@dxos/plugin-kanban 0.8.4-main.5ea62a8 → 0.8.4-main.66e292d

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 (60) hide show
  1. package/dist/lib/browser/{blueprint-definition-GFG7LX2C.mjs → blueprint-definition-UYVX622Q.mjs} +3 -3
  2. package/dist/lib/browser/{blueprint-definition-GFG7LX2C.mjs.map → blueprint-definition-UYVX622Q.mjs.map} +1 -1
  3. package/dist/lib/browser/{chunk-NCNNL74W.mjs → chunk-B7EZTXV2.mjs} +35 -16
  4. package/dist/lib/browser/chunk-B7EZTXV2.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +25 -28
  6. package/dist/lib/browser/index.mjs.map +3 -3
  7. package/dist/lib/browser/{intent-resolver-2IYZ7TZE.mjs → intent-resolver-ANBDVEJ2.mjs} +18 -15
  8. package/dist/lib/browser/intent-resolver-ANBDVEJ2.mjs.map +7 -0
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/{react-surface-XRHHQ4OI.mjs → react-surface-7ONRKYBB.mjs} +63 -76
  11. package/dist/lib/browser/react-surface-7ONRKYBB.mjs.map +7 -0
  12. package/dist/lib/browser/types/index.mjs +5 -3
  13. package/dist/lib/node-esm/{blueprint-definition-MIMDXMUM.mjs → blueprint-definition-42P47FUY.mjs} +3 -3
  14. package/dist/lib/node-esm/{blueprint-definition-MIMDXMUM.mjs.map → blueprint-definition-42P47FUY.mjs.map} +1 -1
  15. package/dist/lib/node-esm/{chunk-5B3LKGA7.mjs → chunk-WBN5YQGD.mjs} +35 -16
  16. package/dist/lib/node-esm/chunk-WBN5YQGD.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +25 -28
  18. package/dist/lib/node-esm/index.mjs.map +3 -3
  19. package/dist/lib/node-esm/{intent-resolver-T7CEL6EN.mjs → intent-resolver-X4UZDRI7.mjs} +18 -15
  20. package/dist/lib/node-esm/intent-resolver-X4UZDRI7.mjs.map +7 -0
  21. package/dist/lib/node-esm/meta.json +1 -1
  22. package/dist/lib/node-esm/{react-surface-BTB5JAKG.mjs → react-surface-D7XTGTZL.mjs} +63 -76
  23. package/dist/lib/node-esm/react-surface-D7XTGTZL.mjs.map +7 -0
  24. package/dist/lib/node-esm/types/index.mjs +5 -3
  25. package/dist/types/src/KanbanPlugin.d.ts +1 -1
  26. package/dist/types/src/KanbanPlugin.d.ts.map +1 -1
  27. package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
  28. package/dist/types/src/capabilities/blueprint-definition.d.ts +1 -1
  29. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  30. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  31. package/dist/types/src/components/KanbanContainer.d.ts +3 -3
  32. package/dist/types/src/components/KanbanContainer.d.ts.map +1 -1
  33. package/dist/types/src/components/KanbanContainer.stories.d.ts +23 -10
  34. package/dist/types/src/components/KanbanContainer.stories.d.ts.map +1 -1
  35. package/dist/types/src/components/KanbanViewEditor.d.ts +3 -3
  36. package/dist/types/src/components/KanbanViewEditor.d.ts.map +1 -1
  37. package/dist/types/src/meta.d.ts +0 -1
  38. package/dist/types/src/meta.d.ts.map +1 -1
  39. package/dist/types/src/translations.d.ts +21 -9
  40. package/dist/types/src/translations.d.ts.map +1 -1
  41. package/dist/types/src/types/schema.d.ts +14 -43
  42. package/dist/types/src/types/schema.d.ts.map +1 -1
  43. package/dist/types/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +41 -41
  45. package/src/KanbanPlugin.tsx +45 -51
  46. package/src/capabilities/artifact-definition.ts +9 -8
  47. package/src/capabilities/intent-resolver.ts +8 -13
  48. package/src/capabilities/react-surface.tsx +19 -20
  49. package/src/components/KanbanContainer.stories.tsx +41 -53
  50. package/src/components/KanbanContainer.tsx +14 -27
  51. package/src/components/KanbanViewEditor.tsx +18 -19
  52. package/src/meta.ts +7 -5
  53. package/src/translations.ts +5 -5
  54. package/src/types/schema.ts +22 -10
  55. package/dist/lib/browser/chunk-NCNNL74W.mjs.map +0 -7
  56. package/dist/lib/browser/intent-resolver-2IYZ7TZE.mjs.map +0 -7
  57. package/dist/lib/browser/react-surface-XRHHQ4OI.mjs.map +0 -7
  58. package/dist/lib/node-esm/chunk-5B3LKGA7.mjs.map +0 -7
  59. package/dist/lib/node-esm/intent-resolver-T7CEL6EN.mjs.map +0 -7
  60. package/dist/lib/node-esm/react-surface-BTB5JAKG.mjs.map +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-kanban",
