@proyecto-viviana/solidaria 0.4.0 → 0.4.1
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/tabs.jsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as createPress } from "./createPress.jsx";
|
|
2
2
|
import { t as createFocusRing } from "./createFocusRing.jsx";
|
|
3
3
|
import { t as createHover } from "./createHover.jsx";
|
|
4
|
-
import {
|
|
4
|
+
import { i as useLocale } from "./locale.jsx";
|
|
5
5
|
import { createId } from "../ssr/index.jsx";
|
|
6
|
-
import { createEffect, createMemo } from "solid-js";
|
|
6
|
+
import { batch, createEffect, createMemo } from "solid-js";
|
|
7
7
|
//#region src/tabs/createTabs.ts
|
|
8
8
|
/**
|
|
9
9
|
* ARIA hooks for tab components.
|
|
@@ -98,8 +98,10 @@ function createTabList(props, state) {
|
|
|
98
98
|
}
|
|
99
99
|
if (nextKey !== null) {
|
|
100
100
|
e.preventDefault();
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
batch(() => {
|
|
102
|
+
state.setFocusedKey(nextKey);
|
|
103
|
+
if (keyboardActivation() === "automatic") state.setSelectedKey(nextKey);
|
|
104
|
+
});
|
|
103
105
|
}
|
|
104
106
|
};
|
|
105
107
|
const handleFocus = () => {
|
|
@@ -135,9 +137,7 @@ function createTab(props, state, ref) {
|
|
|
135
137
|
const isKeyFocused = createMemo(() => state.focusedKey() === key());
|
|
136
138
|
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
137
139
|
const selectTab = () => {
|
|
138
|
-
|
|
139
|
-
state.setFocusedKey(tabKey);
|
|
140
|
-
state.setSelectedKey(tabKey);
|
|
140
|
+
state.setSelectedKey(key());
|
|
141
141
|
};
|
|
142
142
|
const { isPressed, pressProps } = createPress({
|
|
143
143
|
get isDisabled() {
|
|
@@ -163,9 +163,11 @@ function createTab(props, state, ref) {
|
|
|
163
163
|
if (Array.isArray(handler) && handler.length >= 2 && typeof handler[1] === "function") handler[1].call(handler[0], event);
|
|
164
164
|
};
|
|
165
165
|
const handleFocus = (e) => {
|
|
166
|
-
state.setFocusedKey(key());
|
|
167
166
|
callHandler(focusProps.onFocus, e);
|
|
168
167
|
};
|
|
168
|
+
const handleFocusIn = () => {
|
|
169
|
+
state.setFocusedKey(key());
|
|
170
|
+
};
|
|
169
171
|
const handleBlur = (e) => {
|
|
170
172
|
callHandler(focusProps.onBlur, e);
|
|
171
173
|
};
|
|
@@ -210,6 +212,7 @@ function createTab(props, state, ref) {
|
|
|
210
212
|
onPointerDown: handlePointerDown,
|
|
211
213
|
onClick: handleClick,
|
|
212
214
|
onFocus: handleFocus,
|
|
215
|
+
onFocusIn: handleFocusIn,
|
|
213
216
|
onBlur: handleBlur
|
|
214
217
|
},
|
|
215
218
|
isSelected,
|
package/dist/_chunk/tabs.jsx.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.jsx","names":[],"sources":["../../src/tabs/createTabs.ts"],"sourcesContent":["/**\n * ARIA hooks for tab components.\n * Based on @react-aria/tabs.\n */\n\nimport { type Accessor, createEffect, createMemo } from \"solid-js\";\nimport { createFocusRing } from \"../interactions\";\nimport { createPress } from \"../interactions\";\nimport { createHover } from \"../interactions\";\nimport { createId } from \"../ssr\";\nimport { useLocale } from \"../i18n\";\nimport type { Key, Collection, CollectionNode } from \"@proyecto-viviana/solid-stately\";\n\nexport type TabOrientation = \"horizontal\" | \"vertical\";\nexport type KeyboardActivation = \"automatic\" | \"manual\";\n\nexport interface TabListState<T = unknown> {\n collection: Accessor<Collection<T>>;\n selectedKey: Accessor<Key | null>;\n setSelectedKey(key: Key): void;\n selectedItem: Accessor<CollectionNode<T> | null>;\n isDisabled: Accessor<boolean>;\n keyboardActivation: Accessor<KeyboardActivation>;\n orientation: Accessor<TabOrientation>;\n isKeyDisabled(key: Key): boolean;\n disabledKeys: Accessor<Set<Key>>;\n isFocused: Accessor<boolean>;\n setFocused(isFocused: boolean): void;\n focusedKey: Accessor<Key | null>;\n setFocusedKey(key: Key | null): void;\n}\n\nexport interface AriaTabListProps {\n /** The orientation of the tab list. */\n orientation?: TabOrientation;\n /** How tabs are activated (on focus or on click). */\n keyboardActivation?: KeyboardActivation;\n /** Whether the tab list is disabled. */\n isDisabled?: boolean;\n /** Label for the tab list. */\n \"aria-label\"?: string;\n /** ID of element that labels the tab list. */\n \"aria-labelledby\"?: string;\n /** ID of element that describes the tab list. */\n \"aria-describedby\"?: string;\n}\n\nexport interface TabListAria {\n /** Props for the tab list container element. */\n tabListProps: {\n role: \"tablist\";\n \"aria-orientation\": TabOrientation;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n onKeyDown: (e: KeyboardEvent) => void;\n // React's bubbling onFocus/onBlur map to focusin/focusout in Solid; the\n // tab list must observe focus entering/leaving its child tabs.\n onFocusIn: (e: FocusEvent) => void;\n onFocusOut: (e: FocusEvent) => void;\n };\n}\n\nexport interface AriaTabProps {\n /** The key of the tab. */\n key: Key;\n /** Whether the tab is disabled. */\n isDisabled?: boolean;\n /** Label for the tab. */\n \"aria-label\"?: string;\n /** ID reference for the tab label. */\n \"aria-labelledby\"?: string;\n}\n\nexport interface TabAria {\n /** Props for the tab element. */\n tabProps: {\n id: string;\n role: \"tab\";\n \"aria-selected\": boolean;\n \"aria-disabled\": boolean | undefined;\n \"aria-controls\": string | undefined;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n tabIndex: number | undefined;\n onKeyDown: (e: KeyboardEvent) => void;\n onMouseDown: (e: MouseEvent) => void;\n onPointerDown: (e: PointerEvent) => void;\n onClick: (e: MouseEvent) => void;\n onFocus: (e: FocusEvent) => void;\n onBlur: (e: FocusEvent) => void;\n };\n /** Whether the tab is selected. */\n isSelected: Accessor<boolean>;\n /** Whether the tab is disabled. */\n isDisabled: Accessor<boolean>;\n /** Whether the tab is pressed. */\n isPressed: Accessor<boolean>;\n /** Whether the tab has focus. */\n isFocused: Accessor<boolean>;\n /** Whether the tab has visible focus ring. */\n isFocusVisible: Accessor<boolean>;\n /** Whether the tab is hovered. */\n isHovered: Accessor<boolean>;\n}\n\nexport interface AriaTabPanelProps {\n /** The key of the associated tab. */\n id?: Key;\n /** Label for the tab panel. */\n \"aria-label\"?: string;\n /** ID of element that labels the tab panel. */\n \"aria-labelledby\"?: string;\n /** ID of element that describes the tab panel. */\n \"aria-describedby\"?: string;\n}\n\nexport interface TabPanelAria {\n /** Props for the tab panel element. */\n tabPanelProps: {\n id: string;\n role: \"tabpanel\";\n \"aria-labelledby\"?: string;\n \"aria-label\"?: string;\n \"aria-describedby\"?: string;\n tabIndex: number;\n };\n /** Whether this panel is the selected one. */\n isSelected: Accessor<boolean>;\n}\n\nconst tabListIds = new WeakMap<TabListState<unknown>, string>();\n\nfunction getTabListId<T>(state: TabListState<T>): string {\n let id = tabListIds.get(state as TabListState<unknown>);\n if (!id) {\n id = createId();\n tabListIds.set(state as TabListState<unknown>, id);\n }\n return id;\n}\n\nfunction generateTabId<T>(state: TabListState<T>, key: Key): string {\n const baseId = getTabListId(state);\n const keyStr = String(key).replace(/\\s+/g, \"-\");\n return `${baseId}-tab-${keyStr}`;\n}\n\nfunction generateTabPanelId<T>(state: TabListState<T>, key: Key): string {\n const baseId = getTabListId(state);\n const keyStr = String(key).replace(/\\s+/g, \"-\");\n return `${baseId}-tabpanel-${keyStr}`;\n}\n\nfunction getNextKey<T>(state: TabListState<T>, currentKey: Key): Key | null {\n const coll = state.collection();\n const keys = [...coll].map((node) => node.key);\n const currentIndex = keys.indexOf(currentKey);\n\n if (currentIndex === -1) return keys[0] ?? null;\n\n // Find next non-disabled key, wrapping around\n for (let i = 1; i <= keys.length; i++) {\n const nextIndex = (currentIndex + i) % keys.length;\n const nextKey = keys[nextIndex];\n if (!state.isKeyDisabled(nextKey)) {\n return nextKey;\n }\n }\n\n return null;\n}\n\nfunction getPreviousKey<T>(state: TabListState<T>, currentKey: Key): Key | null {\n const coll = state.collection();\n const keys = [...coll].map((node) => node.key);\n const currentIndex = keys.indexOf(currentKey);\n\n if (currentIndex === -1) return keys[keys.length - 1] ?? null;\n\n // Find previous non-disabled key, wrapping around\n for (let i = 1; i <= keys.length; i++) {\n const prevIndex = (currentIndex - i + keys.length) % keys.length;\n const prevKey = keys[prevIndex];\n if (!state.isKeyDisabled(prevKey)) {\n return prevKey;\n }\n }\n\n return null;\n}\n\nfunction getFirstKey<T>(state: TabListState<T>): Key | null {\n const coll = state.collection();\n for (const node of coll) {\n if (!state.isKeyDisabled(node.key)) {\n return node.key;\n }\n }\n return null;\n}\n\nfunction getLastKey<T>(state: TabListState<T>): Key | null {\n const coll = state.collection();\n const keys = [...coll].map((node) => node.key).reverse();\n for (const key of keys) {\n if (!state.isKeyDisabled(key)) {\n return key;\n }\n }\n return null;\n}\n\n/**\n * Creates ARIA props for a tab list container.\n */\nexport function createTabList<T>(props: AriaTabListProps, state: TabListState<T>): TabListAria {\n const locale = useLocale();\n const orientation = () => props.orientation ?? state.orientation() ?? \"horizontal\";\n const keyboardActivation = () =>\n props.keyboardActivation ?? state.keyboardActivation() ?? \"automatic\";\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (state.isDisabled()) return;\n\n const currentKey = state.focusedKey() ?? state.selectedKey();\n if (currentKey === null) return;\n\n let nextKey: Key | null = null;\n const isHorizontal = orientation() === \"horizontal\";\n const isRTL = locale().direction === \"rtl\";\n\n switch (e.key) {\n case \"ArrowLeft\":\n if (isHorizontal) {\n nextKey = isRTL ? getNextKey(state, currentKey) : getPreviousKey(state, currentKey);\n }\n break;\n case \"ArrowRight\":\n if (isHorizontal) {\n nextKey = isRTL ? getPreviousKey(state, currentKey) : getNextKey(state, currentKey);\n }\n break;\n case \"ArrowUp\":\n if (!isHorizontal) {\n nextKey = getPreviousKey(state, currentKey);\n }\n break;\n case \"ArrowDown\":\n if (!isHorizontal) {\n nextKey = getNextKey(state, currentKey);\n }\n break;\n case \"Home\":\n nextKey = getFirstKey(state);\n break;\n case \"End\":\n nextKey = getLastKey(state);\n break;\n case \"Enter\":\n case \" \":\n // In manual mode, Enter/Space activates the focused tab\n if (keyboardActivation() === \"manual\" && state.focusedKey()) {\n state.setSelectedKey(state.focusedKey()!);\n e.preventDefault();\n }\n return;\n default:\n return;\n }\n\n if (nextKey !== null) {\n e.preventDefault();\n state.setFocusedKey(nextKey);\n // Selection follows focus only for keyboard navigation in automatic mode\n // (mirrors useSelectableCollection's selectOnFocus in navigateToKey).\n if (keyboardActivation() === \"automatic\") {\n state.setSelectedKey(nextKey);\n }\n }\n };\n\n const handleFocus = () => {\n state.setFocused(true);\n // If no focused key, focus the selected key\n if (state.focusedKey() === null && state.selectedKey() !== null) {\n state.setFocusedKey(state.selectedKey());\n }\n };\n\n const handleBlur = (e: FocusEvent) => {\n // Only blur if focus is leaving the tab list entirely\n const relatedTarget = e.relatedTarget as Element | null;\n if (relatedTarget && (e.currentTarget as Element).contains(relatedTarget)) {\n return;\n }\n state.setFocused(false);\n };\n\n return {\n tabListProps: {\n role: \"tablist\",\n \"aria-orientation\": orientation(),\n \"aria-label\": props[\"aria-label\"],\n \"aria-labelledby\": props[\"aria-labelledby\"],\n \"aria-describedby\": props[\"aria-describedby\"],\n onKeyDown: handleKeyDown,\n onFocusIn: handleFocus,\n onFocusOut: handleBlur,\n },\n };\n}\n\n/**\n * Creates ARIA props for an individual tab.\n */\nexport function createTab<T>(\n props: AriaTabProps,\n state: TabListState<T>,\n ref?: Accessor<HTMLElement | null>,\n): TabAria {\n const key = () => props.key;\n\n const isSelected = createMemo(() => state.selectedKey() === key());\n const isDisabled = createMemo(() => {\n if (props.isDisabled) return true;\n return state.isKeyDisabled(key());\n });\n\n // Whether this tab is the roving-focus target (state layer), used for the\n // roving tabIndex and DOM focus alignment. The returned isFocused is the\n // DOM-focus-based ring state, matching upstream's useFocusRing semantics.\n const isKeyFocused = createMemo(() => state.focusedKey() === key());\n\n // Focus ring\n const { isFocused, isFocusVisible, focusProps } = createFocusRing();\n\n // Press handling. Selection timing mirrors useSelectableItem's default\n // (non-shouldSelectOnPressUp) path: mouse selects on press start and\n // keyboard on key down, while touch, pen, and virtual pointers select on\n // press up.\n const selectTab = () => {\n const tabKey = key();\n state.setFocusedKey(tabKey);\n state.setSelectedKey(tabKey);\n };\n const { isPressed, pressProps } = createPress({\n get isDisabled() {\n return isDisabled();\n },\n onPressStart: (e) => {\n if (e.pointerType === \"mouse\" || e.pointerType === \"keyboard\") {\n selectTab();\n }\n },\n onPress: (e) => {\n if (e.pointerType === \"touch\" || e.pointerType === \"pen\" || e.pointerType === \"virtual\") {\n selectTab();\n }\n },\n });\n\n // Hover handling\n const { isHovered } = createHover({\n get isDisabled() {\n return isDisabled();\n },\n });\n\n // Generate IDs\n const tabId = generateTabId(state, key());\n const tabPanelId = generateTabPanelId(state, key());\n\n // Helper to safely call event handlers that may be bound tuples\n const callHandler = <E extends Event>(handler: unknown, event: E) => {\n if (typeof handler === \"function\") {\n (handler as (e: E) => void)(event);\n return;\n }\n if (Array.isArray(handler) && handler.length >= 2 && typeof handler[1] === \"function\") {\n (handler[1] as (this: unknown, e: E) => void).call(handler[0], event);\n }\n };\n\n // Focus management\n const handleFocus = (e: FocusEvent) => {\n state.setFocusedKey(key());\n callHandler(focusProps.onFocus, e);\n };\n\n const handleBlur = (e: FocusEvent) => {\n callHandler(focusProps.onBlur, e);\n };\n\n // Combine all handlers\n const handleKeyDown = (e: KeyboardEvent) => {\n callHandler(pressProps.onKeyDown, e);\n };\n\n const handleMouseDown = (e: MouseEvent) => {\n callHandler(pressProps.onMouseDown, e);\n };\n\n const handlePointerDown = (e: PointerEvent) => {\n callHandler(pressProps.onPointerDown, e);\n };\n\n const handleClick = (e: MouseEvent) => {\n callHandler(pressProps.onClick, e);\n };\n\n // Keep DOM focus aligned with focusedKey updates from keyboard navigation.\n // Only while the tab list itself is focused (mirrors useSelectableItem's\n // manager.isFocused guard), so programmatic selection changes don't steal\n // focus from elsewhere in the document.\n createEffect(() => {\n const element = ref?.();\n if (!state.isFocused() || !isKeyFocused() || !element) return;\n\n const activeElement = element.ownerDocument?.activeElement;\n if (activeElement !== element) {\n element.focus();\n }\n });\n\n return {\n tabProps: {\n id: tabId,\n role: \"tab\",\n get \"aria-selected\"() {\n return isSelected();\n },\n get \"aria-disabled\"() {\n return isDisabled() || undefined;\n },\n get \"aria-controls\"() {\n return isSelected() ? tabPanelId : undefined;\n },\n \"aria-label\": props[\"aria-label\"],\n \"aria-labelledby\": props[\"aria-labelledby\"],\n get tabIndex() {\n // Roving tabIndex follows the focused key (mirrors useSelectableItem);\n // disabled tabs get no tabIndex at all (mirrors useTab).\n if (isDisabled()) return undefined;\n return isKeyFocused() ? 0 : -1;\n },\n onKeyDown: handleKeyDown,\n onMouseDown: handleMouseDown,\n onPointerDown: handlePointerDown,\n onClick: handleClick,\n onFocus: handleFocus,\n onBlur: handleBlur,\n },\n isSelected,\n isDisabled,\n isPressed,\n isFocused,\n isFocusVisible,\n isHovered,\n };\n}\n\n/**\n * Creates ARIA props for a tab panel.\n */\nexport function createTabPanel<T>(\n props: AriaTabPanelProps,\n state: TabListState<T> | null,\n): TabPanelAria {\n const fallbackId = createId();\n\n // Shared panel pattern: if no explicit id is provided, associate the panel\n // with the currently selected tab.\n const associatedKey = createMemo<Key | null>(() => {\n if (state === null) return null;\n return props.id ?? state.selectedKey();\n });\n\n // If state is null, the panel is always visible (SSR fallback).\n const isSelected = createMemo(() => {\n if (state === null) return true;\n if (props.id === undefined) {\n return state.selectedKey() !== null;\n }\n return state.selectedKey() === props.id;\n });\n\n return {\n tabPanelProps: {\n get id() {\n const key = associatedKey();\n if (state && key !== null) {\n return generateTabPanelId(state, key);\n }\n return fallbackId;\n },\n role: \"tabpanel\",\n get \"aria-labelledby\"() {\n if (props[\"aria-labelledby\"]) return props[\"aria-labelledby\"];\n const key = associatedKey();\n if (state && key !== null) {\n return generateTabId(state, key);\n }\n return undefined;\n },\n \"aria-label\": props[\"aria-label\"],\n \"aria-describedby\": props[\"aria-describedby\"],\n // Make panel focusable if no tabbable children\n tabIndex: 0,\n },\n isSelected,\n };\n}\n"],"mappings":";;;;;;;;;;;AAmIA,MAAM,6BAAa,IAAI,QAAuC;AAE9D,SAAS,aAAgB,OAAgC;CACvD,IAAI,KAAK,WAAW,IAAI,KAA8B;CACtD,IAAI,CAAC,IAAI;EACP,KAAK,SAAS;EACd,WAAW,IAAI,OAAgC,EAAE;CACnD;CACA,OAAO;AACT;AAEA,SAAS,cAAiB,OAAwB,KAAkB;CAGlE,OAAO,GAFQ,aAAa,KAEb,EAAE,OADF,OAAO,GAAG,CAAC,CAAC,QAAQ,QAAQ,GACd;AAC/B;AAEA,SAAS,mBAAsB,OAAwB,KAAkB;CAGvE,OAAO,GAFQ,aAAa,KAEb,EAAE,YADF,OAAO,GAAG,CAAC,CAAC,QAAQ,QAAQ,GACT;AACpC;AAEA,SAAS,WAAc,OAAwB,YAA6B;CAE1E,MAAM,OAAO,CAAC,GADD,MAAM,WACC,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG;CAC7C,MAAM,eAAe,KAAK,QAAQ,UAAU;CAE5C,IAAI,iBAAiB,IAAI,OAAO,KAAK,MAAM;CAG3C,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,QAAQ,KAAK;EAErC,MAAM,UAAU,MADG,eAAe,KAAK,KAAK;EAE5C,IAAI,CAAC,MAAM,cAAc,OAAO,GAC9B,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAS,eAAkB,OAAwB,YAA6B;CAE9E,MAAM,OAAO,CAAC,GADD,MAAM,WACC,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG;CAC7C,MAAM,eAAe,KAAK,QAAQ,UAAU;CAE5C,IAAI,iBAAiB,IAAI,OAAO,KAAK,KAAK,SAAS,MAAM;CAGzD,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,QAAQ,KAAK;EAErC,MAAM,UAAU,MADG,eAAe,IAAI,KAAK,UAAU,KAAK;EAE1D,IAAI,CAAC,MAAM,cAAc,OAAO,GAC9B,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAS,YAAe,OAAoC;CAC1D,MAAM,OAAO,MAAM,WAAW;CAC9B,KAAK,MAAM,QAAQ,MACjB,IAAI,CAAC,MAAM,cAAc,KAAK,GAAG,GAC/B,OAAO,KAAK;CAGhB,OAAO;AACT;AAEA,SAAS,WAAc,OAAoC;CAEzD,MAAM,OAAO,CAAC,GADD,MAAM,WACC,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG,CAAC,CAAC,QAAQ;CACvD,KAAK,MAAM,OAAO,MAChB,IAAI,CAAC,MAAM,cAAc,GAAG,GAC1B,OAAO;CAGX,OAAO;AACT;;;;AAKA,SAAgB,cAAiB,OAAyB,OAAqC;CAC7F,MAAM,SAAS,UAAU;CACzB,MAAM,oBAAoB,MAAM,eAAe,MAAM,YAAY,KAAK;CACtE,MAAM,2BACJ,MAAM,sBAAsB,MAAM,mBAAmB,KAAK;CAE5D,MAAM,iBAAiB,MAAqB;EAC1C,IAAI,MAAM,WAAW,GAAG;EAExB,MAAM,aAAa,MAAM,WAAW,KAAK,MAAM,YAAY;EAC3D,IAAI,eAAe,MAAM;EAEzB,IAAI,UAAsB;EAC1B,MAAM,eAAe,YAAY,MAAM;EACvC,MAAM,QAAQ,OAAO,CAAC,CAAC,cAAc;EAErC,QAAQ,EAAE,KAAV;GACE,KAAK;IACH,IAAI,cACF,UAAU,QAAQ,WAAW,OAAO,UAAU,IAAI,eAAe,OAAO,UAAU;IAEpF;GACF,KAAK;IACH,IAAI,cACF,UAAU,QAAQ,eAAe,OAAO,UAAU,IAAI,WAAW,OAAO,UAAU;IAEpF;GACF,KAAK;IACH,IAAI,CAAC,cACH,UAAU,eAAe,OAAO,UAAU;IAE5C;GACF,KAAK;IACH,IAAI,CAAC,cACH,UAAU,WAAW,OAAO,UAAU;IAExC;GACF,KAAK;IACH,UAAU,YAAY,KAAK;IAC3B;GACF,KAAK;IACH,UAAU,WAAW,KAAK;IAC1B;GACF,KAAK;GACL,KAAK;IAEH,IAAI,mBAAmB,MAAM,YAAY,MAAM,WAAW,GAAG;KAC3D,MAAM,eAAe,MAAM,WAAW,CAAE;KACxC,EAAE,eAAe;IACnB;IACA;GACF,SACE;EACJ;EAEA,IAAI,YAAY,MAAM;GACpB,EAAE,eAAe;GACjB,MAAM,cAAc,OAAO;GAG3B,IAAI,mBAAmB,MAAM,aAC3B,MAAM,eAAe,OAAO;EAEhC;CACF;CAEA,MAAM,oBAAoB;EACxB,MAAM,WAAW,IAAI;EAErB,IAAI,MAAM,WAAW,MAAM,QAAQ,MAAM,YAAY,MAAM,MACzD,MAAM,cAAc,MAAM,YAAY,CAAC;CAE3C;CAEA,MAAM,cAAc,MAAkB;EAEpC,MAAM,gBAAgB,EAAE;EACxB,IAAI,iBAAkB,EAAE,cAA0B,SAAS,aAAa,GACtE;EAEF,MAAM,WAAW,KAAK;CACxB;CAEA,OAAO,EACL,cAAc;EACZ,MAAM;EACN,oBAAoB,YAAY;EAChC,cAAc,MAAM;EACpB,mBAAmB,MAAM;EACzB,oBAAoB,MAAM;EAC1B,WAAW;EACX,WAAW;EACX,YAAY;CACd,EACF;AACF;;;;AAKA,SAAgB,UACd,OACA,OACA,KACS;CACT,MAAM,YAAY,MAAM;CAExB,MAAM,aAAa,iBAAiB,MAAM,YAAY,MAAM,IAAI,CAAC;CACjE,MAAM,aAAa,iBAAiB;EAClC,IAAI,MAAM,YAAY,OAAO;EAC7B,OAAO,MAAM,cAAc,IAAI,CAAC;CAClC,CAAC;CAKD,MAAM,eAAe,iBAAiB,MAAM,WAAW,MAAM,IAAI,CAAC;CAGlE,MAAM,EAAE,WAAW,gBAAgB,eAAe,gBAAgB;CAMlE,MAAM,kBAAkB;EACtB,MAAM,SAAS,IAAI;EACnB,MAAM,cAAc,MAAM;EAC1B,MAAM,eAAe,MAAM;CAC7B;CACA,MAAM,EAAE,WAAW,eAAe,YAAY;EAC5C,IAAI,aAAa;GACf,OAAO,WAAW;EACpB;EACA,eAAe,MAAM;GACnB,IAAI,EAAE,gBAAgB,WAAW,EAAE,gBAAgB,YACjD,UAAU;EAEd;EACA,UAAU,MAAM;GACd,IAAI,EAAE,gBAAgB,WAAW,EAAE,gBAAgB,SAAS,EAAE,gBAAgB,WAC5E,UAAU;EAEd;CACF,CAAC;CAGD,MAAM,EAAE,cAAc,YAAY,EAChC,IAAI,aAAa;EACf,OAAO,WAAW;CACpB,EACF,CAAC;CAGD,MAAM,QAAQ,cAAc,OAAO,IAAI,CAAC;CACxC,MAAM,aAAa,mBAAmB,OAAO,IAAI,CAAC;CAGlD,MAAM,eAAgC,SAAkB,UAAa;EACnE,IAAI,OAAO,YAAY,YAAY;GACjC,QAA4B,KAAK;GACjC;EACF;EACA,IAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,UAAU,KAAK,OAAO,QAAQ,OAAO,YACzE,QAAS,EAAE,CAAmC,KAAK,QAAQ,IAAI,KAAK;CAExE;CAGA,MAAM,eAAe,MAAkB;EACrC,MAAM,cAAc,IAAI,CAAC;EACzB,YAAY,WAAW,SAAS,CAAC;CACnC;CAEA,MAAM,cAAc,MAAkB;EACpC,YAAY,WAAW,QAAQ,CAAC;CAClC;CAGA,MAAM,iBAAiB,MAAqB;EAC1C,YAAY,WAAW,WAAW,CAAC;CACrC;CAEA,MAAM,mBAAmB,MAAkB;EACzC,YAAY,WAAW,aAAa,CAAC;CACvC;CAEA,MAAM,qBAAqB,MAAoB;EAC7C,YAAY,WAAW,eAAe,CAAC;CACzC;CAEA,MAAM,eAAe,MAAkB;EACrC,YAAY,WAAW,SAAS,CAAC;CACnC;CAMA,mBAAmB;EACjB,MAAM,UAAU,MAAM;EACtB,IAAI,CAAC,MAAM,UAAU,KAAK,CAAC,aAAa,KAAK,CAAC,SAAS;EAGvD,IADsB,QAAQ,eAAe,kBACvB,SACpB,QAAQ,MAAM;CAElB,CAAC;CAED,OAAO;EACL,UAAU;GACR,IAAI;GACJ,MAAM;GACN,IAAI,kBAAkB;IACpB,OAAO,WAAW;GACpB;GACA,IAAI,kBAAkB;IACpB,OAAO,WAAW,KAAK,KAAA;GACzB;GACA,IAAI,kBAAkB;IACpB,OAAO,WAAW,IAAI,aAAa,KAAA;GACrC;GACA,cAAc,MAAM;GACpB,mBAAmB,MAAM;GACzB,IAAI,WAAW;IAGb,IAAI,WAAW,GAAG,OAAO,KAAA;IACzB,OAAO,aAAa,IAAI,IAAI;GAC9B;GACA,WAAW;GACX,aAAa;GACb,eAAe;GACf,SAAS;GACT,SAAS;GACT,QAAQ;EACV;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;AAKA,SAAgB,eACd,OACA,OACc;CACd,MAAM,aAAa,SAAS;CAI5B,MAAM,gBAAgB,iBAA6B;EACjD,IAAI,UAAU,MAAM,OAAO;EAC3B,OAAO,MAAM,MAAM,MAAM,YAAY;CACvC,CAAC;CAGD,MAAM,aAAa,iBAAiB;EAClC,IAAI,UAAU,MAAM,OAAO;EAC3B,IAAI,MAAM,OAAO,KAAA,GACf,OAAO,MAAM,YAAY,MAAM;EAEjC,OAAO,MAAM,YAAY,MAAM,MAAM;CACvC,CAAC;CAED,OAAO;EACL,eAAe;GACb,IAAI,KAAK;IACP,MAAM,MAAM,cAAc;IAC1B,IAAI,SAAS,QAAQ,MACnB,OAAO,mBAAmB,OAAO,GAAG;IAEtC,OAAO;GACT;GACA,MAAM;GACN,IAAI,oBAAoB;IACtB,IAAI,MAAM,oBAAoB,OAAO,MAAM;IAC3C,MAAM,MAAM,cAAc;IAC1B,IAAI,SAAS,QAAQ,MACnB,OAAO,cAAc,OAAO,GAAG;GAGnC;GACA,cAAc,MAAM;GACpB,oBAAoB,MAAM;GAE1B,UAAU;EACZ;EACA;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"tabs.jsx","names":[],"sources":["../../src/tabs/createTabs.ts"],"sourcesContent":["/**\n * ARIA hooks for tab components.\n * Based on @react-aria/tabs.\n */\n\nimport { type Accessor, batch, createEffect, createMemo } from \"solid-js\";\nimport { createFocusRing } from \"../interactions\";\nimport { createPress } from \"../interactions\";\nimport { createHover } from \"../interactions\";\nimport { createId } from \"../ssr\";\nimport { useLocale } from \"../i18n\";\nimport type { Key, Collection, CollectionNode } from \"@proyecto-viviana/solid-stately\";\n\nexport type TabOrientation = \"horizontal\" | \"vertical\";\nexport type KeyboardActivation = \"automatic\" | \"manual\";\n\nexport interface TabListState<T = unknown> {\n collection: Accessor<Collection<T>>;\n selectedKey: Accessor<Key | null>;\n setSelectedKey(key: Key): void;\n selectedItem: Accessor<CollectionNode<T> | null>;\n isDisabled: Accessor<boolean>;\n keyboardActivation: Accessor<KeyboardActivation>;\n orientation: Accessor<TabOrientation>;\n isKeyDisabled(key: Key): boolean;\n disabledKeys: Accessor<Set<Key>>;\n isFocused: Accessor<boolean>;\n setFocused(isFocused: boolean): void;\n focusedKey: Accessor<Key | null>;\n setFocusedKey(key: Key | null): void;\n}\n\nexport interface AriaTabListProps {\n /** The orientation of the tab list. */\n orientation?: TabOrientation;\n /** How tabs are activated (on focus or on click). */\n keyboardActivation?: KeyboardActivation;\n /** Whether the tab list is disabled. */\n isDisabled?: boolean;\n /** Label for the tab list. */\n \"aria-label\"?: string;\n /** ID of element that labels the tab list. */\n \"aria-labelledby\"?: string;\n /** ID of element that describes the tab list. */\n \"aria-describedby\"?: string;\n}\n\nexport interface TabListAria {\n /** Props for the tab list container element. */\n tabListProps: {\n role: \"tablist\";\n \"aria-orientation\": TabOrientation;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n onKeyDown: (e: KeyboardEvent) => void;\n // React's bubbling onFocus/onBlur map to focusin/focusout in Solid; the\n // tab list must observe focus entering/leaving its child tabs.\n onFocusIn: (e: FocusEvent) => void;\n onFocusOut: (e: FocusEvent) => void;\n };\n}\n\nexport interface AriaTabProps {\n /** The key of the tab. */\n key: Key;\n /** Whether the tab is disabled. */\n isDisabled?: boolean;\n /** Label for the tab. */\n \"aria-label\"?: string;\n /** ID reference for the tab label. */\n \"aria-labelledby\"?: string;\n}\n\nexport interface TabAria {\n /** Props for the tab element. */\n tabProps: {\n id: string;\n role: \"tab\";\n \"aria-selected\": boolean;\n \"aria-disabled\": boolean | undefined;\n \"aria-controls\": string | undefined;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n tabIndex: number | undefined;\n onKeyDown: (e: KeyboardEvent) => void;\n onMouseDown: (e: MouseEvent) => void;\n onPointerDown: (e: PointerEvent) => void;\n onClick: (e: MouseEvent) => void;\n onFocus: (e: FocusEvent) => void;\n onFocusIn: (e: FocusEvent) => void;\n onBlur: (e: FocusEvent) => void;\n };\n /** Whether the tab is selected. */\n isSelected: Accessor<boolean>;\n /** Whether the tab is disabled. */\n isDisabled: Accessor<boolean>;\n /** Whether the tab is pressed. */\n isPressed: Accessor<boolean>;\n /** Whether the tab has focus. */\n isFocused: Accessor<boolean>;\n /** Whether the tab has visible focus ring. */\n isFocusVisible: Accessor<boolean>;\n /** Whether the tab is hovered. */\n isHovered: Accessor<boolean>;\n}\n\nexport interface AriaTabPanelProps {\n /** The key of the associated tab. */\n id?: Key;\n /** Label for the tab panel. */\n \"aria-label\"?: string;\n /** ID of element that labels the tab panel. */\n \"aria-labelledby\"?: string;\n /** ID of element that describes the tab panel. */\n \"aria-describedby\"?: string;\n}\n\nexport interface TabPanelAria {\n /** Props for the tab panel element. */\n tabPanelProps: {\n id: string;\n role: \"tabpanel\";\n \"aria-labelledby\"?: string;\n \"aria-label\"?: string;\n \"aria-describedby\"?: string;\n tabIndex: number;\n };\n /** Whether this panel is the selected one. */\n isSelected: Accessor<boolean>;\n}\n\nconst tabListIds = new WeakMap<TabListState<unknown>, string>();\n\nfunction getTabListId<T>(state: TabListState<T>): string {\n let id = tabListIds.get(state as TabListState<unknown>);\n if (!id) {\n id = createId();\n tabListIds.set(state as TabListState<unknown>, id);\n }\n return id;\n}\n\nfunction generateTabId<T>(state: TabListState<T>, key: Key): string {\n const baseId = getTabListId(state);\n const keyStr = String(key).replace(/\\s+/g, \"-\");\n return `${baseId}-tab-${keyStr}`;\n}\n\nfunction generateTabPanelId<T>(state: TabListState<T>, key: Key): string {\n const baseId = getTabListId(state);\n const keyStr = String(key).replace(/\\s+/g, \"-\");\n return `${baseId}-tabpanel-${keyStr}`;\n}\n\nfunction getNextKey<T>(state: TabListState<T>, currentKey: Key): Key | null {\n const coll = state.collection();\n const keys = [...coll].map((node) => node.key);\n const currentIndex = keys.indexOf(currentKey);\n\n if (currentIndex === -1) return keys[0] ?? null;\n\n // Find next non-disabled key, wrapping around\n for (let i = 1; i <= keys.length; i++) {\n const nextIndex = (currentIndex + i) % keys.length;\n const nextKey = keys[nextIndex];\n if (!state.isKeyDisabled(nextKey)) {\n return nextKey;\n }\n }\n\n return null;\n}\n\nfunction getPreviousKey<T>(state: TabListState<T>, currentKey: Key): Key | null {\n const coll = state.collection();\n const keys = [...coll].map((node) => node.key);\n const currentIndex = keys.indexOf(currentKey);\n\n if (currentIndex === -1) return keys[keys.length - 1] ?? null;\n\n // Find previous non-disabled key, wrapping around\n for (let i = 1; i <= keys.length; i++) {\n const prevIndex = (currentIndex - i + keys.length) % keys.length;\n const prevKey = keys[prevIndex];\n if (!state.isKeyDisabled(prevKey)) {\n return prevKey;\n }\n }\n\n return null;\n}\n\nfunction getFirstKey<T>(state: TabListState<T>): Key | null {\n const coll = state.collection();\n for (const node of coll) {\n if (!state.isKeyDisabled(node.key)) {\n return node.key;\n }\n }\n return null;\n}\n\nfunction getLastKey<T>(state: TabListState<T>): Key | null {\n const coll = state.collection();\n const keys = [...coll].map((node) => node.key).reverse();\n for (const key of keys) {\n if (!state.isKeyDisabled(key)) {\n return key;\n }\n }\n return null;\n}\n\n/**\n * Creates ARIA props for a tab list container.\n */\nexport function createTabList<T>(props: AriaTabListProps, state: TabListState<T>): TabListAria {\n const locale = useLocale();\n const orientation = () => props.orientation ?? state.orientation() ?? \"horizontal\";\n const keyboardActivation = () =>\n props.keyboardActivation ?? state.keyboardActivation() ?? \"automatic\";\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (state.isDisabled()) return;\n\n const currentKey = state.focusedKey() ?? state.selectedKey();\n if (currentKey === null) return;\n\n let nextKey: Key | null = null;\n const isHorizontal = orientation() === \"horizontal\";\n const isRTL = locale().direction === \"rtl\";\n\n switch (e.key) {\n case \"ArrowLeft\":\n if (isHorizontal) {\n nextKey = isRTL ? getNextKey(state, currentKey) : getPreviousKey(state, currentKey);\n }\n break;\n case \"ArrowRight\":\n if (isHorizontal) {\n nextKey = isRTL ? getPreviousKey(state, currentKey) : getNextKey(state, currentKey);\n }\n break;\n case \"ArrowUp\":\n if (!isHorizontal) {\n nextKey = getPreviousKey(state, currentKey);\n }\n break;\n case \"ArrowDown\":\n if (!isHorizontal) {\n nextKey = getNextKey(state, currentKey);\n }\n break;\n case \"Home\":\n nextKey = getFirstKey(state);\n break;\n case \"End\":\n nextKey = getLastKey(state);\n break;\n case \"Enter\":\n case \" \":\n // In manual mode, Enter/Space activates the focused tab\n if (keyboardActivation() === \"manual\" && state.focusedKey()) {\n state.setSelectedKey(state.focusedKey()!);\n e.preventDefault();\n }\n return;\n default:\n return;\n }\n\n if (nextKey !== null) {\n e.preventDefault();\n // Batch the focus + selection writes so their observable ordering matches\n // React. `setFocusedKey` drives a reactive effect that moves DOM focus\n // (firing native focusout/focusin); `setSelectedKey` calls\n // `onSelectionChange` synchronously. Written bare, Solid flushes the focus\n // effect the instant `setFocusedKey` runs — so focus moves *before* the\n // selection callback, inverting React's order. React batches both state\n // updates in the handler (callback fires synchronously) and defers the\n // focus move to a layout effect. `batch()` is the Solid equivalent: it\n // holds the focus effect until the batch closes, so the synchronous\n // `onSelectionChange` fires first, then focus moves — matching upstream's\n // `callback → focusout → focusin` sequence (D4 event-sequence oracle).\n batch(() => {\n state.setFocusedKey(nextKey);\n // Selection follows focus only for keyboard navigation in automatic mode\n // (mirrors useSelectableCollection's selectOnFocus in navigateToKey).\n if (keyboardActivation() === \"automatic\") {\n state.setSelectedKey(nextKey);\n }\n });\n }\n };\n\n const handleFocus = () => {\n state.setFocused(true);\n // If no focused key, focus the selected key\n if (state.focusedKey() === null && state.selectedKey() !== null) {\n state.setFocusedKey(state.selectedKey());\n }\n };\n\n const handleBlur = (e: FocusEvent) => {\n // Only blur if focus is leaving the tab list entirely\n const relatedTarget = e.relatedTarget as Element | null;\n if (relatedTarget && (e.currentTarget as Element).contains(relatedTarget)) {\n return;\n }\n state.setFocused(false);\n };\n\n return {\n tabListProps: {\n role: \"tablist\",\n \"aria-orientation\": orientation(),\n \"aria-label\": props[\"aria-label\"],\n \"aria-labelledby\": props[\"aria-labelledby\"],\n \"aria-describedby\": props[\"aria-describedby\"],\n onKeyDown: handleKeyDown,\n onFocusIn: handleFocus,\n onFocusOut: handleBlur,\n },\n };\n}\n\n/**\n * Creates ARIA props for an individual tab.\n */\nexport function createTab<T>(\n props: AriaTabProps,\n state: TabListState<T>,\n ref?: Accessor<HTMLElement | null>,\n): TabAria {\n const key = () => props.key;\n\n const isSelected = createMemo(() => state.selectedKey() === key());\n const isDisabled = createMemo(() => {\n if (props.isDisabled) return true;\n return state.isKeyDisabled(key());\n });\n\n // Whether this tab is the roving-focus target (state layer), used for the\n // roving tabIndex and DOM focus alignment. The returned isFocused is the\n // DOM-focus-based ring state, matching upstream's useFocusRing semantics.\n const isKeyFocused = createMemo(() => state.focusedKey() === key());\n\n // Focus ring\n const { isFocused, isFocusVisible, focusProps } = createFocusRing();\n\n // Press handling. Selection timing mirrors useSelectableItem's default\n // (non-shouldSelectOnPressUp) path: mouse selects on press start and\n // keyboard on key down, while touch, pen, and virtual pointers select on\n // press up.\n const selectTab = () => {\n // Press handlers select only — they do NOT set the focused key. Upstream's\n // useSelectableItem does the same: its press/onSelect path calls\n // replaceSelection, while `focusedKey` is driven exclusively by the DOM\n // `onFocus` handler (see handleFocus below). Setting the focused key here too\n // flipped the roving tabIndex synchronously at pointer-up — *before* the\n // browser's native focus reached the tab — so a touch tap logged the tapped\n // tab with tabIndex 0 at its own `focusin`, where React (which updates\n // tabIndex only on the post-event commit) still shows -1. Letting native\n // focus alone advance `focusedKey` defers the tabIndex flip past the focus\n // event, matching React's D4 event sequence.\n state.setSelectedKey(key());\n };\n const { isPressed, pressProps } = createPress({\n get isDisabled() {\n return isDisabled();\n },\n onPressStart: (e) => {\n if (e.pointerType === \"mouse\" || e.pointerType === \"keyboard\") {\n selectTab();\n }\n },\n onPress: (e) => {\n if (e.pointerType === \"touch\" || e.pointerType === \"pen\" || e.pointerType === \"virtual\") {\n selectTab();\n }\n },\n });\n\n // Hover handling\n const { isHovered } = createHover({\n get isDisabled() {\n return isDisabled();\n },\n });\n\n // Generate IDs\n const tabId = generateTabId(state, key());\n const tabPanelId = generateTabPanelId(state, key());\n\n // Helper to safely call event handlers that may be bound tuples\n const callHandler = <E extends Event>(handler: unknown, event: E) => {\n if (typeof handler === \"function\") {\n (handler as (e: E) => void)(event);\n return;\n }\n if (Array.isArray(handler) && handler.length >= 2 && typeof handler[1] === \"function\") {\n (handler[1] as (this: unknown, e: E) => void).call(handler[0], event);\n }\n };\n\n // Focus management. The focus ring reacts to the native `focus` event, but the\n // roving-tabindex commit is deliberately bound to `focusin` (see\n // handleFocusIn) so its DOM reflection lands one event later — matching React,\n // whose `onFocus` is a `focusin`-delegated listener at the app root.\n const handleFocus = (e: FocusEvent) => {\n callHandler(focusProps.onFocus, e);\n };\n\n // Roving-tabindex commit (D4 event-ordering). React's `onFocus` is delegated\n // to a single `focusin` listener at the app root, so the roving tabIndex it\n // drives reflects one event *after* the native `focus`. Binding the\n // focusedKey write here (to `focusin`) mirrors that timing: the D4 oracle\n // records event targets from a document-level capture-phase listener, which\n // runs before this at-target handler, so a touch tap — whose selection lands\n // on press-up, after focus — is still observed with tabIndex=-1 at `focusin`,\n // exactly as React. A mouse press selects on press-start and syncs focusedKey\n // before focus (createTabListState's selection→focus effect), so its tab\n // already reads tabIndex=0 at `focusin`, again matching React. Setting it on\n // the earlier `focus` event flipped the tab a whole event too soon, so touch\n // taps diverged at `focusin`. See recertification.md D4 event-ordering.\n const handleFocusIn = () => {\n state.setFocusedKey(key());\n };\n\n const handleBlur = (e: FocusEvent) => {\n callHandler(focusProps.onBlur, e);\n };\n\n // Combine all handlers\n const handleKeyDown = (e: KeyboardEvent) => {\n callHandler(pressProps.onKeyDown, e);\n };\n\n const handleMouseDown = (e: MouseEvent) => {\n callHandler(pressProps.onMouseDown, e);\n };\n\n const handlePointerDown = (e: PointerEvent) => {\n callHandler(pressProps.onPointerDown, e);\n };\n\n const handleClick = (e: MouseEvent) => {\n callHandler(pressProps.onClick, e);\n };\n\n // Keep DOM focus aligned with focusedKey updates from keyboard navigation.\n // Only while the tab list itself is focused (mirrors useSelectableItem's\n // manager.isFocused guard), so programmatic selection changes don't steal\n // focus from elsewhere in the document.\n createEffect(() => {\n const element = ref?.();\n if (!state.isFocused() || !isKeyFocused() || !element) return;\n\n const activeElement = element.ownerDocument?.activeElement;\n if (activeElement !== element) {\n element.focus();\n }\n });\n\n return {\n tabProps: {\n id: tabId,\n role: \"tab\",\n get \"aria-selected\"() {\n return isSelected();\n },\n get \"aria-disabled\"() {\n return isDisabled() || undefined;\n },\n get \"aria-controls\"() {\n return isSelected() ? tabPanelId : undefined;\n },\n \"aria-label\": props[\"aria-label\"],\n \"aria-labelledby\": props[\"aria-labelledby\"],\n get tabIndex() {\n // Roving tabIndex follows the focused key (mirrors useSelectableItem);\n // disabled tabs get no tabIndex at all (mirrors useTab).\n if (isDisabled()) return undefined;\n return isKeyFocused() ? 0 : -1;\n },\n onKeyDown: handleKeyDown,\n onMouseDown: handleMouseDown,\n onPointerDown: handlePointerDown,\n onClick: handleClick,\n onFocus: handleFocus,\n onFocusIn: handleFocusIn,\n onBlur: handleBlur,\n },\n isSelected,\n isDisabled,\n isPressed,\n isFocused,\n isFocusVisible,\n isHovered,\n };\n}\n\n/**\n * Creates ARIA props for a tab panel.\n */\nexport function createTabPanel<T>(\n props: AriaTabPanelProps,\n state: TabListState<T> | null,\n): TabPanelAria {\n const fallbackId = createId();\n\n // Shared panel pattern: if no explicit id is provided, associate the panel\n // with the currently selected tab.\n const associatedKey = createMemo<Key | null>(() => {\n if (state === null) return null;\n return props.id ?? state.selectedKey();\n });\n\n // If state is null, the panel is always visible (SSR fallback).\n const isSelected = createMemo(() => {\n if (state === null) return true;\n if (props.id === undefined) {\n return state.selectedKey() !== null;\n }\n return state.selectedKey() === props.id;\n });\n\n return {\n tabPanelProps: {\n get id() {\n const key = associatedKey();\n if (state && key !== null) {\n return generateTabPanelId(state, key);\n }\n return fallbackId;\n },\n role: \"tabpanel\",\n get \"aria-labelledby\"() {\n if (props[\"aria-labelledby\"]) return props[\"aria-labelledby\"];\n const key = associatedKey();\n if (state && key !== null) {\n return generateTabId(state, key);\n }\n return undefined;\n },\n \"aria-label\": props[\"aria-label\"],\n \"aria-describedby\": props[\"aria-describedby\"],\n // Make panel focusable if no tabbable children\n tabIndex: 0,\n },\n isSelected,\n };\n}\n"],"mappings":";;;;;;;;;;;AAoIA,MAAM,6BAAa,IAAI,QAAuC;AAE9D,SAAS,aAAgB,OAAgC;CACvD,IAAI,KAAK,WAAW,IAAI,KAA8B;CACtD,IAAI,CAAC,IAAI;EACP,KAAK,SAAS;EACd,WAAW,IAAI,OAAgC,EAAE;CACnD;CACA,OAAO;AACT;AAEA,SAAS,cAAiB,OAAwB,KAAkB;CAGlE,OAAO,GAFQ,aAAa,KAEb,EAAE,OADF,OAAO,GAAG,CAAC,CAAC,QAAQ,QAAQ,GACd;AAC/B;AAEA,SAAS,mBAAsB,OAAwB,KAAkB;CAGvE,OAAO,GAFQ,aAAa,KAEb,EAAE,YADF,OAAO,GAAG,CAAC,CAAC,QAAQ,QAAQ,GACT;AACpC;AAEA,SAAS,WAAc,OAAwB,YAA6B;CAE1E,MAAM,OAAO,CAAC,GADD,MAAM,WACC,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG;CAC7C,MAAM,eAAe,KAAK,QAAQ,UAAU;CAE5C,IAAI,iBAAiB,IAAI,OAAO,KAAK,MAAM;CAG3C,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,QAAQ,KAAK;EAErC,MAAM,UAAU,MADG,eAAe,KAAK,KAAK;EAE5C,IAAI,CAAC,MAAM,cAAc,OAAO,GAC9B,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAS,eAAkB,OAAwB,YAA6B;CAE9E,MAAM,OAAO,CAAC,GADD,MAAM,WACC,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG;CAC7C,MAAM,eAAe,KAAK,QAAQ,UAAU;CAE5C,IAAI,iBAAiB,IAAI,OAAO,KAAK,KAAK,SAAS,MAAM;CAGzD,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,QAAQ,KAAK;EAErC,MAAM,UAAU,MADG,eAAe,IAAI,KAAK,UAAU,KAAK;EAE1D,IAAI,CAAC,MAAM,cAAc,OAAO,GAC9B,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAS,YAAe,OAAoC;CAC1D,MAAM,OAAO,MAAM,WAAW;CAC9B,KAAK,MAAM,QAAQ,MACjB,IAAI,CAAC,MAAM,cAAc,KAAK,GAAG,GAC/B,OAAO,KAAK;CAGhB,OAAO;AACT;AAEA,SAAS,WAAc,OAAoC;CAEzD,MAAM,OAAO,CAAC,GADD,MAAM,WACC,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG,CAAC,CAAC,QAAQ;CACvD,KAAK,MAAM,OAAO,MAChB,IAAI,CAAC,MAAM,cAAc,GAAG,GAC1B,OAAO;CAGX,OAAO;AACT;;;;AAKA,SAAgB,cAAiB,OAAyB,OAAqC;CAC7F,MAAM,SAAS,UAAU;CACzB,MAAM,oBAAoB,MAAM,eAAe,MAAM,YAAY,KAAK;CACtE,MAAM,2BACJ,MAAM,sBAAsB,MAAM,mBAAmB,KAAK;CAE5D,MAAM,iBAAiB,MAAqB;EAC1C,IAAI,MAAM,WAAW,GAAG;EAExB,MAAM,aAAa,MAAM,WAAW,KAAK,MAAM,YAAY;EAC3D,IAAI,eAAe,MAAM;EAEzB,IAAI,UAAsB;EAC1B,MAAM,eAAe,YAAY,MAAM;EACvC,MAAM,QAAQ,OAAO,CAAC,CAAC,cAAc;EAErC,QAAQ,EAAE,KAAV;GACE,KAAK;IACH,IAAI,cACF,UAAU,QAAQ,WAAW,OAAO,UAAU,IAAI,eAAe,OAAO,UAAU;IAEpF;GACF,KAAK;IACH,IAAI,cACF,UAAU,QAAQ,eAAe,OAAO,UAAU,IAAI,WAAW,OAAO,UAAU;IAEpF;GACF,KAAK;IACH,IAAI,CAAC,cACH,UAAU,eAAe,OAAO,UAAU;IAE5C;GACF,KAAK;IACH,IAAI,CAAC,cACH,UAAU,WAAW,OAAO,UAAU;IAExC;GACF,KAAK;IACH,UAAU,YAAY,KAAK;IAC3B;GACF,KAAK;IACH,UAAU,WAAW,KAAK;IAC1B;GACF,KAAK;GACL,KAAK;IAEH,IAAI,mBAAmB,MAAM,YAAY,MAAM,WAAW,GAAG;KAC3D,MAAM,eAAe,MAAM,WAAW,CAAE;KACxC,EAAE,eAAe;IACnB;IACA;GACF,SACE;EACJ;EAEA,IAAI,YAAY,MAAM;GACpB,EAAE,eAAe;GAYjB,YAAY;IACV,MAAM,cAAc,OAAO;IAG3B,IAAI,mBAAmB,MAAM,aAC3B,MAAM,eAAe,OAAO;GAEhC,CAAC;EACH;CACF;CAEA,MAAM,oBAAoB;EACxB,MAAM,WAAW,IAAI;EAErB,IAAI,MAAM,WAAW,MAAM,QAAQ,MAAM,YAAY,MAAM,MACzD,MAAM,cAAc,MAAM,YAAY,CAAC;CAE3C;CAEA,MAAM,cAAc,MAAkB;EAEpC,MAAM,gBAAgB,EAAE;EACxB,IAAI,iBAAkB,EAAE,cAA0B,SAAS,aAAa,GACtE;EAEF,MAAM,WAAW,KAAK;CACxB;CAEA,OAAO,EACL,cAAc;EACZ,MAAM;EACN,oBAAoB,YAAY;EAChC,cAAc,MAAM;EACpB,mBAAmB,MAAM;EACzB,oBAAoB,MAAM;EAC1B,WAAW;EACX,WAAW;EACX,YAAY;CACd,EACF;AACF;;;;AAKA,SAAgB,UACd,OACA,OACA,KACS;CACT,MAAM,YAAY,MAAM;CAExB,MAAM,aAAa,iBAAiB,MAAM,YAAY,MAAM,IAAI,CAAC;CACjE,MAAM,aAAa,iBAAiB;EAClC,IAAI,MAAM,YAAY,OAAO;EAC7B,OAAO,MAAM,cAAc,IAAI,CAAC;CAClC,CAAC;CAKD,MAAM,eAAe,iBAAiB,MAAM,WAAW,MAAM,IAAI,CAAC;CAGlE,MAAM,EAAE,WAAW,gBAAgB,eAAe,gBAAgB;CAMlE,MAAM,kBAAkB;EAWtB,MAAM,eAAe,IAAI,CAAC;CAC5B;CACA,MAAM,EAAE,WAAW,eAAe,YAAY;EAC5C,IAAI,aAAa;GACf,OAAO,WAAW;EACpB;EACA,eAAe,MAAM;GACnB,IAAI,EAAE,gBAAgB,WAAW,EAAE,gBAAgB,YACjD,UAAU;EAEd;EACA,UAAU,MAAM;GACd,IAAI,EAAE,gBAAgB,WAAW,EAAE,gBAAgB,SAAS,EAAE,gBAAgB,WAC5E,UAAU;EAEd;CACF,CAAC;CAGD,MAAM,EAAE,cAAc,YAAY,EAChC,IAAI,aAAa;EACf,OAAO,WAAW;CACpB,EACF,CAAC;CAGD,MAAM,QAAQ,cAAc,OAAO,IAAI,CAAC;CACxC,MAAM,aAAa,mBAAmB,OAAO,IAAI,CAAC;CAGlD,MAAM,eAAgC,SAAkB,UAAa;EACnE,IAAI,OAAO,YAAY,YAAY;GACjC,QAA4B,KAAK;GACjC;EACF;EACA,IAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,UAAU,KAAK,OAAO,QAAQ,OAAO,YACzE,QAAS,EAAE,CAAmC,KAAK,QAAQ,IAAI,KAAK;CAExE;CAMA,MAAM,eAAe,MAAkB;EACrC,YAAY,WAAW,SAAS,CAAC;CACnC;CAcA,MAAM,sBAAsB;EAC1B,MAAM,cAAc,IAAI,CAAC;CAC3B;CAEA,MAAM,cAAc,MAAkB;EACpC,YAAY,WAAW,QAAQ,CAAC;CAClC;CAGA,MAAM,iBAAiB,MAAqB;EAC1C,YAAY,WAAW,WAAW,CAAC;CACrC;CAEA,MAAM,mBAAmB,MAAkB;EACzC,YAAY,WAAW,aAAa,CAAC;CACvC;CAEA,MAAM,qBAAqB,MAAoB;EAC7C,YAAY,WAAW,eAAe,CAAC;CACzC;CAEA,MAAM,eAAe,MAAkB;EACrC,YAAY,WAAW,SAAS,CAAC;CACnC;CAMA,mBAAmB;EACjB,MAAM,UAAU,MAAM;EACtB,IAAI,CAAC,MAAM,UAAU,KAAK,CAAC,aAAa,KAAK,CAAC,SAAS;EAGvD,IADsB,QAAQ,eAAe,kBACvB,SACpB,QAAQ,MAAM;CAElB,CAAC;CAED,OAAO;EACL,UAAU;GACR,IAAI;GACJ,MAAM;GACN,IAAI,kBAAkB;IACpB,OAAO,WAAW;GACpB;GACA,IAAI,kBAAkB;IACpB,OAAO,WAAW,KAAK,KAAA;GACzB;GACA,IAAI,kBAAkB;IACpB,OAAO,WAAW,IAAI,aAAa,KAAA;GACrC;GACA,cAAc,MAAM;GACpB,mBAAmB,MAAM;GACzB,IAAI,WAAW;IAGb,IAAI,WAAW,GAAG,OAAO,KAAA;IACzB,OAAO,aAAa,IAAI,IAAI;GAC9B;GACA,WAAW;GACX,aAAa;GACb,eAAe;GACf,SAAS;GACT,SAAS;GACT,WAAW;GACX,QAAQ;EACV;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;AAKA,SAAgB,eACd,OACA,OACc;CACd,MAAM,aAAa,SAAS;CAI5B,MAAM,gBAAgB,iBAA6B;EACjD,IAAI,UAAU,MAAM,OAAO;EAC3B,OAAO,MAAM,MAAM,MAAM,YAAY;CACvC,CAAC;CAGD,MAAM,aAAa,iBAAiB;EAClC,IAAI,UAAU,MAAM,OAAO;EAC3B,IAAI,MAAM,OAAO,KAAA,GACf,OAAO,MAAM,YAAY,MAAM;EAEjC,OAAO,MAAM,YAAY,MAAM,MAAM;CACvC,CAAC;CAED,OAAO;EACL,eAAe;GACb,IAAI,KAAK;IACP,MAAM,MAAM,cAAc;IAC1B,IAAI,SAAS,QAAQ,MACnB,OAAO,mBAAmB,OAAO,GAAG;IAEtC,OAAO;GACT;GACA,MAAM;GACN,IAAI,oBAAoB;IACtB,IAAI,MAAM,oBAAoB,OAAO,MAAM;IAC3C,MAAM,MAAM,cAAc;IAC1B,IAAI,SAAS,QAAQ,MACnB,OAAO,cAAc,OAAO,GAAG;GAGnC;GACA,cAAc,MAAM;GACpB,oBAAoB,MAAM;GAE1B,UAAU;EACZ;EACA;CACF;AACF"}
|
package/dist/_chunk/tag.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as createPress } from "./createPress.js";
|
|
2
|
-
import { i as
|
|
2
|
+
import { i as mergeProps$1 } from "./env.js";
|
|
3
3
|
import { t as filterDOMProps } from "./filterDOMProps.js";
|
|
4
|
+
import { t as access } from "./reactivity.js";
|
|
4
5
|
import { n as createFocusable } from "./createFocusable.js";
|
|
5
6
|
import { createId } from "../ssr/index.js";
|
|
6
7
|
import { t as createLabel } from "./createLabel.js";
|
|
@@ -37,6 +38,9 @@ function createTagGroup(props, state, _ref) {
|
|
|
37
38
|
id,
|
|
38
39
|
get onRemove() {
|
|
39
40
|
return getProps().onRemove;
|
|
41
|
+
},
|
|
42
|
+
get direction() {
|
|
43
|
+
return getProps().direction ?? "ltr";
|
|
40
44
|
}
|
|
41
45
|
};
|
|
42
46
|
const domProps = () => filterDOMProps(getProps(), { labelable: true });
|
|
@@ -67,18 +71,55 @@ function createTagGroup(props, state, _ref) {
|
|
|
67
71
|
if (p.errorMessage) ids.push(errorMessageId);
|
|
68
72
|
return ids.length > 0 ? ids.join(" ") : void 0;
|
|
69
73
|
};
|
|
74
|
+
const getRef = () => _ref?.() ?? null;
|
|
75
|
+
const getFirstNavigableKey = () => {
|
|
76
|
+
const collection = state.collection();
|
|
77
|
+
let candidate = collection.getFirstKey();
|
|
78
|
+
while (candidate != null && state.isDisabled(candidate)) candidate = collection.getKeyAfter(candidate);
|
|
79
|
+
return candidate;
|
|
80
|
+
};
|
|
81
|
+
const getLastNavigableKey = () => {
|
|
82
|
+
const collection = state.collection();
|
|
83
|
+
let candidate = collection.getLastKey();
|
|
84
|
+
while (candidate != null && state.isDisabled(candidate)) candidate = collection.getKeyBefore(candidate);
|
|
85
|
+
return candidate;
|
|
86
|
+
};
|
|
87
|
+
const onFocus = (e) => {
|
|
88
|
+
state.setFocused(true);
|
|
89
|
+
const container = e.currentTarget;
|
|
90
|
+
if (container && e.target && !container.contains(e.target)) return;
|
|
91
|
+
if (state.focusedKey() != null || getProps().isDisabled) return;
|
|
92
|
+
const relatedTarget = e.relatedTarget;
|
|
93
|
+
const enterKey = relatedTarget && container && container.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING ? getLastNavigableKey() : getFirstNavigableKey();
|
|
94
|
+
if (enterKey != null) state.setFocusedKey(enterKey);
|
|
95
|
+
};
|
|
96
|
+
const onBlur = () => {
|
|
97
|
+
state.setFocused(false);
|
|
98
|
+
};
|
|
99
|
+
createEffect(() => {
|
|
100
|
+
const key = state.focusedKey();
|
|
101
|
+
const el = getRef();
|
|
102
|
+
if (!el || key == null) return;
|
|
103
|
+
const active = document.activeElement;
|
|
104
|
+
if (!active || active !== el && !el.contains(active)) return;
|
|
105
|
+
const target = el.querySelector(`[data-key="${CSS.escape(String(key))}"]`);
|
|
106
|
+
if (target && target !== active) target.focus();
|
|
107
|
+
});
|
|
70
108
|
return {
|
|
71
109
|
get gridProps() {
|
|
72
110
|
const p = getProps();
|
|
73
111
|
const hasItems = state.collection().size > 0;
|
|
74
|
-
return mergeProps(domProps(), fieldProps, {
|
|
112
|
+
return mergeProps$1(domProps(), fieldProps, {
|
|
75
113
|
id,
|
|
76
114
|
role: hasItems ? "grid" : "group",
|
|
77
115
|
"aria-multiselectable": hasItems && state.selectionMode() === "multiple" ? true : void 0,
|
|
78
116
|
"aria-atomic": false,
|
|
79
117
|
"aria-relevant": "additions",
|
|
80
118
|
"aria-describedby": getAriaDescribedBy(),
|
|
81
|
-
"aria-disabled": p.isDisabled || void 0
|
|
119
|
+
"aria-disabled": p.isDisabled || void 0,
|
|
120
|
+
tabIndex: p.isDisabled ? void 0 : state.focusedKey() != null ? -1 : 0,
|
|
121
|
+
onFocus,
|
|
122
|
+
onBlur
|
|
82
123
|
});
|
|
83
124
|
},
|
|
84
125
|
get labelProps() {
|
|
@@ -179,13 +220,20 @@ function createTag(props, state, ref) {
|
|
|
179
220
|
}, ref);
|
|
180
221
|
const handleKeyDown = (e) => {
|
|
181
222
|
if (isDisabled()) return;
|
|
223
|
+
const isRtl = getData()?.direction === "rtl";
|
|
182
224
|
switch (e.key) {
|
|
183
225
|
case "ArrowRight":
|
|
226
|
+
e.preventDefault();
|
|
227
|
+
focusKey(isRtl ? getPreviousFocusableKey(key()) : getNextFocusableKey(key()));
|
|
228
|
+
return;
|
|
229
|
+
case "ArrowLeft":
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
focusKey(isRtl ? getNextFocusableKey(key()) : getPreviousFocusableKey(key()));
|
|
232
|
+
return;
|
|
184
233
|
case "ArrowDown":
|
|
185
234
|
e.preventDefault();
|
|
186
235
|
focusKey(getNextFocusableKey(key()));
|
|
187
236
|
return;
|
|
188
|
-
case "ArrowLeft":
|
|
189
237
|
case "ArrowUp":
|
|
190
238
|
e.preventDefault();
|
|
191
239
|
focusKey(getPreviousFocusableKey(key()));
|
|
@@ -212,19 +260,7 @@ function createTag(props, state, ref) {
|
|
|
212
260
|
};
|
|
213
261
|
const tabIndex = createMemo(() => {
|
|
214
262
|
if (isDisabled()) return -1;
|
|
215
|
-
|
|
216
|
-
if (state.focusedKey() !== null) return -1;
|
|
217
|
-
const collection = state.collection();
|
|
218
|
-
let defaultTabStop = null;
|
|
219
|
-
if (state.selectionMode() !== "none") {
|
|
220
|
-
for (const item of collection) if (!state.isDisabled(item.key) && state.isSelected(item.key)) {
|
|
221
|
-
defaultTabStop = item.key;
|
|
222
|
-
break;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (defaultTabStop == null) defaultTabStop = getFirstFocusableKey();
|
|
226
|
-
if (key() === defaultTabStop) return 0;
|
|
227
|
-
return -1;
|
|
263
|
+
return isFocused() || state.focusedKey() == null ? 0 : -1;
|
|
228
264
|
});
|
|
229
265
|
const domProps = () => filterDOMProps(getProps());
|
|
230
266
|
const allowsRemoving = createMemo(() => {
|
|
@@ -233,7 +269,7 @@ function createTag(props, state, ref) {
|
|
|
233
269
|
const rootRole = createMemo(() => getProps().role ?? "option");
|
|
234
270
|
return {
|
|
235
271
|
get rowProps() {
|
|
236
|
-
return mergeProps(domProps(), focusableProps, pressProps, {
|
|
272
|
+
return mergeProps$1(domProps(), focusableProps, pressProps, {
|
|
237
273
|
id: rowId,
|
|
238
274
|
role: rootRole(),
|
|
239
275
|
tabIndex: tabIndex(),
|
package/dist/_chunk/tag.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag.js","names":[],"sources":["../../src/tag/createTagGroup.ts","../../src/tag/createTag.ts"],"sourcesContent":["/**\n * TagGroup hook for Solidaria\n *\n * Provides the behavior and accessibility implementation for a tag group component.\n * A tag group is a focusable list of labels, categories, keywords, filters, or other items,\n * with support for keyboard navigation, selection, and removal.\n *\n * Based on @react-aria/tag useTagGroup\n */\n\nimport { createEffect, onCleanup } from \"solid-js\";\nimport { createLabel } from \"../label/createLabel\";\nimport { filterDOMProps } from \"../utils/filterDOMProps\";\nimport { mergeProps } from \"../utils/mergeProps\";\nimport { createId } from \"../ssr\";\nimport { access, type MaybeAccessor } from \"../utils/reactivity\";\nimport type { ListState, Key } from \"@proyecto-viviana/solid-stately\";\n\nexport interface AriaTagGroupProps {\n /** An ID for the tag group. */\n id?: string;\n /** Whether the tag group is disabled. */\n isDisabled?: boolean;\n /** The label for the tag group. */\n label?: string;\n /** An accessible label for the tag group when no visible label is provided. */\n \"aria-label\"?: string;\n /** The ID of an element that labels the tag group. */\n \"aria-labelledby\"?: string;\n /** The ID of an element that describes the tag group. */\n \"aria-describedby\"?: string;\n /** A description of the tag group. */\n description?: string;\n /** An error message for the tag group. */\n errorMessage?: string;\n /** Handler that is called when a user removes a tag. */\n onRemove?: (keys: Set<Key>) => void;\n}\n\nexport interface TagGroupAria {\n /** Props for the tag group container element. */\n gridProps: Record<string, unknown>;\n /** Props for the tag group's visible label (if any). */\n labelProps: Record<string, unknown>;\n /** Props for the tag group description element, if any. */\n descriptionProps: Record<string, unknown>;\n /** Props for the tag group error message element, if any. */\n errorMessageProps: Record<string, unknown>;\n}\n\n// Shared data between tag group and tags\nconst tagGroupData = new WeakMap<object, TagGroupData>();\n\ninterface TagGroupData {\n id: string;\n onRemove?: (keys: Set<Key>) => void;\n}\n\nexport function getTagGroupData(state: ListState): TagGroupData | undefined {\n return tagGroupData.get(state);\n}\n\n/**\n * Provides the behavior and accessibility implementation for a tag group component.\n * A tag group is a focusable list of labels, categories, keywords, filters, or other items,\n * with support for keyboard navigation, selection, and removal.\n */\nexport function createTagGroup<T>(\n props: MaybeAccessor<AriaTagGroupProps>,\n state: ListState<T>,\n _ref?: () => HTMLElement | null,\n): TagGroupAria {\n const getProps = () => access(props);\n const id = createId(getProps().id);\n const descriptionId = createId();\n const errorMessageId = createId();\n const getFallbackAriaLabel = () => {\n const p = getProps();\n return !p.label && !p[\"aria-label\"] && !p[\"aria-labelledby\"] ? \"Tag list\" : undefined;\n };\n const sharedData: TagGroupData = {\n id,\n get onRemove() {\n return getProps().onRemove;\n },\n };\n\n // Filter DOM props\n const domProps = () =>\n filterDOMProps(getProps() as unknown as Record<string, unknown>, { labelable: true });\n\n // Create label handling\n const { labelProps, fieldProps } = createLabel({\n get label() {\n return getProps().label;\n },\n get \"aria-label\"() {\n return getProps()[\"aria-label\"] ?? getFallbackAriaLabel();\n },\n get \"aria-labelledby\"() {\n return getProps()[\"aria-labelledby\"];\n },\n labelElementType: \"span\",\n });\n\n // Share data with child tags before they create their aria state.\n tagGroupData.set(state, sharedData);\n\n // Clean up the shared state when the tag group owner is disposed.\n createEffect(() => {\n tagGroupData.set(state, sharedData);\n\n onCleanup(() => {\n if (tagGroupData.get(state) === sharedData) {\n tagGroupData.delete(state);\n }\n });\n });\n\n // Build aria-describedby\n const getAriaDescribedBy = () => {\n const p = getProps();\n const ids: string[] = [];\n if (p[\"aria-describedby\"]) {\n ids.push(p[\"aria-describedby\"]);\n }\n if (p.description) {\n ids.push(descriptionId);\n }\n if (p.errorMessage) {\n ids.push(errorMessageId);\n }\n return ids.length > 0 ? ids.join(\" \") : undefined;\n };\n\n return {\n get gridProps() {\n const p = getProps();\n const hasItems = state.collection().size > 0;\n\n return mergeProps(domProps(), fieldProps as Record<string, unknown>, {\n id,\n role: hasItems ? \"grid\" : \"group\",\n \"aria-multiselectable\": hasItems && state.selectionMode() === \"multiple\" ? true : undefined,\n \"aria-atomic\": false,\n \"aria-relevant\": \"additions\",\n \"aria-describedby\": getAriaDescribedBy(),\n \"aria-disabled\": p.isDisabled || undefined,\n });\n },\n get labelProps() {\n return labelProps as Record<string, unknown>;\n },\n get descriptionProps() {\n return {\n id: descriptionId,\n };\n },\n get errorMessageProps() {\n return {\n id: errorMessageId,\n };\n },\n };\n}\n","/**\n * Tag hook for Solidaria\n *\n * Provides the behavior and accessibility implementation for a tag component.\n * Tags are individual items within a TagGroup.\n *\n * Based on @react-aria/tag useTag\n */\n\nimport { createMemo } from \"solid-js\";\nimport { createFocusable } from \"../interactions/createFocusable\";\nimport { createPress } from \"../interactions/createPress\";\nimport { filterDOMProps } from \"../utils/filterDOMProps\";\nimport { mergeProps } from \"../utils/mergeProps\";\nimport { createId } from \"../ssr\";\nimport { access, type MaybeAccessor } from \"../utils/reactivity\";\nimport { getTagGroupData } from \"./createTagGroup\";\nimport type { ListState, Key } from \"@proyecto-viviana/solid-stately\";\n\nexport interface AriaTagProps {\n /** The unique key for this tag. */\n key: Key;\n /** The role for the tag root. Components use row semantics inside a grid. */\n role?: \"option\" | \"row\";\n /** Whether the tag is disabled. */\n isDisabled?: boolean;\n /** A text value for the tag used for accessibility. */\n textValue?: string;\n}\n\nexport interface TagAria {\n /** Props for the tag row element. */\n rowProps: Record<string, unknown>;\n /** Props for the tag cell element. */\n gridCellProps: Record<string, unknown>;\n /** Props for the tag remove button. */\n removeButtonProps: Record<string, unknown>;\n /** Whether the tag can be removed. */\n allowsRemoving: boolean;\n /** Whether the tag is selected. */\n isSelected: boolean;\n /** Whether the tag is disabled. */\n isDisabled: boolean;\n /** Whether the tag is focused. */\n isFocused: boolean;\n /** Whether the tag is pressed. */\n isPressed: boolean;\n}\n\n/**\n * Provides the behavior and accessibility implementation for a tag component.\n * Tags are individual items within a TagGroup.\n */\nexport function createTag<T>(\n props: MaybeAccessor<AriaTagProps>,\n state: ListState<T>,\n ref: () => HTMLElement | null,\n): TagAria {\n const getProps = () => access(props);\n const rowId = createId();\n const cellId = createId();\n const removeButtonId = createId();\n\n // Get shared data from tag group\n const getData = () => getTagGroupData(state);\n\n // Get key\n const key = () => getProps().key;\n\n // Compute states\n const isDisabled = createMemo(() => {\n const p = getProps();\n return p.isDisabled || state.isDisabled(key());\n });\n\n const isSelected = createMemo(() => {\n return state.isSelected(key());\n });\n\n const isSelectable = createMemo(() => state.selectionMode() !== \"none\");\n\n const isFocused = createMemo(() => {\n return state.focusedKey() === key();\n });\n\n const getFirstFocusableKey = (): Key | null => {\n const collection = state.collection();\n let candidate = collection.getFirstKey();\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyAfter(candidate);\n }\n return candidate;\n };\n\n const getLastFocusableKey = (): Key | null => {\n const collection = state.collection();\n let candidate = collection.getLastKey();\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyBefore(candidate);\n }\n return candidate;\n };\n\n const getNextFocusableKey = (fromKey: Key): Key | null => {\n const collection = state.collection();\n let candidate = collection.getKeyAfter(fromKey);\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyAfter(candidate);\n }\n\n if (candidate != null) {\n return candidate;\n }\n\n return getFirstFocusableKey();\n };\n\n const getPreviousFocusableKey = (fromKey: Key): Key | null => {\n const collection = state.collection();\n let candidate = collection.getKeyBefore(fromKey);\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyBefore(candidate);\n }\n\n if (candidate != null) {\n return candidate;\n }\n\n return getLastFocusableKey();\n };\n\n const focusKey = (nextKey: Key | null) => {\n if (nextKey == null) {\n return;\n }\n\n state.setFocusedKey(nextKey);\n const currentElement = ref();\n\n if (!currentElement) {\n return;\n }\n\n if (nextKey === key()) {\n currentElement.focus();\n return;\n }\n\n const tagList = currentElement.parentElement;\n if (!tagList) {\n return;\n }\n\n const nextTag = Array.from(\n tagList.querySelectorAll<HTMLElement>('[role=\"option\"], [role=\"row\"]'),\n ).find((el) => el.getAttribute(\"data-key\") === String(nextKey));\n\n nextTag?.focus();\n };\n\n // Handle press for selection\n const { pressProps, isPressed } = createPress({\n isDisabled,\n onPress: () => {\n if (!isDisabled()) {\n state.setFocusedKey(key());\n state.toggleSelection(key());\n }\n },\n });\n\n // Handle focusable\n const { focusableProps } = createFocusable(\n {\n isDisabled,\n onFocus: () => {\n state.setFocusedKey(key());\n },\n },\n ref,\n );\n\n // Handle keyboard for navigation and removal\n const handleKeyDown = (e: KeyboardEvent) => {\n if (isDisabled()) return;\n\n switch (e.key) {\n case \"ArrowRight\":\n case \"ArrowDown\":\n e.preventDefault();\n focusKey(getNextFocusableKey(key()));\n return;\n case \"ArrowLeft\":\n case \"ArrowUp\":\n e.preventDefault();\n focusKey(getPreviousFocusableKey(key()));\n return;\n case \"Home\":\n e.preventDefault();\n focusKey(getFirstFocusableKey());\n return;\n case \"End\":\n e.preventDefault();\n focusKey(getLastFocusableKey());\n return;\n default:\n break;\n }\n\n if (e.key === \"Delete\" || e.key === \"Backspace\") {\n e.preventDefault();\n const data = getData();\n if (data?.onRemove) {\n // Remove selected keys if this tag is selected, otherwise just this tag\n if (isSelected()) {\n const selection = state.selectedKeys();\n const keysToRemove =\n selection === \"all\"\n ? new Set(Array.from(state.collection()).map((item) => (item as { key: Key }).key))\n : new Set(selection);\n data.onRemove(keysToRemove);\n } else {\n data.onRemove(new Set([key()]));\n }\n }\n }\n };\n\n // Compute tabIndex\n const tabIndex = createMemo(() => {\n if (isDisabled()) return -1;\n\n if (isFocused()) {\n return 0;\n }\n\n if (state.focusedKey() !== null) {\n return -1;\n }\n\n const collection = state.collection();\n let defaultTabStop: Key | null = null;\n\n if (state.selectionMode() !== \"none\") {\n for (const item of collection) {\n if (!state.isDisabled(item.key) && state.isSelected(item.key)) {\n defaultTabStop = item.key;\n break;\n }\n }\n }\n\n if (defaultTabStop == null) {\n defaultTabStop = getFirstFocusableKey();\n }\n\n if (key() === defaultTabStop) {\n return 0;\n }\n\n return -1;\n });\n\n // Filter DOM props\n const domProps = () => filterDOMProps(getProps() as unknown as Record<string, unknown>);\n\n // Check if removal is allowed\n const allowsRemoving = createMemo(() => {\n const data = getData();\n return !!data?.onRemove;\n });\n\n const rootRole = createMemo(() => getProps().role ?? \"option\");\n\n return {\n get rowProps() {\n return mergeProps(\n domProps(),\n focusableProps as Record<string, unknown>,\n pressProps as Record<string, unknown>,\n {\n id: rowId,\n role: rootRole(),\n tabIndex: tabIndex(),\n \"data-key\": String(key()),\n \"aria-label\": getProps().textValue,\n \"aria-selected\": isSelectable() ? isSelected() : undefined,\n \"aria-disabled\": isDisabled() || undefined,\n onKeyDown: handleKeyDown,\n },\n );\n },\n get gridCellProps() {\n return {\n id: cellId,\n role: \"gridcell\",\n \"aria-describedby\": allowsRemoving() ? removeButtonId : undefined,\n };\n },\n get removeButtonProps() {\n const data = getData();\n return {\n id: removeButtonId,\n \"aria-label\": \"Remove\",\n \"aria-labelledby\": `${removeButtonId} ${rowId}`,\n isDisabled: isDisabled(),\n onPress: () => {\n if (data?.onRemove && !isDisabled()) {\n data.onRemove(new Set([key()]));\n }\n },\n };\n },\n get allowsRemoving() {\n return allowsRemoving();\n },\n get isSelected() {\n return isSelected();\n },\n get isDisabled() {\n return isDisabled();\n },\n get isFocused() {\n return isFocused();\n },\n get isPressed() {\n return isPressed();\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tag.js","names":["mergeProps","mergeProps"],"sources":["../../src/tag/createTagGroup.ts","../../src/tag/createTag.ts"],"sourcesContent":["/**\n * TagGroup hook for Solidaria\n *\n * Provides the behavior and accessibility implementation for a tag group component.\n * A tag group is a focusable list of labels, categories, keywords, filters, or other items,\n * with support for keyboard navigation, selection, and removal.\n *\n * Based on @react-aria/tag useTagGroup\n */\n\nimport { createEffect, onCleanup } from \"solid-js\";\nimport { createLabel } from \"../label/createLabel\";\nimport { filterDOMProps } from \"../utils/filterDOMProps\";\nimport { mergeProps } from \"../utils/mergeProps\";\nimport { createId } from \"../ssr\";\nimport { access, type MaybeAccessor } from \"../utils/reactivity\";\nimport type { ListState, Key } from \"@proyecto-viviana/solid-stately\";\n\nexport interface AriaTagGroupProps {\n /** An ID for the tag group. */\n id?: string;\n /** Whether the tag group is disabled. */\n isDisabled?: boolean;\n /** The label for the tag group. */\n label?: string;\n /** An accessible label for the tag group when no visible label is provided. */\n \"aria-label\"?: string;\n /** The ID of an element that labels the tag group. */\n \"aria-labelledby\"?: string;\n /** The ID of an element that describes the tag group. */\n \"aria-describedby\"?: string;\n /** A description of the tag group. */\n description?: string;\n /** An error message for the tag group. */\n errorMessage?: string;\n /** Handler that is called when a user removes a tag. */\n onRemove?: (keys: Set<Key>) => void;\n /**\n * The layout direction, threaded from `useLocale`. A TagGroup navigates on the\n * inline axis, so ArrowLeft/ArrowRight flip under RTL (mirrors the direction\n * the ListKeyboardDelegate receives from useTagGroup).\n */\n direction?: \"ltr\" | \"rtl\";\n}\n\nexport interface TagGroupAria {\n /** Props for the tag group container element. */\n gridProps: Record<string, unknown>;\n /** Props for the tag group's visible label (if any). */\n labelProps: Record<string, unknown>;\n /** Props for the tag group description element, if any. */\n descriptionProps: Record<string, unknown>;\n /** Props for the tag group error message element, if any. */\n errorMessageProps: Record<string, unknown>;\n}\n\n// Shared data between tag group and tags\nconst tagGroupData = new WeakMap<object, TagGroupData>();\n\ninterface TagGroupData {\n id: string;\n onRemove?: (keys: Set<Key>) => void;\n direction: \"ltr\" | \"rtl\";\n}\n\nexport function getTagGroupData(state: ListState): TagGroupData | undefined {\n return tagGroupData.get(state);\n}\n\n/**\n * Provides the behavior and accessibility implementation for a tag group component.\n * A tag group is a focusable list of labels, categories, keywords, filters, or other items,\n * with support for keyboard navigation, selection, and removal.\n */\nexport function createTagGroup<T>(\n props: MaybeAccessor<AriaTagGroupProps>,\n state: ListState<T>,\n _ref?: () => HTMLElement | null,\n): TagGroupAria {\n const getProps = () => access(props);\n const id = createId(getProps().id);\n const descriptionId = createId();\n const errorMessageId = createId();\n const getFallbackAriaLabel = () => {\n const p = getProps();\n return !p.label && !p[\"aria-label\"] && !p[\"aria-labelledby\"] ? \"Tag list\" : undefined;\n };\n const sharedData: TagGroupData = {\n id,\n get onRemove() {\n return getProps().onRemove;\n },\n get direction() {\n return getProps().direction ?? \"ltr\";\n },\n };\n\n // Filter DOM props\n const domProps = () =>\n filterDOMProps(getProps() as unknown as Record<string, unknown>, { labelable: true });\n\n // Create label handling\n const { labelProps, fieldProps } = createLabel({\n get label() {\n return getProps().label;\n },\n get \"aria-label\"() {\n return getProps()[\"aria-label\"] ?? getFallbackAriaLabel();\n },\n get \"aria-labelledby\"() {\n return getProps()[\"aria-labelledby\"];\n },\n labelElementType: \"span\",\n });\n\n // Share data with child tags before they create their aria state.\n tagGroupData.set(state, sharedData);\n\n // Clean up the shared state when the tag group owner is disposed.\n createEffect(() => {\n tagGroupData.set(state, sharedData);\n\n onCleanup(() => {\n if (tagGroupData.get(state) === sharedData) {\n tagGroupData.delete(state);\n }\n });\n });\n\n // Build aria-describedby\n const getAriaDescribedBy = () => {\n const p = getProps();\n const ids: string[] = [];\n if (p[\"aria-describedby\"]) {\n ids.push(p[\"aria-describedby\"]);\n }\n if (p.description) {\n ids.push(descriptionId);\n }\n if (p.errorMessage) {\n ids.push(errorMessageId);\n }\n return ids.length > 0 ? ids.join(\" \") : undefined;\n };\n\n const getRef = () => _ref?.() ?? null;\n\n // First/last navigable (non-disabled) row keys — the entry targets.\n const getFirstNavigableKey = (): Key | null => {\n const collection = state.collection();\n let candidate = collection.getFirstKey();\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyAfter(candidate);\n }\n return candidate;\n };\n\n const getLastNavigableKey = (): Key | null => {\n const collection = state.collection();\n let candidate = collection.getLastKey();\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyBefore(candidate);\n }\n return candidate;\n };\n\n // Focus marshalling — the grid container is a trampoline. Its roving tabIndex\n // is 0 only while `focusedKey == null` (see gridProps below), so a forward Tab\n // that reaches the standalone container lands on the container itself; move the\n // focused key onto the first/last row and the post-commit effect below pulls\n // REAL DOM focus there while the container rolls to tabIndex -1. Mirrors\n // useSelectableCollection's `onFocus` (via useTagGroup → useGridList). A\n // Shift+Tab arriving directly on a row is handled by the row's own focusable\n // onFocus, since every non-disabled row is a tab stop when nothing is focused.\n const onFocus = (e: FocusEvent) => {\n state.setFocused(true);\n\n // `focus` is non-bubbling in Solid, so this fires only when the container\n // itself receives focus; ignore anything that bubbled from a descendant.\n const container = e.currentTarget as HTMLElement | null;\n if (container && e.target && !container.contains(e.target as Node)) return;\n if (state.focusedKey() != null || getProps().isDisabled) return;\n\n const relatedTarget = e.relatedTarget as Element | null;\n // Focus arriving from an element that FOLLOWS the group in document order\n // means the user shift-tabbed backward into it → enter at the LAST row;\n // otherwise (forward Tab, or programmatic) enter at the FIRST.\n const enterKey =\n relatedTarget &&\n container &&\n container.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING\n ? getLastNavigableKey()\n : getFirstNavigableKey();\n if (enterKey != null) {\n state.setFocusedKey(enterKey);\n }\n };\n\n const onBlur = () => {\n state.setFocused(false);\n };\n\n // Once the roving tabindex for the focused key has committed to the DOM, move\n // browser focus onto that row (looked up by its stable data-key), mirroring\n // useSelectableCollection. Only manage focus while it already lives inside the\n // container — i.e. the user is navigating via the trampoline — so a background\n // focusedKey change never yanks focus from elsewhere on the page.\n createEffect(() => {\n const key = state.focusedKey();\n const el = getRef();\n if (!el || key == null) return;\n\n const active = document.activeElement;\n if (!active || (active !== el && !el.contains(active))) return;\n\n const target = el.querySelector<HTMLElement>(`[data-key=\"${CSS.escape(String(key))}\"]`);\n if (target && target !== active) {\n target.focus();\n }\n });\n\n return {\n get gridProps() {\n const p = getProps();\n const hasItems = state.collection().size > 0;\n\n return mergeProps(domProps(), fieldProps as Record<string, unknown>, {\n id,\n role: hasItems ? \"grid\" : \"group\",\n \"aria-multiselectable\": hasItems && state.selectionMode() === \"multiple\" ? true : undefined,\n \"aria-atomic\": false,\n \"aria-relevant\": \"additions\",\n \"aria-describedby\": getAriaDescribedBy(),\n \"aria-disabled\": p.isDisabled || undefined,\n // Roving container tabIndex mirrors useSelectableCollection: the container\n // is tabbable (0) only while nothing is focused, then rolls to -1 once a\n // row takes focus so Tab exits the group.\n tabIndex: p.isDisabled ? undefined : state.focusedKey() != null ? -1 : 0,\n onFocus,\n onBlur,\n });\n },\n get labelProps() {\n return labelProps as Record<string, unknown>;\n },\n get descriptionProps() {\n return {\n id: descriptionId,\n };\n },\n get errorMessageProps() {\n return {\n id: errorMessageId,\n };\n },\n };\n}\n","/**\n * Tag hook for Solidaria\n *\n * Provides the behavior and accessibility implementation for a tag component.\n * Tags are individual items within a TagGroup.\n *\n * Based on @react-aria/tag useTag\n */\n\nimport { createMemo } from \"solid-js\";\nimport { createFocusable } from \"../interactions/createFocusable\";\nimport { createPress } from \"../interactions/createPress\";\nimport { filterDOMProps } from \"../utils/filterDOMProps\";\nimport { mergeProps } from \"../utils/mergeProps\";\nimport { createId } from \"../ssr\";\nimport { access, type MaybeAccessor } from \"../utils/reactivity\";\nimport { getTagGroupData } from \"./createTagGroup\";\nimport type { ListState, Key } from \"@proyecto-viviana/solid-stately\";\n\nexport interface AriaTagProps {\n /** The unique key for this tag. */\n key: Key;\n /** The role for the tag root. Components use row semantics inside a grid. */\n role?: \"option\" | \"row\";\n /** Whether the tag is disabled. */\n isDisabled?: boolean;\n /** A text value for the tag used for accessibility. */\n textValue?: string;\n}\n\nexport interface TagAria {\n /** Props for the tag row element. */\n rowProps: Record<string, unknown>;\n /** Props for the tag cell element. */\n gridCellProps: Record<string, unknown>;\n /** Props for the tag remove button. */\n removeButtonProps: Record<string, unknown>;\n /** Whether the tag can be removed. */\n allowsRemoving: boolean;\n /** Whether the tag is selected. */\n isSelected: boolean;\n /** Whether the tag is disabled. */\n isDisabled: boolean;\n /** Whether the tag is focused. */\n isFocused: boolean;\n /** Whether the tag is pressed. */\n isPressed: boolean;\n}\n\n/**\n * Provides the behavior and accessibility implementation for a tag component.\n * Tags are individual items within a TagGroup.\n */\nexport function createTag<T>(\n props: MaybeAccessor<AriaTagProps>,\n state: ListState<T>,\n ref: () => HTMLElement | null,\n): TagAria {\n const getProps = () => access(props);\n const rowId = createId();\n const cellId = createId();\n const removeButtonId = createId();\n\n // Get shared data from tag group\n const getData = () => getTagGroupData(state);\n\n // Get key\n const key = () => getProps().key;\n\n // Compute states\n const isDisabled = createMemo(() => {\n const p = getProps();\n return p.isDisabled || state.isDisabled(key());\n });\n\n const isSelected = createMemo(() => {\n return state.isSelected(key());\n });\n\n const isSelectable = createMemo(() => state.selectionMode() !== \"none\");\n\n const isFocused = createMemo(() => {\n return state.focusedKey() === key();\n });\n\n const getFirstFocusableKey = (): Key | null => {\n const collection = state.collection();\n let candidate = collection.getFirstKey();\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyAfter(candidate);\n }\n return candidate;\n };\n\n const getLastFocusableKey = (): Key | null => {\n const collection = state.collection();\n let candidate = collection.getLastKey();\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyBefore(candidate);\n }\n return candidate;\n };\n\n const getNextFocusableKey = (fromKey: Key): Key | null => {\n const collection = state.collection();\n let candidate = collection.getKeyAfter(fromKey);\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyAfter(candidate);\n }\n\n if (candidate != null) {\n return candidate;\n }\n\n return getFirstFocusableKey();\n };\n\n const getPreviousFocusableKey = (fromKey: Key): Key | null => {\n const collection = state.collection();\n let candidate = collection.getKeyBefore(fromKey);\n while (candidate != null && state.isDisabled(candidate)) {\n candidate = collection.getKeyBefore(candidate);\n }\n\n if (candidate != null) {\n return candidate;\n }\n\n return getLastFocusableKey();\n };\n\n const focusKey = (nextKey: Key | null) => {\n if (nextKey == null) {\n return;\n }\n\n state.setFocusedKey(nextKey);\n const currentElement = ref();\n\n if (!currentElement) {\n return;\n }\n\n if (nextKey === key()) {\n currentElement.focus();\n return;\n }\n\n const tagList = currentElement.parentElement;\n if (!tagList) {\n return;\n }\n\n const nextTag = Array.from(\n tagList.querySelectorAll<HTMLElement>('[role=\"option\"], [role=\"row\"]'),\n ).find((el) => el.getAttribute(\"data-key\") === String(nextKey));\n\n nextTag?.focus();\n };\n\n // Handle press for selection\n const { pressProps, isPressed } = createPress({\n isDisabled,\n onPress: () => {\n if (!isDisabled()) {\n state.setFocusedKey(key());\n state.toggleSelection(key());\n }\n },\n });\n\n // Handle focusable\n const { focusableProps } = createFocusable(\n {\n isDisabled,\n onFocus: () => {\n state.setFocusedKey(key());\n },\n },\n ref,\n );\n\n // Handle keyboard for navigation and removal\n const handleKeyDown = (e: KeyboardEvent) => {\n if (isDisabled()) return;\n\n // A TagGroup is inherently horizontal (useTagGroup passes\n // `orientation: 'horizontal'` to the ListKeyboardDelegate), so the inline\n // (Left/Right) axis is the navigation axis and flips under RTL, while the\n // block (Up/Down) axis stays DOM-ordered. Mirror ListKeyboardDelegate:\n // getKeyRightOf = rtl ? previous : next; getKeyLeftOf = rtl ? next : previous;\n // getKeyBelow/Above are never direction-flipped.\n const isRtl = getData()?.direction === \"rtl\";\n\n switch (e.key) {\n case \"ArrowRight\":\n e.preventDefault();\n focusKey(isRtl ? getPreviousFocusableKey(key()) : getNextFocusableKey(key()));\n return;\n case \"ArrowLeft\":\n e.preventDefault();\n focusKey(isRtl ? getNextFocusableKey(key()) : getPreviousFocusableKey(key()));\n return;\n case \"ArrowDown\":\n e.preventDefault();\n focusKey(getNextFocusableKey(key()));\n return;\n case \"ArrowUp\":\n e.preventDefault();\n focusKey(getPreviousFocusableKey(key()));\n return;\n case \"Home\":\n e.preventDefault();\n focusKey(getFirstFocusableKey());\n return;\n case \"End\":\n e.preventDefault();\n focusKey(getLastFocusableKey());\n return;\n default:\n break;\n }\n\n if (e.key === \"Delete\" || e.key === \"Backspace\") {\n e.preventDefault();\n const data = getData();\n if (data?.onRemove) {\n // Remove selected keys if this tag is selected, otherwise just this tag\n if (isSelected()) {\n const selection = state.selectedKeys();\n const keysToRemove =\n selection === \"all\"\n ? new Set(Array.from(state.collection()).map((item) => (item as { key: Key }).key))\n : new Set(selection);\n data.onRemove(keysToRemove);\n } else {\n data.onRemove(new Set([key()]));\n }\n }\n }\n };\n\n // Compute tabIndex. Mirror useTag (vendored @react-aria/tag/src/useTag.ts):\n // tabIndex = (!isDisabled && (isFocused || focusedKey == null)) ? 0 : -1\n // Every non-disabled row is a tab stop when nothing is focused yet (so native\n // Shift+Tab from a following element lands on the LAST row); once a key is\n // focused, only that row keeps tabIndex 0 (roving single tab stop).\n const tabIndex = createMemo(() => {\n if (isDisabled()) return -1;\n return isFocused() || state.focusedKey() == null ? 0 : -1;\n });\n\n // Filter DOM props\n const domProps = () => filterDOMProps(getProps() as unknown as Record<string, unknown>);\n\n // Check if removal is allowed\n const allowsRemoving = createMemo(() => {\n const data = getData();\n return !!data?.onRemove;\n });\n\n const rootRole = createMemo(() => getProps().role ?? \"option\");\n\n return {\n get rowProps() {\n return mergeProps(\n domProps(),\n focusableProps as Record<string, unknown>,\n pressProps as Record<string, unknown>,\n {\n id: rowId,\n role: rootRole(),\n tabIndex: tabIndex(),\n \"data-key\": String(key()),\n \"aria-label\": getProps().textValue,\n \"aria-selected\": isSelectable() ? isSelected() : undefined,\n \"aria-disabled\": isDisabled() || undefined,\n onKeyDown: handleKeyDown,\n },\n );\n },\n get gridCellProps() {\n return {\n id: cellId,\n role: \"gridcell\",\n \"aria-describedby\": allowsRemoving() ? removeButtonId : undefined,\n };\n },\n get removeButtonProps() {\n const data = getData();\n return {\n id: removeButtonId,\n \"aria-label\": \"Remove\",\n \"aria-labelledby\": `${removeButtonId} ${rowId}`,\n isDisabled: isDisabled(),\n onPress: () => {\n if (data?.onRemove && !isDisabled()) {\n data.onRemove(new Set([key()]));\n }\n },\n };\n },\n get allowsRemoving() {\n return allowsRemoving();\n },\n get isSelected() {\n return isSelected();\n },\n get isDisabled() {\n return isDisabled();\n },\n get isFocused() {\n return isFocused();\n },\n get isPressed() {\n return isPressed();\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/_chunk/tag.jsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as createPress } from "./createPress.jsx";
|
|
2
|
-
import { i as
|
|
2
|
+
import { i as mergeProps$1 } from "./env.jsx";
|
|
3
3
|
import { t as filterDOMProps } from "./filterDOMProps.jsx";
|
|
4
|
+
import { t as access } from "./reactivity.jsx";
|
|
4
5
|
import { n as createFocusable } from "./createFocusable.jsx";
|
|
5
6
|
import { createId } from "../ssr/index.jsx";
|
|
6
7
|
import { t as createLabel } from "./createLabel.jsx";
|
|
@@ -37,6 +38,9 @@ function createTagGroup(props, state, _ref) {
|
|
|
37
38
|
id,
|
|
38
39
|
get onRemove() {
|
|
39
40
|
return getProps().onRemove;
|
|
41
|
+
},
|
|
42
|
+
get direction() {
|
|
43
|
+
return getProps().direction ?? "ltr";
|
|
40
44
|
}
|
|
41
45
|
};
|
|
42
46
|
const domProps = () => filterDOMProps(getProps(), { labelable: true });
|
|
@@ -67,18 +71,55 @@ function createTagGroup(props, state, _ref) {
|
|
|
67
71
|
if (p.errorMessage) ids.push(errorMessageId);
|
|
68
72
|
return ids.length > 0 ? ids.join(" ") : void 0;
|
|
69
73
|
};
|
|
74
|
+
const getRef = () => _ref?.() ?? null;
|
|
75
|
+
const getFirstNavigableKey = () => {
|
|
76
|
+
const collection = state.collection();
|
|
77
|
+
let candidate = collection.getFirstKey();
|
|
78
|
+
while (candidate != null && state.isDisabled(candidate)) candidate = collection.getKeyAfter(candidate);
|
|
79
|
+
return candidate;
|
|
80
|
+
};
|
|
81
|
+
const getLastNavigableKey = () => {
|
|
82
|
+
const collection = state.collection();
|
|
83
|
+
let candidate = collection.getLastKey();
|
|
84
|
+
while (candidate != null && state.isDisabled(candidate)) candidate = collection.getKeyBefore(candidate);
|
|
85
|
+
return candidate;
|
|
86
|
+
};
|
|
87
|
+
const onFocus = (e) => {
|
|
88
|
+
state.setFocused(true);
|
|
89
|
+
const container = e.currentTarget;
|
|
90
|
+
if (container && e.target && !container.contains(e.target)) return;
|
|
91
|
+
if (state.focusedKey() != null || getProps().isDisabled) return;
|
|
92
|
+
const relatedTarget = e.relatedTarget;
|
|
93
|
+
const enterKey = relatedTarget && container && container.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING ? getLastNavigableKey() : getFirstNavigableKey();
|
|
94
|
+
if (enterKey != null) state.setFocusedKey(enterKey);
|
|
95
|
+
};
|
|
96
|
+
const onBlur = () => {
|
|
97
|
+
state.setFocused(false);
|
|
98
|
+
};
|
|
99
|
+
createEffect(() => {
|
|
100
|
+
const key = state.focusedKey();
|
|
101
|
+
const el = getRef();
|
|
102
|
+
if (!el || key == null) return;
|
|
103
|
+
const active = document.activeElement;
|
|
104
|
+
if (!active || active !== el && !el.contains(active)) return;
|
|
105
|
+
const target = el.querySelector(`[data-key="${CSS.escape(String(key))}"]`);
|
|
106
|
+
if (target && target !== active) target.focus();
|
|
107
|
+
});
|
|
70
108
|
return {
|
|
71
109
|
get gridProps() {
|
|
72
110
|
const p = getProps();
|
|
73
111
|
const hasItems = state.collection().size > 0;
|
|
74
|
-
return mergeProps(domProps(), fieldProps, {
|
|
112
|
+
return mergeProps$1(domProps(), fieldProps, {
|
|
75
113
|
id,
|
|
76
114
|
role: hasItems ? "grid" : "group",
|
|
77
115
|
"aria-multiselectable": hasItems && state.selectionMode() === "multiple" ? true : void 0,
|
|
78
116
|
"aria-atomic": false,
|
|
79
117
|
"aria-relevant": "additions",
|
|
80
118
|
"aria-describedby": getAriaDescribedBy(),
|
|
81
|
-
"aria-disabled": p.isDisabled || void 0
|
|
119
|
+
"aria-disabled": p.isDisabled || void 0,
|
|
120
|
+
tabIndex: p.isDisabled ? void 0 : state.focusedKey() != null ? -1 : 0,
|
|
121
|
+
onFocus,
|
|
122
|
+
onBlur
|
|
82
123
|
});
|
|
83
124
|
},
|
|
84
125
|
get labelProps() {
|
|
@@ -179,13 +220,20 @@ function createTag(props, state, ref) {
|
|
|
179
220
|
}, ref);
|
|
180
221
|
const handleKeyDown = (e) => {
|
|
181
222
|
if (isDisabled()) return;
|
|
223
|
+
const isRtl = getData()?.direction === "rtl";
|
|
182
224
|
switch (e.key) {
|
|
183
225
|
case "ArrowRight":
|
|
226
|
+
e.preventDefault();
|
|
227
|
+
focusKey(isRtl ? getPreviousFocusableKey(key()) : getNextFocusableKey(key()));
|
|
228
|
+
return;
|
|
229
|
+
case "ArrowLeft":
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
focusKey(isRtl ? getNextFocusableKey(key()) : getPreviousFocusableKey(key()));
|
|
232
|
+
return;
|
|
184
233
|
case "ArrowDown":
|
|
185
234
|
e.preventDefault();
|
|
186
235
|
focusKey(getNextFocusableKey(key()));
|
|
187
236
|
return;
|
|
188
|
-
case "ArrowLeft":
|
|
189
237
|
case "ArrowUp":
|
|
190
238
|
e.preventDefault();
|
|
191
239
|
focusKey(getPreviousFocusableKey(key()));
|
|
@@ -212,19 +260,7 @@ function createTag(props, state, ref) {
|
|
|
212
260
|
};
|
|
213
261
|
const tabIndex = createMemo(() => {
|
|
214
262
|
if (isDisabled()) return -1;
|
|
215
|
-
|
|
216
|
-
if (state.focusedKey() !== null) return -1;
|
|
217
|
-
const collection = state.collection();
|
|
218
|
-
let defaultTabStop = null;
|
|
219
|
-
if (state.selectionMode() !== "none") {
|
|
220
|
-
for (const item of collection) if (!state.isDisabled(item.key) && state.isSelected(item.key)) {
|
|
221
|
-
defaultTabStop = item.key;
|
|
222
|
-
break;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (defaultTabStop == null) defaultTabStop = getFirstFocusableKey();
|
|
226
|
-
if (key() === defaultTabStop) return 0;
|
|
227
|
-
return -1;
|
|
263
|
+
return isFocused() || state.focusedKey() == null ? 0 : -1;
|
|
228
264
|
});
|
|
229
265
|
const domProps = () => filterDOMProps(getProps());
|
|
230
266
|
const allowsRemoving = createMemo(() => {
|
|
@@ -233,7 +269,7 @@ function createTag(props, state, ref) {
|
|
|
233
269
|
const rootRole = createMemo(() => getProps().role ?? "option");
|
|
234
270
|
return {
|
|
235
271
|
get rowProps() {
|
|
236
|
-
return mergeProps(domProps(), focusableProps, pressProps, {
|
|
272
|
+
return mergeProps$1(domProps(), focusableProps, pressProps, {
|
|
237
273
|
id: rowId,
|
|
238
274
|
role: rootRole(),
|
|
239
275
|
tabIndex: tabIndex(),
|