@dxos/react-ui-table 0.4.8-main.0602afb → 0.4.8-main.06fa7e4

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 (31) hide show
  1. package/dist/lib/browser/index.mjs +275 -191
  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/Cell/Cell.d.ts.map +1 -1
  5. package/dist/types/src/components/ColumnMenu.d.ts.map +1 -1
  6. package/dist/types/src/components/ColumnMenu.stories.d.ts +10 -1
  7. package/dist/types/src/components/ColumnMenu.stories.d.ts.map +1 -1
  8. package/dist/types/src/components/SortButton.d.ts +8 -0
  9. package/dist/types/src/components/SortButton.d.ts.map +1 -0
  10. package/dist/types/src/components/Table/Table.d.ts +2 -0
  11. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  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/Table/TableHead.d.ts.map +1 -1
  15. package/dist/types/src/components/Table/props.d.ts +1 -0
  16. package/dist/types/src/components/Table/props.d.ts.map +1 -1
  17. package/dist/types/src/helpers.d.ts.map +1 -1
  18. package/dist/types/src/theme.d.ts +1 -1
  19. package/dist/types/src/theme.d.ts.map +1 -1
  20. package/package.json +15 -15
  21. package/src/components/Cell/Cell.tsx +4 -1
  22. package/src/components/ColumnMenu.stories.tsx +13 -6
  23. package/src/components/ColumnMenu.tsx +13 -4
  24. package/src/components/SortButton.tsx +34 -0
  25. package/src/components/Table/Table.stories.tsx +53 -64
  26. package/src/components/Table/Table.tsx +65 -41
  27. package/src/components/Table/TableBody.tsx +1 -0
  28. package/src/components/Table/TableHead.tsx +4 -2
  29. package/src/components/Table/props.ts +1 -0
  30. package/src/helpers.tsx +61 -45
  31. package/src/theme.ts +3 -1
@@ -1,10 +1,40 @@
1
1
  // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
2
- import { Check, CaretDown, Trash, X } from "@phosphor-icons/react";
3
- import React, { useRef, useState } from "react";
4
- import { Button, DensityProvider, Input, Popover, Select, Separator, useTranslation } from "@dxos/react-ui";
5
- import { getSize, mx } from "@dxos/react-ui-theme";
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
6
  import { safeParseInt } from "@dxos/util";
7
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
+
8
38
  // packages/ui/react-ui-table/src/translations.ts
9
39
  var translationKey = "table";
