@dxos/react-ui-table 0.4.10-main.ef6fbc2 → 0.4.10-main.f15a546

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 (86) hide show
  1. package/dist/lib/browser/index.mjs +646 -397
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/{ColumnMenu.d.ts → ColumnMenu/ColumnMenu.d.ts} +1 -1
  5. package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts.map +1 -0
  6. package/dist/types/src/components/{ColumnMenu.stories.d.ts → ColumnMenu/ColumnMenu.stories.d.ts} +6 -2
  7. package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -0
  8. package/dist/types/src/components/{ColumnSettingsForm.d.ts → ColumnMenu/ColumnSettingsForm.d.ts} +5 -4
  9. package/dist/types/src/components/ColumnMenu/ColumnSettingsForm.d.ts.map +1 -0
  10. package/dist/types/src/components/ColumnMenu/index.d.ts +3 -0
  11. package/dist/types/src/components/ColumnMenu/index.d.ts.map +1 -0
  12. package/dist/types/src/components/Table/Table.d.ts +17 -4
  13. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  14. package/dist/types/src/components/Table/Table.stories.d.ts +32 -1
  15. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  16. package/dist/types/src/components/Table/TableBody.d.ts.map +1 -1
  17. package/dist/types/src/components/Table/TableRootContext.d.ts +17 -0
  18. package/dist/types/src/components/Table/TableRootContext.d.ts.map +1 -0
  19. package/dist/types/src/components/Table/index.d.ts +1 -0
  20. package/dist/types/src/components/Table/index.d.ts.map +1 -1
  21. package/dist/types/src/components/Table/props.d.ts +2 -3
  22. package/dist/types/src/components/Table/props.d.ts.map +1 -1
  23. package/dist/types/src/components/index.d.ts +1 -1
  24. package/dist/types/src/components/index.d.ts.map +1 -1
  25. package/dist/types/src/helpers.d.ts.map +1 -1
  26. package/dist/types/src/hooks/index.d.ts +5 -0
  27. package/dist/types/src/hooks/index.d.ts.map +1 -0
  28. package/dist/types/src/hooks/useColumnSizing.d.ts +12 -0
  29. package/dist/types/src/hooks/useColumnSizing.d.ts.map +1 -0
  30. package/dist/types/src/hooks/useColumnSorting.d.ts.map +1 -0
  31. package/dist/types/src/hooks/usePinLastRow.d.ts +3 -0
  32. package/dist/types/src/hooks/usePinLastRow.d.ts.map +1 -0
  33. package/dist/types/src/hooks/useRowSelection.d.ts +7 -0
  34. package/dist/types/src/hooks/useRowSelection.d.ts.map +1 -0
  35. package/dist/types/src/index.d.ts +2 -1
  36. package/dist/types/src/index.d.ts.map +1 -1
  37. package/dist/types/src/schema/SchemaToTable.stories.d.ts.map +1 -0
  38. package/dist/types/src/schema/index.d.ts +3 -0
  39. package/dist/types/src/schema/index.d.ts.map +1 -0
  40. package/dist/types/src/{components/schema → schema}/schema.d.ts +1 -1
  41. package/dist/types/src/schema/schema.d.ts.map +1 -0
  42. package/dist/types/src/schema/schema.test.d.ts.map +1 -0
  43. package/dist/types/src/{components/schema → schema}/schemaToColumns.d.ts +1 -1
  44. package/dist/types/src/schema/schemaToColumns.d.ts.map +1 -0
  45. package/dist/types/src/{schema.d.ts → schema/types.d.ts} +1 -1
  46. package/dist/types/src/schema/types.d.ts.map +1 -0
  47. package/package.json +19 -16
  48. package/src/components/{ColumnMenu.stories.tsx → ColumnMenu/ColumnMenu.stories.tsx} +31 -1
  49. package/src/components/{ColumnMenu.tsx → ColumnMenu/ColumnMenu.tsx} +36 -34
  50. package/src/components/{ColumnSettingsForm.tsx → ColumnMenu/ColumnSettingsForm.tsx} +83 -75
  51. package/src/components/ColumnMenu/index.ts +6 -0
  52. package/src/components/Table/Table.stories.tsx +244 -74
  53. package/src/components/Table/Table.tsx +81 -97
  54. package/src/components/Table/TableBody.tsx +6 -1
  55. package/src/components/Table/TableRootContext.ts +39 -0
  56. package/src/components/Table/index.ts +1 -0
  57. package/src/components/Table/props.ts +17 -24
  58. package/src/components/index.ts +1 -1
  59. package/src/helpers.tsx +9 -7
  60. package/src/hooks/index.ts +8 -0
  61. package/src/hooks/useColumnSizing.ts +45 -0
  62. package/src/hooks/usePinLastRow.ts +64 -0
  63. package/src/hooks/useRowSelection.ts +39 -0
  64. package/src/index.ts +3 -1
  65. package/src/{components/schema → schema}/SchemaToTable.stories.tsx +17 -18
  66. package/src/schema/index.ts +6 -0
  67. package/src/{components/schema → schema}/schema.test.ts +1 -1
  68. package/src/{components/schema → schema}/schema.ts +37 -41
  69. package/src/{components/schema → schema}/schemaToColumns.ts +7 -9
  70. package/dist/types/src/components/ColumnMenu.d.ts.map +0 -1
  71. package/dist/types/src/components/ColumnMenu.stories.d.ts.map +0 -1
  72. package/dist/types/src/components/ColumnSettingsForm.d.ts.map +0 -1
  73. package/dist/types/src/components/hooks/useColumnSorting.d.ts.map +0 -1
  74. package/dist/types/src/components/hooks/usePinLastRow.d.ts +0 -3
  75. package/dist/types/src/components/hooks/usePinLastRow.d.ts.map +0 -1
  76. package/dist/types/src/components/schema/SchemaToTable.stories.d.ts.map +0 -1
  77. package/dist/types/src/components/schema/schema.d.ts.map +0 -1
  78. package/dist/types/src/components/schema/schema.test.d.ts.map +0 -1
  79. package/dist/types/src/components/schema/schemaToColumns.d.ts.map +0 -1
  80. package/dist/types/src/schema.d.ts.map +0 -1
  81. package/src/components/hooks/usePinLastRow.ts +0 -43
  82. /package/dist/types/src/{components/hooks → hooks}/useColumnSorting.d.ts +0 -0
  83. /package/dist/types/src/{components/schema → schema}/SchemaToTable.stories.d.ts +0 -0
  84. /package/dist/types/src/{components/schema → schema}/schema.test.d.ts +0 -0
  85. /package/src/{components/hooks → hooks}/useColumnSorting.ts +0 -0
  86. /package/src/{schema.ts → schema/types.ts} +0 -0
@@ -1,16 +1,3 @@
1
- // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
2
- import { X as X2, GearSix, CaretDown, ArrowDown, ArrowUp } from "@phosphor-icons/react";
3
- import React2, { useRef as useRef2, useState as useState3, useCallback } from "react";
4
- import { Button as Button2, DensityProvider, Popover, DropdownMenu } from "@dxos/react-ui";
5
- import { getSize as getSize2, mx as mx2 } from "@dxos/react-ui-theme";
6
-
7
- // packages/ui/react-ui-table/src/components/ColumnSettingsForm.tsx
8
- import { Check, Trash, X } from "@phosphor-icons/react";
9
- import React, { useRef, useState } from "react";
10
- import { Button, Input, Select, Separator, useTranslation } from "@dxos/react-ui";
11
- import { getSize, mx } from "@dxos/react-ui-theme";
12
- import { safeParseInt } from "@dxos/util";
13
-
14
1
  // packages/ui/react-ui-table/src/translations.ts
15
2
  var translationKey = "table";
16
3
  var translations_default = [
@@ -34,25 +21,107 @@ var translations_default = [
34
21
  }
35
22
  ];
36
23
 
37
- // packages/ui/react-ui-table/src/components/ColumnSettingsForm.tsx
38
- var Section = ({ children, className }) => /* @__PURE__ */ React.createElement("div", {
24
+ // packages/ui/react-ui-table/src/components/Cell/CellCombobox.tsx
25
+ import { CaretDown } from "@phosphor-icons/react";
26
+ import React, { useCallback, useState } from "react";
27
+ import { Popover, useTranslation } from "@dxos/react-ui";
28
+ import { PopoverCombobox } from "@dxos/react-ui-searchlist";
29
+ import { descriptionText, getSize, mx, staticPlaceholderText } from "@dxos/react-ui-theme";
30
+ var initialItems = (model, value) => value ? {
31
+ [model.getId(value)]: {
32
+ label: model.getText(value),
33
+ data: value
34
+ }
35
+ } : {};
36
+ var CellCombobox = ({ model, value, onValueChange }) => {
37
+ const { t } = useTranslation(translationKey);
38
+ const [items, setItems] = useState(initialItems(model, value));
39
+ const [loading, setLoading] = useState(false);
40
+ const [searchInputValue, setSearchInputValue] = useState("");
41
+ const handleSearchInputValueChange = async (text) => {
42
+ setSearchInputValue(text ?? "");
43
+ setLoading(true);
44
+ const items2 = await model.query(text);
45
+ setItems(items2.reduce((acc, item) => {
46
+ acc[model.getId(item)] = {
47
+ label: model.getText(item),
48
+ data: item
49
+ };
50
+ return acc;
51
+ }, initialItems(model, value)));
52
+ setLoading(false);
53
+ };
54
+ const handleValueChange = useCallback((id) => {
55
+ onValueChange(items[id]?.data);
56
+ }, [
57
+ items,
58
+ onValueChange
59
+ ]);
60
+ return /* @__PURE__ */ React.createElement(PopoverCombobox.Root, {
61
+ placeholder: t("no selection label")
62
+ }, /* @__PURE__ */ React.createElement(PopoverCombobox.Trigger, {
63
+ variant: "ghost",
64
+ classNames: "is-full rounded-none ring-inset"
65
+ }, value ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
66
+ className: mx("font-normal text-start text-base flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
67
+ }, model.getText(value)), /* @__PURE__ */ React.createElement(CaretDown, {
68
+ weight: "bold",
69
+ className: getSize(3)
70
+ })) : null), /* @__PURE__ */ React.createElement(PopoverCombobox.Content, {
71
+ shouldFilter: false,
72
+ classNames: "is-[--radix-popover-trigger-width]"
73
+ }, /* @__PURE__ */ React.createElement(PopoverCombobox.Input, {
74
+ value: searchInputValue,
75
+ onValueChange: handleSearchInputValueChange
76
+ }), /* @__PURE__ */ React.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React.createElement("p", {
77
+ className: mx("text-center", descriptionText)
78
+ }, "Start typing to search") : loading ? /* @__PURE__ */ React.createElement("p", {
79
+ className: mx("text-center", descriptionText)
80
+ }, "Searching\u2026") : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(PopoverCombobox.Empty, {
81
+ classNames: [
82
+ "text-center",
83
+ descriptionText
84
+ ]
85
+ }, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React.createElement(PopoverCombobox.Item, {
86
+ key: id,
87
+ value: id,
88
+ onSelect: handleValueChange,
89
+ classNames: "truncate"
90
+ }, label)))), /* @__PURE__ */ React.createElement(Popover.Arrow, null)));
91
+ };
92
+
93
+ // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnMenu.tsx
94
+ import { X as X2, GearSix, CaretDown as CaretDown2, ArrowDown, ArrowUp } from "@phosphor-icons/react";
95
+ import React3, { useRef as useRef2, useState as useState6, useCallback as useCallback5 } from "react";
96
+ import { Button as Button2, DensityProvider, Popover as Popover2, DropdownMenu } from "@dxos/react-ui";
97
+ import { getSize as getSize3, mx as mx3 } from "@dxos/react-ui-theme";
98
+
99
+ // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnSettingsForm.tsx
100
+ import { Check, Trash, X } from "@phosphor-icons/react";
101
+ import React2, { useRef, useState as useState2 } from "react";
102
+ import { Button, Input, Select, Separator, useTranslation as useTranslation2 } from "@dxos/react-ui";
103
+ import { getSize as getSize2, mx as mx2 } from "@dxos/react-ui-theme";
104
+ import { safeParseInt } from "@dxos/util";
105
+ var Section = ({ children, className }) => /* @__PURE__ */ React2.createElement("div", {
39
106
  role: "none",
40
- className: mx("p-2", className)
107
+ className: mx2("p-2", className)
41
108
  }, children);
