@limonify/zest-ui 0.3.2 → 0.4.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 +3 -0
- package/lib/alert-dialog/index.parts.d.ts +1 -1
- package/lib/alert-dialog/index.parts.d.ts.map +1 -1
- package/lib/alert-dialog/index.parts.js.map +1 -1
- package/lib/autocomplete/handle.d.ts +15 -0
- package/lib/autocomplete/handle.d.ts.map +1 -0
- package/lib/autocomplete/handle.js +12 -0
- package/lib/autocomplete/handle.js.map +1 -0
- package/lib/autocomplete/index.d.ts +1 -0
- package/lib/autocomplete/index.d.ts.map +1 -1
- package/lib/autocomplete/index.parts.d.ts +1 -0
- package/lib/autocomplete/index.parts.d.ts.map +1 -1
- package/lib/autocomplete/index.parts.js +3 -1
- package/lib/autocomplete/index.parts.js.map +1 -1
- package/lib/autocomplete/root/AutocompleteRoot.d.ts +55 -16
- package/lib/autocomplete/root/AutocompleteRoot.d.ts.map +1 -1
- package/lib/autocomplete/root/AutocompleteRoot.js +2 -18
- package/lib/autocomplete/root/AutocompleteRoot.js.map +1 -1
- package/lib/avatar/fallback/AvatarFallback.d.ts.map +1 -1
- package/lib/avatar/fallback/AvatarFallback.js +3 -1
- package/lib/avatar/fallback/AvatarFallback.js.map +1 -1
- package/lib/avatar/image/AvatarImage.d.ts.map +1 -1
- package/lib/avatar/image/AvatarImage.js +5 -0
- package/lib/avatar/image/AvatarImage.js.map +1 -1
- package/lib/checkbox/root/CheckboxRoot.d.ts.map +1 -1
- package/lib/checkbox/root/CheckboxRoot.js +9 -4
- package/lib/checkbox/root/CheckboxRoot.js.map +1 -1
- package/lib/combobox/backdrop/ComboboxBackdrop.d.ts.map +1 -1
- package/lib/combobox/backdrop/ComboboxBackdrop.js +10 -4
- package/lib/combobox/backdrop/ComboboxBackdrop.js.map +1 -1
- package/lib/combobox/empty/ComboboxEmpty.d.ts.map +1 -1
- package/lib/combobox/empty/ComboboxEmpty.js +4 -1
- package/lib/combobox/empty/ComboboxEmpty.js.map +1 -1
- package/lib/combobox/index.d.ts +2 -0
- package/lib/combobox/index.d.ts.map +1 -1
- package/lib/combobox/index.js +3 -1
- package/lib/combobox/index.js.map +1 -1
- package/lib/combobox/index.parts.d.ts +1 -0
- package/lib/combobox/index.parts.d.ts.map +1 -1
- package/lib/combobox/index.parts.js +4 -1
- package/lib/combobox/index.parts.js.map +1 -1
- package/lib/combobox/input/ComboboxInput.d.ts +24 -3
- package/lib/combobox/input/ComboboxInput.d.ts.map +1 -1
- package/lib/combobox/input/ComboboxInput.js +65 -11
- package/lib/combobox/input/ComboboxInput.js.map +1 -1
- package/lib/combobox/item/ComboboxItem.d.ts +11 -1
- package/lib/combobox/item/ComboboxItem.d.ts.map +1 -1
- package/lib/combobox/item/ComboboxItem.js +9 -6
- package/lib/combobox/item/ComboboxItem.js.map +1 -1
- package/lib/combobox/list/ComboboxList.d.ts +1 -1
- package/lib/combobox/list/ComboboxList.d.ts.map +1 -1
- package/lib/combobox/list/ComboboxList.js +4 -1
- package/lib/combobox/list/ComboboxList.js.map +1 -1
- package/lib/combobox/popup/ComboboxPopup.d.ts +26 -0
- package/lib/combobox/popup/ComboboxPopup.d.ts.map +1 -1
- package/lib/combobox/popup/ComboboxPopup.js +18 -2
- package/lib/combobox/popup/ComboboxPopup.js.map +1 -1
- package/lib/combobox/portal/ComboboxPortal.d.ts.map +1 -1
- package/lib/combobox/portal/ComboboxPortal.js +8 -4
- package/lib/combobox/portal/ComboboxPortal.js.map +1 -1
- package/lib/combobox/portal/ComboboxPortalContext.d.ts +4 -0
- package/lib/combobox/portal/ComboboxPortalContext.d.ts.map +1 -0
- package/lib/combobox/portal/ComboboxPortalContext.js +48 -0
- package/lib/combobox/portal/ComboboxPortalContext.js.map +1 -0
- package/lib/combobox/positioner/ComboboxPositioner.d.ts +7 -2
- package/lib/combobox/positioner/ComboboxPositioner.d.ts.map +1 -1
- package/lib/combobox/positioner/ComboboxPositioner.js +61 -6
- package/lib/combobox/positioner/ComboboxPositioner.js.map +1 -1
- package/lib/combobox/positioner/ComboboxPositionerContext.d.ts +9 -0
- package/lib/combobox/positioner/ComboboxPositionerContext.d.ts.map +1 -0
- package/lib/combobox/positioner/ComboboxPositionerContext.js +48 -0
- package/lib/combobox/positioner/ComboboxPositionerContext.js.map +1 -0
- package/lib/combobox/root/ComboboxItemsContext.d.ts +18 -0
- package/lib/combobox/root/ComboboxItemsContext.d.ts.map +1 -0
- package/lib/combobox/root/ComboboxItemsContext.js +55 -0
- package/lib/combobox/root/ComboboxItemsContext.js.map +1 -0
- package/lib/combobox/root/ComboboxRoot.d.ts +77 -21
- package/lib/combobox/root/ComboboxRoot.d.ts.map +1 -1
- package/lib/combobox/root/ComboboxRoot.js +4 -23
- package/lib/combobox/root/ComboboxRoot.js.map +1 -1
- package/lib/combobox/root/ComboboxRootContext.d.ts +4 -54
- package/lib/combobox/root/ComboboxRootContext.d.ts.map +1 -1
- package/lib/combobox/root/ComboboxRootContext.js.map +1 -1
- package/lib/combobox/root/ComboboxTransitionContext.d.ts +8 -0
- package/lib/combobox/root/ComboboxTransitionContext.d.ts.map +1 -0
- package/lib/combobox/root/ComboboxTransitionContext.js +44 -0
- package/lib/combobox/root/ComboboxTransitionContext.js.map +1 -0
- package/lib/combobox/root/useRenderComboboxRoot.d.ts +39 -0
- package/lib/combobox/root/useRenderComboboxRoot.d.ts.map +1 -0
- package/lib/combobox/root/useRenderComboboxRoot.js +136 -0
- package/lib/combobox/root/useRenderComboboxRoot.js.map +1 -0
- package/lib/combobox/store/ComboboxHandle.d.ts +42 -0
- package/lib/combobox/store/ComboboxHandle.d.ts.map +1 -0
- package/lib/combobox/store/ComboboxHandle.js +65 -0
- package/lib/combobox/store/ComboboxHandle.js.map +1 -0
- package/lib/combobox/store/ComboboxStore.d.ts +147 -0
- package/lib/combobox/store/ComboboxStore.d.ts.map +1 -0
- package/lib/combobox/store/ComboboxStore.js +127 -0
- package/lib/combobox/store/ComboboxStore.js.map +1 -0
- package/lib/combobox/value/ComboboxValue.d.ts.map +1 -1
- package/lib/combobox/value/ComboboxValue.js +2 -1
- package/lib/combobox/value/ComboboxValue.js.map +1 -1
- package/lib/context-menu/positioner/ContextMenuPositioner.d.ts +19 -3
- package/lib/context-menu/positioner/ContextMenuPositioner.d.ts.map +1 -1
- package/lib/context-menu/positioner/ContextMenuPositioner.js +56 -7
- package/lib/context-menu/positioner/ContextMenuPositioner.js.map +1 -1
- package/lib/context-menu/root/ContextMenuRoot.d.ts +8 -0
- package/lib/context-menu/root/ContextMenuRoot.d.ts.map +1 -1
- package/lib/dialog/backdrop/DialogBackdrop.d.ts +9 -0
- package/lib/dialog/backdrop/DialogBackdrop.d.ts.map +1 -1
- package/lib/dialog/backdrop/DialogBackdrop.js +3 -1
- package/lib/dialog/backdrop/DialogBackdrop.js.map +1 -1
- package/lib/dialog/popup/DialogPopup.d.ts +9 -0
- package/lib/dialog/popup/DialogPopup.d.ts.map +1 -1
- package/lib/dialog/popup/DialogPopup.js +2 -2
- package/lib/dialog/popup/DialogPopup.js.map +1 -1
- package/lib/dialog/popup/useDialogPopupProps.d.ts +2 -0
- package/lib/dialog/popup/useDialogPopupProps.d.ts.map +1 -1
- package/lib/dialog/popup/useDialogPopupProps.js +4 -0
- package/lib/dialog/popup/useDialogPopupProps.js.map +1 -1
- package/lib/dialog/root/DialogNestingContext.d.ts +20 -0
- package/lib/dialog/root/DialogNestingContext.d.ts.map +1 -0
- package/lib/dialog/root/DialogNestingContext.js +53 -0
- package/lib/dialog/root/DialogNestingContext.js.map +1 -0
- package/lib/dialog/root/useRenderDialogRoot.d.ts.map +1 -1
- package/lib/dialog/root/useRenderDialogRoot.js +26 -2
- package/lib/dialog/root/useRenderDialogRoot.js.map +1 -1
- package/lib/dialog/store/DialogStore.d.ts +19 -2
- package/lib/dialog/store/DialogStore.d.ts.map +1 -1
- package/lib/dialog/store/DialogStore.js +14 -2
- package/lib/dialog/store/DialogStore.js.map +1 -1
- package/lib/drawer/index.parts.d.ts +1 -1
- package/lib/drawer/index.parts.d.ts.map +1 -1
- package/lib/drawer/index.parts.js.map +1 -1
- package/lib/drawer/popup/DrawerPopup.d.ts +9 -0
- package/lib/drawer/popup/DrawerPopup.d.ts.map +1 -1
- package/lib/drawer/popup/DrawerPopup.js +3 -1
- package/lib/drawer/popup/DrawerPopup.js.map +1 -1
- package/lib/filter/index.d.ts +2 -0
- package/lib/filter/index.d.ts.map +1 -0
- package/lib/filter/index.js +6 -0
- package/lib/filter/index.js.map +1 -0
- package/lib/filter/useFilter.d.ts +45 -0
- package/lib/filter/useFilter.d.ts.map +1 -0
- package/lib/filter/useFilter.js +96 -0
- package/lib/filter/useFilter.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/internals/field/useFieldControlRegistration.d.ts +25 -6
- package/lib/internals/field/useFieldControlRegistration.d.ts.map +1 -1
- package/lib/internals/field/useFieldControlRegistration.js +93 -6
- package/lib/internals/field/useFieldControlRegistration.js.map +1 -1
- package/lib/menu/popup/MenuPopup.d.ts +10 -0
- package/lib/menu/popup/MenuPopup.d.ts.map +1 -1
- package/lib/menu/popup/MenuPopup.js +10 -1
- package/lib/menu/popup/MenuPopup.js.map +1 -1
- package/lib/menu/positioner/MenuPositioner.d.ts +10 -0
- package/lib/menu/positioner/MenuPositioner.d.ts.map +1 -1
- package/lib/menu/positioner/MenuPositioner.js +9 -1
- package/lib/menu/positioner/MenuPositioner.js.map +1 -1
- package/lib/menu/store/MenuStore.d.ts +11 -0
- package/lib/menu/store/MenuStore.d.ts.map +1 -1
- package/lib/menu/store/MenuStore.js +4 -0
- package/lib/menu/store/MenuStore.js.map +1 -1
- package/lib/menu/submenu-trigger/MenuSubmenuTrigger.d.ts.map +1 -1
- package/lib/menu/submenu-trigger/MenuSubmenuTrigger.js +3 -0
- package/lib/menu/submenu-trigger/MenuSubmenuTrigger.js.map +1 -1
- package/lib/menu/trigger/MenuTrigger.d.ts.map +1 -1
- package/lib/menu/trigger/MenuTrigger.js +4 -1
- package/lib/menu/trigger/MenuTrigger.js.map +1 -1
- package/lib/meter/indicator/MeterIndicator.d.ts +2 -1
- package/lib/meter/indicator/MeterIndicator.d.ts.map +1 -1
- package/lib/meter/indicator/MeterIndicator.js +1 -2
- package/lib/meter/indicator/MeterIndicator.js.map +1 -1
- package/lib/meter/label/MeterLabel.d.ts +2 -1
- package/lib/meter/label/MeterLabel.d.ts.map +1 -1
- package/lib/meter/label/MeterLabel.js +1 -2
- package/lib/meter/label/MeterLabel.js.map +1 -1
- package/lib/meter/root/MeterRoot.d.ts +21 -0
- package/lib/meter/root/MeterRoot.d.ts.map +1 -1
- package/lib/meter/root/MeterRoot.js +2 -2
- package/lib/meter/root/MeterRoot.js.map +1 -1
- package/lib/meter/root/MeterRootContext.d.ts +5 -0
- package/lib/meter/root/MeterRootContext.d.ts.map +1 -1
- package/lib/meter/root/MeterRootContext.js.map +1 -1
- package/lib/meter/track/MeterTrack.d.ts +2 -1
- package/lib/meter/track/MeterTrack.d.ts.map +1 -1
- package/lib/meter/track/MeterTrack.js +1 -2
- package/lib/meter/track/MeterTrack.js.map +1 -1
- package/lib/meter/value/MeterValue.d.ts +2 -1
- package/lib/meter/value/MeterValue.d.ts.map +1 -1
- package/lib/meter/value/MeterValue.js +1 -2
- package/lib/meter/value/MeterValue.js.map +1 -1
- package/lib/number-field/input/NumberFieldInput.d.ts.map +1 -1
- package/lib/number-field/input/NumberFieldInput.js +11 -2
- package/lib/number-field/input/NumberFieldInput.js.map +1 -1
- package/lib/number-field/root/NumberFieldRoot.d.ts.map +1 -1
- package/lib/number-field/root/NumberFieldRoot.js +5 -2
- package/lib/number-field/root/NumberFieldRoot.js.map +1 -1
- package/lib/otp-field/input/OTPFieldInput.d.ts.map +1 -1
- package/lib/otp-field/input/OTPFieldInput.js +4 -0
- package/lib/otp-field/input/OTPFieldInput.js.map +1 -1
- package/lib/otp-field/root/OTPFieldRoot.d.ts.map +1 -1
- package/lib/otp-field/root/OTPFieldRoot.js +20 -2
- package/lib/otp-field/root/OTPFieldRoot.js.map +1 -1
- package/lib/popover/popup/PopoverPopup.d.ts +10 -0
- package/lib/popover/popup/PopoverPopup.d.ts.map +1 -1
- package/lib/popover/popup/PopoverPopup.js +10 -1
- package/lib/popover/popup/PopoverPopup.js.map +1 -1
- package/lib/popover/positioner/PopoverPositioner.d.ts +10 -0
- package/lib/popover/positioner/PopoverPositioner.d.ts.map +1 -1
- package/lib/popover/positioner/PopoverPositioner.js +4 -0
- package/lib/popover/positioner/PopoverPositioner.js.map +1 -1
- package/lib/popover/store/PopoverStore.d.ts +11 -0
- package/lib/popover/store/PopoverStore.d.ts.map +1 -1
- package/lib/popover/store/PopoverStore.js +4 -0
- package/lib/popover/store/PopoverStore.js.map +1 -1
- package/lib/popover/trigger/PopoverTrigger.d.ts.map +1 -1
- package/lib/popover/trigger/PopoverTrigger.js +4 -1
- package/lib/popover/trigger/PopoverTrigger.js.map +1 -1
- package/lib/progress/root/ProgressRoot.d.ts +21 -0
- package/lib/progress/root/ProgressRoot.d.ts.map +1 -1
- package/lib/progress/root/ProgressRoot.js +1 -1
- package/lib/progress/root/ProgressRoot.js.map +1 -1
- package/lib/radio-group/RadioGroup.d.ts.map +1 -1
- package/lib/radio-group/RadioGroup.js +5 -2
- package/lib/radio-group/RadioGroup.js.map +1 -1
- package/lib/select/backdrop/SelectBackdrop.d.ts.map +1 -1
- package/lib/select/backdrop/SelectBackdrop.js +3 -0
- package/lib/select/backdrop/SelectBackdrop.js.map +1 -1
- package/lib/select/index.parts.d.ts +1 -0
- package/lib/select/index.parts.d.ts.map +1 -1
- package/lib/select/index.parts.js +4 -1
- package/lib/select/index.parts.js.map +1 -1
- package/lib/select/popup/SelectPopup.d.ts +8 -0
- package/lib/select/popup/SelectPopup.d.ts.map +1 -1
- package/lib/select/popup/SelectPopup.js +10 -1
- package/lib/select/popup/SelectPopup.js.map +1 -1
- package/lib/select/positioner/SelectPositioner.d.ts +4 -0
- package/lib/select/positioner/SelectPositioner.d.ts.map +1 -1
- package/lib/select/positioner/SelectPositioner.js +2 -0
- package/lib/select/positioner/SelectPositioner.js.map +1 -1
- package/lib/select/root/SelectRoot.d.ts +45 -4
- package/lib/select/root/SelectRoot.d.ts.map +1 -1
- package/lib/select/root/SelectRoot.js +43 -5
- package/lib/select/root/SelectRoot.js.map +1 -1
- package/lib/select/store/SelectHandle.d.ts +42 -0
- package/lib/select/store/SelectHandle.d.ts.map +1 -0
- package/lib/select/store/SelectHandle.js +69 -0
- package/lib/select/store/SelectHandle.js.map +1 -0
- package/lib/select/store/SelectStore.d.ts +28 -0
- package/lib/select/store/SelectStore.d.ts.map +1 -1
- package/lib/select/store/SelectStore.js +15 -1
- package/lib/select/store/SelectStore.js.map +1 -1
- package/lib/select/trigger/SelectTrigger.d.ts +18 -3
- package/lib/select/trigger/SelectTrigger.d.ts.map +1 -1
- package/lib/select/trigger/SelectTrigger.js +49 -4
- package/lib/select/trigger/SelectTrigger.js.map +1 -1
- package/lib/slider/root/SliderRoot.d.ts.map +1 -1
- package/lib/slider/root/SliderRoot.js +9 -1
- package/lib/slider/root/SliderRoot.js.map +1 -1
- package/lib/slider/thumb/SliderThumb.d.ts.map +1 -1
- package/lib/slider/thumb/SliderThumb.js +10 -2
- package/lib/slider/thumb/SliderThumb.js.map +1 -1
- package/lib/switch/root/SwitchRoot.d.ts.map +1 -1
- package/lib/switch/root/SwitchRoot.js +6 -2
- package/lib/switch/root/SwitchRoot.js.map +1 -1
- package/lib/tabs/tab/TabsTab.d.ts +2 -10
- package/lib/tabs/tab/TabsTab.d.ts.map +1 -1
- package/lib/tooltip/popup/TooltipPopup.d.ts +10 -0
- package/lib/tooltip/popup/TooltipPopup.d.ts.map +1 -1
- package/lib/tooltip/popup/TooltipPopup.js +10 -1
- package/lib/tooltip/popup/TooltipPopup.js.map +1 -1
- package/lib/tooltip/positioner/TooltipPositioner.d.ts +10 -0
- package/lib/tooltip/positioner/TooltipPositioner.d.ts.map +1 -1
- package/lib/tooltip/positioner/TooltipPositioner.js +4 -0
- package/lib/tooltip/positioner/TooltipPositioner.js.map +1 -1
- package/lib/tooltip/store/TooltipStore.d.ts +11 -0
- package/lib/tooltip/store/TooltipStore.d.ts.map +1 -1
- package/lib/tooltip/store/TooltipStore.js +11 -1
- package/lib/tooltip/store/TooltipStore.js.map +1 -1
- package/lib/tooltip/trigger/TooltipTrigger.d.ts.map +1 -1
- package/lib/tooltip/trigger/TooltipTrigger.js +4 -1
- package/lib/tooltip/trigger/TooltipTrigger.js.map +1 -1
- package/package.json +1 -1
- package/src/alert-dialog/index.parts.ts +1 -1
- package/src/autocomplete/handle.ts +18 -0
- package/src/autocomplete/index.parts.ts +1 -0
- package/src/autocomplete/index.ts +1 -0
- package/src/autocomplete/root/AutocompleteRoot.tsx +65 -50
- package/src/avatar/fallback/AvatarFallback.tsx +3 -1
- package/src/avatar/image/AvatarImage.tsx +5 -0
- package/src/checkbox/root/CheckboxRoot.tsx +7 -2
- package/src/combobox/backdrop/ComboboxBackdrop.tsx +10 -3
- package/src/combobox/empty/ComboboxEmpty.tsx +5 -1
- package/src/combobox/index.parts.ts +1 -0
- package/src/combobox/index.ts +2 -0
- package/src/combobox/input/ComboboxInput.tsx +112 -27
- package/src/combobox/item/ComboboxItem.tsx +24 -6
- package/src/combobox/list/ComboboxList.tsx +7 -2
- package/src/combobox/popup/ComboboxPopup.tsx +44 -2
- package/src/combobox/portal/ComboboxPortal.tsx +19 -13
- package/src/combobox/portal/ComboboxPortalContext.ts +15 -0
- package/src/combobox/positioner/ComboboxPositioner.tsx +45 -10
- package/src/combobox/positioner/ComboboxPositionerContext.ts +23 -0
- package/src/combobox/root/ComboboxItemsContext.ts +32 -0
- package/src/combobox/root/ComboboxRoot.tsx +94 -56
- package/src/combobox/root/ComboboxRootContext.ts +3 -54
- package/src/combobox/root/ComboboxTransitionContext.ts +15 -0
- package/src/combobox/root/useRenderComboboxRoot.tsx +189 -0
- package/src/combobox/store/ComboboxHandle.ts +64 -0
- package/src/combobox/store/ComboboxStore.ts +249 -0
- package/src/combobox/value/ComboboxValue.tsx +2 -1
- package/src/context-menu/positioner/ContextMenuPositioner.tsx +90 -10
- package/src/context-menu/root/ContextMenuRoot.tsx +8 -0
- package/src/dialog/backdrop/DialogBackdrop.tsx +12 -1
- package/src/dialog/popup/DialogPopup.tsx +11 -2
- package/src/dialog/popup/useDialogPopupProps.ts +4 -0
- package/src/dialog/root/DialogNestingContext.ts +27 -0
- package/src/dialog/root/useRenderDialogRoot.tsx +37 -2
- package/src/dialog/store/DialogStore.ts +24 -2
- package/src/drawer/index.parts.ts +1 -1
- package/src/drawer/popup/DrawerPopup.tsx +12 -1
- package/src/filter/index.ts +5 -0
- package/src/filter/useFilter.ts +95 -0
- package/src/index.ts +1 -0
- package/src/internals/field/useFieldControlRegistration.ts +86 -6
- package/src/menu/popup/MenuPopup.tsx +20 -1
- package/src/menu/positioner/MenuPositioner.tsx +19 -1
- package/src/menu/store/MenuStore.ts +13 -0
- package/src/menu/submenu-trigger/MenuSubmenuTrigger.tsx +3 -0
- package/src/menu/trigger/MenuTrigger.tsx +5 -2
- package/src/meter/indicator/MeterIndicator.tsx +3 -4
- package/src/meter/label/MeterLabel.tsx +3 -4
- package/src/meter/root/MeterRoot.tsx +29 -4
- package/src/meter/root/MeterRootContext.ts +5 -0
- package/src/meter/track/MeterTrack.tsx +3 -4
- package/src/meter/value/MeterValue.tsx +3 -4
- package/src/number-field/input/NumberFieldInput.tsx +11 -2
- package/src/number-field/root/NumberFieldRoot.tsx +4 -2
- package/src/otp-field/input/OTPFieldInput.tsx +4 -0
- package/src/otp-field/root/OTPFieldRoot.tsx +22 -2
- package/src/popover/popup/PopoverPopup.tsx +20 -1
- package/src/popover/positioner/PopoverPositioner.tsx +14 -0
- package/src/popover/store/PopoverStore.ts +13 -0
- package/src/popover/trigger/PopoverTrigger.tsx +5 -2
- package/src/progress/root/ProgressRoot.tsx +25 -1
- package/src/radio-group/RadioGroup.tsx +5 -2
- package/src/select/backdrop/SelectBackdrop.tsx +4 -0
- package/src/select/index.parts.ts +1 -0
- package/src/select/popup/SelectPopup.tsx +18 -1
- package/src/select/positioner/SelectPositioner.tsx +9 -3
- package/src/select/root/SelectRoot.tsx +109 -9
- package/src/select/store/SelectHandle.ts +68 -0
- package/src/select/store/SelectStore.ts +38 -1
- package/src/select/trigger/SelectTrigger.tsx +78 -7
- package/src/slider/root/SliderRoot.tsx +11 -1
- package/src/slider/thumb/SliderThumb.tsx +10 -1
- package/src/switch/root/SwitchRoot.tsx +5 -2
- package/src/tabs/tab/TabsTab.tsx +2 -10
- package/src/tooltip/popup/TooltipPopup.tsx +20 -1
- package/src/tooltip/positioner/TooltipPositioner.tsx +14 -0
- package/src/tooltip/store/TooltipStore.ts +20 -1
- package/src/tooltip/trigger/TooltipTrigger.tsx +5 -2
- package/lib/combobox/root/useComboboxRoot.d.ts +0 -29
- package/lib/combobox/root/useComboboxRoot.d.ts.map +0 -1
- package/lib/combobox/root/useComboboxRoot.js +0 -176
- package/lib/combobox/root/useComboboxRoot.js.map +0 -1
- package/lib/utils/fastObjectShallowCompare.d.ts +0 -2
- package/lib/utils/fastObjectShallowCompare.d.ts.map +0 -1
- package/lib/utils/fastObjectShallowCompare.js +0 -29
- package/lib/utils/fastObjectShallowCompare.js.map +0 -1
- package/lib/utils/mergeObjects.d.ts +0 -2
- package/lib/utils/mergeObjects.d.ts.map +0 -1
- package/lib/utils/mergeObjects.js +0 -16
- package/lib/utils/mergeObjects.js.map +0 -1
- package/src/combobox/root/useComboboxRoot.ts +0 -199
- package/src/utils/fastObjectShallowCompare.ts +0 -30
- package/src/utils/mergeObjects.ts +0 -15
|
@@ -5,6 +5,7 @@ import { useControlled } from '../../hooks/useControlled';
|
|
|
5
5
|
import { useId } from '../../hooks/useId';
|
|
6
6
|
import { useStableCallback } from '../../hooks/useStableCallback';
|
|
7
7
|
import { useRenderElement } from '../../use-render/useRenderElement';
|
|
8
|
+
import { useFieldControlRegistration } from '../../internals/field/useFieldControlRegistration';
|
|
8
9
|
import { CompositeList } from '../../internals/composite/list/CompositeList';
|
|
9
10
|
import type { ZestUIComponentProps } from '../../types';
|
|
10
11
|
import type { ZestChangeEventDetails } from '../../utils/createChangeEventDetails';
|
|
@@ -31,7 +32,7 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
|
|
|
31
32
|
autoComplete = 'one-time-code',
|
|
32
33
|
className,
|
|
33
34
|
defaultValue,
|
|
34
|
-
disabled = false,
|
|
35
|
+
disabled: disabledProp = false,
|
|
35
36
|
id: idProp,
|
|
36
37
|
length,
|
|
37
38
|
mask = false,
|
|
@@ -48,6 +49,12 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
|
|
|
48
49
|
...elementProps
|
|
49
50
|
} = componentProps;
|
|
50
51
|
|
|
52
|
+
const { fieldDisabled, fieldProps, markChanged, markTouched } = useFieldControlRegistration({
|
|
53
|
+
initialValue: normalizeOTPValue(defaultValue ?? valueProp, length, validationType, normalizeValue),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const disabled = disabledProp || fieldDisabled;
|
|
57
|
+
|
|
51
58
|
const id = useId(idProp);
|
|
52
59
|
|
|
53
60
|
const [value, setValueState] = useControlled<string>({
|
|
@@ -103,8 +110,11 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
|
|
|
103
110
|
}
|
|
104
111
|
|
|
105
112
|
setValueState(normalized);
|
|
113
|
+
markChanged(normalized);
|
|
106
114
|
|
|
107
115
|
if (normalized.length === length) {
|
|
116
|
+
// A complete code ends the interaction; there is no blur to wait for.
|
|
117
|
+
markTouched(normalized);
|
|
108
118
|
onValueComplete?.(normalized, createChangeEventDetails(eventDetails.reason));
|
|
109
119
|
}
|
|
110
120
|
|
|
@@ -169,7 +179,17 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
|
|
|
169
179
|
const element = useRenderElement(View, componentProps, {
|
|
170
180
|
state,
|
|
171
181
|
ref,
|
|
172
|
-
props:
|
|
182
|
+
props: [
|
|
183
|
+
{
|
|
184
|
+
// The slots are separate inputs but one field: without a group role a
|
|
185
|
+
// screen reader announces N unrelated text boxes. Pass
|
|
186
|
+
// `accessibilityLabel` to name the code being entered.
|
|
187
|
+
role: 'group' as const,
|
|
188
|
+
accessibilityState: { disabled: disabled || undefined },
|
|
189
|
+
...fieldProps,
|
|
190
|
+
},
|
|
191
|
+
elementProps,
|
|
192
|
+
],
|
|
173
193
|
});
|
|
174
194
|
|
|
175
195
|
return (
|
|
@@ -20,10 +20,19 @@ export function PopoverPopup(componentProps: PopoverPopup.Props) {
|
|
|
20
20
|
const { transitionStatus } = usePopoverTransitionContext() ?? { transitionStatus: undefined };
|
|
21
21
|
|
|
22
22
|
const open = store.useState('open');
|
|
23
|
+
const triggerWidth = store.useState('triggerWidth');
|
|
24
|
+
const triggerHeight = store.useState('triggerHeight');
|
|
23
25
|
const titleElementId = store.useState('titleElementId');
|
|
24
26
|
const descriptionElementId = store.useState('descriptionElementId');
|
|
25
27
|
|
|
26
|
-
const state: PopoverPopupState = {
|
|
28
|
+
const state: PopoverPopupState = {
|
|
29
|
+
open,
|
|
30
|
+
transitionStatus,
|
|
31
|
+
side,
|
|
32
|
+
align,
|
|
33
|
+
triggerWidth,
|
|
34
|
+
triggerHeight,
|
|
35
|
+
};
|
|
27
36
|
|
|
28
37
|
return useRenderElement(View, componentProps, {
|
|
29
38
|
state,
|
|
@@ -61,6 +70,16 @@ export interface PopoverPopupState {
|
|
|
61
70
|
* The alignment the popup was actually placed with.
|
|
62
71
|
*/
|
|
63
72
|
align: Align;
|
|
73
|
+
/**
|
|
74
|
+
* The trigger's measured width, available for consumers to size the popup
|
|
75
|
+
* against its anchor. This is the React Native equivalent of the web's
|
|
76
|
+
* `--anchor-width` CSS variable.
|
|
77
|
+
*/
|
|
78
|
+
triggerWidth: number | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* The trigger's measured height.
|
|
81
|
+
*/
|
|
82
|
+
triggerHeight: number | undefined;
|
|
64
83
|
}
|
|
65
84
|
|
|
66
85
|
export interface PopoverPopupProps extends ZestUIComponentProps<typeof View, PopoverPopupState> {}
|
|
@@ -38,6 +38,8 @@ export function PopoverPositioner(componentProps: PopoverPositioner.Props) {
|
|
|
38
38
|
usePopoverPortalContext();
|
|
39
39
|
const store = usePopoverRootContext();
|
|
40
40
|
const open = store.useState('open');
|
|
41
|
+
const triggerWidth = store.useState('triggerWidth');
|
|
42
|
+
const triggerHeight = store.useState('triggerHeight');
|
|
41
43
|
const triggerNode = store.useState('triggerNode');
|
|
42
44
|
|
|
43
45
|
const positioning = useAnchorPositioning({
|
|
@@ -72,6 +74,8 @@ export function PopoverPositioner(componentProps: PopoverPositioner.Props) {
|
|
|
72
74
|
open,
|
|
73
75
|
side: positioning.side,
|
|
74
76
|
align: positioning.align,
|
|
77
|
+
triggerWidth,
|
|
78
|
+
triggerHeight,
|
|
75
79
|
};
|
|
76
80
|
|
|
77
81
|
const contextValue: PopoverPositionerContext = React.useMemo(
|
|
@@ -114,6 +118,16 @@ export interface PopoverPositionerState {
|
|
|
114
118
|
* The alignment the popup was actually placed with.
|
|
115
119
|
*/
|
|
116
120
|
align: Align;
|
|
121
|
+
/**
|
|
122
|
+
* The trigger's measured width, available for consumers to size the popup
|
|
123
|
+
* against its anchor. This is the React Native equivalent of the web's
|
|
124
|
+
* `--anchor-width` CSS variable.
|
|
125
|
+
*/
|
|
126
|
+
triggerWidth: number | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* The trigger's measured height.
|
|
129
|
+
*/
|
|
130
|
+
triggerHeight: number | undefined;
|
|
117
131
|
}
|
|
118
132
|
|
|
119
133
|
export interface PopoverPositionerProps
|
|
@@ -22,6 +22,15 @@ export type State = {
|
|
|
22
22
|
* different subtree from the Trigger, so the store is what carries it across.
|
|
23
23
|
*/
|
|
24
24
|
triggerNode: unknown;
|
|
25
|
+
/**
|
|
26
|
+
* The trigger's measured width, the React Native counterpart of the web's
|
|
27
|
+
* `--anchor-width` CSS variable.
|
|
28
|
+
*/
|
|
29
|
+
triggerWidth: number | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The trigger's measured height.
|
|
32
|
+
*/
|
|
33
|
+
triggerHeight: number | undefined;
|
|
25
34
|
/**
|
|
26
35
|
* Set by the Positioner so the Trigger can request a reposition when it is
|
|
27
36
|
* laid out. React Native has no `autoUpdate`.
|
|
@@ -57,6 +66,8 @@ const selectors = {
|
|
|
57
66
|
descriptionElementId: createSelector((state: State) => state.descriptionElementId),
|
|
58
67
|
disablePointerDismissal: createSelector((state: State) => state.disablePointerDismissal),
|
|
59
68
|
triggerNode: createSelector((state: State) => state.triggerNode),
|
|
69
|
+
triggerWidth: createSelector((state: State) => state.triggerWidth),
|
|
70
|
+
triggerHeight: createSelector((state: State) => state.triggerHeight),
|
|
60
71
|
update: createSelector((state: State) => state.update),
|
|
61
72
|
payload: createSelector((state: State) => state.payload),
|
|
62
73
|
triggerId: createSelector((state: State) => state.triggerIdProp ?? state.triggerId),
|
|
@@ -75,6 +86,8 @@ export class PopoverStore extends ReactStore<Readonly<State>, Context, typeof se
|
|
|
75
86
|
descriptionElementId: undefined,
|
|
76
87
|
disablePointerDismissal: false,
|
|
77
88
|
triggerNode: null,
|
|
89
|
+
triggerWidth: undefined,
|
|
90
|
+
triggerHeight: undefined,
|
|
78
91
|
update: undefined,
|
|
79
92
|
payload: undefined,
|
|
80
93
|
triggerId: null,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { Pressable, type GestureResponderEvent } from 'react-native';
|
|
3
|
+
import { Pressable, type GestureResponderEvent, type LayoutChangeEvent } from 'react-native';
|
|
4
4
|
import { PopoverRootContext } from '../root/PopoverRootContext';
|
|
5
5
|
import { useRenderElement } from '../../use-render/useRenderElement';
|
|
6
6
|
import { useButton } from '../../internals/use-button/useButton';
|
|
@@ -99,7 +99,10 @@ export function PopoverTrigger<Payload = unknown>(componentProps: PopoverTrigger
|
|
|
99
99
|
onPressOut() {
|
|
100
100
|
setPressed(false);
|
|
101
101
|
},
|
|
102
|
-
onLayout() {
|
|
102
|
+
onLayout(event: LayoutChangeEvent) {
|
|
103
|
+
const { width, height } = event.nativeEvent.layout;
|
|
104
|
+
store.set('triggerWidth', width);
|
|
105
|
+
store.set('triggerHeight', height);
|
|
103
106
|
// Nothing tracks the anchor globally in React Native, so a moved or
|
|
104
107
|
// resized trigger has to ask the positioner to recompute.
|
|
105
108
|
store.state.update?.();
|
|
@@ -62,7 +62,10 @@ export function ProgressRoot(componentProps: ProgressRoot.Props) {
|
|
|
62
62
|
: formatNumber(percentageValue / 100, locale, { style: 'percent' });
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
const state: ProgressRootState = React.useMemo(
|
|
65
|
+
const state: ProgressRootState = React.useMemo(
|
|
66
|
+
() => ({ status, value: clampedValue, min, max, percent: percentageValue, formattedValue }),
|
|
67
|
+
[status, clampedValue, min, max, percentageValue, formattedValue],
|
|
68
|
+
);
|
|
66
69
|
|
|
67
70
|
const contextValue: ProgressRootContext = React.useMemo(
|
|
68
71
|
() => ({ formattedValue, percentageValue, setLabelId, state, value }),
|
|
@@ -102,6 +105,27 @@ export interface ProgressRootState {
|
|
|
102
105
|
* The current status.
|
|
103
106
|
*/
|
|
104
107
|
status: ProgressStatus;
|
|
108
|
+
/**
|
|
109
|
+
* The current value, clamped into `[min, max]`, or `null` while indeterminate.
|
|
110
|
+
*/
|
|
111
|
+
value: number | null;
|
|
112
|
+
/**
|
|
113
|
+
* The minimum value.
|
|
114
|
+
*/
|
|
115
|
+
min: number;
|
|
116
|
+
/**
|
|
117
|
+
* The maximum value.
|
|
118
|
+
*/
|
|
119
|
+
max: number;
|
|
120
|
+
/**
|
|
121
|
+
* How far the value sits through the range, `0`–`100`, or `null` while
|
|
122
|
+
* indeterminate. This is what an indicator's width comes from.
|
|
123
|
+
*/
|
|
124
|
+
percent: number | null;
|
|
125
|
+
/**
|
|
126
|
+
* The value as text, through `format`/`locale`. Empty while indeterminate.
|
|
127
|
+
*/
|
|
128
|
+
formattedValue: string;
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
export interface ProgressRootProps extends ZestUIComponentProps<typeof View, ProgressRootState> {
|
|
@@ -29,7 +29,9 @@ export function RadioGroup<Value = any>(componentProps: RadioGroup.Props<Value>)
|
|
|
29
29
|
...elementProps
|
|
30
30
|
} = componentProps;
|
|
31
31
|
|
|
32
|
-
const { fieldDisabled, fieldProps,
|
|
32
|
+
const { fieldDisabled, fieldProps, markChanged, markTouched } = useFieldControlRegistration({
|
|
33
|
+
initialValue: defaultValue ?? valueProp,
|
|
34
|
+
});
|
|
33
35
|
|
|
34
36
|
const disabled = disabledProp || fieldDisabled;
|
|
35
37
|
|
|
@@ -49,7 +51,8 @@ export function RadioGroup<Value = any>(componentProps: RadioGroup.Props<Value>)
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
setCheckedValueUnwrapped(value);
|
|
52
|
-
|
|
54
|
+
markChanged(value);
|
|
55
|
+
markTouched(value);
|
|
53
56
|
},
|
|
54
57
|
);
|
|
55
58
|
|
|
@@ -25,6 +25,10 @@ export function SelectBackdrop(componentProps: SelectBackdrop.Props) {
|
|
|
25
25
|
{
|
|
26
26
|
style: StyleSheet.absoluteFill,
|
|
27
27
|
onPress(event: GestureResponderEvent) {
|
|
28
|
+
if (store.select('disablePointerDismissal')) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
store.setOpen(false, createChangeEventDetails(REASONS.outsidePress, event));
|
|
29
33
|
},
|
|
30
34
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { SelectRoot as Root } from './root/SelectRoot';
|
|
2
|
+
export { createSelectHandle as createHandle, SelectHandle as Handle } from './store/SelectHandle';
|
|
2
3
|
export { SelectLabel as Label } from './label/SelectLabel';
|
|
3
4
|
export { SelectTrigger as Trigger } from './trigger/SelectTrigger';
|
|
4
5
|
export { SelectValue as Value } from './value/SelectValue';
|
|
@@ -21,8 +21,17 @@ export function SelectPopup(componentProps: SelectPopup.Props) {
|
|
|
21
21
|
const { transitionStatus } = useSelectTransitionContext() ?? { transitionStatus: undefined };
|
|
22
22
|
|
|
23
23
|
const open = store.useState('open');
|
|
24
|
+
const triggerWidth = store.useState('triggerWidth');
|
|
25
|
+
const triggerHeight = store.useState('triggerHeight');
|
|
24
26
|
|
|
25
|
-
const state: SelectPopupState = {
|
|
27
|
+
const state: SelectPopupState = {
|
|
28
|
+
open,
|
|
29
|
+
transitionStatus,
|
|
30
|
+
side,
|
|
31
|
+
align,
|
|
32
|
+
triggerWidth,
|
|
33
|
+
triggerHeight,
|
|
34
|
+
};
|
|
26
35
|
|
|
27
36
|
const element = useRenderElement(View, componentProps, {
|
|
28
37
|
state,
|
|
@@ -59,6 +68,14 @@ export interface SelectPopupState {
|
|
|
59
68
|
* The alignment the popup was actually placed with.
|
|
60
69
|
*/
|
|
61
70
|
align: Align;
|
|
71
|
+
/**
|
|
72
|
+
* The trigger's measured width, available for consumers to apply to the popup.
|
|
73
|
+
*/
|
|
74
|
+
triggerWidth: number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* The trigger's measured height.
|
|
77
|
+
*/
|
|
78
|
+
triggerHeight: number | undefined;
|
|
62
79
|
}
|
|
63
80
|
|
|
64
81
|
export interface SelectPopupProps extends ZestUIComponentProps<typeof View, SelectPopupState> {}
|
|
@@ -40,6 +40,7 @@ export function SelectPositioner(componentProps: SelectPositioner.Props) {
|
|
|
40
40
|
const open = store.useState('open');
|
|
41
41
|
const triggerNode = store.useState('triggerNode');
|
|
42
42
|
const triggerWidth = store.useState('triggerWidth');
|
|
43
|
+
const triggerHeight = store.useState('triggerHeight');
|
|
43
44
|
|
|
44
45
|
const positioning = useAnchorPositioning({
|
|
45
46
|
align,
|
|
@@ -66,11 +67,12 @@ export function SelectPositioner(componentProps: SelectPositioner.Props) {
|
|
|
66
67
|
|
|
67
68
|
const mergedRef = useMergedRefs(ref, refs.setFloating);
|
|
68
69
|
|
|
69
|
-
const state: SelectPositionerState = {
|
|
70
|
-
open,
|
|
71
|
-
side: positioning.side,
|
|
70
|
+
const state: SelectPositionerState = {
|
|
71
|
+
open,
|
|
72
|
+
side: positioning.side,
|
|
72
73
|
align: positioning.align,
|
|
73
74
|
triggerWidth,
|
|
75
|
+
triggerHeight,
|
|
74
76
|
};
|
|
75
77
|
|
|
76
78
|
const contextValue: SelectPositionerContext = React.useMemo(
|
|
@@ -108,6 +110,10 @@ export interface SelectPositionerState {
|
|
|
108
110
|
* This is the React Native equivalent of the web's `--anchor-width` CSS variable.
|
|
109
111
|
*/
|
|
110
112
|
triggerWidth: number | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* The trigger's measured height.
|
|
115
|
+
*/
|
|
116
|
+
triggerHeight: number | undefined;
|
|
111
117
|
}
|
|
112
118
|
|
|
113
119
|
export interface SelectPositionerProps
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { useRefWithInit } from '../../hooks/useRefWithInit';
|
|
4
|
+
import { useStableCallback } from '../../hooks/useStableCallback';
|
|
4
5
|
import { useTransitionStatus } from '../../internals/useTransitionStatus';
|
|
6
|
+
import { usePopupRootHandle } from '../../utils/popups/usePopupRootHandle';
|
|
7
|
+
import { useFieldControlRegistration } from '../../internals/field/useFieldControlRegistration';
|
|
5
8
|
import type { ZestChangeEventDetails } from '../../utils/createChangeEventDetails';
|
|
6
9
|
import type { REASONS } from '../../utils/reasons';
|
|
10
|
+
import type { SelectHandle } from '../store/SelectHandle';
|
|
7
11
|
import { SelectStore, type SelectItems } from '../store/SelectStore';
|
|
8
12
|
import { SelectRootContext } from './SelectRootContext';
|
|
9
13
|
import { SelectTransitionContext } from './SelectTransitionContext';
|
|
@@ -15,12 +19,18 @@ import { SelectTransitionContext } from './SelectTransitionContext';
|
|
|
15
19
|
* Unlike the web version there is no hidden `<select>`: React Native has no form
|
|
16
20
|
* submission, so `name`/`form` are omitted. Multi-select is not ported yet.
|
|
17
21
|
*/
|
|
18
|
-
export function SelectRoot<Value = any>(
|
|
22
|
+
export function SelectRoot<Value = any, Payload = unknown>(
|
|
23
|
+
props: SelectRoot.Props<Value, Payload>,
|
|
24
|
+
) {
|
|
19
25
|
const {
|
|
26
|
+
actionsRef,
|
|
20
27
|
children,
|
|
21
28
|
defaultOpen = false,
|
|
29
|
+
defaultTriggerId = null,
|
|
22
30
|
defaultValue,
|
|
23
|
-
|
|
31
|
+
disablePointerDismissal = false,
|
|
32
|
+
disabled: disabledProp = false,
|
|
33
|
+
handle,
|
|
24
34
|
items,
|
|
25
35
|
multiple = false,
|
|
26
36
|
onOpenChange,
|
|
@@ -28,9 +38,16 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
|
|
|
28
38
|
open,
|
|
29
39
|
readOnly = false,
|
|
30
40
|
required = false,
|
|
41
|
+
triggerId,
|
|
31
42
|
value,
|
|
32
43
|
} = props;
|
|
33
44
|
|
|
45
|
+
const { fieldDisabled, markChanged, markTouched } = useFieldControlRegistration({
|
|
46
|
+
initialValue: defaultValue ?? value ?? (multiple ? [] : undefined),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const disabled = disabledProp || fieldDisabled;
|
|
50
|
+
|
|
34
51
|
const store = useRefWithInit(
|
|
35
52
|
() =>
|
|
36
53
|
new SelectStore({
|
|
@@ -45,18 +62,60 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
|
|
|
45
62
|
disabled,
|
|
46
63
|
readOnly,
|
|
47
64
|
required,
|
|
65
|
+
disablePointerDismissal,
|
|
66
|
+
triggerId: defaultTriggerId,
|
|
67
|
+
triggerIdProp: triggerId,
|
|
48
68
|
}),
|
|
49
69
|
).current;
|
|
50
70
|
|
|
71
|
+
// Wrapping the consumer's callbacks is what lets a select report itself to a
|
|
72
|
+
// surrounding `Field.Root`: choosing a value makes the field dirty, and
|
|
73
|
+
// closing the popup is the select's equivalent of a blur.
|
|
74
|
+
const handleValueChange = useStableCallback(
|
|
75
|
+
(nextValue: Value, eventDetails: SelectRoot.ChangeEventDetails) => {
|
|
76
|
+
onValueChange?.(nextValue, eventDetails);
|
|
77
|
+
|
|
78
|
+
if (eventDetails.isCanceled) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
markChanged(nextValue);
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const handleOpenChange = useStableCallback(
|
|
87
|
+
(nextOpen: boolean, eventDetails: SelectRoot.ChangeEventDetails) => {
|
|
88
|
+
onOpenChange?.(nextOpen, eventDetails);
|
|
89
|
+
|
|
90
|
+
if (eventDetails.isCanceled || nextOpen) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
markTouched(store.select('value'));
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
|
|
51
98
|
store.useControlledProp('openProp', open);
|
|
52
99
|
store.useControlledProp('valueProp', value);
|
|
53
|
-
store.
|
|
54
|
-
store.useContextCallback('
|
|
55
|
-
store.
|
|
100
|
+
store.useControlledProp('triggerIdProp', triggerId);
|
|
101
|
+
store.useContextCallback('onOpenChange', handleOpenChange);
|
|
102
|
+
store.useContextCallback('onValueChange', handleValueChange);
|
|
103
|
+
store.useSyncedValues({
|
|
104
|
+
disabled,
|
|
105
|
+
readOnly,
|
|
106
|
+
required,
|
|
107
|
+
items,
|
|
108
|
+
multiple,
|
|
109
|
+
disablePointerDismissal,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
usePopupRootHandle({ store, handle, actionsRef });
|
|
56
113
|
|
|
57
114
|
const resolvedOpen = store.useState('open');
|
|
58
115
|
const { transitionStatus } = useTransitionStatus(resolvedOpen, false, true);
|
|
59
116
|
|
|
117
|
+
const payload = store.useState('payload') as Payload;
|
|
118
|
+
|
|
60
119
|
const transitionContextValue = React.useMemo(
|
|
61
120
|
() => ({ transitionStatus }),
|
|
62
121
|
[transitionStatus],
|
|
@@ -65,7 +124,7 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
|
|
|
65
124
|
return (
|
|
66
125
|
<SelectRootContext.Provider value={store}>
|
|
67
126
|
<SelectTransitionContext.Provider value={transitionContextValue}>
|
|
68
|
-
{children}
|
|
127
|
+
{typeof children === 'function' ? children(payload) : children}
|
|
69
128
|
</SelectTransitionContext.Provider>
|
|
70
129
|
</SelectRootContext.Provider>
|
|
71
130
|
);
|
|
@@ -73,7 +132,19 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
|
|
|
73
132
|
|
|
74
133
|
export interface SelectRootState {}
|
|
75
134
|
|
|
76
|
-
export interface
|
|
135
|
+
export interface SelectRootActions {
|
|
136
|
+
/**
|
|
137
|
+
* Unmounts the popup without firing `onOpenChange`. Call it after an
|
|
138
|
+
* externally controlled closing animation finishes.
|
|
139
|
+
*/
|
|
140
|
+
unmount: () => void;
|
|
141
|
+
/**
|
|
142
|
+
* Closes the popup, reporting the `imperative-action` reason.
|
|
143
|
+
*/
|
|
144
|
+
close: () => void;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface SelectRootProps<Value = any, Payload = unknown> {
|
|
77
148
|
/**
|
|
78
149
|
* The value of the currently selected item.
|
|
79
150
|
*
|
|
@@ -145,10 +216,38 @@ export interface SelectRootProps<Value = any> {
|
|
|
145
216
|
* ```
|
|
146
217
|
*/
|
|
147
218
|
items?: SelectItems | undefined;
|
|
219
|
+
/**
|
|
220
|
+
* Whether to prevent the popup from closing on presses outside it.
|
|
221
|
+
* @default false
|
|
222
|
+
*/
|
|
223
|
+
disablePointerDismissal?: boolean | undefined;
|
|
224
|
+
/**
|
|
225
|
+
* A ref to imperative actions.
|
|
226
|
+
*/
|
|
227
|
+
actionsRef?: React.RefObject<SelectRoot.Actions | null> | undefined;
|
|
228
|
+
/**
|
|
229
|
+
* A handle associating this select with triggers rendered outside it, and
|
|
230
|
+
* letting it be opened and closed imperatively. Create one with
|
|
231
|
+
* `Select.createHandle()`.
|
|
232
|
+
*/
|
|
233
|
+
handle?: SelectHandle<Payload> | undefined;
|
|
234
|
+
/**
|
|
235
|
+
* The id of the trigger the popup is anchored to. Useful together with the
|
|
236
|
+
* `open` prop, to control which trigger a controlled select belongs to.
|
|
237
|
+
*/
|
|
238
|
+
triggerId?: string | null | undefined;
|
|
239
|
+
/**
|
|
240
|
+
* The id of the trigger the popup is initially anchored to. Useful together
|
|
241
|
+
* with `defaultOpen`.
|
|
242
|
+
*/
|
|
243
|
+
defaultTriggerId?: string | null | undefined;
|
|
148
244
|
/**
|
|
149
245
|
* The content of the select.
|
|
246
|
+
*
|
|
247
|
+
* Pass a function to receive the payload the select was opened with, via a
|
|
248
|
+
* trigger's `payload` prop.
|
|
150
249
|
*/
|
|
151
|
-
children?: React.ReactNode;
|
|
250
|
+
children?: React.ReactNode | ((payload: Payload) => React.ReactNode);
|
|
152
251
|
}
|
|
153
252
|
|
|
154
253
|
export type SelectRootChangeEventReason =
|
|
@@ -163,7 +262,8 @@ export type SelectRootChangeEventDetails = ZestChangeEventDetails<SelectRootChan
|
|
|
163
262
|
|
|
164
263
|
export namespace SelectRoot {
|
|
165
264
|
export type State = SelectRootState;
|
|
166
|
-
export type Props<TValue = any> = SelectRootProps<TValue>;
|
|
265
|
+
export type Props<TValue = any, TPayload = unknown> = SelectRootProps<TValue, TPayload>;
|
|
266
|
+
export type Actions = SelectRootActions;
|
|
167
267
|
export type ChangeEventReason = SelectRootChangeEventReason;
|
|
168
268
|
export type ChangeEventDetails = SelectRootChangeEventDetails;
|
|
169
269
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { SelectStore } from './SelectStore';
|
|
2
|
+
import { BasePopupHandle } from '../../utils/popups/BasePopupHandle';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Controls a select imperatively, and associates `Select.Trigger`s rendered
|
|
6
|
+
* outside the root with it. Create one with `Select.createHandle()` and pass it
|
|
7
|
+
* to the root's and the triggers' `handle` prop.
|
|
8
|
+
*
|
|
9
|
+
* The imperative methods only take effect while a root using this handle is
|
|
10
|
+
* mounted; calls made before one attaches (or after it unmounts) are ignored.
|
|
11
|
+
*/
|
|
12
|
+
// `Payload` is unused in the class body but load-bearing in the public API: a
|
|
13
|
+
// `Select.Root`'s `handle?: SelectHandle<Payload>` prop is what infers the
|
|
14
|
+
// payload type its `children(payload)` receives.
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
16
|
+
export class SelectHandle<Payload = unknown> extends BasePopupHandle<SelectStore, SelectStore> {
|
|
17
|
+
constructor() {
|
|
18
|
+
// `true`: a select popup is anchored to its trigger, so opening it by an
|
|
19
|
+
// unknown trigger id is an error rather than a warning — there would be
|
|
20
|
+
// nothing to anchor to.
|
|
21
|
+
super(new SelectStore(), 'Select', true);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Points the positioner at the trigger the popup was opened by. Without this
|
|
26
|
+
* an imperative open would anchor to whatever was last pressed.
|
|
27
|
+
*/
|
|
28
|
+
protected override associateTrigger(store: SelectStore, triggerNode: unknown) {
|
|
29
|
+
if (triggerNode !== undefined) {
|
|
30
|
+
store.set('triggerNode', triggerNode);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Opens the popup, anchored to the trigger with the given id.
|
|
36
|
+
*
|
|
37
|
+
* Call this from an event handler or an effect, never during rendering.
|
|
38
|
+
*
|
|
39
|
+
* @param triggerId The `nativeID` of a mounted `Select.Trigger` carrying this handle.
|
|
40
|
+
*/
|
|
41
|
+
open(triggerId: string) {
|
|
42
|
+
this.openByTrigger(triggerId);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Closes the popup.
|
|
47
|
+
*
|
|
48
|
+
* Call this from an event handler or an effect, never during rendering.
|
|
49
|
+
*/
|
|
50
|
+
close() {
|
|
51
|
+
this.closePopup();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Whether the popup is open. `false` while no root is attached.
|
|
56
|
+
*/
|
|
57
|
+
get isOpen() {
|
|
58
|
+
return this.attachedStore?.select('open') ?? false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Creates a handle that connects a `Select.Root` to `Select.Trigger`s rendered
|
|
64
|
+
* outside it, and controls it imperatively.
|
|
65
|
+
*/
|
|
66
|
+
export function createSelectHandle<Payload = unknown>(): SelectHandle<Payload> {
|
|
67
|
+
return new SelectHandle<Payload>();
|
|
68
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createSelector } from '../../store/createSelector';
|
|
2
2
|
import { ReactStore } from '../../store/ReactStore';
|
|
3
|
+
import { PopupTriggerMap } from '../../utils/popups/PopupTriggerMap';
|
|
3
4
|
import type { SelectRoot } from '../root/SelectRoot';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -101,6 +102,7 @@ export type State = {
|
|
|
101
102
|
disabled: boolean;
|
|
102
103
|
readOnly: boolean;
|
|
103
104
|
required: boolean;
|
|
105
|
+
disablePointerDismissal: boolean;
|
|
104
106
|
/**
|
|
105
107
|
* The anchor's native node, carried across the portal boundary.
|
|
106
108
|
*/
|
|
@@ -115,11 +117,33 @@ export type State = {
|
|
|
115
117
|
* The trigger's measured width, used to size the popup.
|
|
116
118
|
*/
|
|
117
119
|
triggerWidth: number | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* The trigger's measured height.
|
|
122
|
+
*/
|
|
123
|
+
triggerHeight: number | undefined;
|
|
124
|
+
/**
|
|
125
|
+
* The payload of the trigger the select was opened by, handed to the root's
|
|
126
|
+
* children when they are a function.
|
|
127
|
+
*/
|
|
128
|
+
payload: unknown;
|
|
129
|
+
/**
|
|
130
|
+
* The id of the trigger the select is associated with, or `null` for none.
|
|
131
|
+
*/
|
|
132
|
+
triggerId: string | null;
|
|
133
|
+
/**
|
|
134
|
+
* The controlled `triggerId` prop, when provided.
|
|
135
|
+
*/
|
|
136
|
+
triggerIdProp: string | null | undefined;
|
|
118
137
|
};
|
|
119
138
|
|
|
120
139
|
type Context = {
|
|
121
140
|
onValueChange: ((value: any, eventDetails: SelectRoot.ChangeEventDetails) => void) | undefined;
|
|
122
141
|
onOpenChange: ((open: boolean, eventDetails: SelectRoot.ChangeEventDetails) => void) | undefined;
|
|
142
|
+
/**
|
|
143
|
+
* Every trigger bound to this select, by id. A handle resolves `open(id)`
|
|
144
|
+
* through this, which is what lets a trigger rendered outside the root open it.
|
|
145
|
+
*/
|
|
146
|
+
triggerNodes: PopupTriggerMap;
|
|
123
147
|
};
|
|
124
148
|
|
|
125
149
|
const selectors = {
|
|
@@ -137,6 +161,10 @@ const selectors = {
|
|
|
137
161
|
labelId: createSelector((state: State) => state.labelId),
|
|
138
162
|
update: createSelector((state: State) => state.update),
|
|
139
163
|
triggerWidth: createSelector((state: State) => state.triggerWidth),
|
|
164
|
+
triggerHeight: createSelector((state: State) => state.triggerHeight),
|
|
165
|
+
disablePointerDismissal: createSelector((state: State) => state.disablePointerDismissal),
|
|
166
|
+
payload: createSelector((state: State) => state.payload),
|
|
167
|
+
triggerId: createSelector((state: State) => state.triggerIdProp ?? state.triggerId),
|
|
140
168
|
};
|
|
141
169
|
|
|
142
170
|
export class SelectStore extends ReactStore<Readonly<State>, Context, typeof selectors> {
|
|
@@ -153,13 +181,22 @@ export class SelectStore extends ReactStore<Readonly<State>, Context, typeof sel
|
|
|
153
181
|
disabled: false,
|
|
154
182
|
readOnly: false,
|
|
155
183
|
required: false,
|
|
184
|
+
disablePointerDismissal: false,
|
|
156
185
|
triggerNode: null,
|
|
157
186
|
labelId: undefined,
|
|
158
187
|
update: undefined,
|
|
159
188
|
triggerWidth: undefined,
|
|
189
|
+
triggerHeight: undefined,
|
|
190
|
+
payload: undefined,
|
|
191
|
+
triggerId: null,
|
|
192
|
+
triggerIdProp: undefined,
|
|
160
193
|
...initialState,
|
|
161
194
|
},
|
|
162
|
-
{
|
|
195
|
+
{
|
|
196
|
+
onValueChange: undefined,
|
|
197
|
+
onOpenChange: undefined,
|
|
198
|
+
triggerNodes: new PopupTriggerMap(),
|
|
199
|
+
},
|
|
163
200
|
selectors,
|
|
164
201
|
);
|
|
165
202
|
}
|