@dxos/react-ui-table 0.4.10-main.e7449de → 0.4.10-main.e97ef17

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.
Files changed (37) hide show
  1. package/dist/lib/browser/index.mjs +259 -169
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts.map +1 -1
  5. package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts +5 -1
  6. package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -1
  7. package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts.map +1 -1
  8. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  9. package/dist/types/src/components/Table/Table.stories.d.ts +31 -0
  10. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  11. package/dist/types/src/helpers.d.ts.map +1 -1
  12. package/dist/types/src/hooks/index.d.ts +2 -0
  13. package/dist/types/src/hooks/index.d.ts.map +1 -1
  14. package/dist/types/src/hooks/useColumnSizing.d.ts +12 -0
  15. package/dist/types/src/hooks/useColumnSizing.d.ts.map +1 -0
  16. package/dist/types/src/hooks/usePinLastRow.d.ts +1 -1
  17. package/dist/types/src/hooks/usePinLastRow.d.ts.map +1 -1
  18. package/dist/types/src/hooks/useRowSelection.d.ts +7 -0
  19. package/dist/types/src/hooks/useRowSelection.d.ts.map +1 -0
  20. package/dist/types/src/schema/schema.d.ts.map +1 -1
  21. package/dist/types/src/schema/schemaToColumns.d.ts +1 -1
  22. package/dist/types/src/schema/schemaToColumns.d.ts.map +1 -1
  23. package/package.json +17 -16
  24. package/src/components/ColumnMenu/ColumnMenu.stories.tsx +30 -0
  25. package/src/components/ColumnMenu/ColumnMenu.tsx +34 -32
  26. package/src/components/ColumnMenu/ColumnSettingsForm.tsx +69 -63
  27. package/src/components/Table/Table.stories.tsx +162 -3
  28. package/src/components/Table/Table.tsx +35 -60
  29. package/src/helpers.tsx +9 -7
  30. package/src/hooks/index.ts +2 -0
  31. package/src/hooks/useColumnSizing.ts +45 -0
  32. package/src/hooks/usePinLastRow.ts +41 -20
  33. package/src/hooks/useRowSelection.ts +39 -0
  34. package/src/schema/SchemaToTable.stories.tsx +1 -1
  35. package/src/schema/schema.test.ts +1 -1
  36. package/src/schema/schema.ts +36 -37
  37. package/src/schema/schemaToColumns.ts +2 -1
@@ -92,7 +92,7 @@ var CellCombobox = ({ model, value, onValueChange }) => {
92
92
 
93
93
  // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnMenu.tsx
94
94
  import { X as X2, GearSix, CaretDown as CaretDown2, ArrowDown, ArrowUp } from "@phosphor-icons/react";
95
- import React3, { useRef as useRef2, useState as useState5, useCallback as useCallback2 } from "react";
95
+ import React3, { useRef as useRef2, useState as useState6, useCallback as useCallback5 } from "react";
96
96
  import { Button as Button2, DensityProvider, Popover as Popover2, DropdownMenu } from "@dxos/react-ui";
97
97
  import { getSize as getSize3, mx as mx3 } from "@dxos/react-ui-theme";
98
98
 
@@ -107,19 +107,21 @@ var Section = ({ children, className }) => /* @__PURE__ */ React2.createElement(
107
107
  className: mx2("p-2", className)
108
108
  }, children);
