@mortenbrudvik/waveui 0.4.0 → 0.7.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/README.md +1221 -173
- package/dist/_virtual/_rolldown/runtime.cjs +1 -0
- package/dist/components/button/Button.cjs +2 -0
- package/dist/components/button/Button.cjs.map +1 -0
- package/dist/components/button/Button.mjs +50 -0
- package/dist/components/button/Button.mjs.map +1 -0
- package/dist/components/button/Button.semantics.cjs +2 -0
- package/dist/components/button/Button.semantics.cjs.map +1 -0
- package/dist/components/button/Button.semantics.mjs +61 -0
- package/dist/components/button/Button.semantics.mjs.map +1 -0
- package/dist/components/button/Button.slots.cjs +2 -0
- package/dist/components/button/Button.slots.cjs.map +1 -0
- package/dist/components/button/Button.slots.mjs +47 -0
- package/dist/components/button/Button.slots.mjs.map +1 -0
- package/dist/components/button/CompoundButton.cjs +2 -0
- package/dist/components/button/CompoundButton.cjs.map +1 -0
- package/dist/components/button/CompoundButton.mjs +53 -0
- package/dist/components/button/CompoundButton.mjs.map +1 -0
- package/dist/components/button/Link.cjs +2 -0
- package/dist/components/button/Link.cjs.map +1 -0
- package/dist/components/button/Link.mjs +37 -0
- package/dist/components/button/Link.mjs.map +1 -0
- package/dist/components/button/MenuButton.cjs +2 -0
- package/dist/components/button/MenuButton.cjs.map +1 -0
- package/dist/components/button/MenuButton.mjs +45 -0
- package/dist/components/button/MenuButton.mjs.map +1 -0
- package/dist/components/button/SplitButton.cjs +2 -0
- package/dist/components/button/SplitButton.cjs.map +1 -0
- package/dist/components/button/SplitButton.mjs +66 -0
- package/dist/components/button/SplitButton.mjs.map +1 -0
- package/dist/components/button/ToggleButton.cjs +2 -0
- package/dist/components/button/ToggleButton.cjs.map +1 -0
- package/dist/components/button/ToggleButton.mjs +65 -0
- package/dist/components/button/ToggleButton.mjs.map +1 -0
- package/dist/components/button/Toolbar.cjs +2 -0
- package/dist/components/button/Toolbar.cjs.map +1 -0
- package/dist/components/button/Toolbar.context.cjs +2 -0
- package/dist/components/button/Toolbar.context.cjs.map +1 -0
- package/dist/components/button/Toolbar.context.mjs +31 -0
- package/dist/components/button/Toolbar.context.mjs.map +1 -0
- package/dist/components/button/Toolbar.mjs +63 -0
- package/dist/components/button/Toolbar.mjs.map +1 -0
- package/dist/components/button/Toolbar.parts.cjs +2 -0
- package/dist/components/button/Toolbar.parts.cjs.map +1 -0
- package/dist/components/button/Toolbar.parts.mjs +131 -0
- package/dist/components/button/Toolbar.parts.mjs.map +1 -0
- package/dist/components/button/buttonStyles.cjs +2 -0
- package/dist/components/button/buttonStyles.cjs.map +1 -0
- package/dist/components/button/buttonStyles.mjs +39 -0
- package/dist/components/button/buttonStyles.mjs.map +1 -0
- package/dist/components/data-display/Avatar.cjs +2 -0
- package/dist/components/data-display/Avatar.cjs.map +1 -0
- package/dist/components/data-display/Avatar.mjs +157 -0
- package/dist/components/data-display/Avatar.mjs.map +1 -0
- package/dist/components/data-display/AvatarGroup.cjs +2 -0
- package/dist/components/data-display/AvatarGroup.cjs.map +1 -0
- package/dist/components/data-display/AvatarGroup.mjs +134 -0
- package/dist/components/data-display/AvatarGroup.mjs.map +1 -0
- package/dist/components/data-display/Badge.cjs +2 -0
- package/dist/components/data-display/Badge.cjs.map +1 -0
- package/dist/components/data-display/Badge.colors.cjs +2 -0
- package/dist/components/data-display/Badge.colors.cjs.map +1 -0
- package/dist/components/data-display/Badge.colors.mjs +58 -0
- package/dist/components/data-display/Badge.colors.mjs.map +1 -0
- package/dist/components/data-display/Badge.mjs +32 -0
- package/dist/components/data-display/Badge.mjs.map +1 -0
- package/dist/components/data-display/CounterBadge.cjs +2 -0
- package/dist/components/data-display/CounterBadge.cjs.map +1 -0
- package/dist/components/data-display/CounterBadge.mjs +28 -0
- package/dist/components/data-display/CounterBadge.mjs.map +1 -0
- package/dist/components/data-display/Divider.cjs +2 -0
- package/dist/components/data-display/Divider.cjs.map +1 -0
- package/dist/components/data-display/Divider.mjs +52 -0
- package/dist/components/data-display/Divider.mjs.map +1 -0
- package/dist/components/data-display/Image.cjs +2 -0
- package/dist/components/data-display/Image.cjs.map +1 -0
- package/dist/components/data-display/Image.mjs +32 -0
- package/dist/components/data-display/Image.mjs.map +1 -0
- package/dist/components/data-display/InfoLabel.cjs +2 -0
- package/dist/components/data-display/InfoLabel.cjs.map +1 -0
- package/dist/components/data-display/InfoLabel.mjs +104 -0
- package/dist/components/data-display/InfoLabel.mjs.map +1 -0
- package/dist/components/data-display/List.cjs +2 -0
- package/dist/components/data-display/List.cjs.map +1 -0
- package/dist/components/data-display/List.mjs +381 -0
- package/dist/components/data-display/List.mjs.map +1 -0
- package/dist/components/data-display/List.registry.cjs +2 -0
- package/dist/components/data-display/List.registry.cjs.map +1 -0
- package/dist/components/data-display/List.registry.mjs +101 -0
- package/dist/components/data-display/List.registry.mjs.map +1 -0
- package/dist/components/data-display/Persona.cjs +2 -0
- package/dist/components/data-display/Persona.cjs.map +1 -0
- package/dist/components/data-display/Persona.mjs +48 -0
- package/dist/components/data-display/Persona.mjs.map +1 -0
- package/dist/components/data-display/PresenceBadge.cjs +2 -0
- package/dist/components/data-display/PresenceBadge.cjs.map +1 -0
- package/dist/components/data-display/PresenceBadge.mjs +71 -0
- package/dist/components/data-display/PresenceBadge.mjs.map +1 -0
- package/dist/components/data-display/Tag.cjs +2 -0
- package/dist/components/data-display/Tag.cjs.map +1 -0
- package/dist/components/data-display/Tag.mjs +147 -0
- package/dist/components/data-display/Tag.mjs.map +1 -0
- package/dist/components/feedback/MessageBar.cjs +2 -0
- package/dist/components/feedback/MessageBar.cjs.map +1 -0
- package/dist/components/feedback/MessageBar.mjs +144 -0
- package/dist/components/feedback/MessageBar.mjs.map +1 -0
- package/dist/components/feedback/MessageBar.status.cjs +2 -0
- package/dist/components/feedback/MessageBar.status.cjs.map +1 -0
- package/dist/components/feedback/MessageBar.status.mjs +45 -0
- package/dist/components/feedback/MessageBar.status.mjs.map +1 -0
- package/dist/components/feedback/ProgressBar.cjs +2 -0
- package/dist/components/feedback/ProgressBar.cjs.map +1 -0
- package/dist/components/feedback/ProgressBar.mjs +72 -0
- package/dist/components/feedback/ProgressBar.mjs.map +1 -0
- package/dist/components/feedback/Skeleton.cjs +2 -0
- package/dist/components/feedback/Skeleton.cjs.map +1 -0
- package/dist/components/feedback/Skeleton.mjs +47 -0
- package/dist/components/feedback/Skeleton.mjs.map +1 -0
- package/dist/components/feedback/Spinner.cjs +2 -0
- package/dist/components/feedback/Spinner.cjs.map +1 -0
- package/dist/components/feedback/Spinner.mjs +60 -0
- package/dist/components/feedback/Spinner.mjs.map +1 -0
- package/dist/components/feedback/Toast.cjs +2 -0
- package/dist/components/feedback/Toast.cjs.map +1 -0
- package/dist/components/feedback/Toast.mjs +347 -0
- package/dist/components/feedback/Toast.mjs.map +1 -0
- package/dist/components/input/Checkbox.cjs +2 -0
- package/dist/components/input/Checkbox.cjs.map +1 -0
- package/dist/components/input/Checkbox.mjs +96 -0
- package/dist/components/input/Checkbox.mjs.map +1 -0
- package/dist/components/input/ColorPicker.cjs +6 -0
- package/dist/components/input/ColorPicker.cjs.map +1 -0
- package/dist/components/input/ColorPicker.mjs +236 -0
- package/dist/components/input/ColorPicker.mjs.map +1 -0
- package/dist/components/input/Combobox.cjs +2 -0
- package/dist/components/input/Combobox.cjs.map +1 -0
- package/dist/components/input/Combobox.expand.cjs +2 -0
- package/dist/components/input/Combobox.expand.cjs.map +1 -0
- package/dist/components/input/Combobox.expand.mjs +38 -0
- package/dist/components/input/Combobox.expand.mjs.map +1 -0
- package/dist/components/input/Combobox.mjs +187 -0
- package/dist/components/input/Combobox.mjs.map +1 -0
- package/dist/components/input/DatePicker.cjs +2 -0
- package/dist/components/input/DatePicker.cjs.map +1 -0
- package/dist/components/input/DatePicker.mjs +340 -0
- package/dist/components/input/DatePicker.mjs.map +1 -0
- package/dist/components/input/Dropdown.cjs +2 -0
- package/dist/components/input/Dropdown.cjs.map +1 -0
- package/dist/components/input/Dropdown.mjs +128 -0
- package/dist/components/input/Dropdown.mjs.map +1 -0
- package/dist/components/input/Field.cjs +2 -0
- package/dist/components/input/Field.cjs.map +1 -0
- package/dist/components/input/Field.mjs +200 -0
- package/dist/components/input/Field.mjs.map +1 -0
- package/dist/components/input/Input.cjs +2 -0
- package/dist/components/input/Input.cjs.map +1 -0
- package/dist/components/input/Input.mjs +81 -0
- package/dist/components/input/Input.mjs.map +1 -0
- package/dist/components/input/Label.cjs +2 -0
- package/dist/components/input/Label.cjs.map +1 -0
- package/dist/components/input/Label.mjs +28 -0
- package/dist/components/input/Label.mjs.map +1 -0
- package/dist/components/input/Option.cjs +2 -0
- package/dist/components/input/Option.cjs.map +1 -0
- package/dist/components/input/Option.mjs +169 -0
- package/dist/components/input/Option.mjs.map +1 -0
- package/dist/components/input/RadioGroup.cjs +2 -0
- package/dist/components/input/RadioGroup.cjs.map +1 -0
- package/dist/components/input/RadioGroup.mjs +139 -0
- package/dist/components/input/RadioGroup.mjs.map +1 -0
- package/dist/components/input/Rating.cjs +2 -0
- package/dist/components/input/Rating.cjs.map +1 -0
- package/dist/components/input/Rating.mjs +196 -0
- package/dist/components/input/Rating.mjs.map +1 -0
- package/dist/components/input/SearchBox.cjs +2 -0
- package/dist/components/input/SearchBox.cjs.map +1 -0
- package/dist/components/input/SearchBox.mjs +205 -0
- package/dist/components/input/SearchBox.mjs.map +1 -0
- package/dist/components/input/Select.cjs +2 -0
- package/dist/components/input/Select.cjs.map +1 -0
- package/dist/components/input/Select.mjs +33 -0
- package/dist/components/input/Select.mjs.map +1 -0
- package/dist/components/input/Slider.cjs +2 -0
- package/dist/components/input/Slider.cjs.map +1 -0
- package/dist/components/input/Slider.mjs +79 -0
- package/dist/components/input/Slider.mjs.map +1 -0
- package/dist/components/input/SpinButton.cjs +2 -0
- package/dist/components/input/SpinButton.cjs.map +1 -0
- package/dist/components/input/SpinButton.mjs +157 -0
- package/dist/components/input/SpinButton.mjs.map +1 -0
- package/dist/components/input/SwatchPicker.cjs +2 -0
- package/dist/components/input/SwatchPicker.cjs.map +1 -0
- package/dist/components/input/SwatchPicker.mjs +113 -0
- package/dist/components/input/SwatchPicker.mjs.map +1 -0
- package/dist/components/input/Switch.cjs +2 -0
- package/dist/components/input/Switch.cjs.map +1 -0
- package/dist/components/input/Switch.mjs +92 -0
- package/dist/components/input/Switch.mjs.map +1 -0
- package/dist/components/input/TagPicker.cjs +2 -0
- package/dist/components/input/TagPicker.cjs.map +1 -0
- package/dist/components/input/TagPicker.mjs +249 -0
- package/dist/components/input/TagPicker.mjs.map +1 -0
- package/dist/components/input/Textarea.cjs +2 -0
- package/dist/components/input/Textarea.cjs.map +1 -0
- package/dist/components/input/Textarea.mjs +32 -0
- package/dist/components/input/Textarea.mjs.map +1 -0
- package/dist/components/input/TimePicker.cjs +2 -0
- package/dist/components/input/TimePicker.cjs.map +1 -0
- package/dist/components/input/TimePicker.mjs +292 -0
- package/dist/components/input/TimePicker.mjs.map +1 -0
- package/dist/components/input/colorUtils.cjs +2 -0
- package/dist/components/input/colorUtils.cjs.map +1 -0
- package/dist/components/input/colorUtils.mjs +96 -0
- package/dist/components/input/colorUtils.mjs.map +1 -0
- package/dist/components/input/dateUtils.cjs +2 -0
- package/dist/components/input/dateUtils.cjs.map +1 -0
- package/dist/components/input/dateUtils.mjs +250 -0
- package/dist/components/input/dateUtils.mjs.map +1 -0
- package/dist/components/input/pickerStyles.cjs +2 -0
- package/dist/components/input/pickerStyles.cjs.map +1 -0
- package/dist/components/input/pickerStyles.mjs +10 -0
- package/dist/components/input/pickerStyles.mjs.map +1 -0
- package/dist/components/internal/HiddenInput.cjs +2 -0
- package/dist/components/internal/HiddenInput.cjs.map +1 -0
- package/dist/components/internal/HiddenInput.mjs +88 -0
- package/dist/components/internal/HiddenInput.mjs.map +1 -0
- package/dist/components/layout/Accordion.cjs +2 -0
- package/dist/components/layout/Accordion.cjs.map +1 -0
- package/dist/components/layout/Accordion.mjs +236 -0
- package/dist/components/layout/Accordion.mjs.map +1 -0
- package/dist/components/layout/Card.cjs +2 -0
- package/dist/components/layout/Card.cjs.map +1 -0
- package/dist/components/layout/Card.mjs +121 -0
- package/dist/components/layout/Card.mjs.map +1 -0
- package/dist/components/layout/Carousel.cjs +2 -0
- package/dist/components/layout/Carousel.cjs.map +1 -0
- package/dist/components/layout/Carousel.mjs +205 -0
- package/dist/components/layout/Carousel.mjs.map +1 -0
- package/dist/components/layout/Flex.cjs +2 -0
- package/dist/components/layout/Flex.cjs.map +1 -0
- package/dist/components/layout/Flex.mjs +54 -0
- package/dist/components/layout/Flex.mjs.map +1 -0
- package/dist/components/layout/Grid.cjs +2 -0
- package/dist/components/layout/Grid.cjs.map +1 -0
- package/dist/components/layout/Grid.mjs +62 -0
- package/dist/components/layout/Grid.mjs.map +1 -0
- package/dist/components/layout/Overflow.cjs +2 -0
- package/dist/components/layout/Overflow.cjs.map +1 -0
- package/dist/components/layout/Overflow.mjs +269 -0
- package/dist/components/layout/Overflow.mjs.map +1 -0
- package/dist/components/layout/Stack.cjs +2 -0
- package/dist/components/layout/Stack.cjs.map +1 -0
- package/dist/components/layout/Stack.mjs +39 -0
- package/dist/components/layout/Stack.mjs.map +1 -0
- package/dist/components/layout/TabList.cjs +2 -0
- package/dist/components/layout/TabList.cjs.map +1 -0
- package/dist/components/layout/TabList.mjs +238 -0
- package/dist/components/layout/TabList.mjs.map +1 -0
- package/dist/components/layout/Tree.cjs +2 -0
- package/dist/components/layout/Tree.cjs.map +1 -0
- package/dist/components/layout/Tree.mjs +220 -0
- package/dist/components/layout/Tree.mjs.map +1 -0
- package/dist/components/layout/disclosureIds.cjs +2 -0
- package/dist/components/layout/disclosureIds.cjs.map +1 -0
- package/dist/components/layout/disclosureIds.mjs +12 -0
- package/dist/components/layout/disclosureIds.mjs.map +1 -0
- package/dist/components/motion/Presence.cjs +2 -0
- package/dist/components/motion/Presence.cjs.map +1 -0
- package/dist/components/motion/Presence.mjs +35 -0
- package/dist/components/motion/Presence.mjs.map +1 -0
- package/dist/components/navigation/Breadcrumb.cjs +2 -0
- package/dist/components/navigation/Breadcrumb.cjs.map +1 -0
- package/dist/components/navigation/Breadcrumb.mjs +144 -0
- package/dist/components/navigation/Breadcrumb.mjs.map +1 -0
- package/dist/components/navigation/Menu.cjs +2 -0
- package/dist/components/navigation/Menu.cjs.map +1 -0
- package/dist/components/navigation/Menu.context.cjs +2 -0
- package/dist/components/navigation/Menu.context.cjs.map +1 -0
- package/dist/components/navigation/Menu.context.mjs +82 -0
- package/dist/components/navigation/Menu.context.mjs.map +1 -0
- package/dist/components/navigation/Menu.group.cjs +2 -0
- package/dist/components/navigation/Menu.group.cjs.map +1 -0
- package/dist/components/navigation/Menu.group.mjs +58 -0
- package/dist/components/navigation/Menu.group.mjs.map +1 -0
- package/dist/components/navigation/Menu.items.cjs +2 -0
- package/dist/components/navigation/Menu.items.cjs.map +1 -0
- package/dist/components/navigation/Menu.items.mjs +127 -0
- package/dist/components/navigation/Menu.items.mjs.map +1 -0
- package/dist/components/navigation/Menu.link.cjs +2 -0
- package/dist/components/navigation/Menu.link.cjs.map +1 -0
- package/dist/components/navigation/Menu.link.mjs +41 -0
- package/dist/components/navigation/Menu.link.mjs.map +1 -0
- package/dist/components/navigation/Menu.mjs +27 -0
- package/dist/components/navigation/Menu.mjs.map +1 -0
- package/dist/components/navigation/Menu.popover.cjs +2 -0
- package/dist/components/navigation/Menu.popover.cjs.map +1 -0
- package/dist/components/navigation/Menu.popover.mjs +231 -0
- package/dist/components/navigation/Menu.popover.mjs.map +1 -0
- package/dist/components/navigation/Menu.root.cjs +2 -0
- package/dist/components/navigation/Menu.root.cjs.map +1 -0
- package/dist/components/navigation/Menu.root.mjs +308 -0
- package/dist/components/navigation/Menu.root.mjs.map +1 -0
- package/dist/components/navigation/Menu.selectable.cjs +2 -0
- package/dist/components/navigation/Menu.selectable.cjs.map +1 -0
- package/dist/components/navigation/Menu.selectable.mjs +89 -0
- package/dist/components/navigation/Menu.selectable.mjs.map +1 -0
- package/dist/components/navigation/Menu.shared.cjs +2 -0
- package/dist/components/navigation/Menu.shared.cjs.map +1 -0
- package/dist/components/navigation/Menu.shared.mjs +23 -0
- package/dist/components/navigation/Menu.shared.mjs.map +1 -0
- package/dist/components/navigation/Menu.splitGroup.cjs +2 -0
- package/dist/components/navigation/Menu.splitGroup.cjs.map +1 -0
- package/dist/components/navigation/Menu.splitGroup.mjs +51 -0
- package/dist/components/navigation/Menu.splitGroup.mjs.map +1 -0
- package/dist/components/navigation/Menu.trigger.cjs +2 -0
- package/dist/components/navigation/Menu.trigger.cjs.map +1 -0
- package/dist/components/navigation/Menu.trigger.mjs +79 -0
- package/dist/components/navigation/Menu.trigger.mjs.map +1 -0
- package/dist/components/navigation/Nav.cjs +2 -0
- package/dist/components/navigation/Nav.cjs.map +1 -0
- package/dist/components/navigation/Nav.mjs +276 -0
- package/dist/components/navigation/Nav.mjs.map +1 -0
- package/dist/components/navigation/Pagination.cjs +2 -0
- package/dist/components/navigation/Pagination.cjs.map +1 -0
- package/dist/components/navigation/Pagination.mjs +110 -0
- package/dist/components/navigation/Pagination.mjs.map +1 -0
- package/dist/components/navigation/Stepper.cjs +2 -0
- package/dist/components/navigation/Stepper.cjs.map +1 -0
- package/dist/components/navigation/Stepper.mjs +204 -0
- package/dist/components/navigation/Stepper.mjs.map +1 -0
- package/dist/components/overlays/Dialog.cjs +2 -0
- package/dist/components/overlays/Dialog.cjs.map +1 -0
- package/dist/components/overlays/Dialog.mjs +180 -0
- package/dist/components/overlays/Dialog.mjs.map +1 -0
- package/dist/components/overlays/Dialog.shared.cjs +2 -0
- package/dist/components/overlays/Dialog.shared.cjs.map +1 -0
- package/dist/components/overlays/Dialog.shared.mjs +227 -0
- package/dist/components/overlays/Dialog.shared.mjs.map +1 -0
- package/dist/components/overlays/Drawer.cjs +2 -0
- package/dist/components/overlays/Drawer.cjs.map +1 -0
- package/dist/components/overlays/Drawer.mjs +192 -0
- package/dist/components/overlays/Drawer.mjs.map +1 -0
- package/dist/components/overlays/Popover.cjs +2 -0
- package/dist/components/overlays/Popover.cjs.map +1 -0
- package/dist/components/overlays/Popover.mjs +365 -0
- package/dist/components/overlays/Popover.mjs.map +1 -0
- package/dist/components/overlays/Popover.shared.cjs +2 -0
- package/dist/components/overlays/Popover.shared.cjs.map +1 -0
- package/dist/components/overlays/Popover.shared.mjs +182 -0
- package/dist/components/overlays/Popover.shared.mjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.cjs +2 -0
- package/dist/components/overlays/TeachingPopover.cjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.mjs +181 -0
- package/dist/components/overlays/TeachingPopover.mjs.map +1 -0
- package/dist/components/overlays/Tooltip.cjs +2 -0
- package/dist/components/overlays/Tooltip.cjs.map +1 -0
- package/dist/components/overlays/Tooltip.mjs +160 -0
- package/dist/components/overlays/Tooltip.mjs.map +1 -0
- package/dist/components/portal/Portal.cjs +2 -0
- package/dist/components/portal/Portal.cjs.map +1 -0
- package/dist/components/portal/Portal.mjs +45 -0
- package/dist/components/portal/Portal.mjs.map +1 -0
- package/dist/components/provider/WaveProvider.cjs +2 -0
- package/dist/components/provider/WaveProvider.cjs.map +1 -0
- package/dist/components/provider/WaveProvider.mjs +51 -0
- package/dist/components/provider/WaveProvider.mjs.map +1 -0
- package/dist/components/table/DataGrid.cjs +2 -0
- package/dist/components/table/DataGrid.cjs.map +1 -0
- package/dist/components/table/DataGrid.mjs +489 -0
- package/dist/components/table/DataGrid.mjs.map +1 -0
- package/dist/components/table/Table.cjs +2 -0
- package/dist/components/table/Table.cjs.map +1 -0
- package/dist/components/table/Table.mjs +99 -0
- package/dist/components/table/Table.mjs.map +1 -0
- package/dist/components/table/useGridNavigation.cjs +2 -0
- package/dist/components/table/useGridNavigation.cjs.map +1 -0
- package/dist/components/table/useGridNavigation.mjs +336 -0
- package/dist/components/table/useGridNavigation.mjs.map +1 -0
- package/dist/components/typography/Text.cjs +2 -0
- package/dist/components/typography/Text.cjs.map +1 -0
- package/dist/components/typography/Text.mjs +38 -0
- package/dist/components/typography/Text.mjs.map +1 -0
- package/dist/hooks/useAnnounce.cjs +2 -0
- package/dist/hooks/useAnnounce.cjs.map +1 -0
- package/dist/hooks/useAnnounce.mjs +88 -0
- package/dist/hooks/useAnnounce.mjs.map +1 -0
- package/dist/hooks/useCheckedValues.cjs +2 -0
- package/dist/hooks/useCheckedValues.cjs.map +1 -0
- package/dist/hooks/useCheckedValues.mjs +102 -0
- package/dist/hooks/useCheckedValues.mjs.map +1 -0
- package/dist/hooks/useContextMenuAnchor.cjs +2 -0
- package/dist/hooks/useContextMenuAnchor.cjs.map +1 -0
- package/dist/hooks/useContextMenuAnchor.mjs +132 -0
- package/dist/hooks/useContextMenuAnchor.mjs.map +1 -0
- package/dist/hooks/useControllable.cjs +2 -0
- package/dist/hooks/useControllable.cjs.map +1 -0
- package/dist/hooks/useControllable.mjs +37 -0
- package/dist/hooks/useControllable.mjs.map +1 -0
- package/dist/hooks/useDirection.cjs +2 -0
- package/dist/hooks/useDirection.cjs.map +1 -0
- package/dist/hooks/useDirection.mjs +57 -0
- package/dist/hooks/useDirection.mjs.map +1 -0
- package/dist/hooks/useDismiss.cjs +2 -0
- package/dist/hooks/useDismiss.cjs.map +1 -0
- package/dist/hooks/useDismiss.mjs +57 -0
- package/dist/hooks/useDismiss.mjs.map +1 -0
- package/dist/hooks/useEventCallback.cjs +2 -0
- package/dist/hooks/useEventCallback.cjs.map +1 -0
- package/dist/hooks/useEventCallback.mjs +16 -0
- package/dist/hooks/useEventCallback.mjs.map +1 -0
- package/dist/hooks/useFieldControl.cjs +2 -0
- package/dist/hooks/useFieldControl.cjs.map +1 -0
- package/dist/hooks/useFieldControl.mjs +62 -0
- package/dist/hooks/useFieldControl.mjs.map +1 -0
- package/dist/hooks/useFocusTrap.cjs +2 -0
- package/dist/hooks/useFocusTrap.cjs.map +1 -0
- package/dist/hooks/useFocusTrap.mjs +266 -0
- package/dist/hooks/useFocusTrap.mjs.map +1 -0
- package/dist/hooks/useFormReset.cjs +2 -0
- package/dist/hooks/useFormReset.cjs.map +1 -0
- package/dist/hooks/useFormReset.mjs +33 -0
- package/dist/hooks/useFormReset.mjs.map +1 -0
- package/dist/hooks/useHoverIntent.cjs +2 -0
- package/dist/hooks/useHoverIntent.cjs.map +1 -0
- package/dist/hooks/useHoverIntent.mjs +201 -0
- package/dist/hooks/useHoverIntent.mjs.map +1 -0
- package/dist/hooks/useId.cjs +2 -0
- package/dist/hooks/useId.cjs.map +1 -0
- package/dist/hooks/useId.mjs +11 -0
- package/dist/hooks/useId.mjs.map +1 -0
- package/dist/hooks/useIsClient.cjs +2 -0
- package/dist/hooks/useIsClient.cjs.map +1 -0
- package/dist/hooks/useIsClient.mjs +19 -0
- package/dist/hooks/useIsClient.mjs.map +1 -0
- package/dist/hooks/useListbox.cjs +2 -0
- package/dist/hooks/useListbox.cjs.map +1 -0
- package/dist/hooks/useListbox.mjs +492 -0
- package/dist/hooks/useListbox.mjs.map +1 -0
- package/dist/hooks/useMergedRefs.cjs +2 -0
- package/dist/hooks/useMergedRefs.cjs.map +1 -0
- package/dist/hooks/useMergedRefs.mjs +57 -0
- package/dist/hooks/useMergedRefs.mjs.map +1 -0
- package/dist/hooks/useModalIsolation.cjs +2 -0
- package/dist/hooks/useModalIsolation.cjs.map +1 -0
- package/dist/hooks/useModalIsolation.mjs +87 -0
- package/dist/hooks/useModalIsolation.mjs.map +1 -0
- package/dist/hooks/useModalLayer.cjs +2 -0
- package/dist/hooks/useModalLayer.cjs.map +1 -0
- package/dist/hooks/useModalLayer.mjs +30 -0
- package/dist/hooks/useModalLayer.mjs.map +1 -0
- package/dist/hooks/usePopupPosition.cjs +2 -0
- package/dist/hooks/usePopupPosition.cjs.map +1 -0
- package/dist/hooks/usePopupPosition.mjs +117 -0
- package/dist/hooks/usePopupPosition.mjs.map +1 -0
- package/dist/hooks/usePrefersReducedMotion.cjs +2 -0
- package/dist/hooks/usePrefersReducedMotion.cjs.map +1 -0
- package/dist/hooks/usePrefersReducedMotion.mjs +24 -0
- package/dist/hooks/usePrefersReducedMotion.mjs.map +1 -0
- package/dist/hooks/usePresence.cjs +2 -0
- package/dist/hooks/usePresence.cjs.map +1 -0
- package/dist/hooks/usePresence.mjs +136 -0
- package/dist/hooks/usePresence.mjs.map +1 -0
- package/dist/hooks/usePreserveFocus.cjs +2 -0
- package/dist/hooks/usePreserveFocus.cjs.map +1 -0
- package/dist/hooks/usePreserveFocus.mjs +50 -0
- package/dist/hooks/usePreserveFocus.mjs.map +1 -0
- package/dist/hooks/useRestoreFocus.cjs +2 -0
- package/dist/hooks/useRestoreFocus.cjs.map +1 -0
- package/dist/hooks/useRestoreFocus.mjs +271 -0
- package/dist/hooks/useRestoreFocus.mjs.map +1 -0
- package/dist/hooks/useRovingTabIndex.cjs +2 -0
- package/dist/hooks/useRovingTabIndex.cjs.map +1 -0
- package/dist/hooks/useRovingTabIndex.mjs +389 -0
- package/dist/hooks/useRovingTabIndex.mjs.map +1 -0
- package/dist/hooks/useScrollLock.cjs +2 -0
- package/dist/hooks/useScrollLock.cjs.map +1 -0
- package/dist/hooks/useScrollLock.mjs +71 -0
- package/dist/hooks/useScrollLock.mjs.map +1 -0
- package/dist/hooks/useTriggerElement.cjs +2 -0
- package/dist/hooks/useTriggerElement.cjs.map +1 -0
- package/dist/hooks/useTriggerElement.mjs +126 -0
- package/dist/hooks/useTriggerElement.mjs.map +1 -0
- package/dist/hooks/useTypeahead.cjs +2 -0
- package/dist/hooks/useTypeahead.cjs.map +1 -0
- package/dist/hooks/useTypeahead.mjs +38 -0
- package/dist/hooks/useTypeahead.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +9099 -0
- package/dist/index.d.ts +7688 -1027
- package/dist/index.mjs +91 -5695
- package/dist/lib/aria.cjs +2 -0
- package/dist/lib/aria.cjs.map +1 -0
- package/dist/lib/aria.mjs +29 -0
- package/dist/lib/aria.mjs.map +1 -0
- package/dist/lib/children.cjs +2 -0
- package/dist/lib/children.cjs.map +1 -0
- package/dist/lib/children.mjs +37 -0
- package/dist/lib/children.mjs.map +1 -0
- package/dist/lib/cn.cjs +2 -0
- package/dist/lib/cn.cjs.map +1 -0
- package/dist/lib/cn.mjs +64 -0
- package/dist/lib/cn.mjs.map +1 -0
- package/dist/lib/composeEventHandlers.cjs +2 -0
- package/dist/lib/composeEventHandlers.cjs.map +1 -0
- package/dist/lib/composeEventHandlers.mjs +11 -0
- package/dist/lib/composeEventHandlers.mjs.map +1 -0
- package/dist/lib/dev.cjs +2 -0
- package/dist/lib/dev.cjs.map +1 -0
- package/dist/lib/dev.mjs +42 -0
- package/dist/lib/dev.mjs.map +1 -0
- package/dist/lib/direction.cjs +2 -0
- package/dist/lib/direction.cjs.map +1 -0
- package/dist/lib/direction.mjs +35 -0
- package/dist/lib/direction.mjs.map +1 -0
- package/dist/lib/events.cjs +2 -0
- package/dist/lib/events.cjs.map +1 -0
- package/dist/lib/events.mjs +31 -0
- package/dist/lib/events.mjs.map +1 -0
- package/dist/lib/focus.cjs +2 -0
- package/dist/lib/focus.cjs.map +1 -0
- package/dist/lib/focus.mjs +119 -0
- package/dist/lib/focus.mjs.map +1 -0
- package/dist/lib/globalRegistry.cjs +2 -0
- package/dist/lib/globalRegistry.cjs.map +1 -0
- package/dist/lib/globalRegistry.mjs +13 -0
- package/dist/lib/globalRegistry.mjs.map +1 -0
- package/dist/lib/icons.cjs +2 -0
- package/dist/lib/icons.cjs.map +1 -0
- package/dist/lib/icons.mjs +254 -0
- package/dist/lib/icons.mjs.map +1 -0
- package/dist/lib/labelInName.cjs +2 -0
- package/dist/lib/labelInName.cjs.map +1 -0
- package/dist/lib/labelInName.mjs +54 -0
- package/dist/lib/labelInName.mjs.map +1 -0
- package/dist/lib/layers.cjs +2 -0
- package/dist/lib/layers.cjs.map +1 -0
- package/dist/lib/layers.mjs +224 -0
- package/dist/lib/layers.mjs.map +1 -0
- package/dist/lib/mergeProps.cjs +2 -0
- package/dist/lib/mergeProps.cjs.map +1 -0
- package/dist/lib/mergeProps.mjs +21 -0
- package/dist/lib/mergeProps.mjs.map +1 -0
- package/dist/lib/mergeRefs.cjs +2 -0
- package/dist/lib/mergeRefs.cjs.map +1 -0
- package/dist/lib/mergeRefs.mjs +29 -0
- package/dist/lib/mergeRefs.mjs.map +1 -0
- package/dist/lib/renderTrigger.cjs +2 -0
- package/dist/lib/renderTrigger.cjs.map +1 -0
- package/dist/lib/renderTrigger.mjs +29 -0
- package/dist/lib/renderTrigger.mjs.map +1 -0
- package/dist/lib/slot.cjs +2 -0
- package/dist/lib/slot.cjs.map +1 -0
- package/dist/lib/slot.mjs +122 -0
- package/dist/lib/slot.mjs.map +1 -0
- package/dist/lib/styles.cjs +2 -0
- package/dist/lib/styles.cjs.map +1 -0
- package/dist/lib/styles.mjs +16 -0
- package/dist/lib/styles.mjs.map +1 -0
- package/dist/lib/theme.cjs +2 -0
- package/dist/lib/theme.cjs.map +1 -0
- package/dist/lib/theme.mjs +16 -0
- package/dist/lib/theme.mjs.map +1 -0
- package/dist/preflight.css +2 -0
- package/dist/styles.css +2 -0
- package/package.json +149 -100
- package/src/styles/animations.css +7 -39
- package/src/styles/base.css +103 -0
- package/src/styles/globals.css +10 -22
- package/src/styles/legacy-tokens.css +184 -0
- package/src/styles/preflight.css +7 -0
- package/src/styles/styles.css +32 -0
- package/src/styles/tailwind.css +17 -0
- package/src/styles/tokens.css +561 -221
- package/src/styles/variants.css +29 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMergedRefs.cjs","names":["setRef","useRef","useCallback","require_mergeRefs","react","sameRefs","a","b","i","presentRefs","result","ref","refs","attach","node","detachAll","state","entry","attached","useMergedRefs","stateRef","mergedRef","next","kept"],"sources":["../../src/hooks/useMergedRefs.ts"],"sourcesContent":["import { useCallback, useInsertionEffect, useLayoutEffect, useRef } from 'react';\nimport type * as React from 'react';\nimport { setRef } from '../lib/mergeRefs';\n\ntype AnyRef<T> = React.Ref<T> | undefined | null;\ntype RefList<T> = ReadonlyArray<AnyRef<T>>;\ntype PresentRef<T> = NonNullable<React.Ref<T>>;\n\ninterface AttachedRef<T> {\n ref: PresentRef<T>;\n /** Runs the ref's React 19 cleanup, or passes `null` to it (object refs: `current = null`). */\n detach: () => void;\n}\n\ninterface MergedRefState<T> {\n /**\n * The refs of the render being committed. Recorded in the mutation phase (insertion effect),\n * before React attaches refs in the layout phase, so the ref callback never attaches a ref that is\n * no longer in the list, and never one from a render that was not committed (the first\n * StrictMode invocation, a render discarded by a render-phase update).\n */\n refs: RefList<T>;\n /** The element the merged ref is attached to, or `null`. */\n node: T | null;\n /** The refs `node` is attached to, each with its detach function. */\n attached: AttachedRef<T>[];\n}\n\nfunction sameRefs<T>(a: RefList<T>, b: RefList<T>): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n/** The present refs, each once, in order. */\nfunction presentRefs<T>(refs: RefList<T>): PresentRef<T>[] {\n const result: PresentRef<T>[] = [];\n for (const ref of refs) {\n if (ref && !result.includes(ref)) result.push(ref);\n }\n return result;\n}\n\nfunction attach<T>(ref: PresentRef<T>, node: T): AttachedRef<T> {\n const cleanup = setRef(ref, node);\n return {\n ref,\n detach:\n cleanup ??\n (() => {\n setRef(ref, null);\n }),\n };\n}\n\nfunction detachAll<T>(state: MergedRefState<T>): void {\n const { attached } = state;\n state.attached = [];\n state.node = null;\n for (const entry of attached) entry.detach();\n}\n\n/**\n * Merges several refs into one callback ref whose identity never changes (React 19 cleanup-aware,\n * like {@link mergeRefs}, which merges refs without a hook).\n *\n * - The element is attached to every ref when it mounts and detached when it unmounts (object refs\n * reset to `null`; callback refs get their React 19 cleanup called, or `null`).\n * - Refs that keep their identity across renders (object refs, `useCallback` refs, stable ref\n * props) receive the node **once**: the element is not detached and re-attached on every render.\n * - Refs may change between renders — also inline callbacks such as\n * `useMergedRefs(props.ref, (node) => { … })` or a fresh `mergeRefs(…)` result. After each commit\n * a ref that left the list is detached and a new one is attached to the current element, which is\n * what React itself does for an inline callback ref (detach + re-attach per render). The hook\n * never sets state, so an unstable ref cannot cause a render loop.\n * - A ref only receives the element for a render it is part of: an element that appears or is\n * replaced in the same commit in which the list changes goes straight to the new list, and the\n * inline refs of renders that were never committed (StrictMode's first invocation, a render\n * discarded by a render-phase update) never receive it.\n *\n * Attach the returned ref to one element.\n *\n * @example\n * const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n * const ref = useMergedRefs(props.ref, setSurface);\n * return <div ref={ref} />;\n *\n * @param refs - Object refs, callback refs, `null` or `undefined` (ignored).\n * @returns A stable callback ref that forwards the node to every ref.\n */\nexport function useMergedRefs<T>(\n ...refs: Array<React.Ref<T> | undefined | null>\n): React.RefCallback<T> {\n // Written only in the insertion effect, the ref callback and the layout effect below (C-HOOKS:\n // never during render). The initial `refs` is replaced by the insertion effect before any attach.\n const stateRef = useRef<MergedRefState<T>>({ refs, node: null, attached: [] });\n\n // Mutation phase of every commit, before React attaches refs (layout phase): record this\n // render's refs for the ref callback.\n useInsertionEffect(() => {\n stateRef.current.refs = refs;\n });\n\n const mergedRef = useCallback((node: T | null) => {\n const state = stateRef.current;\n detachAll(state);\n if (node === null) return;\n state.node = node;\n state.attached = presentRefs(state.refs).map((ref) => attach(ref, node));\n return () => {\n // Only the element that is still attached detaches (the ref moved to another element first).\n if (state.node === node) detachAll(state);\n };\n }, []);\n\n // After every commit in which the element stayed: bring the attached refs in line with this\n // render's refs (the ref callback already used them when the element changed).\n useLayoutEffect(() => {\n const state = stateRef.current;\n const { node } = state;\n if (node === null) return;\n const next = presentRefs(refs);\n if (\n sameRefs(\n state.attached.map((entry) => entry.ref),\n next,\n )\n ) {\n return;\n }\n const kept = new Map<PresentRef<T>, AttachedRef<T>>();\n for (const entry of state.attached) {\n if (next.includes(entry.ref)) kept.set(entry.ref, entry);\n else entry.detach();\n }\n state.attached = next.map((ref) => kept.get(ref) ?? attach(ref, node));\n });\n\n return mergedRef;\n}\n"],"mappings":"4EA4BA,SAASK,EAAY,EAAe,EAAwB,CAC1D,GAAIC,IAAMC,EAAG,MAAO,GACpB,GAAID,EAAE,SAAWC,EAAE,OAAQ,MAAO,GAClC,IAAK,IAAIC,EAAI,EAAGA,EAAIF,EAAE,OAAQ,IAC5B,GAAIA,EAAEE,KAAOD,EAAEC,GAAI,MAAO,GAE5B,MAAO,EACT,CAGA,SAASC,EAAe,EAAmC,CACzD,IAAMC,EAA0B,CAAC,EACjC,IAAK,IAAMC,KAAOC,EACZD,GAAO,CAACD,EAAO,SAASC,CAAG,GAAGD,EAAO,KAAKC,CAAG,EAEnD,OAAOD,CACT,CAEA,SAASG,EAAU,EAAoB,EAAyB,CAE9D,MAAO,CACL,MACA,OAHcb,EAAAA,OAAOW,EAAKG,CAIxB,QACO,CACLX,EAAA,OAAOQ,EAAK,IAAI,CAClB,EACJ,CACF,CAEA,SAASI,EAAa,EAAgC,CACpD,GAAM,CAAE,YAAaC,EACrB,EAAM,SAAW,CAAC,EAClB,EAAM,KAAO,KACb,IAAK,IAAMC,KAASC,EAAUD,EAAM,OAAO,CAC7C,CA8BA,SAAgBE,EACd,GAAGP,EACmB,CAGtB,IAAMQ,GAAA,EAAWnB,EAAAA,OAAAA,CAA0B,CAAE,OAAM,KAAM,KAAM,SAAU,CAAC,CAAE,CAAC,GAI7E,EAAAG,EAAA,mBAAA,KAAyB,CACvB,EAAS,QAAQ,KAAOQ,CAC1B,CAAC,EAED,IAAMS,GAAA,EAAYnB,EAAAA,YAAAA,CAAa,GAAmB,CAChD,IAAMc,EAAQI,EAAS,QAEvB,GADAL,EAAUC,CAAK,EACXF,IAAS,KAGb,MAFA,GAAM,KAAOA,EACb,EAAM,SAAWL,EAAYO,EAAM,IAAI,CAAC,CAAC,IAAK,GAAQH,EAAOF,EAAKG,CAAI,CAAC,MAC1D,CAEPE,EAAM,OAASF,GAAMC,EAAUC,CAAK,CAC1C,CACF,EAAG,CAAC,CAAC,EAyBL,OArBA,EAAAZ,EAAA,gBAAA,KAAsB,CACpB,IAAMY,EAAQI,EAAS,QACjB,CAAE,QAASJ,EACjB,GAAIF,IAAS,KAAM,OACnB,IAAMQ,EAAOb,EAAYG,CAAI,EAC7B,GACEP,EACEW,EAAM,SAAS,IAAK,GAAUC,EAAM,GAAG,EACvCK,CACF,EAEA,OAEF,IAAMC,EAAO,IAAI,IACjB,IAAK,IAAMN,KAASD,EAAM,SACpBM,EAAK,SAASL,EAAM,GAAG,EAAGM,EAAK,IAAIN,EAAM,IAAKA,CAAK,EAClDA,EAAM,OAAO,EAEpB,EAAM,SAAWK,EAAK,IAAK,GAAQC,EAAK,IAAIZ,CAAG,GAAKE,EAAOF,EAAKG,CAAI,CAAC,CACvE,CAAC,EAEMO,CACT"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { setRef as e } from "../lib/mergeRefs.mjs";
|
|
3
|
+
import { useCallback as t, useInsertionEffect as n, useLayoutEffect as r, useRef as i } from "react";
|
|
4
|
+
//#region src/hooks/useMergedRefs.ts
|
|
5
|
+
function a(e, t) {
|
|
6
|
+
if (e === t) return !0;
|
|
7
|
+
if (e.length !== t.length) return !1;
|
|
8
|
+
for (let n = 0; n < e.length; n++) if (e[n] !== t[n]) return !1;
|
|
9
|
+
return !0;
|
|
10
|
+
}
|
|
11
|
+
function o(e) {
|
|
12
|
+
let t = [];
|
|
13
|
+
for (let n of e) n && !t.includes(n) && t.push(n);
|
|
14
|
+
return t;
|
|
15
|
+
}
|
|
16
|
+
function s(t, n) {
|
|
17
|
+
return {
|
|
18
|
+
ref: t,
|
|
19
|
+
detach: e(t, n) ?? (() => {
|
|
20
|
+
e(t, null);
|
|
21
|
+
})
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function c(e) {
|
|
25
|
+
let { attached: t } = e;
|
|
26
|
+
e.attached = [], e.node = null;
|
|
27
|
+
for (let e of t) e.detach();
|
|
28
|
+
}
|
|
29
|
+
function l(...e) {
|
|
30
|
+
let l = i({
|
|
31
|
+
refs: e,
|
|
32
|
+
node: null,
|
|
33
|
+
attached: []
|
|
34
|
+
});
|
|
35
|
+
n(() => {
|
|
36
|
+
l.current.refs = e;
|
|
37
|
+
});
|
|
38
|
+
let u = t((e) => {
|
|
39
|
+
let t = l.current;
|
|
40
|
+
if (c(t), e !== null) return t.node = e, t.attached = o(t.refs).map((t) => s(t, e)), () => {
|
|
41
|
+
t.node === e && c(t);
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
return r(() => {
|
|
45
|
+
let t = l.current, { node: n } = t;
|
|
46
|
+
if (n === null) return;
|
|
47
|
+
let r = o(e);
|
|
48
|
+
if (a(t.attached.map((e) => e.ref), r)) return;
|
|
49
|
+
let i = /* @__PURE__ */ new Map();
|
|
50
|
+
for (let e of t.attached) r.includes(e.ref) ? i.set(e.ref, e) : e.detach();
|
|
51
|
+
t.attached = r.map((e) => i.get(e) ?? s(e, n));
|
|
52
|
+
}), u;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { l as useMergedRefs };
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=useMergedRefs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMergedRefs.mjs","names":["sameRefs","a","b","i","presentRefs","result","ref","refs","attach","setRef","node","detachAll","state","entry","attached","useMergedRefs","stateRef","useRef","mergedRef","useCallback","useLayoutEffect","next","kept"],"sources":["../../src/hooks/useMergedRefs.ts"],"sourcesContent":["import { useCallback, useInsertionEffect, useLayoutEffect, useRef } from 'react';\nimport type * as React from 'react';\nimport { setRef } from '../lib/mergeRefs';\n\ntype AnyRef<T> = React.Ref<T> | undefined | null;\ntype RefList<T> = ReadonlyArray<AnyRef<T>>;\ntype PresentRef<T> = NonNullable<React.Ref<T>>;\n\ninterface AttachedRef<T> {\n ref: PresentRef<T>;\n /** Runs the ref's React 19 cleanup, or passes `null` to it (object refs: `current = null`). */\n detach: () => void;\n}\n\ninterface MergedRefState<T> {\n /**\n * The refs of the render being committed. Recorded in the mutation phase (insertion effect),\n * before React attaches refs in the layout phase, so the ref callback never attaches a ref that is\n * no longer in the list, and never one from a render that was not committed (the first\n * StrictMode invocation, a render discarded by a render-phase update).\n */\n refs: RefList<T>;\n /** The element the merged ref is attached to, or `null`. */\n node: T | null;\n /** The refs `node` is attached to, each with its detach function. */\n attached: AttachedRef<T>[];\n}\n\nfunction sameRefs<T>(a: RefList<T>, b: RefList<T>): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\n/** The present refs, each once, in order. */\nfunction presentRefs<T>(refs: RefList<T>): PresentRef<T>[] {\n const result: PresentRef<T>[] = [];\n for (const ref of refs) {\n if (ref && !result.includes(ref)) result.push(ref);\n }\n return result;\n}\n\nfunction attach<T>(ref: PresentRef<T>, node: T): AttachedRef<T> {\n const cleanup = setRef(ref, node);\n return {\n ref,\n detach:\n cleanup ??\n (() => {\n setRef(ref, null);\n }),\n };\n}\n\nfunction detachAll<T>(state: MergedRefState<T>): void {\n const { attached } = state;\n state.attached = [];\n state.node = null;\n for (const entry of attached) entry.detach();\n}\n\n/**\n * Merges several refs into one callback ref whose identity never changes (React 19 cleanup-aware,\n * like {@link mergeRefs}, which merges refs without a hook).\n *\n * - The element is attached to every ref when it mounts and detached when it unmounts (object refs\n * reset to `null`; callback refs get their React 19 cleanup called, or `null`).\n * - Refs that keep their identity across renders (object refs, `useCallback` refs, stable ref\n * props) receive the node **once**: the element is not detached and re-attached on every render.\n * - Refs may change between renders — also inline callbacks such as\n * `useMergedRefs(props.ref, (node) => { … })` or a fresh `mergeRefs(…)` result. After each commit\n * a ref that left the list is detached and a new one is attached to the current element, which is\n * what React itself does for an inline callback ref (detach + re-attach per render). The hook\n * never sets state, so an unstable ref cannot cause a render loop.\n * - A ref only receives the element for a render it is part of: an element that appears or is\n * replaced in the same commit in which the list changes goes straight to the new list, and the\n * inline refs of renders that were never committed (StrictMode's first invocation, a render\n * discarded by a render-phase update) never receive it.\n *\n * Attach the returned ref to one element.\n *\n * @example\n * const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n * const ref = useMergedRefs(props.ref, setSurface);\n * return <div ref={ref} />;\n *\n * @param refs - Object refs, callback refs, `null` or `undefined` (ignored).\n * @returns A stable callback ref that forwards the node to every ref.\n */\nexport function useMergedRefs<T>(\n ...refs: Array<React.Ref<T> | undefined | null>\n): React.RefCallback<T> {\n // Written only in the insertion effect, the ref callback and the layout effect below (C-HOOKS:\n // never during render). The initial `refs` is replaced by the insertion effect before any attach.\n const stateRef = useRef<MergedRefState<T>>({ refs, node: null, attached: [] });\n\n // Mutation phase of every commit, before React attaches refs (layout phase): record this\n // render's refs for the ref callback.\n useInsertionEffect(() => {\n stateRef.current.refs = refs;\n });\n\n const mergedRef = useCallback((node: T | null) => {\n const state = stateRef.current;\n detachAll(state);\n if (node === null) return;\n state.node = node;\n state.attached = presentRefs(state.refs).map((ref) => attach(ref, node));\n return () => {\n // Only the element that is still attached detaches (the ref moved to another element first).\n if (state.node === node) detachAll(state);\n };\n }, []);\n\n // After every commit in which the element stayed: bring the attached refs in line with this\n // render's refs (the ref callback already used them when the element changed).\n useLayoutEffect(() => {\n const state = stateRef.current;\n const { node } = state;\n if (node === null) return;\n const next = presentRefs(refs);\n if (\n sameRefs(\n state.attached.map((entry) => entry.ref),\n next,\n )\n ) {\n return;\n }\n const kept = new Map<PresentRef<T>, AttachedRef<T>>();\n for (const entry of state.attached) {\n if (next.includes(entry.ref)) kept.set(entry.ref, entry);\n else entry.detach();\n }\n state.attached = next.map((ref) => kept.get(ref) ?? attach(ref, node));\n });\n\n return mergedRef;\n}\n"],"mappings":";;;;AA4BA,SAASA,EAAY,GAAe,GAAwB;CAC1D,IAAIC,MAAMC,GAAG,OAAO;CACpB,IAAID,EAAE,WAAWC,EAAE,QAAQ,OAAO;CAClC,KAAK,IAAIC,IAAI,GAAGA,IAAIF,EAAE,QAAQ,KAC5B,IAAIA,EAAEE,OAAOD,EAAEC,IAAI,OAAO;CAE5B,OAAO;AACT;AAGA,SAASC,EAAe,GAAmC;CACzD,IAAMC,IAA0B,CAAC;CACjC,KAAK,IAAMC,KAAOC,GAChB,AAAID,KAAO,CAACD,EAAO,SAASC,CAAG,KAAGD,EAAO,KAAKC,CAAG;CAEnD,OAAOD;AACT;AAEA,SAASG,EAAU,GAAoB,GAAyB;CAE9D,OAAO;EACL;EACA,QAHcC,EAAOH,GAAKI,CAIxB,YACO;GACL,EAAOJ,GAAK,IAAI;EAClB;CACJ;AACF;AAEA,SAASK,EAAa,GAAgC;CACpD,IAAM,EAAE,gBAAaC;CAErB,AADA,EAAM,WAAW,CAAC,GAClB,EAAM,OAAO;CACb,KAAK,IAAMC,KAASC,GAAU,EAAM,OAAO;AAC7C;AA8BA,SAAgBC,EACd,GAAGR,GACmB;CAGtB,IAAMS,IAAWC,EAA0B;EAAE;EAAM,MAAM;EAAM,UAAU,CAAC;CAAE,CAAC;CAI7E,QAAyB;EACvB,EAAS,QAAQ,OAAOV;CAC1B,CAAC;CAED,IAAMW,IAAYC,GAAa,MAAmB;EAChD,IAAMP,IAAQI,EAAS;EAEvB,IADAL,EAAUC,CAAK,GACXF,MAAS,MAGb,OAFA,EAAM,OAAOA,GACb,EAAM,WAAWN,EAAYQ,EAAM,IAAI,CAAC,CAAC,KAAK,MAAQJ,EAAOF,GAAKI,CAAI,CAAC,SAC1D;GAEX,AAAIE,EAAM,SAASF,KAAMC,EAAUC,CAAK;EAC1C;CACF,GAAG,CAAC,CAAC;CAyBL,OArBAQ,QAAsB;EACpB,IAAMR,IAAQI,EAAS,SACjB,EAAE,YAASJ;EACjB,IAAIF,MAAS,MAAM;EACnB,IAAMW,IAAOjB,EAAYG,CAAI;EAC7B,IACEP,EACEY,EAAM,SAAS,KAAK,MAAUC,EAAM,GAAG,GACvCQ,CACF,GAEA;EAEF,IAAMC,oBAAO,IAAI,IAAmC;EACpD,KAAK,IAAMT,KAASD,EAAM,UACxB,AAAIS,EAAK,SAASR,EAAM,GAAG,IAAGS,EAAK,IAAIT,EAAM,KAAKA,CAAK,IAClDA,EAAM,OAAO;EAEpB,EAAM,WAAWQ,EAAK,KAAK,MAAQC,EAAK,IAAIhB,CAAG,KAAKE,EAAOF,GAAKI,CAAI,CAAC;CACvE,CAAC,GAEMQ;AACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("../lib/globalRegistry.cjs"),t=require("../lib/layers.cjs");let n=require("react");var r=`[data-wave-announcer]`,i=`[data-wave-portal]`,a=new Set([`script`,`style`,`link`,`template`,`noscript`]);function o(){return e.getGlobalRegistry(`inert`,()=>({entries:new Map}))}function s(e){let{entries:t}=o(),n=t.get(e);n||(n={count:0,original:e.hasAttribute(`inert`)},t.set(e,n),n.original||e.setAttribute(`inert`,``)),n.count+=1}function c(e){let{entries:t}=o(),n=t.get(e);n&&(--n.count,!(n.count>0)&&(t.delete(e),n.original||e.removeAttribute(`inert`)))}function l(e){let n=t.getLayer(e);if(!n)return[];let r=[];for(let a of t.getOpenLayers())if(a.kind===`modal`&&a.id!==e&&!(t.isDescendantLayer(a.id,e)||t.compareLayers(a,n)<=0))for(let e of t.getLayerTreeElements(a.id))r.push(e.closest(i)??e);return r}function u(e,n){let o=e.ownerDocument,s=o.body,c=e.closest(i)??e,u=new Set([c,...t.getLayerTreeElements(n,{includeOwnElements:!1}),...l(n),...Array.from(o.querySelectorAll(t.ALLOW_OUTSIDE_SELECTOR)),...Array.from(o.querySelectorAll(r))]),d=new Set([s]);for(let e of u)if(e.isConnected&&s.contains(e))for(let t=e.parentElement;t&&t!==s;t=t.parentElement)d.add(t);let f=new Set,p=e=>{for(let t of Array.from(e.children))u.has(t)||(d.has(t)?p(t):a.has(t.localName)||f.add(t))};return p(s),{targets:f,path:d}}function d(e,r){let{layerId:i,container:a}=r;(0,n.useLayoutEffect)(()=>{if(!e||!a)return;let n=a.ownerDocument.body;if(!n)return;let r=new Set,o=new Set([n]),l=!0,d=t.registerLayerIsolation(i),f=()=>{if(!l||!a.isConnected)return;let e=u(a,i);o=e.path;for(let t of Array.from(r))e.targets.has(t)||(r.delete(t),c(t));for(let t of e.targets)r.has(t)||(r.add(t),s(t))};f();let p=t.subscribeLayers(f),m=null;return typeof MutationObserver<`u`&&(m=new MutationObserver(e=>{e.some(e=>e.type===`attributes`||e.target.nodeType===1&&o.has(e.target))&&f()}),m.observe(n,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`data-wave-focus-trap-allow`,`data-wave-announcer`]})),()=>{l=!1,d(),p(),m?.disconnect();for(let e of r)c(e);r.clear()}},[e,a,i])}exports.useModalIsolation=d;
|
|
2
|
+
//# sourceMappingURL=useModalIsolation.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useModalIsolation.cjs","names":["getGlobalRegistry","getLayer","getOpenLayers","isDescendantLayer","compareLayers","getLayerTreeElements","ALLOW_OUTSIDE_SELECTOR","registerLayerIsolation","subscribeLayers","require_globalRegistry","require_layers","react","ANNOUNCER_SELECTOR","PORTAL_SELECTOR","NON_RENDERED","getState","acquireInert","entry","entries","el","releaseInert","getModalsAboveElements","self","layerId","result","layer","plan","doc","container","body","root","kept","path","parent","targets","walk","child","useModalIsolation","options","enabled","applied","active","unregisterIsolation","reconcile","next","unsubscribe","observer","records","record"],"sources":["../../src/hooks/useModalIsolation.ts"],"sourcesContent":["import { useLayoutEffect } from 'react';\nimport { getGlobalRegistry } from '../lib/globalRegistry';\nimport {\n ALLOW_OUTSIDE_SELECTOR,\n compareLayers,\n getLayer,\n getLayerTreeElements,\n getOpenLayers,\n isDescendantLayer,\n registerLayerIsolation,\n subscribeLayers,\n} from '../lib/layers';\n\n/** Live regions of `useAnnounce`; never made inert. */\nconst ANNOUNCER_SELECTOR = '[data-wave-announcer]';\n/** The wrapper `Portal` renders around portaled content. */\nconst PORTAL_SELECTOR = '[data-wave-portal]';\n/** Children of `<body>` that render nothing; left alone. */\nconst NON_RENDERED = new Set(['script', 'style', 'link', 'template', 'noscript']);\n\ninterface InertEntry {\n count: number;\n /** Whether the element was inert before any modal touched it. */\n original: boolean;\n}\n\ninterface InertState {\n entries: Map<Element, InertEntry>;\n}\n\nfunction getState(): InertState {\n return getGlobalRegistry<InertState>('inert', () => ({ entries: new Map() }));\n}\n\nfunction acquireInert(el: Element): void {\n const { entries } = getState();\n let entry = entries.get(el);\n if (!entry) {\n entry = { count: 0, original: el.hasAttribute('inert') };\n entries.set(el, entry);\n if (!entry.original) el.setAttribute('inert', '');\n }\n entry.count += 1;\n}\n\nfunction releaseInert(el: Element): void {\n const { entries } = getState();\n const entry = entries.get(el);\n if (!entry) return;\n entry.count -= 1;\n if (entry.count > 0) return;\n entries.delete(el);\n if (!entry.original) el.removeAttribute('inert');\n}\n\ninterface Plan {\n targets: Set<Element>;\n /** Elements whose children were inspected (a kept element lies below them). */\n path: Set<Element>;\n}\n\n/**\n * The elements of every open modal stacked above the modal `layerId` that is not one of its\n * descendants (those are kept through its own tree): a confirm dialog driven by app state, opened\n * from inside this one but rendered as its React sibling. Each element is replaced by its portal\n * wrapper, so the other modal's backdrop stays interactive too. That modal isolates the page\n * (including this modal) itself and its focus trap is the active one; this modal re-plans when it\n * closes.\n */\nfunction getModalsAboveElements(layerId: string): Element[] {\n const self = getLayer(layerId);\n if (!self) return [];\n const result: Element[] = [];\n for (const layer of getOpenLayers()) {\n if (layer.kind !== 'modal' || layer.id === layerId) continue;\n if (isDescendantLayer(layer.id, layerId) || compareLayers(layer, self) <= 0) continue;\n for (const el of getLayerTreeElements(layer.id)) {\n result.push(el.closest(PORTAL_SELECTOR) ?? el);\n }\n }\n return result;\n}\n\n/**\n * Everything to make inert: walking down from `<body>`, every element that is neither a kept\n * element nor an ancestor of one. Kept: the modal's portal wrapper (its surface and backdrop), the\n * portal wrappers and surfaces of its descendant layers, modals stacked above it, allow-listed\n * regions and the announcer.\n */\nfunction plan(container: HTMLElement, layerId: string): Plan {\n const doc = container.ownerDocument;\n const body = doc.body;\n const root = container.closest<HTMLElement>(PORTAL_SELECTOR) ?? container;\n const kept = new Set<Element>([\n root,\n ...getLayerTreeElements(layerId, { includeOwnElements: false }),\n ...getModalsAboveElements(layerId),\n ...Array.from(doc.querySelectorAll(ALLOW_OUTSIDE_SELECTOR)),\n ...Array.from(doc.querySelectorAll(ANNOUNCER_SELECTOR)),\n ]);\n\n const path = new Set<Element>([body]);\n for (const el of kept) {\n if (!el.isConnected || !body.contains(el)) continue;\n for (let parent = el.parentElement; parent && parent !== body; parent = parent.parentElement) {\n path.add(parent);\n }\n }\n\n const targets = new Set<Element>();\n const walk = (parent: Element) => {\n for (const child of Array.from(parent.children)) {\n if (kept.has(child)) continue;\n if (path.has(child)) walk(child);\n else if (!NON_RENDERED.has(child.localName)) targets.add(child);\n }\n };\n walk(body);\n return { targets, path };\n}\n\n/**\n * Isolates a modal (Dialog, Drawer) from the rest of the page while `enabled` — the replacement\n * for `aria-modal`, which would also hide the Toaster and live regions from screen readers.\n *\n * Every element outside the modal's tree is made `inert` (not focusable, not clickable, absent\n * from the accessibility tree), walking from `<body>` down to the modal's portal wrapper. Kept\n * interactive: the modal's own portal wrapper, its descendant layers (popovers or listboxes opened\n * from inside it, which register their portal wrappers with the modal's layer), other modals\n * stacked above it that are not its descendants (a confirm dialog rendered elsewhere in the React\n * tree and opened from inside this one — it isolates the page, this modal included, itself),\n * `[data-wave-focus-trap-allow]` regions (toasts) and `[data-wave-announcer]` live regions.\n *\n * While enabled, the layer is also registered as isolating (`registerLayerIsolation`): outside\n * presses and Escape never reach the layers stacked below it, not even its own ancestor layers\n * (a modal-kind layer without this hook, such as the DatePicker calendar, blocks nothing).\n *\n * A MutationObserver inerts siblings added later (unless they belong to a kept tree), and the plan\n * is recomputed whenever a layer opens or closes. The previous\n * `inert` state of each element is saved and counted in a global registry, so nested modals\n * release their isolation in stack order and elements that were already inert stay inert.\n *\n * Runs in the layout phase: `useModalLayer` removes the isolation before it restores focus (an\n * inert opener cannot take focus).\n */\nexport function useModalIsolation(\n enabled: boolean,\n options: { layerId: string; container: HTMLElement | null },\n): void {\n const { layerId, container } = options;\n\n useLayoutEffect(() => {\n if (!enabled || !container) return;\n const doc = container.ownerDocument;\n const body = doc.body;\n if (!body) return;\n\n const applied = new Set<Element>();\n let path = new Set<Element>([body]);\n let active = true;\n // While isolated, the layer is a barrier: outside presses and Escape never reach the (inert)\n // layers stacked below it.\n const unregisterIsolation = registerLayerIsolation(layerId);\n\n const reconcile = () => {\n if (!active || !container.isConnected) return;\n const next = plan(container, layerId);\n path = next.path;\n for (const el of Array.from(applied)) {\n if (!next.targets.has(el)) {\n applied.delete(el);\n releaseInert(el);\n }\n }\n for (const el of next.targets) {\n if (!applied.has(el)) {\n applied.add(el);\n acquireInert(el);\n }\n }\n };\n\n reconcile();\n\n // A layer opening or closing can change what is kept (a modal stacked above this one, also an\n // inline one whose insertion the observer below would not see as relevant). Registration runs\n // in the layout phase, so a newly opened modal is kept before its focus trap moves focus in.\n const unsubscribe = subscribeLayers(reconcile);\n\n let observer: MutationObserver | null = null;\n if (typeof MutationObserver !== 'undefined') {\n observer = new MutationObserver((records) => {\n // Only changes along the kept paths (or to the kept markers) can change the plan.\n const relevant = records.some(\n (record) =>\n record.type === 'attributes' ||\n (record.target.nodeType === 1 && path.has(record.target as Element)),\n );\n if (relevant) reconcile();\n });\n observer.observe(body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-wave-focus-trap-allow', 'data-wave-announcer'],\n });\n }\n\n return () => {\n active = false;\n unregisterIsolation();\n unsubscribe();\n observer?.disconnect();\n for (const el of applied) releaseInert(el);\n applied.clear();\n };\n }, [enabled, container, layerId]);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { getGlobalRegistry as e } from "../lib/globalRegistry.mjs";
|
|
3
|
+
import { ALLOW_OUTSIDE_SELECTOR as t, compareLayers as n, getLayer as r, getLayerTreeElements as i, getOpenLayers as a, isDescendantLayer as o, registerLayerIsolation as s, subscribeLayers as c } from "../lib/layers.mjs";
|
|
4
|
+
import { useLayoutEffect as l } from "react";
|
|
5
|
+
//#region src/hooks/useModalIsolation.ts
|
|
6
|
+
var u = "[data-wave-announcer]", d = "[data-wave-portal]", f = /* @__PURE__ */ new Set([
|
|
7
|
+
"script",
|
|
8
|
+
"style",
|
|
9
|
+
"link",
|
|
10
|
+
"template",
|
|
11
|
+
"noscript"
|
|
12
|
+
]);
|
|
13
|
+
function p() {
|
|
14
|
+
return e("inert", () => ({ entries: /* @__PURE__ */ new Map() }));
|
|
15
|
+
}
|
|
16
|
+
function m(e) {
|
|
17
|
+
let { entries: t } = p(), n = t.get(e);
|
|
18
|
+
n || (n = {
|
|
19
|
+
count: 0,
|
|
20
|
+
original: e.hasAttribute("inert")
|
|
21
|
+
}, t.set(e, n), n.original || e.setAttribute("inert", "")), n.count += 1;
|
|
22
|
+
}
|
|
23
|
+
function h(e) {
|
|
24
|
+
let { entries: t } = p(), n = t.get(e);
|
|
25
|
+
n && (--n.count, !(n.count > 0) && (t.delete(e), n.original || e.removeAttribute("inert")));
|
|
26
|
+
}
|
|
27
|
+
function g(e) {
|
|
28
|
+
let t = r(e);
|
|
29
|
+
if (!t) return [];
|
|
30
|
+
let s = [];
|
|
31
|
+
for (let r of a()) if (r.kind === "modal" && r.id !== e && !(o(r.id, e) || n(r, t) <= 0)) for (let e of i(r.id)) s.push(e.closest(d) ?? e);
|
|
32
|
+
return s;
|
|
33
|
+
}
|
|
34
|
+
function _(e, n) {
|
|
35
|
+
let r = e.ownerDocument, a = r.body, o = e.closest(d) ?? e, s = /* @__PURE__ */ new Set([
|
|
36
|
+
o,
|
|
37
|
+
...i(n, { includeOwnElements: !1 }),
|
|
38
|
+
...g(n),
|
|
39
|
+
...Array.from(r.querySelectorAll(t)),
|
|
40
|
+
...Array.from(r.querySelectorAll(u))
|
|
41
|
+
]), c = /* @__PURE__ */ new Set([a]);
|
|
42
|
+
for (let e of s) if (e.isConnected && a.contains(e)) for (let t = e.parentElement; t && t !== a; t = t.parentElement) c.add(t);
|
|
43
|
+
let l = /* @__PURE__ */ new Set(), p = (e) => {
|
|
44
|
+
for (let t of Array.from(e.children)) s.has(t) || (c.has(t) ? p(t) : f.has(t.localName) || l.add(t));
|
|
45
|
+
};
|
|
46
|
+
return p(a), {
|
|
47
|
+
targets: l,
|
|
48
|
+
path: c
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function v(e, t) {
|
|
52
|
+
let { layerId: n, container: r } = t;
|
|
53
|
+
l(() => {
|
|
54
|
+
if (!e || !r) return;
|
|
55
|
+
let t = r.ownerDocument.body;
|
|
56
|
+
if (!t) return;
|
|
57
|
+
let i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set([t]), o = !0, l = s(n), u = () => {
|
|
58
|
+
if (!o || !r.isConnected) return;
|
|
59
|
+
let e = _(r, n);
|
|
60
|
+
a = e.path;
|
|
61
|
+
for (let t of Array.from(i)) e.targets.has(t) || (i.delete(t), h(t));
|
|
62
|
+
for (let t of e.targets) i.has(t) || (i.add(t), m(t));
|
|
63
|
+
};
|
|
64
|
+
u();
|
|
65
|
+
let d = c(u), f = null;
|
|
66
|
+
return typeof MutationObserver < "u" && (f = new MutationObserver((e) => {
|
|
67
|
+
e.some((e) => e.type === "attributes" || e.target.nodeType === 1 && a.has(e.target)) && u();
|
|
68
|
+
}), f.observe(t, {
|
|
69
|
+
childList: !0,
|
|
70
|
+
subtree: !0,
|
|
71
|
+
attributes: !0,
|
|
72
|
+
attributeFilter: ["data-wave-focus-trap-allow", "data-wave-announcer"]
|
|
73
|
+
})), () => {
|
|
74
|
+
o = !1, l(), d(), f?.disconnect();
|
|
75
|
+
for (let e of i) h(e);
|
|
76
|
+
i.clear();
|
|
77
|
+
};
|
|
78
|
+
}, [
|
|
79
|
+
e,
|
|
80
|
+
r,
|
|
81
|
+
n
|
|
82
|
+
]);
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { v as useModalIsolation };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=useModalIsolation.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useModalIsolation.mjs","names":["ANNOUNCER_SELECTOR","PORTAL_SELECTOR","NON_RENDERED","getState","getGlobalRegistry","acquireInert","entry","entries","el","releaseInert","getModalsAboveElements","self","getLayer","layerId","result","layer","getOpenLayers","compareLayers","getLayerTreeElements","plan","doc","container","body","root","kept","ALLOW_OUTSIDE_SELECTOR","path","parent","targets","walk","child","useModalIsolation","options","enabled","applied","active","unregisterIsolation","registerLayerIsolation","reconcile","next","unsubscribe","subscribeLayers","observer","records","record"],"sources":["../../src/hooks/useModalIsolation.ts"],"sourcesContent":["import { useLayoutEffect } from 'react';\nimport { getGlobalRegistry } from '../lib/globalRegistry';\nimport {\n ALLOW_OUTSIDE_SELECTOR,\n compareLayers,\n getLayer,\n getLayerTreeElements,\n getOpenLayers,\n isDescendantLayer,\n registerLayerIsolation,\n subscribeLayers,\n} from '../lib/layers';\n\n/** Live regions of `useAnnounce`; never made inert. */\nconst ANNOUNCER_SELECTOR = '[data-wave-announcer]';\n/** The wrapper `Portal` renders around portaled content. */\nconst PORTAL_SELECTOR = '[data-wave-portal]';\n/** Children of `<body>` that render nothing; left alone. */\nconst NON_RENDERED = new Set(['script', 'style', 'link', 'template', 'noscript']);\n\ninterface InertEntry {\n count: number;\n /** Whether the element was inert before any modal touched it. */\n original: boolean;\n}\n\ninterface InertState {\n entries: Map<Element, InertEntry>;\n}\n\nfunction getState(): InertState {\n return getGlobalRegistry<InertState>('inert', () => ({ entries: new Map() }));\n}\n\nfunction acquireInert(el: Element): void {\n const { entries } = getState();\n let entry = entries.get(el);\n if (!entry) {\n entry = { count: 0, original: el.hasAttribute('inert') };\n entries.set(el, entry);\n if (!entry.original) el.setAttribute('inert', '');\n }\n entry.count += 1;\n}\n\nfunction releaseInert(el: Element): void {\n const { entries } = getState();\n const entry = entries.get(el);\n if (!entry) return;\n entry.count -= 1;\n if (entry.count > 0) return;\n entries.delete(el);\n if (!entry.original) el.removeAttribute('inert');\n}\n\ninterface Plan {\n targets: Set<Element>;\n /** Elements whose children were inspected (a kept element lies below them). */\n path: Set<Element>;\n}\n\n/**\n * The elements of every open modal stacked above the modal `layerId` that is not one of its\n * descendants (those are kept through its own tree): a confirm dialog driven by app state, opened\n * from inside this one but rendered as its React sibling. Each element is replaced by its portal\n * wrapper, so the other modal's backdrop stays interactive too. That modal isolates the page\n * (including this modal) itself and its focus trap is the active one; this modal re-plans when it\n * closes.\n */\nfunction getModalsAboveElements(layerId: string): Element[] {\n const self = getLayer(layerId);\n if (!self) return [];\n const result: Element[] = [];\n for (const layer of getOpenLayers()) {\n if (layer.kind !== 'modal' || layer.id === layerId) continue;\n if (isDescendantLayer(layer.id, layerId) || compareLayers(layer, self) <= 0) continue;\n for (const el of getLayerTreeElements(layer.id)) {\n result.push(el.closest(PORTAL_SELECTOR) ?? el);\n }\n }\n return result;\n}\n\n/**\n * Everything to make inert: walking down from `<body>`, every element that is neither a kept\n * element nor an ancestor of one. Kept: the modal's portal wrapper (its surface and backdrop), the\n * portal wrappers and surfaces of its descendant layers, modals stacked above it, allow-listed\n * regions and the announcer.\n */\nfunction plan(container: HTMLElement, layerId: string): Plan {\n const doc = container.ownerDocument;\n const body = doc.body;\n const root = container.closest<HTMLElement>(PORTAL_SELECTOR) ?? container;\n const kept = new Set<Element>([\n root,\n ...getLayerTreeElements(layerId, { includeOwnElements: false }),\n ...getModalsAboveElements(layerId),\n ...Array.from(doc.querySelectorAll(ALLOW_OUTSIDE_SELECTOR)),\n ...Array.from(doc.querySelectorAll(ANNOUNCER_SELECTOR)),\n ]);\n\n const path = new Set<Element>([body]);\n for (const el of kept) {\n if (!el.isConnected || !body.contains(el)) continue;\n for (let parent = el.parentElement; parent && parent !== body; parent = parent.parentElement) {\n path.add(parent);\n }\n }\n\n const targets = new Set<Element>();\n const walk = (parent: Element) => {\n for (const child of Array.from(parent.children)) {\n if (kept.has(child)) continue;\n if (path.has(child)) walk(child);\n else if (!NON_RENDERED.has(child.localName)) targets.add(child);\n }\n };\n walk(body);\n return { targets, path };\n}\n\n/**\n * Isolates a modal (Dialog, Drawer) from the rest of the page while `enabled` — the replacement\n * for `aria-modal`, which would also hide the Toaster and live regions from screen readers.\n *\n * Every element outside the modal's tree is made `inert` (not focusable, not clickable, absent\n * from the accessibility tree), walking from `<body>` down to the modal's portal wrapper. Kept\n * interactive: the modal's own portal wrapper, its descendant layers (popovers or listboxes opened\n * from inside it, which register their portal wrappers with the modal's layer), other modals\n * stacked above it that are not its descendants (a confirm dialog rendered elsewhere in the React\n * tree and opened from inside this one — it isolates the page, this modal included, itself),\n * `[data-wave-focus-trap-allow]` regions (toasts) and `[data-wave-announcer]` live regions.\n *\n * While enabled, the layer is also registered as isolating (`registerLayerIsolation`): outside\n * presses and Escape never reach the layers stacked below it, not even its own ancestor layers\n * (a modal-kind layer without this hook, such as the DatePicker calendar, blocks nothing).\n *\n * A MutationObserver inerts siblings added later (unless they belong to a kept tree), and the plan\n * is recomputed whenever a layer opens or closes. The previous\n * `inert` state of each element is saved and counted in a global registry, so nested modals\n * release their isolation in stack order and elements that were already inert stay inert.\n *\n * Runs in the layout phase: `useModalLayer` removes the isolation before it restores focus (an\n * inert opener cannot take focus).\n */\nexport function useModalIsolation(\n enabled: boolean,\n options: { layerId: string; container: HTMLElement | null },\n): void {\n const { layerId, container } = options;\n\n useLayoutEffect(() => {\n if (!enabled || !container) return;\n const doc = container.ownerDocument;\n const body = doc.body;\n if (!body) return;\n\n const applied = new Set<Element>();\n let path = new Set<Element>([body]);\n let active = true;\n // While isolated, the layer is a barrier: outside presses and Escape never reach the (inert)\n // layers stacked below it.\n const unregisterIsolation = registerLayerIsolation(layerId);\n\n const reconcile = () => {\n if (!active || !container.isConnected) return;\n const next = plan(container, layerId);\n path = next.path;\n for (const el of Array.from(applied)) {\n if (!next.targets.has(el)) {\n applied.delete(el);\n releaseInert(el);\n }\n }\n for (const el of next.targets) {\n if (!applied.has(el)) {\n applied.add(el);\n acquireInert(el);\n }\n }\n };\n\n reconcile();\n\n // A layer opening or closing can change what is kept (a modal stacked above this one, also an\n // inline one whose insertion the observer below would not see as relevant). Registration runs\n // in the layout phase, so a newly opened modal is kept before its focus trap moves focus in.\n const unsubscribe = subscribeLayers(reconcile);\n\n let observer: MutationObserver | null = null;\n if (typeof MutationObserver !== 'undefined') {\n observer = new MutationObserver((records) => {\n // Only changes along the kept paths (or to the kept markers) can change the plan.\n const relevant = records.some(\n (record) =>\n record.type === 'attributes' ||\n (record.target.nodeType === 1 && path.has(record.target as Element)),\n );\n if (relevant) reconcile();\n });\n observer.observe(body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-wave-focus-trap-allow', 'data-wave-announcer'],\n });\n }\n\n return () => {\n active = false;\n unregisterIsolation();\n unsubscribe();\n observer?.disconnect();\n for (const el of applied) releaseInert(el);\n applied.clear();\n };\n }, [enabled, container, layerId]);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("./useDismiss.cjs"),t=require("./useFocusTrap.cjs"),n=require("./useRestoreFocus.cjs"),r=require("./useModalIsolation.cjs"),i=require("./useScrollLock.cjs");function a(a){let{container:o,initialFocus:s,triggerRef:c,finalFocusRef:l,...u}=a,{open:d}=a,f=e.useDismiss({...u,kind:`modal`});return t.useFocusTrap(o,{enabled:d,layerId:f.layerId,initialFocus:s}),r.useModalIsolation(d,{layerId:f.layerId,container:o}),i.useScrollLock(d),n.useRestoreFocus({enabled:d,container:o,triggerRef:c,finalFocusRef:l}),f}exports.useModalLayer=a;
|
|
2
|
+
//# sourceMappingURL=useModalLayer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useModalLayer.cjs","names":["useDismiss","require_useDismiss","require_useFocusTrap","require_useRestoreFocus","require_useModalIsolation","require_useScrollLock","useModalLayer","dismissOptions","options","layer","container","open"],"sources":["../../src/hooks/useModalLayer.ts"],"sourcesContent":["import type * as React from 'react';\nimport { useDismiss, type DismissLayer, type UseDismissOptions } from './useDismiss';\nimport { useFocusTrap, type UseFocusTrapOptions } from './useFocusTrap';\nimport { useModalIsolation } from './useModalIsolation';\nimport { useRestoreFocus } from './useRestoreFocus';\nimport { useScrollLock } from './useScrollLock';\n\n/** Options of {@link useModalLayer}: `useDismiss` options (kind is always `'modal'`) plus focus. */\nexport interface UseModalLayerOptions extends Omit<UseDismissOptions, 'kind'> {\n /** The modal surface, held in state via a callback ref. */\n container: HTMLElement | null;\n /** What the focus trap focuses first. @default 'first' */\n initialFocus?: UseFocusTrapOptions['initialFocus'];\n /** The trigger: preferred focus-restore target. */\n triggerRef?: React.RefObject<HTMLElement | null>;\n /** Consumer override for the focus-restore target. */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n}\n\n/**\n * Everything a modal surface (Dialog, Drawer) needs, composed in the order that works:\n *\n * 1. `useDismiss({ kind: 'modal' })` — Escape and outside presses (the backdrop is outside the\n * content surface, so a click on it dismisses; a drag from the content does not).\n * 2. `useFocusTrap` — initial focus, Tab cycle incl. toasts and descendant layers.\n * 3. `useModalIsolation` — the rest of the page is `inert` (instead of `aria-modal`).\n * 4. `useScrollLock` — ref-counted page scroll lock.\n * 5. `useRestoreFocus` — the opener (or `triggerRef`/`finalFocusRef`) gets focus back.\n *\n * On close the trap is released before the isolation is lifted, and the isolation is lifted\n * before focus is restored (an inert opener cannot take focus). Wrap the surface in\n * `Portal layerId={layerId}` so layers opened inside the modal become its descendants.\n */\nexport function useModalLayer(options: UseModalLayerOptions): DismissLayer {\n const { container, initialFocus, triggerRef, finalFocusRef, ...dismissOptions } = options;\n const { open } = options;\n\n const layer = useDismiss({ ...dismissOptions, kind: 'modal' });\n useFocusTrap(container, { enabled: open, layerId: layer.layerId, initialFocus });\n useModalIsolation(open, { layerId: layer.layerId, container });\n useScrollLock(open);\n useRestoreFocus({ enabled: open, container, triggerRef, finalFocusRef });\n\n return layer;\n}\n"],"mappings":"0LAiCA,SAAgBM,EAAc,EAA6C,CACzE,GAAM,CAAE,YAAW,eAAc,aAAY,gBAAe,GAAGC,GAAmBC,EAC5E,CAAE,QAASA,EAEXC,EAAQT,EAAAA,WAAW,CAAE,GAAGO,EAAgB,KAAM,OAAQ,CAAC,EAM7D,OALAL,EAAA,aAAaQ,EAAW,CAAE,QAASC,EAAM,QAASF,EAAM,QAAS,cAAa,CAAC,EAC/EL,EAAA,kBAAkBO,EAAM,CAAE,QAASF,EAAM,QAAS,WAAU,CAAC,EAC7DJ,EAAA,cAAcM,CAAI,EAClBR,EAAA,gBAAgB,CAAE,QAASQ,EAAM,YAAW,aAAY,eAAc,CAAC,EAEhEF,CACT"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useDismiss as e } from "./useDismiss.mjs";
|
|
3
|
+
import { useFocusTrap as t } from "./useFocusTrap.mjs";
|
|
4
|
+
import { useRestoreFocus as n } from "./useRestoreFocus.mjs";
|
|
5
|
+
import { useModalIsolation as r } from "./useModalIsolation.mjs";
|
|
6
|
+
import { useScrollLock as i } from "./useScrollLock.mjs";
|
|
7
|
+
//#region src/hooks/useModalLayer.ts
|
|
8
|
+
function a(a) {
|
|
9
|
+
let { container: o, initialFocus: s, triggerRef: c, finalFocusRef: l, ...u } = a, { open: d } = a, f = e({
|
|
10
|
+
...u,
|
|
11
|
+
kind: "modal"
|
|
12
|
+
});
|
|
13
|
+
return t(o, {
|
|
14
|
+
enabled: d,
|
|
15
|
+
layerId: f.layerId,
|
|
16
|
+
initialFocus: s
|
|
17
|
+
}), r(d, {
|
|
18
|
+
layerId: f.layerId,
|
|
19
|
+
container: o
|
|
20
|
+
}), i(d), n({
|
|
21
|
+
enabled: d,
|
|
22
|
+
container: o,
|
|
23
|
+
triggerRef: c,
|
|
24
|
+
finalFocusRef: l
|
|
25
|
+
}), f;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { a as useModalLayer };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=useModalLayer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useModalLayer.mjs","names":["useModalLayer","dismissOptions","options","layer","useDismiss","useFocusTrap","container","open","useModalIsolation","useScrollLock","useRestoreFocus"],"sources":["../../src/hooks/useModalLayer.ts"],"sourcesContent":["import type * as React from 'react';\nimport { useDismiss, type DismissLayer, type UseDismissOptions } from './useDismiss';\nimport { useFocusTrap, type UseFocusTrapOptions } from './useFocusTrap';\nimport { useModalIsolation } from './useModalIsolation';\nimport { useRestoreFocus } from './useRestoreFocus';\nimport { useScrollLock } from './useScrollLock';\n\n/** Options of {@link useModalLayer}: `useDismiss` options (kind is always `'modal'`) plus focus. */\nexport interface UseModalLayerOptions extends Omit<UseDismissOptions, 'kind'> {\n /** The modal surface, held in state via a callback ref. */\n container: HTMLElement | null;\n /** What the focus trap focuses first. @default 'first' */\n initialFocus?: UseFocusTrapOptions['initialFocus'];\n /** The trigger: preferred focus-restore target. */\n triggerRef?: React.RefObject<HTMLElement | null>;\n /** Consumer override for the focus-restore target. */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n}\n\n/**\n * Everything a modal surface (Dialog, Drawer) needs, composed in the order that works:\n *\n * 1. `useDismiss({ kind: 'modal' })` — Escape and outside presses (the backdrop is outside the\n * content surface, so a click on it dismisses; a drag from the content does not).\n * 2. `useFocusTrap` — initial focus, Tab cycle incl. toasts and descendant layers.\n * 3. `useModalIsolation` — the rest of the page is `inert` (instead of `aria-modal`).\n * 4. `useScrollLock` — ref-counted page scroll lock.\n * 5. `useRestoreFocus` — the opener (or `triggerRef`/`finalFocusRef`) gets focus back.\n *\n * On close the trap is released before the isolation is lifted, and the isolation is lifted\n * before focus is restored (an inert opener cannot take focus). Wrap the surface in\n * `Portal layerId={layerId}` so layers opened inside the modal become its descendants.\n */\nexport function useModalLayer(options: UseModalLayerOptions): DismissLayer {\n const { container, initialFocus, triggerRef, finalFocusRef, ...dismissOptions } = options;\n const { open } = options;\n\n const layer = useDismiss({ ...dismissOptions, kind: 'modal' });\n useFocusTrap(container, { enabled: open, layerId: layer.layerId, initialFocus });\n useModalIsolation(open, { layerId: layer.layerId, container });\n useScrollLock(open);\n useRestoreFocus({ enabled: open, container, triggerRef, finalFocusRef });\n\n return layer;\n}\n"],"mappings":";;;;;;;AAiCA,SAAgBA,EAAc,GAA6C;CACzE,IAAM,EAAE,cAAW,iBAAc,eAAY,kBAAe,GAAGC,MAAmBC,GAC5E,EAAE,YAASA,GAEXC,IAAQC,EAAW;EAAE,GAAGH;EAAgB,MAAM;CAAQ,CAAC;CAM7D,OALAI,EAAaC,GAAW;EAAE,SAASC;EAAM,SAASJ,EAAM;EAAS;CAAa,CAAC,GAC/EK,EAAkBD,GAAM;EAAE,SAASJ,EAAM;EAAS;CAAU,CAAC,GAC7DM,EAAcF,CAAI,GAClBG,EAAgB;EAAE,SAASH;EAAM;EAAW;EAAY;CAAc,CAAC,GAEhEJ;AACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("./useEventCallback.cjs"),t=require("./useDirection.cjs");let n=require("react"),r=require("@floating-ui/react-dom");var i={top:`bottom`,bottom:`top`,left:`right`,right:`left`},a=`calc(var(--wave-popup-arrow-size, 8px) / -2)`;function o(e,t){return e===`start`?t===`rtl`?`right`:`left`:e===`end`?t===`rtl`?`left`:`right`:e}var s={x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0};function c(e){return typeof e.nodeType==`number`}function l(e,t){return{getBoundingClientRect:()=>e.current?.getBoundingClientRect()??s,contextElement:t}}function u(e,t,n){return(0,r.autoUpdate)(e,t,n,{elementResize:typeof ResizeObserver<`u`,layoutShift:typeof IntersectionObserver<`u`})}var d=({availableWidth:e,availableHeight:t,rects:n,elements:r})=>{let i=r.floating.style;i.setProperty(`--wave-popup-available-width`,`${Math.max(0,Math.floor(e))}px`),i.setProperty(`--wave-popup-available-height`,`${Math.max(0,Math.floor(t))}px`),i.setProperty(`--wave-popup-reference-width`,`${Math.round(n.reference.width)}px`)};function f(s){let{open:f,side:p=`bottom`,align:m=`start`,offset:h=4,flip:g=!0,shift:_={padding:8},matchReferenceWidth:v=!1,fitViewport:y=!1,arrowRef:b,strategy:x=`fixed`}=s,S=t.useDirection(),C=o(p,S),w=m===`center`?C:`${C}-${m}`,T=_===!1?0:_===!0?8:_.padding,E=typeof _==`object`&&_.crossAxis===!0,D=[(0,r.offset)(h)];g&&D.push((0,r.flip)({padding:T})),_!==!1&&D.push((0,r.shift)({padding:T,crossAxis:E})),(v||y)&&D.push((0,r.size)({padding:T,apply:d})),b&&D.push((0,r.arrow)({element:b}));let O=(0,n.useMemo)(()=>({...r.platform,isRTL:()=>S===`rtl`}),[S]),{refs:k,floatingStyles:A,placement:j,middlewareData:M,isPositioned:N,update:P}=(0,r.useFloating)({open:f,placement:w,strategy:x,middleware:D,platform:O,whileElementsMounted:f?u:void 0}),F=(0,n.useRef)(null),I=(0,n.useRef)(null),L=e.useEventCallback(P),{setReference:R,reference:z}=k,B=(0,n.useCallback)(e=>{if(e===null||c(e)){F.current=null,R(e);return}F.current=e;let t=I.current;(!t||t.contextElement!==e.contextElement)&&(t=l(F,e.contextElement),I.current=t),z.current===t?L():R(t)},[R,z,L]),[V,H=`center`]=j.split(`-`),U=(0,n.useMemo)(()=>{let e={...A};return v&&(e.width=`var(--wave-popup-reference-width)`),y&&(e.maxWidth=`var(--wave-popup-available-width)`,e.maxHeight=`var(--wave-popup-available-height)`),e},[A,v,y]),W=M.arrow?.x,G=M.arrow?.y,K=(0,n.useMemo)(()=>{let e={position:`absolute`,left:W==null?``:`${W}px`,top:G==null?``:`${G}px`};return e[i[V]]=a,e},[W,G,V]),q=(0,n.useMemo)(()=>({"data-side":V,"data-align":H,style:U}),[V,H,U]);return{setReference:B,setFloating:k.setFloating,floatingStyles:U,arrowStyles:K,placement:j,side:V,isPositioned:N,floatingProps:q}}exports.usePopupPosition=f;
|
|
2
|
+
//# sourceMappingURL=usePopupPosition.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePopupPosition.cjs","names":["autoUpdate","useDirection","offsetMiddleware","flipMiddleware","shiftMiddleware","sizeMiddleware","arrowMiddleware","useMemo","platform","useFloating","useRef","useEventCallback","useCallback","require_useEventCallback","require_useDirection","react","_floating_ui_react_dom","STATIC_SIDE","ARROW_OFFSET","resolveSide","side","dir","EMPTY_RECT","isElementAnchor","anchor","createVirtualProxy","latest","whileElementsMounted","reference","floating","update","sizeApply","style","elements","availableWidth","availableHeight","rects","usePopupPosition","options","physicalSide","requestedPlacement","align","padding","shift","shiftCrossAxis","middleware","offset","flip","matchReferenceWidth","fitViewport","arrowRef","directionalPlatform","open","virtualRef","proxyRef","updatePosition","setFloatingReference","floatingReference","refs","setReference","proxy","finalSide","finalAlign","placement","next","floatingStyles","arrowX","middlewareData","arrowY","arrowStyles","styles","floatingProps"],"sources":["../../src/hooks/usePopupPosition.ts"],"sourcesContent":["import { useCallback, useMemo, useRef } from 'react';\nimport type * as React from 'react';\nimport {\n arrow as arrowMiddleware,\n autoUpdate,\n flip as flipMiddleware,\n offset as offsetMiddleware,\n platform,\n shift as shiftMiddleware,\n size as sizeMiddleware,\n useFloating,\n type Middleware,\n type Placement,\n type Platform,\n type ReferenceType,\n type SizeOptions,\n} from '@floating-ui/react-dom';\nimport type { PopupAlign, PopupRect, PopupSide, VirtualElement } from '../lib/types';\nimport type { Direction } from '../lib/direction';\nimport { useDirection } from './useDirection';\nimport { useEventCallback } from './useEventCallback';\n\n/** Options of {@link usePopupPosition}. */\nexport interface UsePopupPositionOptions {\n /** Whether the popup is open; positions are kept up to date only while `true`. */\n open: boolean;\n /** Side of the anchor. `start`/`end` follow the writing direction. @default 'bottom' */\n side?: PopupSide;\n /** Alignment along that side. @default 'start' */\n align?: PopupAlign;\n /** Distance from the anchor in px. @default 4 (tooltips use 8) */\n offset?: number;\n /** Flip to the opposite side when there is not enough room. @default true */\n flip?: boolean;\n /**\n * Shift along the side to stay inside the viewport. Its padding is also the viewport padding of\n * `flip` and of `size` (`fitViewport`, `matchReferenceWidth`): `true` means 8px, and `false`\n * lets the popup flip only once it touches the viewport edge and grow right up to it. With\n * `crossAxis: true` it also shifts across the side, over the anchor, when neither side has room\n * after `flip` (submenus), and `fitViewport` then offers the whole viewport in that direction.\n * @default { padding: 8 }\n */\n shift?: boolean | { padding: number; crossAxis?: boolean };\n /** Make the surface as wide as the anchor (listboxes). @default false */\n matchReferenceWidth?: boolean;\n /** Limit the surface to the available space (`max-width`/`max-height`). @default false */\n fitViewport?: boolean;\n /** An arrow (beak) element inside the surface, positioned through `arrowStyles`. */\n arrowRef?: React.RefObject<HTMLElement | null>;\n /** CSS positioning strategy. @default 'fixed' */\n strategy?: 'absolute' | 'fixed';\n}\n\n/** Returned by {@link usePopupPosition}. */\nexport interface UsePopupPositionResult {\n /**\n * Sets the anchor: a ref callback for the anchor (trigger) element, or a call from a layout\n * effect or an event. The anchor is an element or a `VirtualElement` (a rectangle such as the\n * pointer position; a new object on every render is fine); give it a `contextElement` so\n * scrolling its containers updates the position.\n */\n setReference(el: HTMLElement | VirtualElement | null): void;\n /** Ref callback for the popup surface. */\n setFloating(el: HTMLElement | null): void;\n /** Position styles for the surface (also in `floatingProps.style`). */\n floatingStyles: React.CSSProperties;\n /** Position styles for the arrow element. */\n arrowStyles: React.CSSProperties;\n /** Final placement after flipping, e.g. `'top-start'`. */\n placement: string;\n /** Final physical side after flipping. */\n side: 'top' | 'bottom' | 'left' | 'right';\n /** Whether a position has been computed since the popup opened. */\n isPositioned: boolean;\n /** Spread onto the surface: `data-side`, `data-align` and the position style. */\n floatingProps: { 'data-side': string; 'data-align': string; style: React.CSSProperties };\n}\n\ntype PhysicalSide = 'top' | 'bottom' | 'left' | 'right';\n\nconst STATIC_SIDE: Record<PhysicalSide, PhysicalSide> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\n/** Half the arrow size, so the arrow sticks out of the surface towards the anchor. */\nconst ARROW_OFFSET = 'calc(var(--wave-popup-arrow-size, 8px) / -2)';\n\nfunction resolveSide(side: PopupSide, dir: Direction): PhysicalSide {\n if (side === 'start') return dir === 'rtl' ? 'right' : 'left';\n if (side === 'end') return dir === 'rtl' ? 'left' : 'right';\n return side;\n}\n\n/** The rectangle of a virtual anchor that is not set (never reached while one is the reference). */\nconst EMPTY_RECT: PopupRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n};\n\n/** Whether an anchor is a DOM element (duck typed, so an element of another realm counts). */\nfunction isElementAnchor(anchor: HTMLElement | VirtualElement): anchor is HTMLElement {\n return typeof (anchor as Partial<Node>).nodeType === 'number';\n}\n\n/**\n * The stable stand-in floating-ui gets for virtual anchors: it reads the latest `VirtualElement`\n * from `latest`, so a new virtual object sets no floating-ui state. One proxy per\n * `contextElement`, so `autoUpdate` observes the scroll containers of the current one.\n */\ninterface VirtualProxy extends VirtualElement {\n contextElement: Element | undefined;\n}\n\nfunction createVirtualProxy(\n latest: React.RefObject<VirtualElement | null>,\n contextElement: Element | undefined,\n): VirtualProxy {\n return {\n getBoundingClientRect: () => latest.current?.getBoundingClientRect() ?? EMPTY_RECT,\n contextElement,\n };\n}\n\n/** Keeps the position updated while mounted; observers are used only where they exist. */\nfunction whileElementsMounted(\n reference: ReferenceType,\n floating: HTMLElement,\n update: () => void,\n): () => void {\n return autoUpdate(reference, floating, update, {\n elementResize: typeof ResizeObserver !== 'undefined',\n layoutShift: typeof IntersectionObserver !== 'undefined',\n });\n}\n\n/**\n * Writes the available space and the anchor width as CSS variables on the surface:\n * `--wave-popup-available-width`, `--wave-popup-available-height`, `--wave-popup-reference-width`.\n * It captures no options (floating-ui compares middleware functions by source text).\n */\nconst sizeApply: NonNullable<SizeOptions['apply']> = ({\n availableWidth,\n availableHeight,\n rects,\n elements,\n}) => {\n const style = elements.floating.style;\n style.setProperty('--wave-popup-available-width', `${Math.max(0, Math.floor(availableWidth))}px`);\n style.setProperty(\n '--wave-popup-available-height',\n `${Math.max(0, Math.floor(availableHeight))}px`,\n );\n style.setProperty('--wave-popup-reference-width', `${Math.round(rects.reference.width)}px`);\n};\n\n/**\n * Positions a popup surface next to its anchor with `@floating-ui/react-dom` (Tooltip, Popover,\n * Menu, listboxes, the DatePicker calendar, TeachingPopover): `offset`, `flip`, `shift`, optional\n * `size` (reference width / available space as CSS variables) and `arrow`. `flip`, `shift` and\n * `size` keep the same viewport padding, taken from the `shift` option (8px by default). Logical\n * `start`/`end` sides follow `useDirection()` (the WaveProvider `dir`, else the document\n * direction), and so does start/end alignment.\n *\n * Positions update only while `open` (`autoUpdate` on scroll/resize; element resizes and layout\n * shifts only where `ResizeObserver`/`IntersectionObserver` exist). Spread `floatingProps` onto the\n * surface: `data-side`/`data-align` expose the final placement for styling (C-CLASS).\n *\n * The anchor is an element or a `VirtualElement` (a rectangle such as the pointer position; a new\n * object on every render is fine); give it a `contextElement` so scrolling its containers updates\n * the position. A virtual anchor reaches floating-ui through one stable proxy that reads the latest\n * object: a new object only recomputes the position (which renders only when the position\n * changes), and a new proxy is made only when the `contextElement` changes.\n *\n * Destructure the result: `eslint-plugin-react-hooks` (`react-hooks/refs`) treats an object\n * whose member is passed to a `ref` prop as a ref, and then rejects reading its other members\n * during render.\n *\n * @example\n * const { setReference, setFloating, floatingProps } = usePopupPosition({ open, side: 'bottom' });\n * <button ref={setReference} />\n * {open && <Portal><div ref={setFloating} {...floatingProps} /></Portal>}\n */\nexport function usePopupPosition(options: UsePopupPositionOptions): UsePopupPositionResult {\n const {\n open,\n side = 'bottom',\n align = 'start',\n offset = 4,\n flip = true,\n shift = { padding: 8 },\n matchReferenceWidth = false,\n fitViewport = false,\n arrowRef,\n strategy = 'fixed',\n } = options;\n const dir = useDirection();\n const physicalSide = resolveSide(side, dir);\n const requestedPlacement = (\n align === 'center' ? physicalSide : `${physicalSide}-${align}`\n ) as Placement;\n const padding = shift === false ? 0 : shift === true ? 8 : shift.padding;\n const shiftCrossAxis = typeof shift === 'object' && shift.crossAxis === true;\n\n const middleware: Middleware[] = [offsetMiddleware(offset)];\n if (flip) middleware.push(flipMiddleware({ padding }));\n if (shift !== false) {\n middleware.push(shiftMiddleware({ padding, crossAxis: shiftCrossAxis }));\n }\n if (matchReferenceWidth || fitViewport) {\n middleware.push(sizeMiddleware({ padding, apply: sizeApply }));\n }\n if (arrowRef) middleware.push(arrowMiddleware({ element: arrowRef }));\n\n // Alignment follows the hook's direction (not only the surface's computed CSS direction).\n const directionalPlatform = useMemo<Platform>(\n () => ({ ...platform, isRTL: () => dir === 'rtl' }),\n [dir],\n );\n\n const { refs, floatingStyles, placement, middlewareData, isPositioned, update } = useFloating({\n open,\n placement: requestedPlacement,\n strategy,\n middleware,\n platform: directionalPlatform,\n whileElementsMounted: open ? whileElementsMounted : undefined,\n });\n\n // Virtual anchors: the latest object (written in setReference, never during render) and the\n // proxy floating-ui holds for it.\n const virtualRef = useRef<VirtualElement | null>(null);\n const proxyRef = useRef<VirtualProxy | null>(null);\n const updatePosition = useEventCallback(update);\n const { setReference: setFloatingReference, reference: floatingReference } = refs;\n const setReference = useCallback(\n (anchor: HTMLElement | VirtualElement | null) => {\n if (anchor === null || isElementAnchor(anchor)) {\n virtualRef.current = null;\n setFloatingReference(anchor);\n return;\n }\n virtualRef.current = anchor;\n let proxy = proxyRef.current;\n if (!proxy || proxy.contextElement !== anchor.contextElement) {\n proxy = createVirtualProxy(virtualRef, anchor.contextElement);\n proxyRef.current = proxy;\n }\n if (floatingReference.current === proxy) updatePosition();\n else setFloatingReference(proxy);\n },\n [setFloatingReference, floatingReference, updatePosition],\n );\n\n const [finalSide, finalAlign = 'center'] = placement.split('-') as [PhysicalSide, string?];\n\n const style = useMemo<React.CSSProperties>(() => {\n const next: React.CSSProperties = { ...floatingStyles };\n if (matchReferenceWidth) next.width = 'var(--wave-popup-reference-width)';\n if (fitViewport) {\n next.maxWidth = 'var(--wave-popup-available-width)';\n next.maxHeight = 'var(--wave-popup-available-height)';\n }\n return next;\n }, [floatingStyles, matchReferenceWidth, fitViewport]);\n\n const arrowX = middlewareData.arrow?.x;\n const arrowY = middlewareData.arrow?.y;\n const arrowStyles = useMemo<React.CSSProperties>(() => {\n const styles: Record<string, string> = {\n position: 'absolute',\n left: arrowX != null ? `${arrowX}px` : '',\n top: arrowY != null ? `${arrowY}px` : '',\n };\n styles[STATIC_SIDE[finalSide]] = ARROW_OFFSET;\n return styles as React.CSSProperties;\n }, [arrowX, arrowY, finalSide]);\n\n const floatingProps = useMemo(\n () => ({ 'data-side': finalSide, 'data-align': finalAlign, style }),\n [finalSide, finalAlign, style],\n );\n\n return {\n setReference,\n setFloating: refs.setFloating,\n floatingStyles: style,\n arrowStyles,\n placement,\n side: finalSide,\n isPositioned,\n floatingProps,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEventCallback as e } from "./useEventCallback.mjs";
|
|
3
|
+
import { useDirection as t } from "./useDirection.mjs";
|
|
4
|
+
import { useCallback as n, useMemo as r, useRef as i } from "react";
|
|
5
|
+
import { arrow as a, autoUpdate as o, flip as s, offset as c, platform as l, shift as u, size as d, useFloating as f } from "@floating-ui/react-dom";
|
|
6
|
+
//#region src/hooks/usePopupPosition.ts
|
|
7
|
+
var p = {
|
|
8
|
+
top: "bottom",
|
|
9
|
+
bottom: "top",
|
|
10
|
+
left: "right",
|
|
11
|
+
right: "left"
|
|
12
|
+
}, m = "calc(var(--wave-popup-arrow-size, 8px) / -2)";
|
|
13
|
+
function h(e, t) {
|
|
14
|
+
return e === "start" ? t === "rtl" ? "right" : "left" : e === "end" ? t === "rtl" ? "left" : "right" : e;
|
|
15
|
+
}
|
|
16
|
+
var g = {
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0,
|
|
19
|
+
width: 0,
|
|
20
|
+
height: 0,
|
|
21
|
+
top: 0,
|
|
22
|
+
right: 0,
|
|
23
|
+
bottom: 0,
|
|
24
|
+
left: 0
|
|
25
|
+
};
|
|
26
|
+
function _(e) {
|
|
27
|
+
return typeof e.nodeType == "number";
|
|
28
|
+
}
|
|
29
|
+
function v(e, t) {
|
|
30
|
+
return {
|
|
31
|
+
getBoundingClientRect: () => e.current?.getBoundingClientRect() ?? g,
|
|
32
|
+
contextElement: t
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function y(e, t, n) {
|
|
36
|
+
return o(e, t, n, {
|
|
37
|
+
elementResize: typeof ResizeObserver < "u",
|
|
38
|
+
layoutShift: typeof IntersectionObserver < "u"
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
var b = ({ availableWidth: e, availableHeight: t, rects: n, elements: r }) => {
|
|
42
|
+
let i = r.floating.style;
|
|
43
|
+
i.setProperty("--wave-popup-available-width", `${Math.max(0, Math.floor(e))}px`), i.setProperty("--wave-popup-available-height", `${Math.max(0, Math.floor(t))}px`), i.setProperty("--wave-popup-reference-width", `${Math.round(n.reference.width)}px`);
|
|
44
|
+
};
|
|
45
|
+
function x(o) {
|
|
46
|
+
let { open: g, side: x = "bottom", align: S = "start", offset: C = 4, flip: w = !0, shift: T = { padding: 8 }, matchReferenceWidth: E = !1, fitViewport: D = !1, arrowRef: O, strategy: k = "fixed" } = o, A = t(), j = h(x, A), M = S === "center" ? j : `${j}-${S}`, N = T === !1 ? 0 : T === !0 ? 8 : T.padding, P = typeof T == "object" && T.crossAxis === !0, F = [c(C)];
|
|
47
|
+
w && F.push(s({ padding: N })), T !== !1 && F.push(u({
|
|
48
|
+
padding: N,
|
|
49
|
+
crossAxis: P
|
|
50
|
+
})), (E || D) && F.push(d({
|
|
51
|
+
padding: N,
|
|
52
|
+
apply: b
|
|
53
|
+
})), O && F.push(a({ element: O }));
|
|
54
|
+
let I = r(() => ({
|
|
55
|
+
...l,
|
|
56
|
+
isRTL: () => A === "rtl"
|
|
57
|
+
}), [A]), { refs: L, floatingStyles: R, placement: z, middlewareData: B, isPositioned: V, update: H } = f({
|
|
58
|
+
open: g,
|
|
59
|
+
placement: M,
|
|
60
|
+
strategy: k,
|
|
61
|
+
middleware: F,
|
|
62
|
+
platform: I,
|
|
63
|
+
whileElementsMounted: g ? y : void 0
|
|
64
|
+
}), U = i(null), W = i(null), G = e(H), { setReference: K, reference: q } = L, J = n((e) => {
|
|
65
|
+
if (e === null || _(e)) {
|
|
66
|
+
U.current = null, K(e);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
U.current = e;
|
|
70
|
+
let t = W.current;
|
|
71
|
+
(!t || t.contextElement !== e.contextElement) && (t = v(U, e.contextElement), W.current = t), q.current === t ? G() : K(t);
|
|
72
|
+
}, [
|
|
73
|
+
K,
|
|
74
|
+
q,
|
|
75
|
+
G
|
|
76
|
+
]), [Y, X = "center"] = z.split("-"), Z = r(() => {
|
|
77
|
+
let e = { ...R };
|
|
78
|
+
return E && (e.width = "var(--wave-popup-reference-width)"), D && (e.maxWidth = "var(--wave-popup-available-width)", e.maxHeight = "var(--wave-popup-available-height)"), e;
|
|
79
|
+
}, [
|
|
80
|
+
R,
|
|
81
|
+
E,
|
|
82
|
+
D
|
|
83
|
+
]), Q = B.arrow?.x, $ = B.arrow?.y, ee = r(() => {
|
|
84
|
+
let e = {
|
|
85
|
+
position: "absolute",
|
|
86
|
+
left: Q == null ? "" : `${Q}px`,
|
|
87
|
+
top: $ == null ? "" : `${$}px`
|
|
88
|
+
};
|
|
89
|
+
return e[p[Y]] = m, e;
|
|
90
|
+
}, [
|
|
91
|
+
Q,
|
|
92
|
+
$,
|
|
93
|
+
Y
|
|
94
|
+
]), te = r(() => ({
|
|
95
|
+
"data-side": Y,
|
|
96
|
+
"data-align": X,
|
|
97
|
+
style: Z
|
|
98
|
+
}), [
|
|
99
|
+
Y,
|
|
100
|
+
X,
|
|
101
|
+
Z
|
|
102
|
+
]);
|
|
103
|
+
return {
|
|
104
|
+
setReference: J,
|
|
105
|
+
setFloating: L.setFloating,
|
|
106
|
+
floatingStyles: Z,
|
|
107
|
+
arrowStyles: ee,
|
|
108
|
+
placement: z,
|
|
109
|
+
side: Y,
|
|
110
|
+
isPositioned: V,
|
|
111
|
+
floatingProps: te
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { x as usePopupPosition };
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=usePopupPosition.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePopupPosition.mjs","names":["shift","offsetMiddleware","offset","flip","flipMiddleware","shiftMiddleware","sizeMiddleware","arrowMiddleware","STATIC_SIDE","ARROW_OFFSET","resolveSide","side","dir","EMPTY_RECT","isElementAnchor","anchor","createVirtualProxy","latest","whileElementsMounted","autoUpdate","reference","floating","update","sizeApply","style","elements","availableWidth","availableHeight","rects","usePopupPosition","offset$1","flip$1","shift$1","options","useDirection","physicalSide","requestedPlacement","align","padding","shiftCrossAxis","middleware","offset","flip","shift","matchReferenceWidth","fitViewport","size","arrowRef","arrow","directionalPlatform","useMemo","platform","useFloating","open","virtualRef","useRef","proxyRef","updatePosition","useEventCallback","setFloatingReference","floatingReference","refs","setReference","useCallback","proxy","finalSide","finalAlign","placement","next","floatingStyles","arrowX","middlewareData","arrowY","arrowStyles","styles","floatingProps"],"sources":["../../src/hooks/usePopupPosition.ts"],"sourcesContent":["import { useCallback, useMemo, useRef } from 'react';\nimport type * as React from 'react';\nimport {\n arrow as arrowMiddleware,\n autoUpdate,\n flip as flipMiddleware,\n offset as offsetMiddleware,\n platform,\n shift as shiftMiddleware,\n size as sizeMiddleware,\n useFloating,\n type Middleware,\n type Placement,\n type Platform,\n type ReferenceType,\n type SizeOptions,\n} from '@floating-ui/react-dom';\nimport type { PopupAlign, PopupRect, PopupSide, VirtualElement } from '../lib/types';\nimport type { Direction } from '../lib/direction';\nimport { useDirection } from './useDirection';\nimport { useEventCallback } from './useEventCallback';\n\n/** Options of {@link usePopupPosition}. */\nexport interface UsePopupPositionOptions {\n /** Whether the popup is open; positions are kept up to date only while `true`. */\n open: boolean;\n /** Side of the anchor. `start`/`end` follow the writing direction. @default 'bottom' */\n side?: PopupSide;\n /** Alignment along that side. @default 'start' */\n align?: PopupAlign;\n /** Distance from the anchor in px. @default 4 (tooltips use 8) */\n offset?: number;\n /** Flip to the opposite side when there is not enough room. @default true */\n flip?: boolean;\n /**\n * Shift along the side to stay inside the viewport. Its padding is also the viewport padding of\n * `flip` and of `size` (`fitViewport`, `matchReferenceWidth`): `true` means 8px, and `false`\n * lets the popup flip only once it touches the viewport edge and grow right up to it. With\n * `crossAxis: true` it also shifts across the side, over the anchor, when neither side has room\n * after `flip` (submenus), and `fitViewport` then offers the whole viewport in that direction.\n * @default { padding: 8 }\n */\n shift?: boolean | { padding: number; crossAxis?: boolean };\n /** Make the surface as wide as the anchor (listboxes). @default false */\n matchReferenceWidth?: boolean;\n /** Limit the surface to the available space (`max-width`/`max-height`). @default false */\n fitViewport?: boolean;\n /** An arrow (beak) element inside the surface, positioned through `arrowStyles`. */\n arrowRef?: React.RefObject<HTMLElement | null>;\n /** CSS positioning strategy. @default 'fixed' */\n strategy?: 'absolute' | 'fixed';\n}\n\n/** Returned by {@link usePopupPosition}. */\nexport interface UsePopupPositionResult {\n /**\n * Sets the anchor: a ref callback for the anchor (trigger) element, or a call from a layout\n * effect or an event. The anchor is an element or a `VirtualElement` (a rectangle such as the\n * pointer position; a new object on every render is fine); give it a `contextElement` so\n * scrolling its containers updates the position.\n */\n setReference(el: HTMLElement | VirtualElement | null): void;\n /** Ref callback for the popup surface. */\n setFloating(el: HTMLElement | null): void;\n /** Position styles for the surface (also in `floatingProps.style`). */\n floatingStyles: React.CSSProperties;\n /** Position styles for the arrow element. */\n arrowStyles: React.CSSProperties;\n /** Final placement after flipping, e.g. `'top-start'`. */\n placement: string;\n /** Final physical side after flipping. */\n side: 'top' | 'bottom' | 'left' | 'right';\n /** Whether a position has been computed since the popup opened. */\n isPositioned: boolean;\n /** Spread onto the surface: `data-side`, `data-align` and the position style. */\n floatingProps: { 'data-side': string; 'data-align': string; style: React.CSSProperties };\n}\n\ntype PhysicalSide = 'top' | 'bottom' | 'left' | 'right';\n\nconst STATIC_SIDE: Record<PhysicalSide, PhysicalSide> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\n/** Half the arrow size, so the arrow sticks out of the surface towards the anchor. */\nconst ARROW_OFFSET = 'calc(var(--wave-popup-arrow-size, 8px) / -2)';\n\nfunction resolveSide(side: PopupSide, dir: Direction): PhysicalSide {\n if (side === 'start') return dir === 'rtl' ? 'right' : 'left';\n if (side === 'end') return dir === 'rtl' ? 'left' : 'right';\n return side;\n}\n\n/** The rectangle of a virtual anchor that is not set (never reached while one is the reference). */\nconst EMPTY_RECT: PopupRect = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n};\n\n/** Whether an anchor is a DOM element (duck typed, so an element of another realm counts). */\nfunction isElementAnchor(anchor: HTMLElement | VirtualElement): anchor is HTMLElement {\n return typeof (anchor as Partial<Node>).nodeType === 'number';\n}\n\n/**\n * The stable stand-in floating-ui gets for virtual anchors: it reads the latest `VirtualElement`\n * from `latest`, so a new virtual object sets no floating-ui state. One proxy per\n * `contextElement`, so `autoUpdate` observes the scroll containers of the current one.\n */\ninterface VirtualProxy extends VirtualElement {\n contextElement: Element | undefined;\n}\n\nfunction createVirtualProxy(\n latest: React.RefObject<VirtualElement | null>,\n contextElement: Element | undefined,\n): VirtualProxy {\n return {\n getBoundingClientRect: () => latest.current?.getBoundingClientRect() ?? EMPTY_RECT,\n contextElement,\n };\n}\n\n/** Keeps the position updated while mounted; observers are used only where they exist. */\nfunction whileElementsMounted(\n reference: ReferenceType,\n floating: HTMLElement,\n update: () => void,\n): () => void {\n return autoUpdate(reference, floating, update, {\n elementResize: typeof ResizeObserver !== 'undefined',\n layoutShift: typeof IntersectionObserver !== 'undefined',\n });\n}\n\n/**\n * Writes the available space and the anchor width as CSS variables on the surface:\n * `--wave-popup-available-width`, `--wave-popup-available-height`, `--wave-popup-reference-width`.\n * It captures no options (floating-ui compares middleware functions by source text).\n */\nconst sizeApply: NonNullable<SizeOptions['apply']> = ({\n availableWidth,\n availableHeight,\n rects,\n elements,\n}) => {\n const style = elements.floating.style;\n style.setProperty('--wave-popup-available-width', `${Math.max(0, Math.floor(availableWidth))}px`);\n style.setProperty(\n '--wave-popup-available-height',\n `${Math.max(0, Math.floor(availableHeight))}px`,\n );\n style.setProperty('--wave-popup-reference-width', `${Math.round(rects.reference.width)}px`);\n};\n\n/**\n * Positions a popup surface next to its anchor with `@floating-ui/react-dom` (Tooltip, Popover,\n * Menu, listboxes, the DatePicker calendar, TeachingPopover): `offset`, `flip`, `shift`, optional\n * `size` (reference width / available space as CSS variables) and `arrow`. `flip`, `shift` and\n * `size` keep the same viewport padding, taken from the `shift` option (8px by default). Logical\n * `start`/`end` sides follow `useDirection()` (the WaveProvider `dir`, else the document\n * direction), and so does start/end alignment.\n *\n * Positions update only while `open` (`autoUpdate` on scroll/resize; element resizes and layout\n * shifts only where `ResizeObserver`/`IntersectionObserver` exist). Spread `floatingProps` onto the\n * surface: `data-side`/`data-align` expose the final placement for styling (C-CLASS).\n *\n * The anchor is an element or a `VirtualElement` (a rectangle such as the pointer position; a new\n * object on every render is fine); give it a `contextElement` so scrolling its containers updates\n * the position. A virtual anchor reaches floating-ui through one stable proxy that reads the latest\n * object: a new object only recomputes the position (which renders only when the position\n * changes), and a new proxy is made only when the `contextElement` changes.\n *\n * Destructure the result: `eslint-plugin-react-hooks` (`react-hooks/refs`) treats an object\n * whose member is passed to a `ref` prop as a ref, and then rejects reading its other members\n * during render.\n *\n * @example\n * const { setReference, setFloating, floatingProps } = usePopupPosition({ open, side: 'bottom' });\n * <button ref={setReference} />\n * {open && <Portal><div ref={setFloating} {...floatingProps} /></Portal>}\n */\nexport function usePopupPosition(options: UsePopupPositionOptions): UsePopupPositionResult {\n const {\n open,\n side = 'bottom',\n align = 'start',\n offset = 4,\n flip = true,\n shift = { padding: 8 },\n matchReferenceWidth = false,\n fitViewport = false,\n arrowRef,\n strategy = 'fixed',\n } = options;\n const dir = useDirection();\n const physicalSide = resolveSide(side, dir);\n const requestedPlacement = (\n align === 'center' ? physicalSide : `${physicalSide}-${align}`\n ) as Placement;\n const padding = shift === false ? 0 : shift === true ? 8 : shift.padding;\n const shiftCrossAxis = typeof shift === 'object' && shift.crossAxis === true;\n\n const middleware: Middleware[] = [offsetMiddleware(offset)];\n if (flip) middleware.push(flipMiddleware({ padding }));\n if (shift !== false) {\n middleware.push(shiftMiddleware({ padding, crossAxis: shiftCrossAxis }));\n }\n if (matchReferenceWidth || fitViewport) {\n middleware.push(sizeMiddleware({ padding, apply: sizeApply }));\n }\n if (arrowRef) middleware.push(arrowMiddleware({ element: arrowRef }));\n\n // Alignment follows the hook's direction (not only the surface's computed CSS direction).\n const directionalPlatform = useMemo<Platform>(\n () => ({ ...platform, isRTL: () => dir === 'rtl' }),\n [dir],\n );\n\n const { refs, floatingStyles, placement, middlewareData, isPositioned, update } = useFloating({\n open,\n placement: requestedPlacement,\n strategy,\n middleware,\n platform: directionalPlatform,\n whileElementsMounted: open ? whileElementsMounted : undefined,\n });\n\n // Virtual anchors: the latest object (written in setReference, never during render) and the\n // proxy floating-ui holds for it.\n const virtualRef = useRef<VirtualElement | null>(null);\n const proxyRef = useRef<VirtualProxy | null>(null);\n const updatePosition = useEventCallback(update);\n const { setReference: setFloatingReference, reference: floatingReference } = refs;\n const setReference = useCallback(\n (anchor: HTMLElement | VirtualElement | null) => {\n if (anchor === null || isElementAnchor(anchor)) {\n virtualRef.current = null;\n setFloatingReference(anchor);\n return;\n }\n virtualRef.current = anchor;\n let proxy = proxyRef.current;\n if (!proxy || proxy.contextElement !== anchor.contextElement) {\n proxy = createVirtualProxy(virtualRef, anchor.contextElement);\n proxyRef.current = proxy;\n }\n if (floatingReference.current === proxy) updatePosition();\n else setFloatingReference(proxy);\n },\n [setFloatingReference, floatingReference, updatePosition],\n );\n\n const [finalSide, finalAlign = 'center'] = placement.split('-') as [PhysicalSide, string?];\n\n const style = useMemo<React.CSSProperties>(() => {\n const next: React.CSSProperties = { ...floatingStyles };\n if (matchReferenceWidth) next.width = 'var(--wave-popup-reference-width)';\n if (fitViewport) {\n next.maxWidth = 'var(--wave-popup-available-width)';\n next.maxHeight = 'var(--wave-popup-available-height)';\n }\n return next;\n }, [floatingStyles, matchReferenceWidth, fitViewport]);\n\n const arrowX = middlewareData.arrow?.x;\n const arrowY = middlewareData.arrow?.y;\n const arrowStyles = useMemo<React.CSSProperties>(() => {\n const styles: Record<string, string> = {\n position: 'absolute',\n left: arrowX != null ? `${arrowX}px` : '',\n top: arrowY != null ? `${arrowY}px` : '',\n };\n styles[STATIC_SIDE[finalSide]] = ARROW_OFFSET;\n return styles as React.CSSProperties;\n }, [arrowX, arrowY, finalSide]);\n\n const floatingProps = useMemo(\n () => ({ 'data-side': finalSide, 'data-align': finalAlign, style }),\n [finalSide, finalAlign, style],\n );\n\n return {\n setReference,\n setFloating: refs.setFloating,\n floatingStyles: style,\n arrowStyles,\n placement,\n side: finalSide,\n isPositioned,\n floatingProps,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";let e=require("react");var t=`(prefers-reduced-motion: reduce)`;function n(){return typeof window>`u`||typeof window.matchMedia!=`function`?null:window.matchMedia(t)}function r(e){let t=n();return t?typeof t.addEventListener==`function`?(t.addEventListener(`change`,e),()=>t.removeEventListener(`change`,e)):(t.addListener(e),()=>t.removeListener(e)):()=>{}}function i(){return n()?.matches??!1}function a(){return!1}function o(){return(0,e.useSyncExternalStore)(r,i,a)}exports.usePrefersReducedMotion=o;
|
|
2
|
+
//# sourceMappingURL=usePrefersReducedMotion.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePrefersReducedMotion.cjs","names":["useSyncExternalStore","react","QUERY","getMediaQueryList","subscribe","mql","notify","getSnapshot","getServerSnapshot","usePrefersReducedMotion"],"sources":["../../src/hooks/usePrefersReducedMotion.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\nconst QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction getMediaQueryList(): MediaQueryList | null {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return null;\n return window.matchMedia(QUERY);\n}\n\nfunction subscribe(notify: () => void): () => void {\n const mql = getMediaQueryList();\n if (!mql) return () => {};\n if (typeof mql.addEventListener === 'function') {\n mql.addEventListener('change', notify);\n return () => mql.removeEventListener('change', notify);\n }\n // Safari < 14\n mql.addListener(notify);\n return () => mql.removeListener(notify);\n}\n\nfunction getSnapshot(): boolean {\n return getMediaQueryList()?.matches ?? false;\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n\n/**\n * `true` while the user asks for reduced motion (`prefers-reduced-motion: reduce`), updated when\n * the preference changes. `false` on the server and where `matchMedia` is unavailable.\n *\n * Use it for behaviour that CSS `motion-reduce:` variants cannot express, e.g. starting a carousel\n * paused.\n */\nexport function usePrefersReducedMotion(): boolean {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n"],"mappings":"oCAEA,IAAME,EAAQ,mCAEd,SAASC,GAA2C,CAElD,OADI,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,WAAmB,KAC9E,OAAO,WAAWD,CAAK,CAChC,CAEA,SAASE,EAAU,EAAgC,CACjD,IAAMC,EAAMF,EAAkB,EAQ9B,OAPKE,EACD,OAAOA,EAAI,kBAAqB,YAClCA,EAAI,iBAAiB,SAAUC,CAAM,MACxBD,EAAI,oBAAoB,SAAUC,CAAM,IAGvDD,EAAI,YAAYC,CAAM,MACTD,EAAI,eAAeC,CAAM,OAPf,CAAC,CAQ1B,CAEA,SAASC,GAAuB,CAC9B,OAAOJ,EAAkB,CAAC,EAAE,SAAW,EACzC,CAEA,SAASK,GAA6B,CACpC,MAAO,EACT,CASA,SAAgBC,GAAmC,CACjD,OAAA,EAAOT,EAAAA,qBAAAA,CAAqBI,EAAWG,EAAaC,CAAiB,CACvE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useSyncExternalStore as e } from "react";
|
|
3
|
+
//#region src/hooks/usePrefersReducedMotion.ts
|
|
4
|
+
var t = "(prefers-reduced-motion: reduce)";
|
|
5
|
+
function n() {
|
|
6
|
+
return typeof window > "u" || typeof window.matchMedia != "function" ? null : window.matchMedia(t);
|
|
7
|
+
}
|
|
8
|
+
function r(e) {
|
|
9
|
+
let t = n();
|
|
10
|
+
return t ? typeof t.addEventListener == "function" ? (t.addEventListener("change", e), () => t.removeEventListener("change", e)) : (t.addListener(e), () => t.removeListener(e)) : () => {};
|
|
11
|
+
}
|
|
12
|
+
function i() {
|
|
13
|
+
return n()?.matches ?? !1;
|
|
14
|
+
}
|
|
15
|
+
function a() {
|
|
16
|
+
return !1;
|
|
17
|
+
}
|
|
18
|
+
function o() {
|
|
19
|
+
return e(r, i, a);
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { o as usePrefersReducedMotion };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=usePrefersReducedMotion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePrefersReducedMotion.mjs","names":["QUERY","getMediaQueryList","subscribe","mql","notify","getSnapshot","getServerSnapshot","usePrefersReducedMotion","useSyncExternalStore"],"sources":["../../src/hooks/usePrefersReducedMotion.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\nconst QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction getMediaQueryList(): MediaQueryList | null {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return null;\n return window.matchMedia(QUERY);\n}\n\nfunction subscribe(notify: () => void): () => void {\n const mql = getMediaQueryList();\n if (!mql) return () => {};\n if (typeof mql.addEventListener === 'function') {\n mql.addEventListener('change', notify);\n return () => mql.removeEventListener('change', notify);\n }\n // Safari < 14\n mql.addListener(notify);\n return () => mql.removeListener(notify);\n}\n\nfunction getSnapshot(): boolean {\n return getMediaQueryList()?.matches ?? false;\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n\n/**\n * `true` while the user asks for reduced motion (`prefers-reduced-motion: reduce`), updated when\n * the preference changes. `false` on the server and where `matchMedia` is unavailable.\n *\n * Use it for behaviour that CSS `motion-reduce:` variants cannot express, e.g. starting a carousel\n * paused.\n */\nexport function usePrefersReducedMotion(): boolean {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n"],"mappings":";;;AAEA,IAAMA,IAAQ;AAEd,SAASC,IAA2C;CAElD,OADI,OAAO,SAAW,OAAe,OAAO,OAAO,cAAe,aAAmB,OAC9E,OAAO,WAAWD,CAAK;AAChC;AAEA,SAASE,EAAU,GAAgC;CACjD,IAAMC,IAAMF,EAAkB;CAQ9B,OAPKE,IACD,OAAOA,EAAI,oBAAqB,cAClCA,EAAI,iBAAiB,UAAUC,CAAM,SACxBD,EAAI,oBAAoB,UAAUC,CAAM,MAGvDD,EAAI,YAAYC,CAAM,SACTD,EAAI,eAAeC,CAAM,WAPf,CAAC;AAQ1B;AAEA,SAASC,IAAuB;CAC9B,OAAOJ,EAAkB,CAAC,EAAE,WAAW;AACzC;AAEA,SAASK,IAA6B;CACpC,OAAO;AACT;AASA,SAAgBC,IAAmC;CACjD,OAAOC,EAAqBN,GAAWG,GAAaC,CAAiB;AACvE"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("./useEventCallback.cjs"),t=require("./useIsClient.cjs"),n=require("./usePrefersReducedMotion.cjs");let r=require("react");var i=50;function a(e){return e.split(`,`).map(e=>{let t=e.trim(),n=parseFloat(t);return Number.isNaN(n)?0:t.endsWith(`ms`)?n:t.endsWith(`s`)?n*1e3:0})}function o(e){return e.split(`,`).map(e=>e.trim()).filter(e=>e!==``)}function s(e,t,n){return e.length===0?n:e[t%e.length]}function c(e){if(e.playState!==`running`)return!1;let t=e.effect?.getComputedTiming().endTime;return t===void 0||Number.isFinite(Number(t))}function l(e){let t=e.ownerDocument.defaultView?.getComputedStyle(e),n=new Set,r=new Set,i=0;if(!t)return{time:i,animations:n,transitions:r};let c=o(t.animationName),l=a(t.animationDuration),u=a(t.animationDelay),d=o(t.animationIterationCount);c.forEach((e,t)=>{if(e===`none`)return;let r=Number(s(d,t,`1`));if(!Number.isFinite(r))return;let a=s(u,t,0)+s(l,t,0)*r;a<=0||(n.add(e),i=Math.max(i,a))});let f=o(t.transitionProperty),p=a(t.transitionDuration),m=a(t.transitionDelay);return f.forEach((e,t)=>{let n=s(p,t,0);if(e===`none`||n<=0)return;let a=s(m,t,0)+n;a<=0||(r.add(e),i=Math.max(i,a))}),{time:i,animations:n,transitions:r}}var u=[`animationend`,`animationcancel`,`transitionend`,`transitioncancel`];function d(e,t){if(typeof e.getAnimations==`function`){let n=e.getAnimations().filter(c);if(n.length===0)return null;let r=!0;return Promise.allSettled(n.map(e=>e.finished)).then(()=>{r&&t()}),()=>{r=!1}}let{time:n,animations:r,transitions:a}=l(e);if(n<=0)return null;let o=()=>{f(),t()},s=t=>{if(t.target===e){if(t.type.startsWith(`animation`))r.delete(t.animationName);else{let e=t.propertyName;a.delete(e)||a.delete(`all`)}r.size===0&&a.size===0&&o()}},d=setTimeout(o,n+i);for(let t of u)e.addEventListener(t,s);function f(){clearTimeout(d);for(let t of u)e.removeEventListener(t,s)}return f}function f(i,a={}){let{appear:o=!1,unmountOnExit:s=!0,onEntered:c,onExited:l}=a,u=t.useIsClient(),f=n.usePrefersReducedMotion(),[p,m]=(0,r.useState)(()=>i?u&&o?`entering`:`entered`:`exited`),[h,g]=(0,r.useState)(i);i!==h&&(g(i),i?m(`entering`):p!==`exited`&&m(`exiting`));let[_,v]=(0,r.useState)(null),y=(0,r.useRef)(null),b=(0,r.useCallback)(e=>{y.current=e,v(e)},[]);(0,r.useLayoutEffect)(()=>{if(p!==`entering`&&p!==`exiting`)return;let e=p===`entering`?`entered`:`exited`,t=y.current,n=!0,r=t&&!f?d(t,()=>{n&&m(t=>t===p?e:t)}):null;if(!r){m(e);return}return()=>{n=!1,r()}},[p,_,f]);let x=e.useEventCallback(c),S=e.useEventCallback(l),C=(0,r.useRef)(null);(0,r.useLayoutEffect)(()=>{let e=C.current;C.current=p,e===`entering`&&p===`entered`?x():e===`exiting`&&p===`exited`&&S()},[p,x,S]);let w=p===`exited`&&!s,T=(0,r.useMemo)(()=>{let e={"data-presence":p};return(p===`exiting`||w)&&(e.inert=!0),w&&(e.hidden=!0),e},[p,w]);return{isMounted:p!==`exited`||!s,phase:p,ref:b,presenceProps:T}}exports.usePresence=f;
|
|
2
|
+
//# sourceMappingURL=usePresence.cjs.map
|