@dxos/react-ui-table 0.7.5-main.9d26e3a → 0.7.5-main.b19bfc8

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 (116) hide show
  1. package/dist/lib/browser/{chunk-AT7O4RAD.mjs → chunk-3FR6NHPD.mjs} +6 -4
  2. package/dist/lib/browser/chunk-3FR6NHPD.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +476 -282
  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-YSBXNBDJ.cjs → chunk-NB3SFHGA.cjs} +8 -6
  8. package/dist/lib/node/chunk-NB3SFHGA.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +468 -268
  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-6OH2NHUX.mjs → chunk-RLVVOZW5.mjs} +6 -4
  15. package/dist/lib/node-esm/chunk-RLVVOZW5.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +476 -282
  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/_deprecated/components/Cell/Cell.d.ts +2 -2
  21. package/dist/types/src/_deprecated/components/Cell/Cell.d.ts.map +1 -1
  22. package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts +1 -2
  23. package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts.map +1 -1
  24. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts +2 -3
  25. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts.map +1 -1
  26. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts +6 -7
  27. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -1
  28. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts +1 -2
  29. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts.map +1 -1
  30. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts +6 -7
  31. package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts.map +1 -1
  32. package/dist/types/src/_deprecated/components/Table/Table.d.ts +5 -5
  33. package/dist/types/src/_deprecated/components/Table/Table.d.ts.map +1 -1
  34. package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts +8 -9
  35. package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts.map +1 -1
  36. package/dist/types/src/_deprecated/components/Table/TableBody.d.ts +1 -2
  37. package/dist/types/src/_deprecated/components/Table/TableBody.d.ts.map +1 -1
  38. package/dist/types/src/_deprecated/components/Table/TableContext.d.ts +1 -1
  39. package/dist/types/src/_deprecated/components/Table/TableContext.d.ts.map +1 -1
  40. package/dist/types/src/_deprecated/components/Table/TableHead.d.ts +1 -2
  41. package/dist/types/src/_deprecated/components/Table/TableHead.d.ts.map +1 -1
  42. package/dist/types/src/_deprecated/schema/Schema.stories.d.ts +2 -3
  43. package/dist/types/src/_deprecated/schema/Schema.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -2
  45. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  46. package/dist/types/src/components/Table/ColumnSettings.d.ts +1 -2
  47. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  48. package/dist/types/src/components/Table/CreateRefPanel.d.ts +1 -2
  49. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  50. package/dist/types/src/components/Table/RefPanel.d.ts +1 -2
  51. package/dist/types/src/components/Table/RefPanel.d.ts.map +1 -1
  52. package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -2
  53. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  54. package/dist/types/src/components/Table/Table.d.ts +1 -1
  55. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  56. package/dist/types/src/components/Table/Table.stories.d.ts +1 -4
  57. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +1 -2
  59. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  60. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +17 -0
  61. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -0
  62. package/dist/types/src/components/TableToolbar/index.d.ts +2 -0
  63. package/dist/types/src/components/TableToolbar/index.d.ts.map +1 -0
  64. package/dist/types/src/components/index.d.ts +1 -1
  65. package/dist/types/src/components/index.d.ts.map +1 -1
  66. package/dist/types/src/components/testing.d.ts +12 -35
  67. package/dist/types/src/components/testing.d.ts.map +1 -1
  68. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  69. package/dist/types/src/model/table-model.d.ts +11 -19
  70. package/dist/types/src/model/table-model.d.ts.map +1 -1
  71. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  72. package/dist/types/src/model/table-sorting.d.ts +53 -0
  73. package/dist/types/src/model/table-sorting.d.ts.map +1 -0
  74. package/dist/types/src/translations.d.ts +2 -1
  75. package/dist/types/src/translations.d.ts.map +1 -1
  76. package/dist/types/src/types/table.d.ts +21 -90
  77. package/dist/types/src/types/table.d.ts.map +1 -1
  78. package/dist/types/src/util/table-buttons.d.ts +15 -1
  79. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  80. package/dist/types/src/util/table.d.ts +2 -1
  81. package/dist/types/src/util/table.d.ts.map +1 -1
  82. package/dist/types/tsconfig.tsbuildinfo +1 -1
  83. package/package.json +36 -34
  84. package/src/_deprecated/schema/Schema.stories.tsx +1 -1
  85. package/src/components/Table/ColumnActionsMenu.tsx +4 -4
  86. package/src/components/Table/Table.stories.tsx +55 -44
  87. package/src/components/Table/Table.tsx +4 -0
  88. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +1 -1
  89. package/src/components/TableToolbar/TableToolbar.tsx +72 -0
  90. package/src/components/{Toolbar → TableToolbar}/index.ts +1 -1
  91. package/src/components/index.ts +1 -1
  92. package/src/hooks/useTableModel.ts +21 -0
  93. package/src/model/table-model.test.ts +0 -5
  94. package/src/model/table-model.ts +41 -99
  95. package/src/model/table-presentation.ts +25 -4
  96. package/src/model/table-sorting.ts +215 -0
  97. package/src/playwright/smoke.spec.ts +21 -14
  98. package/src/translations.ts +2 -1
  99. package/src/types/table.ts +3 -3
  100. package/src/util/table-buttons.ts +33 -3
  101. package/src/util/table-controls.ts +2 -2
  102. package/src/util/table.ts +85 -52
  103. package/dist/lib/browser/chunk-AT7O4RAD.mjs.map +0 -7
  104. package/dist/lib/node/chunk-YSBXNBDJ.cjs.map +0 -7
  105. package/dist/lib/node-esm/chunk-6OH2NHUX.mjs.map +0 -7
  106. package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -21
  107. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
  108. package/dist/types/src/components/Toolbar/common.d.ts +0 -14
  109. package/dist/types/src/components/Toolbar/common.d.ts.map +0 -1
  110. package/dist/types/src/components/Toolbar/index.d.ts +0 -2
  111. package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
  112. package/dist/types/src/playwright/playwright.config.d.ts +0 -3
  113. package/dist/types/src/playwright/playwright.config.d.ts.map +0 -1
  114. package/src/components/Toolbar/Toolbar.tsx +0 -87
  115. package/src/components/Toolbar/common.tsx +0 -71
  116. /package/src/playwright/{playwright.config.ts → playwright.config.cts} +0 -0