109
109
  var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onClose }) => {
110
- const [prop, setProp] = useState2(column.id);
111
- const [refTable, setRefTable] = useState2(column.refTable);
112
- const [refProp, setRefProp] = useState2(column.refProp);
113
- const [type, setType] = useState2(String(column.type));
114
- const [label, setLabel] = useState2(column.label);
115
- const [digits, setDigits] = useState2(String(column.digits ?? "0"));
110
+ const [formState, setFormState] = useState2({
111
+ prop: column.id,
112
+ refTable: column.refTable,
113
+ refProp: column.refProp,
114
+ type: String(column.type),
115
+ label: column.label,
116
+ digits: String(column.digits ?? "0")
117
+ });
116
118
  const propRef = useRef(null);
117
119
  const { t } = useTranslation2(translationKey);
118
120
  const handleCancel = () => {
119
- setProp(column.id);
120
121
  onClose?.();
121
122
  };
122
123
  const handleSave = () => {
124
+ const { prop, refTable, refProp, type, label, digits } = formState;
123
125
  if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {
124
126
  propRef.current?.focus();
125
127
  return;
@@ -131,7 +133,7 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
131
133
  return;
132
134
  }
133
135
  }
134
- onUpdate?.(prop, {
136
+ onUpdate?.(column.id, {
135
137
  id: prop,
136
138
  prop,
137
139
  label,
@@ -148,22 +150,30 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
148
150
  classNames: "mbe-1"
149
151
  }, t("column label label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
150
152
  placeholder: "Column label",
151
- value: label ?? "",
152
- onChange: (event) => setLabel(event.target.value),
153
+ value: formState.label ?? "",
154
+ onChange: (event) => setFormState((prevState) => ({
155
+ ...prevState,
156
+ label: event.target.value
157
+ })),
153
158
  autoFocus: true
154
159
  })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
155
160
  classNames: "mbe-1 mbs-3"
156
161
  }, t("property key label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
157
162
  ref: propRef,
158
163
  placeholder: "Property key",
159
- // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.
160
- value: prop ?? "",
161
- onChange: (event) => setProp(event.target.value.replace(/[^\w_]/g, ""))
164
+ value: formState.prop ?? "",
165
+ onChange: (event) => setFormState((prevState) => ({
166
+ ...prevState,
167
+ prop: event.target.value.replace(/[^\w_]/g, "")
168
+ }))
162
169
  })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
163
170
  classNames: "mbe-1 mbs-3"
164
171
  }, t("column type label")), /* @__PURE__ */ React2.createElement(Select.Root, {
165
- value: type,
166
- onValueChange: setType
172
+ value: formState.type,
173
+ onValueChange: (value) => setFormState((prevState) => ({
174
+ ...prevState,
175
+ type: value
176
+ }))
167
177
  }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
168
178
  placeholder: "Type",
169
179
  classNames: "is-full"
@@ -172,37 +182,46 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
172
182
  "boolean",
173
183
  "string",
174
184
  "ref"
175
- ].map((type2) => /* @__PURE__ */ React2.createElement(Select.Option, {
176
- key: type2,
177
- value: type2
178
- }, t(`${type2} column type label`))))))))), type === "number" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
185
+ ].map((type) => /* @__PURE__ */ React2.createElement(Select.Option, {
186
+ key: type,
187
+ value: type
188
+ }, t(`${type} column type label`))))))))), formState.type === "number" && /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
179
189
  classNames: "mbe-1 mbs-3"
180
190
  }, t("digits label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
181
- value: digits ?? "",
182
- onChange: (event) => setDigits(event.target.value)
183
- })))), type === "ref" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
191
+ value: formState.digits ?? "",
192
+ onChange: (event) => setFormState((prevState) => ({
193
+ ...prevState,
194
+ digits: event.target.value
195
+ }))
196
+ }))), formState.type === "ref" && /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
184
197
  classNames: "mbe-1 mbs-3"
185
198
  }, "Table"), /* @__PURE__ */ React2.createElement(Select.Root, {
186
- value: refTable,
187
- onValueChange: setRefTable
199
+ value: formState.refTable,
200
+ onValueChange: (value) => setFormState((prevState) => ({
201
+ ...prevState,
202
+ refTable: value
203
+ }))
188
204
  }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
189
205
  placeholder: "Table",
190
206
  classNames: "is-full"
191
207
  }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, tableDefs.filter((t2) => t2.id !== tableDef.id).map(({ id, name }) => /* @__PURE__ */ React2.createElement(Select.Option, {
192
208
  key: id,
193
209
  value: id
194
- }, name ?? id))))))), refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
210
+ }, name ?? id))))))), formState.refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
195
211
  classNames: "mbe-1 mbs-3"
