@dxos/react-ui-table 0.4.10-main.b3cf40d → 0.4.10-main.bb9f1bf

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 (71) hide show
  1. package/dist/lib/browser/index.mjs +601 -359
  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} +6 -2
  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/Table/Table.d.ts.map +1 -1
  13. package/dist/types/src/components/Table/Table.stories.d.ts +31 -0
  14. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  15. package/dist/types/src/components/index.d.ts +1 -1
  16. package/dist/types/src/components/index.d.ts.map +1 -1
  17. package/dist/types/src/helpers.d.ts +4 -0
  18. package/dist/types/src/helpers.d.ts.map +1 -1
  19. package/dist/types/src/hooks/index.d.ts +5 -0
  20. package/dist/types/src/hooks/index.d.ts.map +1 -0
  21. package/dist/types/src/hooks/useColumnSizing.d.ts +12 -0
  22. package/dist/types/src/hooks/useColumnSizing.d.ts.map +1 -0
  23. package/dist/types/src/hooks/useColumnSorting.d.ts.map +1 -0
  24. package/dist/types/src/hooks/usePinLastRow.d.ts +3 -0
  25. package/dist/types/src/hooks/usePinLastRow.d.ts.map +1 -0
  26. package/dist/types/src/hooks/useRowSelection.d.ts +7 -0
  27. package/dist/types/src/hooks/useRowSelection.d.ts.map +1 -0
  28. package/dist/types/src/index.d.ts +2 -1
  29. package/dist/types/src/index.d.ts.map +1 -1
  30. package/dist/types/src/schema/SchemaToTable.stories.d.ts +11 -0
  31. package/dist/types/src/schema/SchemaToTable.stories.d.ts.map +1 -0
  32. package/dist/types/src/schema/index.d.ts +3 -0
  33. package/dist/types/src/schema/index.d.ts.map +1 -0
  34. package/dist/types/src/schema/schema.d.ts +5 -0
  35. package/dist/types/src/schema/schema.d.ts.map +1 -0
  36. package/dist/types/src/schema/schema.test.d.ts +2 -0
  37. package/dist/types/src/schema/schema.test.d.ts.map +1 -0
  38. package/dist/types/src/schema/schemaToColumns.d.ts +4 -0
  39. package/dist/types/src/schema/schemaToColumns.d.ts.map +1 -0
  40. package/dist/types/src/{schema.d.ts → schema/types.d.ts} +1 -1
  41. package/dist/types/src/schema/types.d.ts.map +1 -0
  42. package/package.json +20 -16
  43. package/src/components/{ColumnMenu.stories.tsx → ColumnMenu/ColumnMenu.stories.tsx} +31 -1
  44. package/src/components/{ColumnMenu.tsx → ColumnMenu/ColumnMenu.tsx} +36 -34
  45. package/src/components/{ColumnSettingsForm.tsx → ColumnMenu/ColumnSettingsForm.tsx} +83 -75
  46. package/src/components/ColumnMenu/index.ts +6 -0
  47. package/src/components/Table/Table.stories.tsx +162 -3
  48. package/src/components/Table/Table.tsx +35 -60
  49. package/src/components/index.ts +1 -1
  50. package/src/helpers.tsx +31 -7
  51. package/src/hooks/index.ts +8 -0
  52. package/src/hooks/useColumnSizing.ts +45 -0
  53. package/src/hooks/usePinLastRow.ts +64 -0
  54. package/src/hooks/useRowSelection.ts +39 -0
  55. package/src/index.ts +3 -1
  56. package/src/schema/SchemaToTable.stories.tsx +72 -0
  57. package/src/schema/index.ts +6 -0
  58. package/src/schema/schema.test.ts +148 -0
  59. package/src/schema/schema.ts +92 -0
  60. package/src/schema/schemaToColumns.ts +48 -0
  61. package/dist/types/src/components/ColumnMenu.d.ts.map +0 -1
  62. package/dist/types/src/components/ColumnMenu.stories.d.ts.map +0 -1
  63. package/dist/types/src/components/ColumnSettingsForm.d.ts.map +0 -1
  64. package/dist/types/src/components/hooks/useColumnSorting.d.ts.map +0 -1
  65. package/dist/types/src/components/hooks/usePinLastRow.d.ts +0 -3
  66. package/dist/types/src/components/hooks/usePinLastRow.d.ts.map +0 -1
  67. package/dist/types/src/schema.d.ts.map +0 -1
  68. package/src/components/hooks/usePinLastRow.ts +0 -43
  69. /package/dist/types/src/{components/hooks → hooks}/useColumnSorting.d.ts +0 -0
  70. /package/src/{components/hooks → hooks}/useColumnSorting.ts +0 -0
  71. /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,25 +21,107 @@ 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 useState6, useCallback as useCallback5 } 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 [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
+ });
49
118
  const propRef = useRef(null);
50
- const { t } = useTranslation(translationKey);
119
+ const { t } = useTranslation2(translationKey);
51
120
  const handleCancel = () => {
52
- setProp(column.id);
53
- onClose;
121
+ onClose?.();
54
122
  };
55
123
  const handleSave = () => {
124
+ const { prop, refTable, refProp, type, label, digits } = formState;
56
125
  if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {
57
126
  propRef.current?.focus();
58
127
  return;
@@ -64,7 +133,7 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
64
133
  return;
65
134
  }
66
135
  }