@@ -34,9 +34,9 @@ __export(node_exports, {
34
34
  Table: () => Table,
35
35
  TableModel: () => TableModel,
36
36
  TablePresentation: () => TablePresentation,
37
- TableSchema: () => import_chunk_YSBXNBDJ.TableSchema,
38
- TableType: () => import_chunk_YSBXNBDJ.TableType,
39
- Toolbar: () => Toolbar,
37
+ TableSchema: () => import_chunk_NB3SFHGA.TableSchema,
38
+ TableToolbar: () => TableToolbar,
39
+ TableType: () => import_chunk_NB3SFHGA.TableType,
40
40
  initializeTable: () => initializeTable,
41
41
  renderCheckbox: () => renderCheckbox,
42
42
  renderSwitch: () => renderSwitch,
@@ -44,11 +44,10 @@ __export(node_exports, {
44
44
  tableControls: () => tableControls,
45
45
  touch: () => touch,
46
46
  translations: () => translations_default,
47
- useTableModel: () => useTableModel,
48
- useToolbarContext: () => useToolbarContext
47
+ useTableModel: () => useTableModel
49
48
  });
50
49
  module.exports = __toCommonJS(node_exports);
51
- var import_chunk_YSBXNBDJ = require("./chunk-YSBXNBDJ.cjs");
50
+ var import_chunk_NB3SFHGA = require("./chunk-NB3SFHGA.cjs");
52
51
  var import_react = __toESM(require("react"));
53
52
  var import_echo_schema = require("@dxos/echo-schema");
54
53
  var import_invariant = require("@dxos/invariant");
@@ -77,7 +76,6 @@ var import_react_ui_form3 = require("@dxos/react-ui-form");
77
76
  var import_react6 = __toESM(require("react"));
78
77
  var import_react_ui6 = require("@dxos/react-ui");
79
78
  var import_signals_core = require("@preact/signals-core");
80
- var import_lodash = __toESM(require("lodash.orderby"));
81
79
  var import_context = require("@dxos/context");
82
80
  var import_echo_schema3 = require("@dxos/echo-schema");
83
81
  var import_invariant2 = require("@dxos/invariant");
@@ -87,30 +85,34 @@ var import_react_ui_form4 = require("@dxos/react-ui-form");
87
85
  var import_signals_core2 = require("@preact/signals-core");
88
86
  var import_context2 = require("@dxos/context");
89
87
  var import_echo_schema4 = require("@dxos/echo-schema");
90
- var import_log = require("@dxos/log");
91
88
  var import_react_client2 = require("@dxos/react-client");
92
89
  var import_echo5 = require("@dxos/react-client/echo");
93
90
  var import_schema = require("@dxos/schema");
94
91
  var import_signals_core3 = require("@preact/signals-core");
95
- var import_log2 = require("@dxos/log");
96
- var import_signals_core4 = require("@preact/signals-core");
92
+ var import_lodash = __toESM(require("lodash.orderby"));
97
93
  var import_echo_schema5 = require("@dxos/echo-schema");
98
94
  var import_react_ui_form5 = require("@dxos/react-ui-form");
95
+ var import_signals_core4 = require("@preact/signals-core");
96
+ var import_log = require("@dxos/log");
97
+ var import_signals_core5 = require("@preact/signals-core");
98
+ var import_echo_schema6 = require("@dxos/echo-schema");
99
+ var import_react_ui_form6 = require("@dxos/react-ui-form");
99
100
  var import_react_ui_grid3 = require("@dxos/react-ui-grid");
100
101
  var import_react_ui_theme2 = require("@dxos/react-ui-theme");
101
102
  var import_schema2 = require("@dxos/schema");
102
103
  var import_react7 = __toESM(require("react"));
103
- var import_echo_schema6 = require("@dxos/echo-schema");
104
+ var import_echo_schema7 = require("@dxos/echo-schema");
104
105
  var import_invariant3 = require("@dxos/invariant");
105
106
  var import_react_ui_grid4 = require("@dxos/react-ui-grid");
106
107
  var import_autocomplete = require("@codemirror/autocomplete");
107
108
  var import_view = require("@codemirror/view");
108
- var import_react_context = require("@radix-ui/react-context");
109
109
  var import_react8 = __toESM(require("react"));
110
- var import_react_ui7 = require("@dxos/react-ui");
111
- var import_react9 = __toESM(require("react"));
112
- var import_react_ui8 = require("@dxos/react-ui");
113
- var import_react10 = require("react");
110
+ var import_live_object2 = require("@dxos/live-object");
111
+ var import_react_ui_menu = require("@dxos/react-ui-menu");
112
+ var import_signals_core6 = require("@preact/signals-core");
113
+ var import_react9 = require("react");
114
+ var import_react_ui_attention2 = require("@dxos/react-ui-attention");
115
+ var import_util2 = require("@dxos/util");
114
116
  var translationKey = "table";
115
117
  var translations_default = [
116
118
  {
@@ -124,7 +126,7 @@ var translations_default = [
124
126
  "new schema": "New schema",
125
127
  "continue label": "Continue",
126
128
  "create stack section label": "Create table",
127
- "add row": "Add row",
129
+ "add row label": "Add row",
128
130
  "create comment": "Create thread",
129
131
  "column action sort descending": "Sort Descending",
130
132
  "column action sort ascending": "Sort Ascending",
@@ -135,7 +137,8 @@ var translations_default = [
135
137
  "bulk delete row label": "Delete selected rows",
136
138
  "column deleted label": "Column deleted",
137
139
  "new column button label": "Create column",
138
- "create new object label": "Create new object \u201C{{text}}\u201D"
140
+ "create new object label": "Create new object \u201C{{text}}\u201D",
141
+ "save view label": "Save changes to view"
139
142
  }
140
143
  }
141
144
  }
@@ -146,7 +149,7 @@ var ColumnActionsMenu = ({ model, modals }) => {
146
149
  if (state?.type !== "column") {
147
150
  return null;
148
151
  }
149
- const currentSort = model.sorting;
152
+ const currentSort = model.sorting?.sorting;
150
153
  const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
151
154
  return /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Root, {
152
155
  modal: false,
@@ -156,13 +159,13 @@ var ColumnActionsMenu = ({ model, modals }) => {
156
159
  virtualRef: modals.trigger
157
160
  }), /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Portal, null, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Content, null, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
158
161
  "data-testid": "column-sort-descending",
159
- onClick: () => model.setSort(state.fieldId, "desc")
162
+ onClick: () => model.sorting?.setSort(state.fieldId, "desc")
160
163
  }, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
161
164
  "data-testid": "column-sort-ascending",
162
- onClick: () => model.setSort(state.fieldId, "asc")
165
+ onClick: () => model.sorting?.setSort(state.fieldId, "asc")
163
166
  }, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
164
167
  "data-testid": "column-clear-sort",
165
- onClick: () => model.clearSort()
168
+ onClick: () => model.sorting?.clearSort()
166
169
  }, t("column action clear sorting")), model.getColumnCount() > 1 && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
167
170
  "data-testid": "column-delete",
168
171
  onClick: () => model.deleteColumn(state.fieldId)
@@ -352,79 +355,97 @@ var RowActionsMenu = ({ model, modals }) => {
352
355
  }, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.DropdownMenu.Arrow, null)));
353
356
  };
354
357
  var touch = (value) => value;
