@dxos/react-ui-table 0.7.4 → 0.7.5-main.499c70c

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-IYCSJDMB.mjs → chunk-AT7O4RAD.mjs} +4 -4
  2. package/dist/lib/browser/{chunk-IYCSJDMB.mjs.map → chunk-AT7O4RAD.mjs.map} +2 -2
  3. package/dist/lib/browser/index.mjs +1398 -1216
  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-MHBMVCFZ.cjs → chunk-YSBXNBDJ.cjs} +6 -6
  8. package/dist/lib/node/{chunk-MHBMVCFZ.cjs.map → chunk-YSBXNBDJ.cjs.map} +2 -2
  9. package/dist/lib/node/index.cjs +1130 -934
  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-BMWGPXPL.mjs → chunk-6OH2NHUX.mjs} +4 -4
  15. package/dist/lib/node-esm/{chunk-BMWGPXPL.mjs.map → chunk-6OH2NHUX.mjs.map} +2 -2
  16. package/dist/lib/node-esm/index.mjs +1398 -1216
  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/hooks/useColumnSorting.d.ts +1 -1
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +4 -3
  22. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts +3 -2
  24. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/CreateRefPanel.d.ts +3 -2
  26. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/RefPanel.d.ts +4 -3
  28. package/dist/types/src/components/Table/RefPanel.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/RowActionsMenu.d.ts +3 -2
  30. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  31. package/dist/types/src/components/Table/Table.d.ts +2 -1
  32. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  34. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +3 -2
  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 +55 -71
  38. package/dist/types/src/components/testing.d.ts.map +1 -1
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.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/modal-controller.d.ts +6 -2
  44. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  45. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  46. package/dist/types/src/model/table-model.d.ts +8 -12
  47. package/dist/types/src/model/table-model.d.ts.map +1 -1
  48. package/dist/types/src/model/table-presentation.d.ts +22 -0
  49. package/dist/types/src/model/table-presentation.d.ts.map +1 -0
  50. package/dist/types/src/model/table-presentation.test.d.ts +2 -0
  51. package/dist/types/src/model/table-presentation.test.d.ts.map +1 -0
  52. package/dist/types/src/playwright/TableManager.d.ts +2 -1
  53. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  54. package/dist/types/src/types/table.d.ts +118 -154
  55. package/dist/types/src/types/table.d.ts.map +1 -1
  56. package/dist/types/src/util/index.d.ts +1 -0
  57. package/dist/types/src/util/index.d.ts.map +1 -1
  58. package/dist/types/src/util/table-buttons.d.ts +50 -20
  59. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  60. package/dist/types/src/util/table-controls.d.ts +32 -9
  61. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  62. package/dist/types/src/util/table.d.ts +2 -2
  63. package/dist/types/src/util/table.d.ts.map +1 -1
  64. package/dist/types/tsconfig.tsbuildinfo +1 -0
  65. package/package.json +29 -29
  66. package/src/components/Table/ColumnActionsMenu.tsx +8 -8
  67. package/src/components/Table/ColumnSettings.tsx +11 -11
  68. package/src/components/Table/CreateRefPanel.tsx +10 -10
  69. package/src/components/Table/RefPanel.tsx +9 -9
  70. package/src/components/Table/RowActionsMenu.tsx +6 -7
  71. package/src/components/Table/Table.stories.tsx +40 -23
  72. package/src/components/Table/Table.tsx +235 -148
  73. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +13 -12
  74. package/src/components/TableCellEditor/TableCellEditor.tsx +6 -4
  75. package/src/components/testing.ts +10 -8
  76. package/src/index.ts +2 -0
  77. package/src/model/index.ts +1 -0
  78. package/src/model/modal-controller.ts +15 -48
  79. package/src/model/selection-model.ts +12 -1
  80. package/src/model/table-model.test.ts +4 -71
  81. package/src/model/table-model.ts +59 -232
  82. package/src/model/table-presentation.test.ts +102 -0
  83. package/src/model/table-presentation.ts +214 -0
  84. package/src/playwright/TableManager.ts +5 -1
  85. package/src/playwright/smoke.spec.ts +64 -1
  86. package/src/types/table.ts +3 -3
  87. package/src/util/index.ts +1 -0
  88. package/src/util/table-buttons.ts +97 -48
  89. package/src/util/table-controls.ts +71 -7
  90. package/src/util/table.ts +21 -13
