@dxos/react-ui-table 0.4.10-main.ec8b427 → 0.4.10-main.eedd150

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 (47) hide show
  1. package/dist/lib/browser/index.mjs +353 -183
  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 +8 -2
  5. package/dist/types/src/components/ColumnMenu.d.ts.map +1 -1
  6. package/dist/types/src/components/ColumnMenu.stories.d.ts +4 -0
  7. package/dist/types/src/components/ColumnMenu.stories.d.ts.map +1 -1
  8. package/dist/types/src/components/ColumnSettingsForm.d.ts +10 -0
  9. package/dist/types/src/components/ColumnSettingsForm.d.ts.map +1 -0
  10. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  11. package/dist/types/src/components/Table/Table.stories.d.ts +3 -0
  12. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  13. package/dist/types/src/components/Table/TableBody.d.ts.map +1 -1
  14. package/dist/types/src/components/hooks/useColumnSorting.d.ts +9 -0
  15. package/dist/types/src/components/hooks/useColumnSorting.d.ts.map +1 -0
  16. package/dist/types/src/components/hooks/usePinLastRow.d.ts +3 -0
  17. package/dist/types/src/components/hooks/usePinLastRow.d.ts.map +1 -0
  18. package/dist/types/src/components/schema/SchemaToTable.stories.d.ts +11 -0
  19. package/dist/types/src/components/schema/SchemaToTable.stories.d.ts.map +1 -0
  20. package/dist/types/src/components/schema/schema.d.ts +5 -0
  21. package/dist/types/src/components/schema/schema.d.ts.map +1 -0
  22. package/dist/types/src/components/schema/schema.test.d.ts +2 -0
  23. package/dist/types/src/components/schema/schema.test.d.ts.map +1 -0
  24. package/dist/types/src/components/schema/schemaToColumns.d.ts +4 -0
  25. package/dist/types/src/components/schema/schemaToColumns.d.ts.map +1 -0
  26. package/dist/types/src/helpers.d.ts +4 -0
  27. package/dist/types/src/helpers.d.ts.map +1 -1
  28. package/dist/types/src/theme.d.ts +1 -0
  29. package/dist/types/src/theme.d.ts.map +1 -1
  30. package/package.json +18 -15
  31. package/src/components/ColumnMenu.stories.tsx +52 -1
  32. package/src/components/ColumnMenu.tsx +129 -211
  33. package/src/components/ColumnSettingsForm.tsx +206 -0
  34. package/src/components/Table/Table.stories.tsx +31 -0
  35. package/src/components/Table/Table.tsx +6 -15
  36. package/src/components/Table/TableBody.tsx +6 -1
  37. package/src/components/hooks/useColumnSorting.ts +54 -0
  38. package/src/components/hooks/usePinLastRow.ts +43 -0
  39. package/src/components/schema/SchemaToTable.stories.tsx +72 -0
  40. package/src/components/schema/schema.test.ts +148 -0
  41. package/src/components/schema/schema.ts +96 -0
  42. package/src/components/schema/schemaToColumns.ts +50 -0
  43. package/src/helpers.tsx +23 -1
  44. package/src/theme.ts +3 -2
  45. package/dist/types/src/components/SortButton.d.ts +0 -8
  46. package/dist/types/src/components/SortButton.d.ts.map +0 -1
  47. package/src/components/SortButton.tsx +0 -34
@@ -1,39 +1,15 @@
1
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";
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";
7
6
 
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
- };
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";
37
13
 
38
14
  // packages/ui/react-ui-table/src/translations.ts
39
15
  var translationKey = "table";
@@ -58,34 +34,12 @@ var translations_default = [
58
34
  }
59
35
  ];
60
36
 
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
- })));
82
- };
83
- var Section = ({ children, className }) => /* @__PURE__ */ React2.createElement("div", {
37
+ // packages/ui/react-ui-table/src/components/ColumnSettingsForm.tsx
38
+ var Section = ({ children, className }) => /* @__PURE__ */ React.createElement("div", {
84
39
  role: "none",
85
40
  className: mx("p-2", className)
86
41
  }, children);
87
- var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete }) => {
88
- const [open, setOpen] = useState(false);
42
+ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onClose }) => {
89
43
  const [prop, setProp] = useState(column.id);
90
44
  const [refTable, setRefTable] = useState(column.refTable);
91
45
  const [refProp, setRefProp] = useState(column.refProp);
@@ -96,7 +50,7 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
96
50
  const { t } = useTranslation(translationKey);
97
51
  const handleCancel = () => {
98
52
  setProp(column.id);
99
- setOpen(false);
53
+ onClose;
100
54
  };
101
55
  const handleSave = () => {
102
56
  if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {
@@ -119,117 +73,275 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
119
73
  refProp,
120
74
  digits: safeParseInt(digits)
121
75
  });
122
- setOpen(false);
76
+ onClose();
123
77
  };
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", {
78
+ return /* @__PURE__ */ React.createElement("div", {
138
79
  className: "flex flex-col gap-1"
139
- }, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
80
+ }, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
140
81
  classNames: "mbe-1"
