@dxos/plugin-board 0.9.1-staging.ee54ba693a → 0.11.0

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 (65) hide show
  1. package/dist/lib/BoardPlugin.mjs +21 -0
  2. package/dist/lib/BoardPlugin.mjs.map +1 -0
  3. package/dist/lib/capabilities.mjs +8 -0
  4. package/dist/lib/capabilities.mjs.map +1 -0
  5. package/dist/lib/chunk-BoardArticle.mjs +190 -0
  6. package/dist/lib/chunk-BoardArticle.mjs.map +1 -0
  7. package/dist/lib/chunk-create-object.mjs +24 -0
  8. package/dist/lib/chunk-create-object.mjs.map +1 -0
  9. package/dist/lib/{neutral/chunk-TIEIAVKG.mjs → chunk-meta.mjs} +20 -27
  10. package/dist/lib/chunk-meta.mjs.map +1 -0
  11. package/dist/lib/chunk-react-surface.mjs +21 -0
  12. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  13. package/dist/lib/chunk-types.mjs +41 -0
  14. package/dist/lib/chunk-types.mjs.map +1 -0
  15. package/dist/lib/components.mjs +0 -0
  16. package/dist/lib/containers.mjs +7 -0
  17. package/dist/lib/containers.mjs.map +1 -0
  18. package/dist/lib/index.mjs +3 -0
  19. package/dist/lib/meta.mjs +2 -0
  20. package/dist/lib/plugin.mjs +8 -0
  21. package/dist/lib/plugin.mjs.map +1 -0
  22. package/dist/lib/translations.mjs +22 -0
  23. package/dist/lib/translations.mjs.map +1 -0
  24. package/dist/lib/types.mjs +2 -0
  25. package/dist/types/src/capabilities/create-object.d.ts +1 -1
  26. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  27. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  28. package/dist/types/src/containers/BoardArticle/BoardArticle.d.ts +4 -1
  29. package/dist/types/src/containers/BoardArticle/BoardArticle.d.ts.map +1 -1
  30. package/dist/types/src/containers/BoardArticle/BoardArticle.stories.d.ts.map +1 -1
  31. package/dist/types/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +39 -39
  33. package/src/capabilities/{react-surface.tsx → react-surface.ts} +2 -4
  34. package/src/containers/BoardArticle/BoardArticle.stories.tsx +2 -1
  35. package/src/containers/BoardArticle/BoardArticle.tsx +116 -78
  36. package/dist/lib/neutral/BoardArticle-S7VMVBPU.mjs +0 -167
  37. package/dist/lib/neutral/BoardArticle-S7VMVBPU.mjs.map +0 -7
  38. package/dist/lib/neutral/BoardPlugin.mjs +0 -42
  39. package/dist/lib/neutral/BoardPlugin.mjs.map +0 -7
  40. package/dist/lib/neutral/capabilities/index.mjs +0 -11
  41. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  42. package/dist/lib/neutral/chunk-I4YKWAK6.mjs +0 -35
  43. package/dist/lib/neutral/chunk-I4YKWAK6.mjs.map +0 -7
  44. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  45. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  46. package/dist/lib/neutral/chunk-TIEIAVKG.mjs.map +0 -7
  47. package/dist/lib/neutral/components/index.mjs +0 -1
  48. package/dist/lib/neutral/components/index.mjs.map +0 -7
  49. package/dist/lib/neutral/containers/index.mjs +0 -9
  50. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  51. package/dist/lib/neutral/create-object-VMKGCE3J.mjs +0 -27
  52. package/dist/lib/neutral/create-object-VMKGCE3J.mjs.map +0 -7
  53. package/dist/lib/neutral/index.mjs +0 -12
  54. package/dist/lib/neutral/index.mjs.map +0 -7
  55. package/dist/lib/neutral/meta.json +0 -1
  56. package/dist/lib/neutral/meta.mjs +0 -8
  57. package/dist/lib/neutral/meta.mjs.map +0 -7
  58. package/dist/lib/neutral/plugin.mjs +0 -12
  59. package/dist/lib/neutral/plugin.mjs.map +0 -7
  60. package/dist/lib/neutral/react-surface-M5JHK3ZQ.mjs +0 -26
  61. package/dist/lib/neutral/react-surface-M5JHK3ZQ.mjs.map +0 -7
  62. package/dist/lib/neutral/translations.mjs +0 -30
  63. package/dist/lib/neutral/translations.mjs.map +0 -7
  64. package/dist/lib/neutral/types/index.mjs +0 -8
  65. package/dist/lib/neutral/types/index.mjs.map +0 -7
