@dxos/react-ui-table 0.4.10-main.3e0c8a5 → 0.4.10-main.41833ea

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 (59) hide show
  1. package/dist/lib/browser/index.mjs +435 -283
  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.d.ts → ColumnMenu/ColumnMenu.d.ts} +1 -1
  5. package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts.map +1 -0
  6. package/dist/types/src/components/{ColumnMenu.stories.d.ts → ColumnMenu/ColumnMenu.stories.d.ts} +1 -1
  7. package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -0
  8. package/dist/types/src/components/{ColumnSettingsForm.d.ts → ColumnMenu/ColumnSettingsForm.d.ts} +5 -4
  9. package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts.map +1 -0
  10. package/dist/types/src/components/ColumnMenu/index.d.ts +3 -0
  11. package/dist/types/src/components/ColumnMenu/index.d.ts.map +1 -0
  12. package/dist/types/src/components/index.d.ts +1 -1
  13. package/dist/types/src/components/index.d.ts.map +1 -1
  14. package/dist/types/src/helpers.d.ts +4 -0
  15. package/dist/types/src/helpers.d.ts.map +1 -1
  16. package/dist/types/src/hooks/index.d.ts +3 -0
  17. package/dist/types/src/hooks/index.d.ts.map +1 -0
  18. package/dist/types/src/hooks/useColumnSorting.d.ts.map +1 -0
  19. package/dist/types/src/hooks/usePinLastRow.d.ts.map +1 -0
  20. package/dist/types/src/index.d.ts +2 -1
  21. package/dist/types/src/index.d.ts.map +1 -1
  22. package/dist/types/src/schema/SchemaToTable.stories.d.ts +11 -0
  23. package/dist/types/src/schema/SchemaToTable.stories.d.ts.map +1 -0
  24. package/dist/types/src/schema/index.d.ts +3 -0
  25. package/dist/types/src/schema/index.d.ts.map +1 -0
  26. package/dist/types/src/schema/schema.d.ts +5 -0
  27. package/dist/types/src/schema/schema.d.ts.map +1 -0
  28. package/dist/types/src/schema/schema.test.d.ts +2 -0
  29. package/dist/types/src/schema/schema.test.d.ts.map +1 -0
  30. package/dist/types/src/schema/schemaToColumns.d.ts +4 -0
  31. package/dist/types/src/schema/schemaToColumns.d.ts.map +1 -0
  32. package/dist/types/src/{schema.d.ts → schema/types.d.ts} +1 -1
  33. package/dist/types/src/schema/types.d.ts.map +1 -0
  34. package/package.json +18 -15
  35. package/src/components/{ColumnMenu.stories.tsx → ColumnMenu/ColumnMenu.stories.tsx} +1 -1
  36. package/src/components/{ColumnMenu.tsx → ColumnMenu/ColumnMenu.tsx} +2 -2
  37. package/src/components/{ColumnSettingsForm.tsx → ColumnMenu/ColumnSettingsForm.tsx} +14 -12
  38. package/src/components/ColumnMenu/index.ts +6 -0
  39. package/src/components/Table/Table.tsx +1 -1
  40. package/src/components/index.ts +1 -1
  41. package/src/helpers.tsx +22 -0
  42. package/src/hooks/index.ts +6 -0
  43. package/src/index.ts +3 -1
  44. package/src/schema/SchemaToTable.stories.tsx +72 -0
  45. package/src/schema/index.ts +6 -0
  46. package/src/schema/schema.test.ts +148 -0
  47. package/src/schema/schema.ts +93 -0
  48. package/src/schema/schemaToColumns.ts +47 -0
  49. package/dist/types/src/components/ColumnMenu.d.ts.map +0 -1
  50. package/dist/types/src/components/ColumnMenu.stories.d.ts.map +0 -1
  51. package/dist/types/src/components/ColumnSettingsForm.d.ts.map +0 -1
  52. package/dist/types/src/components/hooks/useColumnSorting.d.ts.map +0 -1
  53. package/dist/types/src/components/hooks/usePinLastRow.d.ts.map +0 -1
  54. package/dist/types/src/schema.d.ts.map +0 -1
  55. /package/dist/types/src/{components/hooks → hooks}/useColumnSorting.d.ts +0 -0
  56. /package/dist/types/src/{components/hooks → hooks}/usePinLastRow.d.ts +0 -0
  57. /package/src/{components/hooks → hooks}/useColumnSorting.ts +0 -0
  58. /package/src/{components/hooks → hooks}/usePinLastRow.ts +0 -0
  59. /package/src/{schema.ts → schema/types.ts} +0 -0
@@ -1,16 +1,3 @@
1
- // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
2
- import { X as X2, GearSix, CaretDown, ArrowDown, ArrowUp } from "@phosphor-icons/react";
3
- import React2, { useRef as useRef2, useState as useState3, useCallback } from "react";
4
- import { Button as Button2, DensityProvider, Popover, DropdownMenu } from "@dxos/react-ui";
5
- import { getSize as getSize2, mx as mx2 } from "@dxos/react-ui-theme";
6
-
7
- // packages/ui/react-ui-table/src/components/ColumnSettingsForm.tsx
8
- import { Check, Trash, X } from "@phosphor-icons/react";
9
- import React, { useRef, useState } from "react";
10
- import { Button, Input, Select, Separator, useTranslation } from "@dxos/react-ui";
11
- import { getSize, mx } from "@dxos/react-ui-theme";
12
- import { safeParseInt } from "@dxos/util";
13
-
14
1
  // packages/ui/react-ui-table/src/translations.ts
15
2
  var translationKey = "table";
16
3
  var translations_default = [
@@ -34,23 +21,103 @@ var translations_default = [
34
21
  }
35
22
  ];
36
23
 