355
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/util/table.ts";
356
- var initializeTable = async ({ space, table, initialRow = true }) => {
357
- (0, import_log.log)("initializeTable", {
358
- table
359
- }, {
360
- F: __dxlog_file,
361
- L: 36,
362
- S: void 0,
363
- C: (f, a) => f(...a)
364
- });
365
- const ContactSchema = (0, import_echo_schema4.TypedObject)({
366
- typename: `example.com/type/${import_react_client2.PublicKey.random().truncate()}`,
367
- version: "0.1.0"
368
- })({
369
- name: import_echo_schema4.S.optional(import_echo_schema4.S.String).annotations({
370
- [import_echo_schema4.AST.TitleAnnotationId]: "Name"
371
- }),
372
- active: import_echo_schema4.S.optional(import_echo_schema4.S.Boolean),
373
- email: import_echo_schema4.S.optional(import_echo_schema4.Format.Email),
374
- salary: import_echo_schema4.S.optional(import_echo_schema4.Format.Currency()).annotations({
375
- [import_echo_schema4.AST.TitleAnnotationId]: "Salary"
376
- })
377
- });
378
- const [contactSchema] = await space.db.schemaRegistry.register([
379
- ContactSchema
380
- ]);
381
- table.view = (0, import_echo5.makeRef)((0, import_schema.createView)({
382
- name: "Test",
383
- typename: contactSchema.typename,
384
- jsonSchema: contactSchema.jsonSchema,
385
- fields: [
386
- "name",
387
- "active",
388
- "email",
389
- "salary"
390
- ]
391
- }));
392
- const projection = new import_schema.ViewProjection(contactSchema, table.view.target);
393
- projection.setFieldProjection({
394
- field: {
395
- id: table.view.target.fields.find((f) => f.path === "salary").id,
396
- path: "salary",
397
- size: 150
358
+ var initializeTable = async ({ space, table, initialRow = true, initialSchema }) => {
359
+ if (initialSchema) {
360
+ const schema = await space.db.schemaRegistry.query({
361
+ typename: initialSchema
362
+ }).firstOrUndefined();
363
+ if (!schema) {
364
+ throw new Error(`Schema not found: ${initialSchema}`);
398
365
  }
399
- });
400
- projection.setFieldProjection({
401
- field: {
402
- id: (0, import_schema.createFieldId)(),
403
- path: "manager",
404
- referencePath: "name"
405
- },
406
- props: {
407
- property: "manager",
408
- type: import_echo_schema4.TypeEnum.Ref,
409
- format: import_echo_schema4.FormatEnum.Ref,
410
- referenceSchema: contactSchema.typename,
411
- title: "Manager"
366
+ const fields = (0, import_schema.getSchemaProperties)(schema.ast).filter((prop) => prop.format !== import_echo_schema4.FormatEnum.Ref).map((prop) => prop.name);
367
+ table.view = (0, import_echo5.makeRef)((0, import_schema.createView)({
368
+ // TODO(ZaymonFC): Don't hardcode name?
369
+ name: "View",
370
+ typename: schema.typename,
371
+ jsonSchema: schema.jsonSchema,
372
+ fields
373
+ }));
374
+ return schema;
375
+ } else {
376
+ const ContactSchema = (0, import_echo_schema4.TypedObject)({
377
+ typename: `example.com/type/${import_react_client2.PublicKey.random().truncate()}`,
378
+ version: "0.1.0"
379
+ })({
380
+ name: import_echo_schema4.S.optional(import_echo_schema4.S.String).annotations({
381
+ [import_echo_schema4.AST.TitleAnnotationId]: "Name"
382
+ }),
383
+ active: import_echo_schema4.S.optional(import_echo_schema4.S.Boolean),
384
+ email: import_echo_schema4.S.optional(import_echo_schema4.Format.Email),
385
+ salary: import_echo_schema4.S.optional(import_echo_schema4.Format.Currency()).annotations({
386
+ [import_echo_schema4.AST.TitleAnnotationId]: "Salary"
387
+ })
388
+ });
389
+ const [contactSchema] = await space.db.schemaRegistry.register([
390
+ ContactSchema
391
+ ]);
392
+ table.view = (0, import_echo5.makeRef)((0, import_schema.createView)({
393
+ name: "View",
394
+ typename: contactSchema.typename,
395
+ jsonSchema: contactSchema.jsonSchema,
396
+ fields: [
397
+ "name",
398
+ "email",
399
+ "salary",
400
+ "active"
401
+ ]
402
+ }));
403
+ const projection = new import_schema.ViewProjection(contactSchema, table.view.target);
404
+ projection.setFieldProjection({
405
+ field: {
406
+ id: table.view.target.fields.find((f) => f.path === "salary").id,
407
+ path: "salary",
408
+ size: 150
409
+ }
410
+ });
411
+ projection.setFieldProjection({
412
+ field: {
413
+ id: table.view.target.fields.find((f) => f.path === "active").id,
414
+ path: "active",
415
+ size: 100
416
+ }
417
+ });
418
+ projection.setFieldProjection({
419
+ field: {
420
+ id: (0, import_schema.createFieldId)(),
421
+ path: "manager",
422
+ referencePath: "name"
423
+ },
424
+ props: {
425
+ property: "manager",
426
+ type: import_echo_schema4.TypeEnum.Ref,
427
+ format: import_echo_schema4.FormatEnum.Ref,
428
+ referenceSchema: contactSchema.typename,
429
+ title: "Manager"
430
+ }
431
+ });
432
+ if (initialRow) {
433
+ space.db.add((0, import_echo5.create)(contactSchema, {}));
412
434
  }
413
- });
414
- if (initialRow) {
415
- space.db.add((0, import_echo5.create)(contactSchema, {}));
435
+ return contactSchema;
416
436
  }
417
- return contactSchema;
418
437
  };
419
438
  var BUTTON_IDENTIFIERS = {
420
439
  columnSettings: "data-table-column-settings-button",
421
440
  newColumn: "data-table-new-column-button",
422
441
  referencedCell: "data-table-ref-cell-button",
423
- rowMenu: "data-table-row-menu-button"
442
+ rowMenu: "data-table-row-menu-button",
443
+ sort: "data-table-sort-button"
424
444
  };
425
- var createButton = ({ attr, data, disabled = false, icon, testId }) => {
445
+ var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
426
446
  const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
427
- return `<button ${attr} data-testid="${testId}" class="ch-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 inline-end-2" ${dataAttrs} ${disabled ? "disabled" : ""}><svg><use href="/icons.svg#${icon}"/></svg></button>`;
447
+ const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
448
+ return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? "disabled" : ""}><svg><use href="/icons.svg#${icon}"/></svg></button>`;
428
449
  };
429
450
  var addColumnButton = {
430
451
  attr: BUTTON_IDENTIFIERS.newColumn,
@@ -498,19 +519,43 @@ var rowMenuButton = {
498
519
  rowIndex: Number(el.getAttribute("data-row-index"))
499
520
  })
500
521
  };
522
+ var sortButton = {
523
+ attr: BUTTON_IDENTIFIERS.sort,
524
+ icon: "ph--sort-ascending--regular",
525
+ render: ({ fieldId, direction }) => {
526
+ return createButton({
527
+ attr: BUTTON_IDENTIFIERS.sort,
528
+ icon: direction === "desc" ? "ph--sort-descending--regular" : "ph--sort-ascending--regular",
529
+ data: {
530
+ "data-field-id": fieldId,
531
+ "data-direction": direction ?? ""
532
+ },
533
+ testId: "table-sort-button",
534
+ // TODO(ZaymonFC): All buttons should be rendered into an absolutely positioned flex container.
535
+ // This is a bit hacky.
536
+ type: "secondary"
537
+ });
538
+ },
539
+ getData: (el) => ({
540
+ type: "sort",
541
+ fieldId: el.getAttribute("data-field-id"),
542
+ direction: el.getAttribute("data-direction")
543
+ })
544
+ };
501
545
  var tableButtons = {
502
546
  addColumn: addColumnButton,
503
547
  columnSettings: columnSettingsButton,
504
548
  referencedCell: referencedCellButton,
505
- rowMenu: rowMenuButton
549
+ rowMenu: rowMenuButton,
550
+ sort: sortButton
506
551
  };
507
552
  var CONTROL_IDENTIFIERS = {
508
553
  checkbox: "data-table-checkbox",
509
554
  switch: "data-table-switch"
510
555
  };
511
556
  var BASE_CLASSES = {
512
- checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] ch-checkbox",
513
- switch: "absolute inset-block-[.25rem] inline-end-[.25rem] ch-checkbox--switch"
557
+ checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] dx-checkbox",
558
+ switch: "absolute inset-block-[.25rem] inline-end-[.25rem] dx-checkbox--switch"
514
559
  };
515
560
  var renderAttributes = (data) => {
516
561
  return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
@@ -634,7 +679,166 @@ var SelectionModel = class extends import_context2.Resource {
634
679
  return this._allSelected;
635
680
  }
636
681
  };
637
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
682
+ var TableSorting = class {
683
+ constructor(rows, _view, _projection) {
684
+ this._view = _view;
685
+ this._projection = _projection;
686
+ this._displayToDataIndex = /* @__PURE__ */ new Map();
687
+ this._localSort = (0, import_signals_core3.signal)(void 0);
688
+ this._rows = rows;
689
+ this._isDirty = (0, import_signals_core3.computed)(() => {
690
+ const local = this._localSort.value;
691
+ const viewSort = this._view?.query.sort?.[0];
692
+ if (local?.type === "cleared") {
693
+ return viewSort !== void 0;
694
+ }
695
+ if (local?.type === "active") {
696
+ if (!viewSort) {
697
+ return true;
698
+ }
699
+ return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
700
+ }
701
+ return false;
702
+ });
703
+ this.sortedRows = this.initialiseSortedRows();
704
+ }
705
+ /**
706
+ * @reactive
707
+ * @returns Local sort if present, falls back to view sort.
708
+ */
709
+ get sorting() {
710
+ const local = this._localSort.value;
711
+ if (local?.type === "cleared") {
712
+ return void 0;
713
+ }
714
+ if (local?.type === "active") {
715
+ return local.sort;
716
+ }
717
+ return this._view?.query.sort?.[0];
718
+ }
719
+ /**
720
+ * @reactive
721
+ * @returns Whether local sort differs from view sort.
722
+ */
723
+ get isDirty() {
724
+ return this._isDirty.value;
725
+ }
726
+ getDataIndex(displayIndex) {
727
+ return this._displayToDataIndex.get(displayIndex) ?? displayIndex;
728
+ }
729
+ setSort(fieldId, direction) {
730
+ this._localSort.value = {
731
+ type: "active",
732
+ sort: {
733
+ fieldId,
734
+ direction
735
+ }
736
+ };
737
+ }
738
+ toggleSort(fieldId) {
739
+ if (!this._view || !this.sorting || this.sorting.fieldId !== fieldId) {
740
+ return;
741
+ }
742
+ switch (this.sorting.direction) {
743
+ case "asc": {
744
+ this.setSort(fieldId, "desc");
745
+ break;
746
+ }
747
+ case "desc": {
748
+ this.setSort(fieldId, "asc");
749
+ break;
750
+ }
751
+ }
752
+ }
753
+ clearSort() {
754
+ this._localSort.value = {
755
+ type: "cleared"
756
+ };
757
+ }
758
+ save() {
759
+ if (this._view && this._localSort.value !== void 0) {
760
+ if (this._localSort.value.type === "active") {
761
+ this._view.query.sort = [
762
+ this._localSort.value.sort
763
+ ];
764
+ } else {
765
+ this._view.query.sort = [];
766
+ }
767
+ this._localSort.value = void 0;
768
+ }
769
+ }
770
+ //
771
+ // Initialisation.
772
+ //
773
+ initialiseSortedRows() {
774
+ return (0, import_signals_core3.computed)(() => {
775
+ this._displayToDataIndex.clear();
776
+ const sort = this.sorting;
777
+ if (!sort || !this._view) {
778
+ return this._rows.value;
779
+ }
780
+ const field = this._view.fields.find((f) => f.id === sort.fieldId);
781
+ if (!field) {
782
+ return this._rows.value;
783
+ }
784
+ const { props } = this._projection.getFieldProjection(field.id);
785
+ const dataWithIndices = this._rows.value.map((item, index) => {
786
+ const sortValue = this.getSortValue(props, field, item);
787
+ const isEmpty = !(props.type === import_echo_schema5.TypeEnum.Boolean) && (sortValue == null || sortValue === "");
788
+ return {
789
+ item,
790
+ index,
791
+ value: sortValue,
792
+ isEmpty
793
+ };
794
+ });
795
+ const ordered = (0, import_lodash.default)(dataWithIndices, [
796
+ "isEmpty",
797
+ "value"
798
+ ], [
799
+ "asc",
800
+ sort.direction
801
+ ]);
802
+ ordered.forEach(({ index: dataIndex }, displayIndex) => {
803
+ if (displayIndex !== dataIndex) {
804
+ this._displayToDataIndex.set(displayIndex, dataIndex);
805
+ }
806
+ });
807
+ return ordered.map(({ item }) => item);
808
+ });
809
+ }
810
+ getSortValue(props, field, item) {
811
+ const { type, format } = props;
812
+ const value = (0, import_echo_schema5.getValue)(item, field.path);
813
+ if (type === import_echo_schema5.TypeEnum.Boolean) {
814
+ return !!value;
815
+ }
816
+ if (type === import_echo_schema5.TypeEnum.Number) {
817
+ return value;
818
+ }
819
+ if (value == null) {
820
+ return value;
821
+ }
822
+ if (format === import_echo_schema5.FormatEnum.SingleSelect) {
823
+ const options = props.options;
824
+ if (!options) {
825
+ return void 0;
826
+ }
827
+ const option = options.find((option2) => option2.id === value);
828
+ return option ? options.indexOf(option) : void 0;
829
+ }
830
+ if (format === import_echo_schema5.FormatEnum.Ref && field.referencePath) {
831
+ const refValue = (0, import_echo_schema5.getValue)(value.target, field.referencePath);
832
+ return refValue;
833
+ }
834
+ return (0, import_react_ui_form5.formatForDisplay)({
835
+ type,
836
+ format,
837
+ value
838
+ });
839
+ }
840
+ };
841
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
638
842
  var TableModel = class extends import_context.Resource {
639
843
  constructor({ table, projection, sorting = [], pinnedRows = {
640
844
  top: [],
@@ -652,8 +856,6 @@ var TableModel = class extends import_context.Resource {
652
856
  col: 0
653
857
  }
654
858
  });
655
- this._displayToDataIndex = /* @__PURE__ */ new Map();
656
- this._sorting = (0, import_signals_core.signal)(void 0);
657
859
  this._rows = (0, import_signals_core.signal)([]);
658
860
  this.setRows = (obj) => {
659
861
  this._rows.value = obj;
@@ -661,11 +863,11 @@ var TableModel = class extends import_context.Resource {
661
863
  this.getRowCount = () => this._rows.value.length;
662
864
  this.getColumnCount = () => this.table.view?.target?.fields.length ?? 0;
663
865
  this.insertRow = (rowIndex) => {
664
- const row = rowIndex !== void 0 ? this._displayToDataIndex.get(rowIndex) ?? rowIndex : this._rows.value.length;
866
+ const row = rowIndex !== void 0 ? this._sorting.getDataIndex(rowIndex) : this._rows.value.length;
665
867
  this._onInsertRow?.(row);
666
868
  };
667
869
  this.deleteRow = (rowIndex) => {
668
- const row = this._displayToDataIndex.get(rowIndex) ?? rowIndex;
870
+ const row = this._sorting.getDataIndex(rowIndex);
669
871
  const obj = this._rows.value[row];
670
872
  const objectsToDelete = [];
671
873
  if (this._selection.hasSelection.value) {
@@ -682,7 +884,7 @@ var TableModel = class extends import_context.Resource {
682
884
  return void 0;
683
885
  }
684
886
  const field = fields[col];
685
- const dataIndex = this._displayToDataIndex.get(row) ?? row;
887
+ const dataIndex = this._sorting.getDataIndex(row);
686
888
  const value = (0, import_echo_schema3.getValue)(this._rows.value[dataIndex], field.path);
687
889
  if (value == null) {
688
890
  return "";
@@ -705,7 +907,7 @@ var TableModel = class extends import_context.Resource {
705
907
  }
706
908
  };
707
909
  this.setCellData = ({ col, row }, value) => {
708
- const rowIdx = this._displayToDataIndex.get(row) ?? row;
910
+ const rowIdx = this._sorting.getDataIndex(row);
709
911
  const fields = this.table.view?.target?.fields ?? [];
710
912
  if (col < 0 || col >= fields.length) {
711
913
  return;
@@ -731,7 +933,11 @@ var TableModel = class extends import_context.Resource {
731
933
  };
732
934
  this._table = table;
733
935
  this._projection = projection;
734
- this._sorting.value = sorting.at(0);
936
+ this._sorting = new TableSorting(this._rows, table.view?.target, projection);
937
+ if (sorting.length > 0) {
938
+ const [sort] = sorting;
939
+ this._sorting.setSort(sort.fieldId, sort.direction);
940
+ }
735
941
  this._pinnedRows = pinnedRows;
736
942
  this._onInsertRow = onInsertRow;
737
943
  this._onDeleteRows = onDeleteRows;
@@ -746,14 +952,20 @@ var TableModel = class extends import_context.Resource {
746
952
  return this._projection;
747
953
  }
748
954
  get rows() {
749
- return this._sortedRows;
955
+ return this._sorting.sortedRows;
956
+ }
957
+ /**
958
+ * @reactive
959
+ */
960
+ get sorting() {
961
+ return this._sorting;
750
962
  }
751
963
  get pinnedRows() {
752
964
  return this._pinnedRows;
753
965
  }
754
966
  get columnMeta() {
755
967
  (0, import_invariant2.invariant)(this._columnMeta, void 0, {
756
- F: __dxlog_file2,
968
+ F: __dxlog_file,
757
969
  L: 117,
758
970
  S: this,
759
971
  A: [
@@ -763,20 +975,20 @@ var TableModel = class extends import_context.Resource {
763
975
  });
764
976
  return this._columnMeta;
765
977
  }
766
- get sorting() {
767
- return this._sorting.value;
768
- }
769
978
  get selection() {
770
979
  return this._selection;
771
980
  }
981
+ /** @reactive */
982
+ get isViewDirty() {
983
+ return this._sorting.isDirty;
984
+ }
772
985
  //
773
986
  // Initialisation
774
987
  //
775
988
  async _open() {
776
989
  this.initializeColumnMeta();
777
- this.initializeSorting();
778
990
  this.initializeEffects();
779
- this._selection = new SelectionModel(this._sortedRows, () => this._onRowOrderChanged?.());
991
+ this._selection = new SelectionModel(this._sorting.sortedRows, () => this._onRowOrderChanged?.());
780
992
  await this._selection.open(this._ctx);
781
993
  }
782
994
  initializeColumnMeta() {
@@ -806,60 +1018,9 @@ var TableModel = class extends import_context.Resource {
806
1018
  };
807
1019
  });
808
1020
  }
809
- initializeSorting() {
810
- this._sortedRows = (0, import_signals_core.computed)(() => {
811
- this._displayToDataIndex.clear();
812
- const sort = this._sorting.value;
813
- if (!sort) {
814
- return this._rows.value;
815
- }
816
- const field = this._table.view?.target?.fields.find((field2) => field2.id === sort.fieldId);
817
- if (!field) {
818
- return this._rows.value;
819
- }
820
- const { props } = this._projection.getFieldProjection(field.id);
821
- const dataWithIndices = this._rows.value.map((item, index) => {
822
- const rawValue = (0, import_echo_schema3.getValue)(item, field.path);
823
- let sortValue = rawValue;
824
- if (props.type.startsWith("boolean")) {
825
- sortValue = !!rawValue;
826
- } else if (rawValue != null) {
827
- if (props.format === import_echo_schema3.FormatEnum.Ref && field.referencePath) {
828
- sortValue = (0, import_echo_schema3.getValue)(rawValue, field.referencePath);
829
- } else {
830
- sortValue = (0, import_react_ui_form4.formatForDisplay)({
831
- type: props.type,
832
- format: props.format,
833
- value: rawValue
834
- });
835
- }
836
- }
837
- return {
838
- item,
839
- index,
840
- value: sortValue,
841
- isEmpty: !props.type.startsWith("boolean") && (sortValue == null || sortValue === "")
842
- };
843
- });
844
- const sorted = (0, import_lodash.default)(dataWithIndices, [
845
- "isEmpty",
846
- "value"
847
- ], [
848
- "asc",
849
- sort.direction
850
- ]);
851
- for (let displayIndex = 0; displayIndex < sorted.length; displayIndex++) {
852
- const { index: dataIndex } = sorted[displayIndex];
853
- if (displayIndex !== dataIndex) {
854
- this._displayToDataIndex.set(displayIndex, dataIndex);
855
- }
856
- }
857
- return sorted.map(({ item }) => item);
858
- });
859
- }
860
1021
  initializeEffects() {
861
1022
  const rowOrderWatcher = (0, import_signals_core.effect)(() => {
862
- touch(this._sortedRows.value);
1023
+ touch(this._sorting.sortedRows.value);
863
1024
  this._onRowOrderChanged?.();
864
1025
  });
865
1026
  this._ctx.onDispose(rowOrderWatcher);
@@ -868,7 +1029,7 @@ var TableModel = class extends import_context.Resource {
868
1029
  const rowEffects = [];
869
1030
  for (let row = start.row; row <= end.row; row++) {
870
1031
  rowEffects.push((0, import_signals_core.effect)(() => {
871
- const obj = this._sortedRows.value[row];
1032
+ const obj = this._sorting.sortedRows.value[row];
872
1033
  this?._table?.view?.target?.fields.forEach((field) => touch((0, import_echo_schema3.getValue)(obj, field.path)));
873
1034
  this._onCellUpdate?.({
874
1035
  row,
@@ -887,7 +1048,7 @@ var TableModel = class extends import_context.Resource {
887
1048
  * @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
888
1049
  */
889
1050
  updateCellData({ col, row }, update) {
890
- const dataRow = this._displayToDataIndex.get(row) ?? row;
1051
+ const dataRow = this._sorting.getDataIndex(row);
891
1052
  const fields = this.table.view?.target?.fields ?? [];
892
1053
  const field = fields[col];
893
1054
  const value = (0, import_echo_schema3.getValue)(this._rows.value[dataRow], field.path);
@@ -903,9 +1064,6 @@ var TableModel = class extends import_context.Resource {
903
1064
  }
904
1065
  const field = this.table.view.target?.fields.find((field2) => field2.id === fieldId);
905
1066
  if (field && this._onDeleteColumn) {
906
- if (this._sorting.value?.fieldId === fieldId) {
907
- this.clearSort();
908
- }
909
1067
  this._onDeleteColumn(field.id);
910
1068
  }
911
1069
  }
@@ -923,18 +1081,6 @@ var TableModel = class extends import_context.Resource {
923
1081
  }
924
1082
  }
925
1083
  //
926
- // Sorting
927
- //
928
- setSort(fieldId, direction) {
929
- this._sorting.value = {
930
- fieldId,
931
- direction
932
- };
933
- }
934
- clearSort() {
935
- this._sorting.value = void 0;
936
- }
937
- //
938
1084
  // Pinning
939
1085
  //
940
1086
  // TODO(burdon): Change to setPinned(on/off).
@@ -945,11 +1091,17 @@ var TableModel = class extends import_context.Resource {
945
1091
  this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
946
1092
  this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
947
1093
  }
1094
+ //
1095
+ // View operations
1096
+ //
1097
+ saveView() {
1098
+ this._sorting.save();
1099
+ }
948
1100
  };
949
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
1101
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
950
1102
  var ModalController = class {
951
1103
  constructor() {
952
- this._state = (0, import_signals_core3.signal)({
1104
+ this._state = (0, import_signals_core4.signal)({
953
1105
  type: "closed"
954
1106
  });
955
1107
  this._triggerRef = {
@@ -1009,8 +1161,8 @@ var ModalController = class {
1009
1161
  onCreate
1010
1162
  };
1011
1163
  } else {
1012
- import_log2.log.warn("anchor cell not found while creating new ref", void 0, {
1013
- F: __dxlog_file3,
1164
+ import_log.log.warn("anchor cell not found while creating new ref", void 0, {
1165
+ F: __dxlog_file2,
1014
1166
  L: 86,
1015
1167
  S: this,
1016
1168
  C: (f, a) => f(...a)
@@ -1031,7 +1183,7 @@ var ModalController = class {
1031
1183
  }
1032
1184
  };
1033
1185
  var TablePresentation = class {
1034
- constructor(model, _visibleRange = (0, import_signals_core4.signal)({
1186
+ constructor(model, _visibleRange = (0, import_signals_core5.signal)({
1035
1187
  start: {
1036
1188
  row: 0,
1037
1189
  col: 0
@@ -1070,22 +1222,23 @@ var TablePresentation = class {
1070
1222
  const { props } = this.model.projection.getFieldProjection(field.id);
1071
1223
  const cell = {
1072
1224
  get value() {
1073
- const value = (0, import_echo_schema5.getValue)(obj, field.path);
1225
+ const value = (0, import_echo_schema6.getValue)(obj, field.path);
1074
1226
  if (value == null) {
1075
1227
  return "";
1076
1228
  }
1077
1229
  switch (props.format) {
1078
- case import_echo_schema5.FormatEnum.Boolean: {
1230
+ case import_echo_schema6.FormatEnum.Boolean:
1231
+ case import_echo_schema6.FormatEnum.SingleSelect: {
1079
1232
  return "";
1080
1233
  }
1081
- case import_echo_schema5.FormatEnum.Ref: {
1234
+ case import_echo_schema6.FormatEnum.Ref: {
1082
1235
  if (!field.referencePath) {
1083
1236
  return "";
1084
1237
  }
1085
- return (0, import_echo_schema5.getValue)(value.target, field.referencePath);
1238
+ return (0, import_echo_schema6.getValue)(value.target, field.referencePath);
1086
1239
  }
1087
1240
  default: {
1088
- return (0, import_react_ui_form5.formatForDisplay)({
1241
+ return (0, import_react_ui_form6.formatForDisplay)({
1089
1242
  type: props.type,
1090
1243
  format: props.format,
1091
1244
  value
@@ -1095,22 +1248,22 @@ var TablePresentation = class {
1095
1248
  }
1096
1249
  };
1097
1250
  const classes = [];
1098
- const formatClasses = (0, import_react_ui_form5.cellClassesForFieldType)({
1251
+ const formatClasses = (0, import_react_ui_form6.cellClassesForFieldType)({
1099
1252
  type: props.type,
1100
1253
  format: props.format
1101
1254
  });
1102
1255
  if (formatClasses) {
1103
1256
  classes.push(formatClasses);
1104
1257
  }
1105
- const rowSelectionClasses = (0, import_react_ui_form5.cellClassesForRowSelection)(this.model.selection.isObjectSelected(obj));
1258
+ const rowSelectionClasses = (0, import_react_ui_form6.cellClassesForRowSelection)(this.model.selection.isObjectSelected(obj));
1106
1259
  if (rowSelectionClasses) {
1107
1260
  classes.push(rowSelectionClasses);
1108
1261
  }
1109
1262
  if (classes.length > 0) {
1110
1263
  cell.className = (0, import_react_ui_theme2.mx)(classes.flat());
1111
1264
  }
1112
- if (props.format === import_echo_schema5.FormatEnum.Ref && props.referenceSchema) {
1113
- const targetObj = (0, import_echo_schema5.getValue)(obj, field.path)?.target;
1265
+ if (props.format === import_echo_schema6.FormatEnum.Ref && props.referenceSchema) {
1266
+ const targetObj = (0, import_echo_schema6.getValue)(obj, field.path)?.target;
1114
1267
  if (targetObj) {
1115
1268
  cell.accessoryHtml = tableButtons.referencedCell.render({
1116
1269
  targetId: targetObj.id,
@@ -1118,8 +1271,8 @@ var TablePresentation = class {
1118
1271
  });
1119
1272
  }
1120
1273
  }
1121
- if (props.format === import_echo_schema5.FormatEnum.Boolean) {
1122
- const value = (0, import_echo_schema5.getValue)(obj, field.path);
1274
+ if (props.format === import_echo_schema6.FormatEnum.Boolean) {
1275
+ const value = (0, import_echo_schema6.getValue)(obj, field.path);
1123
1276
  cell.accessoryHtml = tableControls.switch.render({
1124
1277
  colIndex,
1125
1278
  rowIndex: displayIndex,
@@ -1127,6 +1280,16 @@ var TablePresentation = class {
1127
1280
  });
1128
1281
  cell.readonly = true;
1129
1282
  }
1283
+ if (props.format === import_echo_schema6.FormatEnum.SingleSelect) {
1284
+ const value = (0, import_echo_schema6.getValue)(obj, field.path);
1285
+ const options = this.model.projection.getFieldProjection(field.id).props.options;
1286
+ if (options) {
1287
+ const option = options.find((o) => o.id === value);
1288
+ if (option) {
1289
+ cell.accessoryHtml = `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
1290
+ }
1291
+ }
1292
+ }
1130
1293
  const idx = (0, import_react_ui_grid3.toPlaneCellIndex)({
1131
1294
  col: colIndex,
1132
1295
  row: displayIndex
@@ -1149,6 +1312,8 @@ var TablePresentation = class {
1149
1312
  const fields = this.model.table.view?.target?.fields ?? [];
1150
1313
  for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1151
1314
  const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
1315
+ const sorting = this.model.sorting?.sorting;
1316
+ const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
1152
1317
  cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1153
1318
  col,
1154
1319
  row: 0
@@ -1157,9 +1322,16 @@ var TablePresentation = class {
1157
1322
  value: props.title ?? field.path,
1158
1323
  readonly: true,
1159
1324
  resizeHandle: "col",
1160
- accessoryHtml: tableButtons.columnSettings.render({
1325
+ accessoryHtml: `
1326
+ ${direction !== void 0 ? tableButtons.sort.render({
1327
+ fieldId: field.id,
1328
+ direction
1329
+ }) : ""}
1330
+ ${tableButtons.columnSettings.render({
1161
1331
  fieldId: field.id
1162
- })
1332
+ })}
1333
+ `,
1334
+ className: "!bg-gridHeader"
1163
1335
  };
1164
1336
  }
1165
1337
  return cells;
@@ -1168,7 +1340,7 @@ var TablePresentation = class {
1168
1340
  const cells = {};
1169
1341
  for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1170
1342
  const isSelected = this.model.selection.isRowIndexSelected(row);
1171
- const classes = (0, import_react_ui_form5.cellClassesForRowSelection)(isSelected);
1343
+ const classes = (0, import_react_ui_form6.cellClassesForRowSelection)(isSelected);
1172
1344
  cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1173
1345
  col: 0,
1174
1346
  row
@@ -1188,7 +1360,7 @@ var TablePresentation = class {
1188
1360
  const cells = {};
1189
1361
  for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1190
1362
  const isSelected = this.model.selection.isRowIndexSelected(row);
1191
- const classes = (0, import_react_ui_form5.cellClassesForRowSelection)(isSelected);
1363
+ const classes = (0, import_react_ui_form6.cellClassesForRowSelection)(isSelected);
1192
1364
  cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1193
1365
  col: 0,
1194
1366
  row
@@ -1209,13 +1381,14 @@ var TablePresentation = class {
1209
1381
  col: 0,
1210
1382
  row: 0
1211
1383
  })]: {
1212
- value: "",
1213
1384
  accessoryHtml: tableControls.checkbox.render({
1214
1385
  rowIndex: 0,
1215
1386
  header: true,
1216
1387
  checked: this.model.selection.allRowsSeleted.value
1217
1388
  }),
1218
- readonly: true
1389
+ className: "!bg-gridHeader",
1390
+ readonly: true,
1391
+ value: ""
1219
1392
  }
1220
1393
  };
1221
1394
  }
@@ -1225,11 +1398,12 @@ var TablePresentation = class {
1225
1398
  col: 0,
1226
1399
  row: 0
1227
1400
  })]: {
1228
- value: "",
1229
1401
  accessoryHtml: tableButtons.addColumn.render({
1230
1402
  disabled: (this.model.table.view?.target?.fields?.length ?? 0) >= import_schema2.VIEW_FIELD_LIMIT
1231
1403
  }),
1232
- readonly: true
1404
+ className: "!bg-gridHeader",
1405
+ readonly: true,
1406
+ value: ""
1233
1407
  }
1234
1408
  };