10
40
  var translations_default = [
@@ -31,19 +61,26 @@ var translations_default = [
31
61
  // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
32
62
  var ColumnMenu = ({ column, ...props }) => {
33
63
  const title = column.label?.length ? column.label : column.id;
34
- return /* @__PURE__ */ React.createElement("div", {
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", {
35
69
  className: "flex items-center gap-2"
36
- }, /* @__PURE__ */ React.createElement("div", {
70
+ }, /* @__PURE__ */ React2.createElement("div", {
37
71
  className: "flex-1 min-is-0 truncate",
38
72
  title
39
- }, title), /* @__PURE__ */ React.createElement("div", {
40
- className: "flex shrink-0"
41
- }, /* @__PURE__ */ React.createElement(ColumnPanel, {
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, {
42
79
  ...props,
43
80
  column
44
81
  })));
45
82
  };
46
- var Section = ({ children, className }) => /* @__PURE__ */ React.createElement("div", {
83
+ var Section = ({ children, className }) => /* @__PURE__ */ React2.createElement("div", {
47
84
  role: "none",
48
85
  className: mx("p-2", className)
49
86
  }, children);
@@ -84,123 +121,122 @@ var ColumnPanel = ({ context, tableDefs, tableDef, column, onUpdate, onDelete })
84
121
  });
85
122
  setOpen(false);
86
123
  };
87
- return /* @__PURE__ */ React.createElement(Popover.Root, {
124
+ return /* @__PURE__ */ React2.createElement(Popover.Root, {
88
125
  open,
89
126
  onOpenChange: (nextOpen) => setOpen(nextOpen)
90
- }, /* @__PURE__ */ React.createElement(Popover.Trigger, {
127
+ }, /* @__PURE__ */ React2.createElement(Popover.Trigger, {
91
128
  asChild: true
92
- }, /* @__PURE__ */ React.createElement(Button, {
93
- variant: "ghost",
94
- classNames: "p-1"
95
- }, /* @__PURE__ */ React.createElement(CaretDown, {
96
- className: getSize(4)
97
- }))), /* @__PURE__ */ React.createElement(Popover.Portal, null, /* @__PURE__ */ React.createElement(Popover.Content, null, /* @__PURE__ */ React.createElement(Popover.Viewport, {
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, {
98
134
  classNames: "w-60"
99
- }, /* @__PURE__ */ React.createElement(DensityProvider, {
135
+ }, /* @__PURE__ */ React2.createElement(DensityProvider, {
100
136
  density: "fine"
101
- }, /* @__PURE__ */ React.createElement("div", {
137
+ }, /* @__PURE__ */ React2.createElement("div", {
102
138
  className: "flex flex-col gap-1"
103
- }, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
139
+ }, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
104
140
  classNames: "mbe-1"
105
- }, t("column label label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
141
+ }, t("column label label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
106
142
  placeholder: "Column label",
107
143
  value: label ?? "",
108
144
  onChange: (event) => setLabel(event.target.value),
109
145
  autoFocus: true
110
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
146
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
111
147
  classNames: "mbe-1 mbs-3"
112
- }, t("property key label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
148
+ }, t("property key label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
113
149
  ref: propRef,
114
150
  placeholder: "Property key",
115
151
  // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.
116
152
  value: prop ?? "",
117
153
  onChange: (event) => setProp(event.target.value.replace(/[^\w_]/g, ""))
118
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
154
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
119
155
  classNames: "mbe-1 mbs-3"
120
- }, t("column type label")), /* @__PURE__ */ React.createElement(Select.Root, {
156
+ }, t("column type label")), /* @__PURE__ */ React2.createElement(Select.Root, {
121
157
  value: type,
122
158
  onValueChange: setType
123
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
159
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
124
160
  placeholder: "Type",
125
161
  classNames: "is-full"
126
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, [
162
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, [
127
163
  "number",
128
164
  "boolean",
129
165
  "string",
130
166
  "ref"
131
- ].map((type2) => /* @__PURE__ */ React.createElement(Select.Option, {
167
+ ].map((type2) => /* @__PURE__ */ React2.createElement(Select.Option, {
132
168
  key: type2,
133
169
  value: type2
134
- }, 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, {
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, {
135
171
  classNames: "mbe-1 mbs-3"
136
- }, t("digits label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
172
+ }, t("digits label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
137
173
  value: digits ?? "",
138
174
  onChange: (event) => setDigits(event.target.value)
139
- })))), type === "ref" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
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, {
140
176
  classNames: "mbe-1 mbs-3"
141
- }, "Table"), /* @__PURE__ */ React.createElement(Select.Root, {
177
+ }, "Table"), /* @__PURE__ */ React2.createElement(Select.Root, {
142
178
  value: refTable,
143
179
  onValueChange: setRefTable
144
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
180
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
145
181
  placeholder: "Table",
146
182
  classNames: "is-full"
147
- }), /* @__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, {
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, {
148
184
  key: id,
149
185
  value: id
150
- }, name ?? id))))))), refTable && /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
186
+ }, name ?? id))))))), refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
151
187
  classNames: "mbe-1 mbs-3"
152
- }, "Table property"), /* @__PURE__ */ React.createElement(Select.Root, {
188
+ }, "Table property"), /* @__PURE__ */ React2.createElement(Select.Root, {
153
189
  value: refProp,
154
190
  onValueChange: setRefProp
155
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
191
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
156
192
  placeholder: "Property",
157
193
  classNames: "is-full"
158
- }), /* @__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, {
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, {
159
195
  key: id,
160
196
  value: id
161
- }, label2 ?? id))))))))), /* @__PURE__ */ React.createElement(Separator, {
197
+ }, label2 ?? id))))))))), /* @__PURE__ */ React2.createElement(Separator, {
162
198
  classNames: "mli-2"
163
- }), /* @__PURE__ */ React.createElement(Section, {
199
+ }), /* @__PURE__ */ React2.createElement(Section, {
164
200
  className: "space-b-1.5"
165
- }, /* @__PURE__ */ React.createElement(Button, {
201
+ }, /* @__PURE__ */ React2.createElement(Button2, {
166
202
  variant: "primary",
167
203
  classNames: "is-full flex gap-2",
168
204
  onClick: handleSave
169
- }, /* @__PURE__ */ React.createElement("span", null, t("save label")), /* @__PURE__ */ React.createElement("div", {
205
+ }, /* @__PURE__ */ React2.createElement("span", null, t("save label")), /* @__PURE__ */ React2.createElement("div", {
170
206
  className: "grow"
171
- }), /* @__PURE__ */ React.createElement(Check, {
172
- className: getSize(5)
173
- })), /* @__PURE__ */ React.createElement(Button, {
207
+ }), /* @__PURE__ */ React2.createElement(Check, {
208
+ className: getSize2(5)
209
+ })), /* @__PURE__ */ React2.createElement(Button2, {
174
210
  classNames: "is-full flex gap-2",
175
211
  onClick: handleCancel
176
- }, /* @__PURE__ */ React.createElement("span", null, t("cancel label", {
212
+ }, /* @__PURE__ */ React2.createElement("span", null, t("cancel label", {
177
213
  ns: "os"
178
- })), /* @__PURE__ */ React.createElement("div", {
214
+ })), /* @__PURE__ */ React2.createElement("div", {
179
215
  className: "grow"
180
- }), /* @__PURE__ */ React.createElement(X, {
181
- className: getSize(5)
182
- })), /* @__PURE__ */ React.createElement(Button, {
216
+ }), /* @__PURE__ */ React2.createElement(X, {
217
+ className: getSize2(5)
218
+ })), /* @__PURE__ */ React2.createElement(Button2, {
183
219
  classNames: "is-full flex gap-2",
184
220
  onClick: () => onDelete?.(column.id)
185
- }, /* @__PURE__ */ React.createElement("span", null, t("delete label")), /* @__PURE__ */ React.createElement("div", {
221
+ }, /* @__PURE__ */ React2.createElement("span", null, t("delete label")), /* @__PURE__ */ React2.createElement("div", {
186
222
  className: "grow"
187
- }), /* @__PURE__ */ React.createElement(Trash, {
188
- className: getSize(5)
189
- })))))), /* @__PURE__ */ React.createElement(Popover.Arrow, null))));
223
+ }), /* @__PURE__ */ React2.createElement(Trash, {
224
+ className: getSize2(5)
225
+ })))))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
190
226
  };
191
227
 
192
228
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
193
229
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
194
- import { getCoreRowModel, useReactTable, getGroupedRowModel } from "@tanstack/react-table";
230
+ import { getCoreRowModel, getSortedRowModel, useReactTable, getGroupedRowModel, getExpandedRowModel } from "@tanstack/react-table";
195
231
  import { useVirtualizer } from "@tanstack/react-virtual";
196
- import React6, { Fragment, useCallback, useEffect, useState as useState2 } from "react";
197
- import { debounce } from "@dxos/async";
232
+ import React7, { Fragment, useCallback, useEffect, useState as useState2 } from "react";
198
233
  import { log } from "@dxos/log";
234
+ import { useDefaultValue, useOnTransition } from "@dxos/react-ui";
199
235
 
200
236
  // packages/ui/react-ui-table/src/components/Table/TableBody.tsx
201
237
  import { useArrowNavigationGroup } from "@fluentui/react-tabster";
202
238
  import { flexRender } from "@tanstack/react-table";
203
- import React3 from "react";
239
+ import React4 from "react";
204
240
 
205
241
  // packages/ui/react-ui-table/src/components/Table/TableContext.tsx
206
242
  import { createContext } from "@radix-ui/react-context";
@@ -215,7 +251,7 @@ var selectedRow = "!bg-primary-100 dark:!bg-primary-700";
215
251
  var flushPadding = "pli-0 plb-0";
216
252
  var textPadding = "pli-2 plb-0.5";
217
253
  var headPadding = "pli-2 plb-1.5";
218
- var gridCellFocusRing = "focus:z-[11] focus:outline outline-2 outline-primary-500 dark:outline-primary-400";
254
+ var gridCellFocusRing = "focus-within:z-[11] focus-within:outline outline-2 outline-primary-500 dark:outline-primary-400";
219
255
  var tableRoot = ({ fullWidth }, ...etc) => mx2("table-fixed", fullWidth && "is-full", ...etc);
220
256
  var groupTh = (_props, ...etc) => mx2("text-start font-medium", flushPadding, ...etc);
221
257
  var theadRoot = ({ header, stickyHeader }, ...etc) => mx2(header ? stickyHeader && "sticky block-start-[--sticky-top] z-[1]" : "collapse", header && fixedSurface, ...etc);
