@dxos/react-ui-table 0.8.4-main.67995b8 → 0.8.4-main.f5c0578

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 (90) hide show
  1. package/dist/lib/browser/{chunk-5XLSHLOG.mjs → chunk-ZAOSIG3L.mjs} +382 -319
  2. package/dist/lib/browser/chunk-ZAOSIG3L.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +399 -380
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +4 -2
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/{chunk-Y66YLSTC.mjs → chunk-ZOFFI3JJ.mjs} +382 -319
  9. package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +399 -380
  11. package/dist/lib/node-esm/index.mjs.map +4 -4
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +4 -2
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -1
  16. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  17. package/dist/types/src/components/Table/ColumnSettings.d.ts +1 -1
  18. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  19. package/dist/types/src/components/Table/CreateRefPanel.d.ts +1 -1
  20. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  21. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  22. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +1 -1
  23. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/Table/{relations.stories.d.ts → Relations.stories.d.ts} +2 -2
  25. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
  26. package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
  27. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  28. package/dist/types/src/components/Table/Table.d.ts +1 -0
  29. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  30. package/dist/types/src/components/Table/Table.stories.d.ts +1 -1
  31. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  32. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  33. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +5 -5
  34. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  35. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +1 -1
  37. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  38. package/dist/types/src/hooks/useTableModel.d.ts +1 -1
  39. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  40. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  41. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  42. package/dist/types/src/model/table-model.d.ts +3 -2
  43. package/dist/types/src/model/table-model.d.ts.map +1 -1
  44. package/dist/types/src/model/table-presentation.d.ts +2 -1
  45. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  46. package/dist/types/src/model/table-sorting.d.ts +2 -2
  47. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  48. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  49. package/dist/types/src/translations.d.ts +2 -2
  50. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  51. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  52. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  53. package/dist/types/src/util/table.d.ts +2 -1
  54. package/dist/types/src/util/table.d.ts.map +1 -1
  55. package/dist/types/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +46 -46
  57. package/src/components/Table/ColumnActionsMenu.tsx +1 -1
  58. package/src/components/Table/ColumnSettings.tsx +1 -1
  59. package/src/components/Table/CreateRefPanel.tsx +1 -1
  60. package/src/components/Table/DynamicTable.stories.tsx +3 -2
  61. package/src/components/Table/DynamicTable.tsx +4 -3
  62. package/src/components/Table/{relations.stories.tsx → Relations.stories.tsx} +12 -4
  63. package/src/components/Table/RowActionsMenu.tsx +3 -3
  64. package/src/components/Table/Table.stories.tsx +12 -7
  65. package/src/components/Table/Table.tsx +49 -43
  66. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
  67. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +4 -3
  68. package/src/components/TableCellEditor/TableCellEditor.tsx +16 -20
  69. package/src/components/TableCellEditor/extension.ts +2 -2
  70. package/src/components/TableToolbar/TableToolbar.tsx +2 -2
  71. package/src/components/testing.ts +1 -1
  72. package/src/hooks/useTableModel.ts +1 -1
  73. package/src/model/modal-controller.ts +1 -1
  74. package/src/model/selection-model.ts +3 -2
  75. package/src/model/table-model.test.ts +2 -1
  76. package/src/model/table-model.ts +13 -10
  77. package/src/model/table-presentation.test.ts +3 -2
  78. package/src/model/table-presentation.ts +28 -6
  79. package/src/model/table-sorting.ts +3 -3
  80. package/src/playwright/smoke.spec.ts +92 -0
  81. package/src/testing/useTestTableModel.ts +3 -2
  82. package/src/translations.ts +2 -2
  83. package/src/util/dynamic-table.ts +2 -2
  84. package/src/util/schema.ts +1 -1
  85. package/src/util/table-buttons.ts +2 -1
  86. package/src/util/table-controls.ts +4 -1
  87. package/src/util/table.ts +7 -3
  88. package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +0 -7
  89. package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +0 -7
  90. package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-table",
3
- "version": "0.8.4-main.67995b8",
3
+ "version": "0.8.4-main.f5c0578",
4
4
  "description": "A table component.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -10,28 +10,28 @@
10
10
  "type": "module",