141
- }, t("column label label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
82
+ }, t("column label label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
142
83
  placeholder: "Column label",
143
84
  value: label ?? "",
144
85
  onChange: (event) => setLabel(event.target.value),
145
86
  autoFocus: true
146
- })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
87
+ })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
147
88
  classNames: "mbe-1 mbs-3"
148
- }, t("property key label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
89
+ }, t("property key label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
149
90
  ref: propRef,
150
91
  placeholder: "Property key",
151
92
  // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.
152
93
  value: prop ?? "",
153
94
  onChange: (event) => setProp(event.target.value.replace(/[^\w_]/g, ""))
154
- })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
95
+ })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
155
96
  classNames: "mbe-1 mbs-3"
156
- }, t("column type label")), /* @__PURE__ */ React2.createElement(Select.Root, {
97
+ }, t("column type label")), /* @__PURE__ */ React.createElement(Select.Root, {
157
98
  value: type,
158
99
  onValueChange: setType
159
- }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
100
+ }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
160
101
  placeholder: "Type",
161
102
  classNames: "is-full"
162
- }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, [
103
+ }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, [
163
104
  "number",
164
105
  "boolean",
165
106
  "string",
166
107
  "ref"
167
- ].map((type2) => /* @__PURE__ */ React2.createElement(Select.Option, {
108
+ ].map((type2) => /* @__PURE__ */ React.createElement(Select.Option, {
168
109
  key: type2,
169
110
  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, {
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, {
171
112
  classNames: "mbe-1 mbs-3"
172
- }, t("digits label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
113
+ }, t("digits label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
173
114
  value: digits ?? "",
174
115
  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, {
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, {
176
117
  classNames: "mbe-1 mbs-3"
177
- }, "Table"), /* @__PURE__ */ React2.createElement(Select.Root, {
118
+ }, "Table"), /* @__PURE__ */ React.createElement(Select.Root, {
178
119
  value: refTable,
179
120
  onValueChange: setRefTable
180
- }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
121
+ }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
181
122
  placeholder: "Table",
182
123
  classNames: "is-full"
183
- }), /* @__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, {
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, {
184
125
  key: id,
185
126
  value: id
186
- }, name ?? id))))))), refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
127
+ }, name ?? id))))))), refTable && /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
187
128
  classNames: "mbe-1 mbs-3"
188
- }, "Table property"), /* @__PURE__ */ React2.createElement(Select.Root, {
129
+ }, "Table property"), /* @__PURE__ */ React.createElement(Select.Root, {
189
130
  value: refProp,
190
131
  onValueChange: setRefProp
191
- }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
132
+ }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
192
133
  placeholder: "Property",
193
134
  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, {
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, {
195
136
  key: id,
196
137
  value: id
197
- }, label2 ?? id))))))))), /* @__PURE__ */ React2.createElement(Separator, {
138
+ }, label2 ?? id))))))))), /* @__PURE__ */ React.createElement(Separator, {
198
139
  classNames: "mli-2"
199
- }), /* @__PURE__ */ React2.createElement(Section, {
140
+ }), /* @__PURE__ */ React.createElement(Section, {
200
141
  className: "space-b-1.5"
201
- }, /* @__PURE__ */ React2.createElement(Button2, {
142
+ }, /* @__PURE__ */ React.createElement(Button, {
202
143
  variant: "primary",
203
144
  classNames: "is-full flex gap-2",
204
145
  onClick: handleSave
205
- }, /* @__PURE__ */ React2.createElement("span", null, t("save label")), /* @__PURE__ */ React2.createElement("div", {
146
+ }, /* @__PURE__ */ React.createElement("span", null, t("save label")), /* @__PURE__ */ React.createElement("div", {
206
147
  className: "grow"
207
- }), /* @__PURE__ */ React2.createElement(Check, {
208
- className: getSize2(5)
209
- })), /* @__PURE__ */ React2.createElement(Button2, {
148
+ }), /* @__PURE__ */ React.createElement(Check, {
149
+ className: getSize(5)
150
+ })), /* @__PURE__ */ React.createElement(Button, {
210
151
  classNames: "is-full flex gap-2",
211
152
  onClick: handleCancel
212
- }, /* @__PURE__ */ React2.createElement("span", null, t("cancel label", {
153
+ }, /* @__PURE__ */ React.createElement("span", null, t("cancel label", {
213
154
  ns: "os"
214
- })), /* @__PURE__ */ React2.createElement("div", {
155
+ })), /* @__PURE__ */ React.createElement("div", {
215
156
  className: "grow"
216
- }), /* @__PURE__ */ React2.createElement(X, {
217
- className: getSize2(5)
218
- })), /* @__PURE__ */ React2.createElement(Button2, {
157
+ }), /* @__PURE__ */ React.createElement(X, {
158
+ className: getSize(5)
159
+ })), /* @__PURE__ */ React.createElement(Button, {
219
160
  classNames: "is-full flex gap-2",
220
161
  onClick: () => onDelete?.(column.id)
221
- }, /* @__PURE__ */ React2.createElement("span", null, t("delete label")), /* @__PURE__ */ React2.createElement("div", {
162
+ }, /* @__PURE__ */ React.createElement("span", null, t("delete label")), /* @__PURE__ */ React.createElement("div", {
222
163
  className: "grow"
223
- }), /* @__PURE__ */ React2.createElement(Trash, {
224
- className: getSize2(5)
225
- })))))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
164
+ }), /* @__PURE__ */ React.createElement(Trash, {
165
+ className: getSize(5)
166
+ }))));
167
+ };
168
+
169
+ // packages/ui/react-ui-table/src/components/hooks/useColumnSorting.ts
170
+ import { useState as useState2 } from "react";
171
+ var useColumnSorting = (column) => {
172
+ const [sortDirection, setSortDirection] = useState2(column.getIsSorted());
173
+ const [firstSort, setFirstSort] = useState2();
174
+ const canSort = column.getCanSort();
175
+ const updateColumnSort = (direction) => {
176
+ setSortDirection(direction);
177
+ switch (direction) {
178
+ case false:
179
+ column.clearSorting();
180
+ break;
181
+ case "asc":
182
+ column.toggleSorting(false);
183
+ break;
184
+ case "desc":
185
+ column.toggleSorting(true);
186
+ break;
187
+ }
188
+ };
189
+ const onToggleSort = () => {
190
+ if (sortDirection === false) {
191
+ return;
192
+ }
193
+ if (sortDirection === firstSort) {
194
+ updateColumnSort(firstSort === "asc" ? "desc" : "asc");
195
+ } else {
196
+ updateColumnSort(false);
197
+ }
198
+ };
199
+ const onSelectSort = (direction) => {
200
+ setFirstSort(direction);
201
+ updateColumnSort(direction);
202
+ };
203
+ const onClearSort = () => {
204
+ updateColumnSort(false);
205
+ };
206
+ return {
207
+ canSort,
208
+ sortDirection,
209
+ onSelectSort,
210
+ onToggleSort,
211
+ onClearSort
212
+ };
213
+ };
214
+
215
+ // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
216
+ var ColumnMenu = ({ column, ...props }) => {
217
+ const title = column.label?.length ? column.label : column.id;
218
+ const header = props.context.header;
219
+ const { canSort, sortDirection, onSelectSort, onToggleSort, onClearSort } = useColumnSorting(header.column);
220
+ const columnSettingsAnchorRef = useRef2(null);
221
+ const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState3(false);
222
+ const shouldPreventFocusOnClose = useRef2(false);
223
+ const onOpenColumnSettings = useCallback(() => {
224
+ shouldPreventFocusOnClose.current = true;
225
+ setIsColumnSettingsOpen(true);
226
+ }, [
227
+ shouldPreventFocusOnClose,
228
+ setIsColumnSettingsOpen
229
+ ]);
230
+ const onDropdownCloseAutoFocus = useCallback((event) => {
231
+ if (shouldPreventFocusOnClose.current) {
232
+ event.preventDefault();
233
+ shouldPreventFocusOnClose.current = false;
234
+ }
235
+ }, [
236
+ shouldPreventFocusOnClose
237
+ ]);
238
+ return /* @__PURE__ */ React2.createElement("div", {
239
+ className: "flex items-center justify-center justify-between"
240
+ }, /* @__PURE__ */ React2.createElement("div", {
241
+ className: "flex items-center gap-1 truncate",
242
+ title
243
+ }, /* @__PURE__ */ React2.createElement(SortIndicator, {
244
+ direction: sortDirection,
245
+ onClick: onToggleSort
246
+ }), /* @__PURE__ */ React2.createElement("div", {
247
+ className: "truncate"
248
+ }, title)), /* @__PURE__ */ React2.createElement(DropdownMenu.Root, {
249
+ modal: false
250
+ }, /* @__PURE__ */ React2.createElement(Popover.Root, {
251
+ open: isColumnSettingsOpen,
252
+ onOpenChange: setIsColumnSettingsOpen,
253
+ modal: false
254
+ }, /* @__PURE__ */ React2.createElement(DropdownMenu.Trigger, {
255
+ ref: columnSettingsAnchorRef,
256
+ asChild: true
257
+ }, /* @__PURE__ */ React2.createElement(Popover.Anchor, {
258
+ asChild: true
259
+ }, /* @__PURE__ */ React2.createElement(Button2, {
260
+ variant: "ghost"
261
+ }, /* @__PURE__ */ React2.createElement(CaretDown, {
262
+ className: getSize2(4)
263
+ })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Content, {
264
+ onCloseAutoFocus: onDropdownCloseAutoFocus,
265
+ sideOffset: 4,
266
+ collisionPadding: 8
267
+ }, /* @__PURE__ */ React2.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
268
+ onClick: () => onSelectSort("asc")
269
+ }, /* @__PURE__ */ React2.createElement("span", {
270
+ className: "grow"
271
+ }, "Sort ascending"), /* @__PURE__ */ React2.createElement("span", {
272
+ className: "opacity-50"
273
+ }, /* @__PURE__ */ React2.createElement(ArrowUp, {
274
+ className: getSize2(4)
275
+ }))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
276
+ onClick: () => onSelectSort("desc")
277
+ }, /* @__PURE__ */ React2.createElement("span", {
278
+ className: "grow"
279
+ }, "Sort descending"), /* @__PURE__ */ React2.createElement("span", {
280
+ className: "opacity-50"
281
+ }, /* @__PURE__ */ React2.createElement(ArrowDown, {
282
+ className: getSize2(4)
283
+ }))), sortDirection !== false && /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
284
+ onClick: onClearSort
285
+ }, /* @__PURE__ */ React2.createElement("span", {
286
+ className: "grow"
287
+ }, "Clear sort"), /* @__PURE__ */ React2.createElement("span", {
288
+ className: "opacity-50"
289
+ }, /* @__PURE__ */ React2.createElement(X2, {
290
+ className: getSize2(4)
291
+ })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
292
+ onClick: onOpenColumnSettings
293
+ }, /* @__PURE__ */ React2.createElement("span", {
294
+ className: "grow"
295
+ }, "Column settings"), /* @__PURE__ */ React2.createElement("span", {
296
+ 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, {
300
+ ...props,
301
+ column,
302
+ onClose: () => setIsColumnSettingsOpen(false)
303
+ }))));
304
+ };
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, {
306
+ classNames: "w-60"
307
+ }, /* @__PURE__ */ React2.createElement(DensityProvider, {
308
+ density: "fine"
309
+ }, /* @__PURE__ */ React2.createElement(ColumnSettingsForm, {
310
+ column,
311
+ tableDefs,
312
+ tableDef,
313
+ onUpdate,
314
+ onDelete,
315
+ onClose
316
+ }))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null)));
317
+ var SortIndicator = ({ direction, onClick }) => {
318
+ if (direction === false) {
319
+ return null;
320
+ }
321
+ let icon;
322
+ switch (direction) {
323
+ case "asc":
324
+ icon = /* @__PURE__ */ React2.createElement(ArrowUp, {
325
+ className: getSize2(3)
326
+ });
327
+ break;
328
+ case "desc":
329
+ icon = /* @__PURE__ */ React2.createElement(ArrowDown, {
330
+ className: getSize2(3)
331
+ });
332
+ break;
333
+ }
334
+ return /* @__PURE__ */ React2.createElement("div", {
335
+ onClick,
336
+ className: "flex items-center cursor-pointer"
337
+ }, icon);
226
338
  };
