@mortenbrudvik/waveui 0.7.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 +395 -132
- package/dist/components/button/Button.cjs +1 -1
- package/dist/components/button/Button.cjs.map +1 -1
- package/dist/components/button/Button.mjs +36 -35
- package/dist/components/button/Button.mjs.map +1 -1
- package/dist/components/button/Button.slots.cjs +1 -1
- package/dist/components/button/Button.slots.cjs.map +1 -1
- package/dist/components/button/Button.slots.mjs +31 -21
- package/dist/components/button/Button.slots.mjs.map +1 -1
- package/dist/components/button/CompoundButton.cjs +1 -1
- package/dist/components/button/CompoundButton.cjs.map +1 -1
- package/dist/components/button/CompoundButton.mjs +31 -29
- package/dist/components/button/CompoundButton.mjs.map +1 -1
- package/dist/components/button/Link.cjs +1 -1
- package/dist/components/button/Link.cjs.map +1 -1
- package/dist/components/button/Link.mjs +24 -23
- package/dist/components/button/Link.mjs.map +1 -1
- package/dist/components/button/MenuButton.cjs +1 -1
- package/dist/components/button/MenuButton.cjs.map +1 -1
- package/dist/components/button/MenuButton.mjs +29 -28
- package/dist/components/button/MenuButton.mjs.map +1 -1
- package/dist/components/button/SplitButton.cjs +1 -1
- package/dist/components/button/SplitButton.cjs.map +1 -1
- package/dist/components/button/SplitButton.mjs +46 -45
- package/dist/components/button/SplitButton.mjs.map +1 -1
- package/dist/components/button/ToggleButton.cjs +1 -1
- package/dist/components/button/ToggleButton.cjs.map +1 -1
- package/dist/components/button/ToggleButton.mjs +38 -35
- package/dist/components/button/ToggleButton.mjs.map +1 -1
- package/dist/components/button/Toolbar.cjs +1 -1
- package/dist/components/button/Toolbar.cjs.map +1 -1
- package/dist/components/button/Toolbar.mjs +43 -42
- package/dist/components/button/Toolbar.mjs.map +1 -1
- package/dist/components/button/Toolbar.parts.cjs +1 -1
- package/dist/components/button/Toolbar.parts.cjs.map +1 -1
- package/dist/components/button/Toolbar.parts.mjs +76 -81
- package/dist/components/button/Toolbar.parts.mjs.map +1 -1
- package/dist/components/data-display/Avatar.cjs +1 -1
- package/dist/components/data-display/Avatar.cjs.map +1 -1
- package/dist/components/data-display/Avatar.mjs +72 -67
- package/dist/components/data-display/Avatar.mjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.cjs +1 -1
- package/dist/components/data-display/AvatarGroup.cjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.mjs +89 -88
- package/dist/components/data-display/AvatarGroup.mjs.map +1 -1
- package/dist/components/data-display/Badge.cjs +1 -1
- package/dist/components/data-display/Badge.cjs.map +1 -1
- package/dist/components/data-display/Badge.mjs +17 -16
- package/dist/components/data-display/Badge.mjs.map +1 -1
- package/dist/components/data-display/CounterBadge.cjs +1 -1
- package/dist/components/data-display/CounterBadge.cjs.map +1 -1
- package/dist/components/data-display/CounterBadge.mjs +18 -17
- package/dist/components/data-display/CounterBadge.mjs.map +1 -1
- package/dist/components/data-display/Divider.cjs +1 -1
- package/dist/components/data-display/Divider.cjs.map +1 -1
- package/dist/components/data-display/Divider.mjs +31 -30
- package/dist/components/data-display/Divider.mjs.map +1 -1
- package/dist/components/data-display/Image.cjs +1 -1
- package/dist/components/data-display/Image.cjs.map +1 -1
- package/dist/components/data-display/Image.mjs +16 -15
- package/dist/components/data-display/Image.mjs.map +1 -1
- package/dist/components/data-display/InfoLabel.cjs +1 -1
- package/dist/components/data-display/InfoLabel.cjs.map +1 -1
- package/dist/components/data-display/InfoLabel.mjs +74 -73
- package/dist/components/data-display/InfoLabel.mjs.map +1 -1
- package/dist/components/data-display/List.cjs +1 -1
- package/dist/components/data-display/List.cjs.map +1 -1
- package/dist/components/data-display/List.mjs +175 -174
- package/dist/components/data-display/List.mjs.map +1 -1
- package/dist/components/data-display/Persona.cjs +1 -1
- package/dist/components/data-display/Persona.cjs.map +1 -1
- package/dist/components/data-display/Persona.mjs +31 -29
- package/dist/components/data-display/Persona.mjs.map +1 -1
- package/dist/components/data-display/PresenceBadge.cjs +1 -1
- package/dist/components/data-display/PresenceBadge.cjs.map +1 -1
- package/dist/components/data-display/PresenceBadge.mjs +25 -24
- package/dist/components/data-display/PresenceBadge.mjs.map +1 -1
- package/dist/components/data-display/Tag.cjs +1 -1
- package/dist/components/data-display/Tag.cjs.map +1 -1
- package/dist/components/data-display/Tag.mjs +87 -82
- package/dist/components/data-display/Tag.mjs.map +1 -1
- package/dist/components/feedback/MessageBar.cjs +1 -1
- package/dist/components/feedback/MessageBar.cjs.map +1 -1
- package/dist/components/feedback/MessageBar.mjs +129 -71
- package/dist/components/feedback/MessageBar.mjs.map +1 -1
- 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 +1 -1
- package/dist/components/feedback/MessageBar.status.cjs.map +1 -1
- package/dist/components/feedback/MessageBar.status.mjs +2 -1
- package/dist/components/feedback/MessageBar.status.mjs.map +1 -1
- package/dist/components/feedback/ProgressBar.cjs +1 -1
- package/dist/components/feedback/ProgressBar.cjs.map +1 -1
- package/dist/components/feedback/ProgressBar.mjs +44 -43
- package/dist/components/feedback/ProgressBar.mjs.map +1 -1
- package/dist/components/feedback/Skeleton.cjs +1 -1
- package/dist/components/feedback/Skeleton.cjs.map +1 -1
- package/dist/components/feedback/Skeleton.mjs +26 -24
- package/dist/components/feedback/Skeleton.mjs.map +1 -1
- package/dist/components/feedback/Spinner.cjs +1 -1
- package/dist/components/feedback/Spinner.cjs.map +1 -1
- package/dist/components/feedback/Spinner.mjs +32 -31
- package/dist/components/feedback/Spinner.mjs.map +1 -1
- package/dist/components/feedback/Toast.cjs +1 -1
- package/dist/components/feedback/Toast.cjs.map +1 -1
- 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 +10 -342
- package/dist/components/feedback/Toast.mjs.map +1 -1
- 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 +1 -1
- package/dist/components/input/Checkbox.cjs.map +1 -1
- package/dist/components/input/Checkbox.mjs +47 -46
- package/dist/components/input/Checkbox.mjs.map +1 -1
- 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 +5 -5
- package/dist/components/input/ColorPicker.cjs.map +1 -1
- package/dist/components/input/ColorPicker.mjs +142 -165
- package/dist/components/input/ColorPicker.mjs.map +1 -1
- 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 +1 -1
- package/dist/components/input/Combobox.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.cjs +1 -1
- package/dist/components/input/Combobox.expand.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.mjs +9 -9
- package/dist/components/input/Combobox.expand.mjs.map +1 -1
- package/dist/components/input/Combobox.mjs +90 -85
- package/dist/components/input/Combobox.mjs.map +1 -1
- package/dist/components/input/DatePicker.cjs +1 -1
- package/dist/components/input/DatePicker.cjs.map +1 -1
- package/dist/components/input/DatePicker.mjs +186 -185
- package/dist/components/input/DatePicker.mjs.map +1 -1
- package/dist/components/input/Dropdown.cjs +1 -1
- package/dist/components/input/Dropdown.cjs.map +1 -1
- package/dist/components/input/Dropdown.mjs +71 -68
- package/dist/components/input/Dropdown.mjs.map +1 -1
- package/dist/components/input/Field.cjs +1 -1
- package/dist/components/input/Field.cjs.map +1 -1
- package/dist/components/input/Field.mjs +113 -112
- package/dist/components/input/Field.mjs.map +1 -1
- package/dist/components/input/Input.cjs +1 -1
- package/dist/components/input/Input.cjs.map +1 -1
- package/dist/components/input/Input.mjs +55 -54
- package/dist/components/input/Input.mjs.map +1 -1
- package/dist/components/input/Label.cjs +1 -1
- package/dist/components/input/Label.cjs.map +1 -1
- package/dist/components/input/Label.mjs +12 -11
- package/dist/components/input/Label.mjs.map +1 -1
- package/dist/components/input/Option.cjs +1 -1
- package/dist/components/input/Option.cjs.map +1 -1
- package/dist/components/input/Option.mjs +100 -98
- package/dist/components/input/Option.mjs.map +1 -1
- package/dist/components/input/RadioGroup.cjs +1 -1
- package/dist/components/input/RadioGroup.cjs.map +1 -1
- package/dist/components/input/RadioGroup.mjs +89 -88
- package/dist/components/input/RadioGroup.mjs.map +1 -1
- package/dist/components/input/Rating.cjs +1 -1
- package/dist/components/input/Rating.cjs.map +1 -1
- package/dist/components/input/Rating.mjs +110 -109
- package/dist/components/input/Rating.mjs.map +1 -1
- package/dist/components/input/SearchBox.cjs +1 -1
- package/dist/components/input/SearchBox.cjs.map +1 -1
- package/dist/components/input/SearchBox.mjs +118 -119
- package/dist/components/input/SearchBox.mjs.map +1 -1
- package/dist/components/input/Select.cjs +1 -1
- package/dist/components/input/Select.cjs.map +1 -1
- package/dist/components/input/Select.mjs +25 -24
- package/dist/components/input/Select.mjs.map +1 -1
- package/dist/components/input/Slider.cjs +1 -1
- package/dist/components/input/Slider.cjs.map +1 -1
- package/dist/components/input/Slider.mjs +47 -46
- package/dist/components/input/Slider.mjs.map +1 -1
- package/dist/components/input/SpinButton.cjs +1 -1
- package/dist/components/input/SpinButton.cjs.map +1 -1
- package/dist/components/input/SpinButton.mjs +76 -75
- package/dist/components/input/SpinButton.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.cjs +1 -1
- package/dist/components/input/SwatchPicker.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.mjs +38 -37
- package/dist/components/input/SwatchPicker.mjs.map +1 -1
- package/dist/components/input/Switch.cjs +1 -1
- package/dist/components/input/Switch.cjs.map +1 -1
- package/dist/components/input/Switch.mjs +65 -64
- package/dist/components/input/Switch.mjs.map +1 -1
- package/dist/components/input/TagPicker.cjs +1 -1
- package/dist/components/input/TagPicker.cjs.map +1 -1
- package/dist/components/input/TagPicker.mjs +161 -157
- package/dist/components/input/TagPicker.mjs.map +1 -1
- package/dist/components/input/Textarea.cjs +1 -1
- package/dist/components/input/Textarea.cjs.map +1 -1
- package/dist/components/input/Textarea.mjs +24 -23
- package/dist/components/input/Textarea.mjs.map +1 -1
- package/dist/components/input/TimePicker.cjs +1 -1
- package/dist/components/input/TimePicker.cjs.map +1 -1
- package/dist/components/input/TimePicker.mjs +202 -199
- package/dist/components/input/TimePicker.mjs.map +1 -1
- 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 +1 -1
- package/dist/components/input/colorUtils.cjs.map +1 -1
- package/dist/components/input/colorUtils.mjs +154 -56
- package/dist/components/input/colorUtils.mjs.map +1 -1
- package/dist/components/layout/Accordion.cjs +1 -1
- package/dist/components/layout/Accordion.cjs.map +1 -1
- package/dist/components/layout/Accordion.mjs +130 -129
- package/dist/components/layout/Accordion.mjs.map +1 -1
- package/dist/components/layout/Card.cjs +1 -1
- package/dist/components/layout/Card.cjs.map +1 -1
- package/dist/components/layout/Card.mjs +78 -77
- package/dist/components/layout/Card.mjs.map +1 -1
- package/dist/components/layout/Carousel.cjs +1 -1
- package/dist/components/layout/Carousel.cjs.map +1 -1
- package/dist/components/layout/Carousel.mjs +111 -110
- package/dist/components/layout/Carousel.mjs.map +1 -1
- package/dist/components/layout/Flex.cjs +1 -1
- package/dist/components/layout/Flex.cjs.map +1 -1
- package/dist/components/layout/Flex.mjs +22 -21
- package/dist/components/layout/Flex.mjs.map +1 -1
- package/dist/components/layout/Grid.cjs +1 -1
- package/dist/components/layout/Grid.cjs.map +1 -1
- package/dist/components/layout/Grid.mjs +19 -18
- package/dist/components/layout/Grid.mjs.map +1 -1
- package/dist/components/layout/Overflow.cjs +1 -1
- package/dist/components/layout/Overflow.cjs.map +1 -1
- package/dist/components/layout/Overflow.mjs +92 -91
- package/dist/components/layout/Overflow.mjs.map +1 -1
- package/dist/components/layout/Stack.cjs +1 -1
- package/dist/components/layout/Stack.cjs.map +1 -1
- package/dist/components/layout/Stack.mjs +14 -13
- package/dist/components/layout/Stack.mjs.map +1 -1
- package/dist/components/layout/TabList.cjs +1 -1
- package/dist/components/layout/TabList.cjs.map +1 -1
- package/dist/components/layout/TabList.mjs +118 -117
- package/dist/components/layout/TabList.mjs.map +1 -1
- package/dist/components/layout/Tree.cjs +1 -1
- package/dist/components/layout/Tree.cjs.map +1 -1
- 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 +7 -215
- package/dist/components/layout/Tree.mjs.map +1 -1
- 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/navigation/Breadcrumb.cjs +1 -1
- package/dist/components/navigation/Breadcrumb.cjs.map +1 -1
- package/dist/components/navigation/Breadcrumb.mjs +76 -75
- package/dist/components/navigation/Breadcrumb.mjs.map +1 -1
- package/dist/components/navigation/Menu.group.cjs +1 -1
- package/dist/components/navigation/Menu.group.cjs.map +1 -1
- package/dist/components/navigation/Menu.group.mjs +39 -37
- package/dist/components/navigation/Menu.group.mjs.map +1 -1
- package/dist/components/navigation/Menu.items.cjs +1 -1
- package/dist/components/navigation/Menu.items.cjs.map +1 -1
- package/dist/components/navigation/Menu.items.mjs +67 -61
- package/dist/components/navigation/Menu.items.mjs.map +1 -1
- package/dist/components/navigation/Menu.link.cjs +1 -1
- package/dist/components/navigation/Menu.link.cjs.map +1 -1
- package/dist/components/navigation/Menu.link.mjs +34 -28
- package/dist/components/navigation/Menu.link.mjs.map +1 -1
- package/dist/components/navigation/Menu.popover.cjs +1 -1
- package/dist/components/navigation/Menu.popover.cjs.map +1 -1
- package/dist/components/navigation/Menu.popover.mjs +110 -109
- package/dist/components/navigation/Menu.popover.mjs.map +1 -1
- package/dist/components/navigation/Menu.root.cjs +1 -1
- package/dist/components/navigation/Menu.root.cjs.map +1 -1
- package/dist/components/navigation/Menu.root.mjs +171 -170
- package/dist/components/navigation/Menu.root.mjs.map +1 -1
- package/dist/components/navigation/Menu.selectable.cjs +1 -1
- package/dist/components/navigation/Menu.selectable.cjs.map +1 -1
- package/dist/components/navigation/Menu.selectable.mjs +85 -63
- package/dist/components/navigation/Menu.selectable.mjs.map +1 -1
- package/dist/components/navigation/Menu.splitGroup.cjs +1 -1
- package/dist/components/navigation/Menu.splitGroup.cjs.map +1 -1
- package/dist/components/navigation/Menu.splitGroup.mjs +27 -26
- package/dist/components/navigation/Menu.splitGroup.mjs.map +1 -1
- package/dist/components/navigation/Menu.trigger.cjs +1 -1
- package/dist/components/navigation/Menu.trigger.cjs.map +1 -1
- package/dist/components/navigation/Menu.trigger.mjs +6 -6
- package/dist/components/navigation/Nav.cjs +1 -1
- package/dist/components/navigation/Nav.cjs.map +1 -1
- package/dist/components/navigation/Nav.mjs +170 -155
- package/dist/components/navigation/Nav.mjs.map +1 -1
- package/dist/components/navigation/Pagination.cjs +1 -1
- package/dist/components/navigation/Pagination.cjs.map +1 -1
- package/dist/components/navigation/Pagination.mjs +73 -65
- package/dist/components/navigation/Pagination.mjs.map +1 -1
- package/dist/components/navigation/Stepper.cjs +1 -1
- package/dist/components/navigation/Stepper.cjs.map +1 -1
- package/dist/components/navigation/Stepper.mjs +110 -109
- package/dist/components/navigation/Stepper.mjs.map +1 -1
- package/dist/components/overlays/Dialog.cjs +1 -1
- package/dist/components/overlays/Dialog.cjs.map +1 -1
- package/dist/components/overlays/Dialog.mjs +109 -108
- package/dist/components/overlays/Dialog.mjs.map +1 -1
- package/dist/components/overlays/Drawer.cjs +1 -1
- package/dist/components/overlays/Drawer.cjs.map +1 -1
- package/dist/components/overlays/Drawer.mjs +110 -109
- package/dist/components/overlays/Drawer.mjs.map +1 -1
- package/dist/components/overlays/Popover.cjs +1 -1
- package/dist/components/overlays/Popover.cjs.map +1 -1
- package/dist/components/overlays/Popover.mjs +229 -227
- package/dist/components/overlays/Popover.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.cjs +1 -1
- package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.mjs +41 -37
- package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
- package/dist/components/overlays/Tooltip.cjs +1 -1
- package/dist/components/overlays/Tooltip.cjs.map +1 -1
- package/dist/components/overlays/Tooltip.mjs +87 -86
- package/dist/components/overlays/Tooltip.mjs.map +1 -1
- package/dist/components/portal/Portal.cjs +1 -1
- package/dist/components/portal/Portal.cjs.map +1 -1
- package/dist/components/portal/Portal.mjs +33 -32
- package/dist/components/portal/Portal.mjs.map +1 -1
- package/dist/components/provider/WaveProvider.cjs +1 -1
- package/dist/components/provider/WaveProvider.cjs.map +1 -1
- package/dist/components/provider/WaveProvider.mjs +31 -30
- package/dist/components/provider/WaveProvider.mjs.map +1 -1
- package/dist/components/table/DataGrid.cjs +1 -1
- package/dist/components/table/DataGrid.cjs.map +1 -1
- package/dist/components/table/DataGrid.mjs +228 -227
- package/dist/components/table/DataGrid.mjs.map +1 -1
- package/dist/components/table/Table.cjs +1 -1
- package/dist/components/table/Table.cjs.map +1 -1
- package/dist/components/table/Table.mjs +60 -59
- package/dist/components/table/Table.mjs.map +1 -1
- package/dist/components/typography/Text.cjs +1 -1
- package/dist/components/typography/Text.cjs.map +1 -1
- package/dist/components/typography/Text.mjs +12 -11
- package/dist/components/typography/Text.mjs.map +1 -1
- 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/usePrefersReducedMotion.cjs +1 -1
- package/dist/hooks/usePrefersReducedMotion.cjs.map +1 -1
- package/dist/hooks/usePrefersReducedMotion.mjs +4 -18
- package/dist/hooks/usePrefersReducedMotion.mjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.cjs +1 -1
- package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.mjs +3 -3
- package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2089 -102
- package/dist/index.d.ts +2089 -102
- package/dist/index.mjs +99 -87
- 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/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/globalRegistry.cjs.map +1 -1
- package/dist/lib/globalRegistry.mjs.map +1 -1
- 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/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.mjs","names":["React","PROGRESS_VAR","progressPercent","share","max","min","value","railClasses","forcedColorsFill","Slider","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","props","fieldProps","useFieldControl","label","inputRef","mergedRef","useMergedRefs","ref","rangeMin","rangeMax","renderedProgress","defaultValue","updateFill","useEventCallback","input","next","step","useFormReset","form","handleChange","composeEventHandlers","onChange","onValueChange","event","cn","focusRing","forcedColors","className","style"],"sources":["../../../src/components/input/Slider.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\n\n/** Properties for the Slider component. */\nexport interface SliderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {\n /** Controlled slider value. */\n value?: number;\n /** Initial value for uncontrolled usage. */\n defaultValue?: number;\n /** Native change event handler (`event.target.value` is a string). */\n onChange?: React.ChangeEventHandler<HTMLInputElement>;\n /** Called with the new value as a number on every change, next to the native `onChange`. */\n onValueChange?: (value: number) => void;\n /** Minimum allowed value. */\n min?: number;\n /** Maximum allowed value. */\n max?: number;\n /** Step increment between values. */\n step?: number;\n /**\n * Accessible label for the slider (sets `aria-label`; an explicit `aria-label` wins). Inside a\n * `Field`, leave it out so the Field's label names the slider.\n */\n label?: string;\n /** Ref to the `<input type=\"range\">` element. */\n ref?: React.Ref<HTMLInputElement>;\n}\n\n/** The CSS variable that holds how much of the rail the fill covers (`<p>%`). */\nconst PROGRESS_VAR = '--wave-slider-progress';\n\n/** The share of the rail up to `value`, as a CSS percentage: 0–100, and 0 when `max <= min`. */\nfunction progressPercent(value: number, min: number, max: number): string {\n const share = max > min ? ((value - min) / (max - min)) * 100 : 0;\n return `${Number.isFinite(share) ? Math.min(100, Math.max(0, share)) : 0}%`;\n}\n\n/**\n * The rail: the primary fill up to the thumb, the accessible stroke after it. WebKit and Blink\n * draw it as a gradient on the track (mirrored for right-to-left); Firefox has a progress part and\n * mirrors it itself. The track color stays underneath (the whole rail without the variable).\n */\nconst railClasses = [\n // The rail color gives the rail itself 3:1 non-text contrast.\n '[&::-webkit-slider-runnable-track]:h-1 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-stroke-accessible',\n '[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--wave-primary)_var(--wave-slider-progress),var(--wave-stroke-accessible)_var(--wave-slider-progress))]',\n 'wave-rtl:[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_left,var(--wave-primary)_var(--wave-slider-progress),var(--wave-stroke-accessible)_var(--wave-slider-progress))]',\n '[&::-moz-range-track]:h-1 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-stroke-accessible',\n '[&::-moz-range-progress]:h-1 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-primary',\n];\n\n/**\n * Forced colors, after `forcedColors.rangeInput` (which draws the whole rail in CanvasText): the\n * filled part in Highlight; a disabled rail stays GrayText, without the fill.\n */\nconst forcedColorsFill = [\n 'forced-colors:[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,Highlight_var(--wave-slider-progress),CanvasText_var(--wave-slider-progress))]',\n 'forced-colors:wave-rtl:[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_left,Highlight_var(--wave-slider-progress),CanvasText_var(--wave-slider-progress))]',\n 'forced-colors:[&::-moz-range-progress]:bg-[Highlight]',\n 'forced-colors:disabled:[&::-webkit-slider-runnable-track]:bg-none forced-colors:disabled:[&::-moz-range-progress]:bg-[GrayText]',\n];\n\n/**\n * A native range input with Fluent styling: a rail drawn in the accessible stroke color (3:1\n * against the page), filled in the primary color up to a primary thumb; in forced-colors mode the\n * rail, fill and thumb are drawn in system colors. Inside a `Field` it picks up the label, hint,\n * validation message, `required` and invalid state automatically.\n *\n * The fill follows the value through the `--wave-slider-progress` variable on the input (also in\n * the server HTML), including the browser's snapping to `step` and a form reset.\n *\n * @example\n * <Slider label=\"Volume\" min={0} max={100} value={volume} onValueChange={setVolume} />\n */\nexport const Slider = ({\n className,\n style,\n label,\n value,\n defaultValue,\n min,\n max,\n step,\n form,\n onChange,\n onValueChange,\n ref,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n ...props\n}: SliderProps) => {\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label': ariaLabel ?? label,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n },\n { nativeRequired: true },\n );\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedRef = useMergedRefs(inputRef, ref);\n const rangeMin = min ?? 0;\n const rangeMax = max ?? 100;\n // During render (and on the server): the value, else the default, else the native midpoint.\n const renderedProgress = progressPercent(\n value ?? defaultValue ?? rangeMin + (rangeMax - rangeMin) / 2,\n rangeMin,\n rangeMax,\n );\n\n /** Writes the fill of the value the input really has (the browser snaps it to `step`). */\n const updateFill = useEventCallback(() => {\n const input = inputRef.current;\n if (!input) return;\n const next = progressPercent(Number(input.value), rangeMin, rangeMax);\n if (input.style.getPropertyValue(PROGRESS_VAR) !== next) {\n input.style.setProperty(PROGRESS_VAR, next);\n }\n });\n\n // On mount and whenever the value or its range changes: React wrote the variable from the props,\n // the input may hold another value (step snapping, an uncontrolled value the user moved).\n React.useLayoutEffect(() => {\n updateFill();\n }, [value, defaultValue, min, max, step, updateFill]);\n\n // The reset event fires before the form restores the value: read it a microtask later.\n useFormReset(inputRef, () => queueMicrotask(updateFill), form);\n\n const handleChange = composeEventHandlers(\n onChange,\n (event: React.ChangeEvent<HTMLInputElement>) => {\n // A controlled fill follows `value` (a parent that rejects the change keeps it).\n if (value === undefined) updateFill();\n onValueChange?.(Number(event.currentTarget.value));\n },\n { checkDefaultPrevented: false },\n );\n\n return (\n <input\n ref={mergedRef}\n type=\"range\"\n className={cn(\n 'w-full cursor-pointer appearance-none bg-transparent',\n railClasses,\n // Thumb. WebKit and Blink align its top with the rail's top, so it is pulled up by half the\n // difference of the two heights (5 and 1 spacing units): it stays centred at any root\n // font size.\n '[&::-webkit-slider-thumb]:-mt-2 [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-background [&::-webkit-slider-thumb]:bg-primary [&::-webkit-slider-thumb]:shadow',\n // Firefox thumb\n '[&::-moz-range-thumb]:h-5 [&::-moz-range-thumb]:w-5 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-background [&::-moz-range-thumb]:bg-primary [&::-moz-range-thumb]:shadow',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n focusRing,\n // Forced colors replace the author backgrounds of the rail and thumb with Canvas: give\n // every part a system color instead.\n forcedColors.rangeInput,\n forcedColorsFill,\n className,\n )}\n style={{ ...style, [PROGRESS_VAR]: renderedProgress } as React.CSSProperties}\n value={value}\n defaultValue={defaultValue}\n min={min}\n max={max}\n step={step}\n form={form}\n {...props}\n {...fieldProps}\n onChange={handleChange}\n />\n );\n};\n\nSlider.displayName = 'Slider';\n"],"mappings":";;;;;;;;;;;AAmCA,IAAMC,IAAe;AAGrB,SAASC,EAAgB,GAAe,GAAa,GAAqB;CACxE,IAAMC,IAAQC,IAAMC,KAAQC,IAAQD,MAAQD,IAAMC,KAAQ,MAAM;CAChE,OAAO,GAAG,OAAO,SAASF,CAAK,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAGA,CAAK,CAAC,IAAI,EAAE;AAC3E;AAOA,IAAMI,IAAc;CAElB;CACA;CACA;CACA;CACA;AACF,GAMMC,IAAmB;CACvB;CACA;CACA;CACA;AACF,GAcaC,KAAU,EACrB,cACA,UACA,UACA,UACA,iBACA,QACA,QACA,SACA,SACA,aACA,kBACA,QACA,OACA,cAAcC,GACd,mBAAmBC,GACnB,oBAAoBC,GACpB,gBAAgBC,GAChB,iBAAiBC,GACjB,aACA,GAAGC,QACc;CACjB,IAAMC,IAAaC,EACjB;EACE;EACA,cAAcP,KAAaQ;EAC3B,mBAAmBP;EACnB,oBAAoBC;EACpB,gBAAgBC;EAChB,iBAAiBC;EACjB;CACF,GACA,EAAE,gBAAgB,GAAK,CACzB,GAEMK,IAAWnB,EAAM,OAAyB,IAAI,GAC9CoB,IAAYC,EAAcF,GAAUG,CAAG,GACvCC,IAAWlB,KAAO,GAClBmB,IAAWpB,KAAO,KAElBqB,IAAmBvB,EACvBI,KAASoB,KAAgBH,KAAYC,IAAWD,KAAY,GAC5DA,GACAC,CACF,GAGMG,IAAaC,QAAuB;EACxC,IAAMC,IAAQV,EAAS;EACvB,IAAI,CAACU,GAAO;EACZ,IAAMC,IAAO5B,EAAgB,OAAO2B,EAAM,KAAK,GAAGN,GAAUC,CAAQ;EACpE,AAAIK,EAAM,MAAM,iBAAiB5B,CAAY,MAAM6B,KACjDD,EAAM,MAAM,YAAY5B,GAAc6B,CAAI;CAE9C,CAAC;CASD,AALA9B,EAAM,sBAAsB;EAC1B,EAAW;CACb,GAAG;EAACM;EAAOoB;EAAcrB;EAAKD;EAAK2B;EAAMJ;CAAU,CAAC,GAGpDK,EAAab,SAAgB,eAAeQ,CAAU,GAAGM,CAAI;CAE7D,IAAMC,IAAeC,EACnBC,IACC,MAA+C;EAG9C,AADI9B,MAAU,KAAA,KAAWqB,EAAW,GACpCU,IAAgB,OAAOC,EAAM,cAAc,KAAK,CAAC;CACnD,GACA,EAAE,uBAAuB,GAAM,CACjC;CAEA,OACE,kBAAC,SAAD;EACE,KAAKlB;EACL,MAAK;EACL,WAAWmB,EACT,wDACAhC,GAIA,qUAEA,+NACA,mDACAiC,GAGAC,EAAa,YACbjC,GACAkC,CACF;EACA,OAAO;GAAE,GAAGC;IAAQ1C,IAAewB;EAAiB;EAC7C;EACO;EACT;EACA;EACC;EACA;EACN,GAAIV;EACJ,GAAIC;EACJ,UAAUkB;CACX,CAAA;AAEL;AAEA,EAAO,cAAc"}
|
|
1
|
+
{"version":3,"file":"Slider.mjs","names":["React","PROGRESS_VAR","progressPercent","share","max","min","value","railClasses","forcedColorsFill","Slider","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","props","fieldProps","useFieldControl","label","inputRef","mergedRef","useMergedRefs","ref","rangeMin","rangeMax","renderedProgress","defaultValue","updateFill","useEventCallback","input","next","step","useFormReset","form","handleChange","composeEventHandlers","onChange","onValueChange","event","cn","sliderClassNames","focusRing","forcedColors","className","style"],"sources":["../../../src/components/input/Slider.tsx"],"sourcesContent":["import * as React from 'react';\nimport { sliderClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\n\n/** Properties for the Slider component. */\nexport interface SliderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {\n /** Controlled slider value. */\n value?: number;\n /** Initial value for uncontrolled usage. */\n defaultValue?: number;\n /** Native change event handler (`event.target.value` is a string). */\n onChange?: React.ChangeEventHandler<HTMLInputElement>;\n /** Called with the new value as a number on every change, next to the native `onChange`. */\n onValueChange?: (value: number) => void;\n /** Minimum allowed value. */\n min?: number;\n /** Maximum allowed value. */\n max?: number;\n /** Step increment between values. */\n step?: number;\n /**\n * Accessible label for the slider (sets `aria-label`; an explicit `aria-label` wins). Inside a\n * `Field`, leave it out so the Field's label names the slider.\n */\n label?: string;\n /** Ref to the `<input type=\"range\">` element. */\n ref?: React.Ref<HTMLInputElement>;\n}\n\n/** The CSS variable that holds how much of the rail the fill covers (`<p>%`). */\nconst PROGRESS_VAR = '--wave-slider-progress';\n\n/** The share of the rail up to `value`, as a CSS percentage: 0–100, and 0 when `max <= min`. */\nfunction progressPercent(value: number, min: number, max: number): string {\n const share = max > min ? ((value - min) / (max - min)) * 100 : 0;\n return `${Number.isFinite(share) ? Math.min(100, Math.max(0, share)) : 0}%`;\n}\n\n/**\n * The rail: the primary fill up to the thumb, the accessible stroke after it. WebKit and Blink\n * draw it as a gradient on the track (mirrored for right-to-left); Firefox has a progress part and\n * mirrors it itself. The track color stays underneath (the whole rail without the variable).\n */\nconst railClasses = [\n // The rail color gives the rail itself 3:1 non-text contrast.\n '[&::-webkit-slider-runnable-track]:h-1 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-stroke-accessible',\n '[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--wave-primary)_var(--wave-slider-progress),var(--wave-stroke-accessible)_var(--wave-slider-progress))]',\n 'wave-rtl:[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_left,var(--wave-primary)_var(--wave-slider-progress),var(--wave-stroke-accessible)_var(--wave-slider-progress))]',\n '[&::-moz-range-track]:h-1 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-stroke-accessible',\n '[&::-moz-range-progress]:h-1 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-primary',\n];\n\n/**\n * Forced colors, after `forcedColors.rangeInput` (which draws the whole rail in CanvasText): the\n * filled part in Highlight; a disabled rail stays GrayText, without the fill.\n */\nconst forcedColorsFill = [\n 'forced-colors:[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,Highlight_var(--wave-slider-progress),CanvasText_var(--wave-slider-progress))]',\n 'forced-colors:wave-rtl:[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_left,Highlight_var(--wave-slider-progress),CanvasText_var(--wave-slider-progress))]',\n 'forced-colors:[&::-moz-range-progress]:bg-[Highlight]',\n 'forced-colors:disabled:[&::-webkit-slider-runnable-track]:bg-none forced-colors:disabled:[&::-moz-range-progress]:bg-[GrayText]',\n];\n\n/**\n * A native range input with Fluent styling: a rail drawn in the accessible stroke color (3:1\n * against the page), filled in the primary color up to a primary thumb; in forced-colors mode the\n * rail, fill and thumb are drawn in system colors. Inside a `Field` it picks up the label, hint,\n * validation message, `required` and invalid state automatically.\n *\n * The fill follows the value through the `--wave-slider-progress` variable on the input (also in\n * the server HTML), including the browser's snapping to `step` and a form reset.\n *\n * @example\n * <Slider label=\"Volume\" min={0} max={100} value={volume} onValueChange={setVolume} />\n */\nexport const Slider = ({\n className,\n style,\n label,\n value,\n defaultValue,\n min,\n max,\n step,\n form,\n onChange,\n onValueChange,\n ref,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n ...props\n}: SliderProps) => {\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label': ariaLabel ?? label,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n },\n { nativeRequired: true },\n );\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedRef = useMergedRefs(inputRef, ref);\n const rangeMin = min ?? 0;\n const rangeMax = max ?? 100;\n // During render (and on the server): the value, else the default, else the native midpoint.\n const renderedProgress = progressPercent(\n value ?? defaultValue ?? rangeMin + (rangeMax - rangeMin) / 2,\n rangeMin,\n rangeMax,\n );\n\n /** Writes the fill of the value the input really has (the browser snaps it to `step`). */\n const updateFill = useEventCallback(() => {\n const input = inputRef.current;\n if (!input) return;\n const next = progressPercent(Number(input.value), rangeMin, rangeMax);\n if (input.style.getPropertyValue(PROGRESS_VAR) !== next) {\n input.style.setProperty(PROGRESS_VAR, next);\n }\n });\n\n // On mount and whenever the value or its range changes: React wrote the variable from the props,\n // the input may hold another value (step snapping, an uncontrolled value the user moved).\n React.useLayoutEffect(() => {\n updateFill();\n }, [value, defaultValue, min, max, step, updateFill]);\n\n // The reset event fires before the form restores the value: read it a microtask later.\n useFormReset(inputRef, () => queueMicrotask(updateFill), form);\n\n const handleChange = composeEventHandlers(\n onChange,\n (event: React.ChangeEvent<HTMLInputElement>) => {\n // A controlled fill follows `value` (a parent that rejects the change keeps it).\n if (value === undefined) updateFill();\n onValueChange?.(Number(event.currentTarget.value));\n },\n { checkDefaultPrevented: false },\n );\n\n return (\n <input\n ref={mergedRef}\n type=\"range\"\n className={cn(\n sliderClassNames.root,\n 'w-full cursor-pointer appearance-none bg-transparent',\n railClasses,\n // Thumb. WebKit and Blink align its top with the rail's top, so it is pulled up by half the\n // difference of the two heights (5 and 1 spacing units): it stays centred at any root\n // font size.\n '[&::-webkit-slider-thumb]:-mt-2 [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-background [&::-webkit-slider-thumb]:bg-primary [&::-webkit-slider-thumb]:shadow',\n // Firefox thumb\n '[&::-moz-range-thumb]:h-5 [&::-moz-range-thumb]:w-5 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-background [&::-moz-range-thumb]:bg-primary [&::-moz-range-thumb]:shadow',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n focusRing,\n // Forced colors replace the author backgrounds of the rail and thumb with Canvas: give\n // every part a system color instead.\n forcedColors.rangeInput,\n forcedColorsFill,\n className,\n )}\n style={{ ...style, [PROGRESS_VAR]: renderedProgress } as React.CSSProperties}\n value={value}\n defaultValue={defaultValue}\n min={min}\n max={max}\n step={step}\n form={form}\n {...props}\n {...fieldProps}\n onChange={handleChange}\n />\n );\n};\n\nSlider.displayName = 'Slider';\n"],"mappings":";;;;;;;;;;;;AAoCA,IAAMC,IAAe;AAGrB,SAASC,EAAgB,GAAe,GAAa,GAAqB;CACxE,IAAMC,IAAQC,IAAMC,KAAQC,IAAQD,MAAQD,IAAMC,KAAQ,MAAM;CAChE,OAAO,GAAG,OAAO,SAASF,CAAK,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAGA,CAAK,CAAC,IAAI,EAAE;AAC3E;AAOA,IAAMI,IAAc;CAElB;CACA;CACA;CACA;CACA;AACF,GAMMC,IAAmB;CACvB;CACA;CACA;CACA;AACF,GAcaC,KAAU,EACrB,cACA,UACA,UACA,UACA,iBACA,QACA,QACA,SACA,SACA,aACA,kBACA,QACA,OACA,cAAcC,GACd,mBAAmBC,GACnB,oBAAoBC,GACpB,gBAAgBC,GAChB,iBAAiBC,GACjB,aACA,GAAGC,QACc;CACjB,IAAMC,IAAaC,EACjB;EACE;EACA,cAAcP,KAAaQ;EAC3B,mBAAmBP;EACnB,oBAAoBC;EACpB,gBAAgBC;EAChB,iBAAiBC;EACjB;CACF,GACA,EAAE,gBAAgB,GAAK,CACzB,GAEMK,IAAWnB,EAAM,OAAyB,IAAI,GAC9CoB,IAAYC,EAAcF,GAAUG,CAAG,GACvCC,IAAWlB,KAAO,GAClBmB,IAAWpB,KAAO,KAElBqB,IAAmBvB,EACvBI,KAASoB,KAAgBH,KAAYC,IAAWD,KAAY,GAC5DA,GACAC,CACF,GAGMG,IAAaC,QAAuB;EACxC,IAAMC,IAAQV,EAAS;EACvB,IAAI,CAACU,GAAO;EACZ,IAAMC,IAAO5B,EAAgB,OAAO2B,EAAM,KAAK,GAAGN,GAAUC,CAAQ;EACpE,AAAIK,EAAM,MAAM,iBAAiB5B,CAAY,MAAM6B,KACjDD,EAAM,MAAM,YAAY5B,GAAc6B,CAAI;CAE9C,CAAC;CASD,AALA9B,EAAM,sBAAsB;EAC1B,EAAW;CACb,GAAG;EAACM;EAAOoB;EAAcrB;EAAKD;EAAK2B;EAAMJ;CAAU,CAAC,GAGpDK,EAAab,SAAgB,eAAeQ,CAAU,GAAGM,CAAI;CAE7D,IAAMC,IAAeC,EACnBC,IACC,MAA+C;EAG9C,AADI9B,MAAU,KAAA,KAAWqB,EAAW,GACpCU,IAAgB,OAAOC,EAAM,cAAc,KAAK,CAAC;CACnD,GACA,EAAE,uBAAuB,GAAM,CACjC;CAEA,OACE,kBAAC,SAAD;EACE,KAAKlB;EACL,MAAK;EACL,WAAWmB,EACTC,EAAiB,MACjB,wDACAjC,GAIA,qUAEA,+NACA,mDACAkC,GAGAC,EAAa,YACblC,GACAmC,CACF;EACA,OAAO;GAAE,GAAGC;IAAQ3C,IAAewB;EAAiB;EAC7C;EACO;EACT;EACA;EACC;EACA;EACN,GAAIV;EACJ,GAAIC;EACJ,UAAUkB;CACX,CAAA;AAEL;AAEA,EAAO,cAAc"}
|
|
@@ -1,2 +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/composeEventHandlers.cjs"),ee=require("../../hooks/useControllable.cjs"),te=require("../../hooks/useMergedRefs.cjs"),ne=require("../../hooks/useFieldControl.cjs"),re=require("../../lib/styles.cjs"),
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),ee=require("../../hooks/useControllable.cjs"),te=require("../../hooks/useMergedRefs.cjs"),ne=require("../../hooks/useFieldControl.cjs"),re=require("../../lib/styles.cjs"),a=require("../../lib/icons.cjs"),ie=require("./Input.cjs"),ae=require("../../hooks/useFormReset.cjs"),oe=require("../internal/HiddenInput.cjs");let o=require("react");o=e.__toESM(o,1);let s=require("react/jsx-runtime");var c=/^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i,se=/^[+-]?\.?$/;function l(e){let t=e.trim();if(!c.test(t))return null;let n=Number(t);return Number.isFinite(n)?n:null}function u(e){if(!Number.isFinite(e))return 0;let[t,n]=String(e).toLowerCase().split(`e`),r=t.split(`.`)[1]?.length??0;return Math.max(0,r-(n?Number(n):0))}function d(e,t){return Number(e.toFixed(Math.min(t,20)))}var f=t.cn(`flex h-8 w-8 shrink-0 items-center justify-center border-input bg-transparent p-0 text-foreground`,`not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:active:bg-subtle-pressed`,`disabled:pointer-events-none`),p=({value:e,defaultValue:c,onValueChange:p,onChange:m,min:h=-1/0,max:g=1/0,step:_=1,largeStep:v,disabled:y,name:ce,form:b,labels:x,className:le,hidden:ue,ref:de,controlRef:fe,id:pe,"aria-label":me,"aria-labelledby":he,"aria-describedby":S,"aria-invalid":C,"aria-required":w,"aria-errormessage":T,"aria-details":E,"aria-valuetext":D,required:O,readOnly:k,placeholder:A,maxLength:j,spellCheck:M,autoComplete:N=`off`,autoFocus:P,inputMode:F,enterKeyHint:I,tabIndex:L,onFocus:R,onBlur:ge,onKeyDown:_e,onKeyUp:ve,...ye})=>{m!==void 0&&n.warnDeprecated(`SpinButton`,`onChange`,`onValueChange`);let z=c??0,[B,V]=ee.useControllable(e,z,e=>{p?.(e),m?.(e)}),[H,U]=o.useState(null),[be,xe]=o.useState(B);Object.is(be,B)||(xe(B),U(null));let W=H===null?null:l(H),G=W??B,Se=H!==null&&W===null&&H.trim()!==``&&!se.test(H.trim()),Ce=e=>Math.min(g,Math.max(h,e)),K=!y&&!k,q=e=>{U(null),V(Ce(e))},J=e=>{let t=Math.max(u(_),u(e),u(G));q(d(G+e,t))},Y=()=>{H!==null&&(W===null?U(null):q(W))},X=o.useRef(null),we=te.useMergedRefs(X,fe),Z=ne.useFieldControl({id:pe,"aria-label":me,"aria-labelledby":he,"aria-describedby":S,"aria-invalid":C,"aria-required":w,required:O},{nativeRequired:!0}),Q=Se?!0:Z[`aria-invalid`],Te=ie.isInvalidLook(!1,Q);ae.useFormReset(X,()=>{U(null),V(z)},b),o.useEffect(()=>{let e=X.current;e&&(e.hasAttribute(`aria-label`)||e.hasAttribute(`aria-labelledby`)||(e.labels?.length??0)>0||e.hasAttribute(`title`)||n.warnOnce(`SpinButton:unnamed`,"SpinButton: the spinbutton has no accessible name. Pass `aria-label` or `aria-labelledby`, use a <label htmlFor>, or render it inside a Field."))});let Ee=e=>{if(!K||e.altKey||e.ctrlKey||e.metaKey)return;let t=v??d(_*10,u(_));switch(e.key){case`ArrowUp`:case`ArrowDown`:case`PageUp`:case`PageDown`:{e.preventDefault();let n=e.key===`ArrowUp`||e.key===`ArrowDown`?_:t;J(e.key===`ArrowUp`||e.key===`PageUp`?n:-n);return}case`Home`:case`End`:{let t=e.key===`Home`?h:g;if(!Number.isFinite(t))return;e.preventDefault(),q(t);return}case`Enter`:Y();return;case`Escape`:H!==null&&(e.preventDefault(),U(null));return}},De=h<0?`text`:u(_)>0||u(h)>0?`decimal`:`numeric`,$=e=>e.preventDefault();return(0,s.jsxs)(`div`,{ref:de,className:t.cn(i.spinButtonClassNames.root,`relative inline-flex items-center rounded border border-input border-b-stroke-accessible bg-background`,re.inputFocusWithin,Te&&`border-destructive focus-within:border-b-destructive`,y&&`cursor-not-allowed opacity-50`,le),hidden:ue,...ye,children:[(0,s.jsx)(`button`,{type:`button`,tabIndex:-1,onMouseDown:$,onClick:()=>J(-_),disabled:!K||G<=h,"aria-label":x?.decrement??`Decrement`,className:t.cn(i.spinButtonClassNames.decrementButton,f,`border-e`,!y&&`disabled:opacity-50`),children:(0,s.jsx)(a.SubtractIcon,{size:12})}),(0,s.jsx)(`input`,{ref:we,type:`text`,role:`spinbutton`,inputMode:F??De,autoComplete:N,autoFocus:P,enterKeyHint:I,placeholder:A,maxLength:j,spellCheck:M,tabIndex:L,readOnly:k,form:b,...Z,"aria-invalid":Q,"aria-errormessage":T,"aria-details":E,"aria-valuenow":B,"aria-valuemin":Number.isFinite(h)?h:void 0,"aria-valuemax":Number.isFinite(g)?g:void 0,"aria-valuetext":D,value:H??String(B),onChange:e=>U(e.target.value),onFocus:R,onBlur:r.composeEventHandlers(ge,Y,{checkDefaultPrevented:!1}),onKeyDown:r.composeEventHandlers(_e,Ee),onKeyUp:ve,disabled:y,className:t.cn(i.spinButtonClassNames.input,`h-8 w-12 min-w-0 border-none bg-transparent text-center text-body-1 text-foreground focus:outline-hidden disabled:cursor-not-allowed [appearance:textfield]`)}),(0,s.jsx)(`button`,{type:`button`,tabIndex:-1,onMouseDown:$,onClick:()=>J(_),disabled:!K||G>=g,"aria-label":x?.increment??`Increment`,className:t.cn(i.spinButtonClassNames.incrementButton,f,`border-s`,!y&&`disabled:opacity-50`),children:(0,s.jsx)(a.AddIcon,{size:12})}),(0,s.jsx)(oe.HiddenInput,{name:ce,form:b,disabled:y,value:String(B)})]})};p.displayName=`SpinButton`,exports.SpinButton=p;
|
|
2
2
|
//# sourceMappingURL=SpinButton.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpinButton.cjs","names":["cn","useControllable","React","useMergedRefs","useFieldControl","isInvalidLook","inputFocusWithin","SubtractIcon","composeEventHandlers","AddIcon","HiddenInput","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_useControllable","require_useMergedRefs","require_useFieldControl","require_styles","require_icons","require_Input","require_useFormReset","require_HiddenInput","react","react_jsx_runtime","NUMBER_TEXT","PARTIAL_NUMBER_TEXT","parseNumberText","trimmed","text","decimalsOf","n","mantissa","exponent","fraction","roundTo","decimals","stepButtonClass","SpinButton","valueProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaValueText","rest","onChange","initialValue","defaultValue","value","setValue","onValueChange","next","draft","setDraft","prevValue","setPrevValue","draftNumber","current","draftInvalid","clamp","max","min","interactive","disabled","readOnly","commit","stepBy","precision","step","delta","commitDraft","inputRef","mergedInputRef","controlRef","fieldProps","ariaInvalidValue","invalidLook","form","input","handleKeyDown","big","largeStep","size","bound","defaultInputMode","keepFocus","className","labels","inputMode","onBlur","onKeyDown"],"sources":["../../../src/components/input/SpinButton.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { AddIcon, SubtractIcon } from '../../lib/icons';\nimport { inputFocusWithin, inputInvalidWithin } from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { isInvalidLook } from './Input';\n\n/**\n * Props that SpinButton routes to its `<input role=\"spinbutton\">` (C-ROUTING): the id, the ARIA\n * naming/validation attributes, native text-input attributes and the focus/keyboard handlers.\n */\nexport type SpinButtonInputProps = Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n | 'id'\n | 'aria-label'\n | 'aria-labelledby'\n | 'aria-describedby'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-errormessage'\n | 'aria-details'\n | 'aria-valuetext'\n | 'required'\n | 'readOnly'\n | 'placeholder'\n | 'maxLength'\n | 'spellCheck'\n | 'autoComplete'\n | 'autoFocus'\n | 'inputMode'\n | 'enterKeyHint'\n | 'tabIndex'\n | 'onFocus'\n | 'onBlur'\n | 'onKeyDown'\n | 'onKeyUp'\n>;\n\n/**\n * Names of the SpinButton's step buttons, for localization. Each member is optional and falls back\n * to its English default.\n */\nexport interface SpinButtonLabels {\n /** Name of the button that steps up.\n * @default 'Increment'\n */\n increment?: string;\n /** Name of the button that steps down.\n * @default 'Decrement'\n */\n decrement?: string;\n}\n\n/** Properties for the SpinButton component. */\nexport interface SpinButtonProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | keyof SpinButtonInputProps\n >,\n SpinButtonInputProps {\n /** Controlled numeric value. */\n value?: number;\n /** Initial value for uncontrolled usage (also what a form reset restores).\n * @default 0\n */\n defaultValue?: number;\n /**\n * Called with the new value when it changes: a step (buttons, arrow keys, PageUp/PageDown,\n * Home/End) or a typed value committed on blur or Enter. Not called while the user is typing,\n * nor when the value stays the same.\n */\n onValueChange?: (value: number) => void;\n /**\n * Called with the new value when it changes.\n * @deprecated Use `onValueChange`. (`onChange` is reserved for native change events.)\n */\n onChange?: (value: number) => void;\n /** Minimum allowed value.\n * @default -Infinity\n */\n min?: number;\n /** Maximum allowed value.\n * @default Infinity\n */\n max?: number;\n /** Step of the increment/decrement buttons and of ArrowUp/ArrowDown.\n * @default 1\n */\n step?: number;\n /** Step of PageUp/PageDown.\n * @default step * 10\n */\n largeStep?: number;\n /** Whether the spin button is disabled and non-interactive. */\n disabled?: boolean;\n /** Form field name. With a name, the committed value is submitted with the form. */\n name?: string;\n /** Id of the form the spin button belongs to, when it is rendered outside that form. */\n form?: string;\n /**\n * Names of the −/+ step buttons (not tab stops, but in the accessibility tree), for\n * localization. Unset members keep their English defaults.\n */\n labels?: SpinButtonLabels;\n /** Ref to the root `<div>`. */\n ref?: React.Ref<HTMLDivElement>;\n /** Ref to the `<input role=\"spinbutton\">` (the focusable control). */\n controlRef?: React.Ref<HTMLInputElement>;\n}\n\n/** Decimal numbers as a user types them: `12`, `-3`, `1.5`, `.5`, `2.`, `1e3`. */\nconst NUMBER_TEXT = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n/** Text on the way to a number (`-`, `.`, `-.`): not a value yet, but not an error either. */\nconst PARTIAL_NUMBER_TEXT = /^[+-]?\\.?$/;\n\nfunction parseNumberText(text: string): number | null {\n const trimmed = text.trim();\n if (!NUMBER_TEXT.test(trimmed)) return null;\n const n = Number(trimmed);\n return Number.isFinite(n) ? n : null;\n}\n\n/** Number of decimals of `n` as written by JavaScript (`0.1` → 1, `1e-7` → 7). */\nfunction decimalsOf(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const [mantissa, exponent] = String(n).toLowerCase().split('e');\n const fraction = mantissa.split('.')[1]?.length ?? 0;\n return Math.max(0, fraction - (exponent ? Number(exponent) : 0));\n}\n\nfunction roundTo(n: number, decimals: number): number {\n return Number(n.toFixed(Math.min(decimals, 20)));\n}\n\nconst stepButtonClass = cn(\n // Padding and background set here (C-NATIVE): an app-wide `button` rule cannot fill them.\n 'flex h-8 w-8 shrink-0 items-center justify-center border-input bg-transparent p-0 text-foreground',\n 'not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:active:bg-subtle-pressed',\n 'disabled:pointer-events-none',\n);\n\n/**\n * A numeric input with decrement/increment buttons (APG spinbutton pattern).\n *\n * - **Keyboard** on the input: ArrowUp/ArrowDown step by `step`, PageUp/PageDown by `largeStep`\n * (default ten steps), Home/End jump to `min`/`max` when they are finite. The −/+ buttons are\n * not tab stops and never take focus, so focus stays on the spinbutton and screen readers\n * announce the new value.\n * - **Typing** edits a draft: the value is parsed, clamped and committed on blur or Enter\n * (Escape reverts). Text that is not a number is flagged with `aria-invalid` and reverted on\n * blur. Steps (keys and buttons) start from the typed number, and the −/+ buttons are disabled\n * when that number is at `min`/`max`. Steps are rounded to the precision of `step` and of the\n * value, so `0.1 + 0.2` is `0.3`.\n * - **Routing**: `id`, ARIA, native input attributes and focus/keyboard handlers go to the\n * `<input role=\"spinbutton\">`; `className`, `style`, `data-*`, other handlers and `ref` stay on\n * the root (`controlRef` reaches the input). Inside a `Field` it picks up the label, hint, error\n * and required state automatically. It has no built-in name: pass `aria-label`/`aria-labelledby`\n * or use a label (development warning otherwise).\n * - **Forms**: with `name` the committed value is submitted; `required` makes the input natively\n * required; a form reset restores `defaultValue`.\n * - The −/+ buttons are named \"Decrement\"/\"Increment\"; `labels` localizes the names.\n *\n * @example\n * <SpinButton aria-label=\"Quantity\" min={1} max={10} value={qty} onValueChange={setQty} />\n */\nexport const SpinButton = ({\n value: valueProp,\n defaultValue,\n onValueChange,\n onChange,\n min = -Infinity,\n max = Infinity,\n step = 1,\n largeStep,\n disabled,\n name,\n form,\n labels,\n className,\n hidden,\n ref,\n controlRef,\n // Routed to the input (C-ROUTING)\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 'aria-valuetext': ariaValueText,\n required,\n readOnly,\n placeholder,\n maxLength,\n spellCheck,\n autoComplete = 'off',\n autoFocus,\n inputMode,\n enterKeyHint,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n ...rest\n}: SpinButtonProps) => {\n if (onChange !== undefined) warnDeprecated('SpinButton', 'onChange', 'onValueChange');\n const initialValue = defaultValue ?? 0;\n const [value, setValue] = useControllable(valueProp, initialValue, (next: number) => {\n onValueChange?.(next);\n onChange?.(next);\n });\n\n // The text is a draft while the user types (null = show the value).\n const [draft, setDraft] = React.useState<string | null>(null);\n // A value that changes from outside replaces the draft (adjust state during render, C-HOOKS).\n const [prevValue, setPrevValue] = React.useState(value);\n if (!Object.is(prevValue, value)) {\n setPrevValue(value);\n setDraft(null);\n }\n\n const draftNumber = draft === null ? null : parseNumberText(draft);\n // What stepping starts from: the typed draft when it is a number, else the value. The −/+\n // buttons are enabled by it too, so they agree with ArrowUp/ArrowDown while the user types.\n const current = draftNumber ?? value;\n const draftInvalid =\n draft !== null &&\n draftNumber === null &&\n draft.trim() !== '' &&\n !PARTIAL_NUMBER_TEXT.test(draft.trim());\n\n const clamp = (n: number) => Math.min(max, Math.max(min, n));\n const interactive = !disabled && !readOnly;\n\n const commit = (next: number) => {\n setDraft(null);\n setValue(clamp(next));\n };\n\n /** Steps from the typed draft when it is a number, else from the value. */\n const stepBy = (delta: number) => {\n const precision = Math.max(decimalsOf(step), decimalsOf(delta), decimalsOf(current));\n commit(roundTo(current + delta, precision));\n };\n\n const commitDraft = () => {\n if (draft === null) return;\n if (draftNumber === null) setDraft(null);\n else commit(draftNumber);\n };\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef);\n\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n },\n { nativeRequired: true },\n );\n // Typed text that is not a number is invalid whatever the consumer says; otherwise the\n // consumer's or the Field's `aria-invalid` is passed through as is (`grammar` included), and the\n // error look follows the shared rule of the text controls.\n const ariaInvalidValue = draftInvalid ? true : fieldProps['aria-invalid'];\n const invalidLook = isInvalidLook(false, ariaInvalidValue);\n\n useFormReset(\n inputRef,\n () => {\n setDraft(null);\n setValue(initialValue);\n },\n form,\n );\n\n // No built-in name any more (\"Value\" named every instance the same): report unnamed inputs.\n React.useEffect(() => {\n const input = inputRef.current;\n if (!input) return;\n const named =\n input.hasAttribute('aria-label') ||\n input.hasAttribute('aria-labelledby') ||\n (input.labels?.length ?? 0) > 0 ||\n input.hasAttribute('title');\n if (!named) {\n warnOnce(\n 'SpinButton:unnamed',\n 'SpinButton: the spinbutton has no accessible name. Pass `aria-label` or `aria-labelledby`, use a <label htmlFor>, or render it inside a Field.',\n );\n }\n });\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Read-only: the keys keep their native caret behaviour and never change the value.\n if (!interactive || e.altKey || e.ctrlKey || e.metaKey) return;\n // Ten steps, rounded: step * 10 carries float error (0.07 * 10 = 0.7000000000000001) that\n // stepBy would otherwise keep, since it rounds to the precision of the delta too.\n const big = largeStep ?? roundTo(step * 10, decimalsOf(step));\n switch (e.key) {\n case 'ArrowUp':\n case 'ArrowDown':\n case 'PageUp':\n case 'PageDown': {\n e.preventDefault();\n const size = e.key === 'ArrowUp' || e.key === 'ArrowDown' ? step : big;\n stepBy(e.key === 'ArrowUp' || e.key === 'PageUp' ? size : -size);\n return;\n }\n case 'Home':\n case 'End': {\n const bound = e.key === 'Home' ? min : max;\n if (!Number.isFinite(bound)) return; // no bound: Home/End move the caret\n e.preventDefault();\n commit(bound);\n return;\n }\n case 'Enter':\n // Not prevented: Enter still submits the surrounding form, with the committed value.\n commitDraft();\n return;\n case 'Escape':\n if (draft !== null) {\n e.preventDefault(); // enclosing layers (a Dialog) ignore this Escape\n setDraft(null);\n }\n return;\n default:\n }\n };\n\n const defaultInputMode: React.HTMLAttributes<HTMLInputElement>['inputMode'] =\n min < 0 ? 'text' : decimalsOf(step) > 0 || decimalsOf(min) > 0 ? 'decimal' : 'numeric';\n\n // The step buttons never take focus: a pointer press leaves it where it is (on the input while\n // editing), so a button that becomes disabled at a bound cannot drop focus to <body>.\n const keepFocus = (e: React.MouseEvent) => e.preventDefault();\n\n return (\n <div\n ref={ref}\n className={cn(\n 'relative inline-flex items-center rounded border border-input border-b-stroke-accessible bg-background',\n inputFocusWithin,\n invalidLook && inputInvalidWithin,\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n hidden={hidden}\n {...rest}\n >\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(-step)}\n disabled={!interactive || current <= min}\n aria-label={labels?.decrement ?? 'Decrement'}\n className={cn(stepButtonClass, 'border-e', !disabled && 'disabled:opacity-50')}\n >\n <SubtractIcon size={12} />\n </button>\n\n <input\n ref={mergedInputRef}\n type=\"text\"\n role=\"spinbutton\"\n inputMode={inputMode ?? defaultInputMode}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n enterKeyHint={enterKeyHint}\n placeholder={placeholder}\n maxLength={maxLength}\n spellCheck={spellCheck}\n tabIndex={tabIndex}\n readOnly={readOnly}\n form={form}\n {...fieldProps}\n aria-invalid={ariaInvalidValue}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-valuenow={value}\n aria-valuemin={Number.isFinite(min) ? min : undefined}\n aria-valuemax={Number.isFinite(max) ? max : undefined}\n aria-valuetext={ariaValueText}\n value={draft ?? String(value)}\n onChange={(e) => setDraft(e.target.value)}\n onFocus={onFocus}\n onBlur={composeEventHandlers(onBlur, commitDraft, { checkDefaultPrevented: false })}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyUp={onKeyUp}\n disabled={disabled}\n className=\"h-8 w-12 min-w-0 border-none bg-transparent text-center text-body-1 text-foreground focus:outline-hidden disabled:cursor-not-allowed [appearance:textfield]\"\n />\n\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(step)}\n disabled={!interactive || current >= max}\n aria-label={labels?.increment ?? 'Increment'}\n className={cn(stepButtonClass, 'border-s', !disabled && 'disabled:opacity-50')}\n >\n <AddIcon size={12} />\n </button>\n\n <HiddenInput name={name} form={form} disabled={disabled} value={String(value)} />\n </div>\n );\n};\n\nSpinButton.displayName = 'SpinButton';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SpinButton.cjs","names":["cn","useControllable","React","useMergedRefs","useFieldControl","isInvalidLook","spinButtonClassNames","inputFocusWithin","SubtractIcon","composeEventHandlers","AddIcon","HiddenInput","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","react","react_jsx_runtime","NUMBER_TEXT","PARTIAL_NUMBER_TEXT","parseNumberText","trimmed","text","decimalsOf","n","mantissa","exponent","fraction","roundTo","decimals","stepButtonClass","SpinButton","valueProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaValueText","rest","onChange","initialValue","defaultValue","value","setValue","onValueChange","next","draft","setDraft","prevValue","setPrevValue","draftNumber","current","draftInvalid","clamp","max","min","interactive","disabled","readOnly","commit","stepBy","precision","step","delta","commitDraft","inputRef","mergedInputRef","controlRef","fieldProps","ariaInvalidValue","invalidLook","form","input","handleKeyDown","big","largeStep","size","bound","defaultInputMode","keepFocus","className","labels","inputMode","onBlur","onKeyDown"],"sources":["../../../src/components/input/SpinButton.tsx"],"sourcesContent":["import * as React from 'react';\nimport { spinButtonClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { AddIcon, SubtractIcon } from '../../lib/icons';\nimport { inputFocusWithin, inputInvalidWithin } from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { isInvalidLook } from './Input';\n\n/**\n * Props that SpinButton routes to its `<input role=\"spinbutton\">` (C-ROUTING): the id, the ARIA\n * naming/validation attributes, native text-input attributes and the focus/keyboard handlers.\n */\nexport type SpinButtonInputProps = Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n | 'id'\n | 'aria-label'\n | 'aria-labelledby'\n | 'aria-describedby'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-errormessage'\n | 'aria-details'\n | 'aria-valuetext'\n | 'required'\n | 'readOnly'\n | 'placeholder'\n | 'maxLength'\n | 'spellCheck'\n | 'autoComplete'\n | 'autoFocus'\n | 'inputMode'\n | 'enterKeyHint'\n | 'tabIndex'\n | 'onFocus'\n | 'onBlur'\n | 'onKeyDown'\n | 'onKeyUp'\n>;\n\n/**\n * Names of the SpinButton's step buttons, for localization. Each member is optional and falls back\n * to its English default.\n */\nexport interface SpinButtonLabels {\n /** Name of the button that steps up.\n * @default 'Increment'\n */\n increment?: string;\n /** Name of the button that steps down.\n * @default 'Decrement'\n */\n decrement?: string;\n}\n\n/** Properties for the SpinButton component. */\nexport interface SpinButtonProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | keyof SpinButtonInputProps\n >,\n SpinButtonInputProps {\n /** Controlled numeric value. */\n value?: number;\n /** Initial value for uncontrolled usage (also what a form reset restores).\n * @default 0\n */\n defaultValue?: number;\n /**\n * Called with the new value when it changes: a step (buttons, arrow keys, PageUp/PageDown,\n * Home/End) or a typed value committed on blur or Enter. Not called while the user is typing,\n * nor when the value stays the same.\n */\n onValueChange?: (value: number) => void;\n /**\n * Called with the new value when it changes.\n * @deprecated Use `onValueChange`. (`onChange` is reserved for native change events.)\n */\n onChange?: (value: number) => void;\n /** Minimum allowed value.\n * @default -Infinity\n */\n min?: number;\n /** Maximum allowed value.\n * @default Infinity\n */\n max?: number;\n /** Step of the increment/decrement buttons and of ArrowUp/ArrowDown.\n * @default 1\n */\n step?: number;\n /** Step of PageUp/PageDown.\n * @default step * 10\n */\n largeStep?: number;\n /** Whether the spin button is disabled and non-interactive. */\n disabled?: boolean;\n /** Form field name. With a name, the committed value is submitted with the form. */\n name?: string;\n /** Id of the form the spin button belongs to, when it is rendered outside that form. */\n form?: string;\n /**\n * Names of the −/+ step buttons (not tab stops, but in the accessibility tree), for\n * localization. Unset members keep their English defaults.\n */\n labels?: SpinButtonLabels;\n /** Ref to the root `<div>`. */\n ref?: React.Ref<HTMLDivElement>;\n /** Ref to the `<input role=\"spinbutton\">` (the focusable control). */\n controlRef?: React.Ref<HTMLInputElement>;\n}\n\n/** Decimal numbers as a user types them: `12`, `-3`, `1.5`, `.5`, `2.`, `1e3`. */\nconst NUMBER_TEXT = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n/** Text on the way to a number (`-`, `.`, `-.`): not a value yet, but not an error either. */\nconst PARTIAL_NUMBER_TEXT = /^[+-]?\\.?$/;\n\nfunction parseNumberText(text: string): number | null {\n const trimmed = text.trim();\n if (!NUMBER_TEXT.test(trimmed)) return null;\n const n = Number(trimmed);\n return Number.isFinite(n) ? n : null;\n}\n\n/** Number of decimals of `n` as written by JavaScript (`0.1` → 1, `1e-7` → 7). */\nfunction decimalsOf(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const [mantissa, exponent] = String(n).toLowerCase().split('e');\n const fraction = mantissa.split('.')[1]?.length ?? 0;\n return Math.max(0, fraction - (exponent ? Number(exponent) : 0));\n}\n\nfunction roundTo(n: number, decimals: number): number {\n return Number(n.toFixed(Math.min(decimals, 20)));\n}\n\nconst stepButtonClass = cn(\n // Padding and background set here (C-NATIVE): an app-wide `button` rule cannot fill them.\n 'flex h-8 w-8 shrink-0 items-center justify-center border-input bg-transparent p-0 text-foreground',\n 'not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:active:bg-subtle-pressed',\n 'disabled:pointer-events-none',\n);\n\n/**\n * A numeric input with decrement/increment buttons (APG spinbutton pattern).\n *\n * - **Keyboard** on the input: ArrowUp/ArrowDown step by `step`, PageUp/PageDown by `largeStep`\n * (default ten steps), Home/End jump to `min`/`max` when they are finite. The −/+ buttons are\n * not tab stops and never take focus, so focus stays on the spinbutton and screen readers\n * announce the new value.\n * - **Typing** edits a draft: the value is parsed, clamped and committed on blur or Enter\n * (Escape reverts). Text that is not a number is flagged with `aria-invalid` and reverted on\n * blur. Steps (keys and buttons) start from the typed number, and the −/+ buttons are disabled\n * when that number is at `min`/`max`. Steps are rounded to the precision of `step` and of the\n * value, so `0.1 + 0.2` is `0.3`.\n * - **Routing**: `id`, ARIA, native input attributes and focus/keyboard handlers go to the\n * `<input role=\"spinbutton\">`; `className`, `style`, `data-*`, other handlers and `ref` stay on\n * the root (`controlRef` reaches the input). Inside a `Field` it picks up the label, hint, error\n * and required state automatically. It has no built-in name: pass `aria-label`/`aria-labelledby`\n * or use a label (development warning otherwise).\n * - **Forms**: with `name` the committed value is submitted; `required` makes the input natively\n * required; a form reset restores `defaultValue`.\n * - The −/+ buttons are named \"Decrement\"/\"Increment\"; `labels` localizes the names.\n *\n * @example\n * <SpinButton aria-label=\"Quantity\" min={1} max={10} value={qty} onValueChange={setQty} />\n */\nexport const SpinButton = ({\n value: valueProp,\n defaultValue,\n onValueChange,\n onChange,\n min = -Infinity,\n max = Infinity,\n step = 1,\n largeStep,\n disabled,\n name,\n form,\n labels,\n className,\n hidden,\n ref,\n controlRef,\n // Routed to the input (C-ROUTING)\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 'aria-valuetext': ariaValueText,\n required,\n readOnly,\n placeholder,\n maxLength,\n spellCheck,\n autoComplete = 'off',\n autoFocus,\n inputMode,\n enterKeyHint,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n ...rest\n}: SpinButtonProps) => {\n if (onChange !== undefined) warnDeprecated('SpinButton', 'onChange', 'onValueChange');\n const initialValue = defaultValue ?? 0;\n const [value, setValue] = useControllable(valueProp, initialValue, (next: number) => {\n onValueChange?.(next);\n onChange?.(next);\n });\n\n // The text is a draft while the user types (null = show the value).\n const [draft, setDraft] = React.useState<string | null>(null);\n // A value that changes from outside replaces the draft (adjust state during render, C-HOOKS).\n const [prevValue, setPrevValue] = React.useState(value);\n if (!Object.is(prevValue, value)) {\n setPrevValue(value);\n setDraft(null);\n }\n\n const draftNumber = draft === null ? null : parseNumberText(draft);\n // What stepping starts from: the typed draft when it is a number, else the value. The −/+\n // buttons are enabled by it too, so they agree with ArrowUp/ArrowDown while the user types.\n const current = draftNumber ?? value;\n const draftInvalid =\n draft !== null &&\n draftNumber === null &&\n draft.trim() !== '' &&\n !PARTIAL_NUMBER_TEXT.test(draft.trim());\n\n const clamp = (n: number) => Math.min(max, Math.max(min, n));\n const interactive = !disabled && !readOnly;\n\n const commit = (next: number) => {\n setDraft(null);\n setValue(clamp(next));\n };\n\n /** Steps from the typed draft when it is a number, else from the value. */\n const stepBy = (delta: number) => {\n const precision = Math.max(decimalsOf(step), decimalsOf(delta), decimalsOf(current));\n commit(roundTo(current + delta, precision));\n };\n\n const commitDraft = () => {\n if (draft === null) return;\n if (draftNumber === null) setDraft(null);\n else commit(draftNumber);\n };\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef);\n\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n },\n { nativeRequired: true },\n );\n // Typed text that is not a number is invalid whatever the consumer says; otherwise the\n // consumer's or the Field's `aria-invalid` is passed through as is (`grammar` included), and the\n // error look follows the shared rule of the text controls.\n const ariaInvalidValue = draftInvalid ? true : fieldProps['aria-invalid'];\n const invalidLook = isInvalidLook(false, ariaInvalidValue);\n\n useFormReset(\n inputRef,\n () => {\n setDraft(null);\n setValue(initialValue);\n },\n form,\n );\n\n // No built-in name any more (\"Value\" named every instance the same): report unnamed inputs.\n React.useEffect(() => {\n const input = inputRef.current;\n if (!input) return;\n const named =\n input.hasAttribute('aria-label') ||\n input.hasAttribute('aria-labelledby') ||\n (input.labels?.length ?? 0) > 0 ||\n input.hasAttribute('title');\n if (!named) {\n warnOnce(\n 'SpinButton:unnamed',\n 'SpinButton: the spinbutton has no accessible name. Pass `aria-label` or `aria-labelledby`, use a <label htmlFor>, or render it inside a Field.',\n );\n }\n });\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Read-only: the keys keep their native caret behaviour and never change the value.\n if (!interactive || e.altKey || e.ctrlKey || e.metaKey) return;\n // Ten steps, rounded: step * 10 carries float error (0.07 * 10 = 0.7000000000000001) that\n // stepBy would otherwise keep, since it rounds to the precision of the delta too.\n const big = largeStep ?? roundTo(step * 10, decimalsOf(step));\n switch (e.key) {\n case 'ArrowUp':\n case 'ArrowDown':\n case 'PageUp':\n case 'PageDown': {\n e.preventDefault();\n const size = e.key === 'ArrowUp' || e.key === 'ArrowDown' ? step : big;\n stepBy(e.key === 'ArrowUp' || e.key === 'PageUp' ? size : -size);\n return;\n }\n case 'Home':\n case 'End': {\n const bound = e.key === 'Home' ? min : max;\n if (!Number.isFinite(bound)) return; // no bound: Home/End move the caret\n e.preventDefault();\n commit(bound);\n return;\n }\n case 'Enter':\n // Not prevented: Enter still submits the surrounding form, with the committed value.\n commitDraft();\n return;\n case 'Escape':\n if (draft !== null) {\n e.preventDefault(); // enclosing layers (a Dialog) ignore this Escape\n setDraft(null);\n }\n return;\n default:\n }\n };\n\n const defaultInputMode: React.HTMLAttributes<HTMLInputElement>['inputMode'] =\n min < 0 ? 'text' : decimalsOf(step) > 0 || decimalsOf(min) > 0 ? 'decimal' : 'numeric';\n\n // The step buttons never take focus: a pointer press leaves it where it is (on the input while\n // editing), so a button that becomes disabled at a bound cannot drop focus to <body>.\n const keepFocus = (e: React.MouseEvent) => e.preventDefault();\n\n return (\n <div\n ref={ref}\n className={cn(\n spinButtonClassNames.root,\n 'relative inline-flex items-center rounded border border-input border-b-stroke-accessible bg-background',\n inputFocusWithin,\n invalidLook && inputInvalidWithin,\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n hidden={hidden}\n {...rest}\n >\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(-step)}\n disabled={!interactive || current <= min}\n aria-label={labels?.decrement ?? 'Decrement'}\n className={cn(\n spinButtonClassNames.decrementButton,\n stepButtonClass,\n 'border-e',\n !disabled && 'disabled:opacity-50',\n )}\n >\n <SubtractIcon size={12} />\n </button>\n\n <input\n ref={mergedInputRef}\n type=\"text\"\n role=\"spinbutton\"\n inputMode={inputMode ?? defaultInputMode}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n enterKeyHint={enterKeyHint}\n placeholder={placeholder}\n maxLength={maxLength}\n spellCheck={spellCheck}\n tabIndex={tabIndex}\n readOnly={readOnly}\n form={form}\n {...fieldProps}\n aria-invalid={ariaInvalidValue}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-valuenow={value}\n aria-valuemin={Number.isFinite(min) ? min : undefined}\n aria-valuemax={Number.isFinite(max) ? max : undefined}\n aria-valuetext={ariaValueText}\n value={draft ?? String(value)}\n onChange={(e) => setDraft(e.target.value)}\n onFocus={onFocus}\n onBlur={composeEventHandlers(onBlur, commitDraft, { checkDefaultPrevented: false })}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyUp={onKeyUp}\n disabled={disabled}\n className={cn(\n spinButtonClassNames.input,\n 'h-8 w-12 min-w-0 border-none bg-transparent text-center text-body-1 text-foreground focus:outline-hidden disabled:cursor-not-allowed [appearance:textfield]',\n )}\n />\n\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(step)}\n disabled={!interactive || current >= max}\n aria-label={labels?.increment ?? 'Increment'}\n className={cn(\n spinButtonClassNames.incrementButton,\n stepButtonClass,\n 'border-s',\n !disabled && 'disabled:opacity-50',\n )}\n >\n <AddIcon size={12} />\n </button>\n\n <HiddenInput name={name} form={form} disabled={disabled} value={String(value)} />\n </div>\n );\n};\n\nSpinButton.displayName = 'SpinButton';\n"],"mappings":"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"}
|
|
@@ -2,76 +2,77 @@
|
|
|
2
2
|
import { cn as e } from "../../lib/cn.mjs";
|
|
3
3
|
import { warnDeprecated as t, warnOnce as n } from "../../lib/dev.mjs";
|
|
4
4
|
import { composeEventHandlers as r } from "../../lib/composeEventHandlers.mjs";
|
|
5
|
+
import { spinButtonClassNames as i } from "../../lib/classNames.mjs";
|
|
5
6
|
import { useControllable as ee } from "../../hooks/useControllable.mjs";
|
|
6
7
|
import { useMergedRefs as te } from "../../hooks/useMergedRefs.mjs";
|
|
7
8
|
import { useFieldControl as ne } from "../../hooks/useFieldControl.mjs";
|
|
8
|
-
import { inputFocusWithin as
|
|
9
|
+
import { inputFocusWithin as a } from "../../lib/styles.mjs";
|
|
9
10
|
import { AddIcon as re, SubtractIcon as ie } from "../../lib/icons.mjs";
|
|
10
11
|
import { isInvalidLook as ae } from "./Input.mjs";
|
|
11
12
|
import { useFormReset as oe } from "../../hooks/useFormReset.mjs";
|
|
12
13
|
import { HiddenInput as se } from "../internal/HiddenInput.mjs";
|
|
13
|
-
import * as
|
|
14
|
-
import { jsx as
|
|
14
|
+
import * as o from "react";
|
|
15
|
+
import { jsx as s, jsxs as ce } from "react/jsx-runtime";
|
|
15
16
|
//#region src/components/input/SpinButton.tsx
|
|
16
|
-
var
|
|
17
|
-
function
|
|
17
|
+
var c = /^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i, l = /^[+-]?\.?$/;
|
|
18
|
+
function le(e) {
|
|
18
19
|
let t = e.trim();
|
|
19
|
-
if (!
|
|
20
|
+
if (!c.test(t)) return null;
|
|
20
21
|
let n = Number(t);
|
|
21
22
|
return Number.isFinite(n) ? n : null;
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
+
function u(e) {
|
|
24
25
|
if (!Number.isFinite(e)) return 0;
|
|
25
26
|
let [t, n] = String(e).toLowerCase().split("e"), r = t.split(".")[1]?.length ?? 0;
|
|
26
27
|
return Math.max(0, r - (n ? Number(n) : 0));
|
|
27
28
|
}
|
|
28
|
-
function
|
|
29
|
+
function d(e, t) {
|
|
29
30
|
return Number(e.toFixed(Math.min(t, 20)));
|
|
30
31
|
}
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
let z =
|
|
34
|
-
ue?.(e),
|
|
35
|
-
}), [H, U] =
|
|
36
|
-
Object.is(
|
|
37
|
-
let W = H === null ? null :
|
|
38
|
-
U(null), V(
|
|
32
|
+
var f = e("flex h-8 w-8 shrink-0 items-center justify-center border-input bg-transparent p-0 text-foreground", "not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:active:bg-subtle-pressed", "disabled:pointer-events-none"), p = ({ value: c, defaultValue: p, onValueChange: ue, onChange: m, min: h = -Infinity, max: g = Infinity, step: _ = 1, largeStep: de, disabled: v, name: fe, form: y, labels: b, className: pe, hidden: me, ref: he, controlRef: x, id: S, "aria-label": C, "aria-labelledby": w, "aria-describedby": T, "aria-invalid": E, "aria-required": D, "aria-errormessage": O, "aria-details": k, "aria-valuetext": A, required: j, readOnly: M, placeholder: N, maxLength: P, spellCheck: F, autoComplete: I = "off", autoFocus: L, inputMode: R, enterKeyHint: ge, tabIndex: _e, onFocus: ve, onBlur: ye, onKeyDown: be, onKeyUp: xe, ...Se }) => {
|
|
33
|
+
m !== void 0 && t("SpinButton", "onChange", "onValueChange");
|
|
34
|
+
let z = p ?? 0, [B, V] = ee(c, z, (e) => {
|
|
35
|
+
ue?.(e), m?.(e);
|
|
36
|
+
}), [H, U] = o.useState(null), [Ce, we] = o.useState(B);
|
|
37
|
+
Object.is(Ce, B) || (we(B), U(null));
|
|
38
|
+
let W = H === null ? null : le(H), G = W ?? B, Te = H !== null && W === null && H.trim() !== "" && !l.test(H.trim()), Ee = (e) => Math.min(g, Math.max(h, e)), K = !v && !M, q = (e) => {
|
|
39
|
+
U(null), V(Ee(e));
|
|
39
40
|
}, J = (e) => {
|
|
40
|
-
let t = Math.max(
|
|
41
|
-
q(
|
|
41
|
+
let t = Math.max(u(_), u(e), u(G));
|
|
42
|
+
q(d(G + e, t));
|
|
42
43
|
}, Y = () => {
|
|
43
44
|
H !== null && (W === null ? U(null) : q(W));
|
|
44
|
-
}, X =
|
|
45
|
-
id:
|
|
46
|
-
"aria-label":
|
|
47
|
-
"aria-labelledby":
|
|
48
|
-
"aria-describedby":
|
|
49
|
-
"aria-invalid":
|
|
50
|
-
"aria-required":
|
|
51
|
-
required:
|
|
52
|
-
}, { nativeRequired: !0 }), Q =
|
|
45
|
+
}, X = o.useRef(null), De = te(X, x), Z = ne({
|
|
46
|
+
id: S,
|
|
47
|
+
"aria-label": C,
|
|
48
|
+
"aria-labelledby": w,
|
|
49
|
+
"aria-describedby": T,
|
|
50
|
+
"aria-invalid": E,
|
|
51
|
+
"aria-required": D,
|
|
52
|
+
required: j
|
|
53
|
+
}, { nativeRequired: !0 }), Q = Te ? !0 : Z["aria-invalid"], Oe = ae(!1, Q);
|
|
53
54
|
oe(X, () => {
|
|
54
55
|
U(null), V(z);
|
|
55
|
-
},
|
|
56
|
+
}, y), o.useEffect(() => {
|
|
56
57
|
let e = X.current;
|
|
57
58
|
e && (e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby") || (e.labels?.length ?? 0) > 0 || e.hasAttribute("title") || n("SpinButton:unnamed", "SpinButton: the spinbutton has no accessible name. Pass `aria-label` or `aria-labelledby`, use a <label htmlFor>, or render it inside a Field."));
|
|
58
59
|
});
|
|
59
|
-
let
|
|
60
|
+
let ke = (e) => {
|
|
60
61
|
if (!K || e.altKey || e.ctrlKey || e.metaKey) return;
|
|
61
|
-
let t = de ??
|
|
62
|
+
let t = de ?? d(_ * 10, u(_));
|
|
62
63
|
switch (e.key) {
|
|
63
64
|
case "ArrowUp":
|
|
64
65
|
case "ArrowDown":
|
|
65
66
|
case "PageUp":
|
|
66
67
|
case "PageDown": {
|
|
67
68
|
e.preventDefault();
|
|
68
|
-
let n = e.key === "ArrowUp" || e.key === "ArrowDown" ?
|
|
69
|
+
let n = e.key === "ArrowUp" || e.key === "ArrowDown" ? _ : t;
|
|
69
70
|
J(e.key === "ArrowUp" || e.key === "PageUp" ? n : -n);
|
|
70
71
|
return;
|
|
71
72
|
}
|
|
72
73
|
case "Home":
|
|
73
74
|
case "End": {
|
|
74
|
-
let t = e.key === "Home" ?
|
|
75
|
+
let t = e.key === "Home" ? h : g;
|
|
75
76
|
if (!Number.isFinite(t)) return;
|
|
76
77
|
e.preventDefault(), q(t);
|
|
77
78
|
return;
|
|
@@ -83,75 +84,75 @@ var d = e("flex h-8 w-8 shrink-0 items-center justify-center border-input bg-tra
|
|
|
83
84
|
H !== null && (e.preventDefault(), U(null));
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
86
|
-
},
|
|
87
|
+
}, Ae = h < 0 ? "text" : u(_) > 0 || u(h) > 0 ? "decimal" : "numeric", $ = (e) => e.preventDefault();
|
|
87
88
|
return /* @__PURE__ */ ce("div", {
|
|
88
89
|
ref: he,
|
|
89
|
-
className: e("relative inline-flex items-center rounded border border-input border-b-stroke-accessible bg-background",
|
|
90
|
+
className: e(i.root, "relative inline-flex items-center rounded border border-input border-b-stroke-accessible bg-background", a, Oe && "border-destructive focus-within:border-b-destructive", v && "cursor-not-allowed opacity-50", pe),
|
|
90
91
|
hidden: me,
|
|
91
|
-
...
|
|
92
|
+
...Se,
|
|
92
93
|
children: [
|
|
93
|
-
/* @__PURE__ */
|
|
94
|
+
/* @__PURE__ */ s("button", {
|
|
94
95
|
type: "button",
|
|
95
96
|
tabIndex: -1,
|
|
96
97
|
onMouseDown: $,
|
|
97
|
-
onClick: () => J(-
|
|
98
|
-
disabled: !K || G <=
|
|
99
|
-
"aria-label":
|
|
100
|
-
className: e(
|
|
101
|
-
children: /* @__PURE__ */
|
|
98
|
+
onClick: () => J(-_),
|
|
99
|
+
disabled: !K || G <= h,
|
|
100
|
+
"aria-label": b?.decrement ?? "Decrement",
|
|
101
|
+
className: e(i.decrementButton, f, "border-e", !v && "disabled:opacity-50"),
|
|
102
|
+
children: /* @__PURE__ */ s(ie, { size: 12 })
|
|
102
103
|
}),
|
|
103
|
-
/* @__PURE__ */
|
|
104
|
-
ref:
|
|
104
|
+
/* @__PURE__ */ s("input", {
|
|
105
|
+
ref: De,
|
|
105
106
|
type: "text",
|
|
106
107
|
role: "spinbutton",
|
|
107
|
-
inputMode:
|
|
108
|
-
autoComplete:
|
|
109
|
-
autoFocus:
|
|
110
|
-
enterKeyHint:
|
|
111
|
-
placeholder:
|
|
112
|
-
maxLength:
|
|
113
|
-
spellCheck:
|
|
114
|
-
tabIndex:
|
|
115
|
-
readOnly:
|
|
116
|
-
form:
|
|
108
|
+
inputMode: R ?? Ae,
|
|
109
|
+
autoComplete: I,
|
|
110
|
+
autoFocus: L,
|
|
111
|
+
enterKeyHint: ge,
|
|
112
|
+
placeholder: N,
|
|
113
|
+
maxLength: P,
|
|
114
|
+
spellCheck: F,
|
|
115
|
+
tabIndex: _e,
|
|
116
|
+
readOnly: M,
|
|
117
|
+
form: y,
|
|
117
118
|
...Z,
|
|
118
119
|
"aria-invalid": Q,
|
|
119
|
-
"aria-errormessage":
|
|
120
|
-
"aria-details":
|
|
120
|
+
"aria-errormessage": O,
|
|
121
|
+
"aria-details": k,
|
|
121
122
|
"aria-valuenow": B,
|
|
122
|
-
"aria-valuemin": Number.isFinite(
|
|
123
|
-
"aria-valuemax": Number.isFinite(
|
|
124
|
-
"aria-valuetext":
|
|
123
|
+
"aria-valuemin": Number.isFinite(h) ? h : void 0,
|
|
124
|
+
"aria-valuemax": Number.isFinite(g) ? g : void 0,
|
|
125
|
+
"aria-valuetext": A,
|
|
125
126
|
value: H ?? String(B),
|
|
126
127
|
onChange: (e) => U(e.target.value),
|
|
127
|
-
onFocus:
|
|
128
|
-
onBlur: r(
|
|
129
|
-
onKeyDown: r(
|
|
130
|
-
onKeyUp:
|
|
131
|
-
disabled:
|
|
132
|
-
className: "h-8 w-12 min-w-0 border-none bg-transparent text-center text-body-1 text-foreground focus:outline-hidden disabled:cursor-not-allowed [appearance:textfield]"
|
|
128
|
+
onFocus: ve,
|
|
129
|
+
onBlur: r(ye, Y, { checkDefaultPrevented: !1 }),
|
|
130
|
+
onKeyDown: r(be, ke),
|
|
131
|
+
onKeyUp: xe,
|
|
132
|
+
disabled: v,
|
|
133
|
+
className: e(i.input, "h-8 w-12 min-w-0 border-none bg-transparent text-center text-body-1 text-foreground focus:outline-hidden disabled:cursor-not-allowed [appearance:textfield]")
|
|
133
134
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
135
|
+
/* @__PURE__ */ s("button", {
|
|
135
136
|
type: "button",
|
|
136
137
|
tabIndex: -1,
|
|
137
138
|
onMouseDown: $,
|
|
138
|
-
onClick: () => J(
|
|
139
|
-
disabled: !K || G >=
|
|
140
|
-
"aria-label":
|
|
141
|
-
className: e(
|
|
142
|
-
children: /* @__PURE__ */
|
|
139
|
+
onClick: () => J(_),
|
|
140
|
+
disabled: !K || G >= g,
|
|
141
|
+
"aria-label": b?.increment ?? "Increment",
|
|
142
|
+
className: e(i.incrementButton, f, "border-s", !v && "disabled:opacity-50"),
|
|
143
|
+
children: /* @__PURE__ */ s(re, { size: 12 })
|
|
143
144
|
}),
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ s(se, {
|
|
145
146
|
name: fe,
|
|
146
|
-
form:
|
|
147
|
-
disabled:
|
|
147
|
+
form: y,
|
|
148
|
+
disabled: v,
|
|
148
149
|
value: String(B)
|
|
149
150
|
})
|
|
150
151
|
]
|
|
151
152
|
});
|
|
152
153
|
};
|
|
153
|
-
|
|
154
|
+
p.displayName = "SpinButton";
|
|
154
155
|
//#endregion
|
|
155
|
-
export {
|
|
156
|
+
export { p as SpinButton };
|
|
156
157
|
|
|
157
158
|
//# sourceMappingURL=SpinButton.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpinButton.mjs","names":["React","NUMBER_TEXT","PARTIAL_NUMBER_TEXT","parseNumberText","trimmed","text","decimalsOf","n","mantissa","exponent","fraction","roundTo","decimals","stepButtonClass","cn","SpinButton","valueProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaValueText","rest","onChange","warnDeprecated","initialValue","defaultValue","value","setValue","useControllable","onValueChange","next","draft","setDraft","prevValue","setPrevValue","draftNumber","current","draftInvalid","clamp","max","min","interactive","disabled","readOnly","commit","stepBy","precision","step","delta","commitDraft","inputRef","mergedInputRef","useMergedRefs","controlRef","fieldProps","useFieldControl","ariaInvalidValue","invalidLook","isInvalidLook","useFormReset","form","input","warnOnce","handleKeyDown","big","largeStep","size","bound","defaultInputMode","keepFocus","inputFocusWithin","className","labels","SubtractIcon","inputMode","composeEventHandlers","onBlur","onKeyDown","AddIcon","HiddenInput"],"sources":["../../../src/components/input/SpinButton.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { AddIcon, SubtractIcon } from '../../lib/icons';\nimport { inputFocusWithin, inputInvalidWithin } from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { isInvalidLook } from './Input';\n\n/**\n * Props that SpinButton routes to its `<input role=\"spinbutton\">` (C-ROUTING): the id, the ARIA\n * naming/validation attributes, native text-input attributes and the focus/keyboard handlers.\n */\nexport type SpinButtonInputProps = Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n | 'id'\n | 'aria-label'\n | 'aria-labelledby'\n | 'aria-describedby'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-errormessage'\n | 'aria-details'\n | 'aria-valuetext'\n | 'required'\n | 'readOnly'\n | 'placeholder'\n | 'maxLength'\n | 'spellCheck'\n | 'autoComplete'\n | 'autoFocus'\n | 'inputMode'\n | 'enterKeyHint'\n | 'tabIndex'\n | 'onFocus'\n | 'onBlur'\n | 'onKeyDown'\n | 'onKeyUp'\n>;\n\n/**\n * Names of the SpinButton's step buttons, for localization. Each member is optional and falls back\n * to its English default.\n */\nexport interface SpinButtonLabels {\n /** Name of the button that steps up.\n * @default 'Increment'\n */\n increment?: string;\n /** Name of the button that steps down.\n * @default 'Decrement'\n */\n decrement?: string;\n}\n\n/** Properties for the SpinButton component. */\nexport interface SpinButtonProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | keyof SpinButtonInputProps\n >,\n SpinButtonInputProps {\n /** Controlled numeric value. */\n value?: number;\n /** Initial value for uncontrolled usage (also what a form reset restores).\n * @default 0\n */\n defaultValue?: number;\n /**\n * Called with the new value when it changes: a step (buttons, arrow keys, PageUp/PageDown,\n * Home/End) or a typed value committed on blur or Enter. Not called while the user is typing,\n * nor when the value stays the same.\n */\n onValueChange?: (value: number) => void;\n /**\n * Called with the new value when it changes.\n * @deprecated Use `onValueChange`. (`onChange` is reserved for native change events.)\n */\n onChange?: (value: number) => void;\n /** Minimum allowed value.\n * @default -Infinity\n */\n min?: number;\n /** Maximum allowed value.\n * @default Infinity\n */\n max?: number;\n /** Step of the increment/decrement buttons and of ArrowUp/ArrowDown.\n * @default 1\n */\n step?: number;\n /** Step of PageUp/PageDown.\n * @default step * 10\n */\n largeStep?: number;\n /** Whether the spin button is disabled and non-interactive. */\n disabled?: boolean;\n /** Form field name. With a name, the committed value is submitted with the form. */\n name?: string;\n /** Id of the form the spin button belongs to, when it is rendered outside that form. */\n form?: string;\n /**\n * Names of the −/+ step buttons (not tab stops, but in the accessibility tree), for\n * localization. Unset members keep their English defaults.\n */\n labels?: SpinButtonLabels;\n /** Ref to the root `<div>`. */\n ref?: React.Ref<HTMLDivElement>;\n /** Ref to the `<input role=\"spinbutton\">` (the focusable control). */\n controlRef?: React.Ref<HTMLInputElement>;\n}\n\n/** Decimal numbers as a user types them: `12`, `-3`, `1.5`, `.5`, `2.`, `1e3`. */\nconst NUMBER_TEXT = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n/** Text on the way to a number (`-`, `.`, `-.`): not a value yet, but not an error either. */\nconst PARTIAL_NUMBER_TEXT = /^[+-]?\\.?$/;\n\nfunction parseNumberText(text: string): number | null {\n const trimmed = text.trim();\n if (!NUMBER_TEXT.test(trimmed)) return null;\n const n = Number(trimmed);\n return Number.isFinite(n) ? n : null;\n}\n\n/** Number of decimals of `n` as written by JavaScript (`0.1` → 1, `1e-7` → 7). */\nfunction decimalsOf(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const [mantissa, exponent] = String(n).toLowerCase().split('e');\n const fraction = mantissa.split('.')[1]?.length ?? 0;\n return Math.max(0, fraction - (exponent ? Number(exponent) : 0));\n}\n\nfunction roundTo(n: number, decimals: number): number {\n return Number(n.toFixed(Math.min(decimals, 20)));\n}\n\nconst stepButtonClass = cn(\n // Padding and background set here (C-NATIVE): an app-wide `button` rule cannot fill them.\n 'flex h-8 w-8 shrink-0 items-center justify-center border-input bg-transparent p-0 text-foreground',\n 'not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:active:bg-subtle-pressed',\n 'disabled:pointer-events-none',\n);\n\n/**\n * A numeric input with decrement/increment buttons (APG spinbutton pattern).\n *\n * - **Keyboard** on the input: ArrowUp/ArrowDown step by `step`, PageUp/PageDown by `largeStep`\n * (default ten steps), Home/End jump to `min`/`max` when they are finite. The −/+ buttons are\n * not tab stops and never take focus, so focus stays on the spinbutton and screen readers\n * announce the new value.\n * - **Typing** edits a draft: the value is parsed, clamped and committed on blur or Enter\n * (Escape reverts). Text that is not a number is flagged with `aria-invalid` and reverted on\n * blur. Steps (keys and buttons) start from the typed number, and the −/+ buttons are disabled\n * when that number is at `min`/`max`. Steps are rounded to the precision of `step` and of the\n * value, so `0.1 + 0.2` is `0.3`.\n * - **Routing**: `id`, ARIA, native input attributes and focus/keyboard handlers go to the\n * `<input role=\"spinbutton\">`; `className`, `style`, `data-*`, other handlers and `ref` stay on\n * the root (`controlRef` reaches the input). Inside a `Field` it picks up the label, hint, error\n * and required state automatically. It has no built-in name: pass `aria-label`/`aria-labelledby`\n * or use a label (development warning otherwise).\n * - **Forms**: with `name` the committed value is submitted; `required` makes the input natively\n * required; a form reset restores `defaultValue`.\n * - The −/+ buttons are named \"Decrement\"/\"Increment\"; `labels` localizes the names.\n *\n * @example\n * <SpinButton aria-label=\"Quantity\" min={1} max={10} value={qty} onValueChange={setQty} />\n */\nexport const SpinButton = ({\n value: valueProp,\n defaultValue,\n onValueChange,\n onChange,\n min = -Infinity,\n max = Infinity,\n step = 1,\n largeStep,\n disabled,\n name,\n form,\n labels,\n className,\n hidden,\n ref,\n controlRef,\n // Routed to the input (C-ROUTING)\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 'aria-valuetext': ariaValueText,\n required,\n readOnly,\n placeholder,\n maxLength,\n spellCheck,\n autoComplete = 'off',\n autoFocus,\n inputMode,\n enterKeyHint,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n ...rest\n}: SpinButtonProps) => {\n if (onChange !== undefined) warnDeprecated('SpinButton', 'onChange', 'onValueChange');\n const initialValue = defaultValue ?? 0;\n const [value, setValue] = useControllable(valueProp, initialValue, (next: number) => {\n onValueChange?.(next);\n onChange?.(next);\n });\n\n // The text is a draft while the user types (null = show the value).\n const [draft, setDraft] = React.useState<string | null>(null);\n // A value that changes from outside replaces the draft (adjust state during render, C-HOOKS).\n const [prevValue, setPrevValue] = React.useState(value);\n if (!Object.is(prevValue, value)) {\n setPrevValue(value);\n setDraft(null);\n }\n\n const draftNumber = draft === null ? null : parseNumberText(draft);\n // What stepping starts from: the typed draft when it is a number, else the value. The −/+\n // buttons are enabled by it too, so they agree with ArrowUp/ArrowDown while the user types.\n const current = draftNumber ?? value;\n const draftInvalid =\n draft !== null &&\n draftNumber === null &&\n draft.trim() !== '' &&\n !PARTIAL_NUMBER_TEXT.test(draft.trim());\n\n const clamp = (n: number) => Math.min(max, Math.max(min, n));\n const interactive = !disabled && !readOnly;\n\n const commit = (next: number) => {\n setDraft(null);\n setValue(clamp(next));\n };\n\n /** Steps from the typed draft when it is a number, else from the value. */\n const stepBy = (delta: number) => {\n const precision = Math.max(decimalsOf(step), decimalsOf(delta), decimalsOf(current));\n commit(roundTo(current + delta, precision));\n };\n\n const commitDraft = () => {\n if (draft === null) return;\n if (draftNumber === null) setDraft(null);\n else commit(draftNumber);\n };\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef);\n\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n },\n { nativeRequired: true },\n );\n // Typed text that is not a number is invalid whatever the consumer says; otherwise the\n // consumer's or the Field's `aria-invalid` is passed through as is (`grammar` included), and the\n // error look follows the shared rule of the text controls.\n const ariaInvalidValue = draftInvalid ? true : fieldProps['aria-invalid'];\n const invalidLook = isInvalidLook(false, ariaInvalidValue);\n\n useFormReset(\n inputRef,\n () => {\n setDraft(null);\n setValue(initialValue);\n },\n form,\n );\n\n // No built-in name any more (\"Value\" named every instance the same): report unnamed inputs.\n React.useEffect(() => {\n const input = inputRef.current;\n if (!input) return;\n const named =\n input.hasAttribute('aria-label') ||\n input.hasAttribute('aria-labelledby') ||\n (input.labels?.length ?? 0) > 0 ||\n input.hasAttribute('title');\n if (!named) {\n warnOnce(\n 'SpinButton:unnamed',\n 'SpinButton: the spinbutton has no accessible name. Pass `aria-label` or `aria-labelledby`, use a <label htmlFor>, or render it inside a Field.',\n );\n }\n });\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Read-only: the keys keep their native caret behaviour and never change the value.\n if (!interactive || e.altKey || e.ctrlKey || e.metaKey) return;\n // Ten steps, rounded: step * 10 carries float error (0.07 * 10 = 0.7000000000000001) that\n // stepBy would otherwise keep, since it rounds to the precision of the delta too.\n const big = largeStep ?? roundTo(step * 10, decimalsOf(step));\n switch (e.key) {\n case 'ArrowUp':\n case 'ArrowDown':\n case 'PageUp':\n case 'PageDown': {\n e.preventDefault();\n const size = e.key === 'ArrowUp' || e.key === 'ArrowDown' ? step : big;\n stepBy(e.key === 'ArrowUp' || e.key === 'PageUp' ? size : -size);\n return;\n }\n case 'Home':\n case 'End': {\n const bound = e.key === 'Home' ? min : max;\n if (!Number.isFinite(bound)) return; // no bound: Home/End move the caret\n e.preventDefault();\n commit(bound);\n return;\n }\n case 'Enter':\n // Not prevented: Enter still submits the surrounding form, with the committed value.\n commitDraft();\n return;\n case 'Escape':\n if (draft !== null) {\n e.preventDefault(); // enclosing layers (a Dialog) ignore this Escape\n setDraft(null);\n }\n return;\n default:\n }\n };\n\n const defaultInputMode: React.HTMLAttributes<HTMLInputElement>['inputMode'] =\n min < 0 ? 'text' : decimalsOf(step) > 0 || decimalsOf(min) > 0 ? 'decimal' : 'numeric';\n\n // The step buttons never take focus: a pointer press leaves it where it is (on the input while\n // editing), so a button that becomes disabled at a bound cannot drop focus to <body>.\n const keepFocus = (e: React.MouseEvent) => e.preventDefault();\n\n return (\n <div\n ref={ref}\n className={cn(\n 'relative inline-flex items-center rounded border border-input border-b-stroke-accessible bg-background',\n inputFocusWithin,\n invalidLook && inputInvalidWithin,\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n hidden={hidden}\n {...rest}\n >\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(-step)}\n disabled={!interactive || current <= min}\n aria-label={labels?.decrement ?? 'Decrement'}\n className={cn(stepButtonClass, 'border-e', !disabled && 'disabled:opacity-50')}\n >\n <SubtractIcon size={12} />\n </button>\n\n <input\n ref={mergedInputRef}\n type=\"text\"\n role=\"spinbutton\"\n inputMode={inputMode ?? defaultInputMode}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n enterKeyHint={enterKeyHint}\n placeholder={placeholder}\n maxLength={maxLength}\n spellCheck={spellCheck}\n tabIndex={tabIndex}\n readOnly={readOnly}\n form={form}\n {...fieldProps}\n aria-invalid={ariaInvalidValue}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-valuenow={value}\n aria-valuemin={Number.isFinite(min) ? min : undefined}\n aria-valuemax={Number.isFinite(max) ? max : undefined}\n aria-valuetext={ariaValueText}\n value={draft ?? String(value)}\n onChange={(e) => setDraft(e.target.value)}\n onFocus={onFocus}\n onBlur={composeEventHandlers(onBlur, commitDraft, { checkDefaultPrevented: false })}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyUp={onKeyUp}\n disabled={disabled}\n className=\"h-8 w-12 min-w-0 border-none bg-transparent text-center text-body-1 text-foreground focus:outline-hidden disabled:cursor-not-allowed [appearance:textfield]\"\n />\n\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(step)}\n disabled={!interactive || current >= max}\n aria-label={labels?.increment ?? 'Increment'}\n className={cn(stepButtonClass, 'border-s', !disabled && 'disabled:opacity-50')}\n >\n <AddIcon size={12} />\n </button>\n\n <HiddenInput name={name} form={form} disabled={disabled} value={String(value)} />\n </div>\n );\n};\n\nSpinButton.displayName = 'SpinButton';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SpinButton.mjs","names":["React","NUMBER_TEXT","PARTIAL_NUMBER_TEXT","parseNumberText","trimmed","text","decimalsOf","n","mantissa","exponent","fraction","roundTo","decimals","stepButtonClass","cn","SpinButton","valueProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaInvalid","ariaRequired","ariaErrorMessage","ariaDetails","ariaValueText","rest","onChange","warnDeprecated","initialValue","defaultValue","value","setValue","useControllable","onValueChange","next","draft","setDraft","prevValue","setPrevValue","draftNumber","current","draftInvalid","clamp","max","min","interactive","disabled","readOnly","commit","stepBy","precision","step","delta","commitDraft","inputRef","mergedInputRef","useMergedRefs","controlRef","fieldProps","useFieldControl","ariaInvalidValue","invalidLook","isInvalidLook","useFormReset","form","input","warnOnce","handleKeyDown","big","largeStep","size","bound","defaultInputMode","keepFocus","spinButtonClassNames","inputFocusWithin","className","labels","SubtractIcon","inputMode","composeEventHandlers","onBlur","onKeyDown","AddIcon","HiddenInput"],"sources":["../../../src/components/input/SpinButton.tsx"],"sourcesContent":["import * as React from 'react';\nimport { spinButtonClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnDeprecated, warnOnce } from '../../lib/dev';\nimport { AddIcon, SubtractIcon } from '../../lib/icons';\nimport { inputFocusWithin, inputInvalidWithin } from '../../lib/styles';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useFieldControl } from '../../hooks/useFieldControl';\nimport { useFormReset } from '../../hooks/useFormReset';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { HiddenInput } from '../internal/HiddenInput';\nimport { isInvalidLook } from './Input';\n\n/**\n * Props that SpinButton routes to its `<input role=\"spinbutton\">` (C-ROUTING): the id, the ARIA\n * naming/validation attributes, native text-input attributes and the focus/keyboard handlers.\n */\nexport type SpinButtonInputProps = Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n | 'id'\n | 'aria-label'\n | 'aria-labelledby'\n | 'aria-describedby'\n | 'aria-invalid'\n | 'aria-required'\n | 'aria-errormessage'\n | 'aria-details'\n | 'aria-valuetext'\n | 'required'\n | 'readOnly'\n | 'placeholder'\n | 'maxLength'\n | 'spellCheck'\n | 'autoComplete'\n | 'autoFocus'\n | 'inputMode'\n | 'enterKeyHint'\n | 'tabIndex'\n | 'onFocus'\n | 'onBlur'\n | 'onKeyDown'\n | 'onKeyUp'\n>;\n\n/**\n * Names of the SpinButton's step buttons, for localization. Each member is optional and falls back\n * to its English default.\n */\nexport interface SpinButtonLabels {\n /** Name of the button that steps up.\n * @default 'Increment'\n */\n increment?: string;\n /** Name of the button that steps down.\n * @default 'Decrement'\n */\n decrement?: string;\n}\n\n/** Properties for the SpinButton component. */\nexport interface SpinButtonProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | keyof SpinButtonInputProps\n >,\n SpinButtonInputProps {\n /** Controlled numeric value. */\n value?: number;\n /** Initial value for uncontrolled usage (also what a form reset restores).\n * @default 0\n */\n defaultValue?: number;\n /**\n * Called with the new value when it changes: a step (buttons, arrow keys, PageUp/PageDown,\n * Home/End) or a typed value committed on blur or Enter. Not called while the user is typing,\n * nor when the value stays the same.\n */\n onValueChange?: (value: number) => void;\n /**\n * Called with the new value when it changes.\n * @deprecated Use `onValueChange`. (`onChange` is reserved for native change events.)\n */\n onChange?: (value: number) => void;\n /** Minimum allowed value.\n * @default -Infinity\n */\n min?: number;\n /** Maximum allowed value.\n * @default Infinity\n */\n max?: number;\n /** Step of the increment/decrement buttons and of ArrowUp/ArrowDown.\n * @default 1\n */\n step?: number;\n /** Step of PageUp/PageDown.\n * @default step * 10\n */\n largeStep?: number;\n /** Whether the spin button is disabled and non-interactive. */\n disabled?: boolean;\n /** Form field name. With a name, the committed value is submitted with the form. */\n name?: string;\n /** Id of the form the spin button belongs to, when it is rendered outside that form. */\n form?: string;\n /**\n * Names of the −/+ step buttons (not tab stops, but in the accessibility tree), for\n * localization. Unset members keep their English defaults.\n */\n labels?: SpinButtonLabels;\n /** Ref to the root `<div>`. */\n ref?: React.Ref<HTMLDivElement>;\n /** Ref to the `<input role=\"spinbutton\">` (the focusable control). */\n controlRef?: React.Ref<HTMLInputElement>;\n}\n\n/** Decimal numbers as a user types them: `12`, `-3`, `1.5`, `.5`, `2.`, `1e3`. */\nconst NUMBER_TEXT = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n/** Text on the way to a number (`-`, `.`, `-.`): not a value yet, but not an error either. */\nconst PARTIAL_NUMBER_TEXT = /^[+-]?\\.?$/;\n\nfunction parseNumberText(text: string): number | null {\n const trimmed = text.trim();\n if (!NUMBER_TEXT.test(trimmed)) return null;\n const n = Number(trimmed);\n return Number.isFinite(n) ? n : null;\n}\n\n/** Number of decimals of `n` as written by JavaScript (`0.1` → 1, `1e-7` → 7). */\nfunction decimalsOf(n: number): number {\n if (!Number.isFinite(n)) return 0;\n const [mantissa, exponent] = String(n).toLowerCase().split('e');\n const fraction = mantissa.split('.')[1]?.length ?? 0;\n return Math.max(0, fraction - (exponent ? Number(exponent) : 0));\n}\n\nfunction roundTo(n: number, decimals: number): number {\n return Number(n.toFixed(Math.min(decimals, 20)));\n}\n\nconst stepButtonClass = cn(\n // Padding and background set here (C-NATIVE): an app-wide `button` rule cannot fill them.\n 'flex h-8 w-8 shrink-0 items-center justify-center border-input bg-transparent p-0 text-foreground',\n 'not-disabled:not-aria-disabled:hover:bg-subtle-hover not-disabled:not-aria-disabled:active:bg-subtle-pressed',\n 'disabled:pointer-events-none',\n);\n\n/**\n * A numeric input with decrement/increment buttons (APG spinbutton pattern).\n *\n * - **Keyboard** on the input: ArrowUp/ArrowDown step by `step`, PageUp/PageDown by `largeStep`\n * (default ten steps), Home/End jump to `min`/`max` when they are finite. The −/+ buttons are\n * not tab stops and never take focus, so focus stays on the spinbutton and screen readers\n * announce the new value.\n * - **Typing** edits a draft: the value is parsed, clamped and committed on blur or Enter\n * (Escape reverts). Text that is not a number is flagged with `aria-invalid` and reverted on\n * blur. Steps (keys and buttons) start from the typed number, and the −/+ buttons are disabled\n * when that number is at `min`/`max`. Steps are rounded to the precision of `step` and of the\n * value, so `0.1 + 0.2` is `0.3`.\n * - **Routing**: `id`, ARIA, native input attributes and focus/keyboard handlers go to the\n * `<input role=\"spinbutton\">`; `className`, `style`, `data-*`, other handlers and `ref` stay on\n * the root (`controlRef` reaches the input). Inside a `Field` it picks up the label, hint, error\n * and required state automatically. It has no built-in name: pass `aria-label`/`aria-labelledby`\n * or use a label (development warning otherwise).\n * - **Forms**: with `name` the committed value is submitted; `required` makes the input natively\n * required; a form reset restores `defaultValue`.\n * - The −/+ buttons are named \"Decrement\"/\"Increment\"; `labels` localizes the names.\n *\n * @example\n * <SpinButton aria-label=\"Quantity\" min={1} max={10} value={qty} onValueChange={setQty} />\n */\nexport const SpinButton = ({\n value: valueProp,\n defaultValue,\n onValueChange,\n onChange,\n min = -Infinity,\n max = Infinity,\n step = 1,\n largeStep,\n disabled,\n name,\n form,\n labels,\n className,\n hidden,\n ref,\n controlRef,\n // Routed to the input (C-ROUTING)\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 'aria-valuetext': ariaValueText,\n required,\n readOnly,\n placeholder,\n maxLength,\n spellCheck,\n autoComplete = 'off',\n autoFocus,\n inputMode,\n enterKeyHint,\n tabIndex,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n ...rest\n}: SpinButtonProps) => {\n if (onChange !== undefined) warnDeprecated('SpinButton', 'onChange', 'onValueChange');\n const initialValue = defaultValue ?? 0;\n const [value, setValue] = useControllable(valueProp, initialValue, (next: number) => {\n onValueChange?.(next);\n onChange?.(next);\n });\n\n // The text is a draft while the user types (null = show the value).\n const [draft, setDraft] = React.useState<string | null>(null);\n // A value that changes from outside replaces the draft (adjust state during render, C-HOOKS).\n const [prevValue, setPrevValue] = React.useState(value);\n if (!Object.is(prevValue, value)) {\n setPrevValue(value);\n setDraft(null);\n }\n\n const draftNumber = draft === null ? null : parseNumberText(draft);\n // What stepping starts from: the typed draft when it is a number, else the value. The −/+\n // buttons are enabled by it too, so they agree with ArrowUp/ArrowDown while the user types.\n const current = draftNumber ?? value;\n const draftInvalid =\n draft !== null &&\n draftNumber === null &&\n draft.trim() !== '' &&\n !PARTIAL_NUMBER_TEXT.test(draft.trim());\n\n const clamp = (n: number) => Math.min(max, Math.max(min, n));\n const interactive = !disabled && !readOnly;\n\n const commit = (next: number) => {\n setDraft(null);\n setValue(clamp(next));\n };\n\n /** Steps from the typed draft when it is a number, else from the value. */\n const stepBy = (delta: number) => {\n const precision = Math.max(decimalsOf(step), decimalsOf(delta), decimalsOf(current));\n commit(roundTo(current + delta, precision));\n };\n\n const commitDraft = () => {\n if (draft === null) return;\n if (draftNumber === null) setDraft(null);\n else commit(draftNumber);\n };\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const mergedInputRef = useMergedRefs(inputRef, controlRef);\n\n const fieldProps = useFieldControl(\n {\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n required,\n },\n { nativeRequired: true },\n );\n // Typed text that is not a number is invalid whatever the consumer says; otherwise the\n // consumer's or the Field's `aria-invalid` is passed through as is (`grammar` included), and the\n // error look follows the shared rule of the text controls.\n const ariaInvalidValue = draftInvalid ? true : fieldProps['aria-invalid'];\n const invalidLook = isInvalidLook(false, ariaInvalidValue);\n\n useFormReset(\n inputRef,\n () => {\n setDraft(null);\n setValue(initialValue);\n },\n form,\n );\n\n // No built-in name any more (\"Value\" named every instance the same): report unnamed inputs.\n React.useEffect(() => {\n const input = inputRef.current;\n if (!input) return;\n const named =\n input.hasAttribute('aria-label') ||\n input.hasAttribute('aria-labelledby') ||\n (input.labels?.length ?? 0) > 0 ||\n input.hasAttribute('title');\n if (!named) {\n warnOnce(\n 'SpinButton:unnamed',\n 'SpinButton: the spinbutton has no accessible name. Pass `aria-label` or `aria-labelledby`, use a <label htmlFor>, or render it inside a Field.',\n );\n }\n });\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Read-only: the keys keep their native caret behaviour and never change the value.\n if (!interactive || e.altKey || e.ctrlKey || e.metaKey) return;\n // Ten steps, rounded: step * 10 carries float error (0.07 * 10 = 0.7000000000000001) that\n // stepBy would otherwise keep, since it rounds to the precision of the delta too.\n const big = largeStep ?? roundTo(step * 10, decimalsOf(step));\n switch (e.key) {\n case 'ArrowUp':\n case 'ArrowDown':\n case 'PageUp':\n case 'PageDown': {\n e.preventDefault();\n const size = e.key === 'ArrowUp' || e.key === 'ArrowDown' ? step : big;\n stepBy(e.key === 'ArrowUp' || e.key === 'PageUp' ? size : -size);\n return;\n }\n case 'Home':\n case 'End': {\n const bound = e.key === 'Home' ? min : max;\n if (!Number.isFinite(bound)) return; // no bound: Home/End move the caret\n e.preventDefault();\n commit(bound);\n return;\n }\n case 'Enter':\n // Not prevented: Enter still submits the surrounding form, with the committed value.\n commitDraft();\n return;\n case 'Escape':\n if (draft !== null) {\n e.preventDefault(); // enclosing layers (a Dialog) ignore this Escape\n setDraft(null);\n }\n return;\n default:\n }\n };\n\n const defaultInputMode: React.HTMLAttributes<HTMLInputElement>['inputMode'] =\n min < 0 ? 'text' : decimalsOf(step) > 0 || decimalsOf(min) > 0 ? 'decimal' : 'numeric';\n\n // The step buttons never take focus: a pointer press leaves it where it is (on the input while\n // editing), so a button that becomes disabled at a bound cannot drop focus to <body>.\n const keepFocus = (e: React.MouseEvent) => e.preventDefault();\n\n return (\n <div\n ref={ref}\n className={cn(\n spinButtonClassNames.root,\n 'relative inline-flex items-center rounded border border-input border-b-stroke-accessible bg-background',\n inputFocusWithin,\n invalidLook && inputInvalidWithin,\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n hidden={hidden}\n {...rest}\n >\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(-step)}\n disabled={!interactive || current <= min}\n aria-label={labels?.decrement ?? 'Decrement'}\n className={cn(\n spinButtonClassNames.decrementButton,\n stepButtonClass,\n 'border-e',\n !disabled && 'disabled:opacity-50',\n )}\n >\n <SubtractIcon size={12} />\n </button>\n\n <input\n ref={mergedInputRef}\n type=\"text\"\n role=\"spinbutton\"\n inputMode={inputMode ?? defaultInputMode}\n autoComplete={autoComplete}\n autoFocus={autoFocus}\n enterKeyHint={enterKeyHint}\n placeholder={placeholder}\n maxLength={maxLength}\n spellCheck={spellCheck}\n tabIndex={tabIndex}\n readOnly={readOnly}\n form={form}\n {...fieldProps}\n aria-invalid={ariaInvalidValue}\n aria-errormessage={ariaErrorMessage}\n aria-details={ariaDetails}\n aria-valuenow={value}\n aria-valuemin={Number.isFinite(min) ? min : undefined}\n aria-valuemax={Number.isFinite(max) ? max : undefined}\n aria-valuetext={ariaValueText}\n value={draft ?? String(value)}\n onChange={(e) => setDraft(e.target.value)}\n onFocus={onFocus}\n onBlur={composeEventHandlers(onBlur, commitDraft, { checkDefaultPrevented: false })}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onKeyUp={onKeyUp}\n disabled={disabled}\n className={cn(\n spinButtonClassNames.input,\n 'h-8 w-12 min-w-0 border-none bg-transparent text-center text-body-1 text-foreground focus:outline-hidden disabled:cursor-not-allowed [appearance:textfield]',\n )}\n />\n\n <button\n type=\"button\"\n tabIndex={-1}\n onMouseDown={keepFocus}\n onClick={() => stepBy(step)}\n disabled={!interactive || current >= max}\n aria-label={labels?.increment ?? 'Increment'}\n className={cn(\n spinButtonClassNames.incrementButton,\n stepButtonClass,\n 'border-s',\n !disabled && 'disabled:opacity-50',\n )}\n >\n <AddIcon size={12} />\n </button>\n\n <HiddenInput name={name} form={form} disabled={disabled} value={String(value)} />\n </div>\n );\n};\n\nSpinButton.displayName = 'SpinButton';\n"],"mappings":"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"}
|
|
@@ -1,2 +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/composeEventHandlers.cjs"),i=require("../../hooks/useControllable.cjs"),
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useControllable.cjs"),o=require("../../hooks/useRovingTabIndex.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../../hooks/useFieldControl.cjs"),l=require("../../lib/styles.cjs"),u=require("../../lib/icons.cjs"),d=require("../../hooks/useFormReset.cjs"),f=require("../internal/HiddenInput.cjs"),p=require("./colorUtils.cjs");let m=require("react");m=e.__toESM(m,1);let h=require("react/jsx-runtime");var g={small:`w-6 h-6`,medium:`w-8 h-8`,large:`w-10 h-10`},_={small:12,medium:16,large:20},v={circular:`rounded-full`,square:`rounded-none`,rounded:`rounded`};function y({color:e,size:t}){let{glyph:n,halo:r}=p.getCheckColors(e);return(0,h.jsxs)(`span`,{"aria-hidden":`true`,className:`pointer-events-none grid`,children:[(0,h.jsx)(u.CheckIcon,{size:t,strokeWidth:4,className:`col-start-1 row-start-1`,style:{color:r}}),(0,h.jsx)(u.CheckIcon,{size:t,strokeWidth:2,className:`col-start-1 row-start-1`,style:{color:n}})]})}var b=({items:e,value:u,defaultValue:p,onValueChange:b,onChange:x,size:S=`medium`,shape:C=`circular`,name:w,required:T,form:E,className:D,id:O,"aria-label":k,"aria-labelledby":A,"aria-describedby":j,"aria-invalid":M,"aria-required":N,onKeyDown:P,onFocus:F,ref:I,...L})=>{x!==void 0&&n.warnDeprecated(`SwatchPicker`,`onChange`,`onValueChange`);let R=p??``,[z,B]=a.useControllable(u,R,e=>{b?.(e),x?.(e)}),{containerProps:V,getTabIndex:H}=o.useRovingTabIndex({activeValue:z||null,orientation:`both`,onFocusMove:e=>B(e)}),U=m.useRef(null),W=s.useMergedRefs(I,V.ref,U),G=c.useFieldContext(),K=c.useFieldControl({id:O,"aria-label":k,"aria-labelledby":A,"aria-describedby":j,"aria-invalid":M,"aria-required":N??T},{labelable:!1}),q=T??G?.required??!1,J=K[`aria-label`]===void 0&&K[`aria-labelledby`]===void 0,Y=e.find(e=>!e.label)?.value;m.useEffect(()=>{J&&n.warnOnce(`SwatchPicker:unnamed`,"SwatchPicker: the radiogroup has no accessible name. Pass `aria-label` or `aria-labelledby`, or render it inside a Field.")},[J]),m.useEffect(()=>{Y!==void 0&&n.warnOnce(`SwatchPicker:item-label`,`SwatchPicker: swatch "${Y}" has no \`label\`, so it is announced by its color value. Give every item a \`label\`.`)},[Y]),d.useFormReset(U,()=>B(R),E);let X=()=>{U.current?.querySelector(`[data-roving-value][tabindex="0"]`)?.focus()};return(0,h.jsxs)(`div`,{role:`radiogroup`,...K,className:t.cn(i.swatchPickerClassNames.root,`relative flex flex-wrap gap-2`,D),...L,ref:W,"data-roving-container":``,onKeyDown:r.composeEventHandlers(P,V.onKeyDown),onFocus:r.composeEventHandlers(F,V.onFocus,{checkDefaultPrevented:!1}),children:[e.map(e=>{let n=z===e.value;return(0,h.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":n,"aria-label":e.label||e.color,"data-roving-value":e.value,"data-selected":n?``:void 0,tabIndex:H(e.value),onClick:()=>B(e.value),className:t.cn(i.swatchPickerClassNames.swatch,g[S],v[C],`relative flex shrink-0 items-center justify-center border-2 border-transparent p-0`,l.motionSafeTransition,`forced-colors:forced-color-adjust-none`,l.forcedColors.border,l.focusRing,`focus-visible:outline-offset-4`,n?`ring-2 ring-foreground ring-offset-2 ring-offset-background`:`hover:border-stroke-hover`),style:{backgroundColor:e.color},children:n&&(0,h.jsx)(y,{color:e.color,size:_[S]})},e.value)}),(0,h.jsx)(f.HiddenInput,{type:`radio`,name:w,form:E,value:z,required:q,onInvalid:X})]})};b.displayName=`SwatchPicker`,exports.SwatchPicker=b;
|
|
2
2
|
//# sourceMappingURL=SwatchPicker.cjs.map
|