@navikt/ds-react 7.36.0 → 7.38.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/cjs/accordion/AccordionContent.js +1 -1
- package/cjs/accordion/AccordionContent.js.map +1 -1
- package/cjs/accordion/AccordionHeader.js +1 -1
- package/cjs/accordion/AccordionHeader.js.map +1 -1
- package/cjs/alert/base-alert/content/BaseAlertContent.js +1 -1
- package/cjs/alert/base-alert/content/BaseAlertContent.js.map +1 -1
- package/cjs/alert/base-alert/root/BaseAlertRoot.context.d.ts +3 -2
- package/cjs/alert/base-alert/root/BaseAlertRoot.context.js +2 -3
- package/cjs/alert/base-alert/root/BaseAlertRoot.context.js.map +1 -1
- package/cjs/chips/Removable.js +1 -1
- package/cjs/chips/Removable.js.map +1 -1
- package/cjs/chips/Toggle.js +1 -1
- package/cjs/chips/Toggle.js.map +1 -1
- package/cjs/collapsible/Collapsible.context.d.ts +3 -2
- package/cjs/collapsible/Collapsible.context.js +3 -3
- package/cjs/collapsible/Collapsible.context.js.map +1 -1
- package/cjs/copybutton/CopyButton.js +5 -5
- package/cjs/copybutton/CopyButton.js.map +1 -1
- package/cjs/date/Date.Dialog.js +5 -1
- package/cjs/date/Date.Dialog.js.map +1 -1
- package/cjs/date/Date.Input.d.ts +3 -2
- package/cjs/date/Date.Input.js +4 -3
- package/cjs/date/Date.Input.js.map +1 -1
- package/cjs/date/Date.locale.d.ts +3 -2
- package/cjs/date/Date.locale.js +4 -2
- package/cjs/date/Date.locale.js.map +1 -1
- package/cjs/date/datepicker/parts/DatePicker.DayButton.d.ts +1 -1
- package/cjs/date/datepicker/parts/DatePicker.DayButton.js +1 -1
- package/cjs/date/datepicker/parts/DatePicker.DayButton.js.map +1 -1
- package/cjs/date/monthpicker/MonthPicker.context.d.ts +1 -1
- package/cjs/date/monthpicker/MonthPicker.context.js +2 -2
- package/cjs/date/monthpicker/MonthPicker.context.js.map +1 -1
- package/cjs/date/monthpicker/MonthPicker.js +1 -2
- package/cjs/date/monthpicker/MonthPicker.js.map +1 -1
- package/cjs/dialog/backdrop/DialogBackdropInternal.d.ts +5 -0
- package/cjs/dialog/backdrop/DialogBackdropInternal.js +59 -0
- package/cjs/dialog/backdrop/DialogBackdropInternal.js.map +1 -0
- package/cjs/dialog/body/DialogBody.d.ts +18 -0
- package/cjs/{link/stories/RandomIcon.js → dialog/body/DialogBody.js} +33 -13
- package/cjs/dialog/body/DialogBody.js.map +1 -0
- package/cjs/dialog/close-trigger/DialogCloseTrigger.d.ts +20 -0
- package/cjs/dialog/close-trigger/DialogCloseTrigger.js +76 -0
- package/cjs/dialog/close-trigger/DialogCloseTrigger.js.map +1 -0
- package/cjs/dialog/description/DialogDescription.d.ts +19 -0
- package/cjs/dialog/description/DialogDescription.js +73 -0
- package/cjs/dialog/description/DialogDescription.js.map +1 -0
- package/cjs/dialog/footer/DialogFooter.d.ts +20 -0
- package/cjs/dialog/footer/DialogFooter.js +71 -0
- package/cjs/dialog/footer/DialogFooter.js.map +1 -0
- package/cjs/dialog/header/DialogHeader.d.ts +25 -0
- package/cjs/dialog/header/DialogHeader.js +77 -0
- package/cjs/dialog/header/DialogHeader.js.map +1 -0
- package/cjs/dialog/index.d.ts +18 -0
- package/cjs/dialog/index.js +26 -0
- package/cjs/dialog/index.js.map +1 -0
- package/cjs/dialog/popup/DialogPopup.d.ts +22 -0
- package/cjs/dialog/popup/DialogPopup.js +80 -0
- package/cjs/dialog/popup/DialogPopup.js.map +1 -0
- package/cjs/dialog/popup/DialogPopupInternal.d.ts +60 -0
- package/cjs/dialog/popup/DialogPopupInternal.js +166 -0
- package/cjs/dialog/popup/DialogPopupInternal.js.map +1 -0
- package/cjs/dialog/root/DialogRoot.context.d.ts +84 -0
- package/cjs/dialog/root/DialogRoot.context.js +11 -0
- package/cjs/dialog/root/DialogRoot.context.js.map +1 -0
- package/cjs/dialog/root/DialogRoot.d.ts +179 -0
- package/cjs/dialog/root/DialogRoot.js +134 -0
- package/cjs/dialog/root/DialogRoot.js.map +1 -0
- package/cjs/dialog/title/DialogTitle.d.ts +18 -0
- package/cjs/dialog/title/DialogTitle.js +80 -0
- package/cjs/dialog/title/DialogTitle.js.map +1 -0
- package/cjs/dialog/trigger/DialogTrigger.d.ts +20 -0
- package/cjs/dialog/trigger/DialogTrigger.js +71 -0
- package/cjs/dialog/trigger/DialogTrigger.js.map +1 -0
- package/cjs/expansion-card/ExpansionCardContent.js +1 -1
- package/cjs/expansion-card/ExpansionCardContent.js.map +1 -1
- package/cjs/form/checkbox/Checkbox.js +1 -1
- package/cjs/form/checkbox/Checkbox.js.map +1 -1
- package/cjs/form/combobox/Combobox.d.ts +1 -1
- package/cjs/form/combobox/ComboboxWrapper.js +3 -1
- package/cjs/form/combobox/ComboboxWrapper.js.map +1 -1
- package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +2 -4
- package/cjs/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +1 -1
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +2 -2
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
- package/cjs/form/combobox/Input/Input.context.d.ts +1 -1
- package/cjs/form/combobox/Input/Input.context.js +2 -2
- package/cjs/form/combobox/Input/Input.context.js.map +1 -1
- package/cjs/form/combobox/Input/InputController.d.ts +1 -1
- package/cjs/form/combobox/Input/InputController.js.map +1 -1
- package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +1 -1
- package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.js +4 -2
- package/cjs/form/combobox/SelectedOptions/selectedOptionsContext.js.map +1 -1
- package/cjs/form/combobox/customOptionsContext.d.ts +1 -1
- package/cjs/form/combobox/customOptionsContext.js +2 -2
- package/cjs/form/combobox/customOptionsContext.js.map +1 -1
- package/cjs/form/error-summary/ErrorSummary.js +3 -1
- package/cjs/form/error-summary/ErrorSummary.js.map +1 -1
- package/cjs/form/file-upload/FileUpload.context.d.ts +3 -2
- package/cjs/form/file-upload/FileUpload.context.js +4 -2
- package/cjs/form/file-upload/FileUpload.context.js.map +1 -1
- package/cjs/form/file-upload/parts/dropzone/Dropzone.js +2 -0
- package/cjs/form/file-upload/parts/dropzone/Dropzone.js.map +1 -1
- package/cjs/form/file-upload/useFileUpload.d.ts +1 -1
- package/cjs/form/radio/Radio.js +1 -1
- package/cjs/form/radio/Radio.js.map +1 -1
- package/cjs/form/search/Search.js +3 -2
- package/cjs/form/search/Search.js.map +1 -1
- package/cjs/guide-panel/GuidePanel.js +1 -1
- package/cjs/guide-panel/GuidePanel.js.map +1 -1
- package/cjs/help-text/HelpText.js +1 -1
- package/cjs/help-text/HelpText.js.map +1 -1
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +3 -1
- package/cjs/index.js.map +1 -1
- package/cjs/inline-message/root/InlineMessage.js +1 -1
- package/cjs/inline-message/root/InlineMessage.js.map +1 -1
- package/cjs/internal-header/InternalHeader.js +1 -1
- package/cjs/internal-header/InternalHeader.js.map +1 -1
- package/cjs/layout/base/BasePrimitive.js +1 -1
- package/cjs/layout/base/BasePrimitive.js.map +1 -1
- package/cjs/layout/base/PrimitiveAsChildProps.d.ts +1 -4
- package/cjs/layout/bleed/Bleed.js +1 -1
- package/cjs/layout/bleed/Bleed.js.map +1 -1
- package/cjs/layout/box/Box.js +1 -1
- package/cjs/layout/box/Box.js.map +1 -1
- package/cjs/layout/grid/HGrid.js +1 -1
- package/cjs/layout/grid/HGrid.js.map +1 -1
- package/cjs/layout/page/Page.js +1 -1
- package/cjs/layout/page/Page.js.map +1 -1
- package/cjs/layout/stack/Stack.js +1 -1
- package/cjs/layout/stack/Stack.js.map +1 -1
- package/cjs/link/Link.js +1 -1
- package/cjs/link/Link.js.map +1 -1
- package/cjs/link-card/LinkCard.js +2 -2
- package/cjs/link-card/LinkCard.js.map +1 -1
- package/cjs/list/List.js +1 -1
- package/cjs/list/List.js.map +1 -1
- package/cjs/modal/Modal.context.d.ts +4 -3
- package/cjs/modal/Modal.context.js +3 -3
- package/cjs/modal/Modal.context.js.map +1 -1
- package/cjs/modal/Modal.js +10 -3
- package/cjs/modal/Modal.js.map +1 -1
- package/cjs/overlays/action-menu/ActionMenu.js +9 -5
- package/cjs/overlays/action-menu/ActionMenu.js.map +1 -1
- package/cjs/overlays/dismissablelayer/DismissableLayer.d.ts +17 -4
- package/cjs/overlays/dismissablelayer/DismissableLayer.js +67 -19
- package/cjs/overlays/dismissablelayer/DismissableLayer.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/dispatchCustomEvent.d.ts +3 -2
- package/cjs/overlays/dismissablelayer/util/dispatchCustomEvent.js +1 -0
- package/cjs/overlays/dismissablelayer/util/dispatchCustomEvent.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/useEscapeKeydown.js +9 -4
- package/cjs/overlays/dismissablelayer/util/useEscapeKeydown.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/useFocusOutside.js +2 -2
- package/cjs/overlays/dismissablelayer/util/useFocusOutside.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.d.ts +2 -2
- package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.js +2 -2
- package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.js.map +1 -1
- package/cjs/overlays/dismissablelayer/util/usePointerUpOutside.d.ts +10 -0
- package/cjs/overlays/dismissablelayer/util/usePointerUpOutside.js +79 -0
- package/cjs/overlays/dismissablelayer/util/usePointerUpOutside.js.map +1 -0
- package/cjs/overlays/floating/Floating.d.ts +3 -2
- package/cjs/overlays/floating/Floating.js +9 -12
- package/cjs/overlays/floating/Floating.js.map +1 -1
- package/cjs/overlays/floating-menu/Menu.js +15 -19
- package/cjs/overlays/floating-menu/Menu.js.map +1 -1
- package/cjs/overlays/floating-menu/parts/RovingFocus.js +2 -1
- package/cjs/overlays/floating-menu/parts/RovingFocus.js.map +1 -1
- package/cjs/pagination/PaginationItem.js +1 -1
- package/cjs/pagination/PaginationItem.js.map +1 -1
- package/cjs/popover/Popover.js +1 -1
- package/cjs/popover/Popover.js.map +1 -1
- package/cjs/portal/Portal.js +1 -1
- package/cjs/portal/Portal.js.map +1 -1
- package/cjs/process/Process.js +2 -4
- package/cjs/process/Process.js.map +1 -1
- package/cjs/progress-bar/ProgressBar.js +4 -8
- package/cjs/progress-bar/ProgressBar.js.map +1 -1
- package/cjs/provider/Provider.d.ts +1 -5
- package/cjs/provider/Provider.js +0 -2
- package/cjs/provider/Provider.js.map +1 -1
- package/cjs/slot/Slot.js +12 -5
- package/cjs/slot/Slot.js.map +1 -1
- package/cjs/stepper/context.d.ts +3 -2
- package/cjs/stepper/context.js +3 -5
- package/cjs/stepper/context.js.map +1 -1
- package/cjs/tabs/Tabs.context.d.ts +5 -4
- package/cjs/tabs/Tabs.context.js +3 -5
- package/cjs/tabs/Tabs.context.js.map +1 -1
- package/cjs/tabs/parts/tab/useTab.d.ts +1 -1
- package/cjs/tabs/parts/tab/useTab.js +2 -1
- package/cjs/tabs/parts/tab/useTab.js.map +1 -1
- package/cjs/theme/Theme.d.ts +2 -2
- package/cjs/theme/Theme.js +4 -8
- package/cjs/theme/Theme.js.map +1 -1
- package/cjs/timeline/period/ClickablePeriod.js +1 -1
- package/cjs/timeline/period/ClickablePeriod.js.map +1 -1
- package/cjs/timeline/period/index.js +1 -1
- package/cjs/timeline/period/index.js.map +1 -1
- package/cjs/toggle-group/ToggleGroup.context.d.ts +5 -4
- package/cjs/toggle-group/ToggleGroup.context.js +3 -5
- package/cjs/toggle-group/ToggleGroup.context.js.map +1 -1
- package/cjs/toggle-group/ToggleGroup.js +1 -1
- package/cjs/toggle-group/ToggleGroup.js.map +1 -1
- package/cjs/toggle-group/parts/useToggleItem.d.ts +1 -1
- package/cjs/toggle-group/parts/useToggleItem.js +2 -1
- package/cjs/toggle-group/parts/useToggleItem.js.map +1 -1
- package/cjs/tooltip/Tooltip.js +3 -1
- package/cjs/tooltip/Tooltip.js.map +1 -1
- package/cjs/util/composition-warning/CompositionWarning.d.ts +3 -2
- package/cjs/util/composition-warning/CompositionWarning.js +3 -2
- package/cjs/util/composition-warning/CompositionWarning.js.map +1 -1
- package/cjs/util/create-strict-context.d.ts +40 -0
- package/cjs/util/{create-context.js → create-strict-context.js} +21 -19
- package/cjs/util/create-strict-context.js.map +1 -0
- package/cjs/util/focus-boundary/FocusBoundary.d.ts +1 -1
- package/cjs/util/focus-boundary/FocusBoundary.js +59 -16
- package/cjs/util/focus-boundary/FocusBoundary.js.map +1 -1
- package/cjs/util/hideNonTargetElements.js +2 -2
- package/cjs/util/hooks/descendants/useDescendant.d.ts +2 -2
- package/cjs/util/hooks/descendants/useDescendant.js +4 -3
- package/cjs/util/hooks/descendants/useDescendant.js.map +1 -1
- package/cjs/util/hooks/index.d.ts +0 -1
- package/cjs/util/hooks/index.js +1 -3
- package/cjs/util/hooks/index.js.map +1 -1
- package/{esm/overlays/overlay → cjs/util}/hooks/useAnimationsFinished.d.ts +1 -1
- package/cjs/{overlays/overlay → util}/hooks/useAnimationsFinished.js +7 -8
- package/cjs/util/hooks/useAnimationsFinished.js.map +1 -0
- package/cjs/util/hooks/useControllableState.js +4 -4
- package/cjs/util/hooks/useControllableState.js.map +1 -1
- package/cjs/util/hooks/useEventCallback.d.ts +2 -5
- package/cjs/util/hooks/useEventCallback.js +2 -3
- package/cjs/util/hooks/useEventCallback.js.map +1 -1
- package/cjs/util/hooks/useId.js +4 -1
- package/cjs/util/hooks/useId.js.map +1 -1
- package/cjs/util/hooks/useMergeRefs.d.ts +15 -9
- package/cjs/util/hooks/useMergeRefs.js +94 -28
- package/cjs/util/hooks/useMergeRefs.js.map +1 -1
- package/cjs/{overlays/overlay → util}/hooks/useOpenChangeAnimationComplete.js +3 -3
- package/cjs/util/hooks/useOpenChangeAnimationComplete.js.map +1 -0
- package/cjs/util/hooks/usePrevious.js.map +1 -1
- package/cjs/util/hooks/useScrollLock.js.map +1 -1
- package/cjs/{overlays/overlay → util}/hooks/useTransitionStatus.d.ts +6 -1
- package/cjs/{overlays/overlay → util}/hooks/useTransitionStatus.js +15 -4
- package/cjs/util/hooks/useTransitionStatus.js.map +1 -0
- package/cjs/util/hooks/useValueAsRef.d.ts +6 -0
- package/cjs/util/hooks/{useLatestRef.js → useValueAsRef.js} +3 -3
- package/cjs/util/hooks/useValueAsRef.js.map +1 -0
- package/cjs/util/link-anchor/LinkAnchor.js +2 -2
- package/cjs/util/link-anchor/LinkAnchor.js.map +1 -1
- package/cjs/util/resolveRef.d.ts +8 -0
- package/cjs/util/resolveRef.js +16 -0
- package/cjs/util/resolveRef.js.map +1 -0
- package/cjs/util/types/AsChildProps.d.ts +0 -4
- package/cjs/util/virtualfocus/Context.d.ts +5 -4
- package/cjs/util/virtualfocus/Context.js +4 -2
- package/cjs/util/virtualfocus/Context.js.map +1 -1
- package/esm/accordion/AccordionContent.js +1 -1
- package/esm/accordion/AccordionContent.js.map +1 -1
- package/esm/accordion/AccordionHeader.js +1 -1
- package/esm/accordion/AccordionHeader.js.map +1 -1
- package/esm/alert/base-alert/content/BaseAlertContent.js +1 -1
- package/esm/alert/base-alert/content/BaseAlertContent.js.map +1 -1
- package/esm/alert/base-alert/root/BaseAlertRoot.context.d.ts +3 -2
- package/esm/alert/base-alert/root/BaseAlertRoot.context.js +2 -3
- package/esm/alert/base-alert/root/BaseAlertRoot.context.js.map +1 -1
- package/esm/chips/Removable.js +1 -1
- package/esm/chips/Removable.js.map +1 -1
- package/esm/chips/Toggle.js +1 -1
- package/esm/chips/Toggle.js.map +1 -1
- package/esm/collapsible/Collapsible.context.d.ts +3 -2
- package/esm/collapsible/Collapsible.context.js +2 -2
- package/esm/collapsible/Collapsible.context.js.map +1 -1
- package/esm/copybutton/CopyButton.js +5 -5
- package/esm/copybutton/CopyButton.js.map +1 -1
- package/esm/date/Date.Dialog.js +5 -1
- package/esm/date/Date.Dialog.js.map +1 -1
- package/esm/date/Date.Input.d.ts +3 -2
- package/esm/date/Date.Input.js +3 -2
- package/esm/date/Date.Input.js.map +1 -1
- package/esm/date/Date.locale.d.ts +3 -2
- package/esm/date/Date.locale.js +4 -2
- package/esm/date/Date.locale.js.map +1 -1
- package/esm/date/datepicker/parts/DatePicker.DayButton.d.ts +1 -1
- package/esm/date/datepicker/parts/DatePicker.DayButton.js +1 -1
- package/esm/date/datepicker/parts/DatePicker.DayButton.js.map +1 -1
- package/esm/date/monthpicker/MonthPicker.context.d.ts +1 -1
- package/esm/date/monthpicker/MonthPicker.context.js +2 -2
- package/esm/date/monthpicker/MonthPicker.context.js.map +1 -1
- package/esm/date/monthpicker/MonthPicker.js +1 -2
- package/esm/date/monthpicker/MonthPicker.js.map +1 -1
- package/esm/dialog/backdrop/DialogBackdropInternal.d.ts +5 -0
- package/esm/dialog/backdrop/DialogBackdropInternal.js +23 -0
- package/esm/dialog/backdrop/DialogBackdropInternal.js.map +1 -0
- package/esm/dialog/body/DialogBody.d.ts +18 -0
- package/esm/dialog/body/DialogBody.js +33 -0
- package/esm/dialog/body/DialogBody.js.map +1 -0
- package/esm/dialog/close-trigger/DialogCloseTrigger.d.ts +20 -0
- package/esm/dialog/close-trigger/DialogCloseTrigger.js +40 -0
- package/esm/dialog/close-trigger/DialogCloseTrigger.js.map +1 -0
- package/esm/dialog/description/DialogDescription.d.ts +19 -0
- package/esm/dialog/description/DialogDescription.js +37 -0
- package/esm/dialog/description/DialogDescription.js.map +1 -0
- package/esm/dialog/footer/DialogFooter.d.ts +20 -0
- package/esm/dialog/footer/DialogFooter.js +35 -0
- package/esm/dialog/footer/DialogFooter.js.map +1 -0
- package/esm/dialog/header/DialogHeader.d.ts +25 -0
- package/esm/dialog/header/DialogHeader.js +41 -0
- package/esm/dialog/header/DialogHeader.js.map +1 -0
- package/esm/dialog/index.d.ts +18 -0
- package/esm/dialog/index.js +11 -0
- package/esm/dialog/index.js.map +1 -0
- package/esm/dialog/popup/DialogPopup.d.ts +22 -0
- package/esm/dialog/popup/DialogPopup.js +44 -0
- package/esm/dialog/popup/DialogPopup.js.map +1 -0
- package/esm/dialog/popup/DialogPopupInternal.d.ts +60 -0
- package/esm/dialog/popup/DialogPopupInternal.js +130 -0
- package/esm/dialog/popup/DialogPopupInternal.js.map +1 -0
- package/esm/dialog/root/DialogRoot.context.d.ts +84 -0
- package/esm/dialog/root/DialogRoot.context.js +7 -0
- package/esm/dialog/root/DialogRoot.context.js.map +1 -0
- package/esm/dialog/root/DialogRoot.d.ts +179 -0
- package/esm/dialog/root/DialogRoot.js +97 -0
- package/esm/dialog/root/DialogRoot.js.map +1 -0
- package/esm/dialog/title/DialogTitle.d.ts +18 -0
- package/esm/dialog/title/DialogTitle.js +44 -0
- package/esm/dialog/title/DialogTitle.js.map +1 -0
- package/esm/dialog/trigger/DialogTrigger.d.ts +20 -0
- package/esm/dialog/trigger/DialogTrigger.js +35 -0
- package/esm/dialog/trigger/DialogTrigger.js.map +1 -0
- package/esm/expansion-card/ExpansionCardContent.js +1 -1
- package/esm/expansion-card/ExpansionCardContent.js.map +1 -1
- package/esm/form/checkbox/Checkbox.js +1 -1
- package/esm/form/checkbox/Checkbox.js.map +1 -1
- package/esm/form/combobox/Combobox.d.ts +1 -1
- package/esm/form/combobox/ComboboxWrapper.js +3 -1
- package/esm/form/combobox/ComboboxWrapper.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js +2 -4
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +1 -1
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +2 -2
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
- package/esm/form/combobox/Input/Input.context.d.ts +1 -1
- package/esm/form/combobox/Input/Input.context.js +2 -2
- package/esm/form/combobox/Input/Input.context.js.map +1 -1
- package/esm/form/combobox/Input/InputController.d.ts +1 -1
- package/esm/form/combobox/Input/InputController.js.map +1 -1
- package/esm/form/combobox/SelectedOptions/selectedOptionsContext.d.ts +1 -1
- package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js +4 -2
- package/esm/form/combobox/SelectedOptions/selectedOptionsContext.js.map +1 -1
- package/esm/form/combobox/customOptionsContext.d.ts +1 -1
- package/esm/form/combobox/customOptionsContext.js +2 -2
- package/esm/form/combobox/customOptionsContext.js.map +1 -1
- package/esm/form/error-summary/ErrorSummary.js +3 -1
- package/esm/form/error-summary/ErrorSummary.js.map +1 -1
- package/esm/form/file-upload/FileUpload.context.d.ts +3 -2
- package/esm/form/file-upload/FileUpload.context.js +4 -2
- package/esm/form/file-upload/FileUpload.context.js.map +1 -1
- package/esm/form/file-upload/parts/dropzone/Dropzone.js +2 -0
- package/esm/form/file-upload/parts/dropzone/Dropzone.js.map +1 -1
- package/esm/form/file-upload/useFileUpload.d.ts +1 -1
- package/esm/form/radio/Radio.js +1 -1
- package/esm/form/radio/Radio.js.map +1 -1
- package/esm/form/search/Search.js +3 -2
- package/esm/form/search/Search.js.map +1 -1
- package/esm/guide-panel/GuidePanel.js +1 -1
- package/esm/guide-panel/GuidePanel.js.map +1 -1
- package/esm/help-text/HelpText.js +1 -1
- package/esm/help-text/HelpText.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/inline-message/root/InlineMessage.js +1 -1
- package/esm/inline-message/root/InlineMessage.js.map +1 -1
- package/esm/internal-header/InternalHeader.js +1 -1
- package/esm/internal-header/InternalHeader.js.map +1 -1
- package/esm/layout/base/BasePrimitive.js +1 -1
- package/esm/layout/base/BasePrimitive.js.map +1 -1
- package/esm/layout/base/PrimitiveAsChildProps.d.ts +1 -4
- package/esm/layout/bleed/Bleed.js +1 -1
- package/esm/layout/bleed/Bleed.js.map +1 -1
- package/esm/layout/box/Box.js +1 -1
- package/esm/layout/box/Box.js.map +1 -1
- package/esm/layout/grid/HGrid.js +1 -1
- package/esm/layout/grid/HGrid.js.map +1 -1
- package/esm/layout/page/Page.js +1 -1
- package/esm/layout/page/Page.js.map +1 -1
- package/esm/layout/stack/Stack.js +1 -1
- package/esm/layout/stack/Stack.js.map +1 -1
- package/esm/link/Link.js +1 -1
- package/esm/link/Link.js.map +1 -1
- package/esm/link-card/LinkCard.js +2 -2
- package/esm/link-card/LinkCard.js.map +1 -1
- package/esm/list/List.js +1 -1
- package/esm/list/List.js.map +1 -1
- package/esm/modal/Modal.context.d.ts +4 -3
- package/esm/modal/Modal.context.js +2 -2
- package/esm/modal/Modal.context.js.map +1 -1
- package/esm/modal/Modal.js +10 -3
- package/esm/modal/Modal.js.map +1 -1
- package/esm/overlays/action-menu/ActionMenu.js +9 -5
- package/esm/overlays/action-menu/ActionMenu.js.map +1 -1
- package/esm/overlays/dismissablelayer/DismissableLayer.d.ts +17 -4
- package/esm/overlays/dismissablelayer/DismissableLayer.js +68 -20
- package/esm/overlays/dismissablelayer/DismissableLayer.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/dispatchCustomEvent.d.ts +3 -2
- package/esm/overlays/dismissablelayer/util/dispatchCustomEvent.js +1 -0
- package/esm/overlays/dismissablelayer/util/dispatchCustomEvent.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/useEscapeKeydown.js +9 -4
- package/esm/overlays/dismissablelayer/util/useEscapeKeydown.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/useFocusOutside.js +2 -2
- package/esm/overlays/dismissablelayer/util/useFocusOutside.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/usePointerDownOutside.d.ts +2 -2
- package/esm/overlays/dismissablelayer/util/usePointerDownOutside.js +2 -2
- package/esm/overlays/dismissablelayer/util/usePointerDownOutside.js.map +1 -1
- package/esm/overlays/dismissablelayer/util/usePointerUpOutside.d.ts +10 -0
- package/esm/overlays/dismissablelayer/util/usePointerUpOutside.js +76 -0
- package/esm/overlays/dismissablelayer/util/usePointerUpOutside.js.map +1 -0
- package/esm/overlays/floating/Floating.d.ts +3 -2
- package/esm/overlays/floating/Floating.js +9 -12
- package/esm/overlays/floating/Floating.js.map +1 -1
- package/esm/overlays/floating-menu/Menu.js +16 -20
- package/esm/overlays/floating-menu/Menu.js.map +1 -1
- package/esm/overlays/floating-menu/parts/RovingFocus.js +3 -2
- package/esm/overlays/floating-menu/parts/RovingFocus.js.map +1 -1
- package/esm/pagination/PaginationItem.js +1 -1
- package/esm/pagination/PaginationItem.js.map +1 -1
- package/esm/popover/Popover.js +1 -1
- package/esm/popover/Popover.js.map +1 -1
- package/esm/portal/Portal.js +1 -1
- package/esm/portal/Portal.js.map +1 -1
- package/esm/process/Process.js +2 -4
- package/esm/process/Process.js.map +1 -1
- package/esm/progress-bar/ProgressBar.js +4 -8
- package/esm/progress-bar/ProgressBar.js.map +1 -1
- package/esm/provider/Provider.d.ts +1 -5
- package/esm/provider/Provider.js +0 -2
- package/esm/provider/Provider.js.map +1 -1
- package/esm/slot/Slot.js +12 -5
- package/esm/slot/Slot.js.map +1 -1
- package/esm/stepper/context.d.ts +3 -2
- package/esm/stepper/context.js +2 -4
- package/esm/stepper/context.js.map +1 -1
- package/esm/tabs/Tabs.context.d.ts +5 -4
- package/esm/tabs/Tabs.context.js +2 -4
- package/esm/tabs/Tabs.context.js.map +1 -1
- package/esm/tabs/parts/tab/useTab.d.ts +1 -1
- package/esm/tabs/parts/tab/useTab.js +3 -2
- package/esm/tabs/parts/tab/useTab.js.map +1 -1
- package/esm/theme/Theme.d.ts +2 -2
- package/esm/theme/Theme.js +4 -8
- package/esm/theme/Theme.js.map +1 -1
- package/esm/timeline/period/ClickablePeriod.js +1 -1
- package/esm/timeline/period/ClickablePeriod.js.map +1 -1
- package/esm/timeline/period/index.js +1 -1
- package/esm/timeline/period/index.js.map +1 -1
- package/esm/toggle-group/ToggleGroup.context.d.ts +5 -4
- package/esm/toggle-group/ToggleGroup.context.js +2 -4
- package/esm/toggle-group/ToggleGroup.context.js.map +1 -1
- package/esm/toggle-group/ToggleGroup.js +1 -1
- package/esm/toggle-group/ToggleGroup.js.map +1 -1
- package/esm/toggle-group/parts/useToggleItem.d.ts +1 -1
- package/esm/toggle-group/parts/useToggleItem.js +3 -2
- package/esm/toggle-group/parts/useToggleItem.js.map +1 -1
- package/esm/tooltip/Tooltip.js +3 -1
- package/esm/tooltip/Tooltip.js.map +1 -1
- package/esm/util/composition-warning/CompositionWarning.d.ts +3 -2
- package/esm/util/composition-warning/CompositionWarning.js +3 -2
- package/esm/util/composition-warning/CompositionWarning.js.map +1 -1
- package/esm/util/create-strict-context.d.ts +40 -0
- package/esm/util/{create-context.js → create-strict-context.js} +22 -19
- package/esm/util/create-strict-context.js.map +1 -0
- package/esm/util/focus-boundary/FocusBoundary.d.ts +1 -1
- package/esm/util/focus-boundary/FocusBoundary.js +57 -14
- package/esm/util/focus-boundary/FocusBoundary.js.map +1 -1
- package/esm/util/hideNonTargetElements.js +2 -2
- package/esm/util/hooks/descendants/useDescendant.d.ts +2 -2
- package/esm/util/hooks/descendants/useDescendant.js +5 -4
- package/esm/util/hooks/descendants/useDescendant.js.map +1 -1
- package/esm/util/hooks/index.d.ts +0 -1
- package/esm/util/hooks/index.js +0 -1
- package/esm/util/hooks/index.js.map +1 -1
- package/{cjs/overlays/overlay → esm/util}/hooks/useAnimationsFinished.d.ts +1 -1
- package/esm/{overlays/overlay → util}/hooks/useAnimationsFinished.js +7 -8
- package/esm/util/hooks/useAnimationsFinished.js.map +1 -0
- package/esm/util/hooks/useControllableState.js +4 -4
- package/esm/util/hooks/useControllableState.js.map +1 -1
- package/esm/util/hooks/useEventCallback.d.ts +2 -5
- package/esm/util/hooks/useEventCallback.js +4 -4
- package/esm/util/hooks/useEventCallback.js.map +1 -1
- package/esm/util/hooks/useId.js +4 -1
- package/esm/util/hooks/useId.js.map +1 -1
- package/esm/util/hooks/useMergeRefs.d.ts +15 -9
- package/esm/util/hooks/useMergeRefs.js +93 -24
- package/esm/util/hooks/useMergeRefs.js.map +1 -1
- package/esm/{overlays/overlay → util}/hooks/useOpenChangeAnimationComplete.js +3 -3
- package/esm/util/hooks/useOpenChangeAnimationComplete.js.map +1 -0
- package/esm/util/hooks/usePrevious.js.map +1 -1
- package/esm/util/hooks/useScrollLock.js.map +1 -1
- package/esm/{overlays/overlay → util}/hooks/useTransitionStatus.d.ts +6 -1
- package/esm/{overlays/overlay → util}/hooks/useTransitionStatus.js +12 -2
- package/esm/util/hooks/useTransitionStatus.js.map +1 -0
- package/esm/util/hooks/useValueAsRef.d.ts +6 -0
- package/esm/util/hooks/{useLatestRef.js → useValueAsRef.js} +3 -2
- package/esm/util/hooks/useValueAsRef.js.map +1 -0
- package/esm/util/link-anchor/LinkAnchor.js +2 -2
- package/esm/util/link-anchor/LinkAnchor.js.map +1 -1
- package/esm/util/resolveRef.d.ts +8 -0
- package/esm/util/resolveRef.js +14 -0
- package/esm/util/resolveRef.js.map +1 -0
- package/esm/util/types/AsChildProps.d.ts +0 -4
- package/esm/util/virtualfocus/Context.d.ts +5 -4
- package/esm/util/virtualfocus/Context.js +4 -2
- package/esm/util/virtualfocus/Context.js.map +1 -1
- package/package.json +13 -3
- package/src/accordion/AccordionContent.tsx +1 -1
- package/src/accordion/AccordionHeader.tsx +1 -1
- package/src/alert/base-alert/content/BaseAlertContent.tsx +1 -1
- package/src/alert/base-alert/root/BaseAlertRoot.context.tsx +5 -5
- package/src/chips/Removable.tsx +1 -1
- package/src/chips/Toggle.tsx +1 -1
- package/src/collapsible/Collapsible.context.tsx +9 -7
- package/src/copybutton/CopyButton.tsx +5 -5
- package/src/date/Date.Dialog.tsx +6 -1
- package/src/date/Date.Input.tsx +8 -5
- package/src/date/Date.locale.ts +7 -3
- package/src/date/datepicker/parts/DatePicker.DayButton.tsx +1 -1
- package/src/date/monthpicker/MonthPicker.context.tsx +9 -7
- package/src/date/monthpicker/MonthPicker.tsx +1 -2
- package/src/dialog/backdrop/DialogBackdropInternal.tsx +29 -0
- package/src/dialog/body/DialogBody.tsx +36 -0
- package/src/dialog/close-trigger/DialogCloseTrigger.tsx +51 -0
- package/src/dialog/description/DialogDescription.tsx +44 -0
- package/src/dialog/footer/DialogFooter.tsx +38 -0
- package/src/dialog/header/DialogHeader.tsx +62 -0
- package/src/dialog/index.ts +19 -0
- package/src/dialog/popup/DialogPopup.tsx +67 -0
- package/src/dialog/popup/DialogPopupInternal.tsx +285 -0
- package/src/dialog/root/DialogRoot.context.ts +89 -0
- package/src/dialog/root/DialogRoot.tsx +296 -0
- package/src/dialog/title/DialogTitle.tsx +52 -0
- package/src/dialog/trigger/DialogTrigger.tsx +47 -0
- package/src/expansion-card/ExpansionCardContent.tsx +1 -1
- package/src/form/checkbox/Checkbox.tsx +1 -1
- package/src/form/combobox/ComboboxWrapper.tsx +1 -0
- package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +1 -2
- package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +9 -7
- package/src/form/combobox/Input/Input.context.tsx +3 -3
- package/src/form/combobox/Input/InputController.tsx +1 -0
- package/src/form/combobox/SelectedOptions/selectedOptionsContext.tsx +7 -3
- package/src/form/combobox/customOptionsContext.tsx +9 -7
- package/src/form/error-summary/ErrorSummary.tsx +1 -0
- package/src/form/file-upload/FileUpload.context.tsx +7 -3
- package/src/form/file-upload/parts/dropzone/Dropzone.tsx +6 -4
- package/src/form/radio/Radio.tsx +1 -1
- package/src/form/search/Search.tsx +3 -2
- package/src/guide-panel/GuidePanel.tsx +1 -1
- package/src/help-text/HelpText.tsx +1 -1
- package/src/index.ts +12 -0
- package/src/inline-message/root/InlineMessage.tsx +2 -1
- package/src/internal-header/InternalHeader.tsx +1 -1
- package/src/layout/base/BasePrimitive.tsx +1 -1
- package/src/layout/base/PrimitiveAsChildProps.ts +1 -4
- package/src/layout/bleed/Bleed.tsx +1 -1
- package/src/layout/box/Box.tsx +1 -1
- package/src/layout/grid/HGrid.tsx +1 -1
- package/src/layout/page/Page.tsx +1 -1
- package/src/layout/stack/Stack.tsx +1 -1
- package/src/link/Link.tsx +1 -1
- package/src/link-card/LinkCard.tsx +3 -3
- package/src/list/List.tsx +1 -1
- package/src/modal/Modal.context.ts +4 -4
- package/src/modal/Modal.tsx +10 -2
- package/src/overlays/action-menu/ActionMenu.tsx +10 -7
- package/src/overlays/dismissablelayer/DismissableLayer.tsx +117 -29
- package/src/overlays/dismissablelayer/util/dispatchCustomEvent.ts +3 -2
- package/src/overlays/dismissablelayer/util/useEscapeKeydown.ts +9 -4
- package/src/overlays/dismissablelayer/util/useFocusOutside.ts +2 -2
- package/src/overlays/dismissablelayer/util/usePointerDownOutside.ts +4 -4
- package/src/overlays/dismissablelayer/util/usePointerUpOutside.ts +95 -0
- package/src/overlays/floating/Floating.tsx +15 -20
- package/src/overlays/floating-menu/Menu.tsx +25 -26
- package/src/overlays/floating-menu/parts/RovingFocus.tsx +3 -2
- package/src/pagination/PaginationItem.tsx +1 -1
- package/src/popover/Popover.tsx +1 -1
- package/src/portal/Portal.tsx +1 -1
- package/src/process/Process.tsx +3 -5
- package/src/progress-bar/ProgressBar.tsx +2 -4
- package/src/provider/Provider.tsx +1 -5
- package/src/slot/Slot.tsx +14 -9
- package/src/stepper/context.ts +8 -8
- package/src/tabs/Tabs.context.ts +7 -8
- package/src/tabs/parts/tab/useTab.ts +4 -2
- package/src/theme/Theme.tsx +15 -17
- package/src/timeline/period/ClickablePeriod.tsx +1 -1
- package/src/timeline/period/index.tsx +2 -1
- package/src/toggle-group/ToggleGroup.context.ts +8 -8
- package/src/toggle-group/ToggleGroup.tsx +1 -1
- package/src/toggle-group/parts/useToggleItem.ts +4 -2
- package/src/tooltip/Tooltip.tsx +3 -1
- package/src/util/__tests__/useMergeRefs.test.ts +92 -0
- package/src/util/composition-warning/CompositionWarning.tsx +4 -3
- package/src/util/create-strict-context.tsx +91 -0
- package/src/util/focus-boundary/FocusBoundary.tsx +76 -17
- package/src/util/hideNonTargetElements.ts +2 -2
- package/src/util/hooks/descendants/useDescendant.tsx +9 -6
- package/src/util/hooks/index.ts +0 -1
- package/src/{overlays/overlay → util}/hooks/useAnimationsFinished.ts +8 -9
- package/src/util/hooks/useControllableState.ts +10 -13
- package/src/util/hooks/useEventCallback.ts +5 -6
- package/src/util/hooks/useId.ts +6 -1
- package/src/util/hooks/useMergeRefs.ts +147 -22
- package/src/{overlays/overlay → util}/hooks/useOpenChangeAnimationComplete.ts +3 -3
- package/src/util/hooks/usePrevious.ts +1 -0
- package/src/util/hooks/useScrollLock.ts +0 -1
- package/src/{overlays/overlay → util}/hooks/useTransitionStatus.ts +14 -2
- package/src/util/hooks/{useLatestRef.ts → useValueAsRef.ts} +3 -1
- package/src/util/link-anchor/LinkAnchor.tsx +7 -5
- package/src/util/resolveRef.ts +20 -0
- package/src/util/types/AsChildProps.ts +0 -4
- package/src/util/virtualfocus/Context.tsx +8 -6
- package/cjs/link/stories/RandomIcon.d.ts +0 -2
- package/cjs/link/stories/RandomIcon.js.map +0 -1
- package/cjs/overlays/overlay/hooks/useAnimationsFinished.js.map +0 -1
- package/cjs/overlays/overlay/hooks/useOpenChangeAnimationComplete.js.map +0 -1
- package/cjs/overlays/overlay/hooks/useTransitionStatus.js.map +0 -1
- package/cjs/util/create-context.d.ts +0 -20
- package/cjs/util/create-context.js.map +0 -1
- package/cjs/util/hooks/useCallbackRef.d.ts +0 -6
- package/cjs/util/hooks/useCallbackRef.js +0 -18
- package/cjs/util/hooks/useCallbackRef.js.map +0 -1
- package/cjs/util/hooks/useLatestRef.d.ts +0 -5
- package/cjs/util/hooks/useLatestRef.js.map +0 -1
- package/esm/link/stories/RandomIcon.d.ts +0 -2
- package/esm/link/stories/RandomIcon.js +0 -9
- package/esm/link/stories/RandomIcon.js.map +0 -1
- package/esm/overlays/overlay/hooks/useAnimationsFinished.js.map +0 -1
- package/esm/overlays/overlay/hooks/useOpenChangeAnimationComplete.js.map +0 -1
- package/esm/overlays/overlay/hooks/useTransitionStatus.js.map +0 -1
- package/esm/util/create-context.d.ts +0 -20
- package/esm/util/create-context.js.map +0 -1
- package/esm/util/hooks/useCallbackRef.d.ts +0 -6
- package/esm/util/hooks/useCallbackRef.js +0 -15
- package/esm/util/hooks/useCallbackRef.js.map +0 -1
- package/esm/util/hooks/useLatestRef.d.ts +0 -5
- package/esm/util/hooks/useLatestRef.js.map +0 -1
- package/src/link/stories/RandomIcon.tsx +0 -10
- package/src/util/create-context.tsx +0 -79
- package/src/util/hooks/useCallbackRef.ts +0 -20
- /package/cjs/{overlays/overlay → util}/hooks/useOpenChangeAnimationComplete.d.ts +0 -0
- /package/esm/{overlays/overlay → util}/hooks/useOpenChangeAnimationComplete.d.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
2
|
import { composeEventHandlers } from "../../util/composeEventHandlers";
|
|
3
|
-
import {
|
|
3
|
+
import { useMergeRefs } from "../../util/hooks/useMergeRefs";
|
|
4
4
|
import {
|
|
5
5
|
useToggleGroupContext,
|
|
6
6
|
useToggleGroupDescendant,
|
|
@@ -96,8 +96,10 @@ export function useToggleItem<P extends UseToggleItemProps>(
|
|
|
96
96
|
[descendants, focusedValue, selectedValue, setFocusedValue],
|
|
97
97
|
);
|
|
98
98
|
|
|
99
|
+
const refs = useMergeRefs(register, ref);
|
|
100
|
+
|
|
99
101
|
return {
|
|
100
|
-
ref:
|
|
102
|
+
ref: refs,
|
|
101
103
|
isSelected,
|
|
102
104
|
isFocused: focusedValue === value,
|
|
103
105
|
onClick: composeEventHandlers(
|
package/src/tooltip/Tooltip.tsx
CHANGED
|
@@ -133,7 +133,9 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
|
|
|
133
133
|
|
|
134
134
|
const arrowRef = useRef<HTMLDivElement | null>(null);
|
|
135
135
|
const modalContext = useModalContext(false);
|
|
136
|
-
const rootElement = modalContext
|
|
136
|
+
const rootElement = modalContext
|
|
137
|
+
? modalContext.modalRef.current
|
|
138
|
+
: undefined;
|
|
137
139
|
|
|
138
140
|
const {
|
|
139
141
|
x,
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { renderHook } from "@testing-library/react";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { describe, expect, test, vi } from "vitest";
|
|
4
|
+
import { useMergeRefs } from "../hooks/useMergeRefs";
|
|
5
|
+
|
|
6
|
+
describe("useMergeRefs", () => {
|
|
7
|
+
test("returns null when all refs are null or undefined", () => {
|
|
8
|
+
const { result } = renderHook(() => useMergeRefs(null, undefined));
|
|
9
|
+
expect(result.current).toBeNull();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("assigns instance to object ref", () => {
|
|
13
|
+
const { result } = renderHook(() => {
|
|
14
|
+
const ref = useRef<HTMLDivElement | null>(null);
|
|
15
|
+
return { merged: useMergeRefs(ref, null), ref };
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const div = document.createElement("div");
|
|
19
|
+
result.current.merged?.(div);
|
|
20
|
+
|
|
21
|
+
expect(result.current.ref.current).toBe(div);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("calls function ref with instance", () => {
|
|
25
|
+
const fnRef = vi.fn();
|
|
26
|
+
const { result } = renderHook(() => useMergeRefs(fnRef, null));
|
|
27
|
+
|
|
28
|
+
const div = document.createElement("div");
|
|
29
|
+
result.current?.(div);
|
|
30
|
+
|
|
31
|
+
expect(fnRef).toHaveBeenCalledWith(div);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("handles mixed ref types", () => {
|
|
35
|
+
const fnRef = vi.fn();
|
|
36
|
+
const { result } = renderHook(() => {
|
|
37
|
+
const objRef = useRef<HTMLDivElement | null>(null);
|
|
38
|
+
return { merged: useMergeRefs(objRef, fnRef, null), objRef };
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const div = document.createElement("div");
|
|
42
|
+
result.current.merged?.(div);
|
|
43
|
+
|
|
44
|
+
expect(result.current.objRef.current).toBe(div);
|
|
45
|
+
expect(fnRef).toHaveBeenCalledWith(div);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("cleanup resets object ref to null", () => {
|
|
49
|
+
const { result } = renderHook(() => {
|
|
50
|
+
const ref = useRef<HTMLDivElement | null>(null);
|
|
51
|
+
return { merged: useMergeRefs(ref, null), ref };
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const div = document.createElement("div");
|
|
55
|
+
result.current.merged?.(div);
|
|
56
|
+
expect(result.current.ref.current).toBe(div);
|
|
57
|
+
|
|
58
|
+
result.current.merged?.(null);
|
|
59
|
+
expect(result.current.ref.current).toBeNull();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("cleanup calls returned cleanup function from callback ref", () => {
|
|
63
|
+
const cleanup = vi.fn();
|
|
64
|
+
const fnRef = vi.fn().mockReturnValue(cleanup);
|
|
65
|
+
const { result } = renderHook(() => useMergeRefs(fnRef, null));
|
|
66
|
+
|
|
67
|
+
const div1 = document.createElement("div");
|
|
68
|
+
result.current?.(div1);
|
|
69
|
+
|
|
70
|
+
const div2 = document.createElement("div");
|
|
71
|
+
result.current?.(div2);
|
|
72
|
+
|
|
73
|
+
expect(cleanup).toHaveBeenCalledTimes(1);
|
|
74
|
+
expect(fnRef).not.toHaveBeenCalledWith(null);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("runs previous cleanup before assigning new instance", () => {
|
|
78
|
+
const callOrder: string[] = [];
|
|
79
|
+
const cleanup = vi.fn(() => callOrder.push("cleanup"));
|
|
80
|
+
const fnRef = vi.fn(() => {
|
|
81
|
+
callOrder.push("ref");
|
|
82
|
+
return cleanup;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const { result } = renderHook(() => useMergeRefs(fnRef, null));
|
|
86
|
+
|
|
87
|
+
result.current?.(document.createElement("div"));
|
|
88
|
+
result.current?.(document.createElement("div"));
|
|
89
|
+
|
|
90
|
+
expect(callOrder).toEqual(["ref", "cleanup", "ref"]);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import React, { useEffect, useRef } from "react";
|
|
15
15
|
import { Slot } from "../../slot/Slot";
|
|
16
|
-
import {
|
|
16
|
+
import { createStrictContext } from "../create-strict-context";
|
|
17
17
|
|
|
18
18
|
type CompositionName = string;
|
|
19
19
|
|
|
@@ -26,8 +26,9 @@ type CompositionWarningContextType = {
|
|
|
26
26
|
name: CompositionName;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
|
|
29
|
+
const { Provider: CompositionWarning, useContext: useCompositionWarning } =
|
|
30
|
+
createStrictContext<CompositionWarningContextType>({
|
|
31
|
+
name: "CompositionWarningContext",
|
|
31
32
|
errorMessage:
|
|
32
33
|
"useCompositionWarning() must be used within <CompositionWarning />",
|
|
33
34
|
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom createStrictContext to consolidate context-implementation across the system.
|
|
3
|
+
* Unlike React's createContext, this throws an error by default when used outside a provider.
|
|
4
|
+
*
|
|
5
|
+
* Inspired by:
|
|
6
|
+
* - https://github.com/radix-ui/primitives/blob/main/packages/react/context/src/createContext.tsx
|
|
7
|
+
* - https://github.com/chakra-ui/chakra-ui/blob/5ec0be610b5a69afba01a9c22365155c1b519136/packages/hooks/context/src/index.ts
|
|
8
|
+
*/
|
|
9
|
+
import React, {
|
|
10
|
+
createContext as createReactContext,
|
|
11
|
+
useContext as useReactContext,
|
|
12
|
+
} from "react";
|
|
13
|
+
|
|
14
|
+
type ProviderProps<T> = T & { children: React.ReactNode; ref?: never };
|
|
15
|
+
|
|
16
|
+
function getErrorMessage(name: string) {
|
|
17
|
+
return `Aksel: use${name}Context returned \`undefined\`. Seems you forgot to wrap component within ${name}Provider`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* -----------------------------------------------------------------------------
|
|
21
|
+
* Overload signatures
|
|
22
|
+
* -------------------------------------------------------------------------- */
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* When defaultValue is provided, context is always defined.
|
|
26
|
+
* The hook will always return T (no strict parameter needed).
|
|
27
|
+
*/
|
|
28
|
+
function createStrictContext<T>(options: {
|
|
29
|
+
name: string;
|
|
30
|
+
errorMessage?: string;
|
|
31
|
+
defaultValue: T;
|
|
32
|
+
}): { Provider: React.FC<ProviderProps<T>>; useContext: () => T };
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* When no defaultValue is provided, context may be undefined.
|
|
36
|
+
* The hook accepts an optional `strict` parameter (default: true).
|
|
37
|
+
* - strict=true (default): throws if undefined, returns T
|
|
38
|
+
* - strict=false: returns T | undefined
|
|
39
|
+
*/
|
|
40
|
+
function createStrictContext<T>(options: {
|
|
41
|
+
name: string;
|
|
42
|
+
errorMessage?: string;
|
|
43
|
+
defaultValue?: undefined;
|
|
44
|
+
}): {
|
|
45
|
+
Provider: React.FC<ProviderProps<T>>;
|
|
46
|
+
useContext: <S extends boolean = true>(
|
|
47
|
+
strict?: S,
|
|
48
|
+
) => S extends true ? T : T | undefined;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/* -----------------------------------------------------------------------------
|
|
52
|
+
* Implementation
|
|
53
|
+
* -------------------------------------------------------------------------- */
|
|
54
|
+
|
|
55
|
+
function createStrictContext<T>(options: {
|
|
56
|
+
name: string;
|
|
57
|
+
errorMessage?: string;
|
|
58
|
+
defaultValue?: T;
|
|
59
|
+
}) {
|
|
60
|
+
const { name, defaultValue, errorMessage } = options;
|
|
61
|
+
const hasDefault = "defaultValue" in options;
|
|
62
|
+
|
|
63
|
+
const Context = createReactContext<T | undefined>(defaultValue);
|
|
64
|
+
Context.displayName = name;
|
|
65
|
+
|
|
66
|
+
function Provider({ children, ...context }: ProviderProps<T>) {
|
|
67
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: Object.values(context) includes all dependencies.
|
|
68
|
+
const value = React.useMemo(() => context, Object.values(context)) as T; // eslint-disable-line react-hooks/exhaustive-deps
|
|
69
|
+
|
|
70
|
+
return <Context.Provider value={value}>{children}</Context.Provider>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Provider.displayName = `${name}Provider`;
|
|
74
|
+
|
|
75
|
+
function useContext(strict = true) {
|
|
76
|
+
const context = useReactContext(Context);
|
|
77
|
+
|
|
78
|
+
if (!hasDefault && !context && strict) {
|
|
79
|
+
const error = new Error(errorMessage ?? getErrorMessage(name));
|
|
80
|
+
error.name = "ContextError";
|
|
81
|
+
Error.captureStackTrace?.(error, useContext);
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return context;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { Provider, useContext } as const;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { createStrictContext };
|
|
@@ -8,8 +8,9 @@ import React, {
|
|
|
8
8
|
import { Slot } from "../../slot/Slot";
|
|
9
9
|
import { useClientLayoutEffect, useMergeRefs } from "../../util/hooks";
|
|
10
10
|
import { hideNonTargetElements } from "../hideNonTargetElements";
|
|
11
|
-
import {
|
|
11
|
+
import { useValueAsRef } from "../hooks/useValueAsRef";
|
|
12
12
|
import { ownerDocument } from "../owner";
|
|
13
|
+
import { resolveRef } from "../resolveRef";
|
|
13
14
|
|
|
14
15
|
/* -------------------------------------------------------------------------- */
|
|
15
16
|
/* FocusBoundary */
|
|
@@ -59,7 +60,10 @@ interface FocusBoundaryProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
59
60
|
*
|
|
60
61
|
* Set to `false` to not focus anything.
|
|
61
62
|
*/
|
|
62
|
-
returnFocus?:
|
|
63
|
+
returnFocus?:
|
|
64
|
+
| boolean
|
|
65
|
+
| React.MutableRefObject<HTMLElement | null>
|
|
66
|
+
| (() => boolean | HTMLElement | null | undefined);
|
|
63
67
|
/**
|
|
64
68
|
* Hides all outside content from screen readers when true.
|
|
65
69
|
* @default false
|
|
@@ -79,8 +83,8 @@ const FocusBoundary = forwardRef<HTMLDivElement, FocusBoundaryProps>(
|
|
|
79
83
|
}: FocusBoundaryProps,
|
|
80
84
|
forwardedRef,
|
|
81
85
|
) => {
|
|
82
|
-
const initialFocusRef =
|
|
83
|
-
const returnFocusRef =
|
|
86
|
+
const initialFocusRef = useValueAsRef(initialFocus);
|
|
87
|
+
const returnFocusRef = useValueAsRef(returnFocus);
|
|
84
88
|
|
|
85
89
|
const lastFocusedElementRef = useRef<HTMLElement | null>(null);
|
|
86
90
|
const [container, setContainer] = useState<HTMLElement | null>(null);
|
|
@@ -121,7 +125,6 @@ const FocusBoundary = forwardRef<HTMLDivElement, FocusBoundaryProps>(
|
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
const relatedTarget = event.relatedTarget as HTMLElement | null;
|
|
124
|
-
|
|
125
128
|
/*
|
|
126
129
|
* `focusout` event with a `null` `relatedTarget` will happen in a few known cases:
|
|
127
130
|
* 1. When the user switches app/tabs/windows/the browser itself loses focus.
|
|
@@ -181,6 +184,11 @@ const FocusBoundary = forwardRef<HTMLDivElement, FocusBoundaryProps>(
|
|
|
181
184
|
return;
|
|
182
185
|
}
|
|
183
186
|
|
|
187
|
+
const ownerDoc = ownerDocument(container);
|
|
188
|
+
const activeElement = ownerDoc.activeElement;
|
|
189
|
+
const closestContainer = activeElement?.closest("[data-focus-boundary]");
|
|
190
|
+
|
|
191
|
+
addPreviouslyFocusedElement(ownerDoc.activeElement, closestContainer);
|
|
184
192
|
focusBoundarysStack.add(focusBoundary);
|
|
185
193
|
|
|
186
194
|
return () => {
|
|
@@ -190,6 +198,17 @@ const FocusBoundary = forwardRef<HTMLDivElement, FocusBoundaryProps>(
|
|
|
190
198
|
};
|
|
191
199
|
}, [container, focusBoundary]);
|
|
192
200
|
|
|
201
|
+
/**
|
|
202
|
+
* On unmount, we need to clean up previously focused elements associated with this container
|
|
203
|
+
* This makes sure we don't accidentally try to focus elements that are no longer relevant
|
|
204
|
+
* or will be removed from the DOM.
|
|
205
|
+
*/
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
return () => {
|
|
208
|
+
container && deleteContainerAndPreviouslyFocusedElements(container);
|
|
209
|
+
};
|
|
210
|
+
}, [container]);
|
|
211
|
+
|
|
193
212
|
useEffect(() => {
|
|
194
213
|
if (!container || !modal) {
|
|
195
214
|
return;
|
|
@@ -253,10 +272,14 @@ const FocusBoundary = forwardRef<HTMLDivElement, FocusBoundaryProps>(
|
|
|
253
272
|
return;
|
|
254
273
|
}
|
|
255
274
|
const ownerDoc = ownerDocument(container);
|
|
256
|
-
const previouslyFocusedElement = ownerDoc.activeElement;
|
|
257
275
|
|
|
258
276
|
function getReturnElement() {
|
|
259
|
-
|
|
277
|
+
const resolvedReturnFocusValueOrFn = returnFocusRef.current;
|
|
278
|
+
|
|
279
|
+
let resolvedReturnFocusValue =
|
|
280
|
+
typeof resolvedReturnFocusValueOrFn === "function"
|
|
281
|
+
? resolvedReturnFocusValueOrFn()
|
|
282
|
+
: resolvedReturnFocusValueOrFn;
|
|
260
283
|
|
|
261
284
|
if (
|
|
262
285
|
resolvedReturnFocusValue === undefined ||
|
|
@@ -271,11 +294,11 @@ const FocusBoundary = forwardRef<HTMLDivElement, FocusBoundaryProps>(
|
|
|
271
294
|
}
|
|
272
295
|
|
|
273
296
|
if (typeof resolvedReturnFocusValue === "boolean") {
|
|
274
|
-
const el =
|
|
297
|
+
const el = getPreviouslyFocusedElement();
|
|
275
298
|
return el?.isConnected ? el : ownerDoc.body;
|
|
276
299
|
}
|
|
277
300
|
|
|
278
|
-
const fallback =
|
|
301
|
+
const fallback = getPreviouslyFocusedElement() || ownerDoc.body;
|
|
279
302
|
|
|
280
303
|
return resolveRef(resolvedReturnFocusValue) || fallback;
|
|
281
304
|
}
|
|
@@ -354,6 +377,7 @@ const FocusBoundary = forwardRef<HTMLDivElement, FocusBoundaryProps>(
|
|
|
354
377
|
{...restProps}
|
|
355
378
|
ref={mergedRefs}
|
|
356
379
|
onKeyDown={handleKeyDown}
|
|
380
|
+
data-focus-boundary
|
|
357
381
|
/>
|
|
358
382
|
);
|
|
359
383
|
},
|
|
@@ -508,16 +532,51 @@ function removeLinks(items: HTMLElement[]) {
|
|
|
508
532
|
return items.filter((item) => item.tagName !== "A");
|
|
509
533
|
}
|
|
510
534
|
|
|
535
|
+
const LIST_LIMIT = 10;
|
|
536
|
+
let previouslyFocusedElements: Element[] = [];
|
|
537
|
+
const focusedElementsByContainer = new WeakMap<Element, Element[]>();
|
|
538
|
+
|
|
539
|
+
function clearDisconnectedPreviouslyFocusedElements() {
|
|
540
|
+
previouslyFocusedElements = previouslyFocusedElements.filter(
|
|
541
|
+
(el) => el.isConnected,
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
|
|
511
545
|
/**
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
* Non-generic to safely handle refs whose `.current` may be `null`.
|
|
546
|
+
* Removes "will be" unmounted elements from previouslyFocusedElements,
|
|
547
|
+
* and deletes the container from focusedElementsByContainer.
|
|
516
548
|
*/
|
|
517
|
-
function
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
549
|
+
function deleteContainerAndPreviouslyFocusedElements(container: HTMLElement) {
|
|
550
|
+
const nestedElements = focusedElementsByContainer.get(container) || [];
|
|
551
|
+
previouslyFocusedElements = previouslyFocusedElements.filter((el) => {
|
|
552
|
+
return !nestedElements.includes(el);
|
|
553
|
+
});
|
|
554
|
+
focusedElementsByContainer.delete(container);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function addPreviouslyFocusedElement(
|
|
558
|
+
element: Element | null,
|
|
559
|
+
container: Element | null | undefined,
|
|
560
|
+
) {
|
|
561
|
+
clearDisconnectedPreviouslyFocusedElements();
|
|
562
|
+
if (element && element?.nodeName !== "BODY") {
|
|
563
|
+
previouslyFocusedElements.push(element);
|
|
564
|
+
|
|
565
|
+
if (container) {
|
|
566
|
+
const nestedElements = focusedElementsByContainer.get(container) || [];
|
|
567
|
+
nestedElements.push(element);
|
|
568
|
+
focusedElementsByContainer.set(container, nestedElements);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if (previouslyFocusedElements.length > LIST_LIMIT) {
|
|
572
|
+
previouslyFocusedElements = previouslyFocusedElements.slice(-LIST_LIMIT);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function getPreviouslyFocusedElement() {
|
|
578
|
+
clearDisconnectedPreviouslyFocusedElements();
|
|
579
|
+
return previouslyFocusedElements[previouslyFocusedElements.length - 1];
|
|
521
580
|
}
|
|
522
581
|
|
|
523
582
|
export { FocusBoundary };
|
|
@@ -169,11 +169,11 @@ function hideNonTargetElements(avoidElements: Element[]): UndoFn {
|
|
|
169
169
|
* Assume that elements with `aria-live` or `script` tags should not be hidden.
|
|
170
170
|
* This ensures that live regions and scripts continue to function properly.
|
|
171
171
|
*/
|
|
172
|
-
const
|
|
172
|
+
const ignoredElements = Array.from(
|
|
173
173
|
body.querySelectorAll("[aria-live], script"),
|
|
174
174
|
);
|
|
175
175
|
|
|
176
|
-
return applyAttributeToOthers(avoidElements.concat(
|
|
176
|
+
return applyAttributeToOthers(avoidElements.concat(ignoredElements), body);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
export { hideNonTargetElements };
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* https://github.com/chakra-ui/chakra-ui/tree/5ec0be610b5a69afba01a9c22365155c1b519136/packages/components/descendant
|
|
3
3
|
*/
|
|
4
4
|
import React, { useRef, useState } from "react";
|
|
5
|
-
import {
|
|
5
|
+
import { createStrictContext } from "../../create-strict-context";
|
|
6
6
|
import { useClientLayoutEffect } from "../useClientLayoutEffect";
|
|
7
|
-
import {
|
|
7
|
+
import { useMergeRefs } from "../useMergeRefs";
|
|
8
8
|
import { DescendantOptions, DescendantsManager } from "./descendant";
|
|
9
9
|
import { cast } from "./utils";
|
|
10
10
|
|
|
@@ -15,9 +15,10 @@ export function createDescendantContext<
|
|
|
15
15
|
T extends HTMLElement = HTMLElement,
|
|
16
16
|
K extends Record<string, any> = object,
|
|
17
17
|
>() {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const {
|
|
19
|
+
Provider: DescendantsContextProvider,
|
|
20
|
+
useContext: useDescendantsContext,
|
|
21
|
+
} = createStrictContext<ReturnType<typeof useDescendants>>({
|
|
21
22
|
name: "DescendantsProvider",
|
|
22
23
|
errorMessage:
|
|
23
24
|
"useDescendantsContext must be used within DescendantsProvider",
|
|
@@ -65,11 +66,13 @@ export function createDescendantContext<
|
|
|
65
66
|
? cast<React.RefCallback<T>>(descendants.register(options))
|
|
66
67
|
: cast<React.RefCallback<T>>(descendants.register);
|
|
67
68
|
|
|
69
|
+
const refs = useMergeRefs(refCallback, ref);
|
|
70
|
+
|
|
68
71
|
return {
|
|
69
72
|
descendants,
|
|
70
73
|
index,
|
|
71
74
|
enabledIndex: descendants.enabledIndexOf(ref.current),
|
|
72
|
-
register:
|
|
75
|
+
register: refs,
|
|
73
76
|
};
|
|
74
77
|
}
|
|
75
78
|
|
package/src/util/hooks/index.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { useCallback, useEffect } from "react";
|
|
4
4
|
import ReactDOM from "react-dom";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveRef } from "../resolveRef";
|
|
6
|
+
import { useEventCallback } from "./useEventCallback";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Returns a stable function that, when invoked, waits for all current CSS/Web Animations
|
|
@@ -15,7 +16,7 @@ import { useEventCallback } from "../../../util/hooks/useEventCallback";
|
|
|
15
16
|
*
|
|
16
17
|
* Mechanics:
|
|
17
18
|
* 1. Resolves the concrete `HTMLElement` (direct element or from ref) – early no-op if missing.
|
|
18
|
-
* 2. If `getAnimations` is unsupported or animations are globally disabled (`
|
|
19
|
+
* 2. If `getAnimations` is unsupported or animations are globally disabled (`AKSEL_NO_EXIT_ANIMATIONS`),
|
|
19
20
|
* runs the callback immediately.
|
|
20
21
|
* 3. Schedules a frame so style/animation changes applied this render are committed.
|
|
21
22
|
* 4. Optionally schedules an additional frame (`waitForNextTick=true`) to catch animations that
|
|
@@ -66,12 +67,8 @@ export function useAnimationsFinished(
|
|
|
66
67
|
// Cancel any in-flight scheduling from a previous invocation (next-frame debounce semantics)
|
|
67
68
|
cancelScheduled();
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
70
|
+
const element = resolveRef(elementOrRef);
|
|
72
71
|
|
|
73
|
-
const element =
|
|
74
|
-
"current" in elementOrRef ? elementOrRef.current : elementOrRef;
|
|
75
72
|
if (element == null) {
|
|
76
73
|
return;
|
|
77
74
|
}
|
|
@@ -80,7 +77,7 @@ export function useAnimationsFinished(
|
|
|
80
77
|
if (
|
|
81
78
|
typeof element.getAnimations !== "function" ||
|
|
82
79
|
// Flag hook for test envs.
|
|
83
|
-
(globalThis as any).
|
|
80
|
+
(globalThis as any).AKSEL_NO_EXIT_ANIMATIONS
|
|
84
81
|
) {
|
|
85
82
|
fnToExecute();
|
|
86
83
|
return;
|
|
@@ -96,7 +93,9 @@ export function useAnimationsFinished(
|
|
|
96
93
|
Promise.allSettled(
|
|
97
94
|
element.getAnimations().map((anim) => anim.finished),
|
|
98
95
|
).then(() => {
|
|
99
|
-
if (signal?.aborted)
|
|
96
|
+
if (signal?.aborted) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
100
99
|
// Ensure any state updates inside the callback are flushed synchronously,
|
|
101
100
|
// guaranteeing that dependent logic observes the current
|
|
102
101
|
// tree rather than a stale in-progress update.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// https://github.com/chakra-ui/chakra-ui/tree/5ec0be610b5a69afba01a9c22365155c1b519136/packages/hooks/use-controllable-state
|
|
2
2
|
import { useState } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { useEventCallback } from "./useEventCallback";
|
|
4
4
|
|
|
5
5
|
export interface UseControllableStateProps<T> {
|
|
6
6
|
value?: T;
|
|
@@ -16,25 +16,22 @@ export function useControllableState<T>({
|
|
|
16
16
|
defaultValue,
|
|
17
17
|
onChange,
|
|
18
18
|
}: UseControllableStateProps<T>) {
|
|
19
|
-
const onChangeProp =
|
|
19
|
+
const onChangeProp = useEventCallback(onChange);
|
|
20
20
|
|
|
21
21
|
const [uncontrolledState, setUncontrolledState] = useState(defaultValue);
|
|
22
22
|
const controlled = valueProp !== undefined;
|
|
23
23
|
const value = controlled ? valueProp : uncontrolledState;
|
|
24
24
|
|
|
25
|
-
const setValue =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const nextValue = typeof next === "function" ? setter(value) : next;
|
|
25
|
+
const setValue = useEventCallback((next: React.SetStateAction<T>) => {
|
|
26
|
+
const setter = next as (prevState?: T) => T;
|
|
27
|
+
const nextValue = typeof next === "function" ? setter(value) : next;
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
if (!controlled) {
|
|
30
|
+
setUncontrolledState(nextValue);
|
|
31
|
+
}
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
[controlled, onChangeProp, value],
|
|
37
|
-
);
|
|
33
|
+
onChangeProp(nextValue);
|
|
34
|
+
});
|
|
38
35
|
|
|
39
36
|
return [value, setValue] as const;
|
|
40
37
|
}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Guarantees: stable identity; latest logic executed; no calls from uncommitted renders; dev
|
|
16
16
|
* error if invoked during render; safe when `callback` is undefined (no-op).
|
|
17
|
+
*
|
|
18
|
+
* This hook is a more permissive version of React 19.2's `React.useEffectEvent` in that it can be passed through contexts and called in event handler props, not just effects.
|
|
17
19
|
*/
|
|
18
20
|
import React, { useLayoutEffect } from "react";
|
|
19
21
|
import { useRefWithInit } from "./useRefWithInit";
|
|
@@ -42,12 +44,7 @@ type Stable<T extends Callback> = {
|
|
|
42
44
|
effect: () => void;
|
|
43
45
|
};
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
* TODO: Long term, replace `useCallbackRef` with this hook.
|
|
47
|
-
*/
|
|
48
|
-
export function useEventCallback<T extends Callback>(
|
|
49
|
-
callback: T | undefined,
|
|
50
|
-
): T {
|
|
47
|
+
function useEventCallback<T extends Callback>(callback: T | undefined): T {
|
|
51
48
|
const stable = useRefWithInit(createStableCallback).current as Stable<T>;
|
|
52
49
|
stable.next = callback;
|
|
53
50
|
useSafeInsertionEffect(stable.effect);
|
|
@@ -71,3 +68,5 @@ function assertNotCalled() {
|
|
|
71
68
|
throw new Error("Aksel: Cannot call an event handler while rendering.");
|
|
72
69
|
}
|
|
73
70
|
}
|
|
71
|
+
|
|
72
|
+
export { useEventCallback };
|
package/src/util/hooks/useId.ts
CHANGED
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
//https://github.com/mui/material-ui/blob/master/packages/mui-utils/src/useId.ts
|
|
4
4
|
import React, { useEffect, useState } from "react";
|
|
5
5
|
|
|
6
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
7
|
+
|
|
6
8
|
let globalId = 0;
|
|
7
9
|
function useGlobalId(idOverride?: string): string | undefined {
|
|
10
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: At runtime, `useGlobalId` is invariant.
|
|
8
11
|
const [defaultId, setDefaultId] = useState(idOverride);
|
|
9
12
|
const id = idOverride || defaultId;
|
|
13
|
+
|
|
14
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: At runtime, `useGlobalId` is invariant.
|
|
10
15
|
useEffect(() => {
|
|
11
16
|
if (defaultId == null) {
|
|
12
17
|
// Fallback to this default id when possible.
|
|
@@ -34,6 +39,6 @@ export function useId(idOverride?: string): string {
|
|
|
34
39
|
const reactId = maybeReactUseId();
|
|
35
40
|
return idOverride ?? reactId.replace(/(:)/g, "");
|
|
36
41
|
}
|
|
37
|
-
//
|
|
42
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: `useId` is invariant at runtime.
|
|
38
43
|
return useGlobalId(idOverride) ?? "";
|
|
39
44
|
}
|