227
339
 
228
340
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
229
341
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
230
342
  import { getCoreRowModel, getSortedRowModel, useReactTable, getGroupedRowModel, getExpandedRowModel } from "@tanstack/react-table";
231
343
  import { useVirtualizer } from "@tanstack/react-virtual";
232
- import React8, { Fragment, useCallback, useEffect, useState as useState2 } from "react";
344
+ import React8, { Fragment, useCallback as useCallback2, useEffect as useEffect2, useState as useState5 } from "react";
233
345
  import { log } from "@dxos/log";
234
346
  import { useDefaultValue, useOnTransition } from "@dxos/react-ui";
235
347
 
@@ -252,28 +364,28 @@ var useTableContext = () => {
252
364
  };
253
365
 
254
366
  // packages/ui/react-ui-table/src/theme.ts
255
- import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx2 } from "@dxos/react-ui-theme";
367
+ import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx3 } from "@dxos/react-ui-theme";
256
368
  var currentRow = "!bg-neutral-75 !dark:bg-neutral-850";
257
369
  var selectedRow = "!bg-primary-100 dark:!bg-primary-700";
258
370
  var flushPadding = "pli-0 plb-0";
259
371
  var textPadding = "pli-2 plb-0.5";
260
372
  var headPadding = "pli-2 plb-1";
