@proyecto-viviana/solidaria 0.4.0 → 0.4.2
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/dist/_chunk/DragManager.js +627 -0
- package/dist/_chunk/DragManager.js.map +1 -0
- package/dist/_chunk/DragManager.jsx +627 -0
- package/dist/_chunk/DragManager.jsx.map +1 -0
- package/dist/_chunk/FocusScope.js +400 -0
- package/dist/_chunk/FocusScope.js.map +1 -0
- package/dist/_chunk/FocusScope.jsx +375 -0
- package/dist/_chunk/FocusScope.jsx.map +1 -0
- package/dist/_chunk/actiongroup.js +13 -79
- package/dist/_chunk/actiongroup.js.map +1 -1
- package/dist/_chunk/actiongroup.jsx +13 -79
- package/dist/_chunk/actiongroup.jsx.map +1 -1
- package/dist/_chunk/{live-announcer.js → announce.js} +1 -1
- package/dist/_chunk/announce.js.map +1 -0
- package/dist/_chunk/{live-announcer.jsx → announce.jsx} +1 -1
- package/dist/_chunk/announce.jsx.map +1 -0
- package/dist/_chunk/autocomplete.js +56 -8
- package/dist/_chunk/autocomplete.js.map +1 -1
- package/dist/_chunk/autocomplete.jsx +56 -8
- package/dist/_chunk/autocomplete.jsx.map +1 -1
- package/dist/_chunk/breadcrumbs.js +6 -4
- package/dist/_chunk/breadcrumbs.js.map +1 -1
- package/dist/_chunk/breadcrumbs.jsx +6 -4
- package/dist/_chunk/breadcrumbs.jsx.map +1 -1
- package/dist/_chunk/button.js +8 -9
- package/dist/_chunk/button.js.map +1 -1
- package/dist/_chunk/button.jsx +8 -9
- package/dist/_chunk/button.jsx.map +1 -1
- package/dist/_chunk/calendar.js +27 -26
- package/dist/_chunk/calendar.js.map +1 -1
- package/dist/_chunk/calendar.jsx +27 -26
- package/dist/_chunk/calendar.jsx.map +1 -1
- package/dist/_chunk/checkbox.js +5 -4
- package/dist/_chunk/checkbox.js.map +1 -1
- package/dist/_chunk/checkbox.jsx +5 -4
- package/dist/_chunk/checkbox.jsx.map +1 -1
- package/dist/_chunk/color.js +302 -18
- package/dist/_chunk/color.js.map +1 -1
- package/dist/_chunk/color.jsx +302 -18
- package/dist/_chunk/color.jsx.map +1 -1
- package/dist/_chunk/combobox.js +638 -12
- package/dist/_chunk/combobox.js.map +1 -1
- package/dist/_chunk/combobox.jsx +638 -12
- package/dist/_chunk/combobox.jsx.map +1 -1
- package/dist/_chunk/constants.js +19 -0
- package/dist/_chunk/constants.js.map +1 -0
- package/dist/_chunk/constants.jsx +19 -0
- package/dist/_chunk/constants.jsx.map +1 -0
- package/dist/_chunk/createCollator.js +3 -171
- package/dist/_chunk/createCollator.js.map +1 -1
- package/dist/_chunk/createCollator.jsx +3 -165
- package/dist/_chunk/createCollator.jsx.map +1 -1
- package/dist/_chunk/createField.js +2 -1
- package/dist/_chunk/createField.js.map +1 -1
- package/dist/_chunk/createField.jsx +2 -1
- package/dist/_chunk/createField.jsx.map +1 -1
- package/dist/_chunk/createFocus.js +12 -8
- package/dist/_chunk/createFocus.js.map +1 -1
- package/dist/_chunk/createFocus.jsx +12 -8
- package/dist/_chunk/createFocus.jsx.map +1 -1
- package/dist/_chunk/createFocusWithin.js +12 -13
- package/dist/_chunk/createFocusWithin.js.map +1 -1
- package/dist/_chunk/createFocusWithin.jsx +12 -13
- package/dist/_chunk/createFocusWithin.jsx.map +1 -1
- package/dist/_chunk/createFocusable.js +3 -3
- package/dist/_chunk/createFocusable.js.map +1 -1
- package/dist/_chunk/createFocusable.jsx +3 -3
- package/dist/_chunk/createFocusable.jsx.map +1 -1
- package/dist/_chunk/{form.js → createFormReset.js} +1 -1
- package/dist/_chunk/createFormReset.js.map +1 -0
- package/dist/_chunk/{form.jsx → createFormReset.jsx} +1 -1
- package/dist/_chunk/createFormReset.jsx.map +1 -0
- package/dist/_chunk/createHover.js +2 -1
- package/dist/_chunk/createHover.js.map +1 -1
- package/dist/_chunk/createHover.jsx +2 -1
- package/dist/_chunk/createHover.jsx.map +1 -1
- package/dist/_chunk/createInteractionModality.js +2 -3
- package/dist/_chunk/createInteractionModality.js.map +1 -1
- package/dist/_chunk/createInteractionModality.jsx +2 -3
- package/dist/_chunk/createInteractionModality.jsx.map +1 -1
- package/dist/_chunk/createLabel.js +2 -1
- package/dist/_chunk/createLabel.js.map +1 -1
- package/dist/_chunk/createLabel.jsx +2 -1
- package/dist/_chunk/createLabel.jsx.map +1 -1
- package/dist/_chunk/createLabels.js +3 -2
- package/dist/_chunk/createLabels.js.map +1 -1
- package/dist/_chunk/createLabels.jsx +3 -2
- package/dist/_chunk/createLabels.jsx.map +1 -1
- package/dist/_chunk/createLandmark.js +1 -1
- package/dist/_chunk/createLandmark.jsx +1 -1
- package/dist/_chunk/createProgressBar.js +2 -1
- package/dist/_chunk/createProgressBar.js.map +1 -1
- package/dist/_chunk/createProgressBar.jsx +2 -1
- package/dist/_chunk/createProgressBar.jsx.map +1 -1
- package/dist/_chunk/createSelectableItem.js +7 -3
- package/dist/_chunk/createSelectableItem.js.map +1 -1
- package/dist/_chunk/createSelectableItem.jsx +7 -3
- package/dist/_chunk/createSelectableItem.jsx.map +1 -1
- package/dist/_chunk/createStringFormatter.js +61 -0
- package/dist/_chunk/createStringFormatter.js.map +1 -0
- package/dist/_chunk/createStringFormatter.jsx +61 -0
- package/dist/_chunk/createStringFormatter.jsx.map +1 -0
- package/dist/_chunk/createToggle.js +5 -4
- package/dist/_chunk/createToggle.js.map +1 -1
- package/dist/_chunk/createToggle.jsx +5 -4
- package/dist/_chunk/createToggle.jsx.map +1 -1
- package/dist/_chunk/datepicker.js +1413 -1100
- package/dist/_chunk/datepicker.js.map +1 -1
- package/dist/_chunk/datepicker.jsx +1413 -1100
- package/dist/_chunk/datepicker.jsx.map +1 -1
- package/dist/_chunk/disclosure.js +2 -2
- package/dist/_chunk/disclosure.js.map +1 -1
- package/dist/_chunk/disclosure.jsx +2 -2
- package/dist/_chunk/disclosure.jsx.map +1 -1
- package/dist/_chunk/dnd.js +1586 -495
- package/dist/_chunk/dnd.js.map +1 -1
- package/dist/_chunk/dnd.jsx +1586 -495
- package/dist/_chunk/dnd.jsx.map +1 -1
- package/dist/_chunk/env.js +1 -19
- package/dist/_chunk/env.js.map +1 -1
- package/dist/_chunk/env.jsx +1 -19
- package/dist/_chunk/env.jsx.map +1 -1
- package/dist/_chunk/focus.js +1 -1
- package/dist/_chunk/focus.js.map +1 -1
- package/dist/_chunk/focus.jsx +1 -1
- package/dist/_chunk/focus.jsx.map +1 -1
- package/dist/_chunk/focus2.js +54 -318
- package/dist/_chunk/focus2.js.map +1 -1
- package/dist/_chunk/focus2.jsx +53 -292
- package/dist/_chunk/focus2.jsx.map +1 -1
- package/dist/_chunk/grid.js +1 -1
- package/dist/_chunk/grid.jsx +1 -1
- package/dist/_chunk/gridlist.js +14 -9
- package/dist/_chunk/gridlist.js.map +1 -1
- package/dist/_chunk/gridlist.jsx +14 -9
- package/dist/_chunk/gridlist.jsx.map +1 -1
- package/dist/_chunk/i18n.js +3 -58
- package/dist/_chunk/i18n.js.map +1 -1
- package/dist/_chunk/i18n.jsx +3 -58
- package/dist/_chunk/i18n.jsx.map +1 -1
- package/dist/_chunk/interactions.js +99 -9
- package/dist/_chunk/interactions.js.map +1 -1
- package/dist/_chunk/interactions.jsx +97 -9
- package/dist/_chunk/interactions.jsx.map +1 -1
- package/dist/_chunk/link.js +2 -1
- package/dist/_chunk/link.js.map +1 -1
- package/dist/_chunk/link.jsx +2 -1
- package/dist/_chunk/link.jsx.map +1 -1
- package/dist/_chunk/listbox.js +42 -10
- package/dist/_chunk/listbox.js.map +1 -1
- package/dist/_chunk/listbox.jsx +42 -10
- package/dist/_chunk/listbox.jsx.map +1 -1
- package/dist/_chunk/locale.js +173 -0
- package/dist/_chunk/locale.js.map +1 -0
- package/dist/_chunk/locale.jsx +167 -0
- package/dist/_chunk/locale.jsx.map +1 -0
- package/dist/_chunk/menu.js +5 -4
- package/dist/_chunk/menu.js.map +1 -1
- package/dist/_chunk/menu.jsx +5 -4
- package/dist/_chunk/menu.jsx.map +1 -1
- package/dist/_chunk/numberfield.js +3 -2
- package/dist/_chunk/numberfield.js.map +1 -1
- package/dist/_chunk/numberfield.jsx +3 -2
- package/dist/_chunk/numberfield.jsx.map +1 -1
- package/dist/_chunk/overlays.js +1 -1
- package/dist/_chunk/overlays.jsx +1 -1
- package/dist/_chunk/popover.js +3 -3
- package/dist/_chunk/popover.js.map +1 -1
- package/dist/_chunk/popover.jsx +3 -3
- package/dist/_chunk/popover.jsx.map +1 -1
- package/dist/_chunk/radio.js +7 -6
- package/dist/_chunk/radio.js.map +1 -1
- package/dist/_chunk/radio.jsx +7 -6
- package/dist/_chunk/radio.jsx.map +1 -1
- package/dist/_chunk/reactivity.js +21 -0
- package/dist/_chunk/reactivity.js.map +1 -0
- package/dist/_chunk/reactivity.jsx +21 -0
- package/dist/_chunk/reactivity.jsx.map +1 -0
- package/dist/_chunk/searchfield.js +2 -1
- package/dist/_chunk/searchfield.js.map +1 -1
- package/dist/_chunk/searchfield.jsx +2 -1
- package/dist/_chunk/searchfield.jsx.map +1 -1
- package/dist/_chunk/select.js +8 -5
- package/dist/_chunk/select.js.map +1 -1
- package/dist/_chunk/select.jsx +8 -5
- package/dist/_chunk/select.jsx.map +1 -1
- package/dist/_chunk/selection.js +8 -21
- package/dist/_chunk/selection.js.map +1 -1
- package/dist/_chunk/selection.jsx +8 -21
- package/dist/_chunk/selection.jsx.map +1 -1
- package/dist/_chunk/separator.js +1 -1
- package/dist/_chunk/separator.jsx +1 -1
- package/dist/_chunk/slider.js +5 -4
- package/dist/_chunk/slider.js.map +1 -1
- package/dist/_chunk/slider.jsx +5 -4
- package/dist/_chunk/slider.jsx.map +1 -1
- package/dist/_chunk/spinbutton.js +153 -0
- package/dist/_chunk/spinbutton.js.map +1 -0
- package/dist/_chunk/spinbutton.jsx +153 -0
- package/dist/_chunk/spinbutton.jsx.map +1 -0
- package/dist/_chunk/table.js +45 -8
- package/dist/_chunk/table.js.map +1 -1
- package/dist/_chunk/table.jsx +45 -8
- package/dist/_chunk/table.jsx.map +1 -1
- package/dist/_chunk/tabs.js +11 -8
- package/dist/_chunk/tabs.js.map +1 -1
- package/dist/_chunk/tabs.jsx +11 -8
- package/dist/_chunk/tabs.jsx.map +1 -1
- package/dist/_chunk/tag.js +54 -18
- package/dist/_chunk/tag.js.map +1 -1
- package/dist/_chunk/tag.jsx +54 -18
- package/dist/_chunk/tag.jsx.map +1 -1
- package/dist/_chunk/textfield.js +2 -1
- package/dist/_chunk/textfield.js.map +1 -1
- package/dist/_chunk/textfield.jsx +2 -1
- package/dist/_chunk/textfield.jsx.map +1 -1
- package/dist/_chunk/toolbar.js +4 -36
- package/dist/_chunk/toolbar.js.map +1 -1
- package/dist/_chunk/toolbar.jsx +4 -36
- package/dist/_chunk/toolbar.jsx.map +1 -1
- package/dist/_chunk/tooltip.js +2 -2
- package/dist/_chunk/tooltip.js.map +1 -1
- package/dist/_chunk/tooltip.jsx +2 -2
- package/dist/_chunk/tooltip.jsx.map +1 -1
- package/dist/_chunk/tree.js +42 -14
- package/dist/_chunk/tree.js.map +1 -1
- package/dist/_chunk/tree.jsx +42 -14
- package/dist/_chunk/tree.jsx.map +1 -1
- package/dist/_chunk/utils.js +59 -19
- package/dist/_chunk/utils.js.map +1 -1
- package/dist/_chunk/utils.jsx +59 -19
- package/dist/_chunk/utils.jsx.map +1 -1
- package/dist/_chunk/visually-hidden.js +3 -2
- package/dist/_chunk/visually-hidden.js.map +1 -1
- package/dist/_chunk/visually-hidden.jsx +3 -2
- package/dist/_chunk/visually-hidden.jsx.map +1 -1
- package/dist/actiongroup/createActionGroup.d.ts.map +1 -1
- package/dist/autocomplete/createAutocomplete.d.ts +10 -7
- package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
- package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
- package/dist/button/createToggleButtonGroup.d.ts.map +1 -1
- package/dist/calendar/createCalendar.d.ts.map +1 -1
- package/dist/calendar/createCalendarCell.d.ts.map +1 -1
- package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
- package/dist/calendar/createRangeCalendar.d.ts.map +1 -1
- package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
- package/dist/calendar/intl/index.d.ts +1 -1
- package/dist/calendar/intl/index.d.ts.map +1 -1
- package/dist/collections/index.js +1 -1
- package/dist/collections/index.jsx +1 -1
- package/dist/color/createColorArea.d.ts.map +1 -1
- package/dist/color/createColorField.d.ts.map +1 -1
- package/dist/color/createColorSlider.d.ts.map +1 -1
- package/dist/color/createColorSwatch.d.ts.map +1 -1
- package/dist/color/createColorWheel.d.ts.map +1 -1
- package/dist/color/intl/index.d.ts +30 -0
- package/dist/color/intl/index.d.ts.map +1 -0
- package/dist/combobox/createComboBox.d.ts.map +1 -1
- package/dist/combobox/intl/generated-locales.d.ts +16 -0
- package/dist/combobox/intl/generated-locales.d.ts.map +1 -0
- package/dist/combobox/intl/index.d.ts +2 -2
- package/dist/combobox/intl/index.d.ts.map +1 -1
- package/dist/datepicker/createDateField.d.ts +45 -23
- package/dist/datepicker/createDateField.d.ts.map +1 -1
- package/dist/datepicker/createDatePicker.d.ts +34 -6
- package/dist/datepicker/createDatePicker.d.ts.map +1 -1
- package/dist/datepicker/createDatePickerGroup.d.ts +13 -13
- package/dist/datepicker/createDatePickerGroup.d.ts.map +1 -1
- package/dist/datepicker/createDateRangePicker.d.ts +55 -7
- package/dist/datepicker/createDateRangePicker.d.ts.map +1 -1
- package/dist/datepicker/createDateSegment.d.ts +6 -15
- package/dist/datepicker/createDateSegment.d.ts.map +1 -1
- package/dist/datepicker/createDisplayNames.d.ts +17 -0
- package/dist/datepicker/createDisplayNames.d.ts.map +1 -0
- package/dist/datepicker/createTimeField.d.ts +12 -49
- package/dist/datepicker/createTimeField.d.ts.map +1 -1
- package/dist/datepicker/index.d.ts +3 -3
- package/dist/datepicker/index.d.ts.map +1 -1
- package/dist/datepicker/index.js +2 -2
- package/dist/datepicker/index.jsx +2 -2
- package/dist/datepicker/intl.d.ts +12 -0
- package/dist/datepicker/intl.d.ts.map +1 -0
- package/dist/dnd/DragManager.d.ts +86 -0
- package/dist/dnd/DragManager.d.ts.map +1 -0
- package/dist/dnd/DropTargetKeyboardNavigation.d.ts +42 -0
- package/dist/dnd/DropTargetKeyboardNavigation.d.ts.map +1 -0
- package/dist/dnd/createDrag.d.ts.map +1 -1
- package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
- package/dist/dnd/createDraggableItem.d.ts +12 -7
- package/dist/dnd/createDraggableItem.d.ts.map +1 -1
- package/dist/dnd/createDroppableCollection.d.ts +7 -15
- package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
- package/dist/dnd/index.d.ts +5 -1
- package/dist/dnd/index.d.ts.map +1 -1
- package/dist/dnd/index.js +3 -2
- package/dist/dnd/index.jsx +3 -2
- package/dist/dnd/intl/index.d.ts +39 -0
- package/dist/dnd/intl/index.d.ts.map +1 -0
- package/dist/dnd/utils.d.ts +5 -0
- package/dist/dnd/utils.d.ts.map +1 -1
- package/dist/focus/FocusScope.d.ts +7 -0
- package/dist/focus/FocusScope.d.ts.map +1 -1
- package/dist/focus/index.d.ts +2 -1
- package/dist/focus/index.d.ts.map +1 -1
- package/dist/focus/index.js +3 -2
- package/dist/focus/index.jsx +3 -2
- package/dist/focus/virtualFocus.d.ts +26 -0
- package/dist/focus/virtualFocus.d.ts.map +1 -0
- package/dist/form/index.js +1 -1
- package/dist/form/index.jsx +1 -1
- package/dist/gridlist/createGridList.d.ts.map +1 -1
- package/dist/i18n/index.js +4 -2
- package/dist/i18n/index.jsx +4 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -12
- package/dist/index.jsx +18 -12
- package/dist/interactions/FocusableProvider.d.ts.map +1 -1
- package/dist/interactions/createFocus.d.ts.map +1 -1
- package/dist/interactions/createFocusWithin.d.ts.map +1 -1
- package/dist/interactions/createInteractionModality.d.ts.map +1 -1
- package/dist/interactions/index.js +1 -2
- package/dist/interactions/index.jsx +1 -2
- package/dist/label/createLabels.d.ts.map +1 -1
- package/dist/listbox/createListBox.d.ts.map +1 -1
- package/dist/listbox/createOption.d.ts +1 -1
- package/dist/listbox/createOption.d.ts.map +1 -1
- package/dist/live-announcer/index.js +1 -1
- package/dist/live-announcer/index.jsx +1 -1
- package/dist/select/createSelect.d.ts +2 -0
- package/dist/select/createSelect.d.ts.map +1 -1
- package/dist/selection/createSelectableItem.d.ts.map +1 -1
- package/dist/selection/index.js +2 -1
- package/dist/selection/index.jsx +2 -1
- package/dist/spinbutton/createSpinButton.d.ts +41 -0
- package/dist/spinbutton/createSpinButton.d.ts.map +1 -0
- package/dist/spinbutton/index.d.ts +3 -0
- package/dist/spinbutton/index.d.ts.map +1 -0
- package/dist/spinbutton/index.js +2 -0
- package/dist/spinbutton/index.jsx +2 -0
- package/dist/spinbutton/intl.d.ts +5 -0
- package/dist/spinbutton/intl.d.ts.map +1 -0
- package/dist/table/createTable.d.ts.map +1 -1
- package/dist/table/createTableColumnHeader.d.ts.map +1 -1
- package/dist/table/createTableRow.d.ts.map +1 -1
- package/dist/table/createTableSelectionCheckbox.d.ts.map +1 -1
- package/dist/table/types.d.ts +8 -0
- package/dist/table/types.d.ts.map +1 -1
- package/dist/table/utils.d.ts +15 -0
- package/dist/table/utils.d.ts.map +1 -0
- package/dist/tabs/createTabs.d.ts +1 -0
- package/dist/tabs/createTabs.d.ts.map +1 -1
- package/dist/tag/createTag.d.ts.map +1 -1
- package/dist/tag/createTagGroup.d.ts +7 -0
- package/dist/tag/createTagGroup.d.ts.map +1 -1
- package/dist/toolbar/createToolbar.d.ts.map +1 -1
- package/dist/tree/createTree.d.ts.map +1 -1
- package/dist/tree/createTreeSelectionCheckbox.d.ts.map +1 -1
- package/dist/utils/animation.d.ts.map +1 -1
- package/dist/utils/dom.d.ts +1 -0
- package/dist/utils/dom.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -3
- package/dist/utils/index.jsx +4 -3
- package/package.json +2 -2
- package/src/actiongroup/createActionGroup.ts +26 -109
- package/src/autocomplete/createAutocomplete.ts +136 -15
- package/src/breadcrumbs/createBreadcrumbs.ts +12 -4
- package/src/button/createToggleButtonGroup.ts +19 -14
- package/src/calendar/createCalendar.ts +3 -4
- package/src/calendar/createCalendarCell.ts +17 -3
- package/src/calendar/createCalendarGrid.ts +5 -4
- package/src/calendar/createRangeCalendar.ts +27 -17
- package/src/calendar/createRangeCalendarCell.ts +17 -3
- package/src/calendar/intl/index.ts +8 -0
- package/src/color/createColorArea.ts +17 -10
- package/src/color/createColorField.ts +8 -1
- package/src/color/createColorSlider.ts +1 -2
- package/src/color/createColorSwatch.ts +4 -2
- package/src/color/createColorWheel.ts +0 -6
- package/src/color/intl/index.ts +316 -0
- package/src/combobox/createComboBox.ts +35 -4
- package/src/combobox/intl/generated-locales.ts +635 -0
- package/src/combobox/intl/index.ts +8 -2
- package/src/datepicker/createDateField.ts +228 -213
- package/src/datepicker/createDatePicker.ts +157 -146
- package/src/datepicker/createDatePickerGroup.ts +88 -82
- package/src/datepicker/createDateRangePicker.ts +230 -179
- package/src/datepicker/createDateSegment.ts +386 -389
- package/src/datepicker/createDisplayNames.ts +45 -0
- package/src/datepicker/createTimeField.ts +36 -129
- package/src/datepicker/index.ts +13 -14
- package/src/datepicker/intl.ts +633 -0
- package/src/dnd/DragManager.ts +693 -0
- package/src/dnd/DropTargetKeyboardNavigation.ts +337 -0
- package/src/dnd/createDrag.ts +31 -5
- package/src/dnd/createDraggableCollection.ts +33 -15
- package/src/dnd/createDraggableItem.ts +92 -5
- package/src/dnd/createDroppableCollection.ts +487 -373
- package/src/dnd/index.ts +11 -0
- package/src/dnd/intl/ar-AE.json +29 -0
- package/src/dnd/intl/bg-BG.json +29 -0
- package/src/dnd/intl/cs-CZ.json +29 -0
- package/src/dnd/intl/da-DK.json +29 -0
- package/src/dnd/intl/de-DE.json +29 -0
- package/src/dnd/intl/el-GR.json +29 -0
- package/src/dnd/intl/en-US.json +29 -0
- package/src/dnd/intl/es-ES.json +29 -0
- package/src/dnd/intl/et-EE.json +29 -0
- package/src/dnd/intl/fi-FI.json +29 -0
- package/src/dnd/intl/fr-FR.json +29 -0
- package/src/dnd/intl/he-IL.json +29 -0
- package/src/dnd/intl/hr-HR.json +29 -0
- package/src/dnd/intl/hu-HU.json +29 -0
- package/src/dnd/intl/index.ts +139 -0
- package/src/dnd/intl/it-IT.json +29 -0
- package/src/dnd/intl/ja-JP.json +29 -0
- package/src/dnd/intl/ko-KR.json +29 -0
- package/src/dnd/intl/lt-LT.json +29 -0
- package/src/dnd/intl/lv-LV.json +29 -0
- package/src/dnd/intl/nb-NO.json +29 -0
- package/src/dnd/intl/nl-NL.json +29 -0
- package/src/dnd/intl/pl-PL.json +29 -0
- package/src/dnd/intl/pt-BR.json +29 -0
- package/src/dnd/intl/pt-PT.json +29 -0
- package/src/dnd/intl/ro-RO.json +29 -0
- package/src/dnd/intl/ru-RU.json +29 -0
- package/src/dnd/intl/sk-SK.json +29 -0
- package/src/dnd/intl/sl-SI.json +29 -0
- package/src/dnd/intl/sr-SP.json +29 -0
- package/src/dnd/intl/sv-SE.json +29 -0
- package/src/dnd/intl/tr-TR.json +29 -0
- package/src/dnd/intl/uk-UA.json +29 -0
- package/src/dnd/intl/zh-CN.json +29 -0
- package/src/dnd/intl/zh-TW.json +29 -0
- package/src/dnd/utils.ts +36 -0
- package/src/focus/FocusScope.tsx +120 -12
- package/src/focus/index.ts +8 -0
- package/src/focus/virtualFocus.ts +55 -0
- package/src/gridlist/createGridList.ts +52 -16
- package/src/index.ts +11 -3
- package/src/interactions/FocusableProvider.tsx +11 -6
- package/src/interactions/createFocus.ts +26 -21
- package/src/interactions/createFocusWithin.ts +23 -24
- package/src/interactions/createInteractionModality.ts +5 -3
- package/src/label/createLabels.ts +7 -4
- package/src/listbox/createListBox.ts +74 -2
- package/src/listbox/createOption.ts +16 -1
- package/src/select/createSelect.ts +23 -2
- package/src/selection/createSelectableItem.ts +14 -0
- package/src/spinbutton/createSpinButton.ts +163 -0
- package/src/spinbutton/index.ts +10 -0
- package/src/spinbutton/intl.ts +115 -0
- package/src/table/createTable.ts +26 -1
- package/src/table/createTableColumnHeader.ts +10 -0
- package/src/table/createTableRow.ts +10 -0
- package/src/table/createTableSelectionCheckbox.ts +24 -1
- package/src/table/types.ts +8 -0
- package/src/table/utils.ts +41 -0
- package/src/tabs/createTabs.ts +53 -12
- package/src/tag/createTag.ts +21 -32
- package/src/tag/createTagGroup.ts +92 -0
- package/src/toolbar/createToolbar.ts +6 -58
- package/src/tree/createTree.ts +69 -14
- package/src/tree/createTreeSelectionCheckbox.ts +14 -1
- package/src/utils/animation.ts +119 -27
- package/src/utils/dom.ts +3 -2
- package/src/utils/index.ts +2 -0
- package/dist/_chunk/createLongPress.js +0 -91
- package/dist/_chunk/createLongPress.js.map +0 -1
- package/dist/_chunk/createLongPress.jsx +0 -91
- package/dist/_chunk/createLongPress.jsx.map +0 -1
- package/dist/_chunk/form.js.map +0 -1
- package/dist/_chunk/form.jsx.map +0 -1
- package/dist/_chunk/live-announcer.js.map +0 -1
- package/dist/_chunk/live-announcer.jsx.map +0 -1
- package/dist/datepicker/createTimeSegment.d.ts +0 -29
- package/dist/datepicker/createTimeSegment.d.ts.map +0 -1
- package/src/datepicker/createTimeSegment.ts +0 -352
package/dist/_chunk/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","names":[],"sources":["../../src/utils/mergeProps.ts","../../src/utils/
|
|
1
|
+
{"version":3,"file":"env.js","names":[],"sources":["../../src/utils/mergeProps.ts","../../src/utils/env.ts"],"sourcesContent":["type Props = { [key: string]: unknown };\n\n/**\n * Merges multiple props objects together, handling event handlers specially\n * by chaining them rather than replacing.\n *\n * Based on react-aria's mergeProps but adapted for SolidJS.\n *\n * @param args - Props objects to merge\n * @returns Merged props object. Use type parameter R to specify the result type.\n */\nexport function mergeProps<R extends object = Record<string, unknown>, T extends object = object>(\n ...args: T[]\n): R {\n const result: Props = {};\n const setResultValue = (key: string, value: unknown) => {\n const resultDescriptor = Object.getOwnPropertyDescriptor(result, key);\n\n if (resultDescriptor?.get || resultDescriptor?.set) {\n Object.defineProperty(result, key, {\n enumerable: true,\n configurable: true,\n writable: true,\n value,\n });\n return;\n }\n\n result[key] = value;\n };\n\n for (const props of args) {\n for (const key in props) {\n const descriptor = Object.getOwnPropertyDescriptor(props, key);\n const hasGetter = typeof descriptor?.get === \"function\";\n const getValue = () => (hasGetter ? descriptor.get!.call(props) : props[key]);\n const value = getValue();\n const existingValue = result[key];\n\n if (\n typeof existingValue === \"function\" &&\n typeof value === \"function\" &&\n key.startsWith(\"on\") &&\n key[2] === key[2]?.toUpperCase()\n ) {\n setResultValue(key, chainHandlers(existingValue as Function, value as Function));\n } else if (\n (key === \"class\" || key === \"className\" || key === \"UNSAFE_className\") &&\n typeof existingValue === \"string\" &&\n typeof value === \"string\"\n ) {\n // Join only when both sides are plain strings (react-aria mergeProps\n // semantics); a render-prop class function must pass through intact,\n // not be coerced to its source text.\n setResultValue(key, mergeClassNames(existingValue, value));\n } else if (\n key === \"style\" &&\n typeof existingValue === \"object\" &&\n typeof value === \"object\"\n ) {\n setResultValue(key, { ...(existingValue as object), ...(value as object) });\n } else if (hasGetter && (value !== undefined || !(key in result))) {\n Object.defineProperty(result, key, {\n enumerable: true,\n configurable: true,\n get: getValue,\n });\n } else if (value !== undefined) {\n setResultValue(key, value);\n }\n }\n }\n\n return result as R;\n}\n\nfunction chainHandlers(existingHandler: Function, newHandler: Function) {\n return (...args: unknown[]) => {\n existingHandler(...args);\n newHandler(...args);\n };\n}\n\nfunction mergeClassNames(...classes: unknown[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","/**\n * Environment detection utilities.\n * These avoid direct references to process.env which can cause TypeScript issues in browser environments.\n * Compatible with Node.js and Vite environments.\n */\n\ntype ImportMetaWithEnv = ImportMeta & {\n env?: Record<string, unknown> & { DEV?: boolean; PROD?: boolean };\n};\ntype ProcessLike = { env?: Record<string, string | undefined> };\n\nfunction getEnvVar(key: string): string | undefined {\n const importMetaEnv = (import.meta as ImportMetaWithEnv).env;\n if (importMetaEnv && typeof importMetaEnv[key] === \"string\") {\n return importMetaEnv[key] as string;\n }\n\n const processEnv = (globalThis as typeof globalThis & { process?: ProcessLike }).process?.env;\n if (processEnv) {\n return processEnv[key];\n }\n return undefined;\n}\n\n/**\n * Check if we're running in a test environment.\n */\nexport function isTestEnv(): boolean {\n return getEnvVar(\"NODE_ENV\") === \"test\";\n}\n\n/**\n * Check if we're running in a development environment (not production).\n */\nexport function isDevEnv(): boolean {\n const importMetaEnv = (import.meta as ImportMetaWithEnv).env;\n if (importMetaEnv?.DEV === true) {\n return true;\n }\n const nodeEnv = getEnvVar(\"NODE_ENV\");\n return nodeEnv !== \"production\";\n}\n\n/**\n * Check if we're running in production.\n */\nexport function isProdEnv(): boolean {\n const importMetaEnv = (import.meta as ImportMetaWithEnv).env;\n if (importMetaEnv?.PROD === true) {\n return true;\n }\n return getEnvVar(\"NODE_ENV\") === \"production\";\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,WACd,GAAG,MACA;CACH,MAAM,SAAgB,CAAC;CACvB,MAAM,kBAAkB,KAAa,UAAmB;EACtD,MAAM,mBAAmB,OAAO,yBAAyB,QAAQ,GAAG;EAEpE,IAAI,kBAAkB,OAAO,kBAAkB,KAAK;GAClD,OAAO,eAAe,QAAQ,KAAK;IACjC,YAAY;IACZ,cAAc;IACd,UAAU;IACV;GACF,CAAC;GACD;EACF;EAEA,OAAO,OAAO;CAChB;CAEA,KAAK,MAAM,SAAS,MAClB,KAAK,MAAM,OAAO,OAAO;EACvB,MAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;EAC7D,MAAM,YAAY,OAAO,YAAY,QAAQ;EAC7C,MAAM,iBAAkB,YAAY,WAAW,IAAK,KAAK,KAAK,IAAI,MAAM;EACxE,MAAM,QAAQ,SAAS;EACvB,MAAM,gBAAgB,OAAO;EAE7B,IACE,OAAO,kBAAkB,cACzB,OAAO,UAAU,cACjB,IAAI,WAAW,IAAI,KACnB,IAAI,OAAO,IAAI,EAAE,EAAE,YAAY,GAE/B,eAAe,KAAK,cAAc,eAA2B,KAAiB,CAAC;OAC1E,KACJ,QAAQ,WAAW,QAAQ,eAAe,QAAQ,uBACnD,OAAO,kBAAkB,YACzB,OAAO,UAAU,UAKjB,eAAe,KAAK,gBAAgB,eAAe,KAAK,CAAC;OACpD,IACL,QAAQ,WACR,OAAO,kBAAkB,YACzB,OAAO,UAAU,UAEjB,eAAe,KAAK;GAAE,GAAI;GAA0B,GAAI;EAAiB,CAAC;OACrE,IAAI,cAAc,UAAU,KAAA,KAAa,EAAE,OAAO,UACvD,OAAO,eAAe,QAAQ,KAAK;GACjC,YAAY;GACZ,cAAc;GACd,KAAK;EACP,CAAC;OACI,IAAI,UAAU,KAAA,GACnB,eAAe,KAAK,KAAK;CAE7B;CAGF,OAAO;AACT;AAEA,SAAS,cAAc,iBAA2B,YAAsB;CACtE,QAAQ,GAAG,SAAoB;EAC7B,gBAAgB,GAAG,IAAI;EACvB,WAAW,GAAG,IAAI;CACpB;AACF;AAEA,SAAS,gBAAgB,GAAG,SAA4B;CACtD,OAAO,QAAQ,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AACzC;;;AC1EA,SAAS,UAAU,KAAiC;CAClD,MAAM,gBAAiB,OAAO,KAA2B;CACzD,IAAI,iBAAiB,OAAO,cAAc,SAAS,UACjD,OAAO,cAAc;CAGvB,MAAM,aAAc,WAA6D,SAAS;CAC1F,IAAI,YACF,OAAO,WAAW;AAGtB;;;;AAKA,SAAgB,YAAqB;CACnC,OAAO,UAAU,UAAU,MAAM;AACnC;;;;AAKA,SAAgB,WAAoB;CAElC,IADuB,OAAO,KAA2B,KACtC,QAAQ,MACzB,OAAO;CAGT,OADgB,UAAU,UACb,MAAM;AACrB;;;;AAKA,SAAgB,YAAqB;CAEnC,IADuB,OAAO,KAA2B,KACtC,SAAS,MAC1B,OAAO;CAET,OAAO,UAAU,UAAU,MAAM;AACnC"}
|
package/dist/_chunk/env.jsx
CHANGED
|
@@ -54,24 +54,6 @@ function mergeClassNames(...classes) {
|
|
|
54
54
|
return classes.filter(Boolean).join(" ");
|
|
55
55
|
}
|
|
56
56
|
//#endregion
|
|
57
|
-
//#region src/utils/reactivity.ts
|
|
58
|
-
/**
|
|
59
|
-
* Unwraps a MaybeAccessor to get the underlying value.
|
|
60
|
-
* If the input is a function, it calls it to get the value.
|
|
61
|
-
* Otherwise, it returns the value directly.
|
|
62
|
-
*
|
|
63
|
-
* @param value - The value or accessor to unwrap.
|
|
64
|
-
*/
|
|
65
|
-
function access(value) {
|
|
66
|
-
return typeof value === "function" ? value() : value;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Checks if a value is an accessor function.
|
|
70
|
-
*/
|
|
71
|
-
function isAccessor(value) {
|
|
72
|
-
return typeof value === "function";
|
|
73
|
-
}
|
|
74
|
-
//#endregion
|
|
75
57
|
//#region src/utils/env.ts
|
|
76
58
|
function getEnvVar(key) {
|
|
77
59
|
const importMetaEnv = import.meta.env;
|
|
@@ -100,6 +82,6 @@ function isProdEnv() {
|
|
|
100
82
|
return getEnvVar("NODE_ENV") === "production";
|
|
101
83
|
}
|
|
102
84
|
//#endregion
|
|
103
|
-
export {
|
|
85
|
+
export { mergeProps as i, isProdEnv as n, isTestEnv as r, isDevEnv as t };
|
|
104
86
|
|
|
105
87
|
//# sourceMappingURL=env.jsx.map
|
package/dist/_chunk/env.jsx.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.jsx","names":[],"sources":["../../src/utils/mergeProps.ts","../../src/utils/
|
|
1
|
+
{"version":3,"file":"env.jsx","names":[],"sources":["../../src/utils/mergeProps.ts","../../src/utils/env.ts"],"sourcesContent":["type Props = { [key: string]: unknown };\n\n/**\n * Merges multiple props objects together, handling event handlers specially\n * by chaining them rather than replacing.\n *\n * Based on react-aria's mergeProps but adapted for SolidJS.\n *\n * @param args - Props objects to merge\n * @returns Merged props object. Use type parameter R to specify the result type.\n */\nexport function mergeProps<R extends object = Record<string, unknown>, T extends object = object>(\n ...args: T[]\n): R {\n const result: Props = {};\n const setResultValue = (key: string, value: unknown) => {\n const resultDescriptor = Object.getOwnPropertyDescriptor(result, key);\n\n if (resultDescriptor?.get || resultDescriptor?.set) {\n Object.defineProperty(result, key, {\n enumerable: true,\n configurable: true,\n writable: true,\n value,\n });\n return;\n }\n\n result[key] = value;\n };\n\n for (const props of args) {\n for (const key in props) {\n const descriptor = Object.getOwnPropertyDescriptor(props, key);\n const hasGetter = typeof descriptor?.get === \"function\";\n const getValue = () => (hasGetter ? descriptor.get!.call(props) : props[key]);\n const value = getValue();\n const existingValue = result[key];\n\n if (\n typeof existingValue === \"function\" &&\n typeof value === \"function\" &&\n key.startsWith(\"on\") &&\n key[2] === key[2]?.toUpperCase()\n ) {\n setResultValue(key, chainHandlers(existingValue as Function, value as Function));\n } else if (\n (key === \"class\" || key === \"className\" || key === \"UNSAFE_className\") &&\n typeof existingValue === \"string\" &&\n typeof value === \"string\"\n ) {\n // Join only when both sides are plain strings (react-aria mergeProps\n // semantics); a render-prop class function must pass through intact,\n // not be coerced to its source text.\n setResultValue(key, mergeClassNames(existingValue, value));\n } else if (\n key === \"style\" &&\n typeof existingValue === \"object\" &&\n typeof value === \"object\"\n ) {\n setResultValue(key, { ...(existingValue as object), ...(value as object) });\n } else if (hasGetter && (value !== undefined || !(key in result))) {\n Object.defineProperty(result, key, {\n enumerable: true,\n configurable: true,\n get: getValue,\n });\n } else if (value !== undefined) {\n setResultValue(key, value);\n }\n }\n }\n\n return result as R;\n}\n\nfunction chainHandlers(existingHandler: Function, newHandler: Function) {\n return (...args: unknown[]) => {\n existingHandler(...args);\n newHandler(...args);\n };\n}\n\nfunction mergeClassNames(...classes: unknown[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","/**\n * Environment detection utilities.\n * These avoid direct references to process.env which can cause TypeScript issues in browser environments.\n * Compatible with Node.js and Vite environments.\n */\n\ntype ImportMetaWithEnv = ImportMeta & {\n env?: Record<string, unknown> & { DEV?: boolean; PROD?: boolean };\n};\ntype ProcessLike = { env?: Record<string, string | undefined> };\n\nfunction getEnvVar(key: string): string | undefined {\n const importMetaEnv = (import.meta as ImportMetaWithEnv).env;\n if (importMetaEnv && typeof importMetaEnv[key] === \"string\") {\n return importMetaEnv[key] as string;\n }\n\n const processEnv = (globalThis as typeof globalThis & { process?: ProcessLike }).process?.env;\n if (processEnv) {\n return processEnv[key];\n }\n return undefined;\n}\n\n/**\n * Check if we're running in a test environment.\n */\nexport function isTestEnv(): boolean {\n return getEnvVar(\"NODE_ENV\") === \"test\";\n}\n\n/**\n * Check if we're running in a development environment (not production).\n */\nexport function isDevEnv(): boolean {\n const importMetaEnv = (import.meta as ImportMetaWithEnv).env;\n if (importMetaEnv?.DEV === true) {\n return true;\n }\n const nodeEnv = getEnvVar(\"NODE_ENV\");\n return nodeEnv !== \"production\";\n}\n\n/**\n * Check if we're running in production.\n */\nexport function isProdEnv(): boolean {\n const importMetaEnv = (import.meta as ImportMetaWithEnv).env;\n if (importMetaEnv?.PROD === true) {\n return true;\n }\n return getEnvVar(\"NODE_ENV\") === \"production\";\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,WACd,GAAG,MACA;CACH,MAAM,SAAgB,CAAC;CACvB,MAAM,kBAAkB,KAAa,UAAmB;EACtD,MAAM,mBAAmB,OAAO,yBAAyB,QAAQ,GAAG;EAEpE,IAAI,kBAAkB,OAAO,kBAAkB,KAAK;GAClD,OAAO,eAAe,QAAQ,KAAK;IACjC,YAAY;IACZ,cAAc;IACd,UAAU;IACV;GACF,CAAC;GACD;EACF;EAEA,OAAO,OAAO;CAChB;CAEA,KAAK,MAAM,SAAS,MAClB,KAAK,MAAM,OAAO,OAAO;EACvB,MAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;EAC7D,MAAM,YAAY,OAAO,YAAY,QAAQ;EAC7C,MAAM,iBAAkB,YAAY,WAAW,IAAK,KAAK,KAAK,IAAI,MAAM;EACxE,MAAM,QAAQ,SAAS;EACvB,MAAM,gBAAgB,OAAO;EAE7B,IACE,OAAO,kBAAkB,cACzB,OAAO,UAAU,cACjB,IAAI,WAAW,IAAI,KACnB,IAAI,OAAO,IAAI,EAAE,EAAE,YAAY,GAE/B,eAAe,KAAK,cAAc,eAA2B,KAAiB,CAAC;OAC1E,KACJ,QAAQ,WAAW,QAAQ,eAAe,QAAQ,uBACnD,OAAO,kBAAkB,YACzB,OAAO,UAAU,UAKjB,eAAe,KAAK,gBAAgB,eAAe,KAAK,CAAC;OACpD,IACL,QAAQ,WACR,OAAO,kBAAkB,YACzB,OAAO,UAAU,UAEjB,eAAe,KAAK;GAAE,GAAI;GAA0B,GAAI;EAAiB,CAAC;OACrE,IAAI,cAAc,UAAU,KAAA,KAAa,EAAE,OAAO,UACvD,OAAO,eAAe,QAAQ,KAAK;GACjC,YAAY;GACZ,cAAc;GACd,KAAK;EACP,CAAC;OACI,IAAI,UAAU,KAAA,GACnB,eAAe,KAAK,KAAK;CAE7B;CAGF,OAAO;AACT;AAEA,SAAS,cAAc,iBAA2B,YAAsB;CACtE,QAAQ,GAAG,SAAoB;EAC7B,gBAAgB,GAAG,IAAI;EACvB,WAAW,GAAG,IAAI;CACpB;AACF;AAEA,SAAS,gBAAgB,GAAG,SAA4B;CACtD,OAAO,QAAQ,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;AACzC;;;AC1EA,SAAS,UAAU,KAAiC;CAClD,MAAM,gBAAiB,OAAO,KAA2B;CACzD,IAAI,iBAAiB,OAAO,cAAc,SAAS,UACjD,OAAO,cAAc;CAGvB,MAAM,aAAc,WAA6D,SAAS;CAC1F,IAAI,YACF,OAAO,WAAW;AAGtB;;;;AAKA,SAAgB,YAAqB;CACnC,OAAO,UAAU,UAAU,MAAM;AACnC;;;;AAKA,SAAgB,WAAoB;CAElC,IADuB,OAAO,KAA2B,KACtC,QAAQ,MACzB,OAAO;CAGT,OADgB,UAAU,UACb,MAAM;AACrB;;;;AAKA,SAAgB,YAAqB;CAEnC,IADuB,OAAO,KAA2B,KACtC,SAAS,MAC1B,OAAO;CAET,OAAO,UAAU,UAAU,MAAM;AACnC"}
|
package/dist/_chunk/focus.js
CHANGED
|
@@ -284,7 +284,7 @@ function isFocusWithin(element) {
|
|
|
284
284
|
* selectable collection as a single tab stop.
|
|
285
285
|
*/
|
|
286
286
|
function getFocusableTreeWalker(root, opts) {
|
|
287
|
-
const accept = (node) => opts?.tabbable ? isTabbable(node) : isFocusable(node);
|
|
287
|
+
const accept = (node) => (opts?.tabbable ? isTabbable(node) : isFocusable(node)) && (!opts?.accept || opts.accept(node));
|
|
288
288
|
const walker = getOwnerDocument(root).createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { acceptNode(node) {
|
|
289
289
|
if (opts?.from?.contains(node)) return NodeFilter.FILTER_REJECT;
|
|
290
290
|
if (accept(node)) return NodeFilter.FILTER_ACCEPT;
|
package/dist/_chunk/focus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus.js","names":[],"sources":["../../src/utils/dom.ts","../../src/utils/focus.ts"],"sourcesContent":["/**\n * DOM utilities for cross-browser compatibility.\n * Based on @react-aria/utils DOM utilities.\n */\n\n/**\n * Gets the owner document of an element, or the global document.\n */\nexport function getOwnerDocument(el: Element | null | undefined): Document {\n return el?.ownerDocument ?? document;\n}\n\n/**\n * Gets the owner window of an element, or the global window.\n */\nexport function getOwnerWindow(el: Element | null | undefined): Window & typeof globalThis {\n return getOwnerDocument(el).defaultView ?? window;\n}\n\n/**\n * Cross-browser implementation of Node.contains that works with ShadowDOM.\n * In Safari, Node.contains doesn't properly detect elements inside shadow roots.\n */\nexport function nodeContains(parent: Node | null, child: Node | null): boolean {\n if (!parent || !child) {\n return false;\n }\n\n // Standard contains check\n if (parent.contains(child)) {\n return true;\n }\n\n // Check if child is in a shadow root\n let node: Node | null = child;\n while (node) {\n if (node === parent) {\n return true;\n }\n\n // Check shadow root host\n if ((node as ShadowRoot).host) {\n node = (node as ShadowRoot).host;\n } else {\n node = node.parentNode;\n }\n }\n\n return false;\n}\n\n/**\n * Gets the event target, handling composed path for shadow DOM.\n */\nexport function getEventTarget<T extends EventTarget>(event: Event): T | null {\n // Use composedPath to get the real target when using Shadow DOM\n if (typeof event.composedPath === \"function\") {\n const path = event.composedPath();\n if (path.length > 0) {\n return path[0] as T;\n }\n }\n return event.target as T | null;\n}\n\n// Ports @react-aria/utils `isElementVisible`/`isFocusable`/`isTabbable` (v3.34.1,\n// the version paired with our pinned RAC 1.19.0) so focusability matches upstream:\n// a candidate must match the focusable selector AND not be inside an `inert`\n// subtree AND be visible (unless `skipVisibilityCheck`). The previous `isFocusable`\n// was a simplified tagName/tabindex check with no visibility or `inert` filtering.\n// Owner-window lookups go through `getOwnerWindow`, which falls back to the global\n// window, so these stay robust on detached documents (`defaultView === null`).\n\nconst supportsCheckVisibility =\n typeof Element !== \"undefined\" && \"checkVisibility\" in Element.prototype;\n\n// Solid clones templates with the document that is global at creation time, so a\n// node portaled into another document (e.g. an iframe) keeps its original realm's\n// prototype even though `getOwnerWindow` now resolves to the other document's\n// window. Upstream React creates portal nodes with the container's `ownerDocument`,\n// so its single `instanceof getOwnerWindow(element)` check suffices; we also accept\n// the global realm's constructors so cross-document focus scopes still recognize\n// real elements. In the common same-realm case this is identical to upstream.\nfunction isHTMLOrSVGElement(element: Element): element is HTMLElement | SVGElement {\n const windowObject = getOwnerWindow(element);\n return (\n element instanceof windowObject.HTMLElement ||\n element instanceof windowObject.SVGElement ||\n (typeof HTMLElement !== \"undefined\" && element instanceof HTMLElement) ||\n (typeof SVGElement !== \"undefined\" && element instanceof SVGElement)\n );\n}\n\nfunction isStyleVisible(element: Element): boolean {\n if (!isHTMLOrSVGElement(element)) {\n return false;\n }\n\n const { display, visibility } = element.style;\n\n let isVisible = display !== \"none\" && visibility !== \"hidden\" && visibility !== \"collapse\";\n\n if (isVisible) {\n const { getComputedStyle } = getOwnerWindow(element);\n const { display: computedDisplay, visibility: computedVisibility } = getComputedStyle(element);\n\n isVisible =\n computedDisplay !== \"none\" &&\n computedVisibility !== \"hidden\" &&\n computedVisibility !== \"collapse\";\n }\n\n return isVisible;\n}\n\nfunction isAttributeVisible(element: Element, childElement?: Element): boolean {\n return (\n !element.hasAttribute(\"hidden\") &&\n // Ignore HiddenSelect when tree walking.\n !element.hasAttribute(\"data-react-aria-prevent-focus\") &&\n (element.nodeName === \"DETAILS\" && childElement && childElement.nodeName !== \"SUMMARY\"\n ? element.hasAttribute(\"open\")\n : true)\n );\n}\n\n/**\n * Whether an element is visible, and so eligible for focus. Adapted from\n * @react-aria/utils, which adapts testing-library/jest-dom and\n * vue-test-utils-next (MIT): uses `checkVisibility` when supported, otherwise\n * walks computed style and visibility-affecting attributes up the ancestor chain.\n */\nexport function isElementVisible(element: Element, childElement?: Element): boolean {\n if (supportsCheckVisibility) {\n return (\n element.checkVisibility({ visibilityProperty: true }) &&\n !element.closest(\"[data-react-aria-prevent-focus]\")\n );\n }\n\n return (\n element.nodeName !== \"#comment\" &&\n isStyleVisible(element) &&\n isAttributeVisible(element, childElement) &&\n (!element.parentElement || isElementVisible(element.parentElement, element))\n );\n}\n\nconst focusableElements = [\n \"input:not([disabled]):not([type=hidden])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"button:not([disabled])\",\n \"a[href]\",\n \"area[href]\",\n \"summary\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"audio[controls]\",\n \"video[controls]\",\n '[contenteditable]:not([contenteditable^=\"false\"])',\n \"permission\",\n];\n\nconst FOCUSABLE_ELEMENT_SELECTOR =\n focusableElements.join(\":not([hidden]),\") + \",[tabindex]:not([disabled]):not([hidden])\";\n\nfocusableElements.push('[tabindex]:not([tabindex=\"-1\"]):not([disabled])');\nconst TABBABLE_ELEMENT_SELECTOR = focusableElements.join(':not([hidden]):not([tabindex=\"-1\"]),');\n\n/**\n * Checks if an element is a valid focusable element: it matches the focusable\n * selector, is not inside an `inert` subtree, and is visible. A negative tabindex\n * is programmatically focusable (matched here) but not tabbable. `skipVisibilityCheck`\n * lets callers (e.g. the press-path `preventFocus` ancestor walk) skip the\n * `isElementVisible` step, which also avoids touching layout on detached documents.\n */\nexport function isFocusable(\n element: Element,\n options?: { skipVisibilityCheck?: boolean },\n): boolean {\n return (\n element.matches(FOCUSABLE_ELEMENT_SELECTOR) &&\n !isInert(element) &&\n (options?.skipVisibilityCheck || isElementVisible(element))\n );\n}\n\n/**\n * Checks if an element is tabbable (reachable via the Tab key): focusable,\n * visible, not inert, and not `tabindex=\"-1\"`.\n */\nexport function isTabbable(element: Element): boolean {\n return (\n element.matches(TABBABLE_ELEMENT_SELECTOR) && isElementVisible(element) && !isInert(element)\n );\n}\n\nfunction isInert(element: Element): boolean {\n let node: Element | null = element;\n while (node != null) {\n // Realm-tolerant HTMLElement check (see isHTMLOrSVGElement): Solid-portaled\n // nodes keep their creating realm's prototype, so also accept the global one.\n const isHTMLElement =\n node instanceof getOwnerWindow(node).HTMLElement ||\n (typeof HTMLElement !== \"undefined\" && node instanceof HTMLElement);\n if (isHTMLElement && (node as HTMLElement).inert) {\n return true;\n }\n\n node = node.parentElement;\n }\n\n return false;\n}\n\n/**\n * Checks if a keyboard event should trigger the default action (like clicking).\n */\nexport function isValidKeyboardEvent(event: KeyboardEvent, currentTarget: Element): boolean {\n const { key, code } = event;\n const element = currentTarget as HTMLElement;\n const tagName = element.tagName.toLowerCase();\n const role = element.getAttribute(\"role\");\n\n // Only accept Enter and Space\n const isActivationKey = key === \"Enter\" || key === \" \" || key === \"Spacebar\" || code === \"Space\";\n if (!isActivationKey) {\n return false;\n }\n\n // Text inputs should handle their own keyboard events\n if (tagName === \"textarea\") {\n return false;\n }\n\n // Content editable elements should handle their own keyboard events\n if (element.isContentEditable) {\n return false;\n }\n\n // Links should only respond to Enter, not Space\n const isLink = role === \"link\" || (!role && isHTMLAnchorLink(element));\n if (isLink && key !== \"Enter\") {\n return false;\n }\n\n // Input elements have specific key handling\n if (tagName === \"input\") {\n return isValidInputKey(element as HTMLInputElement, key);\n }\n\n return true;\n}\n\n/**\n * Checks if a key is valid for a specific input type.\n */\nexport function isValidInputKey(target: HTMLInputElement, key: string): boolean {\n const type = target.type.toLowerCase();\n\n // Checkbox and radio only respond to Space\n if (type === \"checkbox\" || type === \"radio\") {\n return key === \" \" || key === \"Spacebar\";\n }\n\n // Text-like inputs handle their own keyboard events\n const textInputTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n if (textInputTypes.includes(type)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks if an element is an HTML anchor link (has href attribute).\n */\nexport function isHTMLAnchorLink(target: Element): boolean {\n return target.tagName === \"A\" && target.hasAttribute(\"href\");\n}\n\n/**\n * Whether to prevent default on keyboard events for this element.\n */\nexport function shouldPreventDefaultKeyboard(target: Element, key: string): boolean {\n if (target instanceof HTMLInputElement) {\n return !isValidInputKey(target, key);\n }\n\n return shouldPreventDefaultUp(target);\n}\n\n/**\n * Whether to prevent default on pointer up for this element.\n */\nexport function shouldPreventDefaultUp(target: Element): boolean {\n const tagName = target.tagName.toLowerCase();\n\n // Never prevent default on form elements\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return false;\n }\n\n // Don't prevent default on links\n if (tagName === \"a\" || target.getAttribute(\"role\") === \"link\") {\n return false;\n }\n\n // Buttons with submit/reset type should not prevent default\n if (tagName === \"button\") {\n const type = (target as HTMLButtonElement).type;\n if (type === \"submit\" || type === \"reset\") {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Opens a link, supporting both same-window and new-window navigation.\n * Used for keyboard activation of links with Space key (which doesn't natively open links).\n */\nexport function openLink(target: HTMLAnchorElement, event: Event, allowOpener = false): void {\n const { href, target: linkTarget, rel } = target;\n (openLink as { isOpening?: boolean }).isOpening = true;\n\n // Handle modifier keys for open-in-new-tab behavior\n const keyEvent = event as KeyboardEvent;\n const shouldOpenInNewTab =\n linkTarget === \"_blank\" ||\n keyEvent?.metaKey ||\n keyEvent?.ctrlKey ||\n keyEvent?.shiftKey ||\n keyEvent?.altKey;\n\n if (shouldOpenInNewTab) {\n const features = !allowOpener && rel?.includes(\"noopener\") ? \"noopener\" : undefined;\n window.open(href, linkTarget || \"_blank\", features);\n } else {\n window.location.href = href;\n }\n\n (openLink as { isOpening?: boolean }).isOpening = false;\n}\n\n(openLink as { isOpening?: boolean }).isOpening = false;\n\n/**\n * Checks if an element is scrollable based on its overflow style.\n * @param node - The element to check\n * @param checkForOverflow - If true, also check if the element actually overflows\n */\nexport function isScrollable(node: Element | null, checkForOverflow?: boolean): boolean {\n if (!node) {\n return false;\n }\n\n const style = window.getComputedStyle(node);\n const scrollable = /(auto|scroll)/.test(style.overflow + style.overflowX + style.overflowY);\n\n if (scrollable && checkForOverflow) {\n return node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth;\n }\n\n return scrollable;\n}\n\n/**\n * Gets the nearest scrollable parent element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only return parents that actually overflow\n */\nexport function getScrollParent(node: Element, checkForOverflow?: boolean): Element {\n let scrollableNode: Element | null = node;\n\n if (isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n return scrollableNode || document.scrollingElement || document.documentElement;\n}\n\n/**\n * Gets every scrollable ancestor of an element, from the nearest up to (and\n * including) the document scrolling element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only include parents that actually overflow\n */\nexport function getScrollParents(node: Element, checkForOverflow?: boolean): Element[] {\n const parentElements: Element[] = [];\n const root = document.scrollingElement || document.documentElement;\n let current: Element | null = node;\n\n while (current) {\n if (isScrollable(current, checkForOverflow)) {\n parentElements.push(current);\n }\n if (current === root) {\n break;\n }\n current = current.parentElement;\n }\n\n return parentElements;\n}\n\n/**\n * Checks if an element will open a virtual keyboard when focused.\n * Used for iOS Safari scroll handling.\n */\nexport function willOpenKeyboard(target: Element | null): boolean {\n if (!target) {\n return false;\n }\n\n const tagName = target.tagName.toLowerCase();\n\n // Inputs that open keyboard (not all input types do)\n if (tagName === \"input\") {\n const type = (target as HTMLInputElement).type.toLowerCase();\n // These input types open the keyboard\n const keyboardTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n return keyboardTypes.includes(type);\n }\n\n // Textareas always open keyboard\n if (tagName === \"textarea\") {\n return true;\n }\n\n // Contenteditable elements open keyboard\n if (\n target.hasAttribute(\"contenteditable\") &&\n target.getAttribute(\"contenteditable\") !== \"false\"\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns the deepest active element, descending through open shadow roots.\n * Mirrors @react-aria/utils' `getActiveElement`.\n */\nexport function getActiveElement(doc: Document = document): Element | null {\n let activeElement = doc.activeElement;\n while (activeElement?.shadowRoot?.activeElement) {\n activeElement = activeElement.shadowRoot.activeElement;\n }\n return activeElement;\n}\n\n/**\n * Whether the (deepest) active element is `element` or is contained within it.\n * Mirrors @react-aria/utils' `isFocusWithin`.\n */\nexport function isFocusWithin(element: Element): boolean {\n const activeElement = getActiveElement(getOwnerDocument(element));\n return !!activeElement && nodeContains(element, activeElement);\n}\n\n/**\n * Creates a `TreeWalker` that visits the focusable (or, when `tabbable`, the\n * tabbable) descendants of `root`, skipping invisible and inert elements.\n * Mirrors @react-aria/focus's `getFocusableTreeWalker`, minus the focus-scope\n * containment filter (we don't model nested scopes here). Used to treat a\n * selectable collection as a single tab stop.\n */\nexport function getFocusableTreeWalker(\n root: Element,\n opts?: { tabbable?: boolean; from?: Node },\n): TreeWalker {\n const accept = (node: Element) => (opts?.tabbable ? isTabbable(node) : isFocusable(node));\n const walker = getOwnerDocument(root).createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node) {\n // Skip nodes inside the optional starting node.\n if (opts?.from?.contains(node)) {\n return NodeFilter.FILTER_REJECT;\n }\n if (accept(node as Element)) {\n return NodeFilter.FILTER_ACCEPT;\n }\n return NodeFilter.FILTER_SKIP;\n },\n });\n if (opts?.from) {\n walker.currentNode = opts.from;\n }\n return walker;\n}\n","/**\n * Focus management utilities.\n * Based on @react-aria/utils focus utilities.\n */\n\nimport { getEventTarget, getOwnerDocument, getOwnerWindow, isFocusable } from \"./dom\";\n\n/**\n * Focuses an element without scrolling the page.\n * Uses preventScroll option with fallback for older browsers.\n */\nexport function focusWithoutScrolling(element: HTMLElement | null): void {\n if (!element) return;\n\n try {\n element.focus({ preventScroll: true });\n } catch {\n // Fallback for browsers that don't support preventScroll\n const scrollableElements = getScrollableAncestors(element);\n const scrollPositions = scrollableElements.map((el) => ({\n element: el,\n scrollTop: el.scrollTop,\n scrollLeft: el.scrollLeft,\n }));\n\n element.focus();\n\n for (const { element: el, scrollTop, scrollLeft } of scrollPositions) {\n el.scrollTop = scrollTop;\n el.scrollLeft = scrollLeft;\n }\n }\n}\n\n/**\n * Gets all scrollable ancestors of an element.\n */\nfunction getScrollableAncestors(element: Element): Element[] {\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n\n while (parent) {\n const style = getComputedStyle(parent);\n const overflowY = style.overflowY;\n const overflowX = style.overflowX;\n\n if (\n overflowY === \"auto\" ||\n overflowY === \"scroll\" ||\n overflowX === \"auto\" ||\n overflowX === \"scroll\"\n ) {\n ancestors.push(parent);\n }\n\n parent = parent.parentElement;\n }\n\n // Also include the document scrolling element\n const doc = getOwnerDocument(element);\n ancestors.push(doc.documentElement);\n\n return ancestors;\n}\n\n/**\n * Prevents focus from moving to a new element temporarily.\n * Used when clicking on a button that shouldn't steal focus.\n */\nexport function preventFocus(target: Element | null): (() => void) | undefined {\n while (target && !isFocusable(target)) {\n target = target.parentElement;\n }\n\n const ownerWindow = getOwnerWindow(target);\n const activeElement = ownerWindow.document.activeElement as HTMLElement | null;\n\n if (!activeElement || activeElement === target) {\n return undefined;\n }\n\n let isRefocusing = false;\n\n const onBlur = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusOut = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!target && !isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n const onFocus = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusIn = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n ownerWindow.addEventListener(\"blur\", onBlur, true);\n ownerWindow.addEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.addEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.addEventListener(\"focus\", onFocus, true);\n\n const raf = ownerWindow.requestAnimationFrame(cleanup);\n\n function cleanup() {\n ownerWindow.cancelAnimationFrame(raf);\n ownerWindow.removeEventListener(\"blur\", onBlur, true);\n ownerWindow.removeEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.removeEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.removeEventListener(\"focus\", onFocus, true);\n isRefocusing = false;\n }\n\n return cleanup;\n}\n\n/**\n * Safely focuses an element, alias for focusWithoutScrolling.\n * This matches the react-aria focusSafely function name.\n */\nexport const focusSafely = focusWithoutScrolling;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"focus.js","names":[],"sources":["../../src/utils/dom.ts","../../src/utils/focus.ts"],"sourcesContent":["/**\n * DOM utilities for cross-browser compatibility.\n * Based on @react-aria/utils DOM utilities.\n */\n\n/**\n * Gets the owner document of an element, or the global document.\n */\nexport function getOwnerDocument(el: Element | null | undefined): Document {\n return el?.ownerDocument ?? document;\n}\n\n/**\n * Gets the owner window of an element, or the global window.\n */\nexport function getOwnerWindow(el: Element | null | undefined): Window & typeof globalThis {\n return getOwnerDocument(el).defaultView ?? window;\n}\n\n/**\n * Cross-browser implementation of Node.contains that works with ShadowDOM.\n * In Safari, Node.contains doesn't properly detect elements inside shadow roots.\n */\nexport function nodeContains(parent: Node | null, child: Node | null): boolean {\n if (!parent || !child) {\n return false;\n }\n\n // Standard contains check\n if (parent.contains(child)) {\n return true;\n }\n\n // Check if child is in a shadow root\n let node: Node | null = child;\n while (node) {\n if (node === parent) {\n return true;\n }\n\n // Check shadow root host\n if ((node as ShadowRoot).host) {\n node = (node as ShadowRoot).host;\n } else {\n node = node.parentNode;\n }\n }\n\n return false;\n}\n\n/**\n * Gets the event target, handling composed path for shadow DOM.\n */\nexport function getEventTarget<T extends EventTarget>(event: Event): T | null {\n // Use composedPath to get the real target when using Shadow DOM\n if (typeof event.composedPath === \"function\") {\n const path = event.composedPath();\n if (path.length > 0) {\n return path[0] as T;\n }\n }\n return event.target as T | null;\n}\n\n// Ports @react-aria/utils `isElementVisible`/`isFocusable`/`isTabbable` (v3.34.1,\n// the version paired with our pinned RAC 1.19.0) so focusability matches upstream:\n// a candidate must match the focusable selector AND not be inside an `inert`\n// subtree AND be visible (unless `skipVisibilityCheck`). The previous `isFocusable`\n// was a simplified tagName/tabindex check with no visibility or `inert` filtering.\n// Owner-window lookups go through `getOwnerWindow`, which falls back to the global\n// window, so these stay robust on detached documents (`defaultView === null`).\n\nconst supportsCheckVisibility =\n typeof Element !== \"undefined\" && \"checkVisibility\" in Element.prototype;\n\n// Solid clones templates with the document that is global at creation time, so a\n// node portaled into another document (e.g. an iframe) keeps its original realm's\n// prototype even though `getOwnerWindow` now resolves to the other document's\n// window. Upstream React creates portal nodes with the container's `ownerDocument`,\n// so its single `instanceof getOwnerWindow(element)` check suffices; we also accept\n// the global realm's constructors so cross-document focus scopes still recognize\n// real elements. In the common same-realm case this is identical to upstream.\nfunction isHTMLOrSVGElement(element: Element): element is HTMLElement | SVGElement {\n const windowObject = getOwnerWindow(element);\n return (\n element instanceof windowObject.HTMLElement ||\n element instanceof windowObject.SVGElement ||\n (typeof HTMLElement !== \"undefined\" && element instanceof HTMLElement) ||\n (typeof SVGElement !== \"undefined\" && element instanceof SVGElement)\n );\n}\n\nfunction isStyleVisible(element: Element): boolean {\n if (!isHTMLOrSVGElement(element)) {\n return false;\n }\n\n const { display, visibility } = element.style;\n\n let isVisible = display !== \"none\" && visibility !== \"hidden\" && visibility !== \"collapse\";\n\n if (isVisible) {\n const { getComputedStyle } = getOwnerWindow(element);\n const { display: computedDisplay, visibility: computedVisibility } = getComputedStyle(element);\n\n isVisible =\n computedDisplay !== \"none\" &&\n computedVisibility !== \"hidden\" &&\n computedVisibility !== \"collapse\";\n }\n\n return isVisible;\n}\n\nfunction isAttributeVisible(element: Element, childElement?: Element): boolean {\n return (\n !element.hasAttribute(\"hidden\") &&\n // Ignore HiddenSelect when tree walking.\n !element.hasAttribute(\"data-react-aria-prevent-focus\") &&\n (element.nodeName === \"DETAILS\" && childElement && childElement.nodeName !== \"SUMMARY\"\n ? element.hasAttribute(\"open\")\n : true)\n );\n}\n\n/**\n * Whether an element is visible, and so eligible for focus. Adapted from\n * @react-aria/utils, which adapts testing-library/jest-dom and\n * vue-test-utils-next (MIT): uses `checkVisibility` when supported, otherwise\n * walks computed style and visibility-affecting attributes up the ancestor chain.\n */\nexport function isElementVisible(element: Element, childElement?: Element): boolean {\n if (supportsCheckVisibility) {\n return (\n element.checkVisibility({ visibilityProperty: true }) &&\n !element.closest(\"[data-react-aria-prevent-focus]\")\n );\n }\n\n return (\n element.nodeName !== \"#comment\" &&\n isStyleVisible(element) &&\n isAttributeVisible(element, childElement) &&\n (!element.parentElement || isElementVisible(element.parentElement, element))\n );\n}\n\nconst focusableElements = [\n \"input:not([disabled]):not([type=hidden])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"button:not([disabled])\",\n \"a[href]\",\n \"area[href]\",\n \"summary\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"audio[controls]\",\n \"video[controls]\",\n '[contenteditable]:not([contenteditable^=\"false\"])',\n \"permission\",\n];\n\nconst FOCUSABLE_ELEMENT_SELECTOR =\n focusableElements.join(\":not([hidden]),\") + \",[tabindex]:not([disabled]):not([hidden])\";\n\nfocusableElements.push('[tabindex]:not([tabindex=\"-1\"]):not([disabled])');\nconst TABBABLE_ELEMENT_SELECTOR = focusableElements.join(':not([hidden]):not([tabindex=\"-1\"]),');\n\n/**\n * Checks if an element is a valid focusable element: it matches the focusable\n * selector, is not inside an `inert` subtree, and is visible. A negative tabindex\n * is programmatically focusable (matched here) but not tabbable. `skipVisibilityCheck`\n * lets callers (e.g. the press-path `preventFocus` ancestor walk) skip the\n * `isElementVisible` step, which also avoids touching layout on detached documents.\n */\nexport function isFocusable(\n element: Element,\n options?: { skipVisibilityCheck?: boolean },\n): boolean {\n return (\n element.matches(FOCUSABLE_ELEMENT_SELECTOR) &&\n !isInert(element) &&\n (options?.skipVisibilityCheck || isElementVisible(element))\n );\n}\n\n/**\n * Checks if an element is tabbable (reachable via the Tab key): focusable,\n * visible, not inert, and not `tabindex=\"-1\"`.\n */\nexport function isTabbable(element: Element): boolean {\n return (\n element.matches(TABBABLE_ELEMENT_SELECTOR) && isElementVisible(element) && !isInert(element)\n );\n}\n\nfunction isInert(element: Element): boolean {\n let node: Element | null = element;\n while (node != null) {\n // Realm-tolerant HTMLElement check (see isHTMLOrSVGElement): Solid-portaled\n // nodes keep their creating realm's prototype, so also accept the global one.\n const isHTMLElement =\n node instanceof getOwnerWindow(node).HTMLElement ||\n (typeof HTMLElement !== \"undefined\" && node instanceof HTMLElement);\n if (isHTMLElement && (node as HTMLElement).inert) {\n return true;\n }\n\n node = node.parentElement;\n }\n\n return false;\n}\n\n/**\n * Checks if a keyboard event should trigger the default action (like clicking).\n */\nexport function isValidKeyboardEvent(event: KeyboardEvent, currentTarget: Element): boolean {\n const { key, code } = event;\n const element = currentTarget as HTMLElement;\n const tagName = element.tagName.toLowerCase();\n const role = element.getAttribute(\"role\");\n\n // Only accept Enter and Space\n const isActivationKey = key === \"Enter\" || key === \" \" || key === \"Spacebar\" || code === \"Space\";\n if (!isActivationKey) {\n return false;\n }\n\n // Text inputs should handle their own keyboard events\n if (tagName === \"textarea\") {\n return false;\n }\n\n // Content editable elements should handle their own keyboard events\n if (element.isContentEditable) {\n return false;\n }\n\n // Links should only respond to Enter, not Space\n const isLink = role === \"link\" || (!role && isHTMLAnchorLink(element));\n if (isLink && key !== \"Enter\") {\n return false;\n }\n\n // Input elements have specific key handling\n if (tagName === \"input\") {\n return isValidInputKey(element as HTMLInputElement, key);\n }\n\n return true;\n}\n\n/**\n * Checks if a key is valid for a specific input type.\n */\nexport function isValidInputKey(target: HTMLInputElement, key: string): boolean {\n const type = target.type.toLowerCase();\n\n // Checkbox and radio only respond to Space\n if (type === \"checkbox\" || type === \"radio\") {\n return key === \" \" || key === \"Spacebar\";\n }\n\n // Text-like inputs handle their own keyboard events\n const textInputTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n if (textInputTypes.includes(type)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks if an element is an HTML anchor link (has href attribute).\n */\nexport function isHTMLAnchorLink(target: Element): boolean {\n return target.tagName === \"A\" && target.hasAttribute(\"href\");\n}\n\n/**\n * Whether to prevent default on keyboard events for this element.\n */\nexport function shouldPreventDefaultKeyboard(target: Element, key: string): boolean {\n if (target instanceof HTMLInputElement) {\n return !isValidInputKey(target, key);\n }\n\n return shouldPreventDefaultUp(target);\n}\n\n/**\n * Whether to prevent default on pointer up for this element.\n */\nexport function shouldPreventDefaultUp(target: Element): boolean {\n const tagName = target.tagName.toLowerCase();\n\n // Never prevent default on form elements\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return false;\n }\n\n // Don't prevent default on links\n if (tagName === \"a\" || target.getAttribute(\"role\") === \"link\") {\n return false;\n }\n\n // Buttons with submit/reset type should not prevent default\n if (tagName === \"button\") {\n const type = (target as HTMLButtonElement).type;\n if (type === \"submit\" || type === \"reset\") {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Opens a link, supporting both same-window and new-window navigation.\n * Used for keyboard activation of links with Space key (which doesn't natively open links).\n */\nexport function openLink(target: HTMLAnchorElement, event: Event, allowOpener = false): void {\n const { href, target: linkTarget, rel } = target;\n (openLink as { isOpening?: boolean }).isOpening = true;\n\n // Handle modifier keys for open-in-new-tab behavior\n const keyEvent = event as KeyboardEvent;\n const shouldOpenInNewTab =\n linkTarget === \"_blank\" ||\n keyEvent?.metaKey ||\n keyEvent?.ctrlKey ||\n keyEvent?.shiftKey ||\n keyEvent?.altKey;\n\n if (shouldOpenInNewTab) {\n const features = !allowOpener && rel?.includes(\"noopener\") ? \"noopener\" : undefined;\n window.open(href, linkTarget || \"_blank\", features);\n } else {\n window.location.href = href;\n }\n\n (openLink as { isOpening?: boolean }).isOpening = false;\n}\n\n(openLink as { isOpening?: boolean }).isOpening = false;\n\n/**\n * Checks if an element is scrollable based on its overflow style.\n * @param node - The element to check\n * @param checkForOverflow - If true, also check if the element actually overflows\n */\nexport function isScrollable(node: Element | null, checkForOverflow?: boolean): boolean {\n if (!node) {\n return false;\n }\n\n const style = window.getComputedStyle(node);\n const scrollable = /(auto|scroll)/.test(style.overflow + style.overflowX + style.overflowY);\n\n if (scrollable && checkForOverflow) {\n return node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth;\n }\n\n return scrollable;\n}\n\n/**\n * Gets the nearest scrollable parent element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only return parents that actually overflow\n */\nexport function getScrollParent(node: Element, checkForOverflow?: boolean): Element {\n let scrollableNode: Element | null = node;\n\n if (isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n return scrollableNode || document.scrollingElement || document.documentElement;\n}\n\n/**\n * Gets every scrollable ancestor of an element, from the nearest up to (and\n * including) the document scrolling element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only include parents that actually overflow\n */\nexport function getScrollParents(node: Element, checkForOverflow?: boolean): Element[] {\n const parentElements: Element[] = [];\n const root = document.scrollingElement || document.documentElement;\n let current: Element | null = node;\n\n while (current) {\n if (isScrollable(current, checkForOverflow)) {\n parentElements.push(current);\n }\n if (current === root) {\n break;\n }\n current = current.parentElement;\n }\n\n return parentElements;\n}\n\n/**\n * Checks if an element will open a virtual keyboard when focused.\n * Used for iOS Safari scroll handling.\n */\nexport function willOpenKeyboard(target: Element | null): boolean {\n if (!target) {\n return false;\n }\n\n const tagName = target.tagName.toLowerCase();\n\n // Inputs that open keyboard (not all input types do)\n if (tagName === \"input\") {\n const type = (target as HTMLInputElement).type.toLowerCase();\n // These input types open the keyboard\n const keyboardTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n return keyboardTypes.includes(type);\n }\n\n // Textareas always open keyboard\n if (tagName === \"textarea\") {\n return true;\n }\n\n // Contenteditable elements open keyboard\n if (\n target.hasAttribute(\"contenteditable\") &&\n target.getAttribute(\"contenteditable\") !== \"false\"\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns the deepest active element, descending through open shadow roots.\n * Mirrors @react-aria/utils' `getActiveElement`.\n */\nexport function getActiveElement(doc: Document = document): Element | null {\n let activeElement = doc.activeElement;\n while (activeElement?.shadowRoot?.activeElement) {\n activeElement = activeElement.shadowRoot.activeElement;\n }\n return activeElement;\n}\n\n/**\n * Whether the (deepest) active element is `element` or is contained within it.\n * Mirrors @react-aria/utils' `isFocusWithin`.\n */\nexport function isFocusWithin(element: Element): boolean {\n const activeElement = getActiveElement(getOwnerDocument(element));\n return !!activeElement && nodeContains(element, activeElement);\n}\n\n/**\n * Creates a `TreeWalker` that visits the focusable (or, when `tabbable`, the\n * tabbable) descendants of `root`, skipping invisible and inert elements.\n * Mirrors @react-aria/focus's `getFocusableTreeWalker`, minus the focus-scope\n * containment filter (we don't model nested scopes here). Used to treat a\n * selectable collection as a single tab stop.\n */\nexport function getFocusableTreeWalker(\n root: Element,\n opts?: { tabbable?: boolean; from?: Node; accept?: (node: Element) => boolean },\n): TreeWalker {\n const accept = (node: Element) =>\n (opts?.tabbable ? isTabbable(node) : isFocusable(node)) && (!opts?.accept || opts.accept(node));\n const walker = getOwnerDocument(root).createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node) {\n // Skip nodes inside the optional starting node.\n if (opts?.from?.contains(node)) {\n return NodeFilter.FILTER_REJECT;\n }\n if (accept(node as Element)) {\n return NodeFilter.FILTER_ACCEPT;\n }\n return NodeFilter.FILTER_SKIP;\n },\n });\n if (opts?.from) {\n walker.currentNode = opts.from;\n }\n return walker;\n}\n","/**\n * Focus management utilities.\n * Based on @react-aria/utils focus utilities.\n */\n\nimport { getEventTarget, getOwnerDocument, getOwnerWindow, isFocusable } from \"./dom\";\n\n/**\n * Focuses an element without scrolling the page.\n * Uses preventScroll option with fallback for older browsers.\n */\nexport function focusWithoutScrolling(element: HTMLElement | null): void {\n if (!element) return;\n\n try {\n element.focus({ preventScroll: true });\n } catch {\n // Fallback for browsers that don't support preventScroll\n const scrollableElements = getScrollableAncestors(element);\n const scrollPositions = scrollableElements.map((el) => ({\n element: el,\n scrollTop: el.scrollTop,\n scrollLeft: el.scrollLeft,\n }));\n\n element.focus();\n\n for (const { element: el, scrollTop, scrollLeft } of scrollPositions) {\n el.scrollTop = scrollTop;\n el.scrollLeft = scrollLeft;\n }\n }\n}\n\n/**\n * Gets all scrollable ancestors of an element.\n */\nfunction getScrollableAncestors(element: Element): Element[] {\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n\n while (parent) {\n const style = getComputedStyle(parent);\n const overflowY = style.overflowY;\n const overflowX = style.overflowX;\n\n if (\n overflowY === \"auto\" ||\n overflowY === \"scroll\" ||\n overflowX === \"auto\" ||\n overflowX === \"scroll\"\n ) {\n ancestors.push(parent);\n }\n\n parent = parent.parentElement;\n }\n\n // Also include the document scrolling element\n const doc = getOwnerDocument(element);\n ancestors.push(doc.documentElement);\n\n return ancestors;\n}\n\n/**\n * Prevents focus from moving to a new element temporarily.\n * Used when clicking on a button that shouldn't steal focus.\n */\nexport function preventFocus(target: Element | null): (() => void) | undefined {\n while (target && !isFocusable(target)) {\n target = target.parentElement;\n }\n\n const ownerWindow = getOwnerWindow(target);\n const activeElement = ownerWindow.document.activeElement as HTMLElement | null;\n\n if (!activeElement || activeElement === target) {\n return undefined;\n }\n\n let isRefocusing = false;\n\n const onBlur = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusOut = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!target && !isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n const onFocus = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusIn = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n ownerWindow.addEventListener(\"blur\", onBlur, true);\n ownerWindow.addEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.addEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.addEventListener(\"focus\", onFocus, true);\n\n const raf = ownerWindow.requestAnimationFrame(cleanup);\n\n function cleanup() {\n ownerWindow.cancelAnimationFrame(raf);\n ownerWindow.removeEventListener(\"blur\", onBlur, true);\n ownerWindow.removeEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.removeEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.removeEventListener(\"focus\", onFocus, true);\n isRefocusing = false;\n }\n\n return cleanup;\n}\n\n/**\n * Safely focuses an element, alias for focusWithoutScrolling.\n * This matches the react-aria focusSafely function name.\n */\nexport const focusSafely = focusWithoutScrolling;\n"],"mappings":"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"}
|
package/dist/_chunk/focus.jsx
CHANGED
|
@@ -284,7 +284,7 @@ function isFocusWithin(element) {
|
|
|
284
284
|
* selectable collection as a single tab stop.
|
|
285
285
|
*/
|
|
286
286
|
function getFocusableTreeWalker(root, opts) {
|
|
287
|
-
const accept = (node) => opts?.tabbable ? isTabbable(node) : isFocusable(node);
|
|
287
|
+
const accept = (node) => (opts?.tabbable ? isTabbable(node) : isFocusable(node)) && (!opts?.accept || opts.accept(node));
|
|
288
288
|
const walker = getOwnerDocument(root).createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { acceptNode(node) {
|
|
289
289
|
if (opts?.from?.contains(node)) return NodeFilter.FILTER_REJECT;
|
|
290
290
|
if (accept(node)) return NodeFilter.FILTER_ACCEPT;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus.jsx","names":[],"sources":["../../src/utils/dom.ts","../../src/utils/focus.ts"],"sourcesContent":["/**\n * DOM utilities for cross-browser compatibility.\n * Based on @react-aria/utils DOM utilities.\n */\n\n/**\n * Gets the owner document of an element, or the global document.\n */\nexport function getOwnerDocument(el: Element | null | undefined): Document {\n return el?.ownerDocument ?? document;\n}\n\n/**\n * Gets the owner window of an element, or the global window.\n */\nexport function getOwnerWindow(el: Element | null | undefined): Window & typeof globalThis {\n return getOwnerDocument(el).defaultView ?? window;\n}\n\n/**\n * Cross-browser implementation of Node.contains that works with ShadowDOM.\n * In Safari, Node.contains doesn't properly detect elements inside shadow roots.\n */\nexport function nodeContains(parent: Node | null, child: Node | null): boolean {\n if (!parent || !child) {\n return false;\n }\n\n // Standard contains check\n if (parent.contains(child)) {\n return true;\n }\n\n // Check if child is in a shadow root\n let node: Node | null = child;\n while (node) {\n if (node === parent) {\n return true;\n }\n\n // Check shadow root host\n if ((node as ShadowRoot).host) {\n node = (node as ShadowRoot).host;\n } else {\n node = node.parentNode;\n }\n }\n\n return false;\n}\n\n/**\n * Gets the event target, handling composed path for shadow DOM.\n */\nexport function getEventTarget<T extends EventTarget>(event: Event): T | null {\n // Use composedPath to get the real target when using Shadow DOM\n if (typeof event.composedPath === \"function\") {\n const path = event.composedPath();\n if (path.length > 0) {\n return path[0] as T;\n }\n }\n return event.target as T | null;\n}\n\n// Ports @react-aria/utils `isElementVisible`/`isFocusable`/`isTabbable` (v3.34.1,\n// the version paired with our pinned RAC 1.19.0) so focusability matches upstream:\n// a candidate must match the focusable selector AND not be inside an `inert`\n// subtree AND be visible (unless `skipVisibilityCheck`). The previous `isFocusable`\n// was a simplified tagName/tabindex check with no visibility or `inert` filtering.\n// Owner-window lookups go through `getOwnerWindow`, which falls back to the global\n// window, so these stay robust on detached documents (`defaultView === null`).\n\nconst supportsCheckVisibility =\n typeof Element !== \"undefined\" && \"checkVisibility\" in Element.prototype;\n\n// Solid clones templates with the document that is global at creation time, so a\n// node portaled into another document (e.g. an iframe) keeps its original realm's\n// prototype even though `getOwnerWindow` now resolves to the other document's\n// window. Upstream React creates portal nodes with the container's `ownerDocument`,\n// so its single `instanceof getOwnerWindow(element)` check suffices; we also accept\n// the global realm's constructors so cross-document focus scopes still recognize\n// real elements. In the common same-realm case this is identical to upstream.\nfunction isHTMLOrSVGElement(element: Element): element is HTMLElement | SVGElement {\n const windowObject = getOwnerWindow(element);\n return (\n element instanceof windowObject.HTMLElement ||\n element instanceof windowObject.SVGElement ||\n (typeof HTMLElement !== \"undefined\" && element instanceof HTMLElement) ||\n (typeof SVGElement !== \"undefined\" && element instanceof SVGElement)\n );\n}\n\nfunction isStyleVisible(element: Element): boolean {\n if (!isHTMLOrSVGElement(element)) {\n return false;\n }\n\n const { display, visibility } = element.style;\n\n let isVisible = display !== \"none\" && visibility !== \"hidden\" && visibility !== \"collapse\";\n\n if (isVisible) {\n const { getComputedStyle } = getOwnerWindow(element);\n const { display: computedDisplay, visibility: computedVisibility } = getComputedStyle(element);\n\n isVisible =\n computedDisplay !== \"none\" &&\n computedVisibility !== \"hidden\" &&\n computedVisibility !== \"collapse\";\n }\n\n return isVisible;\n}\n\nfunction isAttributeVisible(element: Element, childElement?: Element): boolean {\n return (\n !element.hasAttribute(\"hidden\") &&\n // Ignore HiddenSelect when tree walking.\n !element.hasAttribute(\"data-react-aria-prevent-focus\") &&\n (element.nodeName === \"DETAILS\" && childElement && childElement.nodeName !== \"SUMMARY\"\n ? element.hasAttribute(\"open\")\n : true)\n );\n}\n\n/**\n * Whether an element is visible, and so eligible for focus. Adapted from\n * @react-aria/utils, which adapts testing-library/jest-dom and\n * vue-test-utils-next (MIT): uses `checkVisibility` when supported, otherwise\n * walks computed style and visibility-affecting attributes up the ancestor chain.\n */\nexport function isElementVisible(element: Element, childElement?: Element): boolean {\n if (supportsCheckVisibility) {\n return (\n element.checkVisibility({ visibilityProperty: true }) &&\n !element.closest(\"[data-react-aria-prevent-focus]\")\n );\n }\n\n return (\n element.nodeName !== \"#comment\" &&\n isStyleVisible(element) &&\n isAttributeVisible(element, childElement) &&\n (!element.parentElement || isElementVisible(element.parentElement, element))\n );\n}\n\nconst focusableElements = [\n \"input:not([disabled]):not([type=hidden])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"button:not([disabled])\",\n \"a[href]\",\n \"area[href]\",\n \"summary\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"audio[controls]\",\n \"video[controls]\",\n '[contenteditable]:not([contenteditable^=\"false\"])',\n \"permission\",\n];\n\nconst FOCUSABLE_ELEMENT_SELECTOR =\n focusableElements.join(\":not([hidden]),\") + \",[tabindex]:not([disabled]):not([hidden])\";\n\nfocusableElements.push('[tabindex]:not([tabindex=\"-1\"]):not([disabled])');\nconst TABBABLE_ELEMENT_SELECTOR = focusableElements.join(':not([hidden]):not([tabindex=\"-1\"]),');\n\n/**\n * Checks if an element is a valid focusable element: it matches the focusable\n * selector, is not inside an `inert` subtree, and is visible. A negative tabindex\n * is programmatically focusable (matched here) but not tabbable. `skipVisibilityCheck`\n * lets callers (e.g. the press-path `preventFocus` ancestor walk) skip the\n * `isElementVisible` step, which also avoids touching layout on detached documents.\n */\nexport function isFocusable(\n element: Element,\n options?: { skipVisibilityCheck?: boolean },\n): boolean {\n return (\n element.matches(FOCUSABLE_ELEMENT_SELECTOR) &&\n !isInert(element) &&\n (options?.skipVisibilityCheck || isElementVisible(element))\n );\n}\n\n/**\n * Checks if an element is tabbable (reachable via the Tab key): focusable,\n * visible, not inert, and not `tabindex=\"-1\"`.\n */\nexport function isTabbable(element: Element): boolean {\n return (\n element.matches(TABBABLE_ELEMENT_SELECTOR) && isElementVisible(element) && !isInert(element)\n );\n}\n\nfunction isInert(element: Element): boolean {\n let node: Element | null = element;\n while (node != null) {\n // Realm-tolerant HTMLElement check (see isHTMLOrSVGElement): Solid-portaled\n // nodes keep their creating realm's prototype, so also accept the global one.\n const isHTMLElement =\n node instanceof getOwnerWindow(node).HTMLElement ||\n (typeof HTMLElement !== \"undefined\" && node instanceof HTMLElement);\n if (isHTMLElement && (node as HTMLElement).inert) {\n return true;\n }\n\n node = node.parentElement;\n }\n\n return false;\n}\n\n/**\n * Checks if a keyboard event should trigger the default action (like clicking).\n */\nexport function isValidKeyboardEvent(event: KeyboardEvent, currentTarget: Element): boolean {\n const { key, code } = event;\n const element = currentTarget as HTMLElement;\n const tagName = element.tagName.toLowerCase();\n const role = element.getAttribute(\"role\");\n\n // Only accept Enter and Space\n const isActivationKey = key === \"Enter\" || key === \" \" || key === \"Spacebar\" || code === \"Space\";\n if (!isActivationKey) {\n return false;\n }\n\n // Text inputs should handle their own keyboard events\n if (tagName === \"textarea\") {\n return false;\n }\n\n // Content editable elements should handle their own keyboard events\n if (element.isContentEditable) {\n return false;\n }\n\n // Links should only respond to Enter, not Space\n const isLink = role === \"link\" || (!role && isHTMLAnchorLink(element));\n if (isLink && key !== \"Enter\") {\n return false;\n }\n\n // Input elements have specific key handling\n if (tagName === \"input\") {\n return isValidInputKey(element as HTMLInputElement, key);\n }\n\n return true;\n}\n\n/**\n * Checks if a key is valid for a specific input type.\n */\nexport function isValidInputKey(target: HTMLInputElement, key: string): boolean {\n const type = target.type.toLowerCase();\n\n // Checkbox and radio only respond to Space\n if (type === \"checkbox\" || type === \"radio\") {\n return key === \" \" || key === \"Spacebar\";\n }\n\n // Text-like inputs handle their own keyboard events\n const textInputTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n if (textInputTypes.includes(type)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks if an element is an HTML anchor link (has href attribute).\n */\nexport function isHTMLAnchorLink(target: Element): boolean {\n return target.tagName === \"A\" && target.hasAttribute(\"href\");\n}\n\n/**\n * Whether to prevent default on keyboard events for this element.\n */\nexport function shouldPreventDefaultKeyboard(target: Element, key: string): boolean {\n if (target instanceof HTMLInputElement) {\n return !isValidInputKey(target, key);\n }\n\n return shouldPreventDefaultUp(target);\n}\n\n/**\n * Whether to prevent default on pointer up for this element.\n */\nexport function shouldPreventDefaultUp(target: Element): boolean {\n const tagName = target.tagName.toLowerCase();\n\n // Never prevent default on form elements\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return false;\n }\n\n // Don't prevent default on links\n if (tagName === \"a\" || target.getAttribute(\"role\") === \"link\") {\n return false;\n }\n\n // Buttons with submit/reset type should not prevent default\n if (tagName === \"button\") {\n const type = (target as HTMLButtonElement).type;\n if (type === \"submit\" || type === \"reset\") {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Opens a link, supporting both same-window and new-window navigation.\n * Used for keyboard activation of links with Space key (which doesn't natively open links).\n */\nexport function openLink(target: HTMLAnchorElement, event: Event, allowOpener = false): void {\n const { href, target: linkTarget, rel } = target;\n (openLink as { isOpening?: boolean }).isOpening = true;\n\n // Handle modifier keys for open-in-new-tab behavior\n const keyEvent = event as KeyboardEvent;\n const shouldOpenInNewTab =\n linkTarget === \"_blank\" ||\n keyEvent?.metaKey ||\n keyEvent?.ctrlKey ||\n keyEvent?.shiftKey ||\n keyEvent?.altKey;\n\n if (shouldOpenInNewTab) {\n const features = !allowOpener && rel?.includes(\"noopener\") ? \"noopener\" : undefined;\n window.open(href, linkTarget || \"_blank\", features);\n } else {\n window.location.href = href;\n }\n\n (openLink as { isOpening?: boolean }).isOpening = false;\n}\n\n(openLink as { isOpening?: boolean }).isOpening = false;\n\n/**\n * Checks if an element is scrollable based on its overflow style.\n * @param node - The element to check\n * @param checkForOverflow - If true, also check if the element actually overflows\n */\nexport function isScrollable(node: Element | null, checkForOverflow?: boolean): boolean {\n if (!node) {\n return false;\n }\n\n const style = window.getComputedStyle(node);\n const scrollable = /(auto|scroll)/.test(style.overflow + style.overflowX + style.overflowY);\n\n if (scrollable && checkForOverflow) {\n return node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth;\n }\n\n return scrollable;\n}\n\n/**\n * Gets the nearest scrollable parent element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only return parents that actually overflow\n */\nexport function getScrollParent(node: Element, checkForOverflow?: boolean): Element {\n let scrollableNode: Element | null = node;\n\n if (isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n return scrollableNode || document.scrollingElement || document.documentElement;\n}\n\n/**\n * Gets every scrollable ancestor of an element, from the nearest up to (and\n * including) the document scrolling element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only include parents that actually overflow\n */\nexport function getScrollParents(node: Element, checkForOverflow?: boolean): Element[] {\n const parentElements: Element[] = [];\n const root = document.scrollingElement || document.documentElement;\n let current: Element | null = node;\n\n while (current) {\n if (isScrollable(current, checkForOverflow)) {\n parentElements.push(current);\n }\n if (current === root) {\n break;\n }\n current = current.parentElement;\n }\n\n return parentElements;\n}\n\n/**\n * Checks if an element will open a virtual keyboard when focused.\n * Used for iOS Safari scroll handling.\n */\nexport function willOpenKeyboard(target: Element | null): boolean {\n if (!target) {\n return false;\n }\n\n const tagName = target.tagName.toLowerCase();\n\n // Inputs that open keyboard (not all input types do)\n if (tagName === \"input\") {\n const type = (target as HTMLInputElement).type.toLowerCase();\n // These input types open the keyboard\n const keyboardTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n return keyboardTypes.includes(type);\n }\n\n // Textareas always open keyboard\n if (tagName === \"textarea\") {\n return true;\n }\n\n // Contenteditable elements open keyboard\n if (\n target.hasAttribute(\"contenteditable\") &&\n target.getAttribute(\"contenteditable\") !== \"false\"\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns the deepest active element, descending through open shadow roots.\n * Mirrors @react-aria/utils' `getActiveElement`.\n */\nexport function getActiveElement(doc: Document = document): Element | null {\n let activeElement = doc.activeElement;\n while (activeElement?.shadowRoot?.activeElement) {\n activeElement = activeElement.shadowRoot.activeElement;\n }\n return activeElement;\n}\n\n/**\n * Whether the (deepest) active element is `element` or is contained within it.\n * Mirrors @react-aria/utils' `isFocusWithin`.\n */\nexport function isFocusWithin(element: Element): boolean {\n const activeElement = getActiveElement(getOwnerDocument(element));\n return !!activeElement && nodeContains(element, activeElement);\n}\n\n/**\n * Creates a `TreeWalker` that visits the focusable (or, when `tabbable`, the\n * tabbable) descendants of `root`, skipping invisible and inert elements.\n * Mirrors @react-aria/focus's `getFocusableTreeWalker`, minus the focus-scope\n * containment filter (we don't model nested scopes here). Used to treat a\n * selectable collection as a single tab stop.\n */\nexport function getFocusableTreeWalker(\n root: Element,\n opts?: { tabbable?: boolean; from?: Node },\n): TreeWalker {\n const accept = (node: Element) => (opts?.tabbable ? isTabbable(node) : isFocusable(node));\n const walker = getOwnerDocument(root).createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node) {\n // Skip nodes inside the optional starting node.\n if (opts?.from?.contains(node)) {\n return NodeFilter.FILTER_REJECT;\n }\n if (accept(node as Element)) {\n return NodeFilter.FILTER_ACCEPT;\n }\n return NodeFilter.FILTER_SKIP;\n },\n });\n if (opts?.from) {\n walker.currentNode = opts.from;\n }\n return walker;\n}\n","/**\n * Focus management utilities.\n * Based on @react-aria/utils focus utilities.\n */\n\nimport { getEventTarget, getOwnerDocument, getOwnerWindow, isFocusable } from \"./dom\";\n\n/**\n * Focuses an element without scrolling the page.\n * Uses preventScroll option with fallback for older browsers.\n */\nexport function focusWithoutScrolling(element: HTMLElement | null): void {\n if (!element) return;\n\n try {\n element.focus({ preventScroll: true });\n } catch {\n // Fallback for browsers that don't support preventScroll\n const scrollableElements = getScrollableAncestors(element);\n const scrollPositions = scrollableElements.map((el) => ({\n element: el,\n scrollTop: el.scrollTop,\n scrollLeft: el.scrollLeft,\n }));\n\n element.focus();\n\n for (const { element: el, scrollTop, scrollLeft } of scrollPositions) {\n el.scrollTop = scrollTop;\n el.scrollLeft = scrollLeft;\n }\n }\n}\n\n/**\n * Gets all scrollable ancestors of an element.\n */\nfunction getScrollableAncestors(element: Element): Element[] {\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n\n while (parent) {\n const style = getComputedStyle(parent);\n const overflowY = style.overflowY;\n const overflowX = style.overflowX;\n\n if (\n overflowY === \"auto\" ||\n overflowY === \"scroll\" ||\n overflowX === \"auto\" ||\n overflowX === \"scroll\"\n ) {\n ancestors.push(parent);\n }\n\n parent = parent.parentElement;\n }\n\n // Also include the document scrolling element\n const doc = getOwnerDocument(element);\n ancestors.push(doc.documentElement);\n\n return ancestors;\n}\n\n/**\n * Prevents focus from moving to a new element temporarily.\n * Used when clicking on a button that shouldn't steal focus.\n */\nexport function preventFocus(target: Element | null): (() => void) | undefined {\n while (target && !isFocusable(target)) {\n target = target.parentElement;\n }\n\n const ownerWindow = getOwnerWindow(target);\n const activeElement = ownerWindow.document.activeElement as HTMLElement | null;\n\n if (!activeElement || activeElement === target) {\n return undefined;\n }\n\n let isRefocusing = false;\n\n const onBlur = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusOut = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!target && !isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n const onFocus = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusIn = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n ownerWindow.addEventListener(\"blur\", onBlur, true);\n ownerWindow.addEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.addEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.addEventListener(\"focus\", onFocus, true);\n\n const raf = ownerWindow.requestAnimationFrame(cleanup);\n\n function cleanup() {\n ownerWindow.cancelAnimationFrame(raf);\n ownerWindow.removeEventListener(\"blur\", onBlur, true);\n ownerWindow.removeEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.removeEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.removeEventListener(\"focus\", onFocus, true);\n isRefocusing = false;\n }\n\n return cleanup;\n}\n\n/**\n * Safely focuses an element, alias for focusWithoutScrolling.\n * This matches the react-aria focusSafely function name.\n */\nexport const focusSafely = focusWithoutScrolling;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"focus.jsx","names":[],"sources":["../../src/utils/dom.ts","../../src/utils/focus.ts"],"sourcesContent":["/**\n * DOM utilities for cross-browser compatibility.\n * Based on @react-aria/utils DOM utilities.\n */\n\n/**\n * Gets the owner document of an element, or the global document.\n */\nexport function getOwnerDocument(el: Element | null | undefined): Document {\n return el?.ownerDocument ?? document;\n}\n\n/**\n * Gets the owner window of an element, or the global window.\n */\nexport function getOwnerWindow(el: Element | null | undefined): Window & typeof globalThis {\n return getOwnerDocument(el).defaultView ?? window;\n}\n\n/**\n * Cross-browser implementation of Node.contains that works with ShadowDOM.\n * In Safari, Node.contains doesn't properly detect elements inside shadow roots.\n */\nexport function nodeContains(parent: Node | null, child: Node | null): boolean {\n if (!parent || !child) {\n return false;\n }\n\n // Standard contains check\n if (parent.contains(child)) {\n return true;\n }\n\n // Check if child is in a shadow root\n let node: Node | null = child;\n while (node) {\n if (node === parent) {\n return true;\n }\n\n // Check shadow root host\n if ((node as ShadowRoot).host) {\n node = (node as ShadowRoot).host;\n } else {\n node = node.parentNode;\n }\n }\n\n return false;\n}\n\n/**\n * Gets the event target, handling composed path for shadow DOM.\n */\nexport function getEventTarget<T extends EventTarget>(event: Event): T | null {\n // Use composedPath to get the real target when using Shadow DOM\n if (typeof event.composedPath === \"function\") {\n const path = event.composedPath();\n if (path.length > 0) {\n return path[0] as T;\n }\n }\n return event.target as T | null;\n}\n\n// Ports @react-aria/utils `isElementVisible`/`isFocusable`/`isTabbable` (v3.34.1,\n// the version paired with our pinned RAC 1.19.0) so focusability matches upstream:\n// a candidate must match the focusable selector AND not be inside an `inert`\n// subtree AND be visible (unless `skipVisibilityCheck`). The previous `isFocusable`\n// was a simplified tagName/tabindex check with no visibility or `inert` filtering.\n// Owner-window lookups go through `getOwnerWindow`, which falls back to the global\n// window, so these stay robust on detached documents (`defaultView === null`).\n\nconst supportsCheckVisibility =\n typeof Element !== \"undefined\" && \"checkVisibility\" in Element.prototype;\n\n// Solid clones templates with the document that is global at creation time, so a\n// node portaled into another document (e.g. an iframe) keeps its original realm's\n// prototype even though `getOwnerWindow` now resolves to the other document's\n// window. Upstream React creates portal nodes with the container's `ownerDocument`,\n// so its single `instanceof getOwnerWindow(element)` check suffices; we also accept\n// the global realm's constructors so cross-document focus scopes still recognize\n// real elements. In the common same-realm case this is identical to upstream.\nfunction isHTMLOrSVGElement(element: Element): element is HTMLElement | SVGElement {\n const windowObject = getOwnerWindow(element);\n return (\n element instanceof windowObject.HTMLElement ||\n element instanceof windowObject.SVGElement ||\n (typeof HTMLElement !== \"undefined\" && element instanceof HTMLElement) ||\n (typeof SVGElement !== \"undefined\" && element instanceof SVGElement)\n );\n}\n\nfunction isStyleVisible(element: Element): boolean {\n if (!isHTMLOrSVGElement(element)) {\n return false;\n }\n\n const { display, visibility } = element.style;\n\n let isVisible = display !== \"none\" && visibility !== \"hidden\" && visibility !== \"collapse\";\n\n if (isVisible) {\n const { getComputedStyle } = getOwnerWindow(element);\n const { display: computedDisplay, visibility: computedVisibility } = getComputedStyle(element);\n\n isVisible =\n computedDisplay !== \"none\" &&\n computedVisibility !== \"hidden\" &&\n computedVisibility !== \"collapse\";\n }\n\n return isVisible;\n}\n\nfunction isAttributeVisible(element: Element, childElement?: Element): boolean {\n return (\n !element.hasAttribute(\"hidden\") &&\n // Ignore HiddenSelect when tree walking.\n !element.hasAttribute(\"data-react-aria-prevent-focus\") &&\n (element.nodeName === \"DETAILS\" && childElement && childElement.nodeName !== \"SUMMARY\"\n ? element.hasAttribute(\"open\")\n : true)\n );\n}\n\n/**\n * Whether an element is visible, and so eligible for focus. Adapted from\n * @react-aria/utils, which adapts testing-library/jest-dom and\n * vue-test-utils-next (MIT): uses `checkVisibility` when supported, otherwise\n * walks computed style and visibility-affecting attributes up the ancestor chain.\n */\nexport function isElementVisible(element: Element, childElement?: Element): boolean {\n if (supportsCheckVisibility) {\n return (\n element.checkVisibility({ visibilityProperty: true }) &&\n !element.closest(\"[data-react-aria-prevent-focus]\")\n );\n }\n\n return (\n element.nodeName !== \"#comment\" &&\n isStyleVisible(element) &&\n isAttributeVisible(element, childElement) &&\n (!element.parentElement || isElementVisible(element.parentElement, element))\n );\n}\n\nconst focusableElements = [\n \"input:not([disabled]):not([type=hidden])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"button:not([disabled])\",\n \"a[href]\",\n \"area[href]\",\n \"summary\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"audio[controls]\",\n \"video[controls]\",\n '[contenteditable]:not([contenteditable^=\"false\"])',\n \"permission\",\n];\n\nconst FOCUSABLE_ELEMENT_SELECTOR =\n focusableElements.join(\":not([hidden]),\") + \",[tabindex]:not([disabled]):not([hidden])\";\n\nfocusableElements.push('[tabindex]:not([tabindex=\"-1\"]):not([disabled])');\nconst TABBABLE_ELEMENT_SELECTOR = focusableElements.join(':not([hidden]):not([tabindex=\"-1\"]),');\n\n/**\n * Checks if an element is a valid focusable element: it matches the focusable\n * selector, is not inside an `inert` subtree, and is visible. A negative tabindex\n * is programmatically focusable (matched here) but not tabbable. `skipVisibilityCheck`\n * lets callers (e.g. the press-path `preventFocus` ancestor walk) skip the\n * `isElementVisible` step, which also avoids touching layout on detached documents.\n */\nexport function isFocusable(\n element: Element,\n options?: { skipVisibilityCheck?: boolean },\n): boolean {\n return (\n element.matches(FOCUSABLE_ELEMENT_SELECTOR) &&\n !isInert(element) &&\n (options?.skipVisibilityCheck || isElementVisible(element))\n );\n}\n\n/**\n * Checks if an element is tabbable (reachable via the Tab key): focusable,\n * visible, not inert, and not `tabindex=\"-1\"`.\n */\nexport function isTabbable(element: Element): boolean {\n return (\n element.matches(TABBABLE_ELEMENT_SELECTOR) && isElementVisible(element) && !isInert(element)\n );\n}\n\nfunction isInert(element: Element): boolean {\n let node: Element | null = element;\n while (node != null) {\n // Realm-tolerant HTMLElement check (see isHTMLOrSVGElement): Solid-portaled\n // nodes keep their creating realm's prototype, so also accept the global one.\n const isHTMLElement =\n node instanceof getOwnerWindow(node).HTMLElement ||\n (typeof HTMLElement !== \"undefined\" && node instanceof HTMLElement);\n if (isHTMLElement && (node as HTMLElement).inert) {\n return true;\n }\n\n node = node.parentElement;\n }\n\n return false;\n}\n\n/**\n * Checks if a keyboard event should trigger the default action (like clicking).\n */\nexport function isValidKeyboardEvent(event: KeyboardEvent, currentTarget: Element): boolean {\n const { key, code } = event;\n const element = currentTarget as HTMLElement;\n const tagName = element.tagName.toLowerCase();\n const role = element.getAttribute(\"role\");\n\n // Only accept Enter and Space\n const isActivationKey = key === \"Enter\" || key === \" \" || key === \"Spacebar\" || code === \"Space\";\n if (!isActivationKey) {\n return false;\n }\n\n // Text inputs should handle their own keyboard events\n if (tagName === \"textarea\") {\n return false;\n }\n\n // Content editable elements should handle their own keyboard events\n if (element.isContentEditable) {\n return false;\n }\n\n // Links should only respond to Enter, not Space\n const isLink = role === \"link\" || (!role && isHTMLAnchorLink(element));\n if (isLink && key !== \"Enter\") {\n return false;\n }\n\n // Input elements have specific key handling\n if (tagName === \"input\") {\n return isValidInputKey(element as HTMLInputElement, key);\n }\n\n return true;\n}\n\n/**\n * Checks if a key is valid for a specific input type.\n */\nexport function isValidInputKey(target: HTMLInputElement, key: string): boolean {\n const type = target.type.toLowerCase();\n\n // Checkbox and radio only respond to Space\n if (type === \"checkbox\" || type === \"radio\") {\n return key === \" \" || key === \"Spacebar\";\n }\n\n // Text-like inputs handle their own keyboard events\n const textInputTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n if (textInputTypes.includes(type)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks if an element is an HTML anchor link (has href attribute).\n */\nexport function isHTMLAnchorLink(target: Element): boolean {\n return target.tagName === \"A\" && target.hasAttribute(\"href\");\n}\n\n/**\n * Whether to prevent default on keyboard events for this element.\n */\nexport function shouldPreventDefaultKeyboard(target: Element, key: string): boolean {\n if (target instanceof HTMLInputElement) {\n return !isValidInputKey(target, key);\n }\n\n return shouldPreventDefaultUp(target);\n}\n\n/**\n * Whether to prevent default on pointer up for this element.\n */\nexport function shouldPreventDefaultUp(target: Element): boolean {\n const tagName = target.tagName.toLowerCase();\n\n // Never prevent default on form elements\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return false;\n }\n\n // Don't prevent default on links\n if (tagName === \"a\" || target.getAttribute(\"role\") === \"link\") {\n return false;\n }\n\n // Buttons with submit/reset type should not prevent default\n if (tagName === \"button\") {\n const type = (target as HTMLButtonElement).type;\n if (type === \"submit\" || type === \"reset\") {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Opens a link, supporting both same-window and new-window navigation.\n * Used for keyboard activation of links with Space key (which doesn't natively open links).\n */\nexport function openLink(target: HTMLAnchorElement, event: Event, allowOpener = false): void {\n const { href, target: linkTarget, rel } = target;\n (openLink as { isOpening?: boolean }).isOpening = true;\n\n // Handle modifier keys for open-in-new-tab behavior\n const keyEvent = event as KeyboardEvent;\n const shouldOpenInNewTab =\n linkTarget === \"_blank\" ||\n keyEvent?.metaKey ||\n keyEvent?.ctrlKey ||\n keyEvent?.shiftKey ||\n keyEvent?.altKey;\n\n if (shouldOpenInNewTab) {\n const features = !allowOpener && rel?.includes(\"noopener\") ? \"noopener\" : undefined;\n window.open(href, linkTarget || \"_blank\", features);\n } else {\n window.location.href = href;\n }\n\n (openLink as { isOpening?: boolean }).isOpening = false;\n}\n\n(openLink as { isOpening?: boolean }).isOpening = false;\n\n/**\n * Checks if an element is scrollable based on its overflow style.\n * @param node - The element to check\n * @param checkForOverflow - If true, also check if the element actually overflows\n */\nexport function isScrollable(node: Element | null, checkForOverflow?: boolean): boolean {\n if (!node) {\n return false;\n }\n\n const style = window.getComputedStyle(node);\n const scrollable = /(auto|scroll)/.test(style.overflow + style.overflowX + style.overflowY);\n\n if (scrollable && checkForOverflow) {\n return node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth;\n }\n\n return scrollable;\n}\n\n/**\n * Gets the nearest scrollable parent element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only return parents that actually overflow\n */\nexport function getScrollParent(node: Element, checkForOverflow?: boolean): Element {\n let scrollableNode: Element | null = node;\n\n if (isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {\n scrollableNode = scrollableNode.parentElement;\n }\n\n return scrollableNode || document.scrollingElement || document.documentElement;\n}\n\n/**\n * Gets every scrollable ancestor of an element, from the nearest up to (and\n * including) the document scrolling element.\n * @param node - The starting element\n * @param checkForOverflow - If true, only include parents that actually overflow\n */\nexport function getScrollParents(node: Element, checkForOverflow?: boolean): Element[] {\n const parentElements: Element[] = [];\n const root = document.scrollingElement || document.documentElement;\n let current: Element | null = node;\n\n while (current) {\n if (isScrollable(current, checkForOverflow)) {\n parentElements.push(current);\n }\n if (current === root) {\n break;\n }\n current = current.parentElement;\n }\n\n return parentElements;\n}\n\n/**\n * Checks if an element will open a virtual keyboard when focused.\n * Used for iOS Safari scroll handling.\n */\nexport function willOpenKeyboard(target: Element | null): boolean {\n if (!target) {\n return false;\n }\n\n const tagName = target.tagName.toLowerCase();\n\n // Inputs that open keyboard (not all input types do)\n if (tagName === \"input\") {\n const type = (target as HTMLInputElement).type.toLowerCase();\n // These input types open the keyboard\n const keyboardTypes = [\n \"text\",\n \"search\",\n \"url\",\n \"tel\",\n \"email\",\n \"password\",\n \"date\",\n \"month\",\n \"week\",\n \"time\",\n \"datetime-local\",\n \"number\",\n ];\n return keyboardTypes.includes(type);\n }\n\n // Textareas always open keyboard\n if (tagName === \"textarea\") {\n return true;\n }\n\n // Contenteditable elements open keyboard\n if (\n target.hasAttribute(\"contenteditable\") &&\n target.getAttribute(\"contenteditable\") !== \"false\"\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns the deepest active element, descending through open shadow roots.\n * Mirrors @react-aria/utils' `getActiveElement`.\n */\nexport function getActiveElement(doc: Document = document): Element | null {\n let activeElement = doc.activeElement;\n while (activeElement?.shadowRoot?.activeElement) {\n activeElement = activeElement.shadowRoot.activeElement;\n }\n return activeElement;\n}\n\n/**\n * Whether the (deepest) active element is `element` or is contained within it.\n * Mirrors @react-aria/utils' `isFocusWithin`.\n */\nexport function isFocusWithin(element: Element): boolean {\n const activeElement = getActiveElement(getOwnerDocument(element));\n return !!activeElement && nodeContains(element, activeElement);\n}\n\n/**\n * Creates a `TreeWalker` that visits the focusable (or, when `tabbable`, the\n * tabbable) descendants of `root`, skipping invisible and inert elements.\n * Mirrors @react-aria/focus's `getFocusableTreeWalker`, minus the focus-scope\n * containment filter (we don't model nested scopes here). Used to treat a\n * selectable collection as a single tab stop.\n */\nexport function getFocusableTreeWalker(\n root: Element,\n opts?: { tabbable?: boolean; from?: Node; accept?: (node: Element) => boolean },\n): TreeWalker {\n const accept = (node: Element) =>\n (opts?.tabbable ? isTabbable(node) : isFocusable(node)) && (!opts?.accept || opts.accept(node));\n const walker = getOwnerDocument(root).createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {\n acceptNode(node) {\n // Skip nodes inside the optional starting node.\n if (opts?.from?.contains(node)) {\n return NodeFilter.FILTER_REJECT;\n }\n if (accept(node as Element)) {\n return NodeFilter.FILTER_ACCEPT;\n }\n return NodeFilter.FILTER_SKIP;\n },\n });\n if (opts?.from) {\n walker.currentNode = opts.from;\n }\n return walker;\n}\n","/**\n * Focus management utilities.\n * Based on @react-aria/utils focus utilities.\n */\n\nimport { getEventTarget, getOwnerDocument, getOwnerWindow, isFocusable } from \"./dom\";\n\n/**\n * Focuses an element without scrolling the page.\n * Uses preventScroll option with fallback for older browsers.\n */\nexport function focusWithoutScrolling(element: HTMLElement | null): void {\n if (!element) return;\n\n try {\n element.focus({ preventScroll: true });\n } catch {\n // Fallback for browsers that don't support preventScroll\n const scrollableElements = getScrollableAncestors(element);\n const scrollPositions = scrollableElements.map((el) => ({\n element: el,\n scrollTop: el.scrollTop,\n scrollLeft: el.scrollLeft,\n }));\n\n element.focus();\n\n for (const { element: el, scrollTop, scrollLeft } of scrollPositions) {\n el.scrollTop = scrollTop;\n el.scrollLeft = scrollLeft;\n }\n }\n}\n\n/**\n * Gets all scrollable ancestors of an element.\n */\nfunction getScrollableAncestors(element: Element): Element[] {\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n\n while (parent) {\n const style = getComputedStyle(parent);\n const overflowY = style.overflowY;\n const overflowX = style.overflowX;\n\n if (\n overflowY === \"auto\" ||\n overflowY === \"scroll\" ||\n overflowX === \"auto\" ||\n overflowX === \"scroll\"\n ) {\n ancestors.push(parent);\n }\n\n parent = parent.parentElement;\n }\n\n // Also include the document scrolling element\n const doc = getOwnerDocument(element);\n ancestors.push(doc.documentElement);\n\n return ancestors;\n}\n\n/**\n * Prevents focus from moving to a new element temporarily.\n * Used when clicking on a button that shouldn't steal focus.\n */\nexport function preventFocus(target: Element | null): (() => void) | undefined {\n while (target && !isFocusable(target)) {\n target = target.parentElement;\n }\n\n const ownerWindow = getOwnerWindow(target);\n const activeElement = ownerWindow.document.activeElement as HTMLElement | null;\n\n if (!activeElement || activeElement === target) {\n return undefined;\n }\n\n let isRefocusing = false;\n\n const onBlur = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusOut = (event: FocusEvent) => {\n if (getEventTarget(event) === activeElement || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!target && !isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n const onFocus = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n }\n };\n\n const onFocusIn = (event: FocusEvent) => {\n if (getEventTarget(event) === target || isRefocusing) {\n event.stopImmediatePropagation();\n\n if (!isRefocusing) {\n isRefocusing = true;\n focusWithoutScrolling(activeElement);\n cleanup();\n }\n }\n };\n\n ownerWindow.addEventListener(\"blur\", onBlur, true);\n ownerWindow.addEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.addEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.addEventListener(\"focus\", onFocus, true);\n\n const raf = ownerWindow.requestAnimationFrame(cleanup);\n\n function cleanup() {\n ownerWindow.cancelAnimationFrame(raf);\n ownerWindow.removeEventListener(\"blur\", onBlur, true);\n ownerWindow.removeEventListener(\"focusout\", onFocusOut, true);\n ownerWindow.removeEventListener(\"focusin\", onFocusIn, true);\n ownerWindow.removeEventListener(\"focus\", onFocus, true);\n isRefocusing = false;\n }\n\n return cleanup;\n}\n\n/**\n * Safely focuses an element, alias for focusWithoutScrolling.\n * This matches the react-aria focusSafely function name.\n */\nexport const focusSafely = focusWithoutScrolling;\n"],"mappings":"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"}
|