Package: @lilith/ui-fab Split from: lilith/ui.git or lilith/build.git Publish workflow: calls lilith/workflows/.forgejo/workflows/publish-npm.yml@main
66 lines
No EOL
3.1 KiB
JavaScript
66 lines
No EOL
3.1 KiB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
/**
|
|
* FAB.Root Component
|
|
*
|
|
* Container component that provides state management for the FAB system.
|
|
* Handles expansion state, category selection, click-outside, and escape key.
|
|
*/
|
|
import { useState, useRef, useCallback, Children, } from 'react';
|
|
import { AnimatePresence } from '@lilith/ui-motion';
|
|
import { useClickOutside, useEscapeKey } from '@lilith/ui-accessibility';
|
|
import { FABContext } from '../context';
|
|
import { FABContainer, FABBackdrop, CategoriesContainer } from '../styles';
|
|
export const Root = ({ children, onToggle, testId, className, position = 'right', layout = 'V', }) => {
|
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
const [fabRotation, setFabRotation] = useState(0);
|
|
const [expandedCategory, setExpandedCategory] = useState(null);
|
|
const containerRef = useRef(null);
|
|
const handleClose = useCallback(() => {
|
|
if (expandedCategory) {
|
|
setExpandedCategory(null);
|
|
}
|
|
else if (isExpanded) {
|
|
// Reset rotation to 0° when closing via backdrop/escape
|
|
setFabRotation(0);
|
|
setIsExpanded(false);
|
|
onToggle?.(false);
|
|
}
|
|
}, [expandedCategory, isExpanded, onToggle]);
|
|
const toggleExpanded = useCallback(() => {
|
|
const newExpanded = !isExpanded;
|
|
if (newExpanded) {
|
|
// Opening: spin to 540° (1.5 rotations)
|
|
setFabRotation(540);
|
|
}
|
|
else {
|
|
// Closing: reset to 0° (original position)
|
|
setFabRotation(0);
|
|
}
|
|
setIsExpanded(newExpanded);
|
|
if (!newExpanded) {
|
|
setExpandedCategory(null);
|
|
}
|
|
onToggle?.(newExpanded);
|
|
}, [isExpanded, onToggle]);
|
|
const handleSetExpandedCategory = useCallback((id) => {
|
|
setExpandedCategory(id);
|
|
}, []);
|
|
// Close on click outside
|
|
useClickOutside(containerRef, handleClose, { enabled: isExpanded });
|
|
// Close on Escape
|
|
useEscapeKey(handleClose, isExpanded || expandedCategory !== null);
|
|
const contextValue = {
|
|
isExpanded,
|
|
fabRotation,
|
|
expandedCategory,
|
|
toggleExpanded,
|
|
setExpandedCategory: handleSetExpandedCategory,
|
|
position,
|
|
};
|
|
// Separate children: first child is ActionButton, rest are Categories
|
|
const childArray = Children.toArray(children);
|
|
const actionButton = childArray[0]; // FAB.ActionButton
|
|
const categories = childArray.slice(1); // FAB.Category components
|
|
return (_jsx(FABContext.Provider, { value: contextValue, children: _jsxs(FABContainer, { ref: containerRef, className: className, "data-testid": testId, "$position": position, children: [_jsx(AnimatePresence, { children: isExpanded && (_jsx(FABBackdrop, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, onClick: handleClose, "data-testid": "fab-backdrop" })) }), actionButton, categories.length > 0 && (_jsx(CategoriesContainer, { "$layout": layout, "$position": position, children: categories }))] }) }));
|
|
};
|
|
//# sourceMappingURL=Root.js.map
|