@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/Table.tsx
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
createSignal,
|
|
15
15
|
onCleanup,
|
|
16
16
|
splitProps,
|
|
17
|
+
untrack,
|
|
17
18
|
useContext,
|
|
18
19
|
For,
|
|
19
20
|
Show,
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
} from "@proyecto-viviana/solidaria";
|
|
37
38
|
import {
|
|
38
39
|
createTableState,
|
|
40
|
+
createTreeGridState,
|
|
39
41
|
createTableCollection,
|
|
40
42
|
createTableColumnResizeState,
|
|
41
43
|
type TableState,
|
|
@@ -44,9 +46,11 @@ import {
|
|
|
44
46
|
type Key,
|
|
45
47
|
type SortDescriptor,
|
|
46
48
|
type ColumnDefinition,
|
|
49
|
+
type RowDefinition,
|
|
47
50
|
type ColumnSize,
|
|
48
51
|
type GridNode,
|
|
49
52
|
type DropTarget,
|
|
53
|
+
type Collection,
|
|
50
54
|
} from "@proyecto-viviana/solid-stately";
|
|
51
55
|
import {
|
|
52
56
|
type RenderChildren,
|
|
@@ -59,7 +63,7 @@ import {
|
|
|
59
63
|
} from "./utils";
|
|
60
64
|
import { SharedElementTransition } from "./SharedElementTransition";
|
|
61
65
|
import { type DragAndDropHooks } from "./useDragAndDrop";
|
|
62
|
-
import { ButtonContext, type ButtonProps } from "./Button";
|
|
66
|
+
import { ButtonContext, type ButtonContextValue, type ButtonProps } from "./Button";
|
|
63
67
|
import {
|
|
64
68
|
CollectionRendererContext,
|
|
65
69
|
type CollectionRendererContextValue,
|
|
@@ -122,6 +126,35 @@ function normalizeColumnDefinitions<T>(
|
|
|
122
126
|
});
|
|
123
127
|
}
|
|
124
128
|
|
|
129
|
+
/** Resolves a stable, unique key for a tree-grid item (keys must be unique across levels). */
|
|
130
|
+
function resolveItemKey<T>(item: T, getKey: ((item: T) => Key) | undefined, index: number): Key {
|
|
131
|
+
if (getKey) return getKey(item);
|
|
132
|
+
const record = item as { id?: Key; key?: Key };
|
|
133
|
+
return record.id ?? record.key ?? index;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Turns the flat `items` into nested {@link RowDefinition}s by recursively expanding each
|
|
138
|
+
* item's children via `getChildItems`. The result feeds the tree-grid collection.
|
|
139
|
+
*/
|
|
140
|
+
function toTreeRowDefinitions<T>(
|
|
141
|
+
items: Iterable<T>,
|
|
142
|
+
getKey: ((item: T) => Key) | undefined,
|
|
143
|
+
getChildItems: ((item: T) => Iterable<T> | undefined) | undefined,
|
|
144
|
+
): RowDefinition<T>[] {
|
|
145
|
+
return Array.from(items).map((item, index) => {
|
|
146
|
+
const childItems = getChildItems?.(item);
|
|
147
|
+
const childRows = childItems
|
|
148
|
+
? toTreeRowDefinitions(childItems, getKey, getChildItems)
|
|
149
|
+
: undefined;
|
|
150
|
+
return {
|
|
151
|
+
key: resolveItemKey(item, getKey, index),
|
|
152
|
+
value: item,
|
|
153
|
+
childRows: childRows && childRows.length > 0 ? childRows : undefined,
|
|
154
|
+
};
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
125
158
|
function getRowHeaderColumnKeys<T>(columns: (ColumnDefinition<T> & { id?: Key })[]): Set<Key> {
|
|
126
159
|
const keys = new Set<Key>();
|
|
127
160
|
|
|
@@ -192,6 +225,18 @@ export interface TableProps<T extends object> extends Omit<AriaTableProps, "chil
|
|
|
192
225
|
) => JSX.Element;
|
|
193
226
|
/** Drag and drop hooks from `useDragAndDrop`. */
|
|
194
227
|
dragAndDropHooks?: DragAndDropHooks<T>;
|
|
228
|
+
/**
|
|
229
|
+
* Derives the child rows of an item, turning the flat `items` into a tree grid
|
|
230
|
+
* (expandable rows). Providing this — or any `UNSTABLE_*expandedKeys` prop — switches the
|
|
231
|
+
* table into tree-grid mode. Mirrors `@react-aria/table`'s `UNSTABLE_` tree-grid feature.
|
|
232
|
+
*/
|
|
233
|
+
UNSTABLE_childItems?: (item: T) => Iterable<T> | undefined;
|
|
234
|
+
/** The currently expanded row keys (controlled). Tree grid only. */
|
|
235
|
+
UNSTABLE_expandedKeys?: "all" | Iterable<Key>;
|
|
236
|
+
/** The initial expanded row keys (uncontrolled). Tree grid only. */
|
|
237
|
+
UNSTABLE_defaultExpandedKeys?: "all" | Iterable<Key>;
|
|
238
|
+
/** Handler called when rows are expanded or collapsed. Tree grid only. */
|
|
239
|
+
UNSTABLE_onExpandedChange?: (keys: Set<Key>) => void;
|
|
195
240
|
}
|
|
196
241
|
|
|
197
242
|
export interface TableHeaderRenderProps {
|
|
@@ -324,6 +369,21 @@ export interface TableRowRenderProps {
|
|
|
324
369
|
isHovered: boolean;
|
|
325
370
|
/** Whether the row is disabled. */
|
|
326
371
|
isDisabled: boolean;
|
|
372
|
+
/**
|
|
373
|
+
* Whether the row is expanded (tree grid only; `false` for a flat table).
|
|
374
|
+
* @selector [data-expanded]
|
|
375
|
+
*/
|
|
376
|
+
isExpanded: boolean;
|
|
377
|
+
/**
|
|
378
|
+
* Whether the row has child rows (tree grid only; `false` for a flat table).
|
|
379
|
+
* @selector [data-has-child-items]
|
|
380
|
+
*/
|
|
381
|
+
hasChildItems: boolean;
|
|
382
|
+
/**
|
|
383
|
+
* The 1-based nesting depth of the row within the table (1 for a flat table).
|
|
384
|
+
* @selector [data-level]
|
|
385
|
+
*/
|
|
386
|
+
level: number;
|
|
327
387
|
}
|
|
328
388
|
|
|
329
389
|
export interface TableRowProps<T> extends SlotProps {
|
|
@@ -380,6 +440,27 @@ export interface TableCellRenderProps {
|
|
|
380
440
|
isPressed: boolean;
|
|
381
441
|
/** Whether the cell is hovered. */
|
|
382
442
|
isHovered: boolean;
|
|
443
|
+
/**
|
|
444
|
+
* Whether the cell is in the tree column — the one that renders the expand/collapse
|
|
445
|
+
* chevron and nesting indentation (tree grid only; `false` for a flat table).
|
|
446
|
+
* @selector [data-tree-column]
|
|
447
|
+
*/
|
|
448
|
+
isTreeColumn: boolean;
|
|
449
|
+
/**
|
|
450
|
+
* Whether the cell's row is expanded (tree grid only; `false` for a flat table).
|
|
451
|
+
* @selector [data-expanded]
|
|
452
|
+
*/
|
|
453
|
+
isExpanded: boolean;
|
|
454
|
+
/**
|
|
455
|
+
* Whether the cell's row has child rows (tree grid only; `false` for a flat table).
|
|
456
|
+
* @selector [data-has-child-items]
|
|
457
|
+
*/
|
|
458
|
+
hasChildItems: boolean;
|
|
459
|
+
/**
|
|
460
|
+
* The 1-based nesting depth of the cell's row within the table (1 for a flat table).
|
|
461
|
+
* @selector [data-level]
|
|
462
|
+
*/
|
|
463
|
+
level: number;
|
|
383
464
|
}
|
|
384
465
|
|
|
385
466
|
export interface TableCellProps extends SlotProps {
|
|
@@ -443,6 +524,8 @@ export const TableColumnResizeStateContext = createContext<{
|
|
|
443
524
|
interface TableRowContextValue {
|
|
444
525
|
rowKey: Key;
|
|
445
526
|
rowNode: GridNode<unknown>;
|
|
527
|
+
/** The row's resolved disabled state, so a child selection checkbox can gate on it. */
|
|
528
|
+
isRowDisabled: boolean;
|
|
446
529
|
getCellColumnKey(cellId: string, explicitId?: Key): Key | undefined;
|
|
447
530
|
}
|
|
448
531
|
|
|
@@ -472,6 +555,10 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
472
555
|
"sortDescriptor",
|
|
473
556
|
"onSortChange",
|
|
474
557
|
"showSelectionCheckboxes",
|
|
558
|
+
"UNSTABLE_childItems",
|
|
559
|
+
"UNSTABLE_expandedKeys",
|
|
560
|
+
"UNSTABLE_defaultExpandedKeys",
|
|
561
|
+
"UNSTABLE_onExpandedChange",
|
|
475
562
|
],
|
|
476
563
|
);
|
|
477
564
|
|
|
@@ -479,34 +566,71 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
479
566
|
const normalizedColumns = createMemo(() => normalizeColumnDefinitions(stateProps.columns));
|
|
480
567
|
const rowHeaderColumnKeys = createMemo(() => getRowHeaderColumnKeys(normalizedColumns()));
|
|
481
568
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
569
|
+
// Tree-grid mode is selected structurally by the presence of any expansion prop. Like
|
|
570
|
+
// controlled-vs-uncontrolled, this is a one-time decision, not a reactive toggle.
|
|
571
|
+
const isTreeGrid =
|
|
572
|
+
stateProps.UNSTABLE_childItems !== undefined ||
|
|
573
|
+
stateProps.UNSTABLE_expandedKeys !== undefined ||
|
|
574
|
+
stateProps.UNSTABLE_defaultExpandedKeys !== undefined ||
|
|
575
|
+
stateProps.UNSTABLE_onExpandedChange !== undefined;
|
|
576
|
+
|
|
577
|
+
const getTextValue = () =>
|
|
578
|
+
stateProps.getTextValue as ((item: T, column: ColumnDefinition<T>) => string) | undefined;
|
|
579
|
+
|
|
580
|
+
const state: TableState<T, TableCollection<T>> = isTreeGrid
|
|
581
|
+
? createTreeGridState<T, TableCollection<T>>(() => ({
|
|
582
|
+
columns: normalizedColumns(),
|
|
583
|
+
rows: toTreeRowDefinitions(
|
|
584
|
+
stateProps.items,
|
|
585
|
+
stateProps.getKey,
|
|
586
|
+
stateProps.UNSTABLE_childItems,
|
|
587
|
+
),
|
|
588
|
+
getKey: stateProps.getKey,
|
|
589
|
+
getTextValue: getTextValue(),
|
|
590
|
+
showSelectionCheckboxes: stateProps.showSelectionCheckboxes ?? false,
|
|
591
|
+
rowHeaderColumnKeys: rowHeaderColumnKeys().size > 0 ? rowHeaderColumnKeys() : undefined,
|
|
592
|
+
disabledKeys: stateProps.disabledKeys,
|
|
593
|
+
disabledBehavior: stateProps.disabledBehavior,
|
|
594
|
+
selectionMode: stateProps.selectionMode,
|
|
595
|
+
selectionBehavior: stateProps.selectionBehavior,
|
|
596
|
+
selectedKeys: stateProps.selectedKeys,
|
|
597
|
+
defaultSelectedKeys: stateProps.defaultSelectedKeys,
|
|
598
|
+
onSelectionChange: stateProps.onSelectionChange,
|
|
599
|
+
sortDescriptor: stateProps.sortDescriptor,
|
|
600
|
+
onSortChange: stateProps.onSortChange,
|
|
601
|
+
UNSTABLE_expandedKeys: stateProps.UNSTABLE_expandedKeys,
|
|
602
|
+
UNSTABLE_defaultExpandedKeys: stateProps.UNSTABLE_defaultExpandedKeys,
|
|
603
|
+
UNSTABLE_onExpandedChange: stateProps.UNSTABLE_onExpandedChange,
|
|
604
|
+
}))
|
|
605
|
+
: createTableState<T, TableCollection<T>>(() => ({
|
|
606
|
+
collection: createTableCollection<T>({
|
|
607
|
+
columns: normalizedColumns(),
|
|
608
|
+
rows: stateProps.items,
|
|
609
|
+
getKey: stateProps.getKey,
|
|
610
|
+
getTextValue: getTextValue(),
|
|
611
|
+
showSelectionCheckboxes: stateProps.showSelectionCheckboxes ?? false,
|
|
612
|
+
rowHeaderColumnKeys: rowHeaderColumnKeys().size > 0 ? rowHeaderColumnKeys() : undefined,
|
|
613
|
+
}),
|
|
614
|
+
disabledKeys: stateProps.disabledKeys,
|
|
615
|
+
disabledBehavior: stateProps.disabledBehavior,
|
|
616
|
+
selectionMode: stateProps.selectionMode,
|
|
617
|
+
selectionBehavior: stateProps.selectionBehavior,
|
|
618
|
+
selectedKeys: stateProps.selectedKeys,
|
|
619
|
+
defaultSelectedKeys: stateProps.defaultSelectedKeys,
|
|
620
|
+
onSelectionChange: stateProps.onSelectionChange,
|
|
621
|
+
sortDescriptor: stateProps.sortDescriptor,
|
|
622
|
+
onSortChange: stateProps.onSortChange,
|
|
623
|
+
showSelectionCheckboxes: stateProps.showSelectionCheckboxes,
|
|
624
|
+
}));
|
|
625
|
+
const collection = () => state.collection;
|
|
507
626
|
const parentCollectionRenderer = useCollectionRenderer<T>();
|
|
508
627
|
|
|
509
|
-
|
|
628
|
+
// Keep the hook's return object (do NOT destructure `gridProps`): the grid's
|
|
629
|
+
// sort-description `aria-describedby` is emitted via a `createDescription`
|
|
630
|
+
// effect that resolves its id AFTER the first render, so `gridProps` must be
|
|
631
|
+
// read reactively through the getter. Destructuring would freeze the initial
|
|
632
|
+
// (describedby-less) snapshot. Mirrors how columnHeader/row aria is consumed.
|
|
633
|
+
const tableAria = createTable<T>(
|
|
510
634
|
() => ({
|
|
511
635
|
id: ariaProps.id,
|
|
512
636
|
"aria-label": ariaProps["aria-label"],
|
|
@@ -549,7 +673,7 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
549
673
|
});
|
|
550
674
|
|
|
551
675
|
const cleanGridProps = () => {
|
|
552
|
-
const { ref: _ref1, ...rest } = gridProps as Record<string, unknown>;
|
|
676
|
+
const { ref: _ref1, ...rest } = tableAria.gridProps as Record<string, unknown>;
|
|
553
677
|
return rest;
|
|
554
678
|
};
|
|
555
679
|
const cleanFocusProps = () => {
|
|
@@ -641,8 +765,11 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
641
765
|
getKeyPageBelow: (key) => state.collection.getKeyAfter?.(key) ?? null,
|
|
642
766
|
getKeyPageAbove: (key) => state.collection.getKeyBefore?.(key) ?? null,
|
|
643
767
|
},
|
|
768
|
+
// TableCollection carries a wider node.type union (GridNode's 'cell'/
|
|
769
|
+
// 'column') than the narrow Collection option, but is structurally a
|
|
770
|
+
// valid Collection for navigate()/focus restoration — cast at the seam.
|
|
644
771
|
get collection() {
|
|
645
|
-
return state.collection;
|
|
772
|
+
return state.collection as unknown as Collection;
|
|
646
773
|
},
|
|
647
774
|
get selectedKeys() {
|
|
648
775
|
return state.selectedKeys;
|
|
@@ -707,8 +834,16 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
707
834
|
dndDropIndicator(index, position) ??
|
|
708
835
|
parentCollectionRenderer?.renderDropIndicator?.(index, position),
|
|
709
836
|
}));
|
|
837
|
+
// The root children function builds the structural `<TableHeader>`/`<TableBody>`
|
|
838
|
+
// subtree once. React re-invokes it on every render and reconciles the result, so
|
|
839
|
+
// reading focus-dependent render values (isFocused/isFocusVisible) there is cheap.
|
|
840
|
+
// Solid has no reconciliation: re-invoking recreates the entire thead/tbody subtree,
|
|
841
|
+
// which detaches the DOM-focused row and drops keyboard focus (Space/Enter never reach
|
|
842
|
+
// the row). So invoke it with an untracked snapshot of the render values — the insert
|
|
843
|
+
// below stays stable across focus changes while children still see current values at
|
|
844
|
+
// creation. Render values for collection structure are not reactive in practice.
|
|
710
845
|
const tableChildren = () =>
|
|
711
|
-
typeof props.children === "function" ? props.children(renderValues
|
|
846
|
+
typeof props.children === "function" ? props.children(untrack(renderValues)) : props.children;
|
|
712
847
|
const tableProps = () =>
|
|
713
848
|
({
|
|
714
849
|
ref: (el: HTMLTableElement) => {
|
|
@@ -728,7 +863,6 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
728
863
|
"data-empty": stateProps.items.length === 0 || undefined,
|
|
729
864
|
"data-drop-target": isRootDropTarget() || undefined,
|
|
730
865
|
slot: local.slot,
|
|
731
|
-
children: tableChildren(),
|
|
732
866
|
}) as JSX.HTMLAttributes<HTMLTableElement>;
|
|
733
867
|
|
|
734
868
|
return (
|
|
@@ -737,7 +871,11 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
737
871
|
value={state as unknown as TableState<object, TableCollection<object>>}
|
|
738
872
|
>
|
|
739
873
|
<CollectionRendererContext.Provider value={collectionRenderer()}>
|
|
740
|
-
{local.render ?
|
|
874
|
+
{local.render ? (
|
|
875
|
+
local.render({ ...tableProps(), children: tableChildren() }, renderValues())
|
|
876
|
+
) : (
|
|
877
|
+
<table {...tableProps()}>{tableChildren()}</table>
|
|
878
|
+
)}
|
|
741
879
|
</CollectionRendererContext.Provider>
|
|
742
880
|
</TableStateContext.Provider>
|
|
743
881
|
</TableContext.Provider>
|
|
@@ -1071,6 +1209,8 @@ export function TableBody<T extends object>(props: TableBodyProps<T>): JSX.Eleme
|
|
|
1071
1209
|
context.collection,
|
|
1072
1210
|
);
|
|
1073
1211
|
const virtualRange = createMemo(() => {
|
|
1212
|
+
// Tree grids render every visible (flattened) row; virtual windowing is a follow-up.
|
|
1213
|
+
if (context.state.treeColumn != null) return null;
|
|
1074
1214
|
if (!virtualizer || !parentCollectionRenderer?.isVirtualized) return null;
|
|
1075
1215
|
const rowCount = items().length;
|
|
1076
1216
|
const baseRange = virtualizer.getVisibleRange(rowCount);
|
|
@@ -1125,6 +1265,11 @@ export function TableBody<T extends object>(props: TableBodyProps<T>): JSX.Eleme
|
|
|
1125
1265
|
});
|
|
1126
1266
|
});
|
|
1127
1267
|
const visibleItems = createMemo(() => {
|
|
1268
|
+
// Tree grid: render the flattened set of visible rows (top-level + expanded descendants)
|
|
1269
|
+
// the collection materialises in document order, so the render fn runs once per visible row.
|
|
1270
|
+
if (context.state.treeColumn != null) {
|
|
1271
|
+
return rowNodes().map((node) => node.value as T);
|
|
1272
|
+
}
|
|
1128
1273
|
const range = virtualRange();
|
|
1129
1274
|
if (!range) return items();
|
|
1130
1275
|
return items().slice(range.start, range.end);
|
|
@@ -1435,7 +1580,7 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1435
1580
|
if (!context) {
|
|
1436
1581
|
throw new Error("TableRow must be used within a Table");
|
|
1437
1582
|
}
|
|
1438
|
-
const { state
|
|
1583
|
+
const { state } = context;
|
|
1439
1584
|
const tableContext = context as unknown as TableContextValue<T>;
|
|
1440
1585
|
const registeredCellIds: string[] = [];
|
|
1441
1586
|
const generatedId = createUniqueId();
|
|
@@ -1454,8 +1599,10 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1454
1599
|
|
|
1455
1600
|
const [ref, setRef] = createSignal<HTMLTableRowElement | null>(null);
|
|
1456
1601
|
|
|
1602
|
+
// Read through `state.collection` (not the destructured snapshot) so the node tracks
|
|
1603
|
+
// collection rebuilds — e.g. a tree-grid row staying mounted across an expand/collapse.
|
|
1457
1604
|
const rowNode = createMemo(() => {
|
|
1458
|
-
const node = collection.getItem(rowKey());
|
|
1605
|
+
const node = state.collection.getItem(rowKey());
|
|
1459
1606
|
if (!node) {
|
|
1460
1607
|
return {
|
|
1461
1608
|
type: "item" as const,
|
|
@@ -1492,7 +1639,12 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1492
1639
|
const isPressed = () => rowAria.isPressed;
|
|
1493
1640
|
const isInteractive = () => {
|
|
1494
1641
|
const tableData = getTableData(state as TableState<object, TableCollection<object>>);
|
|
1495
|
-
return
|
|
1642
|
+
return (
|
|
1643
|
+
state.selectionMode !== "none" ||
|
|
1644
|
+
!!tableData?.actions.onRowAction ||
|
|
1645
|
+
!!local.onAction ||
|
|
1646
|
+
!!local.href
|
|
1647
|
+
);
|
|
1496
1648
|
};
|
|
1497
1649
|
|
|
1498
1650
|
const { isHovered, hoverProps } = createHover({
|
|
@@ -1549,6 +1701,13 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1549
1701
|
);
|
|
1550
1702
|
});
|
|
1551
1703
|
|
|
1704
|
+
// Tree-grid (expandable rows): nesting depth, child presence and expansion. These are
|
|
1705
|
+
// inert for a flat table (level 1, no children, not expanded).
|
|
1706
|
+
const isTreeRow = () => state.treeColumn != null;
|
|
1707
|
+
const rowLevel = () => rowNode().level + 1;
|
|
1708
|
+
const hasChildItems = () => rowAria.hasChildRows;
|
|
1709
|
+
const isExpanded = () => rowAria.isExpanded;
|
|
1710
|
+
|
|
1552
1711
|
const renderValues = createMemo<TableRowRenderProps>(() => ({
|
|
1553
1712
|
isSelected: isSelected(),
|
|
1554
1713
|
isFocused: isFocused(),
|
|
@@ -1556,6 +1715,9 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1556
1715
|
isPressed: isPressed(),
|
|
1557
1716
|
isHovered: isHovered(),
|
|
1558
1717
|
isDisabled: isDisabled(),
|
|
1718
|
+
isExpanded: isExpanded(),
|
|
1719
|
+
hasChildItems: hasChildItems(),
|
|
1720
|
+
level: rowLevel(),
|
|
1559
1721
|
}));
|
|
1560
1722
|
|
|
1561
1723
|
// Resolve render props (children rendered directly in JSX to avoid eager evaluation)
|
|
@@ -1584,6 +1746,9 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1584
1746
|
const rowContextValue: TableRowContextValue = {
|
|
1585
1747
|
rowKey: rowKey(),
|
|
1586
1748
|
rowNode: rowNode(),
|
|
1749
|
+
get isRowDisabled() {
|
|
1750
|
+
return isDisabled();
|
|
1751
|
+
},
|
|
1587
1752
|
getCellColumnKey(cellId, explicitId) {
|
|
1588
1753
|
if (explicitId === "__selection__") {
|
|
1589
1754
|
return explicitId;
|
|
@@ -1610,73 +1775,197 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1610
1775
|
},
|
|
1611
1776
|
};
|
|
1612
1777
|
});
|
|
1613
|
-
|
|
1778
|
+
// A STABLE context object: its identity never changes, so the surrounding ButtonContext.Provider
|
|
1779
|
+
// never tears down and recreates the row's children. The slots are getters, so a slotted
|
|
1780
|
+
// <Button slot="drag"|"chevron"> reads the current drag/expand props each time it is (re)created —
|
|
1781
|
+
// e.g. when the tree column recreates the chevron on expand/collapse.
|
|
1782
|
+
const buttonContextValue: ButtonContextValue = {
|
|
1614
1783
|
slots: {
|
|
1615
1784
|
default: {},
|
|
1616
|
-
drag
|
|
1785
|
+
get drag() {
|
|
1786
|
+
return dragButtonProps();
|
|
1787
|
+
},
|
|
1788
|
+
// Tree-grid expand/collapse chevron; the slotted <Button slot="chevron"> picks these up.
|
|
1789
|
+
// The aria hook yields DOM button attributes, merged onto the Button as passthrough props.
|
|
1790
|
+
get chevron() {
|
|
1791
|
+
return rowAria.expandButtonProps as unknown as ButtonProps;
|
|
1792
|
+
},
|
|
1617
1793
|
},
|
|
1618
|
-
}
|
|
1794
|
+
};
|
|
1619
1795
|
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
)
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
"data-hovered": isHovered() || undefined,
|
|
1660
|
-
"data-disabled": isDisabled() || undefined,
|
|
1661
|
-
"data-href": linkProps().href,
|
|
1662
|
-
"data-target": linkProps().target,
|
|
1663
|
-
"data-rel": linkProps().rel,
|
|
1664
|
-
"data-download":
|
|
1665
|
-
typeof linkProps().download === "string"
|
|
1666
|
-
? linkProps().download
|
|
1667
|
-
: linkProps().download
|
|
1668
|
-
? ""
|
|
1669
|
-
: undefined,
|
|
1670
|
-
"data-ping": linkProps().ping,
|
|
1671
|
-
"data-referrer-policy": linkProps().referrerPolicy,
|
|
1672
|
-
"data-dragging": draggableItem()?.isDragging || undefined,
|
|
1673
|
-
"data-drop-target": droppableItem()?.isDropTarget || undefined,
|
|
1674
|
-
children: rowChildren(),
|
|
1675
|
-
}) as JSX.HTMLAttributes<HTMLTableRowElement>;
|
|
1796
|
+
// Render props handed to the row's children as a STABLE getter proxy: reading a getter stays
|
|
1797
|
+
// fine-grained reactive at the point of use, without forcing the children to be re-derived (and
|
|
1798
|
+
// therefore disposed + recreated) whenever an unrelated render prop flips.
|
|
1799
|
+
const childRenderProps: TableRowRenderProps = {
|
|
1800
|
+
get isSelected() {
|
|
1801
|
+
return isSelected();
|
|
1802
|
+
},
|
|
1803
|
+
get isFocused() {
|
|
1804
|
+
return isFocused();
|
|
1805
|
+
},
|
|
1806
|
+
get isFocusVisible() {
|
|
1807
|
+
return isFocusVisible() && isFocused();
|
|
1808
|
+
},
|
|
1809
|
+
get isPressed() {
|
|
1810
|
+
return isPressed();
|
|
1811
|
+
},
|
|
1812
|
+
get isHovered() {
|
|
1813
|
+
return isHovered();
|
|
1814
|
+
},
|
|
1815
|
+
get isDisabled() {
|
|
1816
|
+
return isDisabled();
|
|
1817
|
+
},
|
|
1818
|
+
get isExpanded() {
|
|
1819
|
+
return isExpanded();
|
|
1820
|
+
},
|
|
1821
|
+
get hasChildItems() {
|
|
1822
|
+
return hasChildItems();
|
|
1823
|
+
},
|
|
1824
|
+
get level() {
|
|
1825
|
+
return rowLevel();
|
|
1826
|
+
},
|
|
1827
|
+
};
|
|
1828
|
+
|
|
1829
|
+
// Tree-grid rows carry their nesting depth as a CSS var so the tree column can indent.
|
|
1830
|
+
const rowStyle = () => {
|
|
1831
|
+
const base = renderProps.style();
|
|
1832
|
+
if (!isTreeRow()) return base;
|
|
1833
|
+
return { ...(base ?? {}), "--table-row-level": rowLevel() } as JSX.CSSProperties;
|
|
1834
|
+
};
|
|
1676
1835
|
|
|
1677
1836
|
return (
|
|
1678
1837
|
<TableRowContext.Provider value={rowContextValue}>
|
|
1679
|
-
|
|
1838
|
+
<ButtonContext.Provider value={buttonContextValue}>
|
|
1839
|
+
{(() => {
|
|
1840
|
+
// Build the row's children HERE — inside BOTH providers — so each cell instantiates under
|
|
1841
|
+
// this owner. TableCell/EditableCell read TableRowContext, and a slotted
|
|
1842
|
+
// <Button slot="drag"|"chevron"> reads ButtonContext; in Solid useContext binds at the
|
|
1843
|
+
// owner active when the component executes, so the children must be created inside the
|
|
1844
|
+
// providers, not merely wrapped by them afterwards. They are built EXACTLY ONCE: a press
|
|
1845
|
+
// or focus bubbling up from interactive cell content (e.g. an EditableCell's edit button)
|
|
1846
|
+
// flips the row's render-props signals, and re-deriving the children on every such change
|
|
1847
|
+
// would dispose and recreate the subtree, destroying the in-flight press. Cells claim
|
|
1848
|
+
// their column by render order (see getCellColumnKey), so reset the registry once before
|
|
1849
|
+
// this single pass.
|
|
1850
|
+
registeredCellIds.length = 0;
|
|
1851
|
+
const rowChildrenContent =
|
|
1852
|
+
typeof local.children === "function" ? (
|
|
1853
|
+
local.columns ? (
|
|
1854
|
+
<For each={local.columns}>
|
|
1855
|
+
{(column) =>
|
|
1856
|
+
(local.children as (column: TableColumnDefinition<T>) => JSX.Element)(column)
|
|
1857
|
+
}
|
|
1858
|
+
</For>
|
|
1859
|
+
) : (
|
|
1860
|
+
(local.children as (renderProps: TableRowRenderProps) => JSX.Element)(
|
|
1861
|
+
childRenderProps,
|
|
1862
|
+
)
|
|
1863
|
+
)
|
|
1864
|
+
) : (
|
|
1865
|
+
local.children
|
|
1866
|
+
);
|
|
1867
|
+
const tableRowProps = () =>
|
|
1868
|
+
({
|
|
1869
|
+
ref: (el: HTMLTableRowElement) => {
|
|
1870
|
+
setRef(el);
|
|
1871
|
+
assignRef(local.ref, el);
|
|
1872
|
+
},
|
|
1873
|
+
...domProps,
|
|
1874
|
+
...mergeProps(
|
|
1875
|
+
cleanRowProps(),
|
|
1876
|
+
cleanHoverProps(),
|
|
1877
|
+
cleanFocusProps(),
|
|
1878
|
+
focusWithinProps as Record<string, unknown>,
|
|
1879
|
+
(draggableItem()?.dragProps as Record<string, unknown> | undefined) ?? {},
|
|
1880
|
+
(droppableItem()?.dropProps as Record<string, unknown> | undefined) ?? {},
|
|
1881
|
+
),
|
|
1882
|
+
class: renderProps.class(),
|
|
1883
|
+
style: rowStyle(),
|
|
1884
|
+
"data-key": rowKey(),
|
|
1885
|
+
"data-selected": isSelected() || undefined,
|
|
1886
|
+
"data-focused": isFocused() || undefined,
|
|
1887
|
+
"data-focus-visible": (isFocusVisible() && isFocused()) || undefined,
|
|
1888
|
+
"data-focus-visible-within": dataAttr(isFocusWithin() && isGlobalFocusVisible()),
|
|
1889
|
+
"data-pressed": isPressed() || undefined,
|
|
1890
|
+
"data-hovered": isHovered() || undefined,
|
|
1891
|
+
"data-disabled": isDisabled() || undefined,
|
|
1892
|
+
"data-href": linkProps().href,
|
|
1893
|
+
"data-target": linkProps().target,
|
|
1894
|
+
"data-rel": linkProps().rel,
|
|
1895
|
+
"data-download":
|
|
1896
|
+
typeof linkProps().download === "string"
|
|
1897
|
+
? linkProps().download
|
|
1898
|
+
: linkProps().download
|
|
1899
|
+
? ""
|
|
1900
|
+
: undefined,
|
|
1901
|
+
"data-ping": linkProps().ping,
|
|
1902
|
+
"data-referrer-policy": linkProps().referrerPolicy,
|
|
1903
|
+
"data-dragging": draggableItem()?.isDragging || undefined,
|
|
1904
|
+
"data-drop-target": droppableItem()?.isDropTarget || undefined,
|
|
1905
|
+
"data-expanded": (isTreeRow() && isExpanded()) || undefined,
|
|
1906
|
+
"data-has-child-items": (isTreeRow() && hasChildItems()) || undefined,
|
|
1907
|
+
"data-level": isTreeRow() ? rowLevel() : undefined,
|
|
1908
|
+
children: rowChildrenContent,
|
|
1909
|
+
}) as JSX.HTMLAttributes<HTMLTableRowElement>;
|
|
1910
|
+
|
|
1911
|
+
return (
|
|
1912
|
+
<Show
|
|
1913
|
+
when={local.render}
|
|
1914
|
+
fallback={
|
|
1915
|
+
// Bind attributes individually on a STABLE <tr> (mirroring TableCell) so a
|
|
1916
|
+
// render-props change updates attributes in place instead of recreating the element
|
|
1917
|
+
// and its subtree.
|
|
1918
|
+
<tr
|
|
1919
|
+
ref={(el: HTMLTableRowElement) => {
|
|
1920
|
+
setRef(el);
|
|
1921
|
+
assignRef(local.ref, el);
|
|
1922
|
+
}}
|
|
1923
|
+
{...domProps}
|
|
1924
|
+
{...mergeProps(
|
|
1925
|
+
cleanRowProps(),
|
|
1926
|
+
cleanHoverProps(),
|
|
1927
|
+
cleanFocusProps(),
|
|
1928
|
+
focusWithinProps as Record<string, unknown>,
|
|
1929
|
+
(draggableItem()?.dragProps as Record<string, unknown> | undefined) ?? {},
|
|
1930
|
+
(droppableItem()?.dropProps as Record<string, unknown> | undefined) ?? {},
|
|
1931
|
+
)}
|
|
1932
|
+
class={renderProps.class()}
|
|
1933
|
+
style={rowStyle()}
|
|
1934
|
+
data-key={rowKey()}
|
|
1935
|
+
data-selected={isSelected() || undefined}
|
|
1936
|
+
data-focused={isFocused() || undefined}
|
|
1937
|
+
data-focus-visible={(isFocusVisible() && isFocused()) || undefined}
|
|
1938
|
+
data-focus-visible-within={dataAttr(isFocusWithin() && isGlobalFocusVisible())}
|
|
1939
|
+
data-pressed={isPressed() || undefined}
|
|
1940
|
+
data-hovered={isHovered() || undefined}
|
|
1941
|
+
data-disabled={isDisabled() || undefined}
|
|
1942
|
+
data-href={linkProps().href}
|
|
1943
|
+
data-target={linkProps().target}
|
|
1944
|
+
data-rel={linkProps().rel}
|
|
1945
|
+
data-download={
|
|
1946
|
+
typeof linkProps().download === "string"
|
|
1947
|
+
? linkProps().download
|
|
1948
|
+
: linkProps().download
|
|
1949
|
+
? ""
|
|
1950
|
+
: undefined
|
|
1951
|
+
}
|
|
1952
|
+
data-ping={linkProps().ping}
|
|
1953
|
+
data-referrer-policy={linkProps().referrerPolicy}
|
|
1954
|
+
data-dragging={draggableItem()?.isDragging || undefined}
|
|
1955
|
+
data-drop-target={droppableItem()?.isDropTarget || undefined}
|
|
1956
|
+
data-expanded={(isTreeRow() && isExpanded()) || undefined}
|
|
1957
|
+
data-has-child-items={(isTreeRow() && hasChildItems()) || undefined}
|
|
1958
|
+
data-level={isTreeRow() ? rowLevel() : undefined}
|
|
1959
|
+
>
|
|
1960
|
+
{rowChildrenContent}
|
|
1961
|
+
</tr>
|
|
1962
|
+
}
|
|
1963
|
+
>
|
|
1964
|
+
{local.render!(tableRowProps(), renderValues())}
|
|
1965
|
+
</Show>
|
|
1966
|
+
);
|
|
1967
|
+
})()}
|
|
1968
|
+
</ButtonContext.Provider>
|
|
1680
1969
|
</TableRowContext.Provider>
|
|
1681
1970
|
);
|
|
1682
1971
|
}
|
|
@@ -1706,7 +1995,7 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1706
1995
|
throw new Error("TableCell must be used within a Table");
|
|
1707
1996
|
}
|
|
1708
1997
|
|
|
1709
|
-
const { state
|
|
1998
|
+
const { state } = tableContext;
|
|
1710
1999
|
const { rowKey, rowNode } = rowContext;
|
|
1711
2000
|
|
|
1712
2001
|
const [ref, setRef] = createSignal<HTMLTableCellElement | null>(null);
|
|
@@ -1717,7 +2006,7 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1717
2006
|
const key = columnKey();
|
|
1718
2007
|
if (key != null) {
|
|
1719
2008
|
const cellKey = `${rowKey}-${key}`;
|
|
1720
|
-
const node = collection.getItem(cellKey);
|
|
2009
|
+
const node = state.collection.getItem(cellKey);
|
|
1721
2010
|
if (node) return node;
|
|
1722
2011
|
}
|
|
1723
2012
|
|
|
@@ -1737,9 +2026,21 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1737
2026
|
const key = columnKey();
|
|
1738
2027
|
if (key == null) return undefined;
|
|
1739
2028
|
const cellKey = `${rowKey}-${key}`;
|
|
1740
|
-
return collection.getItem(cellKey) ? (cellNode().index ?? 0) : undefined;
|
|
2029
|
+
return state.collection.getItem(cellKey) ? (cellNode().index ?? 0) : undefined;
|
|
1741
2030
|
});
|
|
1742
2031
|
|
|
2032
|
+
// Tree-grid (expandable rows): the cell mirrors its row's nesting/expansion and flags the
|
|
2033
|
+
// tree column (the one that renders the chevron + indentation). Inert for a flat table.
|
|
2034
|
+
const isTreeGridCell = () => state.treeColumn != null;
|
|
2035
|
+
const parentRowNode = createMemo(() => state.collection.getItem(rowKey));
|
|
2036
|
+
const cellLevel = () => (parentRowNode()?.level ?? rowNode.level ?? 0) + 1;
|
|
2037
|
+
const cellHasChildItems = () => parentRowNode()?.isExpandable ?? false;
|
|
2038
|
+
const cellIsExpanded = () => {
|
|
2039
|
+
if (!isTreeGridCell() || !cellHasChildItems()) return false;
|
|
2040
|
+
return state.expandedKeys === "all" || state.expandedKeys.has(rowKey);
|
|
2041
|
+
};
|
|
2042
|
+
const isTreeColumn = () => isTreeGridCell() && columnKey() === state.treeColumn;
|
|
2043
|
+
|
|
1743
2044
|
const cellAria = createTableCell<object>(
|
|
1744
2045
|
() => ({
|
|
1745
2046
|
node: cellNode(),
|
|
@@ -1763,6 +2064,10 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1763
2064
|
columnIndex: cellColumnIndex() ?? 0,
|
|
1764
2065
|
isPressed: isPressed(),
|
|
1765
2066
|
isHovered: isHovered(),
|
|
2067
|
+
isTreeColumn: isTreeColumn(),
|
|
2068
|
+
isExpanded: cellIsExpanded(),
|
|
2069
|
+
hasChildItems: cellHasChildItems(),
|
|
2070
|
+
level: cellLevel(),
|
|
1766
2071
|
}));
|
|
1767
2072
|
|
|
1768
2073
|
// Resolve render props (children rendered directly in JSX to avoid eager evaluation)
|
|
@@ -1801,11 +2106,16 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1801
2106
|
colSpan: local.colSpan,
|
|
1802
2107
|
class: renderProps.class(),
|
|
1803
2108
|
style: renderProps.style(),
|
|
2109
|
+
"data-key": cellNode().key,
|
|
1804
2110
|
"data-focused": isFocused() || undefined,
|
|
1805
2111
|
"data-focus-visible": (isFocusVisible() && isFocused()) || undefined,
|
|
1806
2112
|
"data-column-index": cellColumnIndex(),
|
|
1807
2113
|
"data-pressed": isPressed() || undefined,
|
|
1808
2114
|
"data-hovered": isHovered() || undefined,
|
|
2115
|
+
"data-tree-column": isTreeColumn() || undefined,
|
|
2116
|
+
"data-expanded": (isTreeGridCell() && cellIsExpanded()) || undefined,
|
|
2117
|
+
"data-has-child-items": (isTreeGridCell() && cellHasChildItems()) || undefined,
|
|
2118
|
+
"data-level": isTreeGridCell() ? cellLevel() : undefined,
|
|
1809
2119
|
children: cellChildren(),
|
|
1810
2120
|
}) as JSX.TdHTMLAttributes<HTMLTableCellElement>;
|
|
1811
2121
|
|
|
@@ -1822,11 +2132,16 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1822
2132
|
colSpan={local.colSpan}
|
|
1823
2133
|
class={renderProps.class()}
|
|
1824
2134
|
style={renderProps.style()}
|
|
2135
|
+
data-key={cellNode().key}
|
|
1825
2136
|
data-focused={isFocused() || undefined}
|
|
1826
2137
|
data-focus-visible={(isFocusVisible() && isFocused()) || undefined}
|
|
1827
2138
|
data-column-index={cellColumnIndex()}
|
|
1828
2139
|
data-pressed={isPressed() || undefined}
|
|
1829
2140
|
data-hovered={isHovered() || undefined}
|
|
2141
|
+
data-tree-column={isTreeColumn() || undefined}
|
|
2142
|
+
data-expanded={(isTreeGridCell() && cellIsExpanded()) || undefined}
|
|
2143
|
+
data-has-child-items={(isTreeGridCell() && cellHasChildItems()) || undefined}
|
|
2144
|
+
data-level={isTreeGridCell() ? cellLevel() : undefined}
|
|
1830
2145
|
>
|
|
1831
2146
|
{cellChildren()}
|
|
1832
2147
|
</td>
|
|
@@ -1851,9 +2166,10 @@ export function TableSelectionCheckbox(props: TableSelectionCheckboxProps): JSX.
|
|
|
1851
2166
|
}
|
|
1852
2167
|
|
|
1853
2168
|
const { state } = context;
|
|
2169
|
+
const rowContext = useContext(TableRowContext);
|
|
1854
2170
|
|
|
1855
2171
|
const selectionCheckboxAria = createTableSelectionCheckbox<object>(
|
|
1856
|
-
() => ({ key: props.rowKey }),
|
|
2172
|
+
() => ({ key: props.rowKey, isRowDisabled: rowContext?.isRowDisabled }),
|
|
1857
2173
|
() => state as TableState<object, TableCollection<object>>,
|
|
1858
2174
|
);
|
|
1859
2175
|
|
|
@@ -1864,6 +2180,11 @@ export function TableSelectionCheckbox(props: TableSelectionCheckboxProps): JSX.
|
|
|
1864
2180
|
style={props.style}
|
|
1865
2181
|
tabIndex={props.excludeFromTabOrder ? -1 : selectionCheckboxAria.checkboxProps.tabIndex}
|
|
1866
2182
|
aria-label={props["aria-label"] ?? selectionCheckboxAria.checkboxProps["aria-label"]}
|
|
2183
|
+
onClick={(event) => event.stopPropagation()}
|
|
2184
|
+
onKeyDown={(event) => event.stopPropagation()}
|
|
2185
|
+
onKeyUp={(event) => event.stopPropagation()}
|
|
2186
|
+
onPointerDown={(event) => event.stopPropagation()}
|
|
2187
|
+
onPointerUp={(event) => event.stopPropagation()}
|
|
1867
2188
|
/>
|
|
1868
2189
|
);
|
|
1869
2190
|
}
|
|
@@ -1889,8 +2210,16 @@ export function TableSelectAllCheckbox(props: TableSelectAllCheckboxProps = {}):
|
|
|
1889
2210
|
() => state as TableState<object, TableCollection<object>>,
|
|
1890
2211
|
);
|
|
1891
2212
|
|
|
2213
|
+
let inputRef: HTMLInputElement | undefined;
|
|
2214
|
+
createEffect(() => {
|
|
2215
|
+
if (inputRef) {
|
|
2216
|
+
inputRef.indeterminate = selectAllCheckboxAria.isIndeterminate;
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
|
|
1892
2220
|
return (
|
|
1893
2221
|
<input
|
|
2222
|
+
ref={inputRef}
|
|
1894
2223
|
{...selectAllCheckboxAria.checkboxProps}
|
|
1895
2224
|
class={props.class}
|
|
1896
2225
|
style={props.style}
|