UNPKG

@reusable-ui/collapse

Version:

A generic element with dynamic visibility (show/hide).

117 lines (116 loc) 4.79 kB
// react: import { // react: default as React, } from 'react'; // cssfn: import { // style sheets: dynamicStyleSheet, } from '@cssfn/cssfn-react'; // writes css in react hook // reusable-ui core: import { // react helper hooks: useMergeEvents, useMergeRefs, useMergeClasses, useMergeStyles, useFloatable, useOrientationable, useCollapsible, useCollapsibleEvent, useLastKnownExpandedSize, } from '@reusable-ui/core'; // a set of reusable-ui packages which are responsible for building any component // reusable-ui components: import { Generic, } from '@reusable-ui/generic'; // a generic component // internals: import { // defaults: defaultOrientationableOptions, } from './defaults.js'; // styles: export const useCollapseStyleSheet = dynamicStyleSheet(() => import(/* webpackPrefetch: true */ './styles/styles.js'), { id: 'gh2oi6zjs0' }); // a unique salt for SSR support, ensures the server-side & client-side have the same generated class names const Collapse = (props) => { // styles: const styleSheet = useCollapseStyleSheet(); // variants: const orientationableVariant = useOrientationable(props, defaultOrientationableOptions); // states: const collapsibleState = useCollapsible(props); const isVisible = collapsibleState.isVisible; // visible = showing, shown, hidding ; !visible = hidden useCollapsibleEvent(props, collapsibleState); const lastKnownExpandedSize = useLastKnownExpandedSize(collapsibleState); // capabilities: /* collapsibleState.state: Collapsed = 0, => false => not updateFloatingPosition() Collapsing = 1, => true => do updateFloatingPosition() Expanding = 2, => true => do updateFloatingPosition() Expanded = 3, => true => do updateFloatingPosition() */ const floatable = useFloatable(props, collapsibleState.state); // rest props: const { // variants: orientation: _orientation, // remove // behaviors: lazy = false, // states: expanded: _expanded, // remove onExpandStart: _onExpandStart, // remove onCollapseStart: _onCollapseStart, // remove onExpandEnd: _onExpandEnd, // remove onCollapseEnd: _onCollapseEnd, // remove // floatable: floatingRef: _floatingRef, // remove floatingOn: _floatingOn, // remove floatingPlacement: _floatingPlacement, // remove floatingMiddleware: _floatingMiddleware, // remove floatingStrategy: _floatingStrategy, // remove floatingAutoFlip: _floatingAutoFlip, // remove floatingAutoShift: _floatingAutoShift, // remove floatingOffset: _floatingOffset, // remove floatingShift: _floatingShift, // remove onFloatingUpdate: _onFloatingUpdate, // remove // children: children, ...restGenericProps } = props; // refs: const mergedOuterRef = useMergeRefs( // preserves the original `outerRef`: props.outerRef, floatable.outerRef, lastKnownExpandedSize.setRef); // classes: const variantClasses = useMergeClasses( // preserves the original `variantClasses`: props.variantClasses, // variants: orientationableVariant.class); const stateClasses = useMergeClasses( // preserves the original `stateClasses`: props.stateClasses, // states: collapsibleState.class); const classes = useMergeClasses( // preserves the original `classes`: props.classes, // capabilities: floatable.classes); // styles: const mergedStyle = useMergeStyles( // styles: lastKnownExpandedSize.style, // preserves the original `style` (can overwrite the `lastKnownExpandedSize.style`): props.style); // handlers: const handleAnimationStart = useMergeEvents( // preserves the original `onAnimationStart`: props.onAnimationStart, // states: collapsibleState.handleAnimationStart); const handleAnimationEnd = useMergeEvents( // preserves the original `onAnimationEnd`: props.onAnimationEnd, // states: collapsibleState.handleAnimationEnd); // jsx: return (React.createElement(Generic, { ...restGenericProps, // refs: outerRef: mergedOuterRef, // semantics: // no need to set [aria-orientation], because the expand/collapse is for styling purpose: // aria-orientation={props['aria-orientation'] ?? orientationableVariant['aria-orientation']} // classes: mainClass: props.mainClass ?? styleSheet.main, variantClasses: variantClasses, stateClasses: stateClasses, classes: classes, // styles: style: mergedStyle, ...collapsibleState.props, // handlers: onAnimationStart: handleAnimationStart, onAnimationEnd: handleAnimationEnd }, (!lazy || isVisible) && children)); }; export { Collapse, Collapse as default, };