261
373
  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);
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);
267
379
  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");
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");
269
381
  };
270
- var tbodyRoot = (_props, ...etc) => mx2(...etc);
271
- var tbodyTr = ({ canBeCurrent }, ...etc) => mx2("group", canBeCurrent ? ghostSelectedCurrent : ghostSelected, canBeCurrent && focusRing, canBeCurrent && "cursor-pointer rounded", ...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);
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);
277
389
 
278
390
  // packages/ui/react-ui-table/src/components/Cell/Cell.tsx
279
391
  import { useFocusableGroup } from "@fluentui/react-tabster";
@@ -318,11 +430,14 @@ var TableBody = ({ rows }) => {
318
430
  return /* @__PURE__ */ React5.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
319
431
  const isCurrent = currentDatum === row.original;
320
432
  const isSelected = rowSelection?.[row.id];
433
+ const isPinned = row.getIsPinned();
434
+ const classNames = tbodyTr({
435
+ canBeCurrent,
436
+ isPinned: isPinned !== false
437
+ });
321
438
  return /* @__PURE__ */ React5.createElement("tr", {
322
439
  key: keyAccessor ? keyAccessor(row.original) : row.id,
323
- className: tbodyTr({
324
- canBeCurrent
325
- }),
440
+ className: classNames,
326
441
  ...isCurrent && {
327
442
  "aria-current": "location"
328
443
  },
@@ -419,6 +534,42 @@ var TableHead = (_props) => {
419
534
  };
420
535
  TableHead.displayName = TABLE_HEAD_NAME;
421
536
 
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
+
422
573
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
423
574
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
424
575
  var Table = (props) => {
@@ -426,9 +577,9 @@ var Table = (props) => {
426
577
  const columns = useDefaultValue(props.columns, []);
427
578
  const data = useDefaultValue(props.data, []);
428
579
  const TableProvider2 = TableProvider;
429
- const [columnsInitialised, setColumnsInitialised] = useState2(false);
430
- const [columnSizing, setColumnSizing] = useState2({});
431
- useEffect(() => {
580
+ const [columnsInitialised, setColumnsInitialised] = useState5(false);
581
+ const [columnSizing, setColumnSizing] = useState5({});
582
+ useEffect2(() => {
432
583
  if (columnsInitialised) {
433
584
  return;
434
585
  }
@@ -441,8 +592,8 @@ var Table = (props) => {
441
592
  columns,
442
593
  setColumnSizing
443
594
  ]);
444
- const [columnSizingInfo, setColumnSizingInfo] = useState2({});
445
- const notifyColumnResize = useCallback(() => onColumnResize?.(columnSizing), [
595
+ const [columnSizingInfo, setColumnSizingInfo] = useState5({});
596
+ const notifyColumnResize = useCallback2(() => onColumnResize?.(columnSizing), [
446
597
  onColumnResize,
447
598
  columnSizing
448
599
  ]);
@@ -452,7 +603,7 @@ var Table = (props) => {
452
603
  onChange: props.onRowSelectionChange,
453
604
  defaultProp: props.defaultRowSelection
454
605
  });
455
- const handleRowSelectionChange = useCallback((updaterOrValue) => {
606
+ const handleRowSelectionChange = useCallback2((updaterOrValue) => {
456
607
  const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
457
608
  if (rowsSelectable === "multi") {
458
609
  setRowSelection(nextRowSelection);
@@ -469,8 +620,8 @@ var Table = (props) => {
469
620
  setRowSelection,
470
621
  rowSelection
471
622
  ]);
472
- const [grouping, handleGroupingChange] = useState2(props.grouping ?? []);
473
- useEffect(() => handleGroupingChange(props.grouping ?? []), [
623
+ const [grouping, handleGroupingChange] = useState5(props.grouping ?? []);
624
+ useEffect2(() => handleGroupingChange(props.grouping ?? []), [
474
625
  handleGroupingChange,
475
626
  props.grouping
476
627
  ]);
@@ -512,30 +663,19 @@ var Table = (props) => {
512
663
  // Debug
513
664
  debugTable: debug
514
665
  });
515
- useEffect(() => {
666
+ useEffect2(() => {
516
667
  onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
517
668
  }, [
518
669
  onDataSelectionChange,
519
670
  rowSelection,
520
671
  table
521
672
  ]);
522
- useEffect(() => {
523
- if (!pinLastRow) {
524
- return;
525
- }
526
- table.resetRowPinning();
527
- const rows = table.getRowModel().rows;
528
- rows[rows.length - 1].pin("bottom");
529
- }, [
530
- pinLastRow,
531
- table,
532
- data
533
- ]);
673
+ usePinLastRow(pinLastRow, table, data, getScrollElement);
534
674
  const expand = false;
535
675
  if (!getScrollElement) {
536
676
  log.warn("Table: getScrollElement is not set. This is required for virtualized tables.", void 0, {
537
677
  F: __dxlog_file,
538
- L: 168,
678
+ L: 159,
539
679
  S: void 0,
540
680
  C: (f, a) => f(...a)
541
681
  });
@@ -588,13 +728,9 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
588
728
  const { table } = useTableContext();
589
729
  const centerRows = table.getCenterRows();
590
730
  const pinnedRows = table.getBottomRows();
591
- const rows = [
592
- ...centerRows,
593
- ...pinnedRows
594
- ];
595
731
  const { getTotalSize, getVirtualItems } = useVirtualizer({
596
732
  getScrollElement,
597
- count: rows.length,
733
+ count: centerRows.length,
598
734
  overscan: 8,
599
735
  estimateSize: () => 40
600
736
  });
@@ -602,6 +738,10 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
602
738
  const totalSize = getTotalSize();
603
739
  const paddingTop = virtualRows.length > 0 ? virtualRows?.[0]?.start || 0 : 0;
604
740
  const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows?.[virtualRows.length - 1]?.end || 0) : 0;
741
+ const rowsToRender = [
742
+ ...virtualRows.map((virtualRow) => centerRows[virtualRow.index]),
743
+ ...pinnedRows
744
+ ];
605
745
  return /* @__PURE__ */ React8.createElement(React8.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React8.createElement("tbody", {
606
746
  role: "none"
607
747
  }, /* @__PURE__ */ React8.createElement("tr", {
@@ -612,7 +752,7 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
612
752
  },
613
753
  role: "none"
614
754
  }))), /* @__PURE__ */ React8.createElement(TableBody, {
615
- rows: virtualRows.map((virtualRow) => rows[virtualRow.index])
755
+ rows: rowsToRender
616
756
  }), paddingBottom > 0 && /* @__PURE__ */ React8.createElement("tbody", {
617
757
  role: "none"
618
758
  }, /* @__PURE__ */ React8.createElement("tr", {
@@ -641,11 +781,11 @@ var GroupedTableContent = () => {
641
781
  };
642
782
 
643
783
  // packages/ui/react-ui-table/src/components/Cell/CellCombobox.tsx
644
- import { CaretDown } from "@phosphor-icons/react";
645
- import React9, { useCallback as useCallback2, useState as useState3 } from "react";
784
+ import { CaretDown as CaretDown2 } from "@phosphor-icons/react";
785
+ import React9, { useCallback as useCallback3, useState as useState6 } from "react";
646
786
  import { Popover as Popover2, useTranslation as useTranslation2 } from "@dxos/react-ui";
647
787
  import { PopoverCombobox } from "@dxos/react-ui-searchlist";
648
- import { descriptionText, getSize as getSize3, mx as mx3, staticPlaceholderText } from "@dxos/react-ui-theme";
788
+ import { descriptionText, getSize as getSize3, mx as mx4, staticPlaceholderText } from "@dxos/react-ui-theme";
649
789
  var initialItems = (model, value) => value ? {
650
790
  [model.getId(value)]: {
651
791
  label: model.getText(value),
@@ -654,9 +794,9 @@ var initialItems = (model, value) => value ? {
654
794
  } : {};
655
795
  var CellCombobox = ({ model, value, onValueChange }) => {
656
796
  const { t } = useTranslation2(translationKey);
657
- const [items, setItems] = useState3(initialItems(model, value));
658
- const [loading, setLoading] = useState3(false);
659
- const [searchInputValue, setSearchInputValue] = useState3("");
797
+ const [items, setItems] = useState6(initialItems(model, value));
798
+ const [loading, setLoading] = useState6(false);
799
+ const [searchInputValue, setSearchInputValue] = useState6("");
660
800
  const handleSearchInputValueChange = async (text) => {
661
801
  setSearchInputValue(text ?? "");
662
802
  setLoading(true);
@@ -670,7 +810,7 @@ var CellCombobox = ({ model, value, onValueChange }) => {
670
810
  }, initialItems(model, value)));
671
811
  setLoading(false);
672
812
  };
673
- const handleValueChange = useCallback2((id) => {
813
+ const handleValueChange = useCallback3((id) => {
674
814
  onValueChange(items[id]?.data);
675
815
  }, [
676
816
  items,
@@ -682,8 +822,8 @@ var CellCombobox = ({ model, value, onValueChange }) => {
682
822
  variant: "ghost",
683
823
  classNames: "is-full rounded-none ring-inset"
684
824
  }, value ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement("span", {
685
- className: mx3("font-normal text-start text-base flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
686
- }, model.getText(value)), /* @__PURE__ */ React9.createElement(CaretDown, {
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, {
687
827
  weight: "bold",
688
828
  className: getSize3(3)
689
829
  })) : null), /* @__PURE__ */ React9.createElement(PopoverCombobox.Content, {
@@ -693,9 +833,9 @@ var CellCombobox = ({ model, value, onValueChange }) => {
693
833
  value: searchInputValue,
694
834
  onValueChange: handleSearchInputValueChange
695
835
  }), /* @__PURE__ */ React9.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React9.createElement("p", {
696
- className: mx3("text-center", descriptionText)
836
+ className: mx4("text-center", descriptionText)
697
837
  }, "Start typing to search") : loading ? /* @__PURE__ */ React9.createElement("p", {
698
- className: mx3("text-center", descriptionText)
838
+ className: mx4("text-center", descriptionText)
699
839
  }, "Searching\u2026") : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(PopoverCombobox.Empty, {
700
840
  classNames: [
701
841
  "text-center",
@@ -711,14 +851,14 @@ var CellCombobox = ({ model, value, onValueChange }) => {
711
851
 
712
852
  // packages/ui/react-ui-table/src/helpers.tsx
713
853
  import { useFocusFinders } from "@fluentui/react-tabster";
714
- import { Check as Check2, ClipboardText, X as X2 } from "@phosphor-icons/react";
854
+ import { Check as Check2, ClipboardText, X as X3 } from "@phosphor-icons/react";
715
855
  import { createColumnHelper } from "@tanstack/react-table";
716
856
  import { format } from "date-fns/format";
717
857
  import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
718
- import React10, { useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
858
+ import React10, { useEffect as useEffect3, useRef as useRef3, useState as useState7 } from "react";
719
859
  import { log as log2 } from "@dxos/log";
720
860
  import { Input as Input2, Tooltip } from "@dxos/react-ui";
721
- import { getSize as getSize4, mx as mx4 } from "@dxos/react-ui-theme";
861
+ import { getSize as getSize4, mx as mx5 } from "@dxos/react-ui-theme";
722
862
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/helpers.tsx";
723
863
  var createColumnBuilder = () => ({
724
864
  helper: createColumnHelper(),
@@ -733,11 +873,11 @@ var ComboboxBuilderCell = (cellContext) => {
733
873
  }) : null;
734
874
  };
735
875
  var StringBuilderCell = (cellContext) => {
736
- const ref = useRef2(null);
876
+ const ref = useRef3(null);
737
877
  const { findPrevFocusable } = useFocusFinders();
738
878
  const { onUpdate, cell } = cellContext.column.columnDef.meta;
739
879
  const initialValue = cellContext.getValue();
740
- const [value, setValue] = useState4(() => {
880
+ const [value, setValue] = useState7(() => {
741
881
  if (initialValue?.content) {
742
882
  return initialValue?.content;
743
883
  }
@@ -779,10 +919,10 @@ var displayNumber = (value, digits) => value || value === 0 ? value.toLocaleStri
779
919
  var NumberBuilderCell = (cellContext) => {
780
920
  const { onUpdate, digits } = cellContext.column.columnDef.meta;
781
921
  const value = cellContext.getValue();
782
- const [text, setText] = useState4(displayNumber(value, digits));
922
+ const [text, setText] = useState7(displayNumber(value, digits));
783
923
  const { findPrevFocusable } = useFocusFinders();
784
- const ref = useRef2(null);
785
- useEffect2(() => {
924
+ const ref = useRef3(null);
925
+ useEffect3(() => {
786
926
  (!document.activeElement || document.activeElement !== ref.current) && setText(displayNumber(value, digits));
787
927
  }, [
788
928
  digits,
@@ -869,7 +1009,7 @@ var ColumnBuilder = class {
869
1009
  cell: model && onUpdate ? ComboboxBuilderCell : (cellContext) => {
870
1010
  const cellValue = cellContext.getValue();
871
1011
  return /* @__PURE__ */ React10.createElement("div", {
872
- className: mx4("truncate", classNames)
1012
+ className: mx5("truncate", classNames)
873
1013
  }, cellValue ? model?.getText(cellValue) : "");
874
1014
  },
875
1015
  ...props,
@@ -900,7 +1040,7 @@ var ColumnBuilder = class {
900
1040
  value = value.content;
901
1041
  }
902
1042
  return /* @__PURE__ */ React10.createElement("div", {
903
- className: mx4("truncate", textPadding, classNames)
1043
+ className: mx5("truncate", textPadding, classNames)
904
1044
  }, value);
905
1045
  },
906
1046
  ...props,
@@ -929,7 +1069,6 @@ var ColumnBuilder = class {
929
1069
  onUpdate,
930
1070
  digits,
931
1071
  header: {
932
- classNames: "text-end",
933
1072
  ...props.meta?.header
934
1073
  },
935
1074
  cell: {
@@ -955,7 +1094,7 @@ var ColumnBuilder = class {
955
1094
  addSuffix: true
956
1095
  }) : value.toISOString() : void 0;
957
1096
  return /* @__PURE__ */ React10.createElement("div", {
958
- className: mx4(textPadding, classNames)
1097
+ className: mx5(textPadding, classNames)
959
1098
  }, str);
960
1099
  } catch (err) {
961
1100
  log2.info("formatError", {
@@ -1082,7 +1221,7 @@ var ColumnBuilder = class {
1082
1221
  */
1083
1222
  icon({ label, size, on, off, ...props } = {}) {
1084
1223
  const IconOn = on?.Icon ?? Check2;
1085
- const IconOff = off?.Icon ?? X2;
1224
+ const IconOff = off?.Icon ?? X3;
1086
1225
  return {
1087
1226
  size: size ?? 32,
1088
1227
  // TODO(Zan): Implement sort algorithm
@@ -1094,11 +1233,11 @@ var ColumnBuilder = class {
1094
1233
  const value = cell.getValue();
1095
1234
  if (value) {
1096
1235
  return /* @__PURE__ */ React10.createElement(IconOn, {
1097
- className: mx4("block mli-auto", getSize4(6), on?.className ?? "text-green-700")
1236
+ className: mx5("block mli-auto", getSize4(6), on?.className ?? "text-green-700")
1098
1237
  });
1099
1238
  } else if (value === false) {
1100
1239
  return /* @__PURE__ */ React10.createElement(IconOff, {
1101
- className: mx4("block mli-auto", getSize4(6), off?.className ?? "text-red-700")
1240
+ className: mx5("block mli-auto", getSize4(6), off?.className ?? "text-red-700")
1102
1241
  });
1103
1242
  } else {
1104
1243
  return null;
@@ -1107,13 +1246,44 @@ var ColumnBuilder = class {
1107
1246
  ...props
1108
1247
  };
1109
1248
  }
1249
+ /**
1250
+ * This display column type is for nested/unhandled data to appear as JSON.
1251
+ */
1252
+ display({ label, classNames, ...props } = {}) {
1253
+ return {
1254
+ size: 120,
1255
+ minSize: 120,
1256
+ header: (cell) => label ?? cell.header.id,
1257
+ cell: (cell) => {
1258
+ const value = cell.getValue();
1259
+ return /* @__PURE__ */ React10.createElement("div", {
1260
+ className: "overflow-scroll"
1261
+ }, /* @__PURE__ */ React10.createElement("code", {
1262
+ className: "text-xs"
1263
+ }, JSON.stringify(value)));
1264
+ },
1265
+ ...props,
1266
+ meta: {
1267
+ ...props.meta,
1268
+ cell: {
1269
+ ...props.meta?.cell,
1270
+ classNames: [
1271
+ "font-mono",
1272
+ textPadding,
1273
+ classNames
1274
+ ]
1275
+ }
1276
+ }
1277
+ };
1278
+ }
1110
1279
  };
1111
1280
  export {
1112
1281
  CellCombobox,
1113
1282
  ColumnBuilder,
1114
1283
  ColumnMenu,
1115
- ColumnPanel,
1284
+ ColumnSettingsPanel,
1116
1285
  MemoizedVirtualisedTableContent,
1286
+ SortIndicator,
1117
1287
  Table,
1118
1288
  createColumnBuilder,
1119
1289
  currentRow,