42
109
  var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onClose }) => {
43
- const [prop, setProp] = useState(column.id);
44
- const [refTable, setRefTable] = useState(column.refTable);
45
- const [refProp, setRefProp] = useState(column.refProp);
46
- const [type, setType] = useState(String(column.type));
47
- const [label, setLabel] = useState(column.label);
48
- const [digits, setDigits] = useState(String(column.digits ?? "0"));
110
+ const [formState, setFormState] = useState2({
111
+ prop: column.id,
112
+ refTable: column.refTable,
113
+ refProp: column.refProp,
114
+ type: String(column.type),
115
+ label: column.label,
116
+ digits: String(column.digits ?? "0")
117
+ });
49
118
  const propRef = useRef(null);
50
- const { t } = useTranslation(translationKey);
119
+ const { t } = useTranslation2(translationKey);
51
120
  const handleCancel = () => {
52
- setProp(column.id);
53
- onClose;
121
+ onClose?.();
54
122
  };
55
123
  const handleSave = () => {
124
+ const { prop, refTable, refProp, type, label, digits } = formState;
56
125
  if (!prop.length || !prop.match(/^[a-zA-Z_].+/i)) {
57
126
  propRef.current?.focus();
58
127
  return;
@@ -64,7 +133,7 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
64
133
  return;
65
134
  }
66
135
  }
67
- onUpdate?.(prop, {
136
+ onUpdate?.(column.id, {
68
137
  id: prop,
69
138
  prop,
70
139
  label,
@@ -73,104 +142,154 @@ var ColumnSettingsForm = ({ column, tableDef, tableDefs, onUpdate, onDelete, onC
73
142
  refProp,
74
143
  digits: safeParseInt(digits)
75
144
  });
76
- onClose();
145
+ onClose?.();
77
146
  };
78
- return /* @__PURE__ */ React.createElement("div", {
147
+ return /* @__PURE__ */ React2.createElement("div", {
79
148
  className: "flex flex-col gap-1"
80
- }, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
149
+ }, /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
81
150
  classNames: "mbe-1"
82
- }, t("column label label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
151
+ }, t("column label label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
83
152
  placeholder: "Column label",
84
- value: label ?? "",
85
- onChange: (event) => setLabel(event.target.value),
153
+ value: formState.label ?? "",
154
+ onChange: (event) => setFormState((prevState) => ({
155
+ ...prevState,
156
+ label: event.target.value
157
+ })),
86
158
  autoFocus: true
87
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
159
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
88
160
  classNames: "mbe-1 mbs-3"
89
- }, t("property key label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
161
+ }, t("property key label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
90
162
  ref: propRef,
91
163
  placeholder: "Property key",
92
- // TODO(burdon): Provide hooks for value normalization, ENTER, ESC, etc.
93
- value: prop ?? "",
94
- onChange: (event) => setProp(event.target.value.replace(/[^\w_]/g, ""))
95
- })), /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
164
+ value: formState.prop ?? "",
165
+ onChange: (event) => setFormState((prevState) => ({
166
+ ...prevState,
167
+ prop: event.target.value.replace(/[^\w_]/g, "")
168
+ }))
169
+ })), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
96
170
  classNames: "mbe-1 mbs-3"
97
- }, t("column type label")), /* @__PURE__ */ React.createElement(Select.Root, {
98
- value: type,
99
- onValueChange: setType
100
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
171
+ }, t("column type label")), /* @__PURE__ */ React2.createElement(Select.Root, {
172
+ value: formState.type,
173
+ onValueChange: (value) => setFormState((prevState) => ({
174
+ ...prevState,
175
+ type: value
176
+ }))
177
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
101
178
  placeholder: "Type",
102
179
  classNames: "is-full"
103
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, [
180
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, [
104
181
  "number",
105
182
  "boolean",
106
183
  "string",
107
184
  "ref"
108
- ].map((type2) => /* @__PURE__ */ React.createElement(Select.Option, {
109
- key: type2,
110
- value: type2
111
- }, t(`${type2} column type label`))))))))), type === "number" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
185
+ ].map((type) => /* @__PURE__ */ React2.createElement(Select.Option, {
186
+ key: type,
187
+ value: type
188
+ }, t(`${type} column type label`))))))))), formState.type === "number" && /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
112
189
  classNames: "mbe-1 mbs-3"
113
- }, t("digits label")), /* @__PURE__ */ React.createElement(Input.TextInput, {
114
- value: digits ?? "",
115
- onChange: (event) => setDigits(event.target.value)
116
- })))), type === "ref" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
190
+ }, t("digits label")), /* @__PURE__ */ React2.createElement(Input.TextInput, {
191
+ value: formState.digits ?? "",
192
+ onChange: (event) => setFormState((prevState) => ({
193
+ ...prevState,
194
+ digits: event.target.value
195
+ }))
196
+ }))), formState.type === "ref" && /* @__PURE__ */ React2.createElement(Section, null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
117
197
  classNames: "mbe-1 mbs-3"
118
- }, "Table"), /* @__PURE__ */ React.createElement(Select.Root, {
119
- value: refTable,
120
- onValueChange: setRefTable
121
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
198
+ }, "Table"), /* @__PURE__ */ React2.createElement(Select.Root, {
199
+ value: formState.refTable,
200
+ onValueChange: (value) => setFormState((prevState) => ({
201
+ ...prevState,
202
+ refTable: value
203
+ }))
204
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
122
205
  placeholder: "Table",
123
206
  classNames: "is-full"
124
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, tableDefs.filter((t2) => t2.id !== tableDef.id).map(({ id, name }) => /* @__PURE__ */ React.createElement(Select.Option, {
207
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, tableDefs.filter((t2) => t2.id !== tableDef.id).map(({ id, name }) => /* @__PURE__ */ React2.createElement(Select.Option, {
125
208
  key: id,
126
209
  value: id
127
- }, name ?? id))))))), refTable && /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, {
210
+ }, name ?? id))))))), formState.refTable && /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.Label, {
128
211
  classNames: "mbe-1 mbs-3"
129
- }, "Table property"), /* @__PURE__ */ React.createElement(Select.Root, {
130
- value: refProp,
131
- onValueChange: setRefProp
132
- }, /* @__PURE__ */ React.createElement(Select.TriggerButton, {
212
+ }, "Table property"), /* @__PURE__ */ React2.createElement(Select.Root, {
213
+ value: formState.refProp,
214
+ onValueChange: (value) => setFormState((prevState) => ({
215
+ ...prevState,
216
+ refProp: value
217
+ }))
218
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
133
219
  placeholder: "Property",
134
220
  classNames: "is-full"
135
- }), /* @__PURE__ */ React.createElement(Select.Portal, null, /* @__PURE__ */ React.createElement(Select.Content, null, /* @__PURE__ */ React.createElement(Select.Viewport, null, tableDefs.find((tableDef2) => tableDef2.id === refTable)?.columns.map(({ id, label: label2 }) => /* @__PURE__ */ React.createElement(Select.Option, {
221
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, tableDefs.find((tableDef2) => tableDef2.id === formState.refTable)?.columns.map(({ id, label }) => /* @__PURE__ */ React2.createElement(Select.Option, {
136
222
  key: id,
137
223
  value: id
138
- }, label2 ?? id))))))))), /* @__PURE__ */ React.createElement(Separator, {
224
+ }, label ?? id)))))))), /* @__PURE__ */ React2.createElement(Separator, {
139
225
  classNames: "mli-2"
140
- }), /* @__PURE__ */ React.createElement(Section, {
226
+ }), /* @__PURE__ */ React2.createElement(Section, {
141
227
  className: "space-b-1.5"
142
- }, /* @__PURE__ */ React.createElement(Button, {
228
+ }, /* @__PURE__ */ React2.createElement(Button, {
143
229
  variant: "primary",
144
230
  classNames: "is-full flex gap-2",
145
231
  onClick: handleSave
146
- }, /* @__PURE__ */ React.createElement("span", null, t("save label")), /* @__PURE__ */ React.createElement("div", {
232
+ }, /* @__PURE__ */ React2.createElement("span", null, t("save label")), /* @__PURE__ */ React2.createElement("div", {
147
233
  className: "grow"
148
- }), /* @__PURE__ */ React.createElement(Check, {
149
- className: getSize(5)
150
- })), /* @__PURE__ */ React.createElement(Button, {
234
+ }), /* @__PURE__ */ React2.createElement(Check, {
235
+ className: getSize2(5)
236
+ })), /* @__PURE__ */ React2.createElement(Button, {
151
237
  classNames: "is-full flex gap-2",
152
238
  onClick: handleCancel
153
- }, /* @__PURE__ */ React.createElement("span", null, t("cancel label", {
239
+ }, /* @__PURE__ */ React2.createElement("span", null, t("cancel label", {
154
240
  ns: "os"
155
- })), /* @__PURE__ */ React.createElement("div", {
241
+ })), /* @__PURE__ */ React2.createElement("div", {
156
242
  className: "grow"
157
- }), /* @__PURE__ */ React.createElement(X, {
158
- className: getSize(5)
159
- })), /* @__PURE__ */ React.createElement(Button, {
243
+ }), /* @__PURE__ */ React2.createElement(X, {
244
+ className: getSize2(5)
245
+ })), /* @__PURE__ */ React2.createElement(Button, {
160
246
  classNames: "is-full flex gap-2",
161
247
  onClick: () => onDelete?.(column.id)
162
- }, /* @__PURE__ */ React.createElement("span", null, t("delete label")), /* @__PURE__ */ React.createElement("div", {
248
+ }, /* @__PURE__ */ React2.createElement("span", null, t("delete label")), /* @__PURE__ */ React2.createElement("div", {
163
249
  className: "grow"
164
- }), /* @__PURE__ */ React.createElement(Trash, {
165
- className: getSize(5)
250
+ }), /* @__PURE__ */ React2.createElement(Trash, {
251
+ className: getSize2(5)
166
252
  }))));
167
253
  };
