@proyecto-viviana/solidaria-components 0.5.0 → 0.7.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-APACHE-2.0 +201 -0
- package/NOTICE +91 -0
- package/README.md +4 -7
- package/dist/ActionBar.d.ts +2 -10
- package/dist/ActionBar.d.ts.map +1 -1
- package/dist/ActionBar.js +95 -59
- package/dist/ActionBar.js.map +1 -1
- package/dist/ActionBar.jsx +42 -15
- package/dist/ActionBar.jsx.map +1 -1
- package/dist/ActionGroup.d.ts +1 -12
- package/dist/ActionGroup.d.ts.map +1 -1
- package/dist/ActionGroup.js +66 -44
- package/dist/ActionGroup.js.map +1 -1
- package/dist/ActionGroup.jsx +25 -10
- package/dist/ActionGroup.jsx.map +1 -1
- package/dist/Alert.d.ts +4 -1
- package/dist/Alert.d.ts.map +1 -1
- package/dist/Alert.js +25 -17
- package/dist/Alert.js.map +1 -1
- package/dist/Alert.jsx +9 -5
- package/dist/Alert.jsx.map +1 -1
- package/dist/Autocomplete.d.ts +2 -9
- package/dist/Autocomplete.d.ts.map +1 -1
- package/dist/Autocomplete.js +18 -5
- package/dist/Autocomplete.js.map +1 -1
- package/dist/Autocomplete.jsx +20 -7
- package/dist/Autocomplete.jsx.map +1 -1
- package/dist/Breadcrumbs.d.ts +2 -7
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs.js +71 -51
- package/dist/Breadcrumbs.js.map +1 -1
- package/dist/Breadcrumbs.jsx +25 -12
- package/dist/Breadcrumbs.jsx.map +1 -1
- package/dist/Button.d.ts +1 -7
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +125 -72
- package/dist/Button.js.map +1 -1
- package/dist/Button.jsx +105 -43
- package/dist/Button.jsx.map +1 -1
- package/dist/Calendar.d.ts +1 -7
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Calendar.js +297 -221
- package/dist/Calendar.js.map +1 -1
- package/dist/Calendar.jsx +52 -32
- package/dist/Calendar.jsx.map +1 -1
- package/dist/CalendarPicker.d.ts +1 -10
- package/dist/CalendarPicker.d.ts.map +1 -1
- package/dist/CalendarPicker.js +12 -0
- package/dist/CalendarPicker.js.map +1 -1
- package/dist/CalendarPicker.jsx +12 -0
- package/dist/CalendarPicker.jsx.map +1 -1
- package/dist/Checkbox.d.ts +2 -7
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +332 -270
- package/dist/Checkbox.js.map +1 -1
- package/dist/Checkbox.jsx +70 -77
- package/dist/Checkbox.jsx.map +1 -1
- package/dist/Collection.d.ts +33 -7
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +128 -74
- package/dist/Collection.js.map +1 -1
- package/dist/Collection.jsx +46 -7
- package/dist/Collection.jsx.map +1 -1
- package/dist/Color.d.ts +15 -20
- package/dist/Color.d.ts.map +1 -1
- package/dist/Color.js +572 -334
- package/dist/Color.js.map +1 -1
- package/dist/Color.jsx +205 -85
- package/dist/Color.jsx.map +1 -1
- package/dist/ColorEditor.d.ts +3 -1
- package/dist/ColorEditor.d.ts.map +1 -1
- package/dist/ColorEditor.js +147 -124
- package/dist/ColorEditor.js.map +1 -1
- package/dist/ColorEditor.jsx +4 -1
- package/dist/ColorEditor.jsx.map +1 -1
- package/dist/ComboBox.d.ts +31 -10
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ComboBox.js +539 -274
- package/dist/ComboBox.js.map +1 -1
- package/dist/ComboBox.jsx +213 -70
- package/dist/ComboBox.jsx.map +1 -1
- package/dist/ContextualHelpTrigger.d.ts +1 -7
- package/dist/ContextualHelpTrigger.d.ts.map +1 -1
- package/dist/ContextualHelpTrigger.js +102 -72
- package/dist/ContextualHelpTrigger.js.map +1 -1
- package/dist/ContextualHelpTrigger.jsx +36 -16
- package/dist/ContextualHelpTrigger.jsx.map +1 -1
- package/dist/DateField.d.ts +2 -7
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DateField.js +0 -2
- package/dist/DateField.jsx +0 -2
- package/dist/DateField2.js +194 -179
- package/dist/DateField2.js.map +1 -1
- package/dist/DateField2.jsx +58 -55
- package/dist/DateField2.jsx.map +1 -1
- package/dist/DatePicker.d.ts +7 -7
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DatePicker.js +2 -2
- package/dist/DatePicker.jsx +2 -2
- package/dist/DatePicker2.js +357 -435
- package/dist/DatePicker2.js.map +1 -1
- package/dist/DatePicker2.jsx +109 -178
- package/dist/DatePicker2.jsx.map +1 -1
- package/dist/DateRangePickerContext.d.ts +7 -0
- package/dist/DateRangePickerContext.d.ts.map +1 -1
- package/dist/Dialog.d.ts +4 -9
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +168 -101
- package/dist/Dialog.js.map +1 -1
- package/dist/Dialog.jsx +75 -27
- package/dist/Dialog.jsx.map +1 -1
- package/dist/Disclosure.d.ts +1 -9
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/Disclosure.js +121 -79
- package/dist/Disclosure.js.map +1 -1
- package/dist/Disclosure.jsx +32 -19
- package/dist/Disclosure.jsx.map +1 -1
- package/dist/DragAndDrop.d.ts +9 -6
- package/dist/DragAndDrop.d.ts.map +1 -1
- package/dist/DragAndDrop.js +37 -22
- package/dist/DragAndDrop.js.map +1 -1
- package/dist/DragAndDrop.jsx +20 -4
- package/dist/DragAndDrop.jsx.map +1 -1
- package/dist/DragPreview.d.ts +1 -1
- package/dist/DragPreview.d.ts.map +1 -1
- package/dist/DropZone.d.ts +1 -7
- package/dist/DropZone.d.ts.map +1 -1
- package/dist/DropZone.js +74 -40
- package/dist/DropZone.js.map +1 -1
- package/dist/DropZone.jsx +24 -8
- package/dist/DropZone.jsx.map +1 -1
- package/dist/ElementTag.d.ts +9 -20
- package/dist/ElementTag.d.ts.map +1 -1
- package/dist/ElementTag.js +8 -210
- package/dist/ElementTag.js.map +1 -1
- package/dist/ElementTag.jsx +8 -57
- package/dist/ElementTag.jsx.map +1 -1
- package/dist/FieldError.d.ts +8 -7
- package/dist/FieldError.d.ts.map +1 -1
- package/dist/FieldError.js +33 -13
- package/dist/FieldError.js.map +1 -1
- package/dist/FieldError.jsx +20 -5
- package/dist/FieldError.jsx.map +1 -1
- package/dist/FileTrigger.d.ts +1 -7
- package/dist/FileTrigger.d.ts.map +1 -1
- package/dist/FileTrigger.js +30 -12
- package/dist/FileTrigger.js.map +1 -1
- package/dist/FileTrigger.jsx +15 -2
- package/dist/FileTrigger.jsx.map +1 -1
- package/dist/Focusable.d.ts +2 -8
- package/dist/Focusable.d.ts.map +1 -1
- package/dist/Focusable.js +23 -6
- package/dist/Focusable.js.map +1 -1
- package/dist/Focusable.jsx +22 -5
- package/dist/Focusable.jsx.map +1 -1
- package/dist/Form.d.ts +9 -8
- package/dist/Form.d.ts.map +1 -1
- package/dist/Form.js +66 -43
- package/dist/Form.js.map +1 -1
- package/dist/Form.jsx +36 -16
- package/dist/Form.jsx.map +1 -1
- package/dist/GridList.d.ts +5 -10
- package/dist/GridList.d.ts.map +1 -1
- package/dist/GridList.js +372 -243
- package/dist/GridList.js.map +1 -1
- package/dist/GridList.jsx +177 -99
- package/dist/GridList.jsx.map +1 -1
- package/dist/HiddenDateInput.d.ts +1 -7
- package/dist/HiddenDateInput.d.ts.map +1 -1
- package/dist/Icon.d.ts +4 -1
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Icon.js +41 -37
- package/dist/Icon.js.map +1 -1
- package/dist/Icon.jsx +7 -3
- package/dist/Icon.jsx.map +1 -1
- package/dist/Keyboard.d.ts +1 -7
- package/dist/Keyboard.d.ts.map +1 -1
- package/dist/Keyboard.js +24 -11
- package/dist/Keyboard.js.map +1 -1
- package/dist/Keyboard.jsx +15 -2
- package/dist/Keyboard.jsx.map +1 -1
- package/dist/Label.d.ts +20 -0
- package/dist/Label.d.ts.map +1 -0
- package/dist/Label.js +60 -0
- package/dist/Label.js.map +1 -0
- package/dist/Label.jsx +47 -0
- package/dist/Label.jsx.map +1 -0
- package/dist/Landmark.d.ts +4 -1
- package/dist/Landmark.d.ts.map +1 -1
- package/dist/Landmark.js +10 -4
- package/dist/Landmark.js.map +1 -1
- package/dist/Landmark.jsx +5 -1
- package/dist/Landmark.jsx.map +1 -1
- package/dist/Link.d.ts +2 -7
- package/dist/Link.d.ts.map +1 -1
- package/dist/Link.js +56 -36
- package/dist/Link.js.map +1 -1
- package/dist/Link.jsx +52 -10
- package/dist/Link.jsx.map +1 -1
- package/dist/ListBox.d.ts +17 -13
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListBox.js +647 -348
- package/dist/ListBox.js.map +1 -1
- package/dist/ListBox.jsx +339 -236
- package/dist/ListBox.jsx.map +1 -1
- package/dist/ListDropTargetDelegate.d.ts +3 -0
- package/dist/ListDropTargetDelegate.d.ts.map +1 -1
- package/dist/Menu.d.ts +39 -30
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Menu.js +547 -368
- package/dist/Menu.js.map +1 -1
- package/dist/Menu.jsx +328 -230
- package/dist/Menu.jsx.map +1 -1
- package/dist/Meter.d.ts +6 -13
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Meter.js +55 -18
- package/dist/Meter.js.map +1 -1
- package/dist/Meter.jsx +33 -8
- package/dist/Meter.jsx.map +1 -1
- package/dist/Modal.d.ts +1 -7
- package/dist/Modal.d.ts.map +1 -1
- package/dist/Modal.js +104 -56
- package/dist/Modal.js.map +1 -1
- package/dist/Modal.jsx +68 -38
- package/dist/Modal.jsx.map +1 -1
- package/dist/NumberField.d.ts +4 -7
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/NumberField.js +243 -124
- package/dist/NumberField.js.map +1 -1
- package/dist/NumberField.jsx +115 -26
- package/dist/NumberField.jsx.map +1 -1
- package/dist/Popover.d.ts +15 -7
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js +370 -181
- package/dist/Popover.js.map +1 -1
- package/dist/Popover.jsx +215 -82
- package/dist/Popover.jsx.map +1 -1
- package/dist/Pressable.d.ts +2 -8
- package/dist/Pressable.d.ts.map +1 -1
- package/dist/Pressable.js +23 -6
- package/dist/Pressable.js.map +1 -1
- package/dist/Pressable.jsx +22 -5
- package/dist/Pressable.jsx.map +1 -1
- package/dist/PreviewTrigger.d.ts +24 -0
- package/dist/PreviewTrigger.d.ts.map +1 -0
- package/dist/PreviewTrigger.js +128 -0
- package/dist/PreviewTrigger.js.map +1 -0
- package/dist/PreviewTrigger.jsx +117 -0
- package/dist/PreviewTrigger.jsx.map +1 -0
- package/dist/ProgressBar.d.ts +1 -7
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar.js +34 -14
- package/dist/ProgressBar.js.map +1 -1
- package/dist/ProgressBar.jsx +17 -3
- package/dist/ProgressBar.jsx.map +1 -1
- package/dist/RadioGroup.d.ts +2 -7
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +388 -269
- package/dist/RadioGroup.js.map +1 -1
- package/dist/RadioGroup.jsx +110 -99
- package/dist/RadioGroup.jsx.map +1 -1
- package/dist/RangeCalendar.d.ts +3 -7
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RangeCalendar.js +271 -202
- package/dist/RangeCalendar.js.map +1 -1
- package/dist/RangeCalendar.jsx +56 -37
- package/dist/RangeCalendar.jsx.map +1 -1
- package/dist/RouterProvider.d.ts +3 -9
- package/dist/RouterProvider.d.ts.map +1 -1
- package/dist/RouterProvider.js +15 -14
- package/dist/RouterProvider.js.map +1 -1
- package/dist/RouterProvider.jsx +14 -13
- package/dist/RouterProvider.jsx.map +1 -1
- package/dist/SearchField.d.ts +4 -7
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/SearchField.js +191 -164
- package/dist/SearchField.js.map +1 -1
- package/dist/SearchField.jsx +69 -62
- package/dist/SearchField.jsx.map +1 -1
- package/dist/Select.d.ts +5 -10
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +565 -359
- package/dist/Select.js.map +1 -1
- package/dist/Select.jsx +281 -161
- package/dist/Select.jsx.map +1 -1
- package/dist/SelectionIndicator.d.ts +1 -4
- package/dist/SelectionIndicator.d.ts.map +1 -1
- package/dist/SelectionIndicator.js +29 -13
- package/dist/SelectionIndicator.js.map +1 -1
- package/dist/SelectionIndicator.jsx +18 -4
- package/dist/SelectionIndicator.jsx.map +1 -1
- package/dist/Separator.d.ts +1 -7
- package/dist/Separator.d.ts.map +1 -1
- package/dist/Separator.js +22 -6
- package/dist/Separator.js.map +1 -1
- package/dist/Separator.jsx +16 -3
- package/dist/Separator.jsx.map +1 -1
- package/dist/SharedElementTransition.d.ts +1 -10
- package/dist/SharedElementTransition.d.ts.map +1 -1
- package/dist/SharedElementTransition.js +68 -40
- package/dist/SharedElementTransition.js.map +1 -1
- package/dist/SharedElementTransition.jsx +49 -25
- package/dist/SharedElementTransition.jsx.map +1 -1
- package/dist/Slider.d.ts +2 -8
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Slider.js +155 -97
- package/dist/Slider.js.map +1 -1
- package/dist/Slider.jsx +25 -12
- package/dist/Slider.jsx.map +1 -1
- package/dist/StepList.d.ts +1 -7
- package/dist/StepList.d.ts.map +1 -1
- package/dist/StepList.js +112 -68
- package/dist/StepList.js.map +1 -1
- package/dist/StepList.jsx +58 -20
- package/dist/StepList.jsx.map +1 -1
- package/dist/Switch.d.ts +2 -9
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Switch.js +164 -114
- package/dist/Switch.js.map +1 -1
- package/dist/Switch.jsx +26 -13
- package/dist/Switch.jsx.map +1 -1
- package/dist/Table.d.ts +2 -1
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +689 -592
- package/dist/Table.js.map +1 -1
- package/dist/Table.jsx +317 -237
- package/dist/Table.jsx.map +1 -1
- package/dist/Tabs.d.ts +2 -7
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js +278 -293
- package/dist/Tabs.js.map +1 -1
- package/dist/Tabs.jsx +68 -66
- package/dist/Tabs.jsx.map +1 -1
- package/dist/TagGroup.d.ts +4 -11
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/TagGroup.js +153 -115
- package/dist/TagGroup.js.map +1 -1
- package/dist/TagGroup.jsx +37 -24
- package/dist/TagGroup.jsx.map +1 -1
- package/dist/Text.d.ts +3 -3
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +24 -7
- package/dist/Text.js.map +1 -1
- package/dist/Text.jsx +17 -5
- package/dist/Text.jsx.map +1 -1
- package/dist/TextField.d.ts +3 -16
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TextField.js +104 -129
- package/dist/TextField.js.map +1 -1
- package/dist/TextField.jsx +76 -102
- package/dist/TextField.jsx.map +1 -1
- package/dist/TimeField.d.ts +2 -15
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/TimeField.js +86 -102
- package/dist/TimeField.js.map +1 -1
- package/dist/TimeField.jsx +32 -49
- package/dist/TimeField.jsx.map +1 -1
- package/dist/Toast.d.ts +10 -13
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js +209 -108
- package/dist/Toast.js.map +1 -1
- package/dist/Toast.jsx +127 -22
- package/dist/Toast.jsx.map +1 -1
- package/dist/ToggleButton.d.ts +1 -7
- package/dist/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton.js +57 -35
- package/dist/ToggleButton.js.map +1 -1
- package/dist/ToggleButton.jsx +26 -12
- package/dist/ToggleButton.jsx.map +1 -1
- package/dist/ToggleButtonGroup.d.ts +1 -7
- package/dist/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButtonGroup.js +59 -44
- package/dist/ToggleButtonGroup.js.map +1 -1
- package/dist/ToggleButtonGroup.jsx +25 -12
- package/dist/ToggleButtonGroup.jsx.map +1 -1
- package/dist/TokenField.d.ts +52 -0
- package/dist/TokenField.d.ts.map +1 -0
- package/dist/TokenField.js +301 -0
- package/dist/TokenField.js.map +1 -0
- package/dist/TokenField.jsx +197 -0
- package/dist/TokenField.jsx.map +1 -0
- package/dist/Toolbar.d.ts +2 -7
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar.js +35 -16
- package/dist/Toolbar.js.map +1 -1
- package/dist/Toolbar.jsx +15 -2
- package/dist/Toolbar.jsx.map +1 -1
- package/dist/Tooltip.d.ts +2 -7
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js +105 -68
- package/dist/Tooltip.js.map +1 -1
- package/dist/Tooltip.jsx +60 -36
- package/dist/Tooltip.jsx.map +1 -1
- package/dist/Tree.d.ts +8 -11
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Tree.js +486 -339
- package/dist/Tree.js.map +1 -1
- package/dist/Tree.jsx +155 -107
- package/dist/Tree.jsx.map +1 -1
- package/dist/Virtualizer.d.ts +39 -9
- package/dist/Virtualizer.d.ts.map +1 -1
- package/dist/Virtualizer.js +2 -2
- package/dist/Virtualizer.jsx +2 -2
- package/dist/Virtualizer2.js +491 -136
- package/dist/Virtualizer2.js.map +1 -1
- package/dist/Virtualizer2.jsx +455 -122
- package/dist/Virtualizer2.jsx.map +1 -1
- package/dist/VirtualizerLayouts.d.ts +55 -2
- package/dist/VirtualizerLayouts.d.ts.map +1 -1
- package/dist/VisuallyHidden.d.ts +4 -3
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +18 -11
- package/dist/VisuallyHidden.js.map +1 -1
- package/dist/VisuallyHidden.jsx +15 -9
- package/dist/VisuallyHidden.jsx.map +1 -1
- package/dist/contexts.d.ts +25 -0
- package/dist/contexts.d.ts.map +1 -1
- package/dist/contexts.js +3 -0
- package/dist/contexts.js.map +1 -1
- package/dist/contexts.jsx +3 -0
- package/dist/contexts.jsx.map +1 -1
- package/dist/index.d.ts +11 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -11
- package/dist/index.jsx +14 -11
- package/dist/intl/index.d.ts +16 -0
- package/dist/intl/index.d.ts.map +1 -0
- package/dist/intl.js +212 -0
- package/dist/intl.js.map +1 -0
- package/dist/intl.jsx +212 -0
- package/dist/intl.jsx.map +1 -0
- package/dist/useDragAndDrop.d.ts +4 -2
- package/dist/useDragAndDrop.d.ts.map +1 -1
- package/dist/useDragAndDrop2.js +39 -21
- package/dist/useDragAndDrop2.js.map +1 -1
- package/dist/useDragAndDrop2.jsx +39 -21
- package/dist/useDragAndDrop2.jsx.map +1 -1
- package/dist/utils.d.ts +28 -9
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +96 -24
- package/dist/utils.js.map +1 -1
- package/dist/utils.jsx +81 -24
- package/dist/utils.jsx.map +1 -1
- package/dist/virtualizer/Layout.d.ts +9 -0
- package/dist/virtualizer/Layout.d.ts.map +1 -1
- package/dist/virtualizer/Layout.js +23 -2
- package/dist/virtualizer/Layout.js.map +1 -1
- package/dist/virtualizer/Layout.jsx +23 -2
- package/dist/virtualizer/Layout.jsx.map +1 -1
- package/package.json +29 -10
- package/src/ActionBar.tsx +50 -24
- package/src/ActionGroup.tsx +31 -19
- package/src/Alert.tsx +10 -4
- package/src/Autocomplete.tsx +24 -15
- package/src/Breadcrumbs.tsx +32 -16
- package/src/Button.tsx +182 -67
- package/src/Calendar.tsx +65 -47
- package/src/CalendarPicker.tsx +16 -1
- package/src/Checkbox.tsx +84 -116
- package/src/Collection.tsx +84 -3
- package/src/Color.tsx +282 -104
- package/src/ColorEditor.tsx +5 -1
- package/src/ComboBox.tsx +384 -109
- package/src/ContextualHelpTrigger.tsx +47 -41
- package/src/DateField.tsx +74 -106
- package/src/DatePicker.tsx +156 -352
- package/src/DateRangePickerContext.tsx +8 -0
- package/src/Dialog.tsx +105 -38
- package/src/Disclosure.tsx +29 -19
- package/src/DragAndDrop.tsx +43 -8
- package/src/DragPreview.tsx +20 -1
- package/src/DropZone.tsx +32 -18
- package/src/ElementTag.tsx +14 -104
- package/src/FieldError.tsx +39 -7
- package/src/FileTrigger.tsx +18 -3
- package/src/Focusable.tsx +27 -6
- package/src/Form.tsx +57 -11
- package/src/GridList.tsx +233 -141
- package/src/HiddenDateInput.tsx +19 -3
- package/src/Icon.tsx +8 -2
- package/src/Keyboard.tsx +18 -2
- package/src/Label.tsx +77 -0
- package/src/Landmark.tsx +6 -1
- package/src/Link.tsx +65 -19
- package/src/ListBox.tsx +645 -468
- package/src/ListDropTargetDelegate.ts +4 -0
- package/src/Menu.tsx +512 -349
- package/src/Meter.tsx +42 -8
- package/src/Modal.tsx +85 -42
- package/src/NumberField.tsx +161 -48
- package/src/Popover.tsx +424 -148
- package/src/Pressable.tsx +27 -6
- package/src/PreviewTrigger.tsx +171 -0
- package/src/ProgressBar.tsx +25 -3
- package/src/RadioGroup.tsx +230 -161
- package/src/RangeCalendar.tsx +75 -63
- package/src/RouterProvider.tsx +24 -14
- package/src/SearchField.tsx +118 -121
- package/src/Select.tsx +454 -274
- package/src/SelectionIndicator.tsx +21 -3
- package/src/Separator.tsx +17 -1
- package/src/SharedElementTransition.tsx +115 -97
- package/src/Slider.tsx +35 -17
- package/src/StepList.tsx +71 -32
- package/src/Switch.tsx +45 -29
- package/src/Table.tsx +446 -380
- package/src/Tabs.tsx +132 -155
- package/src/TagGroup.tsx +53 -40
- package/src/Text.tsx +23 -6
- package/src/TextField.tsx +118 -159
- package/src/TimeField.tsx +34 -95
- package/src/Toast.tsx +141 -67
- package/src/ToggleButton.tsx +33 -15
- package/src/ToggleButtonGroup.tsx +27 -9
- package/src/TokenField.tsx +379 -0
- package/src/Toolbar.tsx +19 -9
- package/src/Tooltip.tsx +126 -84
- package/src/Tree.tsx +233 -173
- package/src/Virtualizer.tsx +400 -138
- package/src/VirtualizerLayouts.ts +211 -26
- package/src/VisuallyHidden.tsx +22 -8
- package/src/contexts.ts +13 -0
- package/src/index.ts +32 -11
- package/src/intl/ar-AE.json +6 -0
- package/src/intl/bg-BG.json +6 -0
- package/src/intl/cs-CZ.json +6 -0
- package/src/intl/da-DK.json +6 -0
- package/src/intl/de-DE.json +6 -0
- package/src/intl/el-GR.json +6 -0
- package/src/intl/en-US.json +6 -0
- package/src/intl/es-ES.json +6 -0
- package/src/intl/et-EE.json +6 -0
- package/src/intl/fi-FI.json +6 -0
- package/src/intl/fr-FR.json +6 -0
- package/src/intl/he-IL.json +6 -0
- package/src/intl/hr-HR.json +6 -0
- package/src/intl/hu-HU.json +6 -0
- package/src/intl/index.ts +125 -0
- package/src/intl/it-IT.json +6 -0
- package/src/intl/ja-JP.json +6 -0
- package/src/intl/ko-KR.json +6 -0
- package/src/intl/lt-LT.json +6 -0
- package/src/intl/lv-LV.json +6 -0
- package/src/intl/nb-NO.json +6 -0
- package/src/intl/nl-NL.json +6 -0
- package/src/intl/pl-PL.json +6 -0
- package/src/intl/pt-BR.json +6 -0
- package/src/intl/pt-PT.json +6 -0
- package/src/intl/ro-RO.json +6 -0
- package/src/intl/ru-RU.json +6 -0
- package/src/intl/sk-SK.json +6 -0
- package/src/intl/sl-SI.json +6 -0
- package/src/intl/sr-SP.json +6 -0
- package/src/intl/sv-SE.json +6 -0
- package/src/intl/tr-TR.json +6 -0
- package/src/intl/uk-UA.json +6 -0
- package/src/intl/zh-CN.json +6 -0
- package/src/intl/zh-TW.json +6 -0
- package/src/useDragAndDrop.ts +30 -32
- package/src/utils.tsx +124 -68
- package/src/virtualizer/Layout.ts +29 -0
package/src/ListBox.tsx
CHANGED
|
@@ -1,33 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Ported to SolidJS for Proyecto Viviana; based on packages/react-aria-components/src/ListBox.tsx
|
|
14
|
+
|
|
1
15
|
/**
|
|
2
16
|
* ListBox component for solidaria-components
|
|
3
17
|
*
|
|
4
18
|
* A pre-wired headless listbox that combines state + aria hooks.
|
|
5
|
-
*
|
|
19
|
+
* Solid adaptation of the pinned ListBox component.
|
|
6
20
|
*/
|
|
7
21
|
|
|
8
22
|
import {
|
|
9
|
-
type JSX,
|
|
10
23
|
createContext,
|
|
11
24
|
createEffect,
|
|
12
25
|
createMemo,
|
|
26
|
+
createRenderEffect,
|
|
13
27
|
createSignal,
|
|
14
|
-
on,
|
|
15
28
|
onCleanup,
|
|
16
|
-
|
|
29
|
+
untrack,
|
|
17
30
|
useContext,
|
|
18
31
|
For,
|
|
19
32
|
Show,
|
|
33
|
+
createTrackedEffect,
|
|
20
34
|
} from "solid-js";
|
|
35
|
+
import type { Context, Accessor } from "solid-js";
|
|
36
|
+
import type { JSX } from "@solidjs/web";
|
|
21
37
|
import {
|
|
22
38
|
createListBox,
|
|
23
39
|
createOption,
|
|
24
40
|
createFocusRing,
|
|
25
41
|
createScrollIntoViewOnFocus,
|
|
26
42
|
createStringFormatter,
|
|
27
|
-
createDragSession,
|
|
28
|
-
getGlobalDraggingCollectionRef,
|
|
29
|
-
getGlobalDraggingKeys,
|
|
30
|
-
registerDropItem,
|
|
31
43
|
dndIntlStrings,
|
|
32
44
|
mergeProps,
|
|
33
45
|
moveVirtualFocus,
|
|
@@ -44,6 +56,8 @@ import {
|
|
|
44
56
|
type ListFilterFn,
|
|
45
57
|
type Key,
|
|
46
58
|
type DropTarget,
|
|
59
|
+
type DroppableCollectionState,
|
|
60
|
+
type Collection,
|
|
47
61
|
} from "@proyecto-viviana/solid-stately";
|
|
48
62
|
import { useAutocompleteCollection } from "./Autocomplete";
|
|
49
63
|
import {
|
|
@@ -51,18 +65,24 @@ import {
|
|
|
51
65
|
type ClassNameOrFunction,
|
|
52
66
|
type StyleOrFunction,
|
|
53
67
|
type SlotProps,
|
|
68
|
+
DEFAULT_SLOT,
|
|
69
|
+
OptionContent,
|
|
70
|
+
Provider,
|
|
54
71
|
useRenderProps,
|
|
55
72
|
filterDOMProps,
|
|
73
|
+
dataAttr,
|
|
56
74
|
} from "./utils";
|
|
75
|
+
import { TextContext } from "./Text";
|
|
57
76
|
import { SharedElementTransition } from "./SharedElementTransition";
|
|
58
77
|
import {
|
|
59
78
|
SelectionIndicatorContext,
|
|
60
79
|
type SelectionIndicatorContextValue,
|
|
61
80
|
} from "./SelectionIndicator";
|
|
62
|
-
import { useVirtualizerContext } from "./Virtualizer";
|
|
81
|
+
import { useVirtualizerContext, PersistedVirtualItem, VirtualizerItem } from "./Virtualizer";
|
|
63
82
|
import { type DragAndDropHooks } from "./useDragAndDrop";
|
|
64
83
|
import {
|
|
65
84
|
getNormalizedDropTargetKey,
|
|
85
|
+
indexesOutsideRange,
|
|
66
86
|
mergePersistedKeysIntoVirtualRange,
|
|
67
87
|
useDndPersistedKeys,
|
|
68
88
|
useRenderDropIndicator,
|
|
@@ -70,6 +90,7 @@ import {
|
|
|
70
90
|
type DropIndicatorProps,
|
|
71
91
|
} from "./DragAndDrop";
|
|
72
92
|
import type { ItemDropTarget } from "@proyecto-viviana/solid-stately";
|
|
93
|
+
import { splitProps } from "@proyecto-viviana/solidaria/utils";
|
|
73
94
|
import {
|
|
74
95
|
CollectionRendererContext,
|
|
75
96
|
Section,
|
|
@@ -77,8 +98,10 @@ import {
|
|
|
77
98
|
Group,
|
|
78
99
|
type CollectionEntry,
|
|
79
100
|
type CollectionRendererContextValue,
|
|
101
|
+
type CollectionSection,
|
|
80
102
|
type SectionProps,
|
|
81
103
|
useCollectionRenderer,
|
|
104
|
+
useCollectionRoot,
|
|
82
105
|
isCollectionSection,
|
|
83
106
|
flattenCollectionEntries,
|
|
84
107
|
} from "./Collection";
|
|
@@ -166,6 +189,12 @@ export interface ListBoxOptionRenderProps {
|
|
|
166
189
|
isDisabled: boolean;
|
|
167
190
|
}
|
|
168
191
|
|
|
192
|
+
export type ListBoxItemProps<T> = ListBoxOptionProps<T>;
|
|
193
|
+
export type ListBoxItemRenderProps = ListBoxOptionRenderProps;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @deprecated Use {@link ListBoxItemProps}. Removed in a future minor.
|
|
197
|
+
*/
|
|
169
198
|
export interface ListBoxOptionProps<T>
|
|
170
199
|
extends Omit<AriaOptionProps, "children" | "key">, SlotProps {
|
|
171
200
|
/** The unique key for the option. */
|
|
@@ -214,12 +243,168 @@ export const ListBoxContext = createContext<ListBoxContextValue<unknown> | null>
|
|
|
214
243
|
export const ListBoxStateContext = createContext<ListState<unknown> | null>(null);
|
|
215
244
|
export const ListStateContext = ListBoxStateContext;
|
|
216
245
|
|
|
246
|
+
function dropIndicatorLabel(
|
|
247
|
+
target: ItemDropTarget,
|
|
248
|
+
collection: Collection<unknown>,
|
|
249
|
+
format: (
|
|
250
|
+
key: "dropOnItem" | "insertBetween" | "insertAfter" | "insertBefore",
|
|
251
|
+
args?: Record<string, string>,
|
|
252
|
+
) => string,
|
|
253
|
+
): string {
|
|
254
|
+
const getText = (key: Key | null): string => {
|
|
255
|
+
if (key == null) return "";
|
|
256
|
+
return collection.getTextValue(key) ?? collection.getItem(key)?.textValue ?? "";
|
|
257
|
+
};
|
|
258
|
+
if (target.dropPosition === "on") {
|
|
259
|
+
return format("dropOnItem", { itemText: getText(target.key) });
|
|
260
|
+
}
|
|
261
|
+
let before: Key | null;
|
|
262
|
+
let after: Key | null;
|
|
263
|
+
if (target.dropPosition === "before") {
|
|
264
|
+
const prevKey = collection.getKeyBefore(target.key);
|
|
265
|
+
const prevNode = prevKey != null ? collection.getItem(prevKey) : null;
|
|
266
|
+
before = prevNode?.type === "item" ? prevNode.key : null;
|
|
267
|
+
} else {
|
|
268
|
+
before = target.key;
|
|
269
|
+
}
|
|
270
|
+
if (target.dropPosition === "after") {
|
|
271
|
+
const nextKey = collection.getKeyAfter(target.key);
|
|
272
|
+
const nextNode = nextKey != null ? collection.getItem(nextKey) : null;
|
|
273
|
+
after = nextNode?.type === "item" ? nextNode.key : null;
|
|
274
|
+
} else {
|
|
275
|
+
after = target.key;
|
|
276
|
+
}
|
|
277
|
+
if (before != null && after != null) {
|
|
278
|
+
return format("insertBetween", {
|
|
279
|
+
beforeItemText: getText(before),
|
|
280
|
+
afterItemText: getText(after),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
if (before != null) {
|
|
284
|
+
return format("insertAfter", { itemText: getText(before) });
|
|
285
|
+
}
|
|
286
|
+
if (after != null) {
|
|
287
|
+
return format("insertBefore", { itemText: getText(after) });
|
|
288
|
+
}
|
|
289
|
+
return "";
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* RAC `ListBox.tsx:662-717` `ListBoxDropIndicatorWrapper` — a stable module-level
|
|
294
|
+
* component so Solid does not remount (and unregister) the indicator on every
|
|
295
|
+
* parent ListBox re-render. `useDropIndicator` owns register + focus
|
|
296
|
+
* (`useDroppableItem.ts:49-88`).
|
|
297
|
+
*/
|
|
298
|
+
function ListBoxDropIndicatorWrapper(props: DropIndicatorProps): JSX.Element {
|
|
299
|
+
const listContext = useContext(ListBoxContext);
|
|
300
|
+
const listState = useContext(ListBoxStateContext);
|
|
301
|
+
const [el, setEl] = createSignal<HTMLDivElement | null>(null);
|
|
302
|
+
const dndFormatter = createStringFormatter(dndIntlStrings);
|
|
303
|
+
const dropState = listContext?.dropState as DroppableCollectionState | undefined;
|
|
304
|
+
const indicator = listContext?.dragAndDropHooks?.useDropIndicator?.(
|
|
305
|
+
{ target: props.target },
|
|
306
|
+
dropState as DroppableCollectionState,
|
|
307
|
+
el,
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
return (
|
|
311
|
+
<Show when={indicator && !indicator.isHidden}>
|
|
312
|
+
<div
|
|
313
|
+
{...indicator?.dropIndicatorProps}
|
|
314
|
+
ref={setEl}
|
|
315
|
+
role="option"
|
|
316
|
+
class="solidaria-DropIndicator"
|
|
317
|
+
aria-label={
|
|
318
|
+
listState
|
|
319
|
+
? dropIndicatorLabel(props.target, listState.collection(), (key, args) =>
|
|
320
|
+
dndFormatter().format(key, args),
|
|
321
|
+
)
|
|
322
|
+
: undefined
|
|
323
|
+
}
|
|
324
|
+
data-drop-target={dataAttr(indicator?.isDropTarget)}
|
|
325
|
+
/>
|
|
326
|
+
</Show>
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Owns only the collection item. Drop-indicator siblings live in their own
|
|
332
|
+
* components so their tracking cannot remount this node.
|
|
333
|
+
*
|
|
334
|
+
* Comparison hyperscript children (`hc` thunks) are one-shot: if the fragment
|
|
335
|
+
* insert that owns the option also tracks indicator `Show`, the effect
|
|
336
|
+
* re-runs, disposes the option, and Chromium maps focus to
|
|
337
|
+
* `listbox:Permissions`. RAC `ListBoxItem` stays mounted while Collection
|
|
338
|
+
* inserts indicator siblings (`react-aria-components/src/ListBox.tsx`).
|
|
339
|
+
*/
|
|
340
|
+
function ListBoxRenderedItem<T>(props: {
|
|
341
|
+
item: T;
|
|
342
|
+
renderItem: (item: T) => JSX.Element;
|
|
343
|
+
}): JSX.Element {
|
|
344
|
+
// Comparison `hc` returns a one-shot thunk. Solid's insert treats a function
|
|
345
|
+
// child as an accessor and will call it again when a sibling indicator
|
|
346
|
+
// invalidates. Instantiate once under this owner so the option node stays.
|
|
347
|
+
const child = untrack(() => {
|
|
348
|
+
const rendered = props.renderItem(props.item);
|
|
349
|
+
return typeof rendered === "function" ? (rendered as () => JSX.Element)() : rendered;
|
|
350
|
+
});
|
|
351
|
+
return child as JSX.Element;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function ListBoxDropIndicatorSlot(props: {
|
|
355
|
+
itemIndex: number | Accessor<number>;
|
|
356
|
+
position: "before" | "after" | "on";
|
|
357
|
+
renderDropIndicator?: (
|
|
358
|
+
index: number,
|
|
359
|
+
position: "before" | "after" | "on",
|
|
360
|
+
) => JSX.Element | undefined;
|
|
361
|
+
}): JSX.Element {
|
|
362
|
+
const itemIndex = () =>
|
|
363
|
+
typeof props.itemIndex === "function" ? props.itemIndex() : props.itemIndex;
|
|
364
|
+
return <>{props.renderDropIndicator?.(itemIndex(), props.position)}</>;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Stable per-item row so drop-indicator mount does not remount the option.
|
|
369
|
+
*/
|
|
370
|
+
function ListBoxItemWithDropIndicators<T>(props: {
|
|
371
|
+
item: T;
|
|
372
|
+
itemIndex: number | Accessor<number>;
|
|
373
|
+
isLastInLevel: boolean | Accessor<boolean>;
|
|
374
|
+
renderItem: (item: T) => JSX.Element;
|
|
375
|
+
renderDropIndicator?: (
|
|
376
|
+
index: number,
|
|
377
|
+
position: "before" | "after" | "on",
|
|
378
|
+
) => JSX.Element | undefined;
|
|
379
|
+
}): JSX.Element {
|
|
380
|
+
const isLast = () =>
|
|
381
|
+
typeof props.isLastInLevel === "function" ? props.isLastInLevel() : props.isLastInLevel;
|
|
382
|
+
return (
|
|
383
|
+
<>
|
|
384
|
+
<ListBoxDropIndicatorSlot
|
|
385
|
+
itemIndex={props.itemIndex}
|
|
386
|
+
position="before"
|
|
387
|
+
renderDropIndicator={props.renderDropIndicator}
|
|
388
|
+
/>
|
|
389
|
+
<ListBoxRenderedItem item={props.item} renderItem={props.renderItem} />
|
|
390
|
+
<Show when={isLast()}>
|
|
391
|
+
<ListBoxDropIndicatorSlot
|
|
392
|
+
itemIndex={props.itemIndex}
|
|
393
|
+
position="after"
|
|
394
|
+
renderDropIndicator={props.renderDropIndicator}
|
|
395
|
+
/>
|
|
396
|
+
</Show>
|
|
397
|
+
</>
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
|
|
217
401
|
/**
|
|
218
402
|
* A listbox displays a list of options and allows a user to select one or more of them.
|
|
219
403
|
*/
|
|
220
404
|
export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
221
405
|
const parentContext = useContext(ListBoxContext) as ListBoxContextValue<T> | null;
|
|
222
|
-
const contextSlotProps =
|
|
406
|
+
const contextSlotProps =
|
|
407
|
+
parentContext?.slots?.[typeof props.slot === "string" ? props.slot : "default"];
|
|
223
408
|
const mergedListBoxProps = contextSlotProps
|
|
224
409
|
? (mergeProps(contextSlotProps, props) as ListBoxProps<T>)
|
|
225
410
|
: props;
|
|
@@ -326,8 +511,7 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
326
511
|
// option emits aria-posinset/aria-setsize for the windowed (incomplete) DOM.
|
|
327
512
|
const parentCollectionRenderer = useCollectionRenderer<unknown>();
|
|
328
513
|
const listBoxAria = createListBox(
|
|
329
|
-
{
|
|
330
|
-
...ariaProps,
|
|
514
|
+
mergeProps(ariaProps, {
|
|
331
515
|
get isVirtualized() {
|
|
332
516
|
return parentCollectionRenderer?.isVirtualized ?? ariaProps.isVirtualized;
|
|
333
517
|
},
|
|
@@ -357,7 +541,7 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
357
541
|
get direction() {
|
|
358
542
|
return locale().direction;
|
|
359
543
|
},
|
|
360
|
-
},
|
|
544
|
+
}),
|
|
361
545
|
state,
|
|
362
546
|
() => listRef(),
|
|
363
547
|
);
|
|
@@ -365,7 +549,10 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
365
549
|
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
366
550
|
|
|
367
551
|
const renderValues = createMemo<ListBoxRenderProps>(() => ({
|
|
368
|
-
|
|
552
|
+
// RAC ListBox.tsx:366-414: `data-focused` / render-prop `isFocused` come from
|
|
553
|
+
// `useFocusRing` on the listbox element, not collection focus. Virtual focus
|
|
554
|
+
// (ComboBox) leaves the listbox itself unfocused.
|
|
555
|
+
isFocused: isFocused(),
|
|
369
556
|
isFocusVisible: isFocusVisible(),
|
|
370
557
|
isDisabled: resolveDisabled(),
|
|
371
558
|
isEmpty: state.collection().size === 0,
|
|
@@ -408,19 +595,19 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
408
595
|
ref: () => listRef(),
|
|
409
596
|
});
|
|
410
597
|
|
|
411
|
-
// Autocomplete bridge.
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
//
|
|
415
|
-
// handlers and useSelectableItem's per-item moveVirtualFocus, at the component
|
|
416
|
-
// layer, without touching the shared hooks (protecting ComboBox/Picker).
|
|
598
|
+
// Autocomplete bridge. The shared selectable collection owns keyboard
|
|
599
|
+
// navigation and collection focus. This component keeps the Solid DOM handoff
|
|
600
|
+
// that mirrors the focused key to the input's active descendant. Ticket #100
|
|
601
|
+
// tracks moving the remaining virtual-focus work into the shared item layer.
|
|
417
602
|
if (autocompleteCtx) {
|
|
418
603
|
// Forward path: the input dispatches FOCUS_EVENT/CLEAR_FOCUS_EVENT onto the
|
|
419
604
|
// collection element. FOCUS_EVENT marks the collection focused (and, when the
|
|
420
|
-
// user types forward, requests the first item)
|
|
421
|
-
//
|
|
605
|
+
// user types forward, requests the first item). The shared collection handles
|
|
606
|
+
// the re-dispatched keyboard event.
|
|
422
607
|
let shouldVirtualFocusFirst = false;
|
|
423
|
-
|
|
608
|
+
createTrackedEffect(() => {
|
|
609
|
+
const _s2Cleanups: Array<() => void> = [];
|
|
610
|
+
|
|
424
611
|
const list = listRef();
|
|
425
612
|
if (!list) return;
|
|
426
613
|
const onFocusEvent = (e: Event) => {
|
|
@@ -440,10 +627,14 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
440
627
|
};
|
|
441
628
|
list.addEventListener(FOCUS_EVENT, onFocusEvent);
|
|
442
629
|
list.addEventListener(CLEAR_FOCUS_EVENT, onClearFocusEvent);
|
|
443
|
-
|
|
630
|
+
_s2Cleanups.push(() => {
|
|
444
631
|
list.removeEventListener(FOCUS_EVENT, onFocusEvent);
|
|
445
632
|
list.removeEventListener(CLEAR_FOCUS_EVENT, onClearFocusEvent);
|
|
446
633
|
});
|
|
634
|
+
|
|
635
|
+
return () => {
|
|
636
|
+
for (const c of _s2Cleanups) c();
|
|
637
|
+
};
|
|
447
638
|
});
|
|
448
639
|
|
|
449
640
|
// Focus the first item once the (filtered) collection settles after the user
|
|
@@ -451,41 +642,53 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
451
642
|
// descendant by moving virtual focus onto the collection itself (its focusin
|
|
452
643
|
// reaches the input's clear branch). Mirrors useSelectableCollection.
|
|
453
644
|
createEffect(
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
{ defer: true },
|
|
468
|
-
),
|
|
645
|
+
() => [state.collection().getFirstKey?.() ?? null, state.collection().size] as const,
|
|
646
|
+
([firstKey, size]) => {
|
|
647
|
+
if (!shouldVirtualFocusFirst) return;
|
|
648
|
+
if (firstKey == null) {
|
|
649
|
+
const list = listRef();
|
|
650
|
+
if (list) moveVirtualFocus(list);
|
|
651
|
+
if (size > 0) shouldVirtualFocusFirst = false;
|
|
652
|
+
} else {
|
|
653
|
+
state.setFocusedKey(firstKey);
|
|
654
|
+
shouldVirtualFocusFirst = false;
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
{ defer: true },
|
|
469
658
|
);
|
|
470
659
|
|
|
471
660
|
// Reverse path: mirror the focused key onto the option's DOM element via a
|
|
472
661
|
// synthetic, bubbling focusin (moveVirtualFocus). The input's focusin listener
|
|
473
662
|
// reads target.id into its aria-activedescendant. Option ids are String(key)
|
|
474
663
|
// in this path (createOption). Real DOM focus stays on the input.
|
|
475
|
-
createEffect(
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
664
|
+
createEffect(
|
|
665
|
+
() => {
|
|
666
|
+
const key = state.focusedKey();
|
|
667
|
+
const list = listRef();
|
|
668
|
+
const focused = state.isFocused();
|
|
669
|
+
return { key, list, focused };
|
|
670
|
+
},
|
|
671
|
+
({ key, list, focused }) => {
|
|
672
|
+
if (!list || !focused) return;
|
|
673
|
+
if (key == null) return;
|
|
674
|
+
const el = list.ownerDocument.getElementById(String(key));
|
|
675
|
+
if (el) moveVirtualFocus(el);
|
|
676
|
+
},
|
|
677
|
+
);
|
|
483
678
|
}
|
|
484
679
|
|
|
485
|
-
|
|
680
|
+
// RAC ListBox iterates CollectionRoot's filtered collection, not the
|
|
681
|
+
// unfiltered `items` prop. Keyboard already walks `state.collection()`
|
|
682
|
+
// (createFilteredListState under Autocomplete; baseState otherwise).
|
|
486
683
|
const getItemNodes = createMemo(() =>
|
|
487
684
|
Array.from(state.collection()).filter((node) => node.type === "item"),
|
|
488
685
|
);
|
|
686
|
+
const collectionItems = createMemo(() => getItemNodes().map((node) => node.value as T));
|
|
687
|
+
const isEmpty = () => state.collection().size === 0;
|
|
688
|
+
const isLastDropItem = (itemIndex: number | Accessor<number>) => {
|
|
689
|
+
const i = typeof itemIndex === "function" ? itemIndex() : itemIndex;
|
|
690
|
+
return getItemNodes().length > 0 && i === getItemNodes().length - 1;
|
|
691
|
+
};
|
|
489
692
|
const getDropTargetByIndex = (
|
|
490
693
|
index: number,
|
|
491
694
|
position: "before" | "after" | "on",
|
|
@@ -504,40 +707,36 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
504
707
|
hooks.ListDropTargetDelegate),
|
|
505
708
|
);
|
|
506
709
|
});
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
710
|
+
const dropStateValue = hasDroppableDnd()
|
|
711
|
+
? local.dragAndDropHooks?.useDroppableCollectionState?.({
|
|
712
|
+
get collection() {
|
|
713
|
+
return state.collection();
|
|
714
|
+
},
|
|
715
|
+
})
|
|
716
|
+
: undefined;
|
|
717
|
+
const dropState = () => dropStateValue;
|
|
511
718
|
const hasDraggableDnd = createMemo(() => {
|
|
512
719
|
const hooks = local.dragAndDropHooks;
|
|
513
720
|
return Boolean(hooks?.useDraggableCollectionState && hooks.useDraggableCollection);
|
|
514
721
|
});
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const droppableCollection = createMemo(() => {
|
|
722
|
+
const dragStateValue = hasDraggableDnd()
|
|
723
|
+
? local.dragAndDropHooks?.useDraggableCollectionState?.({
|
|
724
|
+
items: flatItems(),
|
|
725
|
+
collection: state.collection(),
|
|
726
|
+
selectedKeys: state.selectionManager.selectedKeys,
|
|
727
|
+
isSelected: (key) => state.selectionManager.isSelected(key),
|
|
728
|
+
})
|
|
729
|
+
: undefined;
|
|
730
|
+
const dragState = () => dragStateValue;
|
|
731
|
+
if (local.dragAndDropHooks?.useDraggableCollection && dragStateValue) {
|
|
732
|
+
local.dragAndDropHooks.useDraggableCollection({}, dragStateValue, () => listRef());
|
|
733
|
+
}
|
|
734
|
+
const droppableCollectionValue = (() => {
|
|
529
735
|
if (!hasDroppableDnd()) return undefined;
|
|
530
736
|
const hooks = local.dragAndDropHooks;
|
|
531
|
-
const activeDropState =
|
|
737
|
+
const activeDropState = dropStateValue;
|
|
532
738
|
if (!hooks?.useDroppableCollection || !activeDropState) return undefined;
|
|
533
|
-
const resolveDirection = (): "ltr" | "rtl" =>
|
|
534
|
-
const el = listRef();
|
|
535
|
-
if (el && typeof window !== "undefined" && typeof window.getComputedStyle === "function") {
|
|
536
|
-
const dir = window.getComputedStyle(el).direction;
|
|
537
|
-
if (dir === "rtl") return "rtl";
|
|
538
|
-
}
|
|
539
|
-
return typeof document !== "undefined" && document.dir === "rtl" ? "rtl" : "ltr";
|
|
540
|
-
};
|
|
739
|
+
const resolveDirection = (): "ltr" | "rtl" => locale().direction;
|
|
541
740
|
const dropTargetDelegate =
|
|
542
741
|
hooks.dropTargetDelegate ??
|
|
543
742
|
parentCollectionRenderer?.dropTargetDelegate ??
|
|
@@ -564,15 +763,21 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
564
763
|
// (`navigate()` walks getKeyAfter/getKeyBefore) and post-drop focus
|
|
565
764
|
// restoration. Reading it here re-registers the drop target when the
|
|
566
765
|
// collection changes (mirrors upstream keying its effect on the state).
|
|
567
|
-
|
|
568
|
-
|
|
766
|
+
get collection() {
|
|
767
|
+
return state.collection();
|
|
768
|
+
},
|
|
769
|
+
get selectedKeys() {
|
|
770
|
+
return state.selectionManager.selectedKeys;
|
|
771
|
+
},
|
|
569
772
|
setSelectedKeys: (keys) => state.selectionManager.setSelectedKeys(keys),
|
|
570
773
|
setFocusedKey: (key) => state.setFocusedKey(key),
|
|
774
|
+
setFocused: (isFocused) => state.setFocused(isFocused),
|
|
571
775
|
},
|
|
572
776
|
activeDropState,
|
|
573
777
|
() => listRef(),
|
|
574
778
|
);
|
|
575
|
-
});
|
|
779
|
+
})();
|
|
780
|
+
const droppableCollection = () => droppableCollectionValue;
|
|
576
781
|
const isRootDropTarget = createMemo(() => {
|
|
577
782
|
return Boolean(dropState()?.target?.type === "root");
|
|
578
783
|
});
|
|
@@ -584,163 +789,14 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
584
789
|
if (!target || target.type !== "item") return undefined;
|
|
585
790
|
return dndRenderDropIndicator()?.(target);
|
|
586
791
|
};
|
|
792
|
+
// Stable callback so `For` item templates do not track drop-indicator
|
|
793
|
+
// reactivity (that remounts the option). The row component reads this.
|
|
794
|
+
const renderItemDropIndicator = (index: number, position: "before" | "after" | "on") =>
|
|
795
|
+
dndDropIndicator(index, position) ??
|
|
796
|
+
parentCollectionRenderer?.renderDropIndicator?.(index, position);
|
|
587
797
|
|
|
588
|
-
// ── Drop indicator (Fix B: labeled, self-focusing) ─────────────────────────
|
|
589
|
-
// The port of react-aria-components' ListBoxDropIndicatorWrapper +
|
|
590
|
-
// useDropIndicator. The droppable-collection state layer diverged to a minimal
|
|
591
|
-
// reactive target-holder with no collection reference, so the label (which
|
|
592
|
-
// needs the collection's text values) and the self-focus (which needs the live
|
|
593
|
-
// drag session) are computed here in the host layer, where both are available.
|
|
594
|
-
const dndFormatter = createStringFormatter(dndIntlStrings);
|
|
595
|
-
const dragSession = createDragSession();
|
|
596
|
-
const dropIndicatorTargetsEqual = (
|
|
597
|
-
a: DropTarget | null | undefined,
|
|
598
|
-
b: ItemDropTarget,
|
|
599
|
-
): boolean =>
|
|
600
|
-
!!a && a.type === "item" && a.key === b.key && a.dropPosition === b.dropPosition;
|
|
601
|
-
// Faithful port of useDropIndicator's label logic: "Drop on X" for an on-item
|
|
602
|
-
// target, else "Insert between X and Y" / "Insert before X" / "Insert after X"
|
|
603
|
-
// resolved from the target's neighbours in the collection.
|
|
604
|
-
const dropIndicatorLabel = (target: ItemDropTarget): string => {
|
|
605
|
-
const collection = state.collection();
|
|
606
|
-
const getText = (key: Key | null): string => {
|
|
607
|
-
if (key == null) return "";
|
|
608
|
-
return collection.getTextValue(key) ?? collection.getItem(key)?.textValue ?? "";
|
|
609
|
-
};
|
|
610
|
-
if (target.dropPosition === "on") {
|
|
611
|
-
return dndFormatter().format("dropOnItem", { itemText: getText(target.key) });
|
|
612
|
-
}
|
|
613
|
-
let before: Key | null;
|
|
614
|
-
let after: Key | null;
|
|
615
|
-
if (target.dropPosition === "before") {
|
|
616
|
-
const prevKey = collection.getKeyBefore(target.key);
|
|
617
|
-
const prevNode = prevKey != null ? collection.getItem(prevKey) : null;
|
|
618
|
-
before = prevNode?.type === "item" ? prevNode.key : null;
|
|
619
|
-
} else {
|
|
620
|
-
before = target.key;
|
|
621
|
-
}
|
|
622
|
-
if (target.dropPosition === "after") {
|
|
623
|
-
const nextKey = collection.getKeyAfter(target.key);
|
|
624
|
-
const nextNode = nextKey != null ? collection.getItem(nextKey) : null;
|
|
625
|
-
after = nextNode?.type === "item" ? nextNode.key : null;
|
|
626
|
-
} else {
|
|
627
|
-
after = target.key;
|
|
628
|
-
}
|
|
629
|
-
if (before != null && after != null) {
|
|
630
|
-
return dndFormatter().format("insertBetween", {
|
|
631
|
-
beforeItemText: getText(before),
|
|
632
|
-
afterItemText: getText(after),
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
if (before != null) {
|
|
636
|
-
return dndFormatter().format("insertAfter", { itemText: getText(before) });
|
|
637
|
-
}
|
|
638
|
-
if (after != null) {
|
|
639
|
-
return dndFormatter().format("insertBefore", { itemText: getText(after) });
|
|
640
|
-
}
|
|
641
|
-
return "";
|
|
642
|
-
};
|
|
643
|
-
// Wrap the raw Set<string> the DragManager hands drop items into the DragTypes
|
|
644
|
-
// delegate the port state expects (mirrors createDroppableCollection.wrapTypes).
|
|
645
|
-
const wrapDropTypes = (types: Set<string>) => ({
|
|
646
|
-
has: (type: string | string[]) => {
|
|
647
|
-
if (typeof type === "string") return types.has(type);
|
|
648
|
-
if (Array.isArray(type)) return type.some((t) => typeof t === "string" && types.has(t));
|
|
649
|
-
return false;
|
|
650
|
-
},
|
|
651
|
-
});
|
|
652
|
-
const ListBoxDropIndicator = (props: { target: ItemDropTarget }): JSX.Element => {
|
|
653
|
-
const [indicatorRef, setIndicatorRef] = createSignal<HTMLDivElement | null>(null);
|
|
654
|
-
const isDropTarget = createMemo(() =>
|
|
655
|
-
dropIndicatorTargetsEqual(dropState()?.target, props.target),
|
|
656
|
-
);
|
|
657
|
-
// aria-hidden mirrors useDropIndicator: outside a drag session, or on a
|
|
658
|
-
// non-active target, the indicator is hidden from AT ('true'); the active
|
|
659
|
-
// target during a session is exposed (undefined). isHidden then tells us
|
|
660
|
-
// whether to omit the element entirely (RAC returns null when hidden).
|
|
661
|
-
const ariaHidden = createMemo(() =>
|
|
662
|
-
!dragSession() ? "true" : isDropTarget() ? undefined : "true",
|
|
663
|
-
);
|
|
664
|
-
const isHidden = createMemo(() => !isDropTarget() && !!ariaHidden());
|
|
665
|
-
// Faithful port of useDroppableItem. Registration (of the indicator element as
|
|
666
|
-
// a DragManager droppable item) and the self-focus must happen in one effect,
|
|
667
|
-
// registration first: the DragManager's onFocus keys off the dropItems map, so
|
|
668
|
-
// if the element self-focused before it was registered, onFocus would treat it
|
|
669
|
-
// as an unknown target and redirect focus back to the collection (a pickup
|
|
670
|
-
// bounce). React's two useDroppableItem effects run in guaranteed order after
|
|
671
|
-
// the ref is attached; Solid's independent effects race, so we fuse them. The
|
|
672
|
-
// dropItems map keys off live elements — the ref nulls itself on Show cleanup
|
|
673
|
-
// (below), so a hidden indicator unregisters instead of lingering as a stale
|
|
674
|
-
// detached entry.
|
|
675
|
-
createEffect(() => {
|
|
676
|
-
const el = indicatorRef();
|
|
677
|
-
if (!el) return;
|
|
678
|
-
const unregister = registerDropItem({
|
|
679
|
-
element: el,
|
|
680
|
-
target: props.target,
|
|
681
|
-
getDropOperation: (types, allowedOperations) => {
|
|
682
|
-
const st = dropState();
|
|
683
|
-
if (!st) return "cancel";
|
|
684
|
-
// Thread the same drag identity the collection uses (see
|
|
685
|
-
// createDroppableCollection.isInternalDropOperation): an internal
|
|
686
|
-
// keyboard reorder must report `isInternal` so the state's feature
|
|
687
|
-
// detection keeps before/after indicators valid (and rejects "on" for a
|
|
688
|
-
// reorder-only host). Without it every indicator would return "cancel"
|
|
689
|
-
// and drop out of the DragManager's ariaHideOutside keep-set.
|
|
690
|
-
const isInternal = getGlobalDraggingCollectionRef() === listRef();
|
|
691
|
-
return st.getDropOperation(
|
|
692
|
-
props.target,
|
|
693
|
-
wrapDropTypes(types) as Parameters<typeof st.getDropOperation>[1],
|
|
694
|
-
allowedOperations,
|
|
695
|
-
isInternal,
|
|
696
|
-
getGlobalDraggingKeys(),
|
|
697
|
-
);
|
|
698
|
-
},
|
|
699
|
-
});
|
|
700
|
-
onCleanup(unregister);
|
|
701
|
-
// While a drag session is active, the current drop target moves real DOM
|
|
702
|
-
// focus onto itself, so keyboard drop navigation lands on the labeled
|
|
703
|
-
// insertion point rather than the collection element. The self-focus is
|
|
704
|
-
// deferred to an animation frame to mirror upstream's timing: in
|
|
705
|
-
// useDroppableItem the focus is a *passive* useEffect, so it commits only
|
|
706
|
-
// after the browser's microtask checkpoint. That ordering matters because
|
|
707
|
-
// the DragManager keeps the active drop indicator visible via
|
|
708
|
-
// ariaHideOutside, whose keep-set is `[dragSource, ...registered drop
|
|
709
|
-
// items]` (the collection is dropped from the set once it owns items). A
|
|
710
|
-
// freshly-mounted indicator is momentarily `inert` — it only leaves the
|
|
711
|
-
// keep-set's blind spot once the DragManager's MutationObserver re-runs
|
|
712
|
-
// updateValidDropTargets on a later microtask. Focusing synchronously (or
|
|
713
|
-
// on a microtask) would call .focus() while the element is still inert and
|
|
714
|
-
// silently no-op; the animation frame runs after that refresh, exactly as
|
|
715
|
-
// React's passive effect does.
|
|
716
|
-
if (dragSession() && isDropTarget()) {
|
|
717
|
-
requestAnimationFrame(() => {
|
|
718
|
-
if (dragSession() && isDropTarget() && indicatorRef() === el) {
|
|
719
|
-
el.focus();
|
|
720
|
-
}
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
});
|
|
724
|
-
return (
|
|
725
|
-
<Show when={!isHidden()}>
|
|
726
|
-
<div
|
|
727
|
-
ref={(el) => {
|
|
728
|
-
setIndicatorRef(el);
|
|
729
|
-
onCleanup(() => setIndicatorRef(null));
|
|
730
|
-
}}
|
|
731
|
-
role="option"
|
|
732
|
-
class="solidaria-DropIndicator"
|
|
733
|
-
aria-roledescription={dndFormatter().format("dropIndicator")}
|
|
734
|
-
aria-label={dropIndicatorLabel(props.target)}
|
|
735
|
-
aria-hidden={ariaHidden()}
|
|
736
|
-
tabindex={-1}
|
|
737
|
-
data-drop-target={isDropTarget() || undefined}
|
|
738
|
-
/>
|
|
739
|
-
</Show>
|
|
740
|
-
);
|
|
741
|
-
};
|
|
742
798
|
const dropIndicatorContextValue = {
|
|
743
|
-
render: (p: DropIndicatorProps) => <
|
|
799
|
+
render: (p: DropIndicatorProps) => <ListBoxDropIndicatorWrapper {...p} />,
|
|
744
800
|
};
|
|
745
801
|
|
|
746
802
|
const virtualizer = useVirtualizerContext();
|
|
@@ -752,36 +808,34 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
752
808
|
);
|
|
753
809
|
const virtualRange = createMemo(() => {
|
|
754
810
|
if (!virtualizer || !parentCollectionRenderer?.isVirtualized || hasSections()) return null;
|
|
755
|
-
const
|
|
811
|
+
const itemCount = getItemNodes().length;
|
|
812
|
+
const baseRange = virtualizer.getVisibleRange(itemCount);
|
|
756
813
|
const itemNodes = getItemNodes();
|
|
757
|
-
const persistedIndexes = Array.from(persistedKeys())
|
|
758
|
-
.map((key) => itemNodes.findIndex((node) => node.key === key))
|
|
759
|
-
.filter((index) => index >= 0);
|
|
760
814
|
const dropTarget = dropState()?.target;
|
|
761
815
|
const normalizedDropKey = getNormalizedDropTargetKey(dropTarget, state.collection());
|
|
762
|
-
const focusedKey = state.focusedKey();
|
|
763
|
-
const focusedIndex =
|
|
764
|
-
focusedKey != null ? itemNodes.findIndex((node) => node.key === focusedKey) : -1;
|
|
765
816
|
const forceIncludeIndexes = [
|
|
766
817
|
dropTarget?.type === "item" ? itemNodes.findIndex((node) => node.key === dropTarget.key) : -1,
|
|
767
818
|
normalizedDropKey != null
|
|
768
819
|
? itemNodes.findIndex((node) => node.key === normalizedDropKey)
|
|
769
820
|
: -1,
|
|
770
|
-
dropTarget?.type === "item" ? -1 : focusedIndex,
|
|
771
821
|
].filter((index) => index >= 0);
|
|
772
|
-
return mergePersistedKeysIntoVirtualRange(
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
822
|
+
return mergePersistedKeysIntoVirtualRange(baseRange, [], itemCount, virtualizer, 80, {
|
|
823
|
+
forceIncludeIndexes,
|
|
824
|
+
forceIncludeMaxSpan: 320,
|
|
825
|
+
});
|
|
826
|
+
});
|
|
827
|
+
const persistedOutsideIndexes = createMemo(() => {
|
|
828
|
+
const range = virtualRange();
|
|
829
|
+
if (!range) return [] as number[];
|
|
830
|
+
const itemNodes = getItemNodes();
|
|
831
|
+
const persistedIndexes = Array.from(persistedKeys())
|
|
832
|
+
.map((key) => itemNodes.findIndex((node) => node.key === key))
|
|
833
|
+
.filter((index) => index >= 0);
|
|
834
|
+
return indexesOutsideRange(range, persistedIndexes);
|
|
783
835
|
});
|
|
784
|
-
|
|
836
|
+
createTrackedEffect(() => {
|
|
837
|
+
const _s2Cleanups: Array<() => void> = [];
|
|
838
|
+
|
|
785
839
|
if (!virtualizer || !parentCollectionRenderer?.isVirtualized) return;
|
|
786
840
|
const getItemNodes = () =>
|
|
787
841
|
Array.from(state.collection()).filter((node) => node.type === "item");
|
|
@@ -798,44 +852,54 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
798
852
|
key: typeof node.key === "string" || typeof node.key === "number" ? node.key : undefined,
|
|
799
853
|
};
|
|
800
854
|
});
|
|
801
|
-
|
|
855
|
+
_s2Cleanups.push(() => {
|
|
802
856
|
virtualizer.setDropTargetIndexResolver(undefined);
|
|
803
857
|
virtualizer.setDropTargetItemCountResolver(undefined);
|
|
804
858
|
virtualizer.setDropTargetResolver(undefined);
|
|
805
859
|
});
|
|
860
|
+
|
|
861
|
+
return () => {
|
|
862
|
+
for (const c of _s2Cleanups) c();
|
|
863
|
+
};
|
|
806
864
|
});
|
|
807
865
|
const visibleItems = createMemo(() => {
|
|
808
866
|
const range = virtualRange();
|
|
809
|
-
|
|
810
|
-
|
|
867
|
+
const items = collectionItems();
|
|
868
|
+
if (!range) return items;
|
|
869
|
+
return items.slice(range.start, range.end);
|
|
811
870
|
});
|
|
812
|
-
// Spacers reserve the windowed-out extent along the virtualizer's primary axis,
|
|
813
|
-
// so a horizontal layout offsets along width rather than height.
|
|
814
|
-
const virtualSpacerStyle = (size: number): JSX.CSSProperties =>
|
|
815
|
-
virtualizer?.orientation === "horizontal" ? { width: `${size}px` } : { height: `${size}px` };
|
|
816
871
|
const sectionedRenderEntries = createMemo(() => {
|
|
872
|
+
const values = new Set(collectionItems());
|
|
817
873
|
let globalIndex = 0;
|
|
818
|
-
|
|
874
|
+
const entries: Array<
|
|
875
|
+
| { type: "section"; section: CollectionSection<T>; items: { item: T; index: number }[] }
|
|
876
|
+
| { type: "item"; item: { item: T; index: number } }
|
|
877
|
+
> = [];
|
|
878
|
+
for (const entry of stateProps.items) {
|
|
819
879
|
if (isCollectionSection(entry)) {
|
|
820
|
-
const sectionItems = entry.items
|
|
821
|
-
item
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
880
|
+
const sectionItems = entry.items
|
|
881
|
+
.filter((item) => values.has(item))
|
|
882
|
+
.map((item) => ({
|
|
883
|
+
item,
|
|
884
|
+
index: globalIndex++,
|
|
885
|
+
}));
|
|
886
|
+
if (sectionItems.length === 0) continue;
|
|
887
|
+
entries.push({
|
|
825
888
|
type: "section" as const,
|
|
826
889
|
section: entry,
|
|
827
890
|
items: sectionItems,
|
|
828
|
-
};
|
|
891
|
+
});
|
|
892
|
+
} else if (values.has(entry as T)) {
|
|
893
|
+
entries.push({
|
|
894
|
+
type: "item" as const,
|
|
895
|
+
item: {
|
|
896
|
+
item: entry as T,
|
|
897
|
+
index: globalIndex++,
|
|
898
|
+
},
|
|
899
|
+
});
|
|
829
900
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
index: globalIndex++,
|
|
833
|
-
};
|
|
834
|
-
return {
|
|
835
|
-
type: "item" as const,
|
|
836
|
-
item: indexedItem,
|
|
837
|
-
};
|
|
838
|
-
});
|
|
901
|
+
}
|
|
902
|
+
return entries;
|
|
839
903
|
});
|
|
840
904
|
const collectionRenderer = createMemo<CollectionRendererContextValue<unknown>>(() => ({
|
|
841
905
|
...parentCollectionRenderer,
|
|
@@ -844,9 +908,10 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
844
908
|
dndDropIndicator(index, position) ??
|
|
845
909
|
parentCollectionRenderer?.renderDropIndicator?.(index, position),
|
|
846
910
|
}));
|
|
911
|
+
const CollectionRoot = useCollectionRoot();
|
|
847
912
|
|
|
848
913
|
return (
|
|
849
|
-
<ListBoxContext
|
|
914
|
+
<ListBoxContext
|
|
850
915
|
value={
|
|
851
916
|
{
|
|
852
917
|
state,
|
|
@@ -858,144 +923,208 @@ export function ListBox<T>(props: ListBoxProps<T>): JSX.Element {
|
|
|
858
923
|
} as ListBoxContextValue<unknown>
|
|
859
924
|
}
|
|
860
925
|
>
|
|
861
|
-
<ListBoxStateContext
|
|
862
|
-
<CollectionRendererContext
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
<div
|
|
947
|
-
role="presentation"
|
|
948
|
-
aria-hidden="true"
|
|
949
|
-
style={virtualSpacerStyle(virtualRange()!.offsetTop)}
|
|
950
|
-
data-virtualizer-spacer="top"
|
|
951
|
-
/>
|
|
952
|
-
) : null}
|
|
953
|
-
<For each={visibleItems()}>
|
|
954
|
-
{(item, index) => {
|
|
955
|
-
const itemIndex = () => (virtualRange()?.start ?? 0) + index();
|
|
956
|
-
const beforeIndicator = () =>
|
|
957
|
-
collectionRenderer().renderDropIndicator?.(itemIndex(), "before");
|
|
958
|
-
const onIndicator = () =>
|
|
959
|
-
collectionRenderer().renderDropIndicator?.(itemIndex(), "on");
|
|
960
|
-
const afterIndicator = () =>
|
|
961
|
-
collectionRenderer().renderDropIndicator?.(itemIndex(), "after");
|
|
962
|
-
return (
|
|
926
|
+
<ListBoxStateContext value={state}>
|
|
927
|
+
<CollectionRendererContext value={collectionRenderer()}>
|
|
928
|
+
<DropIndicatorContext value={dropIndicatorContextValue}>
|
|
929
|
+
<>
|
|
930
|
+
<Show when={ariaProps.label}>
|
|
931
|
+
<span {...cleanLabelProps()}>{ariaProps.label as JSX.Element}</span>
|
|
932
|
+
</Show>
|
|
933
|
+
<div
|
|
934
|
+
{...mergeProps(
|
|
935
|
+
domProps(),
|
|
936
|
+
cleanListBoxProps(),
|
|
937
|
+
cleanFocusProps(),
|
|
938
|
+
(droppableCollection()?.collectionProps as Record<string, unknown> | undefined) ??
|
|
939
|
+
{},
|
|
940
|
+
)}
|
|
941
|
+
ref={(el) => {
|
|
942
|
+
setListRef(el);
|
|
943
|
+
assignRef(local.ref, el);
|
|
944
|
+
autocompleteCtx?.collectionRef(el);
|
|
945
|
+
}}
|
|
946
|
+
class={renderProps.class()}
|
|
947
|
+
style={renderProps.style()}
|
|
948
|
+
data-focused={dataAttr(isFocused())}
|
|
949
|
+
data-focus-visible={dataAttr(isFocusVisible())}
|
|
950
|
+
data-disabled={dataAttr(resolveDisabled())}
|
|
951
|
+
data-empty={dataAttr(isEmpty())}
|
|
952
|
+
data-layout={stateProps.layout || "stack"}
|
|
953
|
+
data-orientation={stateProps.orientation || "vertical"}
|
|
954
|
+
data-drop-target={dataAttr(isRootDropTarget())}
|
|
955
|
+
slot={local.slot}
|
|
956
|
+
>
|
|
957
|
+
<SharedElementTransition>
|
|
958
|
+
{parentCollectionRenderer?.isVirtualized ? (
|
|
959
|
+
<>
|
|
960
|
+
<CollectionRoot
|
|
961
|
+
collection={virtualRange() ? collectionItems() : []}
|
|
962
|
+
scrollRef={() => listRef()}
|
|
963
|
+
persistedKeys={persistedKeys()}
|
|
964
|
+
>
|
|
965
|
+
{isEmpty() && local.renderEmptyState ? null : hasSections() ? (
|
|
966
|
+
<For each={sectionedRenderEntries()}>
|
|
967
|
+
{(entry) =>
|
|
968
|
+
entry.type === "section" ? (
|
|
969
|
+
<div role="presentation" data-section-wrapper>
|
|
970
|
+
<Section class="solidaria-ListBox-section">
|
|
971
|
+
{entry.section.title != null && (
|
|
972
|
+
<Header class="solidaria-ListBox-sectionHeader">
|
|
973
|
+
{entry.section.title}
|
|
974
|
+
</Header>
|
|
975
|
+
)}
|
|
976
|
+
<Group class="solidaria-ListBox-sectionGroup">
|
|
977
|
+
<div role="group" aria-label={entry.section["aria-label"]}>
|
|
978
|
+
<For each={entry.items}>
|
|
979
|
+
{(indexedItem) => (
|
|
980
|
+
<VirtualizerItem index={indexedItem.index}>
|
|
981
|
+
<ListBoxItemWithDropIndicators
|
|
982
|
+
item={indexedItem.item}
|
|
983
|
+
itemIndex={indexedItem.index}
|
|
984
|
+
isLastInLevel={() =>
|
|
985
|
+
isLastDropItem(indexedItem.index)
|
|
986
|
+
}
|
|
987
|
+
renderItem={local.children}
|
|
988
|
+
renderDropIndicator={renderItemDropIndicator}
|
|
989
|
+
/>
|
|
990
|
+
</VirtualizerItem>
|
|
991
|
+
)}
|
|
992
|
+
</For>
|
|
993
|
+
</div>
|
|
994
|
+
</Group>
|
|
995
|
+
</Section>
|
|
996
|
+
</div>
|
|
997
|
+
) : (
|
|
998
|
+
<VirtualizerItem index={entry.item.index}>
|
|
999
|
+
<ListBoxItemWithDropIndicators
|
|
1000
|
+
item={entry.item.item}
|
|
1001
|
+
itemIndex={entry.item.index}
|
|
1002
|
+
isLastInLevel={() => isLastDropItem(entry.item.index)}
|
|
1003
|
+
renderItem={local.children}
|
|
1004
|
+
renderDropIndicator={renderItemDropIndicator}
|
|
1005
|
+
/>
|
|
1006
|
+
</VirtualizerItem>
|
|
1007
|
+
)
|
|
1008
|
+
}
|
|
1009
|
+
</For>
|
|
1010
|
+
) : (
|
|
963
1011
|
<>
|
|
964
|
-
{
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1012
|
+
<For each={visibleItems()}>
|
|
1013
|
+
{(item, index) => (
|
|
1014
|
+
<VirtualizerItem
|
|
1015
|
+
index={() => (virtualRange()?.start ?? 0) + index()}
|
|
1016
|
+
>
|
|
1017
|
+
<ListBoxItemWithDropIndicators
|
|
1018
|
+
item={item as T}
|
|
1019
|
+
itemIndex={() => (virtualRange()?.start ?? 0) + index()}
|
|
1020
|
+
isLastInLevel={() =>
|
|
1021
|
+
isLastDropItem((virtualRange()?.start ?? 0) + index())
|
|
1022
|
+
}
|
|
1023
|
+
renderItem={local.children}
|
|
1024
|
+
renderDropIndicator={renderItemDropIndicator}
|
|
1025
|
+
/>
|
|
1026
|
+
</VirtualizerItem>
|
|
1027
|
+
)}
|
|
1028
|
+
</For>
|
|
1029
|
+
<For each={persistedOutsideIndexes()}>
|
|
1030
|
+
{(index) => (
|
|
1031
|
+
<PersistedVirtualItem index={index}>
|
|
1032
|
+
<ListBoxItemWithDropIndicators
|
|
1033
|
+
item={collectionItems()[index] as T}
|
|
1034
|
+
itemIndex={() => index}
|
|
1035
|
+
isLastInLevel={() => isLastDropItem(index)}
|
|
1036
|
+
renderItem={local.children}
|
|
1037
|
+
renderDropIndicator={renderItemDropIndicator}
|
|
1038
|
+
/>
|
|
1039
|
+
</PersistedVirtualItem>
|
|
1040
|
+
)}
|
|
1041
|
+
</For>
|
|
968
1042
|
</>
|
|
969
|
-
)
|
|
970
|
-
|
|
1043
|
+
)}
|
|
1044
|
+
</CollectionRoot>
|
|
1045
|
+
{isEmpty() && local.renderEmptyState ? (
|
|
1046
|
+
<div role="option" style={{ display: "contents" }} data-empty-state>
|
|
1047
|
+
{local.renderEmptyState()}
|
|
1048
|
+
</div>
|
|
1049
|
+
) : null}
|
|
1050
|
+
</>
|
|
1051
|
+
) : isEmpty() && local.renderEmptyState ? (
|
|
1052
|
+
<div role="option" style={{ display: "contents" }} data-empty-state>
|
|
1053
|
+
{local.renderEmptyState()}
|
|
1054
|
+
</div>
|
|
1055
|
+
) : hasSections() ? (
|
|
1056
|
+
<For each={sectionedRenderEntries()}>
|
|
1057
|
+
{(entry) =>
|
|
1058
|
+
entry.type === "section" ? (
|
|
1059
|
+
<div role="presentation" data-section-wrapper>
|
|
1060
|
+
<Section class="solidaria-ListBox-section">
|
|
1061
|
+
{entry.section.title != null && (
|
|
1062
|
+
<Header class="solidaria-ListBox-sectionHeader">
|
|
1063
|
+
{entry.section.title}
|
|
1064
|
+
</Header>
|
|
1065
|
+
)}
|
|
1066
|
+
<Group class="solidaria-ListBox-sectionGroup">
|
|
1067
|
+
<div role="group" aria-label={entry.section["aria-label"]}>
|
|
1068
|
+
<For each={entry.items}>
|
|
1069
|
+
{(indexedItem) => (
|
|
1070
|
+
<ListBoxItemWithDropIndicators
|
|
1071
|
+
item={indexedItem.item}
|
|
1072
|
+
itemIndex={indexedItem.index}
|
|
1073
|
+
isLastInLevel={() => isLastDropItem(indexedItem.index)}
|
|
1074
|
+
renderItem={local.children}
|
|
1075
|
+
renderDropIndicator={renderItemDropIndicator}
|
|
1076
|
+
/>
|
|
1077
|
+
)}
|
|
1078
|
+
</For>
|
|
1079
|
+
</div>
|
|
1080
|
+
</Group>
|
|
1081
|
+
</Section>
|
|
1082
|
+
</div>
|
|
1083
|
+
) : (
|
|
1084
|
+
<ListBoxItemWithDropIndicators
|
|
1085
|
+
item={entry.item.item}
|
|
1086
|
+
itemIndex={entry.item.index}
|
|
1087
|
+
isLastInLevel={() => isLastDropItem(entry.item.index)}
|
|
1088
|
+
renderItem={local.children}
|
|
1089
|
+
renderDropIndicator={renderItemDropIndicator}
|
|
1090
|
+
/>
|
|
1091
|
+
)
|
|
1092
|
+
}
|
|
971
1093
|
</For>
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1094
|
+
) : (
|
|
1095
|
+
<>
|
|
1096
|
+
<For each={visibleItems()}>
|
|
1097
|
+
{(item, index) => (
|
|
1098
|
+
<ListBoxItemWithDropIndicators
|
|
1099
|
+
item={item as T}
|
|
1100
|
+
itemIndex={() => (virtualRange()?.start ?? 0) + index()}
|
|
1101
|
+
isLastInLevel={() =>
|
|
1102
|
+
isLastDropItem((virtualRange()?.start ?? 0) + index())
|
|
1103
|
+
}
|
|
1104
|
+
renderItem={local.children}
|
|
1105
|
+
renderDropIndicator={renderItemDropIndicator}
|
|
1106
|
+
/>
|
|
1107
|
+
)}
|
|
1108
|
+
</For>
|
|
1109
|
+
</>
|
|
1110
|
+
)}
|
|
1111
|
+
</SharedElementTransition>
|
|
1112
|
+
{local.hasMore && local.onLoadMore && (
|
|
1113
|
+
<ListBoxLoadMoreItem onLoadMore={local.onLoadMore} isLoading={local.isLoading} />
|
|
981
1114
|
)}
|
|
982
|
-
</
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
</DropIndicatorContext.Provider>
|
|
989
|
-
</CollectionRendererContext.Provider>
|
|
990
|
-
</ListBoxStateContext.Provider>
|
|
991
|
-
</ListBoxContext.Provider>
|
|
1115
|
+
</div>
|
|
1116
|
+
</>
|
|
1117
|
+
</DropIndicatorContext>
|
|
1118
|
+
</CollectionRendererContext>
|
|
1119
|
+
</ListBoxStateContext>
|
|
1120
|
+
</ListBoxContext>
|
|
992
1121
|
);
|
|
993
1122
|
}
|
|
994
1123
|
|
|
995
1124
|
/**
|
|
996
|
-
* An
|
|
1125
|
+
* An item in a listbox.
|
|
997
1126
|
*/
|
|
998
|
-
export function
|
|
1127
|
+
export function ListBoxItem<T>(props: ListBoxItemProps<T>): JSX.Element {
|
|
999
1128
|
const [local, ariaProps] = splitProps(props, [
|
|
1000
1129
|
"class",
|
|
1001
1130
|
"style",
|
|
@@ -1008,7 +1137,7 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
|
|
|
1008
1137
|
|
|
1009
1138
|
const context = useContext(ListBoxStateContext);
|
|
1010
1139
|
if (!context) {
|
|
1011
|
-
throw new Error("
|
|
1140
|
+
throw new Error("ListBoxItem must be used within a ListBox");
|
|
1012
1141
|
}
|
|
1013
1142
|
const state = context as ListState<T>;
|
|
1014
1143
|
const listContext = useContext(ListBoxContext) as ListBoxContextValue<T> | null;
|
|
@@ -1021,7 +1150,7 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
|
|
|
1021
1150
|
return Boolean(ariaProps.isDisabled || listContext?.isDisabled());
|
|
1022
1151
|
},
|
|
1023
1152
|
get "aria-label"() {
|
|
1024
|
-
return ariaProps["aria-label"]
|
|
1153
|
+
return ariaProps["aria-label"];
|
|
1025
1154
|
},
|
|
1026
1155
|
get shouldSelectOnPressUp() {
|
|
1027
1156
|
return ariaProps.shouldSelectOnPressUp;
|
|
@@ -1063,9 +1192,6 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
|
|
|
1063
1192
|
},
|
|
1064
1193
|
renderValues,
|
|
1065
1194
|
);
|
|
1066
|
-
const hasPrimitiveLabel = () => {
|
|
1067
|
-
return typeof props.children === "string" || typeof props.children === "number";
|
|
1068
|
-
};
|
|
1069
1195
|
|
|
1070
1196
|
const selectionIndicatorContext = createMemo<SelectionIndicatorContextValue>(() => ({
|
|
1071
1197
|
isSelected: optionAria.isSelected,
|
|
@@ -1096,24 +1222,59 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
|
|
|
1096
1222
|
});
|
|
1097
1223
|
|
|
1098
1224
|
const cleanOptionProps = () => {
|
|
1099
|
-
const {
|
|
1100
|
-
ref: _ref1,
|
|
1101
|
-
"aria-describedby": _ariaDescribedby,
|
|
1102
|
-
...rest
|
|
1103
|
-
} = optionAria.optionProps as Record<string, unknown>;
|
|
1104
|
-
if (!hasPrimitiveLabel() && rest["aria-label"] == null) {
|
|
1105
|
-
delete rest["aria-labelledby"];
|
|
1106
|
-
}
|
|
1225
|
+
const { ref: _ref1, ...rest } = optionAria.optionProps as Record<string, unknown>;
|
|
1107
1226
|
return rest;
|
|
1108
1227
|
};
|
|
1228
|
+
|
|
1229
|
+
const optionTextSlots = {
|
|
1230
|
+
slots: {
|
|
1231
|
+
get [DEFAULT_SLOT]() {
|
|
1232
|
+
return optionAria.labelProps;
|
|
1233
|
+
},
|
|
1234
|
+
get label() {
|
|
1235
|
+
return optionAria.labelProps;
|
|
1236
|
+
},
|
|
1237
|
+
get description() {
|
|
1238
|
+
return optionAria.descriptionProps;
|
|
1239
|
+
},
|
|
1240
|
+
},
|
|
1241
|
+
};
|
|
1242
|
+
|
|
1243
|
+
// Styled hosts (S2 ComboBoxItem / PickerItem) emit `<span slot="label">` rather
|
|
1244
|
+
// than `<Text>`. Stamp the slot id onto that node before `createSlotId` probes
|
|
1245
|
+
// the DOM, matching RAC TextContext + useSlotId.
|
|
1246
|
+
createRenderEffect(
|
|
1247
|
+
() => ({
|
|
1248
|
+
el: ref(),
|
|
1249
|
+
labelId: optionAria.labelProps.id,
|
|
1250
|
+
descriptionId: optionAria.descriptionProps.id,
|
|
1251
|
+
}),
|
|
1252
|
+
({ el, labelId, descriptionId }) => {
|
|
1253
|
+
if (!el) return;
|
|
1254
|
+
if (labelId) {
|
|
1255
|
+
const label = el.querySelector("[slot='label']");
|
|
1256
|
+
if (label && !label.id) label.id = labelId;
|
|
1257
|
+
}
|
|
1258
|
+
if (descriptionId) {
|
|
1259
|
+
const description = el.querySelector("[slot='description']");
|
|
1260
|
+
if (description && !description.id) description.id = descriptionId;
|
|
1261
|
+
}
|
|
1262
|
+
},
|
|
1263
|
+
);
|
|
1109
1264
|
const domProps = () => filterDOMProps(ariaProps as Record<string, unknown>, { global: true });
|
|
1110
1265
|
|
|
1266
|
+
const selectionMode = () => state.selectionMode();
|
|
1267
|
+
|
|
1111
1268
|
return (
|
|
1112
|
-
<SelectionIndicatorContext
|
|
1269
|
+
<SelectionIndicatorContext value={selectionIndicatorContext()}>
|
|
1113
1270
|
<div
|
|
1114
1271
|
ref={(el) => {
|
|
1115
1272
|
setRef(el);
|
|
1116
1273
|
assignRef(local.ref, el);
|
|
1274
|
+
const dragRef = (
|
|
1275
|
+
draggableItem()?.dragProps as { ref?: (el: HTMLDivElement) => void } | undefined
|
|
1276
|
+
)?.ref;
|
|
1277
|
+
if (typeof dragRef === "function") dragRef(el);
|
|
1117
1278
|
}}
|
|
1118
1279
|
{...mergeProps(
|
|
1119
1280
|
domProps(),
|
|
@@ -1123,23 +1284,25 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
|
|
|
1123
1284
|
)}
|
|
1124
1285
|
class={renderProps.class()}
|
|
1125
1286
|
style={renderProps.style()}
|
|
1126
|
-
data-selected={optionAria.isSelected()
|
|
1127
|
-
data-focused={optionAria.isFocused()
|
|
1128
|
-
data-focus-visible={optionAria.isFocusVisible()
|
|
1129
|
-
data-pressed={optionAria.isPressed()
|
|
1130
|
-
data-hovered={optionAria.isHovered()
|
|
1131
|
-
data-disabled={optionAria.isDisabled()
|
|
1132
|
-
data-dragging={draggableItem()?.isDragging
|
|
1133
|
-
data-drop-target={droppableItem()?.isDropTarget
|
|
1287
|
+
data-selected={dataAttr(optionAria.isSelected())}
|
|
1288
|
+
data-focused={dataAttr(optionAria.isFocused())}
|
|
1289
|
+
data-focus-visible={dataAttr(optionAria.isFocusVisible())}
|
|
1290
|
+
data-pressed={dataAttr(optionAria.isPressed())}
|
|
1291
|
+
data-hovered={dataAttr(optionAria.isHovered())}
|
|
1292
|
+
data-disabled={dataAttr(optionAria.isDisabled())}
|
|
1293
|
+
data-dragging={dataAttr(draggableItem()?.isDragging)}
|
|
1294
|
+
data-drop-target={dataAttr(droppableItem()?.isDropTarget)}
|
|
1295
|
+
data-selection-mode={selectionMode() === "none" ? undefined : selectionMode()}
|
|
1134
1296
|
slot={local.slot}
|
|
1135
1297
|
>
|
|
1136
|
-
{
|
|
1137
|
-
<
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1298
|
+
<Provider values={[[TextContext, optionTextSlots] as [Context<unknown>, unknown]]}>
|
|
1299
|
+
<OptionContent
|
|
1300
|
+
render={renderProps.renderChildrenStable}
|
|
1301
|
+
labelProps={optionAria.labelProps}
|
|
1302
|
+
/>
|
|
1303
|
+
</Provider>
|
|
1141
1304
|
</div>
|
|
1142
|
-
</SelectionIndicatorContext
|
|
1305
|
+
</SelectionIndicatorContext>
|
|
1143
1306
|
);
|
|
1144
1307
|
}
|
|
1145
1308
|
|
|
@@ -1147,8 +1310,9 @@ export function ListBoxOption<T>(props: ListBoxOptionProps<T>): JSX.Element {
|
|
|
1147
1310
|
* Load more sentinel item for listbox collections.
|
|
1148
1311
|
*/
|
|
1149
1312
|
export function ListBoxLoadMoreItem(props: ListBoxLoadMoreItemProps): JSX.Element {
|
|
1150
|
-
|
|
1313
|
+
const [sentinel, setSentinel] = createSignal<HTMLDivElement | undefined>();
|
|
1151
1314
|
const [isPending, setIsPending] = createSignal(false);
|
|
1315
|
+
const scrollOffsetValue = createMemo(() => props.scrollOffset ?? 1);
|
|
1152
1316
|
|
|
1153
1317
|
const isLoading = () => !!props.isLoading || isPending();
|
|
1154
1318
|
|
|
@@ -1162,28 +1326,31 @@ export function ListBoxLoadMoreItem(props: ListBoxLoadMoreItemProps): JSX.Elemen
|
|
|
1162
1326
|
}
|
|
1163
1327
|
};
|
|
1164
1328
|
|
|
1165
|
-
createEffect(
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
(
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1329
|
+
createEffect(
|
|
1330
|
+
() => ({
|
|
1331
|
+
current: sentinel(),
|
|
1332
|
+
scrollOffset: scrollOffsetValue(),
|
|
1333
|
+
}),
|
|
1334
|
+
({ current, scrollOffset }) => {
|
|
1335
|
+
if (!current || typeof IntersectionObserver !== "function") return;
|
|
1336
|
+
const margin = `0px 0px ${100 * scrollOffset}% 0px`;
|
|
1337
|
+
const observer = new IntersectionObserver(
|
|
1338
|
+
(entries) => {
|
|
1339
|
+
if (entries[0]?.isIntersecting) {
|
|
1340
|
+
void triggerLoadMore();
|
|
1341
|
+
}
|
|
1342
|
+
},
|
|
1343
|
+
{ rootMargin: margin },
|
|
1344
|
+
);
|
|
1345
|
+
observer.observe(current);
|
|
1346
|
+
return () => observer.disconnect();
|
|
1347
|
+
},
|
|
1348
|
+
);
|
|
1182
1349
|
|
|
1183
1350
|
const renderProps = useRenderProps(
|
|
1184
1351
|
{
|
|
1185
1352
|
get children() {
|
|
1186
|
-
return props.children
|
|
1353
|
+
return props.children;
|
|
1187
1354
|
},
|
|
1188
1355
|
class: props.class,
|
|
1189
1356
|
style: props.style,
|
|
@@ -1192,24 +1359,29 @@ export function ListBoxLoadMoreItem(props: ListBoxLoadMoreItemProps): JSX.Elemen
|
|
|
1192
1359
|
() => ({ isLoading: isLoading() }),
|
|
1193
1360
|
);
|
|
1194
1361
|
|
|
1362
|
+
// RAC ListBoxLoadMoreItem (ListBox.tsx:781-803): always mount the 0×0
|
|
1363
|
+
// sentinel; render the loader `option` only while `isLoading` and children
|
|
1364
|
+
// exist. A visible "Load more" row when idle/`loading` is a local invention.
|
|
1195
1365
|
return (
|
|
1196
1366
|
<>
|
|
1197
1367
|
<div style={{ position: "relative", width: 0, height: 0, overflow: "hidden" }} inert>
|
|
1198
|
-
<div
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
tabIndex={0}
|
|
1204
|
-
onFocus={() => {
|
|
1205
|
-
void triggerLoadMore();
|
|
1206
|
-
}}
|
|
1207
|
-
class={renderProps.class()}
|
|
1208
|
-
style={renderProps.style()}
|
|
1209
|
-
data-loading={isLoading() || undefined}
|
|
1210
|
-
>
|
|
1211
|
-
{renderProps.renderChildren()}
|
|
1368
|
+
<div
|
|
1369
|
+
data-testid="loadMoreSentinel"
|
|
1370
|
+
ref={setSentinel}
|
|
1371
|
+
style={{ position: "absolute", height: "1px", width: "1px" }}
|
|
1372
|
+
/>
|
|
1212
1373
|
</div>
|
|
1374
|
+
<Show when={isLoading() && props.children}>
|
|
1375
|
+
<div
|
|
1376
|
+
role="option"
|
|
1377
|
+
tabindex={-1}
|
|
1378
|
+
class={renderProps.class()}
|
|
1379
|
+
style={renderProps.style()}
|
|
1380
|
+
data-loading
|
|
1381
|
+
>
|
|
1382
|
+
{renderProps.renderChildren()}
|
|
1383
|
+
</div>
|
|
1384
|
+
</Show>
|
|
1213
1385
|
</>
|
|
1214
1386
|
);
|
|
1215
1387
|
}
|
|
@@ -1221,5 +1393,10 @@ export function ListBoxSection(props: ListBoxSectionProps): JSX.Element {
|
|
|
1221
1393
|
return <Section {...props} />;
|
|
1222
1394
|
}
|
|
1223
1395
|
|
|
1224
|
-
|
|
1396
|
+
/**
|
|
1397
|
+
* @deprecated Use {@link ListBoxItem}. Removed in a future minor.
|
|
1398
|
+
*/
|
|
1399
|
+
export const ListBoxOption = ListBoxItem;
|
|
1400
|
+
|
|
1401
|
+
ListBox.Option = ListBoxItem;
|
|
1225
1402
|
ListBox.LoadMoreItem = ListBoxLoadMoreItem;
|