@@ -9,13 +9,13 @@ import { DropdownMenu } from '@dxos/react-ui';
9
9
  import { FieldEditor } from '@dxos/react-ui-form';
10
10
  import { type FieldType } from '@dxos/schema';
11
11
 
12
- import { type TableModel } from '../../model';
12
+ import { type TableModel, type ModalController } from '../../model';
13
13
 
14
- type ColumnSettingsProps = { model?: TableModel; onNewColumn: () => void };
14
+ type ColumnSettingsProps = { model?: TableModel; modals: ModalController; onNewColumn: () => void };
15
15
 
16
- export const ColumnSettings = ({ model, onNewColumn }: ColumnSettingsProps) => {
16
+ export const ColumnSettings = ({ model, modals, onNewColumn }: ColumnSettingsProps) => {
17
17
  const [newField, setNewField] = useState<FieldType>();
18
- const state = model?.modalController.state.value;
18
+ const state = modals.state.value;
19
19
 
20
20
  const space = getSpace(model?.table);
21
21
 
@@ -34,17 +34,17 @@ export const ColumnSettings = ({ model, onNewColumn }: ColumnSettingsProps) => {
34
34
  if (state?.type === 'columnSettings') {
35
35
  const { mode } = state;
36
36
  if (mode.type === 'edit') {
37
- return model?.table?.view?.fields.find((f) => f.id === mode.fieldId);
37
+ return model?.table?.view?.target?.fields.find((f) => f.id === mode.fieldId);
38
38
  }
39
39
  }
40
40
  return undefined;
41
- }, [model?.table?.view?.fields, state]);
41
+ }, [model?.table?.view?.target?.fields, state]);
42
42
 
43
43
  const field = existingField ?? newField;
44
44
 
45
45
  const handleSave = useCallback(() => {
46
- model?.modalController.close();
47
- }, [model?.modalController]);
46
+ modals.close();
47
+ }, [modals]);
48
48
 
