UNPKG

@amaui/ui-react

Version:
323 lines (322 loc) 18.4 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = __importDefault(require("react")); const utils_1 = require("@amaui/utils"); const style_react_1 = require("@amaui/style-react"); const IconMaterialExpandMoreW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialExpandMoreW100")); const Checkbox_1 = __importDefault(require("../Checkbox")); const Surface_1 = __importDefault(require("../Surface")); const Type_1 = __importDefault(require("../Type")); const Fade_1 = __importDefault(require("../Fade")); const Expand_1 = __importDefault(require("../Expand")); const Interaction_1 = __importDefault(require("../Interaction")); const Line_1 = __importDefault(require("../Line")); const utils_2 = require("../utils"); const useStyle = (0, style_react_1.style)(theme => ({ root: { position: 'relative' }, line: { '&::before': { content: "''", position: 'absolute', insetInlineStart: '-12px', height: '100%', width: '2px', background: theme.palette.light ? theme.palette.color.neutral['90'] : theme.palette.color.neutral['20'] }, '&:last-of-type': { '&::before': { height: '2px' } } }, main: { // Reset fontFamily: 'inherit', background: 'transparent', border: 'none', fontSize: '100%', lineHeight: '1.15', margin: '0', position: 'relative', color: 'inherit', padding: `${theme.methods.space.value(0.25, 'px')} ${theme.methods.space.value(1, 'px')}`, borderRadius: `${theme.shape.radius.unit * 0.5}px` }, main_line: { '&::before': { content: "''", position: 'absolute', top: 'calc(50% - 15px)', insetInlineStart: '-12px', width: '10px', height: '14px', borderLeft: '2px solid', borderBottom: '2px solid', borderColor: theme.palette.light ? theme.palette.color.neutral['90'] : theme.palette.color.neutral['20'], borderBottomLeftRadius: '6px', transform: `rotateY(${theme.direction === 'ltr' ? 0 : 180}deg)` } }, item: { padding: `${theme.methods.space.value(0.25, 'px')} 0` }, middle: { flex: '1 1 auto' }, indicator: { transition: theme.methods.transitions.make('transform') }, indicator_open: { transform: 'rotate(-180deg)' }, button: { // Reset fontFamily: 'inherit', '-webkit-appearance': 'none', appearance: 'none', background: 'transparent', border: 'none', fontSize: '100%', lineHeight: '1.15', padding: '0', margin: '0', overflow: 'visible', textTransform: 'none', userSelect: 'none', cursor: 'pointer' }, disabled: { pointerEvents: 'none', cursor: 'default', opacity: theme.palette.visual_contrast.default.opacity.disabled } }), { name: 'amaui-Tree' }); const TreeDelays = { Transition: { enter: 70 } }; const Tree = react_1.default.forwardRef((props_, ref) => { const theme = (0, style_react_1.useAmauiTheme)(); const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiTree) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props_)); }, [props_]); const Line = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Line) || Line_1.default; }, [theme]); const Checkbox = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Checkbox) || Checkbox_1.default; }, [theme]); const Surface = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Surface) || Surface_1.default; }, [theme]); const Type = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Type) || Type_1.default; }, [theme]); const Fade = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Fade) || Fade_1.default; }, [theme]); const Expand = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Expand) || Expand_1.default; }, [theme]); const Interaction = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Interaction) || Interaction_1.default; }, [theme]); const { tonal = true, color = 'default', version = 'text', open: open_, openDefault, onChange, selected, line, indicator, arrow = true, checkbox, indicatorPosition = 'start', level = 0, icon, iconOpen, start: start_, middle, end: end_, button = true, noTransition, noExpand, noPadding, parentDisabled, disabled, ExpandProps, MainProps: MainProps_, StartProps, MiddleProps, EndProps, IndicatorProps, TransitionComponentProps: TransitionComponentProps_, TreeProps, IconArrow = IconMaterialExpandMoreW100_1.default, TransitionComponent: TransitionComponent_ = Fade, Component = 'div', className, style, children: children_ } = props, other = __rest(props, ["tonal", "color", "version", "open", "openDefault", "onChange", "selected", "line", "indicator", "arrow", "checkbox", "indicatorPosition", "level", "icon", "iconOpen", "start", "middle", "end", "button", "noTransition", "noExpand", "noPadding", "parentDisabled", "disabled", "ExpandProps", "MainProps", "StartProps", "MiddleProps", "EndProps", "IndicatorProps", "TransitionComponentProps", "TreeProps", "IconArrow", "TransitionComponent", "Component", "className", "style", "children"]); const { classes } = useStyle(); const [init, setInit] = react_1.default.useState(false); const [focus, setFocus] = react_1.default.useState(false); const [open, setOpen] = react_1.default.useState(openDefault !== undefined ? openDefault : open_); const refs = { root: react_1.default.useRef(undefined), ids: { middle: react_1.default.useId() }, inProgressTransition: react_1.default.useRef() }; const styles = { root: {} }; let TransitionComponent = TransitionComponent_; let TransitionComponentProps = Object.assign({ add: true, delay: { enter: TreeDelays.Transition.enter } }, TransitionComponentProps_); react_1.default.useEffect(() => { setInit(true); }, []); react_1.default.useEffect(() => { if (init) { if (open_ !== open) setOpen(open_); } }, [open_]); const onKeyDown = (event) => { var _a; const rootDocument = (0, utils_1.isEnvironment)('browser') ? (((_a = refs.root.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) || window.document) : undefined; if (level === 0) { let allElements = []; let index = 0; if (['ArrowUp', 'ArrowDown'].includes(event.key)) { allElements = Array.from(refs.root.current.querySelectorAll(`[tabindex='0']`)); } switch (event.key) { case 'ArrowUp': case 'ArrowDown': index = (0, utils_1.clamp)(allElements.findIndex(item => item === rootDocument.activeElement), 0); event.key === 'ArrowDown' ? index++ : index--; allElements[(0, utils_1.clamp)(index, 0, allElements.length - 1)].focus(); event.preventDefault(); return; default: break; } } }; const onClick = react_1.default.useCallback((event) => { if ((0, utils_1.is)('function', MiddleProps === null || MiddleProps === void 0 ? void 0 : MiddleProps.onClick)) MiddleProps.onClick(event); if (refs.inProgressTransition.current) return; if (!disabled && !noExpand && children_) { const valueNew = !open; // Update inner or controlled if (!props.hasOwnProperty('open')) setOpen(valueNew); if ((0, utils_1.is)('function', onChange)) onChange(valueNew); } }, [open, noExpand, children_, disabled]); if (!noTransition) TransitionComponentProps.in = open; else { TransitionComponent = react_1.default.Fragment; TransitionComponentProps = {}; } const onBlur = react_1.default.useCallback((event) => { if (!disabled) setFocus(false); }, [disabled]); const onFocus = react_1.default.useCallback((event) => { if (!disabled) setFocus(true); }, [disabled]); const start = react_1.default.Children.toArray(start_); // Icon if (!open ? icon : iconOpen || icon) start.push((!open ? icon : iconOpen || icon)); const end = react_1.default.Children.toArray(end_); if (indicator && button && children_ && !noExpand) { let Indicator; if (arrow) { Indicator = ((0, jsx_runtime_1.jsx)(IconArrow, Object.assign({ className: (0, style_react_1.classNames)([ classes.indicator, open && classes.indicator_open ]) }, IndicatorProps))); } if (checkbox) { Indicator = ((0, jsx_runtime_1.jsx)(Checkbox, Object.assign({ size: 'small', checked: open }, IndicatorProps))); } if (indicatorPosition === 'start') start.unshift(Indicator); else if (indicatorPosition === 'end') end.push(Indicator); } const MainProps = Object.assign({}, MainProps_); if (!disabled) { MainProps.onBlur = onBlur; MainProps.onFocus = onFocus; } if (level > 0 && !noPadding) { styles.root.marginInlineStart = `${theme.space.unit * 2.5}px`; } const children = (react_1.default.Children.toArray(children_).map((item) => (react_1.default.cloneElement(item, { tonal: item.props.tonal !== undefined ? item.props.tonal : tonal, color: item.props.color !== undefined ? item.props.color : color, version: item.props.version !== undefined ? item.props.version : version, line: item.props.line !== undefined ? item.props.line : line, checkbox: item.props.checkbox !== undefined ? item.props.checkbox : checkbox, IconArrow: item.props.IconArrow !== undefined ? item.props.IconArrow : IconArrow, indicator: item.props.indicator !== undefined ? item.props.indicator : indicator, indicatorPosition: item.props.indicatorPosition !== undefined ? item.props.indicatorPosition : indicatorPosition, noExpand: item.props.noExpand !== undefined ? item.props.noExpand : noExpand, noTransition: item.props.noTransition !== undefined ? item.props.noTransition : noTransition, parentDisabled: item.props.parentDisabled !== undefined ? item.props.parentDisabled : parentDisabled || disabled, level: level + 1 })))); return ((0, jsx_runtime_1.jsxs)(Surface, Object.assign({ ref: item => { if (ref) { if ((0, utils_1.is)('function', ref)) ref(item); else if (ref === null || ref === void 0 ? void 0 : ref.current) ref.current = item; } refs.root.current = item; }, tonal: tonal, color: color, version: version, gap: 0, align: 'unset', justify: 'unset', onKeyDown: onKeyDown, role: level === 0 ? 'tree' : 'treeitem', "aria-labelledby": refs.ids.middle, "aria-expanded": open, "aria-selected": selected, Component: Line, AdditionalProps: { Component }, className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('Tree', theme) && [ 'amaui-Tree-root', children ? `amaui-Tree-children` : `amaui-Tree-empty`, parentDisabled && `amaui-Tree-parent-disabled`, disabled && `amaui-Tree-disabled` ], className, classes.root, (level > 0 && line) && classes.line, disabled && classes.disabled ]), style: Object.assign(Object.assign({}, styles.root), style) }, other, { children: [(0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 1, tabIndex: (!disabled && !parentDisabled) ? 0 : -1, onClick: onClick, direction: 'row', align: 'center', justify: 'unset', role: (button && children) ? 'button' : undefined, Component: (button && children) ? 'button' : 'div' }, MainProps, { className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('Tree', theme) && [ 'amaui-Tree-main' ], MainProps === null || MainProps === void 0 ? void 0 : MainProps.className, classes.main, button && classes.button, (level > 0 && line) && classes.main_line ]) }, { children: [button && ((0, jsx_runtime_1.jsx)(Interaction, { selected: selected, pulse: focus })), !!start.length && ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, direction: 'row', align: 'center', justify: 'unset' }, StartProps, { className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('Tree', theme) && [ 'amaui-Tree-item', 'amaui-Tree-aside', 'amaui-Tree-start' ], StartProps === null || StartProps === void 0 ? void 0 : StartProps.className, classes.item, classes.aside, classes.start ]) }, { children: start.map((item, index) => (react_1.default.cloneElement(item, { key: index }))) }))), middle && ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, id: refs.ids.middle, Component: (0, utils_1.is)('simple', middle) ? Type : undefined }, MiddleProps, { className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('Tree', theme) && [ 'amaui-Tree-item', 'amaui-Tree-middle', 'amaui-Tree-end' ], MiddleProps === null || MiddleProps === void 0 ? void 0 : MiddleProps.className, classes.item, classes.middle ]) }, { children: middle }))), !!end.length && ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, direction: 'row', align: 'center', justify: 'unset' }, EndProps, { className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('Tree', theme) && [ 'amaui-Tree-item', 'amaui-Tree-aside', 'amaui-Tree-end' ], EndProps === null || EndProps === void 0 ? void 0 : EndProps.className, classes.item, classes.aside, classes.end ]) }, { children: end.map((item, index) => (react_1.default.cloneElement(item, { key: index }))) })))] })), noExpand && children, !noExpand && children && ((0, jsx_runtime_1.jsx)(Expand, Object.assign({ in: open, parent: parent || refs.root.current, onTransition: (element, status) => { refs.inProgressTransition.current = !['entered', 'removed'].includes(status); } }, ExpandProps, { children: (0, jsx_runtime_1.jsx)(TransitionComponent, Object.assign({}, TransitionComponentProps, { children: (0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0, align: 'unset', justify: 'unset', role: 'group' }, TreeProps, { className: (0, style_react_1.classNames)([ (0, utils_2.staticClassName)('Tree', theme) && [ 'amaui-Tree-tree' ], TreeProps === null || TreeProps === void 0 ? void 0 : TreeProps.className, classes.tree ]) }, { children: children.map((item, index) => (react_1.default.cloneElement(item, { key: index }))) })) })) })))] }))); }); Tree.displayName = 'amaui-Tree'; exports.default = Tree;