@mortenbrudvik/waveui 0.4.0 → 0.8.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 +1484 -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 +51 -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 +57 -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 +55 -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 +38 -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 +46 -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 +67 -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 +68 -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 +64 -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 +126 -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 +162 -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 +135 -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 +33 -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 +29 -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 +53 -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 +33 -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 +105 -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 +382 -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 +50 -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 +72 -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 +152 -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 +202 -0
- package/dist/components/feedback/MessageBar.mjs.map +1 -0
- package/dist/components/feedback/MessageBar.parts.cjs +2 -0
- package/dist/components/feedback/MessageBar.parts.cjs.map +1 -0
- package/dist/components/feedback/MessageBar.parts.mjs +84 -0
- package/dist/components/feedback/MessageBar.parts.mjs.map +1 -0
- package/dist/components/feedback/MessageBar.reflow.cjs +2 -0
- package/dist/components/feedback/MessageBar.reflow.cjs.map +1 -0
- package/dist/components/feedback/MessageBar.reflow.mjs +74 -0
- package/dist/components/feedback/MessageBar.reflow.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 +46 -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 +73 -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 +49 -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 +61 -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.context.cjs +2 -0
- package/dist/components/feedback/Toast.context.cjs.map +1 -0
- package/dist/components/feedback/Toast.context.mjs +23 -0
- package/dist/components/feedback/Toast.context.mjs.map +1 -0
- package/dist/components/feedback/Toast.mjs +15 -0
- package/dist/components/feedback/Toast.mjs.map +1 -0
- package/dist/components/feedback/Toast.parts.cjs +2 -0
- package/dist/components/feedback/Toast.parts.cjs.map +1 -0
- package/dist/components/feedback/Toast.parts.mjs +98 -0
- package/dist/components/feedback/Toast.parts.mjs.map +1 -0
- package/dist/components/feedback/Toast.root.cjs +2 -0
- package/dist/components/feedback/Toast.root.cjs.map +1 -0
- package/dist/components/feedback/Toast.root.mjs +109 -0
- package/dist/components/feedback/Toast.root.mjs.map +1 -0
- package/dist/components/feedback/Toaster.cjs +2 -0
- package/dist/components/feedback/Toaster.cjs.map +1 -0
- package/dist/components/feedback/Toaster.mjs +564 -0
- package/dist/components/feedback/Toaster.mjs.map +1 -0
- package/dist/components/input/AlphaSlider.cjs +2 -0
- package/dist/components/input/AlphaSlider.cjs.map +1 -0
- package/dist/components/input/AlphaSlider.mjs +115 -0
- package/dist/components/input/AlphaSlider.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 +97 -0
- package/dist/components/input/Checkbox.mjs.map +1 -0
- package/dist/components/input/ColorArea.cjs +2 -0
- package/dist/components/input/ColorArea.cjs.map +1 -0
- package/dist/components/input/ColorArea.mjs +204 -0
- package/dist/components/input/ColorArea.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 +213 -0
- package/dist/components/input/ColorPicker.mjs.map +1 -0
- package/dist/components/input/ColorPicker.parts.cjs +2 -0
- package/dist/components/input/ColorPicker.parts.cjs.map +1 -0
- package/dist/components/input/ColorPicker.parts.mjs +192 -0
- package/dist/components/input/ColorPicker.parts.mjs.map +1 -0
- package/dist/components/input/ColorSlider.cjs +2 -0
- package/dist/components/input/ColorSlider.cjs.map +1 -0
- package/dist/components/input/ColorSlider.mjs +138 -0
- package/dist/components/input/ColorSlider.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 +192 -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 +341 -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 +131 -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 +201 -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 +82 -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 +29 -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 +171 -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 +140 -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 +197 -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 +204 -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 +34 -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 +80 -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 +158 -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 +114 -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 +93 -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 +253 -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 +33 -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 +295 -0
- package/dist/components/input/TimePicker.mjs.map +1 -0
- package/dist/components/input/colorName.cjs +2 -0
- package/dist/components/input/colorName.cjs.map +1 -0
- package/dist/components/input/colorName.mjs +30 -0
- package/dist/components/input/colorName.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 +194 -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 +237 -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 +122 -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 +206 -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 +55 -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 +63 -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 +270 -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 +40 -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 +239 -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.context.cjs +2 -0
- package/dist/components/layout/Tree.context.cjs.map +1 -0
- package/dist/components/layout/Tree.context.mjs +33 -0
- package/dist/components/layout/Tree.context.mjs.map +1 -0
- package/dist/components/layout/Tree.core.cjs +2 -0
- package/dist/components/layout/Tree.core.cjs.map +1 -0
- package/dist/components/layout/Tree.core.mjs +416 -0
- package/dist/components/layout/Tree.core.mjs.map +1 -0
- package/dist/components/layout/Tree.itemPersonaLayout.cjs +2 -0
- package/dist/components/layout/Tree.itemPersonaLayout.cjs.map +1 -0
- package/dist/components/layout/Tree.itemPersonaLayout.mjs +46 -0
- package/dist/components/layout/Tree.itemPersonaLayout.mjs.map +1 -0
- package/dist/components/layout/Tree.mjs +12 -0
- package/dist/components/layout/Tree.mjs.map +1 -0
- package/dist/components/layout/Tree.selection.cjs +2 -0
- package/dist/components/layout/Tree.selection.cjs.map +1 -0
- package/dist/components/layout/Tree.selection.mjs +73 -0
- package/dist/components/layout/Tree.selection.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 +145 -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 +60 -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 +133 -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 +47 -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 +232 -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 +309 -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 +111 -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 +52 -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 +291 -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 +118 -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 +205 -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 +181 -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 +193 -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 +367 -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 +185 -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 +161 -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 +46 -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 +52 -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 +490 -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 +100 -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 +39 -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/useMediaQuery.cjs +2 -0
- package/dist/hooks/useMediaQuery.cjs.map +1 -0
- package/dist/hooks/useMediaQuery.mjs +20 -0
- package/dist/hooks/useMediaQuery.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 +10 -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 +11086 -0
- package/dist/index.d.ts +10405 -1757
- package/dist/index.mjs +103 -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/classNames.cjs +2 -0
- package/dist/lib/classNames.cjs.map +1 -0
- package/dist/lib/classNames.mjs +415 -0
- package/dist/lib/classNames.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/color.cjs +2 -0
- package/dist/lib/color.cjs.map +1 -0
- package/dist/lib/color.mjs +86 -0
- package/dist/lib/color.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/lib/toaster.cjs +2 -0
- package/dist/lib/toaster.cjs.map +1 -0
- package/dist/lib/toaster.mjs +77 -0
- package/dist/lib/toaster.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":"DatePicker.mjs","names":["formatLocaleDate","parseLocaleDate","useId","useId$1","React","defaultInvalidDateLabel","pattern","defaultOutOfRangeLabel","min","max","ICON_BUTTON_CLASSES","NAV_BUTTON_CLASSES","DAY_CLASSES","toWeeks","weeks","i","days","DatePicker","valueProp","formatDateProp","parseDateProp","openProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","rest","props","onChange","warnDeprecated","hasCustomFormat","hasCustomParse","warnOnce","locale","isValidLocaleTag","selectedDate","setSelectedDate","useControllable","defaultValue","onValueChange","next","interactive","disabled","readOnly","openState","setOpen","defaultOpen","onOpenChange","isClient","useIsClient","isOpen","openControlled","format","date","formatDate","parse","text","parseDate","draft","setDraft","invalid","setInvalid","wasInteractive","setWasInteractive","selectedDay","formatISODate","seenDay","setSeenDay","isUnavailable","isDateInRange","minDate","maxDate","disabledDates","startOfDay","commitDate","normalized","isSameDay","commitDraft","parsed","reason","rejected","onInvalidInput","today","initialView","startOfMonth","clampDate","viewMonth","setViewMonth","focusedDay","setFocusedDay","openedFromInput","setOpenedFromInput","openSeen","setOpenSeen","getCalendarDays","firstDayOfWeek","inView","isSameMonth","inGrid","clampedToday","firstInRange","focusTarget","focusIso","moveFocus","target","navigateMonth","nextView","addMonths","delta","moved","handleDayFocus","day","previousDisabled","addDays","nextDisabled","weekdays","getWeekdayNames","inputRef","toggleRef","gridRef","surfaceRef","restoreTargetRef","surface","setSurface","inputRefs","useMergedRefs","controlRef","dialogId","headingId","gridId","errorId","close","restoreTo","useDismiss","event","FOCUSABLE_SELECTOR","usePopupPosition","surfaceRefs","setFloating","useFocusTrap","useRestoreFocus","grid","active","button","field","useFieldContext","validates","required","showOwnError","fieldProps","useFieldControl","joinIds","invalidLook","isInvalidLook","form","showClear","clearable","handleInputChange","handleInputKeyDown","composeEventHandlers","onKeyDown","flushSync","handleInputBlur","onBlur","handleToggle","handleClear","handleClearMouseDown","selectDate","handleDialogKeyDown","handleGridKeyDown","weekOffset","intent","getArrowIntent","getDirection","inputText","errorMessage","labels","getLocaleDateFormat","cn","datePickerClassNames","className","setReference","inputBase","inputFocus","disabledStyles","DismissIcon","focusRing","CalendarIcon","HiddenInput","Portal","floatingProps","focusableDisabledProps","preventIfDisabled","ChevronLeftIcon","formatMonthYear","ChevronRightIcon","weekday","week","iso","isSelected","isToday","isFocused","unavailable","formatDayLabel","forcedColors","formatDayNumber","column","row"],"sources":["../../../src/components/input/DatePicker.tsx"],"sourcesContent":["import * as React from 'react';\nimport { flushSync } from 'react-dom';\nimport { cn } from '../../lib/cn';\nimport { focusableDisabledProps, joinIds, preventIfDisabled } from '../../lib/aria';\nimport { datePickerClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { FOCUSABLE_SELECTOR } from '../../lib/focus';\nimport { CalendarIcon, ChevronLeftIcon, ChevronRightIcon, DismissIcon } from '../../lib/icons';\nimport {\n disabledStyles,\n focusRing,\n forcedColors,\n inputBase,\n inputFocus,\n inputInvalid,\n} from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useDismiss } from '../../hooks/useDismiss';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFocusTrap } from '../../hooks/useFocusTrap';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useId } from '../../hooks/useId';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { usePopupPosition } from '../../hooks/usePopupPosition';\nimport { useRestoreFocus } from '../../hooks/useRestoreFocus';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { Portal } from '../portal/Portal';\nimport {\n addDays,\n addMonths,\n clampDate,\n formatDate as formatLocaleDate,\n formatDayLabel,\n formatDayNumber,\n formatISODate,\n formatMonthYear,\n getCalendarDays,\n getLocaleDateFormat,\n getWeekdayNames,\n isDateInRange,\n isSameDay,\n isSameMonth,\n isValidLocaleTag,\n parseDate as parseLocaleDate,\n startOfDay,\n startOfMonth,\n} from './dateUtils';\nimport { isInvalidLook } from './Input';\nimport type { RoutedHandlers } from './routedHandlers';\n\n/** Why typed text was not accepted (see {@link DatePickerProps.onInvalidInput}). */\nexport type DatePickerInvalidReason = 'unparseable' | 'out-of-range' | 'disabled';\n\n/**\n * The DatePicker's built-in button names and error texts, for localization. Each member is\n * optional and falls back to its English default. Month and weekday names and the day labels\n * follow `locale`.\n */\nexport interface DatePickerLabels {\n /** Name of the clear button.\n * @default 'Clear date'\n */\n clear?: string;\n /** Name of the button that opens the calendar.\n * @default 'Open calendar'\n */\n openCalendar?: string;\n /** Name of the calendar's previous-month button.\n * @default 'Previous month'\n */\n previousMonth?: string;\n /** Name of the calendar's next-month button.\n * @default 'Next month'\n */\n nextMonth?: string;\n /**\n * Error text for typed text that is not a date. `pattern` is the default format of `locale`\n * written with English field letters (`'MM/DD/YYYY'`, `'DD.MM.YYYY'`), or `undefined` with a\n * custom `parseDate` (its format is unknown to the picker).\n * @default (pattern) => pattern ? `Enter a date in the format ${pattern}.` : 'Enter a valid date.'\n */\n invalidDate?: (pattern: string | undefined) => string;\n /**\n * Error text for a typed date outside `minDate`/`maxDate`. The bounds are passed as the input\n * shows dates (`formatDate`); a bound that is not set is `undefined`.\n * @default (min, max) => `Enter a date between ${min} and ${max}.` (only `min`: `Enter a date on\n * or after ${min}.`; only `max`: `Enter a date on or before ${max}.`)\n */\n outOfRange?: (min: string | undefined, max: string | undefined) => string;\n /** Error text for a typed date that `disabledDates` excludes.\n * @default 'This date is not available.'\n */\n unavailableDate?: string;\n}\n\nconst defaultInvalidDateLabel = (pattern: string | undefined) =>\n pattern ? `Enter a date in the format ${pattern}.` : 'Enter a valid date.';\n\nconst defaultOutOfRangeLabel = (min: string | undefined, max: string | undefined) => {\n if (min !== undefined && max !== undefined) return `Enter a date between ${min} and ${max}.`;\n if (min !== undefined) return `Enter a date on or after ${min}.`;\n return `Enter a date on or before ${max}.`;\n};\n\n/** Properties for the DatePicker component. */\nexport interface DatePickerProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | 'placeholder' | RoutedHandlers\n> {\n /** Controlled selected date (`null` for none). Emitted dates are always local midnight. */\n value?: Date | null;\n /**\n * Initial date for uncontrolled usage.\n * @default null\n */\n defaultValue?: Date | null;\n /** Called with the new date (local midnight) or `null` whenever the selected day changes. */\n onValueChange?: (date: Date | null) => void;\n /**\n * @deprecated Use `onValueChange`. Still called with the new date (warns once in development).\n */\n onChange?: (date: Date | null) => void;\n /**\n * Formats the selected date for the input. Supply `parseDate` as its inverse: without it, typed\n * text is parsed with the default parser for `locale` (development warning).\n * @default Intl.DateTimeFormat(locale, { year: 'numeric', month: '2-digit', day: '2-digit' }),\n * in the Gregorian calendar when the locale's own has other months (see `locale`)\n */\n formatDate?: (date: Date) => string;\n /**\n * Parses typed text into a date (`null` when it is not one); the result is normalized to local\n * midnight. The default is the exact inverse of the default format for `locale` and also\n * accepts ISO `yyyy-mm-dd`.\n */\n parseDate?: (text: string) => Date | null;\n /**\n * BCP 47 locale of the default format/parse, the month and weekday names and the day labels\n * (runtime default when omitted). Pass it explicitly when rendering on the server, so the server\n * and the browser format the same text. The grid is Gregorian: a locale calendar with other\n * months or eras (the Persian default of `fa-IR`, `-u-ca-islamic`, `-u-ca-japanese`) is replaced\n * by the Gregorian one in the locale's language and digits; the Buddhist years of `th-TH` stay.\n * A tag `Intl` rejects (the POSIX `de_DE`, a typo) falls back to the runtime default locale\n * (development warning).\n */\n locale?: string;\n /** Earliest selectable day (the whole day is included). */\n minDate?: Date;\n /** Latest selectable day (the whole day is included). */\n maxDate?: Date;\n /** Returns `true` for days that cannot be selected (called with local-midnight dates). */\n disabledDates?: (date: Date) => boolean;\n /**\n * Placeholder text shown when no date is selected.\n * @default 'Select a date'\n */\n placeholder?: string;\n /**\n * Whether the date picker is disabled and non-interactive (the calendar is not shown).\n * @default false\n */\n disabled?: boolean;\n /**\n * Makes the input read-only: the calendar does not open and the value cannot change. Turning it\n * (or `disabled`) on while the user is typing drops the typed text.\n */\n readOnly?: boolean;\n /**\n * Whether to show a clear button when a date is selected (not shown while `readOnly`). Tab from\n * erased text clears the value before focus moves, so focus goes on to the calendar button, past\n * the clear button that disappears with it.\n * @default false\n */\n clearable?: boolean;\n /**\n * First day of the week (0 = Sunday, 1 = Monday, etc.).\n * @default 0\n */\n firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n /**\n * Controlled open state of the calendar. The calendar renders only in the browser: an open\n * picker is closed in the server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Initial open state for uncontrolled usage. A picker that starts disabled or read-only starts\n * closed. The calendar renders only in the browser: it is closed in the server HTML and opens\n * once the picker has hydrated.\n * @default false\n */\n defaultOpen?: boolean;\n /** Called when the calendar opens or closes (only when the state changes). */\n onOpenChange?: (open: boolean) => void;\n /**\n * Called when typed text is not accepted on Enter, Alt+ArrowDown or blur (once per edit): it\n * cannot be parsed (`'unparseable'`), lies outside `minDate`/`maxDate` (`'out-of-range'`) or is\n * excluded by `disabledDates` (`'disabled'`). The text stays in the input, which is marked\n * `aria-invalid` and described by an error message (left to the surrounding `Field` when it\n * shows an error). Enter reports it again when pressed again.\n */\n onInvalidInput?: (text: string, reason: DatePickerInvalidReason) => void;\n /**\n * Names of the clear, calendar and month buttons and the error texts of rejected typed text, for\n * localization. Unset members keep their English defaults.\n */\n labels?: DatePickerLabels;\n /** Form field name: the date is submitted as ISO `yyyy-mm-dd` (hidden input). */\n name?: string;\n /** Id of the `<form>` the value belongs to, when the picker is outside it. */\n form?: string;\n /**\n * Blocks form submission while no date is selected; sets `aria-required` on the input. Like a\n * native readonly input, a `readOnly` DatePicker does not block submission.\n */\n required?: boolean;\n /** Native `autocomplete` of the input. @default 'off' */\n autoComplete?: string;\n /** Focus handler of the text input (the root keeps the other handlers). */\n onFocus?: React.FocusEventHandler<HTMLInputElement>;\n /** Blur handler of the text input. */\n onBlur?: React.FocusEventHandler<HTMLInputElement>;\n /** Key handler of the text input; `preventDefault()` skips the picker's own keys. */\n onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n /** Key handler of the text input. */\n onKeyUp?: React.KeyboardEventHandler<HTMLInputElement>;\n /** Ref to the text input; `ref` stays on the root. */\n controlRef?: React.Ref<HTMLInputElement>;\n /** Ref to the root element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n// Every button sets its own padding and background (C-NATIVE): an app-wide `button` rule would\n// otherwise pad and fill them.\nconst ICON_BUTTON_CLASSES =\n 'absolute flex h-6 w-6 items-center justify-center rounded bg-transparent p-0 text-muted-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:hover:text-foreground';\n\nconst NAV_BUTTON_CLASSES =\n 'flex h-8 w-8 items-center justify-center rounded bg-transparent p-0 text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover';\n\n// An unavailable day stays focusable in the roving grid (`aria-disabled`); the day button adds\n// `disabledStyles`, whose dimmed look lifts while the focus ring shows (opacity would dim the ring).\nconst DAY_CLASSES =\n 'flex h-8 w-8 items-center justify-center rounded bg-transparent p-0 text-caption-1 text-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover data-[outside]:text-muted-foreground data-[today]:border data-[today]:border-primary data-[today]:font-semibold data-[selected]:bg-primary data-[selected]:font-semibold data-[selected]:text-primary-foreground not-disabled:not-aria-disabled:data-[selected]:hover:bg-primary-hover aria-disabled:line-through';\n\n/** The 42 grid days as 6 weeks. */\nfunction toWeeks(days: Date[]): Date[][] {\n const weeks: Date[][] = [];\n for (let i = 0; i < days.length; i += 7) weeks.push(days.slice(i, i + 7));\n return weeks;\n}\n\n/**\n * A date input with a calendar dialog (APG date picker dialog).\n *\n * - **Typing**: the input accepts the default display format of `locale` (`Intl` numeric\n * year/month/day, e.g. `03/04/2025` for `en-GB`, `04/03/2025` for `en-US`) and ISO\n * `yyyy-mm-dd`. Text is committed on Enter, on Alt+ArrowDown (before the calendar opens) or when\n * the field loses focus — only when it was edited, and only when it names a different day. Text\n * that is not an available date is kept, the input is marked invalid and an error message\n * describes it (`onInvalidInput`, reported once per edit) until the text is edited or replaced\n * (a day picked in the calendar, the clear button, a form reset, a new day from the parent).\n * - **Calendar**: the toggle (`aria-haspopup=\"dialog\"`) or Alt+ArrowDown in the input opens a\n * modal dialog labelled by the month heading. Focus moves to the selected day (else today, else\n * the first available day of the month) and Tab stays inside. Arrow keys move by day/week\n * (mirrored in RTL), PageUp/PageDown by month, Shift+PageUp/PageDown by year (the day is clamped\n * to the month), Home/End to the start/end of the week, Enter/Space select. Escape closes and\n * returns focus to where the calendar was opened from (the toggle, or the input after\n * Alt+ArrowDown); a press outside closes it too. Unavailable days stay focusable\n * (`aria-disabled`); a day focused by pointer becomes the starting point of the arrow keys. The\n * selected day is `aria-selected` on its gridcell and `aria-pressed` on its focusable button, so\n * the state is announced when focus lands on it; today is `aria-current=\"date\"`.\n * - The calendar closes when the picker becomes disabled or read-only (uncontrolled `open`: it\n * stays closed when the picker is enabled again), and the text typed until then is dropped.\n * - `clearable` shows a clear button while a date is selected (not while read-only). Tab from\n * erased text clears the value first, so focus moves on to the calendar button instead of to the\n * clear button that disappears.\n * - Every emitted date is local midnight. The calendar opens on the month of the selected date or\n * today, clamped into `minDate`/`maxDate`.\n * - The input (`controlRef`) receives `id`, `aria-label`, `aria-labelledby`, `aria-describedby`,\n * `aria-invalid`, `aria-required`, `aria-errormessage`, `aria-details`, `tabIndex`,\n * `autoFocus`, `onFocus`/`onBlur`/`onKeyDown`/`onKeyUp` and the text input attributes\n * `autoComplete`, `autoCapitalize`, `autoCorrect`, `inputMode`, `spellCheck` and\n * `enterKeyHint`. `ref`, `className`, `style`, other `aria-*` attributes and the remaining props\n * stay on the root `<div>`. Inside a `Field`, the input is labelled and described by it.\n * - `name`/`required` add a hidden input for native forms (ISO `yyyy-mm-dd`); the value resets\n * with its form.\n * - The built-in button names and error texts are English; `labels` localizes them.\n * - Pass `locale` explicitly when rendering on the server (see `locale`). The calendar renders only\n * in the browser: an open calendar (`defaultOpen`, `open`) is closed in the server HTML and opens\n * once the picker has hydrated.\n */\nexport const DatePicker = (props: DatePickerProps) => {\n const {\n value: valueProp,\n defaultValue,\n onValueChange,\n onChange,\n formatDate: formatDateProp,\n parseDate: parseDateProp,\n locale,\n minDate,\n maxDate,\n disabledDates,\n placeholder = 'Select a date',\n disabled = false,\n readOnly,\n clearable = false,\n firstDayOfWeek = 0,\n open: openProp,\n defaultOpen,\n onOpenChange,\n onInvalidInput,\n labels,\n name,\n form,\n required,\n autoComplete = 'off',\n autoCapitalize,\n autoCorrect,\n enterKeyHint,\n inputMode,\n spellCheck,\n autoFocus,\n tabIndex,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n controlRef,\n className,\n ref,\n ...rest\n } = props;\n\n if (onChange !== undefined) warnDeprecated('DatePicker', 'onChange', 'onValueChange');\n\n const hasCustomFormat = formatDateProp !== undefined;\n const hasCustomParse = parseDateProp !== undefined;\n React.useEffect(() => {\n if (hasCustomFormat && !hasCustomParse) {\n warnOnce(\n 'DatePicker:formatDate-without-parseDate',\n 'DatePicker: `formatDate` is set without `parseDate`. Typed dates are parsed with the ' +\n 'default parser for `locale` (its numeric format or yyyy-mm-dd), which may not read ' +\n 'your format; pass `parseDate` as the inverse of `formatDate`.',\n );\n }\n }, [hasCustomFormat, hasCustomParse]);\n React.useEffect(() => {\n if (locale !== undefined && !isValidLocaleTag(locale)) {\n warnOnce(\n `DatePicker:invalid-locale:${locale}`,\n `DatePicker: \\`locale\\` \"${locale}\" is not a valid BCP 47 language tag (use hyphens, as ` +\n 'in \"en-US\"). The runtime default locale formats and parses the dates instead, so the ' +\n 'server and the browser may render different text.',\n );\n }\n }, [locale]);\n\n const [selectedDate, setSelectedDate] = useControllable<Date | null>(\n valueProp,\n defaultValue ?? null,\n (next) => {\n onValueChange?.(next);\n onChange?.(next);\n },\n );\n const interactive = !disabled && !readOnly;\n const [openState, setOpen] = useControllable<boolean>(\n openProp,\n // A picker that starts disabled or read-only never shows its calendar, so it starts closed\n // (no close to report later).\n (defaultOpen ?? false) && interactive,\n onOpenChange,\n );\n // The calendar lives in a portal, which renders only in the browser: until then (the server\n // HTML, hydration) the picker reports it closed, so no reference names a missing element.\n const isClient = useIsClient();\n const isOpen = openState && interactive && isClient;\n const openControlled = openProp !== undefined;\n\n // A calendar hidden because the picker became disabled or read-only is closed for good\n // (uncontrolled), so enabling the picker again does not bring it back and take focus.\n // onOpenChange(false) reports it; a controlled `open` stays the parent's.\n React.useEffect(() => {\n if (!interactive && openState && !openControlled) setOpen(false);\n }, [interactive, openState, openControlled, setOpen]);\n\n const format = (date: Date) =>\n formatDateProp ? formatDateProp(date) : formatLocaleDate(date, locale);\n const parse = (text: string) =>\n parseDateProp ? parseDateProp(text) : parseLocaleDate(text, locale);\n\n /* ---- draft text and validation ---------------------------------- */\n\n /** Typed text; `null` shows the formatted selected date (draft model). */\n const [draft, setDraft] = React.useState<string | null>(null);\n const [invalid, setInvalid] = React.useState<DatePickerInvalidReason | null>(null);\n\n // Adjusted during render (C-HOOKS). Locking the picker (readOnly/disabled) while the user types\n // drops the typed text and its error, so no later blur commits it (the value cannot change).\n const [wasInteractive, setWasInteractive] = React.useState(interactive);\n if (wasInteractive !== interactive) {\n setWasInteractive(interactive);\n if (!interactive) {\n setDraft(null);\n setInvalid(null);\n }\n }\n // A selected day the parent changes replaces rejected text (commits clear it themselves), so the\n // input never shows an error next to a valid value. Text the user is still typing stays.\n const selectedDay = selectedDate ? formatISODate(selectedDate) : '';\n const [seenDay, setSeenDay] = React.useState(selectedDay);\n if (seenDay !== selectedDay) {\n setSeenDay(selectedDay);\n if (invalid !== null) {\n setDraft(null);\n setInvalid(null);\n }\n }\n\n const isUnavailable = (date: Date) =>\n !isDateInRange(date, minDate, maxDate) || !!disabledDates?.(startOfDay(date));\n\n /** Commits a day (or `null`); nothing is emitted when it is the same day. */\n const commitDate = (next: Date | null) => {\n const normalized = next ? startOfDay(next) : null;\n const unchanged = normalized ? isSameDay(normalized, selectedDate) : selectedDate === null;\n if (!unchanged) setSelectedDate(normalized);\n setDraft(null);\n setInvalid(null);\n };\n\n /** Validates and commits the typed text; `false` when it was rejected (the text is kept). */\n const commitDraft = (text: string): boolean => {\n if (!text.trim()) {\n commitDate(null);\n return true;\n }\n const parsed = parse(text);\n let reason: DatePickerInvalidReason | null = null;\n if (!parsed || Number.isNaN(parsed.getTime())) reason = 'unparseable';\n else if (!isDateInRange(parsed, minDate, maxDate)) reason = 'out-of-range';\n else if (disabledDates?.(startOfDay(parsed))) reason = 'disabled';\n if (reason || !parsed) {\n const rejected = reason ?? 'unparseable';\n setInvalid(rejected);\n onInvalidInput?.(text, rejected);\n return false;\n }\n commitDate(parsed);\n return true;\n };\n\n /* ---- calendar view and focused day ------------------------------- */\n\n const today = startOfDay(new Date());\n const initialView = () => startOfMonth(clampDate(selectedDate ?? today, minDate, maxDate));\n const [viewMonth, setViewMonth] = React.useState<Date>(initialView);\n const [focusedDay, setFocusedDay] = React.useState<Date | null>(null);\n\n /** Opened with Alt+ArrowDown in the input: Escape returns focus there instead of the toggle. */\n const [openedFromInput, setOpenedFromInput] = React.useState(false);\n\n // Every opening shows the selected (or current) month again: adjusted during render (C-HOOKS).\n const [openSeen, setOpenSeen] = React.useState(isOpen);\n if (openSeen !== isOpen) {\n setOpenSeen(isOpen);\n if (isOpen) {\n setViewMonth(initialView());\n setFocusedDay(null);\n }\n }\n // A closed calendar forgets where it was opened from. This also drops an Alt+ArrowDown whose\n // opening a controlled parent declined (it renders in the same update, still closed), so a later\n // opening by the parent returns focus to the toggle, not the input.\n if (openedFromInput && !isOpen) setOpenedFromInput(false);\n\n const weeks = React.useMemo(\n () => toWeeks(getCalendarDays(viewMonth, firstDayOfWeek)),\n [viewMonth, firstDayOfWeek],\n );\n\n // The focused day is derived: the day moved to while it is shown (a pointer-focused day of the\n // previous/next month counts too), else the selected day of the month, else today (clamped into\n // the range), else the first available day of the month.\n const inView = (date: Date | null | undefined): date is Date =>\n !!date && isSameMonth(date, viewMonth);\n const inGrid = (date: Date | null | undefined): date is Date =>\n !!date && date >= weeks[0][0] && date <= weeks[weeks.length - 1][6];\n const clampedToday = clampDate(today, minDate, maxDate);\n const firstInRange = clampDate(viewMonth, minDate, maxDate);\n const focusTarget = inGrid(focusedDay)\n ? focusedDay\n : inView(selectedDate)\n ? startOfDay(selectedDate)\n : inView(clampedToday)\n ? clampedToday\n : inView(firstInRange)\n ? firstInRange\n : viewMonth;\n const focusIso = formatISODate(focusTarget);\n\n const moveFocus = (next: Date) => {\n const target = clampDate(next, minDate, maxDate);\n setFocusedDay(target);\n if (!isSameMonth(target, viewMonth)) setViewMonth(startOfMonth(target));\n };\n\n const navigateMonth = (delta: number) => {\n const nextView = addMonths(viewMonth, delta);\n const moved = clampDate(addMonths(focusTarget, delta), minDate, maxDate);\n setViewMonth(nextView);\n // From a day of the previous/next month the moved day may fall outside the new month: the\n // focused day is then derived again (selected, today or the first day of the month).\n setFocusedDay(isSameMonth(moved, nextView) ? moved : null);\n };\n\n /** Pointer (or assistive technology) focus on a day makes it the roving day; the month stays. */\n const handleDayFocus = (day: Date) => {\n if (!isSameDay(day, focusTarget)) setFocusedDay(day);\n };\n\n const previousDisabled = !!minDate && addDays(viewMonth, -1) < startOfDay(minDate);\n const nextDisabled = !!maxDate && addMonths(viewMonth, 1) > startOfDay(maxDate);\n\n const weekdays = React.useMemo(\n () => getWeekdayNames(locale, firstDayOfWeek),\n [locale, firstDayOfWeek],\n );\n\n /* ---- elements, popup primitives ---------------------------------- */\n\n const inputRef = React.useRef<HTMLInputElement | null>(null);\n const toggleRef = React.useRef<HTMLButtonElement | null>(null);\n const gridRef = React.useRef<HTMLTableElement | null>(null);\n const surfaceRef = React.useRef<HTMLDivElement | null>(null);\n /** Where focus goes when the calendar closes (`null`: back to the toggle). */\n const restoreTargetRef = React.useRef<HTMLElement | null>(null);\n const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n const inputRefs = useMergedRefs<HTMLInputElement>(controlRef, inputRef);\n\n const dialogId = useId('datepicker-dialog');\n const headingId = useId('datepicker-heading');\n const gridId = useId('datepicker-grid');\n const errorId = useId('datepicker-error');\n\n const close = (restoreTo: HTMLElement | null) => {\n restoreTargetRef.current = restoreTo;\n setOpen(false);\n };\n\n const { layerId } = useDismiss({\n open: isOpen,\n onDismiss: (reason, event) => {\n // An outside press on another control hands focus to it (the trap held it until now);\n // otherwise focus returns to where the calendar was opened from.\n const target =\n reason === 'outside-press' && event.target instanceof Element\n ? event.target.closest<HTMLElement>(FOCUSABLE_SELECTOR)\n : null;\n close(target ?? (openedFromInput ? inputRef.current : null));\n },\n refs: [surfaceRef, toggleRef],\n anchorRef: toggleRef,\n kind: 'modal',\n });\n\n const { setReference, setFloating, floatingProps } = usePopupPosition({\n open: isOpen,\n side: 'bottom',\n align: 'start',\n });\n const surfaceRefs = useMergedRefs<HTMLDivElement>(surfaceRef, setSurface, setFloating);\n\n useFocusTrap(surface, {\n enabled: isOpen,\n layerId,\n initialFocus: () => gridRef.current?.querySelector<HTMLElement>('button[tabindex=\"0\"]') ?? null,\n });\n\n useRestoreFocus({\n enabled: isOpen,\n container: surface,\n triggerRef: toggleRef,\n finalFocusRef: restoreTargetRef,\n onlyIfFocusInside: true,\n });\n\n // A new opening starts without a restore target (the toggle returns focus to itself, Escape to\n // where the calendar was opened from).\n React.useLayoutEffect(() => {\n if (isOpen) restoreTargetRef.current = null;\n }, [isOpen]);\n\n // Roving focus: while the grid holds focus, focus follows the focused day.\n React.useLayoutEffect(() => {\n const grid = gridRef.current;\n if (!grid) return;\n const active = grid.ownerDocument.activeElement;\n if (!active || !grid.contains(active)) return;\n const button = grid.querySelector<HTMLElement>(`button[data-date=\"${focusIso}\"]`);\n if (button && button !== active) button.focus();\n }, [focusIso]);\n\n /* ---- forms and Field --------------------------------------------- */\n\n const field = useFieldContext();\n const isRequired = required ?? field?.required ?? false;\n // Like a native readonly input, a read-only picker is barred from constraint validation (the\n // user could not fix it); its value is still submitted.\n const validates = isRequired && !readOnly;\n const showOwnError = invalid !== null && !field?.hasErrorMessage;\n const fieldProps = useFieldControl({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': joinIds(ariaDescribedBy, showOwnError ? errorId : undefined),\n 'aria-invalid': invalid !== null ? true : ariaInvalid,\n // An explicit `required={false}` wins over a required Field, so aria-required matches\n // `isRequired`.\n 'aria-required': ariaRequired ?? required,\n });\n const invalidLook = isInvalidLook(false, fieldProps['aria-invalid']);\n\n // Through the commit path: the default is emitted as local midnight, and only when it names\n // another day; the typed text and its error are dropped.\n useFormReset(inputRef, () => commitDate(defaultValue ?? null), form);\n\n // Read-only pickers offer no clear action (the value cannot change).\n const showClear = clearable && !readOnly && selectedDate !== null;\n\n /* ---- handlers ---------------------------------------------------- */\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (!interactive) return;\n setDraft(event.target.value);\n setInvalid(null);\n };\n\n const handleInputKeyDown = composeEventHandlers(\n onKeyDown,\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n // Keys that belong to an IME composition (its confirming Enter) are left to the IME.\n if (!interactive || event.nativeEvent.isComposing) return;\n if (event.key === 'Enter' && draft !== null) {\n // An edit is committed instead of submitting the form; untouched text lets Enter submit.\n event.preventDefault();\n commitDraft(draft);\n } else if (\n event.key === 'Tab' &&\n !event.shiftKey &&\n showClear &&\n draft !== null &&\n !draft.trim()\n ) {\n // Erased text clears the value, and with it the clear button, the next tab stop. It is\n // settled before Tab moves focus (the blur would settle it while focus moves to that\n // button), so focus moves on to the calendar button instead of dropping to <body> with\n // the clear button (C-DISABLED).\n flushSync(() => commitDraft(draft));\n } else if (event.key === 'ArrowDown' && event.altKey && !isOpen) {\n event.preventDefault();\n // The edit is committed first, so the calendar opens on the typed month; rejected text is\n // kept and reported once (the blur that follows does not report it again).\n if (draft !== null && invalid === null) commitDraft(draft);\n setOpenedFromInput(true);\n setOpen(true);\n }\n },\n );\n\n const handleInputBlur = composeEventHandlers(onBlur, () => {\n // Text already rejected (Enter, Alt+ArrowDown) is kept without being reported again.\n if (interactive && draft !== null && invalid === null) commitDraft(draft);\n });\n\n const handleToggle = () => {\n if (!interactive) return;\n restoreTargetRef.current = null;\n setOpenedFromInput(false);\n setOpen(!isOpen);\n };\n\n const handleClear = () => {\n if (!interactive) return;\n commitDate(null);\n inputRef.current?.focus();\n };\n\n // The clear button keeps focus on the input: its blur would otherwise commit (or reject) the\n // edited text just before the clear, emitting twice for one click.\n const handleClearMouseDown = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault();\n };\n\n const selectDate = (day: Date) => {\n if (!interactive || isUnavailable(day)) return;\n commitDate(day);\n close(inputRef.current);\n };\n\n const handleDialogKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key !== 'Escape' || event.defaultPrevented || event.nativeEvent.isComposing) return;\n // Consumed here, so enclosing layers (a Dialog around the picker) ignore it.\n event.preventDefault();\n close(openedFromInput ? inputRef.current : null);\n };\n\n const handleGridKeyDown = (event: React.KeyboardEvent<HTMLTableElement>) => {\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n const weekOffset = (focusTarget.getDay() - firstDayOfWeek + 7) % 7;\n let next: Date;\n switch (event.key) {\n case 'ArrowLeft':\n case 'ArrowRight': {\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(event.currentTarget),\n });\n next = addDays(focusTarget, intent === 'next' ? 1 : -1);\n break;\n }\n case 'ArrowDown':\n next = addDays(focusTarget, 7);\n break;\n case 'ArrowUp':\n next = addDays(focusTarget, -7);\n break;\n case 'PageDown':\n next = addMonths(focusTarget, event.shiftKey ? 12 : 1);\n break;\n case 'PageUp':\n next = addMonths(focusTarget, event.shiftKey ? -12 : -1);\n break;\n case 'Home':\n next = addDays(focusTarget, -weekOffset);\n break;\n case 'End':\n next = addDays(focusTarget, 6 - weekOffset);\n break;\n default:\n // Enter and Space activate the focused day button natively (click).\n return;\n }\n event.preventDefault();\n moveFocus(next);\n };\n\n /* ---- render ------------------------------------------------------ */\n\n const inputText = draft ?? (selectedDate ? format(selectedDate) : '');\n\n let errorMessage = '';\n if (invalid === 'unparseable') {\n errorMessage = (labels?.invalidDate ?? defaultInvalidDateLabel)(\n hasCustomParse ? undefined : getLocaleDateFormat(locale).pattern,\n );\n } else if (invalid === 'out-of-range' && (minDate || maxDate)) {\n errorMessage = (labels?.outOfRange ?? defaultOutOfRangeLabel)(\n minDate ? format(startOfDay(minDate)) : undefined,\n maxDate ? format(startOfDay(maxDate)) : undefined,\n );\n } else if (invalid === 'disabled') {\n errorMessage = labels?.unavailableDate ?? 'This date is not available.';\n }\n\n return (\n <div\n {...rest}\n ref={ref}\n className={cn(datePickerClassNames.root, 'relative inline-flex flex-col', className)}\n >\n <div ref={setReference} className=\"relative flex items-center\">\n <input\n ref={inputRefs}\n type=\"text\"\n {...fieldProps}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n value={inputText}\n onChange={handleInputChange}\n onFocus={onFocus}\n onBlur={handleInputBlur}\n onKeyDown={handleInputKeyDown}\n onKeyUp={onKeyUp}\n placeholder={placeholder}\n disabled={disabled}\n readOnly={readOnly}\n autoComplete={autoComplete}\n autoCapitalize={autoCapitalize}\n autoCorrect={autoCorrect}\n enterKeyHint={enterKeyHint}\n inputMode={inputMode}\n spellCheck={spellCheck}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n className={cn(\n datePickerClassNames.input,\n inputBase,\n 'border-b-stroke-accessible',\n inputFocus,\n disabledStyles,\n invalidLook && inputInvalid,\n showClear ? 'pe-14' : 'pe-8',\n )}\n />\n {showClear && (\n <button\n type=\"button\"\n aria-label={labels?.clear ?? 'Clear date'}\n disabled={disabled}\n onMouseDown={handleClearMouseDown}\n onClick={handleClear}\n className={cn(\n datePickerClassNames.clearButton,\n ICON_BUTTON_CLASSES,\n 'end-7',\n focusRing,\n disabledStyles,\n )}\n >\n <DismissIcon />\n </button>\n )}\n <button\n ref={toggleRef}\n type=\"button\"\n aria-label={labels?.openCalendar ?? 'Open calendar'}\n aria-haspopup=\"dialog\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? dialogId : undefined}\n disabled={disabled || readOnly}\n onClick={handleToggle}\n className={cn(\n datePickerClassNames.openCalendarButton,\n ICON_BUTTON_CLASSES,\n 'end-1',\n focusRing,\n disabledStyles,\n )}\n >\n <CalendarIcon />\n </button>\n </div>\n {showOwnError && (\n <p\n id={errorId}\n role=\"alert\"\n className={cn(datePickerClassNames.errorMessage, 'mt-1 text-caption-1 text-error')}\n >\n {errorMessage}\n </p>\n )}\n <HiddenInput\n name={name}\n form={form}\n disabled={disabled}\n value={selectedDate ? formatISODate(selectedDate) : ''}\n type=\"text\"\n required={validates}\n onInvalid={() => inputRef.current?.focus()}\n />\n {isOpen && (\n <Portal layerId={layerId}>\n <div\n ref={surfaceRefs}\n id={dialogId}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={headingId}\n {...floatingProps}\n data-state=\"open\"\n onKeyDown={handleDialogKeyDown}\n className={cn(\n datePickerClassNames.surface,\n 'rounded-md border border-border bg-background p-3 text-foreground shadow-16',\n )}\n >\n <div\n className={cn(\n datePickerClassNames.header,\n 'mb-2 flex items-center justify-between gap-2',\n )}\n >\n <button\n type=\"button\"\n aria-label={labels?.previousMonth ?? 'Previous month'}\n aria-controls={gridId}\n {...focusableDisabledProps(previousDisabled)}\n onClick={preventIfDisabled(previousDisabled, () => navigateMonth(-1))}\n className={cn(\n datePickerClassNames.previousMonthButton,\n NAV_BUTTON_CLASSES,\n focusRing,\n disabledStyles,\n )}\n >\n <ChevronLeftIcon className=\"wave-rtl:-scale-x-100\" />\n </button>\n <h2\n id={headingId}\n aria-live=\"polite\"\n className={cn(datePickerClassNames.heading, 'text-body-1 font-semibold')}\n >\n {formatMonthYear(viewMonth, locale)}\n </h2>\n <button\n type=\"button\"\n aria-label={labels?.nextMonth ?? 'Next month'}\n aria-controls={gridId}\n {...focusableDisabledProps(nextDisabled)}\n onClick={preventIfDisabled(nextDisabled, () => navigateMonth(1))}\n className={cn(\n datePickerClassNames.nextMonthButton,\n NAV_BUTTON_CLASSES,\n focusRing,\n disabledStyles,\n )}\n >\n <ChevronRightIcon className=\"wave-rtl:-scale-x-100\" />\n </button>\n </div>\n <table\n ref={gridRef}\n id={gridId}\n role=\"grid\"\n aria-labelledby={headingId}\n onKeyDown={handleGridKeyDown}\n className={cn(datePickerClassNames.grid, 'border-collapse')}\n >\n <thead>\n <tr>\n {weekdays.map((weekday) => (\n <th\n key={weekday.long}\n scope=\"col\"\n abbr={weekday.long}\n aria-label={weekday.long}\n className={cn(\n datePickerClassNames.weekday,\n 'h-8 w-8 text-center text-caption-1 font-normal text-muted-foreground',\n )}\n >\n <span aria-hidden=\"true\">{weekday.short}</span>\n <span className=\"sr-only\">{weekday.long}</span>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {weeks.map((week, row) => (\n // Rows and cells are keyed by position, so the focused button survives a\n // month change and focus stays in the grid while it moves to the new day.\n <tr key={row}>\n {week.map((day, column) => {\n const iso = formatISODate(day);\n const isSelected = isSameDay(day, selectedDate);\n const isToday = isSameDay(day, today);\n const isFocused = iso === focusIso;\n const unavailable = isUnavailable(day);\n return (\n <td key={column} role=\"gridcell\" aria-selected={isSelected} className=\"p-0\">\n {/* Focus rests on the button, and screen readers do not reliably\n announce the gridcell's aria-selected from inside it: the selected\n day's button is also pressed. */}\n <button\n type=\"button\"\n tabIndex={isFocused ? 0 : -1}\n aria-label={formatDayLabel(day, locale)}\n aria-pressed={isSelected || undefined}\n aria-current={isToday ? 'date' : undefined}\n {...focusableDisabledProps(unavailable)}\n data-date={iso}\n data-selected={isSelected ? '' : undefined}\n data-today={isToday ? '' : undefined}\n data-outside={isSameMonth(day, viewMonth) ? undefined : ''}\n onFocus={() => handleDayFocus(day)}\n onClick={() => selectDate(day)}\n className={cn(\n datePickerClassNames.day,\n DAY_CLASSES,\n focusRing,\n disabledStyles,\n isSelected && forcedColors.selectedLeaf,\n )}\n >\n {formatDayNumber(day, locale)}\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </Portal>\n )}\n </div>\n );\n};\n\nDatePicker.displayName = 'DatePicker';\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"),ee=require("../../lib/dev.cjs"),n=require("../../lib/composeEventHandlers.cjs"),r=require("../../lib/classNames.cjs"),i=require("../../hooks/useControllable.cjs"),a=require("../../hooks/useMergedRefs.cjs"),o=require("../../hooks/useFieldControl.cjs"),s=require("../../lib/styles.cjs"),c=require("../../lib/icons.cjs"),l=require("./Input.cjs"),u=require("../../hooks/useFormReset.cjs"),te=require("../internal/HiddenInput.cjs"),d=require("../../hooks/useListbox.cjs"),ne=require("./pickerStyles.cjs"),f=require("./Option.cjs");let p=require("react");p=e.__toESM(p,1);let m=require("react/jsx-runtime");var h=e=>{let{value:h,defaultValue:g,onValueChange:_,onOptionSelect:v,open:y,defaultOpen:re,onOpenChange:ie,placeholder:ae=`Select an option`,disabled:b=!1,name:oe,form:x,required:S,clearable:se=!1,labels:ce,autoFocus:le,tabIndex:ue,id:de,"aria-label":fe,"aria-labelledby":pe,"aria-describedby":C,"aria-invalid":w,"aria-required":T,"aria-errormessage":E,"aria-details":D,onFocus:O,onBlur:k,onKeyDown:A,onKeyUp:j,controlRef:M,className:N,children:P,ref:F,...I}=e;v!==void 0&&ee.warnDeprecated(`Dropdown`,`onOptionSelect`,`onValueChange`);let L=o.useFieldContext(),R=S??L?.required??!1,z=o.useFieldControl({id:de,"aria-label":fe,"aria-labelledby":pe,"aria-describedby":C,"aria-invalid":w,"aria-required":T??S}),B=l.isInvalidLook(!1,z[`aria-invalid`]),[V,H]=i.useControllable(h,g??``,_),[U,W]=i.useControllable(y,(re??!1)&&!b,ie),G=U&&!b,K=b&&U;p.useEffect(()=>{K&&W(!1)},[K,W]);let q=p.useRef(null),J=p.useRef(null),me=p.useMemo(()=>d.collectOptionLabels(P),[P]),Y=d.useListbox({open:G,onOpenChange:e=>W(e),mode:`select-only`,selectedValues:V?[V]:[],onSelect:e=>{H(e),v?.(e)},idPrefix:`dropdown-listbox`}),X=G&&Y.items.length>0,{layerId:he,setReference:Z,surfaceRef:ge,floatingProps:_e}=f.useListboxPopup({open:G,surfaceOpen:X,onDismiss:()=>W(!1),rootRef:q,anchorRef:J}),ve=a.useMergedRefs(q,F),ye=a.useMergedRefs(J,M,Z);u.useFormReset(J,()=>H(g??``),x);let Q=V?Y.getItem(V)?.label??me.get(V)??``:``,be=e=>{if(e.key===`Escape`&&G&&!X&&!e.nativeEvent.isComposing){W(!1);return}Y.onKeyDown(e)},xe=()=>{H(``),W(!1),J.current?.focus()},$=se&&V!==``,Se=z[`aria-label`]===void 0?z[`aria-labelledby`]??L?.labelId:z[`aria-labelledby`];return(0,m.jsxs)(`div`,{...I,ref:ve,className:t.cn(r.dropdownClassNames.root,`relative inline-flex flex-col`,N),children:[(0,m.jsxs)(`div`,{className:`relative flex items-center`,children:[(0,m.jsxs)(`button`,{type:`button`,...z,...Y.getComboboxProps(),"aria-expanded":X,"aria-errormessage":E,"aria-details":D,ref:ye,disabled:b,autoFocus:le,tabIndex:ue,onClick:()=>W(e=>!e),onKeyDown:n.composeEventHandlers(A,be),onKeyUp:n.composeEventHandlers(j,Y.onKeyUp),onFocus:O,onBlur:k,className:t.cn(r.dropdownClassNames.button,`relative flex h-8 w-full items-center justify-between rounded border border-input border-b-stroke-accessible bg-background px-3 py-0 text-start text-body-1 text-foreground`,ne.pickerEndPadding($?2:1),s.inputFocus,s.disabledStyles,B&&`border-destructive focus:border-b-destructive`),children:[(0,m.jsx)(`span`,{className:t.cn(r.dropdownClassNames.value,`truncate`,!Q&&`text-muted-foreground`),children:Q||ae}),(0,m.jsx)(c.ChevronDownIcon,{className:t.cn(r.dropdownClassNames.expandIcon,`absolute end-3 transition-transform motion-reduce:transition-none`,X&&`rotate-180`)})]}),$&&(0,m.jsx)(`button`,{type:`button`,"aria-label":ce?.clear??`Clear selection`,disabled:b,onMouseDown:e=>e.preventDefault(),onClick:xe,className:t.cn(r.dropdownClassNames.clearButton,`absolute flex h-6 w-6 items-center justify-center rounded bg-transparent p-0 text-muted-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:hover:text-foreground`,`end-7`,`focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring`,`disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:focus-visible:opacity-100`),children:(0,m.jsx)(c.DismissIcon,{})})]}),(0,m.jsx)(f.ListboxSurface,{listbox:Y,layerId:he,surfaceRef:ge,floatingProps:_e,open:G,expanded:X,listboxClassName:r.dropdownClassNames.listbox,surfaceClassName:r.dropdownClassNames.surface,"aria-label":z[`aria-label`],"aria-labelledby":Se,children:P}),(0,m.jsx)(te.HiddenInput,{name:oe,form:x,disabled:b,value:V,type:`text`,required:R,onInvalid:()=>J.current?.focus()})]})};h.displayName=`Dropdown`;var g=f.Option,_=f.OptionGroup,v=Object.assign(h,{Option:f.Option,OptionGroup:f.OptionGroup});exports.Dropdown=v,exports.DropdownOption=g,exports.DropdownOptionGroup=_;
|
|
2
|
+
//# sourceMappingURL=Dropdown.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dropdown.cjs","names":["useFieldContext","useFieldControl","isInvalidLook","useControllable","React","collectOptionLabels","useListbox","useListboxPopup","useMergedRefs","cn","dropdownClassNames","composeEventHandlers","pickerEndPadding","inputFocus","disabledStyles","ChevronDownIcon","DismissIcon","ListboxSurface","HiddenInput","Option","OptionGroup","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_classNames","require_useControllable","require_useMergedRefs","require_useFieldControl","require_styles","require_icons","require_Input","require_useFormReset","require_HiddenInput","require_useListbox","require_pickerStyles","require_Option","react","react_jsx_runtime","DropdownRoot","valueProp","openProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","rest","props","onOptionSelect","field","isRequired","required","fieldProps","invalidLook","value","setValue","defaultValue","onValueChange","openState","setOpen","defaultOpen","disabled","onOpenChange","open","lockedOpen","rootRef","buttonRef","optionLabels","children","listbox","next","expanded","rootMergedRef","ref","buttonMergedRef","controlRef","setReference","form","displayText","handleKeyDown","event","handleClear","showClear","clearable","listLabelledBy","className","current","onKeyDown","onKeyUp","placeholder","labels","DropdownOption","DropdownOptionGroup","Dropdown"],"sources":["../../../src/components/input/Dropdown.tsx"],"sourcesContent":["import * as React from 'react';\nimport { dropdownClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated } from '../../lib/dev';\nimport { ChevronDownIcon, DismissIcon } from '../../lib/icons';\nimport { disabledStyles, focusRing, inputFocus, inputInvalid } from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { collectOptionLabels, useListbox } from '../../hooks/useListbox';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { isInvalidLook } from './Input';\nimport { ListboxSurface, Option, OptionGroup, useListboxPopup } from './Option';\nimport { PICKER_ICON_BUTTON_CLASSES, pickerEndPadding } from './pickerStyles';\nimport type { RoutedHandlers } from './routedHandlers';\n\n/* ------------------------------------------------------------------ */\n/* Dropdown */\n/* ------------------------------------------------------------------ */\n\n/**\n * The Dropdown's built-in texts, for localization. Each member is optional and falls back to its\n * English default.\n */\nexport interface DropdownLabels {\n /** Name of the clear button (`clearable`).\n * @default 'Clear selection'\n */\n clear?: string;\n}\n\n/** Properties for the Dropdown component. */\nexport interface DropdownProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | RoutedHandlers\n> {\n /** Controlled selected value (`''` for none). */\n value?: string;\n /**\n * Initial selected value for uncontrolled usage.\n * @default ''\n */\n defaultValue?: string;\n /** Called with the new value when a different option is selected. */\n onValueChange?: (value: string) => void;\n /**\n * Called on every option activation, also when the current option is selected again.\n * @deprecated Use `onValueChange`.\n */\n onOptionSelect?: (value: string) => void;\n /**\n * Controlled open state of the listbox. The list renders only in the browser: an open dropdown\n * is closed in the server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Initial open state for uncontrolled usage. A dropdown that starts disabled starts closed. The\n * list renders only in the browser: it is closed in the server HTML and opens once the dropdown\n * has hydrated.\n * @default false\n */\n defaultOpen?: boolean;\n /** Called when the listbox opens or closes. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Placeholder text shown when no value is selected. It is not an accessible name: label the\n * Dropdown with a `Field`, `aria-label` or `aria-labelledby`.\n * @default 'Select an option'\n */\n placeholder?: string;\n /**\n * Whether the dropdown is disabled and non-interactive. Turning it on while the listbox is open\n * closes it (`onOpenChange(false)`).\n * @default false\n */\n disabled?: boolean;\n /** Name of the value in form submissions (renders a hidden input). */\n name?: string;\n /** Id of the form the value belongs to, when the Dropdown is outside it. */\n form?: string;\n /** A value is required to submit the form (native constraint validation). */\n required?: boolean;\n /**\n * Shows a clear button while a value is selected (shown disabled while `disabled`). It clears\n * the value, closes the list and moves focus to the combobox button. It is a tab stop after it.\n * @default false\n */\n clearable?: boolean;\n /** The name of the clear button, for localization. Unset members keep their English defaults. */\n labels?: DropdownLabels;\n /** Called when the `<button role=\"combobox\">` receives focus (the root keeps other handlers). */\n onFocus?: React.FocusEventHandler<HTMLButtonElement>;\n /** Called when the `<button role=\"combobox\">` loses focus. */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /**\n * Called on a key press on the `<button role=\"combobox\">`, before the built-in listbox keys;\n * `event.preventDefault()` skips them.\n */\n onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Called when a key is released on the `<button role=\"combobox\">`. */\n onKeyUp?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Ref to the `<button role=\"combobox\">` (the focusable element). */\n controlRef?: React.Ref<HTMLButtonElement>;\n /** Ref to the root `<div>`. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\nconst DropdownRoot = (props: DropdownProps) => {\n const {\n value: valueProp,\n defaultValue,\n onValueChange,\n onOptionSelect,\n open: openProp,\n defaultOpen,\n onOpenChange,\n placeholder = 'Select an option',\n disabled = false,\n name,\n form,\n required,\n clearable = false,\n labels,\n autoFocus,\n tabIndex,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n controlRef,\n className,\n children,\n ref,\n ...rest\n } = props;\n\n if (onOptionSelect !== undefined) warnDeprecated('Dropdown', 'onOptionSelect', 'onValueChange');\n\n const field = useFieldContext();\n const isRequired = required ?? field?.required ?? false;\n const fieldProps = useFieldControl({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n // An explicit `required={false}` wins over a required Field, so aria-required matches\n // `isRequired`.\n 'aria-required': ariaRequired ?? required,\n });\n // The error look follows the resolved state: the consumer's `aria-invalid` or the Field's.\n const invalidLook = isInvalidLook(false, fieldProps['aria-invalid']);\n\n const [value, setValue] = useControllable(valueProp, defaultValue ?? '', onValueChange);\n // A dropdown that starts disabled never shows its list, so it starts closed (no close to report\n // later).\n const [openState, setOpen] = useControllable(\n openProp,\n (defaultOpen ?? false) && !disabled,\n onOpenChange,\n );\n const open = openState && !disabled;\n // Disabling also closes the list itself, not only the derived `open`, so enabling it again does\n // not reopen it without a user action. The close is reported through onOpenChange (a consumer\n // callback from an effect, C-HOOKS); a controlled `open` that stays true is not shown meanwhile.\n const lockedOpen = disabled && openState;\n React.useEffect(() => {\n if (lockedOpen) setOpen(false);\n }, [lockedOpen, setOpen]);\n\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const buttonRef = React.useRef<HTMLButtonElement | null>(null);\n\n const optionLabels = React.useMemo(() => collectOptionLabels(children), [children]);\n\n const listbox = useListbox({\n open,\n onOpenChange: (next) => setOpen(next),\n mode: 'select-only',\n selectedValues: value ? [value] : [],\n onSelect: (next) => {\n setValue(next);\n onOptionSelect?.(next);\n },\n idPrefix: 'dropdown-listbox',\n });\n\n const expanded = open && listbox.items.length > 0;\n const { layerId, setReference, surfaceRef, floatingProps } = useListboxPopup({\n open,\n surfaceOpen: expanded,\n onDismiss: () => setOpen(false),\n rootRef,\n anchorRef: buttonRef,\n });\n\n const rootMergedRef = useMergedRefs<HTMLDivElement>(rootRef, ref);\n const buttonMergedRef = useMergedRefs<HTMLButtonElement>(buttonRef, controlRef, setReference);\n\n useFormReset(buttonRef, () => setValue(defaultValue ?? ''), form);\n\n const displayText = value ? (listbox.getItem(value)?.label ?? optionLabels.get(value) ?? '') : '';\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (event.key === 'Escape' && open && !expanded && !event.nativeEvent.isComposing) {\n // Open with nothing shown (no options): close, but leave Escape to an enclosing layer\n // (overlays#1) instead of consuming it for an invisible list.\n setOpen(false);\n return;\n }\n listbox.onKeyDown(event);\n };\n\n // The button disappears with the value, so focus moves to the combobox explicitly (C-DISABLED).\n const handleClear = () => {\n setValue('');\n setOpen(false);\n buttonRef.current?.focus();\n };\n\n const showClear = clearable && value !== '';\n\n const listLabelledBy =\n fieldProps['aria-label'] === undefined\n ? (fieldProps['aria-labelledby'] ?? field?.labelId)\n : fieldProps['aria-labelledby'];\n\n return (\n <div\n {...rest}\n ref={rootMergedRef}\n className={cn(dropdownClassNames.root, 'relative inline-flex flex-col', className)}\n >\n <div className=\"relative flex items-center\">\n <button\n type=\"button\"\n {...fieldProps}\n {...listbox.getComboboxProps()}\n aria-expanded={expanded}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n ref={buttonMergedRef}\n disabled={disabled}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n onClick={() => setOpen((current) => !current)}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyUp={composeEventHandlers(onKeyUp, listbox.onKeyUp)}\n onFocus={onFocus}\n onBlur={onBlur}\n className={cn(\n dropdownClassNames.button,\n // Every padding is set here (C-NATIVE), not left to an app-wide `button` rule. The end\n // padding keeps the text clear of the chevron (and of the clear button while it shows).\n 'relative flex h-8 w-full items-center justify-between rounded border border-input border-b-stroke-accessible bg-background px-3 py-0 text-start text-body-1 text-foreground',\n pickerEndPadding(showClear ? 2 : 1),\n inputFocus,\n disabledStyles,\n invalidLook && inputInvalid,\n )}\n >\n <span\n className={cn(\n dropdownClassNames.value,\n 'truncate',\n !displayText && 'text-muted-foreground',\n )}\n >\n {displayText || placeholder}\n </span>\n <ChevronDownIcon\n className={cn(\n dropdownClassNames.expandIcon,\n 'absolute end-3 transition-transform motion-reduce:transition-none',\n expanded && 'rotate-180',\n )}\n />\n </button>\n {showClear && (\n <button\n type=\"button\"\n aria-label={labels?.clear ?? 'Clear selection'}\n disabled={disabled}\n // Keeps focus on the combobox while the pointer clears it.\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n className={cn(\n dropdownClassNames.clearButton,\n PICKER_ICON_BUTTON_CLASSES,\n 'end-7',\n focusRing,\n disabledStyles,\n )}\n >\n <DismissIcon />\n </button>\n )}\n </div>\n <ListboxSurface\n listbox={listbox}\n layerId={layerId}\n surfaceRef={surfaceRef}\n floatingProps={floatingProps}\n open={open}\n expanded={expanded}\n listboxClassName={dropdownClassNames.listbox}\n surfaceClassName={dropdownClassNames.surface}\n aria-label={fieldProps['aria-label']}\n aria-labelledby={listLabelledBy}\n >\n {children}\n </ListboxSurface>\n <HiddenInput\n name={name}\n form={form}\n disabled={disabled}\n value={value}\n type=\"text\"\n required={isRequired}\n onInvalid={() => buttonRef.current?.focus()}\n />\n </div>\n );\n};\nDropdownRoot.displayName = 'Dropdown';\n\n/** Flat name of `Dropdown.Option` for React Server Components. */\nexport const DropdownOption = Option;\n/** Flat name of `Dropdown.OptionGroup` for React Server Components. */\nexport const DropdownOptionGroup = OptionGroup;\n\n/**\n * A select-only combobox (APG): a button that opens a listbox of `Option`s. Enter, Space,\n * ArrowDown/ArrowUp, Home/End and typing a character open it and move the highlight\n * (`aria-activedescendant`); Enter/Space select, Tab selects the highlighted option and moves on,\n * Escape closes. `clearable` adds a clear button, a tab stop after the combobox button; both sit\n * in a wrapper `<div>` inside the root.\n *\n * The `<button>` receives `id`, `aria-label`, `aria-labelledby`, `aria-describedby`,\n * `aria-invalid`, `aria-required`, `aria-errormessage`, `aria-details`, `tabIndex`, `autoFocus`\n * and `onFocus`/`onBlur`/`onKeyDown`/`onKeyUp`. `ref`, `className`, `style`, other `aria-*`\n * attributes and the remaining props stay on the root `<div>`. Inside a `Field` the button is\n * labelled and described by it — otherwise give it an `aria-label`. It shows the error look\n * whenever it ends up `aria-invalid` (its own `aria-invalid` or a `Field` error). With\n * `name`/`required` the value takes part in form submission, validation and reset. The open\n * listbox renders in a portal; while closed it stays in the DOM, hidden.\n *\n * Sub-components: `Dropdown.Option`, `Dropdown.OptionGroup`. React Server Components import the\n * flat names `DropdownOption` / `DropdownOptionGroup` (dotted access needs a client file).\n */\nexport const Dropdown = /* @__PURE__ */ Object.assign(DropdownRoot, {\n Option,\n OptionGroup,\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../../lib/cn.mjs";
|
|
3
|
+
import { warnDeprecated as ee } from "../../lib/dev.mjs";
|
|
4
|
+
import { composeEventHandlers as t } from "../../lib/composeEventHandlers.mjs";
|
|
5
|
+
import { dropdownClassNames as n } from "../../lib/classNames.mjs";
|
|
6
|
+
import { useControllable as r } from "../../hooks/useControllable.mjs";
|
|
7
|
+
import { useMergedRefs as i } from "../../hooks/useMergedRefs.mjs";
|
|
8
|
+
import { useFieldContext as te, useFieldControl as ne } from "../../hooks/useFieldControl.mjs";
|
|
9
|
+
import { disabledStyles as re, inputFocus as ie } from "../../lib/styles.mjs";
|
|
10
|
+
import { ChevronDownIcon as ae, DismissIcon as oe } from "../../lib/icons.mjs";
|
|
11
|
+
import { isInvalidLook as se } from "./Input.mjs";
|
|
12
|
+
import { useFormReset as ce } from "../../hooks/useFormReset.mjs";
|
|
13
|
+
import { HiddenInput as le } from "../internal/HiddenInput.mjs";
|
|
14
|
+
import { collectOptionLabels as ue, useListbox as a } from "../../hooks/useListbox.mjs";
|
|
15
|
+
import { pickerEndPadding as o } from "./pickerStyles.mjs";
|
|
16
|
+
import { ListboxSurface as s, Option as c, OptionGroup as l, useListboxPopup as de } from "./Option.mjs";
|
|
17
|
+
import * as u from "react";
|
|
18
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
19
|
+
//#region src/components/input/Dropdown.tsx
|
|
20
|
+
var p = (c) => {
|
|
21
|
+
let { value: l, defaultValue: p, onValueChange: m, onOptionSelect: h, open: g, defaultOpen: fe, onOpenChange: pe, placeholder: me = "Select an option", disabled: _ = !1, name: he, form: v, required: y, clearable: b = !1, labels: x, autoFocus: S, tabIndex: C, id: w, "aria-label": T, "aria-labelledby": E, "aria-describedby": D, "aria-invalid": O, "aria-required": k, "aria-errormessage": A, "aria-details": j, onFocus: M, onBlur: N, onKeyDown: P, onKeyUp: F, controlRef: I, className: L, children: R, ref: ge, ..._e } = c;
|
|
22
|
+
h !== void 0 && ee("Dropdown", "onOptionSelect", "onValueChange");
|
|
23
|
+
let z = te(), ve = y ?? z?.required ?? !1, B = ne({
|
|
24
|
+
id: w,
|
|
25
|
+
"aria-label": T,
|
|
26
|
+
"aria-labelledby": E,
|
|
27
|
+
"aria-describedby": D,
|
|
28
|
+
"aria-invalid": O,
|
|
29
|
+
"aria-required": k ?? y
|
|
30
|
+
}), ye = se(!1, B["aria-invalid"]), [V, H] = r(l, p ?? "", m), [U, W] = r(g, (fe ?? !1) && !_, pe), G = U && !_, K = _ && U;
|
|
31
|
+
u.useEffect(() => {
|
|
32
|
+
K && W(!1);
|
|
33
|
+
}, [K, W]);
|
|
34
|
+
let q = u.useRef(null), J = u.useRef(null), be = u.useMemo(() => ue(R), [R]), Y = a({
|
|
35
|
+
open: G,
|
|
36
|
+
onOpenChange: (e) => W(e),
|
|
37
|
+
mode: "select-only",
|
|
38
|
+
selectedValues: V ? [V] : [],
|
|
39
|
+
onSelect: (e) => {
|
|
40
|
+
H(e), h?.(e);
|
|
41
|
+
},
|
|
42
|
+
idPrefix: "dropdown-listbox"
|
|
43
|
+
}), X = G && Y.items.length > 0, { layerId: xe, setReference: Se, surfaceRef: Ce, floatingProps: we } = de({
|
|
44
|
+
open: G,
|
|
45
|
+
surfaceOpen: X,
|
|
46
|
+
onDismiss: () => W(!1),
|
|
47
|
+
rootRef: q,
|
|
48
|
+
anchorRef: J
|
|
49
|
+
}), Te = i(q, ge), Z = i(J, I, Se);
|
|
50
|
+
ce(J, () => H(p ?? ""), v);
|
|
51
|
+
let Q = V ? Y.getItem(V)?.label ?? be.get(V) ?? "" : "", Ee = (e) => {
|
|
52
|
+
if (e.key === "Escape" && G && !X && !e.nativeEvent.isComposing) {
|
|
53
|
+
W(!1);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
Y.onKeyDown(e);
|
|
57
|
+
}, De = () => {
|
|
58
|
+
H(""), W(!1), J.current?.focus();
|
|
59
|
+
}, $ = b && V !== "", Oe = B["aria-label"] === void 0 ? B["aria-labelledby"] ?? z?.labelId : B["aria-labelledby"];
|
|
60
|
+
return /* @__PURE__ */ f("div", {
|
|
61
|
+
..._e,
|
|
62
|
+
ref: Te,
|
|
63
|
+
className: e(n.root, "relative inline-flex flex-col", L),
|
|
64
|
+
children: [
|
|
65
|
+
/* @__PURE__ */ f("div", {
|
|
66
|
+
className: "relative flex items-center",
|
|
67
|
+
children: [/* @__PURE__ */ f("button", {
|
|
68
|
+
type: "button",
|
|
69
|
+
...B,
|
|
70
|
+
...Y.getComboboxProps(),
|
|
71
|
+
"aria-expanded": X,
|
|
72
|
+
"aria-errormessage": A,
|
|
73
|
+
"aria-details": j,
|
|
74
|
+
ref: Z,
|
|
75
|
+
disabled: _,
|
|
76
|
+
autoFocus: S,
|
|
77
|
+
tabIndex: C,
|
|
78
|
+
onClick: () => W((e) => !e),
|
|
79
|
+
onKeyDown: t(P, Ee),
|
|
80
|
+
onKeyUp: t(F, Y.onKeyUp),
|
|
81
|
+
onFocus: M,
|
|
82
|
+
onBlur: N,
|
|
83
|
+
className: e(n.button, "relative flex h-8 w-full items-center justify-between rounded border border-input border-b-stroke-accessible bg-background px-3 py-0 text-start text-body-1 text-foreground", o($ ? 2 : 1), ie, re, ye && "border-destructive focus:border-b-destructive"),
|
|
84
|
+
children: [/* @__PURE__ */ d("span", {
|
|
85
|
+
className: e(n.value, "truncate", !Q && "text-muted-foreground"),
|
|
86
|
+
children: Q || me
|
|
87
|
+
}), /* @__PURE__ */ d(ae, { className: e(n.expandIcon, "absolute end-3 transition-transform motion-reduce:transition-none", X && "rotate-180") })]
|
|
88
|
+
}), $ && /* @__PURE__ */ d("button", {
|
|
89
|
+
type: "button",
|
|
90
|
+
"aria-label": x?.clear ?? "Clear selection",
|
|
91
|
+
disabled: _,
|
|
92
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
93
|
+
onClick: De,
|
|
94
|
+
className: e(n.clearButton, "absolute flex h-6 w-6 items-center justify-center rounded bg-transparent p-0 text-muted-foreground not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:hover:text-foreground", "end-7", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", "disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:focus-visible:opacity-100"),
|
|
95
|
+
children: /* @__PURE__ */ d(oe, {})
|
|
96
|
+
})]
|
|
97
|
+
}),
|
|
98
|
+
/* @__PURE__ */ d(s, {
|
|
99
|
+
listbox: Y,
|
|
100
|
+
layerId: xe,
|
|
101
|
+
surfaceRef: Ce,
|
|
102
|
+
floatingProps: we,
|
|
103
|
+
open: G,
|
|
104
|
+
expanded: X,
|
|
105
|
+
listboxClassName: n.listbox,
|
|
106
|
+
surfaceClassName: n.surface,
|
|
107
|
+
"aria-label": B["aria-label"],
|
|
108
|
+
"aria-labelledby": Oe,
|
|
109
|
+
children: R
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ d(le, {
|
|
112
|
+
name: he,
|
|
113
|
+
form: v,
|
|
114
|
+
disabled: _,
|
|
115
|
+
value: V,
|
|
116
|
+
type: "text",
|
|
117
|
+
required: ve,
|
|
118
|
+
onInvalid: () => J.current?.focus()
|
|
119
|
+
})
|
|
120
|
+
]
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
p.displayName = "Dropdown";
|
|
124
|
+
var m = c, h = l, g = /* @__PURE__ */ Object.assign(p, {
|
|
125
|
+
Option: c,
|
|
126
|
+
OptionGroup: l
|
|
127
|
+
});
|
|
128
|
+
//#endregion
|
|
129
|
+
export { g as Dropdown, m as DropdownOption, h as DropdownOptionGroup };
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=Dropdown.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dropdown.mjs","names":["React","DropdownRoot","valueProp","openProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","rest","props","onOptionSelect","warnDeprecated","field","useFieldContext","isRequired","required","fieldProps","useFieldControl","invalidLook","isInvalidLook","value","setValue","useControllable","defaultValue","onValueChange","openState","setOpen","defaultOpen","disabled","onOpenChange","open","lockedOpen","rootRef","buttonRef","optionLabels","collectOptionLabels","children","listbox","useListbox","next","expanded","useListboxPopup","rootMergedRef","useMergedRefs","ref","buttonMergedRef","controlRef","setReference","form","displayText","handleKeyDown","event","handleClear","showClear","clearable","listLabelledBy","cn","dropdownClassNames","className","current","composeEventHandlers","onKeyDown","onKeyUp","pickerEndPadding","inputFocus","disabledStyles","placeholder","ChevronDownIcon","labels","DismissIcon","ListboxSurface","HiddenInput","DropdownOption","Option","DropdownOptionGroup","OptionGroup","Dropdown"],"sources":["../../../src/components/input/Dropdown.tsx"],"sourcesContent":["import * as React from 'react';\nimport { dropdownClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated } from '../../lib/dev';\nimport { ChevronDownIcon, DismissIcon } from '../../lib/icons';\nimport { disabledStyles, focusRing, inputFocus, inputInvalid } from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldContext, useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { collectOptionLabels, useListbox } from '../../hooks/useListbox';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { isInvalidLook } from './Input';\nimport { ListboxSurface, Option, OptionGroup, useListboxPopup } from './Option';\nimport { PICKER_ICON_BUTTON_CLASSES, pickerEndPadding } from './pickerStyles';\nimport type { RoutedHandlers } from './routedHandlers';\n\n/* ------------------------------------------------------------------ */\n/* Dropdown */\n/* ------------------------------------------------------------------ */\n\n/**\n * The Dropdown's built-in texts, for localization. Each member is optional and falls back to its\n * English default.\n */\nexport interface DropdownLabels {\n /** Name of the clear button (`clearable`).\n * @default 'Clear selection'\n */\n clear?: string;\n}\n\n/** Properties for the Dropdown component. */\nexport interface DropdownProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | RoutedHandlers\n> {\n /** Controlled selected value (`''` for none). */\n value?: string;\n /**\n * Initial selected value for uncontrolled usage.\n * @default ''\n */\n defaultValue?: string;\n /** Called with the new value when a different option is selected. */\n onValueChange?: (value: string) => void;\n /**\n * Called on every option activation, also when the current option is selected again.\n * @deprecated Use `onValueChange`.\n */\n onOptionSelect?: (value: string) => void;\n /**\n * Controlled open state of the listbox. The list renders only in the browser: an open dropdown\n * is closed in the server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Initial open state for uncontrolled usage. A dropdown that starts disabled starts closed. The\n * list renders only in the browser: it is closed in the server HTML and opens once the dropdown\n * has hydrated.\n * @default false\n */\n defaultOpen?: boolean;\n /** Called when the listbox opens or closes. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Placeholder text shown when no value is selected. It is not an accessible name: label the\n * Dropdown with a `Field`, `aria-label` or `aria-labelledby`.\n * @default 'Select an option'\n */\n placeholder?: string;\n /**\n * Whether the dropdown is disabled and non-interactive. Turning it on while the listbox is open\n * closes it (`onOpenChange(false)`).\n * @default false\n */\n disabled?: boolean;\n /** Name of the value in form submissions (renders a hidden input). */\n name?: string;\n /** Id of the form the value belongs to, when the Dropdown is outside it. */\n form?: string;\n /** A value is required to submit the form (native constraint validation). */\n required?: boolean;\n /**\n * Shows a clear button while a value is selected (shown disabled while `disabled`). It clears\n * the value, closes the list and moves focus to the combobox button. It is a tab stop after it.\n * @default false\n */\n clearable?: boolean;\n /** The name of the clear button, for localization. Unset members keep their English defaults. */\n labels?: DropdownLabels;\n /** Called when the `<button role=\"combobox\">` receives focus (the root keeps other handlers). */\n onFocus?: React.FocusEventHandler<HTMLButtonElement>;\n /** Called when the `<button role=\"combobox\">` loses focus. */\n onBlur?: React.FocusEventHandler<HTMLButtonElement>;\n /**\n * Called on a key press on the `<button role=\"combobox\">`, before the built-in listbox keys;\n * `event.preventDefault()` skips them.\n */\n onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Called when a key is released on the `<button role=\"combobox\">`. */\n onKeyUp?: React.KeyboardEventHandler<HTMLButtonElement>;\n /** Ref to the `<button role=\"combobox\">` (the focusable element). */\n controlRef?: React.Ref<HTMLButtonElement>;\n /** Ref to the root `<div>`. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\nconst DropdownRoot = (props: DropdownProps) => {\n const {\n value: valueProp,\n defaultValue,\n onValueChange,\n onOptionSelect,\n open: openProp,\n defaultOpen,\n onOpenChange,\n placeholder = 'Select an option',\n disabled = false,\n name,\n form,\n required,\n clearable = false,\n labels,\n autoFocus,\n tabIndex,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-errormessage': ariaErrorMessage,\n 'aria-details': ariaDetails,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n controlRef,\n className,\n children,\n ref,\n ...rest\n } = props;\n\n if (onOptionSelect !== undefined) warnDeprecated('Dropdown', 'onOptionSelect', 'onValueChange');\n\n const field = useFieldContext();\n const isRequired = required ?? field?.required ?? false;\n const fieldProps = useFieldControl({\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n // An explicit `required={false}` wins over a required Field, so aria-required matches\n // `isRequired`.\n 'aria-required': ariaRequired ?? required,\n });\n // The error look follows the resolved state: the consumer's `aria-invalid` or the Field's.\n const invalidLook = isInvalidLook(false, fieldProps['aria-invalid']);\n\n const [value, setValue] = useControllable(valueProp, defaultValue ?? '', onValueChange);\n // A dropdown that starts disabled never shows its list, so it starts closed (no close to report\n // later).\n const [openState, setOpen] = useControllable(\n openProp,\n (defaultOpen ?? false) && !disabled,\n onOpenChange,\n );\n const open = openState && !disabled;\n // Disabling also closes the list itself, not only the derived `open`, so enabling it again does\n // not reopen it without a user action. The close is reported through onOpenChange (a consumer\n // callback from an effect, C-HOOKS); a controlled `open` that stays true is not shown meanwhile.\n const lockedOpen = disabled && openState;\n React.useEffect(() => {\n if (lockedOpen) setOpen(false);\n }, [lockedOpen, setOpen]);\n\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const buttonRef = React.useRef<HTMLButtonElement | null>(null);\n\n const optionLabels = React.useMemo(() => collectOptionLabels(children), [children]);\n\n const listbox = useListbox({\n open,\n onOpenChange: (next) => setOpen(next),\n mode: 'select-only',\n selectedValues: value ? [value] : [],\n onSelect: (next) => {\n setValue(next);\n onOptionSelect?.(next);\n },\n idPrefix: 'dropdown-listbox',\n });\n\n const expanded = open && listbox.items.length > 0;\n const { layerId, setReference, surfaceRef, floatingProps } = useListboxPopup({\n open,\n surfaceOpen: expanded,\n onDismiss: () => setOpen(false),\n rootRef,\n anchorRef: buttonRef,\n });\n\n const rootMergedRef = useMergedRefs<HTMLDivElement>(rootRef, ref);\n const buttonMergedRef = useMergedRefs<HTMLButtonElement>(buttonRef, controlRef, setReference);\n\n useFormReset(buttonRef, () => setValue(defaultValue ?? ''), form);\n\n const displayText = value ? (listbox.getItem(value)?.label ?? optionLabels.get(value) ?? '') : '';\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (event.key === 'Escape' && open && !expanded && !event.nativeEvent.isComposing) {\n // Open with nothing shown (no options): close, but leave Escape to an enclosing layer\n // (overlays#1) instead of consuming it for an invisible list.\n setOpen(false);\n return;\n }\n listbox.onKeyDown(event);\n };\n\n // The button disappears with the value, so focus moves to the combobox explicitly (C-DISABLED).\n const handleClear = () => {\n setValue('');\n setOpen(false);\n buttonRef.current?.focus();\n };\n\n const showClear = clearable && value !== '';\n\n const listLabelledBy =\n fieldProps['aria-label'] === undefined\n ? (fieldProps['aria-labelledby'] ?? field?.labelId)\n : fieldProps['aria-labelledby'];\n\n return (\n <div\n {...rest}\n ref={rootMergedRef}\n className={cn(dropdownClassNames.root, 'relative inline-flex flex-col', className)}\n >\n <div className=\"relative flex items-center\">\n <button\n type=\"button\"\n {...fieldProps}\n {...listbox.getComboboxProps()}\n aria-expanded={expanded}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n ref={buttonMergedRef}\n disabled={disabled}\n autoFocus={autoFocus}\n tabIndex={tabIndex}\n onClick={() => setOpen((current) => !current)}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyUp={composeEventHandlers(onKeyUp, listbox.onKeyUp)}\n onFocus={onFocus}\n onBlur={onBlur}\n className={cn(\n dropdownClassNames.button,\n // Every padding is set here (C-NATIVE), not left to an app-wide `button` rule. The end\n // padding keeps the text clear of the chevron (and of the clear button while it shows).\n 'relative flex h-8 w-full items-center justify-between rounded border border-input border-b-stroke-accessible bg-background px-3 py-0 text-start text-body-1 text-foreground',\n pickerEndPadding(showClear ? 2 : 1),\n inputFocus,\n disabledStyles,\n invalidLook && inputInvalid,\n )}\n >\n <span\n className={cn(\n dropdownClassNames.value,\n 'truncate',\n !displayText && 'text-muted-foreground',\n )}\n >\n {displayText || placeholder}\n </span>\n <ChevronDownIcon\n className={cn(\n dropdownClassNames.expandIcon,\n 'absolute end-3 transition-transform motion-reduce:transition-none',\n expanded && 'rotate-180',\n )}\n />\n </button>\n {showClear && (\n <button\n type=\"button\"\n aria-label={labels?.clear ?? 'Clear selection'}\n disabled={disabled}\n // Keeps focus on the combobox while the pointer clears it.\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n className={cn(\n dropdownClassNames.clearButton,\n PICKER_ICON_BUTTON_CLASSES,\n 'end-7',\n focusRing,\n disabledStyles,\n )}\n >\n <DismissIcon />\n </button>\n )}\n </div>\n <ListboxSurface\n listbox={listbox}\n layerId={layerId}\n surfaceRef={surfaceRef}\n floatingProps={floatingProps}\n open={open}\n expanded={expanded}\n listboxClassName={dropdownClassNames.listbox}\n surfaceClassName={dropdownClassNames.surface}\n aria-label={fieldProps['aria-label']}\n aria-labelledby={listLabelledBy}\n >\n {children}\n </ListboxSurface>\n <HiddenInput\n name={name}\n form={form}\n disabled={disabled}\n value={value}\n type=\"text\"\n required={isRequired}\n onInvalid={() => buttonRef.current?.focus()}\n />\n </div>\n );\n};\nDropdownRoot.displayName = 'Dropdown';\n\n/** Flat name of `Dropdown.Option` for React Server Components. */\nexport const DropdownOption = Option;\n/** Flat name of `Dropdown.OptionGroup` for React Server Components. */\nexport const DropdownOptionGroup = OptionGroup;\n\n/**\n * A select-only combobox (APG): a button that opens a listbox of `Option`s. Enter, Space,\n * ArrowDown/ArrowUp, Home/End and typing a character open it and move the highlight\n * (`aria-activedescendant`); Enter/Space select, Tab selects the highlighted option and moves on,\n * Escape closes. `clearable` adds a clear button, a tab stop after the combobox button; both sit\n * in a wrapper `<div>` inside the root.\n *\n * The `<button>` receives `id`, `aria-label`, `aria-labelledby`, `aria-describedby`,\n * `aria-invalid`, `aria-required`, `aria-errormessage`, `aria-details`, `tabIndex`, `autoFocus`\n * and `onFocus`/`onBlur`/`onKeyDown`/`onKeyUp`. `ref`, `className`, `style`, other `aria-*`\n * attributes and the remaining props stay on the root `<div>`. Inside a `Field` the button is\n * labelled and described by it — otherwise give it an `aria-label`. It shows the error look\n * whenever it ends up `aria-invalid` (its own `aria-invalid` or a `Field` error). With\n * `name`/`required` the value takes part in form submission, validation and reset. The open\n * listbox renders in a portal; while closed it stays in the DOM, hidden.\n *\n * Sub-components: `Dropdown.Option`, `Dropdown.OptionGroup`. React Server Components import the\n * flat names `DropdownOption` / `DropdownOptionGroup` (dotted access needs a client file).\n */\nexport const Dropdown = /* @__PURE__ */ Object.assign(DropdownRoot, {\n Option,\n OptionGroup,\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"),r=require("../../lib/slot.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useId.cjs"),o=require("../../lib/aria.cjs"),s=require("../../hooks/useFieldControl.cjs"),c=require("../../lib/icons.cjs");let l=require("react");l=e.__toESM(l,1);let u=require("react/jsx-runtime");var d=new Set([`button`,`input`,`meter`,`output`,`progress`,`select`,`textarea`]),f=new Set([`button`,`image`,`reset`,`submit`]),p=new Set([`caption`,`code`,`deletion`,`emphasis`,`generic`,`insertion`,`none`,`paragraph`,`presentation`,`strong`,`subscript`,`superscript`]),m=new Set([`checkbox`,`columnheader`,`combobox`,`gridcell`,`listbox`,`radiogroup`,`rowheader`,`searchbox`,`spinbutton`,`switch`,`textbox`,`tree`,`treegrid`]);function h(e){if(typeof e==`string`)return e.trim().split(/\s+/)[0]?.toLowerCase()||void 0}function g(e){return typeof e==`string`&&e.includes(`-`)}function _(e,t){return e===`select`||e===`textarea`?!0:e===`input`?typeof t!=`string`||!f.has(t.trim().toLowerCase()):!1}function v(e){if(typeof e.type!=`string`)return!0;let t=h(e.props.role);return t===void 0?_(e.type,e.props.type):m.has(t)}function y(e){if(e.type===l.Fragment)return;if(typeof e.type!=`string`||d.has(e.type))return`label-for`;let t=h(e.props.role);return t===void 0?g(e.type)?`label-for`:void 0:p.has(t)?void 0:`labelledby`}function b(e){let t,n=0;l.Children.forEach(e,e=>{l.isValidElement(e)&&(n+=1,t===void 0&&(t=e))});let r=t?y(t):void 0;return{target:r?t:void 0,mode:r,elementCount:n}}function x(e,t){let{target:n,mode:r}=b(e);if(!n||!r)return l.Children.map(e,e=>e);let i=n.props,a=!g(n.type)||`true`,s={};return r===`label-for`?i.id===void 0&&(s.id=t.controlId):t.labelId!==void 0&&i[`aria-label`]===void 0&&(s[`aria-labelledby`]=o.joinIds(i[`aria-labelledby`],t.labelId)),(t.messageId||t.hintId)&&(s[`aria-describedby`]=o.joinIds(i[`aria-describedby`],t.messageId,t.hintId)),t.invalid&&i[`aria-invalid`]===void 0&&(s[`aria-invalid`]=a),t.required&&i.required!==!1&&(i[`aria-required`]===void 0&&v(n)&&(s[`aria-required`]=a),typeof n.type==`string`&&_(n.type,i.type)&&i.required===void 0&&(s.required=!0)),l.Children.map(e,e=>e===n?l.cloneElement(n,s):e)}function S(e){let{target:t,mode:n,elementCount:r}=b(e),i=n===`label-for`;return{elementCount:r,targetId:i?t?.props.id:void 0,controlIdAssigned:i}}var C={error:c.ErrorIcon,warning:c.WarningIcon,success:c.SuccessIcon,none:null},w={error:`text-error`,warning:`text-warning-tint-foreground`,success:`text-success-tint-foreground`,none:`text-muted-foreground`},T=`[&>:first-child:has([role=checkbox],[role=switch],label>[role=radio])]:py-1.5`,E=`mt-0.5 inline-flex shrink-0`;function D(e,n){if(n!==void 0)return r.slotRendersContent(n)?r.renderSlot(n,`span`,t.cn(i.fieldClassNames.validationMessageIcon,E),{"aria-hidden":!0}):null;let a=C[e];return a?(0,u.jsx)(`span`,{"aria-hidden":`true`,className:t.cn(i.fieldClassNames.validationMessageIcon,E),children:(0,u.jsx)(a,{size:12})}):null}var O=({label:e,hint:o,error:c,validationState:d,validationMessage:f,validationMessageIcon:p,orientation:m=`vertical`,required:h=!1,htmlFor:g,className:_,children:v,ref:y,...b})=>{let C=a.useId(`field`),[E]=l.useState(s.createFieldControlIdClaim),{elementCount:O,targetId:k,controlIdAssigned:A}=S(v),j=r.slotRendersContent(c),M=c===!0||j,N=r.slotRendersContent(f),P=M?`error`:d??(N?`error`:`none`),F=M?j?c:void 0:f,I=M?j:N,L=P===`error`,R=r.slotRendersContent(o),z=M&&(N||d!==void 0&&d!==`error`),B=k??g??C,V=r.slotRendersContent(e),H=V?`${C}-label`:void 0,U=I?`${C}-${L?`error`:`message`}`:void 0,W=L?U:void 0,G=L&&I,K=R?`${C}-hint`:void 0;l.useEffect(()=>{O>1&&n.warnOnce(`Field:multiple-children`,`Field: only the first element child receives the Field's id and ARIA attributes; the other ${O-1} element child(ren) are rendered unchanged. Wrap each control in its own Field.`)},[O]),l.useEffect(()=>{z&&n.warnOnce(`Field:error-and-validation`,"Field: `error` and `validationMessage`/`validationState` are both set; `error` wins. Use one of them.")},[z]);let q=l.useMemo(()=>({controlId:B,labelId:H,hintId:K,errorId:W,invalid:L,required:h,hasErrorMessage:G,controlIdAssigned:A,controlIdClaim:E,validationState:P,validationMessageId:U}),[B,H,K,W,L,h,G,A,E,P,U]),J=x(v,{controlId:B,labelId:H,messageId:U,hintId:K,invalid:L,required:h}),Y=m===`horizontal`,X=(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(s.FieldContext.Provider,{value:q,children:J}),I?(0,u.jsxs)(`p`,{id:U,role:P===`error`||P===`warning`?`alert`:void 0,"data-validation-state":P,className:t.cn(i.fieldClassNames.validationMessage,`mt-1 flex items-start gap-1 text-caption-1`,w[P]),children:[D(P,p),(0,u.jsx)(`span`,{children:r.materialiseSlotContent(F)})]},`message-${P}`):null,R?(0,u.jsx)(`p`,{id:K,className:t.cn(i.fieldClassNames.hint,`mt-1 text-caption-1 text-muted-foreground`),children:r.materialiseSlotContent(o)},`hint`):null]});return(0,u.jsxs)(`div`,{ref:y,"data-orientation":m,"data-validation-state":P,className:t.cn(i.fieldClassNames.root,`flex`,Y?`flex-row items-start gap-x-3`:`flex-col`,_),...b,children:[V?(0,u.jsxs)(`label`,{id:H,htmlFor:B,className:t.cn(i.fieldClassNames.label,`mb-1 text-body-1 font-semibold text-foreground`,Y&&`mb-0 shrink-0 basis-1/3 pt-1.5`),children:[r.materialiseSlotContent(e),h&&(0,u.jsx)(`span`,{"aria-hidden":`true`,className:t.cn(i.fieldClassNames.required,`ms-0.5 text-error`),children:`*`})]}):null,Y?(0,u.jsx)(`div`,{className:t.cn(`flex min-w-0 flex-1 flex-col`,T),children:X}):X]})};O.displayName=`Field`,exports.Field=O;
|
|
2
|
+
//# sourceMappingURL=Field.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Field.cjs","names":["React","joinIds","ErrorIcon","WarningIcon","SuccessIcon","slotRendersContent","renderSlot","cn","fieldClassNames","useId","createFieldControlIdClaim","_Fragment","FieldContext","materialiseSlotContent","require_runtime","require_cn","require_dev","require_slot","require_classNames","require_useId","require_aria","require_useFieldControl","require_icons","react","react_jsx_runtime","LABELABLE_ELEMENTS","BUTTON_INPUT_TYPES","UNNAMED_ROLES","ARIA_REQUIRED_ROLES","explicitRole","role","isCustomElement","type","isNativeValueControl","tag","inputType","supportsAriaRequired","child","getMergeMode","inspectChildren","first","elementCount","children","mode","mergeIntoFirstChild","target","childProps","ariaTrue","injected","state","getChildInfo","assigned","MESSAGE_ICONS","MESSAGE_COLORS","SHORT_ROW_FIRST_CHILD","MESSAGE_ICON_CLASSES","renderMessageIcon","icon","Icon","Field","rest","fieldId","controlIdClaim","errorRendersContent","error","usesError","validationMessageRendersContent","validationMessage","validationState","message","hasMessage","invalid","hasHint","hint","errorAndValidation","controlId","targetId","htmlFor","hasLabel","label","labelId","messageId","errorId","hasErrorMessage","hintId","context","required","controlIdAssigned","content","horizontal","orientation","control","validationMessageIcon","className"],"sources":["../../../src/components/input/Field.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { joinIds } from '../../lib/aria';\nimport { fieldClassNames } from '../../lib/classNames';\nimport { warnOnce } from '../../lib/dev';\nimport { ErrorIcon, SuccessIcon, WarningIcon, type IconComponent } from '../../lib/icons';\nimport { materialiseSlotContent, renderSlot, slotRendersContent, type Slot } from '../../lib/slot';\nimport type { Orientation, ValidationState } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport {\n FieldContext,\n createFieldControlIdClaim,\n type FieldContextValue,\n} from '../../hooks/useFieldControl';\n\n/** Props Field reads from and merges into its first element child. */\ninterface InjectedFieldProps {\n id?: string;\n role?: string;\n type?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-invalid'?: React.AriaAttributes['aria-invalid'];\n 'aria-required'?: React.AriaAttributes['aria-required'];\n required?: boolean;\n}\n\n/** Properties for the Field component. */\nexport interface FieldProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Label displayed above the control (beside it with `orientation=\"horizontal\"`); names the\n * control.\n */\n label?: React.ReactNode;\n /** Hint shown below the control, after any validation message; describes the control. */\n hint?: React.ReactNode;\n /**\n * Validation error. Content is rendered below the control in a `role=\"alert\"` element that\n * describes the control, and the control is marked `aria-invalid`. `true` marks the control\n * invalid without a message. A value that renders nothing (`null`, `false`, `''`, or an array of\n * only those, such as an empty `errors.map(…)`) is no error; `0` is content.\n *\n * Shorthand for `validationState=\"error\"` with this message; wins over `validationMessage` and\n * `validationState` (development warning when both are set).\n */\n error?: React.ReactNode;\n /**\n * Validation state of `validationMessage`: `error` marks the control invalid (`aria-invalid`) and\n * announces the message (`role=\"alert\"`); `warning` announces it without marking the control\n * invalid; `success` and `none` show it without announcing. Default: `'error'` when\n * `validationMessage` renders content, else `'none'`. Ignored while `error` is set.\n */\n validationState?: ValidationState;\n /**\n * Message below the control, styled and announced by `validationState`; it describes the control\n * (`aria-describedby`). `error` is the shorthand for an error message and wins over this prop.\n */\n validationMessage?: React.ReactNode;\n /**\n * Icon before the message. Default: an error, warning or success glyph per state; none for\n * `'none'`. `null` (or content that renders nothing) shows no icon. Decorative (`aria-hidden`).\n */\n validationMessageIcon?: Slot<'span'>;\n /**\n * `vertical`: the label above the control. `horizontal`: the label in a start column (a third\n * of the width) beside the control; the message and the hint stay below the control. The\n * label's first line lines up with a 32px control (Input, Select, …) and with the first line of\n * a Checkbox, Switch or RadioGroup, which gets 6px of padding above and below for it. The\n * horizontal layout wraps the control in a column, so changing `orientation` on a mounted Field\n * remounts the control: an uncontrolled control loses its state and focus (control it, or keep\n * one orientation while the Field is mounted).\n * @default 'vertical'\n */\n orientation?: Orientation;\n /**\n * Whether the field is required: shows a decorative asterisk next to the label, sets\n * `aria-required`, and turns on native constraint validation. `<input>`, `<select>`,\n * `<textarea>` and Input, Select, Textarea, Slider, SearchBox and SpinButton get the native\n * `required` attribute. Checkbox, Switch, RadioGroup, Rating, ColorPicker, SwatchPicker,\n * Combobox, Dropdown, TagPicker, DatePicker and TimePicker render a hidden required input (with\n * or without `name`), so submit is blocked until they are checked, switched on or have a value.\n * An explicit `required={false}` on the control wins, including for `aria-required`.\n */\n required?: boolean;\n /**\n * The id of the control the label points at, when the control has no `id` of its own\n * (default: a generated id).\n */\n htmlFor?: string;\n /** Ref to the root `<div>`. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Intrinsic elements a `<label htmlFor>` can name (HTML \"labelable elements\"). */\nconst LABELABLE_ELEMENTS: ReadonlySet<string> = new Set([\n 'button',\n 'input',\n 'meter',\n 'output',\n 'progress',\n 'select',\n 'textarea',\n]);\n\n/** `<input>` types whose implicit role is `button`: they take neither `aria-required` nor `required`. */\nconst BUTTON_INPUT_TYPES: ReadonlySet<string> = new Set(['button', 'image', 'reset', 'submit']);\n\n/**\n * Roles that cannot be named (ARIA 1.2 \"name prohibited\") or that remove semantics: an element\n * with one of them is a layout wrapper, not a widget, and Field leaves it alone.\n */\nconst UNNAMED_ROLES: ReadonlySet<string> = new Set([\n 'caption',\n 'code',\n 'deletion',\n 'emphasis',\n 'generic',\n 'insertion',\n 'none',\n 'paragraph',\n 'presentation',\n 'strong',\n 'subscript',\n 'superscript',\n]);\n\n/** Roles that support `aria-required` (ARIA 1.2, including the roles that inherit it). */\nconst ARIA_REQUIRED_ROLES: ReadonlySet<string> = new Set([\n 'checkbox',\n 'columnheader',\n 'combobox',\n 'gridcell',\n 'listbox',\n 'radiogroup',\n 'rowheader',\n 'searchbox',\n 'spinbutton',\n 'switch',\n 'textbox',\n 'tree',\n 'treegrid',\n]);\n\n/**\n * How Field merges into its first element child:\n * - `label-for`: components (library controls, consumer inputs, wrappers such as Tooltip),\n * labelable intrinsic elements (`<input>`, `<select>`, `<button>`, …) and role-less custom\n * elements (`<my-text-field>`, possibly form-associated). The child receives the `id` the\n * `<label htmlFor>` points at (unless it has its own id, which the label then uses).\n * - `labelledby`: an intrinsic element with an explicit widget `role` (a consumer's own\n * `<div role=\"radiogroup\">`). A `<label htmlFor>` cannot name it, so it is named through\n * `aria-labelledby` and receives no `id` (a library control inside it keeps the control id).\n */\ntype MergeMode = 'label-for' | 'labelledby';\n\n/** The first token of an explicit `role` attribute (lower case), or `undefined`. */\nfunction explicitRole(role: unknown): string | undefined {\n if (typeof role !== 'string') return undefined;\n return role.trim().split(/\\s+/)[0]?.toLowerCase() || undefined;\n}\n\n/** Whether `type` is an autonomous custom element (`<my-text-field>`): its tag name has a hyphen. */\nfunction isCustomElement(type: unknown): type is string {\n return typeof type === 'string' && type.includes('-');\n}\n\n/**\n * Whether an intrinsic element is a native form control that takes a value (`<select>`,\n * `<textarea>`, or an `<input>` that is not a button): it takes the native `required` attribute\n * and, without an explicit role, `aria-required`.\n */\nfunction isNativeValueControl(tag: string, inputType: unknown): boolean {\n if (tag === 'select' || tag === 'textarea') return true;\n if (tag !== 'input') return false;\n return typeof inputType !== 'string' || !BUTTON_INPUT_TYPES.has(inputType.trim().toLowerCase());\n}\n\n/**\n * Whether Field may add `aria-required` to `child`: a component (it may render any control and\n * decides where the attribute goes), an element whose explicit role supports it, or a native form\n * control that takes a value. Never a `<button>`, `<meter>`, `<output>`, `<progress>`, button-type\n * `<input>` or role-less custom element, where axe reports `aria-allowed-attr`.\n */\nfunction supportsAriaRequired(child: React.ReactElement<InjectedFieldProps>): boolean {\n if (typeof child.type !== 'string') return true;\n const role = explicitRole(child.props.role);\n if (role !== undefined) return ARIA_REQUIRED_ROLES.has(role);\n return isNativeValueControl(child.type, child.props.type);\n}\n\n/**\n * Whether and how Field merges its props into `child` (see {@link MergeMode}). A Fragment and a\n * role-less (or presentational) non-labelable intrinsic wrapper (`<div>`, `<span>`) are left\n * alone; the library control inside them reads `FieldContext`. A role-less custom element\n * (`<my-text-field>`) is treated like a component: it may be a form-associated element, which a\n * `<label htmlFor>` names.\n */\nfunction getMergeMode(child: React.ReactElement<InjectedFieldProps>): MergeMode | undefined {\n if (child.type === React.Fragment) return undefined;\n if (typeof child.type !== 'string' || LABELABLE_ELEMENTS.has(child.type)) return 'label-for';\n const role = explicitRole(child.props.role);\n if (role !== undefined) return UNNAMED_ROLES.has(role) ? undefined : 'labelledby';\n return isCustomElement(child.type) ? 'label-for' : undefined;\n}\n\ninterface FieldChildren {\n /** The element child Field merges into, or `undefined`. */\n target: React.ReactElement<InjectedFieldProps> | undefined;\n /** How Field merges into `target` (`undefined` when there is no target). */\n mode: MergeMode | undefined;\n /** How many element children there are (only the first one is merged). */\n elementCount: number;\n}\n\nfunction inspectChildren(children: React.ReactNode): FieldChildren {\n let first: React.ReactElement<InjectedFieldProps> | undefined;\n let elementCount = 0;\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement<InjectedFieldProps>(child)) return;\n elementCount += 1;\n if (first === undefined) first = child;\n });\n const mode = first ? getMergeMode(first) : undefined;\n return { target: mode ? first : undefined, mode, elementCount };\n}\n\n/** What Field merges into its first element child. */\ninterface FieldMergeState {\n controlId: string;\n labelId: string | undefined;\n /** The id of the rendered validation message, in any state. */\n messageId: string | undefined;\n hintId: string | undefined;\n /** Only the `error` validation state is invalid. */\n invalid: boolean;\n required: boolean;\n}\n\n/**\n * Returns `children` with Field's props merged into the merge target (only defined keys; the\n * child's own `id`, `aria-label`, `aria-invalid`, `aria-required` and `required` are kept, its\n * `aria-labelledby` and `aria-describedby` are joined with the message and the hint).\n */\nfunction mergeIntoFirstChild(children: React.ReactNode, state: FieldMergeState): React.ReactNode {\n const { target, mode } = inspectChildren(children);\n // Always map, so the children keep the same keys whether or not one of them is merged.\n if (!target || !mode) return React.Children.map(children, (child) => child);\n\n const childProps = target.props;\n // React renders a boolean `true` on a custom element as an empty attribute (`aria-invalid=\"\"`).\n const ariaTrue = isCustomElement(target.type) ? 'true' : true;\n const injected: InjectedFieldProps = {};\n if (mode === 'label-for') {\n if (childProps.id === undefined) injected.id = state.controlId;\n } else if (state.labelId !== undefined && childProps['aria-label'] === undefined) {\n injected['aria-labelledby'] = joinIds(childProps['aria-labelledby'], state.labelId);\n }\n if (state.messageId || state.hintId) {\n injected['aria-describedby'] = joinIds(\n childProps['aria-describedby'],\n state.messageId,\n state.hintId,\n );\n }\n // The child's own `aria-invalid` wins, as `useFieldControl` lets it win for a nested control.\n if (state.invalid && childProps['aria-invalid'] === undefined) {\n injected['aria-invalid'] = ariaTrue;\n }\n // A child's own `required={false}` wins: it gets neither `aria-required` nor `required`, so what\n // is announced matches what is validated.\n if (state.required && childProps.required !== false) {\n if (childProps['aria-required'] === undefined && supportsAriaRequired(target)) {\n injected['aria-required'] = ariaTrue;\n }\n if (\n typeof target.type === 'string' &&\n isNativeValueControl(target.type, childProps.type) &&\n childProps.required === undefined\n ) {\n injected.required = true;\n }\n }\n return React.Children.map(children, (child) =>\n child === target ? React.cloneElement(target, injected) : child,\n );\n}\n\n/** Primitive facts about the children, read during render (no element objects escape). */\nfunction getChildInfo(children: React.ReactNode): {\n elementCount: number;\n targetId: string | undefined;\n controlIdAssigned: boolean;\n} {\n const { target, mode, elementCount } = inspectChildren(children);\n // Only a label-for target holds the control id (Field merges it, or the target's own id becomes\n // the control id). A <label htmlFor> cannot name a role widget, so the library control inside\n // one keeps the control id. With `controlIdAssigned`, a library control that receives no id is\n // nested in the target or is a later sibling: useFieldControl gives it an id of its own and\n // names it through aria-labelledby.\n const assigned = mode === 'label-for';\n return {\n elementCount,\n targetId: assigned ? target?.props.id : undefined,\n controlIdAssigned: assigned,\n };\n}\n\n/** The default glyph of each message state (`none` has none). */\nconst MESSAGE_ICONS: Readonly<Record<ValidationState, IconComponent | null>> = {\n error: ErrorIcon,\n warning: WarningIcon,\n success: SuccessIcon,\n none: null,\n};\n\n/** Text color of each message state (the `*-tint-foreground` tokens keep 4.5:1 on page and card). */\nconst MESSAGE_COLORS: Readonly<Record<ValidationState, string>> = {\n error: 'text-error',\n warning: 'text-warning-tint-foreground',\n success: 'text-success-tint-foreground',\n none: 'text-muted-foreground',\n};\n\n/**\n * Horizontal layout: the label's first line is centred on a 32px row, the height of an Input, a\n * Select and the other text controls. Checkbox, Switch and RadioGroup rows are one 20px line, so a\n * first child that holds one (also a wrapper of several) gets 6px above and below: its first line\n * then lines up with the label's, also when its label wraps or a group lists its items one below\n * the other.\n */\nconst SHORT_ROW_FIRST_CHILD =\n '[&>:first-child:has([role=checkbox],[role=switch],label>[role=radio])]:py-1.5';\n\n/** The icon box before a message: 12px glyphs line up with the first line of caption text. */\nconst MESSAGE_ICON_CLASSES = 'mt-0.5 inline-flex shrink-0';\n\n/**\n * The icon before a message: the state's glyph while `icon` is `undefined`, else the consumer's\n * slot (`null` or content that renders nothing shows none).\n */\nfunction renderMessageIcon(state: ValidationState, icon: Slot<'span'> | undefined) {\n if (icon !== undefined) {\n return slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(fieldClassNames.validationMessageIcon, MESSAGE_ICON_CLASSES), {\n 'aria-hidden': true,\n })\n : null;\n }\n const Icon = MESSAGE_ICONS[state];\n return Icon ? (\n <span\n aria-hidden=\"true\"\n className={cn(fieldClassNames.validationMessageIcon, MESSAGE_ICON_CLASSES)}\n >\n <Icon size={12} />\n </span>\n ) : null;\n}\n\n/**\n * Lays out a form control with a label, a validation message, a hint and a required indicator,\n * and wires them to the control.\n *\n * - Validation: `validationMessage` with a `validationState` (`error`, `warning`, `success`,\n * `none`), or `error`, the shorthand for an error message. The message renders below the\n * control with the state's icon and color, followed by the hint (which stays visible); both\n * describe the control. Only the `error` state marks the control `aria-invalid`; `error` and\n * `warning` messages are announced (`role=\"alert\"`). The root carries `data-validation-state`\n * and `data-orientation`.\n * - `orientation=\"horizontal\"` puts the label in a start column beside the control, with the\n * message and the hint below the control. The label lines up with the first line of the\n * control (a Checkbox, Switch or RadioGroup gets 6px of padding above and below for it).\n * - Provides `FieldContext`: the library's inputs (Input, Select, Textarea, Slider, SearchBox,\n * Checkbox, Switch, RadioGroup, Rating, SpinButton, pickers, …) read it wherever they are inside\n * the Field and are named by the label, described by the message and the hint and marked\n * invalid/required.\n * - Merges into its **first** element child (a native `<input>`/`<select>`/`<textarea>`, a\n * library control or your own component): `id` (unless the child has one — the label then\n * points at the child's id), `aria-describedby` (joined with the child's own ids),\n * `aria-invalid` (in the error state), `aria-required` and, for native form controls that take a\n * value, `required`. Only defined values are merged; the child's own values are kept, so a\n * child's `aria-invalid={false}` stays valid while the Field error still describes it (as for a\n * library control nested deeper). Further element children are rendered as they are.\n * - `aria-required` is added only where it is allowed: components (Field cannot see what they\n * render, so they decide where it goes — see the wrapper note below), `<input>` (not\n * `type=\"button\"`/`\"submit\"`/`\"reset\"`/`\"image\"`), `<select>`, `<textarea>`, and elements\n * whose explicit `role` supports it (`checkbox`, `combobox`, `switch`, `textbox`, …). A\n * `<button>`, `<meter>`, `<output>` or `<progress>` is labelled and described but not marked\n * required.\n * - Your own widget built on an element with an explicit `role` (`<div role=\"radiogroup\">`) is\n * named through `aria-labelledby` (joined with its own; not added when it has an\n * `aria-label`), described, marked invalid, and gets `aria-required` when its role supports\n * it. It receives no `id`, because a `<label htmlFor>` cannot name it. A role-less `<div>` or\n * `<span>` wrapper (or a `role=\"presentation\"`/`\"none\"` one) is left alone: the library\n * control inside it reads `FieldContext`.\n * - A custom element (`<my-text-field>`) without a role is treated like a component: it receives\n * the `id`, the description and `aria-invalid` (a form-associated custom element is named by\n * the label). Field does not guess its semantics: pass `required`/`aria-required` or an\n * explicit `role` yourself.\n * - **One control per Field.** A Field labels and describes a single control; wrap each control\n * in its own Field (a development warning is logged when a Field has more than one element\n * child). Further element children are rendered as they are. A library control among them\n * still reads `FieldContext`, so it shares the Field's name and description (when the first\n * child holds the control id, it gets an id of its own and is named through\n * `aria-labelledby`). Several library controls inside one plain wrapper element (`<div>`) are\n * all named and described too: the first one takes the control id the label points at, the\n * others get ids of their own and are named through `aria-labelledby` (when the first one is\n * removed, the next one takes the control id over).\n * - **Wrapper and layout components around a library control** (a `Tooltip`, your own `Row`):\n * put them inside a plain element (`<div>`, `<div className=\"flex\">`), which Field leaves\n * alone; the library control inside then holds the control id and is labelled, described and\n * marked invalid/required through `FieldContext`. Field cannot see inside a component, so a\n * component **first child** is treated as the control (it may be your own input): it receives\n * the control `id`, `aria-describedby`, `aria-invalid` and, with `required`, `aria-required`,\n * and a wrapper puts them on its own element (Tooltip's `<span>`, the layout `<div>`). The\n * library control inside still gets an id of its own and is named by the label through\n * `aria-labelledby`, but clicking the label does not focus it, and with `required`,\n * `aria-required` on the wrapper's non-widget element is an ARIA error (axe\n * `aria-allowed-attr`), even though the control inside is correctly marked required.\n *\n * @example\n * <Field label=\"Email\" hint=\"We never share it\" error={errors.email} required>\n * <Input type=\"email\" value={email} onValueChange={setEmail} />\n * </Field>\n *\n * @example\n * <Field label=\"Password\" hint=\"At least 12 characters\" validationState=\"warning\"\n * validationMessage=\"This password is common\">\n * <Input type=\"password\" />\n * </Field>\n *\n * @example\n * // A wrapper component goes inside a plain element.\n * <Field label=\"Name\" required>\n * <div>\n * <Tooltip content=\"As on your passport\">\n * <Input />\n * </Tooltip>\n * </div>\n * </Field>\n */\nexport const Field = ({\n label,\n hint,\n error,\n validationState,\n validationMessage,\n validationMessageIcon,\n orientation = 'vertical',\n required = false,\n htmlFor,\n className,\n children,\n ref,\n ...rest\n}: FieldProps) => {\n const fieldId = useId('field');\n // Hands the control id to one library control when Field leaves its first child alone.\n const [controlIdClaim] = React.useState(createFieldControlIdClaim);\n const { elementCount, targetId, controlIdAssigned } = getChildInfo(children);\n\n // The library's \"renders nothing\" rule: nullish, booleans, '' and collections of only those (an\n // empty `errors.map(…)`) are no label, hint or message; `0` is content.\n const errorRendersContent = slotRendersContent(error);\n const usesError = error === true || errorRendersContent;\n const validationMessageRendersContent = slotRendersContent(validationMessage);\n // `error` is the shorthand for an error message and wins over the validation props.\n const state: ValidationState = usesError\n ? 'error'\n : (validationState ?? (validationMessageRendersContent ? 'error' : 'none'));\n const message = usesError ? (errorRendersContent ? error : undefined) : validationMessage;\n const hasMessage = usesError ? errorRendersContent : validationMessageRendersContent;\n const invalid = state === 'error';\n const hasHint = slotRendersContent(hint);\n const errorAndValidation =\n usesError &&\n (validationMessageRendersContent ||\n (validationState !== undefined && validationState !== 'error'));\n\n const controlId = targetId ?? htmlFor ?? fieldId;\n const hasLabel = slotRendersContent(label);\n const labelId = hasLabel ? `${fieldId}-label` : undefined;\n // The error message keeps its 0.5 id; the other states get their own.\n const messageId = hasMessage ? `${fieldId}-${invalid ? 'error' : 'message'}` : undefined;\n const errorId = invalid ? messageId : undefined;\n const hasErrorMessage = invalid && hasMessage;\n const hintId = hasHint ? `${fieldId}-hint` : undefined;\n\n React.useEffect(() => {\n if (elementCount > 1) {\n warnOnce(\n 'Field:multiple-children',\n \"Field: only the first element child receives the Field's id and ARIA attributes; the other \" +\n `${elementCount - 1} element child(ren) are rendered unchanged. Wrap each control in its own Field.`,\n );\n }\n }, [elementCount]);\n\n React.useEffect(() => {\n if (errorAndValidation) {\n warnOnce(\n 'Field:error-and-validation',\n 'Field: `error` and `validationMessage`/`validationState` are both set; `error` wins. Use one of them.',\n );\n }\n }, [errorAndValidation]);\n\n const context = React.useMemo<FieldContextValue>(\n () => ({\n controlId,\n labelId,\n hintId,\n errorId,\n invalid,\n required,\n hasErrorMessage,\n controlIdAssigned,\n controlIdClaim,\n validationState: state,\n validationMessageId: messageId,\n }),\n [\n controlId,\n labelId,\n hintId,\n errorId,\n invalid,\n required,\n hasErrorMessage,\n controlIdAssigned,\n controlIdClaim,\n state,\n messageId,\n ],\n );\n\n const content = mergeIntoFirstChild(children, {\n controlId,\n labelId,\n messageId,\n hintId,\n invalid,\n required,\n });\n\n const horizontal = orientation === 'horizontal';\n const control = (\n <>\n <FieldContext.Provider value={context}>{content}</FieldContext.Provider>\n {/* Keyed by state: a message whose state changes (a hint-only Field that gets an error, a\n warning that becomes an error) is a newly inserted element, which screen readers\n announce reliably as an alert, not an existing node with a new role. */}\n {hasMessage ? (\n <p\n key={`message-${state}`}\n id={messageId}\n role={state === 'error' || state === 'warning' ? 'alert' : undefined}\n data-validation-state={state}\n className={cn(\n fieldClassNames.validationMessage,\n 'mt-1 flex items-start gap-1 text-caption-1',\n MESSAGE_COLORS[state],\n )}\n >\n {renderMessageIcon(state, validationMessageIcon)}\n <span>{materialiseSlotContent(message)}</span>\n </p>\n ) : null}\n {hasHint ? (\n <p\n key=\"hint\"\n id={hintId}\n className={cn(fieldClassNames.hint, 'mt-1 text-caption-1 text-muted-foreground')}\n >\n {materialiseSlotContent(hint)}\n </p>\n ) : null}\n </>\n );\n\n return (\n <div\n ref={ref}\n data-orientation={orientation}\n data-validation-state={state}\n className={cn(\n fieldClassNames.root,\n 'flex',\n horizontal ? 'flex-row items-start gap-x-3' : 'flex-col',\n className,\n )}\n {...rest}\n >\n {hasLabel ? (\n <label\n id={labelId}\n htmlFor={controlId}\n className={cn(\n fieldClassNames.label,\n 'mb-1 text-body-1 font-semibold text-foreground',\n // Beside the control: a third of the width, its first line centred on a 32px row.\n horizontal && 'mb-0 shrink-0 basis-1/3 pt-1.5',\n )}\n >\n {materialiseSlotContent(label)}\n {required && (\n <span aria-hidden=\"true\" className={cn(fieldClassNames.required, 'ms-0.5 text-error')}>\n *\n </span>\n )}\n </label>\n ) : null}\n {horizontal ? (\n <div className={cn('flex min-w-0 flex-1 flex-col', SHORT_ROW_FIRST_CHILD)}>{control}</div>\n ) : (\n control\n )}\n </div>\n );\n};\n\nField.displayName = 'Field';\n"],"mappings":"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"}
|