11
11
  "exports": {
12
12
  "./deprecated": {
13
+ "source": "./src/deprecated/index.ts",
13
14
  "types": "./dist/types/src/deprecated/index.d.ts",
14
15
  "browser": "./dist/lib/browser/deprecated/index.mjs",
15
- "node": "./dist/lib/node-esm/deprecated/index.mjs",
16
- "source": "./src/deprecated/index.ts"
16
+ "node": "./dist/lib/node-esm/deprecated/index.mjs"
17
17
  },
18
18
  ".": {
19
+ "source": "./src/index.ts",
19
20
  "types": "./dist/types/src/index.d.ts",
20
21
  "browser": "./dist/lib/browser/index.mjs",
21
- "node": "./dist/lib/node-esm/index.mjs",
22
- "source": "./src/index.ts"
22
+ "node": "./dist/lib/node-esm/index.mjs"
23
23
  },
24
24
  "./testing": {
25
+ "source": "./src/testing/index.ts",
25
26
  "types": "./dist/types/src/testing/index.d.ts",
26
27
  "browser": "./dist/lib/browser/testing/index.mjs",
27
- "node": "./dist/lib/node-esm/testing/index.mjs",
28
- "source": "./src/testing/index.ts"
28
+ "node": "./dist/lib/node-esm/testing/index.mjs"
29
29
  },
30
30
  "./types": {
31
+ "source": "./src/types/index.ts",
31
32
  "types": "./dist/types/src/types/index.d.ts",
32
33
  "browser": "./dist/lib/browser/types/index.mjs",
33
- "node": "./dist/lib/node-esm/types/index.mjs",
34
- "source": "./src/types/index.ts"
34
+ "node": "./dist/lib/node-esm/types/index.mjs"
35
35
  }
36
36
  },
37
37
  "types": "dist/types/src/index.d.ts",
@@ -65,51 +65,51 @@
65
65
  "@radix-ui/react-use-controllable-state": "1.1.0",
66
66
  "date-fns": "^3.3.1",
67
67
  "lodash.orderby": "^4.6.0",
68
- "@dxos/context": "0.8.4-main.67995b8",
69
- "@dxos/echo": "0.8.4-main.67995b8",
70
- "@dxos/debug": "0.8.4-main.67995b8",
71
- "@dxos/echo-schema": "0.8.4-main.67995b8",
72
- "@dxos/echo-db": "0.8.4-main.67995b8",
73
- "@dxos/invariant": "0.8.4-main.67995b8",
74
- "@dxos/keys": "0.8.4-main.67995b8",
75
- "@dxos/effect": "0.8.4-main.67995b8",
76
- "@dxos/lit-grid": "0.8.4-main.67995b8",
77
- "@dxos/log": "0.8.4-main.67995b8",
78
- "@dxos/plugin-search": "0.8.4-main.67995b8",
79
- "@dxos/random": "0.8.4-main.67995b8",
80
- "@dxos/live-object": "0.8.4-main.67995b8",
81
- "@dxos/react-client": "0.8.4-main.67995b8",
82
- "@dxos/react-ui-attention": "0.8.4-main.67995b8",
83
- "@dxos/react-ui-editor": "0.8.4-main.67995b8",
84
- "@dxos/react-ui-form": "0.8.4-main.67995b8",
85
- "@dxos/react-ui-grid": "0.8.4-main.67995b8",
86
- "@dxos/react-ui-stack": "0.8.4-main.67995b8",
87
- "@dxos/react-ui-menu": "0.8.4-main.67995b8",
88
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.67995b8",
89
- "@dxos/react-ui-searchlist": "0.8.4-main.67995b8",
90
- "@dxos/react-ui-tag-picker": "0.8.4-main.67995b8",
91
- "@dxos/react-ui-types": "0.8.4-main.67995b8",
92
- "@dxos/schema": "0.8.4-main.67995b8",
93
- "@dxos/util": "0.8.4-main.67995b8"
68
+ "@dxos/debug": "0.8.4-main.f5c0578",
69
+ "@dxos/context": "0.8.4-main.f5c0578",
70
+ "@dxos/echo": "0.8.4-main.f5c0578",
71
+ "@dxos/echo-db": "0.8.4-main.f5c0578",
72
+ "@dxos/echo-schema": "0.8.4-main.f5c0578",
73
+ "@dxos/effect": "0.8.4-main.f5c0578",
74
+ "@dxos/invariant": "0.8.4-main.f5c0578",
75
+ "@dxos/keys": "0.8.4-main.f5c0578",
76
+ "@dxos/lit-grid": "0.8.4-main.f5c0578",
77
+ "@dxos/live-object": "0.8.4-main.f5c0578",
78
+ "@dxos/log": "0.8.4-main.f5c0578",
79
+ "@dxos/plugin-search": "0.8.4-main.f5c0578",
80
+ "@dxos/random": "0.8.4-main.f5c0578",
81
+ "@dxos/react-client": "0.8.4-main.f5c0578",
82
+ "@dxos/react-ui-editor": "0.8.4-main.f5c0578",
83
+ "@dxos/react-ui-attention": "0.8.4-main.f5c0578",
84
+ "@dxos/react-ui-form": "0.8.4-main.f5c0578",
85
+ "@dxos/react-ui-grid": "0.8.4-main.f5c0578",
86
+ "@dxos/react-ui-menu": "0.8.4-main.f5c0578",
87
+ "@dxos/react-ui-searchlist": "0.8.4-main.f5c0578",
88
+ "@dxos/react-ui-tag-picker": "0.8.4-main.f5c0578",
89
+ "@dxos/react-ui-types": "0.8.4-main.f5c0578",
90
+ "@dxos/react-ui-stack": "0.8.4-main.f5c0578",
91
+ "@dxos/schema": "0.8.4-main.f5c0578",
92
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.f5c0578",
93
+ "@dxos/util": "0.8.4-main.f5c0578"
94
94
  },
