@lupinum/board-core 1.0.0-beta.2 → 1.0.0-beta.4

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 (51) hide show
  1. package/README.md +24 -0
  2. package/dist/agent/AGENTS.md +63 -0
  3. package/dist/agent/manifest.json +320 -0
  4. package/dist/agent/pages/docs/build-features/connections.md +241 -0
  5. package/dist/agent/pages/docs/build-features/custom-node-renderers.md +219 -0
  6. package/dist/agent/pages/docs/build-features/groups-and-nesting.md +172 -0
  7. package/dist/agent/pages/docs/build-features/performance.md +76 -0
  8. package/dist/agent/pages/docs/build-features/read-only-and-command-guards.md +52 -0
  9. package/dist/agent/pages/docs/build-features/save-and-load.md +142 -0
  10. package/dist/agent/pages/docs/build-features/selection-and-keyboard.md +145 -0
  11. package/dist/agent/pages/docs/build-features/ssr-and-deterministic-state.md +67 -0
  12. package/dist/agent/pages/docs/build-features/theming.md +102 -0
  13. package/dist/agent/pages/docs/build-features/undo-and-redo.md +124 -0
  14. package/dist/agent/pages/docs/evaluate/design-decisions.md +44 -0
  15. package/dist/agent/pages/docs/evaluate/how-nuxt-board-works.md +41 -0
  16. package/dist/agent/pages/docs/evaluate/why-nuxt-board.md +61 -0
  17. package/dist/agent/pages/docs/project/contributing.md +101 -0
  18. package/dist/agent/pages/docs/project/support-and-security.md +40 -0
  19. package/dist/agent/pages/docs/reference/board-core-types.md +82 -0
  20. package/dist/agent/pages/docs/reference/board-core.md +261 -0
  21. package/dist/agent/pages/docs/reference/connections.md +531 -0
  22. package/dist/agent/pages/docs/reference/events-and-errors.md +158 -0
  23. package/dist/agent/pages/docs/reference/glossary.md +58 -0
  24. package/dist/agent/pages/docs/reference/history.md +193 -0
  25. package/dist/agent/pages/docs/reference/minimap.md +157 -0
  26. package/dist/agent/pages/docs/reference/nuxt-board.md +148 -0
  27. package/dist/agent/pages/docs/reference/package-overview.md +58 -0
  28. package/dist/agent/pages/docs/reference/vue-board.md +424 -0
  29. package/dist/agent/pages/docs/reference/vue-composables.md +293 -0
  30. package/dist/agent/pages/docs/solutions/mind-map.md +104 -0
  31. package/dist/agent/pages/docs/solutions/nuxt-application.md +47 -0
  32. package/dist/agent/pages/docs/solutions/planning-board.md +51 -0
  33. package/dist/agent/pages/docs/solutions/read-only-viewer.md +61 -0
  34. package/dist/agent/pages/docs/solutions/workflow-builder.md +124 -0
  35. package/dist/agent/pages/docs/start-building/add-connections-and-history.md +42 -0
  36. package/dist/agent/pages/docs/start-building/customize-your-first-node.md +38 -0
  37. package/dist/agent/pages/docs/start-building/installation.md +76 -0
  38. package/dist/agent/pages/docs/start-building/your-first-board.md +52 -0
  39. package/dist/agent/pages/docs/understand-the-system/camera-and-coordinates.md +22 -0
  40. package/dist/agent/pages/docs/understand-the-system/commands-and-transactions.md +31 -0
  41. package/dist/agent/pages/docs/understand-the-system/document-and-session-state.md +25 -0
  42. package/dist/agent/pages/docs/understand-the-system/nodes-and-hierarchy.md +24 -0
  43. package/dist/agent/pages/docs/understand-the-system/packages-and-plugins.md +29 -0
  44. package/dist/agent/pages/docs/understand-the-system/persistence-and-json-canvas.md +25 -0
  45. package/dist/agent/pages/docs/understand-the-system/rendering-and-interaction.md +22 -0
  46. package/dist/agent/pages/docs/understand-the-system/the-engine.md +28 -0
  47. package/dist/agent/pages/docs.md +18 -0
  48. package/dist/engine/transaction.d.ts +2 -2
  49. package/dist/index.js +18 -7
  50. package/dist/types.d.ts +2 -2
  51. package/package.json +3 -2
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: "Support and security"
3
+ description: "Where to report bugs, request features, and disclose security issues."
4
+ url: "https://nuxt-board.lupinum.com/docs/project/support-and-security"
5
+ route: "/docs/project/support-and-security"
6
+ locale: "en"
7
+ section: "Documentation"
8
+ collection: "docs"
9
+ source: "ginko-content"
10
+ ---
11
+
12
+ # Support and security
13
+
14
+ > Where to report bugs, request features, and disclose security issues.
15
+
16
+ Use GitHub issues for bugs and feature requests. Include a reproduction when the issue involves interaction, rendering, serialization, or Nuxt integration.
17
+
18
+ ## Bug reports
19
+
20
+ A useful bug report includes:
21
+
22
+ - package versions
23
+ - browser and operating system when UI behavior is involved
24
+ - a small reproduction or failing test
25
+ - expected behavior
26
+ - actual behavior
27
+ - screenshots or video for visual regressions
28
+
29
+ ## Feature requests
30
+
31
+ Describe the product workflow first. API proposals are welcome, but the use case matters more than the first shape of the API.
32
+
33
+ ## Security reports
34
+
35
+ Use GitHub private vulnerability reporting. If that channel is not available,
36
+ email `info@lupinum.com`. Do not open a public issue with exploit details.
37
+
38
+ Include the affected package, the suspected impact, and reproduction steps if you can share them safely.
39
+
40
+ The root [`SECURITY.md`](https://github.com/lupinum-dev/nuxt-board/blob/main/SECURITY.md) is the source of truth for the current reporting policy.
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: "@lupinum/board-core types"
3
+ description: "The public state, node, and JSON Canvas document types."
4
+ url: "https://nuxt-board.lupinum.com/docs/reference/board-core-types"
5
+ route: "/docs/reference/board-core-types"
6
+ locale: "en"
7
+ section: "Documentation"
8
+ collection: "docs"
9
+ source: "ginko-content"
10
+ ---
11
+
12
+ # @lupinum/board-core types
13
+
14
+ > The public state, node, and JSON Canvas document types.
15
+
16
+ ## Persisted documents
17
+
18
+ Persisted board data uses `JsonCanvasDocument`.
19
+
20
+ ```ts
21
+ interface JsonCanvasDocument {
22
+ readonly nodes: readonly JsonCanvasNode[]
23
+ readonly edges?: readonly JsonCanvasEdge[]
24
+ readonly 'x-lupinum-board'?: BoardDocumentMetadata
25
+ }
26
+ ```
27
+
28
+ Core owns node persistence and board metadata. The connections package owns edge
29
+ persistence. Runtime snapshot fields such as `camera`, `grid`, and `selection`
30
+ are not accepted as top-level persisted document fields.
31
+
32
+ ## Runtime state
33
+
34
+ `BoardState` is the immutable runtime view used by renderers and UI reads.
35
+
36
+ ```ts
37
+ interface BoardState {
38
+ readonly camera: Camera
39
+ readonly grid: GridSettings
40
+ readonly nodes: ReadonlyMap<NodeId, BoardNode>
41
+ readonly selection: ReadonlySet<NodeId>
42
+ readonly interaction: InteractionState
43
+ readonly snapGuides: readonly SnapGuide[]
44
+ }
45
+ ```
46
+
47
+ Read it with `engine.getState()`. Use `engine.exportDocument()` and
48
+ `engine.loadDocument()` for persistence; runtime state is not a persistence
49
+ payload.
50
+
51
+ ## BoardNode
52
+
53
+ ```ts
54
+ interface BoardNodeBase {
55
+ readonly id: NodeId
56
+ readonly x: number
57
+ readonly y: number
58
+ readonly width: number
59
+ readonly height: number
60
+ readonly color?: CanvasColor
61
+ readonly zIndex: number
62
+ readonly locked: boolean
63
+ readonly visible: boolean
64
+ readonly parentId?: NodeId
65
+ }
66
+
67
+ type BoardNode =
68
+ | (BoardNodeBase & { type: 'text'; text: string })
69
+ | (BoardNodeBase & { type: 'file'; file: string; subpath?: string })
70
+ | (BoardNodeBase & { type: 'link'; url: string })
71
+ | (BoardNodeBase & {
72
+ type: 'group'
73
+ label?: string
74
+ background?: string
75
+ backgroundStyle?: 'cover' | 'ratio' | 'repeat'
76
+ })
77
+ ```
78
+
79
+ There is no `data` property on public nodes. `BoardNode` is discriminated by
80
+ `type`, so narrowing guarantees the corresponding JSON Canvas content field.
81
+ `NodeInput` defaults to a text node; file and link inputs require `file` and
82
+ `url` respectively.
@@ -0,0 +1,261 @@
1
+ ---
2
+ title: "@lupinum/board-core"
3
+ description: "The supported public API for the headless board engine."
4
+ url: "https://nuxt-board.lupinum.com/docs/reference/board-core"
5
+ route: "/docs/reference/board-core"
6
+ locale: "en"
7
+ section: "Documentation"
8
+ collection: "docs"
9
+ source: "ginko-content"
10
+ ---
11
+
12
+ # @lupinum/board-core
13
+
14
+ > The supported public API for the headless board engine.
15
+
16
+ `@lupinum/board-core` exports the engine factory, public board types, JSON Canvas
17
+ document types, color helpers, and selection helpers.
18
+
19
+ It does not expose transaction roots, plugin persistence hooks, or history
20
+ internals as stable consumer API.
21
+
22
+ The package also publishes `@lupinum/board-core/internal` so first-party
23
+ packages such as `@lupinum/board-history` and `@lupinum/board-connections` can
24
+ compose with the core engine after they are installed from npm. That subpath is
25
+ the first-party feature ABI, not an application plugin API; app code should use
26
+ the top-level `@lupinum/board-core` entrypoint and install supported features
27
+ through `plugins`.
28
+
29
+ ## createBoardEngine
30
+
31
+ ```ts
32
+ import { createBoardEngine } from '@lupinum/board-core'
33
+
34
+ const engine = createBoardEngine({
35
+ grid: { size: 24, snap: true },
36
+ onUnhandledError(error, context) {
37
+ reportError(error, context)
38
+ },
39
+ })
40
+ ```
41
+
42
+ Listener, reactive subscriber, and finalized plugin commit-effect failures are
43
+ reported through `onUnhandledError` after a commit; they cannot roll committed
44
+ state back. Inspect `context.source` to distinguish `event-listener`,
45
+ `subscriber`, and `commit-effect` failures. Without a hook, the engine falls
46
+ back to `console.error`.
47
+
48
+ Install first-party packages with `plugins`.
49
+
50
+ ```ts
51
+ const engine = createBoardEngine({
52
+ plugins: [historyPlugin(), connectionsPlugin()],
53
+ })
54
+ ```
55
+
56
+ Plugin names must be unique. Construction throws `BoardConflictError` before
57
+ any plugin installs when the tuple contains a duplicate name.
58
+
59
+ ## Nodes
60
+
61
+ Nodes use JSON Canvas fields directly.
62
+
63
+ ```ts
64
+ engine.createNode({
65
+ type: 'text',
66
+ x: 120,
67
+ y: 80,
68
+ width: 240,
69
+ height: 120,
70
+ text: 'Release plan',
71
+ })
72
+ ```
73
+
74
+ Supported node fields are `text`, `file`, `subpath`, `url`, `label`,
75
+ `background`, and `backgroundStyle`. There is no legacy data compatibility layer.
76
+
77
+ ## Persistence
78
+
79
+ Use `exportDocument()` and `loadDocument()` for persisted documents.
80
+
81
+ ```ts
82
+ const document = engine.exportDocument()
83
+ engine.loadDocument(document, { mode: 'replace' })
84
+ ```
85
+
86
+ Core persists nodes and board metadata. Edges belong to
87
+ `@lupinum/board-connections`; importing a document with edges without that
88
+ connections package installed fails instead of dropping edge data.
89
+
90
+ ## Engine reference
91
+
92
+ The engine is the public mutation boundary. App code should use these methods
93
+ instead of editing node maps, selection sets, or camera objects directly.
94
+
95
+ ### State and lifecycle
96
+
97
+ | API | Purpose |
98
+ | --- | --- |
99
+ | `engine.plugins` | Feature APIs installed through `plugins`. |
100
+ | `engine.$camera` | Subscribable camera state. |
101
+ | `engine.$nodes` | Subscribable read-only map of nodes. |
102
+ | `engine.$selection` | Subscribable read-only set of selected node IDs. |
103
+ | `engine.$interaction` | Subscribable current pointer/editing interaction state. |
104
+ | `engine.$snapGuides` | Subscribable active snap guides. |
105
+ | `destroy()` | Tear down engine subscriptions and resources. |
106
+ | `batch(fn)` | Run multiple commands while deferring subscribable notifications. |
107
+ | `getState()` | Read the current board state. |
108
+ | `getGridSettings()` | Read resolved grid settings. |
109
+ | `updateGridSettings(patch)` | Update grid settings and return the resolved settings. |
110
+ | `getViewportSize()` | Read the last viewport size reported by the renderer. |
111
+ | `setViewportSize(size)` | Update viewport size. Renderers call this from resize observation. |
112
+ | `exportTrace()` | Read command trace entries. |
113
+ | `addCommandGuard(fn)` | Register a synchronous command guard for concrete product policy. |
114
+
115
+ ### Events
116
+
117
+ ```ts
118
+ const unsubscribe = engine.on('node:created', (node) => {
119
+ console.log(node.id)
120
+ })
121
+
122
+ engine.once('destroy', () => {
123
+ console.log('engine destroyed')
124
+ })
125
+
126
+ engine.off('node:created', handler)
127
+ unsubscribe()
128
+ ```
129
+
130
+ See [events and subscriptions](/raw/docs/reference/events-and-errors.md) for the full
131
+ event catalog and payloads.
132
+
133
+ ### Coordinate and camera methods
134
+
135
+ | API | Purpose |
136
+ | --- | --- |
137
+ | `screenToWorld(point)` | Convert a screen-space point to world coordinates. |
138
+ | `worldToScreen(point)` | Convert a world-space point to screen coordinates. |
139
+ | `getVisibleBounds(width, height)` | Compute visible world bounds for a viewport size. |
140
+ | `panBy(dx, dy)` | Move the camera by a world-space delta. |
141
+ | `panTo(worldPoint, animated?)` | Pan to a world point, optionally animated. |
142
+ | `zoomAt(screenPoint, delta)` | Zoom around a screen-space point. |
143
+ | `zoomTo(level, animated?)` | Zoom to an absolute level, clamped by zoom settings. |
144
+ | `zoomToFit(padding?, animated?)` | Fit all visible nodes into the viewport. |
145
+ | `zoomToNodes(ids, padding?, animated?)` | Fit specific nodes into the viewport. |
146
+
147
+ ### Node methods
148
+
149
+ | API | Purpose |
150
+ | --- | --- |
151
+ | `getNode(id)` | Return a node or throw if it does not exist. |
152
+ | `findNode(id)` | Return a node or `null`. |
153
+ | `hasNode(id)` | Check whether a node exists. |
154
+ | `getNodeAt(worldPoint)` | Return the topmost visible node at a world point. |
155
+ | `getNodesInBounds(bounds)` | Return visible nodes intersecting the bounds. |
156
+ | `createNode(input)` | Create a node and select it unless `select: false` is passed. |
157
+ | `updateNode(id, patch)` | Update node fields. |
158
+ | `deleteNode(id)` | Delete a node. Deleting a group also deletes descendants. |
159
+ | `moveNode(id, dx, dy)` | Move one node by a world-space delta. |
160
+ | `translateSelectedNodes(dx, dy)` | Move the current selection, respecting group hierarchy. |
161
+ | `resizeNode(id, handle, dx, dy)` | Resize one node from a compass handle. |
162
+ | `bringToFront(id)` | Move a node above other nodes. |
163
+ | `sendToBack(id)` | Move a node behind other nodes. |
164
+ | `lockNode(id)` | Prevent interactive move, resize, and delete. |
165
+ | `unlockNode(id)` | Re-enable interactive changes. |
166
+ | `duplicateNodes(ids, offset?)` | Duplicate nodes and preserve supported hierarchy between copies. |
167
+
168
+ ### Selection and clipboard methods
169
+
170
+ | API | Purpose |
171
+ | --- | --- |
172
+ | `select(ids, mode?)` | Replace, add, remove, or toggle selected node IDs. |
173
+ | `selectAll()` | Select all visible nodes. |
174
+ | `clearSelection()` | Clear the selection. |
175
+ | `deleteSelected()` | Delete unlocked selected nodes and group descendants. |
176
+ | `getSelection()` | Return selected node IDs as an array. |
177
+ | `copySelected()` | Copy selected nodes into the engine clipboard. |
178
+ | `pasteClipboard(offset?)` | Paste nodes from the engine clipboard. |
179
+
180
+ The engine clipboard is internal to the engine. It does not read from or write
181
+ to the system clipboard.
182
+
183
+ ### Text editing and document methods
184
+
185
+ Pointer interactions are intentionally framework-internal. Text editing remains
186
+ public so custom renderers can provide their own editors.
187
+
188
+ | API | Purpose |
189
+ | --- | --- |
190
+ | `beginTextEdit(id)` | Enter text-editing mode for a text node. |
191
+ | `commitTextEdit(id, text?)` | Commit text editing and update the text node. |
192
+ | `cancelTextEdit()` | Leave text editing without changing content. |
193
+ | `exportDocument()` | Return a typed JSON Canvas document. |
194
+ | `loadDocument(document, options?)` | Validate and atomically load with `replace` or `merge`. |
195
+
196
+ ## Public helpers
197
+
198
+ The public helpers are the helpers consumers need to build boards:
199
+
200
+ - color helpers such as `BOARD_COLOR_PRESETS`, `colorForPreset`, and
201
+ `isBoardColorPreset`
202
+ - id helpers such as `asNodeId` and `asEdgeId`
203
+ - selection helpers such as `getSelectionNodes`, `getSelectionBounds`, and
204
+ `toggleIds`
205
+ - geometry helpers used by renderers and overlays
206
+
207
+ ## Math helpers
208
+
209
+ - These utility functions are exported from `@lupinum/board-core`. They are pure functions and can be used outside the engine for custom calculations.
210
+
211
+ The engine also exposes instance methods such as `engine.screenToWorld()` and `engine.worldToScreen()` when the calculation depends on the current board camera.
212
+
213
+ ## General math
214
+
215
+ ### clamp
216
+
217
+ Constrains a value to a range.
218
+
219
+ ```ts
220
+ clamp(value: number, min: number, max: number): number
221
+ ```
222
+
223
+ ```ts
224
+ clamp(15, 0, 10) // 10
225
+ clamp(-5, 0, 10) // 0
226
+ ```
227
+
228
+ ## Bounds logic
229
+
230
+ ### boundsIntersect
231
+
232
+ Returns `true` if two bounds overlap.
233
+
234
+ ```ts
235
+ boundsIntersect(a: Bounds, b: Bounds): boolean
236
+ ```
237
+
238
+ ### getBoundsFromPoints
239
+
240
+ Creates a `Bounds` from two arbitrary points. Minimum and maximum corners are computed automatically.
241
+
242
+ ```ts
243
+ getBoundsFromPoints(a: Point, b: Point): Bounds
244
+ ```
245
+
246
+ ```ts
247
+ const bounds = getBoundsFromPoints({ x: 10, y: 20 }, { x: 50, y: 5 })
248
+ // { minX: 10, minY: 5, maxX: 50, maxY: 20 }
249
+ ```
250
+
251
+ ### getVisibleBounds
252
+
253
+ Returns the world-space bounds visible within a viewport for the given camera.
254
+
255
+ ```ts
256
+ getVisibleBounds(width: number, height: number, camera: Camera): Bounds
257
+ ```
258
+
259
+ ```ts
260
+ const bounds = getVisibleBounds(1280, 720, camera)
261
+ ```