@dxos/react-ui-table 0.4.10-main.308cc0e → 0.4.10-main.30a328e

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 (76) hide show
  1. package/dist/lib/browser/index.mjs +709 -355
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts +19 -0
  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} +10 -2
  7. package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -0
  8. package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts +11 -0
  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 +9 -0
  24. package/dist/types/src/hooks/useColumnSorting.d.ts.map +1 -0
  25. package/dist/types/src/hooks/usePinLastRow.d.ts +3 -0
  26. package/dist/types/src/hooks/usePinLastRow.d.ts.map +1 -0
  27. package/dist/types/src/hooks/useRowSelection.d.ts +7 -0
  28. package/dist/types/src/hooks/useRowSelection.d.ts.map +1 -0
  29. package/dist/types/src/index.d.ts +2 -1
  30. package/dist/types/src/index.d.ts.map +1 -1
  31. package/dist/types/src/schema/SchemaToTable.stories.d.ts +11 -0
  32. package/dist/types/src/schema/SchemaToTable.stories.d.ts.map +1 -0
  33. package/dist/types/src/schema/index.d.ts +3 -0
  34. package/dist/types/src/schema/index.d.ts.map +1 -0
  35. package/dist/types/src/schema/schema.d.ts +5 -0
  36. package/dist/types/src/schema/schema.d.ts.map +1 -0
  37. package/dist/types/src/schema/schema.test.d.ts +2 -0
  38. package/dist/types/src/schema/schema.test.d.ts.map +1 -0
  39. package/dist/types/src/schema/schemaToColumns.d.ts +4 -0
  40. package/dist/types/src/schema/schemaToColumns.d.ts.map +1 -0
  41. package/dist/types/src/{schema.d.ts → schema/types.d.ts} +1 -1
  42. package/dist/types/src/schema/types.d.ts.map +1 -0
  43. package/package.json +20 -16
  44. package/src/components/ColumnMenu/ColumnMenu.stories.tsx +127 -0
  45. package/src/components/ColumnMenu/ColumnMenu.tsx +168 -0
  46. package/src/components/ColumnMenu/ColumnSettingsForm.tsx +214 -0
  47. package/src/components/ColumnMenu/index.ts +6 -0
  48. package/src/components/Table/Table.stories.tsx +162 -3
  49. package/src/components/Table/Table.tsx +35 -60
  50. package/src/components/index.ts +1 -1
  51. package/src/helpers.tsx +32 -8
  52. package/src/hooks/index.ts +8 -0
  53. package/src/hooks/useColumnSizing.ts +45 -0
  54. package/src/hooks/useColumnSorting.ts +54 -0
  55. package/src/hooks/usePinLastRow.ts +64 -0
  56. package/src/hooks/useRowSelection.ts +39 -0
  57. package/src/index.ts +3 -1
  58. package/src/schema/SchemaToTable.stories.tsx +72 -0
  59. package/src/schema/index.ts +6 -0
  60. package/src/schema/schema.test.ts +148 -0
  61. package/src/schema/schema.ts +92 -0
  62. package/src/schema/schemaToColumns.ts +48 -0
  63. package/src/theme.ts +1 -1
  64. package/dist/types/src/components/ColumnMenu.d.ts +0 -13
  65. package/dist/types/src/components/ColumnMenu.d.ts.map +0 -1
  66. package/dist/types/src/components/ColumnMenu.stories.d.ts.map +0 -1
  67. package/dist/types/src/components/SortButton.d.ts +0 -8
  68. package/dist/types/src/components/SortButton.d.ts.map +0 -1
  69. package/dist/types/src/components/hooks/usePinLastRow.d.ts +0 -3
  70. package/dist/types/src/components/hooks/usePinLastRow.d.ts.map +0 -1
  71. package/dist/types/src/schema.d.ts.map +0 -1
  72. package/src/components/ColumnMenu.stories.tsx +0 -46
  73. package/src/components/ColumnMenu.tsx +0 -248
  74. package/src/components/SortButton.tsx +0 -34
  75. package/src/components/hooks/usePinLastRow.ts +0 -43
  76. /package/src/{schema.ts → schema/types.ts} +0 -0
@@ -1,40 +1,3 @@
1
- // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
2
- import { Check, Trash, X, GearSix } from "@phosphor-icons/react";
3
- import React2, { useRef, useState } from "react";
4
- import { Button as Button2, DensityProvider, Input, Popover, Select, Separator, useTranslation } from "@dxos/react-ui";
5
- import { getSize as getSize2, mx } from "@dxos/react-ui-theme";
6
- import { safeParseInt } from "@dxos/util";
7
-
8
- // packages/ui/react-ui-table/src/components/SortButton.tsx
9
- import { CaretUpDown, SortAscending, SortDescending } from "@phosphor-icons/react";
10
- import React from "react";
11
- import { Button } from "@dxos/react-ui";
12
- import { getSize } from "@dxos/react-ui-theme";
13
- var SortButton = ({ sortDirection, onClick }) => {
14
- let icon;
15
- const size = getSize(4);
16
- switch (sortDirection) {
17
- case "asc":
18
- icon = /* @__PURE__ */ React.createElement(SortAscending, {
19
- className: size
20
- });
21
- break;
22
- case "desc":
23
- icon = /* @__PURE__ */ React.createElement(SortDescending, {
24
- className: size
25
- });
26
- break;
27
- default:
28
- icon = /* @__PURE__ */ React.createElement(CaretUpDown, {
29
- className: size
30
- });
31
- }
32
- return /* @__PURE__ */ React.createElement(Button, {
33
- variant: "ghost",
34
- onClick
35
- }, icon);
36
- };
37
-
38
1
  // packages/ui/react-ui-table/src/translations.ts
39
2
  var translationKey = "table";
40
3
  var translations_default = [
@@ -58,47 +21,107 @@ var translations_default = [
58
21
  }
59
22
  ];
60
23
 
61
- // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
62
- var ColumnMenu = ({ column, ...props }) => {
63
- const title = column.label?.length ? column.label : column.id;
64
- const header = props.context.header;
65
- const canSort = header.column.getCanSort();
66
- const sortDirection = header.column.getIsSorted();
67
- const toggleSort = header.column.getToggleSortingHandler();
68
- return /* @__PURE__ */ React2.createElement("div", {
69
- className: "flex items-center gap-2"
70
- }, /* @__PURE__ */ React2.createElement("div", {
71
- className: "flex-1 min-is-0 truncate",
72
- title
73
- }, title), /* @__PURE__ */ React2.createElement("div", {
74
- className: "flex gap-0"
75
- }, canSort && toggleSort && /* @__PURE__ */ React2.createElement(SortButton, {
76
- sortDirection,
77
- onClick: toggleSort
78
- }), /* @__PURE__ */ React2.createElement(ColumnPanel, {
79
- ...props,
80
- column
81
- })));
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)));
82
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";
83
105
  var Section = ({ children, className }) => /* @__PURE__ */ React2.createElement("div", {
84
106
  role: "none",
85
- className: mx("p-2", className)
107
+ className: mx2("p-2", className)
86
108
  }, children);