3
- "version": "0.8.4-main.5ea62a8",
3
+ "version": "0.8.4-main.66e292d",
4
4
  "description": "Kanban DXOS Surface plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -36,51 +36,51 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "@preact-signals/safe-react": "^0.9.0",
39
- "@preact/signals-core": "^1.9.0",
40
- "effect": "3.17.7",
41
- "@dxos/app-framework": "0.8.4-main.5ea62a8",
42
- "@dxos/ai": "0.8.4-main.5ea62a8",
43
- "@dxos/assistant": "0.8.4-main.5ea62a8",
44
- "@dxos/async": "0.8.4-main.5ea62a8",
45
- "@dxos/echo": "0.8.4-main.5ea62a8",
46
- "@dxos/echo-schema": "0.8.4-main.5ea62a8",
47
- "@dxos/blueprints": "0.8.4-main.5ea62a8",
48
- "@dxos/effect": "0.8.4-main.5ea62a8",
49
- "@dxos/functions": "0.8.4-main.5ea62a8",
50
- "@dxos/invariant": "0.8.4-main.5ea62a8",
51
- "@dxos/log": "0.8.4-main.5ea62a8",
52
- "@dxos/plugin-graph": "0.8.4-main.5ea62a8",
53
- "@dxos/plugin-space": "0.8.4-main.5ea62a8",
54
- "@dxos/plugin-search": "0.8.4-main.5ea62a8",
55
- "@dxos/random": "0.8.4-main.5ea62a8",
56
- "@dxos/react-ui": "0.8.4-main.5ea62a8",
57
- "@dxos/react-ui-form": "0.8.4-main.5ea62a8",
58
- "@dxos/react-ui-kanban": "0.8.4-main.5ea62a8",
59
- "@dxos/react-client": "0.8.4-main.5ea62a8",
60
- "@dxos/react-ui-stack": "0.8.4-main.5ea62a8",
61
- "@dxos/schema": "0.8.4-main.5ea62a8",
62
- "@dxos/plugin-client": "0.8.4-main.5ea62a8",
63
- "@dxos/util": "0.8.4-main.5ea62a8"
39
+ "@preact/signals-core": "^1.12.1",
40
+ "effect": "3.18.3",
41
+ "@dxos/app-framework": "0.8.4-main.66e292d",
42
+ "@dxos/assistant": "0.8.4-main.66e292d",
43
+ "@dxos/blueprints": "0.8.4-main.66e292d",
44
+ "@dxos/echo": "0.8.4-main.66e292d",
45
+ "@dxos/effect": "0.8.4-main.66e292d",
46
+ "@dxos/invariant": "0.8.4-main.66e292d",
47
+ "@dxos/functions": "0.8.4-main.66e292d",
48
+ "@dxos/async": "0.8.4-main.66e292d",
49
+ "@dxos/ai": "0.8.4-main.66e292d",
50
+ "@dxos/log": "0.8.4-main.66e292d",
51
+ "@dxos/plugin-client": "0.8.4-main.66e292d",
52
+ "@dxos/plugin-search": "0.8.4-main.66e292d",
53
+ "@dxos/plugin-graph": "0.8.4-main.66e292d",
54
+ "@dxos/random": "0.8.4-main.66e292d",
55
+ "@dxos/react-client": "0.8.4-main.66e292d",
56
+ "@dxos/react-ui": "0.8.4-main.66e292d",
57
+ "@dxos/react-ui-form": "0.8.4-main.66e292d",
58
+ "@dxos/react-ui-kanban": "0.8.4-main.66e292d",
59
+ "@dxos/react-ui-stack": "0.8.4-main.66e292d",
60
+ "@dxos/schema": "0.8.4-main.66e292d",
61
+ "@dxos/plugin-space": "0.8.4-main.66e292d",
62
+ "@dxos/types": "0.8.4-main.66e292d",
63
+ "@dxos/util": "0.8.4-main.66e292d"
64
64
  },