196
212
  }, "Table property"), /* @__PURE__ */ React2.createElement(Select.Root, {
197
- value: refProp,
198
- onValueChange: setRefProp
213
+ value: formState.refProp,
214
+ onValueChange: (value) => setFormState((prevState) => ({
215
+ ...prevState,
216
+ refProp: value
217
+ }))
199
218
  }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
200
219
  placeholder: "Property",
201
220
  classNames: "is-full"
202
- }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, tableDefs.find((tableDef2) => tableDef2.id === refTable)?.columns.map(({ id, label: label2 }) => /* @__PURE__ */ React2.createElement(Select.Option, {
221
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, tableDefs.find((tableDef2) => tableDef2.id === formState.refTable)?.columns.map(({ id, label }) => /* @__PURE__ */ React2.createElement(Select.Option, {
203
222
  key: id,
204
223
  value: id
205
- }, label2 ?? id))))))))), /* @__PURE__ */ React2.createElement(Separator, {
224
+ }, label ?? id)))))))), /* @__PURE__ */ React2.createElement(Separator, {
206
225
  classNames: "mli-2"
207
226
  }), /* @__PURE__ */ React2.createElement(Section, {
208
227
  className: "space-b-1.5"
@@ -233,11 +252,44 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
233
252
  }))));
234
253
  };
235
254
 
255
+ // packages/ui/react-ui-table/src/hooks/useColumnSizing.ts
256
+ import { useCallback as useCallback2, useEffect, useState as useState3 } from "react";
257
+ import { useOnTransition } from "@dxos/react-ui";
258
+ var useColumnResizing = ({ columns, onColumnResize }) => {
259
+ const [columnsInitialised, setColumnsInitialised] = useState3(false);
260
+ const [columnSizing, setColumnSizing] = useState3({});
261
+ useEffect(() => {
262
+ if (columnsInitialised) {
263
+ return;
264
+ }
265
+ setColumnSizing(columns.filter((column) => !!column.size && column.prop !== void 0).reduce((state, column) => {
266
+ state[column.prop] = column.size;
267
+ return state;
268
+ }, {}));
269
+ setColumnsInitialised(true);
270
+ }, [
271
+ columns,
272
+ setColumnSizing
273
+ ]);
274
+ const [columnSizingInfo, setColumnSizingInfo] = useState3({});
275
+ const notifyColumnResize = useCallback2(() => onColumnResize?.(columnSizing), [
276
+ onColumnResize,
277
+ columnSizing
278
+ ]);
279
+ useOnTransition(columnSizingInfo.isResizingColumn, (v) => typeof v === "string", false, notifyColumnResize);
280
+ return {
281
+ columnSizing,
282
+ columnSizingInfo,
283
+ setColumnSizing,
284
+ setColumnSizingInfo
285
+ };
286
+ };
287
+
236
288
  // packages/ui/react-ui-table/src/hooks/useColumnSorting.ts