95
95
  "devDependencies": {
96
96
  "@effect-rx/rx-react": "0.38.0",
97
- "@effect/platform": "0.89.0",
97
+ "@effect/platform": "0.90.2",
98
98
  "@types/lodash.orderby": "^4.6.9",
99
99
  "@types/react": "~18.2.0",
100
100
  "@types/react-dom": "~18.2.0",
101
- "effect": "3.17.0",
101
+ "effect": "3.17.7",
102
102
  "fast-check": "^3.19.0",
103
103
  "react": "~18.2.0",
104
104
  "react-dom": "~18.2.0",
105
105
  "vite": "5.4.7",
106
- "@dxos/plugin-search": "0.8.4-main.67995b8",
107
- "@dxos/echo-signals": "0.8.4-main.67995b8",
108
- "@dxos/random": "0.8.4-main.67995b8",
109
- "@dxos/react-ui": "0.8.4-main.67995b8",
110
- "@dxos/react-ui-theme": "0.8.4-main.67995b8",
111
- "@dxos/storybook-utils": "0.8.4-main.67995b8",
112
- "@dxos/test-utils": "0.8.4-main.67995b8"
106
+ "@dxos/plugin-search": "0.8.4-main.f5c0578",
107
+ "@dxos/random": "0.8.4-main.f5c0578",
108
+ "@dxos/react-ui": "0.8.4-main.f5c0578",
109
+ "@dxos/echo-signals": "0.8.4-main.f5c0578",
110
+ "@dxos/react-ui-theme": "0.8.4-main.f5c0578",
111
+ "@dxos/test-utils": "0.8.4-main.f5c0578",
112
+ "@dxos/storybook-utils": "0.8.4-main.f5c0578"
113
113
  },
114
114
  "peerDependencies": {
115
115
  "@effect-rx/rx-react": "^0.34.1",
@@ -117,8 +117,8 @@
117
117
  "effect": "^3.13.3",
118
118
  "react": "~18.2.0",
119
119
  "react-dom": "~18.2.0",
120
- "@dxos/react-ui": "0.8.4-main.67995b8",
121
- "@dxos/react-ui-theme": "0.8.4-main.67995b8"
120
+ "@dxos/react-ui": "0.8.4-main.f5c0578",
121
+ "@dxos/react-ui-theme": "0.8.4-main.f5c0578"
122
122
  },
