ui-fab/dist/components/Root.js
autocommit 92903f78a2 chore: initial package split from monorepo
Package: @lilith/ui-fab
Split from: lilith/ui.git or lilith/build.git
Publish workflow: calls lilith/workflows/.forgejo/workflows/publish-npm.yml@main
2026-04-20 01:10:29 -07:00

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