@dxos/plugin-board 0.8.4-main.c85a9c8dae → 0.8.4-main.dfabb4ec29

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 (94) hide show
  1. package/dist/lib/{browser/BoardContainer-QVVN3MXA.mjs → neutral/BoardContainer-HS5KHT4R.mjs} +47 -33
  2. package/dist/lib/neutral/BoardContainer-HS5KHT4R.mjs.map +7 -0
  3. package/dist/lib/neutral/BoardPlugin.mjs +30 -0
  4. package/dist/lib/neutral/BoardPlugin.mjs.map +7 -0
  5. package/dist/lib/neutral/capabilities/index.mjs +11 -0
  6. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  7. package/dist/lib/{browser/chunk-DX5POLPL.mjs → neutral/chunk-EFV3E7KE.mjs} +2 -2
  8. package/dist/lib/{browser/chunk-DX5POLPL.mjs.map → neutral/chunk-EFV3E7KE.mjs.map} +3 -3
  9. package/dist/lib/{browser/chunk-KO5FZQGF.mjs → neutral/chunk-XXGRE3CK.mjs} +7 -4
  10. package/dist/lib/neutral/chunk-XXGRE3CK.mjs.map +7 -0
  11. package/dist/lib/neutral/components/index.mjs +1 -0
  12. package/dist/lib/neutral/containers/index.mjs +9 -0
  13. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  14. package/dist/lib/neutral/create-object-OWHPPT3P.mjs +27 -0
  15. package/dist/lib/neutral/create-object-OWHPPT3P.mjs.map +7 -0
  16. package/dist/lib/neutral/index.mjs +12 -0
  17. package/dist/lib/neutral/meta.json +1 -0
  18. package/dist/lib/neutral/meta.mjs +8 -0
  19. package/dist/lib/neutral/plugin.mjs +12 -0
  20. package/dist/lib/neutral/plugin.mjs.map +7 -0
  21. package/dist/lib/neutral/react-surface-FZYKJHNB.mjs +26 -0
  22. package/dist/lib/neutral/react-surface-FZYKJHNB.mjs.map +7 -0
  23. package/dist/lib/neutral/translations.mjs +29 -0
  24. package/dist/lib/neutral/translations.mjs.map +7 -0
  25. package/dist/lib/{browser → neutral}/types/index.mjs +1 -1
  26. package/dist/lib/neutral/types/index.mjs.map +7 -0
  27. package/dist/types/src/BoardPlugin.d.ts +1 -0
  28. package/dist/types/src/BoardPlugin.d.ts.map +1 -1
  29. package/dist/types/src/BoardPlugin.test.d.ts +2 -0
  30. package/dist/types/src/BoardPlugin.test.d.ts.map +1 -0
  31. package/dist/types/src/capabilities/create-object.d.ts +11 -0
  32. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  33. package/dist/types/src/capabilities/index.d.ts +8 -1
  34. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  35. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  36. package/dist/types/src/containers/BoardContainer/BoardContainer.d.ts +4 -4
  37. package/dist/types/src/containers/BoardContainer/BoardContainer.d.ts.map +1 -1
  38. package/dist/types/src/containers/BoardContainer/BoardContainer.stories.d.ts +30 -21
  39. package/dist/types/src/containers/BoardContainer/BoardContainer.stories.d.ts.map +1 -1
  40. package/dist/types/src/containers/BoardContainer/index.d.ts +1 -2
  41. package/dist/types/src/containers/BoardContainer/index.d.ts.map +1 -1
  42. package/dist/types/src/index.d.ts +0 -1
  43. package/dist/types/src/index.d.ts.map +1 -1
  44. package/dist/types/src/plugin.d.ts +3 -0
  45. package/dist/types/src/plugin.d.ts.map +1 -0
  46. package/dist/types/src/translations.d.ts +22 -14
  47. package/dist/types/src/translations.d.ts.map +1 -1
  48. package/dist/types/src/types/Board.d.ts.map +1 -1
  49. package/dist/types/tsconfig.tsbuildinfo +1 -1
  50. package/package.json +92 -56
  51. package/src/BoardPlugin.test.ts +27 -0
  52. package/src/BoardPlugin.tsx +8 -19
  53. package/src/capabilities/create-object.ts +30 -0
  54. package/src/capabilities/index.ts +4 -1
  55. package/src/capabilities/react-surface.tsx +31 -0
  56. package/src/containers/BoardContainer/BoardContainer.stories.tsx +19 -19
  57. package/src/containers/BoardContainer/BoardContainer.tsx +50 -23
  58. package/src/containers/BoardContainer/index.ts +1 -3
  59. package/src/index.ts +0 -2
  60. package/src/meta.ts +1 -1
  61. package/src/plugin.ts +9 -0
  62. package/src/translations.ts +12 -11
  63. package/src/types/Board.ts +6 -2
  64. package/dist/lib/browser/BoardContainer-QVVN3MXA.mjs.map +0 -7
  65. package/dist/lib/browser/chunk-KO5FZQGF.mjs.map +0 -7
  66. package/dist/lib/browser/index.mjs +0 -68
  67. package/dist/lib/browser/index.mjs.map +0 -7
  68. package/dist/lib/browser/meta.json +0 -1
  69. package/dist/lib/browser/react-surface-DBUDXBXD.mjs +0 -38
  70. package/dist/lib/browser/react-surface-DBUDXBXD.mjs.map +0 -7
  71. package/dist/lib/node-esm/BoardContainer-U2P3DS4B.mjs +0 -151
  72. package/dist/lib/node-esm/BoardContainer-U2P3DS4B.mjs.map +0 -7
  73. package/dist/lib/node-esm/chunk-4C3UI73P.mjs +0 -35
  74. package/dist/lib/node-esm/chunk-4C3UI73P.mjs.map +0 -7
  75. package/dist/lib/node-esm/chunk-BKJL6RLQ.mjs +0 -21
  76. package/dist/lib/node-esm/chunk-BKJL6RLQ.mjs.map +0 -7
  77. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  78. package/dist/lib/node-esm/index.mjs +0 -69
  79. package/dist/lib/node-esm/index.mjs.map +0 -7
  80. package/dist/lib/node-esm/meta.json +0 -1
  81. package/dist/lib/node-esm/react-surface-SFB3GP7U.mjs +0 -39
  82. package/dist/lib/node-esm/react-surface-SFB3GP7U.mjs.map +0 -7
  83. package/dist/lib/node-esm/types/index.mjs +0 -9
  84. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  85. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  86. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  87. package/src/capabilities/react-surface/index.ts +0 -7
  88. package/src/capabilities/react-surface/react-surface.tsx +0 -27
  89. /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
  90. /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs.map +0 -0
  91. /package/dist/lib/{browser/types → neutral/components}/index.mjs.map +0 -0
  92. /package/dist/lib/{node-esm/types → neutral}/index.mjs.map +0 -0
  93. /package/dist/lib/{node-esm/chunk-HSLMI22Q.mjs.map → neutral/meta.mjs.map} +0 -0
  94. /package/dist/types/src/capabilities/{react-surface/react-surface.d.ts → react-surface.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-board",
3
- "version": "0.8.4-main.c85a9c8dae",
3
+ "version": "0.8.4-main.dfabb4ec29",
4
4
  "description": "Surface plugin for card baords",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -12,83 +12,119 @@
12
12
  "author": "DXOS.org",
13
13
  "sideEffects": true,
14
14
  "type": "module",
15
+ "imports": {
16
+ "#capabilities": {
17
+ "source": "./src/capabilities/index.ts",
18
+ "types": "./dist/types/src/capabilities/index.d.ts",
19
+ "default": "./dist/lib/neutral/capabilities/index.mjs"
20
+ },
21
+ "#components": {
22
+ "source": "./src/components/index.ts",
23
+ "types": "./dist/types/src/components/index.d.ts",
24
+ "default": "./dist/lib/neutral/components/index.mjs"
25
+ },
26
+ "#containers": {
27
+ "source": "./src/containers/index.ts",
28
+ "types": "./dist/types/src/containers/index.d.ts",
29
+ "default": "./dist/lib/neutral/containers/index.mjs"
30
+ },
31
+ "#meta": {
32
+ "source": "./src/meta.ts",
33
+ "types": "./dist/types/src/meta.d.ts",
34
+ "default": "./dist/lib/neutral/meta.mjs"
35
+ },
36
+ "#plugin": {
37
+ "source": "./src/BoardPlugin.tsx",
38
+ "types": "./dist/types/src/BoardPlugin.d.ts",
39
+ "default": "./dist/lib/neutral/BoardPlugin.mjs"
40
+ },
41
+ "#translations": {
42
+ "source": "./src/translations.ts",
43
+ "types": "./dist/types/src/translations.d.ts",
44
+ "default": "./dist/lib/neutral/translations.mjs"
45
+ },
46
+ "#types": {
47
+ "source": "./src/types/index.ts",
48
+ "types": "./dist/types/src/types/index.d.ts",
49
+ "default": "./dist/lib/neutral/types/index.mjs"
50
+ }
51
+ },
15
52
  "exports": {
16
53
  ".": {
17
54
  "source": "./src/index.ts",
18
- "browser": "./dist/lib/browser/index.mjs",
19
- "node": "./dist/lib/node-esm/index.mjs",
20
- "types": "./dist/types/src/index.d.ts"
55
+ "types": "./dist/types/src/index.d.ts",
56
+ "default": "./dist/lib/neutral/index.mjs"
21
57
  },
22
- "./types": {
23
- "source": "./src/types/index.ts",
24
- "browser": "./dist/lib/browser/types/index.mjs",
25
- "node": "./dist/lib/node-esm/types/index.mjs",
26
- "types": "./dist/types/src/types/index.d.ts"
58
+ "./plugin": {
59
+ "source": "./src/plugin.ts",
60
+ "types": "./dist/types/src/plugin.d.ts",
61
+ "default": "./dist/lib/neutral/plugin.mjs"
62
+ },
63
+ "./translations": {
64
+ "source": "./src/translations.ts",
65
+ "types": "./dist/types/src/translations.d.ts",
66
+ "default": "./dist/lib/neutral/translations.mjs"
27
67
  }
28
68
  },
29
69
  "types": "dist/types/src/index.d.ts",
30
- "typesVersions": {
31
- "*": {
32
- "types": [
33
- "dist/types/src/types/index.d.ts"
34
- ]
35
- }
36
- },
37
70
  "files": [
38
71
  "dist",
39
72
  "src"
40
73
  ],
41
74
  "dependencies": {
42
- "effect": "3.19.16",
43
- "@dxos/ai": "0.8.4-main.c85a9c8dae",
44
- "@dxos/app-toolkit": "0.8.4-main.c85a9c8dae",
45
- "@dxos/app-framework": "0.8.4-main.c85a9c8dae",
46
- "@dxos/assistant": "0.8.4-main.c85a9c8dae",
47
- "@dxos/blueprints": "0.8.4-main.c85a9c8dae",
48
- "@dxos/echo": "0.8.4-main.c85a9c8dae",
49
- "@dxos/effect": "0.8.4-main.c85a9c8dae",
50
- "@dxos/client": "0.8.4-main.c85a9c8dae",
51
- "@dxos/invariant": "0.8.4-main.c85a9c8dae",
52
- "@dxos/log": "0.8.4-main.c85a9c8dae",
53
- "@dxos/operation": "0.8.4-main.c85a9c8dae",
54
- "@dxos/plugin-client": "0.8.4-main.c85a9c8dae",
55
- "@dxos/plugin-graph": "0.8.4-main.c85a9c8dae",
56
- "@dxos/async": "0.8.4-main.c85a9c8dae",
57
- "@dxos/plugin-search": "0.8.4-main.c85a9c8dae",
58
- "@dxos/random": "0.8.4-main.c85a9c8dae",
59
- "@dxos/plugin-space": "0.8.4-main.c85a9c8dae",
60
- "@dxos/react-client": "0.8.4-main.c85a9c8dae",
61
- "@dxos/react-ui": "0.8.4-main.c85a9c8dae",
62
- "@dxos/react-ui-attention": "0.8.4-main.c85a9c8dae",
63
- "@dxos/react-ui-board": "0.8.4-main.c85a9c8dae",
64
- "@dxos/react-ui-form": "0.8.4-main.c85a9c8dae",
65
- "@dxos/react-ui-stack": "0.8.4-main.c85a9c8dae",
66
- "@dxos/react-ui-mosaic": "0.8.4-main.c85a9c8dae",
67
- "@dxos/schema": "0.8.4-main.c85a9c8dae",
68
- "@dxos/types": "0.8.4-main.c85a9c8dae",
69
- "@dxos/util": "0.8.4-main.c85a9c8dae",
70
- "@dxos/echo-react": "0.8.4-main.c85a9c8dae"
75
+ "@effect-atom/atom": "^0.5.1",
76
+ "@effect-atom/atom-react": "^0.5.0",
77
+ "effect": "3.20.0",
78
+ "@dxos/ai": "0.8.4-main.dfabb4ec29",
79
+ "@dxos/app-toolkit": "0.8.4-main.dfabb4ec29",
80
+ "@dxos/app-framework": "0.8.4-main.dfabb4ec29",
81
+ "@dxos/client": "0.8.4-main.dfabb4ec29",
82
+ "@dxos/compute": "0.8.4-main.dfabb4ec29",
83
+ "@dxos/async": "0.8.4-main.dfabb4ec29",
84
+ "@dxos/echo": "0.8.4-main.dfabb4ec29",
85
+ "@dxos/echo-react": "0.8.4-main.dfabb4ec29",
86
+ "@dxos/assistant": "0.8.4-main.dfabb4ec29",
87
+ "@dxos/invariant": "0.8.4-main.dfabb4ec29",
88
+ "@dxos/echo-atom": "0.8.4-main.dfabb4ec29",
89
+ "@dxos/log": "0.8.4-main.dfabb4ec29",
90
+ "@dxos/effect": "0.8.4-main.dfabb4ec29",
91
+ "@dxos/plugin-client": "0.8.4-main.dfabb4ec29",
92
+ "@dxos/plugin-graph": "0.8.4-main.dfabb4ec29",
93
+ "@dxos/plugin-markdown": "0.8.4-main.dfabb4ec29",
94
+ "@dxos/plugin-search": "0.8.4-main.dfabb4ec29",
95
+ "@dxos/random": "0.8.4-main.dfabb4ec29",
96
+ "@dxos/plugin-space": "0.8.4-main.dfabb4ec29",
97
+ "@dxos/react-ui-attention": "0.8.4-main.dfabb4ec29",
98
+ "@dxos/react-ui": "0.8.4-main.dfabb4ec29",
99
+ "@dxos/react-ui-board": "0.8.4-main.dfabb4ec29",
100
+ "@dxos/react-ui-form": "0.8.4-main.dfabb4ec29",
101
+ "@dxos/react-ui-mosaic": "0.8.4-main.dfabb4ec29",
102
+ "@dxos/schema": "0.8.4-main.dfabb4ec29",
103
+ "@dxos/types": "0.8.4-main.dfabb4ec29",
104
+ "@dxos/util": "0.8.4-main.dfabb4ec29",
105
+ "@dxos/react-ui-stack": "0.8.4-main.dfabb4ec29",
106
+ "@dxos/react-client": "0.8.4-main.dfabb4ec29"
71
107
  },
72
108
  "devDependencies": {
73
109
  "@types/react": "~19.2.7",
74
110
  "@types/react-dom": "~19.2.3",
75
111
  "react": "~19.2.3",
76
112
  "react-dom": "~19.2.3",
77
- "vite": "^7.1.11",
78
- "@dxos/plugin-testing": "0.8.4-main.c85a9c8dae",
79
- "@dxos/plugin-theme": "0.8.4-main.c85a9c8dae",
80
- "@dxos/test-utils": "0.8.4-main.c85a9c8dae",
81
- "@dxos/storybook-utils": "0.8.4-main.c85a9c8dae",
82
- "@dxos/plugin-preview": "0.8.4-main.c85a9c8dae",
83
- "@dxos/ui-theme": "0.8.4-main.c85a9c8dae",
84
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.c85a9c8dae"
113
+ "vite": "^8.0.10",
114
+ "@dxos/plugin-preview": "0.8.4-main.dfabb4ec29",
115
+ "@dxos/plugin-testing": "0.8.4-main.dfabb4ec29",
116
+ "@dxos/plugin-theme": "0.8.4-main.dfabb4ec29",
117
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.dfabb4ec29",
118
+ "@dxos/test-utils": "0.8.4-main.dfabb4ec29",
119
+ "@dxos/ui-theme": "0.8.4-main.dfabb4ec29",
120
+ "@dxos/storybook-utils": "0.8.4-main.dfabb4ec29"
85
121
  },
86
122
  "peerDependencies": {
87
- "effect": "3.19.16",
123
+ "effect": "3.20.0",
88
124
  "react": "~19.2.3",
89
125
  "react-dom": "~19.2.3",
90
- "@dxos/react-ui": "0.8.4-main.c85a9c8dae",
91
- "@dxos/ui-theme": "0.8.4-main.c85a9c8dae"
126
+ "@dxos/react-ui": "0.8.4-main.dfabb4ec29",
127
+ "@dxos/ui-theme": "0.8.4-main.dfabb4ec29"
92
128
  },
93
129
  "publishConfig": {
94
130
  "access": "public"
@@ -0,0 +1,27 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { describe, test } from 'vitest';
6
+
7
+ import { ClientPlugin } from '@dxos/plugin-client/plugin';
8
+ import { createComposerTestApp } from '@dxos/plugin-testing/harness';
9
+
10
+ import { BoardPlugin } from '#plugin';
11
+
12
+ import { meta } from './meta';
13
+
14
+ const moduleId = (name: string) => `${meta.id}.module.${name}`;
15
+
16
+ describe('BoardPlugin', () => {
17
+ test('modules activate on the expected events', async ({ expect }) => {
18
+ await using harness = await createComposerTestApp({
19
+ plugins: [ClientPlugin({}), BoardPlugin()],
20
+ });
21
+
22
+ // Modules expected to be active after a normal startup.
23
+ expect(harness.manager.getActive()).toEqual(
24
+ expect.arrayContaining([moduleId('CreateObject'), moduleId('schema'), moduleId('ReactSurface')]),
25
+ );
26
+ });
27
+ });
@@ -2,32 +2,21 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import * as Effect from 'effect/Effect';
6
-
7
5
  import { Plugin } from '@dxos/app-framework';
8
6
  import { AppPlugin } from '@dxos/app-toolkit';
9
- import { type CreateObject } from '@dxos/plugin-space/types';
10
- import { translations as boardTranslations } from '@dxos/react-ui-board';
7
+ import { translations as boardTranslations } from '@dxos/react-ui-board/translations';
11
8
 
12
- import { ReactSurface } from './capabilities';
13
- import { meta } from './meta';
14
- import { translations } from './translations';
15
- import { Board } from './types';
9
+ import { CreateObject, ReactSurface } from '#capabilities';
10
+ import { meta } from '#meta';
11
+ import { translations } from '#translations';
12
+ import { Board } from '#types';
16
13
 
17
14
  export const BoardPlugin = Plugin.define(meta).pipe(
18
- AppPlugin.addMetadataModule({
19
- metadata: {
20
- id: Board.Board.typename,
21
- metadata: {
22
- icon: 'ph--squares-four--regular',
23
- iconHue: 'green',
24
- createObject: ((props) => Effect.sync(() => Board.makeBoard(props))) satisfies CreateObject,
25
- addToCollectionOnCreate: true,
26
- },
27
- },
28
- }),
15
+ AppPlugin.addCreateObjectModule({ activate: CreateObject }),
29
16
  AppPlugin.addSchemaModule({ schema: [Board.Board] }),
30
17
  AppPlugin.addSurfaceModule({ activate: ReactSurface }),
31
18
  AppPlugin.addTranslationsModule({ translations: [...translations, ...boardTranslations] }),
32
19
  Plugin.make,
33
20
  );
21
+
22
+ export default BoardPlugin;
@@ -0,0 +1,30 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { Operation } from '@dxos/compute';
9
+ import { SpaceOperation } from '@dxos/plugin-space';
10
+ import { SpaceCapabilities } from '@dxos/plugin-space';
11
+
12
+ import { Board } from '#types';
13
+
14
+ export default Capability.makeModule(
15
+ Effect.fnUntraced(function* () {
16
+ return Capability.contributes(SpaceCapabilities.CreateObjectEntry, {
17
+ id: Board.Board.typename,
18
+ createObject: (props, options) =>
19
+ Effect.gen(function* () {
20
+ const object = Board.makeBoard(props);
21
+ return yield* Operation.invoke(SpaceOperation.AddObject, {
22
+ object,
23
+ target: options.target,
24
+ hidden: true,
25
+ targetNodeId: options.targetNodeId,
26
+ });
27
+ }),
28
+ });
29
+ }),
30
+ );
@@ -2,4 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './react-surface';
5
+ import { Capability } from '@dxos/app-framework';
6
+
7
+ export const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));
8
+ export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
@@ -0,0 +1,31 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import React from 'react';
7
+
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
+ import { Surface } from '@dxos/app-framework/ui';
10
+ import { AppSurface } from '@dxos/app-toolkit/ui';
11
+
12
+ import { BoardContainer } from '#containers';
13
+ import { Board } from '#types';
14
+
15
+ export default Capability.makeModule(() =>
16
+ Effect.succeed(
17
+ Capability.contributes(Capabilities.ReactSurface, [
18
+ Surface.create({
19
+ id: 'root',
20
+ // TODO(wittjosiah): Split into multiple surfaces if this filter proves too strict for non-article roles.
21
+ filter: AppSurface.oneOf(
22
+ AppSurface.object(AppSurface.Article, Board.Board),
23
+ AppSurface.object(AppSurface.Section, Board.Board),
24
+ ),
25
+ component: ({ role, data }) => (
26
+ <BoardContainer role={role} subject={data.subject} attendableId={data.attendableId} />
27
+ ),
28
+ }),
29
+ ]),
30
+ ),
31
+ );
@@ -8,21 +8,22 @@ import React, { useEffect, useState } from 'react';
8
8
 
9
9
  import { withPluginManager } from '@dxos/app-framework/testing';
10
10
  import { Obj } from '@dxos/echo';
11
- import { ClientPlugin } from '@dxos/plugin-client';
12
- import { PreviewPlugin } from '@dxos/plugin-preview';
11
+ import { ClientPlugin } from '@dxos/plugin-client/plugin';
12
+ import { initializeIdentity } from '@dxos/plugin-client/testing';
13
+ import { PreviewPlugin } from '@dxos/plugin-preview/testing';
13
14
  import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
14
- import { faker } from '@dxos/random';
15
+ import { random } from '@dxos/random';
15
16
  import { Filter, Ref, useQuery, useSpaces } from '@dxos/react-client/echo';
16
- import { withLayout, withTheme } from '@dxos/react-ui/testing';
17
- import { translations as stackTranslations } from '@dxos/react-ui-stack';
17
+ import { translations as stackTranslations } from '@dxos/react-ui-stack/translations';
18
+ import { withLayout } from '@dxos/react-ui/testing';
18
19
  import { Organization, Person } from '@dxos/types';
19
20
 
20
- import { translations } from '../../translations';
21
- import { Board } from '../../types';
21
+ import { translations } from '#translations';
22
+ import { Board } from '#types';
22
23
 
23
24
  import { BoardContainer } from './BoardContainer';
24
25
 
25
- faker.seed(0);
26
+ random.seed(0);
26
27
 
27
28
  const createBoard = () =>
28
29
  Obj.make(Board.Board, {
@@ -36,12 +37,12 @@ const createBoard = () =>
36
37
 
37
38
  const createOrg = () =>
38
39
  Obj.make(Organization.Organization, {
39
- name: faker.commerce.productName(),
40
- description: faker.lorem.paragraph(),
41
- image: faker.image.url(),
42
- website: faker.internet.url(),
40
+ name: random.commerce.productName(),
41
+ description: random.lorem.paragraph(),
42
+ image: random.image.url(),
43
+ website: random.internet.url(),
43
44
  // TODO(burdon): Fix.
44
- // status: faker.helpers.arrayElement(Organization.StatusOptions).id,
45
+ // status: random.helpers.arrayElement(Organization.StatusOptions).id,
45
46
  });
46
47
 
47
48
  const DefaultStory = () => {
@@ -61,7 +62,7 @@ const DefaultStory = () => {
61
62
  return null;
62
63
  }
63
64
 
64
- return <BoardContainer role='board' subject={board} />;
65
+ return <BoardContainer role='board' subject={board} attendableId='test' />;
65
66
  };
66
67
 
67
68
  //
@@ -72,7 +73,6 @@ const meta = {
72
73
  title: 'plugins/plugin-board/containers/BoardContainer',
73
74
  render: DefaultStory,
74
75
  decorators: [
75
- withTheme(),
76
76
  withLayout({ layout: 'fullscreen' }),
77
77
  withPluginManager({
78
78
  plugins: [
@@ -81,18 +81,18 @@ const meta = {
81
81
  types: [Organization.Organization, Person.Person, Board.Board],
82
82
  onClientInitialized: ({ client }) =>
83
83
  Effect.gen(function* () {
84
- yield* Effect.promise(() => client.halo.createIdentity());
84
+ yield* initializeIdentity(client);
85
85
  const space = yield* Effect.promise(() => client.spaces.create());
86
86
  yield* Effect.promise(() => space.waitUntilReady());
87
87
  const board = space.db.add(createBoard());
88
88
 
89
- Obj.change(board, (b) => {
89
+ Obj.update(board, (board) => {
90
90
  // Add some sample items
91
91
  Array.from({ length: 10 }).map(() => {
92
92
  const org = createOrg();
93
93
  space.db.add(org);
94
- b.items.push(Ref.make(org));
95
- b.layout.cells[org.id] = {
94
+ board.items.push(Ref.make(org));
95
+ board.layout.cells[org.id] = {
96
96
  x: Math.floor(Math.random() * 5) - 2,
97
97
  y: Math.floor(Math.random() * 5) - 2,
98
98
  width: 1,
@@ -2,13 +2,17 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { useAtomValue } from '@effect-atom/atom-react';
6
+ import * as Atom from '@effect-atom/atom/Atom';
5
7
  import React, { useCallback, useMemo, useRef, useState } from 'react';
6
8
 
7
9
  import { Surface } from '@dxos/app-framework/ui';
8
- import { type SurfaceComponentProps } from '@dxos/app-toolkit/ui';
10
+ import { AppSurface } from '@dxos/app-toolkit/ui';
9
11
  import { Filter, Obj, Ref } from '@dxos/echo';
10
- import { useObject, useObjects } from '@dxos/echo-react';
12
+ import { AtomObj } from '@dxos/echo-atom';
13
+ import { useObject } from '@dxos/echo-react';
11
14
  import { invariant } from '@dxos/invariant';
15
+ import { Markdown } from '@dxos/plugin-markdown';
12
16
  import { useQuery } from '@dxos/react-client/echo';
13
17
  import { Panel } from '@dxos/react-ui';
14
18
  import { useAttention } from '@dxos/react-ui-attention';
@@ -16,7 +20,7 @@ import { Board, type BoardController, type BoardRootProps, type Position } from
16
20
  import { ObjectPicker, type ObjectPickerContentProps } from '@dxos/react-ui-form';
17
21
  import { isNonNullable } from '@dxos/util';
18
22
 
19
- import { type Board as BoardType } from '../../types';
23
+ import { type Board as BoardType } from '#types';
20
24
 
21
25
  const DEFAULT_POSITION = { x: 0, y: 0 } satisfies Position;
22
26
 
@@ -24,18 +28,32 @@ type PickerState = {
24
28
  position: Position;
25
29
  };
26
30
 
27
- export type BoardContainerProps = SurfaceComponentProps<BoardType.Board>;
31
+ export type BoardContainerProps = AppSurface.ObjectArticleProps<BoardType.Board>;
28
32
 
29
- export const BoardContainer = ({ role, subject: board }: BoardContainerProps) => {
30
- const controller = useRef<BoardController>(null);
33
+ export const BoardContainer = ({ role, subject: board, attendableId }: BoardContainerProps) => {
34
+ const { hasAttention } = useAttention(attendableId);
35
+ const db = Obj.getDatabase(board);
31
36
  const [boardItems] = useObject(board, 'items');
32
- const items = useObjects(boardItems ?? []);
37
+ const itemsAtom = useMemo(
38
+ () =>
39
+ Atom.make((get) => {
40
+ const result: Obj.Unknown[] = [];
41
+ for (const ref of boardItems ?? []) {
42
+ const obj = get(AtomObj.makeWithReactive(ref));
43
+ if (obj) {
44
+ result.push(obj);
45
+ }
46
+ }
47
+ return result;
48
+ }),
49
+ [boardItems],
50
+ );
51
+ const items = useAtomValue(itemsAtom);
52
+
53
+ const controller = useRef<BoardController>(null);
33
54
  const addTriggerRef = useRef<HTMLButtonElement | null>(null);
34
55
  const [pickerState, setPickerState] = useState<PickerState | null>(null);
35
- const attendableId = Obj.getDXN(board).toString();
36
- const { hasAttention } = useAttention(attendableId);
37
56
 
38
- const db = Obj.getDatabase(board);
39
57
  // TODO(burdon): Use search.
40
58
  const objects = useQuery(db, Filter.everything());
41
59
  const options = useMemo<ObjectPickerContentProps['options']>(
@@ -58,13 +76,22 @@ export const BoardContainer = ({ role, subject: board }: BoardContainerProps) =>
58
76
  );
59
77
 
60
78
  const handleAdd = useCallback<NonNullable<BoardRootProps['onAdd']>>(
61
- async (anchor, position = DEFAULT_POSITION) => {
79
+ async (anchor, position) => {
62
80
  const db = Obj.getDatabase(board);
63
81
  invariant(db);
82
+ // Grid backdrop "+" supplies a position → create a new Markdown document directly.
83
+ // Toolbar "+" omits position → fall back to the picker over existing objects.
84
+ if (position) {
85
+ const doc = db.add(Markdown.make());
86
+ Obj.update(board, (board) => {
87
+ board.items.push(Ref.make(doc));
88
+ board.layout.cells[doc.id.toString()] = position;
89
+ });
90
+ return;
91
+ }
92
+
64
93
  addTriggerRef.current = anchor;
65
- setPickerState({
66
- position,
67
- });
94
+ setPickerState({ position: DEFAULT_POSITION });
68
95
  },
69
96
  [board],
70
97
  );
@@ -74,11 +101,11 @@ export const BoardContainer = ({ role, subject: board }: BoardContainerProps) =>
74
101
  (id) => {
75
102
  // TODO(burdon): Impl. DXN.equals and pass in DXN from `id`.
76
103
  const idx = board.items.findIndex((ref) => ref.dxn.asEchoDXN()?.echoId === id);
77
- Obj.change(board, (b) => {
104
+ Obj.update(board, (board) => {
78
105
  if (idx !== -1) {
79
- b.items.splice(idx, 1);
106
+ board.items.splice(idx, 1);
80
107
  }
81
- delete b.layout.cells[id];
108
+ delete board.layout.cells[id];
82
109
  });
83
110
  },
84
111
  [board],
@@ -87,8 +114,8 @@ export const BoardContainer = ({ role, subject: board }: BoardContainerProps) =>
87
114
  const handleMove = useCallback<NonNullable<BoardRootProps['onMove']>>(
88
115
  (id, position) => {
89
116
  const layout = board.layout.cells[id];
90
- Obj.change(board, (b) => {
91
- b.layout.cells[id] = { ...layout, ...position };
117
+ Obj.update(board, (board) => {
118
+ board.layout.cells[id] = { ...layout, ...position };
92
119
  });
93
120
  },
94
121
  [board],
@@ -107,11 +134,11 @@ export const BoardContainer = ({ role, subject: board }: BoardContainerProps) =>
107
134
  }
108
135
 
109
136
  // Create a reference to the selected object and add it to the board.
110
- Obj.change(board, (b) => {
111
- b.items.push(Ref.make(selectedObject));
137
+ Obj.update(board, (board) => {
138
+ board.items.push(Ref.make(selectedObject));
112
139
 
113
140
  // Set the layout position for the new item.
114
- b.layout.cells[selectedObject.id.toString()] = pickerState.position;
141
+ board.layout.cells[selectedObject.id.toString()] = pickerState.position;
115
142
  });
116
143
 
117
144
  // Close the picker.
@@ -139,7 +166,7 @@ export const BoardContainer = ({ role, subject: board }: BoardContainerProps) =>
139
166
  <Board.Content>
140
167
  {items?.map((item, index) => (
141
168
  <Board.Cell item={item} key={index} layout={board.layout?.cells[item.id] ?? { x: 0, y: 0 }}>
142
- <Surface.Surface role='card--content' data={{ subject: item }} limit={1} />
169
+ <Surface.Surface type={AppSurface.Card} data={{ subject: item, editable: true }} limit={1} />
143
170
  </Board.Cell>
144
171
  ))}
145
172
  </Board.Content>
@@ -2,6 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { BoardContainer } from './BoardContainer';
6
-
7
- export default BoardContainer;
5
+ export { BoardContainer as default } from './BoardContainer';
package/src/index.ts CHANGED
@@ -4,5 +4,3 @@
4
4
 
5
5
  export * from './meta';
6
6
  export * from './types';
7
-
8
- export * from './BoardPlugin';
package/src/meta.ts CHANGED
@@ -6,7 +6,7 @@ import { type Plugin } from '@dxos/app-framework';
6
6
  import { trim } from '@dxos/util';
7
7
 
8
8
  export const meta: Plugin.Meta = {
9
- id: 'dxos.org/plugin/board',
9
+ id: 'org.dxos.plugin.board',
10
10
  name: 'Board',
11
11
  description: trim`
12
12
  Infinite canvas workspace that combines sticky notes, media, and whiteboarding tools.
package/src/plugin.ts ADDED
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Plugin } from '@dxos/app-framework';
6
+
7
+ import { meta } from './meta';
8
+
9
+ export const BoardPlugin = Plugin.lazy(meta, () => import('#plugin'));
@@ -4,24 +4,25 @@
4
4
 
5
5
  import { type Resource } from '@dxos/react-ui';
6
6
 
7
- import { meta } from './meta';
8
- import { Board } from './types';
7
+ import { meta } from '#meta';
8
+ import { Board } from '#types';
9
9
 
10
10
  export const translations = [
11
11
  {
12
12
  'en-US': {
13
13
  [Board.Board.typename]: {
14
- 'typename label': 'Board',
15
- 'typename label_zero': 'Boards',
16
- 'typename label_one': 'Board',
17
- 'typename label_other': 'Boards',
18
- 'object name placeholder': 'New board',
19
- 'rename object label': 'Rename board',
20
- 'delete object label': 'Delete board',
21
- 'object deleted label': 'Board deleted',
14
+ 'typename.label': 'Board',
15
+ 'typename.label_zero': 'Boards',
16
+ 'typename.label_one': 'Board',
17
+ 'typename.label_other': 'Boards',
18
+ 'object-name.placeholder': 'New board',
19
+ 'add-object.label': 'Add board',
20
+ 'rename-object.label': 'Rename board',
21
+ 'delete-object.label': 'Delete board',
22
+ 'object-deleted.label': 'Board deleted',
22
23
  },
23
24
  [meta.id]: {
24
- 'plugin name': 'Board',
25
+ 'plugin.name': 'Board',
25
26
  },
26
27
  },
27
28
  },