87
- var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete }) => {
88
- const [open, setOpen] = useState(false);
89
- const [prop, setProp] = useState(column.id);
90
- const [refTable, setRefTable] = useState(column.refTable);
91
- const [refProp, setRefProp] = useState(column.refProp);
92
- const [type, setType] = useState(String(column.type));
93
- const [label, setLabel] = useState(column.label);
94
- const [digits, setDigits] = useState(String(column.digits ?? "0"));
109
+ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onClose }) => {
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
+ });
95
118
  const propRef = useRef(null);
96
- const { t } = useTranslation(translationKey);
119
+ const { t } = useTranslation2(translationKey);
97
120
  const handleCancel = () => {
98
- setProp(column.id);
99
- setOpen(false);
121
+ onClose?.();
100
122
  };
101
123
  const handleSave = () => {
124
+ const { prop, refTable, refProp, type, label, digits } = formState;
102
125
  if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {
103
126
  propRef.current?.focus();
104
127
  return;
@@ -110,7 +133,7 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
110
133
  return;
111
134
  }
112
135
  }
113
- onUpdate?.(prop, {
136
+ onUpdate?.(column.id, {
114
137
  id: prop,
115
138
  prop,
116
139
  label,
@@ -119,43 +142,38 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
119
142
  refProp,
120
143
  digits: safeParseInt(digits)
121
144
  });
122
- setOpen(false);
145
+ onClose?.();
123
146
  };
124
- return /* @__PURE__ */ React2.createElement(Popover.Root, {
125
- open,
126
- onOpenChange: (nextOpen) => setOpen(nextOpen)
127
- }, /* @__PURE__ */ React2.createElement(Popover.Trigger, {
128
- asChild: true
129
- }, /* @__PURE__ */ React2.createElement(Button2, {
130
- variant: "ghost"
131
- }, /* @__PURE__ */ React2.createElement(GearSix, {
132
- className: mx(getSize2(4), "rotate-90")
133
- }))), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, null, /* @__PURE__ */ React2.createElement(Popover.Viewport, {
134
- classNames: "w-60"
135
- }, /* @__PURE__ */ React2.createElement(DensityProvider, {
136
- density: "fine"
137
- }, /* @__PURE__ */ React2.createElement("div", {
147
+ return /* @__PURE__ */ React2.createElement("div", {
138
148
  className: "flex flex-col gap-1"
139
149
  }, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
140
150
  classNames: "mbe-1"
141
151
  }, t("column label label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
142
152
  placeholder: "Column label",
143
- value: label ?? "",
144
- onChange: (event) => setLabel(event.target.value),
153
+ value: formState.label ?? "",
154
+ onChange: (event) => setFormState((prevState) => ({
155
+ ...prevState,
156
+ label: event.target.value
157
+ })),
145
158
  autoFocus: true
146
159
  })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
147
160
  classNames: "mbe-1 mbs-3"
148
161
  }, t("property key label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
149
162
  ref: propRef,
150
163
  placeholder: "Property key",
151
- // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.
152
- value: prop ?? "",
153
- onChange: (event) => setProp(event.target.value.replace(/[^\w_]/g, ""))
164
+ value: formState.prop ?? "",
165
+ onChange: (event) => setFormState((prevState) => ({
166
+ ...prevState,
167
+ prop: event.target.value.replace(/[^\w_]/g, "")
168
+ }))
154
169
  })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
155
170
  classNames: "mbe-1 mbs-3"
156
171
  }, t("column type label")), /* @__PURE__ */ React2.createElement(Select.Root, {
157
- value: type,
158
- onValueChange: setType
172
+ value: formState.type,
173
+ onValueChange: (value) => setFormState((prevState) => ({
174
+ ...prevState,
175
+ type: value
176
+ }))
159
177
  }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
160
178
  placeholder: "Type",
161
179
  classNames: "is-full"
@@ -164,41 +182,50 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
164
182
  "boolean",
165
183
  "string",
166
184
  "ref"
167
- ].map((type2) => /* @__PURE__ */ React2.createElement(Select.Option, {
168
- key: type2,
169
- value: type2
170
- }, t(`${type2} column type label`))))))))), type === "number" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
185
+ ].map((type) => /* @__PURE__ */ React2.createElement(Select.Option, {
186
+ key: type,
187
+ value: type
188
+ }, t(`${type} column type label`))))))))), formState.type === "number" && /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
171
189
  classNames: "mbe-1 mbs-3"
172
190
  }, t("digits label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
173
- value: digits ?? "",
174
- onChange: (event) => setDigits(event.target.value)
175
- })))), type === "ref" && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
191
+ value: formState.digits ?? "",
192
+ onChange: (event) => setFormState((prevState) => ({
193
+ ...prevState,
194
+ digits: event.target.value
195
+ }))
196
+ }))), formState.type === "ref" && /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
176
197
  classNames: "mbe-1 mbs-3"
177
198
  }, "Table"), /* @__PURE__ */ React2.createElement(Select.Root, {
178
- value: refTable,
179
- onValueChange: setRefTable
199
+ value: formState.refTable,
200
+ onValueChange: (value) => setFormState((prevState) => ({
201
+ ...prevState,
202
+ refTable: value
203
+ }))
180
204
  }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
181
205
  placeholder: "Table",
182
206
  classNames: "is-full"
183
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, {
184
208
  key: id,
185
209
  value: id
186
- }, name ?? id))))))), refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
210
+ }, name ?? id))))))), formState.refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
187
211
  classNames: "mbe-1 mbs-3"