168
254
 
169
- // packages/ui/react-ui-table/src/components/hooks/useColumnSorting.ts
170
- import { useState as useState2 } from "react";
255
+ // packages/ui/react-ui-table/src/hooks/useColumnSizing.ts
256
+ import { useCallback as useCallback2, useEffect, useState as useState3 } from "react";
257
+ import { useOnTransition } from "@dxos/react-ui";
258
+ var useColumnResizing = ({ columns, onColumnResize }) => {
259
+ const [columnsInitialised, setColumnsInitialised] = useState3(false);
260
+ const [columnSizing, setColumnSizing] = useState3({});
261
+ useEffect(() => {
262
+ if (columnsInitialised) {
263
+ return;
264
+ }
265
+ setColumnSizing(columns.filter((column) => !!column.size && column.prop !== void 0).reduce((state, column) => {
266
+ state[column.prop] = column.size;
267
+ return state;
268
+ }, {}));
269
+ setColumnsInitialised(true);
270
+ }, [
271
+ columns,
272
+ setColumnSizing
273
+ ]);
274
+ const [columnSizingInfo, setColumnSizingInfo] = useState3({});
275
+ const notifyColumnResize = useCallback2(() => onColumnResize?.(columnSizing), [
276
+ onColumnResize,
277
+ columnSizing
278
+ ]);
279
+ useOnTransition(columnSizingInfo.isResizingColumn, (v) => typeof v === "string", false, notifyColumnResize);
280
+ return {
281
+ columnSizing,
282
+ columnSizingInfo,
283
+ setColumnSizing,
284
+ setColumnSizingInfo
285
+ };
286
+ };
287
+
288
+ // packages/ui/react-ui-table/src/hooks/useColumnSorting.ts
289
+ import { useState as useState4 } from "react";
171
290
  var useColumnSorting = (column) => {
172
- const [sortDirection, setSortDirection] = useState2(column.getIsSorted());
173
- const [firstSort, setFirstSort] = useState2();
291
+ const [sortDirection, setSortDirection] = useState4(column.getIsSorted());
292
+ const [firstSort, setFirstSort] = useState4();
174
293
  const canSort = column.getCanSort();
175
294
  const updateColumnSort = (direction) => {
176
295
  setSortDirection(direction);
@@ -212,22 +331,110 @@ var useColumnSorting = (column) => {
212
331
  };
213
332
  };
214
333
 
215
- // packages/ui/react-ui-table/src/components/ColumnMenu.tsx
334
+ // packages/ui/react-ui-table/src/hooks/usePinLastRow.ts
335
+ import { useCallback as useCallback3, useEffect as useEffect2, useState as useState5 } from "react";
336
+ var usePinLastRow = (pinLastRow, table, data) => {
337
+ const { scrollContextRef } = useTableRootContext();
338
+ const [pinnedRowKey, setPinnedRowKey] = useState5();
339
+ const scrollToBottom = useCallback3(() => {
340
+ const element = scrollContextRef.current;
341
+ const scrollHeight = element?.scrollHeight;
342
+ if (element && scrollHeight) {
343
+ requestAnimationFrame(() => element.scrollTo({
344
+ top: scrollHeight
345
+ }));
346
+ }
347
+ }, []);
348
+ const pinRow = useCallback3((rowToPin) => {
349
+ table.resetRowPinning();
350
+ rowToPin.pin("bottom");
351
+ setPinnedRowKey(rowToPin.id);
352
+ }, [
353
+ table
354
+ ]);
355
+ const clearRowPinning = useCallback3(() => {
356
+ table.resetRowPinning();
357
+ setPinnedRowKey(void 0);
358
+ }, [
359
+ table
360
+ ]);
361
+ const pinLastRowCallback = useCallback3(() => {
362
+ const rows = table.getRowModel().rows;
363
+ if (rows.length === 0) {
364
+ return clearRowPinning();
365
+ }
366
+ const lastRow = rows[rows.length - 1];
367
+ if (lastRow.id === pinnedRowKey) {
368
+ return;
369
+ }
370
+ pinRow(lastRow);
371
+ if (pinnedRowKey !== void 0) {
372
+ scrollToBottom();
373
+ }
374
+ }, [
375
+ table,
376
+ scrollToBottom,
377
+ pinnedRowKey
378
+ ]);
379
+ useEffect2(() => {
380
+ if (pinLastRow) {
381
+ pinLastRowCallback();
382
+ }
383
+ }, [
384
+ data,
385
+ pinLastRow,
386
+ pinLastRowCallback
387
+ ]);
388
+ };
389
+
390
+ // packages/ui/react-ui-table/src/hooks/useRowSelection.ts
391
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
392
+ import { useCallback as useCallback4 } from "react";
393
+ var useRowSelection = (props) => {
394
+ const [rowSelection = {}, setRowSelection] = useControllableState({
395
+ prop: props.rowSelection,
396
+ onChange: props.onRowSelectionChange,
397
+ defaultProp: props.defaultRowSelection
398
+ });
399
+ const handleRowSelectionChange = useCallback4((updaterOrValue) => {
400
+ const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
401
+ if (props.rowsSelectable === "multi") {
402
+ setRowSelection(nextRowSelection);
403
+ } else if (props.rowsSelectable) {
404
+ const nextRowSelectionKey = Object.keys(nextRowSelection).filter((id) => !rowSelection[id])[0];
405
+ setRowSelection(nextRowSelectionKey ? {
406
+ [nextRowSelectionKey]: true
407
+ } : {});
408
+ } else {
409
+ setRowSelection({});
410
+ }
411
+ }, [
412
+ props.rowsSelectable,
413
+ setRowSelection,
414
+ rowSelection
415
+ ]);
416
+ return {
417
+ rowSelection,
418
+ handleRowSelectionChange
419
+ };
420
+ };
421
+
422
+ // packages/ui/react-ui-table/src/components/ColumnMenu/ColumnMenu.tsx
216
423
  var ColumnMenu = ({ column, ...props }) => {
217
424
  const title = column.label?.length ? column.label : column.id;
218
425
  const header = props.context.header;
219
426
  const { canSort, sortDirection, onSelectSort, onToggleSort, onClearSort } = useColumnSorting(header.column);
220
427
  const columnSettingsAnchorRef = useRef2(null);
221
- const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState3(false);
428
+ const [isColumnSettingsOpen, setIsColumnSettingsOpen] = useState6(false);
222
429
  const shouldPreventFocusOnClose = useRef2(false);
223
- const onOpenColumnSettings = useCallback(() => {
430
+ const onOpenColumnSettings = useCallback5(() => {
224
431
  shouldPreventFocusOnClose.current = true;
225
432
  setIsColumnSettingsOpen(true);
226
433
  }, [
227
434
  shouldPreventFocusOnClose,
228
435
  setIsColumnSettingsOpen
229
436
  ]);
230
- const onDropdownCloseAutoFocus = useCallback((event) => {
437
+ const onDropdownCloseAutoFocus = useCallback5((event) => {
231
438
  if (shouldPreventFocusOnClose.current) {
232
439
  event.preventDefault();
233
440
  shouldPreventFocusOnClose.current = false;
@@ -235,85 +442,85 @@ var ColumnMenu = ({ column, ...props }) => {
235
442
  }, [
236
443
  shouldPreventFocusOnClose
237
444
  ]);
238
- return /* @__PURE__ */ React2.createElement("div", {
445
+ return /* @__PURE__ */ React3.createElement("div", {
239
446
  className: "flex items-center justify-center justify-between"
240
- }, /* @__PURE__ */ React2.createElement("div", {
447
+ }, /* @__PURE__ */ React3.createElement("div", {
241
448
  className: "flex items-center gap-1 truncate",
242
449
  title
243
- }, /* @__PURE__ */ React2.createElement(SortIndicator, {
450
+ }, /* @__PURE__ */ React3.createElement(SortIndicator, {
244
451
  direction: sortDirection,
245
452
  onClick: onToggleSort
246
- }), /* @__PURE__ */ React2.createElement("div", {
453
+ }), /* @__PURE__ */ React3.createElement("div", {
247
454
  className: "truncate"
248
- }, title)), /* @__PURE__ */ React2.createElement(DropdownMenu.Root, {
455
+ }, title)), /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
249
456
  modal: false
250
- }, /* @__PURE__ */ React2.createElement(Popover.Root, {
457
+ }, /* @__PURE__ */ React3.createElement(Popover2.Root, {
251
458
  open: isColumnSettingsOpen,
252
459
  onOpenChange: setIsColumnSettingsOpen,
253
460
  modal: false
254
- }, /* @__PURE__ */ React2.createElement(DropdownMenu.Trigger, {
461
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
255
462
  ref: columnSettingsAnchorRef,
256
463
  asChild: true
257
- }, /* @__PURE__ */ React2.createElement(Popover.Anchor, {
464
+ }, /* @__PURE__ */ React3.createElement(Popover2.Anchor, {
258
465
  asChild: true
259
- }, /* @__PURE__ */ React2.createElement(Button2, {
466
+ }, /* @__PURE__ */ React3.createElement(Button2, {
260
467
  variant: "ghost"
261
- }, /* @__PURE__ */ React2.createElement(CaretDown, {
262
- className: getSize2(4)
263
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Content, {
468
+ }, /* @__PURE__ */ React3.createElement(CaretDown2, {
469
+ className: getSize3(4)
470
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
264
471
  onCloseAutoFocus: onDropdownCloseAutoFocus,
265
472
  sideOffset: 4,
266
473
  collisionPadding: 8
267
- }, /* @__PURE__ */ React2.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
474
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, canSort && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
268
475
  onClick: () => onSelectSort("asc")
269
- }, /* @__PURE__ */ React2.createElement("span", {
476
+ }, /* @__PURE__ */ React3.createElement("span", {
270
477
  className: "grow"
271
- }, "Sort ascending"), /* @__PURE__ */ React2.createElement("span", {
478
+ }, "Sort ascending"), /* @__PURE__ */ React3.createElement("span", {
272
479
  className: "opacity-50"
273
- }, /* @__PURE__ */ React2.createElement(ArrowUp, {
274
- className: getSize2(4)
275
- }))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
480
+ }, /* @__PURE__ */ React3.createElement(ArrowUp, {
481
+ className: getSize3(4)
482
+ }))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
276
483
  onClick: () => onSelectSort("desc")
277
- }, /* @__PURE__ */ React2.createElement("span", {
484
+ }, /* @__PURE__ */ React3.createElement("span", {
278
485
  className: "grow"
279
- }, "Sort descending"), /* @__PURE__ */ React2.createElement("span", {
486
+ }, "Sort descending"), /* @__PURE__ */ React3.createElement("span", {
280
487
  className: "opacity-50"
281
- }, /* @__PURE__ */ React2.createElement(ArrowDown, {
282
- className: getSize2(4)
283
- }))), sortDirection !== false && /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
488
+ }, /* @__PURE__ */ React3.createElement(ArrowDown, {
489
+ className: getSize3(4)
490
+ }))), sortDirection !== false && /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
284
491
  onClick: onClearSort
285
- }, /* @__PURE__ */ React2.createElement("span", {
492
+ }, /* @__PURE__ */ React3.createElement("span", {
286
493
  className: "grow"
287
- }, "Clear sort"), /* @__PURE__ */ React2.createElement("span", {
494
+ }, "Clear sort"), /* @__PURE__ */ React3.createElement("span", {
288
495
  className: "opacity-50"
289
- }, /* @__PURE__ */ React2.createElement(X2, {
290
- className: getSize2(4)
291
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
496
+ }, /* @__PURE__ */ React3.createElement(X2, {
497
+ className: getSize3(4)
498
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
292
499
  onClick: onOpenColumnSettings
293
- }, /* @__PURE__ */ React2.createElement("span", {
500
+ }, /* @__PURE__ */ React3.createElement("span", {
294
501
  className: "grow"
295
- }, "Column settings"), /* @__PURE__ */ React2.createElement("span", {
502
+ }, "Column settings"), /* @__PURE__ */ React3.createElement("span", {
296
503
  className: "opacity-50"
297
- }, /* @__PURE__ */ React2.createElement(GearSix, {
298
- className: mx2(getSize2(4), "rotate-90")
299
- })))), /* @__PURE__ */ React2.createElement(DropdownMenu.Arrow, null)), /* @__PURE__ */ React2.createElement(ColumnSettingsPanel, {
504
+ }, /* @__PURE__ */ React3.createElement(GearSix, {
505
+ className: mx3(getSize3(4), "rotate-90")
506
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null))), /* @__PURE__ */ React3.createElement(ColumnSettingsPanel, {
300
507
  ...props,
301
508
  column,
302
509
  onClose: () => setIsColumnSettingsOpen(false)
303
510
  }))));
304
511
  };
305
- var ColumnSettingsPanel = ({ tableDefs, tableDef, column, onUpdate, onDelete, onClose }) => /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, null, /* @__PURE__ */ React2.createElement(Popover.Viewport, {
512
+ var ColumnSettingsPanel = ({ tableDefs, tableDef, column, onUpdate, onDelete, onClose }) => /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, null, /* @__PURE__ */ React3.createElement(Popover2.Viewport, {
306
513
  classNames: "w-60"
307
- }, /* @__PURE__ */ React2.createElement(DensityProvider, {
514
+ }, /* @__PURE__ */ React3.createElement(DensityProvider, {
308
515
  density: "fine"
309
- }, /* @__PURE__ */ React2.createElement(ColumnSettingsForm, {
516
+ }, /* @__PURE__ */ React3.createElement(ColumnSettingsForm, {
310
517
  column,
311
518
  tableDefs,
312
519
  tableDef,
313
520
  onUpdate,
314
521
  onDelete,
315
522
  onClose
316
- }))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null)));
523
+ }))), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null)));
317
524
  var SortIndicator = ({ direction, onClick }) => {
318
525
  if (direction === false) {
319
526
  return null;
@@ -321,40 +528,39 @@ var SortIndicator = ({ direction, onClick }) => {
321
528
  let icon;
322
529
  switch (direction) {
323
530
  case "asc":
324
- icon = /* @__PURE__ */ React2.createElement(ArrowUp, {
325
- className: getSize2(3)
531
+ icon = /* @__PURE__ */ React3.createElement(ArrowUp, {
532
+ className: getSize3(3)
326
533
  });
327
534
  break;
328
535
  case "desc":
329
- icon = /* @__PURE__ */ React2.createElement(ArrowDown, {
330
- className: getSize2(3)
536
+ icon = /* @__PURE__ */ React3.createElement(ArrowDown, {
537
+ className: getSize3(3)
331
538
  });
332
539
  break;
333
540
  }
334
- return /* @__PURE__ */ React2.createElement("div", {
541
+ return /* @__PURE__ */ React3.createElement("div", {
335
542
  onClick,
336
543
  className: "flex items-center cursor-pointer"
337
544
  }, icon);
338
545
  };
339
546
 
340
547
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
341
- import { useControllableState } from "@radix-ui/react-use-controllable-state";
548
+ import { Slot } from "@radix-ui/react-slot";
342
549
  import { getCoreRowModel, getSortedRowModel, useReactTable, getGroupedRowModel, getExpandedRowModel } from "@tanstack/react-table";
343
- import { useVirtualizer } from "@tanstack/react-virtual";
344
- import React8, { Fragment, useCallback as useCallback2, useEffect as useEffect2, useState as useState5 } from "react";
345
- import { log } from "@dxos/log";
346
- import { useDefaultValue, useOnTransition } from "@dxos/react-ui";
550
+ import React9, { Fragment, useCallback as useCallback6, useEffect as useEffect3, useState as useState8, useContext as useContext3 } from "react";
551
+ import { useDefaultValue } from "@dxos/react-ui";
552
+ import { mx as mx5 } from "@dxos/react-ui-theme";
347
553
 
348
554
  // packages/ui/react-ui-table/src/components/Table/TableBody.tsx
349
555
  import { useArrowNavigationGroup } from "@fluentui/react-tabster";
350
556
  import { flexRender } from "@tanstack/react-table";
351
- import React5 from "react";
557
+ import React6, { useContext as useContext2 } from "react";
352
558
 
353
559
  // packages/ui/react-ui-table/src/components/Table/TableContext.tsx
354
- import React3, { useContext, createContext } from "react";
560
+ import React4, { useContext, createContext } from "react";
355
561
  var TableContext = /* @__PURE__ */ createContext({});
356
562
  var TableProvider = ({ children, ...value }) => {
357
- return /* @__PURE__ */ React3.createElement(TableContext.Provider, {
563
+ return /* @__PURE__ */ React4.createElement(TableContext.Provider, {
358
564
  value
359
565
  }, children);
360
566
  };
@@ -363,33 +569,62 @@ var useTableContext = () => {
363
569
  return context;
364
570
  };
365
571
 
572
+ // packages/ui/react-ui-table/src/components/Table/TableRootContext.ts
573
+ import { useVirtualizer } from "@tanstack/react-virtual";
574
+ import { createContext as createContext2, useRef as useRef3, useState as useState7 } from "react";
575
+ var useTableRootContext = () => {
576
+ const scrollContextRef = useRef3(null);
577
+ const [tableCount, setTableCount] = useState7(0);
578
+ const virtualizer = useVirtualizer({
579
+ getScrollElement: () => scrollContextRef?.current ?? null,
580
+ count: tableCount,
581
+ overscan: 8,
582
+ estimateSize: () => 40
583
+ });
584
+ const dispatch = (action) => {
585
+ switch (action.type) {
586
+ case "updateTableCount":
587
+ setTableCount(action.count);
588
+ break;
589
+ default:
590
+ break;
591
+ }
592
+ };
593
+ return {
594
+ scrollContextRef,
595
+ virtualizer,
596
+ dispatch
597
+ };
598
+ };
599
+ var TableRootContext = createContext2({});
600
+
366
601
  // packages/ui/react-ui-table/src/theme.ts
367
- import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx3 } from "@dxos/react-ui-theme";
602
+ import { modalSurface, focusRing, ghostSelected, ghostSelectedCurrent, groupBorder, mx as mx4 } from "@dxos/react-ui-theme";
368
603
  var currentRow = "!bg-neutral-75 !dark:bg-neutral-850";
369
604
  var selectedRow = "!bg-primary-100 dark:!bg-primary-700";
370
605
  var flushPadding = "pli-0 plb-0";
371
606
  var textPadding = "pli-2 plb-0.5";
372
607
  var headPadding = "pli-2 plb-1";
373
608
  var gridCellFocusRing = "focus-within:z-[11] focus-within:outline outline-2 outline-primary-500 dark:outline-primary-400";
374
- var tableRoot = ({ fullWidth }, ...etc) => mx3("table-fixed", fullWidth && "is-full", ...etc);
375
- var groupTh = (_props, ...etc) => mx3("text-start font-medium", flushPadding, ...etc);
376
- var theadRoot = ({ header, stickyHeader }, ...etc) => mx3(header ? stickyHeader && "sticky block-start-[--sticky-top] z-[1]" : "collapse", header && "base-surface", "drop-shadow-sm", ...etc);
377
- var theadTr = (_props, ...etc) => mx3("group", ...etc);
378
- var theadTh = ({ border }, ...etc) => mx3("relative", "text-start font-medium select-none truncate", headPadding, border && groupBorder, border && "border border-t-0 border-b-0 border-neutral-200", ...etc);
609
+ var tableRoot = ({ fullWidth }, ...etc) => mx4("table-fixed", fullWidth && "is-full", ...etc);
610
+ var groupTh = (_props, ...etc) => mx4("text-start font-medium", flushPadding, ...etc);
611
+ var theadRoot = ({ header, stickyHeader }, ...etc) => mx4(header ? stickyHeader && "sticky block-start-[--sticky-top] z-[1]" : "collapse", header && "base-surface", "drop-shadow-sm", ...etc);
612
+ var theadTr = (_props, ...etc) => mx4("group", ...etc);
613
+ var theadTh = ({ border }, ...etc) => mx4("relative", "text-start font-medium select-none truncate", headPadding, border && groupBorder, border && "border border-t-0 border-b-0 border-neutral-200", ...etc);
379
614
  var theadResizeRoot = ({ isResizing }) => {
380
- return mx3("absolute h-full w-[4px] top-0 right-0", "cursor-col-resize", "user-select-none", "touch-action-none", !isResizing && "group-hover:bg-neutral-100 dark:group-hover:bg-neutral-800", "pointer-coarse:bg-neutral-100 dark:pointer-coarse:bg-neutral-800", isResizing && "bg-primary-500 dark:bg-primary-400");
615
+ return mx4("absolute h-full w-[4px] top-0 right-0", "cursor-col-resize", "user-select-none", "touch-action-none", !isResizing && "group-hover:bg-neutral-100 dark:group-hover:bg-neutral-800", "pointer-coarse:bg-neutral-100 dark:pointer-coarse:bg-neutral-800", isResizing && "bg-primary-500 dark:bg-primary-400");
381
616
  };
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);
617
+ var tbodyRoot = (_props, ...etc) => mx4(...etc);
618
+ var tbodyTr = ({ canBeCurrent, isPinned }, ...etc) => mx4("group", canBeCurrent ? ghostSelectedCurrent : ghostSelected, canBeCurrent && focusRing, canBeCurrent && "cursor-pointer rounded", isPinned && "sticky z-1 bottom-[-1px] base-surface", ...etc);
619
+ var tdRoot = ({ border, isGrid }, ...etc) => mx4("relative", flushPadding, border && "border", border && groupBorder, isGrid && gridCellFocusRing, ...etc);
620
+ var tdContent = (_props, ...etc) => mx4(...etc);
621
+ var tfootRoot = (_props, ...etc) => mx4("sticky block-end-0 z-10", modalSurface, ...etc);
622
+ var tfootTr = (_props, ...etc) => mx4(...etc);
623
+ var tfootTh = ({ border }, ...etc) => mx4(textPadding, modalSurface, border && groupBorder, ...etc);
389
624
 
390
625
  // packages/ui/react-ui-table/src/components/Cell/Cell.tsx
391
626
  import { useFocusableGroup } from "@fluentui/react-tabster";
392
- import React4 from "react";
627
+ import React5 from "react";
393
628
  var CELL_NAME = "Cell";
394
629
  var FocusableCell = ({ cell, children }) => {
395
630
  const tableContext = useTableContext();
@@ -397,7 +632,7 @@ var FocusableCell = ({ cell, children }) => {
397
632
  tabBehavior: "limited"
398
633
  });
399
634
  const className = tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames);
400
- return /* @__PURE__ */ React4.createElement("td", {
635
+ return /* @__PURE__ */ React5.createElement("td", {
401
636
  tabIndex: 0,
402
637
  ...domAttributes,
403
638
  className
@@ -405,14 +640,14 @@ var FocusableCell = ({ cell, children }) => {
405
640
  };
406
641
  var StaticCell = ({ cell, children }) => {
407
642
  const tableContext = useTableContext();
408
- return /* @__PURE__ */ React4.createElement("td", {
643
+ return /* @__PURE__ */ React5.createElement("td", {
409
644
  className: tdRoot(tableContext, cell.column.columnDef.meta?.cell?.classNames)
410
645
  }, children);
411
646
  };
412
647
  var Cell = ({ cell, children }) => {
413
648
  const { isGrid } = useTableContext();
414
649
  const Root = isGrid ? FocusableCell : StaticCell;
415
- return /* @__PURE__ */ React4.createElement(Root, {
650
+ return /* @__PURE__ */ React5.createElement(Root, {
416
651
  cell
417
652
  }, children);
418
653
  };
@@ -427,7 +662,8 @@ var TableBody = ({ rows }) => {
427
662
  axis: "grid"
428
663
  });
429
664
  const canBeCurrent = !isGrid && !!onDatumClick;
430
- return /* @__PURE__ */ React5.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
665
+ const { virtualizer } = useContext2(TableRootContext);
666
+ return /* @__PURE__ */ React6.createElement("tbody", isGrid && domAttributes, rows.map((row) => {
431
667
  const isCurrent = currentDatum === row.original;
432
668
  const isSelected = rowSelection?.[row.id];
433
669
  const isPinned = row.getIsPinned();
@@ -435,9 +671,11 @@ var TableBody = ({ rows }) => {
435
671
  canBeCurrent,
436
672
  isPinned: isPinned !== false
437
673
  });
438
- return /* @__PURE__ */ React5.createElement("tr", {
674
+ return /* @__PURE__ */ React6.createElement("tr", {
439
675
  key: keyAccessor ? keyAccessor(row.original) : row.id,
440
676
  className: classNames,
677
+ "data-index": row.index,
678
+ ref: virtualizer.measureElement,
441
679
  ...isCurrent && {
442
680
  "aria-current": "location"
443
681
  },
@@ -455,57 +693,57 @@ var TableBody = ({ rows }) => {
455
693
  }
456
694
  }
457
695
  }
458
- }, debug && /* @__PURE__ */ React5.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
459
- return /* @__PURE__ */ React5.createElement(Cell, {
696
+ }, debug && /* @__PURE__ */ React6.createElement("td", null, row.id), row.getVisibleCells().map((cell) => {
697
+ return /* @__PURE__ */ React6.createElement(Cell, {
460
698
  key: cell.id,
461
699
  cell
462
700
  }, flexRender(cell.column.columnDef.cell, {
463
701
  className: "pli-2",
464
702
  ...cell.getContext()
465
703
  }));
466
- }), expand && /* @__PURE__ */ React5.createElement("td", null));
704
+ }), expand && /* @__PURE__ */ React6.createElement("td", null));
467
705
  }));
468
706
  };
469
707
  TableBody.displayName = TABLE_BODY_NAME;
470
708
 
471
709
  // packages/ui/react-ui-table/src/components/Table/TableFooter.tsx
472
710
  import { flexRender as flexRender2 } from "@tanstack/react-table";
473
- import React6 from "react";
711
+ import React7 from "react";
474
712
  var TABLE_FOOT_NAME = "TableFooter";
475
713
  var TableFooter = (props) => {
476
714
  const tableContext = useTableContext();
477
715
  const { table, expand, debug } = tableContext;
478
716
  const footers = table.getFooterGroups();
479
- return /* @__PURE__ */ React6.createElement("tfoot", {
717
+ return /* @__PURE__ */ React7.createElement("tfoot", {
480
718
  className: tfootRoot(props)
481
- }, footers.map((footerGroup) => /* @__PURE__ */ React6.createElement("tr", {
719
+ }, footers.map((footerGroup) => /* @__PURE__ */ React7.createElement("tr", {
482
720
  key: footerGroup.id,
483
721
  className: tfootTr(tableContext)
484
- }, debug && /* @__PURE__ */ React6.createElement("th", null), footerGroup.headers.map((footer) => {
485
- return /* @__PURE__ */ React6.createElement("th", {
722
+ }, debug && /* @__PURE__ */ React7.createElement("th", null), footerGroup.headers.map((footer) => {
723
+ return /* @__PURE__ */ React7.createElement("th", {
486
724
  key: footer.id,
487
725
  className: tfootTh(tableContext, footer.column.columnDef.meta?.footer?.classNames)
488
726
  }, footer.isPlaceholder ? null : flexRender2(footer.column.columnDef.footer, footer.getContext()));
489
- }), expand && /* @__PURE__ */ React6.createElement("th", null))));
727
+ }), expand && /* @__PURE__ */ React7.createElement("th", null))));
490
728
  };
491
729
  TableFooter.displayName = TABLE_FOOT_NAME;
492
730
 
493
731
  // packages/ui/react-ui-table/src/components/Table/TableHead.tsx
494
732
  import { flexRender as flexRender3 } from "@tanstack/react-table";
495
- import React7 from "react";
733
+ import React8 from "react";
496
734
  var TABLE_HEAD_NAME = "TableHeader";
497
735
  var TableHead = (_props) => {
498
736
  const tableContext = useTableContext();
499
737
  const headerGroups = tableContext.table.getHeaderGroups();
500
- return /* @__PURE__ */ React7.createElement("thead", {
738
+ return /* @__PURE__ */ React8.createElement("thead", {
501
739
  className: theadRoot(tableContext)
502
740
  }, headerGroups.map((headerGroup) => {
503
741
  return (
504
742
  // Group element to hover resize handles.
505
- /* @__PURE__ */ React7.createElement("tr", {
743
+ /* @__PURE__ */ React8.createElement("tr", {
506
744
  key: headerGroup.id,
507
745
  className: theadTr(tableContext)
508
- }, tableContext.debug && /* @__PURE__ */ React7.createElement("th", {
746
+ }, tableContext.debug && /* @__PURE__ */ React8.createElement("th", {
509
747
  className: "font-mono",
510
748
  style: {
511
749
  width: 32
@@ -514,13 +752,13 @@ var TableHead = (_props) => {
514
752
  const isResizing = header.column.getIsResizing();
515
753
  const onResize = header.getResizeHandler();
516
754
  const resizable = header.column.columnDef.meta?.resizable;
517
- return /* @__PURE__ */ React7.createElement("th", {
755
+ return /* @__PURE__ */ React8.createElement("th", {
518
756
  key: header.id,
519
757
  style: {
520
758
  width: header.getSize()
521
759
  },
522
760
  className: theadTh(tableContext, header.column.columnDef.meta?.header?.classNames)
523
- }, !header || header.isPlaceholder ? null : flexRender3(header.column.columnDef.header, header.getContext()), resizable && /* @__PURE__ */ React7.createElement("div", {
761
+ }, !header || header.isPlaceholder ? null : flexRender3(header.column.columnDef.header, header.getContext()), resizable && /* @__PURE__ */ React8.createElement("div", {
524
762
  className: theadResizeRoot({
525
763
  isResizing
526
764
  }),
@@ -528,100 +766,56 @@ var TableHead = (_props) => {
528
766
  onMouseDown: onResize,
529
767
  onTouchStart: onResize
530
768
  }));
531
- }), tableContext.expand && /* @__PURE__ */ React7.createElement("th", null))
769
+ }), tableContext.expand && /* @__PURE__ */ React8.createElement("th", null))
532
770
  );
533
771
  }));
534
772
  };
535
773
  TableHead.displayName = TABLE_HEAD_NAME;
536
774
 
537
- // packages/ui/react-ui-table/src/components/hooks/usePinLastRow.ts
538
- import { useEffect, useState as useState4 } from "react";
539
- var usePinLastRow = (pinLastRow, table, data, getScrollElement) => {
540
- const [pinnedRowKey, setPinnedRowKey] = useState4();
541
- useEffect(() => {
542
- if (!pinLastRow) {
543
- return;
544
- }
545
- const rows = table.getRowModel().rows;
546
- const rowToPin = rows[rows.length - 1];
547
- const rowId = rowToPin.id;
548
- if (rowId === pinnedRowKey) {
549
- return;
550
- }
551
- table.resetRowPinning();
552
- rowToPin.pin("bottom");
553
- const scrollElement = getScrollElement?.();
554
- const isFirstRender = pinnedRowKey === void 0;
555
- if (scrollElement && !isFirstRender) {
556
- requestAnimationFrame(() => {
557
- scrollElement.scrollTo({
558
- top: scrollElement.scrollHeight
559
- });
560
- });
561
- }
562
- setPinnedRowKey(rowId);
563
- }, [
564
- pinLastRow,
565
- table,
566
- getScrollElement,
567
- pinnedRowKey,
568
- setPinnedRowKey,
569
- data
570
- ]);
571
- };
572
-
573
775
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
574
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
575
- var Table = (props) => {
576
- const { role, onColumnResize, columnVisibility, header = true, rowsSelectable, debug, onDataSelectionChange, getScrollElement, pinLastRow } = props;
776
+ var TableRoot = ({ children }) => {
777
+ const contextValue = useTableRootContext();
778
+ return /* @__PURE__ */ React9.createElement(TableRootContext.Provider, {
779
+ value: contextValue
780
+ }, children);
781
+ };
782
+ var TableViewport = ({ children, classNames, asChild, ...props }) => {
783
+ const { scrollContextRef } = useContext3(TableRootContext);
784
+ const classes = mx5(classNames);
785
+ return asChild ? /* @__PURE__ */ React9.createElement(Slot, {
786
+ ref: scrollContextRef,
787
+ ...props
788
+ }, children) : /* @__PURE__ */ React9.createElement("div", {
789
+ role: "none",
790
+ className: classes,
791
+ ref: scrollContextRef,
792
+ ...props
793
+ }, children);
794
+ };
795
+ var TablePrimitive = (props) => {
796
+ const { role, onColumnResize, columnVisibility, header = true, rowsSelectable, debug, onDataSelectionChange, pinLastRow } = props;
577
797
  const columns = useDefaultValue(props.columns, []);
578
- const data = useDefaultValue(props.data, []);
579
- const TableProvider2 = TableProvider;
580
- const [columnsInitialised, setColumnsInitialised] = useState5(false);
581
- const [columnSizing, setColumnSizing] = useState5({});
582
- useEffect2(() => {
583
- if (columnsInitialised) {
584
- return;
585
- }
586
- setColumnSizing(columns.filter((column) => !!column.size && column.prop !== void 0).reduce((state, column) => {
587
- state[column.prop] = column.size;
588
- return state;
589
- }, {}));
590
- setColumnsInitialised(true);
591
- }, [
592
- columns,
593
- setColumnSizing
798
+ const incomingData = useDefaultValue(props.data, []);
799
+ const [data, setData] = useState8([
800
+ ...incomingData
594
801
  ]);
595
- const [columnSizingInfo, setColumnSizingInfo] = useState5({});
596
- const notifyColumnResize = useCallback2(() => onColumnResize?.(columnSizing), [
597
- onColumnResize,
598
- columnSizing
802
+ const forceUpdate = useCallback6(() => setData([
803
+ ...incomingData
804
+ ]), [
805
+ incomingData
599
806
  ]);
600
- useOnTransition(columnSizingInfo.isResizingColumn, (v) => typeof v === "string", false, notifyColumnResize);
601
- const [rowSelection = {}, setRowSelection] = useControllableState({
602
- prop: props.rowSelection,
603
- onChange: props.onRowSelectionChange,
604
- defaultProp: props.defaultRowSelection
605
- });
606
- const handleRowSelectionChange = useCallback2((updaterOrValue) => {
607
- const nextRowSelection = typeof updaterOrValue === "function" ? updaterOrValue(rowSelection) : updaterOrValue;
608
- if (rowsSelectable === "multi") {
609
- setRowSelection(nextRowSelection);
610
- } else if (rowsSelectable) {
611
- const nextRowSelectionKey = Object.keys(nextRowSelection).filter((id) => !rowSelection[id])[0];
612
- setRowSelection(nextRowSelectionKey ? {
613
- [nextRowSelectionKey]: true
614
- } : {});
615
- } else {
616
- setRowSelection({});
617
- }
618
- }, [
619
- rowsSelectable,
620
- setRowSelection,
621
- rowSelection
807
+ useEffect3(() => forceUpdate(), [
808
+ JSON.stringify(incomingData),
809
+ forceUpdate
622
810
  ]);
623
- const [grouping, handleGroupingChange] = useState5(props.grouping ?? []);
624
- useEffect2(() => handleGroupingChange(props.grouping ?? []), [
811
+ const TableProvider2 = TableProvider;
812
+ const { columnSizing, setColumnSizing, columnSizingInfo, setColumnSizingInfo } = useColumnResizing({
813
+ columns,
814
+ onColumnResize
815
+ });
816
+ const { rowSelection, handleRowSelectionChange } = useRowSelection(props);
817
+ const [grouping, handleGroupingChange] = useState8(props.grouping ?? []);
818
+ useEffect3(() => handleGroupingChange(props.grouping ?? []), [
625
819
  handleGroupingChange,
626
820
  props.grouping
627
821
  ]);
@@ -663,52 +857,37 @@ var Table = (props) => {
663
857
  // Debug
664
858
  debugTable: debug
665
859
  });
666
- useEffect2(() => {
860
+ useEffect3(() => {
667
861
  onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
668
862
  }, [
669
863
  onDataSelectionChange,
670
864
  rowSelection,
671
865
  table
672
866
  ]);
673
- usePinLastRow(pinLastRow, table, data, getScrollElement);
867
+ usePinLastRow(pinLastRow, table, data);
674
868
  const expand = false;
675
- if (!getScrollElement) {
676
- log.warn("Table: getScrollElement is not set. This is required for virtualized tables.", void 0, {
677
- F: __dxlog_file,
678
- L: 159,
679
- S: void 0,
680
- C: (f, a) => f(...a)
681
- });
682
- }
683
- return /* @__PURE__ */ React8.createElement(TableProvider2, {
869
+ return /* @__PURE__ */ React9.createElement(TableProvider2, {
684
870
  ...props,
685
871
  table,
686
872
  header,
687
873
  expand,
688
874
  isGrid: role === "grid" || role === "treegrid"
689
- }, /* @__PURE__ */ React8.createElement(TableImpl, {
875
+ }, /* @__PURE__ */ React9.createElement(TableImpl, {
690
876
  debug: false,
691
- getScrollElement,
692
877
  ...props
693
878
  }));
694
879
  };
695
880
  var TableImpl = (props) => {
696
- const { debug, classNames, getScrollElement, role, footer, grouping, fullWidth } = props;
881
+ const { debug, classNames, role, footer, grouping, fullWidth } = props;
697
882
  const { table } = useTableContext();
698
- const centerRows = table.getCenterRows();
699
- const bottomRows = table.getBottomRows();
700
- const rows = [
701
- ...centerRows,
702
- ...bottomRows
703
- ];
704
883
  if (debug) {
705
- return /* @__PURE__ */ React8.createElement("pre", {
884
+ return /* @__PURE__ */ React9.createElement("pre", {
706
885
  className: "font-mono text-xs text-neutral-500 m-1 p-2 ring"
707
- }, /* @__PURE__ */ React8.createElement("code", null, JSON.stringify(table.getState(), void 0, 2)));
886
+ }, /* @__PURE__ */ React9.createElement("code", null, JSON.stringify(table.getState(), void 0, 2)));
708
887
  }
709
- const virtualisable = getScrollElement !== void 0;
710
888
  const isResizingColumn = table.getState().columnSizingInfo.isResizingColumn;
711
- return /* @__PURE__ */ React8.createElement("table", {
889
+ const TableComponent = isResizingColumn ? MemoizedVirtualisedTableContent : VirtualizedTableContent;
890
+ return /* @__PURE__ */ React9.createElement("table", {
712
891
  role,
713
892
  className: tableRoot(props, classNames),
714
893
  ...!fullWidth && {
@@ -716,24 +895,26 @@ var TableImpl = (props) => {
716
895
  width: table.getTotalSize()
717
896
  }
718
897
  }
719
- }, /* @__PURE__ */ React8.createElement(TableHead, null), grouping?.length !== 0 ? virtualisable ? isResizingColumn ? /* @__PURE__ */ React8.createElement(MemoizedVirtualisedTableContent, {
720
- getScrollElement
721
- }) : /* @__PURE__ */ React8.createElement(VirtualizedTableContent, {
722
- getScrollElement
723
- }) : /* @__PURE__ */ React8.createElement(TableBody, {
724
- rows
725
- }) : /* @__PURE__ */ React8.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React8.createElement(TableFooter, null));
898
+ }, /* @__PURE__ */ React9.createElement(TableHead, null), grouping?.length !== 0 ? /* @__PURE__ */ React9.createElement(TableComponent, null) : /* @__PURE__ */ React9.createElement(GroupedTableContent, null), footer && /* @__PURE__ */ React9.createElement(TableFooter, null));
726
899
  };
727
- var VirtualizedTableContent = ({ getScrollElement }) => {
900
+ var VirtualizedTableContent = () => {
728
901
  const { table } = useTableContext();
902
+ const { virtualizer, dispatch } = useContext3(TableRootContext);
729
903
  const centerRows = table.getCenterRows();
730
- const pinnedRows = table.getBottomRows();
731
- const { getTotalSize, getVirtualItems } = useVirtualizer({
732
- getScrollElement,
733
- count: centerRows.length,
734
- overscan: 8,
735
- estimateSize: () => 40
736
- });
904
+ let pinnedRows = [];
905
+ useEffect3(() => {
906
+ dispatch({
907
+ type: "updateTableCount",
908
+ count: centerRows.length
909
+ });
910
+ }, [
911
+ centerRows.length
912
+ ]);
913
+ try {
914
+ pinnedRows = table.getBottomRows();
915
+ } catch (_) {
916
+ }
917
+ const { getTotalSize, getVirtualItems } = virtualizer;
737
918
  const virtualRows = getVirtualItems();
738
919
  const totalSize = getTotalSize();
739
920
  const paddingTop = virtualRows.length > 0 ? virtualRows?.[0]?.start || 0 : 0;
@@ -741,112 +922,48 @@ var VirtualizedTableContent = ({ getScrollElement }) => {
741
922
  const rowsToRender = [
742
923
  ...virtualRows.map((virtualRow) => centerRows[virtualRow.index]),
743
924
  ...pinnedRows
744
- ];
745
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, paddingTop > 0 && /* @__PURE__ */ React8.createElement("tbody", {
925
+ ].filter((r) => !!r);
926
+ return /* @__PURE__ */ React9.createElement(Fragment, null, paddingTop > 0 && /* @__PURE__ */ React9.createElement("tbody", {
746
927
  role: "none"
747
- }, /* @__PURE__ */ React8.createElement("tr", {
928
+ }, /* @__PURE__ */ React9.createElement("tr", {
748
929
  role: "none"
749
- }, /* @__PURE__ */ React8.createElement("td", {
930
+ }, /* @__PURE__ */ React9.createElement("td", {
750
931
  style: {
751
932
  height: `${paddingTop}px`
752
933
  },
753
934
  role: "none"
754
- }))), /* @__PURE__ */ React8.createElement(TableBody, {
935
+ }))), /* @__PURE__ */ React9.createElement(TableBody, {
755
936
  rows: rowsToRender
756
- }), paddingBottom > 0 && /* @__PURE__ */ React8.createElement("tbody", {
937
+ }), paddingBottom > 0 && /* @__PURE__ */ React9.createElement("tbody", {
757
938
  role: "none"
758
- }, /* @__PURE__ */ React8.createElement("tr", {
939
+ }, /* @__PURE__ */ React9.createElement("tr", {
759
940
  role: "none"
760
- }, /* @__PURE__ */ React8.createElement("td", {
941
+ }, /* @__PURE__ */ React9.createElement("td", {
761
942
  style: {
762
943
  height: `${paddingBottom}px`
763
944
  },
764
945
  role: "none"
765
946
  }))));
766
947
  };
767
- var MemoizedVirtualisedTableContent = /* @__PURE__ */ React8.memo(VirtualizedTableContent);
948
+ var MemoizedVirtualisedTableContent = /* @__PURE__ */ React9.memo(VirtualizedTableContent);
768
949
  var GroupedTableContent = () => {
769
950
  const { table: { getGroupedRowModel: getGroupedRowModel2, getHeaderGroups, getState }, debug } = useTableContext();
770
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
771
- return /* @__PURE__ */ React8.createElement(Fragment, {
951
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, getGroupedRowModel2().rows.map((row, i) => {
952
+ return /* @__PURE__ */ React9.createElement(Fragment, {
772
953
  key: i
773
- }, /* @__PURE__ */ React8.createElement("thead", null, /* @__PURE__ */ React8.createElement("tr", null, debug && /* @__PURE__ */ React8.createElement("th", null), /* @__PURE__ */ React8.createElement("th", {
954
+ }, /* @__PURE__ */ React9.createElement("thead", null, /* @__PURE__ */ React9.createElement("tr", null, debug && /* @__PURE__ */ React9.createElement("th", null), /* @__PURE__ */ React9.createElement("th", {
774
955
  // TODO(burdon): Calculate row span.
775
956
  colSpan: getHeaderGroups()[0].headers.length,
776
957
  className: groupTh({})
777
- }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React8.createElement(TableBody, {
958
+ }, getState().grouping[0], "[", String(row.getGroupingValue(getState().grouping[0])), "]"))), /* @__PURE__ */ React9.createElement(TableBody, {
778
959
  rows: row.subRows
779
960
  }));
780
961
  }));
781
962
  };
782
-
783
- // packages/ui/react-ui-table/src/components/Cell/CellCombobox.tsx
784
- import { CaretDown as CaretDown2 } from "@phosphor-icons/react";
785
- import React9, { useCallback as useCallback3, useState as useState6 } from "react";
786
- import { Popover as Popover2, useTranslation as useTranslation2 } from "@dxos/react-ui";
787
- import { PopoverCombobox } from "@dxos/react-ui-searchlist";
788
- import { descriptionText, getSize as getSize3, mx as mx4, staticPlaceholderText } from "@dxos/react-ui-theme";
789
- var initialItems = (model, value) => value ? {
790
- [model.getId(value)]: {
791
- label: model.getText(value),
792
- data: value
793
- }
794
- } : {};
795
- var CellCombobox = ({ model, value, onValueChange }) => {
796
- const { t } = useTranslation2(translationKey);
797
- const [items, setItems] = useState6(initialItems(model, value));
798
- const [loading, setLoading] = useState6(false);
799
- const [searchInputValue, setSearchInputValue] = useState6("");
800
- const handleSearchInputValueChange = async (text) => {
801
- setSearchInputValue(text ?? "");
802
- setLoading(true);
803
- const items2 = await model.query(text);
804
- setItems(items2.reduce((acc, item) => {
805
- acc[model.getId(item)] = {
806
- label: model.getText(item),
807
- data: item
808
- };
809
- return acc;
810
- }, initialItems(model, value)));
811
- setLoading(false);
812
- };
813
- const handleValueChange = useCallback3((id) => {
814
- onValueChange(items[id]?.data);
815
- }, [
816
- items,
817
- onValueChange
818
- ]);
819
- return /* @__PURE__ */ React9.createElement(PopoverCombobox.Root, {
820
- placeholder: t("no selection label")
821
- }, /* @__PURE__ */ React9.createElement(PopoverCombobox.Trigger, {
822
- variant: "ghost",
823
- classNames: "is-full rounded-none ring-inset"
824
- }, value ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement("span", {
825
- className: mx4("font-normal text-start text-base flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
826
- }, model.getText(value)), /* @__PURE__ */ React9.createElement(CaretDown2, {
827
- weight: "bold",
828
- className: getSize3(3)
829
- })) : null), /* @__PURE__ */ React9.createElement(PopoverCombobox.Content, {
830
- shouldFilter: false,
831
- classNames: "is-[--radix-popover-trigger-width]"
832
- }, /* @__PURE__ */ React9.createElement(PopoverCombobox.Input, {
833
- value: searchInputValue,
834
- onValueChange: handleSearchInputValueChange
835
- }), /* @__PURE__ */ React9.createElement(PopoverCombobox.List, null, searchInputValue.length < 1 ? /* @__PURE__ */ React9.createElement("p", {
836
- className: mx4("text-center", descriptionText)
837
- }, "Start typing to search") : loading ? /* @__PURE__ */ React9.createElement("p", {
838
- className: mx4("text-center", descriptionText)
839
- }, "Searching\u2026") : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(PopoverCombobox.Empty, {
840
- classNames: [
841
- "text-center",
842
- descriptionText
843
- ]
844
- }, "No results"), Object.entries(items).map(([id, { label }]) => /* @__PURE__ */ React9.createElement(PopoverCombobox.Item, {
845
- key: id,
846
- value: id,
847
- onSelect: handleValueChange,
848
- classNames: "truncate"
849
- }, label)))), /* @__PURE__ */ React9.createElement(Popover2.Arrow, null)));
963
+ var Table = {
964
+ Root: TableRoot,
965
+ Table: TablePrimitive,
966
+ Viewport: TableViewport
850
967
  };
851
968
 
852
969
  // packages/ui/react-ui-table/src/helpers.tsx
@@ -855,11 +972,11 @@ import { Check as Check2, ClipboardText, X as X3 } from "@phosphor-icons/react";
855
972
  import { createColumnHelper } from "@tanstack/react-table";
856
973
  import { format } from "date-fns/format";
857
974
  import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
858
- import React10, { useEffect as useEffect3, useRef as useRef3, useState as useState7 } from "react";
859
- import { log as log2 } from "@dxos/log";
975
+ import React10, { useCallback as useCallback7, useEffect as useEffect4, useRef as useRef4, useState as useState9 } from "react";
976
+ import { log } from "@dxos/log";
860
977
  import { Input as Input2, Tooltip } from "@dxos/react-ui";
861
- import { getSize as getSize4, mx as mx5 } from "@dxos/react-ui-theme";
862
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/helpers.tsx";
978
+ import { getSize as getSize4, mx as mx6 } from "@dxos/react-ui-theme";
979
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/helpers.tsx";
863
980
  var createColumnBuilder = () => ({
864
981
  helper: createColumnHelper(),
865
982
  builder: new ColumnBuilder()
@@ -873,16 +990,19 @@ var ComboboxBuilderCell = (cellContext) => {
873
990
  }) : null;
874
991
  };
875
992
  var StringBuilderCell = (cellContext) => {
876
- const ref = useRef3(null);
993
+ const ref = useRef4(null);
877
994
  const { findPrevFocusable } = useFocusFinders();
878
995
  const { onUpdate, cell } = cellContext.column.columnDef.meta;
879
996
  const initialValue = cellContext.getValue();
880
- const [value, setValue] = useState7(() => {
881
- if (initialValue?.content) {
882
- return initialValue?.content;
883
- }
884
- return initialValue;
885
- });
997
+ const getInitialValue = useCallback7(() => {
998
+ return initialValue?.content ?? initialValue;
999
+ }, [
1000
+ initialValue
1001
+ ]);
1002
+ const [value, setValue] = useState9(getInitialValue);
1003
+ useEffect4(() => setValue(getInitialValue()), [
1004
+ getInitialValue
1005
+ ]);
886
1006
  const handleSave = () => {
887
1007
  ref.current && document.activeElement === ref.current && findPrevFocusable(ref.current)?.focus();
888
1008
  if (value !== initialValue) {
@@ -919,10 +1039,10 @@ var displayNumber = (value, digits) => value || value === 0 ? value.toLocaleStri
919
1039
  var NumberBuilderCell = (cellContext) => {
920
1040
  const { onUpdate, digits } = cellContext.column.columnDef.meta;
921
1041
  const value = cellContext.getValue();
922
- const [text, setText] = useState7(displayNumber(value, digits));
1042
+ const [text, setText] = useState9(displayNumber(value, digits));
923
1043
  const { findPrevFocusable } = useFocusFinders();
924
- const ref = useRef3(null);
925
- useEffect3(() => {
1044
+ const ref = useRef4(null);
1045
+ useEffect4(() => {
926
1046
  (!document.activeElement || document.activeElement !== ref.current) && setText(displayNumber(value, digits));
927
1047
  }, [
928
1048
  digits,
@@ -1009,7 +1129,7 @@ var ColumnBuilder = class {
1009
1129
  cell: model && onUpdate ? ComboboxBuilderCell : (cellContext) => {
1010
1130
  const cellValue = cellContext.getValue();
1011
1131
  return /* @__PURE__ */ React10.createElement("div", {
1012
- className: mx5("truncate", classNames)
1132
+ className: mx6("truncate", classNames)
1013
1133
  }, cellValue ? model?.getText(cellValue) : "");
1014
1134
  },
1015
1135
  ...props,
@@ -1040,7 +1160,7 @@ var ColumnBuilder = class {
1040
1160
  value = value.content;
1041
1161
  }
1042
1162
  return /* @__PURE__ */ React10.createElement("div", {
1043
- className: mx5("truncate", textPadding, classNames)
1163
+ className: mx6("truncate", textPadding, classNames)
1044
1164
  }, value);
1045
1165
  },
1046
1166
  ...props,
@@ -1094,14 +1214,14 @@ var ColumnBuilder = class {
1094
1214
  addSuffix: true
1095
1215
  }) : value.toISOString() : void 0;
1096
1216
  return /* @__PURE__ */ React10.createElement("div", {
1097
- className: mx5(textPadding, classNames)
1217
+ className: mx6(textPadding, classNames)
1098
1218
  }, str);
1099
1219
  } catch (err) {
1100
- log2.info("formatError", {
1220
+ log.info("formatError", {
1101
1221
  value
1102
1222
  }, {
1103
- F: __dxlog_file2,
1104
- L: 374,
1223
+ F: __dxlog_file,
1224
+ L: 376,
1105
1225
  S: this,
1106
1226
  C: (f, a) => f(...a)
1107
1227
  });
@@ -1233,11 +1353,11 @@ var ColumnBuilder = class {
1233
1353
  const value = cell.getValue();
1234
1354
  if (value) {
1235
1355
  return /* @__PURE__ */ React10.createElement(IconOn, {
1236
- className: mx5("block mli-auto", getSize4(6), on?.className ?? "text-green-700")
1356
+ className: mx6("block mli-auto", getSize4(6), on?.className ?? "text-green-700")
1237
1357
  });
1238
1358
  } else if (value === false) {
1239
1359
  return /* @__PURE__ */ React10.createElement(IconOff, {
1240
- className: mx5("block mli-auto", getSize4(6), off?.className ?? "text-red-700")
1360
+ className: mx6("block mli-auto", getSize4(6), off?.className ?? "text-red-700")
1241
1361
  });
1242
1362
  } else {
1243
1363
  return null;
@@ -1277,20 +1397,144 @@ var ColumnBuilder = class {
1277
1397
  };
1278
1398
  }
1279
1399
  };
1400
+
1401
+ // packages/ui/react-ui-table/src/schema/schema.ts
1402
+ import * as AST from "@effect/schema/AST";
1403
+ var classifySchemaProperties = (schema) => {
1404
+ const recurse = (node, path, acc) => {
1405
+ const properties = AST.getPropertySignatures(node);
1406
+ properties.forEach((prop) => {
1407
+ const propName = prop.name.toString();
1408
+ if (prop.isOptional) {
1409
+ const unwrappedAst = unwrapOptionProperty(prop);
1410
+ if (isStruct(unwrappedAst)) {
1411
+ return recurse(unwrappedAst, [
1412
+ ...path,
1413
+ propName
1414
+ ], acc);
1415
+ }
1416
+ }
1417
+ if (isStruct(prop.type)) {
1418
+ recurse(prop.type, [
1419
+ ...path,
1420
+ propName
1421
+ ], acc);
1422
+ } else {
1423
+ acc.push([
1424
+ path.concat(propName).join("."),
1425
+ propertyToColumn(prop)
1426
+ ]);
1427
+ }
1428
+ });
1429
+ return acc;
1430
+ };
1431
+ return recurse(schema.ast, [], []);
1432
+ };
1433
+ var isStruct = (node) => AST.isTypeLiteral(node);
1434
+ var isOptionalUnion = (prop) => AST.isUnion(prop.type) && prop.isOptional;
1435
+ var unwrapOptionProperty = (prop) => {
1436
+ if (!isOptionalUnion(prop)) {
1437
+ throw new Error(`Not an optional property: ${String(prop.name)}`);
1438
+ }
1439
+ if (!AST.isUnion(prop.type)) {
1440
+ throw new Error(`Not a union type: ${String(prop.name)}`);
1441
+ }
1442
+ const [type, _undefinedCase] = prop.type.types;
1443
+ return type;
1444
+ };
1445
+ var typeToColumn = (type) => {
1446
+ if (AST.isStringKeyword(type)) {
1447
+ return "string";
1448
+ } else if (AST.isNumberKeyword(type)) {
1449
+ return "number";
1450
+ } else if (AST.isBooleanKeyword(type)) {
1451
+ return "boolean";
1452
+ }
1453
+ if (AST.isRefinement(type)) {
1454
+ return typeToColumn(type.from);
1455
+ }
1456
+ if (AST.isTransform(type)) {
1457
+ const identifier = AST.getIdentifierAnnotation(type);
1458
+ if (identifier._tag === "Some") {
1459
+ if (identifier.value === "DateFromString") {
1460
+ return "date";
1461
+ }
1462
+ }
1463
+ }
1464
+ return "display";
1465
+ };
1466
+ var propertyToColumn = (prop) => {
1467
+ let type = prop.type;
1468
+ if (prop.isOptional) {
1469
+ type = unwrapOptionProperty(prop);
1470
+ }
1471
+ return typeToColumn(type);
1472
+ };
1473
+
1474
+ // packages/ui/react-ui-table/src/schema/schemaToColumns.ts
1475
+ var schemaToColumnDefs = (schema) => {
1476
+ const { helper, builder } = createColumnBuilder();
1477
+ const classified = classifySchemaProperties(schema);
1478
+ return classified.map(([name, type]) => {
1479
+ const propertyKey = name.toString();
1480
+ let column;
1481
+ switch (type) {
1482
+ case "string": {
1483
+ column = builder.string({
1484
+ label: propertyKey
1485
+ });
1486
+ break;
1487
+ }
1488
+ case "number": {
1489
+ column = builder.number({
1490
+ label: propertyKey
1491
+ });
1492
+ break;
1493
+ }
1494
+ case "boolean": {
1495
+ column = builder.switch({
1496
+ label: propertyKey
1497
+ });
1498
+ break;
1499
+ }
1500
+ case "date": {
1501
+ column = builder.date({
1502
+ label: propertyKey
1503
+ });
1504
+ break;
1505
+ }
1506
+ case "display": {
1507
+ column = builder.display({
1508
+ label: propertyKey,
1509
+ id: propertyKey
1510
+ });
1511
+ break;
1512
+ }
1513
+ default: {
1514
+ throw new Error(`Unhandled column type: ${type}`);
1515
+ }
1516
+ }
1517
+ return helper.accessor(propertyKey, column);
1518
+ });
1519
+ };
1280
1520
  export {
1281
1521
  CellCombobox,
1282
1522
  ColumnBuilder,
1283
1523
  ColumnMenu,
1524
+ ColumnSettingsForm,
1284
1525
  ColumnSettingsPanel,
1285
1526
  MemoizedVirtualisedTableContent,
1286
1527
  SortIndicator,
1287
1528
  Table,
1529
+ TablePrimitive,
1530
+ TableRootContext,
1288
1531
  createColumnBuilder,
1289
1532
  currentRow,
1290
1533
  flushPadding,
1291
1534
  gridCellFocusRing,
1292
1535
  groupTh,
1293
1536
  headPadding,
1537
+ schemaToColumnDefs,
1294
1538
  selectedRow,
1295
1539
  tableRoot,
1296
1540
  tbodyRoot,
@@ -1305,6 +1549,11 @@ export {
1305
1549
  theadRoot,
1306
1550
  theadTh,
1307
1551
  theadTr,
1308
- translations_default as translations
1552
+ translations_default as translations,
1553
+ useColumnResizing,
1554
+ useColumnSorting,
1555
+ usePinLastRow,
1556
+ useRowSelection,
1557
+ useTableRootContext
1309
1558
  };
1310
1559
  //# sourceMappingURL=index.mjs.map