237
- import { useState as useState3 } from "react";
289
+ import { useState as useState4 } from "react";
238
290
  var useColumnSorting = (column) => {
239
- const [sortDirection, setSortDirection] = useState3(column.getIsSorted());
240
- const [firstSort, setFirstSort] = useState3();
291
+ const [sortDirection, setSortDirection] = useState4(column.getIsSorted());
292
+ const [firstSort, setFirstSort] = useState4();
241
293
  const canSort = column.getCanSort();
242
294
  const updateColumnSort = (direction) => {
243
295
  setSortDirection(direction);
@@ -280,57 +332,109 @@ var useColumnSorting = (column) => {
280
332
  };
281
333
 
282
334
  // packages/ui/react-ui-table/src/hooks/usePinLastRow.ts
283
- import { useEffect, useState as useState4 } from "react";
335
+ import { useCallback as useCallback3, useEffect as useEffect2, useState as useState5 } from "react";
284
336
  var usePinLastRow = (pinLastRow, table, data, getScrollElement) => {
285
- const [pinnedRowKey, setPinnedRowKey] = useState4();
286
- useEffect(() => {
287
- if (!pinLastRow) {
288
- return;
337
+ const [pinnedRowKey, setPinnedRowKey] = useState5();
338
+ const scrollToBottom = useCallback3(() => {
339
+ const scrollElement = getScrollElement?.();
340
+ if (scrollElement) {
341
+ requestAnimationFrame(() => scrollElement.scrollTo({
342
+ top: scrollElement.scrollHeight
343
+ }));
289
344
  }
345
+ }, [
346
+ getScrollElement
347
+ ]);
348
+ const pinRow = useCallback3((rowToPin) => {
349
+ table.resetRowPinning();
350
+ rowToPin.pin("bottom");
351
+ setPinnedRowKey(rowToPin.id);
352
+ }, [
353
+ table
354
+ ]);
355
+ const clearRowPinning = useCallback3(() => {
356
+ table.resetRowPinning();
357
+ setPinnedRowKey(void 0);
358
+ }, [
359
+ table
360
+ ]);
361
+ const pinLastRowCallback = useCallback3(() => {
290
362
  const rows = table.getRowModel().rows;
291
- const rowToPin = rows[rows.length - 1];
292
- const rowId = rowToPin.id;
293
- if (rowId === pinnedRowKey) {
363
+ if (rows.length === 0) {
364
+ return clearRowPinning();
365
+ }
366
+ const lastRow = rows[rows.length - 1];
367
+ if (lastRow.id === pinnedRowKey) {
294
368
  return;
295
369
  }
296
- table.resetRowPinning();
297
- rowToPin.pin("bottom");
298
- const scrollElement = getScrollElement?.();
299
- const isFirstRender = pinnedRowKey === void 0;
300
- if (scrollElement && !isFirstRender) {
301
- requestAnimationFrame(() => {
302
- scrollElement.scrollTo({
303
- top: scrollElement.scrollHeight
304
- });
305
- });
370
+ pinRow(lastRow);
371
+ if (pinnedRowKey !== void 0) {
372
+ scrollToBottom();
306
373
  }
307
- setPinnedRowKey(rowId);
308
374
  }, [
309
- pinLastRow,
310
375
  table,
311
- getScrollElement,
312
- pinnedRowKey,
313
- setPinnedRowKey,
314
- data
376
+ scrollToBottom,
377
+ pinnedRowKey
378
+ ]);
379
+ useEffect2(() => {
380
+ if (pinLastRow) {
381
+ pinLastRowCallback();
382
+ }
383
+ }, [
384
+ data,
385
+ pinLastRow,
386
+ pinLastRowCallback
315
387
  ]);
316
388
  };
317
389
 
390
+ // packages/ui/react-ui-table/src/hooks/useRowSelection.ts
391
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
392
+ import { useCallback as useCallback4 } from "react";
393
+ var useRowSelection = (props) => {
394
+ const [rowSelection = {}, setRowSelection] = useControllableState({
395
+ prop: props.rowSelection,
396
+ onChange: props.onRowSelectionChange,
397
+ defaultProp: props.defaultRowSelection
398
+ });
399
+ const handleRowSelectionChange = useCallback4((updaterOrValue) => {
400
+ const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
401
+ if (props.rowsSelectable === "multi") {
402
+ setRowSelection(nextRowSelection);
403
+ } else if (props.rowsSelectable) {
404
+ const nextRowSelectionKey = Object.keys(nextRowSelection).filter((id) => !rowSelection[id])[0];
405
+ setRowSelection(nextRowSelectionKey ? {
406
+ [nextRowSelectionKey]: true
407
+ } : {});
408
+ } else {
409
+ setRowSelection({});
410
+ }
411
+ }, [
412
+ props.rowsSelectable,
413
+ setRowSelection,
414
+ rowSelection
415
+ ]);
416
+ return {
417
+ rowSelection,
418
+ handleRowSelectionChange
419
+ };
420
+ };
421
+
318
422
  // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnMenu.tsx
319
423
  var ColumnMenu = ({ column, ...props }) => {
320
424
  const title = column.label?.length ? column.label : column.id;
321
425
  const header = props.context.header;
322
426
  const { canSort, sortDirection, onSelectSort, onToggleSort, onClearSort } = useColumnSorting(header.column);
323
427
  const columnSettingsAnchorRef = useRef2(null);
324
- const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState5(false);
428
+ const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState6(false);
325
429
  const shouldPreventFocusOnClose = useRef2(false);
326
- const onOpenColumnSettings = useCallback2(() => {
430
+ const onOpenColumnSettings = useCallback5(() => {
327
431
  shouldPreventFocusOnClose.current = true;
328
432
  setIsColumnSettingsOpen(true);
329
433
  }, [
330
434
  shouldPreventFocusOnClose,
331
435
  setIsColumnSettingsOpen
332
436
  ]);
333
- const onDropdownCloseAutoFocus = useCallback2((event) => {
437
+ const onDropdownCloseAutoFocus = useCallback5((event) => {
334
438
  if (shouldPreventFocusOnClose.current) {
335
439
  event.preventDefault();
336
440
  shouldPreventFocusOnClose.current = false;
@@ -363,7 +467,7 @@ var ColumnMenu = ({ column, ...props }) => {
363
467
  variant: "ghost"
364
468
  }, /* @__PURE__ */ React3.createElement(CaretDown2, {
365
469
  className: getSize3(4)
366
- })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
470
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
367
471
  onCloseAutoFocus: onDropdownCloseAutoFocus,
368
472
  sideOffset: 4,
369
473
  collisionPadding: 8
@@ -399,7 +503,7 @@ var ColumnMenu = ({ column, ...props }) => {
399
503
  className: "opacity-50"
400
504
  }, /* @__PURE__ */ React3.createElement(GearSix, {
401
505
  className: mx3(getSize3(4), "rotate-90")
402
- })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)), /* @__PURE__ */ React3.createElement(ColumnSettingsPanel, {
506
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null))), /* @__PURE__ */ React3.createElement(ColumnSettingsPanel, {
403
507
  ...props,
404
508
  column,
405
509
  onClose: () => setIsColumnSettingsOpen(false)
@@ -441,12 +545,11 @@ var SortIndicator = ({ direction, onClick }) => {
441
545
  };
442
546
 
443
547
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
444
- import { useControllableState } from "@radix-ui/react-use-controllable-state";
445
548
  import { getCoreRowModel, getSortedRowModel, useReactTable, getGroupedRowModel, getExpandedRowModel } from "@tanstack/react-table";
446
549
  import { useVirtualizer } from "@tanstack/react-virtual";
447
- import React9, { Fragment, useCallback as useCallback3, useEffect as useEffect2, useState as useState6 } from "react";
550
+ import React9, { Fragment, useCallback as useCallback6, useEffect as useEffect3, useState as useState7 } from "react";
448
551
  import { log } from "@dxos/log";
449
- import { useDefaultValue, useOnTransition } from "@dxos/react-ui";
552
+ import { useDefaultValue } from "@dxos/react-ui";
450
553
 
451
554
  // packages/ui/react-ui-table/src/components/Table/TableBody.tsx
452
555
  import { useArrowNavigationGroup } from "@fluentui/react-tabster";
@@ -642,53 +745,27 @@ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/c
642
745
  var Table = (props) => {
643
746
  const { role, onColumnResize, columnVisibility, header = true, rowsSelectable, debug, onDataSelectionChange, getScrollElement, pinLastRow } = props;
644
747
  const columns = useDefaultValue(props.columns, []);
645
- const data = useDefaultValue(props.data, []);
646
- const TableProvider2 = TableProvider;
647
- const [columnsInitialised, setColumnsInitialised] = useState6(false);
648
- const [columnSizing, setColumnSizing] = useState6({});
649
- useEffect2(() => {
650
- if (columnsInitialised) {
651
- return;
652
- }
653
- setColumnSizing(columns.filter((column) => !!column.size && column.prop !== void 0).reduce((state, column) => {
654
- state[column.prop] = column.size;
655
- return state;
656
- }, {}));
657
- setColumnsInitialised(true);
658
- }, [
659
- columns,
660
- setColumnSizing
748
+ const incomingData = useDefaultValue(props.data, []);
749
+ const [data, setData] = useState7([
750
+ ...incomingData
661
751
  ]);
662
- const [columnSizingInfo, setColumnSizingInfo] = useState6({});
663
- const notifyColumnResize = useCallback3(() => onColumnResize?.(columnSizing), [
664
- onColumnResize,
665
- columnSizing
752
+ const forceUpdate = useCallback6(() => setData([
753
+ ...incomingData
754
+ ]), [
755
+ incomingData
666
756
  ]);
667
- useOnTransition(columnSizingInfo.isResizingColumn, (v) => typeof v === "string", false, notifyColumnResize);
668
- const [rowSelection = {}, setRowSelection] = useControllableState({
669
- prop: props.rowSelection,
670
- onChange: props.onRowSelectionChange,
671
- defaultProp: props.defaultRowSelection
672
- });
673
- const handleRowSelectionChange = useCallback3((updaterOrValue) => {
674
- const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
675
- if (rowsSelectable === "multi") {
676
- setRowSelection(nextRowSelection);
677
- } else if (rowsSelectable) {
678
- const nextRowSelectionKey = Object.keys(nextRowSelection).filter((id) => !rowSelection[id])[0];
679
- setRowSelection(nextRowSelectionKey ? {
680
- [nextRowSelectionKey]: true
681
- } : {});
682
- } else {
683
- setRowSelection({});
684
- }
685
- }, [
686
- rowsSelectable,
687
- setRowSelection,
688
- rowSelection
757
+ useEffect3(() => forceUpdate(), [
758
+ JSON.stringify(incomingData),
759
+ forceUpdate
689
760
  ]);
690
- const [grouping, handleGroupingChange] = useState6(props.grouping ?? []);
691
- useEffect2(() => handleGroupingChange(props.grouping ?? []), [
761
+ const TableProvider2 = TableProvider;
762
+ const { columnSizing, setColumnSizing, columnSizingInfo, setColumnSizingInfo } = useColumnResizing({
763
+ columns,
764
+ onColumnResize
765
+ });
766
+ const { rowSelection, handleRowSelectionChange } = useRowSelection(props);
767
+ const [grouping, handleGroupingChange] = useState7(props.grouping ?? []);
768
+ useEffect3(() => handleGroupingChange(props.grouping ?? []), [
692
769
  handleGroupingChange,
693
770
  props.grouping
694
771
  ]);
@@ -730,7 +807,7 @@ var Table = (props) => {
730
807
  // Debug
731
808
  debugTable: debug
732
809
  });
733
- useEffect2(() => {
810
+ useEffect3(() => {
734
811
  onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
735
812
  }, [
736
813
  onDataSelectionChange,
@@ -742,7 +819,7 @@ var Table = (props) => {
742
819
  if (!getScrollElement) {
743
820
  log.warn("Table: getScrollElement is not set. This is required for virtualized tables.", void 0, {
744
821
  F: __dxlog_file,
745
- L: 159,
822
+ L: 120,
746
823
  S: void 0,
747
824
  C: (f, a) => f(...a)
748
825
  });
@@ -762,12 +839,6 @@ var Table = (props) => {
762
839
  var TableImpl = (props) => {
763
840
  const { debug, classNames, getScrollElement, role, footer, grouping, fullWidth } = props;
764
841
  const { table } = useTableContext();
765
- const centerRows = table.getCenterRows();
766
- const bottomRows = table.getBottomRows();
767
- const rows = [
768
- ...centerRows,
769
- ...bottomRows
770
- ];
771
842
  if (debug) {
772
843
  return /* @__PURE__ */ React9.createElement("pre", {
773
844
  className: "font-mono text-xs text-neutral-500 m-1 p-2 ring"
@@ -787,14 +858,28 @@ var TableImpl = (props) => {
787
858
  getScrollElement
788
859
  }) : /* @__PURE__ */ React9.createElement(VirtualizedTableContent, {
789
860
  getScrollElement
790
- }) : /* @__PURE__ */ React9.createElement(TableBody, {
861
+ }) : /* @__PURE__ */ React9.createElement(UnvirtualizedTableContent, null) : /* @__PURE__ */ React9.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React9.createElement(TableFooter, null));
862
+ };
863
+ var UnvirtualizedTableContent = () => {
864
+ const { table } = useTableContext();
865
+ const centerRows = table.getCenterRows();
866
+ const pinnedRows = table.getBottomRows();
867
+ const rows = [
868
+ ...centerRows,
869
+ ...pinnedRows
870
+ ];
871
+ return /* @__PURE__ */ React9.createElement(TableBody, {
791
872
  rows
792
- }) : /* @__PURE__ */ React9.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React9.createElement(TableFooter, null));
873
+ });
793
874
  };
794
875
  var VirtualizedTableContent = ({ getScrollElement }) => {
795
876
  const { table } = useTableContext();
796
877
  const centerRows = table.getCenterRows();
797
- const pinnedRows = table.getBottomRows();
878
+ let pinnedRows = [];
879
+ try {
880
+ pinnedRows = table.getBottomRows();
881
+ } catch (_) {
882
+ }
798
883
  const { getTotalSize, getVirtualItems } = useVirtualizer({
799
884
  getScrollElement,
800
885
  count: centerRows.length,
@@ -853,7 +938,7 @@ import { Check as Check2, ClipboardText, X as X3 } from "@phosphor-icons/react";
853
938
  import { createColumnHelper } from "@tanstack/react-table";
854
939
  import { format } from "date-fns/format";
855
940
  import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
856
- import React10, { useEffect as useEffect3, useRef as useRef3, useState as useState7 } from "react";
941
+ import React10, { useCallback as useCallback7, useEffect as useEffect4, useRef as useRef3, useState as useState8 } from "react";
857
942
  import { log as log2 } from "@dxos/log";
858
943
  import { Input as Input2, Tooltip } from "@dxos/react-ui";
859
944
  import { getSize as getSize4, mx as mx5 } from "@dxos/react-ui-theme";
@@ -875,12 +960,15 @@ var StringBuilderCell = (cellContext) => {
875
960
  const { findPrevFocusable } = useFocusFinders();
876
961
  const { onUpdate, cell } = cellContext.column.columnDef.meta;
877
962
  const initialValue = cellContext.getValue();
878
- const [value, setValue] = useState7(() => {
879
- if (initialValue?.content) {
880
- return initialValue?.content;
881
- }
882
- return initialValue;
883
- });
963
+ const getInitialValue = useCallback7(() => {
964
+ return initialValue?.content ?? initialValue;
965
+ }, [
966
+ initialValue
967
+ ]);
968
+ const [value, setValue] = useState8(getInitialValue);
969
+ useEffect4(() => setValue(getInitialValue()), [
970
+ getInitialValue
971
+ ]);
884
972
  const handleSave = () => {
885
973
  ref.current && document.activeElement === ref.current && findPrevFocusable(ref.current)?.focus();
886
974
  if (value !== initialValue) {
@@ -917,10 +1005,10 @@ var displayNumber = (value, digits) => value || value === 0 ? value.toLocaleStri
917
1005
  var NumberBuilderCell = (cellContext) => {
918
1006
  const { onUpdate, digits } = cellContext.column.columnDef.meta;
919
1007
  const value = cellContext.getValue();
920
- const [text, setText] = useState7(displayNumber(value, digits));
1008
+ const [text, setText] = useState8(displayNumber(value, digits));
921
1009
  const { findPrevFocusable } = useFocusFinders();
922
1010
  const ref = useRef3(null);
923
- useEffect3(() => {
1011
+ useEffect4(() => {
924
1012
  (!document.activeElement || document.activeElement !== ref.current) && setText(displayNumber(value, digits));
925
1013
  }, [
926
1014
  digits,
@@ -1099,7 +1187,7 @@ var ColumnBuilder = class {
1099
1187
  value
1100
1188
  }, {
1101
1189
  F: __dxlog_file2,
1102
- L: 374,
1190
+ L: 376,
1103
1191
  S: this,
1104
1192
  C: (f, a) => f(...a)
1105
1193
  });
@@ -1277,14 +1365,45 @@ var ColumnBuilder = class {
1277
1365
  };
1278
1366
 
1279
1367
  // packages/ui/react-ui-table/src/schema/schema.ts
1280
- import { AST } from "@effect/schema";
1368
+ import * as AST from "@effect/schema/AST";
1369
+ var classifySchemaProperties = (schema) => {
1370
+ const recurse = (node, path, acc) => {
1371
+ const properties = AST.getPropertySignatures(node);
1372
+ properties.forEach((prop) => {
1373
+ const propName = prop.name.toString();
1374
+ if (prop.isOptional) {
1375
+ const unwrappedAst = unwrapOptionProperty(prop);
1376
+ if (isStruct(unwrappedAst)) {
1377
+ return recurse(unwrappedAst, [
1378
+ ...path,
1379
+ propName
1380
+ ], acc);
1381
+ }
1382
+ }
1383
+ if (isStruct(prop.type)) {
1384
+ recurse(prop.type, [
1385
+ ...path,
1386
+ propName
1387
+ ], acc);
1388
+ } else {
1389
+ acc.push([
1390
+ path.concat(propName).join("."),
1391
+ propertyToColumn(prop)
1392
+ ]);
1393
+ }
1394
+ });
1395
+ return acc;
1396
+ };
1397
+ return recurse(schema.ast, [], []);
1398
+ };
1399
+ var isStruct = (node) => AST.isTypeLiteral(node);
1281
1400
  var isOptionalUnion = (prop) => AST.isUnion(prop.type) && prop.isOptional;
1282
1401
  var unwrapOptionProperty = (prop) => {
1283
1402
  if (!isOptionalUnion(prop)) {
1284
- throw new Error("Not an optional property");
1403
+ throw new Error(`Not an optional property: ${String(prop.name)}`);
1285
1404
  }
1286
1405
  if (!AST.isUnion(prop.type)) {
1287
- throw new Error("Not a union type");
1406
+ throw new Error(`Not a union type: ${String(prop.name)}`);
1288
1407
  }
1289
1408
  const [type, _undefinedCase] = prop.type.types;
1290
1409
  return type;
@@ -1310,44 +1429,13 @@ var typeToColumn = (type) => {
1310
1429
  }
1311
1430
  return "display";
1312
1431
  };
1313
- var propertyToColumn = (property) => {
1314
- let type = property.type;
1315
- if (property.isOptional) {
1316
- type = unwrapOptionProperty(property);
1432
+ var propertyToColumn = (prop) => {
1433
+ let type = prop.type;
1434
+ if (prop.isOptional) {
1435
+ type = unwrapOptionProperty(prop);
1317
1436
  }
1318
1437
  return typeToColumn(type);
1319
1438
  };
1320
- var isStruct = (node) => AST.isTypeLiteral(node);
1321
- var classifySchemaProperties = (schema) => {
1322
- const recurse = (node, path, acc) => {
1323
- const properties = AST.getPropertySignatures(node);
1324
- properties.forEach((prop) => {
1325
- const propName = prop.name.toString();
1326
- if (prop.isOptional) {
1327
- const unwrappedAst = unwrapOptionProperty(prop);
1328
- if (isStruct(unwrappedAst)) {
1329
- return recurse(unwrappedAst, [
1330
- ...path,
1331
- propName
1332
- ], acc);
1333
- }
1334
- }
1335
- if (isStruct(prop.type)) {
1336
- recurse(prop.type, [
1337
- ...path,
1338
- propName
1339
- ], acc);
1340
- } else {
1341
- acc.push([
1342
- path.concat(propName).join("."),
1343
- propertyToColumn(prop)
1344
- ]);
1345
- }
1346
- });
1347
- return acc;
1348
- };
1349
- return recurse(schema.ast, [], []);
1350
- };
1351
1439
 
1352
1440
  // packages/ui/react-ui-table/src/schema/schemaToColumns.ts
1353
1441
  var schemaToColumnDefs = (schema) => {
@@ -1426,7 +1514,9 @@ export {
1426
1514
  theadTh,
1427
1515
  theadTr,
1428
1516
  translations_default as translations,
1517
+ useColumnResizing,
1429
1518
  useColumnSorting,
1430
- usePinLastRow
1519
+ usePinLastRow,
1520
+ useRowSelection
1431
1521
  };
1432
1522
  //# sourceMappingURL=index.mjs.map