37
- // packages/ui/react-ui-table/src/components/ColumnSettingsForm.tsx
38
- var Section = ({ children, className }) => /* @__PURE__ */ React.createElement("div", {
24
+ // packages/ui/react-ui-table/src/components/Cell/CellCombobox.tsx
25
+ import { CaretDown } from "@phosphor-icons/react";
26
+ import React, { useCallback, useState } from "react";
27
+ import { Popover, useTranslation } from "@dxos/react-ui";
28
+ import { PopoverCombobox } from "@dxos/react-ui-searchlist";
29
+ import { descriptionText, getSize, mx, staticPlaceholderText } from "@dxos/react-ui-theme";
30
+ var initialItems = (model, value) => value ? {
31
+ [model.getId(value)]: {
32
+ label: model.getText(value),
33
+ data: value
34
+ }
35
+ } : {};
36
+ var CellCombobox = ({ model, value, onValueChange }) => {
37
+ const { t } = useTranslation(translationKey);
38
+ const [items, setItems] = useState(initialItems(model, value));
39
+ const [loading, setLoading] = useState(false);
40
+ const [searchInputValue, setSearchInputValue] = useState("");
41
+ const handleSearchInputValueChange = async (text) => {
42
+ setSearchInputValue(text ?? "");
43
+ setLoading(true);
44
+ const items2 = await model.query(text);
45
+ setItems(items2.reduce((acc, item) => {
46
+ acc[model.getId(item)] = {
47
+ label: model.getText(item),
48
+ data: item
49
+ };
50
+ return acc;
51
+ }, initialItems(model, value)));
52
+ setLoading(false);
53
+ };
54
+ const handleValueChange = useCallback((id) => {
55
+ onValueChange(items[id]?.data);
56
+ }, [
57
+ items,
58
+ onValueChange
59
+ ]);
60
+ return /* @__PURE__ */ React.createElement(PopoverCombobox.Root, {
61
+ placeholder: t("no selection label")
62
+ }, /* @__PURE__ */ React.createElement(PopoverCombobox.Trigger, {
63
+ variant: "ghost",
64
+ classNames: "is-full rounded-none ring-inset"
65
+ }, value ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
66
+ className: mx("font-normal text-start text-base flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
67
+ }, model.getText(value)), /* @__PURE__ */ React.createElement(CaretDown, {
68
+ weight: "bold",
69
+ className: getSize(3)
70
+ })) : null), /* @__PURE__ */ React.createElement(PopoverCombobox.Content, {
71
+ shouldFilter: false,
72
+ classNames: "is-[--radix-popover-trigger-width]"
73
+ }, /* @__PURE__ */ React.createElement(PopoverCombobox.Input, {
74
+ value: searchInputValue,
75
+ onValueChange: handleSearchInputValueChange
76
+ }), /* @__PURE__ */ React.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React.createElement("p", {
77
+ className: mx("text-center", descriptionText)
78
+ }, "Start typing to search") : loading ? /* @__PURE__ */ React.createElement("p", {
79
+ className: mx("text-center", descriptionText)
80
+ }, "Searching\u2026") : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(PopoverCombobox.Empty, {
81
+ classNames: [
82
+ "text-center",
83
+ descriptionText
84
+ ]
85
+ }, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React.createElement(PopoverCombobox.Item, {
86
+ key: id,
87
+ value: id,
88
+ onSelect: handleValueChange,
89
+ classNames: "truncate"
90
+ }, label)))), /* @__PURE__ */ React.createElement(Popover.Arrow, null)));
91
+ };
92
+
93
+ // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnMenu.tsx
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";
96
+ import { Button as Button2, DensityProvider, Popover as Popover2, DropdownMenu } from "@dxos/react-ui";
97
+ import { getSize as getSize3, mx as mx3 } from "@dxos/react-ui-theme";
98
+
99
+ // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnSettingsForm.tsx
100
+ import { Check, Trash, X } from "@phosphor-icons/react";
101
+ import React2, { useRef, useState as useState2 } from "react";
102
+ import { Button, Input, Select, Separator, useTranslation as useTranslation2 } from "@dxos/react-ui";
103
+ import { getSize as getSize2, mx as mx2 } from "@dxos/react-ui-theme";
104
+ import { safeParseInt } from "@dxos/util";
105
+ var Section = ({ children, className }) => /* @__PURE__ */ React2.createElement("div", {
39
106
  role: "none",
40
- className: mx("p-2", className)
107
+ className: mx2("p-2", className)
41
108
  }, children);
42
109
  var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onClose }) => {
43
- const [prop, setProp] = useState(column.id);
44
- const [refTable, setRefTable] = useState(column.refTable);
45
- const [refProp, setRefProp] = useState(column.refProp);
46
- const [type, setType] = useState(String(column.type));
47
- const [label, setLabel] = useState(column.label);
48
- const [digits, setDigits] = useState(String(column.digits ?? "0"));
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"));
49
116
  const propRef = useRef(null);
50
- const { t } = useTranslation(translationKey);
117
+ const { t } = useTranslation2(translationKey);
51
118
  const handleCancel = () => {
52
119
  setProp(column.id);
53
- onClose;
120
+ onClose?.();
54
121
  };
55
122
  const handleSave = () => {
56
123
  if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {
@@ -73,104 +140,104 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
73
140
  refProp,
74
141
  digits: safeParseInt(digits)
75
142
  });
76
- onClose();
143
+ onClose?.();
77
144
  };
78
- return /* @__PURE__ */ React.createElement("div", {
145
+ return /* @__PURE__ */ React2.createElement("div", {
79
146
  className: "flex flex-col gap-1"
80
- }, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
147
+ }, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
81
148
  classNames: "mbe-1"
82
- }, t("column label label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
149
+ }, t("column label label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
83
150
  placeholder: "Column label",
84
151
  value: label ?? "",
85
152
  onChange: (event) => setLabel(event.target.value),
86
153
  autoFocus: true
87
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
154
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
88
155
  classNames: "mbe-1 mbs-3"
89
- }, t("property key label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
156
+ }, t("property key label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
90
157
  ref: propRef,
91
158
  placeholder: "Property key",
92
159
  // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.
93
160
  value: prop ?? "",
94
161
  onChange: (event) => setProp(event.target.value.replace(/[^\w_]/g, ""))
95
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
162
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
96
163
  classNames: "mbe-1 mbs-3"
97
- }, t("column type label")), /* @__PURE__ */ React.createElement(Select.Root, {
164
+ }, t("column type label")), /* @__PURE__ */ React2.createElement(Select.Root, {
98
165
  value: type,
99
166
  onValueChange: setType
100
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
167
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
101
168
  placeholder: "Type",
102
169
  classNames: "is-full"
103
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, [
170
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, [
104
171
  "number",
105
172
  "boolean",
106
173
  "string",
107
174
  "ref"
108
- ].map((type2) => /* @__PURE__ */ React.createElement(Select.Option, {
175
+ ].map((type2) => /* @__PURE__ */ React2.createElement(Select.Option, {
109
176
  key: type2,
110
177
  value: type2
111
- }, t(`${type2} column type label`))))))))), type === "number" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
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, {
112
179
  classNames: "mbe-1 mbs-3"
113
- }, t("digits label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
180
+ }, t("digits label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
114
181
  value: digits ?? "",
115
182
  onChange: (event) => setDigits(event.target.value)
116
- })))), type === "ref" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
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, {
117
184
  classNames: "mbe-1 mbs-3"
118
- }, "Table"), /* @__PURE__ */ React.createElement(Select.Root, {
185
+ }, "Table"), /* @__PURE__ */ React2.createElement(Select.Root, {
119
186
  value: refTable,
120
187
  onValueChange: setRefTable
121
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
188
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
122
189
  placeholder: "Table",
123
190
  classNames: "is-full"
124
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, tableDefs.filter((t2) => t2.id !== tableDef.id).map(({ id, name }) => /* @__PURE__ */ React.createElement(Select.Option, {
191
+ }), /* @__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, {
125
192
  key: id,
126
193
  value: id
127
- }, name ?? id))))))), refTable && /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
194
+ }, name ?? id))))))), refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
128
195
  classNames: "mbe-1 mbs-3"
129
- }, "Table property"), /* @__PURE__ */ React.createElement(Select.Root, {
196
+ }, "Table property"), /* @__PURE__ */ React2.createElement(Select.Root, {
130
197
  value: refProp,
131
198
  onValueChange: setRefProp
132
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
199
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
133
200
  placeholder: "Property",
134
201
  classNames: "is-full"
135
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, tableDefs.find((tableDef2) => tableDef2.id === refTable)?.columns.map(({ id, label: label2 }) => /* @__PURE__ */ React.createElement(Select.Option, {
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, {
136
203
  key: id,
137
204
  value: id
138
- }, label2 ?? id))))))))), /* @__PURE__ */ React.createElement(Separator, {
205
+ }, label2 ?? id))))))))), /* @__PURE__ */ React2.createElement(Separator, {
139
206
  classNames: "mli-2"
140
- }), /* @__PURE__ */ React.createElement(Section, {
207
+ }), /* @__PURE__ */ React2.createElement(Section, {
141
208
  className: "space-b-1.5"
142
- }, /* @__PURE__ */ React.createElement(Button, {
209
+ }, /* @__PURE__ */ React2.createElement(Button, {
143
210
  variant: "primary",
144
211
  classNames: "is-full flex gap-2",
145
212
  onClick: handleSave
146
- }, /* @__PURE__ */ React.createElement("span", null, t("save label")), /* @__PURE__ */ React.createElement("div", {
213
+ }, /* @__PURE__ */ React2.createElement("span", null, t("save label")), /* @__PURE__ */ React2.createElement("div", {
147
214
  className: "grow"
148
- }), /* @__PURE__ */ React.createElement(Check, {
149
- className: getSize(5)
150
- })), /* @__PURE__ */ React.createElement(Button, {
215
+ }), /* @__PURE__ */ React2.createElement(Check, {
216
+ className: getSize2(5)
217
+ })), /* @__PURE__ */ React2.createElement(Button, {
151
218
  classNames: "is-full flex gap-2",
152
219
  onClick: handleCancel
153
- }, /* @__PURE__ */ React.createElement("span", null, t("cancel label", {
220
+ }, /* @__PURE__ */ React2.createElement("span", null, t("cancel label", {
154
221
  ns: "os"
155
- })), /* @__PURE__ */ React.createElement("div", {
222
+ })), /* @__PURE__ */ React2.createElement("div", {
156
223
  className: "grow"
157
- }), /* @__PURE__ */ React.createElement(X, {
158
- className: getSize(5)
159
- })), /* @__PURE__ */ React.createElement(Button, {
224
+ }), /* @__PURE__ */ React2.createElement(X, {
225
+ className: getSize2(5)
226
+ })), /* @__PURE__ */ React2.createElement(Button, {
160
227
  classNames: "is-full flex gap-2",
161
228
  onClick: () => onDelete?.(column.id)
162
- }, /* @__PURE__ */ React.createElement("span", null, t("delete label")), /* @__PURE__ */ React.createElement("div", {
229
+ }, /* @__PURE__ */ React2.createElement("span", null, t("delete label")), /* @__PURE__ */ React2.createElement("div", {
163
230
  className: "grow"
164
- }), /* @__PURE__ */ React.createElement(Trash, {
165
- className: getSize(5)
231
+ }), /* @__PURE__ */ React2.createElement(Trash, {
232
+ className: getSize2(5)
166
233
  }))));
167
234
  };