188
212
  }, "Table property"), /* @__PURE__ */ React2.createElement(Select.Root, {
189
- value: refProp,
190
- onValueChange: setRefProp
213
+ value: formState.refProp,
214
+ onValueChange: (value) => setFormState((prevState) => ({
215
+ ...prevState,
216
+ refProp: value
217
+ }))
191
218
  }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
192
219
  placeholder: "Property",
193
220
  classNames: "is-full"
194
- }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, tableDefs.find((tableDef2) => tableDef2.id === refTable)?.columns.map(({ id, label: label2 }) => /* @__PURE__ */ React2.createElement(Select.Option, {
221
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, tableDefs.find((tableDef2) => tableDef2.id === formState.refTable)?.columns.map(({ id, label }) => /* @__PURE__ */ React2.createElement(Select.Option, {
195
222
  key: id,
196
223
  value: id
197
- }, label2 ?? id))))))))), /* @__PURE__ */ React2.createElement(Separator, {
224
+ }, label ?? id)))))))), /* @__PURE__ */ React2.createElement(Separator, {
198
225
  classNames: "mli-2"
199
226
  }), /* @__PURE__ */ React2.createElement(Section, {
200
227
  className: "space-b-1.5"
201
- }, /* @__PURE__ */ React2.createElement(Button2, {
228
+ }, /* @__PURE__ */ React2.createElement(Button, {
202
229
  variant: "primary",
203
230
  classNames: "is-full flex gap-2",
204
231
  onClick: handleSave
@@ -206,7 +233,7 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
206
233
  className: "grow"
207
234
  }), /* @__PURE__ */ React2.createElement(Check, {
208
235
  className: getSize2(5)
209
- })), /* @__PURE__ */ React2.createElement(Button2, {
236
+ })), /* @__PURE__ */ React2.createElement(Button, {
210
237
  classNames: "is-full flex gap-2",
211
238
  onClick: handleCancel
212
239
  }, /* @__PURE__ */ React2.createElement("span", null, t("cancel label", {
@@ -215,34 +242,325 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
215
242
  className: "grow"
216
243
  }), /* @__PURE__ */ React2.createElement(X, {
217
244
  className: getSize2(5)
218
- })), /* @__PURE__ */ React2.createElement(Button2, {
245
+ })), /* @__PURE__ */ React2.createElement(Button, {
219
246
  classNames: "is-full flex gap-2",
220
247
  onClick: () => onDelete?.(column.id)
221
248
  }, /* @__PURE__ */ React2.createElement("span", null, t("delete label")), /* @__PURE__ */ React2.createElement("div", {
222
249
  className: "grow"
223
250
  }), /* @__PURE__ */ React2.createElement(Trash, {
224
251
  className: getSize2(5)
225
- })))))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
252
+ }))));
226
253
  };
227
254
 
228
- // packages/ui/react-ui-table/src/components/Table/Table.tsx
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";
290
+ var useColumnSorting = (column) => {
291
+ const [sortDirection, setSortDirection] = useState4(column.getIsSorted());
292
+ const [firstSort, setFirstSort] = useState4();
293
+ const canSort = column.getCanSort();
294
+ const updateColumnSort = (direction) => {
295
+ setSortDirection(direction);
296
+ switch (direction) {
297
+ case false:
298
+ column.clearSorting();
299
+ break;
300
+ case "asc":
301
+ column.toggleSorting(false);
302
+ break;
303
+ case "desc":
304
+ column.toggleSorting(true);
305
+ break;
306
+ }
307
+ };
308
+ const onToggleSort = () => {
309
+ if (sortDirection === false) {
310
+ return;
311
+ }
312
+ if (sortDirection === firstSort) {
313
+ updateColumnSort(firstSort === "asc" ? "desc" : "asc");
314
+ } else {
315
+ updateColumnSort(false);
316
+ }
317
+ };
318
+ const onSelectSort = (direction) => {
319
+ setFirstSort(direction);
320
+ updateColumnSort(direction);
321
+ };
322
+ const onClearSort = () => {
323
+ updateColumnSort(false);
324
+ };
325
+ return {
326
+ canSort,
327
+ sortDirection,
328
+ onSelectSort,
329
+ onToggleSort,
330
+ onClearSort
331
+ };
332
+ };
333
+
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
229
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
423
+ var ColumnMenu = ({ column, ...props }) => {
424
+ const title = column.label?.length ? column.label : column.id;
425
+ const header = props.context.header;
426
+ const { canSort, sortDirection, onSelectSort, onToggleSort, onClearSort } = useColumnSorting(header.column);
427
+ const columnSettingsAnchorRef = useRef2(null);
428
+ const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState6(false);
429
+ const shouldPreventFocusOnClose = useRef2(false);
430
+ const onOpenColumnSettings = useCallback5(() => {
431
+ shouldPreventFocusOnClose.current = true;
432
+ setIsColumnSettingsOpen(true);
433
+ }, [
434
+ shouldPreventFocusOnClose,
435
+ setIsColumnSettingsOpen
436
+ ]);
437
+ const onDropdownCloseAutoFocus = useCallback5((event) => {
438
+ if (shouldPreventFocusOnClose.current) {
439
+ event.preventDefault();
440
+ shouldPreventFocusOnClose.current = false;
441
+ }
442
+ }, [
443
+ shouldPreventFocusOnClose
444
+ ]);
445
+ return /* @__PURE__ */ React3.createElement("div", {
446
+ className: "flex items-center justify-center justify-between"
447
+ }, /* @__PURE__ */ React3.createElement("div", {
448
+ className: "flex items-center gap-1 truncate",
449
+ title
450
+ }, /* @__PURE__ */ React3.createElement(SortIndicator, {
451
+ direction: sortDirection,
452
+ onClick: onToggleSort
453
+ }), /* @__PURE__ */ React3.createElement("div", {
454
+ className: "truncate"
455
+ }, title)), /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
456
+ modal: false
457
+ }, /* @__PURE__ */ React3.createElement(Popover2.Root, {
458
+ open: isColumnSettingsOpen,
459
+ onOpenChange: setIsColumnSettingsOpen,
460
+ modal: false
461
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
462
+ ref: columnSettingsAnchorRef,
463
+ asChild: true
464
+ }, /* @__PURE__ */ React3.createElement(Popover2.Anchor, {
465
+ asChild: true
466
+ }, /* @__PURE__ */ React3.createElement(Button2, {
467
+ variant: "ghost"
468
+ }, /* @__PURE__ */ React3.createElement(CaretDown2, {
469
+ className: getSize3(4)
470
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
471
+ onCloseAutoFocus: onDropdownCloseAutoFocus,
472
+ sideOffset: 4,
473
+ collisionPadding: 8
474
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
475
+ onClick: () => onSelectSort("asc")
476
+ }, /* @__PURE__ */ React3.createElement("span", {
477
+ className: "grow"
478
+ }, "Sort ascending"), /* @__PURE__ */ React3.createElement("span", {
479
+ className: "opacity-50"
480
+ }, /* @__PURE__ */ React3.createElement(ArrowUp, {
481
+ className: getSize3(4)
482
+ }))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
483
+ onClick: () => onSelectSort("desc")
484
+ }, /* @__PURE__ */ React3.createElement("span", {
485
+ className: "grow"
486
+ }, "Sort descending"), /* @__PURE__ */ React3.createElement("span", {
487
+ className: "opacity-50"
488
+ }, /* @__PURE__ */ React3.createElement(ArrowDown, {
489
+ className: getSize3(4)
490
+ }))), sortDirection !== false && /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
491
+ onClick: onClearSort
492
+ }, /* @__PURE__ */ React3.createElement("span", {
493
+ className: "grow"
494
+ }, "Clear sort"), /* @__PURE__ */ React3.createElement("span", {
495
+ className: "opacity-50"
496
+ }, /* @__PURE__ */ React3.createElement(X2, {
497
+ className: getSize3(4)
498
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
499
+ onClick: onOpenColumnSettings
500
+ }, /* @__PURE__ */ React3.createElement("span", {
501
+ className: "grow"
502
+ }, "Column settings"), /* @__PURE__ */ React3.createElement("span", {
503
+ className: "opacity-50"
504
+ }, /* @__PURE__ */ React3.createElement(GearSix, {
505
+ className: mx3(getSize3(4), "rotate-90")
506
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null))), /* @__PURE__ */ React3.createElement(ColumnSettingsPanel, {
507
+ ...props,
508
+ column,
509
+ onClose: () => setIsColumnSettingsOpen(false)
510
+ }))));
511
+ };
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, {
513
+ classNames: "w-60"
514
+ }, /* @__PURE__ */ React3.createElement(DensityProvider, {
515
+ density: "fine"
516
+ }, /* @__PURE__ */ React3.createElement(ColumnSettingsForm, {
517
+ column,
518
+ tableDefs,
519
+ tableDef,
520
+ onUpdate,
521
+ onDelete,
522
+ onClose
523
+ }))), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null)));
524
+ var SortIndicator = ({ direction, onClick }) => {
525
+ if (direction === false) {
526
+ return null;
527
+ }
528
+ let icon;
529
+ switch (direction) {
530
+ case "asc":
531
+ icon = /* @__PURE__ */ React3.createElement(ArrowUp, {
532
+ className: getSize3(3)
533
+ });
534
+ break;
535
+ case "desc":
536
+ icon = /* @__PURE__ */ React3.createElement(ArrowDown, {
537
+ className: getSize3(3)
538
+ });
539
+ break;
540
+ }
541
+ return /* @__PURE__ */ React3.createElement("div", {
542
+ onClick,
543
+ className: "flex items-center cursor-pointer"
544
+ }, icon);
545
+ };
546
+
547
+ // packages/ui/react-ui-table/src/components/Table/Table.tsx
230
548
  import { getCoreRowModel, getSortedRowModel, useReactTable, getGroupedRowModel, getExpandedRowModel } from "@tanstack/react-table";