49
49
  const handleCancel = useCallback(() => {
50
50
  if (state?.type === 'columnSettings' && state.mode.type === 'create' && newField) {
@@ -52,18 +52,18 @@ export const ColumnSettings = ({ model, onNewColumn }: ColumnSettingsProps) => {
52
52
  }
53
53
  }, [model?.projection, state, newField]);
54
54
 
55
- if (!model?.table?.view || !model.projection || !field) {
55
+ if (!model?.table?.view?.target || !model.projection || !field) {
56
56
  return null;
57
57
  }
58
58
 
59
59
  return (
60
60
  <DropdownMenu.Root modal={false} open={state?.type === 'columnSettings'}>
61
- <DropdownMenu.VirtualTrigger virtualRef={model.modalController.trigger} />
61
+ <DropdownMenu.VirtualTrigger virtualRef={modals.trigger} />
62
62
  <DropdownMenu.Portal>
63
63
  <DropdownMenu.Content classNames='md:is-64'>
64
64
  <DropdownMenu.Viewport>
65
65
  <FieldEditor
66
- view={model.table.view}
66
+ view={model.table.view.target!}
67
67
  projection={model.projection}
68
68
  field={field}
69
69
  registry={space?.db.schemaRegistry}
@@ -10,15 +10,15 @@ import { Popover } from '@dxos/react-ui';
10
10
  import { Form } from '@dxos/react-ui-form';
11
11
  import { type GridScopedProps, useGridContext } from '@dxos/react-ui-grid';
12
12
 
13
- import { type TableModel } from '../../model';
13
+ import { type TableModel, type ModalController } from '../../model';
14
14
 
15
- export type CreateRefPanelProps = { model?: TableModel };
15
+ export type CreateRefPanelProps = { model?: TableModel; modals: ModalController };
16
16
 
17
17
  // TODO(burdon): Factor out Space dependency (to plugin?)
18
- export const CreateRefPanel = ({ model, __gridScope }: GridScopedProps<CreateRefPanelProps>) => {
18
+ export const CreateRefPanel = ({ model, modals, __gridScope }: GridScopedProps<CreateRefPanelProps>) => {
19
19
  const { id: gridId } = useGridContext('TableCellEditor', __gridScope);
20
20
  const space = getSpace(model?.table);
21
- const state = model?.modalController.state.value;
21
+ const state = modals.state.value;
22
22
  const schema = useMemo<S.Schema<any> | undefined>(() => {
23
23
  if (!space || state?.type !== 'createRefPanel') {
24
24
  return;
@@ -44,16 +44,16 @@ export const CreateRefPanel = ({ model, __gridScope }: GridScopedProps<CreateRef
44
44
  state.onCreate?.(obj);
45
45
  }
46
46
 
47
- void model.modalController.close();
47
+ void modals.close();
48
48
  },
49
- [model?.modalController, space, state],
49
+ [modals, space, state],
50
50
  );
51
51
 
52
52
  const handleCancel = useCallback(() => {
53
53
  if (model) {
54
- model.modalController.close();
54
+ modals.close();
55
55
  }
56
- }, [model?.modalController]);
56
+ }, [modals]);
57
57
 
58
58
  if (!model?.table?.view || !model.projection) {
59
59
  return null;
@@ -65,11 +65,11 @@ export const CreateRefPanel = ({ model, __gridScope }: GridScopedProps<CreateRef
65
65
  open={state?.type === 'createRefPanel' && !!schema}
66
66
  onOpenChange={(nextOpen) => {
67
67
  if (model && !nextOpen) {
68
- return model.modalController.close();
68
+ return modals.close();
69
69
  }
70
70
  }}
71
71
  >
72
- <Popover.VirtualTrigger virtualRef={model.modalController.trigger} />
72
+ <Popover.VirtualTrigger virtualRef={modals.trigger} />
73
73
  <Popover.Portal>
74
74
  <Popover.Content classNames='md:is-64' data-grid={gridId}>
75
75
  {state?.type === 'createRefPanel' && schema && (
@@ -8,9 +8,9 @@ import { getSpace, type Space } from '@dxos/react-client/echo';
8
8
  import { Popover } from '@dxos/react-ui';
9
9
  import { Form } from '@dxos/react-ui-form';
10
10
 
11
- import { type TableModel } from '../../model';
11
+ import { type TableModel, type ModalController } from '../../model';
12
12
 
13
- type RefPanelProps = { model?: TableModel };
13
+ type RefPanelProps = { model: TableModel; modals: ModalController };
14
14
 
15
15
  const getRefTargetObj = (space?: Space, id?: string) => {
16
16
  if (space && id) {
@@ -20,13 +20,13 @@ const getRefTargetObj = (space?: Space, id?: string) => {
20
20
  }
21
21
  };
22
22
 
23
- export const RefPanel = ({ model }: RefPanelProps) => {
24
- const state = model?.modalController.state.value;
25
- const space = getSpace(model?.table);
23
+ export const RefPanel = ({ model, modals }: RefPanelProps) => {
24
+ const state = modals.state.value;
25
+ const space = getSpace(model.table);
26
26
  const targetObj = getRefTargetObj(space, state?.type === 'refPanel' ? state.targetId : undefined);
27
27
  const schema = space && state?.type === 'refPanel' ? space.db.schemaRegistry.getSchema(state.typename) : undefined;
28
28
 
29
- if (!model?.table?.view || !model.projection) {
29
+ if (!model.table?.view || !model.projection) {
30
30
  return null;
31
31
  }
32
32
 
@@ -35,12 +35,12 @@ export const RefPanel = ({ model }: RefPanelProps) => {
35
35
  modal={false}
36
36
  open={state?.type === 'refPanel' && !!targetObj && !!schema}
37
37
  onOpenChange={(nextOpen) => {
38
- if (model && !nextOpen) {
39
- return model.modalController.close();
38
+ if (!nextOpen) {
39
+ return modals.close();
40
40
  }
41
41
  }}
42
42
  >
43
- <Popover.VirtualTrigger virtualRef={model.modalController.trigger} />
43
+ <Popover.VirtualTrigger virtualRef={modals.trigger} />
44
44
  <Popover.Portal>
45
45
  <Popover.Content classNames='md:is-64'>
46
46
  {targetObj && schema && <Form readonly values={targetObj} schema={schema} />}
@@ -6,22 +6,21 @@ import React from 'react';
6
6
 
7
7
  import { DropdownMenu, useTranslation } from '@dxos/react-ui';
8
8
 
9
- import { type TableModel } from '../../model';
9
+ import { type TableModel, type ModalController } from '../../model';
10
10
  import { translationKey } from '../../translations';
11
11
 
12
- type RowActionsMenuProps = { model: TableModel };
12
+ type RowActionsMenuProps = { model: TableModel; modals: ModalController };
13
13
 
14
- export const RowActionsMenu = ({ model }: RowActionsMenuProps) => {
14
+ export const RowActionsMenu = ({ model, modals }: RowActionsMenuProps) => {
15
15
  const { t } = useTranslation(translationKey);
16
16
  const hasSelection = model.selection.hasSelection.value;
17
- const state = model.modalController.state.value;
17
+ const state = modals.state.value;
18
18
  if (state?.type !== 'row') {
19
19
  return null;
20
20
  }
21
-
22
21
  return (
23
- <DropdownMenu.Root modal={false} open={true} onOpenChange={model.modalController.close}>
24
- <DropdownMenu.VirtualTrigger virtualRef={model.modalController.trigger} />
22
+ <DropdownMenu.Root modal={false} open={true} onOpenChange={modals.close}>
23
+ <DropdownMenu.VirtualTrigger virtualRef={modals.trigger} />
25
24
  <DropdownMenu.Content>
26
25
  <DropdownMenu.Viewport>
27
26
  <DropdownMenu.Item data-testid='row-menu-delete' onClick={() => model.deleteRow(state.rowIndex)}>
@@ -7,12 +7,12 @@ import '@dxos-theme';
7
7
  import { type StoryObj, type Meta } from '@storybook/react';
8
8
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
9
9
 
10
- import { type MutableSchema } from '@dxos/echo-schema';
10
+ import { type EchoSchema } from '@dxos/echo-schema';
11
11
  import { invariant } from '@dxos/invariant';
12
12
  import { useGlobalFilteredObjects } from '@dxos/plugin-search';
13
13
  import { faker } from '@dxos/random';
14
- import { Filter, useSpaces, useQuery, create } from '@dxos/react-client/echo';
15
- import { withClientProvider } from '@dxos/react-client/testing';
14
+ import { Filter, useQuery, create } from '@dxos/react-client/echo';
15
+ import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
16
16
  import { useDefaultValue } from '@dxos/react-ui';
17
17
  import { ViewEditor } from '@dxos/react-ui-form';
18
18
  import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
@@ -21,12 +21,14 @@ import { withLayout, withTheme } from '@dxos/storybook-utils';
21
21
 
22
22
  import { Table, type TableController } from './Table';
23
23
  import { useTableModel, type UseTableModelParams } from '../../hooks';
24
+ import { TablePresentation } from '../../model';
24
25
  import translations from '../../translations';
25
26
  import { TableType } from '../../types';
26
27
  import { initializeTable } from '../../util';
27
28
  import { Toolbar } from '../Toolbar';
28
29
  import { createItems, createTable, type SimulatorProps, useSimulator } from '../testing';
29
30
 
31
+ // NOTE(ZaymonFC): We rely on this seed being 0 in the smoke tests.
30
32
  faker.seed(0);
31
33
 
32
34
  //
@@ -34,25 +36,26 @@ faker.seed(0);
34
36
  //
35
37
 
36
38
  const DefaultStory = () => {
37
- const spaces = useSpaces();
38
- const space = spaces[spaces.length - 1];
39
+ const { space } = useClientProvider();
40
+ invariant(space);
41
+
39
42
  const tables = useQuery(space, Filter.schema(TableType));
40
43
  const [table, setTable] = useState<TableType>();
41
- const [schema, setSchema] = useState<MutableSchema>();
44
+ const [schema, setSchema] = useState<EchoSchema>();
42
45
  useEffect(() => {
43
- if (tables.length && !table) {
46
+ if (space && tables.length && !table) {
44
47
  const table = tables[0];
45
48
  invariant(table.view);
46
49
  setTable(table);
47
- setSchema(space.db.schemaRegistry.getSchema(table.view.query.type));
50
+ setSchema(space.db.schemaRegistry.getSchema(table.view.target!.query.type));
48
51
  }
49
- }, [tables]);
52
+ }, [space, tables]);
50
53
 
51
54
  const projection = useMemo(() => {
52
- if (schema && table?.view) {
53
- return new ViewProjection(schema, table.view);
55
+ if (schema && table?.view?.target) {
56
+ return new ViewProjection(schema, table.view.target);
54
57
  }
55
- }, [schema, table?.view]);
58
+ }, [schema, table?.view?.target]);
56
59
 
57
60
  const objects = useQuery(space, schema ? Filter.schema(schema) : Filter.nothing());
58
61
  const filteredObjects = useGlobalFilteredObjects(objects);
@@ -93,10 +96,18 @@ const DefaultStory = () => {
93
96
  }
94
97
  }
95
98
  },
96
- [table, spaces],
99
+ [table],
97
100
  );
98
101
 
99
102
  const tableRef = useRef<TableController>(null);
103
+ const handleCellUpdate = useCallback((cell: any) => {
104
+ tableRef.current?.update?.(cell);
105
+ }, []);
106
+
107
+ const handleRowOrderChanged = useCallback(() => {
108
+ tableRef.current?.update?.();
109
+ }, []);
110
+
100
111
  const model = useTableModel({
101
112
  table,
102
113
  projection,
@@ -104,10 +115,16 @@ const DefaultStory = () => {
104
115
  onInsertRow: handleInsertRow,
105
116
  onDeleteRows: handleDeleteRows,
106
117
  onDeleteColumn: handleDeleteColumn,
107
- onCellUpdate: (cell) => tableRef.current?.update?.(cell),
108
- onRowOrderChanged: () => tableRef.current?.update?.(),
118
+ onCellUpdate: handleCellUpdate,
119
+ onRowOrderChanged: handleRowOrderChanged,
109
120
  });
110
121
 
122
+ const presentation = useMemo(() => {
123
+ if (model) {
124
+ return new TablePresentation(model);
125
+ }
126
+ }, [model]);
127
+
111
128
  if (!schema || !table) {
112
129
  return <div />;
113
130
  }
@@ -121,21 +138,21 @@ const DefaultStory = () => {
121
138
  <Toolbar.Actions />
122
139
  </Toolbar.Root>
123
140
  <Table.Root>
124
- <Table.Main ref={tableRef} model={model} ignoreAttention />
141
+ <Table.Main ref={tableRef} model={model} presentation={presentation} ignoreAttention />
125
142
  </Table.Root>
126
143
  </div>
127
144
  <div className='flex flex-col h-full border-l border-separator overflow-y-auto'>
128
- {table.view && (
145
+ {table.view?.target && (
129
146
  <ViewEditor
130
147
  registry={space?.db.schemaRegistry}
131
148
  schema={schema}
132
- view={table.view}
149
+ view={table.view.target!}
133
150
  onDelete={handleDeleteColumn}
134
151
  />
135
152
  )}
136
153
 
137
154
  <SyntaxHighlighter language='json' className='w-full text-xs'>
138
- {JSON.stringify({ view: table.view, schema }, null, 2)}
155
+ {JSON.stringify({ view: table.view?.target, schema }, null, 2)}
139
156
  </SyntaxHighlighter>
140
157
  </div>
141
158
  </div>
@@ -161,9 +178,9 @@ const TablePerformanceStory = (props: StoryProps) => {
161
178
 
162
179
  const handleDeleteColumn = useCallback<NonNullable<UseTableModelParams<any>['onDeleteColumn']>>(
163
180
  (fieldId) => {
164
- if (table && table.view) {
165
- const fieldPosition = table.view.fields.findIndex((field) => field.id === fieldId);
166
- table.view.fields.splice(fieldPosition, 1);
181
+ if (table && table.view?.target) {
182
+ const fieldPosition = table.view.target!.fields.findIndex((field) => field.id === fieldId);
183
+ table.view.target!.fields.splice(fieldPosition, 1);
167
184
  }
168
185
  },
169
186
  [table],
@@ -202,7 +219,7 @@ const meta: Meta<StoryProps> = {
202
219
  createSpace: true,
203
220
  onSpaceCreated: async ({ space }) => {
204
221
  const table = space.db.add(create(TableType, {}));
205
- const schema = initializeTable({ space, table, initialRow: false });
222
+ const schema = await initializeTable({ space, table, initialRow: false });
206
223
  Array.from({ length: 10 }).map(() => {
207
224
  return space.db.add(
208
225
  create(schema, {