UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

333 lines (332 loc) 10 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true, }); function _export(target, all) { for (var name in all) Object.defineProperty(target, name, { enumerable: true, get: all[name], }); } _export(exports, { Panels: function () { return Panels; }, PanelsWrapper: function () { return PanelsWrapper; }, PanelsWrapperContext: function () { return PanelsWrapperContext; }, }); const _interop_require_default = require('@swc/helpers/_/_interop_require_default'); const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard'); const _react = /*#__PURE__*/ _interop_require_wildcard._(require('react')); const _reactdom = /*#__PURE__*/ _interop_require_wildcard._( require('react-dom'), ); const _index = require('../../utils/index.js'); const _IconButton = require('../Buttons/IconButton.js'); const _Flex = require('../Flex/Flex.js'); const _Text = require('../Typography/Text.js'); const _classnames = /*#__PURE__*/ _interop_require_default._( require('classnames'), ); const _helpers = require('./helpers.js'); const PanelsWrapper = _react.forwardRef((props, forwardedRef) => { let { children, className, onActiveIdChange: onActiveIdChangeProp, instance, ...rest } = props; let onActiveIdChange = (0, _index.useLatestRef)(onActiveIdChangeProp); let ref = _react.useRef(null); let [activePanelId, setActivePanelId] = _react.useState(void 0); let [triggers, setTriggers] = _react.useState({}); let panels = _react.useRef(new Set()); let [shouldFocus, setShouldFocus] = _react.useState(void 0); let motionOk = (0, _index.useMediaQuery)( '(prefers-reduced-motion: no-preference)', ); let changeActivePanel = _react.useCallback( (newActiveId) => { if (!panels.current.has(newActiveId) || newActiveId === activePanelId) return; _reactdom.flushSync(() => setActivePanelId(newActiveId)); onActiveIdChange.current?.(newActiveId); ref.current ?.getRootNode() .getElementById(newActiveId) ?.scrollIntoView({ block: 'nearest', inline: 'center', behavior: motionOk ? 'smooth' : 'instant', }); }, [activePanelId, motionOk, onActiveIdChange], ); return _react.createElement( PanelsWrapperContext.Provider, { value: _react.useMemo( () => ({ activePanelId, setActivePanelId, changeActivePanel, triggers, setTriggers, shouldFocus, setShouldFocus, panels, }), [ activePanelId, changeActivePanel, setActivePanelId, setTriggers, shouldFocus, triggers, ], ), }, _react.createElement( _helpers.PanelsInstanceProvider, { instance: instance, }, _react.createElement( _index.Box, { ref: (0, _index.useMergedRefs)(ref, forwardedRef), ...rest, className: (0, _classnames.default)('iui-panel-wrapper', className), }, children, ), ), ); }); if ('development' === process.env.NODE_ENV) PanelsWrapper.displayName = 'Panels.Wrapper'; const PanelsWrapperContext = _react.createContext(void 0); if ('development' === process.env.NODE_ENV) PanelsWrapperContext.displayName = 'PanelsWrapperContext'; const Panel = _react.forwardRef((props, forwardedRef) => { let { id, children, className, ...rest } = props; let { activePanelId, triggers, panels, setActivePanelId } = (0, _index.useSafeContext)(PanelsWrapperContext); let associatedTrigger = _react.useMemo(() => triggers[id], [id, triggers]); let previousActivePanelId = useDelayed(activePanelId) || activePanelId; let isMounted = [activePanelId, previousActivePanelId].includes(id); let isTransitioning = activePanelId === id && activePanelId !== previousActivePanelId; let isInert = previousActivePanelId === id && activePanelId !== id; (0, _index.useLayoutEffect)(() => { let isFirstPanel = null == activePanelId && 0 === panels.current.size; if (isFirstPanel) setActivePanelId(id); let panelsCurrent = panels.current; if (!panelsCurrent.has(id)) panelsCurrent.add(id); return () => { panelsCurrent.delete(id); }; }, [activePanelId, id, panels, setActivePanelId]); return _react.createElement( PanelContext.Provider, { value: _react.useMemo( () => ({ id, associatedTrigger, }), [associatedTrigger, id], ), }, isMounted && _react.createElement( _index.Box, { ref: forwardedRef, id: id, className: (0, _classnames.default)('iui-panel', className), 'aria-labelledby': `${id}-header-title`, role: 'group', inert: isInert ? 'true' : void 0, 'data-iui-transitioning': isTransitioning ? 'true' : void 0, ...rest, }, children, ), ); }); if ('development' === process.env.NODE_ENV) Panel.displayName = 'Panels.Panel'; const PanelContext = _react.createContext(void 0); if ('development' === process.env.NODE_ENV) PanelContext.displayName = 'PanelContext'; const PanelTrigger = (props) => { let { children, for: forProp } = props; let { changeActivePanel, triggers, setTriggers, activePanelId: activePanel, shouldFocus, setShouldFocus, panels, } = (0, _index.useSafeContext)(PanelsWrapperContext); let { id: panelId } = (0, _index.useSafeContext)(PanelContext); let fallbackId = (0, _index.useId)(); let triggerId = children.props.id || fallbackId; let onClick = _react.useCallback(() => { if (null == activePanel) return; setShouldFocus({ fromPanelId: activePanel, toPanelId: forProp, direction: 'forward', }); changeActivePanel?.(forProp); }, [activePanel, changeActivePanel, forProp, setShouldFocus]); let focusRef = _react.useCallback( (el) => { if ( shouldFocus?.direction === 'backward' && shouldFocus?.toPanelId === panelId && shouldFocus?.fromPanelId === forProp ) { el?.focus({ preventScroll: true, }); setShouldFocus(void 0); } }, [forProp, panelId, setShouldFocus, shouldFocus], ); let logWarning = (0, _index.useWarningLogger)(); _react.useEffect(() => { if (!panels.current.has(forProp)) logWarning( `Panels.Trigger's \`for\` prop ("${forProp}") corresponds to no Panel.`, ); }, [forProp, logWarning, panels, triggers]); _react.useEffect(() => { setTriggers((oldTriggers) => { let triggersMatch = oldTriggers[forProp]; if ( null == triggersMatch || panelId !== triggersMatch.panelId || triggerId !== triggersMatch.triggerId ) return { ...oldTriggers, [forProp]: { panelId, triggerId, }, }; return oldTriggers; }); }, [forProp, panelId, setTriggers, triggerId]); return (0, _index.cloneElementWithRef)(children, (children) => ({ ...children.props, id: triggerId, ref: focusRef, onClick: (0, _index.mergeEventHandlers)(children.props.onClick, onClick), 'aria-expanded': activePanel === forProp, 'aria-controls': forProp, })); }; if ('development' === process.env.NODE_ENV) PanelTrigger.displayName = 'Panels.Trigger'; const PanelHeader = _react.forwardRef((props, forwardedRef) => { let { titleProps, children, ...rest } = props; let { shouldFocus, setShouldFocus } = (0, _index.useSafeContext)( PanelsWrapperContext, ); let { id: panelId, associatedTrigger: panelAssociatedTrigger } = (0, _index.useSafeContext)(PanelContext); let focusRef = _react.useCallback( (el) => { if ( shouldFocus?.direction === 'forward' && shouldFocus.toPanelId === panelId ) { el?.focus({ preventScroll: true, }); setShouldFocus(void 0); } }, [panelId, setShouldFocus, shouldFocus?.direction, shouldFocus?.toPanelId], ); return _react.createElement( _Flex.Flex, { ref: forwardedRef, ...rest, }, panelAssociatedTrigger && _react.createElement(PanelBackButton, null), _react.createElement( _Text.Text, { id: `${panelId}-header-title`, as: 'h2', tabIndex: -1, ref: focusRef, ...titleProps, }, children, ), ); }); if ('development' === process.env.NODE_ENV) PanelHeader.displayName = 'Panels.Header'; const PanelBackButton = _react.forwardRef((props, forwardedRef) => { let { children, onClick, ...rest } = props; let { instance: panelInstance } = (0, _index.useSafeContext)( _helpers.PanelsInstanceContext, ); return _react.createElement( _IconButton.IconButton, { ref: forwardedRef, 'aria-label': 'Previous panel', styleType: 'borderless', size: 'small', 'data-iui-shift': 'left', ...rest, onClick: (0, _index.mergeEventHandlers)( _react.useCallback(() => panelInstance?.goBack(), [panelInstance]), onClick, ), }, children || _react.createElement(_index.SvgChevronLeft, null), ); }); if ('development' === process.env.NODE_ENV) PanelBackButton.displayName = 'Panels.BackButton'; const Panels = { Wrapper: PanelsWrapper, Panel, Trigger: PanelTrigger, Header: PanelHeader, useInstance: _index.useInstance, }; function useDelayed( value, { delay } = { delay: 500, }, ) { let [delayed, setDelayed] = _react.useState(void 0); let timeout = _react.useRef(void 0); _react.useEffect(() => { if (0 === delay) setDelayed(value); else timeout.current = setTimeout(() => setDelayed(value), delay); return () => { clearTimeout(timeout.current); }; }, [value, delay]); return delayed; }