231
549
  import { useVirtualizer } from "@tanstack/react-virtual";
232
- import React8, { Fragment, useCallback, useEffect as useEffect2, useState as useState3 } from "react";
550
+ import React9, { Fragment, useCallback as useCallback6, useEffect as useEffect3, useState as useState7 } from "react";
233
551
  import { log } from "@dxos/log";
234
- import { useDefaultValue, useOnTransition } from "@dxos/react-ui";
552
+ import { useDefaultValue } from "@dxos/react-ui";
235
553
 
236
554
  // packages/ui/react-ui-table/src/components/Table/TableBody.tsx
237
555
  import { useArrowNavigationGroup } from "@fluentui/react-tabster";
238
556
  import { flexRender } from "@tanstack/react-table";
239
- import React5 from "react";
557
+ import React6 from "react";
240
558
 
241
559
  // packages/ui/react-ui-table/src/components/Table/TableContext.tsx
242
- import React3, { useContext, createContext } from "react";
560
+ import React4, { useContext, createContext } from "react";
243
561
  var TableContext = /* @__PURE__ */ createContext({});
244
562
  var TableProvider = ({ children, ...value }) => {
245
- return /* @__PURE__ */ React3.createElement(TableContext.Provider, {
563
+ return /* @__PURE__ */ React4.createElement(TableContext.Provider, {
246
564
  value
247
565
  }, children);
248
566
  };
@@ -252,32 +570,32 @@ var useTableContext = () => {
252
570
  };
253
571
 
254
572
  // packages/ui/react-ui-table/src/theme.ts
255
- import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx2 } from "@dxos/react-ui-theme";
573
+ import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx4 } from "@dxos/react-ui-theme";
256
574
  var currentRow = "!bg-neutral-75 !dark:bg-neutral-850";
257
575
  var selectedRow = "!bg-primary-100 dark:!bg-primary-700";
258
576
  var flushPadding = "pli-0 plb-0";
259
577
  var textPadding = "pli-2 plb-0.5";
260
578
  var headPadding = "pli-2 plb-1";
261
579
  var gridCellFocusRing = "focus-within:z-[11] focus-within:outline outline-2 outline-primary-500 dark:outline-primary-400";
262
- var tableRoot = ({ fullWidth }, ...etc) => mx2("table-fixed", fullWidth && "is-full", ...etc);
263
- var groupTh = (_props, ...etc) => mx2("text-start font-medium", flushPadding, ...etc);
264
- var theadRoot = ({ header, stickyHeader }, ...etc) => mx2(header ? stickyHeader && "sticky block-start-[--sticky-top] z-[1]" : "collapse", header && "base-surface", "drop-shadow-sm", ...etc);
265
- var theadTr = (_props, ...etc) => mx2("group", ...etc);
266
- var theadTh = ({ border }, ...etc) => mx2("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);
267
585
  var theadResizeRoot = ({ isResizing }) => {
268
- return mx2("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");
269
587
  };
270
- var tbodyRoot = (_props, ...etc) => mx2(...etc);
271
- var tbodyTr = ({ canBeCurrent, isPinned }, ...etc) => mx2("group", canBeCurrent ? ghostSelectedCurrent : ghostSelected, canBeCurrent && focusRing, canBeCurrent && "cursor-pointer rounded", isPinned && "sticky z-[20] bottom-[-1px] base-surface shadow-sm", ...etc);
272
- var tdRoot = ({ border, isGrid }, ...etc) => mx2("relative", flushPadding, border && "border", border && groupBorder, isGrid && gridCellFocusRing, ...etc);
273
- var tdContent = (_props, ...etc) => mx2(...etc);
274
- var tfootRoot = (_props, ...etc) => mx2("sticky block-end-0 z-10", modalSurface, ...etc);
275
- var tfootTr = (_props, ...etc) => mx2(...etc);
276
- var tfootTh = ({ border }, ...etc) => mx2(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);
277
595
 
278
596
  // packages/ui/react-ui-table/src/components/Cell/Cell.tsx
279
597
  import { useFocusableGroup } from "@fluentui/react-tabster";
280
- import React4 from "react";
598
+ import React5 from "react";
281
599
  var CELL_NAME = "Cell";
282
600
  var FocusableCell = ({ cell, children }) => {
283
601
  const tableContext = useTableContext();
@@ -285,7 +603,7 @@ var FocusableCell = ({ cell, children }) => {
285
603
  tabBehavior: "limited"
286
604
  });
287
605
  const className = tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames);