@@ -0,0 +1,21 @@
1
+ import { Plugin } from "@dxos/app-framework";
2
+ import { AppPlugin } from "@dxos/app-toolkit";
3
+ import { translations } from "@dxos/react-ui-board/translations";
4
+ import { CreateObject, ReactSurface } from "#capabilities";
5
+ import { meta } from "#meta";
6
+ import { translations as translations$1 } from "#translations";
7
+ import { Board } from "#types";
8
+ //#region PLUGIN.mdl?raw
9
+ var PLUGIN_default = "---\nid: org.dxos.plugin.board\nname: BoardPlugin\nversion: 0.1.0\n---\n\nA spatial canvas plugin for `DXOS` Composer that lets users arrange any ECHO objects on an infinite two-dimensional grid.\nItems can be placed freely, moved by dragging, and removed from the canvas without deleting the underlying objects.\n\n## Extensions\n\nThe following extension dialects are used in this document.\nEach extension is defined in the Appendix or resolved via its URI.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `test` | `org.dxos.mdl.test@1.0` |\n| `component` | `org.dxos.mdl.component@1.0` |\n| `op` | `org.dxos.mdl.op@1.0` |\n\n## Types\n\n```mdl\ntype Position\n fields:\n x: number\n y: number\n w?: number\n h?: number\n```\n\n```mdl\ntype BoardLayout\n fields:\n cells: { [id: string]: Position }\n```\n\n```mdl\ntype Board\n desc: Root ECHO object (typename org.dxos.type.board).\n fields:\n name?: string\n items: Ref[] # ordered list of references to ECHO objects on the canvas\n layout: BoardLayout # position of every item keyed by object id\n```\n\n## Components\n\n```mdl\ncomponent BoardArticle\n desc: Full-canvas surface rendered for article and section roles.\n props:\n role: string # AppSurface role (article | section)\n subject: Board # ECHO Board object\n attendableId?: string # attention tracking id\n state:\n items: Obj.Unknown[] # resolved ECHO objects from board.items refs\n pickerState?: PickerState # null when picker closed; Position when open\n slots:\n toolbar?: ReactNode # Board.Toolbar (disabled when not focused)\n cell?: ReactNode # one Surface.Surface per item (Card role)\n actions:\n addItem(anchor, position?) → void\n deleteItem(id: string) → void\n moveItem(id: string, position: Position) → void\n selectFromPicker(id: string) → void\n emits:\n onAdd(anchor: HTMLButtonElement, position?: Position)\n onDelete(id: string)\n onMove(id: string, position: Position)\n layout: |\n ┌────────────────────────────────────┐\n │ Board.Toolbar (attention-gated) │\n ├────────────────────────────────────┤\n │ Board.Viewport │\n │ ┌──────────────────────────────┐ │\n │ │ Board.Backdrop (+) │ │\n │ │ │ │\n │ │ ┌──────┐ ┌──────┐ │ │\n │ │ │ Cell │ │ Cell │ … │ │\n │ │ └──────┘ └──────┘ │ │\n │ └──────────────────────────────┘ │\n ├────────────────────────────────────┤\n │ ObjectPicker (popover, when open) │\n └────────────────────────────────────┘\n```\n\n## Operations\n\n```mdl\nop createBoard\n desc: Creates a new Board ECHO object and adds it to the target space.\n input:\n name?: string\n target?: Space\n targetNodeId?: string\n output: Board\n effects: [echo:write]\n note: Delegates to SpaceOperation.AddObject with hidden=true.\n```\n\n```mdl\nop addItem\n desc: Adds an ECHO object reference to the board at the given grid position.\n input:\n board: Board\n object: Obj.Unknown\n position: Position\n output: Board\n effects: [echo:write]\n note: |\n When a grid \"+\" is clicked with a position, a new Markdown document is\n created inline. When the toolbar \"+\" is clicked without a position, an\n ObjectPicker is shown and the user selects an existing object.\n```\n\n```mdl\nop removeItem\n desc: Removes an item reference and its layout entry from the board.\n input:\n board: Board\n id: string\n output: Board\n effects: [echo:write]\n note: Does not delete the underlying ECHO object; only removes it from the canvas.\n```\n\n```mdl\nop moveItem\n desc: Updates the grid position for an existing board item.\n input:\n board: Board\n id: string\n position: Position\n output: Board\n effects: [echo:write]\n```\n\n## Features\n\n```mdl\nfeat F-1: Create Board\n\n req F-1.1: A new Board is created with an empty items list and an empty layout.\n req F-1.2: The Board is added to the active space using SpaceOperation.AddObject.\n req F-1.3: The Board appears in the space object list immediately after creation.\n```\n\n```mdl\nfeat F-2: Add Item to Board\n\n req F-2.1:\n when: user clicks \"+\" on the grid backdrop at a specific position\n then: a new Markdown document is created and placed at that position\n\n req F-2.2:\n when: user clicks \"+\" on the toolbar (no position)\n then: ObjectPicker opens, listing all space objects that are not the board itself\n\n req F-2.3:\n when: user selects an object from the ObjectPicker\n then: a Ref to that object is appended to board.items; layout entry created at default position\n\n req F-2.4: Objects are sorted alphabetically by label in the ObjectPicker.\n```\n\n```mdl\nfeat F-3: Remove Item from Board\n\n req F-3.1:\n when: user deletes a cell\n then: the Ref is removed from board.items and the layout entry is deleted\n note: the referenced ECHO object is not deleted\n\n req F-3.2: Board is updated atomically via Obj.update.\n```\n\n```mdl\nfeat F-4: Move Item on Board\n\n req F-4.1:\n when: user drags a card to a new position\n then: board.layout.cells[id] is updated with the new Position\n\n req F-4.2: Other items are not affected by a move operation.\n```\n\n```mdl\nfeat F-5: Render Items\n\n req F-5.1: Each item in board.items is rendered as a Surface.Surface with the Card role.\n req F-5.2:\n when: an item's Ref cannot be resolved (deleted object)\n then: the cell is silently omitted from the rendered canvas\n\n req F-5.3: Items are rendered in board.items order; z-ordering follows index.\n```\n\n```mdl\nfeat F-6: Attention and Focus\n\n req F-6.1:\n when: the Board surface does not have attention\n then: Board.Toolbar is rendered in disabled state; drag and add interactions are suppressed\n\n req F-6.2:\n when: the Board surface gains attention\n then: Board.Toolbar becomes interactive\n```\n\n## Acceptance\n\n```mdl\ntest T-1: New board is empty\n given: a new Board has been created\n then:\n - board.items is empty\n - board.layout.cells is empty\n```\n\n```mdl\ntest T-2: Add item via grid backdrop\n given: an empty board is displayed\n when: user clicks the \"+\" hotspot at position (100, 200)\n then:\n - a Markdown document is created in the space\n - board.items contains a Ref to the new document\n - board.layout.cells[doc.id] === { x: 100, y: 200 }\n```\n\n```mdl\ntest T-3: Add existing object via picker\n given: the space contains a Document with label \"Meeting notes\"\n when: user opens the ObjectPicker from the toolbar and selects \"Meeting notes\"\n then:\n - board.items contains a Ref to the Document\n - board.layout.cells[doc.id] === { x: 0, y: 0 }\n - picker is closed\n```\n\n```mdl\ntest T-4: Remove item\n given: board has one item\n when: user deletes the cell\n then:\n - board.items is empty\n - board.layout.cells is empty\n - the referenced ECHO object still exists in the space\n```\n\n```mdl\ntest T-5: Move item\n given: board has one item at position { x: 0, y: 0 }\n when: user drags it to { x: 300, y: 150 }\n then:\n - board.layout.cells[item.id] === { x: 300, y: 150 }\n - board.items length is unchanged\n```\n\n```mdl\ntest T-6: Toolbar gated by attention\n given: board is rendered without focus\n then: Board.Toolbar is disabled\n when: board gains focus\n then: Board.Toolbar is interactive\n```\n\n---\n\n## Appendix: Extension Definitions\n\nExtension block types used in this document are defined below using\nthe core `ext` primitive — the only construct the base language provides.\n\n```mdl\next type\n uri: org.dxos.mdl.type@1.0\n desc: A named data structure with typed fields and optional literals.\n fields:\n desc?: Prose\n fields?: FieldMap # name[?]: TypeExpr (# inline comment)\n literals?: UnionList # a | b | c\n extends?: TypeRef[]\n```\n\n```mdl\next feat\n uri: org.dxos.mdl.feat@1.0\n desc: A named feature grouping one or more requirements.\n fields:\n desc?: Prose\n req: RequirementList\n nesting: self # feat blocks may contain feat blocks\n```\n\n```mdl\next test\n uri: org.dxos.mdl.test@1.0\n desc: An acceptance scenario expressed as given / when / then steps.\n fields:\n given?: Step | Step[]\n when?: Step | Step[]\n then: Step | Step[]\n tags?: TagList\n```\n\n```mdl\next component\n uri: org.dxos.mdl.component@1.0\n desc: A UI component with props, internal state, slots, actions, and events.\n fields:\n desc?: Prose\n props?: FieldMap # external inputs (immutable inside component)\n state?: FieldMap # internal reactive state\n slots?: FieldMap # named ReactNode injection points\n actions?: ActionMap # methods the component exposes or handles\n emits?: EventMap # events the component raises to its parent\n layout?: CodeBlock # ASCII sketch of visual structure (non-normative)\n```\n\n```mdl\next op\n uri: org.dxos.mdl.op@1.0\n desc: |\n A named operation with typed inputs, outputs, and declared errors.\n Pure ops have no effects or requires. Effectful ops declare both.\n fields:\n desc?: Prose\n input?: FieldMap # named input parameters\n output?: TypeExpr # return type\n errors?: ErrorMap # name: Prose (when this error occurs)\n effects?: EffectList # echo:read | echo:write | http | fs | ...\n requires?: ServiceList # injected service dependencies\n note?: Prose # implementation guidance (non-normative)\n```\n";
10
+ //#endregion
11
+ //#region src/BoardPlugin.tsx
12
+ var BoardPlugin = Plugin.define(meta).pipe(AppPlugin.addCreateObjectModule({ activate: CreateObject }), AppPlugin.addSchemaModule({ schema: [Board.Board] }), AppPlugin.addSurfaceModule({ activate: ReactSurface }), AppPlugin.addTranslationsModule({ translations: [...translations$1, ...translations] }), AppPlugin.addPluginAssetModule({ asset: {
13
+ pluginId: meta.profile.key,
14
+ path: "PLUGIN.mdl",
15
+ content: PLUGIN_default,
16
+ mimeType: "application/x-mdl"
17
+ } }), Plugin.make);
18
+ //#endregion
19
+ export { BoardPlugin, BoardPlugin as default };
20
+
21
+ //# sourceMappingURL=BoardPlugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BoardPlugin.mjs","names":[],"sources":["../../src/BoardPlugin.tsx"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { AppPlugin } from '@dxos/app-toolkit';\nimport { translations as boardTranslations } from '@dxos/react-ui-board/translations';\n\nimport { CreateObject, ReactSurface } from '#capabilities';\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { Board } from '#types';\n\n// eslint-disable-next-line import/no-relative-packages\nimport pluginSpec from '../PLUGIN.mdl?raw';\n\nexport const BoardPlugin = Plugin.define(meta).pipe(\n AppPlugin.addCreateObjectModule({ activate: CreateObject }),\n AppPlugin.addSchemaModule({ schema: [Board.Board] }),\n AppPlugin.addSurfaceModule({ activate: ReactSurface }),\n AppPlugin.addTranslationsModule({ translations: [...translations, ...boardTranslations] }),\n AppPlugin.addPluginAssetModule({\n asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },\n }),\n Plugin.make,\n);\n\nexport default BoardPlugin;\n"],"mappings":";;;;;;;;;;;AAgBA,IAAa,cAAc,OAAO,OAAO,IAAI,CAAC,CAAC,KAC7C,UAAU,sBAAsB,EAAE,UAAU,aAAa,CAAC,GAC1D,UAAU,gBAAgB,EAAE,QAAQ,CAAC,MAAM,KAAK,EAAE,CAAC,GACnD,UAAU,iBAAiB,EAAE,UAAU,aAAa,CAAC,GACrD,UAAU,sBAAsB,EAAE,cAAc,CAAC,GAAG,gBAAc,GAAG,YAAiB,EAAE,CAAC,GACzF,UAAU,qBAAqB,EAC7B,OAAO;CAAE,UAAU,KAAK,QAAQ;CAAK,MAAM;CAAc,SAAS;CAAY,UAAU;AAAoB,EAC9G,CAAC,GACD,OAAO,IACT"}
@@ -0,0 +1,8 @@
1
+ import { Capability } from "@dxos/app-framework";
2
+ //#region src/capabilities/index.ts
3
+ var CreateObject = Capability.lazy("CreateObject", () => import("./chunk-create-object.mjs"));
4
+ var ReactSurface = Capability.lazy("ReactSurface", () => import("./chunk-react-surface.mjs"));
5
+ //#endregion
6
+ export { CreateObject, ReactSurface };
7
+
8
+ //# sourceMappingURL=capabilities.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.mjs","names":[],"sources":["../../src/capabilities/index.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Capability } from '@dxos/app-framework';\n\nexport const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));\nexport const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));\n"],"mappings":";;AAMA,IAAa,eAAe,WAAW,KAAK,sBAAsB,OAAO,4BAAkB;AAC3F,IAAa,eAAe,WAAW,KAAK,sBAAsB,OAAO,4BAAkB"}
@@ -0,0 +1,190 @@
1
+ import { isNonNullable } from "@dxos/util";
2
+ import { Filter, Obj, Ref } from "@dxos/echo";
3
+ import { Board, resizeToFit } from "@dxos/react-ui-board";
4
+ import { translationKey } from "@dxos/react-ui-board/translations";
5
+ import { useCallback, useMemo, useRef, useState } from "react";
6
+ import { Surface } from "@dxos/app-framework/ui";
7
+ import { AppSurface } from "@dxos/app-toolkit/ui";
8
+ import { useAtomValue } from "@effect-atom/atom-react";
9
+ import * as Atom from "@effect-atom/atom/Atom";
10
+ import { useObject, useQuery } from "@dxos/echo-react";
11
+ import { invariant } from "@dxos/invariant";
12
+ import { EID } from "@dxos/keys";
13
+ import { Markdown } from "@dxos/plugin-markdown";
14
+ import { Panel, Toolbar, useTranslation } from "@dxos/react-ui";
15
+ import { useAttention } from "@dxos/react-ui-attention";
16
+ import { ObjectPicker } from "@dxos/react-ui-form";
17
+ import { jsx, jsxs } from "react/jsx-runtime";
18
+ //#region src/containers/BoardArticle/BoardArticle.tsx
19
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-board/src/containers/BoardArticle/BoardArticle.tsx";
20
+ var DEFAULT_POSITION = {
21
+ x: 0,
22
+ y: 0
23
+ };
24
+ var normalizeCells = (cells) => {
25
+ const values = Object.values(cells);
26
+ const minX = Math.min(0, ...values.map((cell) => cell.x));
27
+ const minY = Math.min(0, ...values.map((cell) => cell.y));
28
+ if (minX === 0 && minY === 0) return cells;
29
+ return Object.fromEntries(Object.entries(cells).map(([id, cell]) => [id, {
30
+ ...cell,
31
+ x: cell.x - minX,
32
+ y: cell.y - minY
33
+ }]));
34
+ };
35
+ var BoardArticle = ({ role, subject: board, attendableId }) => {
36
+ const { t } = useTranslation(translationKey);
37
+ const { hasAttention } = useAttention(attendableId);
38
+ const db = Obj.getDatabase(board);
39
+ const [boardItems] = useObject(board, "items");
40
+ const items = useAtomValue(useMemo(() => Atom.make((get) => {
41
+ const result = [];
42
+ for (const ref of boardItems ?? []) {
43
+ const obj = get(Obj.atomReactive(ref));
44
+ if (obj) result.push(obj);
45
+ }
46
+ return result;
47
+ }), [boardItems]));
48
+ const controller = useRef(null);
49
+ const addTriggerRef = useRef(null);
50
+ const [pickerState, setPickerState] = useState(null);
51
+ const [zoom, setZoom] = useState(1);
52
+ const layout = useMemo(() => ({ items: normalizeCells(board.layout.cells) }), [board.layout.cells]);
53
+ const bounds = useMemo(() => ({
54
+ columns: board.layout.size.width,
55
+ rows: board.layout.size.height
56
+ }), [board.layout.size.width, board.layout.size.height]);
57
+ const objects = useQuery(db, Filter.everything());
58
+ const options = useMemo(() => objects.filter((obj) => obj.id !== board.id).map((obj) => {
59
+ const label = Obj.getLabel(obj);
60
+ return label ? {
61
+ id: obj.id,
62
+ label,
63
+ hue: "neutral"
64
+ } : void 0;
65
+ }).filter(isNonNullable).sort(({ label: a }, { label: b }) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase())), [objects, board.id]);
66
+ const handleChange = useCallback((next) => {
67
+ Obj.update(board, (board) => {
68
+ board.layout.cells = next.items;
69
+ });
70
+ }, [board]);
71
+ const handleAdd = useCallback((position) => {
72
+ const db = Obj.getDatabase(board);
73
+ invariant(db, void 0, {
74
+ "~LogMeta": "~LogMeta",
75
+ F: __dxlog_file,
76
+ L: 105,
77
+ S: void 0,
78
+ A: ["db", ""]
79
+ });
80
+ const doc = db.add(Markdown.make());
81
+ Obj.update(board, (board) => {
82
+ board.items.push(Ref.make(doc));
83
+ board.layout.cells[doc.id.toString()] = position;
84
+ });
85
+ }, [board]);
86
+ const handleDelete = useCallback((id) => {
87
+ const idx = board.items.findIndex((ref) => {
88
+ const echoUri = EID.tryParse(ref.uri);
89
+ return (echoUri ? EID.getEntityId(echoUri) : void 0) === id;
90
+ });
91
+ Obj.update(board, (board) => {
92
+ if (idx !== -1) board.items.splice(idx, 1);
93
+ delete board.layout.cells[id];
94
+ });
95
+ }, [board]);
96
+ const handleSelect = useCallback((id) => {
97
+ const position = pickerState?.position ?? DEFAULT_POSITION;
98
+ const selected = objects.find((obj) => obj.id === id);
99
+ if (!Obj.isObject(selected)) return;
100
+ Obj.update(board, (board) => {
101
+ board.items.push(Ref.make(selected));
102
+ board.layout.cells[selected.id.toString()] = position;
103
+ });
104
+ setPickerState(null);
105
+ }, [
106
+ pickerState,
107
+ objects,
108
+ board
109
+ ]);
110
+ return /* @__PURE__ */ jsxs(ObjectPicker.Root, {
111
+ open: !!pickerState,
112
+ onOpenChange: (next) => setPickerState(next ? { position: DEFAULT_POSITION } : null),
113
+ children: [
114
+ /* @__PURE__ */ jsx(Board.Root, {
115
+ ref: controller,
116
+ layout,
117
+ bounds,
118
+ mode: "float",
119
+ resolver: resizeToFit,
120
+ zoom,
121
+ onChange: handleChange,
122
+ onAdd: handleAdd,
123
+ onDelete: handleDelete,
124
+ children: /* @__PURE__ */ jsxs(Panel.Root, {
125
+ role,
126
+ children: [/* @__PURE__ */ jsx(Panel.Toolbar, {
127
+ asChild: true,
128
+ children: /* @__PURE__ */ jsxs(Toolbar.Root, { children: [
129
+ /* @__PURE__ */ jsx(Toolbar.IconButton, {
130
+ icon: "ph--crosshair--regular",
131
+ iconOnly: true,
132
+ label: t("move-to-center.button"),
133
+ disabled: !hasAttention,
134
+ onClick: () => controller.current?.center()
135
+ }),
136
+ /* @__PURE__ */ jsx(Toolbar.IconButton, {
137
+ icon: zoom < 1 ? "ph--arrows-in--regular" : "ph--arrows-out--regular",
138
+ iconOnly: true,
139
+ label: t("toggle-zoom.button"),
140
+ disabled: !hasAttention,
141
+ onClick: () => setZoom((value) => value < 1 ? 1 : .5)
142
+ }),
143
+ /* @__PURE__ */ jsx(Toolbar.IconButton, {
144
+ icon: "ph--plus--regular",
145
+ iconOnly: true,
146
+ label: t("add-object.button"),
147
+ disabled: !hasAttention,
148
+ onClick: (event) => {
149
+ addTriggerRef.current = event.currentTarget;
150
+ setPickerState({ position: DEFAULT_POSITION });
151
+ }
152
+ })
153
+ ] })
154
+ }), /* @__PURE__ */ jsx(Panel.Content, {
155
+ asChild: true,
156
+ children: /* @__PURE__ */ jsxs(Board.Container, {
157
+ classNames: "absolute inset-0",
158
+ children: [/* @__PURE__ */ jsxs(Board.Viewport, { children: [/* @__PURE__ */ jsx(Board.Backdrop, {}), /* @__PURE__ */ jsx(Board.Content, { children: items?.map((item) => {
159
+ const itemLayout = layout.items[item.id];
160
+ return itemLayout ? /* @__PURE__ */ jsx(Board.Cell, {
161
+ item,
162
+ layout: itemLayout,
163
+ children: /* @__PURE__ */ jsx(Surface.Surface, {
164
+ type: AppSurface.CardContent,
165
+ data: {
166
+ subject: item,
167
+ editable: true
168
+ },
169
+ limit: 1
170
+ })
171
+ }, item.id) : null;
172
+ }) })] }), /* @__PURE__ */ jsx(Board.Map, { classNames: "absolute bottom-2 right-2 z-10 w-40" })]
173
+ })
174
+ })]
175
+ })
176
+ }),
177
+ /* @__PURE__ */ jsx(ObjectPicker.Content, {
178
+ options,
179
+ onSelect: handleSelect,
180
+ classNames: "dx-card-popover-width"
181
+ }),
182
+ /* @__PURE__ */ jsx(ObjectPicker.VirtualTrigger, { virtualRef: addTriggerRef })
183
+ ]
184
+ });
185
+ };
186
+ BoardArticle.displayName = "BoardArticle";
187
+ //#endregion
188
+ export { BoardArticle as default };
189
+
190
+ //# sourceMappingURL=chunk-BoardArticle.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-BoardArticle.mjs","names":[],"sources":["../../src/containers/BoardArticle/BoardArticle.tsx"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { useAtomValue } from '@effect-atom/atom-react';\nimport * as Atom from '@effect-atom/atom/Atom';\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { Surface } from '@dxos/app-framework/ui';\nimport { AppSurface } from '@dxos/app-toolkit/ui';\nimport { Filter, Obj, Ref } from '@dxos/echo';\nimport { useObject, useQuery } from '@dxos/echo-react';\nimport { invariant } from '@dxos/invariant';\nimport { EID } from '@dxos/keys';\nimport { Markdown } from '@dxos/plugin-markdown';\nimport { Panel, Toolbar, useTranslation } from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\nimport { Board, type BoardController, type BoardRootProps, type Layout, resizeToFit } from '@dxos/react-ui-board';\nimport { translationKey } from '@dxos/react-ui-board/translations';\nimport { ObjectPicker, type ObjectPickerContentProps } from '@dxos/react-ui-form';\nimport { isNonNullable } from '@dxos/util';\n\nimport { type Board as BoardType } from '#types';\n\ntype Position = { x: number; y: number };\n\nconst DEFAULT_POSITION: Position = { x: 0, y: 0 };\n\n// Legacy boards stored cells with a centre origin (signed coords); the engine is 0-based, so shift all\n// cells to non-negative before handing them to the component. Freshly-created boards are already 0-based.\nconst normalizeCells = (cells: BoardType.Board['layout']['cells']): Layout['items'] => {\n const values = Object.values(cells);\n const minX = Math.min(0, ...values.map((cell) => cell.x));\n const minY = Math.min(0, ...values.map((cell) => cell.y));\n if (minX === 0 && minY === 0) {\n return cells;\n }\n return Object.fromEntries(\n Object.entries(cells).map(([id, cell]) => [id, { ...cell, x: cell.x - minX, y: cell.y - minY }]),\n );\n};\n\nexport type BoardArticleProps = AppSurface.ObjectArticleProps<BoardType.Board>;\n\nexport const BoardArticle = ({ role, subject: board, attendableId }: BoardArticleProps) => {\n const { t } = useTranslation(translationKey);\n const { hasAttention } = useAttention(attendableId);\n const db = Obj.getDatabase(board);\n const [boardItems] = useObject(board, 'items');\n const itemsAtom = useMemo(\n () =>\n Atom.make((get) => {\n const result: Obj.Unknown[] = [];\n for (const ref of boardItems ?? []) {\n const obj = get(Obj.atomReactive(ref));\n if (obj) {\n result.push(obj);\n }\n }\n return result;\n }),\n [boardItems],\n );\n const items = useAtomValue(itemsAtom);\n\n const controller = useRef<BoardController>(null);\n const addTriggerRef = useRef<HTMLButtonElement | null>(null);\n const [pickerState, setPickerState] = useState<{ position: Position } | null>(null);\n const [zoom, setZoom] = useState(1);\n\n const layout = useMemo<Layout>(() => ({ items: normalizeCells(board.layout.cells) }), [board.layout.cells]);\n const bounds = useMemo(\n () => ({ columns: board.layout.size.width, rows: board.layout.size.height }),\n [board.layout.size.width, board.layout.size.height],\n );\n\n // TODO(burdon): Use search.\n const objects = useQuery(db, Filter.everything());\n const options = useMemo<ObjectPickerContentProps['options']>(\n () =>\n objects\n .filter((obj) => obj.id !== board.id)\n .map((obj) => {\n const label = Obj.getLabel(obj);\n return label ? { id: obj.id, label, hue: 'neutral' as const } : undefined;\n })\n .filter(isNonNullable)\n .sort(({ label: a }, { label: b }) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase())),\n [objects, board.id],\n );\n\n const handleChange = useCallback<NonNullable<BoardRootProps['onChange']>>(\n (next) => {\n Obj.update(board, (board) => {\n board.layout.cells = next.items;\n });\n },\n [board],\n );\n\n // Backdrop \"+\" supplies a position → create a new Markdown document directly.\n const handleAdd = useCallback<NonNullable<BoardRootProps['onAdd']>>(\n (position) => {\n const db = Obj.getDatabase(board);\n invariant(db);\n const doc = db.add(Markdown.make());\n Obj.update(board, (board) => {\n board.items.push(Ref.make(doc));\n board.layout.cells[doc.id.toString()] = position;\n });\n },\n [board],\n );\n\n // TODO(burdon): Use intents so can be undone.\n const handleDelete = useCallback<NonNullable<BoardRootProps['onDelete']>>(\n (id) => {\n // TODO(burdon): Impl. DXN.equals and pass in DXN from `id`.\n const idx = board.items.findIndex((ref) => {\n const echoUri = EID.tryParse(ref.uri);\n return (echoUri ? EID.getEntityId(echoUri) : undefined) === id;\n });\n Obj.update(board, (board) => {\n if (idx !== -1) {\n board.items.splice(idx, 1);\n }\n delete board.layout.cells[id];\n });\n },\n [board],\n );\n\n // Toolbar \"+\" adds an existing object via the picker.\n const handleSelect = useCallback<NonNullable<ObjectPickerContentProps['onSelect']>>(\n (id) => {\n const position = pickerState?.position ?? DEFAULT_POSITION;\n const selected = objects.find((obj) => obj.id === id);\n if (!Obj.isObject(selected)) {\n return;\n }\n Obj.update(board, (board) => {\n board.items.push(Ref.make(selected));\n board.layout.cells[selected.id.toString()] = position;\n });\n setPickerState(null);\n },\n [pickerState, objects, board],\n );\n\n return (\n <ObjectPicker.Root\n open={!!pickerState}\n onOpenChange={(next: boolean) => setPickerState(next ? { position: DEFAULT_POSITION } : null)}\n >\n <Board.Root\n ref={controller}\n layout={layout}\n bounds={bounds}\n mode='float'\n resolver={resizeToFit}\n zoom={zoom}\n onChange={handleChange}\n onAdd={handleAdd}\n onDelete={handleDelete}\n >\n <Panel.Root role={role}>\n {/* TODO(burdon): Migrate to Menu.Root + useMenuActions (threading attendableId). */}\n <Panel.Toolbar asChild>\n <Toolbar.Root>\n <Toolbar.IconButton\n icon='ph--crosshair--regular'\n iconOnly\n label={t('move-to-center.button')}\n disabled={!hasAttention}\n onClick={() => controller.current?.center()}\n />\n <Toolbar.IconButton\n icon={zoom < 1 ? 'ph--arrows-in--regular' : 'ph--arrows-out--regular'}\n iconOnly\n label={t('toggle-zoom.button')}\n disabled={!hasAttention}\n onClick={() => setZoom((value) => (value < 1 ? 1 : 0.5))}\n />\n <Toolbar.IconButton\n icon='ph--plus--regular'\n iconOnly\n label={t('add-object.button')}\n disabled={!hasAttention}\n onClick={(event) => {\n addTriggerRef.current = event.currentTarget as HTMLButtonElement;\n setPickerState({ position: DEFAULT_POSITION });\n }}\n />\n </Toolbar.Root>\n </Panel.Toolbar>\n <Panel.Content asChild>\n <Board.Container classNames='absolute inset-0'>\n <Board.Viewport>\n <Board.Backdrop />\n <Board.Content>\n {items?.map((item) => {\n const itemLayout = layout.items[item.id];\n return itemLayout ? (\n <Board.Cell item={item} key={item.id} layout={itemLayout}>\n <Surface.Surface\n type={AppSurface.CardContent}\n data={{ subject: item, editable: true }}\n limit={1}\n />\n </Board.Cell>\n ) : null;\n })}\n </Board.Content>\n </Board.Viewport>\n {/* Overview map (outlines the visible region), pinned to the corner over the board. */}\n <Board.Map classNames='absolute bottom-2 right-2 z-10 w-40' />\n </Board.Container>\n </Panel.Content>\n </Panel.Root>\n </Board.Root>\n <ObjectPicker.Content options={options} onSelect={handleSelect} classNames='dx-card-popover-width' />\n <ObjectPicker.VirtualTrigger virtualRef={addTriggerRef} />\n </ObjectPicker.Root>\n );\n};\n\nBoardArticle.displayName = 'BoardArticle';\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { Capability } from "@dxos/app-framework";
2
+ import { Type } from "@dxos/echo";
3
+ import { Board } from "#types";
4
+ import * as Effect from "effect/Effect";
5
+ import { Operation } from "@dxos/compute";
6
+ import { SpaceCapabilities, SpaceOperation } from "@dxos/plugin-space";
7
+ //#region src/capabilities/create-object.ts
8
+ var create_object_default = Capability.makeModule(Effect.fnUntraced(function* () {
9
+ return Capability.contributes(SpaceCapabilities.CreateObjectEntry, {
10
+ id: Type.getTypename(Board.Board),
11
+ createObject: (props, options) => Effect.gen(function* () {
12
+ const object = Board.makeBoard(props);
13
+ return yield* Operation.invoke(SpaceOperation.AddObject, {
14
+ object,
15
+ target: options.target,
16
+ targetNodeId: options.targetNodeId
17
+ });
18
+ })
19
+ });
20
+ }));
21
+ //#endregion
22
+ export { create_object_default as default };
23
+
24
+ //# sourceMappingURL=chunk-create-object.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-create-object.mjs","names":[],"sources":["../../src/capabilities/create-object.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport { Operation } from '@dxos/compute';\nimport { Type } from '@dxos/echo';\nimport { SpaceOperation } from '@dxos/plugin-space';\nimport { SpaceCapabilities } from '@dxos/plugin-space';\n\nimport { Board } from '#types';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n return Capability.contributes(SpaceCapabilities.CreateObjectEntry, {\n id: Type.getTypename(Board.Board),\n createObject: (props, options) =>\n Effect.gen(function* () {\n const object = Board.makeBoard(props);\n return yield* Operation.invoke(SpaceOperation.AddObject, {\n object,\n target: options.target,\n targetNodeId: options.targetNodeId,\n });\n }),\n });\n }),\n);\n"],"mappings":";;;;;;;AAcA,IAAA,wBAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,OAAO,WAAW,YAAY,kBAAkB,mBAAmB;EACjE,IAAI,KAAK,YAAY,MAAM,KAAK;EAChC,eAAe,OAAO,YACpB,OAAO,IAAI,aAAa;GACtB,MAAM,SAAS,MAAM,UAAU,KAAK;GACpC,OAAO,OAAO,UAAU,OAAO,eAAe,WAAW;IACvD;IACA,QAAQ,QAAQ;IAChB,cAAc,QAAQ;GACxB,CAAC;EACH,CAAC;CACL,CAAC;AACH,CAAC,CACH"}
@@ -1,15 +1,12 @@
1
- // src/meta.ts
2
1
  import { Plugin } from "@dxos/app-framework";