168
235
 
169
- // packages/ui/react-ui-table/src/components/hooks/useColumnSorting.ts
170
- import { useState as useState2 } from "react";
236
+ // packages/ui/react-ui-table/src/hooks/useColumnSorting.ts
237
+ import { useState as useState3 } from "react";
171
238
  var useColumnSorting = (column) => {
172
- const [sortDirection, setSortDirection] = useState2(column.getIsSorted());
173
- const [firstSort, setFirstSort] = useState2();
239
+ const [sortDirection, setSortDirection] = useState3(column.getIsSorted());
240
+ const [firstSort, setFirstSort] = useState3();
174
241
  const canSort = column.getCanSort();
175
242
  const updateColumnSort = (direction) => {
176
243
  setSortDirection(direction);
@@ -212,22 +279,58 @@ var useColumnSorting = (column) => {
212
279
  };
213
280
  };
214
281
 
215
- // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
282
+ // packages/ui/react-ui-table/src/hooks/usePinLastRow.ts
283
+ import { useEffect, useState as useState4 } from "react";
284
+ var usePinLastRow = (pinLastRow, table, data, getScrollElement) => {
285
+ const [pinnedRowKey, setPinnedRowKey] = useState4();
286
+ useEffect(() => {
287
+ if (!pinLastRow) {
288
+ return;
289
+ }
290
+ const rows = table.getRowModel().rows;
291
+ const rowToPin = rows[rows.length - 1];
292
+ const rowId = rowToPin.id;
293
+ if (rowId === pinnedRowKey) {
294
+ return;
295
+ }
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
+ });
306
+ }
307
+ setPinnedRowKey(rowId);
308
+ }, [
309
+ pinLastRow,
310
+ table,
311
+ getScrollElement,
312
+ pinnedRowKey,
313
+ setPinnedRowKey,
314
+ data
315
+ ]);
316
+ };
317
+
318
+ // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnMenu.tsx
216
319
  var ColumnMenu = ({ column, ...props }) => {
217
320
  const title = column.label?.length ? column.label : column.id;
218
321
  const header = props.context.header;
219
322
  const { canSort, sortDirection, onSelectSort, onToggleSort, onClearSort } = useColumnSorting(header.column);
220
323
  const columnSettingsAnchorRef = useRef2(null);
221
- const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState3(false);
324
+ const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState5(false);
222
325
  const shouldPreventFocusOnClose = useRef2(false);
223
- const onOpenColumnSettings = useCallback(() => {
326
+ const onOpenColumnSettings = useCallback2(() => {
224
327
  shouldPreventFocusOnClose.current = true;
225
328
  setIsColumnSettingsOpen(true);
226
329
  }, [
227
330
  shouldPreventFocusOnClose,
228
331
  setIsColumnSettingsOpen
229
332
  ]);
230
- const onDropdownCloseAutoFocus = useCallback((event) => {
333
+ const onDropdownCloseAutoFocus = useCallback2((event) => {
231
334
  if (shouldPreventFocusOnClose.current) {
232
335
  event.preventDefault();
233
336
  shouldPreventFocusOnClose.current = false;
@@ -235,85 +338,85 @@ var ColumnMenu = ({ column, ...props }) => {
235
338
  }, [
236
339
  shouldPreventFocusOnClose
237
340
  ]);
238
- return /* @__PURE__ */ React2.createElement("div", {
341
+ return /* @__PURE__ */ React3.createElement("div", {
239
342
  className: "flex items-center justify-center justify-between"
240
- }, /* @__PURE__ */ React2.createElement("div", {
343
+ }, /* @__PURE__ */ React3.createElement("div", {
241
344
  className: "flex items-center gap-1 truncate",
242
345
  title
243
- }, /* @__PURE__ */ React2.createElement(SortIndicator, {
346
+ }, /* @__PURE__ */ React3.createElement(SortIndicator, {
244
347
  direction: sortDirection,
245
348
  onClick: onToggleSort
246
- }), /* @__PURE__ */ React2.createElement("div", {
349
+ }), /* @__PURE__ */ React3.createElement("div", {
247
350
  className: "truncate"
248
- }, title)), /* @__PURE__ */ React2.createElement(DropdownMenu.Root, {
351
+ }, title)), /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
249
352
  modal: false
250
- }, /* @__PURE__ */ React2.createElement(Popover.Root, {
353
+ }, /* @__PURE__ */ React3.createElement(Popover2.Root, {
251
354
  open: isColumnSettingsOpen,
252
355
  onOpenChange: setIsColumnSettingsOpen,
253
356
  modal: false
254
- }, /* @__PURE__ */ React2.createElement(DropdownMenu.Trigger, {
357
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
255
358
  ref: columnSettingsAnchorRef,
256
359
  asChild: true
257
- }, /* @__PURE__ */ React2.createElement(Popover.Anchor, {
360
+ }, /* @__PURE__ */ React3.createElement(Popover2.Anchor, {
258
361
  asChild: true
259
- }, /* @__PURE__ */ React2.createElement(Button2, {
362
+ }, /* @__PURE__ */ React3.createElement(Button2, {
260
363
  variant: "ghost"
261
- }, /* @__PURE__ */ React2.createElement(CaretDown, {
262
- className: getSize2(4)
263
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Content, {
364
+ }, /* @__PURE__ */ React3.createElement(CaretDown2, {
365
+ className: getSize3(4)
366
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
264
367
  onCloseAutoFocus: onDropdownCloseAutoFocus,
265
368
  sideOffset: 4,
266
369
  collisionPadding: 8
267
- }, /* @__PURE__ */ React2.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
370
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
268
371
  onClick: () => onSelectSort("asc")
269
- }, /* @__PURE__ */ React2.createElement("span", {
372
+ }, /* @__PURE__ */ React3.createElement("span", {
270
373
  className: "grow"
271
- }, "Sort ascending"), /* @__PURE__ */ React2.createElement("span", {
374
+ }, "Sort ascending"), /* @__PURE__ */ React3.createElement("span", {
272
375
  className: "opacity-50"
273
- }, /* @__PURE__ */ React2.createElement(ArrowUp, {
274
- className: getSize2(4)
275
- }))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
376
+ }, /* @__PURE__ */ React3.createElement(ArrowUp, {
377
+ className: getSize3(4)
378
+ }))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
276
379
  onClick: () => onSelectSort("desc")
277
- }, /* @__PURE__ */ React2.createElement("span", {
380
+ }, /* @__PURE__ */ React3.createElement("span", {
278
381
  className: "grow"
279
- }, "Sort descending"), /* @__PURE__ */ React2.createElement("span", {
382
+ }, "Sort descending"), /* @__PURE__ */ React3.createElement("span", {
280
383
  className: "opacity-50"
281
- }, /* @__PURE__ */ React2.createElement(ArrowDown, {
282
- className: getSize2(4)
283
- }))), sortDirection !== false && /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
384
+ }, /* @__PURE__ */ React3.createElement(ArrowDown, {
385
+ className: getSize3(4)
386
+ }))), sortDirection !== false && /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
284
387
  onClick: onClearSort
285
- }, /* @__PURE__ */ React2.createElement("span", {
388
+ }, /* @__PURE__ */ React3.createElement("span", {
286
389
  className: "grow"
287
- }, "Clear sort"), /* @__PURE__ */ React2.createElement("span", {
390
+ }, "Clear sort"), /* @__PURE__ */ React3.createElement("span", {
288
391
  className: "opacity-50"
289
- }, /* @__PURE__ */ React2.createElement(X2, {
290
- className: getSize2(4)
291
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
392
+ }, /* @__PURE__ */ React3.createElement(X2, {
393
+ className: getSize3(4)
394
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
292
395
  onClick: onOpenColumnSettings
293
- }, /* @__PURE__ */ React2.createElement("span", {
396
+ }, /* @__PURE__ */ React3.createElement("span", {
294
397
  className: "grow"
295
- }, "Column settings"), /* @__PURE__ */ React2.createElement("span", {
398
+ }, "Column settings"), /* @__PURE__ */ React3.createElement("span", {
296
399
  className: "opacity-50"
297
- }, /* @__PURE__ */ React2.createElement(GearSix, {
298
- className: mx2(getSize2(4), "rotate-90")
299
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Arrow, null)), /* @__PURE__ */ React2.createElement(ColumnSettingsPanel, {
400
+ }, /* @__PURE__ */ React3.createElement(GearSix, {
401
+ className: mx3(getSize3(4), "rotate-90")
402
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null)), /* @__PURE__ */ React3.createElement(ColumnSettingsPanel, {
300
403
  ...props,
301
404
  column,
302
405
  onClose: () => setIsColumnSettingsOpen(false)
303
406
  }))));
304
407
  };
305
- var ColumnSettingsPanel = ({ tableDefs, tableDef, column, onUpdate, onDelete, onClose }) => /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, null, /* @__PURE__ */ React2.createElement(Popover.Viewport, {
408
+ var ColumnSettingsPanel = ({ tableDefs, tableDef, column, onUpdate, onDelete, onClose }) => /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, null, /* @__PURE__ */ React3.createElement(Popover2.Viewport, {
306
409
  classNames: "w-60"
307
- }, /* @__PURE__ */ React2.createElement(DensityProvider, {
410
+ }, /* @__PURE__ */ React3.createElement(DensityProvider, {
308
411
  density: "fine"
309
- }, /* @__PURE__ */ React2.createElement(ColumnSettingsForm, {
412
+ }, /* @__PURE__ */ React3.createElement(ColumnSettingsForm, {
310
413
  column,
311
414
  tableDefs,
312
415
  tableDef,
313
416
  onUpdate,
314
417
  onDelete,
315
418
  onClose
316
- }))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null)));
419
+ }))), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null)));
317
420
  var SortIndicator = ({ direction, onClick }) => {
318
421
  if (direction === false) {
319
422
  return null;
@@ -321,17 +424,17 @@ var SortIndicator = ({ direction, onClick }) => {
321
424
  let icon;
322
425
  switch (direction) {
323
426
  case "asc":
324
- icon = /* @__PURE__ */ React2.createElement(ArrowUp, {
325
- className: getSize2(3)
427
+ icon = /* @__PURE__ */ React3.createElement(ArrowUp, {
428
+ className: getSize3(3)
326
429
  });
327
430
  break;
328
431
  case "desc":
329
- icon = /* @__PURE__ */ React2.createElement(ArrowDown, {
330
- className: getSize2(3)
432
+ icon = /* @__PURE__ */ React3.createElement(ArrowDown, {
433
+ className: getSize3(3)
331
434
  });
332
435
  break;
333
436
  }
334
- return /* @__PURE__ */ React2.createElement("div", {
437
+ return /* @__PURE__ */ React3.createElement("div", {
335
438
  onClick,
336
439
  className: "flex items-center cursor-pointer"
337
440
  }, icon);
@@ -341,20 +444,20 @@ var SortIndicator = ({ direction, onClick }) => {
341
444
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
342
445
  import { getCoreRowModel, getSortedRowModel, useReactTable, getGroupedRowModel, getExpandedRowModel } from "@tanstack/react-table";
343
446
  import { useVirtualizer } from "@tanstack/react-virtual";
344
- import React8, { Fragment, useCallback as useCallback2, useEffect as useEffect2, useState as useState5 } from "react";
447
+ import React9, { Fragment, useCallback as useCallback3, useEffect as useEffect2, useState as useState6 } from "react";
345
448
  import { log } from "@dxos/log";
346
449
  import { useDefaultValue, useOnTransition } from "@dxos/react-ui";
347
450
 
348
451
  // packages/ui/react-ui-table/src/components/Table/TableBody.tsx
349
452
  import { useArrowNavigationGroup } from "@fluentui/react-tabster";
350
453
  import { flexRender } from "@tanstack/react-table";
351
- import React5 from "react";
454
+ import React6 from "react";
352
455
 
353
456
  // packages/ui/react-ui-table/src/components/Table/TableContext.tsx
354
- import React3, { useContext, createContext } from "react";
457
+ import React4, { useContext, createContext } from "react";
355
458
  var TableContext = /* @__PURE__ */ createContext({});
356
459
  var TableProvider = ({ children, ...value }) => {
357
- return /* @__PURE__ */ React3.createElement(TableContext.Provider, {
460
+ return /* @__PURE__ */ React4.createElement(TableContext.Provider, {
358
461
  value
359
462
  }, children);
360
463
  };
@@ -364,32 +467,32 @@ var useTableContext = () => {
364
467
  };
365
468
 
366
469
  // packages/ui/react-ui-table/src/theme.ts
367
- import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx3 } from "@dxos/react-ui-theme";
470
+ import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx4 } from "@dxos/react-ui-theme";
368
471
  var currentRow = "!bg-neutral-75 !dark:bg-neutral-850";
369
472
  var selectedRow = "!bg-primary-100 dark:!bg-primary-700";
370
473
  var flushPadding = "pli-0 plb-0";
371
474
  var textPadding = "pli-2 plb-0.5";
372
475
  var headPadding = "pli-2 plb-1";
373
476
  var gridCellFocusRing = "focus-within:z-[11] focus-within:outline outline-2 outline-primary-500 dark:outline-primary-400";
374
- var tableRoot = ({ fullWidth }, ...etc) => mx3("table-fixed", fullWidth && "is-full", ...etc);
375
- var groupTh = (_props, ...etc) => mx3("text-start font-medium", flushPadding, ...etc);
376
- var theadRoot = ({ header, stickyHeader }, ...etc) => mx3(header ? stickyHeader && "sticky block-start-[--sticky-top] z-[1]" : "collapse", header && "base-surface", "drop-shadow-sm", ...etc);
377
- var theadTr = (_props, ...etc) => mx3("group", ...etc);
378
- var theadTh = ({ border }, ...etc) => mx3("relative", "text-start font-medium select-none truncate", headPadding, border && groupBorder, border && "border border-t-0 border-b-0 border-neutral-200", ...etc);
477
+ var tableRoot = ({ fullWidth }, ...etc) => mx4("table-fixed", fullWidth && "is-full", ...etc);
478
+ var groupTh = (_props, ...etc) => mx4("text-start font-medium", flushPadding, ...etc);
479
+ var theadRoot = ({ header, stickyHeader }, ...etc) => mx4(header ? stickyHeader && "sticky block-start-[--sticky-top] z-[1]" : "collapse", header && "base-surface", "drop-shadow-sm", ...etc);
480
+ var theadTr = (_props, ...etc) => mx4("group", ...etc);
481
+ var theadTh = ({ border }, ...etc) => mx4("relative", "text-start font-medium select-none truncate", headPadding, border && groupBorder, border && "border border-t-0 border-b-0 border-neutral-200", ...etc);
379
482
  var theadResizeRoot = ({ isResizing }) => {
380
- return mx3("absolute h-full w-[4px] top-0 right-0", "cursor-col-resize", "user-select-none", "touch-action-none", !isResizing && "group-hover:bg-neutral-100 dark:group-hover:bg-neutral-800", "pointer-coarse:bg-neutral-100 dark:pointer-coarse:bg-neutral-800", isResizing && "bg-primary-500 dark:bg-primary-400");
483
+ return mx4("absolute h-full w-[4px] top-0 right-0", "cursor-col-resize", "user-select-none", "touch-action-none", !isResizing && "group-hover:bg-neutral-100 dark:group-hover:bg-neutral-800", "pointer-coarse:bg-neutral-100 dark:pointer-coarse:bg-neutral-800", isResizing && "bg-primary-500 dark:bg-primary-400");
381
484
  };
382
- var tbodyRoot = (_props, ...etc) => mx3(...etc);
383
- var tbodyTr = ({ canBeCurrent, isPinned }, ...etc) => mx3("group", canBeCurrent ? ghostSelectedCurrent : ghostSelected, canBeCurrent && focusRing, canBeCurrent && "cursor-pointer rounded", isPinned && "sticky z-1 bottom-[-1px] base-surface", ...etc);
384
- var tdRoot = ({ border, isGrid }, ...etc) => mx3("relative", flushPadding, border && "border", border && groupBorder, isGrid && gridCellFocusRing, ...etc);
385
- var tdContent = (_props, ...etc) => mx3(...etc);
386
- var tfootRoot = (_props, ...etc) => mx3("sticky block-end-0 z-10", modalSurface, ...etc);
387
- var tfootTr = (_props, ...etc) => mx3(...etc);
388
- var tfootTh = ({ border }, ...etc) => mx3(textPadding, modalSurface, border && groupBorder, ...etc);
485
+ var tbodyRoot = (_props, ...etc) => mx4(...etc);
486
+ var tbodyTr = ({ canBeCurrent, isPinned }, ...etc) => mx4("group", canBeCurrent ? ghostSelectedCurrent : ghostSelected, canBeCurrent && focusRing, canBeCurrent && "cursor-pointer rounded", isPinned && "sticky z-1 bottom-[-1px] base-surface", ...etc);
487
+ var tdRoot = ({ border, isGrid }, ...etc) => mx4("relative", flushPadding, border && "border", border && groupBorder, isGrid && gridCellFocusRing, ...etc);
488
+ var tdContent = (_props, ...etc) => mx4(...etc);
489
+ var tfootRoot = (_props, ...etc) => mx4("sticky block-end-0 z-10", modalSurface, ...etc);
490
+ var tfootTr = (_props, ...etc) => mx4(...etc);
491
+ var tfootTh = ({ border }, ...etc) => mx4(textPadding, modalSurface, border && groupBorder, ...etc);
389
492
 
390
493
  // packages/ui/react-ui-table/src/components/Cell/Cell.tsx
391
494
  import { useFocusableGroup } from "@fluentui/react-tabster";
392
- import React4 from "react";
495
+ import React5 from "react";
393
496
  var CELL_NAME = "Cell";
394
497
  var FocusableCell = ({ cell, children }) => {
395
498
  const tableContext = useTableContext();
@@ -397,7 +500,7 @@ var FocusableCell = ({ cell, children }) => {
397
500
  tabBehavior: "limited"
398
501
  });
399
502
  const className = tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames);
400
- return /* @__PURE__ */ React4.createElement("td", {
503
+ return /* @__PURE__ */ React5.createElement("td", {
401
504
  tabIndex: 0,
402
505
  ...domAttributes,
403
506
  className
@@ -405,14 +508,14 @@ var FocusableCell = ({ cell, children }) => {
405
508
  };
406
509
  var StaticCell = ({ cell, children }) => {
407
510
  const tableContext = useTableContext();
408
- return /* @__PURE__ */ React4.createElement("td", {
511
+ return /* @__PURE__ */ React5.createElement("td", {
409
512
  className: tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames)
410
513
  }, children);
411
514
  };
412
515
  var Cell = ({ cell, children }) => {
413
516
  const { isGrid } = useTableContext();
414
517
  const Root = isGrid ? FocusableCell : StaticCell;
415
- return /* @__PURE__ */ React4.createElement(Root, {
518
+ return /* @__PURE__ */ React5.createElement(Root, {
416
519
  cell
417
520
  }, children);
418
521
  };
@@ -427,7 +530,7 @@ var TableBody = ({ rows }) => {
427
530
  axis: "grid"
428
531
  });
429
532
  const canBeCurrent = !isGrid && !!onDatumClick;
430
- return /* @__PURE__ */ React5.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
533
+ return /* @__PURE__ */ React6.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
431
534
  const isCurrent = currentDatum === row.original;
432
535
  const isSelected = rowSelection?.[row.id];
433
536
  const isPinned = row.getIsPinned();
@@ -435,7 +538,7 @@ var TableBody = ({ rows }) => {
435
538
  canBeCurrent,
436
539
  isPinned: isPinned !== false
437
540
  });
438
- return /* @__PURE__ */ React5.createElement("tr", {
541
+ return /* @__PURE__ */ React6.createElement("tr", {
439
542
  key: keyAccessor ? keyAccessor(row.original) : row.id,
440
543
  className: classNames,
441
544
  ...isCurrent && {
@@ -455,57 +558,57 @@ var TableBody = ({ rows }) => {
455
558
  }
456
559
  }
457
560
  }
458
- }, debug && /* @__PURE__ */ React5.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
459
- return /* @__PURE__ */ React5.createElement(Cell, {
561
+ }, debug && /* @__PURE__ */ React6.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
562
+ return /* @__PURE__ */ React6.createElement(Cell, {
460
563
  key: cell.id,
461
564
  cell
462
565
  }, flexRender(cell.column.columnDef.cell, {
463
566
  className: "pli-2",
464
567
  ...cell.getContext()
465
568
  }));
466
- }), expand && /* @__PURE__ */ React5.createElement("td", null));
569
+ }), expand && /* @__PURE__ */ React6.createElement("td", null));
467
570
  }));
468
571
  };
469
572
  TableBody.displayName = TABLE_BODY_NAME;
470
573
 
471
574
  // packages/ui/react-ui-table/src/components/Table/TableFooter.tsx
472
575
  import { flexRender as flexRender2 } from "@tanstack/react-table";
473
- import React6 from "react";
576
+ import React7 from "react";
474
577
  var TABLE_FOOT_NAME = "TableFooter";
475
578
  var TableFooter = (props) => {
476
579
  const tableContext = useTableContext();
477
580
  const { table, expand, debug } = tableContext;
478
581
  const footers = table.getFooterGroups();
479
- return /* @__PURE__ */ React6.createElement("tfoot", {
582
+ return /* @__PURE__ */ React7.createElement("tfoot", {
480
583
  className: tfootRoot(props)
481
- }, footers.map((footerGroup) => /* @__PURE__ */ React6.createElement("tr", {
584
+ }, footers.map((footerGroup) => /* @__PURE__ */ React7.createElement("tr", {
482
585
  key: footerGroup.id,
483
586
  className: tfootTr(tableContext)
484
- }, debug && /* @__PURE__ */ React6.createElement("th", null), footerGroup.headers.map((footer) => {
485
- return /* @__PURE__ */ React6.createElement("th", {
587
+ }, debug && /* @__PURE__ */ React7.createElement("th", null), footerGroup.headers.map((footer) => {
588
+ return /* @__PURE__ */ React7.createElement("th", {
486
589
  key: footer.id,
487
590
  className: tfootTh(tableContext, footer.column.columnDef.meta?.footer?.classNames)
488
591
  }, footer.isPlaceholder ? null : flexRender2(footer.column.columnDef.footer, footer.getContext()));
489
- }), expand && /* @__PURE__ */ React6.createElement("th", null))));
592
+ }), expand && /* @__PURE__ */ React7.createElement("th", null))));
490
593
  };
491
594
  TableFooter.displayName = TABLE_FOOT_NAME;
492
595
 
493
596
  // packages/ui/react-ui-table/src/components/Table/TableHead.tsx
494
597
  import { flexRender as flexRender3 } from "@tanstack/react-table";
495
- import React7 from "react";
598
+ import React8 from "react";
496
599
  var TABLE_HEAD_NAME = "TableHeader";
497
600
  var TableHead = (_props) => {
498
601
  const tableContext = useTableContext();
499
602
  const headerGroups = tableContext.table.getHeaderGroups();
500
- return /* @__PURE__ */ React7.createElement("thead", {
603
+ return /* @__PURE__ */ React8.createElement("thead", {
501
604
  className: theadRoot(tableContext)
502
605
  }, headerGroups.map((headerGroup) => {
503
606
  return (
504
607
  // Group element to hover resize handles.
505
- /* @__PURE__ */ React7.createElement("tr", {
608
+ /* @__PURE__ */ React8.createElement("tr", {
506
609
  key: headerGroup.id,
507
610
  className: theadTr(tableContext)
508
- }, tableContext.debug && /* @__PURE__ */ React7.createElement("th", {
611
+ }, tableContext.debug && /* @__PURE__ */ React8.createElement("th", {
509
612
  className: "font-mono",
510
613
  style: {
511
614
  width: 32
@@ -514,13 +617,13 @@ var TableHead = (_props) => {
514
617
  const isResizing = header.column.getIsResizing();
515
618
  const onResize = header.getResizeHandler();
516
619
  const resizable = header.column.columnDef.meta?.resizable;
517
- return /* @__PURE__ */ React7.createElement("th", {
620
+ return /* @__PURE__ */ React8.createElement("th", {
518
621
  key: header.id,
519
622
  style: {
520
623
  width: header.getSize()
521
624
  },
522
625
  className: theadTh(tableContext, header.column.columnDef.meta?.header?.classNames)
523
- }, !header || header.isPlaceholder ? null : flexRender3(header.column.columnDef.header, header.getContext()), resizable && /* @__PURE__ */ React7.createElement("div", {
626
+ }, !header || header.isPlaceholder ? null : flexRender3(header.column.columnDef.header, header.getContext()), resizable && /* @__PURE__ */ React8.createElement("div", {
524
627
  className: theadResizeRoot({
525
628
  isResizing
526
629
  }),
@@ -528,48 +631,12 @@ var TableHead = (_props) => {
528
631
  onMouseDown: onResize,
529
632
  onTouchStart: onResize
530
633
  }));
531
- }), tableContext.expand && /* @__PURE__ */ React7.createElement("th", null))
634
+ }), tableContext.expand && /* @__PURE__ */ React8.createElement("th", null))
532
635
  );
533
636
  }));
534
637
  };
535
638
  TableHead.displayName = TABLE_HEAD_NAME;
536
639
 
537
- // packages/ui/react-ui-table/src/components/hooks/usePinLastRow.ts
538
- import { useEffect, useState as useState4 } from "react";
539
- var usePinLastRow = (pinLastRow, table, data, getScrollElement) => {
540
- const [pinnedRowKey, setPinnedRowKey] = useState4();
541
- useEffect(() => {
542
- if (!pinLastRow) {
543
- return;
544
- }
545
- const rows = table.getRowModel().rows;
546
- const rowToPin = rows[rows.length - 1];
547
- const rowId = rowToPin.id;
548
- if (rowId === pinnedRowKey) {
549
- return;
550
- }
551
- table.resetRowPinning();
552
- rowToPin.pin("bottom");
553
- const scrollElement = getScrollElement?.();
554
- const isFirstRender = pinnedRowKey === void 0;
555
- if (scrollElement && !isFirstRender) {
556
- requestAnimationFrame(() => {
557
- scrollElement.scrollTo({
558
- top: scrollElement.scrollHeight
559
- });
560
- });
561
- }
562
- setPinnedRowKey(rowId);
563
- }, [
564
- pinLastRow,
565
- table,
566
- getScrollElement,
567
- pinnedRowKey,
568
- setPinnedRowKey,
569
- data
570
- ]);
571
- };
572
-
573
640
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
574
641
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
575
642
  var Table = (props) => {
@@ -577,8 +644,8 @@ var Table = (props) => {
577
644
  const columns = useDefaultValue(props.columns, []);
578
645
  const data = useDefaultValue(props.data, []);
579
646
  const TableProvider2 = TableProvider;
580
- const [columnsInitialised, setColumnsInitialised] = useState5(false);
581
- const [columnSizing, setColumnSizing] = useState5({});
647
+ const [columnsInitialised, setColumnsInitialised] = useState6(false);
648
+ const [columnSizing, setColumnSizing] = useState6({});
582
649
  useEffect2(() => {
583
650
  if (columnsInitialised) {
584
651
  return;
@@ -592,8 +659,8 @@ var Table = (props) => {
592
659
  columns,
593
660
  setColumnSizing
594
661
  ]);
595
- const [columnSizingInfo, setColumnSizingInfo] = useState5({});
596
- const notifyColumnResize = useCallback2(() => onColumnResize?.(columnSizing), [
662
+ const [columnSizingInfo, setColumnSizingInfo] = useState6({});
663
+ const notifyColumnResize = useCallback3(() => onColumnResize?.(columnSizing), [
597
664
  onColumnResize,
598
665
  columnSizing
599
666
  ]);
@@ -603,7 +670,7 @@ var Table = (props) => {
603
670
  onChange: props.onRowSelectionChange,
604
671
  defaultProp: props.defaultRowSelection
605
672
  });
606
- const handleRowSelectionChange = useCallback2((updaterOrValue) => {
673
+ const handleRowSelectionChange = useCallback3((updaterOrValue) => {
607
674
  const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
608
675
  if (rowsSelectable === "multi") {
609
676
  setRowSelection(nextRowSelection);
@@ -620,7 +687,7 @@ var Table = (props) => {
620
687
  setRowSelection,
621
688
  rowSelection
622
689
  ]);
623
- const [grouping, handleGroupingChange] = useState5(props.grouping ?? []);
690
+ const [grouping, handleGroupingChange] = useState6(props.grouping ?? []);
624
691
  useEffect2(() => handleGroupingChange(props.grouping ?? []), [
625
692
  handleGroupingChange,
626
693
  props.grouping
@@ -680,13 +747,13 @@ var Table = (props) => {
680
747
  C: (f, a) => f(...a)
681
748
  });
682
749
  }
683
- return /* @__PURE__ */ React8.createElement(TableProvider2, {
750
+ return /* @__PURE__ */ React9.createElement(TableProvider2, {
684
751
  ...props,
685
752
  table,
686
753
  header,
687
754
  expand,
688
755
  isGrid: role === "grid" || role === "treegrid"
689
- }, /* @__PURE__ */ React8.createElement(TableImpl, {
756
+ }, /* @__PURE__ */ React9.createElement(TableImpl, {
690
757
  debug: false,
691
758
  getScrollElement,
692
759
  ...props
@@ -702,13 +769,13 @@ var TableImpl = (props) => {
702
769
  ...bottomRows
703
770
  ];
704
771
  if (debug) {
705
- return /* @__PURE__ */ React8.createElement("pre", {
772
+ return /* @__PURE__ */ React9.createElement("pre", {
706
773
  className: "font-mono text-xs text-neutral-500 m-1 p-2 ring"
707
- }, /* @__PURE__ */ React8.createElement("code", null, JSON.stringify(table.getState(), void 0, 2)));
774
+ }, /* @__PURE__ */ React9.createElement("code", null, JSON.stringify(table.getState(), void 0, 2)));
708
775
  }
709
776
  const virtualisable = getScrollElement !== void 0;
710
777
  const isResizingColumn = table.getState().columnSizingInfo.isResizingColumn;
711
- return /* @__PURE__ */ React8.createElement("table", {
778
+ return /* @__PURE__ */ React9.createElement("table", {
712
779
  role,
713
780
  className: tableRoot(props, classNames),
714
781
  ...!fullWidth && {
@@ -716,13 +783,13 @@ var TableImpl = (props) => {
716
783
  width: table.getTotalSize()
717
784
  }
718
785
  }
719
- }, /* @__PURE__ */ React8.createElement(TableHead, null), grouping?.length !== 0 ? virtualisable ? isResizingColumn ? /* @__PURE__ */ React8.createElement(MemoizedVirtualisedTableContent, {
786
+ }, /* @__PURE__ */ React9.createElement(TableHead, null), grouping?.length !== 0 ? virtualisable ? isResizingColumn ? /* @__PURE__ */ React9.createElement(MemoizedVirtualisedTableContent, {
720
787
  getScrollElement
721
- }) : /* @__PURE__ */ React8.createElement(VirtualizedTableContent, {
788
+ }) : /* @__PURE__ */ React9.createElement(VirtualizedTableContent, {
722
789
  getScrollElement
723
- }) : /* @__PURE__ */ React8.createElement(TableBody, {
790
+ }) : /* @__PURE__ */ React9.createElement(TableBody, {
724
791
  rows
725
- }) : /* @__PURE__ */ React8.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React8.createElement(TableFooter, null));
792
+ }) : /* @__PURE__ */ React9.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React9.createElement(TableFooter, null));
726
793
  };
727
794
  var VirtualizedTableContent = ({ getScrollElement }) => {
728
795
  const { table } = useTableContext();
@@ -742,113 +809,44 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
742
809
  ...virtualRows.map((virtualRow) => centerRows[virtualRow.index]),
743
810
  ...pinnedRows
744
811
  ];
745
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React8.createElement("tbody", {
812
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React9.createElement("tbody", {
746
813
  role: "none"
747
- }, /* @__PURE__ */ React8.createElement("tr", {
814
+ }, /* @__PURE__ */ React9.createElement("tr", {
748
815
  role: "none"
749
- }, /* @__PURE__ */ React8.createElement("td", {
816
+ }, /* @__PURE__ */ React9.createElement("td", {
750
817
  style: {
751
818
  height: `${paddingTop}px`
752
819
  },
753
820
  role: "none"
754
- }))), /* @__PURE__ */ React8.createElement(TableBody, {
821
+ }))), /* @__PURE__ */ React9.createElement(TableBody, {
755
822
  rows: rowsToRender
756
- }), paddingBottom > 0 && /* @__PURE__ */ React8.createElement("tbody", {
823
+ }), paddingBottom > 0 && /* @__PURE__ */ React9.createElement("tbody", {
757
824
  role: "none"
758
- }, /* @__PURE__ */ React8.createElement("tr", {
825
+ }, /* @__PURE__ */ React9.createElement("tr", {
759
826
  role: "none"
760
- }, /* @__PURE__ */ React8.createElement("td", {
827
+ }, /* @__PURE__ */ React9.createElement("td", {
761
828
  style: {
762
829
  height: `${paddingBottom}px`
763
830
  },
764
831
  role: "none"
765
832
  }))));
766
833
  };
767
- var MemoizedVirtualisedTableContent = /* @__PURE__ */ React8.memo(VirtualizedTableContent);
834
+ var MemoizedVirtualisedTableContent = /* @__PURE__ */ React9.memo(VirtualizedTableContent);
768
835
  var GroupedTableContent = () => {
769
836
  const { table: { getGroupedRowModel: getGroupedRowModel2, getHeaderGroups, getState }, debug } = useTableContext();
770
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
771
- return /* @__PURE__ */ React8.createElement(Fragment, {
837
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
838
+ return /* @__PURE__ */ React9.createElement(Fragment, {
772
839
  key: i
773
- }, /* @__PURE__ */ React8.createElement("thead", null, /* @__PURE__ */ React8.createElement("tr", null, debug && /* @__PURE__ */ React8.createElement("th", null), /* @__PURE__ */ React8.createElement("th", {
840
+ }, /* @__PURE__ */ React9.createElement("thead", null, /* @__PURE__ */ React9.createElement("tr", null, debug && /* @__PURE__ */ React9.createElement("th", null), /* @__PURE__ */ React9.createElement("th", {
774
841
  // TODO(burdon): Calculate row span.
775
842
  colSpan: getHeaderGroups()[0].headers.length,
776
843
  className: groupTh({})
777
- }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React8.createElement(TableBody, {
844
+ }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React9.createElement(TableBody, {
778
845
  rows: row.subRows
779
846
  }));
780
847
  }));
781
848
  };
782
849
 
783
- // packages/ui/react-ui-table/src/components/Cell/CellCombobox.tsx
784
- import { CaretDown as CaretDown2 } from "@phosphor-icons/react";
785
- import React9, { useCallback as useCallback3, useState as useState6 } from "react";
786
- import { Popover as Popover2, useTranslation as useTranslation2 } from "@dxos/react-ui";
787
- import { PopoverCombobox } from "@dxos/react-ui-searchlist";
788
- import { descriptionText, getSize as getSize3, mx as mx4, staticPlaceholderText } from "@dxos/react-ui-theme";
789
- var initialItems = (model, value) => value ? {
790
- [model.getId(value)]: {
791
- label: model.getText(value),
792
- data: value
793
- }
794
- } : {};
795
- var CellCombobox = ({ model, value, onValueChange }) => {
796
- const { t } = useTranslation2(translationKey);
797
- const [items, setItems] = useState6(initialItems(model, value));
798
- const [loading, setLoading] = useState6(false);
799
- const [searchInputValue, setSearchInputValue] = useState6("");
800
- const handleSearchInputValueChange = async (text) => {
801
- setSearchInputValue(text ?? "");
802
- setLoading(true);
803
- const items2 = await model.query(text);
804
- setItems(items2.reduce((acc, item) => {
805
- acc[model.getId(item)] = {
806
- label: model.getText(item),
807
- data: item
808
- };
809
- return acc;
810
- }, initialItems(model, value)));
811
- setLoading(false);
812
- };
813
- const handleValueChange = useCallback3((id) => {
814
- onValueChange(items[id]?.data);
815
- }, [
816
- items,
817
- onValueChange
818
- ]);
819
- return /* @__PURE__ */ React9.createElement(PopoverCombobox.Root, {
820
- placeholder: t("no selection label")
821
- }, /* @__PURE__ */ React9.createElement(PopoverCombobox.Trigger, {
822
- variant: "ghost",
823
- classNames: "is-full rounded-none ring-inset"
824
- }, value ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement("span", {
825
- className: mx4("font-normal text-start text-base flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
826
- }, model.getText(value)), /* @__PURE__ */ React9.createElement(CaretDown2, {
827
- weight: "bold",
828
- className: getSize3(3)
829
- })) : null), /* @__PURE__ */ React9.createElement(PopoverCombobox.Content, {
830
- shouldFilter: false,
831
- classNames: "is-[--radix-popover-trigger-width]"
832
- }, /* @__PURE__ */ React9.createElement(PopoverCombobox.Input, {
833
- value: searchInputValue,
834
- onValueChange: handleSearchInputValueChange
835
- }), /* @__PURE__ */ React9.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React9.createElement("p", {
836
- className: mx4("text-center", descriptionText)
837
- }, "Start typing to search") : loading ? /* @__PURE__ */ React9.createElement("p", {
838
- className: mx4("text-center", descriptionText)
839
- }, "Searching\u2026") : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(PopoverCombobox.Empty, {
840
- classNames: [
841
- "text-center",
842
- descriptionText
843
- ]
844
- }, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React9.createElement(PopoverCombobox.Item, {
845
- key: id,
846
- value: id,
847
- onSelect: handleValueChange,
848
- classNames: "truncate"
849
- }, label)))), /* @__PURE__ */ React9.createElement(Popover2.Arrow, null)));
850
- };
851
-
852
850
  // packages/ui/react-ui-table/src/helpers.tsx
853
851
  import { useFocusFinders } from "@fluentui/react-tabster";
854
852
  import { Check as Check2, ClipboardText, X as X3 } from "@phosphor-icons/react";
@@ -1246,11 +1244,162 @@ var ColumnBuilder = class {
1246
1244
  ...props
1247
1245
  };
1248
1246
  }
1247
+ /**
1248
+ * This display column type is for nested/unhandled data to appear as JSON.
1249
+ */
1250
+ display({ label, classNames, ...props } = {}) {
1251
+ return {
1252
+ size: 120,
1253
+ minSize: 120,
1254
+ header: (cell) => label ?? cell.header.id,
1255
+ cell: (cell) => {
1256
+ const value = cell.getValue();
1257
+ return /* @__PURE__ */ React10.createElement("div", {
1258
+ className: "overflow-scroll"
1259
+ }, /* @__PURE__ */ React10.createElement("code", {
1260
+ className: "text-xs"
1261
+ }, JSON.stringify(value)));
1262
+ },
1263
+ ...props,
1264
+ meta: {
1265
+ ...props.meta,
1266
+ cell: {
1267
+ ...props.meta?.cell,
1268
+ classNames: [
1269
+ "font-mono",
1270
+ textPadding,
1271
+ classNames
1272
+ ]
1273
+ }
1274
+ }
1275
+ };
1276
+ }
1277
+ };
1278
+
1279
+ // packages/ui/react-ui-table/src/schema/schema.ts
1280
+ import { AST } from "@effect/schema";
1281
+ var isOptionalUnion = (prop) => AST.isUnion(prop.type) && prop.isOptional;
1282
+ var unwrapOptionProperty = (prop) => {
1283
+ if (!isOptionalUnion(prop)) {
1284
+ throw new Error("Not an optional property");
1285
+ }
1286
+ if (!AST.isUnion(prop.type)) {
1287
+ throw new Error("Not a union type");
1288
+ }
1289
+ const [type, _undefinedCase] = prop.type.types;
1290
+ return type;
1291
+ };
1292
+ var typeToColumn = (type) => {
1293
+ if (AST.isStringKeyword(type)) {
1294
+ return "string";
1295
+ } else if (AST.isNumberKeyword(type)) {
1296
+ return "number";
1297
+ } else if (AST.isBooleanKeyword(type)) {
1298
+ return "boolean";
1299
+ }
1300
+ if (AST.isRefinement(type)) {
1301
+ return typeToColumn(type.from);
1302
+ }
1303
+ if (AST.isTransform(type)) {
1304
+ const identifier = AST.getIdentifierAnnotation(type);
1305
+ if (identifier._tag === "Some") {
1306
+ if (identifier.value === "DateFromString") {
1307
+ return "date";
1308
+ }
1309
+ }
1310
+ }
1311
+ return "display";
1312
+ };
1313
+ var propertyToColumn = (property) => {
1314
+ let type = property.type;
1315
+ if (property.isOptional) {
1316
+ type = unwrapOptionProperty(property);
1317
+ }
1318
+ return typeToColumn(type);
1319
+ };
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
+
1352
+ // packages/ui/react-ui-table/src/schema/schemaToColumns.ts
1353
+ var schemaToColumnDefs = (schema) => {
1354
+ const { helper, builder } = createColumnBuilder();
1355
+ const classified = classifySchemaProperties(schema);
1356
+ return classified.map(([name, type]) => {
1357
+ const propertyKey = name.toString();
1358
+ let column;
1359
+ switch (type) {
1360
+ case "string": {
1361
+ column = builder.string({
1362
+ label: propertyKey
1363
+ });
1364
+ break;
1365
+ }
1366
+ case "number": {
1367
+ column = builder.number({
1368
+ label: propertyKey
1369
+ });
1370
+ break;
1371
+ }
1372
+ case "boolean": {
1373
+ column = builder.switch({
1374
+ label: propertyKey
1375
+ });
1376
+ break;
1377
+ }
1378
+ case "date": {
1379
+ column = builder.date({
1380
+ label: propertyKey
1381
+ });
1382
+ break;
1383
+ }
1384
+ case "display": {
1385
+ column = builder.display({
1386
+ label: propertyKey,
1387
+ id: propertyKey
1388
+ });
1389
+ break;
1390
+ }
1391
+ default: {
1392
+ throw new Error(`Unhandled column type: ${type}`);
1393
+ }
1394
+ }
1395
+ return helper.accessor(propertyKey, column);
1396
+ });
1249
1397
  };
1250
1398
  export {
1251
1399
  CellCombobox,
1252
1400
  ColumnBuilder,
1253
1401
  ColumnMenu,
1402
+ ColumnSettingsForm,
1254
1403
  ColumnSettingsPanel,
1255
1404
  MemoizedVirtualisedTableContent,
1256
1405
  SortIndicator,
@@ -1261,6 +1410,7 @@ export {
1261
1410
  gridCellFocusRing,
1262
1411
  groupTh,
1263
1412
  headPadding,
1413
+ schemaToColumnDefs,
1264
1414
  selectedRow,
1265
1415
  tableRoot,
1266
1416
  tbodyRoot,
@@ -1275,6 +1425,8 @@ export {
1275
1425
  theadRoot,
1276
1426
  theadTh,
1277
1427
  theadTr,
1278
- translations_default as translations
1428
+ translations_default as translations,
1429
+ useColumnSorting,
1430
+ usePinLastRow
1279
1431
  };
1280
1432
  //# sourceMappingURL=index.mjs.map