67
- onUpdate?.(prop, {
136
+ onUpdate?.(column.id, {
68
137
  id: prop,
69
138
  prop,
70
139
  label,
@@ -73,104 +142,154 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
73
142
  refProp,
74
143
  digits: safeParseInt(digits)
75
144
  });
76
- onClose();
145
+ onClose?.();
77
146
  };
78
- return /* @__PURE__ */ React.createElement("div", {
147
+ return /* @__PURE__ */ React2.createElement("div", {
79
148
  className: "flex flex-col gap-1"
80
- }, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
149
+ }, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
81
150
  classNames: "mbe-1"
82
- }, t("column label label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
151
+ }, t("column label label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
83
152
  placeholder: "Column label",
84
- value: label ?? "",
85
- onChange: (event) => setLabel(event.target.value),
153
+ value: formState.label ?? "",
154
+ onChange: (event) => setFormState((prevState) => ({
155
+ ...prevState,
156
+ label: event.target.value
157
+ })),
86
158
  autoFocus: true
87
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
159
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
88
160
  classNames: "mbe-1 mbs-3"
89
- }, t("property key label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
161
+ }, t("property key label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
90
162
  ref: propRef,
91
163
  placeholder: "Property key",
92
- // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.
93
- value: prop ?? "",
94
- onChange: (event) => setProp(event.target.value.replace(/[^\w_]/g, ""))
95
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
164
+ value: formState.prop ?? "",
165
+ onChange: (event) => setFormState((prevState) => ({
166
+ ...prevState,
167
+ prop: event.target.value.replace(/[^\w_]/g, "")
168
+ }))
169
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
96
170
  classNames: "mbe-1 mbs-3"
97
- }, t("column type label")), /* @__PURE__ */ React.createElement(Select.Root, {
98
- value: type,
99
- onValueChange: setType
100
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
171
+ }, t("column type label")), /* @__PURE__ */ React2.createElement(Select.Root, {
172
+ value: formState.type,
173
+ onValueChange: (value) => setFormState((prevState) => ({
174
+ ...prevState,
175
+ type: value
176
+ }))
177
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
101
178
  placeholder: "Type",
102
179
  classNames: "is-full"
103
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, [
180
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, [
104
181
  "number",
105
182
  "boolean",
106
183
  "string",
107
184
  "ref"
108
- ].map((type2) => /* @__PURE__ */ React.createElement(Select.Option, {
109
- key: type2,
110
- 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, {
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, {
112
189
  classNames: "mbe-1 mbs-3"
113
- }, t("digits label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
114
- value: digits ?? "",
115
- 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, {
190
+ }, t("digits label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
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, {
117
197
  classNames: "mbe-1 mbs-3"
118
- }, "Table"), /* @__PURE__ */ React.createElement(Select.Root, {
119
- value: refTable,
120
- onValueChange: setRefTable
121
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
198
+ }, "Table"), /* @__PURE__ */ React2.createElement(Select.Root, {
199
+ value: formState.refTable,
200
+ onValueChange: (value) => setFormState((prevState) => ({
201
+ ...prevState,
202
+ refTable: value
203
+ }))
204
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
122
205
  placeholder: "Table",
123
206
  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, {
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, {
125
208
  key: id,
126
209
  value: id
127
- }, name ?? id))))))), refTable && /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
210
+ }, name ?? id))))))), formState.refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
128
211
  classNames: "mbe-1 mbs-3"
129
- }, "Table property"), /* @__PURE__ */ React.createElement(Select.Root, {
130
- value: refProp,
131
- onValueChange: setRefProp
132
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
212
+ }, "Table property"), /* @__PURE__ */ React2.createElement(Select.Root, {
213
+ value: formState.refProp,
214
+ onValueChange: (value) => setFormState((prevState) => ({
215
+ ...prevState,
216
+ refProp: value
217
+ }))
218
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
133
219
  placeholder: "Property",
134
220
  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, {
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, {
136
222
  key: id,
137
223
  value: id
138
- }, label2 ?? id))))))))), /* @__PURE__ */ React.createElement(Separator, {
224
+ }, label ?? id)))))))), /* @__PURE__ */ React2.createElement(Separator, {
139
225
  classNames: "mli-2"
140
- }), /* @__PURE__ */ React.createElement(Section, {
226
+ }), /* @__PURE__ */ React2.createElement(Section, {
141
227
  className: "space-b-1.5"
142
- }, /* @__PURE__ */ React.createElement(Button, {
228
+ }, /* @__PURE__ */ React2.createElement(Button, {
143
229
  variant: "primary",
144
230
  classNames: "is-full flex gap-2",
145
231
  onClick: handleSave
146
- }, /* @__PURE__ */ React.createElement("span", null, t("save label")), /* @__PURE__ */ React.createElement("div", {
232
+ }, /* @__PURE__ */ React2.createElement("span", null, t("save label")), /* @__PURE__ */ React2.createElement("div", {
147
233
  className: "grow"
148
- }), /* @__PURE__ */ React.createElement(Check, {
149
- className: getSize(5)
150
- })), /* @__PURE__ */ React.createElement(Button, {
234
+ }), /* @__PURE__ */ React2.createElement(Check, {
235
+ className: getSize2(5)
236
+ })), /* @__PURE__ */ React2.createElement(Button, {
151
237
  classNames: "is-full flex gap-2",
152
238
  onClick: handleCancel
153
- }, /* @__PURE__ */ React.createElement("span", null, t("cancel label", {
239
+ }, /* @__PURE__ */ React2.createElement("span", null, t("cancel label", {
154
240
  ns: "os"
155
- })), /* @__PURE__ */ React.createElement("div", {
241
+ })), /* @__PURE__ */ React2.createElement("div", {
156
242
  className: "grow"
157
- }), /* @__PURE__ */ React.createElement(X, {
158
- className: getSize(5)
159
- })), /* @__PURE__ */ React.createElement(Button, {
243
+ }), /* @__PURE__ */ React2.createElement(X, {
244
+ className: getSize2(5)
245
+ })), /* @__PURE__ */ React2.createElement(Button, {
160
246
  classNames: "is-full flex gap-2",
161
247
  onClick: () => onDelete?.(column.id)
162
- }, /* @__PURE__ */ React.createElement("span", null, t("delete label")), /* @__PURE__ */ React.createElement("div", {
248
+ }, /* @__PURE__ */ React2.createElement("span", null, t("delete label")), /* @__PURE__ */ React2.createElement("div", {
163
249
  className: "grow"
164
- }), /* @__PURE__ */ React.createElement(Trash, {
165
- className: getSize(5)
250
+ }), /* @__PURE__ */ React2.createElement(Trash, {
251
+ className: getSize2(5)
166
252
  }))));
167
253
  };
168
254
 
