PromucFlow_constructor/app/client/src/widgets/useDropdown.tsx

87 lines
2.5 KiB
TypeScript
Raw Normal View History

import React, { useCallback, useEffect, useRef, useState } from "react";
2022-06-09 08:38:08 +00:00
import { getMainCanvas } from "./WidgetUtils";
import styled from "styled-components";
import { BaseSelectRef } from "rc-select";
2022-06-09 08:38:08 +00:00
import { RenderMode, RenderModes } from "constants/WidgetConstants";
const BackDropContainer = styled.div`
position: fixed;
width: 100vw;
height: 100vh;
background: transparent;
top: 0;
left: 0;
`;
type useDropdownProps = {
inputRef: React.RefObject<HTMLInputElement>;
renderMode?: RenderMode;
};
const FOCUS_TIMEOUT = 500;
// TODO: Refactor More functionalities in MultiSelect, MultiTreeSelect and TreeSelect Components
2022-06-09 09:31:02 +00:00
const useDropdown = ({ inputRef, renderMode }: useDropdownProps) => {
// This is to make the dropdown controlled
const [isOpen, setIsOpen] = useState(false);
2022-06-09 08:56:31 +00:00
const popupContainer = useRef<HTMLElement>(getMainCanvas());
const selectRef = useRef<BaseSelectRef | null>(null);
2022-06-09 08:38:08 +00:00
useEffect(() => {
if (!popupContainer.current) {
popupContainer.current = getMainCanvas();
2022-06-09 08:38:08 +00:00
}
}, []);
2022-06-22 00:11:29 +00:00
const onKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
// Backspace would simultaneously remove an option, so it should only be used within the search input
if (event.key === "Backspace") {
event.stopPropagation();
}
};
2022-06-09 08:38:08 +00:00
// Avoid scrolls when Popup is opened
function BackDrop() {
return <BackDropContainer onClick={closeBackDrop} />;
}
2022-06-09 08:56:31 +00:00
// Get PopupContainer on main Canvas
const getPopupContainer = useCallback(() => popupContainer.current, []);
2022-06-09 08:38:08 +00:00
// When Dropdown is opened disable scrolling within the app except the list of options
2022-06-09 09:31:02 +00:00
const onOpen = useCallback(
(open: boolean) => {
setIsOpen(open);
2022-06-09 09:31:02 +00:00
if (open) {
setTimeout(() => inputRef.current?.focus(), FOCUS_TIMEOUT);
2022-06-09 12:50:17 +00:00
// for more context, the Element we attach to in view mode doesn't have an overflow style, so this only applies to edit mode.
2022-06-09 09:31:02 +00:00
if (popupContainer.current && renderMode === RenderModes.CANVAS) {
popupContainer.current.style.overflowY = "hidden";
}
} else {
if (popupContainer.current && renderMode === RenderModes.CANVAS) {
popupContainer.current.style.overflowY = "auto";
}
selectRef.current?.blur();
2022-06-09 08:38:08 +00:00
}
2022-06-09 09:31:02 +00:00
},
[renderMode],
);
2022-06-09 08:38:08 +00:00
const closeBackDrop = useCallback(() => {
if (selectRef.current) {
selectRef.current.blur();
onOpen(false);
}
}, [onOpen]);
2022-06-09 08:38:08 +00:00
return {
BackDrop,
getPopupContainer,
onOpen,
isOpen,
2022-06-09 09:31:02 +00:00
selectRef,
2022-06-22 00:11:29 +00:00
onKeyDown,
2022-06-09 08:38:08 +00:00
};
};
export default useDropdown;