@proyecto-viviana/solidaria-components 0.3.2 → 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/ActionBar.d.ts.map +1 -1
- package/dist/ActionBar.js +175 -0
- package/dist/ActionBar.js.map +1 -0
- package/dist/ActionBar.jsx +119 -0
- package/dist/ActionBar.jsx.map +1 -0
- package/dist/ActionGroup.d.ts.map +1 -1
- package/dist/ActionGroup.js +179 -0
- package/dist/ActionGroup.js.map +1 -0
- package/dist/ActionGroup.jsx +129 -0
- package/dist/ActionGroup.jsx.map +1 -0
- package/dist/Alert.js +111 -0
- package/dist/Alert.js.map +1 -0
- package/dist/Alert.jsx +82 -0
- package/dist/Alert.jsx.map +1 -0
- package/dist/Autocomplete.d.ts +2 -2
- package/dist/Autocomplete.d.ts.map +1 -1
- package/dist/Autocomplete.js +130 -0
- package/dist/Autocomplete.js.map +1 -0
- package/dist/Autocomplete.jsx +116 -0
- package/dist/Autocomplete.jsx.map +1 -0
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs.js +333 -0
- package/dist/Breadcrumbs.js.map +1 -0
- package/dist/Breadcrumbs.jsx +261 -0
- package/dist/Breadcrumbs.jsx.map +1 -0
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +348 -0
- package/dist/Button.js.map +1 -0
- package/dist/Button.jsx +314 -0
- package/dist/Button.jsx.map +1 -0
- package/dist/Calendar.d.ts +4 -4
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Calendar.js +573 -0
- package/dist/Calendar.js.map +1 -0
- package/dist/Calendar.jsx +342 -0
- package/dist/Calendar.jsx.map +1 -0
- package/dist/CalendarPicker.d.ts +33 -0
- package/dist/CalendarPicker.d.ts.map +1 -0
- package/dist/CalendarPicker.js +44 -0
- package/dist/CalendarPicker.js.map +1 -0
- package/dist/CalendarPicker.jsx +44 -0
- package/dist/CalendarPicker.jsx.map +1 -0
- package/dist/Checkbox.d.ts +83 -4
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +923 -0
- package/dist/Checkbox.js.map +1 -0
- package/dist/Checkbox.jsx +707 -0
- package/dist/Checkbox.jsx.map +1 -0
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +202 -0
- package/dist/Collection.js.map +1 -0
- package/dist/Collection.jsx +152 -0
- package/dist/Collection.jsx.map +1 -0
- package/dist/Color.d.ts.map +1 -1
- package/dist/Color.js +1717 -0
- package/dist/Color.js.map +1 -0
- package/dist/Color.jsx +1340 -0
- package/dist/Color.jsx.map +1 -0
- package/dist/ColorEditor.js +208 -0
- package/dist/ColorEditor.js.map +1 -0
- package/dist/ColorEditor.jsx +120 -0
- package/dist/ColorEditor.jsx.map +1 -0
- package/dist/ComboBox.d.ts +8 -4
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ComboBox.js +1000 -0
- package/dist/ComboBox.js.map +1 -0
- package/dist/ComboBox.jsx +724 -0
- package/dist/ComboBox.jsx.map +1 -0
- package/dist/ContextualHelpTrigger.js +146 -0
- package/dist/ContextualHelpTrigger.js.map +1 -0
- package/dist/ContextualHelpTrigger.jsx +109 -0
- package/dist/ContextualHelpTrigger.jsx.map +1 -0
- package/dist/DateField.d.ts +14 -5
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DateField.js +4 -0
- package/dist/DateField.jsx +4 -0
- package/dist/DateField2.js +502 -0
- package/dist/DateField2.js.map +1 -0
- package/dist/DateField2.jsx +354 -0
- package/dist/DateField2.jsx.map +1 -0
- package/dist/DatePicker.d.ts +46 -7
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DatePicker.js +7 -0
- package/dist/DatePicker.jsx +7 -0
- package/dist/DatePicker2.js +1171 -0
- package/dist/DatePicker2.js.map +1 -0
- package/dist/DatePicker2.jsx +820 -0
- package/dist/DatePicker2.jsx.map +1 -0
- package/dist/DateRangePickerContext.d.ts +2 -0
- package/dist/DateRangePickerContext.d.ts.map +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +337 -0
- package/dist/Dialog.js.map +1 -0
- package/dist/Dialog.jsx +192 -0
- package/dist/Dialog.jsx.map +1 -0
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/Disclosure.js +331 -0
- package/dist/Disclosure.js.map +1 -0
- package/dist/Disclosure.jsx +230 -0
- package/dist/Disclosure.jsx.map +1 -0
- package/dist/DragAndDrop.d.ts.map +1 -1
- package/dist/DragAndDrop.js +176 -0
- package/dist/DragAndDrop.js.map +1 -0
- package/dist/DragAndDrop.jsx +160 -0
- package/dist/DragAndDrop.jsx.map +1 -0
- package/dist/DropZone.d.ts.map +1 -1
- package/dist/DropZone.js +189 -0
- package/dist/DropZone.js.map +1 -0
- package/dist/DropZone.jsx +144 -0
- package/dist/DropZone.jsx.map +1 -0
- package/dist/FieldError.js +66 -0
- package/dist/FieldError.js.map +1 -0
- package/dist/FieldError.jsx +47 -0
- package/dist/FieldError.jsx.map +1 -0
- package/dist/FileTrigger.js +79 -0
- package/dist/FileTrigger.js.map +1 -0
- package/dist/FileTrigger.jsx +49 -0
- package/dist/FileTrigger.jsx.map +1 -0
- package/dist/Focusable.js +70 -0
- package/dist/Focusable.js.map +1 -0
- package/dist/Focusable.jsx +69 -0
- package/dist/Focusable.jsx.map +1 -0
- package/dist/Form.js +99 -0
- package/dist/Form.js.map +1 -0
- package/dist/Form.jsx +73 -0
- package/dist/Form.jsx.map +1 -0
- package/dist/GridList.d.ts +34 -2
- package/dist/GridList.d.ts.map +1 -1
- package/dist/GridList.js +723 -0
- package/dist/GridList.js.map +1 -0
- package/dist/GridList.jsx +552 -0
- package/dist/GridList.jsx.map +1 -0
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Icon.js +127 -0
- package/dist/Icon.js.map +1 -0
- package/dist/Icon.jsx +72 -0
- package/dist/Icon.jsx.map +1 -0
- package/dist/Keyboard.js +30 -0
- package/dist/Keyboard.js.map +1 -0
- package/dist/Keyboard.jsx +24 -0
- package/dist/Keyboard.jsx.map +1 -0
- package/dist/Landmark.js +134 -0
- package/dist/Landmark.js.map +1 -0
- package/dist/Landmark.jsx +118 -0
- package/dist/Landmark.jsx.map +1 -0
- package/dist/Link.d.ts.map +1 -1
- package/dist/Link.js +219 -0
- package/dist/Link.js.map +1 -0
- package/dist/Link.jsx +189 -0
- package/dist/Link.jsx.map +1 -0
- package/dist/ListBox.d.ts +2 -2
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListBox.js +831 -0
- package/dist/ListBox.js.map +1 -0
- package/dist/ListBox.jsx +644 -0
- package/dist/ListBox.jsx.map +1 -0
- package/dist/Menu.d.ts +27 -9
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Menu.js +1254 -0
- package/dist/Menu.js.map +1 -0
- package/dist/Menu.jsx +1042 -0
- package/dist/Menu.jsx.map +1 -0
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Meter.js +123 -0
- package/dist/Meter.js.map +1 -0
- package/dist/Meter.jsx +107 -0
- package/dist/Meter.jsx.map +1 -0
- package/dist/Modal.d.ts.map +1 -1
- package/dist/Modal.js +382 -0
- package/dist/Modal.js.map +1 -0
- package/dist/Modal.jsx +314 -0
- package/dist/Modal.jsx.map +1 -0
- package/dist/NumberField.d.ts +3 -3
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/NumberField.js +573 -0
- package/dist/NumberField.js.map +1 -0
- package/dist/NumberField.jsx +443 -0
- package/dist/NumberField.jsx.map +1 -0
- package/dist/Popover.d.ts +10 -2
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js +471 -0
- package/dist/Popover.js.map +1 -0
- package/dist/Popover.jsx +354 -0
- package/dist/Popover.jsx.map +1 -0
- package/dist/Pressable.js +69 -0
- package/dist/Pressable.js.map +1 -0
- package/dist/Pressable.jsx +68 -0
- package/dist/Pressable.jsx.map +1 -0
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar.js +130 -0
- package/dist/ProgressBar.js.map +1 -0
- package/dist/ProgressBar.jsx +114 -0
- package/dist/ProgressBar.jsx.map +1 -0
- package/dist/RadioGroup.d.ts +82 -4
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +931 -0
- package/dist/RadioGroup.js.map +1 -0
- package/dist/RadioGroup.jsx +681 -0
- package/dist/RadioGroup.jsx.map +1 -0
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RangeCalendar.js +546 -0
- package/dist/RangeCalendar.js.map +1 -0
- package/dist/RangeCalendar.jsx +323 -0
- package/dist/RangeCalendar.jsx.map +1 -0
- package/dist/RouterProvider.js +118 -0
- package/dist/RouterProvider.js.map +1 -0
- package/dist/RouterProvider.jsx +112 -0
- package/dist/RouterProvider.jsx.map +1 -0
- package/dist/SearchField.d.ts +2 -2
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/SearchField.js +667 -0
- package/dist/SearchField.js.map +1 -0
- package/dist/SearchField.jsx +550 -0
- package/dist/SearchField.jsx.map +1 -0
- package/dist/Select.d.ts +7 -0
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +1044 -0
- package/dist/Select.js.map +1 -0
- package/dist/Select.jsx +759 -0
- package/dist/Select.jsx.map +1 -0
- package/dist/SelectionIndicator.d.ts.map +1 -1
- package/dist/SelectionIndicator.js +86 -0
- package/dist/SelectionIndicator.js.map +1 -0
- package/dist/SelectionIndicator.jsx +50 -0
- package/dist/SelectionIndicator.jsx.map +1 -0
- package/dist/Separator.js +97 -0
- package/dist/Separator.js.map +1 -0
- package/dist/Separator.jsx +85 -0
- package/dist/Separator.jsx.map +1 -0
- package/dist/SharedElementTransition.d.ts.map +1 -1
- package/dist/SharedElementTransition.js +167 -0
- package/dist/SharedElementTransition.js.map +1 -0
- package/dist/SharedElementTransition.jsx +140 -0
- package/dist/SharedElementTransition.jsx.map +1 -0
- package/dist/Slider.d.ts +33 -1
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Slider.js +515 -0
- package/dist/Slider.js.map +1 -0
- package/dist/Slider.jsx +403 -0
- package/dist/Slider.jsx.map +1 -0
- package/dist/StepList.d.ts.map +1 -1
- package/dist/StepList.js +191 -0
- package/dist/StepList.js.map +1 -0
- package/dist/StepList.jsx +136 -0
- package/dist/StepList.jsx.map +1 -0
- package/dist/Switch.d.ts +65 -2
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Switch.js +534 -0
- package/dist/Switch.js.map +1 -0
- package/dist/Switch.jsx +393 -0
- package/dist/Switch.jsx.map +1 -0
- package/dist/Table.d.ts +50 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +1766 -0
- package/dist/Table.js.map +1 -0
- package/dist/Table.jsx +1355 -0
- package/dist/Table.jsx.map +1 -0
- package/dist/Tabs.d.ts +0 -4
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js +598 -0
- package/dist/Tabs.js.map +1 -0
- package/dist/Tabs.jsx +367 -0
- package/dist/Tabs.jsx.map +1 -0
- package/dist/TagGroup.d.ts +3 -1
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/TagGroup.js +382 -0
- package/dist/TagGroup.js.map +1 -0
- package/dist/TagGroup.jsx +273 -0
- package/dist/TagGroup.jsx.map +1 -0
- package/dist/Text.d.ts +18 -6
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +42 -0
- package/dist/Text.js.map +1 -0
- package/dist/Text.jsx +35 -0
- package/dist/Text.jsx.map +1 -0
- package/dist/TextField.d.ts +6 -6
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TextField.js +439 -0
- package/dist/TextField.js.map +1 -0
- package/dist/TextField.jsx +406 -0
- package/dist/TextField.jsx.map +1 -0
- package/dist/TimeField.d.ts +17 -53
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/TimeField.js +278 -0
- package/dist/TimeField.js.map +1 -0
- package/dist/TimeField.jsx +218 -0
- package/dist/TimeField.jsx.map +1 -0
- package/dist/Toast.d.ts +14 -0
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js +551 -0
- package/dist/Toast.js.map +1 -0
- package/dist/Toast.jsx +361 -0
- package/dist/Toast.jsx.map +1 -0
- package/dist/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton.js +123 -0
- package/dist/ToggleButton.js.map +1 -0
- package/dist/ToggleButton.jsx +88 -0
- package/dist/ToggleButton.jsx.map +1 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButtonGroup.js +114 -0
- package/dist/ToggleButtonGroup.js.map +1 -0
- package/dist/ToggleButtonGroup.jsx +85 -0
- package/dist/ToggleButtonGroup.jsx.map +1 -0
- package/dist/Toolbar.js +112 -0
- package/dist/Toolbar.js.map +1 -0
- package/dist/Toolbar.jsx +92 -0
- package/dist/Toolbar.jsx.map +1 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js +539 -0
- package/dist/Tooltip.js.map +1 -0
- package/dist/Tooltip.jsx +465 -0
- package/dist/Tooltip.jsx.map +1 -0
- package/dist/Tree.d.ts +14 -2
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Tree.js +1424 -0
- package/dist/Tree.js.map +1 -0
- package/dist/Tree.jsx +1172 -0
- package/dist/Tree.jsx.map +1 -0
- package/dist/Virtualizer.d.ts +16 -2
- package/dist/Virtualizer.d.ts.map +1 -1
- package/dist/Virtualizer.js +2 -0
- package/dist/Virtualizer.jsx +2 -0
- package/dist/Virtualizer2.js +751 -0
- package/dist/Virtualizer2.js.map +1 -0
- package/dist/Virtualizer2.jsx +730 -0
- package/dist/Virtualizer2.jsx.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +18 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +42 -0
- package/dist/VisuallyHidden.js.map +1 -0
- package/dist/VisuallyHidden.jsx +35 -0
- package/dist/VisuallyHidden.jsx.map +1 -0
- package/dist/contexts.js +33 -0
- package/dist/contexts.js.map +1 -0
- package/dist/contexts.jsx +33 -0
- package/dist/contexts.jsx.map +1 -0
- package/dist/index.d.ts +9 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +69 -23932
- package/dist/index.jsx +69 -18337
- package/dist/useDragAndDrop.d.ts +0 -8
- package/dist/useDragAndDrop.d.ts.map +1 -1
- package/dist/useDragAndDrop.js +2 -0
- package/dist/useDragAndDrop.jsx +2 -0
- package/dist/useDragAndDrop2.js +399 -0
- package/dist/useDragAndDrop2.js.map +1 -0
- package/dist/useDragAndDrop2.jsx +399 -0
- package/dist/useDragAndDrop2.jsx.map +1 -0
- package/dist/utils.d.ts +84 -11
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +285 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.jsx +277 -0
- package/dist/utils.jsx.map +1 -0
- package/dist/virtualizer/Layout.js +144 -0
- package/dist/virtualizer/Layout.js.map +1 -0
- package/dist/virtualizer/Layout.jsx +144 -0
- package/dist/virtualizer/Layout.jsx.map +1 -0
- package/package.json +395 -4
- package/src/ActionBar.tsx +10 -12
- package/src/ActionGroup.tsx +5 -3
- package/src/Autocomplete.tsx +14 -9
- package/src/Breadcrumbs.tsx +58 -39
- package/src/Button.tsx +22 -2
- package/src/Calendar.tsx +57 -11
- package/src/CalendarPicker.tsx +73 -0
- package/src/Checkbox.tsx +539 -3
- package/src/Collection.tsx +9 -3
- package/src/Color.tsx +84 -41
- package/src/ComboBox.tsx +97 -21
- package/src/DateField.tsx +304 -53
- package/src/DatePicker.tsx +402 -62
- package/src/DateRangePickerContext.tsx +2 -0
- package/src/Dialog.tsx +13 -5
- package/src/Disclosure.tsx +7 -1
- package/src/DragAndDrop.tsx +3 -1
- package/src/DropZone.tsx +3 -1
- package/src/GridList.tsx +133 -26
- package/src/Icon.tsx +3 -1
- package/src/Link.tsx +3 -1
- package/src/ListBox.tsx +354 -25
- package/src/Menu.tsx +252 -128
- package/src/Meter.tsx +3 -1
- package/src/Modal.tsx +120 -56
- package/src/NumberField.tsx +51 -8
- package/src/Popover.tsx +68 -17
- package/src/ProgressBar.tsx +3 -1
- package/src/RadioGroup.tsx +468 -4
- package/src/RangeCalendar.tsx +123 -2
- package/src/SearchField.tsx +80 -4
- package/src/Select.tsx +122 -26
- package/src/SelectionIndicator.tsx +3 -1
- package/src/SharedElementTransition.tsx +95 -37
- package/src/Slider.tsx +159 -13
- package/src/StepList.tsx +0 -7
- package/src/Switch.tsx +395 -2
- package/src/Table.tsx +428 -99
- package/src/Tabs.tsx +17 -45
- package/src/TagGroup.tsx +29 -7
- package/src/Text.tsx +31 -10
- package/src/TextField.tsx +44 -6
- package/src/TimeField.tsx +127 -192
- package/src/Toast.tsx +79 -14
- package/src/ToggleButton.tsx +3 -1
- package/src/ToggleButtonGroup.tsx +3 -1
- package/src/Tooltip.tsx +3 -1
- package/src/Tree.tsx +91 -13
- package/src/Virtualizer.tsx +180 -31
- package/src/VirtualizerLayouts.ts +45 -10
- package/src/index.ts +51 -8
- package/src/useDragAndDrop.ts +8 -10
- package/src/utils.tsx +246 -30
- package/dist/HiddenTimeInput.d.ts +0 -25
- package/dist/HiddenTimeInput.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.jsx.map +0 -1
- package/src/HiddenTimeInput.tsx +0 -133
package/src/Tree.tsx
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
createTree,
|
|
25
25
|
createTreeItem,
|
|
26
26
|
createTreeSelectionCheckbox,
|
|
27
|
+
createGridListSection,
|
|
27
28
|
createFocusRing,
|
|
28
29
|
createHover,
|
|
29
30
|
mergeProps,
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
type Key,
|
|
40
41
|
type DropTarget,
|
|
41
42
|
type ItemDropTarget,
|
|
43
|
+
type Collection,
|
|
42
44
|
} from "@proyecto-viviana/solid-stately";
|
|
43
45
|
import {
|
|
44
46
|
type RenderChildren,
|
|
@@ -60,14 +62,17 @@ import {
|
|
|
60
62
|
CollectionRendererContext,
|
|
61
63
|
flattenCollectionEntries,
|
|
62
64
|
isCollectionSection,
|
|
63
|
-
Section,
|
|
64
|
-
Header,
|
|
65
65
|
type CollectionEntry,
|
|
66
66
|
type CollectionRendererContextValue,
|
|
67
67
|
type SectionProps,
|
|
68
|
-
type HeaderProps,
|
|
69
68
|
useCollectionRenderer,
|
|
70
69
|
} from "./Collection";
|
|
70
|
+
import {
|
|
71
|
+
GridListHeader,
|
|
72
|
+
GridListHeaderContext,
|
|
73
|
+
GridListHeaderInnerContext,
|
|
74
|
+
type GridListHeaderProps,
|
|
75
|
+
} from "./GridList";
|
|
71
76
|
import { useVirtualizerContext } from "./Virtualizer";
|
|
72
77
|
import {
|
|
73
78
|
handleLinkClick,
|
|
@@ -242,7 +247,7 @@ export interface TreeLoadMoreItemProps extends SlotProps {
|
|
|
242
247
|
}
|
|
243
248
|
|
|
244
249
|
export interface TreeSectionProps extends SectionProps {}
|
|
245
|
-
export interface TreeHeaderProps extends
|
|
250
|
+
export interface TreeHeaderProps extends GridListHeaderProps {}
|
|
246
251
|
|
|
247
252
|
interface TreeContextValue<T extends object> {
|
|
248
253
|
state: TreeState<T, TreeCollection<T>>;
|
|
@@ -882,7 +887,13 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
|
|
|
882
887
|
// Resolve writing direction for keyboard expand/collapse parity
|
|
883
888
|
const treeDirection = createMemo(() => ariaProps.direction ?? resolveTreeDirection(ref()));
|
|
884
889
|
|
|
885
|
-
|
|
890
|
+
// Keep the aria object (do NOT destructure `treeProps`): its `treeProps` getter
|
|
891
|
+
// wraps a memo carrying the reactive roving-container `tabIndex`, which rolls to
|
|
892
|
+
// -1 once a row takes focus. Destructuring here would read the getter once and
|
|
893
|
+
// freeze it at its first value (tabIndex 0), so the roll would never reach the
|
|
894
|
+
// DOM. Read `treeAria.treeProps` inside `cleanTreeProps` instead, so the spread's
|
|
895
|
+
// reactive re-run re-enters the memo and tracks `focusedKey`. (Mirrors GridList.)
|
|
896
|
+
const treeAria = createTree<T, TreeCollection<T>>(
|
|
886
897
|
() => ({
|
|
887
898
|
id: ariaProps.id,
|
|
888
899
|
"aria-label": ariaProps["aria-label"],
|
|
@@ -891,6 +902,7 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
|
|
|
891
902
|
isVirtualized: ariaProps.isVirtualized,
|
|
892
903
|
onAction: ariaProps.onAction,
|
|
893
904
|
isDisabled: ariaProps.isDisabled,
|
|
905
|
+
keyboardNavigationBehavior: ariaProps.keyboardNavigationBehavior,
|
|
894
906
|
direction: treeDirection(),
|
|
895
907
|
}),
|
|
896
908
|
() => state,
|
|
@@ -921,7 +933,7 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
|
|
|
921
933
|
});
|
|
922
934
|
|
|
923
935
|
const cleanTreeProps = () => {
|
|
924
|
-
const { ref: _ref1, ...rest } = treeProps as Record<string, unknown>;
|
|
936
|
+
const { ref: _ref1, ...rest } = treeAria.treeProps as Record<string, unknown>;
|
|
925
937
|
return rest;
|
|
926
938
|
};
|
|
927
939
|
const cleanFocusProps = () => {
|
|
@@ -1049,8 +1061,11 @@ export function Tree<T extends object>(props: TreeProps<T>): JSX.Element {
|
|
|
1049
1061
|
getKeyPageBelow: (key) => state.collection.getKeyAfter(key),
|
|
1050
1062
|
getKeyPageAbove: (key) => state.collection.getKeyBefore(key),
|
|
1051
1063
|
},
|
|
1064
|
+
// TreeCollection carries a wider node.type union than the narrow
|
|
1065
|
+
// Collection option but is structurally a valid Collection for
|
|
1066
|
+
// navigate()/focus restoration — cast at the seam.
|
|
1052
1067
|
get collection() {
|
|
1053
|
-
return state.collection;
|
|
1068
|
+
return state.collection as unknown as Collection;
|
|
1054
1069
|
},
|
|
1055
1070
|
get selectedKeys() {
|
|
1056
1071
|
return state.selectedKeys;
|
|
@@ -1565,7 +1580,9 @@ export function TreeItem<T extends object>(props: TreeItemProps<T>): JSX.Element
|
|
|
1565
1580
|
|
|
1566
1581
|
const renderProps = useRenderProps(
|
|
1567
1582
|
{
|
|
1568
|
-
children
|
|
1583
|
+
get children() {
|
|
1584
|
+
return props.children;
|
|
1585
|
+
},
|
|
1569
1586
|
class: local.class,
|
|
1570
1587
|
style: local.style,
|
|
1571
1588
|
defaultClassName: "solidaria-Tree-item",
|
|
@@ -1762,7 +1779,7 @@ export function TreeSelectionCheckbox(props: {
|
|
|
1762
1779
|
{...treeSelectionCheckboxAria.checkboxProps}
|
|
1763
1780
|
class={props.class ?? "solidaria-Tree-checkbox"}
|
|
1764
1781
|
style={props.style}
|
|
1765
|
-
tabIndex={props.excludeFromTabOrder ? -1 :
|
|
1782
|
+
tabIndex={props.excludeFromTabOrder ? -1 : 0}
|
|
1766
1783
|
aria-label={props["aria-label"] ?? treeSelectionCheckboxAria.checkboxProps["aria-label"]}
|
|
1767
1784
|
/>
|
|
1768
1785
|
);
|
|
@@ -1805,7 +1822,9 @@ export function TreeLoadMoreItem(props: TreeLoadMoreItemProps): JSX.Element {
|
|
|
1805
1822
|
|
|
1806
1823
|
const renderProps = useRenderProps(
|
|
1807
1824
|
{
|
|
1808
|
-
|
|
1825
|
+
get children() {
|
|
1826
|
+
return props.children ?? (() => (isLoading() ? "Loading more..." : "Load more"));
|
|
1827
|
+
},
|
|
1809
1828
|
class: props.class,
|
|
1810
1829
|
style: props.style,
|
|
1811
1830
|
defaultClassName: "solidaria-Tree-loadMore",
|
|
@@ -1858,7 +1877,9 @@ export function TreeItemContent(props: TreeItemContentProps): JSX.Element {
|
|
|
1858
1877
|
|
|
1859
1878
|
const renderProps = useRenderProps(
|
|
1860
1879
|
{
|
|
1861
|
-
children
|
|
1880
|
+
get children() {
|
|
1881
|
+
return props.children;
|
|
1882
|
+
},
|
|
1862
1883
|
},
|
|
1863
1884
|
() => context,
|
|
1864
1885
|
);
|
|
@@ -1866,12 +1887,69 @@ export function TreeItemContent(props: TreeItemContentProps): JSX.Element {
|
|
|
1866
1887
|
return <>{renderProps.renderChildren()}</>;
|
|
1867
1888
|
}
|
|
1868
1889
|
|
|
1890
|
+
/**
|
|
1891
|
+
* A section within a Tree. Renders as `role="rowgroup"` and supplies its
|
|
1892
|
+
* optional {@link TreeHeader} with the row/rowheader props that wire up the
|
|
1893
|
+
* section's `aria-labelledby` (mirrors upstream `TreeSection`, which reuses
|
|
1894
|
+
* `useGridListSection`).
|
|
1895
|
+
*/
|
|
1869
1896
|
export function TreeSection(props: TreeSectionProps): JSX.Element {
|
|
1870
|
-
|
|
1897
|
+
const [local, domProps] = splitProps(props, ["children", "class", "style", "slot", "ref"]);
|
|
1898
|
+
|
|
1899
|
+
const section = createGridListSection({
|
|
1900
|
+
get "aria-label"() {
|
|
1901
|
+
return (domProps as { "aria-label"?: string })["aria-label"];
|
|
1902
|
+
},
|
|
1903
|
+
});
|
|
1904
|
+
|
|
1905
|
+
// Mirror upstream: resolve class/style via renderProps but keep children out
|
|
1906
|
+
// of it. The real children must only be evaluated inside the header providers
|
|
1907
|
+
// below, otherwise a child <TreeHeader> would be instantiated in this
|
|
1908
|
+
// component's owner and read the header contexts as null. The values callback
|
|
1909
|
+
// runs during setup, so it must not read `local.children` either; mirror
|
|
1910
|
+
// upstream's `values: undefined` with a constant.
|
|
1911
|
+
const renderProps = useRenderProps(
|
|
1912
|
+
{
|
|
1913
|
+
children: undefined,
|
|
1914
|
+
class: local.class,
|
|
1915
|
+
style: local.style,
|
|
1916
|
+
defaultClassName: "solidaria-TreeSection",
|
|
1917
|
+
},
|
|
1918
|
+
() => ({ hasChildren: true }),
|
|
1919
|
+
);
|
|
1920
|
+
|
|
1921
|
+
const filteredDomProps = createMemo(() => filterDOMProps(domProps, { global: true }));
|
|
1922
|
+
|
|
1923
|
+
return (
|
|
1924
|
+
<div
|
|
1925
|
+
ref={(el) => assignRef(local.ref, el)}
|
|
1926
|
+
{...filteredDomProps()}
|
|
1927
|
+
{...section.rowGroupProps}
|
|
1928
|
+
class={renderProps.class()}
|
|
1929
|
+
style={renderProps.style()}
|
|
1930
|
+
slot={local.slot}
|
|
1931
|
+
data-section
|
|
1932
|
+
>
|
|
1933
|
+
<GridListHeaderContext.Provider value={section.rowProps}>
|
|
1934
|
+
<GridListHeaderInnerContext.Provider value={section.rowHeaderProps}>
|
|
1935
|
+
{local.children}
|
|
1936
|
+
</GridListHeaderInnerContext.Provider>
|
|
1937
|
+
</GridListHeaderContext.Provider>
|
|
1938
|
+
</div>
|
|
1939
|
+
);
|
|
1871
1940
|
}
|
|
1872
1941
|
|
|
1942
|
+
/**
|
|
1943
|
+
* The header of a {@link TreeSection}. Mirrors upstream `TreeHeader`, which is a
|
|
1944
|
+
* thin wrapper over `GridListHeader` with a Tree-specific class. The row and
|
|
1945
|
+
* rowheader semantics come from the enclosing section through context.
|
|
1946
|
+
*/
|
|
1873
1947
|
export function TreeHeader(props: TreeHeaderProps): JSX.Element {
|
|
1874
|
-
return
|
|
1948
|
+
return (
|
|
1949
|
+
<GridListHeader class="solidaria-TreeHeader" {...props}>
|
|
1950
|
+
{props.children}
|
|
1951
|
+
</GridListHeader>
|
|
1952
|
+
);
|
|
1875
1953
|
}
|
|
1876
1954
|
|
|
1877
1955
|
Tree.Item = TreeItem;
|
package/src/Virtualizer.tsx
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
type DefaultVirtualizerLayoutOptions,
|
|
33
33
|
type GridLayoutOptions,
|
|
34
34
|
type LayoutInfo,
|
|
35
|
+
type Orientation,
|
|
35
36
|
type Point,
|
|
36
37
|
type Rect,
|
|
37
38
|
type Size,
|
|
@@ -70,6 +71,13 @@ export interface VirtualizerContextValue<O = unknown> {
|
|
|
70
71
|
layout: VirtualizerLayout<O>;
|
|
71
72
|
layoutOptions?: O;
|
|
72
73
|
isVirtualized: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* The resolved primary orientation of the layout. Consumers render their
|
|
76
|
+
* windowing spacers along this axis (`width` when `horizontal`, `height`
|
|
77
|
+
* when `vertical`) so the spacer size matches the offsets `getVisibleRange`
|
|
78
|
+
* produced.
|
|
79
|
+
*/
|
|
80
|
+
orientation: Orientation;
|
|
73
81
|
getVisibleRange: (itemCount: number) => VirtualizerVisibleRange;
|
|
74
82
|
getLayoutInfo: (index: number) => LayoutInfo;
|
|
75
83
|
getDropTargetFromPoint: (point: Point, itemCount: number) => VirtualizerDropTarget | null;
|
|
@@ -117,6 +125,13 @@ export interface VirtualizerProps<O> extends Omit<
|
|
|
117
125
|
) => JSX.Element | undefined;
|
|
118
126
|
/** Optional operation resolver for collection drop target operations. */
|
|
119
127
|
getDropOperation?: VirtualizerDropOperationResolver;
|
|
128
|
+
/**
|
|
129
|
+
* Whether the collection may scroll with the page rather than only within its
|
|
130
|
+
* own scroll container. When enabled (the default, matching react-aria-components),
|
|
131
|
+
* the visible rect is the intersection of the window viewport with the scroll view,
|
|
132
|
+
* so a virtualizer with unbounded height still virtualizes as the page scrolls.
|
|
133
|
+
*/
|
|
134
|
+
allowsWindowScrolling?: boolean;
|
|
120
135
|
class?: string;
|
|
121
136
|
style?: string | JSX.CSSProperties;
|
|
122
137
|
}
|
|
@@ -159,12 +174,29 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
|
|
|
159
174
|
"layoutOptions",
|
|
160
175
|
"renderDropIndicator",
|
|
161
176
|
"getDropOperation",
|
|
177
|
+
"allowsWindowScrolling",
|
|
162
178
|
"class",
|
|
163
179
|
"style",
|
|
164
180
|
]);
|
|
181
|
+
// The scroll view's own scroll position (its scrollTop).
|
|
165
182
|
const [scrollOffset, setScrollOffset] = createSignal(0);
|
|
183
|
+
// The scroll view's horizontal scroll position (its scrollLeft), used as the
|
|
184
|
+
// primary scroll axis when the layout's orientation is horizontal.
|
|
185
|
+
const [scrollOffsetX, setScrollOffsetX] = createSignal(0);
|
|
186
|
+
// How far the scroll view's top edge is above the window viewport, due to the
|
|
187
|
+
// page (or an ancestor) being scrolled. Mirrors upstream ScrollView.viewportOffset.
|
|
188
|
+
const [viewportOffset, setViewportOffset] = createSignal(0);
|
|
189
|
+
// The window viewport height, used as the visible height cap when window scrolling.
|
|
190
|
+
const [windowViewportSize, setWindowViewportSize] = createSignal(0);
|
|
191
|
+
// The scroll view's own measured size (clientHeight/clientWidth).
|
|
166
192
|
const [measuredViewportSize, setMeasuredViewportSize] = createSignal(0);
|
|
167
193
|
const [measuredViewportWidth, setMeasuredViewportWidth] = createSignal(0);
|
|
194
|
+
const allowsWindowScrolling = createMemo(() => local.allowsWindowScrolling ?? true);
|
|
195
|
+
// Whether the scroll view is actively scrolling. Mirrors upstream ScrollView's
|
|
196
|
+
// `isScrolling`: while scrolling, the content gets `pointer-events: none` so pointer
|
|
197
|
+
// events don't hit rows recycling under a stationary cursor (avoiding hover-state
|
|
198
|
+
// flicker and needless hit-testing). It flips back 300ms after the last scroll.
|
|
199
|
+
const [isScrolling, setIsScrolling] = createSignal(false);
|
|
168
200
|
const [dropTargetResolver, setDropTargetResolver] = createSignal<
|
|
169
201
|
VirtualizerDropTargetResolver | undefined
|
|
170
202
|
>(undefined);
|
|
@@ -218,15 +250,44 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
|
|
|
218
250
|
});
|
|
219
251
|
const itemSize = createMemo(() => getObjectValue(virtualOptions(), "itemSize") ?? 40);
|
|
220
252
|
const overscan = createMemo(() => getObjectValue(virtualOptions(), "overscan") ?? 2);
|
|
221
|
-
const
|
|
222
|
-
() => getObjectValue(virtualOptions(), "
|
|
253
|
+
const orientation = createMemo<Orientation>(
|
|
254
|
+
() => getObjectValue(virtualOptions(), "orientation") ?? "vertical",
|
|
223
255
|
);
|
|
256
|
+
// The effective visible height. When window scrolling, this is the scroll view's
|
|
257
|
+
// size intersected with the window viewport (capped to what is actually on screen),
|
|
258
|
+
// mirroring upstream ScrollView.updateVisibleRect. Otherwise it is the scroll view's
|
|
259
|
+
// own clientHeight. An explicit `viewportSize` layout option still takes precedence.
|
|
260
|
+
const viewportSize = createMemo(() => {
|
|
261
|
+
const explicit = getObjectValue(virtualOptions(), "viewportSize");
|
|
262
|
+
if (explicit != null) return explicit;
|
|
263
|
+
const elementSize = measuredViewportSize() ?? 0;
|
|
264
|
+
if (allowsWindowScrolling()) {
|
|
265
|
+
return Math.max(0, Math.min(elementSize - viewportOffset(), windowViewportSize()));
|
|
266
|
+
}
|
|
267
|
+
return elementSize;
|
|
268
|
+
});
|
|
269
|
+
// The top of the visible rect in content coordinates: the scroll view's own scroll
|
|
270
|
+
// position plus how far it has been pushed above the window viewport by page scroll.
|
|
271
|
+
const effectiveScrollOffset = createMemo(() =>
|
|
272
|
+
allowsWindowScrolling() ? scrollOffset() + viewportOffset() : scrollOffset(),
|
|
273
|
+
);
|
|
274
|
+
// The primary-axis scroll offset and viewport size, selected by orientation.
|
|
275
|
+
// A horizontal layout scrolls along x (scrollLeft / client width); the vertical
|
|
276
|
+
// default scrolls along y (with the window-scrolling adjustments above).
|
|
277
|
+
const mainScrollOffset = createMemo(() =>
|
|
278
|
+
orientation() === "horizontal" ? scrollOffsetX() : effectiveScrollOffset(),
|
|
279
|
+
);
|
|
280
|
+
const mainViewportSize = createMemo(() => {
|
|
281
|
+
if (orientation() !== "horizontal") return viewportSize();
|
|
282
|
+
const explicit = getObjectValue(virtualOptions(), "viewportSize");
|
|
283
|
+
return explicit != null ? explicit : measuredViewportWidth();
|
|
284
|
+
});
|
|
224
285
|
|
|
225
286
|
const getVisibleRange = (itemCount: number): VirtualizerVisibleRange => {
|
|
226
287
|
const ctx: VirtualizerRangeContext = {
|
|
227
288
|
itemCount,
|
|
228
|
-
scrollOffset:
|
|
229
|
-
viewportSize:
|
|
289
|
+
scrollOffset: mainScrollOffset(),
|
|
290
|
+
viewportSize: mainViewportSize(),
|
|
230
291
|
overscan: overscan(),
|
|
231
292
|
viewportWidth: measuredViewportWidth(),
|
|
232
293
|
};
|
|
@@ -250,18 +311,32 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
|
|
|
250
311
|
const getLayoutInfo = (index: number): LayoutInfo => {
|
|
251
312
|
const ctx: VirtualizerLayoutInfoContext = {
|
|
252
313
|
viewportWidth: measuredViewportWidth(),
|
|
314
|
+
viewportHeight: measuredViewportSize(),
|
|
253
315
|
};
|
|
254
316
|
const layoutResult = resolvedLayout().getLayoutInfo?.(index, ctx, layoutOptionsWithViewport());
|
|
255
|
-
const nextInfo =
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
317
|
+
const nextInfo =
|
|
318
|
+
layoutResult ??
|
|
319
|
+
(orientation() === "horizontal"
|
|
320
|
+
? {
|
|
321
|
+
key: String(index),
|
|
322
|
+
index,
|
|
323
|
+
rect: {
|
|
324
|
+
x: index * itemSize(),
|
|
325
|
+
y: 0,
|
|
326
|
+
width: itemSize(),
|
|
327
|
+
height: Math.max(0, measuredViewportSize()),
|
|
328
|
+
},
|
|
329
|
+
}
|
|
330
|
+
: {
|
|
331
|
+
key: String(index),
|
|
332
|
+
index,
|
|
333
|
+
rect: {
|
|
334
|
+
x: 0,
|
|
335
|
+
y: index * itemSize(),
|
|
336
|
+
width: Math.max(0, measuredViewportWidth()),
|
|
337
|
+
height: itemSize(),
|
|
338
|
+
},
|
|
339
|
+
});
|
|
265
340
|
const cachedInfo = layoutInfoCache.get(index);
|
|
266
341
|
if (cachedInfo && isSameLayoutInfo(cachedInfo, nextInfo)) {
|
|
267
342
|
return cachedInfo;
|
|
@@ -566,7 +641,7 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
|
|
|
566
641
|
: direction === "next"
|
|
567
642
|
? -1
|
|
568
643
|
: itemCount;
|
|
569
|
-
const pageSize = Math.max(1, Math.floor(
|
|
644
|
+
const pageSize = Math.max(1, Math.floor(mainViewportSize() / Math.max(1, itemSize())));
|
|
570
645
|
const delta = direction === "next" ? 1 : -1;
|
|
571
646
|
const nextStart = currentIndex + delta * pageSize;
|
|
572
647
|
const clampedStart = Math.max(0, Math.min(itemCount - 1, nextStart));
|
|
@@ -633,6 +708,7 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
|
|
|
633
708
|
layout: resolvedLayout(),
|
|
634
709
|
layoutOptions: resolvedLayoutOptions(),
|
|
635
710
|
isVirtualized: true,
|
|
711
|
+
orientation: orientation(),
|
|
636
712
|
getVisibleRange,
|
|
637
713
|
getLayoutInfo,
|
|
638
714
|
getDropTargetFromPoint,
|
|
@@ -666,26 +742,96 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
|
|
|
666
742
|
if (nextWidth !== measuredViewportWidth()) setMeasuredViewportWidth(nextWidth);
|
|
667
743
|
};
|
|
668
744
|
|
|
745
|
+
const updateWindowViewport = () => {
|
|
746
|
+
if (typeof window === "undefined") return;
|
|
747
|
+
const next = window.innerHeight;
|
|
748
|
+
if (next !== windowViewportSize()) setWindowViewportSize(next);
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
// Recompute how far the scroll view's top edge sits above the window viewport.
|
|
752
|
+
// A negative bounding-rect top means the scroll view has been pushed up by page
|
|
753
|
+
// (or ancestor) scrolling; the offset is the amount scrolled past its top.
|
|
754
|
+
const updateViewportOffset = () => {
|
|
755
|
+
if (!containerRef || !allowsWindowScrolling()) return;
|
|
756
|
+
const rect = containerRef.getBoundingClientRect();
|
|
757
|
+
const next = rect.y < 0 ? -rect.y : 0;
|
|
758
|
+
if (next !== viewportOffset()) setViewportOffset(next);
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
let scrollFrame: number | undefined;
|
|
762
|
+
// Debounce handle that resets `isScrolling` after scrolling stops.
|
|
763
|
+
let scrollEndTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
764
|
+
onCleanup(() => {
|
|
765
|
+
if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
|
|
766
|
+
if (scrollEndTimeout != null) clearTimeout(scrollEndTimeout);
|
|
767
|
+
});
|
|
768
|
+
|
|
669
769
|
onMount(() => {
|
|
670
770
|
updateViewportSize();
|
|
671
|
-
|
|
771
|
+
updateWindowViewport();
|
|
772
|
+
updateViewportOffset();
|
|
773
|
+
|
|
774
|
+
const handleResize = () => {
|
|
775
|
+
updateViewportSize();
|
|
776
|
+
updateWindowViewport();
|
|
777
|
+
updateViewportOffset();
|
|
778
|
+
};
|
|
672
779
|
window.addEventListener("resize", handleResize);
|
|
780
|
+
|
|
673
781
|
const resizeObserver =
|
|
674
782
|
typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => updateViewportSize()) : null;
|
|
675
783
|
if (containerRef && resizeObserver) {
|
|
676
784
|
resizeObserver.observe(containerRef);
|
|
677
785
|
}
|
|
786
|
+
|
|
787
|
+
// A capturing listener on the document sees scroll events on the scroll view
|
|
788
|
+
// itself as well as on any ancestor (including the page), so a single handler
|
|
789
|
+
// can update the local scroll position or the window offset as appropriate.
|
|
790
|
+
const handleDocumentScroll = (e: Event) => {
|
|
791
|
+
if (!containerRef) return;
|
|
792
|
+
const target = e.target as Node | null;
|
|
793
|
+
const isContainer = target === containerRef;
|
|
794
|
+
const isAncestor =
|
|
795
|
+
target === document ||
|
|
796
|
+
target === (window as unknown as Node) ||
|
|
797
|
+
(target instanceof Node && target.contains(containerRef));
|
|
798
|
+
if (!isContainer && !isAncestor) return;
|
|
799
|
+
// An ancestor/page scroll only matters when the collection scrolls with the page.
|
|
800
|
+
if (!isContainer && !allowsWindowScrolling()) return;
|
|
801
|
+
|
|
802
|
+
// Flag active scrolling and (re)arm the reset for 300ms after the last scroll.
|
|
803
|
+
// Our handler is already rAF-throttled, so a plain clear/reset debounce matches
|
|
804
|
+
// upstream's scrollEndTime bookkeeping without the extra accounting.
|
|
805
|
+
if (!isScrolling()) setIsScrolling(true);
|
|
806
|
+
if (scrollEndTimeout != null) clearTimeout(scrollEndTimeout);
|
|
807
|
+
scrollEndTimeout = setTimeout(() => {
|
|
808
|
+
scrollEndTimeout = undefined;
|
|
809
|
+
setIsScrolling(false);
|
|
810
|
+
}, 300);
|
|
811
|
+
|
|
812
|
+
if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
|
|
813
|
+
scrollFrame = requestAnimationFrame(() => {
|
|
814
|
+
scrollFrame = undefined;
|
|
815
|
+
if (isContainer) {
|
|
816
|
+
const next = Math.max(0, containerRef!.scrollTop);
|
|
817
|
+
if (next !== scrollOffset()) setScrollOffset(next);
|
|
818
|
+
const nextX = Math.max(0, containerRef!.scrollLeft);
|
|
819
|
+
if (nextX !== scrollOffsetX()) setScrollOffsetX(nextX);
|
|
820
|
+
} else {
|
|
821
|
+
updateViewportOffset();
|
|
822
|
+
}
|
|
823
|
+
updateViewportSize();
|
|
824
|
+
});
|
|
825
|
+
};
|
|
826
|
+
document.addEventListener("scroll", handleDocumentScroll, true);
|
|
827
|
+
|
|
678
828
|
onCleanup(() => {
|
|
679
829
|
window.removeEventListener("resize", handleResize);
|
|
680
830
|
resizeObserver?.disconnect();
|
|
831
|
+
document.removeEventListener("scroll", handleDocumentScroll, true);
|
|
681
832
|
});
|
|
682
833
|
});
|
|
683
834
|
|
|
684
|
-
let scrollFrame: number | undefined;
|
|
685
|
-
onCleanup(() => {
|
|
686
|
-
if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
|
|
687
|
-
});
|
|
688
|
-
|
|
689
835
|
return (
|
|
690
836
|
<CollectionRendererContext.Provider value={collectionRenderer()}>
|
|
691
837
|
<VirtualizerContext.Provider value={contextValue()}>
|
|
@@ -697,17 +843,19 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
|
|
|
697
843
|
class={local.class}
|
|
698
844
|
style={local.style}
|
|
699
845
|
data-virtualizer
|
|
700
|
-
onScroll={(e) => {
|
|
701
|
-
const target = e.currentTarget as HTMLDivElement;
|
|
702
|
-
if (scrollFrame != null) cancelAnimationFrame(scrollFrame);
|
|
703
|
-
scrollFrame = requestAnimationFrame(() => {
|
|
704
|
-
scrollFrame = undefined;
|
|
705
|
-
if (target.scrollTop !== scrollOffset()) setScrollOffset(target.scrollTop);
|
|
706
|
-
updateViewportSize();
|
|
707
|
-
});
|
|
708
|
-
}}
|
|
709
846
|
>
|
|
710
|
-
{
|
|
847
|
+
{/*
|
|
848
|
+
Content wrapper mirroring upstream ScrollView's inner content div. It
|
|
849
|
+
carries the `pointer-events: none` while-scrolling optimization and is
|
|
850
|
+
otherwise a layout-transparent passthrough (the outer div remains the
|
|
851
|
+
scroll container we measure and read scroll offsets from).
|
|
852
|
+
*/}
|
|
853
|
+
<div
|
|
854
|
+
data-virtualizer-content
|
|
855
|
+
style={{ "pointer-events": isScrolling() ? "none" : undefined }}
|
|
856
|
+
>
|
|
857
|
+
{local.children}
|
|
858
|
+
</div>
|
|
711
859
|
</div>
|
|
712
860
|
</VirtualizerContext.Provider>
|
|
713
861
|
</CollectionRendererContext.Provider>
|
|
@@ -724,6 +872,7 @@ export type {
|
|
|
724
872
|
WaterfallLayoutOptions,
|
|
725
873
|
VirtualizerDropTarget,
|
|
726
874
|
LayoutInfo,
|
|
875
|
+
Orientation,
|
|
727
876
|
Rect,
|
|
728
877
|
Size,
|
|
729
878
|
Point,
|
|
@@ -21,6 +21,13 @@ export interface Size {
|
|
|
21
21
|
height: number;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* The primary orientation of a linear layout — the axis items stack along, which
|
|
26
|
+
* is usually the direction the collection scrolls. Mirrors React Spectrum's
|
|
27
|
+
* `Orientation` and `ListLayout`'s `orientation` option.
|
|
28
|
+
*/
|
|
29
|
+
export type Orientation = "horizontal" | "vertical";
|
|
30
|
+
|
|
24
31
|
export interface LayoutInfo {
|
|
25
32
|
key: string | number;
|
|
26
33
|
index: number;
|
|
@@ -46,6 +53,13 @@ export interface DefaultVirtualizerLayoutOptions {
|
|
|
46
53
|
itemSize?: number;
|
|
47
54
|
overscan?: number;
|
|
48
55
|
viewportSize?: number;
|
|
56
|
+
/**
|
|
57
|
+
* The primary orientation of the items. Items offset along `x`/`width` when
|
|
58
|
+
* `horizontal`, and along `y`/`height` when `vertical`.
|
|
59
|
+
*
|
|
60
|
+
* @default 'vertical'
|
|
61
|
+
*/
|
|
62
|
+
orientation?: Orientation;
|
|
49
63
|
}
|
|
50
64
|
|
|
51
65
|
export interface GridLayoutOptions extends DefaultVirtualizerLayoutOptions {
|
|
@@ -62,6 +76,11 @@ export interface WaterfallLayoutOptions extends GridLayoutOptions {
|
|
|
62
76
|
|
|
63
77
|
export interface VirtualizerLayoutInfoContext {
|
|
64
78
|
viewportWidth: number;
|
|
79
|
+
/**
|
|
80
|
+
* The viewport height, used as the cross-axis size for a `horizontal` layout
|
|
81
|
+
* (the analogue of `viewportWidth` for the `vertical` default).
|
|
82
|
+
*/
|
|
83
|
+
viewportHeight?: number;
|
|
65
84
|
}
|
|
66
85
|
|
|
67
86
|
export interface VirtualizerDropTarget {
|
|
@@ -124,15 +143,29 @@ export class ListLayout {
|
|
|
124
143
|
context: VirtualizerLayoutInfoContext,
|
|
125
144
|
options?: DefaultVirtualizerLayoutOptions,
|
|
126
145
|
): LayoutInfo {
|
|
127
|
-
const
|
|
146
|
+
const itemSize = Math.max(1, options?.itemSize ?? 40);
|
|
147
|
+
if ((options?.orientation ?? "vertical") === "horizontal") {
|
|
148
|
+
// Items stack along the x axis; the cross axis (height) fills the viewport.
|
|
149
|
+
return {
|
|
150
|
+
key: String(index),
|
|
151
|
+
index,
|
|
152
|
+
rect: {
|
|
153
|
+
x: index * itemSize,
|
|
154
|
+
y: 0,
|
|
155
|
+
width: itemSize,
|
|
156
|
+
height: Math.max(0, context.viewportHeight ?? 0),
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// Items stack along the y axis; the cross axis (width) fills the viewport.
|
|
128
161
|
return {
|
|
129
162
|
key: String(index),
|
|
130
163
|
index,
|
|
131
164
|
rect: {
|
|
132
165
|
x: 0,
|
|
133
|
-
y: index *
|
|
166
|
+
y: index * itemSize,
|
|
134
167
|
width: Math.max(0, context.viewportWidth),
|
|
135
|
-
height:
|
|
168
|
+
height: itemSize,
|
|
136
169
|
},
|
|
137
170
|
};
|
|
138
171
|
}
|
|
@@ -143,18 +176,20 @@ export class ListLayout {
|
|
|
143
176
|
options?: DefaultVirtualizerLayoutOptions,
|
|
144
177
|
): VirtualizerDropTarget | null {
|
|
145
178
|
if (itemCount <= 0) return { type: "root", index: -1, position: "on" };
|
|
146
|
-
const
|
|
147
|
-
|
|
179
|
+
const itemSize = Math.max(1, options?.itemSize ?? 40);
|
|
180
|
+
// Measure the drop point along the primary (scroll) axis.
|
|
181
|
+
const offset = (options?.orientation ?? "vertical") === "horizontal" ? point.x : point.y;
|
|
182
|
+
if (offset < 0) {
|
|
148
183
|
return { type: "item", index: 0, position: "before" };
|
|
149
184
|
}
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
185
|
+
const totalSize = itemCount * itemSize;
|
|
186
|
+
if (offset >= totalSize) {
|
|
152
187
|
return { type: "item", index: itemCount - 1, position: "after" };
|
|
153
188
|
}
|
|
154
|
-
const rawIndex = Math.floor(
|
|
189
|
+
const rawIndex = Math.floor(offset / itemSize);
|
|
155
190
|
const index = Math.max(0, Math.min(rawIndex, itemCount - 1));
|
|
156
|
-
const offsetWithinItem = Math.max(0,
|
|
157
|
-
const threshold =
|
|
191
|
+
const offsetWithinItem = Math.max(0, offset - index * itemSize);
|
|
192
|
+
const threshold = itemSize / 3;
|
|
158
193
|
const position: VirtualizerDropTarget["position"] =
|
|
159
194
|
offsetWithinItem < threshold ? "before" : offsetWithinItem > threshold * 2 ? "after" : "on";
|
|
160
195
|
return { type: "item", index, position };
|