123
123
  "publishConfig": {
124
124
  "access": "public"
@@ -6,7 +6,7 @@ import React from 'react';
6
6
 
7
7
  import { DropdownMenu, useTranslation } from '@dxos/react-ui';
8
8
 
9
- import { type TableModel, type ModalController } from '../../model';
9
+ import { type ModalController, type TableModel } from '../../model';
10
10
  import { translationKey } from '../../translations';
11
11
 
12
12
  type ColumnActionsMenuProps = { model: TableModel; modals: ModalController };
@@ -10,7 +10,7 @@ import { Popover } from '@dxos/react-ui';
10
10
  import { FieldEditor } from '@dxos/react-ui-form';
11
11
  import { type FieldType } from '@dxos/schema';
12
12
 
13
- import { type TableModel, type ModalController } from '../../model';
13
+ import { type ModalController, type TableModel } from '../../model';
14
14
 
15
15
  type ColumnSettingsProps = {
16
16
  registry?: SchemaRegistry;
@@ -12,7 +12,7 @@ import { Popover } from '@dxos/react-ui';
12
12
  import { Form } from '@dxos/react-ui-form';
13
13
  import { type GridScopedProps, useGridContext } from '@dxos/react-ui-grid';
14
14
 
15
- import { type TableModel, type ModalController } from '../../model';
15
+ import { type ModalController, type TableModel } from '../../model';
16
16
 
17
17
  export type CreateRefPanelProps = { model?: TableModel; modals: ModalController };
18
18
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import '@dxos-theme';
6
6
 
7
- import { type StoryObj, type Meta } from '@storybook/react-vite';
7
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
8
  import React, { useMemo, useState } from 'react';
9
9
 
10
10
  import { Obj } from '@dxos/echo';
@@ -17,10 +17,11 @@ import { type SchemaPropertyDefinition } from '@dxos/schema';
17
17
  import { Testing } from '@dxos/schema/testing';
18
18
  import { withLayout, withTheme } from '@dxos/storybook-utils';
19
19
 
20
- import { DynamicTable } from './DynamicTable';
21
20
  import { type TableFeatures } from '../../model';
22
21
  import { translations } from '../../translations';
23
22
 
23
+ import { DynamicTable } from './DynamicTable';
24
+
24
25
  faker.seed(0);
25
26
 
26
27
  const useTestPropertiesAndObjects = () => {
@@ -3,16 +3,17 @@
3
3
  //
4
4
 
5
5
  import { type Schema } from 'effect';
6
- import React, { useRef, useMemo, useCallback } from 'react';
6
+ import React, { useCallback, useMemo, useRef } from 'react';
7
7
 
8
8
  import { type JsonSchemaType } from '@dxos/echo-schema';
9
9
  import { type ThemedClassName, useDefaultValue } from '@dxos/react-ui';
10
10
  import { mx } from '@dxos/react-ui-theme';
11
11
 
12
- import { Table, type TableController } from './Table';
13
12
  import { useTableModel } from '../../hooks';
14
13
  import { type TableFeatures, TablePresentation, type TableRowAction } from '../../model';
15
- import { getBaseSchema, makeDynamicTable, type TablePropertyDefinition } from '../../util';
14
+ import { type TablePropertyDefinition, getBaseSchema, makeDynamicTable } from '../../util';
15
+
16
+ import { Table, type TableController } from './Table';
16
17
 
17
18
  type DynamicTableProps = ThemedClassName<{
18
19
  name?: string; // TODO(burdon): Remove?
@@ -4,7 +4,7 @@
4
4
 
5
5
  import '@dxos-theme';
6
6
 
7
- import { type StoryObj, type Meta } from '@storybook/react-vite';
7
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
8
  import React, { useEffect, useMemo, useState } from 'react';
9
9
 
10
10
  import { Type } from '@dxos/echo';
@@ -13,16 +13,17 @@ import { faker } from '@dxos/random';
13
13
  import { useClient } from '@dxos/react-client';
14
14
  import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
15
15
  import { DataType } from '@dxos/schema';
16
- import { createAsyncGenerator, type ValueGenerator } from '@dxos/schema/testing';
16
+ import { type ValueGenerator, createAsyncGenerator } from '@dxos/schema/testing';
17
17
  import { withLayout, withTheme } from '@dxos/storybook-utils';
18
18
 
19
- import { Table } from './Table';
20
19
  import { useTableModel } from '../../hooks';
21
20
  import { type TableFeatures, TablePresentation, type TableRow } from '../../model';
22
21
  import { translations } from '../../translations';
23
22
  import { TableView } from '../../types';
24
23
  import { createTable } from '../../util';
25
24
 
25
+ import { Table } from './Table';
26
+
26
27
  faker.seed(1);
27
28
  const generator: ValueGenerator = faker as any;
28
29
 
@@ -47,14 +48,21 @@ const useTestModel = <S extends Type.Obj.Any>(schema: S, count: number) => {
47
48
  }
48
49
 
49
50
  const timeout = setTimeout(async () => {
50
- const { jsonSchema, view } = await createTable({ client, space, typename: Type.getTypename(schema) });
51
+ const {
52
+ jsonSchema,
53
+ schema: effectSchema,
54
+ view,
55
+ } = await createTable({ client, space, typename: Type.getTypename(schema) });
51
56
  setJsonSchema(jsonSchema);
52
57
  setView(view);
58
+ space.db.add(view);
59
+ await space.db.schemaRegistry.register([effectSchema]);
53
60
  });
54
61
  return () => clearTimeout(timeout);
55
62
  }, [client, space, schema]);
56
63
 
57
64
  const model = useTableModel<TableRow>({ view, schema: jsonSchema, rows: [], features });
65
+
58
66
  useEffect(() => {
59
67
  if (!model || !space) {
60
68
  return;
@@ -4,9 +4,9 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { DropdownMenu, useTranslation } from '@dxos/react-ui';
7
+ import { DropdownMenu, toLocalizedString, useTranslation } from '@dxos/react-ui';
8
8
 
9
- import { type TableModel, type ModalController } from '../../model';
9
+ import { type ModalController, type TableModel } from '../../model';
10
10
  import { translationKey } from '../../translations';
11
11
 
12
12
  type RowActionsMenuProps = { model: TableModel; modals: ModalController };
@@ -38,7 +38,7 @@ export const RowActionsMenu = ({ model, modals }: RowActionsMenuProps) => {
38
38
  model.handleRowAction(action.id, state.rowIndex);
39
39
  }}
40
40
  >
41
- {t(action.translationKey)}
41
+ {toLocalizedString(action.label, t)}
42
42
  </DropdownMenu.Item>
43
43
  ))}
44
44
  </DropdownMenu.Viewport>
@@ -4,36 +4,38 @@
4
4
 
5
5
  import '@dxos-theme';
6
6
 
7
- import { type StoryObj, type Meta } from '@storybook/react-vite';
7
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
8
  import { Schema } from 'effect';
9
9
  import React, { useCallback } from 'react';
10
10
 
11
11
  import { Obj, Type } from '@dxos/echo';
12
12
  import {
13
- FormatEnum,
14
13
  EchoObject,
15
- GeneratorAnnotation,
16
14
  FormatAnnotation,
15
+ FormatEnum,
16
+ GeneratorAnnotation,
17
+ LabelAnnotation,
17
18
  PropertyMetaAnnotationId,
18
19
  } from '@dxos/echo-schema';
19
20
  import { invariant } from '@dxos/invariant';
20
21
  import { faker } from '@dxos/random';
21
22
  import { PublicKey } from '@dxos/react-client';
22
- import { live, type Space } from '@dxos/react-client/echo';
23
+ import { type Space, live } from '@dxos/react-client/echo';
23
24
  import { withClientProvider } from '@dxos/react-client/testing';
24
25
  import { ViewEditor } from '@dxos/react-ui-form';
25
26
  import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
26
- import { getSchemaFromPropertyDefinitions, DataType } from '@dxos/schema';
27
+ import { DataType, getSchemaFromPropertyDefinitions } from '@dxos/schema';
27
28
  import { Testing, createObjectFactory } from '@dxos/schema/testing';
28
29
  import { withLayout, withTheme } from '@dxos/storybook-utils';
29
30
 
30
- import { Table } from './Table';
31
31
  import { useTestTableModel } from '../../testing';
32
32
  import { translations } from '../../translations';
33
33
  import { TableView } from '../../types';
34
34
  import { createTable } from '../../util';
35
35
  import { TableToolbar } from '../TableToolbar';
36
36
 
37
+ import { Table } from './Table';
38
+
37
39
  const TestSchema = Schema.Struct({
38
40
  // TODO(wittjosiah): Should be title. Currently name to work with default label.
39
41
  name: Schema.optional(Schema.String).annotations({ title: 'Title' }),
@@ -58,7 +60,10 @@ const TestSchema = Schema.Struct({
58
60
  parent: Schema.optional(Schema.suspend((): Type.Ref<TestSchema> => Type.Ref(TestSchema))).annotations({
59
61
  title: 'Parent',
60
62
  }),
61
- }).pipe(Type.Obj({ typename: `example.com/type/${PublicKey.random().truncate()}`, version: '0.1.0' }));
63
+ }).pipe(
64
+ Type.Obj({ typename: `example.com/type/${PublicKey.random().truncate()}`, version: '0.1.0' }),
65
+ LabelAnnotation.set(['name']),
66
+ );
62
67
  interface TestSchema extends Schema.Schema.Type<typeof TestSchema> {}
63
68
 
64
69
  const StoryViewEditor = ({
@@ -9,10 +9,10 @@ import React, {
9
9
  type WheelEvent,
10
10
  forwardRef,
11
11
  useCallback,
12
+ useEffect,
12
13
  useImperativeHandle,
13
- useState,
14
14
  useMemo,
15
- useEffect,
15
+ useState,
16
16
  } from 'react';
17
17
 
18
18
  import { type Client } from '@dxos/client';
@@ -24,27 +24,28 @@ import { getSpace } from '@dxos/react-client/echo';
24
24
  import { useTranslation } from '@dxos/react-ui';
25
25
  import { useAttention } from '@dxos/react-ui-attention';
26
26
  import {
27
- closestCell,
28
27
  type DxGridElement,
29
- type DxGridPosition,
30
- type GridContentProps,
31
- Grid,
32
28
  type DxGridPlane,
33
29
  type DxGridPlaneRange,
34
- gridSeparatorInlineEnd,
30
+ type DxGridPosition,
31
+ Grid,
32
+ type GridContentProps,
33
+ closestCell,
35
34
  gridSeparatorBlockEnd,
35
+ gridSeparatorInlineEnd,
36
36
  } from '@dxos/react-ui-grid';
37
37
  import { mx } from '@dxos/react-ui-theme';
38
38
  import { isNotFalsy, safeParseInt } from '@dxos/util';
39
39
 
40
+ import { ModalController, type TableModel, type TablePresentation } from '../../model';
41
+ import { translationKey } from '../../translations';
42
+ import { tableButtons, tableControls } from '../../util';
43
+ import { type TableCellEditorProps, TableValueEditor, createOption } from '../TableCellEditor';
44
+
40
45
  import { ColumnActionsMenu } from './ColumnActionsMenu';
41
46
  import { ColumnSettings } from './ColumnSettings';
42
47
  import { CreateRefPanel } from './CreateRefPanel';
43
48
  import { RowActionsMenu } from './RowActionsMenu';
44
- import { ModalController, type TableModel, type TablePresentation } from '../../model';
45
- import { translationKey } from '../../translations';
46
- import { tableButtons, tableControls } from '../../util';
47
- import { createOption, TableValueEditor, type TableCellEditorProps } from '../TableCellEditor';
48
49
 
49
50
  //
50
51
  // Table.Root
@@ -76,6 +77,7 @@ const TableRoot = ({ children, role = 'article' }: TableRootProps) => {
76
77
 
77
78
  export type TableController = {
78
79
  update?: (cell?: DxGridPosition) => void;
80
+ focusDraft?: () => void;
79
81
  };
80
82
 
81
83
  export type TableMainProps = {
@@ -140,9 +142,29 @@ const TableMain = forwardRef<TableController, TableMainProps>(
140
142
  dxGrid.requestUpdate();
141
143
  }
142
144
  },
145
+ focusDraft: () => {
146
+ requestAnimationFrame(() => {
147
+ dxGrid.setFocus({ plane: 'frozenRowsEnd', col: 0, row: 0 });
148
+ dxGrid.refocus();
149
+ });
150
+ },
143
151
  };
144
152
  }, [presentation, dxGrid]);
145
153
 
154
+ const handleSaveDraftRow = useCallback(
155
+ (rowIndex = 0) => {
156
+ if (model && dxGrid) {
157
+ const didCommitSuccessfully = model.commitDraftRow(rowIndex);
158
+ if (didCommitSuccessfully) {
159
+ requestAnimationFrame(() => {
160
+ dxGrid.scrollToEndRow();
161
+ });
162
+ }
163
+ }
164
+ },
165
+ [model, dxGrid],
166
+ );
167
+
146
168
  const handleGridClick = useCallback(
147
169
  (event: MouseEvent) => {
148
170
  const rowIndex = safeParseInt((event.target as HTMLElement).closest('[aria-rowindex]')?.ariaRowIndex ?? '');
@@ -192,14 +214,7 @@ const TableMain = forwardRef<TableController, TableMainProps>(
192
214
  break;
193
215
  }
194
216
  case 'saveDraftRow': {
195
- if (model) {
196
- const didCommitSuccessfully = model.commitDraftRow(data.rowIndex);
197
- if (dxGrid && didCommitSuccessfully) {
198
- requestAnimationFrame(() => {
199
- dxGrid.scrollToEndRow();
200
- });
201
- }
202
- }
217
+ handleSaveDraftRow();
203
218
  break;
204
219
  }
205
220
  }
@@ -240,32 +255,23 @@ const TableMain = forwardRef<TableController, TableMainProps>(
240
255
  );
241
256
 
242
257
  const handleFocus = useCallback<NonNullable<TableCellEditorProps['onFocus']>>(
243
- (increment, delta) => {
244
- if (dxGrid) {
245
- dxGrid.refocus(increment, delta);
246
- }
247
- },
248
- [dxGrid],
249
- );
250
-
251
- const handleEnter = useCallback<NonNullable<TableCellEditorProps['onEnter']>>(
252
- (cell) => {
253
- if (!model?.features.dataEditable) {
254
- return;
255
- }
256
-
257
- // TODO(burdon): Insert row only if bottom row isn't completely blank already.
258
- if (model && cell.row === model.getRowCount() - 1) {
259
- model.insertRow();
260
- if (dxGrid) {
261
- requestAnimationFrame(() => {
262
- dxGrid?.scrollToRow(cell.row + 1);
263
- dxGrid?.refocus('row', 1);
264
- });
258
+ (increment, delta, cell) => {
259
+ if (dxGrid && model) {
260
+ if (cell?.plane === 'grid' && cell?.row >= model.getRowCount() - 1) {
261
+ if (draftRowCount < 1) {
262
+ model.insertRow();
263
+ }
264
+ dxGrid.setFocus({ plane: 'frozenRowsEnd', col: 0, row: 0 });
265
+ } else if (cell?.plane === 'frozenRowsEnd' && increment === 'row') {
266
+ handleSaveDraftRow(cell.row);
267
+ model.insertRow();
268
+ dxGrid.setFocus({ plane: 'frozenRowsEnd', col: 0, row: 0 });
269
+ } else {
270
+ dxGrid.refocus(increment, delta);
265
271
  }
266
272
  }
267
273
  },
268
- [model, dxGrid],
274
+ [dxGrid, model],
269
275
  );
270
276
 
271
277
  const handleKeyDown = useCallback<NonNullable<GridContentProps['onKeyDown']>>(
@@ -370,6 +376,7 @@ const TableMain = forwardRef<TableController, TableMainProps>(
370
376
 
371
377
  const handleSave = useCallback(() => {
372
378
  dxGrid?.updateCells(true);
379
+ dxGrid?.requestUpdate();
373
380
  }, [dxGrid]);
374
381
 
375
382
  if (!model || !modals) {
@@ -382,7 +389,6 @@ const TableMain = forwardRef<TableController, TableMainProps>(
382
389
  model={model}
383
390
  modals={modals}
384
391
  schema={schema}
385
- onEnter={handleEnter}
386
392
  onFocus={handleFocus}
387
393
  onQuery={handleQuery}
388
394
  onSave={handleSave}
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { useGridContext, type GridScopedProps } from '@dxos/react-ui-grid';
7
+ import { type GridScopedProps, useGridContext } from '@dxos/react-ui-grid';
8
8
 
9
9
  export type CellValidationMessageProps = {
10
10
  validationError: string | null;
@@ -13,17 +13,18 @@ import { invariant } from '@dxos/invariant';
13
13
  import { faker } from '@dxos/random';
14
14
  import { Filter, useQuery } from '@dxos/react-client/echo';
15
15
  import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
16
- import { defaultRowSize, Grid, type GridEditing } from '@dxos/react-ui-grid';
17
- import { createDefaultSchema, DataType } from '@dxos/schema';
16
+ import { Grid, type GridEditing, defaultRowSize } from '@dxos/react-ui-grid';
17
+ import { DataType, createDefaultSchema } from '@dxos/schema';
18
18
  import { withLayout, withTheme } from '@dxos/storybook-utils';
19
19
 
20
- import { TableCellEditor, type TableCellEditorProps } from './TableCellEditor';
21
20
  import { useTableModel } from '../../hooks';
22
21
  import { type TableFeatures } from '../../model';
23
22
  import { translations } from '../../translations';
24
23
  import { TableView } from '../../types';
25
24
  import { createTable } from '../../util';
26
25
 
26
+ import { TableCellEditor, type TableCellEditorProps } from './TableCellEditor';
27
+
27
28
  type StoryProps = {
28
29
  editing: GridEditing;
29
30
  };
@@ -8,29 +8,29 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
8
8
 
9
9
  import { FormatEnum, TypeEnum } from '@dxos/echo-schema';
10
10
  import { invariant } from '@dxos/invariant';
11
- import { type DxGrid } from '@dxos/lit-grid';
11
+ import { type DxGridAxis, type DxGridPosition } from '@dxos/lit-grid';
12
12
  import { useThemeContext } from '@dxos/react-ui';
13
13
  import { createMarkdownExtensions } from '@dxos/react-ui-editor';
14
14
  import {
15
- cellQuery,
16
- editorKeys,
17
- parseCellIndex,
18
- useGridContext,
19
- type DxGridPlanePosition,
15
+ type EditorBlurHandler,
20
16
  type EditorKeyEvent,
21
17
  type EditorKeyOrBlurHandler,
22
- type EditorBlurHandler,
23
18
  GridCellEditor,
24
19
  type GridCellEditorProps,
25
20
  type GridScopedProps,
21
+ cellQuery,
22
+ editorKeys,
23
+ parseCellIndex,
24
+ useGridContext,
26
25
  } from '@dxos/react-ui-grid';
27
- import { tagPicker, createLinks } from '@dxos/react-ui-tag-picker';
26
+ import { createLinks, tagPicker } from '@dxos/react-ui-tag-picker';
28
27
  import { type FieldProjection } from '@dxos/schema';
29
28
 
29
+ import { type ModalController, type TableModel } from '../../model';
30
+
30
31
  import { CellValidationMessage } from './CellValidationMessage';
31
- import { FormCellEditor } from './FormCellEditor';
32
32
  import { completion } from './extension';
33
- import { type TableModel, type ModalController } from '../../model';
33
+ import { FormCellEditor } from './FormCellEditor';
34
34
 
35
35
  const newValue = Symbol.for('newValue');
36
36
 
@@ -47,8 +47,8 @@ export type TableCellEditorProps = {
47
47
  model?: TableModel;
48
48
  modals?: ModalController;
49
49
  schema?: Schema.AnyNoContext;
50
- onEnter?: (cell: DxGridPlanePosition) => void;
51
- onFocus?: DxGrid['refocus'];
50
+ onEnter?: (cell: DxGridPosition) => void;
51
+ onFocus?: (axis?: DxGridAxis, delta?: -1 | 0 | 1, cell?: DxGridPosition) => void;
52
52
  onSave?: () => void;
53
53
  onQuery?: (field: FieldProjection, text: string) => Promise<QueryResult[]>;
54
54
  };
@@ -121,8 +121,8 @@ export const TableCellEditor = ({
121
121
  const { id: gridId, editing, setEditing } = useGridContext('TableCellEditor', __gridScope);
122
122
  const suppressNextBlur = useRef(false);
123
123
  const { themeMode } = useThemeContext();
124
- const [_validationError, setValidationError] = useState<string | null>(null);
125
- const [_validationVariant, setValidationVariant] = useState<'error' | 'warning'>('error');
124
+ const [validationError, setValidationError] = useState<string | null>(null);
125
+ const [validationVariant, setValidationVariant] = useState<'error' | 'warning'>('error');
126
126
 
127
127
  const fieldProjection = useMemo<FieldProjection | undefined>(() => {
128
128
  if (!model || !editing) {
@@ -225,7 +225,7 @@ export const TableCellEditor = ({
225
225
  onSave?.();
226
226
  onEnter?.(cell);
227
227
  if (event && onFocus) {
228
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
228
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
229
229
  }
230
230
  } else {
231
231
  setValidationError(result.error);
@@ -395,11 +395,7 @@ export const TableCellEditor = ({
395
395
 
396
396
  return (
397
397
  <>
398
- <CellValidationMessage
399
- validationError={_validationError}
400
- variant={_validationVariant}
401
- __gridScope={__gridScope}
402
- />
398
+ <CellValidationMessage validationError={validationError} variant={validationVariant} __gridScope={__gridScope} />
403
399
  <GridCellEditor extension={extension} getCellContent={getCellContent} onBlur={handleBlur} slots={editorSlots} />
404
400
  </>
405
401
  );
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import {
6
- autocompletion,
7
- pickedCompletion,
8
6
  type CompletionContext,
9
7
  type CompletionResult,
8
+ autocompletion,
9
+ pickedCompletion,
10
10
  } from '@codemirror/autocomplete';
11
11
  import { type Extension } from '@codemirror/state';
12
12
  import { EditorView } from '@codemirror/view';