chonky
Version:
A File Browser component for React
59 lines (52 loc) • 2.19 kB
text/typescript
import React, { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Nullable } from 'tsdef';
import { ChonkyActions } from '../../action-definitions/index';
import { reduxActions } from '../../redux/reducers';
import { selectContextMenuMounted } from '../../redux/selectors';
import { thunkRequestFileAction } from '../../redux/thunks/dispatchers.thunks';
import { findElementAmongAncestors } from '../../util/helpers';
import { useInstanceVariable } from '../../util/hooks-helpers';
export const findClosestChonkyFileId = (
element: HTMLElement | any
): Nullable<string> => {
const fileEntryWrapperDiv = findElementAmongAncestors(
element,
(element: any) =>
element.tagName &&
element.tagName.toLowerCase() === 'div' &&
element.dataset &&
element.dataset.chonkyFileId
);
return fileEntryWrapperDiv ? fileEntryWrapperDiv.dataset.chonkyFileId! : null;
};
export const useContextMenuTrigger = () => {
const dispatch = useDispatch();
const contextMenuMountedRef = useInstanceVariable(
useSelector(selectContextMenuMounted)
);
return useCallback(
(event: React.MouseEvent<HTMLDivElement>) => {
// Use default browser context menu when Chonky context menu component
// is not mounted.
if (!contextMenuMountedRef.current) return;
// Users can use Alt+Right Click to bring up browser's default
// context menu instead of Chonky's context menu.
if (event.altKey) return;
event.preventDefault();
const triggerFileId = findClosestChonkyFileId(event.target);
dispatch(
thunkRequestFileAction(ChonkyActions.OpenFileContextMenu, {
clientX: event.clientX,
clientY: event.clientY,
triggerFileId,
})
);
},
[contextMenuMountedRef, dispatch]
);
};
export const useContextMenuDismisser = () => {
const dispatch = useDispatch();
return useCallback(() => dispatch(reduxActions.hideContextMenu()), [dispatch]);
};