@proyecto-viviana/solidaria-components 0.2.5 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/ActionBar.d.ts +71 -0
- package/dist/ActionBar.d.ts.map +1 -0
- package/dist/ActionGroup.d.ts +74 -0
- package/dist/ActionGroup.d.ts.map +1 -0
- package/dist/Alert.d.ts +70 -0
- package/dist/Alert.d.ts.map +1 -0
- package/dist/Breadcrumbs.d.ts +10 -2
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Button.d.ts +4 -0
- package/dist/Button.d.ts.map +1 -1
- package/dist/Calendar.d.ts +13 -0
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +2 -2
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Collection.d.ts +125 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Color.d.ts +114 -2
- package/dist/Color.d.ts.map +1 -1
- package/dist/ColorEditor.d.ts +42 -0
- package/dist/ColorEditor.d.ts.map +1 -0
- package/dist/ComboBox.d.ts +64 -0
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ContextualHelpTrigger.d.ts +40 -0
- package/dist/ContextualHelpTrigger.d.ts.map +1 -0
- package/dist/DateField.d.ts +27 -2
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DatePicker.d.ts +67 -2
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Disclosure.d.ts +2 -0
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/DragAndDrop.d.ts +80 -0
- package/dist/DragAndDrop.d.ts.map +1 -0
- package/dist/DragPreview.d.ts +14 -0
- package/dist/DragPreview.d.ts.map +1 -0
- package/dist/DropZone.d.ts +27 -0
- package/dist/DropZone.d.ts.map +1 -0
- package/dist/FieldError.d.ts +23 -0
- package/dist/FieldError.d.ts.map +1 -0
- package/dist/FileTrigger.d.ts +26 -0
- package/dist/FileTrigger.d.ts.map +1 -0
- package/dist/Focusable.d.ts +27 -0
- package/dist/Focusable.d.ts.map +1 -0
- package/dist/Form.d.ts +27 -0
- package/dist/Form.d.ts.map +1 -0
- package/dist/GridList.d.ts +40 -1
- package/dist/GridList.d.ts.map +1 -1
- package/dist/Icon.d.ts +57 -0
- package/dist/Icon.d.ts.map +1 -0
- package/dist/Keyboard.d.ts +13 -0
- package/dist/Keyboard.d.ts.map +1 -0
- package/dist/Link.d.ts.map +1 -1
- package/dist/ListBox.d.ts +43 -1
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListDropTargetDelegate.d.ts +38 -0
- package/dist/ListDropTargetDelegate.d.ts.map +1 -0
- package/dist/Menu.d.ts +20 -2
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Meter.d.ts +2 -2
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Modal.d.ts +2 -0
- package/dist/Modal.d.ts.map +1 -1
- package/dist/NumberField.d.ts +2 -0
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/Popover.d.ts +4 -2
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Pressable.d.ts +27 -0
- package/dist/Pressable.d.ts.map +1 -0
- package/dist/ProgressBar.d.ts +2 -2
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RangeCalendar.d.ts +5 -0
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RouterProvider.d.ts +75 -0
- package/dist/RouterProvider.d.ts.map +1 -0
- package/dist/SearchField.d.ts +2 -3
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/Select.d.ts +11 -0
- package/dist/Select.d.ts.map +1 -1
- package/dist/SelectionIndicator.d.ts +30 -0
- package/dist/SelectionIndicator.d.ts.map +1 -0
- package/dist/SharedElementTransition.d.ts +39 -0
- package/dist/SharedElementTransition.d.ts.map +1 -0
- package/dist/Slider.d.ts +6 -3
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Table.d.ts +39 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +4 -3
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/TagGroup.d.ts +12 -2
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/Text.d.ts +10 -0
- package/dist/Text.d.ts.map +1 -0
- package/dist/TextField.d.ts +4 -0
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TimeField.d.ts +26 -1
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/Toast.d.ts.map +1 -1
- package/dist/ToggleButton.d.ts +30 -0
- package/dist/ToggleButton.d.ts.map +1 -0
- package/dist/ToggleButtonGroup.d.ts +33 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -0
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Tooltip.d.ts +9 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tree.d.ts +44 -2
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Virtualizer.d.ts +61 -0
- package/dist/Virtualizer.d.ts.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +82 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -0
- package/dist/VisuallyHidden.d.ts +3 -1
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/contexts.d.ts +1 -0
- package/dist/contexts.d.ts.map +1 -1
- package/dist/index.d.ts +57 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13961 -5946
- package/dist/index.js.map +1 -7
- package/dist/index.ssr.js +9612 -2401
- package/dist/index.ssr.js.map +1 -7
- package/dist/useDragAndDrop.d.ts +93 -0
- package/dist/useDragAndDrop.d.ts.map +1 -0
- package/dist/utils.d.ts +7 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/virtualizer/Layout.d.ts +79 -0
- package/dist/virtualizer/Layout.d.ts.map +1 -0
- package/package.json +8 -6
- package/src/ActionBar.tsx +248 -0
- package/src/ActionGroup.tsx +285 -0
- package/src/Alert.tsx +177 -0
- package/src/Autocomplete.tsx +1 -1
- package/src/Breadcrumbs.tsx +103 -17
- package/src/Button.tsx +65 -21
- package/src/Calendar.tsx +179 -53
- package/src/Checkbox.tsx +1 -2
- package/src/Collection.tsx +341 -0
- package/src/Color.tsx +652 -34
- package/src/ColorEditor.tsx +231 -0
- package/src/ComboBox.tsx +315 -81
- package/src/ContextualHelpTrigger.tsx +183 -0
- package/src/DateField.tsx +93 -19
- package/src/DatePicker.tsx +495 -25
- package/src/Dialog.tsx +40 -9
- package/src/Disclosure.tsx +33 -27
- package/src/DragAndDrop.tsx +334 -0
- package/src/DragPreview.tsx +45 -0
- package/src/DropZone.tsx +213 -0
- package/src/FieldError.tsx +67 -0
- package/src/FileTrigger.tsx +83 -0
- package/src/Focusable.tsx +106 -0
- package/src/Form.tsx +85 -0
- package/src/GridList.tsx +379 -41
- package/src/Icon.tsx +154 -0
- package/src/Keyboard.tsx +26 -0
- package/src/Link.tsx +14 -1
- package/src/ListBox.tsx +484 -33
- package/src/ListDropTargetDelegate.ts +282 -0
- package/src/Menu.tsx +388 -35
- package/src/Meter.tsx +7 -3
- package/src/Modal.tsx +32 -4
- package/src/NumberField.tsx +163 -43
- package/src/Popover.tsx +136 -180
- package/src/Pressable.tsx +108 -0
- package/src/ProgressBar.tsx +7 -3
- package/src/RadioGroup.tsx +35 -25
- package/src/RangeCalendar.tsx +100 -68
- package/src/RouterProvider.tsx +240 -0
- package/src/SearchField.tsx +142 -34
- package/src/Select.tsx +221 -73
- package/src/SelectionIndicator.tsx +105 -0
- package/src/SharedElementTransition.tsx +258 -0
- package/src/Slider.tsx +16 -6
- package/src/Table.tsx +417 -57
- package/src/Tabs.tsx +68 -35
- package/src/TagGroup.tsx +121 -36
- package/src/Text.tsx +18 -0
- package/src/TextField.tsx +25 -8
- package/src/TimeField.tsx +101 -151
- package/src/Toast.tsx +108 -14
- package/src/ToggleButton.tsx +159 -0
- package/src/ToggleButtonGroup.tsx +136 -0
- package/src/Toolbar.tsx +14 -8
- package/src/Tooltip.tsx +108 -19
- package/src/Tree.tsx +1143 -87
- package/src/Virtualizer.tsx +702 -0
- package/src/VirtualizerLayouts.ts +265 -0
- package/src/VisuallyHidden.tsx +15 -21
- package/src/contexts.ts +1 -0
- package/src/index.ts +1057 -620
- package/src/useDragAndDrop.ts +351 -0
- package/src/utils.tsx +37 -3
- package/src/virtualizer/Layout.ts +200 -0
package/src/Table.tsx
CHANGED
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
import {
|
|
9
9
|
type JSX,
|
|
10
10
|
createContext,
|
|
11
|
+
createEffect,
|
|
11
12
|
createMemo,
|
|
12
13
|
createSignal,
|
|
14
|
+
onCleanup,
|
|
13
15
|
splitProps,
|
|
14
16
|
useContext,
|
|
15
17
|
For,
|
|
@@ -25,6 +27,7 @@ import {
|
|
|
25
27
|
createTableSelectAllCheckbox,
|
|
26
28
|
createFocusRing,
|
|
27
29
|
createHover,
|
|
30
|
+
mergeProps,
|
|
28
31
|
type AriaTableProps,
|
|
29
32
|
} from '@proyecto-viviana/solidaria';
|
|
30
33
|
import {
|
|
@@ -36,6 +39,7 @@ import {
|
|
|
36
39
|
type SortDescriptor,
|
|
37
40
|
type ColumnDefinition,
|
|
38
41
|
type GridNode,
|
|
42
|
+
type DropTarget,
|
|
39
43
|
} from '@proyecto-viviana/solid-stately';
|
|
40
44
|
import {
|
|
41
45
|
type RenderChildren,
|
|
@@ -45,6 +49,16 @@ import {
|
|
|
45
49
|
useRenderProps,
|
|
46
50
|
filterDOMProps,
|
|
47
51
|
} from './utils';
|
|
52
|
+
import { SharedElementTransition } from './SharedElementTransition';
|
|
53
|
+
import { type DragAndDropHooks } from './useDragAndDrop';
|
|
54
|
+
import { CollectionRendererContext, type CollectionRendererContextValue, useCollectionRenderer } from './Collection';
|
|
55
|
+
import { useVirtualizerContext } from './Virtualizer';
|
|
56
|
+
import {
|
|
57
|
+
getNormalizedDropTargetKey,
|
|
58
|
+
mergePersistedKeysIntoVirtualRange,
|
|
59
|
+
useDndPersistedKeys,
|
|
60
|
+
useRenderDropIndicator,
|
|
61
|
+
} from './DragAndDrop';
|
|
48
62
|
|
|
49
63
|
// ============================================
|
|
50
64
|
// TYPES
|
|
@@ -94,6 +108,8 @@ export interface TableProps<T extends object> extends Omit<AriaTableProps, 'chil
|
|
|
94
108
|
style?: StyleOrFunction<TableRenderProps>;
|
|
95
109
|
/** A function to render when the table is empty. */
|
|
96
110
|
renderEmptyState?: () => JSX.Element;
|
|
111
|
+
/** Drag and drop hooks from `useDragAndDrop`. */
|
|
112
|
+
dragAndDropHooks?: DragAndDropHooks<T>;
|
|
97
113
|
}
|
|
98
114
|
|
|
99
115
|
export interface TableHeaderRenderProps {
|
|
@@ -152,6 +168,12 @@ export interface TableBodyProps<T> extends SlotProps {
|
|
|
152
168
|
style?: StyleOrFunction<TableBodyRenderProps>;
|
|
153
169
|
/** A function to render when the body is empty. */
|
|
154
170
|
renderEmptyState?: () => JSX.Element;
|
|
171
|
+
/** Whether there are more rows to load. */
|
|
172
|
+
hasMore?: boolean;
|
|
173
|
+
/** Whether additional rows are currently loading. */
|
|
174
|
+
isLoading?: boolean;
|
|
175
|
+
/** Called when the load more sentinel becomes visible. */
|
|
176
|
+
onLoadMore?: () => void | Promise<void>;
|
|
155
177
|
}
|
|
156
178
|
|
|
157
179
|
export interface TableRowRenderProps {
|
|
@@ -206,6 +228,15 @@ export interface TableCellProps extends SlotProps {
|
|
|
206
228
|
style?: StyleOrFunction<TableCellRenderProps>;
|
|
207
229
|
}
|
|
208
230
|
|
|
231
|
+
export interface TableLoadMoreItemProps extends SlotProps {
|
|
232
|
+
onLoadMore: () => void | Promise<void>;
|
|
233
|
+
isLoading?: boolean;
|
|
234
|
+
colSpan?: number;
|
|
235
|
+
children?: JSX.Element;
|
|
236
|
+
class?: ClassNameOrFunction<{ isLoading: boolean }>;
|
|
237
|
+
style?: StyleOrFunction<{ isLoading: boolean }>;
|
|
238
|
+
}
|
|
239
|
+
|
|
209
240
|
// ============================================
|
|
210
241
|
// CONTEXT
|
|
211
242
|
// ============================================
|
|
@@ -217,10 +248,14 @@ interface TableContextValue<T extends object> {
|
|
|
217
248
|
columns: ColumnDefinition<T>[];
|
|
218
249
|
isDisabled: boolean;
|
|
219
250
|
showSelectionCheckboxes: boolean;
|
|
251
|
+
dragAndDropHooks?: DragAndDropHooks<T>;
|
|
252
|
+
dragState?: unknown;
|
|
253
|
+
dropState?: unknown;
|
|
220
254
|
}
|
|
221
255
|
|
|
222
256
|
export const TableContext = createContext<TableContextValue<object> | null>(null);
|
|
223
257
|
export const TableStateContext = createContext<TableState<object, TableCollection<object>> | null>(null);
|
|
258
|
+
export const TableColumnResizeStateContext = createContext<null>(null);
|
|
224
259
|
|
|
225
260
|
// Row-level context for cells
|
|
226
261
|
interface TableRowContextValue {
|
|
@@ -241,7 +276,7 @@ export const TableRowContext = createContext<TableRowContextValue | null>(null);
|
|
|
241
276
|
export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
242
277
|
const [local, stateProps, ariaProps] = splitProps(
|
|
243
278
|
props,
|
|
244
|
-
['class', 'style', 'slot', 'renderEmptyState'],
|
|
279
|
+
['class', 'style', 'slot', 'renderEmptyState', 'dragAndDropHooks'],
|
|
245
280
|
[
|
|
246
281
|
'items',
|
|
247
282
|
'columns',
|
|
@@ -312,10 +347,10 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
312
347
|
isEmpty: stateProps.items.length === 0,
|
|
313
348
|
}));
|
|
314
349
|
|
|
315
|
-
// Resolve render props
|
|
350
|
+
// Resolve render props (class and style only — children rendered directly in JSX
|
|
351
|
+
// to avoid eager evaluation before context providers mount)
|
|
316
352
|
const renderProps = useRenderProps(
|
|
317
353
|
{
|
|
318
|
-
children: props.children,
|
|
319
354
|
class: local.class,
|
|
320
355
|
style: local.style,
|
|
321
356
|
defaultClassName: 'solidaria-Table',
|
|
@@ -338,6 +373,98 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
338
373
|
const { ref: _ref2, ...rest } = focusProps as Record<string, unknown>;
|
|
339
374
|
return rest;
|
|
340
375
|
};
|
|
376
|
+
const parentCollectionRenderer = useCollectionRenderer<T>();
|
|
377
|
+
const getItemNodes = createMemo(() => Array.from(state.collection).filter((node) => node.type === 'item'));
|
|
378
|
+
const getDropTargetByIndex = (index: number, position: 'before' | 'after' | 'on'): DropTarget | null => {
|
|
379
|
+
const node = getItemNodes()[index];
|
|
380
|
+
if (!node) return null;
|
|
381
|
+
return { type: 'item', key: node.key, dropPosition: position };
|
|
382
|
+
};
|
|
383
|
+
const hasDroppableDnd = createMemo(() => {
|
|
384
|
+
const hooks = local.dragAndDropHooks;
|
|
385
|
+
return Boolean(
|
|
386
|
+
hooks?.useDroppableCollectionState &&
|
|
387
|
+
hooks.useDroppableCollection &&
|
|
388
|
+
(hooks.dropTargetDelegate || parentCollectionRenderer?.dropTargetDelegate || hooks.ListDropTargetDelegate)
|
|
389
|
+
);
|
|
390
|
+
});
|
|
391
|
+
const hasDraggableDnd = createMemo(() => {
|
|
392
|
+
const hooks = local.dragAndDropHooks;
|
|
393
|
+
return Boolean(hooks?.useDraggableCollectionState && hooks.useDraggableCollection);
|
|
394
|
+
});
|
|
395
|
+
const dragState = createMemo(() => {
|
|
396
|
+
if (!hasDraggableDnd()) return undefined;
|
|
397
|
+
return local.dragAndDropHooks?.useDraggableCollectionState?.({
|
|
398
|
+
items: stateProps.items,
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
const dropState = createMemo(() => {
|
|
402
|
+
if (!hasDroppableDnd()) return undefined;
|
|
403
|
+
return local.dragAndDropHooks?.useDroppableCollectionState?.({});
|
|
404
|
+
});
|
|
405
|
+
createEffect(() => {
|
|
406
|
+
if (!hasDraggableDnd()) return;
|
|
407
|
+
const hooks = local.dragAndDropHooks;
|
|
408
|
+
const activeDragState = dragState();
|
|
409
|
+
if (!hooks?.useDraggableCollection || !activeDragState) return;
|
|
410
|
+
hooks.useDraggableCollection({}, activeDragState, () => ref());
|
|
411
|
+
});
|
|
412
|
+
const droppableCollection = createMemo(() => {
|
|
413
|
+
if (!hasDroppableDnd()) return undefined;
|
|
414
|
+
const hooks = local.dragAndDropHooks;
|
|
415
|
+
const activeDropState = dropState();
|
|
416
|
+
if (!hooks?.useDroppableCollection || !activeDropState) return undefined;
|
|
417
|
+
const resolveDirection = (): 'ltr' | 'rtl' => {
|
|
418
|
+
const el = ref();
|
|
419
|
+
if (el && typeof window !== 'undefined' && typeof window.getComputedStyle === 'function') {
|
|
420
|
+
const dir = window.getComputedStyle(el).direction;
|
|
421
|
+
if (dir === 'rtl') return 'rtl';
|
|
422
|
+
}
|
|
423
|
+
return typeof document !== 'undefined' && document.dir === 'rtl' ? 'rtl' : 'ltr';
|
|
424
|
+
};
|
|
425
|
+
const dropTargetDelegate = hooks.dropTargetDelegate
|
|
426
|
+
?? parentCollectionRenderer?.dropTargetDelegate
|
|
427
|
+
?? (hooks.ListDropTargetDelegate
|
|
428
|
+
? new hooks.ListDropTargetDelegate(
|
|
429
|
+
() => state.collection,
|
|
430
|
+
() => ref(),
|
|
431
|
+
{ layout: 'grid', orientation: 'vertical', direction: resolveDirection() }
|
|
432
|
+
)
|
|
433
|
+
: undefined);
|
|
434
|
+
if (!dropTargetDelegate) return undefined;
|
|
435
|
+
return hooks.useDroppableCollection(
|
|
436
|
+
{
|
|
437
|
+
dropTargetDelegate,
|
|
438
|
+
keyboardDelegate: {
|
|
439
|
+
getFirstKey: () => state.collection.getFirstKey?.() ?? null,
|
|
440
|
+
getLastKey: () => state.collection.getLastKey?.() ?? null,
|
|
441
|
+
getKeyBelow: (key) => state.collection.getKeyAfter?.(key) ?? null,
|
|
442
|
+
getKeyAbove: (key) => state.collection.getKeyBefore?.(key) ?? null,
|
|
443
|
+
getKeyLeftOf: (key) =>
|
|
444
|
+
resolveDirection() === 'rtl'
|
|
445
|
+
? state.collection.getKeyAfter?.(key) ?? null
|
|
446
|
+
: state.collection.getKeyBefore?.(key) ?? null,
|
|
447
|
+
getKeyRightOf: (key) =>
|
|
448
|
+
resolveDirection() === 'rtl'
|
|
449
|
+
? state.collection.getKeyBefore?.(key) ?? null
|
|
450
|
+
: state.collection.getKeyAfter?.(key) ?? null,
|
|
451
|
+
getKeyPageBelow: (key) => state.collection.getKeyAfter?.(key) ?? null,
|
|
452
|
+
getKeyPageAbove: (key) => state.collection.getKeyBefore?.(key) ?? null,
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
activeDropState,
|
|
456
|
+
() => ref()
|
|
457
|
+
);
|
|
458
|
+
});
|
|
459
|
+
const isRootDropTarget = createMemo(() => {
|
|
460
|
+
return Boolean(dropState()?.target?.type === 'root');
|
|
461
|
+
});
|
|
462
|
+
const dndRenderDropIndicator = createMemo(() => useRenderDropIndicator(local.dragAndDropHooks, dropState()));
|
|
463
|
+
const dndDropIndicator = (index: number, position: 'before' | 'after' | 'on') => {
|
|
464
|
+
const target = getDropTargetByIndex(index, position);
|
|
465
|
+
if (!target || target.type !== 'item') return undefined;
|
|
466
|
+
return dndRenderDropIndicator()?.(target);
|
|
467
|
+
};
|
|
341
468
|
|
|
342
469
|
const contextValue = createMemo<TableContextValue<T>>(() => ({
|
|
343
470
|
state,
|
|
@@ -346,24 +473,41 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
346
473
|
columns: stateProps.columns,
|
|
347
474
|
isDisabled: false,
|
|
348
475
|
showSelectionCheckboxes: stateProps.showSelectionCheckboxes ?? false,
|
|
476
|
+
dragAndDropHooks: local.dragAndDropHooks,
|
|
477
|
+
dragState: dragState(),
|
|
478
|
+
dropState: dropState(),
|
|
479
|
+
}));
|
|
480
|
+
const collectionRenderer = createMemo<CollectionRendererContextValue<unknown>>(() => ({
|
|
481
|
+
...parentCollectionRenderer,
|
|
482
|
+
renderItem: (item) => item as JSX.Element,
|
|
483
|
+
renderDropIndicator: (index: number, position: 'before' | 'after' | 'on') =>
|
|
484
|
+
dndDropIndicator(index, position) ?? parentCollectionRenderer?.renderDropIndicator?.(index, position),
|
|
349
485
|
}));
|
|
350
486
|
|
|
351
487
|
return (
|
|
352
|
-
<TableContext.Provider value={contextValue() as TableContextValue<object>}>
|
|
488
|
+
<TableContext.Provider value={contextValue() as unknown as TableContextValue<object>}>
|
|
353
489
|
<TableStateContext.Provider value={state as unknown as TableState<object, TableCollection<object>>}>
|
|
354
|
-
<
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
490
|
+
<CollectionRendererContext.Provider value={collectionRenderer()}>
|
|
491
|
+
<table
|
|
492
|
+
ref={setRef}
|
|
493
|
+
{...mergeProps(
|
|
494
|
+
domProps(),
|
|
495
|
+
cleanGridProps(),
|
|
496
|
+
cleanFocusProps(),
|
|
497
|
+
(droppableCollection()?.collectionProps as Record<string, unknown> | undefined) ?? {}
|
|
498
|
+
)}
|
|
499
|
+
class={renderProps.class()}
|
|
500
|
+
style={renderProps.style()}
|
|
501
|
+
data-focused={state.isFocused || undefined}
|
|
502
|
+
data-focus-visible={isFocusVisible() || undefined}
|
|
503
|
+
data-empty={stateProps.items.length === 0 || undefined}
|
|
504
|
+
data-drop-target={isRootDropTarget() || undefined}
|
|
505
|
+
>
|
|
506
|
+
{typeof props.children === 'function'
|
|
507
|
+
? props.children(renderValues())
|
|
508
|
+
: props.children}
|
|
509
|
+
</table>
|
|
510
|
+
</CollectionRendererContext.Provider>
|
|
367
511
|
</TableStateContext.Provider>
|
|
368
512
|
</TableContext.Provider>
|
|
369
513
|
);
|
|
@@ -373,7 +517,7 @@ export function Table<T extends object>(props: TableProps<T>): JSX.Element {
|
|
|
373
517
|
* A header row in a table containing column headers.
|
|
374
518
|
*/
|
|
375
519
|
export function TableHeader(props: TableHeaderProps): JSX.Element {
|
|
376
|
-
const [local] = splitProps(props, ['class', 'style', 'slot']);
|
|
520
|
+
const [local, domProps] = splitProps(props, ['class', 'style', 'slot', 'children']);
|
|
377
521
|
|
|
378
522
|
// Get context
|
|
379
523
|
const context = useContext(TableContext);
|
|
@@ -404,8 +548,8 @@ export function TableHeader(props: TableHeaderProps): JSX.Element {
|
|
|
404
548
|
};
|
|
405
549
|
|
|
406
550
|
return (
|
|
407
|
-
<thead {...cleanRowGroupProps()} class={renderProps.class()} style={renderProps.style()}>
|
|
408
|
-
<tr role="row">{
|
|
551
|
+
<thead {...domProps} {...cleanRowGroupProps()} class={renderProps.class()} style={renderProps.style()}>
|
|
552
|
+
<tr role="row">{local.children}</tr>
|
|
409
553
|
</thead>
|
|
410
554
|
);
|
|
411
555
|
}
|
|
@@ -414,7 +558,7 @@ export function TableHeader(props: TableHeaderProps): JSX.Element {
|
|
|
414
558
|
* A column header in a table.
|
|
415
559
|
*/
|
|
416
560
|
export function TableColumn(props: TableColumnProps): JSX.Element {
|
|
417
|
-
const [local] = splitProps(props, ['class', 'style', 'slot', 'id', 'allowsSorting']);
|
|
561
|
+
const [local, domProps] = splitProps(props, ['class', 'style', 'slot', 'id', 'allowsSorting', 'children']);
|
|
418
562
|
|
|
419
563
|
// Get context
|
|
420
564
|
const context = useContext(TableContext);
|
|
@@ -446,7 +590,7 @@ export function TableColumn(props: TableColumnProps): JSX.Element {
|
|
|
446
590
|
});
|
|
447
591
|
|
|
448
592
|
// Create column header aria props
|
|
449
|
-
const
|
|
593
|
+
const columnHeaderAria = createTableColumnHeader<object>(
|
|
450
594
|
() => ({
|
|
451
595
|
node: columnNode(),
|
|
452
596
|
allowsSorting: local.allowsSorting,
|
|
@@ -481,10 +625,9 @@ export function TableColumn(props: TableColumnProps): JSX.Element {
|
|
|
481
625
|
isHovered: isHovered(),
|
|
482
626
|
}));
|
|
483
627
|
|
|
484
|
-
// Resolve render props
|
|
628
|
+
// Resolve render props (children rendered directly in JSX to avoid eager evaluation)
|
|
485
629
|
const renderProps = useRenderProps(
|
|
486
630
|
{
|
|
487
|
-
children: props.children,
|
|
488
631
|
class: local.class,
|
|
489
632
|
style: local.style,
|
|
490
633
|
defaultClassName: 'solidaria-Table-column',
|
|
@@ -494,7 +637,7 @@ export function TableColumn(props: TableColumnProps): JSX.Element {
|
|
|
494
637
|
|
|
495
638
|
// Remove ref from spread props
|
|
496
639
|
const cleanColumnHeaderProps = () => {
|
|
497
|
-
const { ref: _ref1, ...rest } = columnHeaderProps as Record<string, unknown>;
|
|
640
|
+
const { ref: _ref1, ...rest } = columnHeaderAria.columnHeaderProps as Record<string, unknown>;
|
|
498
641
|
return rest;
|
|
499
642
|
};
|
|
500
643
|
const cleanHoverProps = () => {
|
|
@@ -509,6 +652,7 @@ export function TableColumn(props: TableColumnProps): JSX.Element {
|
|
|
509
652
|
return (
|
|
510
653
|
<th
|
|
511
654
|
ref={setRef}
|
|
655
|
+
{...domProps}
|
|
512
656
|
{...cleanColumnHeaderProps()}
|
|
513
657
|
{...cleanHoverProps()}
|
|
514
658
|
{...cleanFocusProps()}
|
|
@@ -520,7 +664,9 @@ export function TableColumn(props: TableColumnProps): JSX.Element {
|
|
|
520
664
|
data-focused={state.focusedKey === local.id || undefined}
|
|
521
665
|
data-focus-visible={(isFocusVisible() && state.focusedKey === local.id) || undefined}
|
|
522
666
|
>
|
|
523
|
-
{
|
|
667
|
+
{typeof local.children === 'function'
|
|
668
|
+
? local.children(renderValues())
|
|
669
|
+
: local.children}
|
|
524
670
|
</th>
|
|
525
671
|
);
|
|
526
672
|
}
|
|
@@ -529,7 +675,7 @@ export function TableColumn(props: TableColumnProps): JSX.Element {
|
|
|
529
675
|
* The body of a table containing data rows.
|
|
530
676
|
*/
|
|
531
677
|
export function TableBody<T extends object>(props: TableBodyProps<T>): JSX.Element {
|
|
532
|
-
const [local] = splitProps(props, ['items', 'class', 'style', 'slot', 'renderEmptyState']);
|
|
678
|
+
const [local, domProps] = splitProps(props, ['items', 'class', 'style', 'slot', 'renderEmptyState', 'hasMore', 'isLoading', 'onLoadMore', 'children']);
|
|
533
679
|
|
|
534
680
|
// Get context
|
|
535
681
|
const context = useContext(TableContext);
|
|
@@ -563,21 +709,173 @@ export function TableBody<T extends object>(props: TableBodyProps<T>): JSX.Eleme
|
|
|
563
709
|
};
|
|
564
710
|
|
|
565
711
|
const isEmpty = () => items().length === 0;
|
|
712
|
+
const virtualizer = useVirtualizerContext();
|
|
713
|
+
const parentCollectionRenderer = useCollectionRenderer<T>();
|
|
714
|
+
const rowNodes = createMemo(() => Array.from(context.collection).filter((node) => node.type === 'item'));
|
|
715
|
+
const persistedKeys = useDndPersistedKeys(
|
|
716
|
+
{ focusedKey: () => context.state.focusedKey },
|
|
717
|
+
context.dragAndDropHooks,
|
|
718
|
+
context.dropState as { target?: DropTarget | null } | undefined,
|
|
719
|
+
context.collection
|
|
720
|
+
);
|
|
721
|
+
const virtualRange = createMemo(() => {
|
|
722
|
+
if (!virtualizer || !parentCollectionRenderer?.isVirtualized) return null;
|
|
723
|
+
const rowCount = items().length;
|
|
724
|
+
const baseRange = virtualizer.getVisibleRange(rowCount);
|
|
725
|
+
const persistedIndexes = Array.from(persistedKeys())
|
|
726
|
+
.map((key) => rowNodes().findIndex((node) => node.key === key))
|
|
727
|
+
.filter((index) => index >= 0);
|
|
728
|
+
const dropTarget = (context.dropState as { target?: DropTarget | null } | undefined)?.target;
|
|
729
|
+
const normalizedDropKey = getNormalizedDropTargetKey(dropTarget, context.collection);
|
|
730
|
+
const focusedKey = context.state.focusedKey;
|
|
731
|
+
const focusedIndex = focusedKey != null ? rowNodes().findIndex((node) => node.key === focusedKey) : -1;
|
|
732
|
+
const forceIncludeIndexes = [
|
|
733
|
+
dropTarget?.type === 'item' ? rowNodes().findIndex((node) => node.key === dropTarget.key) : -1,
|
|
734
|
+
normalizedDropKey != null ? rowNodes().findIndex((node) => node.key === normalizedDropKey) : -1,
|
|
735
|
+
dropTarget?.type === 'item' ? -1 : focusedIndex,
|
|
736
|
+
].filter((index) => index >= 0);
|
|
737
|
+
return mergePersistedKeysIntoVirtualRange(baseRange, persistedIndexes, rowCount, virtualizer, 80, {
|
|
738
|
+
forceIncludeIndexes,
|
|
739
|
+
forceIncludeMaxSpan: 320,
|
|
740
|
+
});
|
|
741
|
+
});
|
|
742
|
+
createEffect(() => {
|
|
743
|
+
if (!virtualizer || !parentCollectionRenderer?.isVirtualized) return;
|
|
744
|
+
virtualizer.setDropTargetItemCountResolver(() => items().length);
|
|
745
|
+
virtualizer.setDropTargetIndexResolver((key) => {
|
|
746
|
+
const index = rowNodes().findIndex((node) => node.key === key);
|
|
747
|
+
return index >= 0 ? index : null;
|
|
748
|
+
});
|
|
749
|
+
virtualizer.setDropTargetResolver((target) => {
|
|
750
|
+
const node = rowNodes()[target.index];
|
|
751
|
+
if (!node) return target;
|
|
752
|
+
return {
|
|
753
|
+
...target,
|
|
754
|
+
key: typeof node.key === 'string' || typeof node.key === 'number' ? node.key : undefined,
|
|
755
|
+
};
|
|
756
|
+
});
|
|
757
|
+
onCleanup(() => {
|
|
758
|
+
virtualizer.setDropTargetIndexResolver(undefined);
|
|
759
|
+
virtualizer.setDropTargetItemCountResolver(undefined);
|
|
760
|
+
virtualizer.setDropTargetResolver(undefined);
|
|
761
|
+
});
|
|
762
|
+
});
|
|
763
|
+
const visibleItems = createMemo(() => {
|
|
764
|
+
const range = virtualRange();
|
|
765
|
+
if (!range) return items();
|
|
766
|
+
return items().slice(range.start, range.end);
|
|
767
|
+
});
|
|
768
|
+
const spacerColSpan = () => context.columns.length + (context.showSelectionCheckboxes ? 1 : 0);
|
|
566
769
|
|
|
567
770
|
return (
|
|
568
|
-
<tbody {...cleanRowGroupProps()} class={renderProps.class()} style={renderProps.style()}>
|
|
569
|
-
<
|
|
771
|
+
<tbody {...domProps} {...cleanRowGroupProps()} class={renderProps.class()} style={renderProps.style()}>
|
|
772
|
+
<SharedElementTransition>
|
|
773
|
+
<Show when={isEmpty() && local.renderEmptyState} fallback={
|
|
774
|
+
<>
|
|
775
|
+
{virtualRange()?.offsetTop
|
|
776
|
+
? (
|
|
777
|
+
<tr role="presentation" aria-hidden="true" data-virtualizer-spacer="top">
|
|
778
|
+
<td colSpan={spacerColSpan()} style={{ height: `${virtualRange()!.offsetTop}px`, padding: '0', border: '0' }} />
|
|
779
|
+
</tr>
|
|
780
|
+
)
|
|
781
|
+
: null}
|
|
782
|
+
<For each={visibleItems()}>
|
|
783
|
+
{(item, index) => {
|
|
784
|
+
const itemIndex = () => (virtualRange()?.start ?? 0) + index();
|
|
785
|
+
const beforeIndicator = () => parentCollectionRenderer?.renderDropIndicator?.(itemIndex(), 'before');
|
|
786
|
+
const onIndicator = () => parentCollectionRenderer?.renderDropIndicator?.(itemIndex(), 'on');
|
|
787
|
+
const afterIndicator = () => parentCollectionRenderer?.renderDropIndicator?.(itemIndex(), 'after');
|
|
788
|
+
return (
|
|
789
|
+
<>
|
|
790
|
+
{beforeIndicator()}
|
|
791
|
+
{onIndicator()}
|
|
792
|
+
{local.children?.(item)}
|
|
793
|
+
{afterIndicator()}
|
|
794
|
+
</>
|
|
795
|
+
);
|
|
796
|
+
}}
|
|
797
|
+
</For>
|
|
798
|
+
{virtualRange()?.offsetBottom
|
|
799
|
+
? (
|
|
800
|
+
<tr role="presentation" aria-hidden="true" data-virtualizer-spacer="bottom">
|
|
801
|
+
<td colSpan={spacerColSpan()} style={{ height: `${virtualRange()!.offsetBottom}px`, padding: '0', border: '0' }} />
|
|
802
|
+
</tr>
|
|
803
|
+
)
|
|
804
|
+
: null}
|
|
805
|
+
</>
|
|
806
|
+
}>
|
|
570
807
|
{local.renderEmptyState?.()}
|
|
571
808
|
</Show>
|
|
809
|
+
</SharedElementTransition>
|
|
810
|
+
<Show when={local.hasMore && local.onLoadMore}>
|
|
811
|
+
<TableLoadMoreItem
|
|
812
|
+
onLoadMore={local.onLoadMore!}
|
|
813
|
+
isLoading={local.isLoading}
|
|
814
|
+
colSpan={spacerColSpan()}
|
|
815
|
+
/>
|
|
816
|
+
</Show>
|
|
572
817
|
</tbody>
|
|
573
818
|
);
|
|
574
819
|
}
|
|
575
820
|
|
|
821
|
+
export function TableLoadMoreItem(props: TableLoadMoreItemProps): JSX.Element {
|
|
822
|
+
let ref: HTMLTableRowElement | undefined;
|
|
823
|
+
const [isPending, setIsPending] = createSignal(false);
|
|
824
|
+
const isLoading = () => !!props.isLoading || isPending();
|
|
825
|
+
|
|
826
|
+
const triggerLoadMore = async () => {
|
|
827
|
+
if (isLoading()) return;
|
|
828
|
+
setIsPending(true);
|
|
829
|
+
try {
|
|
830
|
+
await props.onLoadMore();
|
|
831
|
+
} finally {
|
|
832
|
+
setIsPending(false);
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
createEffect(() => {
|
|
837
|
+
if (!ref || typeof IntersectionObserver !== 'function') return;
|
|
838
|
+
const observer = new IntersectionObserver((entries) => {
|
|
839
|
+
if (entries[0]?.isIntersecting) {
|
|
840
|
+
void triggerLoadMore();
|
|
841
|
+
}
|
|
842
|
+
});
|
|
843
|
+
observer.observe(ref);
|
|
844
|
+
return () => observer.disconnect();
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
const renderProps = useRenderProps(
|
|
848
|
+
{
|
|
849
|
+
children: props.children ?? (() => (isLoading() ? 'Loading more...' : 'Load more')),
|
|
850
|
+
class: props.class,
|
|
851
|
+
style: props.style,
|
|
852
|
+
defaultClassName: 'solidaria-Table-loadMore',
|
|
853
|
+
},
|
|
854
|
+
() => ({ isLoading: isLoading() })
|
|
855
|
+
);
|
|
856
|
+
|
|
857
|
+
return (
|
|
858
|
+
<tr
|
|
859
|
+
ref={ref}
|
|
860
|
+
role="row"
|
|
861
|
+
tabIndex={0}
|
|
862
|
+
onFocus={() => {
|
|
863
|
+
void triggerLoadMore();
|
|
864
|
+
}}
|
|
865
|
+
class={renderProps.class()}
|
|
866
|
+
style={renderProps.style()}
|
|
867
|
+
data-loading={isLoading() || undefined}
|
|
868
|
+
>
|
|
869
|
+
<td colSpan={props.colSpan ?? 1}>{renderProps.renderChildren()}</td>
|
|
870
|
+
</tr>
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
|
|
576
874
|
/**
|
|
577
875
|
* A row in a table.
|
|
578
876
|
*/
|
|
579
877
|
export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element {
|
|
580
|
-
const [local] = splitProps(props, ['class', 'style', 'slot', 'id', 'item', 'onAction']);
|
|
878
|
+
const [local, domProps] = splitProps(props, ['class', 'style', 'slot', 'id', 'item', 'onAction', 'children']);
|
|
581
879
|
|
|
582
880
|
// Get context
|
|
583
881
|
const context = useContext(TableContext);
|
|
@@ -585,6 +883,7 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
585
883
|
throw new Error('TableRow must be used within a Table');
|
|
586
884
|
}
|
|
587
885
|
const { state, collection } = context;
|
|
886
|
+
const tableContext = context as unknown as TableContextValue<T>;
|
|
588
887
|
|
|
589
888
|
// Create ref signal
|
|
590
889
|
const [ref, setRef] = createSignal<HTMLTableRowElement | null>(null);
|
|
@@ -609,7 +908,7 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
609
908
|
});
|
|
610
909
|
|
|
611
910
|
// Create row aria props
|
|
612
|
-
const
|
|
911
|
+
const rowAria = createTableRow<object>(
|
|
613
912
|
() => ({
|
|
614
913
|
node: rowNode(),
|
|
615
914
|
onAction: local.onAction,
|
|
@@ -617,11 +916,14 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
617
916
|
() => state as TableState<object, TableCollection<object>>,
|
|
618
917
|
ref
|
|
619
918
|
);
|
|
919
|
+
const isSelected = () => rowAria.isSelected;
|
|
920
|
+
const isDisabled = () => rowAria.isDisabled;
|
|
921
|
+
const isPressed = () => rowAria.isPressed;
|
|
620
922
|
|
|
621
923
|
// Create hover
|
|
622
924
|
const { isHovered, hoverProps } = createHover({
|
|
623
925
|
get isDisabled() {
|
|
624
|
-
return isDisabled;
|
|
926
|
+
return isDisabled();
|
|
625
927
|
},
|
|
626
928
|
});
|
|
627
929
|
|
|
@@ -630,21 +932,39 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
630
932
|
|
|
631
933
|
// Check if focused
|
|
632
934
|
const isFocused = createMemo(() => state.focusedKey === local.id);
|
|
935
|
+
const draggableItem = createMemo(() => {
|
|
936
|
+
if (!tableContext.dragAndDropHooks?.useDraggableItem || !tableContext.dragState) return undefined;
|
|
937
|
+
return tableContext.dragAndDropHooks.useDraggableItem(
|
|
938
|
+
{
|
|
939
|
+
key: local.id as string | number,
|
|
940
|
+
},
|
|
941
|
+
tableContext.dragState as Parameters<NonNullable<DragAndDropHooks<T>['useDraggableItem']>>[1]
|
|
942
|
+
);
|
|
943
|
+
});
|
|
944
|
+
const droppableItem = createMemo(() => {
|
|
945
|
+
if (!tableContext.dragAndDropHooks?.useDroppableItem || !tableContext.dropState) return undefined;
|
|
946
|
+
return tableContext.dragAndDropHooks.useDroppableItem(
|
|
947
|
+
{
|
|
948
|
+
key: local.id as string | number,
|
|
949
|
+
},
|
|
950
|
+
tableContext.dropState as Parameters<NonNullable<DragAndDropHooks<T>['useDroppableItem']>>[1],
|
|
951
|
+
() => ref()
|
|
952
|
+
);
|
|
953
|
+
});
|
|
633
954
|
|
|
634
955
|
// Render props values
|
|
635
956
|
const renderValues = createMemo<TableRowRenderProps>(() => ({
|
|
636
|
-
isSelected,
|
|
957
|
+
isSelected: isSelected(),
|
|
637
958
|
isFocused: isFocused(),
|
|
638
959
|
isFocusVisible: isFocusVisible() && isFocused(),
|
|
639
|
-
isPressed,
|
|
960
|
+
isPressed: isPressed(),
|
|
640
961
|
isHovered: isHovered(),
|
|
641
|
-
isDisabled,
|
|
962
|
+
isDisabled: isDisabled(),
|
|
642
963
|
}));
|
|
643
964
|
|
|
644
|
-
// Resolve render props
|
|
965
|
+
// Resolve render props (children rendered directly in JSX to avoid eager evaluation)
|
|
645
966
|
const renderProps = useRenderProps(
|
|
646
967
|
{
|
|
647
|
-
children: props.children,
|
|
648
968
|
class: local.class,
|
|
649
969
|
style: local.style,
|
|
650
970
|
defaultClassName: 'solidaria-Table-row',
|
|
@@ -654,7 +974,7 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
654
974
|
|
|
655
975
|
// Remove ref from spread props
|
|
656
976
|
const cleanRowProps = () => {
|
|
657
|
-
const { ref: _ref1, ...rest } = rowProps as Record<string, unknown>;
|
|
977
|
+
const { ref: _ref1, ...rest } = rowAria.rowProps as Record<string, unknown>;
|
|
658
978
|
return rest;
|
|
659
979
|
};
|
|
660
980
|
const cleanHoverProps = () => {
|
|
@@ -675,19 +995,28 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
675
995
|
<TableRowContext.Provider value={rowContextValue}>
|
|
676
996
|
<tr
|
|
677
997
|
ref={setRef}
|
|
678
|
-
{...
|
|
679
|
-
{...
|
|
680
|
-
|
|
998
|
+
{...domProps}
|
|
999
|
+
{...mergeProps(
|
|
1000
|
+
cleanRowProps(),
|
|
1001
|
+
cleanHoverProps(),
|
|
1002
|
+
cleanFocusProps(),
|
|
1003
|
+
(draggableItem()?.dragProps as Record<string, unknown> | undefined) ?? {},
|
|
1004
|
+
(droppableItem()?.dropProps as Record<string, unknown> | undefined) ?? {}
|
|
1005
|
+
)}
|
|
681
1006
|
class={renderProps.class()}
|
|
682
1007
|
style={renderProps.style()}
|
|
683
|
-
data-selected={isSelected || undefined}
|
|
1008
|
+
data-selected={isSelected() || undefined}
|
|
684
1009
|
data-focused={isFocused() || undefined}
|
|
685
1010
|
data-focus-visible={(isFocusVisible() && isFocused()) || undefined}
|
|
686
|
-
data-pressed={isPressed || undefined}
|
|
1011
|
+
data-pressed={isPressed() || undefined}
|
|
687
1012
|
data-hovered={isHovered() || undefined}
|
|
688
|
-
data-disabled={isDisabled || undefined}
|
|
1013
|
+
data-disabled={isDisabled() || undefined}
|
|
1014
|
+
data-dragging={draggableItem()?.isDragging || undefined}
|
|
1015
|
+
data-drop-target={droppableItem()?.isDropTarget || undefined}
|
|
689
1016
|
>
|
|
690
|
-
{
|
|
1017
|
+
{typeof local.children === 'function'
|
|
1018
|
+
? local.children(renderValues())
|
|
1019
|
+
: local.children}
|
|
691
1020
|
</tr>
|
|
692
1021
|
</TableRowContext.Provider>
|
|
693
1022
|
);
|
|
@@ -697,7 +1026,7 @@ export function TableRow<T extends object>(props: TableRowProps<T>): JSX.Element
|
|
|
697
1026
|
* A cell in a table row.
|
|
698
1027
|
*/
|
|
699
1028
|
export function TableCell(props: TableCellProps): JSX.Element {
|
|
700
|
-
const [local] = splitProps(props, ['class', 'style', 'slot', 'id']);
|
|
1029
|
+
const [local, domProps] = splitProps(props, ['class', 'style', 'slot', 'id', 'children']);
|
|
701
1030
|
|
|
702
1031
|
// Get context
|
|
703
1032
|
const tableContext = useContext(TableContext);
|
|
@@ -740,13 +1069,14 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
740
1069
|
});
|
|
741
1070
|
|
|
742
1071
|
// Create cell aria props
|
|
743
|
-
const
|
|
1072
|
+
const cellAria = createTableCell<object>(
|
|
744
1073
|
() => ({
|
|
745
1074
|
node: cellNode(),
|
|
746
1075
|
}),
|
|
747
1076
|
() => state as TableState<object, TableCollection<object>>,
|
|
748
1077
|
ref
|
|
749
1078
|
);
|
|
1079
|
+
const isPressed = () => cellAria.isPressed;
|
|
750
1080
|
|
|
751
1081
|
// Create hover
|
|
752
1082
|
const { isHovered, hoverProps } = createHover({
|
|
@@ -763,14 +1093,13 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
763
1093
|
const renderValues = createMemo<TableCellRenderProps>(() => ({
|
|
764
1094
|
isFocused: isFocused(),
|
|
765
1095
|
isFocusVisible: isFocusVisible() && isFocused(),
|
|
766
|
-
isPressed,
|
|
1096
|
+
isPressed: isPressed(),
|
|
767
1097
|
isHovered: isHovered(),
|
|
768
1098
|
}));
|
|
769
1099
|
|
|
770
|
-
// Resolve render props
|
|
1100
|
+
// Resolve render props (children rendered directly in JSX to avoid eager evaluation)
|
|
771
1101
|
const renderProps = useRenderProps(
|
|
772
1102
|
{
|
|
773
|
-
children: props.children,
|
|
774
1103
|
class: local.class,
|
|
775
1104
|
style: local.style,
|
|
776
1105
|
defaultClassName: 'solidaria-Table-cell',
|
|
@@ -780,7 +1109,7 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
780
1109
|
|
|
781
1110
|
// Remove ref from spread props
|
|
782
1111
|
const cleanCellProps = () => {
|
|
783
|
-
const { ref: _ref1, ...rest } = gridCellProps as Record<string, unknown>;
|
|
1112
|
+
const { ref: _ref1, ...rest } = cellAria.gridCellProps as Record<string, unknown>;
|
|
784
1113
|
return rest;
|
|
785
1114
|
};
|
|
786
1115
|
const cleanHoverProps = () => {
|
|
@@ -795,6 +1124,7 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
795
1124
|
return (
|
|
796
1125
|
<td
|
|
797
1126
|
ref={setRef}
|
|
1127
|
+
{...domProps}
|
|
798
1128
|
{...cleanCellProps()}
|
|
799
1129
|
{...cleanHoverProps()}
|
|
800
1130
|
{...cleanFocusProps()}
|
|
@@ -802,10 +1132,12 @@ export function TableCell(props: TableCellProps): JSX.Element {
|
|
|
802
1132
|
style={renderProps.style()}
|
|
803
1133
|
data-focused={isFocused() || undefined}
|
|
804
1134
|
data-focus-visible={(isFocusVisible() && isFocused()) || undefined}
|
|
805
|
-
data-pressed={isPressed || undefined}
|
|
1135
|
+
data-pressed={isPressed() || undefined}
|
|
806
1136
|
data-hovered={isHovered() || undefined}
|
|
807
1137
|
>
|
|
808
|
-
{
|
|
1138
|
+
{typeof local.children === 'function'
|
|
1139
|
+
? local.children(renderValues())
|
|
1140
|
+
: local.children}
|
|
809
1141
|
</td>
|
|
810
1142
|
);
|
|
811
1143
|
}
|
|
@@ -821,12 +1153,12 @@ export function TableSelectionCheckbox(props: { rowKey: Key }): JSX.Element {
|
|
|
821
1153
|
|
|
822
1154
|
const { state } = context;
|
|
823
1155
|
|
|
824
|
-
const
|
|
1156
|
+
const selectionCheckboxAria = createTableSelectionCheckbox<object>(
|
|
825
1157
|
() => ({ key: props.rowKey }),
|
|
826
1158
|
() => state as TableState<object, TableCollection<object>>
|
|
827
1159
|
);
|
|
828
1160
|
|
|
829
|
-
return <input {...checkboxProps} />;
|
|
1161
|
+
return <input {...selectionCheckboxAria.checkboxProps} />;
|
|
830
1162
|
}
|
|
831
1163
|
|
|
832
1164
|
/**
|
|
@@ -840,18 +1172,46 @@ export function TableSelectAllCheckbox(): JSX.Element {
|
|
|
840
1172
|
|
|
841
1173
|
const { state } = context;
|
|
842
1174
|
|
|
843
|
-
const
|
|
1175
|
+
const selectAllCheckboxAria = createTableSelectAllCheckbox<object>(
|
|
844
1176
|
() => state as TableState<object, TableCollection<object>>
|
|
845
1177
|
);
|
|
846
1178
|
|
|
847
|
-
return <input {...checkboxProps} />;
|
|
1179
|
+
return <input {...selectAllCheckboxAria.checkboxProps} />;
|
|
848
1180
|
}
|
|
849
1181
|
|
|
850
1182
|
// Attach components as static properties
|
|
851
1183
|
Table.Header = TableHeader;
|
|
852
1184
|
Table.Column = TableColumn;
|
|
853
1185
|
Table.Body = TableBody;
|
|
1186
|
+
Table.LoadMoreItem = TableLoadMoreItem;
|
|
854
1187
|
Table.Row = TableRow;
|
|
855
1188
|
Table.Cell = TableCell;
|
|
856
1189
|
Table.SelectionCheckbox = TableSelectionCheckbox;
|
|
857
1190
|
Table.SelectAllCheckbox = TableSelectAllCheckbox;
|
|
1191
|
+
|
|
1192
|
+
export interface ColumnResizerProps extends SlotProps {
|
|
1193
|
+
class?: string;
|
|
1194
|
+
style?: JSX.CSSProperties;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
export function ColumnResizer(props: ColumnResizerProps): JSX.Element {
|
|
1198
|
+
return <div role="separator" class={props.class ?? 'solidaria-Table-columnResizer'} style={props.style} />;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
export interface ResizableTableContainerProps extends SlotProps {
|
|
1202
|
+
children?: JSX.Element;
|
|
1203
|
+
class?: string;
|
|
1204
|
+
style?: JSX.CSSProperties;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
export function ResizableTableContainer(props: ResizableTableContainerProps): JSX.Element {
|
|
1208
|
+
return (
|
|
1209
|
+
<div class={props.class ?? 'solidaria-ResizableTableContainer'} style={props.style}>
|
|
1210
|
+
{props.children}
|
|
1211
|
+
</div>
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
export function useTableOptions() {
|
|
1216
|
+
return useContext(TableContext);
|
|
1217
|
+
}
|