169
- // packages/ui/react-ui-table/src/components/hooks/useColumnSorting.ts
170
- import { useState as useState2 } from "react";
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
+
288
+ // packages/ui/react-ui-table/src/hooks/useColumnSorting.ts
289
+ import { useState as useState4 } from "react";
171
290
  var useColumnSorting = (column) => {
172
- const [sortDirection, setSortDirection] = useState2(column.getIsSorted());
173
- const [firstSort, setFirstSort] = useState2();
291
+ const [sortDirection, setSortDirection] = useState4(column.getIsSorted());
292
+ const [firstSort, setFirstSort] = useState4();
174
293
  const canSort = column.getCanSort();
175
294
  const updateColumnSort = (direction) => {
176
295
  setSortDirection(direction);
@@ -212,22 +331,110 @@ var useColumnSorting = (column) => {
212
331
  };
213
332
  };
214
333
 
215
- // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
334
+ // packages/ui/react-ui-table/src/hooks/usePinLastRow.ts
335
+ import { useCallback as useCallback3, useEffect as useEffect2, useState as useState5 } from "react";
336
+ var usePinLastRow = (pinLastRow, table, data, getScrollElement) => {
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
+ }));
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(() => {
362
+ const rows = table.getRowModel().rows;
363
+ if (rows.length === 0) {
364
+ return clearRowPinning();
365
+ }
366
+ const lastRow = rows[rows.length - 1];
367
+ if (lastRow.id === pinnedRowKey) {
368
+ return;
369
+ }
370
+ pinRow(lastRow);
371
+ if (pinnedRowKey !== void 0) {
372
+ scrollToBottom();
373
+ }
374
+ }, [
375
+ table,
376
+ scrollToBottom,
377
+ pinnedRowKey
378
+ ]);
379
+ useEffect2(() => {
380
+ if (pinLastRow) {
381
+ pinLastRowCallback();
382
+ }
383
+ }, [
384
+ data,
385
+ pinLastRow,
386
+ pinLastRowCallback
387
+ ]);
388
+ };
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
+
422
+ // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnMenu.tsx
216
423
  var ColumnMenu = ({ column, ...props }) => {
217
424
  const title = column.label?.length ? column.label : column.id;
218
425
  const header = props.context.header;
219
426
  const { canSort, sortDirection, onSelectSort, onToggleSort, onClearSort } = useColumnSorting(header.column);
220
427
  const columnSettingsAnchorRef = useRef2(null);
221
- const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState3(false);
428
+ const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState6(false);
222
429
  const shouldPreventFocusOnClose = useRef2(false);
223
- const onOpenColumnSettings = useCallback(() => {
430
+ const onOpenColumnSettings = useCallback5(() => {
224
431
  shouldPreventFocusOnClose.current = true;
225
432
  setIsColumnSettingsOpen(true);
226
433
  }, [
227
434
  shouldPreventFocusOnClose,
228
435
  setIsColumnSettingsOpen
229
436
  ]);
230
- const onDropdownCloseAutoFocus = useCallback((event) => {
437
+ const onDropdownCloseAutoFocus = useCallback5((event) => {
231
438
  if (shouldPreventFocusOnClose.current) {
232
439
  event.preventDefault();
233
440
  shouldPreventFocusOnClose.current = false;
@@ -235,85 +442,85 @@ var ColumnMenu = ({ column, ...props }) => {
235
442
  }, [
236
443
  shouldPreventFocusOnClose
237
444
  ]);
238
- return /* @__PURE__ */ React2.createElement("div", {
445
+ return /* @__PURE__ */ React3.createElement("div", {
239
446
  className: "flex items-center justify-center justify-between"
240
- }, /* @__PURE__ */ React2.createElement("div", {
447
+ }, /* @__PURE__ */ React3.createElement("div", {
241
448
  className: "flex items-center gap-1 truncate",
242
449
  title
243
- }, /* @__PURE__ */ React2.createElement(SortIndicator, {
450
+ }, /* @__PURE__ */ React3.createElement(SortIndicator, {
244
451
  direction: sortDirection,
245
452
  onClick: onToggleSort
246
- }), /* @__PURE__ */ React2.createElement("div", {
453
+ }), /* @__PURE__ */ React3.createElement("div", {
247
454
  className: "truncate"
248
- }, title)), /* @__PURE__ */ React2.createElement(DropdownMenu.Root, {
455
+ }, title)), /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
249
456
  modal: false
250
- }, /* @__PURE__ */ React2.createElement(Popover.Root, {
457
+ }, /* @__PURE__ */ React3.createElement(Popover2.Root, {
251
458
  open: isColumnSettingsOpen,
252
459
  onOpenChange: setIsColumnSettingsOpen,
253
460
  modal: false
254
- }, /* @__PURE__ */ React2.createElement(DropdownMenu.Trigger, {
461
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
255
462
  ref: columnSettingsAnchorRef,
256
463
  asChild: true
257
- }, /* @__PURE__ */ React2.createElement(Popover.Anchor, {
464
+ }, /* @__PURE__ */ React3.createElement(Popover2.Anchor, {
258
465
  asChild: true
259
- }, /* @__PURE__ */ React2.createElement(Button2, {
466
+ }, /* @__PURE__ */ React3.createElement(Button2, {
260
467
  variant: "ghost"
261
- }, /* @__PURE__ */ React2.createElement(CaretDown, {
262
- className: getSize2(4)
263
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Content, {
468
+ }, /* @__PURE__ */ React3.createElement(CaretDown2, {
469
+ className: getSize3(4)
470
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
264
471
  onCloseAutoFocus: onDropdownCloseAutoFocus,
265
472
  sideOffset: 4,
266
473
  collisionPadding: 8
267
- }, /* @__PURE__ */ React2.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
474
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
268
475
  onClick: () => onSelectSort("asc")
269
- }, /* @__PURE__ */ React2.createElement("span", {
476
+ }, /* @__PURE__ */ React3.createElement("span", {
270
477
  className: "grow"
271
- }, "Sort ascending"), /* @__PURE__ */ React2.createElement("span", {
478
+ }, "Sort ascending"), /* @__PURE__ */ React3.createElement("span", {
272
479
  className: "opacity-50"
273
- }, /* @__PURE__ */ React2.createElement(ArrowUp, {
274
- className: getSize2(4)
275
- }))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
480
+ }, /* @__PURE__ */ React3.createElement(ArrowUp, {
481
+ className: getSize3(4)
482
+ }))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
276
483
  onClick: () => onSelectSort("desc")
277
- }, /* @__PURE__ */ React2.createElement("span", {
484
+ }, /* @__PURE__ */ React3.createElement("span", {
278
485
  className: "grow"
279
- }, "Sort descending"), /* @__PURE__ */ React2.createElement("span", {
486
+ }, "Sort descending"), /* @__PURE__ */ React3.createElement("span", {
280
487
  className: "opacity-50"
281
- }, /* @__PURE__ */ React2.createElement(ArrowDown, {
282
- className: getSize2(4)
283
- }))), sortDirection !== false && /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
488
+ }, /* @__PURE__ */ React3.createElement(ArrowDown, {
489
+ className: getSize3(4)
490
+ }))), sortDirection !== false && /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
284
491
  onClick: onClearSort
285
- }, /* @__PURE__ */ React2.createElement("span", {
492
+ }, /* @__PURE__ */ React3.createElement("span", {
286
493
  className: "grow"
287
- }, "Clear sort"), /* @__PURE__ */ React2.createElement("span", {
494
+ }, "Clear sort"), /* @__PURE__ */ React3.createElement("span", {
288
495
  className: "opacity-50"
289
- }, /* @__PURE__ */ React2.createElement(X2, {
290
- className: getSize2(4)
291
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
496
+ }, /* @__PURE__ */ React3.createElement(X2, {
497
+ className: getSize3(4)
498
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
292
499
  onClick: onOpenColumnSettings
293
- }, /* @__PURE__ */ React2.createElement("span", {
500
+ }, /* @__PURE__ */ React3.createElement("span", {
294
501
  className: "grow"
295
- }, "Column settings"), /* @__PURE__ */ React2.createElement("span", {
502
+ }, "Column settings"), /* @__PURE__ */ React3.createElement("span", {
296
503
  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, {
504
+ }, /* @__PURE__ */ React3.createElement(GearSix, {
505
+ className: mx3(getSize3(4), "rotate-90")
506
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null))), /* @__PURE__ */ React3.createElement(ColumnSettingsPanel, {
300
507
  ...props,
301
508
  column,
302
509
  onClose: () => setIsColumnSettingsOpen(false)
303
510
  }))));
304
511
  };
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, {
512
+ 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
513
  classNames: "w-60"
307
- }, /* @__PURE__ */ React2.createElement(DensityProvider, {
514
+ }, /* @__PURE__ */ React3.createElement(DensityProvider, {
308
515
  density: "fine"
309
- }, /* @__PURE__ */ React2.createElement(ColumnSettingsForm, {
516
+ }, /* @__PURE__ */ React3.createElement(ColumnSettingsForm, {
310
517
  column,
311
518
  tableDefs,
312
519
  tableDef,
313
520
  onUpdate,
314
521
  onDelete,
315
522
  onClose
316
- }))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null)));
523
+ }))), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null)));
317
524
  var SortIndicator = ({ direction, onClick }) => {
318
525
  if (direction === false) {
319
526
  return null;
@@ -321,40 +528,39 @@ var SortIndicator = ({ direction, onClick }) => {
321
528
  let icon;
322
529
  switch (direction) {
323
530
  case "asc":
324
- icon = /* @__PURE__ */ React2.createElement(ArrowUp, {
325
- className: getSize2(3)
531
+ icon = /* @__PURE__ */ React3.createElement(ArrowUp, {
532
+ className: getSize3(3)
326
533
  });
327
534
  break;
328
535
  case "desc":
329
- icon = /* @__PURE__ */ React2.createElement(ArrowDown, {
330
- className: getSize2(3)
536
+ icon = /* @__PURE__ */ React3.createElement(ArrowDown, {
537
+ className: getSize3(3)
331
538
  });
332
539
  break;
333
540
  }
334
- return /* @__PURE__ */ React2.createElement("div", {
541
+ return /* @__PURE__ */ React3.createElement("div", {
335
542
  onClick,
336
543
  className: "flex items-center cursor-pointer"
337
544
  }, icon);
338
545
  };
339
546
 
340
547
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
341
- import { useControllableState } from "@radix-ui/react-use-controllable-state";
342
548
  import { getCoreRowModel, getSortedRowModel, useReactTable, getGroupedRowModel, getExpandedRowModel } from "@tanstack/react-table";
343
549
  import { useVirtualizer } from "@tanstack/react-virtual";
344
- import React8, { Fragment, useCallback as useCallback2, useEffect as useEffect2, useState as useState5 } from "react";
550
+ import React9, { Fragment, useCallback as useCallback6, useEffect as useEffect3, useState as useState7 } from "react";
345
551
  import { log } from "@dxos/log";
346
- import { useDefaultValue, useOnTransition } from "@dxos/react-ui";
552
+ import { useDefaultValue } from "@dxos/react-ui";
347
553
 
348
554
  // packages/ui/react-ui-table/src/components/Table/TableBody.tsx
349
555
  import { useArrowNavigationGroup } from "@fluentui/react-tabster";
350
556
  import { flexRender } from "@tanstack/react-table";
351
- import React5 from "react";
557
+ import React6 from "react";
352
558
 
353
559
  // packages/ui/react-ui-table/src/components/Table/TableContext.tsx
354
- import React3, { useContext, createContext } from "react";
560
+ import React4, { useContext, createContext } from "react";
355
561
  var TableContext = /* @__PURE__ */ createContext({});
356
562
  var TableProvider = ({ children, ...value }) => {
357
- return /* @__PURE__ */ React3.createElement(TableContext.Provider, {
563
+ return /* @__PURE__ */ React4.createElement(TableContext.Provider, {
358
564
  value
359
565
  }, children);
360
566
  };
@@ -364,32 +570,32 @@ var useTableContext = () => {
364
570
  };
365
571
 
366
572
  // packages/ui/react-ui-table/src/theme.ts
367
- import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx3 } from "@dxos/react-ui-theme";
573
+ import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx4 } from "@dxos/react-ui-theme";
368
574
  var currentRow = "!bg-neutral-75 !dark:bg-neutral-850";
369
575
  var selectedRow = "!bg-primary-100 dark:!bg-primary-700";
370
576
  var flushPadding = "pli-0 plb-0";
371
577
  var textPadding = "pli-2 plb-0.5";
372
578
  var headPadding = "pli-2 plb-1";
373
579
  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);
580
+ var tableRoot = ({ fullWidth }, ...etc) => mx4("table-fixed", fullWidth && "is-full", ...etc);
581
+ var groupTh = (_props, ...etc) => mx4("text-start font-medium", flushPadding, ...etc);
582
+ var theadRoot = ({ header, stickyHeader }, ...etc) => mx4(header ? stickyHeader && "sticky block-start-[--sticky-top] z-[1]" : "collapse", header && "base-surface", "drop-shadow-sm", ...etc);
583
+ var theadTr = (_props, ...etc) => mx4("group", ...etc);
584
+ 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
585
  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");
586
+ 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
587
  };
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);
588
+ var tbodyRoot = (_props, ...etc) => mx4(...etc);
589
+ 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);
590
+ var tdRoot = ({ border, isGrid }, ...etc) => mx4("relative", flushPadding, border && "border", border && groupBorder, isGrid && gridCellFocusRing, ...etc);
591
+ var tdContent = (_props, ...etc) => mx4(...etc);
592
+ var tfootRoot = (_props, ...etc) => mx4("sticky block-end-0 z-10", modalSurface, ...etc);
593
+ var tfootTr = (_props, ...etc) => mx4(...etc);
594
+ var tfootTh = ({ border }, ...etc) => mx4(textPadding, modalSurface, border && groupBorder, ...etc);
389
595
 
390
596
  // packages/ui/react-ui-table/src/components/Cell/Cell.tsx
391
597
  import { useFocusableGroup } from "@fluentui/react-tabster";
392
- import React4 from "react";
598
+ import React5 from "react";
393
599
  var CELL_NAME = "Cell";
394
600
  var FocusableCell = ({ cell, children }) => {
395
601
  const tableContext = useTableContext();
@@ -397,7 +603,7 @@ var FocusableCell = ({ cell, children }) => {
397
603
  tabBehavior: "limited"
398
604
  });
399
605
  const className = tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames);
400
- return /* @__PURE__ */ React4.createElement("td", {
606
+ return /* @__PURE__ */ React5.createElement("td", {
401
607
  tabIndex: 0,
402
608
  ...domAttributes,
403
609
  className
@@ -405,14 +611,14 @@ var FocusableCell = ({ cell, children }) => {
405
611
  };
406
612
  var StaticCell = ({ cell, children }) => {
407
613
  const tableContext = useTableContext();
408
- return /* @__PURE__ */ React4.createElement("td", {
614
+ return /* @__PURE__ */ React5.createElement("td", {
409
615
  className: tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames)
410
616
  }, children);
411
617
  };
412
618
  var Cell = ({ cell, children }) => {
413
619
  const { isGrid } = useTableContext();
414
620
  const Root = isGrid ? FocusableCell : StaticCell;
415
- return /* @__PURE__ */ React4.createElement(Root, {
621
+ return /* @__PURE__ */ React5.createElement(Root, {
416
622
  cell
417
623
  }, children);
418
624
  };
@@ -427,7 +633,7 @@ var TableBody = ({ rows }) => {
427
633
  axis: "grid"
428
634
  });
429
635
  const canBeCurrent = !isGrid && !!onDatumClick;
430
- return /* @__PURE__ */ React5.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
636
+ return /* @__PURE__ */ React6.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
431
637
  const isCurrent = currentDatum === row.original;
432
638
  const isSelected = rowSelection?.[row.id];
433
639
  const isPinned = row.getIsPinned();
@@ -435,7 +641,7 @@ var TableBody = ({ rows }) => {
435
641
  canBeCurrent,
436
642
  isPinned: isPinned !== false
437
643
  });
438
- return /* @__PURE__ */ React5.createElement("tr", {
644
+ return /* @__PURE__ */ React6.createElement("tr", {
439
645
  key: keyAccessor ? keyAccessor(row.original) : row.id,
440
646
  className: classNames,
441
647
  ...isCurrent && {
@@ -455,57 +661,57 @@ var TableBody = ({ rows }) => {
455
661
  }
456
662
  }
457
663
  }
458
- }, debug && /* @__PURE__ */ React5.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
459
- return /* @__PURE__ */ React5.createElement(Cell, {
664
+ }, debug && /* @__PURE__ */ React6.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
665
+ return /* @__PURE__ */ React6.createElement(Cell, {
460
666
  key: cell.id,
461
667
  cell
462
668
  }, flexRender(cell.column.columnDef.cell, {
463
669
  className: "pli-2",
464
670
  ...cell.getContext()
465
671
  }));
466
- }), expand && /* @__PURE__ */ React5.createElement("td", null));
672
+ }), expand && /* @__PURE__ */ React6.createElement("td", null));
467
673
  }));
468
674
  };
469
675
  TableBody.displayName = TABLE_BODY_NAME;
470
676
 
471
677
  // packages/ui/react-ui-table/src/components/Table/TableFooter.tsx
472
678
  import { flexRender as flexRender2 } from "@tanstack/react-table";
473
- import React6 from "react";
679
+ import React7 from "react";
474
680
  var TABLE_FOOT_NAME = "TableFooter";
475
681
  var TableFooter = (props) => {
476
682
  const tableContext = useTableContext();
477
683
  const { table, expand, debug } = tableContext;
478
684
  const footers = table.getFooterGroups();
479
- return /* @__PURE__ */ React6.createElement("tfoot", {
685
+ return /* @__PURE__ */ React7.createElement("tfoot", {
480
686
  className: tfootRoot(props)
481
- }, footers.map((footerGroup) => /* @__PURE__ */ React6.createElement("tr", {
687
+ }, footers.map((footerGroup) => /* @__PURE__ */ React7.createElement("tr", {
482
688
  key: footerGroup.id,
483
689
  className: tfootTr(tableContext)
484
- }, debug && /* @__PURE__ */ React6.createElement("th", null), footerGroup.headers.map((footer) => {
485
- return /* @__PURE__ */ React6.createElement("th", {
690
+ }, debug && /* @__PURE__ */ React7.createElement("th", null), footerGroup.headers.map((footer) => {
691
+ return /* @__PURE__ */ React7.createElement("th", {
486
692
  key: footer.id,
487
693
  className: tfootTh(tableContext, footer.column.columnDef.meta?.footer?.classNames)
488
694
  }, footer.isPlaceholder ? null : flexRender2(footer.column.columnDef.footer, footer.getContext()));
489
- }), expand && /* @__PURE__ */ React6.createElement("th", null))));
695
+ }), expand && /* @__PURE__ */ React7.createElement("th", null))));
490
696
  };
491
697
  TableFooter.displayName = TABLE_FOOT_NAME;
492
698
 
493
699
  // packages/ui/react-ui-table/src/components/Table/TableHead.tsx
494
700
  import { flexRender as flexRender3 } from "@tanstack/react-table";
495
- import React7 from "react";
701
+ import React8 from "react";
496
702
  var TABLE_HEAD_NAME = "TableHeader";
497
703
  var TableHead = (_props) => {
498
704
  const tableContext = useTableContext();
499
705
  const headerGroups = tableContext.table.getHeaderGroups();
500
- return /* @__PURE__ */ React7.createElement("thead", {
706
+ return /* @__PURE__ */ React8.createElement("thead", {
501
707
  className: theadRoot(tableContext)
502
708
  }, headerGroups.map((headerGroup) => {
503
709
  return (
504
710
  // Group element to hover resize handles.
505
- /* @__PURE__ */ React7.createElement("tr", {
711
+ /* @__PURE__ */ React8.createElement("tr", {
506
712
  key: headerGroup.id,
507
713
  className: theadTr(tableContext)
508
- }, tableContext.debug && /* @__PURE__ */ React7.createElement("th", {
714
+ }, tableContext.debug && /* @__PURE__ */ React8.createElement("th", {
509
715
  className: "font-mono",
510
716
  style: {
511
717
  width: 32
@@ -514,13 +720,13 @@ var TableHead = (_props) => {
514
720
  const isResizing = header.column.getIsResizing();
515
721
  const onResize = header.getResizeHandler();
516
722
  const resizable = header.column.columnDef.meta?.resizable;
517
- return /* @__PURE__ */ React7.createElement("th", {
723
+ return /* @__PURE__ */ React8.createElement("th", {
518
724
  key: header.id,
519
725
  style: {
520
726
  width: header.getSize()
521
727
  },
522
728
  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", {
729
+ }, !header || header.isPlaceholder ? null : flexRender3(header.column.columnDef.header, header.getContext()), resizable && /* @__PURE__ */ React8.createElement("div", {
524
730
  className: theadResizeRoot({
525
731
  isResizing
526
732
  }),
@@ -528,100 +734,38 @@ var TableHead = (_props) => {
528
734
  onMouseDown: onResize,
529
735
  onTouchStart: onResize
530
736
  }));
531
- }), tableContext.expand && /* @__PURE__ */ React7.createElement("th", null))
737
+ }), tableContext.expand && /* @__PURE__ */ React8.createElement("th", null))
532
738
  );
533
739
  }));
534
740
  };
535
741
  TableHead.displayName = TABLE_HEAD_NAME;
536
742
 
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
743
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
574
744
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
575
745
  var Table = (props) => {
576
746
  const { role, onColumnResize, columnVisibility, header = true, rowsSelectable, debug, onDataSelectionChange, getScrollElement, pinLastRow } = props;
577
747
  const columns = useDefaultValue(props.columns, []);
578
- const data = useDefaultValue(props.data, []);
579
- const TableProvider2 = TableProvider;
580
- const [columnsInitialised, setColumnsInitialised] = useState5(false);
581
- const [columnSizing, setColumnSizing] = useState5({});
582
- useEffect2(() => {
583
- if (columnsInitialised) {
584
- return;
585
- }
586
- setColumnSizing(columns.filter((column) => !!column.size && column.prop !== void 0).reduce((state, column) => {
587
- state[column.prop] = column.size;
588
- return state;
589
- }, {}));
590
- setColumnsInitialised(true);
591
- }, [
592
- columns,
593
- setColumnSizing
748
+ const incomingData = useDefaultValue(props.data, []);
749
+ const [data, setData] = useState7([
750
+ ...incomingData
594
751
  ]);
595
- const [columnSizingInfo, setColumnSizingInfo] = useState5({});
596
- const notifyColumnResize = useCallback2(() => onColumnResize?.(columnSizing), [
597
- onColumnResize,
598
- columnSizing
752
+ const forceUpdate = useCallback6(() => setData([
753
+ ...incomingData
754
+ ]), [
755
+ incomingData
599
756
  ]);
600
- useOnTransition(columnSizingInfo.isResizingColumn, (v) => typeof v === "string", false, notifyColumnResize);
601
- const [rowSelection = {}, setRowSelection] = useControllableState({
602
- prop: props.rowSelection,
603
- onChange: props.onRowSelectionChange,
604
- defaultProp: props.defaultRowSelection
605
- });
606
- const handleRowSelectionChange = useCallback2((updaterOrValue) => {
607
- const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
608
- if (rowsSelectable === "multi") {
609
- setRowSelection(nextRowSelection);
610
- } else if (rowsSelectable) {
611
- const nextRowSelectionKey = Object.keys(nextRowSelection).filter((id) => !rowSelection[id])[0];
612
- setRowSelection(nextRowSelectionKey ? {
613
- [nextRowSelectionKey]: true
614
- } : {});
615
- } else {
616
- setRowSelection({});
617
- }
618
- }, [
619
- rowsSelectable,
620
- setRowSelection,
621
- rowSelection
757
+ useEffect3(() => forceUpdate(), [
758
+ JSON.stringify(incomingData),
759
+ forceUpdate
622
760
  ]);
623
- const [grouping, handleGroupingChange] = useState5(props.grouping ?? []);
624
- 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 ?? []), [
625
769
  handleGroupingChange,
626
770
  props.grouping
627
771
  ]);
@@ -663,7 +807,7 @@ var Table = (props) => {
663
807
  // Debug
664
808
  debugTable: debug
665
809
  });
666
- useEffect2(() => {
810
+ useEffect3(() => {
667
811
  onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
668
812
  }, [
669
813
  onDataSelectionChange,
@@ -675,18 +819,18 @@ var Table = (props) => {
675
819
  if (!getScrollElement) {
676
820
  log.warn("Table: getScrollElement is not set. This is required for virtualized tables.", void 0, {
677
821
  F: __dxlog_file,
678
- L: 159,
822
+ L: 120,
679
823
  S: void 0,
680
824
  C: (f, a) => f(...a)
681
825
  });
682
826
  }
683
- return /* @__PURE__ */ React8.createElement(TableProvider2, {
827
+ return /* @__PURE__ */ React9.createElement(TableProvider2, {
684
828
  ...props,
685
829
  table,
686
830
  header,
687
831
  expand,
688
832
  isGrid: role === "grid" || role === "treegrid"
689
- }, /* @__PURE__ */ React8.createElement(TableImpl, {
833
+ }, /* @__PURE__ */ React9.createElement(TableImpl, {
690
834
  debug: false,
691
835
  getScrollElement,
692
836
  ...props
@@ -695,20 +839,14 @@ var Table = (props) => {
695
839
  var TableImpl = (props) => {
696
840
  const { debug, classNames, getScrollElement, role, footer, grouping, fullWidth } = props;
697
841
  const { table } = useTableContext();
698
- const centerRows = table.getCenterRows();
699
- const bottomRows = table.getBottomRows();
700
- const rows = [
701
- ...centerRows,
702
- ...bottomRows
703
- ];
704
842
  if (debug) {
705
- return /* @__PURE__ */ React8.createElement("pre", {
843
+ return /* @__PURE__ */ React9.createElement("pre", {
706
844
  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)));
845
+ }, /* @__PURE__ */ React9.createElement("code", null, JSON.stringify(table.getState(), void 0, 2)));
708
846
  }
709
847
  const virtualisable = getScrollElement !== void 0;
710
848
  const isResizingColumn = table.getState().columnSizingInfo.isResizingColumn;
711
- return /* @__PURE__ */ React8.createElement("table", {
849
+ return /* @__PURE__ */ React9.createElement("table", {
712
850
  role,
713
851
  className: tableRoot(props, classNames),
714
852
  ...!fullWidth && {
@@ -716,18 +854,32 @@ var TableImpl = (props) => {
716
854
  width: table.getTotalSize()
717
855
  }
718
856
  }
719
- }, /* @__PURE__ */ React8.createElement(TableHead, null), grouping?.length !== 0 ? virtualisable ? isResizingColumn ? /* @__PURE__ */ React8.createElement(MemoizedVirtualisedTableContent, {
857
+ }, /* @__PURE__ */ React9.createElement(TableHead, null), grouping?.length !== 0 ? virtualisable ? isResizingColumn ? /* @__PURE__ */ React9.createElement(MemoizedVirtualisedTableContent, {
720
858
  getScrollElement
721
- }) : /* @__PURE__ */ React8.createElement(VirtualizedTableContent, {
859
+ }) : /* @__PURE__ */ React9.createElement(VirtualizedTableContent, {
722
860
  getScrollElement
723
- }) : /* @__PURE__ */ React8.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, {
724
872
  rows
725
- }) : /* @__PURE__ */ React8.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React8.createElement(TableFooter, null));
873
+ });
726
874
  };
727
875
  var VirtualizedTableContent = ({ getScrollElement }) => {
728
876
  const { table } = useTableContext();
729
877
  const centerRows = table.getCenterRows();
730
- const pinnedRows = table.getBottomRows();
878
+ let pinnedRows = [];
879
+ try {
880
+ pinnedRows = table.getBottomRows();
881
+ } catch (_) {
882
+ }
731
883
  const { getTotalSize, getVirtualItems } = useVirtualizer({
732
884
  getScrollElement,
733
885
  count: centerRows.length,
@@ -742,120 +894,51 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
742
894
  ...virtualRows.map((virtualRow) => centerRows[virtualRow.index]),
743
895
  ...pinnedRows
744
896
  ];
745
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React8.createElement("tbody", {
897
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React9.createElement("tbody", {
746
898
  role: "none"
747
- }, /* @__PURE__ */ React8.createElement("tr", {
899
+ }, /* @__PURE__ */ React9.createElement("tr", {
748
900
  role: "none"
749
- }, /* @__PURE__ */ React8.createElement("td", {
901
+ }, /* @__PURE__ */ React9.createElement("td", {
750
902
  style: {
751
903
  height: `${paddingTop}px`
752
904
  },
753
905
  role: "none"
754
- }))), /* @__PURE__ */ React8.createElement(TableBody, {
906
+ }))), /* @__PURE__ */ React9.createElement(TableBody, {
755
907
  rows: rowsToRender
756
- }), paddingBottom > 0 && /* @__PURE__ */ React8.createElement("tbody", {
908
+ }), paddingBottom > 0 && /* @__PURE__ */ React9.createElement("tbody", {
757
909
  role: "none"
758
- }, /* @__PURE__ */ React8.createElement("tr", {
910
+ }, /* @__PURE__ */ React9.createElement("tr", {
759
911
  role: "none"
760
- }, /* @__PURE__ */ React8.createElement("td", {
912
+ }, /* @__PURE__ */ React9.createElement("td", {
761
913
  style: {
762
914
  height: `${paddingBottom}px`
763
915
  },
764
916
  role: "none"
765
917
  }))));
766
918
  };
767
- var MemoizedVirtualisedTableContent = /* @__PURE__ */ React8.memo(VirtualizedTableContent);
919
+ var MemoizedVirtualisedTableContent = /* @__PURE__ */ React9.memo(VirtualizedTableContent);
768
920
  var GroupedTableContent = () => {
769
921
  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, {
922
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
923
+ return /* @__PURE__ */ React9.createElement(Fragment, {
772
924
  key: i
773
- }, /* @__PURE__ */ React8.createElement("thead", null, /* @__PURE__ */ React8.createElement("tr", null, debug && /* @__PURE__ */ React8.createElement("th", null), /* @__PURE__ */ React8.createElement("th", {
925
+ }, /* @__PURE__ */ React9.createElement("thead", null, /* @__PURE__ */ React9.createElement("tr", null, debug && /* @__PURE__ */ React9.createElement("th", null), /* @__PURE__ */ React9.createElement("th", {
774
926
  // TODO(burdon): Calculate row span.
775
927
  colSpan: getHeaderGroups()[0].headers.length,
776
928
  className: groupTh({})
777
- }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React8.createElement(TableBody, {
929
+ }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React9.createElement(TableBody, {
778
930
  rows: row.subRows
779
931
  }));
780
932
  }));
781
933
  };
782
934
 
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
935
  // packages/ui/react-ui-table/src/helpers.tsx
853
936
  import { useFocusFinders } from "@fluentui/react-tabster";
854
937
  import { Check as Check2, ClipboardText, X as X3 } from "@phosphor-icons/react";
855
938
  import { createColumnHelper } from "@tanstack/react-table";
856
939
  import { format } from "date-fns/format";
857
940
  import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
858
- 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";
859
942
  import { log as log2 } from "@dxos/log";
860
943
  import { Input as Input2, Tooltip } from "@dxos/react-ui";
861
944
  import { getSize as getSize4, mx as mx5 } from "@dxos/react-ui-theme";
@@ -877,12 +960,15 @@ var StringBuilderCell = (cellContext) => {
877
960
  const { findPrevFocusable } = useFocusFinders();
878
961
  const { onUpdate, cell } = cellContext.column.columnDef.meta;
879
962
  const initialValue = cellContext.getValue();
880
- const [value, setValue] = useState7(() => {
881
- if (initialValue?.content) {
882
- return initialValue?.content;
883
- }
884
- return initialValue;
885
- });
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
+ ]);
886
972
  const handleSave = () => {
887
973
  ref.current && document.activeElement === ref.current && findPrevFocusable(ref.current)?.focus();
888
974
  if (value !== initialValue) {
@@ -919,10 +1005,10 @@ var displayNumber = (value, digits) => value || value === 0 ? value.toLocaleStri
919
1005
  var NumberBuilderCell = (cellContext) => {
920
1006
  const { onUpdate, digits } = cellContext.column.columnDef.meta;
921
1007
  const value = cellContext.getValue();
922
- const [text, setText] = useState7(displayNumber(value, digits));
1008
+ const [text, setText] = useState8(displayNumber(value, digits));
923
1009
  const { findPrevFocusable } = useFocusFinders();
924
1010
  const ref = useRef3(null);
925
- useEffect3(() => {
1011
+ useEffect4(() => {
926
1012
  (!document.activeElement || document.activeElement !== ref.current) && setText(displayNumber(value, digits));
927
1013
  }, [
928
1014
  digits,
@@ -1101,7 +1187,7 @@ var ColumnBuilder = class {
1101
1187
  value
1102
1188
  }, {
1103
1189
  F: __dxlog_file2,
1104
- L: 374,
1190
+ L: 376,
1105
1191
  S: this,
1106
1192
  C: (f, a) => f(...a)
1107
1193
  });
@@ -1246,11 +1332,162 @@ var ColumnBuilder = class {
1246
1332
  ...props
1247
1333
  };
1248
1334
  }
1335
+ /**
1336
+ * This display column type is for nested/unhandled data to appear as JSON.
1337
+ */
1338
+ display({ label, classNames, ...props } = {}) {
1339
+ return {
1340
+ size: 120,
1341
+ minSize: 120,
1342
+ header: (cell) => label ?? cell.header.id,
1343
+ cell: (cell) => {
1344
+ const value = cell.getValue();
1345
+ return /* @__PURE__ */ React10.createElement("div", {
1346
+ className: "overflow-scroll"
1347
+ }, /* @__PURE__ */ React10.createElement("code", {
1348
+ className: "text-xs"
1349
+ }, JSON.stringify(value)));
1350
+ },
1351
+ ...props,
1352
+ meta: {
1353
+ ...props.meta,
1354
+ cell: {
1355
+ ...props.meta?.cell,
1356
+ classNames: [
1357
+ "font-mono",
1358
+ textPadding,
1359
+ classNames
1360
+ ]
1361
+ }
1362
+ }
1363
+ };
1364
+ }
1365
+ };
1366
+
1367
+ // packages/ui/react-ui-table/src/schema/schema.ts
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);
1400
+ var isOptionalUnion = (prop) => AST.isUnion(prop.type) && prop.isOptional;
1401
+ var unwrapOptionProperty = (prop) => {
1402
+ if (!isOptionalUnion(prop)) {
1403
+ throw new Error(`Not an optional property: ${String(prop.name)}`);
1404
+ }
1405
+ if (!AST.isUnion(prop.type)) {
1406
+ throw new Error(`Not a union type: ${String(prop.name)}`);
1407
+ }
1408
+ const [type, _undefinedCase] = prop.type.types;
1409
+ return type;
1410
+ };
1411
+ var typeToColumn = (type) => {
1412
+ if (AST.isStringKeyword(type)) {
1413
+ return "string";
1414
+ } else if (AST.isNumberKeyword(type)) {
1415
+ return "number";
1416
+ } else if (AST.isBooleanKeyword(type)) {
1417
+ return "boolean";
1418
+ }
1419
+ if (AST.isRefinement(type)) {
1420
+ return typeToColumn(type.from);
1421
+ }
1422
+ if (AST.isTransform(type)) {
1423
+ const identifier = AST.getIdentifierAnnotation(type);
1424
+ if (identifier._tag === "Some") {
1425
+ if (identifier.value === "DateFromString") {
1426
+ return "date";
1427
+ }
1428
+ }
1429
+ }
1430
+ return "display";
1431
+ };
1432
+ var propertyToColumn = (prop) => {
1433
+ let type = prop.type;
1434
+ if (prop.isOptional) {
1435
+ type = unwrapOptionProperty(prop);
1436
+ }
1437
+ return typeToColumn(type);
1438
+ };
1439
+
1440
+ // packages/ui/react-ui-table/src/schema/schemaToColumns.ts
1441
+ var schemaToColumnDefs = (schema) => {
1442
+ const { helper, builder } = createColumnBuilder();
1443
+ const classified = classifySchemaProperties(schema);
1444
+ return classified.map(([name, type]) => {
1445
+ const propertyKey = name.toString();
1446
+ let column;
1447
+ switch (type) {
1448
+ case "string": {
1449
+ column = builder.string({
1450
+ label: propertyKey
1451
+ });
1452
+ break;
1453
+ }
1454
+ case "number": {
1455
+ column = builder.number({
1456
+ label: propertyKey
1457
+ });
1458
+ break;
1459
+ }
1460
+ case "boolean": {
1461
+ column = builder.switch({
1462
+ label: propertyKey
1463
+ });
1464
+ break;
1465
+ }
1466
+ case "date": {
1467
+ column = builder.date({
1468
+ label: propertyKey
1469
+ });
1470
+ break;
1471
+ }
1472
+ case "display": {
1473
+ column = builder.display({
1474
+ label: propertyKey,
1475
+ id: propertyKey
1476
+ });
1477
+ break;
1478
+ }
1479
+ default: {
1480
+ throw new Error(`Unhandled column type: ${type}`);
1481
+ }
1482
+ }
1483
+ return helper.accessor(propertyKey, column);
1484
+ });
1249
1485
  };
1250
1486
  export {
1251
1487
  CellCombobox,
1252
1488
  ColumnBuilder,
1253
1489
  ColumnMenu,
1490
+ ColumnSettingsForm,
1254
1491
  ColumnSettingsPanel,
1255
1492
  MemoizedVirtualisedTableContent,
1256
1493
  SortIndicator,
@@ -1261,6 +1498,7 @@ export {
1261
1498
  gridCellFocusRing,
1262
1499
  groupTh,
1263
1500
  headPadding,
1501
+ schemaToColumnDefs,
1264
1502
  selectedRow,
1265
1503
  tableRoot,
1266
1504
  tbodyRoot,
@@ -1275,6 +1513,10 @@ export {
1275
1513
  theadRoot,
1276
1514
  theadTh,
1277
1515
  theadTr,
1278
- translations_default as translations
1516
+ translations_default as translations,
1517
+ useColumnResizing,
1518
+ useColumnSorting,
1519
+ usePinLastRow,
1520
+ useRowSelection
1279
1521
  };
1280
1522
  //# sourceMappingURL=index.mjs.map