kedao
Version:
Rich Text Editor Based On Draft.js
79 lines (78 loc) • 4.17 kB
JavaScript
import { classNameParser } from '../../utils/style';
import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle, useCallback } from 'react';
import mergeClassNames from 'merge-class-names';
import styles from "./style.module.css";
import { useClickOutside, usePrevious, useSyncedRef, useWindowSize } from '@react-hookz/web';
import ChevronDownIcon from 'tabler-icons-react/dist/icons/chevron-down';
import { tablerIconProps } from '../../constants';
const cls = classNameParser(styles);
const DropDown = forwardRef(({ disabled, autoHide, getContainerNode, caption, htmlCaption, title, showArrow = true, arrowActive, isActive, onActiveChage, className, children }, ref) => {
const latestIsActive = useSyncedRef(isActive);
const [activeState, setActive] = useState(false);
const active = latestIsActive.current === undefined
? activeState
: latestIsActive.current; // 兼容受控与非受控
const [offset, setOffset] = useState(0);
const dropDownHandlerElement = useRef(null);
const dropDownContentElement = useRef(null);
const size = useWindowSize();
const fixDropDownPosition = () => {
var _a, _b;
const viewRect = getContainerNode().getBoundingClientRect();
const handlerRect = (_a = dropDownHandlerElement.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
const contentRect = (_b = dropDownContentElement.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
let newOffset = 0;
let right = handlerRect.right - handlerRect.width / 2 + contentRect.width / 2;
let left = handlerRect.left + handlerRect.width / 2 - contentRect.width / 2;
right = viewRect.right - right;
left -= viewRect.left;
if (right < 10) {
newOffset = right - 10;
}
else if (left < 10) {
newOffset = left * -1 + 10;
}
if (newOffset !== offset) {
setOffset(newOffset);
}
};
useEffect(fixDropDownPosition, [size]);
useEffect(() => {
if (disabled) {
hide();
}
}, [disabled]);
const previousActive = usePrevious(active);
useEffect(() => {
if (active && active !== previousActive) {
fixDropDownPosition();
}
}, [active]);
const autoHideHandler = useCallback(() => {
if (autoHide && active) {
hide();
}
}, [autoHide, active]);
useClickOutside(dropDownContentElement, autoHideHandler);
const toggle = () => {
onActiveChage === null || onActiveChage === void 0 ? void 0 : onActiveChage(!active);
setActive((active) => !active);
};
const hide = () => {
onActiveChage === null || onActiveChage === void 0 ? void 0 : onActiveChage(false);
setActive(false);
};
useImperativeHandle(ref, () => {
return { hide, toggle };
}, [hide, toggle]);
return (React.createElement("div", { className: cls(mergeClassNames('kedao-dropdown', !disabled && active && 'active', disabled && 'disabled', className)) },
htmlCaption
? (React.createElement("button", { type: "button", className: cls('dropdown-handler'), "data-title": title, "aria-label": "Button", onClick: toggle, dangerouslySetInnerHTML: htmlCaption ? { __html: htmlCaption } : null, ref: dropDownHandlerElement }))
: (React.createElement("button", { type: "button", className: cls('dropdown-handler'), "data-title": title, onClick: toggle, ref: dropDownHandlerElement },
React.createElement("span", null, caption),
showArrow ? React.createElement(ChevronDownIcon, Object.assign({}, tablerIconProps, { size: 16 })) : null)),
React.createElement("div", { className: cls('dropdown-content'), style: { marginLeft: offset }, ref: dropDownContentElement },
React.createElement("i", { style: { marginLeft: offset * -1 }, className: cls(mergeClassNames('dropdown-arrow', arrowActive && 'active')) }),
React.createElement("div", { className: cls('dropdown-content-inner') }, children))));
});
export default DropDown;