@@ -233,29 +269,30 @@ var tfootTh = ({ border }, ...etc) => mx2(textPadding, modalSurface, border && g
233
269
 
234
270
  // packages/ui/react-ui-table/src/components/Cell/Cell.tsx
235
271
  import { useFocusableGroup } from "@fluentui/react-tabster";
236
- import React2 from "react";
272
+ import React3 from "react";
237
273
  var CELL_NAME = "Cell";
238
274
  var FocusableCell = ({ cell, children }) => {
239
275
  const tableContext = useTableContext(CELL_NAME);
240
276
  const domAttributes = useFocusableGroup({
241
277
  tabBehavior: "limited"
242
278
  });
243
- return /* @__PURE__ */ React2.createElement("td", {
279
+ const className = tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames);
280
+ return /* @__PURE__ */ React3.createElement("td", {
244
281
  tabIndex: 0,
245
282
  ...domAttributes,
246
- className: tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames)
283
+ className
247
284
  }, children);
248
285
  };
249
286
  var StaticCell = ({ cell, children }) => {
250
287
  const tableContext = useTableContext(CELL_NAME);
251
- return /* @__PURE__ */ React2.createElement("td", {
288
+ return /* @__PURE__ */ React3.createElement("td", {
252
289
  className: tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames)
253
290
  }, children);
254
291
  };
255
292
  var Cell = ({ cell, children }) => {
256
293
  const { isGrid } = useTableContext(CELL_NAME);
257
294
  const Root = isGrid ? FocusableCell : StaticCell;
258
- return /* @__PURE__ */ React2.createElement(Root, {
295
+ return /* @__PURE__ */ React3.createElement(Root, {
259
296
  cell
260
297
  }, children);
261
298
  };
@@ -270,10 +307,10 @@ var TableBody = ({ rows }) => {
270
307
  axis: "grid"
271
308
  });
272
309
  const canBeCurrent = !isGrid && !!onDatumClick;
273
- return /* @__PURE__ */ React3.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
310
+ return /* @__PURE__ */ React4.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
274
311
  const isCurrent = currentDatum === row.original;
275
312
  const isSelected = rowSelection?.[row.id];
276
- return /* @__PURE__ */ React3.createElement("tr", {
313
+ return /* @__PURE__ */ React4.createElement("tr", {
277
314
  key: keyAccessor ? keyAccessor(row.original) : row.id,
278
315
  className: tbodyTr({
279
316
  canBeCurrent
@@ -295,82 +332,83 @@ var TableBody = ({ rows }) => {
295
332
  }
296
333
  }
297
334
  }
298
- }, debug && /* @__PURE__ */ React3.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
299
- return /* @__PURE__ */ React3.createElement(Cell, {
335
+ }, debug && /* @__PURE__ */ React4.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
336
+ return /* @__PURE__ */ React4.createElement(Cell, {
300
337
  key: cell.id,
301
338
  cell
302
339
  }, flexRender(cell.column.columnDef.cell, {
303
340
  className: "pli-2",
304
341
  ...cell.getContext()
305
342
  }));
306
- }), expand && /* @__PURE__ */ React3.createElement("td", null));
343
+ }), expand && /* @__PURE__ */ React4.createElement("td", null));
307
344
  }));
308
345
  };
309
346
  TableBody.displayName = TABLE_BODY_NAME;
310
347
 
311
348
  // packages/ui/react-ui-table/src/components/Table/TableFooter.tsx
312
349
  import { flexRender as flexRender2 } from "@tanstack/react-table";
313
- import React4 from "react";
350
+ import React5 from "react";
314
351
  var TABLE_FOOT_NAME = "TableFooter";
