@dxos/plugin-kanban 0.8.4-main.937b3ca → 0.8.4-main.9735255

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-kanban",
3
- "version": "0.8.4-main.937b3ca",
3
+ "version": "0.8.4-main.9735255",
4
4
  "description": "Kanban DXOS Surface plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -50,31 +50,31 @@
50
50
  "dependencies": {
51
51
  "@effect-atom/atom-react": "^0.4.6",
52
52
  "effect": "3.19.11",
53
- "@dxos/ai": "0.8.4-main.937b3ca",
54
- "@dxos/app-framework": "0.8.4-main.937b3ca",
55
- "@dxos/assistant": "0.8.4-main.937b3ca",
56
- "@dxos/blueprints": "0.8.4-main.937b3ca",
57
- "@dxos/echo": "0.8.4-main.937b3ca",
58
- "@dxos/effect": "0.8.4-main.937b3ca",
59
- "@dxos/functions": "0.8.4-main.937b3ca",
60
- "@dxos/async": "0.8.4-main.937b3ca",
61
- "@dxos/invariant": "0.8.4-main.937b3ca",
62
- "@dxos/log": "0.8.4-main.937b3ca",
63
- "@dxos/operation": "0.8.4-main.937b3ca",
64
- "@dxos/plugin-client": "0.8.4-main.937b3ca",
65
- "@dxos/plugin-search": "0.8.4-main.937b3ca",
66
- "@dxos/plugin-space": "0.8.4-main.937b3ca",
67
- "@dxos/plugin-graph": "0.8.4-main.937b3ca",
68
- "@dxos/random": "0.8.4-main.937b3ca",
69
- "@dxos/react-client": "0.8.4-main.937b3ca",
70
- "@dxos/react-ui": "0.8.4-main.937b3ca",
71
- "@dxos/react-ui-form": "0.8.4-main.937b3ca",
72
- "@dxos/react-ui-kanban": "0.8.4-main.937b3ca",
73
- "@dxos/schema": "0.8.4-main.937b3ca",
74
- "@dxos/react-ui-mosaic": "0.8.4-main.937b3ca",
75
- "@dxos/util": "0.8.4-main.937b3ca",
76
- "@dxos/react-ui-stack": "0.8.4-main.937b3ca",
77
- "@dxos/types": "0.8.4-main.937b3ca"
53
+ "@dxos/ai": "0.8.4-main.9735255",
54
+ "@dxos/app-framework": "0.8.4-main.9735255",
55
+ "@dxos/assistant": "0.8.4-main.9735255",
56
+ "@dxos/blueprints": "0.8.4-main.9735255",
57
+ "@dxos/echo": "0.8.4-main.9735255",
58
+ "@dxos/async": "0.8.4-main.9735255",
59
+ "@dxos/effect": "0.8.4-main.9735255",
60
+ "@dxos/invariant": "0.8.4-main.9735255",
61
+ "@dxos/functions": "0.8.4-main.9735255",
62
+ "@dxos/log": "0.8.4-main.9735255",
63
+ "@dxos/operation": "0.8.4-main.9735255",
64
+ "@dxos/plugin-client": "0.8.4-main.9735255",
65
+ "@dxos/plugin-search": "0.8.4-main.9735255",
66
+ "@dxos/plugin-graph": "0.8.4-main.9735255",
67
+ "@dxos/plugin-space": "0.8.4-main.9735255",
68
+ "@dxos/react-client": "0.8.4-main.9735255",
69
+ "@dxos/random": "0.8.4-main.9735255",
70
+ "@dxos/react-ui-mosaic": "0.8.4-main.9735255",
71
+ "@dxos/react-ui": "0.8.4-main.9735255",
72
+ "@dxos/react-ui-form": "0.8.4-main.9735255",
73
+ "@dxos/react-ui-stack": "0.8.4-main.9735255",
74
+ "@dxos/types": "0.8.4-main.9735255",
75
+ "@dxos/schema": "0.8.4-main.9735255",
76
+ "@dxos/util": "0.8.4-main.9735255",
77
+ "@dxos/react-ui-kanban": "0.8.4-main.9735255"
78
78
  },
79
79
  "devDependencies": {
80
80
  "@types/react": "~19.2.7",
@@ -82,20 +82,20 @@
82
82
  "react": "~19.2.3",
83
83
  "react-dom": "~19.2.3",
84
84
  "vite": "7.1.9",
85
- "@dxos/plugin-preview": "0.8.4-main.937b3ca",
86
- "@dxos/plugin-testing": "0.8.4-main.937b3ca",
87
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.937b3ca",
88
- "@dxos/plugin-theme": "0.8.4-main.937b3ca",
89
- "@dxos/storybook-utils": "0.8.4-main.937b3ca",
90
- "@dxos/test-utils": "0.8.4-main.937b3ca",
91
- "@dxos/ui-theme": "0.8.4-main.937b3ca"
85
+ "@dxos/plugin-testing": "0.8.4-main.9735255",
86
+ "@dxos/plugin-preview": "0.8.4-main.9735255",
87
+ "@dxos/plugin-theme": "0.8.4-main.9735255",
88
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.9735255",
89
+ "@dxos/storybook-utils": "0.8.4-main.9735255",
90
+ "@dxos/test-utils": "0.8.4-main.9735255",
91
+ "@dxos/ui-theme": "0.8.4-main.9735255"
92
92
  },