65
65
  "devDependencies": {
66
- "@types/react": "~18.2.0",
67
- "@types/react-dom": "~18.2.0",
68
- "react": "~18.2.0",
69
- "react-dom": "~18.2.0",
70
- "vite": "7.1.1",
71
- "@dxos/plugin-theme": "0.8.4-main.5ea62a8",
72
- "@dxos/plugin-preview": "0.8.4-main.5ea62a8",
73
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.5ea62a8",
74
- "@dxos/react-ui-theme": "0.8.4-main.5ea62a8",
75
- "@dxos/storybook-utils": "0.8.4-main.5ea62a8",
76
- "@dxos/test-utils": "0.8.4-main.5ea62a8"
66
+ "@types/react": "~19.2.2",
67
+ "@types/react-dom": "~19.2.2",
68
+ "react": "~19.2.0",
69
+ "react-dom": "~19.2.0",
70
+ "vite": "7.1.9",
71
+ "@dxos/plugin-preview": "0.8.4-main.66e292d",
72
+ "@dxos/plugin-theme": "0.8.4-main.66e292d",
73
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.66e292d",
74
+ "@dxos/react-ui-theme": "0.8.4-main.66e292d",
75
+ "@dxos/storybook-utils": "0.8.4-main.66e292d",
76
+ "@dxos/test-utils": "0.8.4-main.66e292d"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "effect": "^3.13.3",
80
- "react": "~18.2.0",
81
- "react-dom": "~18.2.0",
82
- "@dxos/react-ui": "0.8.4-main.5ea62a8",
83
- "@dxos/react-ui-theme": "0.8.4-main.5ea62a8"
80
+ "react": "^19.0.0",
81
+ "react-dom": "^19.0.0",
82
+ "@dxos/react-ui": "0.8.4-main.66e292d",
83
+ "@dxos/react-ui-theme": "0.8.4-main.66e292d"
84
84
  },
