@ahrowe/ui 0.24.3 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/common/configProvider/configProvider.mjs +1 -1
- package/dist/esm/common/configProvider/configProvider.mjs.map +1 -1
- package/dist/esm/common/configProvider/usePresentationDefault.mjs +2 -0
- package/dist/esm/common/configProvider/usePresentationDefault.mjs.map +1 -0
- package/dist/esm/common/dropdown/dropdown.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.mjs +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.module.mjs +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.module.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.types.mjs +1 -1
- package/dist/esm/common/floatingMenu/floatingMenu.types.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs.map +1 -1
- package/dist/esm/common/hooks/useCoarsePointer.mjs +1 -1
- package/dist/esm/common/hooks/useCoarsePointer.mjs.map +1 -1
- package/dist/esm/common/hooks/useMediaQuery.mjs +2 -0
- package/dist/esm/common/hooks/useMediaQuery.mjs.map +1 -0
- package/dist/esm/common/hooks/useOverlay.mjs +2 -0
- package/dist/esm/common/hooks/useOverlay.mjs.map +1 -0
- package/dist/esm/common/hooks/useSheet.mjs +2 -0
- package/dist/esm/common/hooks/useSheet.mjs.map +1 -0
- package/dist/esm/common/modal/modal.mjs +1 -1
- package/dist/esm/common/modal/modal.mjs.map +1 -1
- package/dist/esm/common/modal/modal.module.mjs +1 -1
- package/dist/esm/common/modal/modal.module.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
- package/dist/esm/common/popover/popover.mjs +1 -1
- package/dist/esm/common/popover/popover.mjs.map +1 -1
- package/dist/esm/common/popover/popover.types.mjs.map +1 -1
- package/dist/esm/common/popover/usePopoverPosition.mjs +1 -1
- package/dist/esm/common/popover/usePopoverPosition.mjs.map +1 -1
- package/dist/esm/common/sheetBackdrop/sheetBackdrop.mjs +2 -0
- package/dist/esm/common/sheetBackdrop/sheetBackdrop.mjs.map +1 -0
- package/dist/esm/common/styles/sheet.module.mjs +2 -0
- package/dist/esm/common/styles/sheet.module.mjs.map +1 -0
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/package/common/configProvider/configProvider.d.ts +9 -1
- package/dist/types/package/common/configProvider/configProvider.types.d.ts +13 -0
- package/dist/types/package/common/configProvider/index.d.ts +1 -0
- package/dist/types/package/common/configProvider/usePresentationDefault.d.ts +8 -0
- package/dist/types/package/common/dropdown/dropdown.types.d.ts +4 -0
- package/dist/types/package/common/floatingMenu/floatingMenu.d.ts +1 -1
- package/dist/types/package/common/floatingMenu/floatingMenu.types.d.ts +13 -1
- package/dist/types/package/common/hooks/useCoarsePointer.d.ts +1 -8
- package/dist/types/package/common/hooks/useMediaQuery.d.ts +9 -0
- package/dist/types/package/common/hooks/useOverlay.d.ts +26 -0
- package/dist/types/package/common/hooks/useSheet.d.ts +16 -0
- package/dist/types/package/common/modal/modal.d.ts +1 -1
- package/dist/types/package/common/modal/modal.types.d.ts +9 -3
- package/dist/types/package/common/popover/popover.d.ts +1 -1
- package/dist/types/package/common/popover/popover.types.d.ts +6 -1
- package/dist/types/package/common/sheetBackdrop/index.d.ts +2 -0
- package/dist/types/package/common/sheetBackdrop/sheetBackdrop.d.ts +16 -0
- package/dist/types/package/common/sheetBackdrop/sheetBackdrop.types.d.ts +7 -0
- package/docs/ConfigProvider.md +32 -1
- package/docs/Dropdown.md +7 -1
- package/docs/FloatingMenu.md +32 -3
- package/docs/Modal.md +27 -3
- package/docs/Popover.md +12 -3
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numberInput.mjs","names":[],"sources":["../../../../package/common/numberInput/numberInput.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport React from 'react';\nimport cx from 'classnames';\nimport { NumericFormat } from 'react-number-format';\nimport type { FormValidator } from 'services/formValidation';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronUp, faChevronDown, faMinus, faPlus } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './numberInput.module.pcss';\nimport Input from '../input';\nimport Button from '../button';\nimport ButtonGroup from '../buttonGroup';\nimport { ButtonSize } from '../button/button.types';\nimport { useComponentDefaults } from '../configProvider';\nimport { useCoarsePointer } from '../hooks/useCoarsePointer';\nimport { useStepRepeat } from './useStepRepeat';\nimport type { NumberInputProps } from './numberInput.types';\n\nexport type { NumberInputProps, NumberInputArrowsLayout } from './numberInput.types';\n\ninterface StepButtonProps {\n label: string;\n icon: typeof faPlus;\n disabled: boolean;\n direction: 1 | -1;\n onStart: (direction: 1 | -1, multiplier: number) => void;\n onStop: () => void;\n}\n\n/** Press-and-hold behaviour shared by both stepper layouts. */\nfunction stepButtonProps({ label, disabled, direction, onStart, onStop }: StepButtonProps) {\n return {\n // The input keeps the tab stop — it carries role=\"spinbutton\", which announces the value\n // and the arrow-key affordance, so two more tab stops per field would be noise.\n tabIndex: -1,\n disabled,\n 'aria-label': label,\n // pointerdown (not click) keeps focus in the field and responds immediately on touch.\n // Deliberately no setPointerCapture: capturing retargets the following click to the captured\n // element, past the node Button's ripple listens on. useStepRepeat watches the window for\n // the release instead.\n onPointerDown: (e: React.PointerEvent<HTMLElement>) => {\n if (e.button !== 0 && e.pointerType === 'mouse') return;\n e.preventDefault();\n onStart(direction, e.shiftKey ? 10 : 1);\n },\n onPointerUp: onStop,\n onPointerCancel: onStop,\n onContextMenu: (e: React.SyntheticEvent) => e.preventDefault(),\n };\n}\n\n/** Stacked-layout chevron: borderless, sits inside the field's border. */\nfunction ChevronStepButton(props: StepButtonProps): ReactElement {\n return (\n <button type=\"button\" {...stepButtonProps(props)} className={styles.arrowBtn}>\n <FontAwesomeIcon icon={props.icon} aria-hidden=\"true\" />\n </button>\n );\n}\n\n/** Split-layout stepper: a standalone control, so a real Button. */\nfunction SplitStepButton(props: StepButtonProps): ReactElement {\n const { disabled, ...handlers } = stepButtonProps(props);\n return (\n <Button\n {...handlers}\n className={styles.splitBtn}\n size={ButtonSize.Icon}\n disabled={disabled}\n icon={props.icon}\n />\n );\n}\n\nfunction NumberInput(props: NumberInputProps): ReactElement {\n const fvRef = React.useRef<FormValidator | null | undefined>(undefined);\n const {\n value,\n onChange,\n formValidator,\n label,\n error,\n className,\n style,\n allowNegative = false,\n decimalSeparator,\n thousandSeparator,\n prefix,\n suffix,\n decimalScale,\n fixedDecimalScale = true,\n placeholder,\n sign,\n showArrows = false,\n step = 1,\n min,\n max,\n arrowsLayout = 'auto',\n increaseLabel = 'Increase',\n decreaseLabel = 'Decrease',\n readOnly = false,\n disabled = false,\n isRequired = false,\n onKeyDown: onKeyDownProp,\n ...rest\n } = useComponentDefaults('NumberInput', props);\n const [, forceUpdate] = React.useState(0);\n React.useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => { formValidator.removeOnUpdateListener(listener); };\n }, [formValidator]);\n const computedIsRequired = isRequired || !!formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n );\n const rawValue = formValidator != null ? formValidator.value as number | string : value;\n // When a sign is forced, display the absolute value — the prefix character carries the sign visually.\n const displayValue = sign != null && rawValue != null ? Math.abs(Number(rawValue)) : rawValue;\n const controlledValue = displayValue != null ? String(displayValue) : '';\n\n function handleValueChange(floatValue: number | undefined) {\n let out = floatValue;\n if (out !== undefined) {\n if (sign === '-') out = -Math.abs(out);\n if (sign === '+') out = Math.abs(out);\n }\n if (formValidator != null) formValidator.set(out ?? null);\n onChange?.(out);\n }\n\n function clamp(next: number): number {\n let out = next;\n if (!allowNegative && sign !== '-') out = Math.max(0, out);\n if (sign === '-') out = Math.min(0, out);\n if (min !== undefined) out = Math.max(min, out);\n if (max !== undefined) out = Math.min(max, out);\n return out;\n }\n\n const currentNumber = rawValue != null && rawValue !== '' ? Number(rawValue) : 0;\n\n /**\n * Called on blur and Enter, never per keystroke: rejecting an out-of-bounds edit as it is\n * typed swallows keystrokes on their way somewhere valid (with `max: 10`, typing `1` in front\n * of `8` to reach `18`). An empty field is skipped so a `min` is never typed in for the user.\n */\n function clampToBounds() {\n if (readOnly || disabled) return;\n if (rawValue == null || rawValue === '') return;\n const n = Number(rawValue);\n if (!Number.isFinite(n)) return;\n const next = clamp(n);\n if (next !== n) handleValueChange(next);\n }\n\n /** Returns whether the value moved, which is how useStepRepeat knows to end a hold at a bound. */\n function handleStep(delta: number): boolean {\n if (readOnly || disabled) return false;\n const next = clamp(currentNumber + delta);\n if (next === currentNumber) return false;\n handleValueChange(next);\n return true;\n }\n\n const { start: startRepeat, stop: stopRepeat } = useStepRepeat((delta) => handleStep(delta * step));\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n // Enter submits the surrounding form without ever blurring, so the blur clamp would not run.\n // Before the stepper guard, since the bounds apply with or without steppers.\n if (e.key === 'Enter') {\n clampToBounds();\n onKeyDownProp?.(e);\n return;\n }\n if (!showStepper) { onKeyDownProp?.(e); return; }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n handleStep(e.shiftKey ? step * 10 : step);\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n handleStep(e.shiftKey ? -step * 10 : -step);\n return;\n }\n onKeyDownProp?.(e);\n }\n\n const resolvedPrefix = sign === '-' ? '-' : sign === '+' ? '+' : prefix;\n\n const isCoarsePointer = useCoarsePointer();\n const showStepper = showArrows && !readOnly && !disabled;\n const isSplit = arrowsLayout === 'split' || (arrowsLayout === 'auto' && isCoarsePointer);\n\n const canIncrease = clamp(currentNumber + step) !== currentNumber;\n const canDecrease = clamp(currentNumber - step) !== currentNumber;\n\n const stepperProps = { onStart: startRepeat, onStop: stopRepeat };\n\n const stackedArrows = showStepper && !isSplit ? (\n <div className={styles.arrows}>\n <ChevronStepButton\n label={increaseLabel}\n icon={faChevronUp}\n disabled={!canIncrease}\n direction={1}\n {...stepperProps}\n />\n <ChevronStepButton\n label={decreaseLabel}\n icon={faChevronDown}\n disabled={!canDecrease}\n direction={-1}\n {...stepperProps}\n />\n </div>\n ) : null;\n\n // aria-* is spread onto NumericFormat, which forwards unknown props to the DOM input.\n // Input's own cloneElement doesn't set these keys, so they survive the clone.\n const spinButtonProps = showStepper\n ? {\n role: 'spinbutton',\n 'aria-valuenow': Number.isFinite(currentNumber) ? currentNumber : undefined,\n 'aria-valuemin': min,\n 'aria-valuemax': max,\n 'aria-valuetext': controlledValue || undefined,\n }\n : {};\n\n // Shared with the split group, whose buttons have to mirror the field's invalid state — they\n // form one continuous border.\n const isValid = formValidator ? (formValidator.touched ? !formValidator.hasError() : true) : !error;\n\n // In the split layout the ButtonGroup is the root, so the consumer's className and style\n // belong there rather than on the Input.\n const isSplitGroup = showStepper && isSplit;\n\n const input = (\n <Input\n label={label}\n className={cx(styles.numberInput, { [styles.numberInputSplit]: isSplitGroup }, isSplitGroup ? undefined : className)}\n style={isSplitGroup ? undefined : style}\n value={controlledValue}\n onChange={() => {}}\n formValidator={null}\n isRequired={computedIsRequired}\n onBlur={() => { clampToBounds(); if (fvRef.current) fvRef.current.touched = true; }}\n isValid={isValid}\n errorMessage={formValidator ? (formValidator.touched ? (formValidator.getCurrentErrorMessage() ?? '') : '') : (error ?? '')}\n placeholder={placeholder}\n readOnly={readOnly}\n disabled={disabled}\n suffix={stackedArrows}\n // Input centres its suffix wrapper; this lets the chevrons claim the field's full height.\n classNames={stackedArrows ? { suffix: styles.arrowSuffix } : undefined}\n inputMode={decimalScale === 0 ? 'numeric' : 'decimal'}\n customInput={\n <NumericFormat\n onValueChange={(vals) => handleValueChange(vals.floatValue)}\n allowNegative={sign != null ? false : allowNegative}\n decimalSeparator={decimalSeparator}\n thousandSeparator={thousandSeparator}\n decimalScale={decimalScale}\n fixedDecimalScale={fixedDecimalScale}\n prefix={resolvedPrefix}\n suffix={suffix}\n onKeyDown={handleKeyDown}\n {...spinButtonProps}\n {...rest}\n />\n }\n />\n );\n\n if (!isSplitGroup) return input;\n\n return (\n // ButtonGroup collapses the doubled borders and flattens the inner corners, so the three\n // read as one control.\n <ButtonGroup className={cx(styles.split, { [styles.splitInvalid]: !isValid }, className)} style={style}>\n <SplitStepButton\n label={decreaseLabel}\n icon={faMinus}\n disabled={!canDecrease}\n direction={-1}\n {...stepperProps}\n />\n {input}\n <SplitStepButton\n label={increaseLabel}\n icon={faPlus}\n disabled={!canIncrease}\n direction={1}\n {...stepperProps}\n />\n </ButtonGroup>\n );\n}\n\nexport default NumberInput;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"numberInput.mjs","names":[],"sources":["../../../../package/common/numberInput/numberInput.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport React from 'react';\nimport cx from 'classnames';\nimport { NumericFormat } from 'react-number-format';\nimport type { FormValidator } from 'services/formValidation';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronUp, faChevronDown, faMinus, faPlus } from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './numberInput.module.pcss';\nimport Input from '../input';\nimport Button from '../button';\nimport ButtonGroup from '../buttonGroup';\nimport { ButtonSize } from '../button/button.types';\nimport { useComponentDefaults } from '../configProvider';\nimport { useCoarsePointer } from '../hooks/useCoarsePointer';\nimport { useStepRepeat } from './useStepRepeat';\nimport type { NumberInputProps } from './numberInput.types';\n\nexport type { NumberInputProps, NumberInputArrowsLayout } from './numberInput.types';\n\ninterface StepButtonProps {\n label: string;\n icon: typeof faPlus;\n disabled: boolean;\n direction: 1 | -1;\n onStart: (direction: 1 | -1, multiplier: number) => void;\n onStop: () => void;\n}\n\n/** Press-and-hold behaviour shared by both stepper layouts. */\nfunction stepButtonProps({ label, disabled, direction, onStart, onStop }: StepButtonProps) {\n return {\n // The input keeps the tab stop — it carries role=\"spinbutton\", which announces the value\n // and the arrow-key affordance, so two more tab stops per field would be noise.\n tabIndex: -1,\n disabled,\n 'aria-label': label,\n // pointerdown (not click) keeps focus in the field and responds immediately on touch.\n // Deliberately no setPointerCapture: capturing retargets the following click to the captured\n // element, past the node Button's ripple listens on. useStepRepeat watches the window for\n // the release instead.\n onPointerDown: (e: React.PointerEvent<HTMLElement>) => {\n if (e.button !== 0 && e.pointerType === 'mouse') return;\n e.preventDefault();\n onStart(direction, e.shiftKey ? 10 : 1);\n },\n onPointerUp: onStop,\n onPointerCancel: onStop,\n onContextMenu: (e: React.SyntheticEvent) => e.preventDefault(),\n };\n}\n\n/** Stacked-layout chevron: borderless, sits inside the field's border. */\nfunction ChevronStepButton(props: StepButtonProps): ReactElement {\n return (\n <button type=\"button\" {...stepButtonProps(props)} className={styles.arrowBtn}>\n <FontAwesomeIcon icon={props.icon} aria-hidden=\"true\" />\n </button>\n );\n}\n\n/** Split-layout stepper: a standalone control, so a real Button. */\nfunction SplitStepButton(props: StepButtonProps): ReactElement {\n const { disabled, ...handlers } = stepButtonProps(props);\n return (\n <Button\n {...handlers}\n className={styles.splitBtn}\n size={ButtonSize.Icon}\n disabled={disabled}\n icon={props.icon}\n />\n );\n}\n\nfunction NumberInput(props: NumberInputProps): ReactElement {\n const fvRef = React.useRef<FormValidator | null | undefined>(undefined);\n const {\n value,\n onChange,\n formValidator,\n label,\n error,\n className,\n style,\n allowNegative = false,\n decimalSeparator,\n thousandSeparator,\n prefix,\n suffix,\n decimalScale,\n fixedDecimalScale = true,\n placeholder,\n sign,\n showArrows = false,\n step = 1,\n min,\n max,\n arrowsLayout = 'auto',\n increaseLabel = 'Increase',\n decreaseLabel = 'Decrease',\n readOnly = false,\n disabled = false,\n isRequired = false,\n onKeyDown: onKeyDownProp,\n ...rest\n } = useComponentDefaults('NumberInput', props);\n const [, forceUpdate] = React.useState(0);\n React.useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => { formValidator.removeOnUpdateListener(listener); };\n }, [formValidator]);\n const computedIsRequired = isRequired || !!formValidator?.validators.find(\n (v) => (v as { validatorId?: string }).validatorId === 'required'\n );\n const rawValue = formValidator != null ? formValidator.value as number | string : value;\n // When a sign is forced, display the absolute value — the prefix character carries the sign visually.\n const displayValue = sign != null && rawValue != null ? Math.abs(Number(rawValue)) : rawValue;\n const controlledValue = displayValue != null ? String(displayValue) : '';\n\n function handleValueChange(floatValue: number | undefined) {\n let out = floatValue;\n if (out !== undefined) {\n if (sign === '-') out = -Math.abs(out);\n if (sign === '+') out = Math.abs(out);\n }\n if (formValidator != null) formValidator.set(out ?? null);\n onChange?.(out);\n }\n\n function clamp(next: number): number {\n let out = next;\n if (!allowNegative && sign !== '-') out = Math.max(0, out);\n if (sign === '-') out = Math.min(0, out);\n if (min !== undefined) out = Math.max(min, out);\n if (max !== undefined) out = Math.min(max, out);\n return out;\n }\n\n const currentNumber = rawValue != null && rawValue !== '' ? Number(rawValue) : 0;\n\n /**\n * Called on blur and Enter, never per keystroke: rejecting an out-of-bounds edit as it is\n * typed swallows keystrokes on their way somewhere valid (with `max: 10`, typing `1` in front\n * of `8` to reach `18`). An empty field is skipped so a `min` is never typed in for the user.\n */\n function clampToBounds() {\n if (readOnly || disabled) return;\n if (rawValue == null || rawValue === '') return;\n const n = Number(rawValue);\n if (!Number.isFinite(n)) return;\n const next = clamp(n);\n if (next !== n) handleValueChange(next);\n }\n\n /** Returns whether the value moved, which is how useStepRepeat knows to end a hold at a bound. */\n function handleStep(delta: number): boolean {\n if (readOnly || disabled) return false;\n const next = clamp(currentNumber + delta);\n if (next === currentNumber) return false;\n handleValueChange(next);\n return true;\n }\n\n const { start: startRepeat, stop: stopRepeat } = useStepRepeat((delta) => handleStep(delta * step));\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n // Enter submits the surrounding form without ever blurring, so the blur clamp would not run.\n // Before the stepper guard, since the bounds apply with or without steppers.\n if (e.key === 'Enter') {\n clampToBounds();\n onKeyDownProp?.(e);\n return;\n }\n if (!showStepper) { onKeyDownProp?.(e); return; }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n handleStep(e.shiftKey ? step * 10 : step);\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n handleStep(e.shiftKey ? -step * 10 : -step);\n return;\n }\n onKeyDownProp?.(e);\n }\n\n const resolvedPrefix = sign === '-' ? '-' : sign === '+' ? '+' : prefix;\n\n const isCoarsePointer = useCoarsePointer();\n const showStepper = showArrows && !readOnly && !disabled;\n const isSplit = arrowsLayout === 'split' || (arrowsLayout === 'auto' && isCoarsePointer);\n\n const canIncrease = clamp(currentNumber + step) !== currentNumber;\n const canDecrease = clamp(currentNumber - step) !== currentNumber;\n\n const stepperProps = { onStart: startRepeat, onStop: stopRepeat };\n\n const stackedArrows = showStepper && !isSplit ? (\n <div className={styles.arrows}>\n <ChevronStepButton\n label={increaseLabel}\n icon={faChevronUp}\n disabled={!canIncrease}\n direction={1}\n {...stepperProps}\n />\n <ChevronStepButton\n label={decreaseLabel}\n icon={faChevronDown}\n disabled={!canDecrease}\n direction={-1}\n {...stepperProps}\n />\n </div>\n ) : null;\n\n // aria-* is spread onto NumericFormat, which forwards unknown props to the DOM input.\n // Input's own cloneElement doesn't set these keys, so they survive the clone.\n const spinButtonProps = showStepper\n ? {\n role: 'spinbutton',\n 'aria-valuenow': Number.isFinite(currentNumber) ? currentNumber : undefined,\n 'aria-valuemin': min,\n 'aria-valuemax': max,\n 'aria-valuetext': controlledValue || undefined,\n }\n : {};\n\n // Shared with the split group, whose buttons have to mirror the field's invalid state — they\n // form one continuous border.\n const isValid = formValidator ? (formValidator.touched ? !formValidator.hasError() : true) : !error;\n\n // In the split layout the ButtonGroup is the root, so the consumer's className and style\n // belong there rather than on the Input.\n const isSplitGroup = showStepper && isSplit;\n\n const input = (\n <Input\n label={label}\n className={cx(styles.numberInput, { [styles.numberInputSplit]: isSplitGroup }, isSplitGroup ? undefined : className)}\n style={isSplitGroup ? undefined : style}\n value={controlledValue}\n onChange={() => {}}\n formValidator={null}\n isRequired={computedIsRequired}\n onBlur={() => { clampToBounds(); if (fvRef.current) fvRef.current.touched = true; }}\n isValid={isValid}\n errorMessage={formValidator ? (formValidator.touched ? (formValidator.getCurrentErrorMessage() ?? '') : '') : (error ?? '')}\n placeholder={placeholder}\n readOnly={readOnly}\n disabled={disabled}\n suffix={stackedArrows}\n // Input centres its suffix wrapper; this lets the chevrons claim the field's full height.\n classNames={stackedArrows ? { suffix: styles.arrowSuffix } : undefined}\n inputMode={decimalScale === 0 ? 'numeric' : 'decimal'}\n customInput={\n <NumericFormat\n onValueChange={(vals) => handleValueChange(vals.floatValue)}\n allowNegative={sign != null ? false : allowNegative}\n decimalSeparator={decimalSeparator}\n thousandSeparator={thousandSeparator}\n decimalScale={decimalScale}\n fixedDecimalScale={fixedDecimalScale}\n prefix={resolvedPrefix}\n suffix={suffix}\n onKeyDown={handleKeyDown}\n {...spinButtonProps}\n {...rest}\n />\n }\n />\n );\n\n if (!isSplitGroup) return input;\n\n return (\n // ButtonGroup collapses the doubled borders and flattens the inner corners, so the three\n // read as one control.\n <ButtonGroup className={cx(styles.split, { [styles.splitInvalid]: !isValid }, className)} style={style}>\n <SplitStepButton\n label={decreaseLabel}\n icon={faMinus}\n disabled={!canDecrease}\n direction={-1}\n {...stepperProps}\n />\n {input}\n <SplitStepButton\n label={increaseLabel}\n icon={faPlus}\n disabled={!canIncrease}\n direction={1}\n {...stepperProps}\n />\n </ButtonGroup>\n );\n}\n\nexport default NumberInput;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"../bodyEnd/bodyEnd.mjs";import{tabbablesIn as
|
|
1
|
+
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{usePresentationDefault as t}from"../configProvider/usePresentationDefault.mjs";import n from"../bodyEnd/bodyEnd.mjs";import r from"../styles/sheet.module.mjs";import i from"../sheetBackdrop/sheetBackdrop.mjs";import{tabbablesIn as a,useFocusBoundary as o}from"../hooks/useFocusBoundary.mjs";import{Presentation as s}from"../floatingMenu/floatingMenu.types.mjs";import ee from"../hooks/useSheet.mjs";import{useOverlay as c}from"../hooks/useOverlay.mjs";import l from"./popover.module.mjs";import{PopoverAlign as u,PopoverPlacement as d,PopoverTrigger as f}from"./popover.types.mjs";import{usePopoverPosition as p}from"./usePopoverPosition.mjs";import{useCallback as m,useEffect as h,useRef as g,useState as te}from"react";import _ from"classnames";import{jsx as v,jsxs as y}from"react/jsx-runtime";function b(b){let{children:x=null,content:S=null,placement:C=d.Bottom,align:w=u.Center,trigger:T=f.Click,isOpen:E,defaultOpen:D=!1,onOpenChange:O=()=>{},offset:ne=10,withArrow:k=!0,closeOnOutsideClick:A=!0,closeOnEscape:j=!0,openDelay:M=100,closeDelay:N=120,disabled:P=!1,presentation:F,className:I,style:L,classNames:R,styles:z,...B}=e(`Popover`,b),V=g(null),H=g(null),U=g(null),W=g(null),G=g(void 0),K=E!==void 0,[q,J]=te(D),Y=K?E:q,X=g(O);h(()=>{X.current=O});let Z=m(e=>{P&&e||(K||J(e),X.current(e))},[P,K]),re=t(),{isSheet:ie,sheetStyle:ae}=ee(F??re??s.Default),Q=ie&&T===f.Click;p({isOpen:!!Y&&!Q,placement:C,align:w,offset:ne,triggerRef:V,floatingRef:H,panelRef:U,arrowRef:k?W:{current:null}}),c({isActive:!!Y,containerRef:U,onEscape:j?()=>{H.current?.contains(document.activeElement)&&(a(V.current)[0]??V.current)?.focus(),Z(!1)}:void 0,trapFocus:!1,lockScroll:Q});let{restoreFocusToTrigger:oe,focusAfterTrigger:se}=o({triggerRef:V,contentRef:H});h(()=>{if(!Y||T!==f.Click)return;let e=a(U.current);e.length!==0&&(H.current?.setAttribute(`role`,`dialog`),e[0].focus())},[Y,T]);function ce(e){if(e.key!==`Tab`||T!==f.Click)return;let t=a(U.current);if(t.length===0)return;let n=document.activeElement;!e.shiftKey&&n===t[t.length-1]?(e.preventDefault(),se(),Z(!1)):e.shiftKey&&n===t[0]&&(e.preventDefault(),oe(),Z(!1))}h(()=>{if(!Y)return;function e(e){let t=e.target,n=H.current?.contains(t),r=V.current?.contains(t);!n&&!r&&Z(!1)}function t(e){let t=e.target,n=H.current?.contains(t),r=V.current?.contains(t);!n&&!r&&Z(!1)}return A&&T!==f.Hover&&(window.addEventListener(`mouseup`,e),document.addEventListener(`focusin`,t)),()=>{window.removeEventListener(`mouseup`,e),document.removeEventListener(`focusin`,t)}},[Y,A,T,Z]),h(()=>()=>clearTimeout(G.current),[]);function $(e){clearTimeout(G.current),G.current=setTimeout(()=>Z(e),e?M:N)}let le=T===f.Click?{onClick:()=>Z(!Y)}:T===f.Hover?{onMouseEnter:()=>$(!0),onMouseLeave:()=>$(!1)}:{onFocus:()=>Z(!0),onBlur:()=>Z(!1)},ue=T===f.Hover?{onMouseEnter:()=>$(!0),onMouseLeave:()=>$(!1)}:{};return y(`div`,{...B,className:_(l.popover,I,R?.root),style:{...L,...z?.root},children:[v(`div`,{ref:V,className:_(l.popoverTrigger,R?.trigger),style:z?.trigger,...le,children:x}),Y&&y(n,{children:[Q&&v(i,{onClose:()=>{A&&Z(!1)},className:R?.backdrop,style:z?.backdrop}),y(`div`,{ref:H,className:_(Q?r.sheet:l.popoverFloating,R?.floating),style:{...Q?ae:void 0,...z?.floating},"data-placement":C,onKeyDown:ce,...ue,children:[v(`div`,{ref:U,className:_(l.popoverPanel,Q&&r.sheetPanel,R?.panel),style:z?.panel,children:S}),k&&!Q&&v(`div`,{ref:W,className:_(l.popoverArrow,R?.arrow),style:z?.arrow})]})]})]})}export{b as default};
|
|
2
2
|
//# sourceMappingURL=popover.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover.mjs","names":[],"sources":["../../../../package/common/popover/popover.tsx"],"sourcesContent":["import { useRef, useEffect, useState, useCallback } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './popover.module.pcss';\nimport { usePopoverPosition } from './usePopoverPosition';\nimport { useFocusBoundary, tabbablesIn } from '../hooks/useFocusBoundary';\nimport { PopoverPlacement, PopoverAlign, PopoverTrigger, type PopoverProps } from './popover.types';\n\nfunction Popover({\n children = null,\n content = null,\n placement = PopoverPlacement.Bottom,\n align = PopoverAlign.Center,\n trigger = PopoverTrigger.Click,\n isOpen,\n defaultOpen = false,\n onOpenChange = () => {},\n offset = 10,\n withArrow = true,\n closeOnOutsideClick = true,\n closeOnEscape = true,\n openDelay = 100,\n closeDelay = 120,\n disabled = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: PopoverProps) {\n const triggerRef = useRef<HTMLDivElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const arrowRef = useRef<HTMLDivElement>(null);\n const hoverTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const isControlled = isOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = isControlled ? isOpen : internalOpen;\n\n // Keep the outside-click/Escape listeners pointed at the latest setter without re-subscribing.\n const onOpenChangeRef = useRef(onOpenChange);\n useEffect(() => { onOpenChangeRef.current = onOpenChange; });\n\n const setOpen = useCallback((next: boolean) => {\n if (disabled && next) return;\n if (!isControlled) setInternalOpen(next);\n onOpenChangeRef.current(next);\n }, [disabled, isControlled]);\n\n usePopoverPosition({\n isOpen: !!open,\n placement,\n align,\n offset,\n triggerRef,\n floatingRef,\n panelRef,\n arrowRef: withArrow ? arrowRef : { current: null },\n });\n\n const { restoreFocusToTrigger, focusAfterTrigger } = useFocusBoundary({\n triggerRef,\n contentRef: floatingRef,\n });\n\n // The panel is portaled to the end of the DOM, so Tab never flows into it naturally. When we\n // manage focus (click trigger + focusable content), move focus in on open and, on Tab out of\n // either end, close and continue focus as if the panel sat right after the trigger.\n useEffect(() => {\n if (!open || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n // Only claim the dialog role when we're actually managing focus for real content.\n floatingRef.current?.setAttribute('role', 'dialog');\n focusables[0].focus();\n }, [open, trigger]);\n\n function handleFloatingKeyDown(event: React.KeyboardEvent) {\n if (event.key !== 'Tab' || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n const active = document.activeElement;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusAfterTrigger();\n setOpen(false);\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n restoreFocusToTrigger();\n setOpen(false);\n }\n }\n\n // Outside click + Escape. Registered only while open and only for the relevant trigger mode.\n useEffect(() => {\n if (!open) return;\n\n function onMouseUp(event: MouseEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== 'Escape') return;\n // Hand focus back to the trigger when it currently sits inside the panel.\n if (floatingRef.current?.contains(document.activeElement)) {\n (tabbablesIn(triggerRef.current)[0] ?? triggerRef.current)?.focus();\n }\n setOpen(false);\n }\n // Keyboard counterpart to the outside click: once focus leaves both the trigger\n // and the (portaled) panel — e.g. tabbing on to the next element — close.\n function onFocusIn(event: FocusEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n\n if (closeOnOutsideClick && trigger !== PopoverTrigger.Hover) {\n window.addEventListener('mouseup', onMouseUp);\n document.addEventListener('focusin', onFocusIn);\n }\n if (closeOnEscape) window.addEventListener('keydown', onKeyDown);\n return () => {\n window.removeEventListener('mouseup', onMouseUp);\n document.removeEventListener('focusin', onFocusIn);\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [open, closeOnOutsideClick, closeOnEscape, trigger, setOpen]);\n\n useEffect(() => () => clearTimeout(hoverTimer.current), []);\n\n function scheduleHover(next: boolean) {\n clearTimeout(hoverTimer.current);\n hoverTimer.current = setTimeout(() => setOpen(next), next ? openDelay : closeDelay);\n }\n\n const triggerHandlers =\n trigger === PopoverTrigger.Click\n ? { onClick: () => setOpen(!open) }\n : trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : { onFocus: () => setOpen(true), onBlur: () => setOpen(false) };\n\n const floatingHoverHandlers =\n trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : {};\n\n return (\n <div\n {...rest}\n className={cx(styles.popover, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div\n ref={triggerRef}\n className={cx(styles.popoverTrigger, classNames?.trigger)}\n style={slotStyles?.trigger}\n {...triggerHandlers}\n >\n {children}\n </div>\n {open && (\n <BodyEnd>\n <div\n ref={floatingRef}\n className={cx(styles.popoverFloating, classNames?.floating)}\n style={slotStyles?.floating}\n data-placement={placement}\n onKeyDown={handleFloatingKeyDown}\n {...floatingHoverHandlers}\n >\n <div\n ref={panelRef}\n className={cx(styles.popoverPanel, classNames?.panel)}\n style={slotStyles?.panel}\n >\n {content}\n </div>\n {withArrow && (\n <div\n ref={arrowRef}\n className={cx(styles.popoverArrow, classNames?.arrow)}\n style={slotStyles?.arrow}\n />\n )}\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default Popover;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"popover.mjs","names":[],"sources":["../../../../package/common/popover/popover.tsx"],"sourcesContent":["import { useRef, useEffect, useState, useCallback } from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './popover.module.pcss';\nimport sheetStyles from '../styles/sheet.module.pcss';\nimport SheetBackdrop from '../sheetBackdrop';\nimport { usePopoverPosition } from './usePopoverPosition';\nimport { useFocusBoundary, tabbablesIn } from '../hooks/useFocusBoundary';\nimport { useSheet } from '../hooks/useSheet';\nimport { useOverlay } from '../hooks/useOverlay';\nimport { useComponentDefaults, usePresentationDefault } from '../configProvider';\nimport { Presentation } from '../floatingMenu/floatingMenu.types';\nimport { PopoverPlacement, PopoverAlign, PopoverTrigger, type PopoverProps } from './popover.types';\n\nfunction Popover(props: PopoverProps) {\n const {\n children = null,\n content = null,\n placement = PopoverPlacement.Bottom,\n align = PopoverAlign.Center,\n trigger = PopoverTrigger.Click,\n isOpen,\n defaultOpen = false,\n onOpenChange = () => {},\n offset = 10,\n withArrow = true,\n closeOnOutsideClick = true,\n closeOnEscape = true,\n openDelay = 100,\n closeDelay = 120,\n disabled = false,\n presentation: presentationProp,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Popover', props);\n const triggerRef = useRef<HTMLDivElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const arrowRef = useRef<HTMLDivElement>(null);\n const hoverTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const isControlled = isOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const open = isControlled ? isOpen : internalOpen;\n\n // Keep the outside-click/Escape listeners pointed at the latest setter without re-subscribing.\n const onOpenChangeRef = useRef(onOpenChange);\n useEffect(() => { onOpenChangeRef.current = onOpenChange; });\n\n const setOpen = useCallback((next: boolean) => {\n if (disabled && next) return;\n if (!isControlled) setInternalOpen(next);\n onOpenChangeRef.current(next);\n }, [disabled, isControlled]);\n\n // Explicit prop → this component's global default → the app-wide one → anchored.\n const appPresentation = usePresentationDefault();\n const presentation = presentationProp ?? appPresentation ?? Presentation.Default;\n const { isSheet: sheetPresentation, sheetStyle } = useSheet(presentation);\n // Hover and focus are pointer affordances that open something small next to what caused them;\n // a sheet is a deliberate, screen-owning open. Only a click asks for one.\n const isSheet = sheetPresentation && trigger === PopoverTrigger.Click;\n\n // A sheet isn't anchored to anything, so there's nothing to track, flip or clamp.\n usePopoverPosition({\n isOpen: !!open && !isSheet,\n placement,\n align,\n offset,\n triggerRef,\n floatingRef,\n panelRef,\n arrowRef: withArrow ? arrowRef : { current: null },\n });\n\n // Registered for as long as it's open, not just as a sheet: this is what puts the popover on\n // the overlay stack, so an enclosing Modal knows something sits above it and neither drags\n // focus out of this (portaled, so outside the modal's panel) panel nor closes itself on the\n // Escape meant for this. Focus isn't trapped: a Popover is deliberately non-modal, and it\n // already moves focus into the panel on open by itself.\n useOverlay({\n isActive: !!open,\n containerRef: panelRef,\n onEscape: closeOnEscape ? () => {\n // Hand focus back to the trigger when it currently sits inside the panel.\n if (floatingRef.current?.contains(document.activeElement)) {\n (tabbablesIn(triggerRef.current)[0] ?? triggerRef.current)?.focus();\n }\n setOpen(false);\n } : undefined,\n trapFocus: false,\n lockScroll: isSheet,\n });\n\n const { restoreFocusToTrigger, focusAfterTrigger } = useFocusBoundary({\n triggerRef,\n contentRef: floatingRef,\n });\n\n // The panel is portaled to the end of the DOM, so Tab never flows into it naturally. When we\n // manage focus (click trigger + focusable content), move focus in on open and, on Tab out of\n // either end, close and continue focus as if the panel sat right after the trigger.\n useEffect(() => {\n if (!open || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n // Only claim the dialog role when we're actually managing focus for real content.\n floatingRef.current?.setAttribute('role', 'dialog');\n focusables[0].focus();\n }, [open, trigger]);\n\n function handleFloatingKeyDown(event: React.KeyboardEvent) {\n if (event.key !== 'Tab' || trigger !== PopoverTrigger.Click) return;\n const focusables = tabbablesIn(panelRef.current);\n if (focusables.length === 0) return;\n const active = document.activeElement;\n if (!event.shiftKey && active === focusables[focusables.length - 1]) {\n event.preventDefault();\n focusAfterTrigger();\n setOpen(false);\n } else if (event.shiftKey && active === focusables[0]) {\n event.preventDefault();\n restoreFocusToTrigger();\n setOpen(false);\n }\n }\n\n // Outside click. Registered only while open and only for the relevant trigger mode; Escape is\n // handled by `useOverlay` above, which scopes it to the innermost open layer.\n useEffect(() => {\n if (!open) return;\n\n function onMouseUp(event: MouseEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n // Keyboard counterpart to the outside click: once focus leaves both the trigger\n // and the (portaled) panel — e.g. tabbing on to the next element — close.\n function onFocusIn(event: FocusEvent) {\n const target = event.target as Node;\n const inPanel = floatingRef.current?.contains(target);\n const inTrigger = triggerRef.current?.contains(target);\n if (!inPanel && !inTrigger) setOpen(false);\n }\n\n if (closeOnOutsideClick && trigger !== PopoverTrigger.Hover) {\n window.addEventListener('mouseup', onMouseUp);\n document.addEventListener('focusin', onFocusIn);\n }\n return () => {\n window.removeEventListener('mouseup', onMouseUp);\n document.removeEventListener('focusin', onFocusIn);\n };\n }, [open, closeOnOutsideClick, trigger, setOpen]);\n\n useEffect(() => () => clearTimeout(hoverTimer.current), []);\n\n function scheduleHover(next: boolean) {\n clearTimeout(hoverTimer.current);\n hoverTimer.current = setTimeout(() => setOpen(next), next ? openDelay : closeDelay);\n }\n\n const triggerHandlers =\n trigger === PopoverTrigger.Click\n ? { onClick: () => setOpen(!open) }\n : trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : { onFocus: () => setOpen(true), onBlur: () => setOpen(false) };\n\n const floatingHoverHandlers =\n trigger === PopoverTrigger.Hover\n ? { onMouseEnter: () => scheduleHover(true), onMouseLeave: () => scheduleHover(false) }\n : {};\n\n return (\n <div\n {...rest}\n className={cx(styles.popover, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div\n ref={triggerRef}\n className={cx(styles.popoverTrigger, classNames?.trigger)}\n style={slotStyles?.trigger}\n {...triggerHandlers}\n >\n {children}\n </div>\n {open && (\n <BodyEnd>\n {isSheet && (\n <SheetBackdrop\n onClose={() => { if (closeOnOutsideClick) setOpen(false); }}\n className={classNames?.backdrop}\n style={slotStyles?.backdrop}\n />\n )}\n <div\n ref={floatingRef}\n className={cx(isSheet ? sheetStyles.sheet : styles.popoverFloating, classNames?.floating)}\n style={{ ...(isSheet ? sheetStyle : undefined), ...slotStyles?.floating }}\n data-placement={placement}\n onKeyDown={handleFloatingKeyDown}\n {...floatingHoverHandlers}\n >\n <div\n ref={panelRef}\n className={cx(styles.popoverPanel, isSheet && sheetStyles.sheetPanel, classNames?.panel)}\n style={slotStyles?.panel}\n >\n {content}\n </div>\n {withArrow && !isSheet && (\n <div\n ref={arrowRef}\n className={cx(styles.popoverArrow, classNames?.arrow)}\n style={slotStyles?.arrow}\n />\n )}\n </div>\n </BodyEnd>\n )}\n </div>\n );\n}\n\nexport default Popover;\n"],"mappings":"s3BAeA,SAAS,EAAQ,EAAqB,CACpC,GAAM,CACN,WAAW,KACX,UAAU,KACV,YAAY,EAAiB,OAC7B,QAAQ,EAAa,OACrB,UAAU,EAAe,MACzB,SACA,cAAc,GACd,mBAAqB,CAAC,EACtB,UAAS,GACT,YAAY,GACZ,sBAAsB,GACtB,gBAAgB,GAChB,YAAY,IACZ,aAAa,IACb,WAAW,GACX,aAAc,EACd,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACC,EAAqB,UAAW,CAAK,EACnC,EAAa,EAAuB,IAAI,EACxC,EAAc,EAAuB,IAAI,EACzC,EAAW,EAAuB,IAAI,EACtC,EAAW,EAAuB,IAAI,EACtC,EAAa,EAAkD,IAAA,EAAS,EAExE,EAAe,IAAW,IAAA,GAC1B,CAAC,EAAc,GAAmB,GAAS,CAAW,EACtD,EAAO,EAAe,EAAS,EAG/B,EAAkB,EAAO,CAAY,EAC3C,MAAgB,CAAE,EAAgB,QAAU,CAAc,CAAC,EAE3D,IAAM,EAAU,EAAa,GAAkB,CACzC,GAAY,IACX,GAAc,EAAgB,CAAI,EACvC,EAAgB,QAAQ,CAAI,EAC9B,EAAG,CAAC,EAAU,CAAY,CAAC,EAGrB,GAAkB,EAAuB,EAEzC,CAAE,QAAS,GAAmB,eAAe,GAD9B,GAAoB,IAAmB,EAAa,OACD,EAGlE,EAAU,IAAqB,IAAY,EAAe,MAGhE,EAAmB,CACjB,OAAQ,CAAC,CAAC,GAAQ,CAAC,EACnB,YACA,QACA,UACA,aACA,cACA,WACA,SAAU,EAAY,EAAW,CAAE,QAAS,IAAK,CACnD,CAAC,EAOD,EAAW,CACT,SAAU,CAAC,CAAC,EACZ,aAAc,EACd,SAAU,MAAsB,CAE1B,EAAY,SAAS,SAAS,SAAS,aAAa,IACrD,EAAY,EAAW,OAAO,EAAE,IAAM,EAAW,UAAU,MAAM,EAEpE,EAAQ,EAAK,CACf,EAAI,IAAA,GACJ,UAAW,GACX,WAAY,CACd,CAAC,EAED,GAAM,CAAE,yBAAuB,sBAAsB,EAAiB,CACpE,aACA,WAAY,CACd,CAAC,EAKD,MAAgB,CACd,GAAI,CAAC,GAAQ,IAAY,EAAe,MAAO,OAC/C,IAAM,EAAa,EAAY,EAAS,OAAO,EAC3C,EAAW,SAAW,IAE1B,EAAY,SAAS,aAAa,OAAQ,QAAQ,EAClD,EAAW,GAAG,MAAM,EACtB,EAAG,CAAC,EAAM,CAAO,CAAC,EAElB,SAAS,GAAsB,EAA4B,CACzD,GAAI,EAAM,MAAQ,OAAS,IAAY,EAAe,MAAO,OAC7D,IAAM,EAAa,EAAY,EAAS,OAAO,EAC/C,GAAI,EAAW,SAAW,EAAG,OAC7B,IAAM,EAAS,SAAS,cACpB,CAAC,EAAM,UAAY,IAAW,EAAW,EAAW,OAAS,IAC/D,EAAM,eAAe,EACrB,GAAkB,EAClB,EAAQ,EAAK,GACJ,EAAM,UAAY,IAAW,EAAW,KACjD,EAAM,eAAe,EACrB,GAAsB,EACtB,EAAQ,EAAK,EAEjB,CAIA,MAAgB,CACd,GAAI,CAAC,EAAM,OAEX,SAAS,EAAU,EAAmB,CACpC,IAAM,EAAS,EAAM,OACf,EAAU,EAAY,SAAS,SAAS,CAAM,EAC9C,EAAY,EAAW,SAAS,SAAS,CAAM,EACjD,CAAC,GAAW,CAAC,GAAW,EAAQ,EAAK,CAC3C,CAGA,SAAS,EAAU,EAAmB,CACpC,IAAM,EAAS,EAAM,OACf,EAAU,EAAY,SAAS,SAAS,CAAM,EAC9C,EAAY,EAAW,SAAS,SAAS,CAAM,EACjD,CAAC,GAAW,CAAC,GAAW,EAAQ,EAAK,CAC3C,CAMA,OAJI,GAAuB,IAAY,EAAe,QACpD,OAAO,iBAAiB,UAAW,CAAS,EAC5C,SAAS,iBAAiB,UAAW,CAAS,OAEnC,CACX,OAAO,oBAAoB,UAAW,CAAS,EAC/C,SAAS,oBAAoB,UAAW,CAAS,CACnD,CACF,EAAG,CAAC,EAAM,EAAqB,EAAS,CAAO,CAAC,EAEhD,UAAsB,aAAa,EAAW,OAAO,EAAG,CAAC,CAAC,EAE1D,SAAS,EAAc,EAAe,CACpC,aAAa,EAAW,OAAO,EAC/B,EAAW,QAAU,eAAiB,EAAQ,CAAI,EAAG,EAAO,EAAY,CAAU,CACpF,CAEA,IAAM,GACJ,IAAY,EAAe,MACvB,CAAE,YAAe,EAAQ,CAAC,CAAI,CAAE,EAChC,IAAY,EAAe,MACzB,CAAE,iBAAoB,EAAc,EAAI,EAAG,iBAAoB,EAAc,EAAK,CAAE,EACpF,CAAE,YAAe,EAAQ,EAAI,EAAG,WAAc,EAAQ,EAAK,CAAE,EAE/D,GACJ,IAAY,EAAe,MACvB,CAAE,iBAAoB,EAAc,EAAI,EAAG,iBAAoB,EAAc,EAAK,CAAE,EACpF,CAAC,EAEP,OACE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EAAG,EAAO,QAAS,EAAW,GAAY,IAAI,EACzD,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,WAHzC,CAKE,EAAC,MAAD,CACE,IAAK,EACL,UAAW,EAAG,EAAO,eAAgB,GAAY,OAAO,EACxD,MAAO,GAAY,QACnB,GAAI,GAEH,UACE,CAAA,EACJ,GACC,EAAC,EAAD,CAAA,SAAA,CACG,GACC,EAAC,EAAD,CACE,YAAe,CAAM,GAAqB,EAAQ,EAAK,CAAG,EAC1D,UAAW,GAAY,SACvB,MAAO,GAAY,QACpB,CAAA,EAEH,EAAC,MAAD,CACE,IAAK,EACL,UAAW,EAAG,EAAU,EAAY,MAAQ,EAAO,gBAAiB,GAAY,QAAQ,EACxF,MAAO,CAAE,GAAI,EAAU,GAAa,IAAA,GAAY,GAAG,GAAY,QAAS,EACxE,iBAAgB,EAChB,UAAW,GACX,GAAI,YANN,CAQE,EAAC,MAAD,CACE,IAAK,EACL,UAAW,EAAG,EAAO,aAAc,GAAW,EAAY,WAAY,GAAY,KAAK,EACvF,MAAO,GAAY,eAElB,CACE,CAAA,EACJ,GAAa,CAAC,GACb,EAAC,MAAD,CACE,IAAK,EACL,UAAW,EAAG,EAAO,aAAc,GAAY,KAAK,EACpD,MAAO,GAAY,KACpB,CAAA,CAEA,GACE,CAAA,CAAA,CAER,GAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover.types.mjs","names":[],"sources":["../../../../package/common/popover/popover.types.ts"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Preferred side of the trigger the panel opens on. Flips to the opposite side when there's no room. */\nexport enum PopoverPlacement {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right',\n}\n\n/** Alignment along the trigger's cross axis (horizontal for top/bottom, vertical for left/right). */\nexport enum PopoverAlign {\n Start = 'start',\n Center = 'center',\n End = 'end',\n}\n\n/** What opens the popover. */\nexport enum PopoverTrigger {\n Click = 'click',\n Hover = 'hover',\n Focus = 'focus',\n}\n\nexport type PopoverSlots = 'root' | 'trigger' | 'floating' | 'panel' | 'arrow';\n\nexport interface PopoverProps extends Omit<HtmlProps, 'content'> {\n /** The trigger element. */\n children?: ReactNode;\n /** The popover body. */\n content?: ReactNode;\n /** Preferred side (default `Bottom`). */\n placement?: PopoverPlacement;\n /** Cross-axis alignment (default `Center`). */\n align?: PopoverAlign;\n /** What opens the popover (default `Click`). */\n trigger?: PopoverTrigger;\n /** Controlled open state. Omit for uncontrolled. */\n isOpen?: boolean;\n /** Initial open state when uncontrolled (default `false`). */\n defaultOpen?: boolean;\n /** Fires whenever the popover wants to open or close. */\n onOpenChange?: (isOpen: boolean) => void;\n /** Gap in px between trigger and panel (default `10`). */\n offset?: number;\n /** Render the arrow pointing at the trigger (default `true`). */\n withArrow?: boolean;\n /** Close when clicking outside the panel (default `true`). */\n closeOnOutsideClick?: boolean;\n /** Close when pressing Escape (default `true`). */\n closeOnEscape?: boolean;\n /** Delay in ms before a hover-triggered popover opens (default `100`). */\n openDelay?: number;\n /** Delay in ms before a hover-triggered popover closes (default `120`). */\n closeDelay?: number;\n /** Prevent the popover from opening. */\n disabled?: boolean;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<PopoverSlots>;\n styles?: SlotStyles<PopoverSlots>;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"popover.types.mjs","names":[],"sources":["../../../../package/common/popover/popover.types.ts"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\nimport type { Presentation } from '../floatingMenu/floatingMenu.types';\n\n/** Preferred side of the trigger the panel opens on. Flips to the opposite side when there's no room. */\nexport enum PopoverPlacement {\n Top = 'top',\n Bottom = 'bottom',\n Left = 'left',\n Right = 'right',\n}\n\n/** Alignment along the trigger's cross axis (horizontal for top/bottom, vertical for left/right). */\nexport enum PopoverAlign {\n Start = 'start',\n Center = 'center',\n End = 'end',\n}\n\n/** What opens the popover. */\nexport enum PopoverTrigger {\n Click = 'click',\n Hover = 'hover',\n Focus = 'focus',\n}\n\nexport type PopoverSlots = 'root' | 'trigger' | 'floating' | 'panel' | 'arrow' | 'backdrop';\n\nexport interface PopoverProps extends Omit<HtmlProps, 'content'> {\n /** The trigger element. */\n children?: ReactNode;\n /** The popover body. */\n content?: ReactNode;\n /** Preferred side (default `Bottom`). */\n placement?: PopoverPlacement;\n /** Cross-axis alignment (default `Center`). */\n align?: PopoverAlign;\n /** What opens the popover (default `Click`). */\n trigger?: PopoverTrigger;\n /** Controlled open state. Omit for uncontrolled. */\n isOpen?: boolean;\n /** Initial open state when uncontrolled (default `false`). */\n defaultOpen?: boolean;\n /** Fires whenever the popover wants to open or close. */\n onOpenChange?: (isOpen: boolean) => void;\n /** Gap in px between trigger and panel (default `10`). */\n offset?: number;\n /** Render the arrow pointing at the trigger (default `true`). */\n withArrow?: boolean;\n /** Close when clicking outside the panel (default `true`). */\n closeOnOutsideClick?: boolean;\n /** Close when pressing Escape (default `true`). */\n closeOnEscape?: boolean;\n /** Delay in ms before a hover-triggered popover opens (default `100`). */\n openDelay?: number;\n /** Delay in ms before a hover-triggered popover closes (default `120`). */\n closeDelay?: number;\n /** Prevent the popover from opening. */\n disabled?: boolean;\n /** Where the panel opens: anchored to the trigger (`Default`), pinned to the bottom of the\n * screen, or the latter only on a small touch screen. Only a `Click` trigger presents as a\n * sheet. */\n presentation?: Presentation;\n\n className?: string;\n style?: CSSProperties;\n classNames?: SlotClassNames<PopoverSlots>;\n styles?: SlotStyles<PopoverSlots>;\n}\n"],"mappings":"AAKA,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,IAAA,MACA,EAAA,OAAA,SACA,EAAA,KAAA,OACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA,EAGY,EAAL,SAAA,EAAA,OACL,GAAA,MAAA,QACA,EAAA,OAAA,SACA,EAAA,IAAA,OACF,EAAA,CAAA,CAAA,EAGY,EAAL,SAAA,EAAA,OACL,GAAA,MAAA,QACA,EAAA,MAAA,QACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{getScrollableAncestors as e,isHiddenByAnyAncestor as t}from"../utils/scrollAncestors.mjs";import{getVisualViewportRect as n}from"../utils/visualViewport.mjs";import{PopoverAlign as r,PopoverPlacement as i}from"./popover.types.mjs";import{useLayoutEffect as a}from"react";var o={[i.Top]:`bottom`,[i.Bottom]:`top`,[i.Left]:`right`,[i.Right]:`left`},s=8;function c({isOpen:c,placement:l,align:u,offset:d,triggerRef:f,floatingRef:p,panelRef:m,arrowRef:h}){a(()=>{if(!c)return;let a,g;function _(){let c=f.current,v=p.current,y=m.current;if(!c||!v||!y){a=requestAnimationFrame(_);return}let b=e(c);function x(){let e=c.getBoundingClientRect(),a=y.offsetWidth,f=y.offsetHeight,p=n(),m={top:e.top-p.top,bottom:p.top+p.height-e.bottom,left:e.left-p.left,right:p.left+p.width-e.right},g=l===i.Top||l===i.Bottom?f:a,_=l,x=o[l];m[_]<g+d&&m[x]>m[_]&&(_=x);let S=_===`top`||_===`bottom`,C,w;_===`bottom`?C=e.bottom+d:_===`top`?C=e.top-d-f:w=_===`right`?e.right+d:e.left-d-a,S?(w=u===r.Start?e.left:u===r.End?e.right-a:e.left+e.width/2-a/2,w=Math.max(p.left+s,Math.min(w,p.left+p.width-a-s))):(C=u===r.Start?e.top:u===r.End?e.bottom-f:e.top+e.height/2-f/2,C=Math.max(p.top+s,Math.min(C,p.top+p.height-f-s))),v.style.top=`${C}px`,v.style.left=`${w}px`,v.style.visibility=t(e,b)?`hidden`:`visible`,v.dataset.placement=_;let T=h.current;if(T){let t=T.offsetWidth/2||5;if(S){let n=e.left+e.width/2-w;T.style.setProperty(`--arrow-x`,`${Math.max(t+2,Math.min(n,a-t-2))}px`),T.style.removeProperty(`--arrow-y`)}else{let n=e.top+e.height/2-C;T.style.setProperty(`--arrow-y`,`${Math.max(t+2,Math.min(n,f-t-2))}px`),T.style.removeProperty(`--arrow-x`)}}}x();let S=[window,...b];S.forEach(e=>e.addEventListener(`scroll`,x,{passive:!0})),window.addEventListener(`resize`,x),window.visualViewport?.addEventListener(`resize`,x),window.visualViewport?.addEventListener(`scroll`,x),g=()=>{S.forEach(e=>e.removeEventListener(`scroll`,x)),window.removeEventListener(`resize`,x),window.visualViewport?.removeEventListener(`resize`,x),window.visualViewport?.removeEventListener(`scroll`,x)}}return _(),()=>{a!==void 0&&cancelAnimationFrame(a),g?.()}},[c,l,u,d,f,p,m,h])}export{c as usePopoverPosition};
|
|
1
|
+
import{getScrollableAncestors as e,isHiddenByAnyAncestor as t}from"../utils/scrollAncestors.mjs";import{getVisualViewportRect as n}from"../utils/visualViewport.mjs";import{PopoverAlign as r,PopoverPlacement as i}from"./popover.types.mjs";import{useLayoutEffect as a}from"react";var o={[i.Top]:`bottom`,[i.Bottom]:`top`,[i.Left]:`right`,[i.Right]:`left`},s=8;function c({isOpen:c,placement:l,align:u,offset:d,triggerRef:f,floatingRef:p,panelRef:m,arrowRef:h}){a(()=>{if(!c)return;let a,g;function _(){let c=f.current,v=p.current,y=m.current;if(!c||!v||!y){a=requestAnimationFrame(_);return}let b=e(c);function x(){let e=c.getBoundingClientRect(),a=y.offsetWidth,f=y.offsetHeight,p=n(),m={top:e.top-p.top,bottom:p.top+p.height-e.bottom,left:e.left-p.left,right:p.left+p.width-e.right},g=l===i.Top||l===i.Bottom?f:a,_=l,x=o[l];m[_]<g+d&&m[x]>m[_]&&(_=x);let S=_===`top`||_===`bottom`,C,w;_===`bottom`?C=e.bottom+d:_===`top`?C=e.top-d-f:w=_===`right`?e.right+d:e.left-d-a,S?(w=u===r.Start?e.left:u===r.End?e.right-a:e.left+e.width/2-a/2,w=Math.max(p.left+s,Math.min(w,p.left+p.width-a-s))):(C=u===r.Start?e.top:u===r.End?e.bottom-f:e.top+e.height/2-f/2,C=Math.max(p.top+s,Math.min(C,p.top+p.height-f-s))),v.style.top=`${C}px`,v.style.left=`${w}px`,v.style.visibility=t(e,b)?`hidden`:`visible`,v.dataset.placement=_;let T=h.current;if(T){let t=T.offsetWidth/2||5;if(S){let n=e.left+e.width/2-w;T.style.setProperty(`--arrow-x`,`${Math.max(t+2,Math.min(n,a-t-2))}px`),T.style.removeProperty(`--arrow-y`)}else{let n=e.top+e.height/2-C;T.style.setProperty(`--arrow-y`,`${Math.max(t+2,Math.min(n,f-t-2))}px`),T.style.removeProperty(`--arrow-x`)}}}x();let S=[window,...b];S.forEach(e=>e.addEventListener(`scroll`,x,{passive:!0})),window.addEventListener(`resize`,x),window.visualViewport?.addEventListener(`resize`,x),window.visualViewport?.addEventListener(`scroll`,x),g=()=>{S.forEach(e=>e.removeEventListener(`scroll`,x)),window.removeEventListener(`resize`,x),window.visualViewport?.removeEventListener(`resize`,x),window.visualViewport?.removeEventListener(`scroll`,x),v.style.top=``,v.style.left=``,v.style.visibility=``}}return _(),()=>{a!==void 0&&cancelAnimationFrame(a),g?.()}},[c,l,u,d,f,p,m,h])}export{c as usePopoverPosition};
|
|
2
2
|
//# sourceMappingURL=usePopoverPosition.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePopoverPosition.mjs","names":[],"sources":["../../../../package/common/popover/usePopoverPosition.ts"],"sourcesContent":["import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\nimport { getVisualViewportRect } from 'components/common/utils/visualViewport';\nimport { PopoverPlacement, PopoverAlign } from './popover.types';\n\ntype Axis = 'top' | 'bottom' | 'left' | 'right';\nconst OPPOSITE: Record<PopoverPlacement, Axis> = {\n [PopoverPlacement.Top]: 'bottom',\n [PopoverPlacement.Bottom]: 'top',\n [PopoverPlacement.Left]: 'right',\n [PopoverPlacement.Right]: 'left',\n};\n\nconst MARGIN = 8; // viewport gutter kept clear when shifting a panel back on-screen\n\nexport interface UsePopoverPositionArgs {\n isOpen: boolean;\n placement: PopoverPlacement;\n align: PopoverAlign;\n offset: number;\n triggerRef: RefObject<HTMLElement | null>;\n /** `position: fixed` wrapper that receives top/left/visibility and the resolved-placement data attribute. */\n floatingRef: RefObject<HTMLElement | null>;\n /** Visible panel, measured to decide flip and shift. */\n panelRef: RefObject<HTMLElement | null>;\n /** Arrow element; gets `--arrow-x` / `--arrow-y` written to it. Pass a null ref when `withArrow` is false. */\n arrowRef: RefObject<HTMLElement | null>;\n}\n\n/**\n * Positions a portaled, `position: fixed` popover on any of the four sides of its trigger with\n * start/center/end cross-axis alignment. Flips to the opposite side when the preferred one has no\n * room, shifts back on-screen along the cross axis, points the arrow at the trigger centre, and\n * hides (not closes) the panel once the trigger scrolls behind a clipping ancestor. Position is\n * written straight to the DOM via refs — going through setState lags the browser's scroll paint.\n */\nexport function usePopoverPosition({\n isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef,\n}: UsePopoverPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The portal target (BodyEnd's #bodyEnd) can still be missing on the first commit, so the\n // floating ref lands one render later. Refs don't re-fire the effect, so retry each frame.\n function trySetup() {\n const trigger = triggerRef.current;\n const floating = floatingRef.current;\n const panel = panelRef.current;\n if (!trigger || !floating || !panel) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const t = trigger!.getBoundingClientRect();\n const pw = panel!.offsetWidth;\n const ph = panel!.offsetHeight;\n // The visible area, not the full layout viewport — shrinks on mobile when a keyboard is\n // open, so the panel flips/clamps against what's actually on screen instead of ending up\n // hidden behind the keyboard.\n const vv = getVisualViewportRect();\n\n // Resolve the main-axis side, flipping when the preferred side lacks room and the\n // opposite side has more.\n const room: Record<Axis, number> = {\n top: t.top - vv.top,\n bottom: vv.top + vv.height - t.bottom,\n left: t.left - vv.left,\n right: vv.left + vv.width - t.right,\n };\n const need = (placement === PopoverPlacement.Top || placement === PopoverPlacement.Bottom) ? ph : pw;\n let side: Axis = placement as unknown as Axis;\n const opp = OPPOSITE[placement];\n if (room[side] < need + offset && room[opp] > room[side]) side = opp;\n\n const vertical = side === 'top' || side === 'bottom';\n\n // Main axis: place the panel just outside the trigger on the resolved side.\n let top: number;\n let left: number;\n if (side === 'bottom') { top = t.bottom + offset; }\n else if (side === 'top') { top = t.top - offset - ph; }\n else if (side === 'right') { left = t.right + offset; }\n else { left = t.left - offset - pw; }\n\n // Cross axis: align start/center/end against the trigger, then shift on-screen.\n if (vertical) {\n if (align === PopoverAlign.Start) left = t.left;\n else if (align === PopoverAlign.End) left = t.right - pw;\n else left = t.left + t.width / 2 - pw / 2;\n left = Math.max(vv.left + MARGIN, Math.min(left!, vv.left + vv.width - pw - MARGIN));\n } else {\n if (align === PopoverAlign.Start) top = t.top;\n else if (align === PopoverAlign.End) top = t.bottom - ph;\n else top = t.top + t.height / 2 - ph / 2;\n top = Math.max(vv.top + MARGIN, Math.min(top!, vv.top + vv.height - ph - MARGIN));\n }\n\n floating!.style.top = `${top!}px`;\n floating!.style.left = `${left!}px`;\n floating!.style.visibility = isHiddenByAnyAncestor(t, ancestors) ? 'hidden' : 'visible';\n floating!.dataset.placement = side;\n\n // Arrow: centre it on the trigger along the cross axis, clamped inside the panel edges.\n const arrow = arrowRef.current;\n if (arrow) {\n const half = arrow.offsetWidth / 2 || 5;\n if (vertical) {\n const x = t.left + t.width / 2 - left!;\n arrow.style.setProperty('--arrow-x', `${Math.max(half + 2, Math.min(x, pw - half - 2))}px`);\n arrow.style.removeProperty('--arrow-y');\n } else {\n const y = t.top + t.height / 2 - top!;\n arrow.style.setProperty('--arrow-y', `${Math.max(half + 2, Math.min(y, ph - half - 2))}px`);\n arrow.style.removeProperty('--arrow-x');\n }\n }\n }\n\n updatePos();\n\n const scrollTargets: (Window | HTMLElement)[] = [window, ...ancestors];\n scrollTargets.forEach((tt) => tt.addEventListener('scroll', updatePos, { passive: true }));\n window.addEventListener('resize', updatePos);\n // `window.resize` doesn't reliably fire when a mobile keyboard opens/closes — visualViewport\n // does, and is what the room/clamp math above is measured against.\n window.visualViewport?.addEventListener('resize', updatePos);\n window.visualViewport?.addEventListener('scroll', updatePos);\n teardown = () => {\n scrollTargets.forEach((tt) => tt.removeEventListener('scroll', updatePos));\n window.removeEventListener('resize', updatePos);\n window.visualViewport?.removeEventListener('resize', updatePos);\n window.visualViewport?.removeEventListener('scroll', updatePos);\n };\n }\n\n trySetup();\n\n return () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n teardown?.();\n };\n }, [isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef]);\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"usePopoverPosition.mjs","names":[],"sources":["../../../../package/common/popover/usePopoverPosition.ts"],"sourcesContent":["import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\nimport { getVisualViewportRect } from 'components/common/utils/visualViewport';\nimport { PopoverPlacement, PopoverAlign } from './popover.types';\n\ntype Axis = 'top' | 'bottom' | 'left' | 'right';\nconst OPPOSITE: Record<PopoverPlacement, Axis> = {\n [PopoverPlacement.Top]: 'bottom',\n [PopoverPlacement.Bottom]: 'top',\n [PopoverPlacement.Left]: 'right',\n [PopoverPlacement.Right]: 'left',\n};\n\nconst MARGIN = 8; // viewport gutter kept clear when shifting a panel back on-screen\n\nexport interface UsePopoverPositionArgs {\n isOpen: boolean;\n placement: PopoverPlacement;\n align: PopoverAlign;\n offset: number;\n triggerRef: RefObject<HTMLElement | null>;\n /** `position: fixed` wrapper that receives top/left/visibility and the resolved-placement data attribute. */\n floatingRef: RefObject<HTMLElement | null>;\n /** Visible panel, measured to decide flip and shift. */\n panelRef: RefObject<HTMLElement | null>;\n /** Arrow element; gets `--arrow-x` / `--arrow-y` written to it. Pass a null ref when `withArrow` is false. */\n arrowRef: RefObject<HTMLElement | null>;\n}\n\n/**\n * Positions a portaled, `position: fixed` popover on any of the four sides of its trigger with\n * start/center/end cross-axis alignment. Flips to the opposite side when the preferred one has no\n * room, shifts back on-screen along the cross axis, points the arrow at the trigger centre, and\n * hides (not closes) the panel once the trigger scrolls behind a clipping ancestor. Position is\n * written straight to the DOM via refs — going through setState lags the browser's scroll paint.\n */\nexport function usePopoverPosition({\n isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef,\n}: UsePopoverPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The portal target (BodyEnd's #bodyEnd) can still be missing on the first commit, so the\n // floating ref lands one render later. Refs don't re-fire the effect, so retry each frame.\n function trySetup() {\n const trigger = triggerRef.current;\n const floating = floatingRef.current;\n const panel = panelRef.current;\n if (!trigger || !floating || !panel) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const t = trigger!.getBoundingClientRect();\n const pw = panel!.offsetWidth;\n const ph = panel!.offsetHeight;\n // The visible area, not the full layout viewport — shrinks on mobile when a keyboard is\n // open, so the panel flips/clamps against what's actually on screen instead of ending up\n // hidden behind the keyboard.\n const vv = getVisualViewportRect();\n\n // Resolve the main-axis side, flipping when the preferred side lacks room and the\n // opposite side has more.\n const room: Record<Axis, number> = {\n top: t.top - vv.top,\n bottom: vv.top + vv.height - t.bottom,\n left: t.left - vv.left,\n right: vv.left + vv.width - t.right,\n };\n const need = (placement === PopoverPlacement.Top || placement === PopoverPlacement.Bottom) ? ph : pw;\n let side: Axis = placement as unknown as Axis;\n const opp = OPPOSITE[placement];\n if (room[side] < need + offset && room[opp] > room[side]) side = opp;\n\n const vertical = side === 'top' || side === 'bottom';\n\n // Main axis: place the panel just outside the trigger on the resolved side.\n let top: number;\n let left: number;\n if (side === 'bottom') { top = t.bottom + offset; }\n else if (side === 'top') { top = t.top - offset - ph; }\n else if (side === 'right') { left = t.right + offset; }\n else { left = t.left - offset - pw; }\n\n // Cross axis: align start/center/end against the trigger, then shift on-screen.\n if (vertical) {\n if (align === PopoverAlign.Start) left = t.left;\n else if (align === PopoverAlign.End) left = t.right - pw;\n else left = t.left + t.width / 2 - pw / 2;\n left = Math.max(vv.left + MARGIN, Math.min(left!, vv.left + vv.width - pw - MARGIN));\n } else {\n if (align === PopoverAlign.Start) top = t.top;\n else if (align === PopoverAlign.End) top = t.bottom - ph;\n else top = t.top + t.height / 2 - ph / 2;\n top = Math.max(vv.top + MARGIN, Math.min(top!, vv.top + vv.height - ph - MARGIN));\n }\n\n floating!.style.top = `${top!}px`;\n floating!.style.left = `${left!}px`;\n floating!.style.visibility = isHiddenByAnyAncestor(t, ancestors) ? 'hidden' : 'visible';\n floating!.dataset.placement = side;\n\n // Arrow: centre it on the trigger along the cross axis, clamped inside the panel edges.\n const arrow = arrowRef.current;\n if (arrow) {\n const half = arrow.offsetWidth / 2 || 5;\n if (vertical) {\n const x = t.left + t.width / 2 - left!;\n arrow.style.setProperty('--arrow-x', `${Math.max(half + 2, Math.min(x, pw - half - 2))}px`);\n arrow.style.removeProperty('--arrow-y');\n } else {\n const y = t.top + t.height / 2 - top!;\n arrow.style.setProperty('--arrow-y', `${Math.max(half + 2, Math.min(y, ph - half - 2))}px`);\n arrow.style.removeProperty('--arrow-x');\n }\n }\n }\n\n updatePos();\n\n const scrollTargets: (Window | HTMLElement)[] = [window, ...ancestors];\n scrollTargets.forEach((tt) => tt.addEventListener('scroll', updatePos, { passive: true }));\n window.addEventListener('resize', updatePos);\n // `window.resize` doesn't reliably fire when a mobile keyboard opens/closes — visualViewport\n // does, and is what the room/clamp math above is measured against.\n window.visualViewport?.addEventListener('resize', updatePos);\n window.visualViewport?.addEventListener('scroll', updatePos);\n teardown = () => {\n scrollTargets.forEach((tt) => tt.removeEventListener('scroll', updatePos));\n window.removeEventListener('resize', updatePos);\n window.visualViewport?.removeEventListener('resize', updatePos);\n window.visualViewport?.removeEventListener('scroll', updatePos);\n // Positioning is written as inline styles, which outrank any class the panel might\n // switch to while it stays mounted — a popover turning into a bottom sheet (`useSheet`)\n // would keep the coordinates computed for its anchored self.\n floating!.style.top = '';\n floating!.style.left = '';\n floating!.style.visibility = '';\n };\n }\n\n trySetup();\n\n return () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n teardown?.();\n };\n }, [isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef]);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"../styles/sheet.module.mjs";import{useEffect as t,useRef as n}from"react";import r from"classnames";import{jsx as i}from"react/jsx-runtime";var a=[`pointerdown`,`pointerup`,`mousedown`,`mouseup`,`touchstart`,`touchend`];function o({onClose:o,className:s,style:c}){let l=n(null);return t(()=>{let e=l.current;if(!e)return;let t=e=>e.stopPropagation();return a.forEach(n=>e.addEventListener(n,t)),()=>a.forEach(n=>e.removeEventListener(n,t))},[]),i(`div`,{ref:l,className:r(e.sheetBackdrop,s),style:c,onClick:e=>{e.stopPropagation(),o()}})}export{o as default};
|
|
2
|
+
//# sourceMappingURL=sheetBackdrop.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sheetBackdrop.mjs","names":[],"sources":["../../../../package/common/sheetBackdrop/sheetBackdrop.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport cx from 'classnames';\n\nimport styles from '../styles/sheet.module.pcss';\nimport type { SheetBackdropProps } from './sheetBackdrop.types';\n\n/** The pointer events a popup's own outside-click handling listens for. */\nconst SWALLOWED_EVENTS = ['pointerdown', 'pointerup', 'mousedown', 'mouseup', 'touchstart', 'touchend'];\n\n/**\n * The dimmed layer behind a bottom sheet, and the thing that closes it when tapped.\n *\n * It closes on its own `click` rather than letting the sheet's usual outside-click handling see\n * the press, because that handling fires on mousedown/mouseup — and the sheet, backdrop included,\n * unmounts the moment it closes. The browser then dispatches the `click` that completes the tap\n * at whatever is under the cursor by then, which is the page behind the sheet: tapping to dismiss\n * would also press a button underneath it.\n *\n * The press is stopped with native listeners rather than React's `stopPropagation`, which would\n * not be enough: React listens at its own root container, so a native handler on `document` or\n * `window` still runs afterwards.\n */\nfunction SheetBackdrop({ onClose, className, style }: SheetBackdropProps) {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n const stop = (event: Event) => event.stopPropagation();\n SWALLOWED_EVENTS.forEach((type) => element.addEventListener(type, stop));\n return () => SWALLOWED_EVENTS.forEach((type) => element.removeEventListener(type, stop));\n }, []);\n\n return (\n <div\n ref={ref}\n className={cx(styles.sheetBackdrop, className)}\n style={style}\n onClick={(event) => {\n event.stopPropagation();\n onClose();\n }}\n />\n );\n}\n\nexport default SheetBackdrop;\n"],"mappings":"0JAOA,IAAM,EAAmB,CAAC,cAAe,YAAa,YAAa,UAAW,aAAc,UAAU,EAetG,SAAS,EAAc,CAAE,UAAS,YAAW,SAA6B,CACxE,IAAM,EAAM,EAAuB,IAAI,EAUvC,OARA,MAAgB,CACd,IAAM,EAAU,EAAI,QACpB,GAAI,CAAC,EAAS,OACd,IAAM,EAAQ,GAAiB,EAAM,gBAAgB,EAErD,OADA,EAAiB,QAAS,GAAS,EAAQ,iBAAiB,EAAM,CAAI,CAAC,MAC1D,EAAiB,QAAS,GAAS,EAAQ,oBAAoB,EAAM,CAAI,CAAC,CACzF,EAAG,CAAC,CAAC,EAGH,EAAC,MAAD,CACO,MACL,UAAW,EAAG,EAAO,cAAe,CAAS,EACtC,QACP,QAAU,GAAU,CAClB,EAAM,gBAAgB,EACtB,EAAQ,CACV,CACD,CAAA,CAEL"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e={sheet:`sheet_cfS92`,sheetSlideIn:`sheetSlideIn_wF6l0`,"sheet-surface":`sheet-surface_-vvdd`,sheetSurface:`sheet-surface_-vvdd`,"sheet-panel":`sheet-panel_HPJjL sheet-surface_-vvdd`,sheetPanel:`sheet-panel_HPJjL sheet-surface_-vvdd`,"sheet-scroll":`sheet-scroll_nda2p`,sheetScroll:`sheet-scroll_nda2p`,"sheet-backdrop":`sheet-backdrop_B-S70`,sheetBackdrop:`sheet-backdrop_B-S70`,sheetBackdropFadeIn:`sheetBackdropFadeIn_MJUJq`};export{e as default};
|
|
2
|
+
//# sourceMappingURL=sheet.module.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sheet.module.mjs","names":[],"sources":["../../../../package/common/styles/sheet.module.pcss"],"sourcesContent":["/*\n * Bottom-sheet presentation, shared by every popup that can switch away from being anchored to\n * its trigger (see `useSheet`).\n *\n * Every selector is doubled (`.sheet.sheet`) on purpose: these classes land on the same elements\n * as a component's own single-class panel styles and have to win over them. Which of two\n * equal-specificity rules wins otherwise depends on the order the bundler happens to emit the\n * two CSS modules in, which is not something a component should have to depend on.\n */\n\n.sheet.sheet {\n position: fixed;\n left: 0;\n right: 0;\n margin: 0 auto;\n width: 100%;\n /* Wide enough for a comfortable list on a phone, narrow enough not to span a tablet. */\n max-width: 560px;\n max-height: var(--sheet-max-height, 70vh);\n max-height: var(--sheet-max-height, 70dvh);\n display: flex;\n flex-direction: column;\n z-index: 1;\n animation: sheetSlideIn 0.2s ease-out;\n}\n\n/* What a sheet looks like where it meets the screen, split out from `.sheet-panel` because a\n component whose own root is the surface (Modal) needs the look without the fill-the-root\n layout below it. */\n.sheet-surface.sheet-surface {\n overscroll-behavior: contain;\n border-radius: calc(var(--default-border-radius) + 4px) calc(var(--default-border-radius) + 4px) 0 0;\n /* Clears the home indicator on a phone without leaving a gap on a device that has none. */\n padding-bottom: max(var(--sheet-safe-padding, 8px), env(safe-area-inset-bottom));\n}\n\n.sheet-panel {\n composes: sheet-surface;\n}\n\n.sheet-panel.sheet-panel {\n position: static;\n width: 100%;\n box-sizing: border-box;\n margin: 0;\n display: flex;\n flex-direction: column;\n min-height: 0;\n max-height: 100%;\n /* Overrides a panel that caps its own width when anchored, e.g. Popover's 320px. */\n max-width: 100%;\n /* The sheet root owns the entrance animation; a panel that scales itself in when anchored\n (Popover) would otherwise play a second, conflicting one on top of the slide-up. */\n animation: none;\n overflow-y: auto;\n}\n\n/* For an inner list that caps its own height when anchored: the sheet caps the height instead. */\n.sheet-scroll.sheet-scroll {\n max-height: none;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n.sheet-backdrop.sheet-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: #00000052;\n z-index: 1;\n animation: sheetBackdropFadeIn 0.2s ease-out;\n}\n\n@keyframes sheetSlideIn {\n from {\n transform: translateY(100%);\n }\n to {\n transform: translateY(0);\n }\n}\n\n@keyframes sheetBackdropFadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n"],"mappings":""}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AccordionStyleType as e}from"./common/accordion/accordion.types.mjs";import t from"./common/configProvider/configProvider.mjs";import{useComponentDefaults as n}from"./common/configProvider/useComponentDefaults.mjs";import r from"./common/accordion/accordion.mjs";import
|
|
1
|
+
import{AccordionStyleType as e}from"./common/accordion/accordion.types.mjs";import t from"./common/configProvider/configProvider.mjs";import{useComponentDefaults as n}from"./common/configProvider/useComponentDefaults.mjs";import{usePresentationDefault as r}from"./common/configProvider/usePresentationDefault.mjs";import i from"./common/accordion/accordion.mjs";import a from"./common/loading/spinnerLoading/index.mjs";import{ButtonSize as o,ButtonStyleType as s,ButtonType as c}from"./common/button/button.types.mjs";import l from"./common/ripple/ripple.mjs";import u from"./common/button/button.mjs";import d from"./common/actionButtons/actionButtons.mjs";import f from"./common/interactableDiv/index.mjs";import p from"./common/actionIcon/actionIcon.mjs";import{AlertStyleType as m}from"./common/alert/alert.types.mjs";import h from"./common/alert/alert.mjs";import g from"./common/animatedLogo/animatedLogo.mjs";import{AnimatedTextUnit as _,AnimatedTextVariant as v}from"./common/animatedText/animatedText.types.mjs";import y from"./common/animatedText/animatedText.mjs";import{BadgePosition as b,BadgeStyleType as x}from"./common/badge/badge.types.mjs";import S from"./common/badge/badge.mjs";import C from"./common/avatar/avatar.mjs";import w from"./common/avatar/avatarGroup.mjs";import T from"./common/bodyEnd/bodyEnd.mjs";import{Align as E,Presentation as D}from"./common/floatingMenu/floatingMenu.types.mjs";import O from"./common/floatingMenu/floatingMenu.mjs";import k from"./common/breadcrumb/breadcrumb.mjs";import{ButtonGroupOrientation as A}from"./common/buttonGroup/buttonGroup.types.mjs";import j from"./common/buttonGroup/buttonGroup.mjs";import{CardStyleType as M}from"./common/card/card.types.mjs";import N from"./common/card/Card.mjs";import P from"./common/card/CardHeader.mjs";import F from"./common/card/CardMedia.mjs";import I from"./common/card/CardContent.mjs";import L from"./common/card/CardActions.mjs";import R from"./common/carousel/carousel.mjs";import z from"./common/checkbox/checkbox.mjs";import{ChipStyleType as B}from"./common/chip/chip.types.mjs";import V from"./common/chip/chip.mjs";import H from"./common/chip/chipContainer.mjs";import U from"./common/tooltip/tooltip.mjs";import{InputIconPosition as W,InputType as G}from"./common/input/input.types.mjs";import K from"./common/input/input.mjs";import q from"./common/colorPicker/colorPicker.mjs";import J from"./common/modal/modal.mjs";import Y from"./common/confirmModal/confirmModal.mjs";import{getLocale as X,mapLocale as Z,setLocale as Q}from"./services/localization.mjs";import $ from"./common/infiniteBlock/infiniteBlock.mjs";import ee from"./common/dropdown/dropdown.mjs";import te from"./common/datePicker/datePicker.mjs";import{DividerOrientation as ne,DividerTextPosition as re}from"./common/divider/divider.types.mjs";import ie from"./common/divider/divider.mjs";import ae from"./common/drawer/drawer.mjs";import{DropZoneReturnType as oe,DropZoneStatus as se}from"./common/dropZone/dropZone.types.mjs";import ce from"./common/dropZone/dropZone.mjs";import le from"./common/emptyState/emptyState.mjs";import{showToast as ue}from"./common/toast/toastService.mjs";import de from"./common/toast/toastProvider.mjs";import fe from"./common/errorBoundary/errorBoundary.mjs";import pe from"./common/fab/fab.mjs";import me from"./common/flip/flip.mjs";import he from"./common/iconPicker/iconPicker.mjs";import ge from"./common/idleManager/idleManager.mjs";import _e from"./common/inputDropdown/inputDropdown.mjs";import ve from"./common/kanbanBoard/KanbanColumn.mjs";import ye from"./common/kanbanBoard/KanbanBoard.mjs";import be from"./common/searchInput/searchInput.mjs";import xe from"./common/klipyPicker/klipyPicker.mjs";import Se from"./common/loading/iconLoading/index.mjs";import Ce from"./common/numberInput/index.mjs";import we from"./common/optionPicker/optionPicker.mjs";import{OtpInputCharset as Te}from"./common/otpInput/otpInput.types.mjs";import Ee from"./common/otpInput/otpInput.mjs";import De from"./common/overscroll/overscroll.mjs";import{PopoverAlign as Oe,PopoverPlacement as ke,PopoverTrigger as Ae}from"./common/popover/popover.types.mjs";import je from"./common/popover/popover.mjs";import Me from"./common/progressBar/progressBar.mjs";import{RadioGroupOrientation as Ne}from"./common/radioGroup/radioGroup.types.mjs";import Pe from"./common/radioGroup/radioGroup.mjs";import Fe from"./common/rating/rating.mjs";import Ie from"./common/revealLens/revealLens.mjs";import Le from"./common/roomDrawer/roomDrawer.mjs";import Re from"./common/roomViewer/roomViewer.mjs";import ze from"./common/scrollbarProvider/index.mjs";import{SectionHeaderSize as Be}from"./common/sectionHeader/sectionHeader.types.mjs";import Ve from"./common/sectionHeader/sectionHeader.mjs";import{SkeletonAnimation as He,SkeletonVariant as Ue}from"./common/skeleton/skeleton.types.mjs";import We from"./common/skeleton/skeleton.mjs";import Ge from"./common/slider/slider.mjs";import Ke from"./common/splitButton/splitButton.mjs";import{StepperAlignment as qe,StepperCollapse as Je,StepperLabelPlacement as Ye,StepperStyleType as Xe}from"./common/stepper/stepper.types.mjs";import Ze from"./common/stepper/stepper.mjs";import Qe from"./common/sticky/sticky.mjs";import $e from"./common/switch/switch.mjs";import et from"./common/tabHeader/tabHeader.mjs";import tt from"./common/textarea/textarea.mjs";import{defaultTheme as nt}from"./common/themeProvider/defaultTheme.mjs";import rt from"./common/themeProvider/themeProvider.mjs";import{useTheme as it}from"./common/themeProvider/useTheme.mjs";import at,{TiltGroupContext as ot,useTiltGroup as st}from"./common/tiltGroup/tiltGroup.mjs";import{defaultTiltEasing as ct}from"./common/tilt/tiltMath.mjs";import lt from"./common/tilt/tilt.mjs";import ut from"./common/timeInput/timeInput.mjs";import{TimelineAlignment as dt,TimelineItemStatus as ft}from"./common/timeline/timeline.types.mjs";import pt from"./common/timeline/timeline.mjs";import mt from"./common/timer/timer.mjs";import ht from"./common/virtualList/virtualList.mjs";import gt from"./common/wizard/wizard.mjs";import _t from"./services/formValidation/FormValidatorGroupWithForm.mjs";import vt from"./services/formValidation/validatableComponent.mjs";import{useFormValidatorGroup as yt}from"./services/formValidation/useFormValidatorGroup.mjs";import{FormValidator as bt,Validators as xt,useFormValidator as St}from"./services/formValidation/index.mjs";import{hasEightPasswordChars as Ct,hasOnePasswordDigit as wt,hasOnePasswordLetter as Tt,isBic as Et,isDate as Dt,isEmail as Ot,isISODate as kt,isNumber as At,isPassword as jt,isURL as Mt}from"@ahrowe/form-validation";export{i as Accordion,e as AccordionStyleType,d as ActionButtons,p as ActionIcon,h as Alert,m as AlertStyleType,E as Align,g as AnimatedLogo,y as AnimatedText,_ as AnimatedTextUnit,v as AnimatedTextVariant,C as Avatar,w as AvatarGroup,S as Badge,b as BadgePosition,x as BadgeStyleType,T as BodyEnd,k as Breadcrumb,u as Button,j as ButtonGroup,A as ButtonGroupOrientation,o as ButtonSize,s as ButtonStyleType,c as ButtonType,N as Card,L as CardActions,I as CardContent,P as CardHeader,F as CardMedia,M as CardStyleType,R as Carousel,z as Checkbox,V as Chip,H as ChipContainer,B as ChipStyleType,q as ColorPicker,t as ConfigProvider,Y as ConfirmModal,te as DatePicker,ie as Divider,ne as DividerOrientation,re as DividerTextPosition,ae as Drawer,ce as DropZone,oe as DropZoneReturnType,se as DropZoneStatus,ee as Dropdown,le as EmptyState,fe as ErrorBoundary,pe as Fab,me as Flip,O as FloatingMenu,bt as FormValidator,_t as FormValidatorGroup,Se as IconLoading,he as IconPicker,ge as IdleManager,$ as InfiniteBlock,K as Input,_e as InputDropdown,W as InputIconPosition,G as InputType,f as InteractableDiv,ye as KanbanBoard,ve as KanbanColumn,xe as KlipyPicker,J as Modal,Ce as NumberInput,we as OptionPicker,Ee as OtpInput,Te as OtpInputCharset,De as Overscroll,je as Popover,Oe as PopoverAlign,ke as PopoverPlacement,Ae as PopoverTrigger,D as Presentation,Me as ProgressBar,Pe as RadioGroup,Ne as RadioGroupOrientation,Fe as Rating,Ie as RevealLens,l as Ripple,Le as RoomDrawer,Re as RoomViewer,ze as ScrollbarProvider,be as SearchInput,Ve as SectionHeader,Be as SectionHeaderSize,We as Skeleton,He as SkeletonAnimation,Ue as SkeletonVariant,Ge as Slider,a as SpinnerLoading,Ke as SplitButton,Ze as Stepper,qe as StepperAlignment,Je as StepperCollapse,Ye as StepperLabelPlacement,Xe as StepperStyleType,Qe as Sticky,$e as Switch,et as TabHeader,tt as Textarea,rt as ThemeProvider,lt as Tilt,at as TiltGroup,ot as TiltGroupContext,ut as TimeInput,pt as Timeline,dt as TimelineAlignment,ft as TimelineItemStatus,mt as Timer,de as ToastProvider,U as Tooltip,vt as ValidatableComponent,xt as Validators,ht as VirtualList,gt as Wizard,nt as defaultTheme,ct as defaultTiltEasing,X as getLocale,Ct as hasEightPasswordChars,wt as hasOnePasswordDigit,Tt as hasOnePasswordLetter,Et as isBic,Dt as isDate,Ot as isEmail,kt as isISODate,At as isNumber,jt as isPassword,Mt as isURL,Z as mapLocale,Q as setLocale,ue as showToast,n as useComponentDefaults,St as useFormValidator,yt as useFormValidatorGroup,r as usePresentationDefault,it as useTheme,st as useTiltGroup};
|