1235
1409
  }
@@ -1269,7 +1443,7 @@ var completion = ({ debug, onQuery, onMatch }) => {
1269
1443
  })
1270
1444
  ];
1271
1445
  };
1272
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
1446
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
1273
1447
  var newValue = Symbol.for("newValue");
1274
1448
  var createOption = (text) => ({
1275
1449
  [newValue]: true,
@@ -1287,7 +1461,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1287
1461
  const field = model.projection.view.fields[col];
1288
1462
  const fieldProjection2 = model.projection.getFieldProjection(field.id);
1289
1463
  (0, import_invariant3.invariant)(fieldProjection2, void 0, {
1290
- F: __dxlog_file4,
1464
+ F: __dxlog_file3,
1291
1465
  L: 67,
1292
1466
  S: void 0,
1293
1467
  A: [
@@ -1361,7 +1535,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1361
1535
  ];
1362
1536
  if (onQuery) {
1363
1537
  switch (fieldProjection.props.format) {
1364
- case import_echo_schema6.FormatEnum.Ref: {
1538
+ case import_echo_schema7.FormatEnum.Ref: {
1365
1539
  extension2.push([
1366
1540
  completion({
1367
1541
  onQuery: (text) => onQuery(fieldProjection, text),
@@ -1435,7 +1609,7 @@ var determineNavigationDelta = ({ key, shift }) => {
1435
1609
  }
1436
1610
  return shift ? -1 : 1;
1437
1611
  };
1438
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
1612
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
1439
1613
  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";
1440
1614
  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";
1441
1615
  var frozen = {
@@ -1503,6 +1677,10 @@ var TableMain = /* @__PURE__ */ (0, import_react.forwardRef)(({ model, presentat
1503
1677
  modals.showReferencePanel(data.targetId, data.schemaId);
1504
1678
  break;
1505
1679
  }
1680
+ case "sort": {
1681
+ model?.sorting?.toggleSort(data.fieldId);
1682
+ break;
1683
+ }
1506
1684
  }
1507
1685
  return;
1508
1686
  }
@@ -1603,8 +1781,8 @@ var TableMain = /* @__PURE__ */ (0, import_react.forwardRef)(({ model, presentat
1603
1781
  if (model && props.referenceSchema && field.referencePath) {
1604
1782
  const space = (0, import_echo.getSpace)(model.table);
1605
1783
  (0, import_invariant.invariant)(space, void 0, {
1606
- F: __dxlog_file5,
1607
- L: 260,
1784
+ F: __dxlog_file4,
1785
+ L: 264,
1608
1786
  S: void 0,
1609
1787
  A: [
1610
1788
  "space",
@@ -1687,73 +1865,76 @@ var Table = {
1687
1865
  Root: TableRoot,
1688
1866
  Main: TableMain
1689
1867
  };
1690
- var buttonStyles = "min-bs-0 p-2";
1691
- var tooltipProps = {
1692
- side: "top",
1693
- classNames: "z-10"
1694
- };
1695
- var ToolbarSeparator = () => /* @__PURE__ */ import_react9.default.createElement("div", {
1696
- role: "separator",
1697
- className: "grow"
1698
- });
1699
- var ToolbarButton = ({ icon, children, ...props }) => {
1700
- return /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Root, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Trigger, {
1701
- asChild: true
1702
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Toolbar.Button, {
1703
- variant: "ghost",
1704
- ...props,
1705
- classNames: buttonStyles
1706
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Icon, {
1707
- icon,
1708
- size: 5
1709
- }), /* @__PURE__ */ import_react9.default.createElement("span", {
1710
- className: "sr-only"
1711
- }, children))), /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Portal, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Content, tooltipProps, children, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Arrow, null))));
1712
- };
1713
- var [ToolbarContextProvider, useToolbarContext] = (0, import_react_context.createContext)("Toolbar");
1714
- var ToolbarRoot = ({ classNames, children, onAction }) => {
1715
- return /* @__PURE__ */ import_react8.default.createElement(ToolbarContextProvider, {
1716
- onAction
1717
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Toolbar.Root, {
1718
- classNames: [
1719
- "is-full shrink-0 overflow-x-auto overflow-y-hidden p-1 attention-surface",
1720
- classNames
1721
- ]
1722
- }, children));
1723
- };
1724
- var Editing = () => {
1725
- const { onAction } = useToolbarContext("Editing");
1726
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
1727
- return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(ToolbarButton, {
1728
- value: "add-row",
1868
+ var createTableToolbarActions = (state) => {
1869
+ const add = (0, import_react_ui_menu.createMenuAction)("add-row", {
1870
+ type: "add-row",
1729
1871
  icon: "ph--plus--regular",
1730
- "data-testid": "table.toolbar.add-row",
1731
- onClick: () => onAction?.({
1732
- type: "add-row"
1733
- })
1734
- }, t("add row")));
1735
- };
1736
- var Actions = () => {
1737
- const { onAction } = useToolbarContext("Actions");
1738
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
1739
- return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(ToolbarButton, {
1740
- value: "comment",
1872
+ label: [
1873
+ "add row",
1874
+ {
1875
+ ns: translationKey
1876
+ }
1877
+ ],
1878
+ testId: "table.toolbar.add-row"
1879
+ });
1880
+ const save = (0, import_react_ui_menu.createMenuAction)("save-view", {
1881
+ type: "save-view",
1882
+ icon: "ph--floppy-disk--regular",
1883
+ label: [
1884
+ "save view label",
1885
+ {
1886
+ ns: translationKey
1887
+ }
1888
+ ],
1889
+ testId: "table.toolbar.save-view",
1890
+ iconOnly: false,
1891
+ hidden: !state.viewDirty
1892
+ });
1893
+ const gap = (0, import_react_ui_menu.createGapSeparator)();
1894
+ const comment = (0, import_react_ui_menu.createMenuAction)("comment", {
1895
+ type: "comment",
1741
1896
  icon: "ph--chat-text--regular",
1742
- "data-testid": "table.toolbar.comment",
1743
- onClick: () => onAction?.({
1744
- type: "comment"
1745
- })
1746
- }, t("create comment")));
1897
+ label: [
1898
+ "create comment",
1899
+ {
1900
+ ns: translationKey
1901
+ }
1902
+ ],
1903
+ testId: "table.toolbar.comment"
1904
+ });
1905
+ const nodes = [
1906
+ add,
1907
+ save,
1908
+ ...gap.nodes,
1909
+ comment
1910
+ ];
1911
+ return {
1912
+ nodes,
1913
+ edges: nodes.map(({ id: target }) => ({
1914
+ source: "root",
1915
+ target
1916
+ }))
1917
+ };
1747
1918
  };
1748
- var Toolbar = {
1749
- Root: ToolbarRoot,
1750
- Editing,
1751
- Actions,
1752
- Separator: ToolbarSeparator
1919
+ var TableToolbar = ({ classNames, viewDirty, attendableId, onAction }) => {
1920
+ const state = (0, import_react8.useMemo)(() => (0, import_live_object2.create)({
1921
+ viewDirty
1922
+ }), []);
1923
+ const actionsCreator = (0, import_react8.useCallback)(() => createTableToolbarActions(state), [
1924
+ state
1925
+ ]);
1926
+ const menu = (0, import_react_ui_menu.useMenuActions)(actionsCreator);
1927
+ return /* @__PURE__ */ import_react8.default.createElement(import_react_ui_menu.MenuProvider, {
1928
+ ...menu,
1929
+ attendableId,
1930
+ onAction
1931
+ }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui_menu.ToolbarMenu, {
1932
+ classNames
1933
+ }));
1753
1934
  };
1754
1935
  var useTableModel = ({ objects, table, projection, ...props }) => {
1755
- const [model, setModel] = (0, import_react10.useState)();
1756
- (0, import_react10.useEffect)(() => {
1936
+ const [model, setModel] = (0, import_react9.useState)();
1937
+ (0, import_react9.useEffect)(() => {
1757
1938
  if (!table || !projection) {
1758
1939
  return;
1759
1940
  }
@@ -1775,7 +1956,7 @@ var useTableModel = ({ objects, table, projection, ...props }) => {
1775
1956
  table,
1776
1957
  projection
1777
1958
  ]);
1778
- (0, import_react10.useEffect)(() => {
1959
+ (0, import_react9.useEffect)(() => {
1779
1960
  if (objects) {
1780
1961
  model?.setRows(objects);
1781
1962
  }
@@ -1783,6 +1964,26 @@ var useTableModel = ({ objects, table, projection, ...props }) => {
1783
1964
  model,
1784
1965
  objects
1785
1966
  ]);
1967
+ const { select, clear } = (0, import_react_ui_attention2.useSelectionActions)([
1968
+ table?.id,
1969
+ table?.view?.target?.query.type
1970
+ ].filter(import_util2.isNonNullable));
1971
+ (0, import_react9.useEffect)(() => {
1972
+ if (!model) {
1973
+ return;
1974
+ }
1975
+ const unsubscribe = (0, import_signals_core6.effect)(() => {
1976
+ select([
1977
+ ...model.selection.selection.value
1978
+ ]);
1979
+ });
1980
+ return () => {
1981
+ clear();
1982
+ unsubscribe();
1983
+ };
1984
+ }, [
1985
+ model
1986
+ ]);
1786
1987
  return model;
1787
1988
  };
1788
1989
  // Annotate the CommonJS export names for ESM import in node:
@@ -1794,8 +1995,8 @@ var useTableModel = ({ objects, table, projection, ...props }) => {
1794
1995
  TableModel,
1795
1996
  TablePresentation,
1796
1997
  TableSchema,
1998
+ TableToolbar,
1797
1999
  TableType,
1798
- Toolbar,
1799
2000
  initializeTable,
1800
2001
  renderCheckbox,
1801
2002
  renderSwitch,
@@ -1803,7 +2004,6 @@ var useTableModel = ({ objects, table, projection, ...props }) => {
1803
2004
  tableControls,
1804
2005
  touch,
1805
2006
  translations,
1806
- useTableModel,
1807
- useToolbarContext
2007
+ useTableModel
1808
2008
  });
1809
2009
  //# sourceMappingURL=index.cjs.map