85
85
  "publishConfig": {
86
86
  "access": "public"
@@ -3,9 +3,9 @@
3
3
  //
4
4
 
5
5
  import { Capabilities, Events, contributes, createIntent, defineModule, definePlugin } from '@dxos/app-framework';
6
- import { ClientEvents } from '@dxos/plugin-client';
7
- import { SpaceCapabilities } from '@dxos/plugin-space';
8
- import { defineObjectForm } from '@dxos/plugin-space/types';
6
+ import { Type } from '@dxos/echo';
7
+ import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
8
+ import { type CreateObjectIntent } from '@dxos/plugin-space/types';
9
9
  import { translations as kanbanTranslations } from '@dxos/react-ui-kanban';
10
10
  import { Kanban } from '@dxos/react-ui-kanban/types';
11
11
 
@@ -14,51 +14,45 @@ import { meta } from './meta';
14
14
  import { translations } from './translations';
15
15
  import { CreateKanbanSchema, KanbanAction } from './types';
16
16
 
17
- export const KanbanPlugin = () =>
18
- definePlugin(meta, [
19
- defineModule({
20
- id: `${meta.id}/module/translations`,
21
- activatesOn: Events.SetupTranslations,
22
- activate: () => contributes(Capabilities.Translations, [...translations, ...kanbanTranslations]),
23
- }),
24
- defineModule({
25
- id: `${meta.id}/module/metadata`,
26
- activatesOn: Events.SetupMetadata,
27
- activate: () =>
28
- contributes(Capabilities.Metadata, {
29
- id: Kanban.Kanban.typename,
30
- metadata: {
31
- icon: 'ph--kanban--regular',
32
- },
33
- }),
34
- }),
35
- defineModule({
36
- id: `${meta.id}/module/object-form`,
37
- activatesOn: ClientEvents.SetupSchema,
38
- activate: () =>
39
- contributes(
40
- SpaceCapabilities.ObjectForm,
41
- defineObjectForm({
42
- objectSchema: Kanban.Kanban,
43
- formSchema: CreateKanbanSchema,
44
- hidden: true,
45
- getIntent: (props, options) => createIntent(KanbanAction.Create, { ...props, space: options.space }),
46
- }),
47
- ),
48
- }),
49
- defineModule({
50
- id: `${meta.id}/module/react-surface`,
51
- activatesOn: Events.SetupReactSurface,
52
- activate: ReactSurface,
53
- }),
54
- defineModule({
55
- id: `${meta.id}/module/intent-resolver`,
56
- activatesOn: Events.SetupIntentResolver,
57
- activate: IntentResolver,
58
- }),
59
- defineModule({
60
- id: `${meta.id}/module/blueprint`,
61
- activatesOn: Events.SetupArtifactDefinition,
62
- activate: BlueprintDefinition,
63
- }),
64
- ]);
17
+ export const KanbanPlugin = definePlugin(meta, () => [
18
+ defineModule({
19
+ id: `${meta.id}/module/translations`,
20
+ activatesOn: Events.SetupTranslations,
21
+ activate: () => contributes(Capabilities.Translations, [...translations, ...kanbanTranslations]),
22
+ }),
23
+ defineModule({
24
+ id: `${meta.id}/module/metadata`,
25
+ activatesOn: Events.SetupMetadata,
26
+ activate: () =>
27
+ contributes(Capabilities.Metadata, {
28
+ id: Type.getTypename(Kanban.Kanban),
29
+ metadata: {
30
+ icon: 'ph--kanban--regular',
31
+ iconHue: 'green',
32
+ inputSchema: CreateKanbanSchema,
33
+ createObjectIntent: ((props, options) =>
34
+ createIntent(KanbanAction.Create, { ...props, space: options.space })) satisfies CreateObjectIntent,
35
+ },
36
+ }),
37
+ }),
38
+ defineModule({
39
+ id: `${meta.id}/module/schema`,
40
+ activatesOn: ClientEvents.SetupSchema,
41
+ activate: () => contributes(ClientCapabilities.Schema, [Kanban.Kanban]),
42
+ }),
43
+ defineModule({
44
+ id: `${meta.id}/module/react-surface`,
45
+ activatesOn: Events.SetupReactSurface,
46
+ activate: ReactSurface,
47
+ }),
48
+ defineModule({
49
+ id: `${meta.id}/module/intent-resolver`,
50
+ activatesOn: Events.SetupIntentResolver,
51
+ activate: IntentResolver,
52
+ }),
53
+ defineModule({
54
+ id: `${meta.id}/module/blueprint`,
55
+ activatesOn: Events.SetupArtifactDefinition,
56
+ activate: BlueprintDefinition,
57
+ }),
58
+ ]);
@@ -5,7 +5,8 @@
5
5
  // ISSUE(burdon): defineArtifact
6
6
  // @ts-nocheck
7
7
 
8
- import { Schema, pipe } from 'effect';
8
+ import * as Function from 'effect/Function';
9
+ import * as Schema from 'effect/Schema';
9
10
 
10
11
  import { ToolResult, createTool } from '@dxos/ai';
11
12
  import { Capabilities, type PromiseIntentDispatcher, chain, contributes, createIntent } from '@dxos/app-framework';
@@ -14,9 +15,9 @@ import { defineArtifact } from '@dxos/blueprints';
14
15
  import { Obj, Query } from '@dxos/echo';
15
16
  import { invariant } from '@dxos/invariant';
16
17
  import { SpaceAction } from '@dxos/plugin-space/types';
17
- import { Filter, type Space, fullyQualifiedId } from '@dxos/react-client/echo';
18
+ import { Filter, type Space } from '@dxos/react-client/echo';
18
19
  import { KanbanView } from '@dxos/react-ui-kanban';
19
- import { DataType } from '@dxos/schema';
20
+ import { View } from '@dxos/schema';
20
21
  import { isNonNullable } from '@dxos/util';
21
22
 
22
23
  import { meta } from '../meta';
@@ -68,7 +69,7 @@ export default () => {
68
69
  return ToolResult.Error(`Schema not found: ${typename}`);
69
70
  }
70
71
 
71
- const intent = pipe(
72
+ const intent = Function.pipe(
72
73
  createIntent(KanbanAction.Create, {
73
74
  space: extensions.space,
74
75
  typename,
@@ -93,7 +94,7 @@ export default () => {
93
94
  execute: async (_input, { extensions }) => {
94
95
  invariant(extensions?.space, 'No space');
95
96
  const space = extensions.space;
96
- const { objects } = await space.db.query(Filter.type(DataType.View)).run();
97
+ const { objects } = await space.db.query(Filter.type(View.View)).run();
97
98
 
98
99
  const boardInfo = await Promise.all(
99
100
  objects.map(async (view) => {
@@ -103,7 +104,7 @@ export default () => {
103
104
  }
104
105
 
105
106
  return {
106
- id: fullyQualifiedId(view),
107
+ id: Obj.getDXN(view).toString(),
107
108
  name: view.name ?? 'Unnamed Kanban',
108
109
  typename: view.query.typename,
109
110
  };
@@ -123,8 +124,8 @@ export default () => {
123
124
  const space = extensions.space;
124
125
  const view = (await space.db
125
126
  // TODO(wittjosiah): Filter.and should aggregate type
126
- .query(Query.select(Filter.and(Filter.type(DataType.View), Filter.ids(id))))
127
- .first()) as DataType.View;
127
+ .query(Query.select(Filter.and(Filter.type(View.View), Filter.ids(id))))
128
+ .first()) as View.View;
128
129
 
129
130
  const kanban = await view.presentation.load();
130
131
  invariant(Obj.instanceOf(KanbanView, kanban));
@@ -7,9 +7,9 @@ import { invariant } from '@dxos/invariant';
7
7
  import { ClientCapabilities } from '@dxos/plugin-client';
8
8
  import { getSpace } from '@dxos/react-client/echo';
9
9
  import { Kanban } from '@dxos/react-ui-kanban/types';
10
- import { ProjectionModel } from '@dxos/schema';
10
+ import { ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
11
11
 
12
- import { KANBAN_PLUGIN } from '../meta';
12
+ import { meta } from '../meta';
13
13
  import { KanbanAction } from '../types';
14
14
 
15
15
  export default (context: PluginContext) =>
@@ -18,20 +18,15 @@ export default (context: PluginContext) =>
18
18
  intent: KanbanAction.Create,
19
19
  resolve: async ({ space, name, typename, initialPivotColumn }) => {
20
20
  const client = context.getCapability(ClientCapabilities.Client);
21
- const { view } = await Kanban.makeView({
22
- client,
23
- space,
24
- name,
25
- typename,
26
- pivotFieldName: initialPivotColumn,
27
- });
28
- return { data: { object: view } };
21
+ const { view } = await View.makeFromSpace({ client, space, typename, pivotFieldName: initialPivotColumn });
22
+ const kanban = Kanban.make({ name, view });
23
+ return { data: { object: kanban } };
29
24
  },
30
25
  }),
31
26
  createResolver({
32
27
  intent: KanbanAction.DeleteCardField,
33
28
  resolve: async ({ view, fieldId, deletionData }, undo) => {
34
- const schema = getSpace(view)?.db.schemaRegistry.getSchema(view.query.typename!);
29
+ const schema = getSpace(view)?.db.schemaRegistry.getSchema(getTypenameFromQuery(view.query.ast)!);
35
30
  invariant(schema);
36
31
  const projection = new ProjectionModel(schema.jsonSchema, view.projection);
37
32
 
@@ -39,7 +34,7 @@ export default (context: PluginContext) =>
39
34
  const { deleted, index } = projection.deleteFieldProjection(fieldId);
40
35
  return {
41
36
  undoable: {
42
- message: ['card field deleted label', { ns: KANBAN_PLUGIN }],
37
+ message: ['card field deleted label', { ns: meta.id }],
43
38
  data: { deletionData: { ...deleted, index } },
44
39
  },
45
40
  };
@@ -59,7 +54,7 @@ export default (context: PluginContext) =>
59
54
  space.db.remove(card);
60
55
  return {
61
56
  undoable: {
62
- message: ['card deleted label', { ns: KANBAN_PLUGIN }],
57
+ message: ['card deleted label', { ns: meta.id }],
63
58
  data: { card },
64
59
  },
65
60
  };
@@ -2,17 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Schema } from 'effect';
5
+ import type * as Schema from 'effect/Schema';
6
6
  import React, { useMemo } from 'react';
7
7
 
8
- import { Capabilities, contributes, createSurface, useCapabilities } from '@dxos/app-framework';
8
+ import { Capabilities, contributes, createSurface } from '@dxos/app-framework';
9
9
  import { Obj, Type } from '@dxos/echo';
10
10
  import { findAnnotation } from '@dxos/effect';
11
- import { ClientCapabilities } from '@dxos/plugin-client';
12
11
  import { type Space, getSpace, isSpace } from '@dxos/react-client/echo';
13
12
  import { type InputProps, SelectInput, useFormValues } from '@dxos/react-ui-form';
14
13
  import { Kanban } from '@dxos/react-ui-kanban/types';
15
- import { DataType } from '@dxos/schema';
14
+ import { type Collection } from '@dxos/schema';
16
15
 
17
16
  import { KanbanContainer, KanbanViewEditor } from '../components';
18
17
  import { meta } from '../meta';
@@ -23,24 +22,26 @@ export default () =>
23
22
  createSurface({
24
23
  id: meta.id,
25
24
  role: ['article', 'section'],
26
- filter: (data): data is { subject: DataType.View } =>
27
- Obj.instanceOf(DataType.View, data.subject) && Obj.instanceOf(Kanban.Kanban, data.subject.presentation.target),
28
- component: ({ data, role }) => <KanbanContainer view={data.subject} role={role} />,
25
+ filter: (data): data is { subject: Kanban.Kanban } => Obj.instanceOf(Kanban.Kanban, data.subject),
26
+ component: ({ data, role }) => <KanbanContainer object={data.subject} role={role} />,
29
27
  }),
30
28
  createSurface({
31
29
  id: `${meta.id}/object-settings`,
32
30
  role: 'object-settings',
33
31
  position: 'hoist',
34
- filter: (data): data is { subject: DataType.View } =>
35
- Obj.instanceOf(DataType.View, data.subject) && Obj.instanceOf(Kanban.Kanban, data.subject.presentation.target),
36
- component: ({ data }) => <KanbanViewEditor view={data.subject} />,
32
+ filter: (data): data is { subject: Kanban.Kanban } => Obj.instanceOf(Kanban.Kanban, data.subject),
33
+ component: ({ data }) => <KanbanViewEditor object={data.subject} />,
37
34
  }),
38
35
  createSurface({
39
36
  id: `${meta.id}/create-initial-schema-form-[pivot-column]`,
40
37
  role: 'form-input',
41
38
  filter: (
42
39
  data,
43
- ): data is { prop: string; schema: Schema.Schema<any>; target: Space | DataType.Collection | undefined } => {
40
+ ): data is {
41
+ prop: string;
42
+ schema: Schema.Schema<any>;
43
+ target: Space | Collection.Collection | undefined;
44
+ } => {
44
45
  const annotation = findAnnotation<boolean>((data.schema as Schema.Schema.All).ast, PivotColumnAnnotationId);
45
46
  return !!annotation;
46
47
  },
@@ -50,16 +51,14 @@ export default () =>
50
51
  if (!space) {
51
52
  return null;
52
53
  }
53
- const { typename } = useFormValues();
54
- // TODO(wittjosiah): Unify this schema lookup.
55
- const schemaWhitelists = useCapabilities(ClientCapabilities.SchemaWhiteList);
56
- const staticSchema = schemaWhitelists.flat().find((schema) => Type.getTypename(schema) === typename);
57
- const [selectedSchema] = space?.db.schemaRegistry.query({ typename }).runSync();
58
54
 
55
+ const { typename } = useFormValues();
56
+ const [selectedSchema] = useMemo(
57
+ () => space?.db.schemaRegistry.query({ location: ['database', 'runtime'], typename }).runSync(),
58
+ [space, typename],
59
+ );
59
60
  const singleSelectColumns = useMemo(() => {
60
- const properties = staticSchema
61
- ? Type.toJsonSchema(staticSchema).properties
62
- : selectedSchema?.jsonSchema?.properties;
61
+ const properties = Type.toJsonSchema(selectedSchema).properties;
63
62
  if (!properties) {
64
63
  return [];
65
64
  }
@@ -72,7 +71,7 @@ export default () =>
72
71
  }, []);
73
72
 
74
73
  return columns;
75
- }, [selectedSchema?.jsonSchema, staticSchema]);
74
+ }, [selectedSchema]);
76
75
 
77
76
  if (!typename) {
78
77
  return null;
@@ -2,14 +2,12 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
- import React, { useCallback, useEffect, useState } from 'react';
6
+ import React, { useCallback } from 'react';
9
7
 
10
8
  import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
11
9
  import { withPluginManager } from '@dxos/app-framework/testing';
12
- import { Obj, Type } from '@dxos/echo';
10
+ import { Obj, type QueryAST, Type } from '@dxos/echo';
13
11
  import { invariant } from '@dxos/invariant';
14
12
  import { ClientPlugin } from '@dxos/plugin-client';
15
13
  import { PreviewPlugin } from '@dxos/plugin-preview';
@@ -20,13 +18,14 @@ import { ThemePlugin } from '@dxos/plugin-theme';
20
18
  import { faker } from '@dxos/random';
21
19
  import { useClient } from '@dxos/react-client';
22
20
  import { Filter, useQuery, useSchema, useSpaces } from '@dxos/react-client/echo';
21
+ import { withTheme } from '@dxos/react-ui/testing';
23
22
  import { ViewEditor } from '@dxos/react-ui-form';
24
- import { Kanban as KanbanComponent, useKanbanModel } from '@dxos/react-ui-kanban';
23
+ import { Kanban as KanbanComponent, useKanbanModel, useProjectionModel } from '@dxos/react-ui-kanban';
25
24
  import { Kanban } from '@dxos/react-ui-kanban/types';
26
25
  import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
27
26
  import { defaultTx } from '@dxos/react-ui-theme';
28
- import { DataType, ProjectionModel } from '@dxos/schema';
29
- import { withLayout } from '@dxos/storybook-utils';
27
+ import { View, getTypenameFromQuery } from '@dxos/schema';
28
+ import { Organization, Person } from '@dxos/types';
30
29
 
31
30
  import { translations } from '../translations';
32
31
 
@@ -41,40 +40,23 @@ const rollOrg = () => ({
41
40
  description: faker.lorem.paragraph(),
42
41
  image: faker.image.url(),
43
42
  website: faker.internet.url(),
44
- status: faker.helpers.arrayElement(DataType.OrganizationStatusOptions).id as DataType.Organization['status'],
43
+ status: faker.helpers.arrayElement(Organization.StatusOptions).id as Organization.Organization['status'],
45
44
  });
46
45
 
47
46
  const StorybookKanban = () => {
48
47
  const client = useClient();
49
48
  const spaces = useSpaces();
50
49
  const space = spaces[spaces.length - 1];
51
- const views = useQuery(space, Filter.type(DataType.View));
52
- const [view, setView] = useState<DataType.View>();
53
- const [projection, setProjection] = useState<ProjectionModel>();
54
- const schema = useSchema(client, space, view?.query.typename);
55
-
56
- useEffect(() => {
57
- if (views.length && !view) {
58
- const view = views[0];
59
- setView(view);
60
- }
61
- }, [views]);
62
-
63
- useEffect(() => {
64
- if (view?.projection && schema) {
65
- const jsonSchema = Type.toJsonSchema(schema);
66
- setProjection(new ProjectionModel(jsonSchema, view.projection));
67
- }
68
- // TODO(ZaymonFC): Is there a better way to get notified about deep changes in the json schema?
69
- // @dmaretskyi? Once resolved, update in multiple places (e.g., storybooks).
70
- }, [view?.projection, schema, JSON.stringify(schema ? Type.toJsonSchema(schema) : {})]);
50
+ const [object] = useQuery(space, Filter.type(Kanban.Kanban));
51
+ const typename = object?.view.target?.query ? getTypenameFromQuery(object.view.target.query.ast) : undefined;
52
+ const schema = useSchema(client, space, typename);
71
53
 
72
54
  const objects = useQuery(space, schema ? Filter.type(schema) : Filter.nothing());
73
55
  const filteredObjects = useGlobalFilteredObjects(objects);
74
56
 
57
+ const projection = useProjectionModel(schema, object);
75
58
  const model = useKanbanModel({
76
- view,
77
- schema,
59
+ object,
78
60
  projection,
79
61
  items: filteredObjects,
80
62
  });
@@ -95,21 +77,21 @@ const StorybookKanban = () => {
95
77
  [space, schema, model],
96
78
  );
97
79
 
98
- const handleRemoveCard = useCallback((card: { id: string }) => space.db.remove(card), [space]);
80
+ const handleRemoveCard = useCallback((card: { id: string }) => Obj.isObject(card) && space?.db.remove(card), [space]);
99
81
 
100
- const handleTypenameChanged = useCallback(
101
- (typename: string) => {
82
+ const handleUpdateQuery = useCallback(
83
+ (newQuery: QueryAST.Query) => {
102
84
  invariant(schema);
103
85
  invariant(Type.isMutable(schema));
104
- invariant(view);
86
+ invariant(object.view.target);
105
87
 
106
- schema.updateTypename(typename);
107
- view.query.typename = typename;
88
+ schema.updateTypename(getTypenameFromQuery(newQuery));
89
+ object.view.target.query.ast = newQuery;
108
90
  },
109
- [view, schema],
91
+ [object, schema],
110
92
  );
111
93
 
112
- if (!schema || !view) {
94
+ if (!schema || !object.view.target) {
113
95
  return null;
114
96
  }
115
97
 
@@ -120,14 +102,14 @@ const StorybookKanban = () => {
120
102
  <ViewEditor
121
103
  registry={space?.db.schemaRegistry}
122
104
  schema={schema}
123
- view={view}
124
- onTypenameChanged={handleTypenameChanged}
105
+ view={object.view.target}
106
+ onQueryChanged={handleUpdateQuery}
125
107
  onDelete={(fieldId: string) => {
126
108
  console.log('[ViewEditor]', 'onDelete', fieldId);
127
109
  }}
128
110
  />
129
- <SyntaxHighlighter language='json' className='w-full text-xs'>
130
- {JSON.stringify({ view, schema }, null, 2)}
111
+ <SyntaxHighlighter language='json' className='text-xs'>
112
+ {JSON.stringify({ view: object.view.target, schema }, null, 2)}
131
113
  </SyntaxHighlighter>
132
114
  </div>
133
115
  </div>
@@ -146,40 +128,46 @@ const meta = {
146
128
  title: 'plugins/plugin-kanban/Kanban',
147
129
  component: StorybookKanban,
148
130
  render: () => <StorybookKanban />,
149
- parameters: { translations },
150
131
  decorators: [
151
- withLayout({ fullscreen: true }),
132
+ withTheme,
152
133
  withPluginManager({
153
134
  plugins: [
154
- ThemePlugin({ tx: defaultTx }),
155
135
  ClientPlugin({
156
- types: [DataType.Organization, DataType.Person, DataType.View, Kanban.Kanban],
136
+ types: [Organization.Organization, Person.Person, View.View, Kanban.Kanban],
157
137
  onClientInitialized: async ({ client }) => {
158
138
  await client.halo.createIdentity();
159
139
  const space = await client.spaces.create();
160
140
  await space.waitUntilReady();
161
- const { view } = await Kanban.makeView({
141
+ const { view } = await View.makeFromSpace({
162
142
  client,
163
143
  space,
164
- typename: DataType.Organization.typename,
144
+ typename: Organization.Organization.typename,
165
145
  pivotFieldName: 'status',
166
146
  });
167
- space.db.add(view);
147
+ const kanban = Kanban.make({ view });
148
+ space.db.add(kanban);
168
149
 
169
150
  // TODO(burdon): Replace with sdk/schema/testing.
170
151
  Array.from({ length: 80 }).map(() => {
171
- return space.db.add(Obj.make(DataType.Organization, rollOrg()));
152
+ return space.db.add(Obj.make(Organization.Organization, rollOrg()));
172
153
  });
173
154
  },
174
155
  }),
175
- StorybookLayoutPlugin(),
176
- PreviewPlugin(),
177
- SpacePlugin(),
156
+ SpacePlugin({}),
178
157
  IntentPlugin(),
179
158
  SettingsPlugin(),
159
+
160
+ // UI
161
+ ThemePlugin({ tx: defaultTx }),
162
+ PreviewPlugin(),
163
+ StorybookLayoutPlugin({}),
180
164
  ],
181
165
  }),
182
166
  ],
167
+ parameters: {
168
+ layout: 'fullscreen',
169
+ translations,
170
+ },
183
171
  } satisfies Meta<typeof StorybookKanban>;
184
172
 
185
173
  export default meta;