@lupinum/board-core 1.0.0-beta.4 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/AGENTS.md +1 -1
- package/dist/agent/manifest.json +19 -19
- package/dist/agent/pages/docs/build-features/connections.md +333 -2
- package/dist/agent/pages/docs/build-features/custom-node-renderers.md +366 -2
- package/dist/agent/pages/docs/build-features/read-only-and-command-guards.md +278 -2
- package/dist/agent/pages/docs/build-features/save-and-load.md +264 -2
- package/dist/agent/pages/docs/build-features/selection-and-keyboard.md +257 -2
- package/dist/agent/pages/docs/build-features/theming.md +285 -2
- package/dist/agent/pages/docs/evaluate/how-nuxt-board-works.md +451 -2
- package/dist/agent/pages/docs/reference/events-and-errors.md +279 -2
- package/dist/agent/pages/docs/solutions/mind-map.md +448 -2
- package/dist/agent/pages/docs/solutions/nuxt-application.md +214 -2
- package/dist/agent/pages/docs/solutions/planning-board.md +281 -2
- package/dist/agent/pages/docs/solutions/read-only-viewer.md +278 -2
- package/dist/agent/pages/docs/solutions/workflow-builder.md +435 -2
- package/dist/agent/pages/docs/start-building/customize-your-first-node.md +381 -2
- package/dist/agent/pages/docs/understand-the-system/commands-and-transactions.md +456 -2
- package/dist/agent/pages/docs/understand-the-system/document-and-session-state.md +348 -2
- package/dist/agent/pages/docs/understand-the-system/persistence-and-json-canvas.md +445 -2
- package/package.json +1 -1
package/dist/agent/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @lupinum/board-core
|
|
2
2
|
|
|
3
|
-
Documentation for installed version 1.0.0-beta.
|
|
3
|
+
Documentation for installed version 1.0.0-beta.5.
|
|
4
4
|
|
|
5
5
|
Read the relevant local pages before changing this package’s integration.
|
|
6
6
|
Project instructions govern architecture, style and permissions.
|
package/dist/agent/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"name": "@lupinum/board-core",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
5
|
-
"entrySha256": "
|
|
4
|
+
"version": "1.0.0-beta.5",
|
|
5
|
+
"entrySha256": "5185db47994ec97fb0513b0deaf03500d6718650b29fd1fdec62828a5041ffaf",
|
|
6
6
|
"startRoutes": [
|
|
7
7
|
"/docs/start-building/installation",
|
|
8
8
|
"/docs/reference/board-core"
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
"route": "/docs/build-features/connections",
|
|
21
21
|
"url": "https://nuxt-board.lupinum.com/docs/build-features/connections",
|
|
22
22
|
"file": "pages/docs/build-features/connections.md",
|
|
23
|
-
"sha256": "
|
|
23
|
+
"sha256": "48dd614db7ff89a12b77229a3a2cc99105ea93dc22d51ec1f0afe4091f56915c"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"title": "Custom renderers",
|
|
27
27
|
"route": "/docs/build-features/custom-node-renderers",
|
|
28
28
|
"url": "https://nuxt-board.lupinum.com/docs/build-features/custom-node-renderers",
|
|
29
29
|
"file": "pages/docs/build-features/custom-node-renderers.md",
|
|
30
|
-
"sha256": "
|
|
30
|
+
"sha256": "1f230989f310cfb34f81c3e70fbf9f791088a39ebd9d64a662fca5765c6bbfbd"
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"title": "Group nodes",
|
|
@@ -48,21 +48,21 @@
|
|
|
48
48
|
"route": "/docs/build-features/read-only-and-command-guards",
|
|
49
49
|
"url": "https://nuxt-board.lupinum.com/docs/build-features/read-only-and-command-guards",
|
|
50
50
|
"file": "pages/docs/build-features/read-only-and-command-guards.md",
|
|
51
|
-
"sha256": "
|
|
51
|
+
"sha256": "31f7cbeeab4d9834a038fe5772f77bdb78f09ba61df24509adb0340543b7f32e"
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
"title": "Serialization",
|
|
55
55
|
"route": "/docs/build-features/save-and-load",
|
|
56
56
|
"url": "https://nuxt-board.lupinum.com/docs/build-features/save-and-load",
|
|
57
57
|
"file": "pages/docs/build-features/save-and-load.md",
|
|
58
|
-
"sha256": "
|
|
58
|
+
"sha256": "bebe29b5302c26dafd4222feff870253104ec5bb646bcfb35507a30776e3d23b"
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
"title": "Selection and interaction",
|
|
62
62
|
"route": "/docs/build-features/selection-and-keyboard",
|
|
63
63
|
"url": "https://nuxt-board.lupinum.com/docs/build-features/selection-and-keyboard",
|
|
64
64
|
"file": "pages/docs/build-features/selection-and-keyboard.md",
|
|
65
|
-
"sha256": "
|
|
65
|
+
"sha256": "6febe652e964ac50418c48d87f8756ebc6a79e24bf7047278799c97593678700"
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
"title": "SSR deterministic scene",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"route": "/docs/build-features/theming",
|
|
77
77
|
"url": "https://nuxt-board.lupinum.com/docs/build-features/theming",
|
|
78
78
|
"file": "pages/docs/build-features/theming.md",
|
|
79
|
-
"sha256": "
|
|
79
|
+
"sha256": "3d3dc7021358becae705b668a6ac4b077686de0c14497815337c2827d576f41d"
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
82
|
"title": "History",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"route": "/docs/evaluate/how-nuxt-board-works",
|
|
98
98
|
"url": "https://nuxt-board.lupinum.com/docs/evaluate/how-nuxt-board-works",
|
|
99
99
|
"file": "pages/docs/evaluate/how-nuxt-board-works.md",
|
|
100
|
-
"sha256": "
|
|
100
|
+
"sha256": "ec28824f2269725d759580836fb8c55f090f0a703a6c7e99145b9cb38519dbb2"
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
"title": "Why Nuxt Board",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"route": "/docs/reference/events-and-errors",
|
|
147
147
|
"url": "https://nuxt-board.lupinum.com/docs/reference/events-and-errors",
|
|
148
148
|
"file": "pages/docs/reference/events-and-errors.md",
|
|
149
|
-
"sha256": "
|
|
149
|
+
"sha256": "8531df0f5cba6b886be4f66c5eafd6905026e8946ad7725c917084d39a210bec"
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
152
|
"title": "Glossary",
|
|
@@ -202,35 +202,35 @@
|
|
|
202
202
|
"route": "/docs/solutions/mind-map",
|
|
203
203
|
"url": "https://nuxt-board.lupinum.com/docs/solutions/mind-map",
|
|
204
204
|
"file": "pages/docs/solutions/mind-map.md",
|
|
205
|
-
"sha256": "
|
|
205
|
+
"sha256": "88e352aac5be758307ec846519ec015b39d7208e5c6bdd91fee552e8e37585f3"
|
|
206
206
|
},
|
|
207
207
|
{
|
|
208
208
|
"title": "Nuxt auto-imports",
|
|
209
209
|
"route": "/docs/solutions/nuxt-application",
|
|
210
210
|
"url": "https://nuxt-board.lupinum.com/docs/solutions/nuxt-application",
|
|
211
211
|
"file": "pages/docs/solutions/nuxt-application.md",
|
|
212
|
-
"sha256": "
|
|
212
|
+
"sha256": "526f7b4dfb7091d4974648e27b2690dee4d8ee88be4361e9d0ad6c5985e0a396"
|
|
213
213
|
},
|
|
214
214
|
{
|
|
215
215
|
"title": "Planning board",
|
|
216
216
|
"route": "/docs/solutions/planning-board",
|
|
217
217
|
"url": "https://nuxt-board.lupinum.com/docs/solutions/planning-board",
|
|
218
218
|
"file": "pages/docs/solutions/planning-board.md",
|
|
219
|
-
"sha256": "
|
|
219
|
+
"sha256": "7902e573b4172a5ea80a06ef4cfc9c4a9dac4e0dedaf7de2e761d258c23e770d"
|
|
220
220
|
},
|
|
221
221
|
{
|
|
222
222
|
"title": "Read-only viewer",
|
|
223
223
|
"route": "/docs/solutions/read-only-viewer",
|
|
224
224
|
"url": "https://nuxt-board.lupinum.com/docs/solutions/read-only-viewer",
|
|
225
225
|
"file": "pages/docs/solutions/read-only-viewer.md",
|
|
226
|
-
"sha256": "
|
|
226
|
+
"sha256": "570130be6620eeae29b4ee1ae1cbae0f8928dac86cd125704f27c0d87a98be5d"
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
229
|
"title": "Workflow renderer demo",
|
|
230
230
|
"route": "/docs/solutions/workflow-builder",
|
|
231
231
|
"url": "https://nuxt-board.lupinum.com/docs/solutions/workflow-builder",
|
|
232
232
|
"file": "pages/docs/solutions/workflow-builder.md",
|
|
233
|
-
"sha256": "
|
|
233
|
+
"sha256": "ef87574808dbf8b3b1b48b0b17aaa31f6ef1e5017661c9c467980d9faf6f2267"
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
236
|
"title": "Add connections and history",
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
"route": "/docs/start-building/customize-your-first-node",
|
|
245
245
|
"url": "https://nuxt-board.lupinum.com/docs/start-building/customize-your-first-node",
|
|
246
246
|
"file": "pages/docs/start-building/customize-your-first-node.md",
|
|
247
|
-
"sha256": "
|
|
247
|
+
"sha256": "3afc862f1ed6062906e19b259c2b13e6ee1590ea4358315b60660387fbb48749"
|
|
248
248
|
},
|
|
249
249
|
{
|
|
250
250
|
"title": "Installation",
|
|
@@ -272,14 +272,14 @@
|
|
|
272
272
|
"route": "/docs/understand-the-system/commands-and-transactions",
|
|
273
273
|
"url": "https://nuxt-board.lupinum.com/docs/understand-the-system/commands-and-transactions",
|
|
274
274
|
"file": "pages/docs/understand-the-system/commands-and-transactions.md",
|
|
275
|
-
"sha256": "
|
|
275
|
+
"sha256": "941a852cbb3e978e953b7b82287e77f71e3ea5ae85be87a5b9abce65b92bcef8"
|
|
276
276
|
},
|
|
277
277
|
{
|
|
278
278
|
"title": "Document and session state",
|
|
279
279
|
"route": "/docs/understand-the-system/document-and-session-state",
|
|
280
280
|
"url": "https://nuxt-board.lupinum.com/docs/understand-the-system/document-and-session-state",
|
|
281
281
|
"file": "pages/docs/understand-the-system/document-and-session-state.md",
|
|
282
|
-
"sha256": "
|
|
282
|
+
"sha256": "990c17cf7c2b02921f23f55575a715c160028e57190ac1895dfd18407f1d7a44"
|
|
283
283
|
},
|
|
284
284
|
{
|
|
285
285
|
"title": "Nodes and hierarchy",
|
|
@@ -300,7 +300,7 @@
|
|
|
300
300
|
"route": "/docs/understand-the-system/persistence-and-json-canvas",
|
|
301
301
|
"url": "https://nuxt-board.lupinum.com/docs/understand-the-system/persistence-and-json-canvas",
|
|
302
302
|
"file": "pages/docs/understand-the-system/persistence-and-json-canvas.md",
|
|
303
|
-
"sha256": "
|
|
303
|
+
"sha256": "968534fdf9672ee920a6006f3ac3d2b1ca05907f54e3ec9ce47fd59d6f8d628f"
|
|
304
304
|
},
|
|
305
305
|
{
|
|
306
306
|
"title": "Rendering and interaction",
|
|
@@ -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
|
-
|
|
19
|
-
|
|
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
|
|