288
- return /* @__PURE__ */ React4.createElement("td", {
606
+ return /* @__PURE__ */ React5.createElement("td", {
289
607
  tabIndex: 0,
290
608
  ...domAttributes,
291
609
  className
@@ -293,14 +611,14 @@ var FocusableCell = ({ cell, children }) => {
293
611
  };
294
612
  var StaticCell = ({ cell, children }) => {
295
613
  const tableContext = useTableContext();
296
- return /* @__PURE__ */ React4.createElement("td", {
614
+ return /* @__PURE__ */ React5.createElement("td", {
297
615
  className: tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames)
298
616
  }, children);
299
617
  };
300
618
  var Cell = ({ cell, children }) => {
301
619
  const { isGrid } = useTableContext();
302
620
  const Root = isGrid ? FocusableCell : StaticCell;
303
- return /* @__PURE__ */ React4.createElement(Root, {
621
+ return /* @__PURE__ */ React5.createElement(Root, {
304
622
  cell
305
623
  }, children);
306
624
  };
@@ -315,7 +633,7 @@ var TableBody = ({ rows }) => {
315
633
  axis: "grid"
316
634
  });
317
635
  const canBeCurrent = !isGrid && !!onDatumClick;
318
- return /* @__PURE__ */ React5.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
636
+ return /* @__PURE__ */ React6.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
319
637
  const isCurrent = currentDatum === row.original;
320
638
  const isSelected = rowSelection?.[row.id];
321
639
  const isPinned = row.getIsPinned();
@@ -323,7 +641,7 @@ var TableBody = ({ rows }) => {
323
641
  canBeCurrent,
324
642
  isPinned: isPinned !== false
325
643
  });
326
- return /* @__PURE__ */ React5.createElement("tr", {
644
+ return /* @__PURE__ */ React6.createElement("tr", {
327
645
  key: keyAccessor ? keyAccessor(row.original) : row.id,
328
646
  className: classNames,
329
647
  ...isCurrent && {
@@ -343,57 +661,57 @@ var TableBody = ({ rows }) => {
343
661
  }
344
662
  }
345
663
  }
346
- }, debug && /* @__PURE__ */ React5.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
347
- return /* @__PURE__ */ React5.createElement(Cell, {
664
+ }, debug && /* @__PURE__ */ React6.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
665
+ return /* @__PURE__ */ React6.createElement(Cell, {
348
666
  key: cell.id,
349
667
  cell
350
668
  }, flexRender(cell.column.columnDef.cell, {
351
669
  className: "pli-2",
352
670
  ...cell.getContext()
353
671
  }));
354
- }), expand && /* @__PURE__ */ React5.createElement("td", null));
672
+ }), expand && /* @__PURE__ */ React6.createElement("td", null));
355
673
  }));
356
674
  };
357
675
  TableBody.displayName = TABLE_BODY_NAME;
358
676
 
359
677
  // packages/ui/react-ui-table/src/components/Table/TableFooter.tsx
360
678
  import { flexRender as flexRender2 } from "@tanstack/react-table";
361
- import React6 from "react";
679
+ import React7 from "react";
362
680
  var TABLE_FOOT_NAME = "TableFooter";
