madiator.com/ui/component/navigationButton/view.jsx
2021-08-16 12:11:25 +02:00

97 lines
3.2 KiB
JavaScript

// @flow
import React, { useState, useCallback } from 'react';
import * as ICONS from 'constants/icons';
import Button from 'component/button';
// the maximum length of history to show per button
const MAX_HISTORY_SIZE = 12;
type Props = {
isBackward: boolean,
history: {
entries: Array<{ key: string, title: string, pathname: string }>,
go: number => void,
goBack: () => void,
goForward: () => void,
index: number,
length: number,
location: { pathname: string },
push: string => void,
},
};
// determines which slice of entries should make up the back or forward button drop-downs (isBackward vs !isBackward respectively)
const sliceEntries = (currentIndex, entries, historyLength, isBackward, maxSize) => {
let l = isBackward ? 0 : currentIndex + 1;
let r = isBackward ? currentIndex : historyLength;
const exceedsMax = maxSize < r - l;
if (!exceedsMax) {
return entries.slice(l, r);
} else if (isBackward) {
l = r - maxSize;
} else {
r = l + maxSize;
}
return entries.slice(l, r);
};
const NavigationButton = (props: Props) => {
const { isBackward, history } = props;
const { entries, go } = history;
const currentIndex = history.index;
const historyLength = history.length;
const [showHistory, setShowHistory] = useState(false);
// creates an <li> intended for the button's <ul>
const makeItem = useCallback(
(entry: { pathname: string, title: string, key: string }, index: number) => {
// difference between the current index and the index of the entry
const backwardDif = index - (currentIndex < MAX_HISTORY_SIZE ? currentIndex : MAX_HISTORY_SIZE);
const forwardDif = index + 1;
return (
<li
className="header__navigation-button"
role="link"
key={entry.key}
onMouseDown={() => {
setShowHistory(false);
go(isBackward ? backwardDif : forwardDif);
}}
>
<span>{entry.title}</span>
<span className="header__navigation-button-help">{entry.pathname === '/' ? __('Home') : entry.pathname}</span>
</li>
);
},
[currentIndex, isBackward, go]
);
const slicedEntries = sliceEntries(currentIndex, entries, historyLength, isBackward, MAX_HISTORY_SIZE);
return (
<div
// @if TARGET='app'
onDoubleClick={e => {
e.stopPropagation();
}}
// @endif
>
<Button
className={`header__navigation-item header__navigation-item--${isBackward ? 'back' : 'forward'}`}
description={isBackward ? __('Navigate back') : __('Navigate forward')}
onBlur={() => setShowHistory(false)}
onClick={() => (isBackward ? history.goBack() : history.goForward())}
onContextMenu={e => {
setShowHistory(!showHistory);
// the following three lines prevent the regular context menu (right click menu) from appearing
e.preventDefault();
e.stopPropagation();
return false;
}}
icon={isBackward ? ICONS.ARROW_LEFT : ICONS.ARROW_RIGHT}
iconSize={18}
disabled={slicedEntries.length === 0}
/>
{showHistory && <ul className={'header__navigation-dropdown'}>{slicedEntries.map(makeItem)}</ul>}
</div>
);
};
export default NavigationButton;