@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":"Popover.mjs","names":["useId","useId$1","React","PopoverContext","inertContext","getInertContext","usePopoverContext","reportMissingContext","componentName","presentIds","present","ids","id","doc","findTriggerLabelId","trigger","resolvedId","named","getTriggerFocusTarget","referencesText","el","subscribeNothing","isFocusInsideContentTree","active","surface","getLayerTreeElements","layerId","isElementTarget","target","createResolvedRef","resolve","getPopoverPreviousStop","anchor","getTabbableThrough","order","PopoverRoot","openProp","openState","setOpen","useControllable","defaultOpen","onOpenChange","hoverCloseRef","requestOpen","useEventCallback","next","isHoverClose","isClient","useIsClient","open","openReason","setOpenReason","hoverRequested","setHoverRequested","previousOpen","setPreviousOpen","reason","generatedContentId","customContentId","setCustomContentId","contentId","triggerId","resolvedTriggerId","setResolvedTriggerId","setSurface","triggerElement","setTriggerElement","triggerRef","surfaceRef","arrowRef","targetElement","targetRef","placedSide","usePopupPosition","contextOpenerRef","resolveFocusTarget","gestureOpener","openOnContext","isConnectedAndFocusable","triggerTarget","targetEl","focusTargetRef","isOutsidePress","event","useDismiss","ignoreOutsideRefs","focusContentRef","contextAnchor","contextOrigin","contextOpener","contextTriggerHandlers","contextSurfaceHandlers","useContextMenuAnchor","origin","triggerFocusRef","useTriggerFocusRef","useRestoreFocus","triggerElementRef","useMergedRefs","surfaceElementRef","setFloating","setReference","fromContext","focusElement","getFirstTabbable","openOnHover","warnOnce","hoverEnabled","canHoverClose","hoverTriggerHandlers","hoverSurfaceHandlers","cancelHover","useHoverIntent","onTriggerClick","current","resolveTabAnchor","tabAnchorRef","onTriggerKeyDown","surfaceElement","first","onContentKeyDown","usePopoverTabOrder","keyboardContext","context","floatingProps","arrowStyles","PopoverTrigger","idProp","rest","hover","gesture","elementRef","ref","triggerProps","contextMode","composeEventHandlers","onClick","onKeyDown","onContextMenu","onPointerEnter","onPointerMove","onPointerLeave","useTriggerElement","children","PopoverContent","ariaLabel","ariaLabelledBy","titleId","hasTitle","slotRendersContent","title","unnamed","checkTrigger","subscribeTrigger","observer","onChange","triggerLabelId","labelledBy","customId","isDev","labelIds","Portal","style","onContentContextMenu","cn","className","PopoverBeak","Popover"],"sources":["../../../src/components/overlays/Popover.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { isDev, reportMissingContext, warnOnce } from '../../lib/dev';\nimport { slotRendersContent } from '../../lib/slot';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { focusElement, getFirstTabbable, isConnectedAndFocusable } from '../../lib/focus';\nimport { getLayerTreeElements } from '../../lib/layers';\nimport type { PopupAlign, PopupSide, PopupTarget } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useControllable, type SetValue } from '../../hooks/useControllable';\nimport { useContextMenuAnchor, type ContextMenuAnchor } from '../../hooks/useContextMenuAnchor';\nimport { useDismiss } from '../../hooks/useDismiss';\nimport { useHoverIntent, type HoverIntent } from '../../hooks/useHoverIntent';\nimport { useRestoreFocus } from '../../hooks/useRestoreFocus';\nimport { usePopupPosition } from '../../hooks/usePopupPosition';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport {\n getTriggerFocusTarget,\n useTriggerElement,\n useTriggerFocusRef,\n} from '../../hooks/useTriggerElement';\nimport { Portal } from '../portal/Portal';\nimport {\n getTabbableThrough,\n PopoverBeak,\n usePopoverTabOrder,\n type PopoverPhysicalSide,\n} from './Popover.shared';\n\n/** Properties for the Popover component. */\nexport interface PopoverProps {\n /**\n * Controlled open state of the popover. The content renders only in the browser: an open\n * popover is closed in the server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Default open state for uncontrolled usage. The content renders only in the browser: a\n * popover open by default is closed in the server HTML and opens once it has hydrated.\n * @default false\n */\n defaultOpen?: boolean;\n /**\n * Called with the requested open state when it differs from the current one: a trigger click,\n * Escape and an outside press; the hover opening and closing of `openOnHover`; and, with\n * `openOnContext`, a context gesture (a right click, a macOS Ctrl+click, Shift+F10 or the\n * ContextMenu key), a right click outside, and a scroll that moves the row it opened at.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * Side of the trigger the content opens on. `start`/`end` follow the writing direction. The\n * content flips to the opposite side when there is not enough room.\n * @default 'bottom'\n */\n side?: PopupSide;\n /** Alignment of the content along the trigger's edge.\n * @default 'start'\n */\n align?: PopupAlign;\n /**\n * Elements outside the popover whose presses must not dismiss it, e.g. an external toggle\n * button that opens and closes the popover itself.\n */\n ignoreOutsideRefs?: ReadonlyArray<React.RefObject<HTMLElement | null>>;\n /**\n * Open the popover when a mouse pointer rests on its trigger (a hover card), and close it once\n * the pointer has been off the trigger and the content for `closeDelay` while focus is not\n * inside the content. A popover opened by hover does not take focus, and its hover close leaves\n * focus where it is; a click on its trigger keeps it open and keeps focus where it is (a second\n * click closes it, as without hover). After Escape or an outside press it does not reopen until\n * the pointer has left the trigger. Touch and pen never open it by hover, and an `aria-disabled`\n * trigger never opens. A triangle between the trigger and the content keeps it open while the\n * pointer moves diagonally into it. Ignored with `openOnContext` (development warning).\n * @default false\n */\n openOnHover?: boolean;\n /**\n * Milliseconds a hovering mouse pointer rests on the trigger before the popover opens (mouse\n * hover only).\n * @default 250\n */\n openDelay?: number;\n /**\n * Milliseconds before a hover-opened popover closes once the mouse pointer has left it and its\n * trigger (Fluent's `mouseLeaveDelay`; mouse hover only).\n * @default 500\n */\n closeDelay?: number;\n /**\n * Make `Popover.Trigger` a context-menu region (a list, a row, a canvas): a right click (a\n * Ctrl+click on macOS, a long press where the browser reports one) opens the popover at the\n * pointer and leaves focus where it is (Tab from that element enters the content), and\n * Shift+F10 or the ContextMenu key opens it at the focused element inside the region and moves\n * focus into the content, instead of a click. Focus returns to the element that had it. The\n * browser's context menu is suppressed there and inside the content, except in text fields\n * inside the region, which keep it. A press elsewhere, a right click outside or a scroll that\n * moves the row it opened at (the one under the pointer, or the focused one), as a scroll of\n * the region's own content does, closes it. The trigger gets no `aria-haspopup`/`aria-expanded`\n * (it is not a popover button; with a render-prop child, do not spread them): name the content\n * with `title`, `aria-label` or `aria-labelledby`, and consider `aria-keyshortcuts=\"Shift+F10\"`\n * on the region. iOS Safari reports no long press. `openOnHover` is ignored with it.\n * @default false\n */\n openOnContext?: boolean;\n /**\n * Where to place the content instead of next to `Popover.Trigger`: an element or a\n * `VirtualElement` (a rectangle, such as a point; an inline object is fine). With a controlled\n * `open`, a popover with a `target` needs no trigger; name it with `title`, `aria-label` or\n * `aria-labelledby`, and give a toggle button you use as the target `aria-haspopup=\"dialog\"`,\n * `aria-expanded` and `aria-controls` yourself. A press on a target element does not close the\n * popover, and Tab from it enters the content when there is no trigger. Hold the element in\n * state (a ref cannot be observed; TeachingPopover's `target` also takes a ref). A popover\n * opened by `openOnContext` is placed at the gesture instead.\n */\n target?: PopupTarget;\n /** `Popover.Trigger` and `Popover.Content`. */\n children: React.ReactNode;\n}\n\n/**\n * Props the trigger puts on its element; a render-prop child of `Popover.Trigger` receives them\n * (spread them onto the element that opens the popover). With `openOnContext` the element is a\n * context-menu region, not a popover button: do not spread `aria-haspopup`, `aria-expanded` and\n * `aria-controls` onto it (`aria-expanded` is then always `false`, `aria-controls` is absent and\n * `onClick` does nothing); spread ones are removed after each commit, with a development warning.\n */\nexport type PopoverTriggerChildProps = Omit<React.HTMLAttributes<HTMLElement>, 'children'> & {\n id: string;\n 'aria-haspopup': 'dialog';\n 'aria-expanded': boolean;\n /** The content's id, only while the popover is open (never with `openOnContext`). */\n 'aria-controls': string | undefined;\n onClick: React.MouseEventHandler<HTMLElement>;\n /**\n * Moves Tab from the open trigger into the portaled content (which lives at the end of the\n * document), so the keyboard order follows the trigger.\n */\n onKeyDown: React.KeyboardEventHandler<HTMLElement>;\n ref: React.RefCallback<HTMLElement>;\n};\n\n/** Properties for the PopoverTrigger sub-component. */\nexport interface PopoverTriggerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that toggles the popover (its props are merged onto it), or a render function\n * that receives the trigger props.\n */\n children: React.ReactNode | ((props: PopoverTriggerChildProps) => React.ReactNode);\n /**\n * `false` renders the 0.4 wrapper `<span>` carrying the trigger props around the children\n * instead of merging them onto the child. `aria-haspopup`, `aria-expanded` and `aria-controls`,\n * which a generic element cannot carry, go to the first element in the tab order inside the\n * span. A render-prop child ignores `asChild` and receives every prop.\n * @default true\n */\n asChild?: boolean;\n /** Ref to the trigger element (the child, or the wrapper span). */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** Properties for the PopoverContent sub-component. */\nexport interface PopoverContentProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Content to render inside the popover. */\n children: React.ReactNode;\n /**\n * Visible heading rendered at the top of the popover; it names the dialog. Without `title`,\n * `aria-label` or `aria-labelledby`, the popover is labelled by its trigger, except with\n * `openOnContext` (a region's text is no name), where it needs one of them.\n */\n title?: React.ReactNode;\n /** Id of the surface; the trigger's `aria-controls` follows it. Defaults to a generated id. */\n id?: string;\n /** Ref to the popover surface. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\ninterface PopoverContextValue {\n open: boolean;\n setOpen: SetValue<boolean>;\n /** The content's id: the consumer's `Popover.Content` id when given, else a generated one. */\n contentId: string;\n /** `Popover.Content` reports the consumer's `id` so the trigger's `aria-controls` follows it. */\n setCustomContentId: (id: string | undefined) => void;\n triggerId: string;\n /** The id the trigger element ended up with (the child's own id wins). */\n resolvedTriggerId: string | undefined;\n setResolvedTriggerId: (id: string) => void;\n triggerRef: React.RefObject<HTMLElement | null>;\n /** The trigger element as state (read during render, e.g. to check the labelling id). */\n triggerElement: HTMLElement | null;\n /** Ref callback for the trigger element: focus-restore target and positioning anchor. */\n triggerElementRef: React.RefCallback<HTMLElement>;\n /** Ref callback for the surface: dismissal, focus restore and positioning. */\n surfaceElementRef: React.RefCallback<HTMLElement>;\n arrowRef: React.RefObject<HTMLDivElement | null>;\n /** The trigger's click: toggles the popover, or pins one that hover opened (keeps it open). */\n onTriggerClick: () => void;\n /** Tab from the open trigger enters the portaled content. */\n onTriggerKeyDown: React.KeyboardEventHandler<HTMLElement>;\n /** Hover opening (`openOnHover`): composed onto the trigger; `null` without it. */\n hoverTriggerHandlers: HoverIntent['triggerHandlers'] | null;\n /** Hover opening (`openOnHover`): composed onto the content; `null` without it. */\n hoverSurfaceHandlers: HoverIntent['surfaceHandlers'] | null;\n /** `openOnContext`: the trigger is a context-menu region, not a popover button. */\n contextMode: boolean;\n /** Context gestures (`openOnContext`): composed onto the trigger; `null` without it. */\n contextTriggerHandlers: ContextMenuAnchor['triggerHandlers'] | null;\n /** Composed onto the content: suppresses the browser's context menu there in context mode. */\n onContentContextMenu: React.MouseEventHandler<HTMLElement>;\n /** Opened by a keyboard context gesture: the content takes focus (itself when nothing can). */\n keyboardContext: boolean;\n /** Tab past the content's edges continues around the trigger in the page order. */\n onContentKeyDown: React.KeyboardEventHandler<HTMLElement>;\n layerId: string;\n floatingProps: { 'data-side': string; 'data-align': string; style: React.CSSProperties };\n arrowStyles: React.CSSProperties;\n placedSide: PopoverPhysicalSide;\n}\n\nconst PopoverContext = React.createContext<PopoverContextValue | null>(null);\nPopoverContext.displayName = 'PopoverContext';\n\nlet inertContext: PopoverContextValue | null = null;\n\n/** Production fallback for a misplaced sub-component: a closed popover that does nothing. */\nfunction getInertContext(): PopoverContextValue {\n inertContext ??= {\n open: false,\n setOpen: () => {},\n contentId: 'wave-popover-inert-content',\n setCustomContentId: () => {},\n triggerId: 'wave-popover-inert-trigger',\n resolvedTriggerId: undefined,\n setResolvedTriggerId: () => {},\n triggerRef: { current: null },\n triggerElement: null,\n triggerElementRef: () => {},\n surfaceElementRef: () => {},\n arrowRef: { current: null },\n onTriggerClick: () => {},\n onTriggerKeyDown: () => {},\n hoverTriggerHandlers: null,\n hoverSurfaceHandlers: null,\n contextMode: false,\n contextTriggerHandlers: null,\n onContentContextMenu: () => {},\n keyboardContext: false,\n onContentKeyDown: () => {},\n layerId: 'wave-popover-inert-layer',\n floatingProps: { 'data-side': 'bottom', 'data-align': 'start', style: {} },\n arrowStyles: {},\n placedSide: 'bottom',\n };\n return inertContext;\n}\n\nfunction usePopoverContext(componentName: string): PopoverContextValue {\n const context = React.useContext(PopoverContext);\n if (context) return context;\n reportMissingContext(componentName, 'Popover');\n return getInertContext();\n}\n\n/** The ids of an id list that exist in `doc`, joined; `undefined` when none does. */\nfunction presentIds(doc: Document, ids: string | null): string | undefined {\n const present = (ids ?? '').split(/\\s+/).filter((id) => id && doc.getElementById(id));\n return present.length > 0 ? present.join(' ') : undefined;\n}\n\n/**\n * The ids `Popover.Content`'s default `aria-labelledby` points at, so the popover gets its\n * trigger's name. The named element is the one with the resolved id when the document has it,\n * otherwise the trigger's focus target (for example the Button inside a Tooltip that sits between\n * `Popover.Trigger` and the Button, whose own id wins), else the trigger element. When that\n * element is itself named through `aria-labelledby` (an icon-only Button inside\n * `Tooltip relationship=\"label\"`, or a button labelled by a visible label), its label ids are\n * returned: a name computation does not follow a second `aria-labelledby` hop, so pointing at the\n * button would leave the popover unnamed. Otherwise the element's id, else the trigger's own.\n * `undefined` when none of them has an id (a render-prop child that does not spread `id`), so the\n * reference never dangles; only ids present in the document are returned. Before the trigger\n * element is known, the resolved id.\n */\nfunction findTriggerLabelId(\n trigger: HTMLElement | null,\n resolvedId: string | undefined,\n): string | undefined {\n if (!trigger) return resolvedId;\n const doc = trigger.ownerDocument;\n const named =\n (resolvedId ? doc.getElementById(resolvedId) : null) ??\n getTriggerFocusTarget(trigger) ??\n trigger;\n return (\n presentIds(doc, named.getAttribute('aria-labelledby')) ?? (named.id || trigger.id || undefined)\n );\n}\n\n/**\n * Whether one of the elements an id list references has text for a name: its own `aria-label`\n * or text, or a descendant's `aria-label`, `alt` or `title`. Deliberately lenient (it only drives\n * a development warning): content that assistive technology ignores still counts as text.\n */\nfunction referencesText(doc: Document, ids: string): boolean {\n return ids.split(/\\s+/).some((id) => {\n const el = id ? doc.getElementById(id) : null;\n if (!el) return false;\n if (el.getAttribute('aria-label')?.trim() || el.textContent?.trim()) return true;\n return !!el.querySelector(\n '[aria-label]:not([aria-label=\"\"]), [alt]:not([alt=\"\"]), [title]:not([title=\"\"])',\n );\n });\n}\n\nconst subscribeNothing = (): (() => void) => () => {};\n\n/**\n * Whether focus is inside the content or in a layer opened from it (a menu of the content, whose\n * portal lives elsewhere): what keeps a hover-opened popover open. Focus on the trigger does not\n * count, although the trigger belongs to the dismiss layer.\n */\nfunction isFocusInsideContentTree(surface: HTMLElement | null, layerId: string): boolean {\n const active = surface?.ownerDocument.activeElement;\n if (!surface || !active) return false;\n if (surface.contains(active)) return true;\n return getLayerTreeElements(layerId, { includeOwnElements: false }).some((el) =>\n el.contains(active),\n );\n}\n\n/** Why an open popover opened: hover (it closes by hover), or anything else (it is pinned). */\ntype OpenReason = 'hover' | 'other';\n\n/** Whether a `target` is an element rather than a VirtualElement (duck typed, any realm). */\nfunction isElementTarget(target: PopupTarget | undefined): target is HTMLElement {\n return !!target && typeof (target as Partial<Node>).nodeType === 'number';\n}\n\n/** A read-only ref whose `current` is `resolve()` at the time it is read (event time). */\nfunction createResolvedRef(resolve: () => HTMLElement | null): React.RefObject<HTMLElement | null> {\n return {\n get current() {\n return resolve();\n },\n };\n}\n\n/**\n * The content's previous stop: the focus target of the element it follows (the trigger, the row of\n * a context gesture, a `target` element), else the tab stop before that element.\n */\nfunction getPopoverPreviousStop(\n anchor: HTMLElement,\n surface: HTMLElement,\n order?: readonly HTMLElement[],\n): HTMLElement | null {\n return getTriggerFocusTarget(anchor) ?? getTabbableThrough(anchor, surface, order);\n}\n\n// A const arrow (like DialogRoot and DrawerRoot): its type can be named in consumers' declaration\n// files, e.g. a story's `satisfies Meta<typeof Popover>` (a function declaration's `typeof` cannot,\n// TS4023).\nconst PopoverRoot = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n side = 'bottom',\n align = 'start',\n ignoreOutsideRefs,\n openOnHover = false,\n openDelay = 250,\n closeDelay = 500,\n openOnContext = false,\n target,\n children,\n}: PopoverProps) => {\n const [openState, setOpen] = useControllable(openProp, defaultOpen ?? false, onOpenChange);\n // A hover close in flight (written in handlers, read when the popover closes): set when the hover\n // intent asks to close, so that close moves no focus even when a controlled parent applies it in\n // a later render (a transition). Every other request to open or close forgets it, and so does\n // the next opening.\n const hoverCloseRef = React.useRef(false);\n const requestOpen = useEventCallback<SetValue<boolean>>((next) => {\n hoverCloseRef.current = false;\n setOpen(next);\n });\n const isHoverClose = React.useCallback(() => hoverCloseRef.current, []);\n // The content lives in a portal, which renders only in the browser: until then (the server\n // HTML, hydration) the popover reports itself closed, so the trigger's aria-expanded and\n // aria-controls never describe content that is not there.\n const isClient = useIsClient();\n const open = openState && isClient;\n\n // Why the popover opened, decided when it opens (C-HOOKS: a previous-value state): `hover` when\n // hover asked for that open (a request consumed by the next render, so an open that a\n // controlled parent refused does not linger), else `other` (click, keys, a context gesture, a\n // controlled open).\n const [openReason, setOpenReason] = React.useState<OpenReason>('other');\n const [hoverRequested, setHoverRequested] = React.useState(false);\n const [previousOpen, setPreviousOpen] = React.useState(open);\n let reason = openReason;\n if (open !== previousOpen) {\n setPreviousOpen(open);\n if (open) reason = hoverRequested ? 'hover' : 'other';\n }\n if (reason !== openReason) setOpenReason(reason);\n if (hoverRequested) setHoverRequested(false);\n\n const generatedContentId = useId('popover-content');\n const [customContentId, setCustomContentId] = React.useState<string | undefined>(undefined);\n const contentId = customContentId ?? generatedContentId;\n const triggerId = useId('popover-trigger');\n const [resolvedTriggerId, setResolvedTriggerId] = React.useState<string | undefined>(undefined);\n const [surface, setSurface] = React.useState<HTMLElement | null>(null);\n const [triggerElement, setTriggerElement] = React.useState<HTMLElement | null>(null);\n const triggerRef = React.useRef<HTMLElement | null>(null);\n const surfaceRef = React.useRef<HTMLElement | null>(null);\n const arrowRef = React.useRef<HTMLDivElement | null>(null);\n // A `target` element (not a VirtualElement) belongs to the dismiss layer, anchors the keyboard\n // order without a trigger and can take focus back.\n const targetElement = isElementTarget(target) ? target : null;\n const targetRef = React.useRef<HTMLElement | null>(null);\n React.useInsertionEffect(() => {\n targetRef.current = targetElement;\n }, [targetElement]);\n\n // Destructured: react-hooks/refs treats an object whose member is passed to `ref` as a ref.\n const {\n setReference,\n setFloating,\n floatingProps,\n arrowStyles,\n side: placedSide,\n } = usePopupPosition({ open, side, align, offset: 8, arrowRef });\n\n // The one focus resolver: the focus-return fallback and the layer's anchor (where a surface\n // opened from the content restores focus once its opener is gone). In context mode the element\n // focused at the gesture (the row) first; then the trigger's focus target (for a wrapper span,\n // the element inside it that carries the state ARIA), a focusable `target` element, and the\n // trigger itself. The context hook's opener ref is stable; it is filled in once the hook runs.\n const contextOpenerRef = React.useRef<React.RefObject<HTMLElement | null> | null>(null);\n const resolveFocusTarget = useEventCallback((): HTMLElement | null => {\n const gestureOpener = openOnContext ? contextOpenerRef.current?.current : null;\n if (gestureOpener && isConnectedAndFocusable(gestureOpener)) return gestureOpener;\n const trigger = triggerRef.current;\n const triggerTarget = trigger ? getTriggerFocusTarget(trigger) : null;\n if (triggerTarget) return triggerTarget;\n const targetEl = targetRef.current;\n if (targetEl && isConnectedAndFocusable(targetEl)) return targetEl;\n return trigger;\n });\n const focusTargetRef = React.useMemo(\n () => createResolvedRef(resolveFocusTarget),\n [resolveFocusTarget],\n );\n\n // In context mode the region is no part of the layer: a primary press elsewhere in it closes the\n // popover like any outside press. A Ctrl+press inside it is a macOS context click, whose\n // `contextmenu` moves the popover instead.\n const isOutsidePress = useEventCallback(\n (event: PointerEvent | MouseEvent) =>\n !(event.ctrlKey && triggerRef.current?.contains(event.target as Node)),\n );\n const { layerId } = useDismiss({\n open,\n onDismiss: () => requestOpen(false),\n refs: openOnContext\n ? [surfaceRef, targetRef, ...(ignoreOutsideRefs ?? [])]\n : [surfaceRef, triggerRef, targetRef, ...(ignoreOutsideRefs ?? [])],\n anchorRef: focusTargetRef,\n kind: 'popover',\n outsidePress: openOnContext ? isOutsidePress : true,\n });\n\n // A keyboard context gesture moves focus into the content, once it is there (see below).\n const focusContentRef = React.useRef(false);\n const {\n anchor: contextAnchor,\n fromContext,\n origin: contextOrigin,\n opener: contextOpener,\n triggerHandlers: contextTriggerHandlers,\n surfaceHandlers: contextSurfaceHandlers,\n } = useContextMenuAnchor({\n enabled: openOnContext,\n open,\n trigger: triggerElement,\n layerId,\n onOpen: (origin) => {\n focusContentRef.current = origin === 'keyboard';\n requestOpen(true);\n },\n onClose: () => requestOpen(false),\n });\n React.useInsertionEffect(() => {\n contextOpenerRef.current = contextOpener;\n }, [contextOpener]);\n\n // Focus returns to the element that takes focus for the trigger, as Shift+Tab from the content\n // does, when the popover closes while focus is inside it or on `<body>`; a hover close restores\n // only focus inside, so it never moves focus. In context mode it returns to the element focused\n // at the gesture (the row): the region is no restore target of its own (as `triggerRef` it\n // would be taken for the opener).\n const triggerFocusRef = useTriggerFocusRef(triggerRef);\n useRestoreFocus({\n enabled: open,\n container: surface,\n triggerRef: openOnContext ? undefined : triggerFocusRef,\n finalFocusRef: openOnContext ? contextOpener : undefined,\n fallback: resolveFocusTarget,\n onlyIfFocusInside: true,\n isHoverClose,\n });\n React.useLayoutEffect(() => {\n if (open) hoverCloseRef.current = false;\n }, [open]);\n\n const triggerElementRef = useMergedRefs<HTMLElement>(triggerRef, setTriggerElement);\n const surfaceElementRef = useMergedRefs<HTMLElement>(surfaceRef, setSurface, setFloating);\n\n // The positioning anchor: the context gesture (the pointer, or the focused row, else the\n // trigger's focus target, else the trigger) while the popover was opened by one, else `target`,\n // else the trigger. A new VirtualElement on every render repositions without a render loop.\n React.useLayoutEffect(() => {\n if (fromContext) {\n setReference(\n contextAnchor ??\n (triggerElement && (getTriggerFocusTarget(triggerElement) ?? triggerElement)),\n );\n } else {\n setReference(target ?? triggerElement);\n }\n }, [contextAnchor, fromContext, target, triggerElement, setReference]);\n\n // After the commit that has the surface (and after a gesture while open): focus its first\n // tabbable element, else the surface itself (it then has `tabIndex={-1}`). A gesture whose open\n // was refused leaves nothing pending. No deps: every commit, since a gesture always renders.\n React.useLayoutEffect(() => {\n if (!focusContentRef.current) return;\n if (!open) {\n focusContentRef.current = false;\n return;\n }\n if (!surface) return;\n focusContentRef.current = false;\n focusElement(getFirstTabbable(surface) ?? surface, { preventScroll: true });\n });\n\n React.useEffect(() => {\n if (!openOnHover || !openOnContext) return;\n warnOnce(\n 'Popover:hover-and-context',\n 'Popover: `openOnHover` is ignored with `openOnContext`: a context popover opens on a right click, Shift+F10 or the ContextMenu key, not on hover.',\n );\n }, [openOnHover, openOnContext]);\n\n // Hover opening: a popover that hover opened closes by hover until a click on the trigger pins\n // it; focus inside the content (or a layer opened from it) keeps it open, focus on the trigger\n // does not.\n const hoverEnabled = openOnHover && !openOnContext;\n const canHoverClose = useEventCallback(\n () => reason === 'hover' && !isFocusInsideContentTree(surfaceRef.current, layerId),\n );\n const {\n triggerHandlers: hoverTriggerHandlers,\n surfaceHandlers: hoverSurfaceHandlers,\n cancel: cancelHover,\n } = useHoverIntent({\n enabled: hoverEnabled,\n open,\n openDelay,\n closeDelay,\n trigger: triggerElement,\n surface,\n onOpen: () => {\n setHoverRequested(true);\n requestOpen(true);\n },\n onClose: () => {\n // Before the request: a parent may apply it synchronously (flushSync).\n hoverCloseRef.current = true;\n setOpen(false);\n },\n canClose: canHoverClose,\n });\n\n const onTriggerClick = useEventCallback(() => {\n cancelHover();\n if (open && reason === 'hover') setOpenReason('other');\n else requestOpen((current) => !current);\n });\n\n // The element the content follows in the keyboard order: in context mode the element focused\n // at the gesture when it lies inside the region, else the trigger, else a `target` element.\n // With neither (a VirtualElement target and no trigger) the content keeps the portal's place.\n const resolveTabAnchor = useEventCallback((): HTMLElement | null => {\n const trigger = triggerRef.current;\n const gestureOpener = openOnContext ? contextOpener.current : null;\n if (gestureOpener && trigger?.contains(gestureOpener)) return gestureOpener;\n return trigger ?? targetRef.current;\n });\n const tabAnchorRef = React.useMemo(() => createResolvedRef(resolveTabAnchor), [resolveTabAnchor]);\n\n // Keyboard order of the portaled content (it lives at the end of the document), as if it\n // followed the trigger like 0.4's inline content: Tab from the open trigger enters it (here, in\n // the trigger's own `onKeyDown`, which runs before a dialog's focus trap), Tab past its last\n // element continues after the trigger, Shift+Tab from its first element returns to the trigger\n // (the element inside a wrapper span), and Shift+Tab from the element after the trigger enters\n // it at its last element. The end of the page does not visit it a second time where its portal\n // is, and no Tab cycle forms (see usePopoverTabOrder). In a context region only Tab from the\n // element the content follows enters it; Tab on the region's other rows moves on as usual.\n const onTriggerKeyDown = useEventCallback((event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key !== 'Tab' || event.shiftKey || !open) return;\n if (openOnContext) {\n const anchor = resolveTabAnchor();\n if (!anchor || event.target !== (getTriggerFocusTarget(anchor) ?? anchor)) return;\n }\n const surfaceElement = surfaceRef.current;\n const first = surfaceElement ? getFirstTabbable(surfaceElement) : null;\n if (!first) return;\n event.preventDefault();\n first.focus();\n });\n\n const onContentKeyDown = usePopoverTabOrder({\n enabled: open,\n surface,\n anchorRef: tabAnchorRef,\n // Shift+Tab from the content's first element returns to the trigger (the element in a span),\n // or, when nothing in the trigger can take focus, to the tab stop before it.\n getPreviousStop: getPopoverPreviousStop,\n });\n\n const keyboardContext = fromContext && contextOrigin === 'keyboard';\n const context = React.useMemo<PopoverContextValue>(\n () => ({\n open,\n setOpen: requestOpen,\n contentId,\n setCustomContentId,\n triggerId,\n resolvedTriggerId,\n setResolvedTriggerId,\n triggerRef,\n triggerElement,\n triggerElementRef,\n surfaceElementRef,\n arrowRef,\n onTriggerClick,\n onTriggerKeyDown,\n hoverTriggerHandlers: hoverEnabled ? hoverTriggerHandlers : null,\n hoverSurfaceHandlers: hoverEnabled ? hoverSurfaceHandlers : null,\n contextMode: openOnContext,\n contextTriggerHandlers: openOnContext ? contextTriggerHandlers : null,\n onContentContextMenu: contextSurfaceHandlers.onContextMenu,\n keyboardContext,\n onContentKeyDown,\n layerId,\n floatingProps,\n arrowStyles,\n placedSide,\n }),\n [\n open,\n requestOpen,\n contentId,\n triggerId,\n resolvedTriggerId,\n triggerElement,\n triggerElementRef,\n surfaceElementRef,\n onTriggerClick,\n onTriggerKeyDown,\n hoverEnabled,\n hoverTriggerHandlers,\n hoverSurfaceHandlers,\n openOnContext,\n contextTriggerHandlers,\n contextSurfaceHandlers,\n keyboardContext,\n onContentKeyDown,\n layerId,\n floatingProps,\n arrowStyles,\n placedSide,\n ],\n );\n\n return <PopoverContext.Provider value={context}>{children}</PopoverContext.Provider>;\n};\n\nPopoverRoot.displayName = 'Popover';\n\n/**\n * The element that toggles the popover. Its props are merged onto the single child (no wrapper\n * element): `aria-haspopup=\"dialog\"`, `aria-expanded`, `aria-controls` (while open), an `id` that\n * labels the content, a composed `onClick` and the ref used as positioning anchor and focus-return\n * target. The child's own `id`, handlers and classes are kept; the live state ARIA always wins.\n * A render function receives the props instead (spread all of them, `id` included: the content is\n * named by it); `asChild={false}` renders the 0.4 wrapper span, and a custom child that neither\n * forwards `ref` nor spreads its props falls back to that span automatically (with a development\n * warning). On the span, the state ARIA goes to the first element in the tab order inside it, and\n * focus returns to that element (to the span when you made it the trigger with a `role` such as\n * `button` and `tabIndex={0}`, or when nothing inside it can take focus).\n *\n * With `openOnHover` a mouse pointer resting on it opens the popover, and a click pins a\n * hover-opened popover instead of closing it. With `openOnContext` it is a context-menu region (a\n * list, a row, a canvas) instead of a button: it receives its `id` and the context-menu and key\n * handlers, but no state ARIA and no click toggle (a render function still receives every prop:\n * do not spread the state ARIA then).\n *\n * A Tooltip goes between the trigger and the button: it passes the trigger's `id` and ARIA on to\n * the button, which the Tooltip also describes.\n *\n * @example\n * <Popover.Trigger>\n * <Tooltip content=\"Narrow the list\">\n * <Button>Filters</Button>\n * </Tooltip>\n * </Popover.Trigger>\n *\n * Also exported as `PopoverTrigger` for React Server Components, which cannot use the dotted\n * `Popover.Trigger` (that needs a client file).\n */\nexport const PopoverTrigger = ({\n children,\n asChild,\n id: idProp,\n onClick,\n onKeyDown,\n onContextMenu,\n onPointerEnter,\n onPointerMove,\n onPointerLeave,\n ref,\n ...rest\n}: PopoverTriggerProps) => {\n const {\n open,\n contentId,\n triggerId,\n triggerElementRef,\n setResolvedTriggerId,\n onTriggerClick,\n onTriggerKeyDown,\n hoverTriggerHandlers: hover,\n contextMode,\n contextTriggerHandlers: gesture,\n } = usePopoverContext('Popover.Trigger');\n const elementRef = useMergedRefs<HTMLElement>(ref, triggerElementRef);\n\n // On a wrapper span (`asChild={false}`, the automatic fallback) useTriggerElement moves the\n // state ARIA onto the first element in the tab order inside it. The hover handlers are there\n // only with `openOnHover`, the context handlers only with `openOnContext`. A context region is\n // no popover button: it gets no state ARIA and no click toggle (useTriggerElement\n // `omitStateAria`), and a render-prop child reads a constant closed state.\n const triggerProps = {\n ...rest,\n id: idProp ?? triggerId,\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': contextMode ? false : open,\n 'aria-controls': open && !contextMode ? contentId : undefined,\n onClick: composeEventHandlers(onClick, contextMode ? undefined : onTriggerClick),\n onKeyDown: composeEventHandlers(\n onKeyDown,\n gesture ? composeEventHandlers(gesture.onKeyDown, onTriggerKeyDown) : onTriggerKeyDown,\n ),\n onContextMenu: gesture\n ? composeEventHandlers(onContextMenu, gesture.onContextMenu)\n : onContextMenu,\n onPointerEnter: hover\n ? composeEventHandlers(onPointerEnter, hover.onPointerEnter)\n : onPointerEnter,\n onPointerMove: hover ? composeEventHandlers(onPointerMove, hover.onPointerMove) : onPointerMove,\n onPointerLeave: hover\n ? composeEventHandlers(onPointerLeave, hover.onPointerLeave)\n : onPointerLeave,\n ref: elementRef,\n } as PopoverTriggerChildProps;\n\n return useTriggerElement(children, triggerProps, {\n componentName: 'Popover.Trigger',\n asChild,\n onResolvedId: setResolvedTriggerId,\n omitStateAria: contextMode,\n });\n};\nPopoverTrigger.displayName = 'PopoverTrigger';\n\n/**\n * The popover surface: a non-modal `role=\"dialog\"` rendered in a portal (so overflow containers\n * never clip it) and positioned next to the trigger with a beak, flipping and shifting to stay in\n * the viewport. It closes on Escape and on a press outside (presses inside nested overlays opened\n * from it count as inside), and focus returns to the trigger when it closes while focus was inside.\n * In the keyboard order it follows the trigger, like inline content: Tab from the open trigger\n * enters it, Tab past its last element continues after the trigger, and Shift+Tab from the element\n * after the trigger enters it at its last element. Tab from the last element of the page moves\n * past it, and Shift+Tab from outside the page reaches the page's last element first, so a lap\n * visits it once. For a trigger outside the tab order (nothing in it can take focus, or\n * `tabIndex={-1}`), Tab from the tab stop before the trigger enters it, and Shift+Tab from its\n * first element returns to the trigger, or to that tab stop when nothing in the trigger can take\n * focus. With no tab stop before the trigger, the content is reached at the end of the page.\n * Named by `title`, `aria-label`/`aria-labelledby`, or else by its trigger: `aria-labelledby`\n * points at the id the trigger element carries in the document, or at the trigger's own label\n * elements when the trigger is named through `aria-labelledby` (an icon-only Button inside\n * `Tooltip relationship=\"label\"`); never at a missing id. A development warning names the problem\n * when the trigger has no id or no text. With `openOnContext` it is never named by the trigger (a\n * region's text is no name): pass `title`, `aria-label` or `aria-labelledby` (a development\n * warning otherwise). A consumer `id` is kept, and the trigger's `aria-controls` follows it. The\n * beak inherits the surface's background and border colors, so a `className` that changes them\n * restyles the beak too.\n *\n * With `openOnContext` it opens at the pointer of a right click, or at the focused row for\n * Shift+F10 and the ContextMenu key, and it follows that row in the keyboard order; with a\n * `target` it is placed at the target and, without a trigger, follows a target element in the\n * keyboard order.\n *\n * Also exported as `PopoverContent` for React Server Components, which cannot use the dotted\n * `Popover.Content` (that needs a client file).\n */\nexport const PopoverContent = ({\n children,\n title,\n id: idProp,\n className,\n style,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n onKeyDown,\n onContextMenu,\n onPointerEnter,\n onPointerLeave,\n ref,\n ...rest\n}: PopoverContentProps) => {\n const {\n open,\n contentId,\n setCustomContentId,\n resolvedTriggerId,\n triggerRef,\n triggerElement,\n surfaceElementRef,\n arrowRef,\n layerId,\n floatingProps,\n arrowStyles,\n placedSide,\n onContentKeyDown,\n hoverSurfaceHandlers: hover,\n contextMode,\n onContentContextMenu,\n keyboardContext,\n } = usePopoverContext('Popover.Content');\n const titleId = useId('popover-title');\n const elementRef = useMergedRefs<HTMLDivElement>(ref, surfaceElementRef);\n const hasTitle = slotRendersContent(title);\n const unnamed = ariaLabelledBy === undefined && !ariaLabel && !hasTitle;\n // A context region is no popover button, and its whole text is no name: in context mode the\n // content is never labelled by the trigger.\n const checkTrigger = open && unnamed && !contextMode;\n\n // The trigger's label ids in the document, re-read when the trigger's ids or labels change: a\n // Tooltip between Popover.Trigger and the Button leaves the Button's own id in place (and with\n // `relationship=\"label\"` names it through `aria-labelledby`), and a render-prop child may not\n // spread `id` at all — never point aria-labelledby at an id that is not there.\n const subscribeTrigger = React.useCallback(\n (onChange: () => void) => {\n if (!checkTrigger || !triggerElement || typeof MutationObserver === 'undefined') {\n return subscribeNothing();\n }\n const observer = new MutationObserver(onChange);\n observer.observe(triggerElement, {\n attributes: true,\n attributeFilter: ['id', 'aria-labelledby'],\n childList: true,\n subtree: true,\n });\n return () => observer.disconnect();\n },\n [checkTrigger, triggerElement],\n );\n const triggerLabelId = React.useSyncExternalStore(\n subscribeTrigger,\n () => (checkTrigger ? findTriggerLabelId(triggerElement, resolvedTriggerId) : undefined),\n () => (checkTrigger ? resolvedTriggerId : undefined),\n );\n\n const labelledBy =\n ariaLabelledBy ?? (ariaLabel ? undefined : hasTitle ? titleId : triggerLabelId);\n const customId = idProp || undefined;\n\n // Report the consumer's id to the root so the trigger's `aria-controls` points at it.\n React.useEffect(() => {\n setCustomContentId(customId);\n return () => setCustomContentId(undefined);\n }, [customId, setCustomContentId]);\n\n React.useEffect(() => {\n if (!open || !unnamed || !contextMode || !isDev) return;\n warnOnce(\n 'Popover.Content:name',\n 'Popover.Content: the popover has no accessible name. A context popover (openOnContext) is not named by its region: pass `title`, `aria-label` or `aria-labelledby`.',\n );\n }, [open, unnamed, contextMode]);\n\n React.useEffect(() => {\n if (!checkTrigger || !isDev) return;\n // Read after commit: a trigger's ref is attached by now even before it reported its id.\n const trigger = triggerRef.current;\n if (!trigger) {\n warnOnce(\n 'Popover.Content:name',\n 'Popover.Content: the popover has no accessible name. Pass `title`, `aria-label` or `aria-labelledby`, or open it from a Popover.Trigger.',\n );\n return;\n }\n const labelIds = findTriggerLabelId(trigger, resolvedTriggerId);\n if (!labelIds) {\n warnOnce(\n 'Popover.Content:trigger-id',\n 'Popover.Content: the popover is named by its trigger, but the trigger element has no `id` (a render-prop child of Popover.Trigger must spread the `id` it receives), so the popover has no accessible name. Spread every trigger prop onto the element, or pass `title`, `aria-label` or `aria-labelledby`.',\n );\n } else if (!referencesText(trigger.ownerDocument, labelIds)) {\n warnOnce(\n 'Popover.Content:trigger-name',\n 'Popover.Content: the popover is named by its trigger, but the trigger has no text to name it (an icon-only trigger needs `aria-label`, or `aria-labelledby` pointing at text), so the popover has no accessible name. Name the trigger, or pass `title`, `aria-label` or `aria-labelledby`.',\n );\n }\n }, [checkTrigger, resolvedTriggerId, triggerRef, triggerLabelId]);\n\n if (!open) return null;\n\n return (\n <Portal layerId={layerId}>\n <div\n role=\"dialog\"\n aria-label={ariaLabel}\n aria-labelledby={labelledBy}\n tabIndex={keyboardContext ? -1 : undefined}\n {...rest}\n ref={elementRef}\n id={customId ?? contentId}\n data-side={floatingProps['data-side']}\n data-align={floatingProps['data-align']}\n style={{ ...style, ...floatingProps.style }}\n onKeyDown={composeEventHandlers(onKeyDown, onContentKeyDown)}\n onContextMenu={composeEventHandlers(onContextMenu, onContentContextMenu)}\n onPointerEnter={\n hover ? composeEventHandlers(onPointerEnter, hover.onPointerEnter) : onPointerEnter\n }\n onPointerLeave={\n hover ? composeEventHandlers(onPointerLeave, hover.onPointerLeave) : onPointerLeave\n }\n className={cn(\n 'w-64 rounded-md border border-border bg-background p-4 text-body-1 font-normal text-foreground normal-case tracking-normal text-start shadow-4',\n className,\n )}\n >\n <PopoverBeak\n ref={arrowRef}\n side={placedSide}\n style={arrowStyles}\n data-wave-popover-arrow=\"\"\n />\n {hasTitle && (\n <h2 id={titleId} className=\"mb-2 text-subtitle-2 font-semibold\">\n {title}\n </h2>\n )}\n {children}\n </div>\n </Portal>\n );\n};\nPopoverContent.displayName = 'PopoverContent';\n\n/**\n * A non-modal popup anchored to a trigger: `Popover.Trigger` (merges its props onto the child\n * button) and `Popover.Content` (portaled, positioned `role=\"dialog\"` surface). Use it for custom\n * popups such as filters or details; for a menu button use `Menu.Trigger` and `Menu.Popover`,\n * which add menu semantics and keyboard support.\n *\n * Controlled (`open`/`onOpenChange`) or uncontrolled (`defaultOpen`); `side`/`align` place the\n * content, and `ignoreOutsideRefs` lists external elements (such as a toggle button) whose presses\n * do not dismiss it.\n *\n * - **Hover cards:** `openOnHover` opens it when a mouse pointer rests on the trigger\n * (`openDelay`) and closes it once the pointer has left the trigger and the content\n * (`closeDelay`), unless focus is inside; a click on the trigger pins it.\n * - **Context popovers:** `openOnContext` makes the trigger a context-menu region: a right click\n * opens it at the pointer, Shift+F10 or the ContextMenu key at the focused row (with focus\n * moving into the content). Name the content with `title` or `aria-label`.\n * - **Custom anchors:** `target` places it at another element or at a `VirtualElement` (a point, a\n * text selection); with a controlled `open` it needs no trigger.\n *\n * @example\n * <Popover>\n * <Popover.Trigger><Button>Details</Button></Popover.Trigger>\n * <Popover.Content title=\"Details\">…</Popover.Content>\n * </Popover>\n */\nexport const Popover = /* @__PURE__ */ Object.assign(PopoverRoot, {\n Trigger: PopoverTrigger,\n Content: PopoverContent,\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/globalRegistry.cjs"),r=require("../../hooks/useEventCallback.cjs"),i=require("../../lib/focus.cjs");let a=require("react");a=e.__toESM(a,1);let o=require("react/jsx-runtime");var s={top:`border-b border-r`,bottom:`border-t border-l`,left:`border-t border-r`,right:`border-b border-l`},c=({side:e,className:n,ref:r,...i})=>(0,o.jsx)(`div`,{ref:r,"aria-hidden":`true`,...i,className:t.cn(`size-2 rotate-45 border-inherit bg-inherit`,s[e],n)});c.displayName=`PopoverBeak`;function l(e,t,n=i.getTabbableElements(e.ownerDocument.body)){let r=e.closest(`[data-wave-portal]`);return n.filter(e=>!t.contains(e)&&e.closest(`[data-wave-portal]`)===r)}function u(e,t,n){return l(e,t,n).find(t=>!e.contains(t)&&!!(e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING))??null}function d(e,t,n){let r=l(e,t,n).filter(t=>e.contains(t)||!!(e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_PRECEDING));return r[r.length-1]??null}function f(e,t,n,r){return!e||r.includes(e)?e:d(t,n,r)}function p(e,t){t&&(e.preventDefault(),t.focus())}function m(e,t){return!t||t===e.body||t===e.documentElement}function h(e){let t=e.ownerDocument,n=t.defaultView,{style:r}=e,i=r.getPropertyValue(`visibility`),a=r.getPropertyPriority(`visibility`);r.setProperty(`visibility`,`hidden`,`important`);let o,s=()=>{t.removeEventListener(`focusout`,s,!0),o!==void 0&&n?.cancelAnimationFrame(o),o=void 0,r.getPropertyValue(`visibility`)===`hidden`&&r.getPropertyPriority(`visibility`)===`important`&&(i?r.setProperty(`visibility`,i,a):r.removeProperty(`visibility`))};t.addEventListener(`focusout`,s,!0),n&&(o=n.requestAnimationFrame(s))}var g={users:0,pressed:!1,refocus:null,lastFocused:null,windowFocused:!1,epoch:0,uninstall:null};function _(e,t){let n=g.lastFocused;if(!n)return!1;let r=n.element.deref();return r?.isConnected?!!(e.compareDocumentPosition(r)&Node.DOCUMENT_POSITION_FOLLOWING):n.surface?.deref()===t}function v(){return n.getGlobalRegistry(`orderedSurfaces`,()=>new Set)}function y(){if(typeof document>`u`)return()=>{};if(g.users+=1,!g.uninstall){let e=document,t=e.defaultView,n=()=>{g.epoch+=1,g.pressed=!0,g.windowFocused=!1},r=()=>{g.epoch+=1,g.windowFocused=!1},i=()=>{g.epoch+=1,g.pressed=!1,g.windowFocused=!1;let t=e.activeElement;g.refocus=!t||m(e,t)?null:new WeakRef(t)},a=()=>{g.epoch+=1,g.windowFocused=!0},o=e=>{let t=e.target,n=t&&[...v()].find(e=>e.contains(t));g.lastFocused=t&&{element:new WeakRef(t),surface:n?new WeakRef(n):null}},s=()=>{g.epoch+=1,g.refocus=null,g.windowFocused=!1};e.addEventListener(`pointerdown`,n,!0),e.addEventListener(`mousedown`,n,!0),e.addEventListener(`keydown`,r,!0),e.addEventListener(`keyup`,r,!0),e.addEventListener(`focusin`,o,!0),e.addEventListener(`focusin`,s),t?.addEventListener(`blur`,i),t?.addEventListener(`focus`,a),g.uninstall=()=>{e.removeEventListener(`pointerdown`,n,!0),e.removeEventListener(`mousedown`,n,!0),e.removeEventListener(`keydown`,r,!0),e.removeEventListener(`keyup`,r,!0),e.removeEventListener(`focusin`,o,!0),e.removeEventListener(`focusin`,s),t?.removeEventListener(`blur`,i),t?.removeEventListener(`focus`,a),g.pressed=!1,g.refocus=null,g.lastFocused=null,g.windowFocused=!1}}let e=!0;return()=>{e&&(e=!1,g.users=Math.max(0,g.users-1),!(g.users>0)&&(g.uninstall?.(),g.uninstall=null))}}function b({enabled:e,surface:t,anchorRef:n,getPreviousStop:o}){let s=r.useEventCallback(o),c=a.useRef(`anchor`),l=a.useRef(null),d=r.useEventCallback(e=>{l.current=null;let r=n.current;if(e.key!==`Tab`||e.defaultPrevented||!r||!t)return;let a=t.ownerDocument,o=a.activeElement;if(o&&t.contains(o))return;let c=i.getTabbableElements(a.body),d=c.filter(e=>t.contains(e)),v=d[0],y=d[d.length-1];if(!v||!y)return;if(!o||m(a,o)){e.shiftKey&&!g.pressed&&c[c.length-1]===y&&!_(y,t)&&(l.current={element:y,from:`far-end`,epoch:g.epoch});return}let b=s(r,t,c);if(e.shiftKey){b&&o===u(r,t,c)&&p(e,y);return}let x=f(b,r,t,c);if(o===b||o===x){p(e,v);return}let S=c.indexOf(o);S!==-1&&c[S+1]===v&&(l.current={element:v,from:`page`,epoch:g.epoch},x&&h(t))});return a.useEffect(()=>y(),[]),a.useEffect(()=>{if(!e||!t)return;let r=t.ownerDocument,a=r.defaultView;c.current=`anchor`;let o=null,u=e=>{o=null;let a=l.current;l.current=null;let u=e.relatedTarget;if(u&&t.contains(u))return;let d=e.target;if(!u&&d===g.refocus?.deref())return;let p=a&&a.epoch===g.epoch&&a.element===d?a.from:null;if(c.current=p===`page`?`page`:`anchor`,p===`page`||!m(r,u)||g.pressed||p!==`far-end`&&!g.windowFocused)return;let h=n.current;if(!h||d!==i.getLastTabbable(t))return;let _=i.getTabbableElements(r.body),y=[...v()],b=_.filter(e=>!y.some(t=>t.contains(e))),x=b[b.length-1],S=s(h,t,_);S&&x&&x!==f(S,h,t,_)&&(o={event:e,pageEnd:x})},p=e=>{let t=o;o=null,t?.event===e&&r.activeElement===e.target&&(i.focusElement(t.pageEnd)||(c.current=`page`))},h=v();return h.add(t),t.addEventListener(`focusin`,u),a?.addEventListener(`focusin`,p),r.addEventListener(`keydown`,d),()=>{h.delete(t),t.removeEventListener(`focusin`,u),a?.removeEventListener(`focusin`,p),r.removeEventListener(`keydown`,d)}},[e,t,n,s,d]),r.useEventCallback(r=>{let a=n.current;if(r.key!==`Tab`||r.defaultPrevented||!e||!t||!a)return;let o=t.ownerDocument.activeElement;if(!o||!t.contains(o)||c.current===`page`)return;let l=i.getTabbableElements(t);if(r.shiftKey){(o===t||o===l[0])&&p(r,s(a,t));return}l.length>0&&o!==l[l.length-1]||p(r,u(a,t))})}exports.PopoverBeak=c,exports.getTabbableAfter=u,exports.getTabbableThrough=d,exports.usePopoverTabOrder=b;
|
|
2
|
+
//# sourceMappingURL=Popover.shared.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Popover.shared.cjs","names":["cn","getTabbableElements","getGlobalRegistry","useEventCallback","React","getLastTabbable","focusElement","require_runtime","require_cn","require_globalRegistry","require_useEventCallback","require_focus","react","react_jsx_runtime","BEAK_BORDER","PopoverBeak","rest","side","className","getScopedTabbables","anchor","scope","order","exclude","el","getTabbableAfter","getTabbableThrough","through","getEntryStop","previous","surface","focusInstead","target","event","isNothing","node","doc","hideForNativeTab","win","value","style","priority","frame","show","focusOrigin","startsAfter","last","start","getOrderedSurfaces","retainFocusOrigin","onPress","onKey","onWindowBlur","active","onWindowFocus","onFocusCapture","open","onFocusIn","retained","usePopoverTabOrder","getPrevious","getPreviousStop","entryRef","pendingRef","onDocumentKeyDown","anchorRef","inside","first","entry","index","enabled","redirect","pending","from","entered","expected","surfaces","outside","pageEnd","onWindowFocusIn","orderedSurfaces","tabbables"],"sources":["../../../src/components/overlays/Popover.shared.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { focusElement, getLastTabbable, getTabbableElements } from '../../lib/focus';\nimport { getGlobalRegistry } from '../../lib/globalRegistry';\nimport type { UsePopupPositionResult } from '../../hooks/usePopupPosition';\nimport { useEventCallback } from '../../hooks/useEventCallback';\n\n// Parts shared by the anchored popups of this folder: Popover.Content and TeachingPopover with a\n// `target`. Internal: not exported from the barrels.\n\n/** Final physical side of a positioned surface (the `side` result of `usePopupPosition`). */\nexport type PopoverPhysicalSide = UsePopupPositionResult['side'];\n\n/** Borders of the rotated square beak that face the anchor, per final physical side. */\nconst BEAK_BORDER: Record<PopoverPhysicalSide, string> = {\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n top: 'border-b border-r',\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n bottom: 'border-t border-l',\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n left: 'border-t border-r',\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n right: 'border-b border-l',\n};\n\n/** Properties for the internal PopoverBeak. */\nexport interface PopoverBeakProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Final physical side of the surface; the beak is drawn on the edge that faces the anchor. */\n side: PopoverPhysicalSide;\n /** Ref to the beak: pass it to `usePopupPosition` as `arrowRef`. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * The beak of an anchored surface: a rotated square, hidden from assistive technology, that\n * inherits the surface's background and border colors (so a `className` that changes them\n * restyles the beak too). Position it with the `arrowStyles` of `usePopupPosition`; its size\n * matches the `--wave-popup-arrow-size` the arrow offset is computed from.\n */\nexport const PopoverBeak = ({ side, className, ref, ...rest }: PopoverBeakProps) => (\n <div\n ref={ref}\n aria-hidden=\"true\"\n {...rest}\n className={cn('size-2 rotate-45 border-inherit bg-inherit', BEAK_BORDER[side], className)}\n />\n);\nPopoverBeak.displayName = 'PopoverBeak';\n\n/**\n * The tabbable elements of the anchor's document, in sequential focus order, that are in the same\n * portal as the anchor (or, like it, in the page) and outside `exclude`. `order` is the document's\n * tabbable elements when the caller has them already.\n */\nfunction getScopedTabbables(\n anchor: HTMLElement,\n exclude: HTMLElement,\n order: readonly HTMLElement[] = getTabbableElements(anchor.ownerDocument.body),\n): HTMLElement[] {\n const scope = anchor.closest('[data-wave-portal]');\n return order.filter((el) => !exclude.contains(el) && el.closest('[data-wave-portal]') === scope);\n}\n\n/**\n * The first tabbable element after `anchor` in document order, not inside it, in the same portal\n * as the anchor and outside `exclude`: the tab stop after a surface placed right after the anchor.\n * Pass the document's tabbable elements as `order` when you have them, to spare a second scan.\n */\nexport function getTabbableAfter(\n anchor: HTMLElement,\n exclude: HTMLElement,\n order?: readonly HTMLElement[],\n): HTMLElement | null {\n return (\n getScopedTabbables(anchor, exclude, order).find(\n (el) =>\n !anchor.contains(el) &&\n !!(anchor.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING),\n ) ?? null\n );\n}\n\n/**\n * The last tabbable element that is `anchor`, inside it or before it in document order, in the\n * same portal as the anchor and outside `exclude`: the tab stop before a surface placed right\n * after the anchor. Pass the document's tabbable elements as `order` when you have them.\n */\nexport function getTabbableThrough(\n anchor: HTMLElement,\n exclude: HTMLElement,\n order?: readonly HTMLElement[],\n): HTMLElement | null {\n const through = getScopedTabbables(anchor, exclude, order).filter(\n (el) =>\n anchor.contains(el) ||\n !!(anchor.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING),\n );\n return through[through.length - 1] ?? null;\n}\n\n/**\n * The tab stop that a surface placed right after `anchor` follows, given its previous stop: that\n * stop, or the tab stop at or before the anchor when the previous stop is outside the tab order\n * (a trigger with `tabIndex={-1}`). `null` when nothing in the tab order comes before the place.\n */\nfunction getEntryStop(\n previous: HTMLElement | null,\n anchor: HTMLElement,\n surface: HTMLElement,\n order: readonly HTMLElement[],\n): HTMLElement | null {\n if (!previous || order.includes(previous)) return previous;\n return getTabbableThrough(anchor, surface, order);\n}\n\nfunction focusInstead(event: { preventDefault(): void }, target: HTMLElement | null): void {\n if (!target) return;\n event.preventDefault();\n target.focus();\n}\n\nfunction isNothing(doc: Document, node: EventTarget | null): boolean {\n return !node || node === doc.body || node === doc.documentElement;\n}\n\n/**\n * Hides `surface` (`visibility: hidden`) for the native Tab in progress, so the browser moves past\n * its elements. It is shown again as soon as focus moves (the `focusout` of that Tab, before the\n * next element takes focus), or before the next frame when the Tab moves nothing.\n */\nfunction hideForNativeTab(surface: HTMLElement): void {\n const doc = surface.ownerDocument;\n const win = doc.defaultView;\n const { style } = surface;\n const value = style.getPropertyValue('visibility');\n const priority = style.getPropertyPriority('visibility');\n style.setProperty('visibility', 'hidden', 'important');\n let frame: number | undefined;\n const show = () => {\n doc.removeEventListener('focusout', show, true);\n if (frame !== undefined) win?.cancelAnimationFrame(frame);\n frame = undefined;\n // Left alone when something else changed it meanwhile.\n const ours =\n style.getPropertyValue('visibility') === 'hidden' &&\n style.getPropertyPriority('visibility') === 'important';\n if (!ours) return;\n if (value) style.setProperty('visibility', value, priority);\n else style.removeProperty('visibility');\n };\n doc.addEventListener('focusout', show, true);\n if (win) frame = win.requestAnimationFrame(show);\n}\n\n/**\n * What the document knows about focus that arrives from nothing (the body): whether it can come\n * from the browser's own controls, and where the browser starts Tab and Shift+Tab from nothing.\n * The listeners are installed while a {@link usePopoverTabOrder} is mounted, open or not, so the\n * press that opened a surface counts too. Elements are held through a `WeakRef`, so a removed\n * subtree is not kept alive while a popover is mounted: an element that is gone was removed.\n */\ninterface FocusOrigin {\n /** Mounted `usePopoverTabOrder` instances. */\n users: number;\n /**\n * A pointer press (`pointerdown`/`mousedown`) came since the window last lost focus. The user is\n * then in the page, not arriving from the browser's controls, which the window must lose focus\n * to reach: a key press does not clear it.\n */\n pressed: boolean;\n /**\n * The element that had focus when the window lost it: the browser focuses it again, from\n * nothing, when the window gets focus back. Cleared by the next `focusin`.\n */\n refocus: WeakRef<Element> | null;\n /**\n * The element that took focus last, and the ordered surface ({@link getOrderedSurfaces}) that\n * contained it then. When focus has gone from it to nothing (it was removed, hidden or blurred),\n * the browser starts sequential navigation where it is, or where it was. Recorded in the capture\n * phase, so a handler that stops a `focusin` from propagating does not hide it.\n */\n lastFocused: {\n element: WeakRef<Element>;\n surface: WeakRef<HTMLElement> | null;\n } | null;\n /**\n * The window has just got focus back: no element took focus since, and no key or pointer press\n * reached the page. Sequential navigation from the browser's own controls gives the window focus\n * right before the element it reaches; focus that arrives from nothing without it comes from the\n * page (a focus restore after the focused element was removed, a script).\n */\n windowFocused: boolean;\n /**\n * Counts the events that end a key press's focus change: key presses and releases, pointer\n * presses, `focusin` and the window's blur and focus. An entry the `keydown` of a Tab expects\n * applies only to the `focusin` of that same Tab.\n */\n epoch: number;\n /** Removes the listeners; `null` while none are installed. */\n uninstall: (() => void) | null;\n}\n\n/**\n * One per copy of the library, not in the global registry: every field is derived from document\n * and window events, and only this copy's hooks read it, each of which keeps this copy's\n * listeners installed from its mount on. A second copy (ESM and CJS side by side) installs its own\n * listeners and derives the same state; `epoch` is compared only within the copy that set it.\n */\nconst focusOrigin: FocusOrigin = {\n users: 0,\n pressed: false,\n refocus: null,\n lastFocused: null,\n windowFocused: false,\n epoch: 0,\n uninstall: null,\n};\n\n/**\n * Whether sequential navigation from nothing starts after `el`, the last tabbable element of\n * `surface`: at the element that took focus last, when that comes after `el` in the document or\n * was removed from `surface` (it may have been anywhere in it, after `el` too). An element removed\n * elsewhere does not count: from a place after the surface (a dismissed toast in a later portal),\n * Shift+Tab lands on `el` just as from the document's end, and from a place before it, it does not\n * land on `el`.\n */\nfunction startsAfter(el: HTMLElement, surface: HTMLElement): boolean {\n const last = focusOrigin.lastFocused;\n if (!last) return false;\n const start = last.element.deref();\n if (start?.isConnected) {\n return !!(el.compareDocumentPosition(start) & Node.DOCUMENT_POSITION_FOLLOWING);\n }\n return last.surface?.deref() === surface;\n}\n\n/**\n * The surfaces whose keyboard order a {@link usePopoverTabOrder} manages right now. Their content\n * takes its place after its anchor, not at the end of the document where its portal is, so none\n * of it is \"the last element of the page\". Kept in `getGlobalRegistry('orderedSurfaces')`, so an\n * app that loads both the ESM and the CJS copy of the library excludes the surfaces of both.\n */\nfunction getOrderedSurfaces(): Set<HTMLElement> {\n return getGlobalRegistry('orderedSurfaces', () => new Set<HTMLElement>());\n}\n\nfunction retainFocusOrigin(): () => void {\n if (typeof document === 'undefined') return () => {};\n focusOrigin.users += 1;\n if (!focusOrigin.uninstall) {\n const doc = document;\n const win = doc.defaultView;\n const onPress = () => {\n focusOrigin.epoch += 1;\n focusOrigin.pressed = true;\n focusOrigin.windowFocused = false;\n };\n const onKey = () => {\n focusOrigin.epoch += 1;\n focusOrigin.windowFocused = false;\n };\n // Not capture listeners: they hear only the window's own blur and focus (an element's do not\n // bubble).\n const onWindowBlur = () => {\n focusOrigin.epoch += 1;\n focusOrigin.pressed = false;\n focusOrigin.windowFocused = false;\n const active = doc.activeElement;\n focusOrigin.refocus = !active || isNothing(doc, active) ? null : new WeakRef(active);\n };\n const onWindowFocus = () => {\n focusOrigin.epoch += 1;\n focusOrigin.windowFocused = true;\n };\n // Capture, like the presses and keys, so a handler that stops a `focusin` from propagating\n // does not hide where focus went. Only the `keydown` of a later Tab reads it: recording it\n // before the surfaces' own `focusin` listeners run changes nothing for them.\n const onFocusCapture = (event: FocusEvent) => {\n const target = event.target as Element | null;\n const surface = target && [...getOrderedSurfaces()].find((open) => open.contains(target));\n focusOrigin.lastFocused = target && {\n element: new WeakRef(target),\n surface: surface ? new WeakRef(surface) : null,\n };\n };\n // Bubbling to the document, after the surfaces' own `focusin` listeners have read the state.\n const onFocusIn = () => {\n focusOrigin.epoch += 1;\n focusOrigin.refocus = null;\n focusOrigin.windowFocused = false;\n };\n // Capture: a handler that stops a press or a key from propagating must not hide it.\n doc.addEventListener('pointerdown', onPress, true);\n doc.addEventListener('mousedown', onPress, true);\n doc.addEventListener('keydown', onKey, true);\n doc.addEventListener('keyup', onKey, true);\n doc.addEventListener('focusin', onFocusCapture, true);\n doc.addEventListener('focusin', onFocusIn);\n win?.addEventListener('blur', onWindowBlur);\n win?.addEventListener('focus', onWindowFocus);\n focusOrigin.uninstall = () => {\n doc.removeEventListener('pointerdown', onPress, true);\n doc.removeEventListener('mousedown', onPress, true);\n doc.removeEventListener('keydown', onKey, true);\n doc.removeEventListener('keyup', onKey, true);\n doc.removeEventListener('focusin', onFocusCapture, true);\n doc.removeEventListener('focusin', onFocusIn);\n win?.removeEventListener('blur', onWindowBlur);\n win?.removeEventListener('focus', onWindowFocus);\n focusOrigin.pressed = false;\n focusOrigin.refocus = null;\n focusOrigin.lastFocused = null;\n focusOrigin.windowFocused = false;\n };\n }\n let retained = true;\n return () => {\n if (!retained) return;\n retained = false;\n focusOrigin.users = Math.max(0, focusOrigin.users - 1);\n if (focusOrigin.users > 0) return;\n focusOrigin.uninstall?.();\n focusOrigin.uninstall = null;\n };\n}\n\n/** Options of {@link usePopoverTabOrder}. */\nexport interface PopoverTabOrderOptions {\n /** Whether the surface is shown next to its anchor; the listeners exist only while `true`. */\n enabled: boolean;\n /** The portaled surface, held in state through its callback ref. */\n surface: HTMLElement | null;\n /** The anchor: the surface takes its place in the keyboard order right after it. */\n anchorRef: React.RefObject<HTMLElement | null>;\n /**\n * The element before the surface's place: Tab from it enters the surface, and Shift+Tab from\n * the surface's first element returns to it. When it is outside the tab order (a trigger with\n * `tabIndex={-1}`), Tab from the tab stop at or before the anchor enters the surface too; `null`\n * when nothing comes before the place. `order`, when given, is the document's tabbable elements.\n */\n getPreviousStop: (\n anchor: HTMLElement,\n surface: HTMLElement,\n order?: readonly HTMLElement[],\n ) => HTMLElement | null;\n}\n\n/**\n * Keyboard order of a surface portaled to the end of the document, as if it were rendered right\n * after its anchor (the order of 0.4's inline content). Returns the surface's `onKeyDown`; while\n * `enabled`, a document `keydown` listener and `focusin` listeners on the surface and the window\n * do the rest. While mounted, shared document listeners record pointer presses, key presses, the\n * element that took focus last and the window's blur and focus.\n *\n * - Tab from the previous stop enters the surface at its first tabbable element (so does Tab\n * from the tab stop at or before the anchor when the previous stop is outside the tab order),\n * and Shift+Tab from the tab stop after the anchor enters it at its last one.\n * - Tab past the surface's last element continues after the anchor; Shift+Tab from its first\n * element (or from the surface itself) returns to the previous stop.\n * - The surface is not visited a second time where its portal is. Tab from the element before\n * the portal moves past the surface (it is hidden for that one Tab), to what follows it or out\n * of the page. Shift+Tab from the browser's own controls (the window gets focus back just before\n * it), or from nothing without a pointer press, lands on the surface's last element as the\n * document's last one: focus goes to the last element of the page instead (outside every open\n * surface: another open popover's content has its own place after its anchor), unless that is\n * the tab stop before the surface's place (the surface then ends the order). Focus moves there\n * once the entry's `focusin` has reached the window, so the entered element's focus handlers\n * run before its blur handlers; a handler that stops that `focusin` from propagating (an\n * `onFocus` in the content that calls `stopPropagation()`) leaves focus on the surface's last\n * element, as an entry at its place after the anchor, with no trap and no Tab cycle. Shift+Tab\n * from nothing does not start at the document's end when the element that had focus comes after\n * the surface's last element or was removed from the surface (a control of the surface that hid\n * or removed itself): the browser starts where it is, or was. An element removed elsewhere (a\n * dismissed toast portaled after the surface) keeps the rule: from its place, too, Shift+Tab\n * lands on the surface's last element. A lap in either direction visits every element once, and\n * there is no Tab cycle.\n * - With no tab stop before its place (nothing in the tab order at or before the anchor), Tab\n * reaches the surface where its portal is, from the element before the portal, and it follows\n * the document order from there. When the previous stop is missing too, Shift+Tab reaches it\n * there as well: its first element leads to the element before the portal, so neither Shift+Tab\n * from the tab stop after the anchor nor from outside the page is moved to its place.\n * - Every other entry keeps the place after the anchor: a click, Shift+Tab from a pressed point,\n * focus restored from nothing (a layer opened from the surface's last element closed), a\n * script, focus that returns to an element as the window gets focus back, and focus the content\n * takes as it mounts (`autoFocus`, before the listeners exist).\n * - Content that the Tab from the page still reaches (it shows itself again before the browser\n * moves focus) follows the document order from there, so Tab past it leaves the page rather\n * than jumping back to the anchor.\n *\n * Every Tab outside the surface costs one scan of the document's tabbable elements. The listeners\n * skip events whose default is already prevented; React handlers (a trigger's own `onKeyDown`,\n * the returned one) run before them and before a dialog's focus trap.\n */\nexport function usePopoverTabOrder({\n enabled,\n surface,\n anchorRef,\n getPreviousStop,\n}: PopoverTabOrderOptions): React.KeyboardEventHandler<HTMLElement> {\n const getPrevious = useEventCallback(getPreviousStop);\n /** How focus last entered the surface: at its place after the anchor, or at the portal's. */\n const entryRef = React.useRef<'anchor' | 'page'>('anchor');\n /**\n * Where the Tab being pressed enters the surface natively: at `element`, from the page (had it\n * not moved past the surface) or, Shift+Tab from nothing, at the document's far end. Valid in\n * the `focusin` of that Tab only (same `epoch`).\n */\n const pendingRef = React.useRef<{\n element: HTMLElement;\n from: 'page' | 'far-end';\n epoch: number;\n } | null>(null);\n\n const onDocumentKeyDown = useEventCallback((event: KeyboardEvent) => {\n pendingRef.current = null;\n const anchor = anchorRef.current;\n if (event.key !== 'Tab' || event.defaultPrevented || !anchor || !surface) return;\n const doc = surface.ownerDocument;\n const active = doc.activeElement as HTMLElement | null;\n if (active && surface.contains(active)) return;\n // One scan of the document; everything below is derived from it.\n const order = getTabbableElements(doc.body);\n const inside = order.filter((el) => surface.contains(el));\n const first = inside[0];\n const last = inside[inside.length - 1];\n if (!first || !last) return;\n if (!active || isNothing(doc, active)) {\n // With no pointer press to start from, Shift+Tab from nothing reaches the document's last\n // element, unless the browser starts after it: where the element that had focus is, or was\n // (a control of the surface that removed or hid itself).\n if (\n event.shiftKey &&\n !focusOrigin.pressed &&\n order[order.length - 1] === last &&\n !startsAfter(last, surface)\n ) {\n pendingRef.current = { element: last, from: 'far-end', epoch: focusOrigin.epoch };\n }\n return;\n }\n const previous = getPrevious(anchor, surface, order);\n if (event.shiftKey) {\n // Without a previous stop, Shift+Tab from the surface's first element follows the document\n // order: entering the surface here would form a cycle.\n if (previous && active === getTabbableAfter(anchor, surface, order)) {\n focusInstead(event, last);\n }\n return;\n }\n const entry = getEntryStop(previous, anchor, surface, order);\n if (active === previous || active === entry) {\n focusInstead(event, first);\n return;\n }\n const index = order.indexOf(active);\n if (index === -1 || order[index + 1] !== first) return;\n pendingRef.current = { element: first, from: 'page', epoch: focusOrigin.epoch };\n // The browser would enter the surface where its portal is. When a tab stop comes before its\n // place, the surface was visited after the anchor: move past it. Otherwise this is its entry.\n if (entry) hideForNativeTab(surface);\n });\n\n // Installed while mounted, not only while enabled: the press that opens the surface counts.\n React.useEffect(() => retainFocusOrigin(), []);\n\n React.useEffect(() => {\n if (!enabled || !surface) return;\n const doc = surface.ownerDocument;\n const win = doc.defaultView;\n // A new surface, or one shown again: focus it took as it mounted (before this listener) was\n // not a native entry from the page, and an earlier entry no longer applies.\n entryRef.current = 'anchor';\n /**\n * An entry that goes on to the last element of the page. Focus moves there once the entry's\n * `focusin` has reached the window, after React (which listens where the portal is, above the\n * surface) has handled it: the entered element's focus handlers run before its blur handlers,\n * so a Tooltip on it does not stay open. Not in a microtask: a browser runs microtasks between\n * the listeners of its own events.\n */\n let redirect: { event: FocusEvent; pageEnd: HTMLElement } | null = null;\n const onFocusIn = (event: FocusEvent) => {\n redirect = null;\n const pending = pendingRef.current;\n pendingRef.current = null;\n const from = event.relatedTarget as Node | null;\n if (from && surface.contains(from)) return;\n const entered = event.target;\n // The window got focus back: focus returns to where it was, in the order it had there.\n if (!from && entered === focusOrigin.refocus?.deref()) return;\n const expected =\n pending && pending.epoch === focusOrigin.epoch && pending.element === entered\n ? pending.from\n : null;\n // The Tab from the page reached the surface after all: follow the document order from here,\n // so Tab past it leaves the page instead of forming a cycle through the anchor.\n entryRef.current = expected === 'page' ? 'page' : 'anchor';\n if (expected === 'page' || !isNothing(doc, from) || focusOrigin.pressed) return;\n // Shift+Tab from the browser's own controls, or from nothing: the document's last element.\n if (expected !== 'far-end' && !focusOrigin.windowFocused) return;\n const anchor = anchorRef.current;\n if (!anchor || entered !== getLastTabbable(surface)) return;\n const order = getTabbableElements(doc.body);\n const surfaces = [...getOrderedSurfaces()];\n const outside = order.filter((el) => !surfaces.some((open) => open.contains(el)));\n const pageEnd = outside[outside.length - 1];\n const previous = getPrevious(anchor, surface, order);\n // The surface ends the order when the tab stop before its place is the page's last element.\n // Without a previous stop it keeps the place of its portal, as Shift+Tab from it does.\n if (!previous || !pageEnd || pageEnd === getEntryStop(previous, anchor, surface, order)) {\n return;\n }\n redirect = { event, pageEnd };\n };\n const onWindowFocusIn = (event: FocusEvent) => {\n const pending = redirect;\n redirect = null;\n // Left alone when a handler of the entry has moved focus already.\n if (pending?.event !== event || doc.activeElement !== event.target) return;\n if (!focusElement(pending.pageEnd)) entryRef.current = 'page';\n };\n const orderedSurfaces = getOrderedSurfaces();\n orderedSurfaces.add(surface);\n surface.addEventListener('focusin', onFocusIn);\n win?.addEventListener('focusin', onWindowFocusIn);\n doc.addEventListener('keydown', onDocumentKeyDown);\n return () => {\n orderedSurfaces.delete(surface);\n surface.removeEventListener('focusin', onFocusIn);\n win?.removeEventListener('focusin', onWindowFocusIn);\n doc.removeEventListener('keydown', onDocumentKeyDown);\n };\n }, [enabled, surface, anchorRef, getPrevious, onDocumentKeyDown]);\n\n return useEventCallback((event: React.KeyboardEvent<HTMLElement>) => {\n const anchor = anchorRef.current;\n if (event.key !== 'Tab' || event.defaultPrevented || !enabled || !surface || !anchor) return;\n const active = surface.ownerDocument.activeElement;\n // Events from nested portaled layers bubble here through React: only handle our own content.\n if (!active || !surface.contains(active) || entryRef.current === 'page') return;\n const tabbables = getTabbableElements(surface);\n if (event.shiftKey) {\n if (active === surface || active === tabbables[0]) {\n focusInstead(event, getPrevious(anchor, surface));\n }\n return;\n }\n if (tabbables.length > 0 && active !== tabbables[tabbables.length - 1]) return;\n focusInstead(event, getTabbableAfter(anchor, surface));\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../../lib/cn.mjs";
|
|
3
|
+
import { getGlobalRegistry as t } from "../../lib/globalRegistry.mjs";
|
|
4
|
+
import { useEventCallback as n } from "../../hooks/useEventCallback.mjs";
|
|
5
|
+
import { focusElement as r, getLastTabbable as i, getTabbableElements as a } from "../../lib/focus.mjs";
|
|
6
|
+
import * as o from "react";
|
|
7
|
+
import { jsx as s } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/overlays/Popover.shared.tsx
|
|
9
|
+
var c = {
|
|
10
|
+
top: "border-b border-r",
|
|
11
|
+
bottom: "border-t border-l",
|
|
12
|
+
left: "border-t border-r",
|
|
13
|
+
right: "border-b border-l"
|
|
14
|
+
}, l = ({ side: t, className: n, ref: r, ...i }) => /* @__PURE__ */ s("div", {
|
|
15
|
+
ref: r,
|
|
16
|
+
"aria-hidden": "true",
|
|
17
|
+
...i,
|
|
18
|
+
className: e("size-2 rotate-45 border-inherit bg-inherit", c[t], n)
|
|
19
|
+
});
|
|
20
|
+
l.displayName = "PopoverBeak";
|
|
21
|
+
function u(e, t, n = a(e.ownerDocument.body)) {
|
|
22
|
+
let r = e.closest("[data-wave-portal]");
|
|
23
|
+
return n.filter((e) => !t.contains(e) && e.closest("[data-wave-portal]") === r);
|
|
24
|
+
}
|
|
25
|
+
function d(e, t, n) {
|
|
26
|
+
return u(e, t, n).find((t) => !e.contains(t) && !!(e.compareDocumentPosition(t) & Node.DOCUMENT_POSITION_FOLLOWING)) ?? null;
|
|
27
|
+
}
|
|
28
|
+
function f(e, t, n) {
|
|
29
|
+
let r = u(e, t, n).filter((t) => e.contains(t) || !!(e.compareDocumentPosition(t) & Node.DOCUMENT_POSITION_PRECEDING));
|
|
30
|
+
return r[r.length - 1] ?? null;
|
|
31
|
+
}
|
|
32
|
+
function p(e, t, n, r) {
|
|
33
|
+
return !e || r.includes(e) ? e : f(t, n, r);
|
|
34
|
+
}
|
|
35
|
+
function m(e, t) {
|
|
36
|
+
t && (e.preventDefault(), t.focus());
|
|
37
|
+
}
|
|
38
|
+
function h(e, t) {
|
|
39
|
+
return !t || t === e.body || t === e.documentElement;
|
|
40
|
+
}
|
|
41
|
+
function g(e) {
|
|
42
|
+
let t = e.ownerDocument, n = t.defaultView, { style: r } = e, i = r.getPropertyValue("visibility"), a = r.getPropertyPriority("visibility");
|
|
43
|
+
r.setProperty("visibility", "hidden", "important");
|
|
44
|
+
let o, s = () => {
|
|
45
|
+
t.removeEventListener("focusout", s, !0), o !== void 0 && n?.cancelAnimationFrame(o), o = void 0, r.getPropertyValue("visibility") === "hidden" && r.getPropertyPriority("visibility") === "important" && (i ? r.setProperty("visibility", i, a) : r.removeProperty("visibility"));
|
|
46
|
+
};
|
|
47
|
+
t.addEventListener("focusout", s, !0), n && (o = n.requestAnimationFrame(s));
|
|
48
|
+
}
|
|
49
|
+
var _ = {
|
|
50
|
+
users: 0,
|
|
51
|
+
pressed: !1,
|
|
52
|
+
refocus: null,
|
|
53
|
+
lastFocused: null,
|
|
54
|
+
windowFocused: !1,
|
|
55
|
+
epoch: 0,
|
|
56
|
+
uninstall: null
|
|
57
|
+
};
|
|
58
|
+
function v(e, t) {
|
|
59
|
+
let n = _.lastFocused;
|
|
60
|
+
if (!n) return !1;
|
|
61
|
+
let r = n.element.deref();
|
|
62
|
+
return r?.isConnected ? !!(e.compareDocumentPosition(r) & Node.DOCUMENT_POSITION_FOLLOWING) : n.surface?.deref() === t;
|
|
63
|
+
}
|
|
64
|
+
function y() {
|
|
65
|
+
return t("orderedSurfaces", () => /* @__PURE__ */ new Set());
|
|
66
|
+
}
|
|
67
|
+
function b() {
|
|
68
|
+
if (typeof document > "u") return () => {};
|
|
69
|
+
if (_.users += 1, !_.uninstall) {
|
|
70
|
+
let e = document, t = e.defaultView, n = () => {
|
|
71
|
+
_.epoch += 1, _.pressed = !0, _.windowFocused = !1;
|
|
72
|
+
}, r = () => {
|
|
73
|
+
_.epoch += 1, _.windowFocused = !1;
|
|
74
|
+
}, i = () => {
|
|
75
|
+
_.epoch += 1, _.pressed = !1, _.windowFocused = !1;
|
|
76
|
+
let t = e.activeElement;
|
|
77
|
+
_.refocus = !t || h(e, t) ? null : new WeakRef(t);
|
|
78
|
+
}, a = () => {
|
|
79
|
+
_.epoch += 1, _.windowFocused = !0;
|
|
80
|
+
}, o = (e) => {
|
|
81
|
+
let t = e.target, n = t && [...y()].find((e) => e.contains(t));
|
|
82
|
+
_.lastFocused = t && {
|
|
83
|
+
element: new WeakRef(t),
|
|
84
|
+
surface: n ? new WeakRef(n) : null
|
|
85
|
+
};
|
|
86
|
+
}, s = () => {
|
|
87
|
+
_.epoch += 1, _.refocus = null, _.windowFocused = !1;
|
|
88
|
+
};
|
|
89
|
+
e.addEventListener("pointerdown", n, !0), e.addEventListener("mousedown", n, !0), e.addEventListener("keydown", r, !0), e.addEventListener("keyup", r, !0), e.addEventListener("focusin", o, !0), e.addEventListener("focusin", s), t?.addEventListener("blur", i), t?.addEventListener("focus", a), _.uninstall = () => {
|
|
90
|
+
e.removeEventListener("pointerdown", n, !0), e.removeEventListener("mousedown", n, !0), e.removeEventListener("keydown", r, !0), e.removeEventListener("keyup", r, !0), e.removeEventListener("focusin", o, !0), e.removeEventListener("focusin", s), t?.removeEventListener("blur", i), t?.removeEventListener("focus", a), _.pressed = !1, _.refocus = null, _.lastFocused = null, _.windowFocused = !1;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
let e = !0;
|
|
94
|
+
return () => {
|
|
95
|
+
e && (e = !1, _.users = Math.max(0, _.users - 1), !(_.users > 0) && (_.uninstall?.(), _.uninstall = null));
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function x({ enabled: e, surface: t, anchorRef: s, getPreviousStop: c }) {
|
|
99
|
+
let l = n(c), u = o.useRef("anchor"), f = o.useRef(null), x = n((e) => {
|
|
100
|
+
f.current = null;
|
|
101
|
+
let n = s.current;
|
|
102
|
+
if (e.key !== "Tab" || e.defaultPrevented || !n || !t) return;
|
|
103
|
+
let r = t.ownerDocument, i = r.activeElement;
|
|
104
|
+
if (i && t.contains(i)) return;
|
|
105
|
+
let o = a(r.body), c = o.filter((e) => t.contains(e)), u = c[0], y = c[c.length - 1];
|
|
106
|
+
if (!u || !y) return;
|
|
107
|
+
if (!i || h(r, i)) {
|
|
108
|
+
e.shiftKey && !_.pressed && o[o.length - 1] === y && !v(y, t) && (f.current = {
|
|
109
|
+
element: y,
|
|
110
|
+
from: "far-end",
|
|
111
|
+
epoch: _.epoch
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
let b = l(n, t, o);
|
|
116
|
+
if (e.shiftKey) {
|
|
117
|
+
b && i === d(n, t, o) && m(e, y);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
let x = p(b, n, t, o);
|
|
121
|
+
if (i === b || i === x) {
|
|
122
|
+
m(e, u);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
let S = o.indexOf(i);
|
|
126
|
+
S !== -1 && o[S + 1] === u && (f.current = {
|
|
127
|
+
element: u,
|
|
128
|
+
from: "page",
|
|
129
|
+
epoch: _.epoch
|
|
130
|
+
}, x && g(t));
|
|
131
|
+
});
|
|
132
|
+
return o.useEffect(() => b(), []), o.useEffect(() => {
|
|
133
|
+
if (!e || !t) return;
|
|
134
|
+
let n = t.ownerDocument, o = n.defaultView;
|
|
135
|
+
u.current = "anchor";
|
|
136
|
+
let c = null, d = (e) => {
|
|
137
|
+
c = null;
|
|
138
|
+
let r = f.current;
|
|
139
|
+
f.current = null;
|
|
140
|
+
let o = e.relatedTarget;
|
|
141
|
+
if (o && t.contains(o)) return;
|
|
142
|
+
let d = e.target;
|
|
143
|
+
if (!o && d === _.refocus?.deref()) return;
|
|
144
|
+
let m = r && r.epoch === _.epoch && r.element === d ? r.from : null;
|
|
145
|
+
if (u.current = m === "page" ? "page" : "anchor", m === "page" || !h(n, o) || _.pressed || m !== "far-end" && !_.windowFocused) return;
|
|
146
|
+
let g = s.current;
|
|
147
|
+
if (!g || d !== i(t)) return;
|
|
148
|
+
let v = a(n.body), b = [...y()], x = v.filter((e) => !b.some((t) => t.contains(e))), S = x[x.length - 1], C = l(g, t, v);
|
|
149
|
+
C && S && S !== p(C, g, t, v) && (c = {
|
|
150
|
+
event: e,
|
|
151
|
+
pageEnd: S
|
|
152
|
+
});
|
|
153
|
+
}, m = (e) => {
|
|
154
|
+
let t = c;
|
|
155
|
+
c = null, t?.event === e && n.activeElement === e.target && (r(t.pageEnd) || (u.current = "page"));
|
|
156
|
+
}, g = y();
|
|
157
|
+
return g.add(t), t.addEventListener("focusin", d), o?.addEventListener("focusin", m), n.addEventListener("keydown", x), () => {
|
|
158
|
+
g.delete(t), t.removeEventListener("focusin", d), o?.removeEventListener("focusin", m), n.removeEventListener("keydown", x);
|
|
159
|
+
};
|
|
160
|
+
}, [
|
|
161
|
+
e,
|
|
162
|
+
t,
|
|
163
|
+
s,
|
|
164
|
+
l,
|
|
165
|
+
x
|
|
166
|
+
]), n((n) => {
|
|
167
|
+
let r = s.current;
|
|
168
|
+
if (n.key !== "Tab" || n.defaultPrevented || !e || !t || !r) return;
|
|
169
|
+
let i = t.ownerDocument.activeElement;
|
|
170
|
+
if (!i || !t.contains(i) || u.current === "page") return;
|
|
171
|
+
let o = a(t);
|
|
172
|
+
if (n.shiftKey) {
|
|
173
|
+
(i === t || i === o[0]) && m(n, l(r, t));
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
o.length > 0 && i !== o[o.length - 1] || m(n, d(r, t));
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
export { l as PopoverBeak, d as getTabbableAfter, f as getTabbableThrough, x as usePopoverTabOrder };
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=Popover.shared.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Popover.shared.mjs","names":["React","BEAK_BORDER","PopoverBeak","rest","cn","side","className","getScopedTabbables","getTabbableElements","anchor","scope","order","exclude","el","getTabbableAfter","getTabbableThrough","through","getEntryStop","previous","surface","focusInstead","target","event","isNothing","node","doc","hideForNativeTab","win","value","style","priority","frame","show","focusOrigin","startsAfter","last","start","getOrderedSurfaces","getGlobalRegistry","retainFocusOrigin","onPress","onKey","onWindowBlur","active","onWindowFocus","onFocusCapture","open","onFocusIn","retained","usePopoverTabOrder","getPrevious","useEventCallback","getPreviousStop","entryRef","pendingRef","onDocumentKeyDown","anchorRef","inside","first","entry","index","enabled","redirect","pending","from","entered","expected","getLastTabbable","surfaces","outside","pageEnd","onWindowFocusIn","focusElement","orderedSurfaces","tabbables"],"sources":["../../../src/components/overlays/Popover.shared.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { focusElement, getLastTabbable, getTabbableElements } from '../../lib/focus';\nimport { getGlobalRegistry } from '../../lib/globalRegistry';\nimport type { UsePopupPositionResult } from '../../hooks/usePopupPosition';\nimport { useEventCallback } from '../../hooks/useEventCallback';\n\n// Parts shared by the anchored popups of this folder: Popover.Content and TeachingPopover with a\n// `target`. Internal: not exported from the barrels.\n\n/** Final physical side of a positioned surface (the `side` result of `usePopupPosition`). */\nexport type PopoverPhysicalSide = UsePopupPositionResult['side'];\n\n/** Borders of the rotated square beak that face the anchor, per final physical side. */\nconst BEAK_BORDER: Record<PopoverPhysicalSide, string> = {\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n top: 'border-b border-r',\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n bottom: 'border-t border-l',\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n left: 'border-t border-r',\n // wave-allow-physical: the beak follows the physical side resolved by the positioning\n right: 'border-b border-l',\n};\n\n/** Properties for the internal PopoverBeak. */\nexport interface PopoverBeakProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Final physical side of the surface; the beak is drawn on the edge that faces the anchor. */\n side: PopoverPhysicalSide;\n /** Ref to the beak: pass it to `usePopupPosition` as `arrowRef`. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * The beak of an anchored surface: a rotated square, hidden from assistive technology, that\n * inherits the surface's background and border colors (so a `className` that changes them\n * restyles the beak too). Position it with the `arrowStyles` of `usePopupPosition`; its size\n * matches the `--wave-popup-arrow-size` the arrow offset is computed from.\n */\nexport const PopoverBeak = ({ side, className, ref, ...rest }: PopoverBeakProps) => (\n <div\n ref={ref}\n aria-hidden=\"true\"\n {...rest}\n className={cn('size-2 rotate-45 border-inherit bg-inherit', BEAK_BORDER[side], className)}\n />\n);\nPopoverBeak.displayName = 'PopoverBeak';\n\n/**\n * The tabbable elements of the anchor's document, in sequential focus order, that are in the same\n * portal as the anchor (or, like it, in the page) and outside `exclude`. `order` is the document's\n * tabbable elements when the caller has them already.\n */\nfunction getScopedTabbables(\n anchor: HTMLElement,\n exclude: HTMLElement,\n order: readonly HTMLElement[] = getTabbableElements(anchor.ownerDocument.body),\n): HTMLElement[] {\n const scope = anchor.closest('[data-wave-portal]');\n return order.filter((el) => !exclude.contains(el) && el.closest('[data-wave-portal]') === scope);\n}\n\n/**\n * The first tabbable element after `anchor` in document order, not inside it, in the same portal\n * as the anchor and outside `exclude`: the tab stop after a surface placed right after the anchor.\n * Pass the document's tabbable elements as `order` when you have them, to spare a second scan.\n */\nexport function getTabbableAfter(\n anchor: HTMLElement,\n exclude: HTMLElement,\n order?: readonly HTMLElement[],\n): HTMLElement | null {\n return (\n getScopedTabbables(anchor, exclude, order).find(\n (el) =>\n !anchor.contains(el) &&\n !!(anchor.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING),\n ) ?? null\n );\n}\n\n/**\n * The last tabbable element that is `anchor`, inside it or before it in document order, in the\n * same portal as the anchor and outside `exclude`: the tab stop before a surface placed right\n * after the anchor. Pass the document's tabbable elements as `order` when you have them.\n */\nexport function getTabbableThrough(\n anchor: HTMLElement,\n exclude: HTMLElement,\n order?: readonly HTMLElement[],\n): HTMLElement | null {\n const through = getScopedTabbables(anchor, exclude, order).filter(\n (el) =>\n anchor.contains(el) ||\n !!(anchor.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING),\n );\n return through[through.length - 1] ?? null;\n}\n\n/**\n * The tab stop that a surface placed right after `anchor` follows, given its previous stop: that\n * stop, or the tab stop at or before the anchor when the previous stop is outside the tab order\n * (a trigger with `tabIndex={-1}`). `null` when nothing in the tab order comes before the place.\n */\nfunction getEntryStop(\n previous: HTMLElement | null,\n anchor: HTMLElement,\n surface: HTMLElement,\n order: readonly HTMLElement[],\n): HTMLElement | null {\n if (!previous || order.includes(previous)) return previous;\n return getTabbableThrough(anchor, surface, order);\n}\n\nfunction focusInstead(event: { preventDefault(): void }, target: HTMLElement | null): void {\n if (!target) return;\n event.preventDefault();\n target.focus();\n}\n\nfunction isNothing(doc: Document, node: EventTarget | null): boolean {\n return !node || node === doc.body || node === doc.documentElement;\n}\n\n/**\n * Hides `surface` (`visibility: hidden`) for the native Tab in progress, so the browser moves past\n * its elements. It is shown again as soon as focus moves (the `focusout` of that Tab, before the\n * next element takes focus), or before the next frame when the Tab moves nothing.\n */\nfunction hideForNativeTab(surface: HTMLElement): void {\n const doc = surface.ownerDocument;\n const win = doc.defaultView;\n const { style } = surface;\n const value = style.getPropertyValue('visibility');\n const priority = style.getPropertyPriority('visibility');\n style.setProperty('visibility', 'hidden', 'important');\n let frame: number | undefined;\n const show = () => {\n doc.removeEventListener('focusout', show, true);\n if (frame !== undefined) win?.cancelAnimationFrame(frame);\n frame = undefined;\n // Left alone when something else changed it meanwhile.\n const ours =\n style.getPropertyValue('visibility') === 'hidden' &&\n style.getPropertyPriority('visibility') === 'important';\n if (!ours) return;\n if (value) style.setProperty('visibility', value, priority);\n else style.removeProperty('visibility');\n };\n doc.addEventListener('focusout', show, true);\n if (win) frame = win.requestAnimationFrame(show);\n}\n\n/**\n * What the document knows about focus that arrives from nothing (the body): whether it can come\n * from the browser's own controls, and where the browser starts Tab and Shift+Tab from nothing.\n * The listeners are installed while a {@link usePopoverTabOrder} is mounted, open or not, so the\n * press that opened a surface counts too. Elements are held through a `WeakRef`, so a removed\n * subtree is not kept alive while a popover is mounted: an element that is gone was removed.\n */\ninterface FocusOrigin {\n /** Mounted `usePopoverTabOrder` instances. */\n users: number;\n /**\n * A pointer press (`pointerdown`/`mousedown`) came since the window last lost focus. The user is\n * then in the page, not arriving from the browser's controls, which the window must lose focus\n * to reach: a key press does not clear it.\n */\n pressed: boolean;\n /**\n * The element that had focus when the window lost it: the browser focuses it again, from\n * nothing, when the window gets focus back. Cleared by the next `focusin`.\n */\n refocus: WeakRef<Element> | null;\n /**\n * The element that took focus last, and the ordered surface ({@link getOrderedSurfaces}) that\n * contained it then. When focus has gone from it to nothing (it was removed, hidden or blurred),\n * the browser starts sequential navigation where it is, or where it was. Recorded in the capture\n * phase, so a handler that stops a `focusin` from propagating does not hide it.\n */\n lastFocused: {\n element: WeakRef<Element>;\n surface: WeakRef<HTMLElement> | null;\n } | null;\n /**\n * The window has just got focus back: no element took focus since, and no key or pointer press\n * reached the page. Sequential navigation from the browser's own controls gives the window focus\n * right before the element it reaches; focus that arrives from nothing without it comes from the\n * page (a focus restore after the focused element was removed, a script).\n */\n windowFocused: boolean;\n /**\n * Counts the events that end a key press's focus change: key presses and releases, pointer\n * presses, `focusin` and the window's blur and focus. An entry the `keydown` of a Tab expects\n * applies only to the `focusin` of that same Tab.\n */\n epoch: number;\n /** Removes the listeners; `null` while none are installed. */\n uninstall: (() => void) | null;\n}\n\n/**\n * One per copy of the library, not in the global registry: every field is derived from document\n * and window events, and only this copy's hooks read it, each of which keeps this copy's\n * listeners installed from its mount on. A second copy (ESM and CJS side by side) installs its own\n * listeners and derives the same state; `epoch` is compared only within the copy that set it.\n */\nconst focusOrigin: FocusOrigin = {\n users: 0,\n pressed: false,\n refocus: null,\n lastFocused: null,\n windowFocused: false,\n epoch: 0,\n uninstall: null,\n};\n\n/**\n * Whether sequential navigation from nothing starts after `el`, the last tabbable element of\n * `surface`: at the element that took focus last, when that comes after `el` in the document or\n * was removed from `surface` (it may have been anywhere in it, after `el` too). An element removed\n * elsewhere does not count: from a place after the surface (a dismissed toast in a later portal),\n * Shift+Tab lands on `el` just as from the document's end, and from a place before it, it does not\n * land on `el`.\n */\nfunction startsAfter(el: HTMLElement, surface: HTMLElement): boolean {\n const last = focusOrigin.lastFocused;\n if (!last) return false;\n const start = last.element.deref();\n if (start?.isConnected) {\n return !!(el.compareDocumentPosition(start) & Node.DOCUMENT_POSITION_FOLLOWING);\n }\n return last.surface?.deref() === surface;\n}\n\n/**\n * The surfaces whose keyboard order a {@link usePopoverTabOrder} manages right now. Their content\n * takes its place after its anchor, not at the end of the document where its portal is, so none\n * of it is \"the last element of the page\". Kept in `getGlobalRegistry('orderedSurfaces')`, so an\n * app that loads both the ESM and the CJS copy of the library excludes the surfaces of both.\n */\nfunction getOrderedSurfaces(): Set<HTMLElement> {\n return getGlobalRegistry('orderedSurfaces', () => new Set<HTMLElement>());\n}\n\nfunction retainFocusOrigin(): () => void {\n if (typeof document === 'undefined') return () => {};\n focusOrigin.users += 1;\n if (!focusOrigin.uninstall) {\n const doc = document;\n const win = doc.defaultView;\n const onPress = () => {\n focusOrigin.epoch += 1;\n focusOrigin.pressed = true;\n focusOrigin.windowFocused = false;\n };\n const onKey = () => {\n focusOrigin.epoch += 1;\n focusOrigin.windowFocused = false;\n };\n // Not capture listeners: they hear only the window's own blur and focus (an element's do not\n // bubble).\n const onWindowBlur = () => {\n focusOrigin.epoch += 1;\n focusOrigin.pressed = false;\n focusOrigin.windowFocused = false;\n const active = doc.activeElement;\n focusOrigin.refocus = !active || isNothing(doc, active) ? null : new WeakRef(active);\n };\n const onWindowFocus = () => {\n focusOrigin.epoch += 1;\n focusOrigin.windowFocused = true;\n };\n // Capture, like the presses and keys, so a handler that stops a `focusin` from propagating\n // does not hide where focus went. Only the `keydown` of a later Tab reads it: recording it\n // before the surfaces' own `focusin` listeners run changes nothing for them.\n const onFocusCapture = (event: FocusEvent) => {\n const target = event.target as Element | null;\n const surface = target && [...getOrderedSurfaces()].find((open) => open.contains(target));\n focusOrigin.lastFocused = target && {\n element: new WeakRef(target),\n surface: surface ? new WeakRef(surface) : null,\n };\n };\n // Bubbling to the document, after the surfaces' own `focusin` listeners have read the state.\n const onFocusIn = () => {\n focusOrigin.epoch += 1;\n focusOrigin.refocus = null;\n focusOrigin.windowFocused = false;\n };\n // Capture: a handler that stops a press or a key from propagating must not hide it.\n doc.addEventListener('pointerdown', onPress, true);\n doc.addEventListener('mousedown', onPress, true);\n doc.addEventListener('keydown', onKey, true);\n doc.addEventListener('keyup', onKey, true);\n doc.addEventListener('focusin', onFocusCapture, true);\n doc.addEventListener('focusin', onFocusIn);\n win?.addEventListener('blur', onWindowBlur);\n win?.addEventListener('focus', onWindowFocus);\n focusOrigin.uninstall = () => {\n doc.removeEventListener('pointerdown', onPress, true);\n doc.removeEventListener('mousedown', onPress, true);\n doc.removeEventListener('keydown', onKey, true);\n doc.removeEventListener('keyup', onKey, true);\n doc.removeEventListener('focusin', onFocusCapture, true);\n doc.removeEventListener('focusin', onFocusIn);\n win?.removeEventListener('blur', onWindowBlur);\n win?.removeEventListener('focus', onWindowFocus);\n focusOrigin.pressed = false;\n focusOrigin.refocus = null;\n focusOrigin.lastFocused = null;\n focusOrigin.windowFocused = false;\n };\n }\n let retained = true;\n return () => {\n if (!retained) return;\n retained = false;\n focusOrigin.users = Math.max(0, focusOrigin.users - 1);\n if (focusOrigin.users > 0) return;\n focusOrigin.uninstall?.();\n focusOrigin.uninstall = null;\n };\n}\n\n/** Options of {@link usePopoverTabOrder}. */\nexport interface PopoverTabOrderOptions {\n /** Whether the surface is shown next to its anchor; the listeners exist only while `true`. */\n enabled: boolean;\n /** The portaled surface, held in state through its callback ref. */\n surface: HTMLElement | null;\n /** The anchor: the surface takes its place in the keyboard order right after it. */\n anchorRef: React.RefObject<HTMLElement | null>;\n /**\n * The element before the surface's place: Tab from it enters the surface, and Shift+Tab from\n * the surface's first element returns to it. When it is outside the tab order (a trigger with\n * `tabIndex={-1}`), Tab from the tab stop at or before the anchor enters the surface too; `null`\n * when nothing comes before the place. `order`, when given, is the document's tabbable elements.\n */\n getPreviousStop: (\n anchor: HTMLElement,\n surface: HTMLElement,\n order?: readonly HTMLElement[],\n ) => HTMLElement | null;\n}\n\n/**\n * Keyboard order of a surface portaled to the end of the document, as if it were rendered right\n * after its anchor (the order of 0.4's inline content). Returns the surface's `onKeyDown`; while\n * `enabled`, a document `keydown` listener and `focusin` listeners on the surface and the window\n * do the rest. While mounted, shared document listeners record pointer presses, key presses, the\n * element that took focus last and the window's blur and focus.\n *\n * - Tab from the previous stop enters the surface at its first tabbable element (so does Tab\n * from the tab stop at or before the anchor when the previous stop is outside the tab order),\n * and Shift+Tab from the tab stop after the anchor enters it at its last one.\n * - Tab past the surface's last element continues after the anchor; Shift+Tab from its first\n * element (or from the surface itself) returns to the previous stop.\n * - The surface is not visited a second time where its portal is. Tab from the element before\n * the portal moves past the surface (it is hidden for that one Tab), to what follows it or out\n * of the page. Shift+Tab from the browser's own controls (the window gets focus back just before\n * it), or from nothing without a pointer press, lands on the surface's last element as the\n * document's last one: focus goes to the last element of the page instead (outside every open\n * surface: another open popover's content has its own place after its anchor), unless that is\n * the tab stop before the surface's place (the surface then ends the order). Focus moves there\n * once the entry's `focusin` has reached the window, so the entered element's focus handlers\n * run before its blur handlers; a handler that stops that `focusin` from propagating (an\n * `onFocus` in the content that calls `stopPropagation()`) leaves focus on the surface's last\n * element, as an entry at its place after the anchor, with no trap and no Tab cycle. Shift+Tab\n * from nothing does not start at the document's end when the element that had focus comes after\n * the surface's last element or was removed from the surface (a control of the surface that hid\n * or removed itself): the browser starts where it is, or was. An element removed elsewhere (a\n * dismissed toast portaled after the surface) keeps the rule: from its place, too, Shift+Tab\n * lands on the surface's last element. A lap in either direction visits every element once, and\n * there is no Tab cycle.\n * - With no tab stop before its place (nothing in the tab order at or before the anchor), Tab\n * reaches the surface where its portal is, from the element before the portal, and it follows\n * the document order from there. When the previous stop is missing too, Shift+Tab reaches it\n * there as well: its first element leads to the element before the portal, so neither Shift+Tab\n * from the tab stop after the anchor nor from outside the page is moved to its place.\n * - Every other entry keeps the place after the anchor: a click, Shift+Tab from a pressed point,\n * focus restored from nothing (a layer opened from the surface's last element closed), a\n * script, focus that returns to an element as the window gets focus back, and focus the content\n * takes as it mounts (`autoFocus`, before the listeners exist).\n * - Content that the Tab from the page still reaches (it shows itself again before the browser\n * moves focus) follows the document order from there, so Tab past it leaves the page rather\n * than jumping back to the anchor.\n *\n * Every Tab outside the surface costs one scan of the document's tabbable elements. The listeners\n * skip events whose default is already prevented; React handlers (a trigger's own `onKeyDown`,\n * the returned one) run before them and before a dialog's focus trap.\n */\nexport function usePopoverTabOrder({\n enabled,\n surface,\n anchorRef,\n getPreviousStop,\n}: PopoverTabOrderOptions): React.KeyboardEventHandler<HTMLElement> {\n const getPrevious = useEventCallback(getPreviousStop);\n /** How focus last entered the surface: at its place after the anchor, or at the portal's. */\n const entryRef = React.useRef<'anchor' | 'page'>('anchor');\n /**\n * Where the Tab being pressed enters the surface natively: at `element`, from the page (had it\n * not moved past the surface) or, Shift+Tab from nothing, at the document's far end. Valid in\n * the `focusin` of that Tab only (same `epoch`).\n */\n const pendingRef = React.useRef<{\n element: HTMLElement;\n from: 'page' | 'far-end';\n epoch: number;\n } | null>(null);\n\n const onDocumentKeyDown = useEventCallback((event: KeyboardEvent) => {\n pendingRef.current = null;\n const anchor = anchorRef.current;\n if (event.key !== 'Tab' || event.defaultPrevented || !anchor || !surface) return;\n const doc = surface.ownerDocument;\n const active = doc.activeElement as HTMLElement | null;\n if (active && surface.contains(active)) return;\n // One scan of the document; everything below is derived from it.\n const order = getTabbableElements(doc.body);\n const inside = order.filter((el) => surface.contains(el));\n const first = inside[0];\n const last = inside[inside.length - 1];\n if (!first || !last) return;\n if (!active || isNothing(doc, active)) {\n // With no pointer press to start from, Shift+Tab from nothing reaches the document's last\n // element, unless the browser starts after it: where the element that had focus is, or was\n // (a control of the surface that removed or hid itself).\n if (\n event.shiftKey &&\n !focusOrigin.pressed &&\n order[order.length - 1] === last &&\n !startsAfter(last, surface)\n ) {\n pendingRef.current = { element: last, from: 'far-end', epoch: focusOrigin.epoch };\n }\n return;\n }\n const previous = getPrevious(anchor, surface, order);\n if (event.shiftKey) {\n // Without a previous stop, Shift+Tab from the surface's first element follows the document\n // order: entering the surface here would form a cycle.\n if (previous && active === getTabbableAfter(anchor, surface, order)) {\n focusInstead(event, last);\n }\n return;\n }\n const entry = getEntryStop(previous, anchor, surface, order);\n if (active === previous || active === entry) {\n focusInstead(event, first);\n return;\n }\n const index = order.indexOf(active);\n if (index === -1 || order[index + 1] !== first) return;\n pendingRef.current = { element: first, from: 'page', epoch: focusOrigin.epoch };\n // The browser would enter the surface where its portal is. When a tab stop comes before its\n // place, the surface was visited after the anchor: move past it. Otherwise this is its entry.\n if (entry) hideForNativeTab(surface);\n });\n\n // Installed while mounted, not only while enabled: the press that opens the surface counts.\n React.useEffect(() => retainFocusOrigin(), []);\n\n React.useEffect(() => {\n if (!enabled || !surface) return;\n const doc = surface.ownerDocument;\n const win = doc.defaultView;\n // A new surface, or one shown again: focus it took as it mounted (before this listener) was\n // not a native entry from the page, and an earlier entry no longer applies.\n entryRef.current = 'anchor';\n /**\n * An entry that goes on to the last element of the page. Focus moves there once the entry's\n * `focusin` has reached the window, after React (which listens where the portal is, above the\n * surface) has handled it: the entered element's focus handlers run before its blur handlers,\n * so a Tooltip on it does not stay open. Not in a microtask: a browser runs microtasks between\n * the listeners of its own events.\n */\n let redirect: { event: FocusEvent; pageEnd: HTMLElement } | null = null;\n const onFocusIn = (event: FocusEvent) => {\n redirect = null;\n const pending = pendingRef.current;\n pendingRef.current = null;\n const from = event.relatedTarget as Node | null;\n if (from && surface.contains(from)) return;\n const entered = event.target;\n // The window got focus back: focus returns to where it was, in the order it had there.\n if (!from && entered === focusOrigin.refocus?.deref()) return;\n const expected =\n pending && pending.epoch === focusOrigin.epoch && pending.element === entered\n ? pending.from\n : null;\n // The Tab from the page reached the surface after all: follow the document order from here,\n // so Tab past it leaves the page instead of forming a cycle through the anchor.\n entryRef.current = expected === 'page' ? 'page' : 'anchor';\n if (expected === 'page' || !isNothing(doc, from) || focusOrigin.pressed) return;\n // Shift+Tab from the browser's own controls, or from nothing: the document's last element.\n if (expected !== 'far-end' && !focusOrigin.windowFocused) return;\n const anchor = anchorRef.current;\n if (!anchor || entered !== getLastTabbable(surface)) return;\n const order = getTabbableElements(doc.body);\n const surfaces = [...getOrderedSurfaces()];\n const outside = order.filter((el) => !surfaces.some((open) => open.contains(el)));\n const pageEnd = outside[outside.length - 1];\n const previous = getPrevious(anchor, surface, order);\n // The surface ends the order when the tab stop before its place is the page's last element.\n // Without a previous stop it keeps the place of its portal, as Shift+Tab from it does.\n if (!previous || !pageEnd || pageEnd === getEntryStop(previous, anchor, surface, order)) {\n return;\n }\n redirect = { event, pageEnd };\n };\n const onWindowFocusIn = (event: FocusEvent) => {\n const pending = redirect;\n redirect = null;\n // Left alone when a handler of the entry has moved focus already.\n if (pending?.event !== event || doc.activeElement !== event.target) return;\n if (!focusElement(pending.pageEnd)) entryRef.current = 'page';\n };\n const orderedSurfaces = getOrderedSurfaces();\n orderedSurfaces.add(surface);\n surface.addEventListener('focusin', onFocusIn);\n win?.addEventListener('focusin', onWindowFocusIn);\n doc.addEventListener('keydown', onDocumentKeyDown);\n return () => {\n orderedSurfaces.delete(surface);\n surface.removeEventListener('focusin', onFocusIn);\n win?.removeEventListener('focusin', onWindowFocusIn);\n doc.removeEventListener('keydown', onDocumentKeyDown);\n };\n }, [enabled, surface, anchorRef, getPrevious, onDocumentKeyDown]);\n\n return useEventCallback((event: React.KeyboardEvent<HTMLElement>) => {\n const anchor = anchorRef.current;\n if (event.key !== 'Tab' || event.defaultPrevented || !enabled || !surface || !anchor) return;\n const active = surface.ownerDocument.activeElement;\n // Events from nested portaled layers bubble here through React: only handle our own content.\n if (!active || !surface.contains(active) || entryRef.current === 'page') return;\n const tabbables = getTabbableElements(surface);\n if (event.shiftKey) {\n if (active === surface || active === tabbables[0]) {\n focusInstead(event, getPrevious(anchor, surface));\n }\n return;\n }\n if (tabbables.length > 0 && active !== tabbables[tabbables.length - 1]) return;\n focusInstead(event, getTabbableAfter(anchor, surface));\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),ee=require("../../lib/composeEventHandlers.cjs"),r=require("../../hooks/useControllable.cjs"),te=require("../../hooks/useId.cjs"),ne=require("../../hooks/useMergedRefs.cjs"),i=require("../../lib/aria.cjs"),re=require("../../hooks/useAnnounce.cjs"),ie=require("../../hooks/useDismiss.cjs"),ae=require("../portal/Portal.cjs"),a=require("../../lib/styles.cjs"),o=require("../button/Button.cjs"),s=require("../../lib/icons.cjs"),oe=require("../../hooks/usePopupPosition.cjs"),c=require("../../hooks/useRestoreFocus.cjs"),l=require("./Popover.shared.cjs");let u=require("react");u=e.__toESM(u,1);let d=require("react/jsx-runtime");var se=`Back`,ce=`Next`,le=`Done`,ue=(e,t)=>`step ${e+1} of ${t}`;function f(e){return`current`in e}function p(e){return e!=null&&!f(e)}function m(e){return e?f(e)?e.current:e:null}function de(e,t){return Number.isFinite(e)?Math.min(Math.max(Math.trunc(e),0),t-1):0}var h=({steps:e,activeStep:h,defaultActiveStep:fe,currentStep:pe,defaultCurrentStep:me,onStepChange:he,onDismiss:g,open:_,defaultOpen:v,onOpenChange:y,closeLabel:ge=`Close`,labels:b,target:x,side:_e=`bottom`,align:ve=`center`,className:ye,style:S,onKeyDown:be,ref:xe,...Se})=>{let Ce=n.resolveDeprecatedProp(`TeachingPopover`,h,pe,`currentStep`,`activeStep`),we=n.resolveDeprecatedProp(`TeachingPopover`,fe,me,`defaultCurrentStep`,`defaultActiveStep`)??0,[C,w]=r.useControllable(Ce,we,he),[T,E]=r.useControllable(_,v??!0,y),D=te.useId(`teaching-popover-title`),O=re.useAnnounce(),k=e.length,A=T&&k>0,j=k>0?de(C,k):0,M=k>0&&j!==C,N=k>0?e[j]:void 0,P=N?.title,F=j===0,I=j===k-1,L=x!==void 0,R=k>0?(b?.step??ue)(j,k):``,[z,Te]=u.useState(null),[B,V]=u.useState(()=>p(x)),H=x===null?!1:p(x)?!0:void 0;H!==void 0&&H!==B&&V(H);let U=u.useRef(null),W=u.useRef(null),G=u.useRef(x),K=u.useRef(B),q=u.useRef(null),{setReference:J,setFloating:Ee,floatingProps:Y,arrowStyles:De,side:Oe,isPositioned:ke}=oe.usePopupPosition({open:A&&L,side:_e,align:ve,offset:12,arrowRef:q}),Ae=x!=null&&(!f(x)||B),X=!L||Ae&&ke,Z=A&&X,je=ne.useMergedRefs(xe,U,Te,Ee);u.useLayoutEffect(()=>{G.current=x,K.current=B;let e=m(x);W.current=e,J(e),x!=null&&f(x)&&queueMicrotask(()=>{let e=m(G.current);e!==W.current&&(W.current=e,J(e));let t=e!==null;t!==K.current&&(K.current=t,V(t))})});let Q=()=>{E(!1),g?.()},{layerId:Me}=ie.useDismiss({open:Z,onDismiss:Q,refs:[U],anchorRef:W,kind:`popover`,outsidePress:!1});c.useRestoreFocus({enabled:Z,container:z,fallback:()=>W.current,onlyIfFocusInside:!0});let Ne=l.usePopoverTabOrder({enabled:Z&&L,surface:z,anchorRef:W,getPreviousStop:l.getTabbableThrough});u.useEffect(()=>{Z&&z&&z.focus({preventScroll:L})},[Z,z,L]);let $=u.useRef(j);if(u.useEffect(()=>{$.current!==j&&($.current=j,Z&&P!==void 0&&O(`${P}, ${R}`))},[j,Z,P,R,O]),u.useEffect(()=>{M&&n.warnOnce(`TeachingPopover:activeStep-range`,`TeachingPopover: activeStep ${C} is out of range for ${k} steps; showing step ${j+1}.`)},[M,C,k,j]),!A||!N)return null;let Pe=()=>w(j-1),Fe=()=>{I?Q():w(j+1)};return(0,d.jsx)(ae.Portal,{disabled:!L,layerId:Me,children:(0,d.jsxs)(`div`,{role:`dialog`,"aria-labelledby":D,tabIndex:-1,...Se,ref:je,onKeyDown:ee.composeEventHandlers(be,Ne),...L?{"data-side":Y[`data-side`],"data-align":Y[`data-align`],style:{...S,...Y.style,...X?void 0:{visibility:`hidden`}}}:{style:S},className:t.cn(`relative w-80 rounded-md border border-border bg-background p-5 text-foreground shadow-8`,a.focusRing,ye),children:[L&&(0,d.jsx)(l.PopoverBeak,{ref:q,side:Oe,style:De,"data-wave-teaching-popover-arrow":``}),(0,d.jsx)(o.Button,{appearance:`subtle`,size:`small`,icon:(0,d.jsx)(s.DismissIcon,{}),"aria-label":ge,className:`absolute end-3 top-3`,onClick:Q}),(0,d.jsxs)(`h3`,{id:D,className:`mb-2 pe-8 text-subtitle-1 font-semibold text-foreground`,children:[N.title,(0,d.jsx)(`span`,{className:`sr-only`,children:`, ${R}`})]}),(0,d.jsx)(`div`,{className:`mb-4 text-body-1 text-muted-foreground`,children:N.body}),(0,d.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,d.jsx)(`div`,{"aria-hidden":`true`,className:`flex items-center gap-1.5`,children:e.map((e,n)=>(0,d.jsx)(`span`,{"data-wave-teaching-popover-dot":``,"aria-current":n===j?`step`:void 0,className:t.cn(`h-1.5 rounded-full transition-[width,background-color] motion-reduce:transition-none`,n===j?t.cn(`w-4 bg-primary`,a.forcedColors.fill):`w-1.5 bg-stroke-accessible forced-colors:bg-[CanvasText] forced-colors:forced-color-adjust-none`)},n))}),(0,d.jsxs)(`div`,{className:`flex items-center gap-2`,children:[k>1&&(0,d.jsx)(o.Button,{...i.focusableDisabledProps(F),onClick:i.preventIfDisabled(F,Pe),children:b?.back??se}),(0,d.jsx)(o.Button,{appearance:`primary`,onClick:Fe,children:I?b?.done??le:b?.next??ce})]})]})]})})};h.displayName=`TeachingPopover`,exports.TeachingPopover=h;
|
|
2
|
+
//# sourceMappingURL=TeachingPopover.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TeachingPopover.cjs","names":["resolveDeprecatedProp","useControllable","useId","useAnnounce","React","usePopupPosition","useMergedRefs","useDismiss","usePopoverTabOrder","getTabbableThrough","Portal","composeEventHandlers","cn","focusRing","PopoverBeak","Button","DismissIcon","forcedColors","focusableDisabledProps","preventIfDisabled","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_useControllable","require_useId","require_useMergedRefs","require_aria","require_useAnnounce","require_useDismiss","require_Portal","require_styles","require_Button","require_icons","require_usePopupPosition","require_useRestoreFocus","require_Popover_shared","react","react_jsx_runtime","DEFAULT_BACK_LABEL","DEFAULT_NEXT_LABEL","DEFAULT_DONE_LABEL","defaultStepLabel","index","count","isRefObject","target","isElementTarget","resolveTarget","clampStep","step","TeachingPopover","activeStepProp","openProp","rest","controlledStep","currentStep","initialStep","defaultActiveStep","defaultCurrentStep","rawStep","setStep","onStepChange","open","setOpen","defaultOpen","onOpenChange","titleId","announce","steps","shown","outOfRange","stepTitle","isFirst","isLast","hasTarget","stepPosition","labels","surface","setSurface","targetResolved","setTargetResolved","elementAvailable","surfaceRef","targetRef","targetPropRef","availabilityRef","arrowRef","placedSide","targetAvailable","anchorReady","isPositioned","visible","elementRef","ref","setFloating","element","setReference","latest","available","dismiss","onDismiss","onSurfaceKeyDown","announcedIndexRef","handleBack","handleNext","onKeyDown","floatingProps","style","className","arrowStyles","closeLabel","i"],"sources":["../../../src/components/overlays/TeachingPopover.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { resolveDeprecatedProp, warnOnce } from '../../lib/dev';\nimport { focusableDisabledProps, preventIfDisabled } from '../../lib/aria';\nimport { DismissIcon } from '../../lib/icons';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport type { PopupAlign, PopupSide } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useId } from '../../hooks/useId';\nimport { useDismiss } from '../../hooks/useDismiss';\nimport { useRestoreFocus } from '../../hooks/useRestoreFocus';\nimport { usePopupPosition } from '../../hooks/usePopupPosition';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useAnnounce } from '../../hooks/useAnnounce';\nimport { Button } from '../button/Button';\nimport { Portal } from '../portal/Portal';\nimport { getTabbableThrough, PopoverBeak, usePopoverTabOrder } from './Popover.shared';\n\n/** Defines a single step in a teaching popover sequence. */\nexport interface TeachingPopoverStep {\n /** Title text for the step. */\n title: string;\n /** Body content for the step. */\n body: React.ReactNode;\n}\n\n/** The built-in text of a TeachingPopover, for localization (see `TeachingPopoverProps.labels`). */\nexport interface TeachingPopoverLabels {\n /** Text of the Back button.\n * @default 'Back'\n */\n back?: string;\n /** Text of the Next button.\n * @default 'Next'\n */\n next?: string;\n /** Text of the button that replaces Next on the last step.\n * @default 'Done'\n */\n done?: string;\n /**\n * The position of the step at `index` (zero-based, like `activeStep`) out of `count` steps. It\n * follows the step title, after a comma, in the visually hidden part of the heading and in the\n * announcement of a step change.\n * @default (index, count) => `step ${index + 1} of ${count}`\n */\n step?: (index: number, count: number) => string;\n}\n\nconst DEFAULT_BACK_LABEL = 'Back';\nconst DEFAULT_NEXT_LABEL = 'Next';\nconst DEFAULT_DONE_LABEL = 'Done';\nconst defaultStepLabel = (index: number, count: number) => `step ${index + 1} of ${count}`;\n\n/** Properties for the TeachingPopover component. */\nexport interface TeachingPopoverProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Steps to display in the teaching popover (a readonly array is accepted). */\n steps: readonly TeachingPopoverStep[];\n /**\n * Controlled index of the displayed step. Out-of-range values are clamped to the first or last\n * step (with a development warning).\n */\n activeStep?: number;\n /** Initial step index for uncontrolled usage.\n * @default 0\n */\n defaultActiveStep?: number;\n /** @deprecated Use `activeStep`. */\n currentStep?: number;\n /** @deprecated Use `defaultActiveStep`. */\n defaultCurrentStep?: number;\n /** Called with the requested step index when Next or Back is activated. */\n onStepChange?: (step: number) => void;\n /** Called when the popover is dismissed with Close, Done or Escape. */\n onDismiss?: () => void;\n /** Controlled visibility of the teaching popover. */\n open?: boolean;\n /** Initial visibility for uncontrolled usage.\n * @default true\n */\n defaultOpen?: boolean;\n /** Called with `false` when Close, Done or Escape dismisses the popover. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Accessible name of the built-in Close button (an icon-only button). Localize it with the\n * page's language.\n * @default 'Close'\n */\n closeLabel?: string;\n /**\n * Text of the Back, Next and Done buttons and the wording of the step position (“step 2 of 3”),\n * for localization. Unset members keep their English defaults.\n */\n labels?: TeachingPopoverLabels;\n /**\n * The element the popover points at (a ref or the element). When given, the popover is\n * rendered in a portal, positioned next to it with a beak, and flips or shifts to stay in view;\n * without it (`undefined`) the popover renders inline where it is placed (0.4 behaviour).\n * While the target is `null` or has not been positioned against yet (an element held in state\n * that is not set yet, a ref that is not attached), the popover stays hidden: it is not\n * shown, takes no focus, announces no step change and does not handle Escape until it can\n * point at the target. It hides the same way when the target goes away later and shows again\n * when a target returns.\n *\n * An element (for example one held in state through a callback ref) is followed as soon as the\n * prop changes. A ref cannot be observed, so it is read after each render of the popover is\n * committed, wherever the target is in the tree: an element attaching to or detaching from the\n * ref is noticed the next time the popover renders (for example when the parent that mounts or\n * unmounts the target re-renders it), not in a commit that does not render the popover. A\n * memoized popover whose target mounts or unmounts in another subtree therefore stays hidden,\n * or keeps pointing at the removed element, until it renders again. A newly passed ref keeps\n * the previous visibility until it has been read, so a tour can move between attached refs\n * (`target={step === 0 ? aRef : bRef}`) without hiding, and a switch to a ref that is not\n * attached hides the popover right after that commit. Pass the element held in state when the\n * target can mount or unmount without the popover re-rendering.\n */\n target?: React.RefObject<HTMLElement | null> | HTMLElement | null;\n /** Side of the `target` to open on; `start`/`end` follow the writing direction.\n * @default 'bottom'\n */\n side?: PopupSide;\n /** Alignment along the `target`'s edge.\n * @default 'center'\n */\n align?: PopupAlign;\n /** Ref to the popover surface (`role=\"dialog\"`). */\n ref?: React.Ref<HTMLDivElement>;\n}\n\nfunction isRefObject(\n target: NonNullable<TeachingPopoverProps['target']>,\n): target is React.RefObject<HTMLElement | null> {\n return 'current' in target;\n}\n\nfunction isElementTarget(target: TeachingPopoverProps['target']): target is HTMLElement {\n return target != null && !isRefObject(target);\n}\n\nfunction resolveTarget(target: TeachingPopoverProps['target']): HTMLElement | null {\n if (!target) return null;\n return isRefObject(target) ? target.current : target;\n}\n\nfunction clampStep(step: number, count: number): number {\n if (!Number.isFinite(step)) return 0;\n return Math.min(Math.max(Math.trunc(step), 0), count - 1);\n}\n\n/**\n * A step-by-step onboarding popover (a non-modal `role=\"dialog\"`) with Back/Next (Done on the\n * last step) and Close.\n *\n * - Visibility is controllable: `open`/`defaultOpen` (default `true`)/`onOpenChange`; Close, Done\n * and Escape (anywhere in the document) dismiss it and call `onDismiss`.\n * - The step is controllable with `activeStep`/`defaultActiveStep`/`onStepChange` and clamped to\n * the available steps. The heading carries a visually hidden “step n of m”, the new step is\n * announced politely, and Back stays focusable (`aria-disabled`) on the first step.\n * - The built-in text is English: `labels` localizes Back, Next, Done and the step position, and\n * `closeLabel` the Close button.\n * - Focus moves to the popover when it opens and returns to the element that had it when it\n * closes (with `target`, to the target when nothing had focus, e.g. a tour opened on page load).\n * - With `target`, the popover is portaled and positioned next to that element with a beak (it\n * inherits the surface colors); it stays hidden while the target is `null`, not positioned yet or\n * no longer mounted (a ref target is read after each render of the popover; see `target`).\n * - With `target`, the keyboard order treats the popover as if it followed the target: Tab past\n * its last button continues after the target, Shift+Tab from its first button (or from the\n * popover itself) returns to the target (for a target outside the Tab order, to the last control\n * inside it, else to the control before it), Tab from there enters the popover, and Shift+Tab\n * from the control after the target enters it at its last button. Tab from the last control of\n * the page moves past the popover (it was visited after the target), and Shift+Tab from outside\n * the page reaches the page's last control first, so a lap visits it once and Tab never cycles.\n * With no control at or before the target, the popover is reached where it is portaled, at the\n * end of the page: Tab from the page's last control and Shift+Tab from outside the page enter\n * it.\n */\nexport const TeachingPopover = ({\n steps,\n activeStep: activeStepProp,\n defaultActiveStep,\n currentStep,\n defaultCurrentStep,\n onStepChange,\n onDismiss,\n open: openProp,\n defaultOpen,\n onOpenChange,\n closeLabel = 'Close',\n labels,\n target,\n side = 'bottom',\n align = 'center',\n className,\n style,\n onKeyDown,\n ref,\n ...rest\n}: TeachingPopoverProps) => {\n const controlledStep = resolveDeprecatedProp(\n 'TeachingPopover',\n activeStepProp,\n currentStep,\n 'currentStep',\n 'activeStep',\n );\n const initialStep =\n resolveDeprecatedProp(\n 'TeachingPopover',\n defaultActiveStep,\n defaultCurrentStep,\n 'defaultCurrentStep',\n 'defaultActiveStep',\n ) ?? 0;\n const [rawStep, setStep] = useControllable(controlledStep, initialStep, onStepChange);\n const [open, setOpen] = useControllable(openProp, defaultOpen ?? true, onOpenChange);\n const titleId = useId('teaching-popover-title');\n const announce = useAnnounce();\n\n const count = steps.length;\n const shown = open && count > 0;\n const index = count > 0 ? clampStep(rawStep, count) : 0;\n const outOfRange = count > 0 && index !== rawStep;\n const step = count > 0 ? steps[index] : undefined;\n const stepTitle = step?.title;\n const isFirst = index === 0;\n const isLast = index === count - 1;\n const hasTarget = target !== undefined;\n const stepPosition = count > 0 ? (labels?.step ?? defaultStepLabel)(index, count) : '';\n\n const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n // Whether `target` pointed at an element when it was last read. An element (or `null`) is known\n // during render and is mirrored here right away (C-HOOKS: adjust state during render). A ref\n // cannot be read during render, React does not re-render when it attaches or detaches, and\n // floating-ui keeps `isPositioned` after `setReference(null)`, so the layout effect below reads\n // a ref after each commit and mirrors it here through a deferred update (C-HOOKS). Until that\n // update has read a newly passed ref, the ref keeps this last known availability: moving between\n // attached refs (a multi-target tour) or passing a new ref object on every render never hides\n // the popover, and a switch to a ref that is not attached hides it once the update lands.\n const [targetResolved, setTargetResolved] = React.useState(() => isElementTarget(target));\n const elementAvailable = target === null ? false : isElementTarget(target) ? true : undefined;\n if (elementAvailable !== undefined && elementAvailable !== targetResolved) {\n setTargetResolved(elementAvailable);\n }\n const surfaceRef = React.useRef<HTMLDivElement | null>(null);\n const targetRef = React.useRef<HTMLElement | null>(null);\n // The latest `target` prop and committed availability, read by the deferred update so that the\n // newest target and attachment win and an unchanged resolution sets no state.\n const targetPropRef = React.useRef(target);\n const availabilityRef = React.useRef(targetResolved);\n const arrowRef = React.useRef<HTMLDivElement | null>(null);\n\n // Destructured: react-hooks/refs treats an object whose member is passed to `ref` as a ref.\n const {\n setReference,\n setFloating,\n floatingProps,\n arrowStyles,\n side: placedSide,\n isPositioned,\n } = usePopupPosition({ open: shown && hasTarget, side, align, offset: 12, arrowRef });\n // An anchored popover is shown only while it points at a resolved target: otherwise the surface\n // is rendered (so it can be measured) but hidden, unfocused, silent and without an Escape layer.\n const targetAvailable = target != null && (isRefObject(target) ? targetResolved : true);\n const anchorReady = !hasTarget || (targetAvailable && isPositioned);\n const visible = shown && anchorReady;\n const elementRef = useMergedRefs<HTMLDivElement>(ref, surfaceRef, setSurface, setFloating);\n\n // Point the positioning at the target after every commit. A ref is read once more when the whole\n // commit is done (the C-HOOKS deferred-update pattern): a target that comes after the popover in\n // the tree attaches its ref after this effect has run. That update re-reads the latest target,\n // and only a changed element or availability updates the reference or the state.\n React.useLayoutEffect(() => {\n targetPropRef.current = target;\n availabilityRef.current = targetResolved;\n const element = resolveTarget(target);\n targetRef.current = element;\n setReference(element);\n if (target == null || !isRefObject(target)) return;\n queueMicrotask(() => {\n const latest = resolveTarget(targetPropRef.current);\n if (latest !== targetRef.current) {\n targetRef.current = latest;\n setReference(latest);\n }\n const available = latest !== null;\n if (available !== availabilityRef.current) {\n availabilityRef.current = available;\n setTargetResolved(available);\n }\n });\n });\n\n const dismiss = () => {\n setOpen(false);\n onDismiss?.();\n };\n\n const { layerId } = useDismiss({\n open: visible,\n onDismiss: dismiss,\n refs: [surfaceRef],\n anchorRef: targetRef,\n kind: 'popover',\n outsidePress: false,\n });\n\n useRestoreFocus({\n enabled: visible,\n container: surface,\n fallback: () => targetRef.current,\n onlyIfFocusInside: true,\n });\n\n // Portaled next to a target: the keyboard order of the popover placed right after the target.\n const onSurfaceKeyDown = usePopoverTabOrder({\n enabled: visible && hasTarget,\n surface,\n anchorRef: targetRef,\n getPreviousStop: getTabbableThrough,\n });\n\n // Move focus into the popover when it becomes visible (and when a new surface mounts).\n React.useEffect(() => {\n if (visible && surface) surface.focus({ preventScroll: hasTarget });\n }, [visible, surface, hasTarget]);\n\n // Announce the new step politely after a step change (not on mount, and not while hidden: the\n // heading, which carries the step position, is read when the popover shows and takes focus).\n const announcedIndexRef = React.useRef(index);\n React.useEffect(() => {\n if (announcedIndexRef.current === index) return;\n announcedIndexRef.current = index;\n if (visible && stepTitle !== undefined) {\n announce(`${stepTitle}, ${stepPosition}`);\n }\n }, [index, visible, stepTitle, stepPosition, announce]);\n\n React.useEffect(() => {\n if (!outOfRange) return;\n warnOnce(\n 'TeachingPopover:activeStep-range',\n `TeachingPopover: activeStep ${rawStep} is out of range for ${count} steps; showing step ${index + 1}.`,\n );\n }, [outOfRange, rawStep, count, index]);\n\n if (!shown || !step) return null;\n\n const handleBack = () => setStep(index - 1);\n const handleNext = () => {\n if (isLast) dismiss();\n else setStep(index + 1);\n };\n\n return (\n <Portal disabled={!hasTarget} layerId={layerId}>\n <div\n role=\"dialog\"\n aria-labelledby={titleId}\n tabIndex={-1}\n {...rest}\n ref={elementRef}\n onKeyDown={composeEventHandlers(onKeyDown, onSurfaceKeyDown)}\n {...(hasTarget\n ? {\n 'data-side': floatingProps['data-side'],\n 'data-align': floatingProps['data-align'],\n style: {\n ...style,\n ...floatingProps.style,\n ...(anchorReady ? undefined : { visibility: 'hidden' as const }),\n },\n }\n : { style })}\n className={cn(\n 'relative w-80 rounded-md border border-border bg-background p-5 text-foreground shadow-8',\n focusRing,\n className,\n )}\n >\n {hasTarget && (\n <PopoverBeak\n ref={arrowRef}\n side={placedSide}\n style={arrowStyles}\n data-wave-teaching-popover-arrow=\"\"\n />\n )}\n\n <Button\n appearance=\"subtle\"\n size=\"small\"\n icon={<DismissIcon />}\n aria-label={closeLabel}\n className=\"absolute end-3 top-3\"\n onClick={dismiss}\n />\n\n <h3 id={titleId} className=\"mb-2 pe-8 text-subtitle-1 font-semibold text-foreground\">\n {step.title}\n <span className=\"sr-only\">{`, ${stepPosition}`}</span>\n </h3>\n\n <div className=\"mb-4 text-body-1 text-muted-foreground\">{step.body}</div>\n\n <div className=\"flex items-center justify-between gap-2\">\n <div aria-hidden=\"true\" className=\"flex items-center gap-1.5\">\n {steps.map((_, i) => (\n <span\n key={i}\n data-wave-teaching-popover-dot=\"\"\n aria-current={i === index ? 'step' : undefined}\n className={cn(\n 'h-1.5 rounded-full transition-[width,background-color] motion-reduce:transition-none',\n i === index\n ? cn('w-4 bg-primary', forcedColors.fill)\n : 'w-1.5 bg-stroke-accessible forced-colors:bg-[CanvasText] forced-colors:forced-color-adjust-none',\n )}\n />\n ))}\n </div>\n\n <div className=\"flex items-center gap-2\">\n {count > 1 && (\n <Button\n {...focusableDisabledProps(isFirst)}\n onClick={preventIfDisabled(isFirst, handleBack)}\n >\n {labels?.back ?? DEFAULT_BACK_LABEL}\n </Button>\n )}\n <Button appearance=\"primary\" onClick={handleNext}>\n {isLast ? (labels?.done ?? DEFAULT_DONE_LABEL) : (labels?.next ?? DEFAULT_NEXT_LABEL)}\n </Button>\n </div>\n </div>\n </div>\n </Portal>\n );\n};\nTeachingPopover.displayName = 'TeachingPopover';\n"],"mappings":"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"}
|