3
-
4
- // dx.config.ts
5
2
  import { Config2 } from "@dxos/app-framework/config";
6
3
  import { trim } from "@dxos/util";
7
- var dx_config_default = Config2.make({
8
- plugin: {
9
- key: "org.dxos.plugin.board",
10
- name: "Board",
11
- author: "DXOS",
12
- description: trim`
4
+ //#region dx.config.ts
5
+ var dx_config_default = Config2.make({ plugin: {
6
+ key: "org.dxos.plugin.board",
7
+ name: "Board",
8
+ author: "DXOS",
9
+ description: trim`
13
10
  Board is an infinite spatial canvas that lets you place any ECHO object — documents, tasks, notes, or rich media — anywhere on a two-dimensional grid.
14
11
  Items are arranged by dragging, resized freely, and removed from the canvas without deleting the underlying data, so the same object can appear on multiple boards simultaneously.
15
12
 
@@ -19,23 +16,19 @@ var dx_config_default = Config2.make({
19
16
  Board is designed as a lightweight composition layer: it imposes no schema on the objects it hosts and delegates rendering to each object's own Card surface, so every plugin contributes its own card representation automatically.
20
17
  This makes it ideal for dashboards, mood boards, project overviews, or any context where spatial relationships between heterogeneous objects carry meaning.
21
18
  `,
22
- source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-board",
23
- icon: {
24
- key: "ph--squares-four--regular",
25
- hue: "green"
26
- },
27
- spec: "PLUGIN.mdl",
28
- screenshots: [],
29
- tags: [
30
- "labs"
31
- ]
32
- }
33
- });
34
-
35
- // src/meta.ts
19
+ source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-board",
20
+ icon: {
21
+ key: "ph--squares-four--regular",
22
+ hue: "green"
23
+ },
24
+ spec: "PLUGIN.mdl",
25
+ screenshots: [],
26
+ tags: ["labs"]
27
+ } });
28
+ //#endregion
29
+ //#region src/meta.ts
36
30
  var meta = Plugin.getMetaFromConfig(dx_config_default);
31
+ //#endregion
32
+ export { meta as t };
37
33
 
38
- export {
39
- meta
40
- };
41
- //# sourceMappingURL=chunk-TIEIAVKG.mjs.map
34
+ //# sourceMappingURL=chunk-meta.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-meta.mjs","names":[],"sources":["../../dx.config.ts","../../src/meta.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Config2 } from '@dxos/app-framework/config';\nimport { trim } from '@dxos/util';\n\nexport default Config2.make({\n plugin: {\n key: 'org.dxos.plugin.board',\n name: 'Board',\n author: 'DXOS',\n description: trim`\n Board is an infinite spatial canvas that lets you place any ECHO object — documents, tasks, notes, or rich media — anywhere on a two-dimensional grid.\n Items are arranged by dragging, resized freely, and removed from the canvas without deleting the underlying data, so the same object can appear on multiple boards simultaneously.\n\n Each board is itself an ECHO object, making it fully collaborative and conflict-free: all participants see live updates as peers add, move, or remove items in real time.\n The canvas scales to any resolution, supports nested surfaces through the Composer slot system, and integrates naturally with other plugins via the shared ObjectPicker.\n\n Board is designed as a lightweight composition layer: it imposes no schema on the objects it hosts and delegates rendering to each object's own Card surface, so every plugin contributes its own card representation automatically.\n This makes it ideal for dashboards, mood boards, project overviews, or any context where spatial relationships between heterogeneous objects carry meaning.\n `,\n source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-board',\n icon: { key: 'ph--squares-four--regular', hue: 'green' },\n spec: 'PLUGIN.mdl',\n screenshots: [],\n tags: ['labs'],\n },\n});\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\n\nimport config from '../dx.config';\n\nexport const meta = Plugin.getMetaFromConfig(config);\n"],"mappings":";;;;AAOA,IAAA,oBAAe,QAAQ,KAAK,EAC1B,QAAQ;CACN,KAAK;CACL,MAAM;CACN,QAAQ;CACR,aAAa,IAAI;;;;;;;;;;CAUjB,QAAQ;CACR,MAAM;EAAE,KAAK;EAA6B,KAAK;CAAQ;CACvD,MAAM;CACN,aAAa,CAAC;CACd,MAAM,CAAC,MAAM;AACf,EACF,CAAC;;;ACpBD,IAAa,OAAO,OAAO,kBAAkB,iBAAM"}
@@ -0,0 +1,21 @@
1
+ import { Capabilities, Capability } from "@dxos/app-framework";
2
+ import { Board } from "#types";
3
+ import * as Effect from "effect/Effect";
4
+ import { Surface } from "@dxos/app-framework/ui";
5
+ import { AppSurface } from "@dxos/app-toolkit/ui";
6
+ import { BoardArticle } from "#containers";
7
+ //#region src/capabilities/react-surface.ts
8
+ var react_surface_default = Capability.makeModule(() => Effect.succeed(Capability.contributes(Capabilities.ReactSurface, [Surface.create({
9
+ id: "root",
10
+ filter: AppSurface.oneOf(AppSurface.object(AppSurface.Article, Board.Board), AppSurface.object(AppSurface.Section, Board.Board)),
11
+ component: BoardArticle,
12
+ props: ({ role, data: { subject, attendableId } }) => ({
13
+ role,
14
+ subject,
15
+ attendableId
16
+ })
17
+ })])));
18
+ //#endregion
19
+ export { react_surface_default as default };
20
+
21
+ //# sourceMappingURL=chunk-react-surface.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-react-surface.mjs","names":[],"sources":["../../src/capabilities/react-surface.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capabilities, Capability } from '@dxos/app-framework';\nimport { Surface } from '@dxos/app-framework/ui';\nimport { AppSurface } from '@dxos/app-toolkit/ui';\n\nimport { BoardArticle } from '#containers';\nimport { Board } from '#types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contributes(Capabilities.ReactSurface, [\n Surface.create({\n id: 'root',\n // TODO(wittjosiah): Split into multiple surfaces if this filter proves too strict for non-article roles.\n filter: AppSurface.oneOf(\n AppSurface.object(AppSurface.Article, Board.Board),\n AppSurface.object(AppSurface.Section, Board.Board),\n ),\n component: BoardArticle,\n props: ({ role, data: { subject, attendableId } }) => ({ role, subject, attendableId }),\n }),\n ]),\n ),\n);\n"],"mappings":";;;;;;;AAaA,IAAA,wBAAe,WAAW,iBACxB,OAAO,QACL,WAAW,YAAY,aAAa,cAAc,CAChD,QAAQ,OAAO;CACb,IAAI;CAEJ,QAAQ,WAAW,MACjB,WAAW,OAAO,WAAW,SAAS,MAAM,KAAK,GACjD,WAAW,OAAO,WAAW,SAAS,MAAM,KAAK,CACnD;CACA,WAAW;CACX,QAAQ,EAAE,MAAM,MAAM,EAAE,SAAS,sBAAsB;EAAE;EAAM;EAAS;CAAa;AACvF,CAAC,CACH,CAAC,CACH,CACF"}
@@ -0,0 +1,41 @@
1
+ import * as Schema from "effect/Schema";
2
+ import { Annotation, DXN, Obj, Ref, Type } from "@dxos/echo";
3
+ import { FormInputAnnotation, LabelAnnotation } from "@dxos/echo/Annotation";
4
+ import { BoardLayout, defaultLayout } from "@dxos/react-ui-board";
5
+ //#region \0rolldown/runtime.js
6
+ var __defProp = Object.defineProperty;
7
+ var __exportAll = (all, no_symbols) => {
8
+ let target = {};
9
+ for (var name in all) __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true
12
+ });
13
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
14
+ return target;
15
+ };
16
+ //#endregion
17
+ //#region src/types/Board.ts
18
+ var Board_exports = /* @__PURE__ */ __exportAll({
19
+ Board: () => Board$1,
20
+ makeBoard: () => makeBoard
21
+ });
22
+ /**
23
+ * Board and layout.
24
+ */
25
+ var Board$1 = class extends Type.makeObject(DXN.make("org.dxos.type.board", "0.1.0"))(Schema.Struct({
26
+ name: Schema.String.pipe(Schema.optional),
27
+ items: Ref.Ref(Obj.Unknown).pipe(Schema.Array, FormInputAnnotation.set(false)),
28
+ layout: BoardLayout.pipe(FormInputAnnotation.set(false))
29
+ }).pipe(LabelAnnotation.set(["name"]), Annotation.IconAnnotation.set({
30
+ icon: "ph--squares-four--regular",
31
+ hue: "green"
32
+ }))) {};
33
+ var makeBoard = (props = {}) => Obj.make(Board$1, {
34
+ items: [],
35
+ layout: defaultLayout,
36
+ ...props
37
+ });
38
+ //#endregion
39
+ export { Board_exports as t };
40
+
41
+ //# sourceMappingURL=chunk-types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-types.mjs","names":[],"sources":["../../src/types/Board.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { Annotation, DXN, Obj, Ref, Type } from '@dxos/echo';\nimport { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/Annotation';\nimport { BoardLayout, defaultLayout } from '@dxos/react-ui-board';\n\n/**\n * Board and layout.\n */\nexport class Board extends Type.makeObject<Board>(DXN.make('org.dxos.type.board', '0.1.0'))(\n Schema.Struct({\n name: Schema.String.pipe(Schema.optional),\n items: Ref.Ref(Obj.Unknown).pipe(Schema.Array, FormInputAnnotation.set(false)),\n layout: BoardLayout.pipe(FormInputAnnotation.set(false)),\n }).pipe(\n LabelAnnotation.set(['name']),\n Annotation.IconAnnotation.set({ icon: 'ph--squares-four--regular', hue: 'green' }),\n ),\n) {}\n\nexport const makeBoard = (props: Partial<Obj.MakeProps<typeof Board>> = {}) =>\n Obj.make(Board, {\n items: [],\n layout: defaultLayout,\n ...props,\n });\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAaA,IAAa,UAAb,cAA2B,KAAK,WAAkB,IAAI,KAAK,uBAAuB,OAAO,CAAC,CAAC,CACzF,OAAO,OAAO;CACZ,MAAM,OAAO,OAAO,KAAK,OAAO,QAAQ;CACxC,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC,KAAK,OAAO,OAAO,oBAAoB,IAAI,KAAK,CAAC;CAC7E,QAAQ,YAAY,KAAK,oBAAoB,IAAI,KAAK,CAAC;AACzD,CAAC,CAAC,CAAC,KACD,gBAAgB,IAAI,CAAC,MAAM,CAAC,GAC5B,WAAW,eAAe,IAAI;CAAE,MAAM;CAA6B,KAAK;AAAQ,CAAC,CACnF,CACF,CAAC,CAAC,CAAC;AAEH,IAAa,aAAa,QAA8C,CAAC,MACvE,IAAI,KAAK,SAAO;CACd,OAAO,CAAC;CACR,QAAQ;CACR,GAAG;AACL,CAAC"}
File without changes
@@ -0,0 +1,7 @@
1
+ import { lazy } from "react";
2
+ //#region src/containers/index.ts
3
+ var BoardArticle = lazy(() => import("./chunk-BoardArticle.mjs"));
4
+ //#endregion
5
+ export { BoardArticle };
6
+
7
+ //# sourceMappingURL=containers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containers.mjs","names":[],"sources":["../../src/containers/index.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type ComponentType, lazy } from 'react';\n\nexport const BoardArticle: ComponentType<any> = lazy(() => import('./BoardArticle'));\n"],"mappings":";;AAMA,IAAa,eAAmC,WAAW,OAAO,2BAAiB"}
@@ -0,0 +1,3 @@
1
+ import { t as Board_exports } from "./chunk-types.mjs";
2
+ import { t as meta } from "./chunk-meta.mjs";
3
+ export { Board_exports as Board, meta };
@@ -0,0 +1,2 @@
1
+ import { t as meta } from "./chunk-meta.mjs";
2
+ export { meta };
@@ -0,0 +1,8 @@
1
+ import { t as meta } from "./chunk-meta.mjs";
2
+ import { Plugin } from "@dxos/app-framework";
3
+ //#region src/plugin.ts
4
+ var BoardPlugin = Plugin.lazy(meta, () => import("#plugin"));
5
+ //#endregion
6
+ export { BoardPlugin };
7
+
8
+ //# sourceMappingURL=plugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../../src/plugin.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\n\nimport { meta } from './meta';\n\nexport const BoardPlugin = Plugin.lazy(meta, () => import('#plugin'));\n"],"mappings":";;;AAQA,IAAa,cAAc,OAAO,KAAK,YAAY,OAAO,UAAU"}
@@ -0,0 +1,22 @@
1
+ import { Type } from "@dxos/echo";
2
+ import { meta } from "#meta";
3
+ import { Board } from "#types";
4
+ //#region src/translations.ts
5
+ var translations = [{ "en-US": {
6
+ [Type.getTypename(Board.Board)]: {
7
+ "typename.label": "Board",
8
+ "typename.label_zero": "Boards",
9
+ "typename.label_one": "Board",
10
+ "typename.label_other": "Boards",
11
+ "object-name.placeholder": "New board",
12
+ "add-object.label": "Add board",
13
+ "rename-object.label": "Rename board",
14
+ "delete-object.label": "Delete board",
15
+ "object-deleted.label": "Board deleted"
16
+ },
17
+ [meta.profile.key]: { "plugin.name": "Board" }
18
+ } }];
19
+ //#endregion
20
+ export { translations };
21
+
22
+ //# sourceMappingURL=translations.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translations.mjs","names":[],"sources":["../../src/translations.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport { Type } from '@dxos/echo';\nimport { type Resource } from '@dxos/react-ui';\n\nimport { meta } from '#meta';\nimport { Board } from '#types';\n\nexport const translations = [\n {\n 'en-US': {\n [Type.getTypename(Board.Board)]: {\n 'typename.label': 'Board',\n 'typename.label_zero': 'Boards',\n 'typename.label_one': 'Board',\n 'typename.label_other': 'Boards',\n 'object-name.placeholder': 'New board',\n 'add-object.label': 'Add board',\n 'rename-object.label': 'Rename board',\n 'delete-object.label': 'Delete board',\n 'object-deleted.label': 'Board deleted',\n },\n [meta.profile.key]: {\n 'plugin.name': 'Board',\n },\n },\n },\n] as const satisfies Resource[];\n"],"mappings":";;;;AAUA,IAAa,eAAe,CAC1B,EACE,SAAS;EACN,KAAK,YAAY,MAAM,KAAK,IAAI;EAC/B,kBAAkB;EAClB,uBAAuB;EACvB,sBAAsB;EACtB,wBAAwB;EACxB,2BAA2B;EAC3B,oBAAoB;EACpB,uBAAuB;EACvB,uBAAuB;EACvB,wBAAwB;CAC1B;EACC,KAAK,QAAQ,MAAM,EAClB,eAAe,QACjB;AACF,EACF,CACF"}
@@ -0,0 +1,2 @@
1
+ import { t as Board_exports } from "./chunk-types.mjs";
2
+ export { Board_exports as Board };
@@ -1,5 +1,5 @@
1
1
  import * as Effect from 'effect/Effect';
