@dxos/react-ui-table 0.8.1-staging.391c573 → 0.8.1-staging.9eaf14f

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 (191) hide show
  1. package/dist/lib/browser/{chunk-3FR6NHPD.mjs → chunk-YWNRUF4J.mjs} +8 -6
  2. package/dist/lib/browser/chunk-YWNRUF4J.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +625 -225
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/types/index.mjs +1 -1
  7. package/dist/lib/node/{chunk-NB3SFHGA.cjs → chunk-TGG6OZ54.cjs} +10 -8
  8. package/dist/lib/node/chunk-TGG6OZ54.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +618 -220
  10. package/dist/lib/node/index.cjs.map +4 -4
  11. package/dist/lib/node/meta.json +1 -1
  12. package/dist/lib/node/types/index.cjs +3 -3
  13. package/dist/lib/node/types/index.cjs.map +1 -1
  14. package/dist/lib/node-esm/{chunk-RLVVOZW5.mjs → chunk-KKLP54L3.mjs} +8 -6
  15. package/dist/lib/node-esm/chunk-KKLP54L3.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +625 -225
  17. package/dist/lib/node-esm/index.mjs.map +4 -4
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/types/index.mjs +1 -1
  20. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  21. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  22. package/dist/types/src/components/Table/DynamicTable.d.ts +24 -0
  23. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -0
  24. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +10 -0
  25. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -0
  26. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/Table.d.ts +1 -0
  28. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/Table.stories.d.ts +4 -3
  30. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  31. package/dist/types/src/components/Table/index.d.ts +1 -0
  32. package/dist/types/src/components/Table/index.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/relations.stories.d.ts +9 -0
  34. package/dist/types/src/components/Table/relations.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  36. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/testing.d.ts +7 -7
  38. package/dist/types/src/components/testing.d.ts.map +1 -1
  39. package/dist/types/src/hooks/useTableModel.d.ts +8 -9
  40. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  41. package/dist/types/src/model/index.d.ts +1 -0
  42. package/dist/types/src/model/index.d.ts.map +1 -1
  43. package/dist/types/src/model/selection-model.d.ts +6 -3
  44. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  45. package/dist/types/src/model/table-model.d.ts +42 -16
  46. package/dist/types/src/model/table-model.d.ts.map +1 -1
  47. package/dist/types/src/model/table-presentation.d.ts +4 -4
  48. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  49. package/dist/types/src/model/table-sorting.d.ts +2 -2
  50. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  51. package/dist/types/src/types/table.d.ts +7 -32
  52. package/dist/types/src/types/table.d.ts.map +1 -1
  53. package/dist/types/src/util/dynamic-table.d.ts +31 -0
  54. package/dist/types/src/util/dynamic-table.d.ts.map +1 -0
  55. package/dist/types/src/util/index.d.ts +1 -0
  56. package/dist/types/src/util/index.d.ts.map +1 -1
  57. package/dist/types/src/util/table-controls.d.ts +2 -2
  58. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  59. package/dist/types/src/util/table.d.ts +5 -3
  60. package/dist/types/src/util/table.d.ts.map +1 -1
  61. package/package.json +37 -36
  62. package/src/components/Table/ColumnActionsMenu.tsx +6 -4
  63. package/src/components/Table/ColumnSettings.tsx +5 -6
  64. package/src/components/Table/CreateRefPanel.tsx +3 -3
  65. package/src/components/Table/DynamicTable.stories.tsx +155 -0
  66. package/src/components/Table/DynamicTable.tsx +104 -0
  67. package/src/components/Table/RefPanel.tsx +3 -3
  68. package/src/components/Table/RowActionsMenu.tsx +18 -3
  69. package/src/components/Table/Table.stories.tsx +170 -115
  70. package/src/components/Table/Table.tsx +71 -26
  71. package/src/components/Table/index.ts +1 -0
  72. package/src/components/Table/relations.stories.tsx +113 -0
  73. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +15 -5
  74. package/src/components/TableCellEditor/TableCellEditor.tsx +102 -4
  75. package/src/components/testing.ts +0 -1
  76. package/src/hooks/useTableModel.ts +35 -14
  77. package/src/model/index.ts +1 -0
  78. package/src/model/selection-model.ts +12 -2
  79. package/src/model/table-model.test.ts +2 -2
  80. package/src/model/table-model.ts +117 -32
  81. package/src/model/table-presentation.test.ts +2 -2
  82. package/src/model/table-presentation.ts +94 -22
  83. package/src/model/table-sorting.ts +3 -2
  84. package/src/playwright/smoke.spec.ts +2 -3
  85. package/src/types/table.ts +9 -10
  86. package/src/util/dynamic-table.ts +103 -0
  87. package/src/util/index.ts +1 -0
  88. package/src/util/table-controls.ts +4 -4
  89. package/src/util/table.ts +68 -65
  90. package/dist/lib/browser/_deprecated/index.mjs +0 -1483
  91. package/dist/lib/browser/_deprecated/index.mjs.map +0 -7
  92. package/dist/lib/browser/chunk-3FR6NHPD.mjs.map +0 -7
  93. package/dist/lib/node/_deprecated/index.cjs +0 -1511
  94. package/dist/lib/node/_deprecated/index.cjs.map +0 -7
  95. package/dist/lib/node/chunk-NB3SFHGA.cjs.map +0 -7
  96. package/dist/lib/node-esm/_deprecated/index.mjs +0 -1485
  97. package/dist/lib/node-esm/_deprecated/index.mjs.map +0 -7
  98. package/dist/lib/node-esm/chunk-RLVVOZW5.mjs.map +0 -7
  99. package/dist/types/src/_deprecated/components/Cell/Cell.d.ts +0 -12
  100. package/dist/types/src/_deprecated/components/Cell/Cell.d.ts.map +0 -1
  101. package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts +0 -13
  102. package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts.map +0 -1
  103. package/dist/types/src/_deprecated/components/Cell/index.d.ts +0 -2
  104. package/dist/types/src/_deprecated/components/Cell/index.d.ts.map +0 -1
  105. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts +0 -23
  106. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts.map +0 -1
  107. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts +0 -36
  108. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts.map +0 -1
  109. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts +0 -15
  110. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts.map +0 -1
  111. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts +0 -84
  112. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts.map +0 -1
  113. package/dist/types/src/_deprecated/components/ColumnMenu/index.d.ts +0 -3
  114. package/dist/types/src/_deprecated/components/ColumnMenu/index.d.ts.map +0 -1
  115. package/dist/types/src/_deprecated/components/Table/Table.d.ts +0 -20
  116. package/dist/types/src/_deprecated/components/Table/Table.d.ts.map +0 -1
  117. package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts +0 -116
  118. package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts.map +0 -1
  119. package/dist/types/src/_deprecated/components/Table/TableBody.d.ts +0 -12
  120. package/dist/types/src/_deprecated/components/Table/TableBody.d.ts.map +0 -1
  121. package/dist/types/src/_deprecated/components/Table/TableContext.d.ts +0 -13
  122. package/dist/types/src/_deprecated/components/Table/TableContext.d.ts.map +0 -1
  123. package/dist/types/src/_deprecated/components/Table/TableHead.d.ts +0 -9
  124. package/dist/types/src/_deprecated/components/Table/TableHead.d.ts.map +0 -1
  125. package/dist/types/src/_deprecated/components/Table/TableRootContext.d.ts +0 -17
  126. package/dist/types/src/_deprecated/components/Table/TableRootContext.d.ts.map +0 -1
  127. package/dist/types/src/_deprecated/components/Table/index.d.ts +0 -5
  128. package/dist/types/src/_deprecated/components/Table/index.d.ts.map +0 -1
  129. package/dist/types/src/_deprecated/components/Table/props.d.ts +0 -42
  130. package/dist/types/src/_deprecated/components/Table/props.d.ts.map +0 -1
  131. package/dist/types/src/_deprecated/components/index.d.ts +0 -4
  132. package/dist/types/src/_deprecated/components/index.d.ts.map +0 -1
  133. package/dist/types/src/_deprecated/helpers.d.ts +0 -91
  134. package/dist/types/src/_deprecated/helpers.d.ts.map +0 -1
  135. package/dist/types/src/_deprecated/hooks/index.d.ts +0 -5
  136. package/dist/types/src/_deprecated/hooks/index.d.ts.map +0 -1
  137. package/dist/types/src/_deprecated/hooks/useColumnSizing.d.ts +0 -12
  138. package/dist/types/src/_deprecated/hooks/useColumnSizing.d.ts.map +0 -1
  139. package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts +0 -15
  140. package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts.map +0 -1
  141. package/dist/types/src/_deprecated/hooks/usePinLastRow.d.ts +0 -3
  142. package/dist/types/src/_deprecated/hooks/usePinLastRow.d.ts.map +0 -1
  143. package/dist/types/src/_deprecated/hooks/useRowSelection.d.ts +0 -7
  144. package/dist/types/src/_deprecated/hooks/useRowSelection.d.ts.map +0 -1
  145. package/dist/types/src/_deprecated/index.d.ts +0 -8
  146. package/dist/types/src/_deprecated/index.d.ts.map +0 -1
  147. package/dist/types/src/_deprecated/schema/Schema.stories.d.ts +0 -11
  148. package/dist/types/src/_deprecated/schema/Schema.stories.d.ts.map +0 -1
  149. package/dist/types/src/_deprecated/schema/column-utils.d.ts +0 -7
  150. package/dist/types/src/_deprecated/schema/column-utils.d.ts.map +0 -1
  151. package/dist/types/src/_deprecated/schema/index.d.ts +0 -3
  152. package/dist/types/src/_deprecated/schema/index.d.ts.map +0 -1
  153. package/dist/types/src/_deprecated/schema/types.d.ts +0 -27
  154. package/dist/types/src/_deprecated/schema/types.d.ts.map +0 -1
  155. package/dist/types/src/_deprecated/theme.d.ts +0 -29
  156. package/dist/types/src/_deprecated/theme.d.ts.map +0 -1
  157. package/dist/types/src/_deprecated/translations.d.ts +0 -21
  158. package/dist/types/src/_deprecated/translations.d.ts.map +0 -1
  159. package/dist/types/src/_deprecated/types.d.ts +0 -26
  160. package/dist/types/src/_deprecated/types.d.ts.map +0 -1
  161. package/src/_deprecated/components/Cell/Cell.tsx +0 -88
  162. package/src/_deprecated/components/Cell/CellCombobox.tsx +0 -103
  163. package/src/_deprecated/components/Cell/index.ts +0 -5
  164. package/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.tsx +0 -129
  165. package/src/_deprecated/components/ColumnMenu/ColumnMenu.tsx +0 -182
  166. package/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.tsx +0 -108
  167. package/src/_deprecated/components/ColumnMenu/ColumnSettings.tsx +0 -207
  168. package/src/_deprecated/components/ColumnMenu/index.ts +0 -6
  169. package/src/_deprecated/components/Table/Table.stories.tsx +0 -508
  170. package/src/_deprecated/components/Table/Table.tsx +0 -301
  171. package/src/_deprecated/components/Table/TableBody.tsx +0 -82
  172. package/src/_deprecated/components/Table/TableContext.tsx +0 -34
  173. package/src/_deprecated/components/Table/TableHead.tsx +0 -78
  174. package/src/_deprecated/components/Table/TableRootContext.ts +0 -39
  175. package/src/_deprecated/components/Table/index.ts +0 -8
  176. package/src/_deprecated/components/Table/props.ts +0 -60
  177. package/src/_deprecated/components/index.ts +0 -7
  178. package/src/_deprecated/helpers.tsx +0 -526
  179. package/src/_deprecated/hooks/index.ts +0 -8
  180. package/src/_deprecated/hooks/useColumnSizing.ts +0 -46
  181. package/src/_deprecated/hooks/useColumnSorting.ts +0 -64
  182. package/src/_deprecated/hooks/usePinLastRow.ts +0 -47
  183. package/src/_deprecated/hooks/useRowSelection.ts +0 -40
  184. package/src/_deprecated/index.ts +0 -12
  185. package/src/_deprecated/schema/Schema.stories.tsx +0 -59
  186. package/src/_deprecated/schema/column-utils.ts +0 -54
  187. package/src/_deprecated/schema/index.ts +0 -6
  188. package/src/_deprecated/schema/types.ts +0 -40
  189. package/src/_deprecated/theme.ts +0 -82
  190. package/src/_deprecated/translations.ts +0 -26
  191. package/src/_deprecated/types.ts +0 -38