315
352
  var TableFooter = (props) => {
316
353
  const tableContext = useTableContext(TABLE_FOOT_NAME);
317
354
  const { table, expand, debug } = tableContext;
318
355
  const footers = table.getFooterGroups();
319
- return /* @__PURE__ */ React4.createElement("tfoot", {
356
+ return /* @__PURE__ */ React5.createElement("tfoot", {
320
357
  className: tfootRoot(props)
321
- }, footers.map((footerGroup) => /* @__PURE__ */ React4.createElement("tr", {
358
+ }, footers.map((footerGroup) => /* @__PURE__ */ React5.createElement("tr", {
322
359
  key: footerGroup.id,
323
360
  className: tfootTr(tableContext)
324
- }, debug && /* @__PURE__ */ React4.createElement("th", null), footerGroup.headers.map((footer) => {
325
- return /* @__PURE__ */ React4.createElement("th", {
361
+ }, debug && /* @__PURE__ */ React5.createElement("th", null), footerGroup.headers.map((footer) => {
362
+ return /* @__PURE__ */ React5.createElement("th", {
326
363
  key: footer.id,
327
364
  className: tfootTh(tableContext, footer.column.columnDef.meta?.footer?.classNames)
328
365
  }, footer.isPlaceholder ? null : flexRender2(footer.column.columnDef.footer, footer.getContext()));
329
- }), expand && /* @__PURE__ */ React4.createElement("th", null))));
366
+ }), expand && /* @__PURE__ */ React5.createElement("th", null))));
330
367
  };
331
368
  TableFooter.displayName = TABLE_FOOT_NAME;
332
369
 
333
370
  // packages/ui/react-ui-table/src/components/Table/TableHead.tsx
334
371
  import { flexRender as flexRender3 } from "@tanstack/react-table";
335
- import React5 from "react";
372
+ import React6 from "react";
336
373
  import { mx as mx3 } from "@dxos/react-ui-theme";
337
374
  var TABLE_HEAD_NAME = "TableHeader";
338
375
  var TableHead = (_props) => {
339
376
  const tableContext = useTableContext(TABLE_HEAD_NAME);
340
377
  const headerGroups = tableContext.table.getHeaderGroups();
341
378
  const state = tableContext.table.getState();
342
- return /* @__PURE__ */ React5.createElement("thead", {
379
+ return /* @__PURE__ */ React6.createElement("thead", {
343
380
  className: theadRoot(tableContext)
344
381
  }, headerGroups.map((headerGroup) => {
345
382
  return (
346
383
  // Group element to hover resize handles.
347
- /* @__PURE__ */ React5.createElement("tr", {
384
+ /* @__PURE__ */ React6.createElement("tr", {
348
385
  key: headerGroup.id,
349
386
  className: theadTr(tableContext)
350
- }, tableContext.debug && /* @__PURE__ */ React5.createElement("th", {
387
+ }, tableContext.debug && /* @__PURE__ */ React6.createElement("th", {
351
388
  className: "font-mono",
352
389
  style: {
353
390
  width: 32
354
391
  }
355
392
  }, "#"), headerGroup.headers.map((header) => {
356
393
  const isResizing = header.column.getIsResizing();
357
- return /* @__PURE__ */ React5.createElement("th", {
394
+ const resizeHandler = header.getResizeHandler();
395
+ return /* @__PURE__ */ React6.createElement("th", {
358
396
  key: header.id,
359
397
  style: {
360
398
  width: header.getSize()
361
399
  },
362
400
  className: theadTh(tableContext, header.column.columnDef.meta?.header?.classNames)
363
- }, !header || header.isPlaceholder ? null : flexRender3(header.column.columnDef.header, header.getContext()), header.column.columnDef.meta?.resizable && /* @__PURE__ */ React5.createElement("div", {
401
+ }, !header || header.isPlaceholder ? null : flexRender3(header.column.columnDef.header, header.getContext()), header.column.columnDef.meta?.resizable && /* @__PURE__ */ React6.createElement("div", {
364
402
  className: theadResizeRoot(tableContext, isResizing && "hidden"),
365
403
  style: {
366
404
  transform: `translateX(${isResizing ? state.columnSizingInfo.deltaOffset : 0}px)`
367
405
  },
368
- onMouseDown: header.getResizeHandler(),
369
- onTouchStart: header.getResizeHandler()
370
- }, /* @__PURE__ */ React5.createElement("div", {
406
+ onMouseDown: resizeHandler,
407
+ onTouchStart: resizeHandler
408
+ }, /* @__PURE__ */ React6.createElement("div", {
371
409
  className: mx3(theadResizeThumb(tableContext))
372
410
  })));
373
- }), tableContext.expand && /* @__PURE__ */ React5.createElement("th", null))
411
+ }), tableContext.expand && /* @__PURE__ */ React6.createElement("th", null))
374
412
  );
375
413
  }));
376
414
  };
@@ -379,37 +417,36 @@ TableHead.displayName = TABLE_HEAD_NAME;
379
417
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
380
418
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
381
419
  var Table = (props) => {
382
- const { role, data = [], columns = [], onColumnResize, columnVisibility, header = true, rowsSelectable, debug, onDataSelectionChange, getScrollElement } = props;
420
+ const { role, onColumnResize, columnVisibility, header = true, rowsSelectable, debug, onDataSelectionChange, getScrollElement, pinLastRow } = props;
421
+ const columns = useDefaultValue(props.columns, []);
422
+ const data = useDefaultValue(props.data, []);
383
423
  const TableProvider2 = TableProvider;
424
+ const [columnsInitialised, setColumnsInitialised] = useState2(false);
384
425
  const [columnSizing, setColumnSizing] = useState2({});
385
426
  useEffect(() => {
427
+ if (columnsInitialised) {
428
+ return;
429
+ }
386
430
  setColumnSizing(columns.filter((column) => !!column.size && column.prop !== void 0).reduce((state, column) => {
387
431
  state[column.prop] = column.size;
388
432
  return state;
389
433
  }, {}));
434
+ setColumnsInitialised(true);
390
435
  }, [
391
- columns
436
+ columns,
437
+ setColumnSizing
392
438
  ]);
393
439
  const [columnSizingInfo, setColumnSizingInfo] = useState2({});
394
- const onColumnResizeDebounced = onColumnResize && debounce(onColumnResize, 1e3);
395
- useEffect(() => {
396
- if (columnSizingInfo.columnSizingStart?.length === 0) {
397
- onColumnResizeDebounced?.(table.getState().columnSizing);
398
- }
399
- }, [
400
- columnSizingInfo
440
+ const notifyColumnResize = useCallback(() => onColumnResize?.(columnSizing), [
441
+ onColumnResize,
442
+ columnSizing
401
443
  ]);
444
+ useOnTransition(columnSizingInfo.isResizingColumn, (v) => typeof v === "string", false, notifyColumnResize);
402
445
  const [rowSelection = {}, setRowSelection] = useControllableState({
403
446
  prop: props.rowSelection,
404
447
  onChange: props.onRowSelectionChange,
405
448
  defaultProp: props.defaultRowSelection
406
449
  });
407
- useEffect(() => {
408
- onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
409
- }, [
410
- onDataSelectionChange,
411
- rowSelection
412
- ]);
413
450
  const handleRowSelectionChange = useCallback((updaterOrValue) => {
414
451
  const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
415
452
  if (rowsSelectable === "multi") {
@@ -423,11 +460,13 @@ var Table = (props) => {
423
460
  setRowSelection({});
424
461
  }
425
462
  }, [
426
- rowSelection,
427
- setRowSelection
463
+ rowsSelectable,
464
+ setRowSelection,
465
+ rowSelection
428
466
  ]);
429
467
  const [grouping, handleGroupingChange] = useState2(props.grouping ?? []);
430
468
  useEffect(() => handleGroupingChange(props.grouping ?? []), [
469
+ handleGroupingChange,
431
470
  props.grouping
432
471
  ]);
433
472
  const table = useReactTable({
@@ -455,35 +494,54 @@ var Table = (props) => {
455
494
  onColumnSizingInfoChange: setColumnSizingInfo,
456
495
  // Rows
457
496
  getCoreRowModel: getCoreRowModel(),
497
+ getSortedRowModel: getSortedRowModel(),
498
+ getExpandedRowModel: getExpandedRowModel(),
458
499
  // Grouping
459
500
  getGroupedRowModel: grouping.length > 1 ? getGroupedRowModel() : void 0,
460
501
  onGroupingChange: handleGroupingChange,
461
- // Selection
462
- ...rowsSelectable === "multi" ? {
463
- enableMultiRowSelection: true
464
- } : rowsSelectable ? {
465
- enableRowSelection: true
466
- } : {},
502
+ enableMultiRowSelection: rowsSelectable === "multi" ? true : void 0,
503
+ enableRowSelection: rowsSelectable === true ? true : void 0,
467
504
  onRowSelectionChange: handleRowSelectionChange,
505
+ enableSorting: true,
506
+ enableColumnPinning: true,
468
507
  // Debug
469
508
  debugTable: debug
470
509
  });
510
+ useEffect(() => {
511
+ onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
512
+ }, [
513
+ onDataSelectionChange,
514
+ rowSelection,
515
+ table
516
+ ]);
517
+ useEffect(() => {
518
+ if (!pinLastRow) {
519
+ return;
520
+ }
521
+ table.resetRowPinning();
522
+ const rows = table.getRowModel().rows;
523
+ rows[rows.length - 1].pin("bottom");
524
+ }, [
525
+ pinLastRow,
526
+ table,
527
+ data
528
+ ]);
471
529
  const expand = false;
472
530
  if (!getScrollElement) {
473
531
  log.warn("Table: getScrollElement is not set. This is required for virtualized tables.", void 0, {
474
532
  F: __dxlog_file,
475
- L: 159,
533
+ L: 168,
476
534
  S: void 0,
477
535
  C: (f, a) => f(...a)
478
536
  });
479
537
  }
480
- return /* @__PURE__ */ React6.createElement(TableProvider2, {
538
+ return /* @__PURE__ */ React7.createElement(TableProvider2, {
481
539
  ...props,
482
540
  table,
483
541
  header,
484
542
  expand,
485
543
  isGrid: role === "grid" || role === "treegrid"
486
- }, /* @__PURE__ */ React6.createElement(TableImpl, {
544
+ }, /* @__PURE__ */ React7.createElement(TableImpl, {
487
545
  debug: false,
488
546
  getScrollElement,
489
547
  ...props
@@ -492,13 +550,19 @@ var Table = (props) => {
492
550
  var TableImpl = (props) => {
493
551
  const { debug, classNames, getScrollElement, role, footer, grouping, fullWidth } = props;
494
552
  const { table } = useTableContext("TableImpl");
495
- const { rows } = table.getRowModel();
553
+ const centerRows = table.getCenterRows();
554
+ const bottomRows = table.getBottomRows();
555
+ const rows = [
556
+ ...centerRows,
557
+ ...bottomRows
558
+ ];
496
559
  if (debug) {
497
- return /* @__PURE__ */ React6.createElement("pre", {
560
+ return /* @__PURE__ */ React7.createElement("pre", {
498
561
  className: "font-mono text-xs text-neutral-500 m-1 p-2 ring"
499
- }, /* @__PURE__ */ React6.createElement("code", null, JSON.stringify(table.getState(), void 0, 2)));
562
+ }, /* @__PURE__ */ React7.createElement("code", null, JSON.stringify(table.getState(), void 0, 2)));
500
563
  }
501
- return /* @__PURE__ */ React6.createElement("table", {
564
+ const isResizingColumn = table.getState().columnSizingInfo.isResizingColumn;
565
+ return /* @__PURE__ */ React7.createElement("table", {
502
566
  role,
503
567
  className: tableRoot(props, classNames),
504
568
  ...!fullWidth && {
@@ -506,15 +570,22 @@ var TableImpl = (props) => {
506
570
  width: table.getTotalSize()
507
571
  }
508
572
  }
509
- }, /* @__PURE__ */ React6.createElement(TableHead, null), grouping?.length !== 0 ? getScrollElement ? /* @__PURE__ */ React6.createElement(VirtualizedTableContent, {
573
+ }, /* @__PURE__ */ React7.createElement(TableHead, null), grouping?.length !== 0 ? getScrollElement ? isResizingColumn ? /* @__PURE__ */ React7.createElement(MemoizedVirtualisedTableContent, {
510
574
  getScrollElement
511
- }) : /* @__PURE__ */ React6.createElement(TableBody, {
575
+ }) : /* @__PURE__ */ React7.createElement(VirtualizedTableContent, {
576
+ getScrollElement
577
+ }) : /* @__PURE__ */ React7.createElement(TableBody, {
512
578
  rows
513
- }) : /* @__PURE__ */ React6.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React6.createElement(TableFooter, null));
579
+ }) : /* @__PURE__ */ React7.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React7.createElement(TableFooter, null));
514
580
  };
515
581
  var VirtualizedTableContent = ({ getScrollElement }) => {
516
- const { table: { getRowModel } } = useTableContext("VirtualizedTableContent");
517
- const rows = getRowModel().rows;
582
+ const { table } = useTableContext("VirtualizedTableContent");
583
+ const centerRows = table.getCenterRows();
584
+ const pinnedRows = table.getBottomRows();
585
+ const rows = [
586
+ ...centerRows,
587
+ ...pinnedRows
588
+ ];
518
589
  const { getTotalSize, getVirtualItems } = useVirtualizer({
519
590
  getScrollElement,
520
591
  count: rows.length,
@@ -525,49 +596,50 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
525
596
  const totalSize = getTotalSize();
526
597
  const paddingTop = virtualRows.length > 0 ? virtualRows?.[0]?.start || 0 : 0;
527
598
  const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows?.[virtualRows.length - 1]?.end || 0) : 0;
528
- return /* @__PURE__ */ React6.createElement(React6.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React6.createElement("tbody", {
599
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React7.createElement("tbody", {
529
600
  role: "none"
530
- }, /* @__PURE__ */ React6.createElement("tr", {
601
+ }, /* @__PURE__ */ React7.createElement("tr", {
531
602
  role: "none"
532
- }, /* @__PURE__ */ React6.createElement("td", {
603
+ }, /* @__PURE__ */ React7.createElement("td", {
533
604
  style: {
534
605
  height: `${paddingTop}px`
535
606
  },
536
607
  role: "none"
537
- }))), /* @__PURE__ */ React6.createElement(TableBody, {
608
+ }))), /* @__PURE__ */ React7.createElement(TableBody, {
538
609
  rows: virtualRows.map((virtualRow) => rows[virtualRow.index])
539
- }), paddingBottom > 0 && /* @__PURE__ */ React6.createElement("tbody", {
610
+ }), paddingBottom > 0 && /* @__PURE__ */ React7.createElement("tbody", {
540
611
  role: "none"
541
- }, /* @__PURE__ */ React6.createElement("tr", {
612
+ }, /* @__PURE__ */ React7.createElement("tr", {
542
613
  role: "none"
543
- }, /* @__PURE__ */ React6.createElement("td", {
614
+ }, /* @__PURE__ */ React7.createElement("td", {
544
615
  style: {
545
616
  height: `${paddingBottom}px`
546
617
  },
547
618
  role: "none"
548
619
  }))));
549
620
  };
621
+ var MemoizedVirtualisedTableContent = /* @__PURE__ */ React7.memo(VirtualizedTableContent);
550
622
  var GroupedTableContent = () => {
551
623
  const { table: { getGroupedRowModel: getGroupedRowModel2, getHeaderGroups, getState }, debug } = useTableContext("GroupedTableContent");
552
- return /* @__PURE__ */ React6.createElement(React6.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
553
- return /* @__PURE__ */ React6.createElement(Fragment, {
624
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
625
+ return /* @__PURE__ */ React7.createElement(Fragment, {
554
626
  key: i
555
- }, /* @__PURE__ */ React6.createElement("thead", null, /* @__PURE__ */ React6.createElement("tr", null, debug && /* @__PURE__ */ React6.createElement("th", null), /* @__PURE__ */ React6.createElement("th", {
627
+ }, /* @__PURE__ */ React7.createElement("thead", null, /* @__PURE__ */ React7.createElement("tr", null, debug && /* @__PURE__ */ React7.createElement("th", null), /* @__PURE__ */ React7.createElement("th", {
556
628
  // TODO(burdon): Calculate row span.
557
629
  colSpan: getHeaderGroups()[0].headers.length,
558
630
  className: groupTh({})
559
- }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React6.createElement(TableBody, {
631
+ }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React7.createElement(TableBody, {
560
632
  rows: row.subRows
561
633
  }));
562
634
  }));
563
635
  };
564
636
 
565
637
  // packages/ui/react-ui-table/src/components/Cell/CellCombobox.tsx
566
- import { CaretDown as CaretDown2 } from "@phosphor-icons/react";
567
- import React7, { useCallback as useCallback2, useState as useState3 } from "react";
638
+ import { CaretDown } from "@phosphor-icons/react";
639
+ import React8, { useCallback as useCallback2, useState as useState3 } from "react";
568
640
  import { Popover as Popover2, useTranslation as useTranslation2 } from "@dxos/react-ui";
569
641
  import { PopoverCombobox } from "@dxos/react-ui-searchlist";
570
- import { descriptionText, getSize as getSize2, mx as mx4, staticPlaceholderText } from "@dxos/react-ui-theme";
642
+ import { descriptionText, getSize as getSize3, mx as mx4, staticPlaceholderText } from "@dxos/react-ui-theme";
571
643
  var initialItems = (model, value) => value ? {
572
644
  [model.getId(value)]: {
573
645
  label: model.getText(value),
@@ -598,37 +670,37 @@ var CellCombobox = ({ model, value, onValueChange }) => {
598
670
  items,
599
671
  onValueChange
600
672
  ]);
601
- return /* @__PURE__ */ React7.createElement(PopoverCombobox.Root, {
673
+ return /* @__PURE__ */ React8.createElement(PopoverCombobox.Root, {
602
674
  placeholder: t("no selection label")
603
- }, /* @__PURE__ */ React7.createElement(PopoverCombobox.Trigger, {
675
+ }, /* @__PURE__ */ React8.createElement(PopoverCombobox.Trigger, {
604
676
  variant: "ghost",
605
677
  classNames: "is-full rounded-none ring-inset"
606
- }, value ? /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement("span", {
678
+ }, value ? /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("span", {
607
679
  className: mx4("font-normal text-start text-base flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
608
- }, model.getText(value)), /* @__PURE__ */ React7.createElement(CaretDown2, {
680
+ }, model.getText(value)), /* @__PURE__ */ React8.createElement(CaretDown, {
609
681
  weight: "bold",
610
- className: getSize2(3)
611
- })) : null), /* @__PURE__ */ React7.createElement(PopoverCombobox.Content, {
682
+ className: getSize3(3)
683
+ })) : null), /* @__PURE__ */ React8.createElement(PopoverCombobox.Content, {
612
684
  shouldFilter: false,
613
685
  classNames: "is-[--radix-popover-trigger-width]"
614
- }, /* @__PURE__ */ React7.createElement(PopoverCombobox.Input, {
686
+ }, /* @__PURE__ */ React8.createElement(PopoverCombobox.Input, {
615
687
  value: searchInputValue,
616
688
  onValueChange: handleSearchInputValueChange
617
- }), /* @__PURE__ */ React7.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React7.createElement("p", {
689
+ }), /* @__PURE__ */ React8.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React8.createElement("p", {
618
690
  className: mx4("text-center", descriptionText)
619
- }, "Start typing to search") : loading ? /* @__PURE__ */ React7.createElement("p", {
691
+ }, "Start typing to search") : loading ? /* @__PURE__ */ React8.createElement("p", {
620
692
  className: mx4("text-center", descriptionText)
621
- }, "Searching\u2026") : /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(PopoverCombobox.Empty, {
693
+ }, "Searching\u2026") : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(PopoverCombobox.Empty, {
622
694
  classNames: [
623
695
  "text-center",
624
696
  descriptionText
625
697
  ]
626
- }, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React7.createElement(PopoverCombobox.Item, {
698
+ }, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React8.createElement(PopoverCombobox.Item, {
627
699
  key: id,
628
700
  value: id,
629
701
  onSelect: handleValueChange,
630
702
  classNames: "truncate"
631
- }, label)))), /* @__PURE__ */ React7.createElement(Popover2.Arrow, null)));
703
+ }, label)))), /* @__PURE__ */ React8.createElement(Popover2.Arrow, null)));
632
704
  };
633
705
 
634
706
  // packages/ui/react-ui-table/src/helpers.tsx
@@ -637,10 +709,10 @@ import { Check as Check2, ClipboardText, X as X2 } from "@phosphor-icons/react";
637
709
  import { createColumnHelper } from "@tanstack/react-table";
638
710
  import { format } from "date-fns/format";
639
711
  import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
640
- import React8, { useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
712
+ import React9, { useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
641
713
  import { log as log2 } from "@dxos/log";
642
714
  import { Input as Input2, Tooltip } from "@dxos/react-ui";
643
- import { getSize as getSize3, mx as mx5 } from "@dxos/react-ui-theme";
715
+ import { getSize as getSize4, mx as mx5 } from "@dxos/react-ui-theme";
644
716
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/helpers.tsx";
645
717
  var createColumnBuilder = () => ({
646
718
  helper: createColumnHelper(),
@@ -648,15 +720,16 @@ var createColumnBuilder = () => ({
648
720
  });
649
721
  var ComboboxBuilderCell = (cellContext) => {
650
722
  const { model, onUpdate } = cellContext.column.columnDef.meta;
651
- return model ? /* @__PURE__ */ React8.createElement(CellCombobox, {
723
+ return model ? /* @__PURE__ */ React9.createElement(CellCombobox, {
652
724
  model,
653
725
  value: cellContext.getValue(),
654
726
  onValueChange: (value) => onUpdate?.(cellContext.row.original, cellContext.column.id, value)
655
727
  }) : null;
656
728
  };
657
729
  var StringBuilderCell = (cellContext) => {
658
- const inputRef = useRef2(null);
659
- const { onUpdate } = cellContext.column.columnDef.meta;
730
+ const ref = useRef2(null);
731
+ const { findPrevFocusable } = useFocusFinders();
732
+ const { onUpdate, cell } = cellContext.column.columnDef.meta;
660
733
  const initialValue = cellContext.getValue();
661
734
  const [value, setValue] = useState4(() => {
662
735
  if (initialValue?.content) {
@@ -665,27 +738,29 @@ var StringBuilderCell = (cellContext) => {
665
738
  return initialValue;
666
739
  });
667
740
  const handleSave = () => {
668
- if (value === initialValue) {
669
- return;
741
+ ref.current && document.activeElement === ref.current && findPrevFocusable(ref.current)?.focus();
742
+ if (value !== initialValue) {
743
+ onUpdate?.(cellContext.row.original, cellContext.column.id, value);
670
744
  }
671
- onUpdate?.(cellContext.row.original, cellContext.column.id, value);
672
- };
673
- const handleCancel = () => {
674
- setValue(initialValue);
675
745
  };
676
- const rows = cellContext.table.getRowModel().flatRows;
746
+ const handleCancel = () => setValue(initialValue);
747
+ let placeholder = false;
677
748
  const columns = cellContext.table.getVisibleFlatColumns();
678
- const placeholder = cellContext.row.index === rows.length - 1 && columns[0].id === cellContext.column.id;
679
- return /* @__PURE__ */ React8.createElement(Input2.Root, null, /* @__PURE__ */ React8.createElement(Input2.TextInput, {
680
- ref: inputRef,
749
+ if (columns[0].id === cellContext.column.id) {
750
+ const rowCount = cellContext.table.getRowModel().rows.length;
751
+ placeholder = cellContext.row.index === rowCount - 1 && columns[0].id === cellContext.column.id;
752
+ }
753
+ return /* @__PURE__ */ React9.createElement(Input2.Root, null, /* @__PURE__ */ React9.createElement(Input2.TextInput, {
754
+ ref,
681
755
  variant: "subdued",
682
756
  placeholder: placeholder ? "Add row..." : void 0,
683
757
  classNames: [
684
758
  "is-full",
685
- textPadding
759
+ textPadding,
760
+ cell?.classNames
686
761
  ],
687
762
  value: value ?? "",
688
- onBlur: () => handleSave(),
763
+ onBlur: handleSave,
689
764
  onChange: (event) => setValue(event.target.value),
690
765
  onKeyDown: (event) => event.key === "Enter" && handleSave() || event.key === "Escape" && handleCancel()
691
766
  }));
@@ -707,22 +782,22 @@ var NumberBuilderCell = (cellContext) => {
707
782
  digits,
708
783
  value
709
784
  ]);
710
- const handleEdit = () => {
711
- if (onUpdate) {
712
- setText(value !== void 0 ? String(value) : "");
713
- }
714
- };
785
+ const handleEdit = () => setText(value !== void 0 ? String(value) : "");
715
786
  const handleSave = () => {
716
787
  const nextValue = parseNumber(text);
717
- onUpdate?.(cellContext.row.original, cellContext.column.id, isNaN(nextValue) ? void 0 : nextValue);
718
- setText(displayNumber(nextValue, digits));
788
+ if (!isNaN(nextValue)) {
789
+ onUpdate?.(cellContext.row.original, cellContext.column.id, nextValue);
790
+ setText(displayNumber(nextValue, digits));
791
+ } else {
792
+ setText(displayNumber(value, digits));
793
+ }
719
794
  ref.current && document.activeElement === ref.current && findPrevFocusable(ref.current)?.focus();
720
795
  };
721
796
  const _handleCancel = () => {
722
797
  setText(displayNumber(value, digits));
723
798
  ref.current && findPrevFocusable(ref.current)?.focus();
724
799
  };
725
- return /* @__PURE__ */ React8.createElement(Input2.Root, null, /* @__PURE__ */ React8.createElement(Input2.TextInput, {
800
+ return /* @__PURE__ */ React9.createElement(Input2.Root, null, /* @__PURE__ */ React9.createElement(Input2.TextInput, {
726
801
  ref,
727
802
  variant: "subdued",
728
803
  value: text,
@@ -745,10 +820,12 @@ var RowSelectorBuilderCell = (cellContext) => {
745
820
  const { cell } = cellContext.column.columnDef.meta;
746
821
  const { row } = cellContext;
747
822
  const checked = row.getCanSelect() ? row.getIsSelected() : row.getCanSelectSubRows() && (row.getIsSomeSelected() ? "indeterminate" : row.getIsAllSubRowsSelected());
748
- return /* @__PURE__ */ React8.createElement(Input2.Root, null, /* @__PURE__ */ React8.createElement(Input2.Checkbox, {
823
+ return /* @__PURE__ */ React9.createElement("div", {
824
+ className: "flex justify-center w-full h-full",
825
+ role: "presentation"
826
+ }, /* @__PURE__ */ React9.createElement(Input2.Root, null, /* @__PURE__ */ React9.createElement(Input2.Checkbox, {
749
827
  size: 4,
750
828
  classNames: [
751
- "mli-auto",
752
829
  cell?.classNames
753
830
  ],
754
831
  checked,
@@ -758,12 +835,12 @@ var RowSelectorBuilderCell = (cellContext) => {
758
835
  }
759
836
  },
760
837
  disabled: !(row.getCanSelect() || row.getCanSelectSubRows())
761
- }));
838
+ })));
762
839
  };
763
840
  var SwitchBuilderCell = (cellContext) => {
764
841
  const { onUpdate } = cellContext.column.columnDef.meta;
765
842
  const value = cellContext.getValue();
766
- return /* @__PURE__ */ React8.createElement(Input2.Root, null, /* @__PURE__ */ React8.createElement(Input2.Switch, {
843
+ return /* @__PURE__ */ React9.createElement(Input2.Root, null, /* @__PURE__ */ React9.createElement(Input2.Switch, {
767
844
  classNames: "block mli-auto",
768
845
  onClick: (event) => event.stopPropagation(),
769
846
  disabled: !onUpdate,
@@ -785,7 +862,7 @@ var ColumnBuilder = class {
785
862
  },
786
863
  cell: model && onUpdate ? ComboboxBuilderCell : (cellContext) => {
787
864
  const cellValue = cellContext.getValue();
788
- return /* @__PURE__ */ React8.createElement("div", {
865
+ return /* @__PURE__ */ React9.createElement("div", {
789
866
  className: mx5("truncate", classNames)
790
867
  }, cellValue ? model?.getText(cellValue) : "");
791
868
  },
@@ -816,7 +893,7 @@ var ColumnBuilder = class {
816
893
  if (typeof value === "object" && value?.__typename === "dxos.Text.v0") {
817
894
  value = value.content;
818
895
  }
819
- return /* @__PURE__ */ React8.createElement("div", {
896
+ return /* @__PURE__ */ React9.createElement("div", {
820
897
  className: mx5("truncate", textPadding, classNames)
821
898
  }, value);
822
899
  },
@@ -871,7 +948,7 @@ var ColumnBuilder = class {
871
948
  const str = value ? formatSpec ? format(value, formatSpec) : relative ? formatDistanceToNow(value, {
872
949
  addSuffix: true
873
950
  }) : value.toISOString() : void 0;
874
- return /* @__PURE__ */ React8.createElement("div", {
951
+ return /* @__PURE__ */ React9.createElement("div", {
875
952
  className: mx5(textPadding, classNames)
876
953
  }, str);
877
954
  } catch (err) {
@@ -879,7 +956,7 @@ var ColumnBuilder = class {
879
956
  value
880
957
  }, {
881
958
  F: __dxlog_file2,
882
- L: 363,
959
+ L: 374,
883
960
  S: this,
884
961
  C: (f, a) => f(...a)
885
962
  });
@@ -913,9 +990,9 @@ var ColumnBuilder = class {
913
990
  if (!tooltip) {
914
991
  return element;
915
992
  }
916
- return /* @__PURE__ */ React8.createElement(Tooltip.Provider, null, /* @__PURE__ */ React8.createElement(Tooltip.Root, null, /* @__PURE__ */ React8.createElement(Tooltip.Trigger, null, element), /* @__PURE__ */ React8.createElement(Tooltip.Portal, null, /* @__PURE__ */ React8.createElement(Tooltip.Content, {
993
+ return /* @__PURE__ */ React9.createElement(Tooltip.Provider, null, /* @__PURE__ */ React9.createElement(Tooltip.Root, null, /* @__PURE__ */ React9.createElement(Tooltip.Trigger, null, element), /* @__PURE__ */ React9.createElement(Tooltip.Portal, null, /* @__PURE__ */ React9.createElement(Tooltip.Content, {
917
994
  side: "right"
918
- }, /* @__PURE__ */ React8.createElement(Tooltip.Arrow, null), /* @__PURE__ */ React8.createElement(ClipboardText, {
995
+ }, /* @__PURE__ */ React9.createElement(Tooltip.Arrow, null), /* @__PURE__ */ React9.createElement(ClipboardText, {
919
996
  onClick: (ev) => {
920
997
  ev.stopPropagation();
921
998
  void navigator.clipboard.writeText(value.toHex());
@@ -943,8 +1020,7 @@ var ColumnBuilder = class {
943
1020
  return {
944
1021
  id,
945
1022
  size: 32,
946
- minSize: 32,
947
- maxSize: 32,
1023
+ enableResizing: false,
948
1024
  meta: {
949
1025
  onUpdate,
950
1026
  cell: {
@@ -954,7 +1030,10 @@ var ColumnBuilder = class {
954
1030
  header: ({ table }) => {
955
1031
  const { rowsSelectable } = useTableContext("HELPER_SELECT_ROW_HEADER_CELL");
956
1032
  const checked = table.getIsSomeRowsSelected() ? "indeterminate" : table.getIsAllRowsSelected();
957
- return rowsSelectable === "multi" ? /* @__PURE__ */ React8.createElement(Input2.Root, null, /* @__PURE__ */ React8.createElement(Input2.Checkbox, {
1033
+ return rowsSelectable === "multi" ? /* @__PURE__ */ React9.createElement("div", {
1034
+ className: "flex justify-center w-full h-full",
1035
+ role: "presentation"
1036
+ }, /* @__PURE__ */ React9.createElement(Input2.Root, null, /* @__PURE__ */ React9.createElement(Input2.Checkbox, {
958
1037
  size: 4,
959
1038
  classNames: [
960
1039
  "mli-auto",
@@ -962,7 +1041,7 @@ var ColumnBuilder = class {
962
1041
  ],
963
1042
  checked,
964
1043
  onCheckedChange: () => table.toggleAllRowsSelected()
965
- })) : null;
1044
+ }))) : null;
966
1045
  },
967
1046
  cell: RowSelectorBuilderCell
968
1047
  };
@@ -975,6 +1054,8 @@ var ColumnBuilder = class {
975
1054
  size: 50,
976
1055
  minSize: 50,
977
1056
  header: (column) => label ?? column.header.id,
1057
+ // TODO(Zan): Implement sort algorithm
1058
+ enableSorting: true,
978
1059
  cell: SwitchBuilderCell,
979
1060
  ...props,
980
1061
  meta: {
@@ -998,18 +1079,20 @@ var ColumnBuilder = class {
998
1079
  const IconOff = off?.Icon ?? X2;
999
1080
  return {
1000
1081
  size: size ?? 32,
1001
- header: (column) => /* @__PURE__ */ React8.createElement("div", {
1082
+ // TODO(Zan): Implement sort algorithm
1083
+ enableSorting: false,
1084
+ header: (column) => /* @__PURE__ */ React9.createElement("div", {
1002
1085
  className: "justify-center"
1003
1086
  }, label ?? column.header.id),
1004
1087
  cell: (cell) => {
1005
1088
  const value = cell.getValue();
1006
1089
  if (value) {
1007
- return /* @__PURE__ */ React8.createElement(IconOn, {
1008
- className: mx5("block mli-auto", getSize3(6), on?.className ?? "text-green-700")
1090
+ return /* @__PURE__ */ React9.createElement(IconOn, {
1091
+ className: mx5("block mli-auto", getSize4(6), on?.className ?? "text-green-700")
1009
1092
  });
1010
1093
  } else if (value === false) {
1011
- return /* @__PURE__ */ React8.createElement(IconOff, {
1012
- className: mx5("block mli-auto", getSize3(6), off?.className ?? "text-red-700")
1094
+ return /* @__PURE__ */ React9.createElement(IconOff, {
1095
+ className: mx5("block mli-auto", getSize4(6), off?.className ?? "text-red-700")
1013
1096
  });
1014
1097
  } else {
1015
1098
  return null;
@@ -1024,6 +1107,7 @@ export {
1024
1107
  ColumnBuilder,
1025
1108
  ColumnMenu,
1026
1109
  ColumnPanel,
1110
+ MemoizedVirtualisedTableContent,
1027
1111
  Table,
1028
1112
  createColumnBuilder,
1029
1113
  currentRow,