@lupinum/board-connections 1.0.0-beta.4 → 1.0.0-beta.6

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 (26) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +46 -25
  3. package/dist/agent/AGENTS.md +53 -57
  4. package/dist/agent/pages/docs/build-features/connections.md +333 -2
  5. package/dist/agent/pages/docs/build-features/custom-node-renderers.md +366 -2
  6. package/dist/agent/pages/docs/build-features/read-only-and-command-guards.md +278 -2
  7. package/dist/agent/pages/docs/build-features/save-and-load.md +264 -2
  8. package/dist/agent/pages/docs/build-features/selection-and-keyboard.md +257 -2
  9. package/dist/agent/pages/docs/build-features/theming.md +285 -2
  10. package/dist/agent/pages/docs/evaluate/how-nuxt-board-works.md +451 -2
  11. package/dist/agent/pages/docs/project/contributing.md +4 -4
  12. package/dist/agent/pages/docs/project/support-and-security.md +1 -1
  13. package/dist/agent/pages/docs/reference/events-and-errors.md +279 -2
  14. package/dist/agent/pages/docs/reference/package-overview.md +2 -2
  15. package/dist/agent/pages/docs/solutions/mind-map.md +448 -2
  16. package/dist/agent/pages/docs/solutions/nuxt-application.md +214 -2
  17. package/dist/agent/pages/docs/solutions/planning-board.md +281 -2
  18. package/dist/agent/pages/docs/solutions/read-only-viewer.md +278 -2
  19. package/dist/agent/pages/docs/solutions/workflow-builder.md +435 -2
  20. package/dist/agent/pages/docs/start-building/customize-your-first-node.md +381 -2
  21. package/dist/agent/pages/docs/start-building/installation.md +6 -14
  22. package/dist/agent/pages/docs/understand-the-system/commands-and-transactions.md +456 -2
  23. package/dist/agent/pages/docs/understand-the-system/document-and-session-state.md +348 -2
  24. package/dist/agent/pages/docs/understand-the-system/persistence-and-json-canvas.md +445 -2
  25. package/package.json +6 -5
  26. package/dist/agent/manifest.json +0 -320
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @lupinum/board-connections
2
+
3
+ ## 1.0.0-beta.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#80](https://github.com/lupinum-dev/nuxt-board/pull/80) [`334b6d5`](https://github.com/lupinum-dev/nuxt-board/commit/334b6d577ed6dd0bb2e7f13399636d056203114e) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Change the packaged agent docs to every documentation page, indexed in `dist/agent/AGENTS.md`, and add an "Agent setup" section to each README.
8
+
9
+ The `./agent-docs` export still resolves to `dist/agent/AGENTS.md`. Each package now also ships its `CHANGELOG.md`.
10
+ - Updated dependencies [[`334b6d5`](https://github.com/lupinum-dev/nuxt-board/commit/334b6d577ed6dd0bb2e7f13399636d056203114e)]:
11
+ - @lupinum/board-core@1.0.0-beta.6
12
+ - @lupinum/vue-board@1.0.0-beta.6
package/README.md CHANGED
@@ -17,30 +17,6 @@
17
17
 
18
18
  Use this plugin when nodes must connect to each other. The plugin owns connection state and provides a Vue SVG layer for rendering.
19
19
 
20
- <!-- BEGIN:consumer-onboarding -->
21
-
22
- ## Use a coding agent
23
-
24
- A coding agent is a development tool that can inspect and change your project.
25
-
26
- Copy this task prompt into your application agent:
27
-
28
- ```text
29
- Use the installed Nuxt Board packages to implement my requested feature.
30
- Read the application's instructions first. Resolve @lupinum/board-core/agent-docs
31
- and each installed Board package’s agent-docs entry from this application
32
- directory. Read the relevant local pages.
33
- Preserve the existing AGENTS.md. If it has no equivalent guidance, append
34
- one short note to resolve installed package docs before integration work
35
- and after dependency changes. Do not install a consumer skill.
36
- Check the completed feature using this project's normal commands.
37
- ```
38
-
39
- The installed documentation matches the package version. If an older version
40
- has no documentation export, use its README, types and matching release docs.
41
-
42
- <!-- END:consumer-onboarding -->
43
-
44
20
  ## Requirements
45
21
 
46
22
  Install the same version of this package, `@lupinum/board-core`, and `@lupinum/vue-board`. The fixed-version release keeps the plugin ABI aligned.
@@ -78,9 +54,54 @@ The package exports the connections plugin and the Vue connection layer.
78
54
 
79
55
  Read the [connections reference](https://nuxt-board.lupinum.com/docs/reference/connections).
80
56
 
57
+ ## Agent setup
58
+
59
+ `@lupinum/board-connections` ships its documentation inside the package for coding
60
+ agents such as Claude Code, Codex and Cursor. The pages match the installed
61
+ version, so an agent does not follow the website for a different version.
62
+
63
+ To set it up, give your coding agent this task:
64
+
65
+ ```text
66
+ Set up @lupinum/board-connections for coding agents as described under "Agent setup" in its README.
67
+ ```
68
+
69
+ ### Steps for the agent
70
+
71
+ 1. Find `node_modules/@lupinum/board-connections/dist/agent/AGENTS.md`. Look in the
72
+ directory of the project that depends on `@lupinum/board-connections` first, then
73
+ in its parent directories up to the repository root (workspaces can hoist
74
+ packages). Read it; it lists the documentation pages.
75
+ 2. Add the section below to the project's agent instructions: `AGENTS.md`, or
76
+ `CLAUDE.md` if the project has only that file. If it has neither, create
77
+ `AGENTS.md`. Write the path relative to the repository root, through
78
+ `node_modules/@lupinum/board-connections` (for example
79
+ `apps/web/node_modules/@lupinum/board-connections/...` in a workspace). Never write
80
+ a resolved path such as `node_modules/.pnpm/...`: it contains the version and
81
+ breaks after an upgrade. If a section for `@lupinum/board-connections` already
82
+ exists, leave it as it is.
83
+
84
+ Use the path you found in place of the sample path:
85
+
86
+ ```md
87
+ ## @lupinum/board-connections
88
+
89
+ Before you change code that uses @lupinum/board-connections, read
90
+ `node_modules/@lupinum/board-connections/dist/agent/AGENTS.md` and the pages it
91
+ lists. They document the installed version. Prefer them over what you
92
+ remember about this package and over the website.
93
+ ```
94
+
95
+ 3. Do not copy the documentation into the project and do not install a skill.
96
+ The section points into the installed package, so it stays correct after
97
+ every upgrade or downgrade.
98
+
99
+ If the file does not exist, the installed version has no packaged
100
+ documentation. Read the package README and its TypeScript types instead.
101
+
81
102
  ## Support and security
82
103
 
83
- Open a [GitHub issue](https://github.com/lupinum-dev/nuxt-board/issues) for support. Report vulnerabilities through the [private security process](https://github.com/lupinum-dev/nuxt-board/security/policy).
104
+ Open a [GitHub issue](https://github.com/lupinum-dev/nuxt-board/issues) for bugs, or ask in the [Lupinum OSS Discord](https://discord.lupinum.com). Report vulnerabilities through the [private security process](https://github.com/lupinum-dev/nuxt-board/security/policy).
84
105
 
85
106
  ## License
86
107
 
@@ -1,63 +1,59 @@
1
- # @lupinum/board-connections
1
+ # @lupinum/board-connections 1.0.0-beta.6 documentation
2
2
 
3
- Documentation for installed version 1.0.0-beta.4.
3
+ These pages document the installed version 1.0.0-beta.6. Prefer them over what you
4
+ remember about this package and over the website, which may describe another version.
5
+ Read the pages that match the task before you write code. If they do not answer a question,
6
+ the user can ask in the Lupinum OSS Discord: https://discord.lupinum.com
4
7
 
5
- Read the relevant local pages before changing this package’s integration.
6
- Project instructions govern architecture, style and permissions.
8
+ > A command-driven board engine and Vue renderer for products that need a real document model.
7
9
 
8
- ## Start here
10
+ ## When to use
9
11
 
10
- - [Installation](./pages/docs/start-building/installation.md) — /docs/start-building/installation
11
- - [@lupinum/board-connections](./pages/docs/reference/connections.md) — /docs/reference/connections
12
+ Use this site to build node-based editors with Nuxt Board.
12
13
 
13
- ## Find a page
14
+ ## Documentation
14
15
 
15
- The index below maps public documentation routes to this installed snapshot.
16
- For links to this documentation site, use the matching local page in manifest.json
17
- instead of fetching a possibly different website version. Preserve URL fragments.
18
- External dependencies have their own versioned contracts. Report missing guidance.
19
-
20
- - [Nuxt Board documentation](./pages/docs.md) — /docs
21
- - [Connections](./pages/docs/build-features/connections.md) — /docs/build-features/connections
22
- - [Custom renderers](./pages/docs/build-features/custom-node-renderers.md) — /docs/build-features/custom-node-renderers
23
- - [Group nodes](./pages/docs/build-features/groups-and-nesting.md) — /docs/build-features/groups-and-nesting
24
- - [Performance](./pages/docs/build-features/performance.md) — /docs/build-features/performance
25
- - [First-party features and command guards](./pages/docs/build-features/read-only-and-command-guards.md) — /docs/build-features/read-only-and-command-guards
26
- - [Serialization](./pages/docs/build-features/save-and-load.md) — /docs/build-features/save-and-load
27
- - [Selection and interaction](./pages/docs/build-features/selection-and-keyboard.md) — /docs/build-features/selection-and-keyboard
28
- - [SSR deterministic scene](./pages/docs/build-features/ssr-and-deterministic-state.md) — /docs/build-features/ssr-and-deterministic-state
29
- - [Theming](./pages/docs/build-features/theming.md) — /docs/build-features/theming
30
- - [History](./pages/docs/build-features/undo-and-redo.md) — /docs/build-features/undo-and-redo
31
- - [Design decisions](./pages/docs/evaluate/design-decisions.md) — /docs/evaluate/design-decisions
32
- - [How Nuxt Board works](./pages/docs/evaluate/how-nuxt-board-works.md) — /docs/evaluate/how-nuxt-board-works
33
- - [Why Nuxt Board](./pages/docs/evaluate/why-nuxt-board.md) — /docs/evaluate/why-nuxt-board
34
- - [Contributing](./pages/docs/project/contributing.md) — /docs/project/contributing
35
- - [Support and security](./pages/docs/project/support-and-security.md) — /docs/project/support-and-security
36
- - [@lupinum/board-core types](./pages/docs/reference/board-core-types.md) — /docs/reference/board-core-types
37
- - [@lupinum/board-core](./pages/docs/reference/board-core.md) — /docs/reference/board-core
38
- - [@lupinum/board-connections](./pages/docs/reference/connections.md) — /docs/reference/connections
39
- - [Events and subscriptions](./pages/docs/reference/events-and-errors.md) — /docs/reference/events-and-errors
40
- - [Glossary](./pages/docs/reference/glossary.md) — /docs/reference/glossary
41
- - [@lupinum/board-history](./pages/docs/reference/history.md) — /docs/reference/history
42
- - [@lupinum/vue-board/minimap](./pages/docs/reference/minimap.md) — /docs/reference/minimap
43
- - [@lupinum/nuxt-board](./pages/docs/reference/nuxt-board.md) — /docs/reference/nuxt-board
44
- - [Package overview](./pages/docs/reference/package-overview.md) — /docs/reference/package-overview
45
- - [@lupinum/vue-board](./pages/docs/reference/vue-board.md) — /docs/reference/vue-board
46
- - [Vue composables](./pages/docs/reference/vue-composables.md) — /docs/reference/vue-composables
47
- - [Mind map](./pages/docs/solutions/mind-map.md) — /docs/solutions/mind-map
48
- - [Nuxt auto-imports](./pages/docs/solutions/nuxt-application.md) — /docs/solutions/nuxt-application
49
- - [Planning board](./pages/docs/solutions/planning-board.md) — /docs/solutions/planning-board
50
- - [Read-only viewer](./pages/docs/solutions/read-only-viewer.md) — /docs/solutions/read-only-viewer
51
- - [Workflow renderer demo](./pages/docs/solutions/workflow-builder.md) — /docs/solutions/workflow-builder
52
- - [Add connections and history](./pages/docs/start-building/add-connections-and-history.md) — /docs/start-building/add-connections-and-history
53
- - [Customize your first node](./pages/docs/start-building/customize-your-first-node.md) — /docs/start-building/customize-your-first-node
54
- - [Installation](./pages/docs/start-building/installation.md) — /docs/start-building/installation
55
- - [Your first board](./pages/docs/start-building/your-first-board.md) — /docs/start-building/your-first-board
56
- - [Camera and coordinates](./pages/docs/understand-the-system/camera-and-coordinates.md) — /docs/understand-the-system/camera-and-coordinates
57
- - [Commands and transactions](./pages/docs/understand-the-system/commands-and-transactions.md) — /docs/understand-the-system/commands-and-transactions
58
- - [Document and session state](./pages/docs/understand-the-system/document-and-session-state.md) — /docs/understand-the-system/document-and-session-state
59
- - [Nodes and hierarchy](./pages/docs/understand-the-system/nodes-and-hierarchy.md) — /docs/understand-the-system/nodes-and-hierarchy
60
- - [Packages and plugins](./pages/docs/understand-the-system/packages-and-plugins.md) — /docs/understand-the-system/packages-and-plugins
61
- - [Persistence and JSON Canvas](./pages/docs/understand-the-system/persistence-and-json-canvas.md) — /docs/understand-the-system/persistence-and-json-canvas
62
- - [Rendering and interaction](./pages/docs/understand-the-system/rendering-and-interaction.md) — /docs/understand-the-system/rendering-and-interaction
63
- - [The engine](./pages/docs/understand-the-system/the-engine.md) — /docs/understand-the-system/the-engine
16
+ - [Why Nuxt Board](./pages/docs/evaluate/why-nuxt-board.md): The product problems Nuxt Board solves and the boundaries it keeps explicit.
17
+ - [How Nuxt Board works](./pages/docs/evaluate/how-nuxt-board-works.md): The complete mental model from application intent to rendered board.
18
+ - [Design decisions](./pages/docs/evaluate/design-decisions.md): The constraints Nuxt Board chooses, the problems they solve, and their costs.
19
+ - [Installation](./pages/docs/start-building/installation.md): Install the smallest Nuxt Board package set for Vue or Nuxt.
20
+ - [Your first board](./pages/docs/start-building/your-first-board.md): Create, populate, and mount a working board with one canonical example.
21
+ - [Customize your first node](./pages/docs/start-building/customize-your-first-node.md): Render product-specific Vue content without creating another document schema.
22
+ - [Add connections and history](./pages/docs/start-building/add-connections-and-history.md): Install edges and undo without expanding the core package.
23
+ - [The engine](./pages/docs/understand-the-system/the-engine.md): State ownership, lifecycle, reads, commands, and subscriptions.
24
+ - [Document and session state](./pages/docs/understand-the-system/document-and-session-state.md): Why rendered state and exported state can differ during a gesture.
25
+ - [Commands and transactions](./pages/docs/understand-the-system/commands-and-transactions.md): How changes are guarded, staged, validated, committed, and published.
26
+ - [Nodes and hierarchy](./pages/docs/understand-the-system/nodes-and-hierarchy.md): The canonical node records, geometry, parent relationships, and z-order.
27
+ - [Camera and coordinates](./pages/docs/understand-the-system/camera-and-coordinates.md): Pan, zoom, viewport measurements, and board-space conversion.
28
+ - [Rendering and interaction](./pages/docs/understand-the-system/rendering-and-interaction.md): What BoardRoot owns and where custom rendering begins.
29
+ - [Packages and plugins](./pages/docs/understand-the-system/packages-and-plugins.md): One owner for each capability and the reason packages stay focused.
30
+ - [Persistence and JSON Canvas](./pages/docs/understand-the-system/persistence-and-json-canvas.md): What the engine exports, validates, normalizes, and deliberately excludes.
31
+ - [Custom renderers](./pages/docs/build-features/custom-node-renderers.md): Register custom Vue components for supported JSON Canvas node types while keeping board interactions intact.
32
+ - [Connections](./pages/docs/build-features/connections.md): Add edges between nodes with the connections plugin — anchors, routing styles, and the SVG connection layer.
33
+ - [Group nodes](./pages/docs/build-features/groups-and-nesting.md): Create groups, assign children, capture nodes by dragging, and keep z-order correct.
34
+ - [History](./pages/docs/build-features/undo-and-redo.md): Record state changes and navigate them with the history plugin.
35
+ - [Selection and interaction](./pages/docs/build-features/selection-and-keyboard.md): Selection modes, box selection, and the interaction state machine.
36
+ - [First-party features and command guards](./pages/docs/build-features/read-only-and-command-guards.md): Install first-party packages and block commands with command guards.
37
+ - [Serialization](./pages/docs/build-features/save-and-load.md): Export and import boards with the engine's JSON Canvas document API.
38
+ - [Theming](./pages/docs/build-features/theming.md): Customize board appearance with CSS custom properties.
39
+ - [Performance](./pages/docs/build-features/performance.md): Viewport culling, level of detail, batching, and rendering habits for large boards.
40
+ - [SSR deterministic scene](./pages/docs/build-features/ssr-and-deterministic-state.md): Seed a board with initial nodes for server-side rendering and hydration.
41
+ - [Workflow renderer demo](./pages/docs/solutions/workflow-builder.md): Render step-style cards with custom renderers, connections, and undo/redo.
42
+ - [Mind map](./pages/docs/solutions/mind-map.md): Spatial topic hierarchy with connections, custom renderers, and branch-from-selection.
43
+ - [Planning board](./pages/docs/solutions/planning-board.md): A practical planning surface with notes, grouping, and zoom-to-fit.
44
+ - [Read-only viewer](./pages/docs/solutions/read-only-viewer.md): Display a board for viewing without allowing edits by using a command guard.
45
+ - [Nuxt auto-imports](./pages/docs/solutions/nuxt-application.md): Use board components and composables without manual imports via the Nuxt module.
46
+ - [Package overview](./pages/docs/reference/package-overview.md): The supported entrypoints and the capability each package owns.
47
+ - [@lupinum/board-core](./pages/docs/reference/board-core.md): The supported public API for the headless board engine.
48
+ - [@lupinum/board-core types](./pages/docs/reference/board-core-types.md): The public state, node, and JSON Canvas document types.
49
+ - [@lupinum/vue-board](./pages/docs/reference/vue-board.md): Vue 3 components for rendering interactive boards.
50
+ - [Vue composables](./pages/docs/reference/vue-composables.md): Reactive composables for accessing board state inside Vue components.
51
+ - [@lupinum/board-connections](./pages/docs/reference/connections.md): Edge and connection management plugin with routing, anchors, and an SVG connection layer.
52
+ - [@lupinum/board-history](./pages/docs/reference/history.md): Deterministic structural undo/redo with connection-aware state restoration.
53
+ - [@lupinum/vue-board/minimap](./pages/docs/reference/minimap.md): Minimap composable and component for board navigation.
54
+ - [@lupinum/nuxt-board](./pages/docs/reference/nuxt-board.md): Nuxt module with auto-imported board components and composables.
55
+ - [Events and subscriptions](./pages/docs/reference/events-and-errors.md): React to state changes with the event system and subscribables.
56
+ - [Glossary](./pages/docs/reference/glossary.md): Canonical definitions for Nuxt Board architecture and API terms.
57
+ - [Contributing](./pages/docs/project/contributing.md): Set up the repo, run the docs, and make changes that are ready to review.
58
+ - [Support and security](./pages/docs/project/support-and-security.md): Where to report bugs, request features, and disclose security issues.
59
+ - [Nuxt Board documentation](./pages/docs.md): Learn how to build domain-specific spatial tools with the command-driven Nuxt Board engine, renderer, and focused feature packages.
@@ -15,8 +15,339 @@ source: "ginko-content"
15
15
 
16
16
  Connections draw edges between nodes. Install the plugin, create edges, and the connection layer renders them as SVG paths with five routing styles.
17
17
 
18
- > Component omitted: `connections-board-demo`.
19
- > This page contains an interactive or site-specific block that has no agent markdown serializer yet.
18
+ ## Live example source
19
+
20
+ Use the installation guide to register @lupinum/nuxt-board. These are the actual documentation demo files. Keep their paths under app/. The module auto-imports Board components; install the optional packages named in imports. For the local content components, use components: [{ path: "~/components/content", pathPrefix: false }, "~/components"] in nuxt.config.ts, as this site does, or import them explicitly. createDemoDocument is a local helper, not a package export. DocsLab and the inspector components provide presentation only.
21
+
22
+ ### app/components/demos/ConnectionsBoardDemo.vue
23
+
24
+ ````vue
25
+ <script setup lang="ts">
26
+ import { computed, onMounted, ref } from 'vue'
27
+ import { asNodeId, createBoardEngine } from '@lupinum/board-core'
28
+ import { createDemoDocument } from '../../utils/demoDocument'
29
+ import {
30
+ connectionsPlugin,
31
+ type ConnectionRouting,
32
+ } from '@lupinum/board-connections'
33
+ import { BoardConnectionLayer } from '@lupinum/board-connections/vue'
34
+ import { historyPlugin } from '@lupinum/board-history'
35
+ import { BoardMinimap } from '@lupinum/vue-board/minimap'
36
+
37
+ const engine = createBoardEngine({
38
+ grid: { size: 20, majorEvery: 5, snap: true, pattern: 'dot' },
39
+ plugins: [historyPlugin(), connectionsPlugin()],
40
+ })
41
+
42
+ const historyState = computed(() => engine.plugins.history.getState())
43
+ const routing = ref<ConnectionRouting>('bezier')
44
+ const INPUT_ID = asNodeId('input')
45
+ const PARSE_ID = asNodeId('parse')
46
+ const SCORE_ID = asNodeId('score')
47
+ const OUTPUT_ID = asNodeId('output')
48
+ let shuffleStep = 0
49
+
50
+ function seed() {
51
+ engine.loadDocument(
52
+ createDemoDocument({
53
+ camera: { x: -80, y: -40, z: 1 },
54
+ grid: engine.getGridSettings(),
55
+ nodes: [
56
+ {
57
+ id: 'input',
58
+ type: 'text',
59
+ x: 80,
60
+ y: 150,
61
+ width: 180,
62
+ height: 96,
63
+ text: 'Collect input',
64
+ zIndex: 1,
65
+ locked: false,
66
+ visible: true,
67
+ },
68
+ {
69
+ id: 'parse',
70
+ type: 'text',
71
+ x: 340,
72
+ y: 80,
73
+ width: 200,
74
+ height: 96,
75
+ text: 'Normalize data',
76
+ zIndex: 2,
77
+ locked: false,
78
+ visible: true,
79
+ },
80
+ {
81
+ id: 'score',
82
+ type: 'text',
83
+ x: 340,
84
+ y: 240,
85
+ width: 200,
86
+ height: 96,
87
+ text: 'Score result',
88
+ zIndex: 3,
89
+ locked: false,
90
+ visible: true,
91
+ },
92
+ {
93
+ id: 'output',
94
+ type: 'text',
95
+ x: 650,
96
+ y: 150,
97
+ width: 180,
98
+ height: 96,
99
+ text: 'Publish output',
100
+ zIndex: 4,
101
+ locked: false,
102
+ visible: true,
103
+ },
104
+ ],
105
+ selection: [],
106
+ nextZIndex: 5,
107
+ }),
108
+ { mode: 'replace' },
109
+ )
110
+ const connections = engine.plugins.connections
111
+ for (const edge of connections.getEdges()) {
112
+ connections.deleteEdge(edge.id)
113
+ }
114
+ connections.createEdge({
115
+ from: INPUT_ID,
116
+ to: PARSE_ID,
117
+ label: 'clean',
118
+ data: {},
119
+ })
120
+ connections.createEdge({
121
+ from: INPUT_ID,
122
+ to: SCORE_ID,
123
+ label: 'rank',
124
+ data: {},
125
+ })
126
+ connections.createEdge({
127
+ from: PARSE_ID,
128
+ to: OUTPUT_ID,
129
+ label: 'emit',
130
+ data: {},
131
+ })
132
+ connections.createEdge({
133
+ from: SCORE_ID,
134
+ to: OUTPUT_ID,
135
+ label: 'merge',
136
+ data: {},
137
+ })
138
+ }
139
+
140
+ function shuffle() {
141
+ shuffleStep = (shuffleStep + 1) % 3
142
+ engine.updateNode(PARSE_ID, {
143
+ x: 320 + shuffleStep * 28,
144
+ y: 60 + shuffleStep * 22,
145
+ })
146
+ engine.updateNode(SCORE_ID, {
147
+ x: 360 - shuffleStep * 20,
148
+ y: 220 + shuffleStep * 18,
149
+ })
150
+ engine.updateNode(OUTPUT_ID, {
151
+ x: 620 + shuffleStep * 26,
152
+ y: 120 + shuffleStep * 24,
153
+ })
154
+ }
155
+
156
+ onMounted(async () => {
157
+ seed()
158
+ await engine.zoomToFit(84, false)
159
+ })
160
+ </script>
161
+
162
+ <template>
163
+ <div class="demo-frame">
164
+ <div class="demo-toolbar">
165
+ <button class="demo-danger" @click="seed">Reset</button>
166
+ <button @click="shuffle">Shuffle</button>
167
+ <span class="demo-toggle-group">
168
+ <button
169
+ :class="{ active: routing === 'bezier' }"
170
+ @click="routing = 'bezier'"
171
+ >
172
+ Bezier
173
+ </button>
174
+ <button
175
+ :class="{ active: routing === 'smooth-step' }"
176
+ @click="routing = 'smooth-step'"
177
+ >
178
+ Smooth
179
+ </button>
180
+ <button
181
+ :class="{ active: routing === 'step' }"
182
+ @click="routing = 'step'"
183
+ >
184
+ Step
185
+ </button>
186
+ <button
187
+ :class="{ active: routing === 'straight' }"
188
+ @click="routing = 'straight'"
189
+ >
190
+ Straight
191
+ </button>
192
+ </span>
193
+ <button
194
+ :disabled="!engine.plugins.history.canUndo()"
195
+ @click="engine.plugins.history.undo()"
196
+ >
197
+ Undo
198
+ </button>
199
+ <button
200
+ :disabled="!engine.plugins.history.canRedo()"
201
+ @click="engine.plugins.history.redo()"
202
+ >
203
+ Redo
204
+ </button>
205
+ <span class="demo-history-badge ml-auto"
206
+ >{{ historyState.undoDepth }} undo /
207
+ {{ historyState.redoDepth }} redo</span
208
+ >
209
+ </div>
210
+
211
+ <div class="relative">
212
+ <BoardRoot :engine="engine" style="height: 360px">
213
+ <BoardConnectionLayer :routing="routing" />
214
+ </BoardRoot>
215
+ <div
216
+ class="absolute right-4 bottom-4 rounded-md border border-default bg-elevated/90 p-2 shadow-lg backdrop-blur"
217
+ >
218
+ <BoardMinimap :engine="engine" :width="180" :height="110" />
219
+ </div>
220
+ </div>
221
+ </div>
222
+ </template>
223
+ ````
224
+
225
+ ### app/utils/demoDocument.ts
226
+
227
+ ````ts
228
+ import type {
229
+ BoardNode,
230
+ BoardNodeMetadata,
231
+ Camera,
232
+ GridSettings,
233
+ JsonCanvasDocument,
234
+ JsonCanvasNode,
235
+ NodeId,
236
+ } from '@lupinum/board-core'
237
+
238
+ type DemoNode = Omit<
239
+ Pick<
240
+ BoardNode,
241
+ | 'id'
242
+ | 'type'
243
+ | 'x'
244
+ | 'y'
245
+ | 'width'
246
+ | 'height'
247
+ | 'color'
248
+ | 'text'
249
+ | 'file'
250
+ | 'subpath'
251
+ | 'url'
252
+ | 'label'
253
+ | 'background'
254
+ | 'backgroundStyle'
255
+ | 'zIndex'
256
+ | 'locked'
257
+ | 'visible'
258
+ | 'parentId'
259
+ >,
260
+ 'id' | 'parentId'
261
+ > & {
262
+ id: NodeId | string
263
+ parentId?: NodeId | string
264
+ }
265
+
266
+ export interface DemoDocumentInput {
267
+ nodes: readonly DemoNode[]
268
+ camera?: Camera
269
+ grid?: GridSettings
270
+ selection?: readonly (NodeId | string)[]
271
+ nextZIndex?: number
272
+ }
273
+
274
+ function toJsonCanvasNode(node: DemoNode): JsonCanvasNode {
275
+ const base = {
276
+ id: node.id as NodeId,
277
+ type: node.type,
278
+ x: node.x,
279
+ y: node.y,
280
+ width: node.width,
281
+ height: node.height,
282
+ ...(node.color ? { color: node.color } : {}),
283
+ }
284
+
285
+ switch (node.type) {
286
+ case 'file':
287
+ return {
288
+ ...base,
289
+ type: 'file',
290
+ file: node.file ?? '',
291
+ ...(node.subpath ? { subpath: node.subpath } : {}),
292
+ }
293
+ case 'link':
294
+ return {
295
+ ...base,
296
+ type: 'link',
297
+ url: node.url ?? '',
298
+ }
299
+ case 'group':
300
+ return {
301
+ ...base,
302
+ type: 'group',
303
+ ...((node.label ?? node.text)
304
+ ? { label: node.label ?? node.text }
305
+ : {}),
306
+ ...(node.background ? { background: node.background } : {}),
307
+ ...(node.backgroundStyle
308
+ ? { backgroundStyle: node.backgroundStyle }
309
+ : {}),
310
+ }
311
+ case 'text':
312
+ default:
313
+ return {
314
+ ...base,
315
+ type: 'text',
316
+ text: node.text ?? '',
317
+ }
318
+ }
319
+ }
320
+
321
+ function toNodeMetadata(node: DemoNode): BoardNodeMetadata {
322
+ return {
323
+ zIndex: node.zIndex,
324
+ locked: node.locked,
325
+ visible: node.visible,
326
+ ...(node.parentId ? { parentId: node.parentId as NodeId } : {}),
327
+ }
328
+ }
329
+
330
+ export function createDemoDocument(
331
+ input: DemoDocumentInput,
332
+ ): JsonCanvasDocument {
333
+ return {
334
+ nodes: input.nodes.map(toJsonCanvasNode),
335
+ 'x-lupinum-board': {
336
+ ...(input.camera ? { camera: input.camera } : {}),
337
+ ...(input.grid ? { grid: input.grid } : {}),
338
+ ...(input.selection
339
+ ? { selection: input.selection.map((id) => id as NodeId) }
340
+ : {}),
341
+ nextZIndex:
342
+ input.nextZIndex ??
343
+ input.nodes.reduce((max, node) => Math.max(max, node.zIndex), 0) + 1,
344
+ nodes: Object.fromEntries(
345
+ input.nodes.map((node) => [node.id, toNodeMetadata(node)]),
346
+ ),
347
+ },
348
+ }
349
+ }
350
+ ````
20
351
 
21
352
  ## Setup
22
353