93
93
  "peerDependencies": {
94
94
  "effect": "3.19.11",
95
95
  "react": "~19.2.3",
96
96
  "react-dom": "~19.2.3",
97
- "@dxos/react-ui": "0.8.4-main.937b3ca",
98
- "@dxos/ui-theme": "0.8.4-main.937b3ca"
97
+ "@dxos/react-ui": "0.8.4-main.9735255",
98
+ "@dxos/ui-theme": "0.8.4-main.9735255"
99
99
  },
100
100
  "publishConfig": {
101
101
  "access": "public"
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { RegistryContext } from '@effect-atom/atom-react';
6
- import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import { type Decorator, type Meta, type StoryObj } from '@storybook/react-vite';
7
7
  import * as Effect from 'effect/Effect';
8
8
  import React, { useCallback, useContext } from 'react';
9
9
  import { expect, waitFor, within } from 'storybook/test';
@@ -18,7 +18,7 @@ import { useGlobalFilteredObjects } from '@dxos/plugin-search';
18
18
  import { SpacePlugin } from '@dxos/plugin-space';
19
19
  import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
20
20
  import { faker } from '@dxos/random';
21
- import { Filter, useQuery, useSchema, useSpaces } from '@dxos/react-client/echo';
21
+ import { Filter, type Space, useQuery, useSchema, useSpaces } from '@dxos/react-client/echo';
22
22
  import { withTheme } from '@dxos/react-ui/testing';
23
23
  import { ViewEditor } from '@dxos/react-ui-form';
24
24
  import {
@@ -44,6 +44,38 @@ const createOrg = () => ({
44
44
  status: faker.helpers.arrayElement(Organization.StatusOptions).id as Organization.Organization['status'],
45
45
  });
46
46
 
47
+ //
48
+ // Story setup helpers.
49
+ //
50
+
51
+ type ClientSetupOptions = {
52
+ types?: Type.Entity.Any[];
53
+ onSpaceCreated?: (space: Space) => Promise<void>;
54
+ };
55
+
56
+ /**
57
+ * Creates the standard plugin manager decorator with client configuration.
58
+ */
59
+ const withKanbanPlugins = ({ types = [], onSpaceCreated }: ClientSetupOptions): Decorator =>
60
+ withPluginManager({
61
+ plugins: [
62
+ ...corePlugins(),
63
+ ClientPlugin({
64
+ types: [...types, View.View, Kanban.Kanban],
65
+ onClientInitialized: ({ client }) =>
66
+ Effect.gen(function* () {
67
+ yield* Effect.promise(() => client.halo.createIdentity());
68
+ const space = yield* Effect.promise(() => client.spaces.create());
69
+ yield* Effect.promise(() => space.waitUntilReady());
70
+ yield* Effect.promise(() => onSpaceCreated?.(space) ?? Promise.resolve());
71
+ }),
72
+ }),
73
+ PreviewPlugin(),
74
+ SpacePlugin({}),
75
+ StorybookPlugin({}),
76
+ ],
77
+ });
78
+
47
79
  //
48
80
  // Story components.
49
81
  //
@@ -98,6 +130,15 @@ const DefaultComponent = () => {
98
130
  [object, schema],
99
131
  );
100
132
 
133
+ const handleDeleteField = useCallback(
134
+ (fieldId: string) => {
135
+ if (schema && Type.isMutable(schema) && projection) {
136
+ projection.deleteFieldProjection(fieldId);
137
+ }
138
+ },
139
+ [schema, projection],
140
+ );
141
+
101
142
  if (!schema || !object.view.target) {
102
143
  return null;
103
144
  }
@@ -112,9 +153,7 @@ const DefaultComponent = () => {
112
153
  schema={schema}
113
154
  view={object.view.target}
114
155
  onQueryChanged={handleUpdateQuery}
115
- onDelete={(fieldId: string) => {
116
- console.log('[ViewEditor]', 'onDelete', fieldId);
117
- }}
156
+ onDelete={Type.isMutable(schema) ? handleDeleteField : undefined}
118
157
  />
119
158
  <JsonFilter data={{ view: object.view.target, schema }} classNames='text-xs' />
120
159
  </div>
@@ -130,41 +169,7 @@ const meta = {
130
169
  title: 'plugins/plugin-kanban/Kanban',
131
170
  component: DefaultComponent,
132
171
  render: () => <DefaultComponent />,
133
- decorators: [
134
- withTheme,
135
- withPluginManager({
136
- plugins: [
137
- ...corePlugins(),
138
- ClientPlugin({
139
- types: [Organization.Organization, Person.Person, View.View, Kanban.Kanban],
140
- onClientInitialized: ({ client }) =>
141
- Effect.gen(function* () {
142
- yield* Effect.promise(() => client.halo.createIdentity());
143
- const space = yield* Effect.promise(() => client.spaces.create());
144
- yield* Effect.promise(() => space.waitUntilReady());
145
-
146
- const { view } = yield* Effect.promise(() =>
147
- View.makeFromDatabase({
148
- db: space.db,
149
- typename: Organization.Organization.typename,
150
- pivotFieldName: 'status',
151
- }),
152
- );
153
- const kanban = Kanban.make({ view });
154
- space.db.add(kanban);
155
-
156
- // TODO(burdon): Replace with sdk/schema/testing.
157
- Array.from({ length: 80 }).map(() => {
158
- return space.db.add(Obj.make(Organization.Organization, createOrg()));
159
- });
160
- }),
161
- }),
162
- PreviewPlugin(),
163
- SpacePlugin({}),
164
- StorybookPlugin({}),
165
- ],
166
- }),
167
- ],
172
+ decorators: [withTheme],
168
173
  parameters: {
169
174
  layout: 'fullscreen',
170
175
  translations: [...translations, ...kanbanTranslations],
@@ -175,7 +180,30 @@ export default meta;
175
180
 
176
181
  type Story = StoryObj<typeof meta>;
177
182
 
183
+ /**
184
+ * Default story using static runtime schema (immutable).
185
+ * Schema mutations are not allowed.
186
+ */
178
187
  export const Default: Story = {
188
+ decorators: [
189
+ withKanbanPlugins({
190
+ types: [Organization.Organization, Person.Person],
191
+ onSpaceCreated: async (space) => {
192
+ const { view } = await View.makeFromDatabase({
193
+ db: space.db,
194
+ typename: Organization.Organization.typename,
195
+ pivotFieldName: 'status',
196
+ });
197
+ const kanban = Kanban.make({ view });
198
+ space.db.add(kanban);
199
+
200
+ // TODO(burdon): Replace with sdk/schema/testing.
201
+ Array.from({ length: 80 }).map(() => {
202
+ return space.db.add(Obj.make(Organization.Organization, createOrg()));
203
+ });
204
+ },
205
+ }),
206
+ ],
179
207
  play: async ({ canvasElement }) => {
180
208
  const canvas = within(canvasElement);
181
209
 
@@ -224,3 +252,35 @@ export const Default: Story = {
224
252
  // See packages/apps/composer-app/src/playwright/stack.spec.ts for reference.
225
253
  },
226
254
  };
255
+
256
+ /**
257
+ * Story variant that uses a mutable database schema (EchoSchema).
258
+ * This allows testing schema mutations like adding/removing fields.
259
+ */
260
+ // TODO(wittjosiah): Card previews (e.g., OrganizationCard) are type-specific and hard-coded.
261
+ // They don't use the projection to determine which fields to display, so deleting a field
262
+ // from the schema won't remove it from the card preview. To fix this, the type-specific
263
+ // cards in PreviewPlugin would need to accept and respect the projection prop.
264
+ export const MutableSchema: Story = {
265
+ decorators: [
266
+ withKanbanPlugins({
267
+ onSpaceCreated: async (space) => {
268
+ // Register schema in the database to make it mutable (EchoSchema).
269
+ const [schema] = await space.db.schemaRegistry.register([Organization.Organization]);
270
+
271
+ const { view } = await View.makeFromDatabase({
272
+ db: space.db,
273
+ typename: schema.typename,
274
+ pivotFieldName: 'status',
275
+ });
276
+ const kanban = Kanban.make({ view });
277
+ space.db.add(kanban);
278
+
279
+ // Create test data using the registered schema.
280
+ Array.from({ length: 80 }).map(() => {
281
+ return space.db.add(Obj.make(schema, createOrg()));
282
+ });
283
+ },
284
+ }),
285
+ ],
286
+ };
@@ -30,7 +30,8 @@ export const KanbanContainer = ({ role, subject: object }: KanbanContainerProps)
30
30
  useEffect(() => {
31
31
  const staticSchema = schemas.flat().find((schema) => Type.getTypename(schema) === typename);
32
32
  if (staticSchema) {
33
- setCardSchema(staticSchema);
33
+ // NOTE: Use functional update to prevent React from calling the schema as a function.
34
+ setCardSchema(() => staticSchema);
34
35
  }
35
36
  if (!staticSchema && typename && db) {
36
37
  const query = db.schemaRegistry.query({ typename });
@@ -38,7 +39,8 @@ export const KanbanContainer = ({ role, subject: object }: KanbanContainerProps)
38
39
  () => {
39
40
  const [schema] = query.results;
40
41
  if (schema) {
41
- setCardSchema(schema);
42
+ // NOTE: Use functional update to prevent React from calling the schema as a function.
43
+ setCardSchema(() => schema);
42
44
  }
43
45
  },
44
46
  { fire: true },