2
2
  import { Capability } from '@dxos/app-framework';
3
- declare const _default: (props: void) => Effect.Effect<Capability.Any, never, never>;
3
+ declare const _default: (props: void) => Effect.Effect<Capability.Any, never, import("effect/Scope").Scope>;
4
4
  export default _default;
5
5
  //# sourceMappingURL=create-object.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import * as Effect from 'effect/Effect';
2
2
  import { Capability } from '@dxos/app-framework';
3
- declare const _default: (props: void) => Effect.Effect<Capability.Any, never, never>;
3
+ declare const _default: (props: void) => Effect.Effect<Capability.Any, never, import("effect/Scope").Scope>;
4
4
  export default _default;
5
5
  //# sourceMappingURL=react-surface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-surface.d.ts","sourceRoot":"","sources":["../../../../src/capabilities/react-surface.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,OAAO,EAAgB,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"react-surface.d.ts","sourceRoot":"","sources":["../../../../src/capabilities/react-surface.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAgB,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
@@ -2,5 +2,8 @@ import React from 'react';
2
2
  import { AppSurface } from '@dxos/app-toolkit/ui';
3
3
  import { type Board as BoardType } from '#types';
4
4
  export type BoardArticleProps = AppSurface.ObjectArticleProps<BoardType.Board>;
