@proyecto-viviana/solidaria-components 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ActionBar.js +184 -0
- package/dist/ActionBar.js.map +1 -0
- package/dist/ActionBar.jsx +128 -0
- package/dist/ActionBar.jsx.map +1 -0
- 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.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 +334 -0
- package/dist/Breadcrumbs.js.map +1 -0
- package/dist/Breadcrumbs.jsx +266 -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 +538 -0
- package/dist/Calendar.js.map +1 -0
- package/dist/Calendar.jsx +333 -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 +1720 -0
- package/dist/Color.js.map +1 -0
- package/dist/Color.jsx +1344 -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 -5
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ComboBox.js +992 -0
- package/dist/ComboBox.js.map +1 -0
- package/dist/ComboBox.jsx +714 -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 +3 -3
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DateField.js +4 -0
- package/dist/DateField.jsx +4 -0
- package/dist/DateField2.js +499 -0
- package/dist/DateField2.js.map +1 -0
- package/dist/DateField2.jsx +317 -0
- package/dist/DateField2.jsx.map +1 -0
- package/dist/DatePicker.d.ts +4 -4
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DatePicker.js +991 -0
- package/dist/DatePicker.js.map +1 -0
- package/dist/DatePicker.jsx +682 -0
- package/dist/DatePicker.jsx.map +1 -0
- 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 +328 -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/HiddenTimeInput.js +104 -0
- package/dist/HiddenTimeInput.js.map +1 -0
- package/dist/HiddenTimeInput.jsx +69 -0
- package/dist/HiddenTimeInput.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.map +1 -1
- package/dist/ListBox.js +670 -0
- package/dist/ListBox.js.map +1 -0
- package/dist/ListBox.jsx +508 -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 +380 -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 +464 -0
- package/dist/Popover.js.map +1 -0
- package/dist/Popover.jsx +333 -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 +410 -0
- package/dist/RangeCalendar.js.map +1 -0
- package/dist/RangeCalendar.jsx +253 -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 +643 -0
- package/dist/SearchField.js.map +1 -0
- package/dist/SearchField.jsx +526 -0
- package/dist/SearchField.jsx.map +1 -0
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +1031 -0
- package/dist/Select.js.map +1 -0
- package/dist/Select.jsx +744 -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 +165 -0
- package/dist/SharedElementTransition.js.map +1 -0
- package/dist/SharedElementTransition.jsx +138 -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.js +198 -0
- package/dist/StepList.js.map +1 -0
- package/dist/StepList.jsx +141 -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 +48 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +1759 -0
- package/dist/Table.js.map +1 -0
- package/dist/Table.jsx +1348 -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 +595 -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.map +1 -1
- package/dist/TagGroup.js +378 -0
- package/dist/TagGroup.js.map +1 -0
- package/dist/TagGroup.jsx +270 -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 +7 -6
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TextField.js +436 -0
- package/dist/TextField.js.map +1 -0
- package/dist/TextField.jsx +403 -0
- package/dist/TextField.jsx.map +1 -0
- package/dist/TimeField.d.ts +3 -3
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/TimeField.js +372 -0
- package/dist/TimeField.js.map +1 -0
- package/dist/TimeField.jsx +224 -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 +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -23711
- package/dist/index.jsx +70 -18116
- package/dist/useDragAndDrop.js +2 -0
- package/dist/useDragAndDrop.jsx +2 -0
- package/dist/useDragAndDrop2.js +395 -0
- package/dist/useDragAndDrop2.js.map +1 -0
- package/dist/useDragAndDrop2.jsx +395 -0
- package/dist/useDragAndDrop2.jsx.map +1 -0
- package/dist/utils.d.ts +83 -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 +401 -4
- package/src/Breadcrumbs.tsx +3 -1
- package/src/Button.tsx +90 -23
- package/src/Calendar.tsx +27 -10
- package/src/CalendarPicker.tsx +73 -0
- package/src/Checkbox.tsx +539 -3
- package/src/Collection.tsx +9 -3
- package/src/Color.tsx +42 -14
- package/src/ComboBox.tsx +126 -14
- package/src/DateField.tsx +20 -2
- package/src/DatePicker.tsx +117 -10
- package/src/Dialog.tsx +13 -5
- package/src/Disclosure.tsx +3 -1
- package/src/DragAndDrop.tsx +3 -1
- package/src/DropZone.tsx +3 -1
- package/src/GridList.tsx +125 -24
- package/src/Icon.tsx +3 -1
- package/src/Link.tsx +3 -1
- package/src/ListBox.tsx +31 -4
- package/src/Menu.tsx +298 -131
- package/src/Meter.tsx +3 -1
- package/src/Modal.tsx +100 -52
- package/src/NumberField.tsx +73 -10
- package/src/Popover.tsx +49 -11
- package/src/ProgressBar.tsx +3 -1
- package/src/RadioGroup.tsx +468 -4
- package/src/RangeCalendar.tsx +3 -1
- package/src/SearchField.tsx +27 -3
- package/src/Select.tsx +22 -7
- package/src/SelectionIndicator.tsx +3 -1
- package/src/SharedElementTransition.tsx +3 -1
- package/src/Slider.tsx +159 -13
- package/src/Switch.tsx +395 -2
- package/src/Table.tsx +409 -95
- package/src/Tabs.tsx +16 -45
- package/src/TagGroup.tsx +4 -1
- package/src/Text.tsx +31 -10
- package/src/TextField.tsx +73 -10
- package/src/TimeField.tsx +20 -2
- package/src/Toast.tsx +79 -14
- package/src/ToggleButton.tsx +3 -1
- package/src/ToggleButtonGroup.tsx +3 -1
- package/src/Tooltip.tsx +55 -8
- package/src/Tree.tsx +77 -9
- package/src/Virtualizer.tsx +180 -31
- package/src/VirtualizerLayouts.ts +45 -10
- package/src/index.ts +50 -0
- package/src/utils.tsx +243 -27
- package/dist/index.js.map +0 -1
- package/dist/index.jsx.map +0 -1
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,6 +46,7 @@ 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,
|
|
@@ -59,7 +62,7 @@ import {
|
|
|
59
62
|
} from "./utils";
|
|
60
63
|
import { SharedElementTransition } from "./SharedElementTransition";
|
|
61
64
|
import { type DragAndDropHooks } from "./useDragAndDrop";
|
|
62
|
-
import { ButtonContext, type ButtonProps } from "./Button";
|
|
65
|
+
import { ButtonContext, type ButtonContextValue, type ButtonProps } from "./Button";
|
|
63
66
|
import {
|
|
64
67
|
CollectionRendererContext,
|
|
65
68
|
type CollectionRendererContextValue,
|
|
@@ -122,6 +125,35 @@ function normalizeColumnDefinitions<T>(
|
|
|
122
125
|
});
|
|
123
126
|
}
|
|
124
127
|
|
|
128
|
+
/** Resolves a stable, unique key for a tree-grid item (keys must be unique across levels). */
|
|
129
|
+
function resolveItemKey<T>(item: T, getKey: ((item: T) => Key) | undefined, index: number): Key {
|
|
130
|
+
if (getKey) return getKey(item);
|
|
131
|
+
const record = item as { id?: Key; key?: Key };
|
|
132
|
+
return record.id ?? record.key ?? index;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Turns the flat `items` into nested {@link RowDefinition}s by recursively expanding each
|
|
137
|
+
* item's children via `getChildItems`. The result feeds the tree-grid collection.
|
|
138
|
+
*/
|
|
139
|
+
function toTreeRowDefinitions<T>(
|
|
140
|
+
items: Iterable<T>,
|
|
141
|
+
getKey: ((item: T) => Key) | undefined,
|
|
142
|
+
getChildItems: ((item: T) => Iterable<T> | undefined) | undefined,
|
|
143
|
+
): RowDefinition<T>[] {
|
|
144
|
+
return Array.from(items).map((item, index) => {
|
|
145
|
+
const childItems = getChildItems?.(item);
|
|
146
|
+
const childRows = childItems
|
|
147
|
+
? toTreeRowDefinitions(childItems, getKey, getChildItems)
|
|
148
|
+
: undefined;
|
|
149
|
+
return {
|
|
150
|
+
key: resolveItemKey(item, getKey, index),
|
|
151
|
+
value: item,
|
|
152
|
+
childRows: childRows && childRows.length > 0 ? childRows : undefined,
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
125
157
|
function getRowHeaderColumnKeys<T>(columns: (ColumnDefinition<T> & { id?: Key })[]): Set<Key> {
|
|
126
158
|
const keys = new Set<Key>();
|
|
127
159
|
|
|
@@ -192,6 +224,18 @@ export interface TableProps<T extends object> extends Omit<AriaTableProps, "chil
|
|
|
192
224
|
) => JSX.Element;
|
|
193
225
|
/** Drag and drop hooks from `useDragAndDrop`. */
|
|
194
226
|
dragAndDropHooks?: DragAndDropHooks<T>;
|
|
227
|
+
/**
|
|
228
|
+
* Derives the child rows of an item, turning the flat `items` into a tree grid
|
|
229
|
+
* (expandable rows). Providing this — or any `UNSTABLE_*expandedKeys` prop — switches the
|
|
230
|
+
* table into tree-grid mode. Mirrors `@react-aria/table`'s `UNSTABLE_` tree-grid feature.
|
|
231
|
+
*/
|
|
232
|
+
UNSTABLE_childItems?: (item: T) => Iterable<T> | undefined;
|
|
233
|
+
/** The currently expanded row keys (controlled). Tree grid only. */
|
|
234
|
+
UNSTABLE_expandedKeys?: "all" | Iterable<Key>;
|
|
235
|
+
/** The initial expanded row keys (uncontrolled). Tree grid only. */
|
|
236
|
+
UNSTABLE_defaultExpandedKeys?: "all" | Iterable<Key>;
|
|
237
|
+
/** Handler called when rows are expanded or collapsed. Tree grid only. */
|
|
238
|
+
UNSTABLE_onExpandedChange?: (keys: Set<Key>) => void;
|
|
195
239
|
}
|
|
196
240
|
|
|
197
241
|
export interface TableHeaderRenderProps {
|
|
@@ -324,6 +368,21 @@ export interface TableRowRenderProps {
|
|
|
324
368
|
isHovered: boolean;
|
|
325
369
|
/** Whether the row is disabled. */
|
|
326
370
|
isDisabled: boolean;
|
|
371
|
+
/**
|
|
372
|
+
* Whether the row is expanded (tree grid only; `false` for a flat table).
|
|
373
|
+
* @selector [data-expanded]
|
|
374
|
+
*/
|
|
375
|
+
isExpanded: boolean;
|
|
376
|
+
/**
|
|
377
|
+
* Whether the row has child rows (tree grid only; `false` for a flat table).
|
|
378
|
+
* @selector [data-has-child-items]
|
|
379
|
+
*/
|
|
380
|
+
hasChildItems: boolean;
|
|
381
|
+
/**
|
|
382
|
+
* The 1-based nesting depth of the row within the table (1 for a flat table).
|
|
383
|
+
* @selector [data-level]
|
|
384
|
+
*/
|
|
385
|
+
level: number;
|
|
327
386
|
}
|
|
328
387
|
|
|
329
388
|
export interface TableRowProps<T> extends SlotProps {
|
|
@@ -380,6 +439,27 @@ export interface TableCellRenderProps {
|
|
|
380
439
|
isPressed: boolean;
|
|
381
440
|
/** Whether the cell is hovered. */
|
|
382
441
|
isHovered: boolean;
|
|
442
|
+
/**
|
|
443
|
+
* Whether the cell is in the tree column — the one that renders the expand/collapse
|
|
444
|
+
* chevron and nesting indentation (tree grid only; `false` for a flat table).
|
|
445
|
+
* @selector [data-tree-column]
|
|
446
|
+
*/
|
|
447
|
+
isTreeColumn: boolean;
|
|
448
|
+
/**
|
|
449
|
+
* Whether the cell's row is expanded (tree grid only; `false` for a flat table).
|
|
450
|
+
* @selector [data-expanded]
|
|
451
|
+
*/
|
|
452
|
+
isExpanded: boolean;
|
|
453
|
+
/**
|
|
454
|
+
* Whether the cell's row has child rows (tree grid only; `false` for a flat table).
|
|
455
|
+
* @selector [data-has-child-items]
|
|
456
|
+
*/
|
|
457
|
+
hasChildItems: boolean;
|
|
458
|
+
/**
|
|
459
|
+
* The 1-based nesting depth of the cell's row within the table (1 for a flat table).
|
|
460
|
+
* @selector [data-level]
|
|
461
|
+
*/
|
|
462
|
+
level: number;
|
|
383
463
|
}
|
|
384
464
|
|
|
385
465
|
export interface TableCellProps extends SlotProps {
|
|
@@ -472,6 +552,10 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
472
552
|
"sortDescriptor",
|
|
473
553
|
"onSortChange",
|
|
474
554
|
"showSelectionCheckboxes",
|
|
555
|
+
"UNSTABLE_childItems",
|
|
556
|
+
"UNSTABLE_expandedKeys",
|
|
557
|
+
"UNSTABLE_defaultExpandedKeys",
|
|
558
|
+
"UNSTABLE_onExpandedChange",
|
|
475
559
|
],
|
|
476
560
|
);
|
|
477
561
|
|
|
@@ -479,31 +563,63 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
479
563
|
const normalizedColumns = createMemo(() => normalizeColumnDefinitions(stateProps.columns));
|
|
480
564
|
const rowHeaderColumnKeys = createMemo(() => getRowHeaderColumnKeys(normalizedColumns()));
|
|
481
565
|
|
|
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
|
-
|
|
566
|
+
// Tree-grid mode is selected structurally by the presence of any expansion prop. Like
|
|
567
|
+
// controlled-vs-uncontrolled, this is a one-time decision, not a reactive toggle.
|
|
568
|
+
const isTreeGrid =
|
|
569
|
+
stateProps.UNSTABLE_childItems !== undefined ||
|
|
570
|
+
stateProps.UNSTABLE_expandedKeys !== undefined ||
|
|
571
|
+
stateProps.UNSTABLE_defaultExpandedKeys !== undefined ||
|
|
572
|
+
stateProps.UNSTABLE_onExpandedChange !== undefined;
|
|
573
|
+
|
|
574
|
+
const getTextValue = () =>
|
|
575
|
+
stateProps.getTextValue as ((item: T, column: ColumnDefinition<T>) => string) | undefined;
|
|
576
|
+
|
|
577
|
+
const state: TableState<T, TableCollection<T>> = isTreeGrid
|
|
578
|
+
? createTreeGridState<T, TableCollection<T>>(() => ({
|
|
579
|
+
columns: normalizedColumns(),
|
|
580
|
+
rows: toTreeRowDefinitions(
|
|
581
|
+
stateProps.items,
|
|
582
|
+
stateProps.getKey,
|
|
583
|
+
stateProps.UNSTABLE_childItems,
|
|
584
|
+
),
|
|
585
|
+
getKey: stateProps.getKey,
|
|
586
|
+
getTextValue: getTextValue(),
|
|
587
|
+
showSelectionCheckboxes: stateProps.showSelectionCheckboxes ?? false,
|
|
588
|
+
rowHeaderColumnKeys: rowHeaderColumnKeys().size > 0 ? rowHeaderColumnKeys() : undefined,
|
|
589
|
+
disabledKeys: stateProps.disabledKeys,
|
|
590
|
+
disabledBehavior: stateProps.disabledBehavior,
|
|
591
|
+
selectionMode: stateProps.selectionMode,
|
|
592
|
+
selectionBehavior: stateProps.selectionBehavior,
|
|
593
|
+
selectedKeys: stateProps.selectedKeys,
|
|
594
|
+
defaultSelectedKeys: stateProps.defaultSelectedKeys,
|
|
595
|
+
onSelectionChange: stateProps.onSelectionChange,
|
|
596
|
+
sortDescriptor: stateProps.sortDescriptor,
|
|
597
|
+
onSortChange: stateProps.onSortChange,
|
|
598
|
+
UNSTABLE_expandedKeys: stateProps.UNSTABLE_expandedKeys,
|
|
599
|
+
UNSTABLE_defaultExpandedKeys: stateProps.UNSTABLE_defaultExpandedKeys,
|
|
600
|
+
UNSTABLE_onExpandedChange: stateProps.UNSTABLE_onExpandedChange,
|
|
601
|
+
}))
|
|
602
|
+
: createTableState<T, TableCollection<T>>(() => ({
|
|
603
|
+
collection: createTableCollection<T>({
|
|
604
|
+
columns: normalizedColumns(),
|
|
605
|
+
rows: stateProps.items,
|
|
606
|
+
getKey: stateProps.getKey,
|
|
607
|
+
getTextValue: getTextValue(),
|
|
608
|
+
showSelectionCheckboxes: stateProps.showSelectionCheckboxes ?? false,
|
|
609
|
+
rowHeaderColumnKeys: rowHeaderColumnKeys().size > 0 ? rowHeaderColumnKeys() : undefined,
|
|
610
|
+
}),
|
|
611
|
+
disabledKeys: stateProps.disabledKeys,
|
|
612
|
+
disabledBehavior: stateProps.disabledBehavior,
|
|
613
|
+
selectionMode: stateProps.selectionMode,
|
|
614
|
+
selectionBehavior: stateProps.selectionBehavior,
|
|
615
|
+
selectedKeys: stateProps.selectedKeys,
|
|
616
|
+
defaultSelectedKeys: stateProps.defaultSelectedKeys,
|
|
617
|
+
onSelectionChange: stateProps.onSelectionChange,
|
|
618
|
+
sortDescriptor: stateProps.sortDescriptor,
|
|
619
|
+
onSortChange: stateProps.onSortChange,
|
|
620
|
+
showSelectionCheckboxes: stateProps.showSelectionCheckboxes,
|
|
621
|
+
}));
|
|
622
|
+
const collection = () => state.collection;
|
|
507
623
|
const parentCollectionRenderer = useCollectionRenderer<T>();
|
|
508
624
|
|
|
509
625
|
const { gridProps } = createTable<T>(
|
|
@@ -707,8 +823,16 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
707
823
|
dndDropIndicator(index, position) ??
|
|
708
824
|
parentCollectionRenderer?.renderDropIndicator?.(index, position),
|
|
709
825
|
}));
|
|
826
|
+
// The root children function builds the structural `<TableHeader>`/`<TableBody>`
|
|
827
|
+
// subtree once. React re-invokes it on every render and reconciles the result, so
|
|
828
|
+
// reading focus-dependent render values (isFocused/isFocusVisible) there is cheap.
|
|
829
|
+
// Solid has no reconciliation: re-invoking recreates the entire thead/tbody subtree,
|
|
830
|
+
// which detaches the DOM-focused row and drops keyboard focus (Space/Enter never reach
|
|
831
|
+
// the row). So invoke it with an untracked snapshot of the render values — the insert
|
|
832
|
+
// below stays stable across focus changes while children still see current values at
|
|
833
|
+
// creation. Render values for collection structure are not reactive in practice.
|
|
710
834
|
const tableChildren = () =>
|
|
711
|
-
typeof props.children === "function" ? props.children(renderValues
|
|
835
|
+
typeof props.children === "function" ? props.children(untrack(renderValues)) : props.children;
|
|
712
836
|
const tableProps = () =>
|
|
713
837
|
({
|
|
714
838
|
ref: (el: HTMLTableElement) => {
|
|
@@ -728,7 +852,6 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
728
852
|
"data-empty": stateProps.items.length === 0 || undefined,
|
|
729
853
|
"data-drop-target": isRootDropTarget() || undefined,
|
|
730
854
|
slot: local.slot,
|
|
731
|
-
children: tableChildren(),
|
|
732
855
|
}) as JSX.HTMLAttributes<HTMLTableElement>;
|
|
733
856
|
|
|
734
857
|
return (
|
|
@@ -737,7 +860,11 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
737
860
|
value={state as unknown as TableState<object, TableCollection<object>>}
|
|
738
861
|
>
|
|
739
862
|
<CollectionRendererContext.Provider value={collectionRenderer()}>
|
|
740
|
-
{local.render ?
|
|
863
|
+
{local.render ? (
|
|
864
|
+
local.render({ ...tableProps(), children: tableChildren() }, renderValues())
|
|
865
|
+
) : (
|
|
866
|
+
<table {...tableProps()}>{tableChildren()}</table>
|
|
867
|
+
)}
|
|
741
868
|
</CollectionRendererContext.Provider>
|
|
742
869
|
</TableStateContext.Provider>
|
|
743
870
|
</TableContext.Provider>
|
|
@@ -1071,6 +1198,8 @@ export function TableBody<T extends object>(props: TableBodyProps<T>): JSX.Eleme
|
|
|
1071
1198
|
context.collection,
|
|
1072
1199
|
);
|
|
1073
1200
|
const virtualRange = createMemo(() => {
|
|
1201
|
+
// Tree grids render every visible (flattened) row; virtual windowing is a follow-up.
|
|
1202
|
+
if (context.state.treeColumn != null) return null;
|
|
1074
1203
|
if (!virtualizer || !parentCollectionRenderer?.isVirtualized) return null;
|
|
1075
1204
|
const rowCount = items().length;
|
|
1076
1205
|
const baseRange = virtualizer.getVisibleRange(rowCount);
|
|
@@ -1125,6 +1254,11 @@ export function TableBody<T extends object>(props: TableBodyProps<T>): JSX.Eleme
|
|
|
1125
1254
|
});
|
|
1126
1255
|
});
|
|
1127
1256
|
const visibleItems = createMemo(() => {
|
|
1257
|
+
// Tree grid: render the flattened set of visible rows (top-level + expanded descendants)
|
|
1258
|
+
// the collection materialises in document order, so the render fn runs once per visible row.
|
|
1259
|
+
if (context.state.treeColumn != null) {
|
|
1260
|
+
return rowNodes().map((node) => node.value as T);
|
|
1261
|
+
}
|
|
1128
1262
|
const range = virtualRange();
|
|
1129
1263
|
if (!range) return items();
|
|
1130
1264
|
return items().slice(range.start, range.end);
|
|
@@ -1435,7 +1569,7 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1435
1569
|
if (!context) {
|
|
1436
1570
|
throw new Error("TableRow must be used within a Table");
|
|
1437
1571
|
}
|
|
1438
|
-
const { state
|
|
1572
|
+
const { state } = context;
|
|
1439
1573
|
const tableContext = context as unknown as TableContextValue<T>;
|
|
1440
1574
|
const registeredCellIds: string[] = [];
|
|
1441
1575
|
const generatedId = createUniqueId();
|
|
@@ -1454,8 +1588,10 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1454
1588
|
|
|
1455
1589
|
const [ref, setRef] = createSignal<HTMLTableRowElement | null>(null);
|
|
1456
1590
|
|
|
1591
|
+
// Read through `state.collection` (not the destructured snapshot) so the node tracks
|
|
1592
|
+
// collection rebuilds — e.g. a tree-grid row staying mounted across an expand/collapse.
|
|
1457
1593
|
const rowNode = createMemo(() => {
|
|
1458
|
-
const node = collection.getItem(rowKey());
|
|
1594
|
+
const node = state.collection.getItem(rowKey());
|
|
1459
1595
|
if (!node) {
|
|
1460
1596
|
return {
|
|
1461
1597
|
type: "item" as const,
|
|
@@ -1492,7 +1628,12 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1492
1628
|
const isPressed = () => rowAria.isPressed;
|
|
1493
1629
|
const isInteractive = () => {
|
|
1494
1630
|
const tableData = getTableData(state as TableState<object, TableCollection<object>>);
|
|
1495
|
-
return
|
|
1631
|
+
return (
|
|
1632
|
+
state.selectionMode !== "none" ||
|
|
1633
|
+
!!tableData?.actions.onRowAction ||
|
|
1634
|
+
!!local.onAction ||
|
|
1635
|
+
!!local.href
|
|
1636
|
+
);
|
|
1496
1637
|
};
|
|
1497
1638
|
|
|
1498
1639
|
const { isHovered, hoverProps } = createHover({
|
|
@@ -1549,6 +1690,13 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1549
1690
|
);
|
|
1550
1691
|
});
|
|
1551
1692
|
|
|
1693
|
+
// Tree-grid (expandable rows): nesting depth, child presence and expansion. These are
|
|
1694
|
+
// inert for a flat table (level 1, no children, not expanded).
|
|
1695
|
+
const isTreeRow = () => state.treeColumn != null;
|
|
1696
|
+
const rowLevel = () => rowNode().level + 1;
|
|
1697
|
+
const hasChildItems = () => rowAria.hasChildRows;
|
|
1698
|
+
const isExpanded = () => rowAria.isExpanded;
|
|
1699
|
+
|
|
1552
1700
|
const renderValues = createMemo<TableRowRenderProps>(() => ({
|
|
1553
1701
|
isSelected: isSelected(),
|
|
1554
1702
|
isFocused: isFocused(),
|
|
@@ -1556,6 +1704,9 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1556
1704
|
isPressed: isPressed(),
|
|
1557
1705
|
isHovered: isHovered(),
|
|
1558
1706
|
isDisabled: isDisabled(),
|
|
1707
|
+
isExpanded: isExpanded(),
|
|
1708
|
+
hasChildItems: hasChildItems(),
|
|
1709
|
+
level: rowLevel(),
|
|
1559
1710
|
}));
|
|
1560
1711
|
|
|
1561
1712
|
// Resolve render props (children rendered directly in JSX to avoid eager evaluation)
|
|
@@ -1610,73 +1761,197 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
1610
1761
|
},
|
|
1611
1762
|
};
|
|
1612
1763
|
});
|
|
1613
|
-
|
|
1764
|
+
// A STABLE context object: its identity never changes, so the surrounding ButtonContext.Provider
|
|
1765
|
+
// never tears down and recreates the row's children. The slots are getters, so a slotted
|
|
1766
|
+
// <Button slot="drag"|"chevron"> reads the current drag/expand props each time it is (re)created —
|
|
1767
|
+
// e.g. when the tree column recreates the chevron on expand/collapse.
|
|
1768
|
+
const buttonContextValue: ButtonContextValue = {
|
|
1614
1769
|
slots: {
|
|
1615
1770
|
default: {},
|
|
1616
|
-
drag
|
|
1771
|
+
get drag() {
|
|
1772
|
+
return dragButtonProps();
|
|
1773
|
+
},
|
|
1774
|
+
// Tree-grid expand/collapse chevron; the slotted <Button slot="chevron"> picks these up.
|
|
1775
|
+
// The aria hook yields DOM button attributes, merged onto the Button as passthrough props.
|
|
1776
|
+
get chevron() {
|
|
1777
|
+
return rowAria.expandButtonProps as unknown as ButtonProps;
|
|
1778
|
+
},
|
|
1617
1779
|
},
|
|
1618
|
-
}
|
|
1780
|
+
};
|
|
1619
1781
|
|
|
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>;
|
|
1782
|
+
// Render props handed to the row's children as a STABLE getter proxy: reading a getter stays
|
|
1783
|
+
// fine-grained reactive at the point of use, without forcing the children to be re-derived (and
|
|
1784
|
+
// therefore disposed + recreated) whenever an unrelated render prop flips.
|
|
1785
|
+
const childRenderProps: TableRowRenderProps = {
|
|
1786
|
+
get isSelected() {
|
|
1787
|
+
return isSelected();
|
|
1788
|
+
},
|
|
1789
|
+
get isFocused() {
|
|
1790
|
+
return isFocused();
|
|
1791
|
+
},
|
|
1792
|
+
get isFocusVisible() {
|
|
1793
|
+
return isFocusVisible() && isFocused();
|
|
1794
|
+
},
|
|
1795
|
+
get isPressed() {
|
|
1796
|
+
return isPressed();
|
|
1797
|
+
},
|
|
1798
|
+
get isHovered() {
|
|
1799
|
+
return isHovered();
|
|
1800
|
+
},
|
|
1801
|
+
get isDisabled() {
|
|
1802
|
+
return isDisabled();
|
|
1803
|
+
},
|
|
1804
|
+
get isExpanded() {
|
|
1805
|
+
return isExpanded();
|
|
1806
|
+
},
|
|
1807
|
+
get hasChildItems() {
|
|
1808
|
+
return hasChildItems();
|
|
1809
|
+
},
|
|
1810
|
+
get level() {
|
|
1811
|
+
return rowLevel();
|
|
1812
|
+
},
|
|
1813
|
+
};
|
|
1814
|
+
|
|
1815
|
+
// Tree-grid rows carry their nesting depth as a CSS var so the tree column can indent.
|
|
1816
|
+
const rowStyle = () => {
|
|
1817
|
+
const base = renderProps.style();
|
|
1818
|
+
if (!isTreeRow()) return base;
|
|
1819
|
+
return { ...(base ?? {}), "--table-row-level": rowLevel() } as JSX.CSSProperties;
|
|
1820
|
+
};
|
|
1676
1821
|
|
|
1677
1822
|
return (
|
|
1678
1823
|
<TableRowContext.Provider value={rowContextValue}>
|
|
1679
|
-
|
|
1824
|
+
<ButtonContext.Provider value={buttonContextValue}>
|
|
1825
|
+
{(() => {
|
|
1826
|
+
// Build the row's children HERE — inside BOTH providers — so each cell instantiates under
|
|
1827
|
+
// this owner. TableCell/EditableCell read TableRowContext, and a slotted
|
|
1828
|
+
// <Button slot="drag"|"chevron"> reads ButtonContext; in Solid useContext binds at the
|
|
1829
|
+
// owner active when the component executes, so the children must be created inside the
|
|
1830
|
+
// providers, not merely wrapped by them afterwards. They are built EXACTLY ONCE: a press
|
|
1831
|
+
// or focus bubbling up from interactive cell content (e.g. an EditableCell's edit button)
|
|
1832
|
+
// flips the row's render-props signals, and re-deriving the children on every such change
|
|
1833
|
+
// would dispose and recreate the subtree, destroying the in-flight press. Cells claim
|
|
1834
|
+
// their column by render order (see getCellColumnKey), so reset the registry once before
|
|
1835
|
+
// this single pass.
|
|
1836
|
+
registeredCellIds.length = 0;
|
|
1837
|
+
const rowChildrenContent =
|
|
1838
|
+
typeof local.children === "function" ? (
|
|
1839
|
+
local.columns ? (
|
|
1840
|
+
<For each={local.columns}>
|
|
1841
|
+
{(column) =>
|
|
1842
|
+
(local.children as (column: TableColumnDefinition<T>) => JSX.Element)(column)
|
|
1843
|
+
}
|
|
1844
|
+
</For>
|
|
1845
|
+
) : (
|
|
1846
|
+
(local.children as (renderProps: TableRowRenderProps) => JSX.Element)(
|
|
1847
|
+
childRenderProps,
|
|
1848
|
+
)
|
|
1849
|
+
)
|
|
1850
|
+
) : (
|
|
1851
|
+
local.children
|
|
1852
|
+
);
|
|
1853
|
+
const tableRowProps = () =>
|
|
1854
|
+
({
|
|
1855
|
+
ref: (el: HTMLTableRowElement) => {
|
|
1856
|
+
setRef(el);
|
|
1857
|
+
assignRef(local.ref, el);
|
|
1858
|
+
},
|
|
1859
|
+
...domProps,
|
|
1860
|
+
...mergeProps(
|
|
1861
|
+
cleanRowProps(),
|
|
1862
|
+
cleanHoverProps(),
|
|
1863
|
+
cleanFocusProps(),
|
|
1864
|
+
focusWithinProps as Record<string, unknown>,
|
|
1865
|
+
(draggableItem()?.dragProps as Record<string, unknown> | undefined) ?? {},
|
|
1866
|
+
(droppableItem()?.dropProps as Record<string, unknown> | undefined) ?? {},
|
|
1867
|
+
),
|
|
1868
|
+
class: renderProps.class(),
|
|
1869
|
+
style: rowStyle(),
|
|
1870
|
+
"data-key": rowKey(),
|
|
1871
|
+
"data-selected": isSelected() || undefined,
|
|
1872
|
+
"data-focused": isFocused() || undefined,
|
|
1873
|
+
"data-focus-visible": (isFocusVisible() && isFocused()) || undefined,
|
|
1874
|
+
"data-focus-visible-within": dataAttr(isFocusWithin() && isGlobalFocusVisible()),
|
|
1875
|
+
"data-pressed": isPressed() || undefined,
|
|
1876
|
+
"data-hovered": isHovered() || undefined,
|
|
1877
|
+
"data-disabled": isDisabled() || undefined,
|
|
1878
|
+
"data-href": linkProps().href,
|
|
1879
|
+
"data-target": linkProps().target,
|
|
1880
|
+
"data-rel": linkProps().rel,
|
|
1881
|
+
"data-download":
|
|
1882
|
+
typeof linkProps().download === "string"
|
|
1883
|
+
? linkProps().download
|
|
1884
|
+
: linkProps().download
|
|
1885
|
+
? ""
|
|
1886
|
+
: undefined,
|
|
1887
|
+
"data-ping": linkProps().ping,
|
|
1888
|
+
"data-referrer-policy": linkProps().referrerPolicy,
|
|
1889
|
+
"data-dragging": draggableItem()?.isDragging || undefined,
|
|
1890
|
+
"data-drop-target": droppableItem()?.isDropTarget || undefined,
|
|
1891
|
+
"data-expanded": (isTreeRow() && isExpanded()) || undefined,
|
|
1892
|
+
"data-has-child-items": (isTreeRow() && hasChildItems()) || undefined,
|
|
1893
|
+
"data-level": isTreeRow() ? rowLevel() : undefined,
|
|
1894
|
+
children: rowChildrenContent,
|
|
1895
|
+
}) as JSX.HTMLAttributes<HTMLTableRowElement>;
|
|
1896
|
+
|
|
1897
|
+
return (
|
|
1898
|
+
<Show
|
|
1899
|
+
when={local.render}
|
|
1900
|
+
fallback={
|
|
1901
|
+
// Bind attributes individually on a STABLE <tr> (mirroring TableCell) so a
|
|
1902
|
+
// render-props change updates attributes in place instead of recreating the element
|
|
1903
|
+
// and its subtree.
|
|
1904
|
+
<tr
|
|
1905
|
+
ref={(el: HTMLTableRowElement) => {
|
|
1906
|
+
setRef(el);
|
|
1907
|
+
assignRef(local.ref, el);
|
|
1908
|
+
}}
|
|
1909
|
+
{...domProps}
|
|
1910
|
+
{...mergeProps(
|
|
1911
|
+
cleanRowProps(),
|
|
1912
|
+
cleanHoverProps(),
|
|
1913
|
+
cleanFocusProps(),
|
|
1914
|
+
focusWithinProps as Record<string, unknown>,
|
|
1915
|
+
(draggableItem()?.dragProps as Record<string, unknown> | undefined) ?? {},
|
|
1916
|
+
(droppableItem()?.dropProps as Record<string, unknown> | undefined) ?? {},
|
|
1917
|
+
)}
|
|
1918
|
+
class={renderProps.class()}
|
|
1919
|
+
style={rowStyle()}
|
|
1920
|
+
data-key={rowKey()}
|
|
1921
|
+
data-selected={isSelected() || undefined}
|
|
1922
|
+
data-focused={isFocused() || undefined}
|
|
1923
|
+
data-focus-visible={(isFocusVisible() && isFocused()) || undefined}
|
|
1924
|
+
data-focus-visible-within={dataAttr(isFocusWithin() && isGlobalFocusVisible())}
|
|
1925
|
+
data-pressed={isPressed() || undefined}
|
|
1926
|
+
data-hovered={isHovered() || undefined}
|
|
1927
|
+
data-disabled={isDisabled() || undefined}
|
|
1928
|
+
data-href={linkProps().href}
|
|
1929
|
+
data-target={linkProps().target}
|
|
1930
|
+
data-rel={linkProps().rel}
|
|
1931
|
+
data-download={
|
|
1932
|
+
typeof linkProps().download === "string"
|
|
1933
|
+
? linkProps().download
|
|
1934
|
+
: linkProps().download
|
|
1935
|
+
? ""
|
|
1936
|
+
: undefined
|
|
1937
|
+
}
|
|
1938
|
+
data-ping={linkProps().ping}
|
|
1939
|
+
data-referrer-policy={linkProps().referrerPolicy}
|
|
1940
|
+
data-dragging={draggableItem()?.isDragging || undefined}
|
|
1941
|
+
data-drop-target={droppableItem()?.isDropTarget || undefined}
|
|
1942
|
+
data-expanded={(isTreeRow() && isExpanded()) || undefined}
|
|
1943
|
+
data-has-child-items={(isTreeRow() && hasChildItems()) || undefined}
|
|
1944
|
+
data-level={isTreeRow() ? rowLevel() : undefined}
|
|
1945
|
+
>
|
|
1946
|
+
{rowChildrenContent}
|
|
1947
|
+
</tr>
|
|
1948
|
+
}
|
|
1949
|
+
>
|
|
1950
|
+
{local.render!(tableRowProps(), renderValues())}
|
|
1951
|
+
</Show>
|
|
1952
|
+
);
|
|
1953
|
+
})()}
|
|
1954
|
+
</ButtonContext.Provider>
|
|
1680
1955
|
</TableRowContext.Provider>
|
|
1681
1956
|
);
|
|
1682
1957
|
}
|
|
@@ -1706,7 +1981,7 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1706
1981
|
throw new Error("TableCell must be used within a Table");
|
|
1707
1982
|
}
|
|
1708
1983
|
|
|
1709
|
-
const { state
|
|
1984
|
+
const { state } = tableContext;
|
|
1710
1985
|
const { rowKey, rowNode } = rowContext;
|
|
1711
1986
|
|
|
1712
1987
|
const [ref, setRef] = createSignal<HTMLTableCellElement | null>(null);
|
|
@@ -1717,7 +1992,7 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1717
1992
|
const key = columnKey();
|
|
1718
1993
|
if (key != null) {
|
|
1719
1994
|
const cellKey = `${rowKey}-${key}`;
|
|
1720
|
-
const node = collection.getItem(cellKey);
|
|
1995
|
+
const node = state.collection.getItem(cellKey);
|
|
1721
1996
|
if (node) return node;
|
|
1722
1997
|
}
|
|
1723
1998
|
|
|
@@ -1737,9 +2012,21 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1737
2012
|
const key = columnKey();
|
|
1738
2013
|
if (key == null) return undefined;
|
|
1739
2014
|
const cellKey = `${rowKey}-${key}`;
|
|
1740
|
-
return collection.getItem(cellKey) ? (cellNode().index ?? 0) : undefined;
|
|
2015
|
+
return state.collection.getItem(cellKey) ? (cellNode().index ?? 0) : undefined;
|
|
1741
2016
|
});
|
|
1742
2017
|
|
|
2018
|
+
// Tree-grid (expandable rows): the cell mirrors its row's nesting/expansion and flags the
|
|
2019
|
+
// tree column (the one that renders the chevron + indentation). Inert for a flat table.
|
|
2020
|
+
const isTreeGridCell = () => state.treeColumn != null;
|
|
2021
|
+
const parentRowNode = createMemo(() => state.collection.getItem(rowKey));
|
|
2022
|
+
const cellLevel = () => (parentRowNode()?.level ?? rowNode.level ?? 0) + 1;
|
|
2023
|
+
const cellHasChildItems = () => parentRowNode()?.isExpandable ?? false;
|
|
2024
|
+
const cellIsExpanded = () => {
|
|
2025
|
+
if (!isTreeGridCell() || !cellHasChildItems()) return false;
|
|
2026
|
+
return state.expandedKeys === "all" || state.expandedKeys.has(rowKey);
|
|
2027
|
+
};
|
|
2028
|
+
const isTreeColumn = () => isTreeGridCell() && columnKey() === state.treeColumn;
|
|
2029
|
+
|
|
1743
2030
|
const cellAria = createTableCell<object>(
|
|
1744
2031
|
() => ({
|
|
1745
2032
|
node: cellNode(),
|
|
@@ -1763,6 +2050,10 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1763
2050
|
columnIndex: cellColumnIndex() ?? 0,
|
|
1764
2051
|
isPressed: isPressed(),
|
|
1765
2052
|
isHovered: isHovered(),
|
|
2053
|
+
isTreeColumn: isTreeColumn(),
|
|
2054
|
+
isExpanded: cellIsExpanded(),
|
|
2055
|
+
hasChildItems: cellHasChildItems(),
|
|
2056
|
+
level: cellLevel(),
|
|
1766
2057
|
}));
|
|
1767
2058
|
|
|
1768
2059
|
// Resolve render props (children rendered directly in JSX to avoid eager evaluation)
|
|
@@ -1801,11 +2092,16 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1801
2092
|
colSpan: local.colSpan,
|
|
1802
2093
|
class: renderProps.class(),
|
|
1803
2094
|
style: renderProps.style(),
|
|
2095
|
+
"data-key": cellNode().key,
|
|
1804
2096
|
"data-focused": isFocused() || undefined,
|
|
1805
2097
|
"data-focus-visible": (isFocusVisible() && isFocused()) || undefined,
|
|
1806
2098
|
"data-column-index": cellColumnIndex(),
|
|
1807
2099
|
"data-pressed": isPressed() || undefined,
|
|
1808
2100
|
"data-hovered": isHovered() || undefined,
|
|
2101
|
+
"data-tree-column": isTreeColumn() || undefined,
|
|
2102
|
+
"data-expanded": (isTreeGridCell() && cellIsExpanded()) || undefined,
|
|
2103
|
+
"data-has-child-items": (isTreeGridCell() && cellHasChildItems()) || undefined,
|
|
2104
|
+
"data-level": isTreeGridCell() ? cellLevel() : undefined,
|
|
1809
2105
|
children: cellChildren(),
|
|
1810
2106
|
}) as JSX.TdHTMLAttributes<HTMLTableCellElement>;
|
|
1811
2107
|
|
|
@@ -1822,11 +2118,16 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
1822
2118
|
colSpan={local.colSpan}
|
|
1823
2119
|
class={renderProps.class()}
|
|
1824
2120
|
style={renderProps.style()}
|
|
2121
|
+
data-key={cellNode().key}
|
|
1825
2122
|
data-focused={isFocused() || undefined}
|
|
1826
2123
|
data-focus-visible={(isFocusVisible() && isFocused()) || undefined}
|
|
1827
2124
|
data-column-index={cellColumnIndex()}
|
|
1828
2125
|
data-pressed={isPressed() || undefined}
|
|
1829
2126
|
data-hovered={isHovered() || undefined}
|
|
2127
|
+
data-tree-column={isTreeColumn() || undefined}
|
|
2128
|
+
data-expanded={(isTreeGridCell() && cellIsExpanded()) || undefined}
|
|
2129
|
+
data-has-child-items={(isTreeGridCell() && cellHasChildItems()) || undefined}
|
|
2130
|
+
data-level={isTreeGridCell() ? cellLevel() : undefined}
|
|
1830
2131
|
>
|
|
1831
2132
|
{cellChildren()}
|
|
1832
2133
|
</td>
|
|
@@ -1864,6 +2165,11 @@ export function TableSelectionCheckbox(props: TableSelectionCheckboxProps): JSX.
|
|
|
1864
2165
|
style={props.style}
|
|
1865
2166
|
tabIndex={props.excludeFromTabOrder ? -1 : selectionCheckboxAria.checkboxProps.tabIndex}
|
|
1866
2167
|
aria-label={props["aria-label"] ?? selectionCheckboxAria.checkboxProps["aria-label"]}
|
|
2168
|
+
onClick={(event) => event.stopPropagation()}
|
|
2169
|
+
onKeyDown={(event) => event.stopPropagation()}
|
|
2170
|
+
onKeyUp={(event) => event.stopPropagation()}
|
|
2171
|
+
onPointerDown={(event) => event.stopPropagation()}
|
|
2172
|
+
onPointerUp={(event) => event.stopPropagation()}
|
|
1867
2173
|
/>
|
|
1868
2174
|
);
|
|
1869
2175
|
}
|
|
@@ -1889,8 +2195,16 @@ export function TableSelectAllCheckbox(props: TableSelectAllCheckboxProps = {}):
|
|
|
1889
2195
|
() => state as TableState<object, TableCollection<object>>,
|
|
1890
2196
|
);
|
|
1891
2197
|
|
|
2198
|
+
let inputRef: HTMLInputElement | undefined;
|
|
2199
|
+
createEffect(() => {
|
|
2200
|
+
if (inputRef) {
|
|
2201
|
+
inputRef.indeterminate = selectAllCheckboxAria.isIndeterminate;
|
|
2202
|
+
}
|
|
2203
|
+
});
|
|
2204
|
+
|
|
1892
2205
|
return (
|
|
1893
2206
|
<input
|
|
2207
|
+
ref={inputRef}
|
|
1894
2208
|
{...selectAllCheckboxAria.checkboxProps}
|
|
1895
2209
|
class={props.class}
|
|
1896
2210
|
style={props.style}
|