@@ -2,7 +2,7 @@ import { createRequire } from 'node:module';const require = createRequire(import
2
2
  import {
3
3
  TableSchema,
4
4
  TableType
5
- } from "./chunk-RLVVOZW5.mjs";
5
+ } from "./chunk-KKLP54L3.mjs";
6
6
 
7
7
  // packages/ui/react-ui-table/src/translations.ts
8
8
  var translationKey = "table";
@@ -37,15 +37,15 @@ var translations_default = [
37
37
  ];
38
38
 
39
39
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
40
- import React7, { forwardRef, useCallback as useCallback4, useImperativeHandle, useState as useState2, useMemo as useMemo4 } from "react";
40
+ import React7, { forwardRef, useCallback as useCallback4, useImperativeHandle, useState as useState2, useMemo as useMemo4, useEffect as useEffect2 } from "react";
41
41
  import { getValue as getValue4 } from "@dxos/echo-schema";
42
42
  import { invariant as invariant3 } from "@dxos/invariant";
43
- import { Filter, getSpace as getSpace4, fullyQualifiedId } from "@dxos/react-client/echo";
43
+ import { Filter } from "@dxos/react-client/echo";
44
44
  import { useTranslation as useTranslation3 } from "@dxos/react-ui";
45
45
  import { useAttention } from "@dxos/react-ui-attention";
46
- import { Grid, closestCell } from "@dxos/react-ui-grid";
46
+ import { closestCell, Grid } from "@dxos/react-ui-grid";
47
47
  import { mx as mx2 } from "@dxos/react-ui-theme";
48
- import { isNotFalsy } from "@dxos/util";
48
+ import { isNotFalsy, safeParseInt } from "@dxos/util";
49
49
 
50
50
  // packages/ui/react-ui-table/src/components/Table/ColumnActionsMenu.tsx
51
51
  import React from "react";
@@ -73,10 +73,10 @@ var ColumnActionsMenu = ({ model, modals }) => {
73
73
  }, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
74
74
  "data-testid": "column-clear-sort",
75
75
  onClick: () => model.sorting?.clearSort()
76
- }, t("column action clear sorting")), model.getColumnCount() > 1 && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
76
+ }, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
77
77
  "data-testid": "column-delete",
78
78
  onClick: () => model.deleteColumn(state.fieldId)
79
- }, t("column action delete")), /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
79
+ }, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
80
80
  "data-testid": "column-settings",
81
81
  onClick: () => modals.openColumnSettings()
82
82
  }, t("column action settings"))), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null))));
@@ -84,13 +84,12 @@ var ColumnActionsMenu = ({ model, modals }) => {
84
84
 
85
85
  // packages/ui/react-ui-table/src/components/Table/ColumnSettings.tsx
86
86
  import React2, { useCallback, useEffect, useMemo, useState } from "react";
87
- import { getSpace } from "@dxos/react-client/echo";
88
87
  import { DropdownMenu as DropdownMenu2 } from "@dxos/react-ui";
89
88
  import { FieldEditor } from "@dxos/react-ui-form";
90
89
  var ColumnSettings = ({ model, modals, onNewColumn }) => {
91
90
  const [newField, setNewField] = useState();
92
91
  const state = modals.state.value;
93
- const space = getSpace(model?.table);
92
+ const space = model?.space;
94
93
  useEffect(() => {
95
94
  if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
96
95
  setNewField(model.projection.createFieldProjection());
@@ -108,12 +107,12 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
108
107
  if (state?.type === "columnSettings") {
109
108
  const { mode } = state;
110
109
  if (mode.type === "edit") {
111
- return model?.table?.view?.target?.fields.find((f) => f.id === mode.fieldId);
110
+ return model?.view?.fields.find((f) => f.id === mode.fieldId);
112
111
  }
113
112
  }
114
113
  return void 0;
115
114
  }, [
116
- model?.table?.view?.target?.fields,
115
+ model?.view?.fields,
117
116
  state
118
117
  ]);
119
118
  const field = existingField ?? newField;
@@ -131,7 +130,7 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
131
130
  state,
132
131
  newField
133
132
  ]);