363
681
  var TableFooter = (props) => {
364
682
  const tableContext = useTableContext();
365
683
  const { table, expand, debug } = tableContext;
366
684
  const footers = table.getFooterGroups();
367
- return /* @__PURE__ */ React6.createElement("tfoot", {
685
+ return /* @__PURE__ */ React7.createElement("tfoot", {
368
686
  className: tfootRoot(props)
369
- }, footers.map((footerGroup) => /* @__PURE__ */ React6.createElement("tr", {
687
+ }, footers.map((footerGroup) => /* @__PURE__ */ React7.createElement("tr", {
370
688
  key: footerGroup.id,
371
689
  className: tfootTr(tableContext)
372
- }, debug && /* @__PURE__ */ React6.createElement("th", null), footerGroup.headers.map((footer) => {
373
- return /* @__PURE__ */ React6.createElement("th", {
690
+ }, debug && /* @__PURE__ */ React7.createElement("th", null), footerGroup.headers.map((footer) => {
691
+ return /* @__PURE__ */ React7.createElement("th", {
374
692
  key: footer.id,
375
693
  className: tfootTh(tableContext, footer.column.columnDef.meta?.footer?.classNames)
376
694
  }, footer.isPlaceholder ? null : flexRender2(footer.column.columnDef.footer, footer.getContext()));
377
- }), expand && /* @__PURE__ */ React6.createElement("th", null))));
695
+ }), expand && /* @__PURE__ */ React7.createElement("th", null))));
378
696
  };
379
697
  TableFooter.displayName = TABLE_FOOT_NAME;
380
698
 
381
699
  // packages/ui/react-ui-table/src/components/Table/TableHead.tsx
382
700
  import { flexRender as flexRender3 } from "@tanstack/react-table";
383
- import React7 from "react";
701
+ import React8 from "react";
384
702
  var TABLE_HEAD_NAME = "TableHeader";
385
703
  var TableHead = (_props) => {
386
704
  const tableContext = useTableContext();
387
705
  const headerGroups = tableContext.table.getHeaderGroups();
388
- return /* @__PURE__ */ React7.createElement("thead", {
706
+ return /* @__PURE__ */ React8.createElement("thead", {
389
707
  className: theadRoot(tableContext)
390
708
  }, headerGroups.map((headerGroup) => {
391
709
  return (
392
710
  // Group element to hover resize handles.
393
- /* @__PURE__ */ React7.createElement("tr", {
711
+ /* @__PURE__ */ React8.createElement("tr", {
394
712
  key: headerGroup.id,
395
713
  className: theadTr(tableContext)
396
- }, tableContext.debug && /* @__PURE__ */ React7.createElement("th", {
714
+ }, tableContext.debug && /* @__PURE__ */ React8.createElement("th", {
397
715
  className: "font-mono",
398
716
  style: {
399
717
  width: 32
@@ -402,13 +720,13 @@ var TableHead = (_props) => {
402
720
  const isResizing = header.column.getIsResizing();
403
721
  const onResize = header.getResizeHandler();
404
722
  const resizable = header.column.columnDef.meta?.resizable;
405
- return /* @__PURE__ */ React7.createElement("th", {
723
+ return /* @__PURE__ */ React8.createElement("th", {
406
724
  key: header.id,
407
725
  style: {
408
726
  width: header.getSize()
409
727
  },
410
728
  className: theadTh(tableContext, header.column.columnDef.meta?.header?.classNames)
411
- }, !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", {
412
730
  className: theadResizeRoot({
413
731
  isResizing
414
732
  }),
@@ -416,100 +734,38 @@ var TableHead = (_props) => {
416
734
  onMouseDown: onResize,
417
735
  onTouchStart: onResize
418
736
  }));
419
- }), tableContext.expand && /* @__PURE__ */ React7.createElement("th", null))
737
+ }), tableContext.expand && /* @__PURE__ */ React8.createElement("th", null))
420
738
  );
421
739
  }));
422
740
  };
423
741
  TableHead.displayName = TABLE_HEAD_NAME;
424
742
 
425
- // packages/ui/react-ui-table/src/components/hooks/usePinLastRow.ts
426
- import { useEffect, useState as useState2 } from "react";
427
- var usePinLastRow = (pinLastRow, table, data, getScrollElement) => {
428
- const [pinnedRowKey, setPinnedRowKey] = useState2();
429
- useEffect(() => {
430
- if (!pinLastRow) {
431
- return;
432
- }
433
- const rows = table.getRowModel().rows;
434
- const rowToPin = rows[rows.length - 1];
435
- const rowId = rowToPin.id;
436
- if (rowId === pinnedRowKey) {
437
- return;
438
- }
439
- table.resetRowPinning();
440
- rowToPin.pin("bottom");
441
- const scrollElement = getScrollElement?.();
442
- const isFirstRender = pinnedRowKey === void 0;
443
- if (scrollElement && !isFirstRender) {
444
- requestAnimationFrame(() => {
445
- scrollElement.scrollTo({
446
- top: scrollElement.scrollHeight
447
- });
448
- });
449
- }
450
- setPinnedRowKey(rowId);
451
- }, [
452
- pinLastRow,
453
- table,
454
- getScrollElement,
455
- pinnedRowKey,
456
- setPinnedRowKey,
457
- data
458
- ]);
459
- };
460
-
461
743
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
462
744
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
463
745
  var Table = (props) => {
464
746
  const { role, onColumnResize, columnVisibility, header = true, rowsSelectable, debug, onDataSelectionChange, getScrollElement, pinLastRow } = props;
465
747
  const columns = useDefaultValue(props.columns, []);
466
- const data = useDefaultValue(props.data, []);
467
- const TableProvider2 = TableProvider;
468
- const [columnsInitialised, setColumnsInitialised] = useState3(false);
469
- const [columnSizing, setColumnSizing] = useState3({});
470
- useEffect2(() => {
471
- if (columnsInitialised) {
472
- return;
473
- }
474
- setColumnSizing(columns.filter((column) => !!column.size && column.prop !== void 0).reduce((state, column) => {
475
- state[column.prop] = column.size;
476
- return state;
477
- }, {}));
478
- setColumnsInitialised(true);
479
- }, [
480
- columns,
481
- setColumnSizing
748
+ const incomingData = useDefaultValue(props.data, []);
749
+ const [data, setData] = useState7([
750
+ ...incomingData
482
751
  ]);
483
- const [columnSizingInfo, setColumnSizingInfo] = useState3({});
484
- const notifyColumnResize = useCallback(() => onColumnResize?.(columnSizing), [
485
- onColumnResize,
486
- columnSizing
752
+ const forceUpdate = useCallback6(() => setData([
753
+ ...incomingData
754
+ ]), [
755
+ incomingData
487
756
  ]);
488
- useOnTransition(columnSizingInfo.isResizingColumn, (v) => typeof v === "string", false, notifyColumnResize);
489
- const [rowSelection = {}, setRowSelection] = useControllableState({
490
- prop: props.rowSelection,
491
- onChange: props.onRowSelectionChange,
492
- defaultProp: props.defaultRowSelection
493
- });
494
- const handleRowSelectionChange = useCallback((updaterOrValue) => {
495
- const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
496
- if (rowsSelectable === "multi") {
497
- setRowSelection(nextRowSelection);
498
- } else if (rowsSelectable) {
499
- const nextRowSelectionKey = Object.keys(nextRowSelection).filter((id) => !rowSelection[id])[0];
500
- setRowSelection(nextRowSelectionKey ? {
501
- [nextRowSelectionKey]: true
502
- } : {});
503
- } else {
504
- setRowSelection({});
505
- }
506
- }, [
507
- rowsSelectable,
508
- setRowSelection,
509
- rowSelection
757
+ useEffect3(() => forceUpdate(), [
758
+ JSON.stringify(incomingData),
759
+ forceUpdate
510
760
  ]);
511
- const [grouping, handleGroupingChange] = useState3(props.grouping ?? []);
512
- 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 ?? []), [
513
769
  handleGroupingChange,
514
770
  props.grouping
515
771
  ]);
@@ -551,7 +807,7 @@ var Table = (props) => {
551
807
  // Debug
552
808
  debugTable: debug
553
809
  });
554
- useEffect2(() => {
810
+ useEffect3(() => {
555
811
  onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
556
812
  }, [
557
813
  onDataSelectionChange,
@@ -563,18 +819,18 @@ var Table = (props) => {
563
819
  if (!getScrollElement) {
564
820
  log.warn("Table: getScrollElement is not set. This is required for virtualized tables.", void 0, {
565
821
  F: __dxlog_file,
566
- L: 159,
822
+ L: 120,
567
823
  S: void 0,
568
824
  C: (f, a) => f(...a)
569
825
  });
570
826
  }
571
- return /* @__PURE__ */ React8.createElement(TableProvider2, {
827
+ return /* @__PURE__ */ React9.createElement(TableProvider2, {
572
828
  ...props,
573
829
  table,
574
830
  header,
575
831
  expand,
576
832
  isGrid: role === "grid" || role === "treegrid"
577
- }, /* @__PURE__ */ React8.createElement(TableImpl, {
833
+ }, /* @__PURE__ */ React9.createElement(TableImpl, {
578
834
  debug: false,
579
835
  getScrollElement,
580
836
  ...props
@@ -583,20 +839,14 @@ var Table = (props) => {
583
839
  var TableImpl = (props) => {
584
840
  const { debug, classNames, getScrollElement, role, footer, grouping, fullWidth } = props;
585
841
  const { table } = useTableContext();
586
- const centerRows = table.getCenterRows();
587
- const bottomRows = table.getBottomRows();
588
- const rows = [
589
- ...centerRows,
590
- ...bottomRows
591
- ];
592
842
  if (debug) {
593
- return /* @__PURE__ */ React8.createElement("pre", {
843
+ return /* @__PURE__ */ React9.createElement("pre", {
594
844
  className: "font-mono text-xs text-neutral-500 m-1 p-2 ring"
595
- }, /* @__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)));
596
846
  }
597
847
  const virtualisable = getScrollElement !== void 0;
598
848
  const isResizingColumn = table.getState().columnSizingInfo.isResizingColumn;
599
- return /* @__PURE__ */ React8.createElement("table", {
849
+ return /* @__PURE__ */ React9.createElement("table", {
600
850
  role,
601
851
  className: tableRoot(props, classNames),
602
852
  ...!fullWidth && {
@@ -604,18 +854,32 @@ var TableImpl = (props) => {
604
854
  width: table.getTotalSize()
605
855
  }
606
856
  }
607
- }, /* @__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, {
608
858
  getScrollElement
609
- }) : /* @__PURE__ */ React8.createElement(VirtualizedTableContent, {
859
+ }) : /* @__PURE__ */ React9.createElement(VirtualizedTableContent, {
610
860
  getScrollElement
611
- }) : /* @__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, {
612
872
  rows
613
- }) : /* @__PURE__ */ React8.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React8.createElement(TableFooter, null));
873
+ });
614
874
  };
615
875
  var VirtualizedTableContent = ({ getScrollElement }) => {
616
876
  const { table } = useTableContext();
617
877
  const centerRows = table.getCenterRows();
618
- const pinnedRows = table.getBottomRows();
878
+ let pinnedRows = [];
879
+ try {
880
+ pinnedRows = table.getBottomRows();
881
+ } catch (_) {
882
+ }
619
883
  const { getTotalSize, getVirtualItems } = useVirtualizer({
620
884
  getScrollElement,
621
885
  count: centerRows.length,
@@ -630,123 +894,54 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
630
894
  ...virtualRows.map((virtualRow) => centerRows[virtualRow.index]),
631
895
  ...pinnedRows
632
896
  ];
633
- 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", {
634
898
  role: "none"
635
- }, /* @__PURE__ */ React8.createElement("tr", {
899
+ }, /* @__PURE__ */ React9.createElement("tr", {
636
900
  role: "none"
637
- }, /* @__PURE__ */ React8.createElement("td", {
901
+ }, /* @__PURE__ */ React9.createElement("td", {
638
902
  style: {
639
903
  height: `${paddingTop}px`
640
904
  },
641
905
  role: "none"
642
- }))), /* @__PURE__ */ React8.createElement(TableBody, {
906
+ }))), /* @__PURE__ */ React9.createElement(TableBody, {
643
907
  rows: rowsToRender
644
- }), paddingBottom > 0 && /* @__PURE__ */ React8.createElement("tbody", {
908
+ }), paddingBottom > 0 && /* @__PURE__ */ React9.createElement("tbody", {
645
909
  role: "none"
646
- }, /* @__PURE__ */ React8.createElement("tr", {
910
+ }, /* @__PURE__ */ React9.createElement("tr", {
647
911
  role: "none"
648
- }, /* @__PURE__ */ React8.createElement("td", {
912
+ }, /* @__PURE__ */ React9.createElement("td", {
649
913
  style: {
650
914
  height: `${paddingBottom}px`
651
915
  },
652
916
  role: "none"
653
917
  }))));
654
918
  };
655
- var MemoizedVirtualisedTableContent = /* @__PURE__ */ React8.memo(VirtualizedTableContent);
919
+ var MemoizedVirtualisedTableContent = /* @__PURE__ */ React9.memo(VirtualizedTableContent);
656
920
  var GroupedTableContent = () => {
657
921
  const { table: { getGroupedRowModel: getGroupedRowModel2, getHeaderGroups, getState }, debug } = useTableContext();
658
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
659
- return /* @__PURE__ */ React8.createElement(Fragment, {
922
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
923
+ return /* @__PURE__ */ React9.createElement(Fragment, {
660
924
  key: i
661
- }, /* @__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", {
662
926
  // TODO(burdon): Calculate row span.
663
927
  colSpan: getHeaderGroups()[0].headers.length,
664
928
  className: groupTh({})
665
- }, 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, {
666
930
  rows: row.subRows
667
931
  }));
668
932
  }));
669
933
  };
670
934
 
671
- // packages/ui/react-ui-table/src/components/Cell/CellCombobox.tsx
672
- import { CaretDown } from "@phosphor-icons/react";
673
- import React9, { useCallback as useCallback2, useState as useState4 } from "react";
674
- import { Popover as Popover2, useTranslation as useTranslation2 } from "@dxos/react-ui";
675
- import { PopoverCombobox } from "@dxos/react-ui-searchlist";
676
- import { descriptionText, getSize as getSize3, mx as mx3, staticPlaceholderText } from "@dxos/react-ui-theme";
677
- var initialItems = (model, value) => value ? {
678
- [model.getId(value)]: {
679
- label: model.getText(value),
680
- data: value
681
- }
682
- } : {};
683
- var CellCombobox = ({ model, value, onValueChange }) => {
684
- const { t } = useTranslation2(translationKey);
685
- const [items, setItems] = useState4(initialItems(model, value));
686
- const [loading, setLoading] = useState4(false);
687
- const [searchInputValue, setSearchInputValue] = useState4("");
688
- const handleSearchInputValueChange = async (text) => {
689
- setSearchInputValue(text ?? "");
690
- setLoading(true);
691
- const items2 = await model.query(text);
692
- setItems(items2.reduce((acc, item) => {
693
- acc[model.getId(item)] = {
694
- label: model.getText(item),
695
- data: item
696
- };
697
- return acc;
698
- }, initialItems(model, value)));
699
- setLoading(false);
700
- };
701
- const handleValueChange = useCallback2((id) => {
702
- onValueChange(items[id]?.data);
703
- }, [
704
- items,
705
- onValueChange
706
- ]);
707
- return /* @__PURE__ */ React9.createElement(PopoverCombobox.Root, {
708
- placeholder: t("no selection label")
709
- }, /* @__PURE__ */ React9.createElement(PopoverCombobox.Trigger, {
710
- variant: "ghost",
711
- classNames: "is-full rounded-none ring-inset"
712
- }, value ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement("span", {
713
- className: mx3("font-normal text-start text-base flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
714
- }, model.getText(value)), /* @__PURE__ */ React9.createElement(CaretDown, {
715
- weight: "bold",
716
- className: getSize3(3)
717
- })) : null), /* @__PURE__ */ React9.createElement(PopoverCombobox.Content, {
718
- shouldFilter: false,
719
- classNames: "is-[--radix-popover-trigger-width]"
720
- }, /* @__PURE__ */ React9.createElement(PopoverCombobox.Input, {
721
- value: searchInputValue,
722
- onValueChange: handleSearchInputValueChange
723
- }), /* @__PURE__ */ React9.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React9.createElement("p", {
724
- className: mx3("text-center", descriptionText)
725
- }, "Start typing to search") : loading ? /* @__PURE__ */ React9.createElement("p", {
726
- className: mx3("text-center", descriptionText)
727
- }, "Searching\u2026") : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(PopoverCombobox.Empty, {
728
- classNames: [
729
- "text-center",
730
- descriptionText
731
- ]
732
- }, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React9.createElement(PopoverCombobox.Item, {
733
- key: id,
734
- value: id,
735
- onSelect: handleValueChange,
736
- classNames: "truncate"
737
- }, label)))), /* @__PURE__ */ React9.createElement(Popover2.Arrow, null)));
738
- };
739
-
740
935
  // packages/ui/react-ui-table/src/helpers.tsx
741
936
  import { useFocusFinders } from "@fluentui/react-tabster";
742
- import { Check as Check2, ClipboardText, X as X2 } from "@phosphor-icons/react";
937
+ import { Check as Check2, ClipboardText, X as X3 } from "@phosphor-icons/react";
743
938
  import { createColumnHelper } from "@tanstack/react-table";
744
939
  import { format } from "date-fns/format";
745
940
  import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
746
- import React10, { useEffect as useEffect3, useRef as useRef2, useState as useState5 } from "react";
941
+ import React10, { useCallback as useCallback7, useEffect as useEffect4, useRef as useRef3, useState as useState8 } from "react";
747
942
  import { log as log2 } from "@dxos/log";
748
943
  import { Input as Input2, Tooltip } from "@dxos/react-ui";
749
- import { getSize as getSize4, mx as mx4 } from "@dxos/react-ui-theme";
944
+ import { getSize as getSize4, mx as mx5 } from "@dxos/react-ui-theme";
750
945
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/helpers.tsx";
751
946
  var createColumnBuilder = () => ({
752
947
  helper: createColumnHelper(),
@@ -761,16 +956,19 @@ var ComboboxBuilderCell = (cellContext) => {
761
956
  }) : null;
762
957
  };
763
958
  var StringBuilderCell = (cellContext) => {
764
- const ref = useRef2(null);
959
+ const ref = useRef3(null);
765
960
  const { findPrevFocusable } = useFocusFinders();
766
961
  const { onUpdate, cell } = cellContext.column.columnDef.meta;
767
962
  const initialValue = cellContext.getValue();
768
- const [value, setValue] = useState5(() => {
769
- if (initialValue?.content) {
770
- return initialValue?.content;
771
- }
772
- return initialValue;
773
- });
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
+ ]);
774
972
  const handleSave = () => {
775
973
  ref.current && document.activeElement === ref.current && findPrevFocusable(ref.current)?.focus();
776
974
  if (value !== initialValue) {
@@ -807,10 +1005,10 @@ var displayNumber = (value, digits) => value || value === 0 ? value.toLocaleStri
807
1005
  var NumberBuilderCell = (cellContext) => {
808
1006
  const { onUpdate, digits } = cellContext.column.columnDef.meta;
809
1007
  const value = cellContext.getValue();
810
- const [text, setText] = useState5(displayNumber(value, digits));
1008
+ const [text, setText] = useState8(displayNumber(value, digits));
811
1009
  const { findPrevFocusable } = useFocusFinders();
812
- const ref = useRef2(null);
813
- useEffect3(() => {
1010
+ const ref = useRef3(null);
1011
+ useEffect4(() => {
814
1012
  (!document.activeElement || document.activeElement !== ref.current) && setText(displayNumber(value, digits));
815
1013
  }, [
816
1014
  digits,
@@ -897,7 +1095,7 @@ var ColumnBuilder = class {
897
1095
  cell: model && onUpdate ? ComboboxBuilderCell : (cellContext) => {
898
1096
  const cellValue = cellContext.getValue();
899
1097
  return /* @__PURE__ */ React10.createElement("div", {
900
- className: mx4("truncate", classNames)
1098
+ className: mx5("truncate", classNames)
901
1099
  }, cellValue ? model?.getText(cellValue) : "");
902
1100
  },
903
1101
  ...props,
@@ -928,7 +1126,7 @@ var ColumnBuilder = class {
928
1126
  value = value.content;
929
1127
  }
930
1128
  return /* @__PURE__ */ React10.createElement("div", {
931
- className: mx4("truncate", textPadding, classNames)
1129
+ className: mx5("truncate", textPadding, classNames)
932
1130
  }, value);
933
1131
  },
934
1132
  ...props,
@@ -957,7 +1155,6 @@ var ColumnBuilder = class {
957
1155
  onUpdate,
958
1156
  digits,
959
1157
  header: {
960
- classNames: "text-end",
961
1158
  ...props.meta?.header
962
1159
  },
963
1160
  cell: {
@@ -983,14 +1180,14 @@ var ColumnBuilder = class {
983
1180
  addSuffix: true
984
1181
  }) : value.toISOString() : void 0;
985
1182
  return /* @__PURE__ */ React10.createElement("div", {
986
- className: mx4(textPadding, classNames)
1183
+ className: mx5(textPadding, classNames)
987
1184
  }, str);
988
1185
  } catch (err) {
989
1186
  log2.info("formatError", {
990
1187
  value
991
1188
  }, {
992
1189
  F: __dxlog_file2,
993
- L: 374,
1190
+ L: 376,
994
1191
  S: this,
995
1192
  C: (f, a) => f(...a)
996
1193
  });
@@ -1110,7 +1307,7 @@ var ColumnBuilder = class {
1110
1307
  */
1111
1308
  icon({ label, size, on, off, ...props } = {}) {
1112
1309
  const IconOn = on?.Icon ?? Check2;
1113
- const IconOff = off?.Icon ?? X2;
1310
+ const IconOff = off?.Icon ?? X3;
1114
1311
  return {
1115
1312
  size: size ?? 32,
1116
1313
  // TODO(Zan): Implement sort algorithm
@@ -1122,11 +1319,11 @@ var ColumnBuilder = class {
1122
1319
  const value = cell.getValue();
1123
1320
  if (value) {
1124
1321
  return /* @__PURE__ */ React10.createElement(IconOn, {
1125
- className: mx4("block mli-auto", getSize4(6), on?.className ?? "text-green-700")
1322
+ className: mx5("block mli-auto", getSize4(6), on?.className ?? "text-green-700")
1126
1323
  });
1127
1324
  } else if (value === false) {
1128
1325
  return /* @__PURE__ */ React10.createElement(IconOff, {
1129
- className: mx4("block mli-auto", getSize4(6), off?.className ?? "text-red-700")
1326
+ className: mx5("block mli-auto", getSize4(6), off?.className ?? "text-red-700")
1130
1327
  });
1131
1328
  } else {
1132
1329
  return null;
@@ -1135,13 +1332,165 @@ var ColumnBuilder = class {
1135
1332
  ...props
1136
1333
  };
1137
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
+ });
1138
1485
  };
1139
1486
  export {
1140
1487
  CellCombobox,
1141
1488
  ColumnBuilder,
1142
1489
  ColumnMenu,
1143
- ColumnPanel,
1490
+ ColumnSettingsForm,
1491
+ ColumnSettingsPanel,
1144
1492
  MemoizedVirtualisedTableContent,
1493
+ SortIndicator,
1145
1494
  Table,
1146
1495
  createColumnBuilder,
1147
1496
  currentRow,
@@ -1149,6 +1498,7 @@ export {
1149
1498
  gridCellFocusRing,
1150
1499
  groupTh,
1151
1500
  headPadding,
1501
+ schemaToColumnDefs,
1152
1502
  selectedRow,
1153
1503
  tableRoot,
1154
1504
  tbodyRoot,
@@ -1163,6 +1513,10 @@ export {
1163
1513
  theadRoot,
1164
1514
  theadTh,
1165
1515
  theadTr,
1166
- translations_default as translations
1516
+ translations_default as translations,
1517
+ useColumnResizing,
1518
+ useColumnSorting,
1519
+ usePinLastRow,
1520
+ useRowSelection
1167
1521
  };
1168
1522
  //# sourceMappingURL=index.mjs.map