5
- export declare const BoardArticle: ({ role, subject: board, attendableId }: BoardArticleProps) => React.JSX.Element;
5
+ export declare function BoardArticle({ role, subject: board, attendableId }: BoardArticleProps): React.JSX.Element;
6
+ export declare namespace BoardArticle {
7
+ var displayName: string;
8
+ }
6
9
  //# sourceMappingURL=BoardArticle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BoardArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/BoardArticle/BoardArticle.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAGtE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAalD,OAAO,EAAE,KAAK,KAAK,IAAI,SAAS,EAAE,MAAM,QAAQ,CAAC;AAQjD,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAE/E,eAAO,MAAM,YAAY,2CAA4C,iBAAiB,sBA4JrF,CAAC"}
1
+ {"version":3,"file":"BoardArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/BoardArticle/BoardArticle.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAGtE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAalD,OAAO,EAAE,KAAK,KAAK,IAAI,SAAS,EAAE,MAAM,QAAQ,CAAC;AAoBjD,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;qCAElD,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,iBAAiB"}
@@ -1 +1 @@
1
- {"version":3,"file":"BoardArticle.stories.d.ts","sourceRoot":"","sources":["../../../../../src/containers/BoardArticle/BoardArticle.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,KAA8B,MAAM,OAAO,CAAC;AAgEnD,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CT,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC"}
1
+ {"version":3,"file":"BoardArticle.stories.d.ts","sourceRoot":"","sources":["../../../../../src/containers/BoardArticle/BoardArticle.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,KAA8B,MAAM,OAAO,CAAC;AAiEnD,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CT,CAAC;eAEa,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC"}