134
- if (!model?.table?.view?.target || !model.projection || !field) {
133
+ if (!model?.view || !model.projection || !field) {
135
134
  return null;
136
135
  }
137
136
  return /* @__PURE__ */ React2.createElement(DropdownMenu2.Root, {
@@ -142,7 +141,7 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
142
141
  }), /* @__PURE__ */ React2.createElement(DropdownMenu2.Portal, null, /* @__PURE__ */ React2.createElement(DropdownMenu2.Content, {
143
142
  classNames: "md:is-64"
144
143
  }, /* @__PURE__ */ React2.createElement(DropdownMenu2.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
145
- view: model.table.view.target,
144
+ view: model.view,
146
145
  projection: model.projection,
147
146
  field,
148
147
  registry: space?.db.schemaRegistry,
@@ -154,13 +153,13 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
154
153
  // packages/ui/react-ui-table/src/components/Table/CreateRefPanel.tsx
155
154
  import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
156
155
  import { S } from "@dxos/echo-schema";
157
- import { create, getSpace as getSpace2 } from "@dxos/react-client/echo";
156
+ import { create } from "@dxos/react-client/echo";
158
157
  import { Popover } from "@dxos/react-ui";
159
158
  import { Form } from "@dxos/react-ui-form";
160
159
  import { useGridContext } from "@dxos/react-ui-grid";
161
160
  var CreateRefPanel = ({ model, modals, __gridScope }) => {
162
161
  const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
163
- const space = getSpace2(model?.table);
162
+ const space = model?.space;
164
163
  const state = modals.state.value;
165
164
  const schema = useMemo2(() => {
166
165
  if (!space || state?.type !== "createRefPanel") {
@@ -201,7 +200,7 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
201
200
  }, [
202
201
  modals
203
202
  ]);
204
- if (!model?.table?.view || !model.projection) {
203
+ if (!model?.view || !model.projection) {
205
204
  return null;
206
205
  }
207
206
  return /* @__PURE__ */ React3.createElement(Popover.Root, {
@@ -227,7 +226,6 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
227
226
 
228
227
  // packages/ui/react-ui-table/src/components/Table/RefPanel.tsx
229
228
  import React4 from "react";
230
- import { getSpace as getSpace3 } from "@dxos/react-client/echo";
231
229
  import { Popover as Popover2 } from "@dxos/react-ui";
232
230
  import { Form as Form2 } from "@dxos/react-ui-form";
233
231
  var getRefTargetObj = (space, id) => {
@@ -239,10 +237,10 @@ var getRefTargetObj = (space, id) => {
239
237
  };
240
238
  var RefPanel = ({ model, modals }) => {
241
239
  const state = modals.state.value;
242
- const space = getSpace3(model.table);
240
+ const space = model?.space;
243
241
  const targetObj = getRefTargetObj(space, state?.type === "refPanel" ? state.targetId : void 0);
244
242
  const schema = space && state?.type === "refPanel" ? space.db.schemaRegistry.getSchema(state.typename) : void 0;
245
- if (!model.table?.view || !model.projection) {
243
+ if (!model.view || !model.projection) {
246
244
  return null;
247
245
  }
248
246
  return /* @__PURE__ */ React4.createElement(Popover2.Root, {
@@ -280,10 +278,17 @@ var RowActionsMenu = ({ model, modals }) => {
280
278
  onOpenChange: modals.close
281
279
  }, /* @__PURE__ */ React5.createElement(DropdownMenu3.VirtualTrigger, {
282
280
  virtualRef: modals.trigger
283
- }), /* @__PURE__ */ React5.createElement(DropdownMenu3.Content, null, /* @__PURE__ */ React5.createElement(DropdownMenu3.Viewport, null, /* @__PURE__ */ React5.createElement(DropdownMenu3.Item, {
281
+ }), /* @__PURE__ */ React5.createElement(DropdownMenu3.Content, null, /* @__PURE__ */ React5.createElement(DropdownMenu3.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React5.createElement(DropdownMenu3.Item, {
284
282
  "data-testid": "row-menu-delete",
285
283
  onClick: () => model.deleteRow(state.rowIndex)
286
- }, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ React5.createElement(DropdownMenu3.Arrow, null)));
284
+ }, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React5.createElement(DropdownMenu3.Item, {
285
+ key: action.id,
286
+ "data-testid": `row-action-${action.id}`,
287
+ onClick: () => {
288
+ modals.close();
289
+ model.handleRowAction(action.id, state.rowIndex);
290
+ }
291
+ }, t(action.translationKey)))), /* @__PURE__ */ React5.createElement(DropdownMenu3.Arrow, null)));
287
292
  };
288
293
 
289
294
  // packages/ui/react-ui-table/src/model/table-model.ts
@@ -291,32 +296,105 @@ import { computed as computed3, effect as effect2, signal as signal3 } from "@pr
291
296
  import { Resource as Resource2 } from "@dxos/context";
292
297
  import { FormatEnum as FormatEnum3, getValue as getValue2, setValue } from "@dxos/echo-schema";
293
298
  import { invariant } from "@dxos/invariant";
294
- import { isReactiveObject, makeRef as makeRef2 } from "@dxos/live-object";
295
- import { PublicKey as PublicKey2 } from "@dxos/react-client";
299
+ import { isReactiveObject, makeRef as makeRef3 } from "@dxos/live-object";
296
300
  import { formatForEditing, parseValue } from "@dxos/react-ui-form";
297
301
 
298
302
  // packages/ui/react-ui-table/src/model/selection-model.ts
299
303
  import { computed, effect, signal } from "@preact/signals-core";
300
304
  import { Resource } from "@dxos/context";
301
305
 
306
+ // packages/ui/react-ui-table/src/util/dynamic-table.ts
307
+ import { create as create2, makeRef } from "@dxos/live-object";
308
+ import { createView, getSchemaFromPropertyDefinitions, ViewProjection } from "@dxos/schema";
309
+ var getBaseSchems = ({ typename, properties, jsonSchema, schema }) => {
310
+ if (typename && properties) {
311
+ const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
312
+ return {
313
+ typename: schema2.typename,
314
+ jsonSchema: schema2.jsonSchema
315
+ };
316
+ } else if (schema) {
317
+ return {
318
+ typename: schema.typename,
319
+ jsonSchema: schema.jsonSchema
320
+ };
321
+ } else if (typename && jsonSchema) {
322
+ return {
323
+ typename,
324
+ jsonSchema
325
+ };
326
+ } else {
327
+ throw new Error("invalid properties");
328
+ }
329
+ };
330
+ var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
331
+ const view = createView({
332
+ name: "dynamic-table",
333
+ typename,
334
+ jsonSchema,
335
+ ...properties && {
336
+ fields: properties.map((property) => property.name)
337
+ }
338
+ });
339
+ const table = create2(TableType, {
340
+ name: "dynamic-table",
341
+ view: makeRef(view)
342
+ });
343
+ const projection = new ViewProjection(jsonSchema, view);
344
+ if (properties && view.fields) {
345
+ setProperties(view, projection, properties);
346
+ }
347
+ return {
348
+ table,
349
+ projection
350
+ };
351
+ };
352
+ var setProperties = (view, projection, properties) => {
353
+ for (const property of properties) {
354
+ const field = view.fields.find((field2) => field2.path === property.name);
355
+ if (field) {
356
+ if (property.size !== void 0) {
357
+ field.size = property.size;
358
+ }
359
+ if (property.title !== void 0) {
360
+ const fieldProjection = projection.getFieldProjection(field.id);
361
+ projection.setFieldProjection({
362
+ ...fieldProjection,
363
+ props: {
364
+ ...fieldProjection.props,
365
+ title: property.title
366
+ }
367
+ });
368
+ }
369
+ if (property.sort) {
370
+ const fieldId = field.id;
371
+ view.query.sort = [
372
+ {
373
+ fieldId,
374
+ direction: property.sort
375
+ }
376
+ ];
377
+ }
378
+ }
379
+ }
380
+ };
381
+
302
382
  // packages/ui/react-ui-table/src/util/signals.ts
303
383
  var touch = (value) => value;
304
384
 
305
385
  // packages/ui/react-ui-table/src/util/table.ts
306
386
  import { AST, Format, FormatEnum, S as S2, TypedObject, TypeEnum } from "@dxos/echo-schema";
307
387
  import { PublicKey } from "@dxos/react-client";
308
- import { create as create2, makeRef } from "@dxos/react-client/echo";
309
- import { createFieldId, createView, getSchemaProperties, ViewProjection } from "@dxos/schema";
310
- var initializeTable = async ({ space, table, initialRow = true, initialSchema }) => {
311
- if (initialSchema) {
312
- const schema = await space.db.schemaRegistry.query({
313
- typename: initialSchema
314
- }).firstOrUndefined();
388
+ import { create as create3, makeRef as makeRef2 } from "@dxos/react-client/echo";
389
+ import { createFieldId, createView as createView2, getSchemaProperties, ViewProjection as ViewProjection2 } from "@dxos/schema";
390
+ var initializeTable = async ({ client, space, table, typename, initialRow = true }) => {
391
+ if (typename) {
392
+ const schema = await space.db.graph.getSchemaByTypename(typename, space.db);
315
393
  if (!schema) {
316
- throw new Error(`Schema not found: ${initialSchema}`);
394
+ throw new Error(`Schema not found: ${typename}`);
317
395
  }
318
396
  const fields = getSchemaProperties(schema.ast).filter((prop) => prop.format !== FormatEnum.Ref).map((prop) => prop.name);
319
- table.view = makeRef(createView({
397
+ table.view = makeRef2(createView2({
320
398
  // TODO(ZaymonFC): Don't hardcode name?
321
399
  name: "View",
322
400
  typename: schema.typename,
@@ -325,68 +403,74 @@ var initializeTable = async ({ space, table, initialRow = true, initialSchema })
325
403
  }));
326
404
  return schema;
327
405
  } else {
328
- const ContactSchema = TypedObject({
329
- typename: `example.com/type/${PublicKey.random().truncate()}`,
330
- version: "0.1.0"
331
- })({
332
- name: S2.optional(S2.String).annotations({
333
- [AST.TitleAnnotationId]: "Name"
334
- }),
335
- active: S2.optional(S2.Boolean),
336
- email: S2.optional(Format.Email),
337
- salary: S2.optional(Format.Currency()).annotations({
338
- [AST.TitleAnnotationId]: "Salary"
339
- })
340
- });
341
- const [contactSchema] = await space.db.schemaRegistry.register([
406
+ const [schema] = await space.db.schemaRegistry.register([
342
407
  ContactSchema
343
408
  ]);
344
- table.view = makeRef(createView({
409
+ const fields = ContactFields;
410
+ table.view = makeRef2(createView2({
345
411
  name: "View",
346
- typename: contactSchema.typename,
347
- jsonSchema: contactSchema.jsonSchema,
348
- fields: [
349
- "name",
350
- "email",
351
- "salary",
352
- "active"
353
- ]
412
+ typename: schema.typename,
413
+ jsonSchema: schema.jsonSchema,
414
+ fields
354
415
  }));
355
- const projection = new ViewProjection(contactSchema, table.view.target);
356
- projection.setFieldProjection({
357
- field: {
358
- id: table.view.target.fields.find((f) => f.path === "salary").id,
359
- path: "salary",
360
- size: 150
361
- }
362
- });
363
- projection.setFieldProjection({
364
- field: {
365
- id: table.view.target.fields.find((f) => f.path === "active").id,
366
- path: "active",
367
- size: 100
368
- }
369
- });
370
- projection.setFieldProjection({
371
- field: {
372
- id: createFieldId(),
373
- path: "manager",
374
- referencePath: "name"
375
- },
376
- props: {
377
- property: "manager",
378
- type: TypeEnum.Ref,
379
- format: FormatEnum.Ref,
380
- referenceSchema: contactSchema.typename,
381
- title: "Manager"
382
- }
383
- });
416
+ createProjection(schema, table.view.target);
384
417
  if (initialRow) {
385
- space.db.add(create2(contactSchema, {}));
418
+ space.db.add(create3(schema, {}));
386
419
  }
387
- return contactSchema;
420
+ return schema;
388
421
  }
389
422
  };
423
+ var ContactSchema = TypedObject({
424
+ typename: `example.com/type/${PublicKey.random().truncate()}`,
425
+ version: "0.1.0"
426
+ })({
427
+ name: S2.optional(S2.String).annotations({
428
+ [AST.TitleAnnotationId]: "Name"
429
+ }),
430
+ active: S2.optional(S2.Boolean),
431
+ email: S2.optional(Format.Email),
432
+ salary: S2.optional(Format.Currency()).annotations({
433
+ [AST.TitleAnnotationId]: "Salary"
434
+ })
435
+ });
436
+ var ContactFields = [
437
+ "name",
438
+ "email",
439
+ "salary",
440
+ "active"
441
+ ];
442
+ var createProjection = (schema, view) => {
443
+ const projection = new ViewProjection2(schema.jsonSchema, view);
444
+ projection.setFieldProjection({
445
+ field: {
446
+ id: view.fields.find((f) => f.path === "salary").id,
447
+ path: "salary",
448
+ size: 150
449
+ }
450
+ });
451
+ projection.setFieldProjection({
452
+ field: {
453
+ id: view.fields.find((f) => f.path === "active").id,
454
+ path: "active",
455
+ size: 100
456
+ }
457
+ });
458
+ projection.setFieldProjection({
459
+ field: {
460
+ id: createFieldId(),
461
+ path: "manager",
462
+ referencePath: "name"
463
+ },
464
+ props: {
465
+ property: "manager",
466
+ type: TypeEnum.Ref,
467
+ format: FormatEnum.Ref,
468
+ referenceSchema: schema.typename,
469
+ title: "Manager"
470
+ }
471
+ });
472
+ return projection;
473
+ };
390
474
 
391
475
  // packages/ui/react-ui-table/src/util/table-buttons.ts
392
476
  var BUTTON_IDENTIFIERS = {
@@ -519,7 +603,7 @@ var renderAttributes = (data) => {
519
603
  var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
520
604
  return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
521
605
  };
522
- var renderCheckbox = ({ rowIndex, header = false, checked = false, disabled = false }) => {
606
+ var CheckboxStory = ({ rowIndex, header = false, checked = false, disabled = false }) => {
523
607
  const attrs = {
524
608
  [CONTROL_IDENTIFIERS.checkbox]: "",
525
609
  "data-row-index": rowIndex.toString(),
@@ -529,7 +613,7 @@ var renderCheckbox = ({ rowIndex, header = false, checked = false, disabled = fa
529
613
  };
530
614
  return renderInput(BASE_CLASSES.checkbox, attrs, checked, disabled, true, "table-selection");
531
615
  };
532
- var renderSwitch = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
616
+ var SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
533
617
  const attrs = {
534
618
  [CONTROL_IDENTIFIERS.switch]: "",
535
619
  "data-row-index": rowIndex.toString(),
@@ -540,7 +624,7 @@ var renderSwitch = ({ colIndex, rowIndex, checked = false, disabled = false }) =
540
624
  var tableControls = {
541
625
  checkbox: {
542
626
  attr: CONTROL_IDENTIFIERS.checkbox,
543
- render: renderCheckbox,
627
+ render: CheckboxStory,
544
628
  getData: (el) => ({
545
629
  type: "checkbox",
546
630
  rowIndex: Number(el.getAttribute("data-row-index")),
@@ -549,7 +633,7 @@ var tableControls = {
549
633
  },
550
634
  switch: {
551
635
  attr: CONTROL_IDENTIFIERS.switch,
552
- render: renderSwitch,
636
+ render: SwitchStory,
553
637
  getData: (el) => ({
554
638
  type: "switch",
555
639
  rowIndex: Number(el.getAttribute("data-row-index")),
@@ -560,9 +644,10 @@ var tableControls = {
560
644
 
561
645
  // packages/ui/react-ui-table/src/model/selection-model.ts
562
646
  var SelectionModel = class extends Resource {
563
- constructor(_rows, _onSelectionChanged) {
647
+ constructor(_rows, _selectionMode, _onSelectionChanged) {
564
648
  super();
565
649
  this._rows = _rows;
650
+ this._selectionMode = _selectionMode;
566
651
  this._onSelectionChanged = _onSelectionChanged;
567
652
  this._selection = signal(/* @__PURE__ */ new Set());
568
653
  this._validSelectedIds = computed(() => {
@@ -600,6 +685,9 @@ var SelectionModel = class extends Resource {
600
685
  if (newSelection.has(row.id)) {
601
686
  newSelection.delete(row.id);
602
687
  } else {
688
+ if (this._selectionMode === "single") {
689
+ newSelection.clear();
690
+ }
603
691
  newSelection.add(row.id);
604
692
  }
605
693
  this._selection.value = newSelection;
@@ -636,6 +724,9 @@ var SelectionModel = class extends Resource {
636
724
  get allRowsSeleted() {
637
725
  return this._allSelected;
638
726
  }
727
+ get selectionMode() {
728
+ return this._selectionMode;
729
+ }
639
730
  };
640
731
 
641
732
  // packages/ui/react-ui-table/src/model/table-sorting.ts
@@ -805,13 +896,20 @@ var TableSorting = class {
805
896
 
806
897
  // packages/ui/react-ui-table/src/model/table-model.ts
807
898
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
899
+ var defaultFeatures = {
900
+ selection: {
901
+ enabled: true,
902
+ mode: "multiple"
903
+ },
904
+ dataEditable: false,
905
+ schemaEditable: false
906
+ };
808
907
  var TableModel = class extends Resource2 {
809
- constructor({ table, projection, sorting = [], pinnedRows = {
908
+ constructor({ id, space, view, projection, features = {}, sorting = [], pinnedRows = {
810
909
  top: [],
811
910
  bottom: []
812
- }, onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChanged }) {
911
+ }, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
813
912
  super();
814
- this.id = `table-model-${PublicKey2.random().truncate()}`;
815
913
  this._visibleRange = signal3({
816
914
  start: {
817
915
  row: 0,
@@ -830,7 +928,7 @@ var TableModel = class extends Resource2 {
830
928
  this._rows.value = obj;
831
929
  };
832
930
  this.getRowCount = () => this._rows.value.length;
833
- this.getColumnCount = () => this.table.view?.target?.fields.length ?? 0;
931
+ this.getColumnCount = () => this._view?.fields.length ?? 0;
834
932
  this.insertRow = (rowIndex) => {
835
933
  const row = rowIndex !== void 0 ? this._sorting.getDataIndex(rowIndex) : this._rows.value.length;
836
934
  this._onInsertRow?.(row);
@@ -839,7 +937,7 @@ var TableModel = class extends Resource2 {
839
937
  const row = this._sorting.getDataIndex(rowIndex);
840
938
  const obj = this._rows.value[row];
841
939
  const objectsToDelete = [];
842
- if (this._selection.hasSelection.value) {
940
+ if (this.features.selection.enabled && this._selection.hasSelection.value) {
843
941
  const selectedRows = this._selection.getSelectedRows();
844
942
  objectsToDelete.push(...selectedRows);
845
943
  } else {
@@ -847,8 +945,18 @@ var TableModel = class extends Resource2 {
847
945
  }
848
946
  this._onDeleteRows?.(row, objectsToDelete);
849
947
  };
948
+ this.handleRowAction = (actionId, rowIndex) => {
949
+ if (!this._onRowAction) {
950
+ return;
951
+ }
952
+ const row = this._sorting.getDataIndex(rowIndex);
953
+ const data = this._rows.value[row];
954
+ if (data) {
955
+ this._onRowAction(actionId, data);
956
+ }
957
+ };
850
958
  this.getCellData = ({ col, row }) => {
851
- const fields = this.table.view?.target?.fields ?? [];
959
+ const fields = this._view?.fields ?? [];
852
960
  if (col < 0 || col >= fields.length) {
853
961
  return void 0;
854
962
  }
@@ -877,7 +985,7 @@ var TableModel = class extends Resource2 {
877
985
  };
878
986
  this.setCellData = ({ col, row }, value) => {
879
987
  const rowIdx = this._sorting.getDataIndex(row);
880
- const fields = this.table.view?.target?.fields ?? [];
988
+ const fields = this._view?.fields ?? [];
881
989
  if (col < 0 || col >= fields.length) {
882
990
  return;
883
991
  }
@@ -886,7 +994,7 @@ var TableModel = class extends Resource2 {
886
994
  switch (props.format) {
887
995
  case FormatEnum3.Ref: {
888
996
  if (isReactiveObject(value)) {
889
- setValue(this._rows.value[rowIdx], field.path, makeRef2(value));
997
+ setValue(this._rows.value[rowIdx], field.path, makeRef3(value));
890
998
  }
891
999
  break;
892
1000
  }
@@ -900,22 +1008,45 @@ var TableModel = class extends Resource2 {
900
1008
  }
901
1009
  }
902
1010
  };
903
- this._table = table;
1011
+ this._id = id;
1012
+ this._space = space;
1013
+ this._view = view;
904
1014
  this._projection = projection;
905
- this._sorting = new TableSorting(this._rows, table.view?.target, projection);
1015
+ this._features = {
1016
+ ...defaultFeatures,
1017
+ ...features
1018
+ };
1019
+ invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
1020
+ F: __dxlog_file,
1021
+ L: 114,
1022
+ S: this,
1023
+ A: [
1024
+ "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
1025
+ "'Single selection is not compatible with editable tables.'"
1026
+ ]
1027
+ });
1028
+ this._sorting = new TableSorting(this._rows, this._view, projection);
906
1029
  if (sorting.length > 0) {
907
1030
  const [sort] = sorting;
908
1031
  this._sorting.setSort(sort.fieldId, sort.direction);
909
1032
  }
910
1033
  this._pinnedRows = pinnedRows;
1034
+ this._rowActions = rowActions;
911
1035
  this._onInsertRow = onInsertRow;
912
1036
  this._onDeleteRows = onDeleteRows;
913
1037
  this._onDeleteColumn = onDeleteColumn;
914
1038
  this._onCellUpdate = onCellUpdate;
915
- this._onRowOrderChanged = onRowOrderChanged;
1039
+ this._onRowOrderChange = onRowOrderChange;
1040
+ this._onRowAction = onRowAction;
1041
+ }
1042
+ get id() {
1043
+ return this._id;
916
1044
  }
917
- get table() {
918
- return this._table;
1045
+ get space() {
1046
+ return this._space;
1047
+ }
1048
+ get view() {
1049
+ return this._view;
919
1050
  }
920
1051
  get projection() {
921
1052
  return this._projection;
@@ -923,19 +1054,31 @@ var TableModel = class extends Resource2 {
923
1054
  get rows() {
924
1055
  return this._sorting.sortedRows;
925
1056
  }
1057
+ get features() {
1058
+ return this._features;
1059
+ }
926
1060
  /**
927
1061
  * @reactive
928
1062
  */
929
1063
  get sorting() {
930
1064
  return this._sorting;
931
1065
  }
1066
+ /**
1067
+ * Gets the row data at the specified display index.
1068
+ */
1069
+ getRowAt(displayIndex) {
1070
+ if (displayIndex < 0 || displayIndex >= this._sorting.sortedRows.value.length) {
1071
+ return void 0;
1072
+ }
1073
+ return this._sorting.sortedRows.value[displayIndex];
1074
+ }
932
1075
  get pinnedRows() {
933
1076
  return this._pinnedRows;
934
1077
  }
935
1078
  get columnMeta() {
936
1079
  invariant(this._columnMeta, void 0, {
937
1080
  F: __dxlog_file,
938
- L: 117,
1081
+ L: 183,
939
1082
  S: this,
940
1083
  A: [
941
1084
  "this._columnMeta",
@@ -951,18 +1094,21 @@ var TableModel = class extends Resource2 {
951
1094
  get isViewDirty() {
952
1095
  return this._sorting.isDirty;
953
1096
  }
1097
+ get rowActions() {
1098
+ return this._rowActions;
1099
+ }
954
1100
  //
955
1101
  // Initialisation
956
1102
  //
957
1103
  async _open() {
958
1104
  this.initializeColumnMeta();
959
1105
  this.initializeEffects();
960
- this._selection = new SelectionModel(this._sorting.sortedRows, () => this._onRowOrderChanged?.());
1106
+ this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", () => this._onRowOrderChange?.());
961
1107
  await this._selection.open(this._ctx);
962
1108
  }
963
1109
  initializeColumnMeta() {
964
1110
  this._columnMeta = computed3(() => {
965
- const fields = this._table.view?.target?.fields ?? [];
1111
+ const fields = this._view?.fields ?? [];
966
1112
  const meta = Object.fromEntries(fields.map((field, index) => [
967
1113
  index,
968
1114
  {
@@ -990,7 +1136,7 @@ var TableModel = class extends Resource2 {
990
1136
  initializeEffects() {
991
1137
  const rowOrderWatcher = effect2(() => {
992
1138
  touch(this._sorting.sortedRows.value);
993
- this._onRowOrderChanged?.();
1139
+ this._onRowOrderChange?.();
994
1140
  });
995
1141
  this._ctx.onDispose(rowOrderWatcher);
996
1142
  const rowEffectManager = effect2(() => {
@@ -999,7 +1145,7 @@ var TableModel = class extends Resource2 {
999
1145
  for (let row = start.row; row <= end.row; row++) {
1000
1146
  rowEffects.push(effect2(() => {
1001
1147
  const obj = this._sorting.sortedRows.value[row];
1002
- this?._table?.view?.target?.fields.forEach((field) => touch(getValue2(obj, field.path)));
1148
+ this._view?.fields.forEach((field) => touch(getValue2(obj, field.path)));
1003
1149
  this._onCellUpdate?.({
1004
1150
  row,
1005
1151
  col: start.col,
@@ -1018,7 +1164,7 @@ var TableModel = class extends Resource2 {
1018
1164
  */
1019
1165
  updateCellData({ col, row }, update) {
1020
1166
  const dataRow = this._sorting.getDataIndex(row);
1021
- const fields = this.table.view?.target?.fields ?? [];
1167
+ const fields = this._view?.fields ?? [];
1022
1168
  const field = fields[col];
1023
1169
  const value = getValue2(this._rows.value[dataRow], field.path);
1024
1170
  const updatedValue = update(value);
@@ -1028,10 +1174,10 @@ var TableModel = class extends Resource2 {
1028
1174
  // Column Operations
1029
1175
  //
1030
1176
  deleteColumn(fieldId) {
1031
- if (!this.table.view) {
1177
+ if (!this._view) {
1032
1178
  return;
1033
1179
  }
1034
- const field = this.table.view.target?.fields.find((field2) => field2.id === fieldId);
1180
+ const field = this._view?.fields.find((field2) => field2.id === fieldId);
1035
1181
  if (field && this._onDeleteColumn) {
1036
1182
  this._onDeleteColumn(field.id);
1037
1183
  }
@@ -1040,7 +1186,7 @@ var TableModel = class extends Resource2 {
1040
1186
  // Resize
1041
1187
  //
1042
1188
  setColumnWidth(columnIndex, width) {
1043
- const fields = this.table.view?.target?.fields ?? [];
1189
+ const fields = this._view?.fields ?? [];
1044
1190
  if (columnIndex < fields.length) {
1045
1191
  const newWidth = Math.max(0, width);
1046
1192
  const field = fields[columnIndex];
@@ -1159,7 +1305,7 @@ var ModalController = class {
1159
1305
  // packages/ui/react-ui-table/src/model/table-presentation.ts
1160
1306
  import { signal as signal5 } from "@preact/signals-core";
1161
1307
  import { FormatEnum as FormatEnum4, getValue as getValue3 } from "@dxos/echo-schema";
1162
- import { cellClassesForFieldType, cellClassesForRowSelection, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
1308
+ import { cellClassesForFieldType, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
1163
1309
  import { toPlaneCellIndex } from "@dxos/react-ui-grid";
1164
1310
  import { mx } from "@dxos/react-ui-theme";
1165
1311
  import { VIEW_FIELD_LIMIT } from "@dxos/schema";
@@ -1178,27 +1324,40 @@ var TablePresentation = class {
1178
1324
  this._visibleRange = _visibleRange;
1179
1325
  }
1180
1326
  getCells(range, plane) {
1327
+ let cells;
1181
1328
  switch (plane) {
1182
1329
  case "grid":
1183
1330
  this._visibleRange.value = range;
1184
- return this.getMainGridCells(range);
1331
+ cells = this.getMainGridCells(range);
1332
+ break;
1185
1333
  case "frozenRowsStart":
1186
- return this.getHeaderCells(range);
1334
+ cells = this.getHeaderCells(range);
1335
+ break;
1187
1336
  case "frozenColsStart":
1188
- return this.getSelectionColumnCells(range);
1337
+ cells = this.getSelectionColumnCells(range);
1338
+ break;
1189
1339
  case "frozenColsEnd":
1190
- return this.getActionColumnCells(range);
1340
+ cells = this.getActionColumnCells(range);
1341
+ break;
1191
1342
  case "fixedStartStart":
1192
- return this.getSelectAllCell();
1343
+ cells = this.getSelectAllCell();
1344
+ break;
1193
1345
  case "fixedStartEnd":
1194
- return this.getNewColumnCell();
1346
+ cells = this.getNewColumnCell();
1347
+ break;
1195
1348
  default:
1196
- return {};
1349
+ cells = {};
1197
1350
  }
1351
+ if (plane === "grid" && this.model.features.dataEditable === false) {
1352
+ Object.values(cells).forEach((cell) => {
1353
+ cell.readonly = "text-select";
1354
+ });
1355
+ }
1356
+ return cells;
1198
1357
  }
1199
1358
  getMainGridCells(range) {
1200
1359
  const cells = {};
1201
- const fields = this.model.table.view?.target?.fields ?? [];
1360
+ const fields = this.model.view?.fields ?? [];
1202
1361
  const addCell = (obj, field, colIndex, displayIndex) => {
1203
1362
  const { props } = this.model.projection.getFieldProjection(field.id);
1204
1363
  const cell = {
@@ -1209,7 +1368,8 @@ var TablePresentation = class {
1209
1368
  }
1210
1369
  switch (props.format) {
1211
1370
  case FormatEnum4.Boolean:
1212
- case FormatEnum4.SingleSelect: {
1371
+ case FormatEnum4.SingleSelect:
1372
+ case FormatEnum4.MultiSelect: {
1213
1373
  return "";
1214
1374
  }
1215
1375
  case FormatEnum4.Ref: {
@@ -1236,7 +1396,7 @@ var TablePresentation = class {
1236
1396
  if (formatClasses) {
1237
1397
  classes.push(formatClasses);
1238
1398
  }
1239
- const rowSelectionClasses = cellClassesForRowSelection(this.model.selection.isObjectSelected(obj));
1399
+ const rowSelectionClasses = cellClassesForRowSelection(this.model.selection.isObjectSelected(obj), this.model.selection.selectionMode);
1240
1400
  if (rowSelectionClasses) {
1241
1401
  classes.push(rowSelectionClasses);
1242
1402
  }
@@ -1259,7 +1419,7 @@ var TablePresentation = class {
1259
1419
  rowIndex: displayIndex,
1260
1420
  checked: value ?? false
1261
1421
  });
1262
- cell.readonly = true;
1422
+ cell.readonly = "no-text-select";
1263
1423
  }
1264
1424
  if (props.format === FormatEnum4.SingleSelect) {
1265
1425
  const value = getValue3(obj, field.path);
@@ -1271,6 +1431,22 @@ var TablePresentation = class {
1271
1431
  }
1272
1432
  }
1273
1433
  }
1434
+ if (props.format === FormatEnum4.MultiSelect) {
1435
+ const values = getValue3(obj, field.path);
1436
+ const options = this.model.projection.getFieldProjection(field.id).props.options;
1437
+ if (options && values && values.length > 0) {
1438
+ const tags = values.map((value) => {
1439
+ const option = options.find((o) => o.id === value);
1440
+ if (option) {
1441
+ return `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
1442
+ }
1443
+ return null;
1444
+ }).filter(Boolean).join(" ");
1445
+ if (tags) {
1446
+ cell.accessoryHtml = tags;
1447
+ }
1448
+ }
1449
+ }
1274
1450
  const idx = toPlaneCellIndex({
1275
1451
  col: colIndex,
1276
1452
  row: displayIndex
@@ -1290,7 +1466,7 @@ var TablePresentation = class {
1290
1466
  }
1291
1467
  getHeaderCells(range) {
1292
1468
  const cells = {};
1293
- const fields = this.model.table.view?.target?.fields ?? [];
1469
+ const fields = this.model.view?.fields ?? [];
1294
1470
  for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1295
1471
  const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
1296
1472
  const sorting = this.model.sorting?.sorting;
@@ -1321,13 +1497,13 @@ var TablePresentation = class {
1321
1497
  const cells = {};
1322
1498
  for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1323
1499
  const isSelected = this.model.selection.isRowIndexSelected(row);
1324
- const classes = cellClassesForRowSelection(isSelected);
1500
+ const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
1325
1501
  cells[toPlaneCellIndex({
1326
1502
  col: 0,
1327
1503
  row
1328
1504
  })] = {
1329
1505
  value: "",
1330
- readonly: true,
1506
+ readonly: "no-text-select",
1331
1507
  className: classes ? mx(classes) : void 0,
1332
1508
  accessoryHtml: tableControls.checkbox.render({
1333
1509
  rowIndex: row,
@@ -1341,7 +1517,7 @@ var TablePresentation = class {
1341
1517
  const cells = {};
1342
1518
  for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1343
1519
  const isSelected = this.model.selection.isRowIndexSelected(row);
1344
- const classes = cellClassesForRowSelection(isSelected);
1520
+ const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
1345
1521
  cells[toPlaneCellIndex({
1346
1522
  col: 0,
1347
1523
  row
@@ -1357,6 +1533,18 @@ var TablePresentation = class {
1357
1533
  return cells;
1358
1534
  }
1359
1535
  getSelectAllCell() {
1536
+ if (!this.model.features.selection.enabled || this.model.selection.selectionMode === "single") {
1537
+ return {
1538
+ [toPlaneCellIndex({
1539
+ col: 0,
1540
+ row: 0
1541
+ })]: {
1542
+ className: "!bg-gridHeader",
1543
+ readonly: true,
1544
+ value: ""
1545
+ }
1546
+ };
1547
+ }
1360
1548
  return {
1361
1549
  [toPlaneCellIndex({
1362
1550
  col: 0,
@@ -1379,9 +1567,9 @@ var TablePresentation = class {
1379
1567
  col: 0,
1380
1568
  row: 0
1381
1569
  })]: {
1382
- accessoryHtml: tableButtons.addColumn.render({
1383
- disabled: (this.model.table.view?.target?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT
1384
- }),
1570
+ accessoryHtml: this.model.features.schemaEditable ? tableButtons.addColumn.render({
1571
+ disabled: (this.model.view?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT
1572
+ }) : void 0,
1385
1573
  className: "!bg-gridHeader",
1386
1574
  readonly: true,
1387
1575
  value: ""
@@ -1389,12 +1577,37 @@ var TablePresentation = class {
1389
1577
  };
1390
1578
  }
1391
1579
  };
1580
+ var cellClassesForRowSelection = (selected, selectionMode) => {
1581
+ if (!selected) {
1582
+ if (selectionMode === "single") {
1583
+ return [
1584
+ "!cursor-pointer"
1585
+ ];
1586
+ } else {
1587
+ return void 0;
1588
+ }
1589
+ }
1590
+ switch (selectionMode) {
1591
+ case "single":
1592
+ return [
1593
+ "!bg-currentRelated hover:bg-hoverSurface",
1594
+ "!cursor-pointer"
1595
+ ];
1596
+ case "multiple":
1597
+ return [
1598
+ "!bg-gridCellSelected"
1599
+ ];
1600
+ }
1601
+ };
1392
1602
 
1393
1603
  // packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx
1394
1604
  import React6, { useCallback as useCallback3, useMemo as useMemo3, useRef } from "react";
1395
1605
  import { FormatEnum as FormatEnum5 } from "@dxos/echo-schema";
1396
1606
  import { invariant as invariant2 } from "@dxos/invariant";
1607
+ import { useThemeContext } from "@dxos/react-ui";
1608
+ import { createMarkdownExtensions } from "@dxos/react-ui-editor";
1397
1609
  import { cellQuery, editorKeys, parseCellIndex, useGridContext as useGridContext2, GridCellEditor } from "@dxos/react-ui-grid";
1610
+ import { tagPickerExtension, createLinks } from "@dxos/react-ui-tag-picker";
1398
1611
 
1399
1612
  // packages/ui/react-ui-table/src/components/TableCellEditor/extension.ts
1400
1613
  import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
@@ -1446,6 +1659,7 @@ var isCreateOption = (data) => typeof data === "object" && data[newValue];
1446
1659
  var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }) => {
1447
1660
  const { id: gridId, editing, setEditing } = useGridContext2("TableCellEditor", __gridScope);
1448
1661
  const suppressNextBlur = useRef(false);
1662
+ const { themeMode } = useThemeContext();
1449
1663
  const fieldProjection = useMemo3(() => {
1450
1664
  if (!model || !editing) {
1451
1665
  return;
@@ -1455,7 +1669,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1455
1669
  const fieldProjection2 = model.projection.getFieldProjection(field.id);
1456
1670
  invariant2(fieldProjection2, void 0, {
1457
1671
  F: __dxlog_file3,
1458
- L: 67,
1672
+ L: 71,
1459
1673
  S: void 0,
1460
1674
  A: [
1461
1675
  "fieldProjection",
@@ -1478,7 +1692,10 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1478
1692
  setEditing(null);
1479
1693
  }, [
1480
1694
  model,
1481
- editing
1695
+ editing,
1696
+ onEnter,
1697
+ onFocus,
1698
+ setEditing
1482
1699
  ]);
1483
1700
  const handleBlur = useCallback3((value) => {
1484
1701
  if (!model || !editing) {
@@ -1510,9 +1727,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1510
1727
  editing,
1511
1728
  onFocus,
1512
1729
  onEnter,
1513
- fieldProjection,
1514
- determineNavigationAxis,
1515
- determineNavigationDelta
1730
+ fieldProjection
1516
1731
  ]);
1517
1732
  const extension = useMemo3(() => {
1518
1733
  if (!fieldProjection) {
@@ -1526,6 +1741,37 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1526
1741
  }
1527
1742
  })
1528
1743
  ];
1744
+ const format = fieldProjection.props.format;
1745
+ if (format === FormatEnum5.SingleSelect || format === FormatEnum5.MultiSelect) {
1746
+ extension2.push(createMarkdownExtensions({
1747
+ themeMode
1748
+ }));
1749
+ const options = fieldProjection.props.options || [];
1750
+ const mode = format === FormatEnum5.SingleSelect ? "single-select" : "multi-select";
1751
+ extension2.push(tagPickerExtension({
1752
+ mode,
1753
+ inGrid: true,
1754
+ onSearch: (text, selectedIds) => {
1755
+ return options.filter((option) => selectedIds.indexOf(option.id) === -1 && (text.length === 0 || option.title.toLowerCase().includes(text.toLowerCase()))).map((option) => ({
1756
+ id: option.id,
1757
+ label: option.title,
1758
+ hue: option.color
1759
+ }));
1760
+ },
1761
+ onUpdate: (ids) => {
1762
+ if (model && editing) {
1763
+ if (ids.length === 0) {
1764
+ return;
1765
+ }
1766
+ if (mode === "single-select") {
1767
+ handleEnter(ids[0]);
1768
+ } else {
1769
+ handleEnter(ids);
1770
+ }
1771
+ }
1772
+ }
1773
+ }));
1774
+ }
1529
1775
  if (onQuery) {
1530
1776
  switch (fieldProjection.props.format) {
1531
1777
  case FormatEnum5.Ref: {
@@ -1561,11 +1807,49 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1561
1807
  modals,
1562
1808
  editing,
1563
1809
  fieldProjection,
1564
- handleClose
1810
+ handleClose,
1811
+ themeMode
1565
1812
  ]);
1566
1813
  const getCellContent = useCallback3(() => {
1567
1814
  if (model && editing) {
1568
- const value = model.getCellData(parseCellIndex(editing.index));
1815
+ const cell = parseCellIndex(editing.index);
1816
+ const { col } = cell;
1817
+ const field = model.projection.view.fields[col];
1818
+ const fieldProjection2 = model.projection.getFieldProjection(field.id);
1819
+ if (fieldProjection2?.props.format === FormatEnum5.SingleSelect || fieldProjection2?.props.format === FormatEnum5.MultiSelect) {
1820
+ const value2 = model.getCellData(cell);
1821
+ if (value2 !== void 0) {
1822
+ const options = fieldProjection2.props.options || [];
1823
+ if (fieldProjection2.props.format === FormatEnum5.MultiSelect && Array.isArray(value2)) {
1824
+ const tagItems = value2.map((id) => {
1825
+ const option = options.find((o) => o.id === id);
1826
+ if (option) {
1827
+ return {
1828
+ id,
1829
+ label: option.title,
1830
+ hue: option.color
1831
+ };
1832
+ }
1833
+ return void 0;
1834
+ }).filter((item) => item !== void 0);
1835
+ return createLinks(tagItems);
1836
+ } else {
1837
+ const option = options.find((o) => o.id === value2);
1838
+ if (option) {
1839
+ const tagItem = {
1840
+ id: value2,
1841
+ label: option.title,
1842
+ hue: option.color
1843
+ };
1844
+ return createLinks([
1845
+ tagItem
1846
+ ]);
1847
+ }
1848
+ }
1849
+ }
1850
+ return "";
1851
+ }
1852
+ const value = model.getCellData(cell);
1569
1853
  return value !== void 0 ? String(value) : "";
1570
1854
  }
1571
1855
  }, [
@@ -1607,27 +1891,40 @@ var determineNavigationDelta = ({ key, shift }) => {
1607
1891
  var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
1608
1892
  var inlineEndLine = "[&>.dx-grid]:relative [&>.dx-grid]:after:absolute [&>.dx-grid]:after:inset-block-0 [&>.dx-grid]:after:-inline-end-px [&>.dx-grid]:after:is-px [&>.dx-grid]:after:bg-separator";
1609
1893
  var blockEndLine = "[&>.dx-grid]:before:absolute [&>.dx-grid]:before:inset-inline-0 [&>.dx-grid]:before:-block-end-px [&>.dx-grid]:before:bs-px [&>.dx-grid]:before:bg-separator";
1610
- var frozen = {
1611
- frozenRowsStart: 1,
1612
- frozenColsStart: 1,
1613
- frozenColsEnd: 1
1614
- };
1615
1894
  var TableRoot = ({ children, role }) => {
1616
1895
  return /* @__PURE__ */ React7.createElement("div", {
1617
1896
  role: "none",
1618
- className: mx2("relative border-bs !border-separator", role === "section" ? "attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]" : "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]")
1897
+ className: mx2("relative !border-separator", role === "section" ? "attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]" : "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]")
1619
1898
  }, children);
1620
1899
  };
1621
- var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention }, forwardedRef) => {
1900
+ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention, onRowClick }, forwardedRef) => {
1622
1901
  const [dxGrid, setDxGrid] = useState2(null);
1623
- const { hasAttention } = useAttention(model?.table ? fullyQualifiedId(model.table) : "table");
1902
+ const { hasAttention } = useAttention(model?.id ?? "table");
1624
1903
  const { t } = useTranslation3(translationKey);
1625
1904
  const modals = useMemo4(() => new ModalController(), []);
1905
+ const frozen = useMemo4(() => {
1906
+ const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
1907
+ return {
1908
+ frozenRowsStart: 1,
1909
+ frozenColsStart: model?.features.selection.enabled ? 1 : 0,
1910
+ frozenColsEnd: noActionColumn ? 0 : 1
1911
+ };
1912
+ }, [
1913
+ model
1914
+ ]);
1915
+ useEffect2(() => {
1916
+ if (!presentation || !dxGrid) {
1917
+ return;
1918
+ }
1919
+ dxGrid.getCells = (range, plane) => presentation.getCells(range, plane);
1920
+ }, [
1921
+ presentation,
1922
+ dxGrid
1923
+ ]);
1626
1924
  useImperativeHandle(forwardedRef, () => {
1627
1925
  if (!presentation || !dxGrid) {
1628
1926
  return {};
1629
1927
  }
1630
- dxGrid.getCells = (range, plane) => presentation.getCells(range, plane);
1631
1928
  return {
1632
1929
  update: (cell) => {
1633
1930
  if (cell) {
@@ -1643,6 +1940,16 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1643
1940
  dxGrid
1644
1941
  ]);
1645
1942
  const handleGridClick = useCallback4((event) => {
1943
+ const rowIndex = safeParseInt(event.target.ariaRowIndex ?? "");
1944
+ if (rowIndex != null) {
1945
+ if (onRowClick) {
1946
+ const row = model?.getRowAt(rowIndex);
1947
+ row && onRowClick(row);
1948
+ }
1949
+ if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
1950
+ model.selection.toggleSelectionForRowIndex(rowIndex);
1951
+ }
1952
+ }
1646
1953
  if (!modals) {
1647
1954
  return;
1648
1955
  }
@@ -1719,6 +2026,9 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1719
2026
  dxGrid
1720
2027
  ]);
1721
2028
  const handleEnter = useCallback4((cell) => {
2029
+ if (!model?.features.dataEditable) {
2030
+ return;
2031
+ }
1722
2032
  if (model && cell.row === model.getRowCount() - 1) {
1723
2033
  model.insertRow(cell.row);
1724
2034
  if (dxGrid) {
@@ -1733,6 +2043,9 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1733
2043
  dxGrid
1734
2044
  ]);
1735
2045
  const handleKeyDown = useCallback4((event) => {
2046
+ if (!model?.features.dataEditable) {
2047
+ return;
2048
+ }
1736
2049
  const cell = closestCell(event.target);
1737
2050
  if (!model || !cell) {
1738
2051
  return;
@@ -1774,10 +2087,10 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1774
2087
  ]);
1775
2088
  const handleQuery = useCallback4(async ({ field, props }, text) => {
1776
2089
  if (model && props.referenceSchema && field.referencePath) {
1777
- const space = getSpace4(model.table);
2090
+ const space = model.space;
1778
2091
  invariant3(space, void 0, {
1779
2092
  F: __dxlog_file4,
1780
- L: 264,
2093
+ L: 312,
1781
2094
  S: void 0,
1782
2095
  A: [
1783
2096
  "space",
@@ -1810,7 +2123,8 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1810
2123
  }
1811
2124
  return [];
1812
2125
  }, [
1813
- model
2126
+ model,
2127
+ t
1814
2128
  ]);
1815
2129
  if (!model || !modals) {
1816
2130
  return /* @__PURE__ */ React7.createElement("span", {
@@ -1819,7 +2133,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1819
2133
  });
1820
2134
  }
1821
2135
  return /* @__PURE__ */ React7.createElement(Grid.Root, {
1822
- id: model.table.id ?? "table-grid"
2136
+ id: model.id ?? "table-grid"
1823
2137
  }, /* @__PURE__ */ React7.createElement(TableCellEditor, {
1824
2138
  model,
1825
2139
  modals,
@@ -1827,16 +2141,17 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1827
2141
  onFocus: handleFocus,
1828
2142
  onQuery: handleQuery
1829
2143
  }), /* @__PURE__ */ React7.createElement(Grid.Content, {
1830
- onWheelCapture: handleWheel,
1831
2144
  className: mx2("[--dx-grid-base:var(--surface-bg)]", inlineEndLine, blockEndLine),
1832
2145
  frozen,
2146
+ // getCells={getCells}
1833
2147
  columns: model.columnMeta.value,
1834
2148
  limitRows: model.getRowCount() ?? 0,
1835
- limitColumns: model.table.view?.target?.fields?.length ?? 0,
2149
+ limitColumns: model.view?.fields?.length ?? 0,
2150
+ overscroll: "trap",
1836
2151
  onAxisResize: handleAxisResize,
1837
2152
  onClick: handleGridClick,
1838
2153
  onKeyDown: handleKeyDown,
1839
- overscroll: "trap",
2154
+ onWheelCapture: handleWheel,
1840
2155
  ref: setDxGrid
1841
2156
  }), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
1842
2157
  model,
@@ -1848,10 +2163,10 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1848
2163
  model,
1849
2164
  modals,
1850
2165
  onNewColumn: handleNewColumn
1851
- }), /* @__PURE__ */ React7.createElement(RefPanel, {
2166
+ }), /* @__PURE__ */ React7.createElement(CreateRefPanel, {
1852
2167
  model,
1853
2168
  modals
1854
- }), /* @__PURE__ */ React7.createElement(CreateRefPanel, {
2169
+ }), /* @__PURE__ */ React7.createElement(RefPanel, {
1855
2170
  model,
1856
2171
  modals
1857
2172
  }));
@@ -1861,9 +2176,150 @@ var Table = {
1861
2176
  Main: TableMain
1862
2177
  };
1863
2178
 
2179
+ // packages/ui/react-ui-table/src/components/Table/DynamicTable.tsx
2180
+ import React8, { useRef as useRef2, useMemo as useMemo5, useCallback as useCallback5 } from "react";
2181
+ import { useDefaultValue } from "@dxos/react-ui";
2182
+ import { mx as mx3 } from "@dxos/react-ui-theme";
2183
+
2184
+ // packages/ui/react-ui-table/src/hooks/useTableModel.ts
2185
+ import { effect as effect3 } from "@preact/signals-core";
2186
+ import { useEffect as useEffect3, useState as useState3 } from "react";
2187
+ import { fullyQualifiedId, getSpace } from "@dxos/react-client/echo";
2188
+ import { useSelectionActions } from "@dxos/react-ui-attention";
2189
+ import { isNonNullable } from "@dxos/util";
2190
+ var useTableModel = ({ table, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
2191
+ const [model, setModel] = useState3();
2192
+ useEffect3(() => {
2193
+ if (!table || !projection) {
2194
+ return;
2195
+ }
2196
+ let model2;
2197
+ const t = setTimeout(async () => {
2198
+ model2 = new TableModel({
2199
+ id: fullyQualifiedId(table),
2200
+ space: getSpace(table),
2201
+ view: table.view?.target,
2202
+ projection,
2203
+ features,
2204
+ rowActions,
2205
+ onRowAction,
2206
+ ...props
2207
+ });
2208
+ await model2.open();
2209
+ setModel(model2);
2210
+ });
2211
+ return () => {
2212
+ clearTimeout(t);
2213
+ void model2?.close();
2214
+ };
2215
+ }, [
2216
+ table,
2217
+ projection,
2218
+ table?.view?.target,
2219
+ features,
2220
+ rowActions
2221
+ ]);
2222
+ useEffect3(() => {
2223
+ if (rows) {
2224
+ model?.setRows(rows);
2225
+ }
2226
+ }, [
2227
+ model,
2228
+ rows
2229
+ ]);
2230
+ const { select, clear } = useSelectionActions([
2231
+ table?.id,
2232
+ table?.view?.target?.query.typename
2233
+ ].filter(isNonNullable));
2234
+ useEffect3(() => {
2235
+ if (!model) {
2236
+ return;
2237
+ }
2238
+ const unsubscribe = effect3(() => {
2239
+ const selectedItems = [
2240
+ ...model.selection.selection.value
2241
+ ];
2242
+ select(selectedItems);
2243
+ onSelectionChanged?.(selectedItems);
2244
+ });
2245
+ return () => {
2246
+ clear();
2247
+ unsubscribe();
2248
+ };
2249
+ }, [
2250
+ model,
2251
+ onSelectionChanged
2252
+ ]);
2253
+ return model;
2254
+ };
2255
+
2256
+ // packages/ui/react-ui-table/src/components/Table/DynamicTable.tsx
2257
+ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
2258
+ const { table, projection } = useMemo5(() => {
2259
+ const props2 = getBaseSchems({
2260
+ typename: name,
2261
+ properties,
2262
+ jsonSchema,
2263
+ schema
2264
+ });
2265
+ return makeDynamicTable({
2266
+ ...props2,
2267
+ properties
2268
+ });
2269
+ }, [
2270
+ name,
2271
+ properties,
2272
+ schema,
2273
+ jsonSchema
2274
+ ]);
2275
+ const tableRef = useRef2(null);
2276
+ const handleCellUpdate = useCallback5((cell) => {
2277
+ tableRef.current?.update?.(cell);
2278
+ }, []);
2279
+ const handleRowOrderChange = useCallback5(() => {
2280
+ tableRef.current?.update?.();
2281
+ }, []);
2282
+ const features = useDefaultValue(props.features, () => ({
2283
+ selection: {
2284
+ enabled: false
2285
+ },
2286
+ dataEditable: false
2287
+ }));
2288
+ const model = useTableModel({
2289
+ table,
2290
+ rows,
2291
+ projection,
2292
+ features,
2293
+ rowActions,
2294
+ onCellUpdate: handleCellUpdate,
2295
+ onRowOrderChange: handleRowOrderChange,
2296
+ onRowAction
2297
+ });
2298
+ const presentation = useMemo5(() => {
2299
+ if (model) {
2300
+ return new TablePresentation(model);
2301
+ }
2302
+ }, [
2303
+ model
2304
+ ]);
2305
+ return /* @__PURE__ */ React8.createElement("div", {
2306
+ role: "none",
2307
+ className: mx3("is-full bs-full grow grid", classNames)
2308
+ }, /* @__PURE__ */ React8.createElement("div", {
2309
+ role: "none",
2310
+ className: "grid min-bs-0 overflow-hidden"
2311
+ }, /* @__PURE__ */ React8.createElement(Table.Root, null, /* @__PURE__ */ React8.createElement(Table.Main, {
2312
+ ref: tableRef,
2313
+ model,
2314
+ presentation,
2315
+ ignoreAttention: true,
2316
+ onRowClick
2317
+ }))));
2318
+ };
2319
+
1864
2320
  // packages/ui/react-ui-table/src/components/TableToolbar/TableToolbar.tsx
1865
- import React8, { useCallback as useCallback5, useMemo as useMemo5 } from "react";
1866
- import { create as create3 } from "@dxos/live-object";
2321
+ import React9, { useCallback as useCallback6, useMemo as useMemo6 } from "react";
2322
+ import { create as create4 } from "@dxos/live-object";
1867
2323
  import { createGapSeparator, createMenuAction, MenuProvider, ToolbarMenu, useMenuActions } from "@dxos/react-ui-menu";
1868
2324
  var createTableToolbarActions = (state) => {
1869
2325
  const add = createMenuAction("add-row", {
@@ -1917,94 +2373,38 @@ var createTableToolbarActions = (state) => {
1917
2373
  };
1918
2374
  };
1919
2375
  var TableToolbar = ({ classNames, viewDirty, attendableId, onAction }) => {
1920
- const state = useMemo5(() => create3({
2376
+ const state = useMemo6(() => create4({
1921
2377
  viewDirty
1922
2378
  }), []);
1923
- const actionsCreator = useCallback5(() => createTableToolbarActions(state), [
2379
+ const actionsCreator = useCallback6(() => createTableToolbarActions(state), [
1924
2380
  state
1925
2381
  ]);
1926
2382
  const menu = useMenuActions(actionsCreator);
1927
- return /* @__PURE__ */ React8.createElement(MenuProvider, {
2383
+ return /* @__PURE__ */ React9.createElement(MenuProvider, {
1928
2384
  ...menu,
1929
2385
  attendableId,
1930
2386
  onAction
1931
- }, /* @__PURE__ */ React8.createElement(ToolbarMenu, {
2387
+ }, /* @__PURE__ */ React9.createElement(ToolbarMenu, {
1932
2388
  classNames
1933
2389
  }));
1934
2390
  };
1935
-
1936
- // packages/ui/react-ui-table/src/hooks/useTableModel.ts
1937
- import { effect as effect3 } from "@preact/signals-core";
1938
- import { useEffect as useEffect2, useState as useState3 } from "react";
1939
- import { useSelectionActions } from "@dxos/react-ui-attention";
1940
- import { isNonNullable } from "@dxos/util";
1941
- var useTableModel = ({ objects, table, projection, ...props }) => {
1942
- const [model, setModel] = useState3();
1943
- useEffect2(() => {
1944
- if (!table || !projection) {
1945
- return;
1946
- }
1947
- let model2;
1948
- const t = setTimeout(async () => {
1949
- model2 = new TableModel({
1950
- table,
1951
- projection,
1952
- ...props
1953
- });
1954
- await model2.open();
1955
- setModel(model2);
1956
- });
1957
- return () => {
1958
- clearTimeout(t);
1959
- void model2?.close();
1960
- };
1961
- }, [
1962
- table,
1963
- projection
1964
- ]);
1965
- useEffect2(() => {
1966
- if (objects) {
1967
- model?.setRows(objects);
1968
- }
1969
- }, [
1970
- model,
1971
- objects
1972
- ]);
1973
- const { select, clear } = useSelectionActions([
1974
- table?.id,
1975
- table?.view?.target?.query.typename
1976
- ].filter(isNonNullable));
1977
- useEffect2(() => {
1978
- if (!model) {
1979
- return;
1980
- }
1981
- const unsubscribe = effect3(() => {
1982
- select([
1983
- ...model.selection.selection.value
1984
- ]);
1985
- });
1986
- return () => {
1987
- clear();
1988
- unsubscribe();
1989
- };
1990
- }, [
1991
- model
1992
- ]);
1993
- return model;
1994
- };
1995
2391
  export {
1996
2392
  BUTTON_IDENTIFIERS,
1997
2393
  CONTROL_IDENTIFIERS,
2394
+ CheckboxStory,
2395
+ DynamicTable,
1998
2396
  ModalController,
2397
+ SwitchStory,
1999
2398
  Table,
2000
2399
  TableModel,
2001
2400
  TablePresentation,
2002
2401
  TableSchema,
2003
2402
  TableToolbar,
2004
2403
  TableType,
2404
+ cellClassesForRowSelection,
2405
+ getBaseSchems,
2005
2406
  initializeTable,
2006
- renderCheckbox,
2007
- renderSwitch,
2407
+ makeDynamicTable,
2008
2408
  tableButtons,
2009
2409
  tableControls,
2010
2410
  touch,