@neta-art/cohub 9.0.1 → 11.0.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 (240) hide show
  1. package/README.md +108 -102
  2. package/dist/board/editor/align.d.ts +11 -0
  3. package/dist/board/editor/align.js +72 -0
  4. package/dist/board/editor/animation.d.ts +17 -0
  5. package/dist/board/editor/animation.js +187 -0
  6. package/dist/board/editor/camera.d.ts +32 -0
  7. package/dist/board/editor/camera.js +137 -0
  8. package/dist/board/editor/clipboard.d.ts +41 -0
  9. package/dist/board/editor/clipboard.js +129 -0
  10. package/dist/board/editor/connection-ports.d.ts +19 -0
  11. package/dist/board/editor/connection-ports.js +85 -0
  12. package/dist/board/editor/context.d.ts +111 -0
  13. package/dist/board/editor/context.js +30 -0
  14. package/dist/board/editor/copy.d.ts +17 -0
  15. package/dist/board/editor/copy.js +121 -0
  16. package/dist/board/editor/creation.d.ts +51 -0
  17. package/dist/board/editor/creation.js +225 -0
  18. package/dist/board/editor/deletion.d.ts +9 -0
  19. package/dist/board/editor/deletion.js +90 -0
  20. package/dist/board/editor/document-edits.d.ts +22 -0
  21. package/dist/board/editor/document-edits.js +193 -0
  22. package/dist/board/editor/document.d.ts +41 -0
  23. package/dist/board/editor/document.js +302 -0
  24. package/dist/board/editor/editor.d.ts +225 -0
  25. package/dist/board/editor/editor.js +439 -0
  26. package/dist/board/editor/index.d.ts +18 -0
  27. package/dist/board/editor/index.js +12 -0
  28. package/dist/board/editor/interaction.d.ts +115 -0
  29. package/dist/board/editor/interaction.js +584 -0
  30. package/dist/board/editor/query.d.ts +27 -0
  31. package/dist/board/editor/query.js +203 -0
  32. package/dist/board/editor/remote.d.ts +11 -0
  33. package/dist/board/editor/remote.js +55 -0
  34. package/dist/board/editor/selection-transform.d.ts +24 -0
  35. package/dist/board/editor/selection-transform.js +81 -0
  36. package/dist/board/editor/selection.d.ts +33 -0
  37. package/dist/board/editor/selection.js +197 -0
  38. package/dist/board/editor/snapping.d.ts +33 -0
  39. package/dist/board/editor/snapping.js +75 -0
  40. package/dist/board/editor/snapshots.d.ts +27 -0
  41. package/dist/board/editor/snapshots.js +132 -0
  42. package/dist/board/editor/spatial.d.ts +41 -0
  43. package/dist/board/editor/spatial.js +191 -0
  44. package/dist/board/editor/state.d.ts +12 -0
  45. package/dist/board/editor/state.js +49 -0
  46. package/dist/board/editor/tool.d.ts +10 -0
  47. package/dist/board/editor/tool.js +19 -0
  48. package/dist/board/editor/wheel.d.ts +5 -0
  49. package/dist/board/editor/wheel.js +17 -0
  50. package/dist/board/export/index.d.ts +28 -6
  51. package/dist/board/export/index.js +47 -13
  52. package/dist/board/export/node/index.d.ts +56 -0
  53. package/dist/board/{headless → export/node}/index.js +26 -21
  54. package/dist/board/export/node/scripts.d.ts +16 -0
  55. package/dist/board/export/node/scripts.js +258 -0
  56. package/dist/board/export/scene.d.ts +8 -5
  57. package/dist/board/export/scene.js +24 -9
  58. package/dist/board/{animation.d.ts → model/animation.d.ts} +8 -5
  59. package/dist/board/{animation.js → model/animation.js} +37 -10
  60. package/dist/board/{core → model}/arrow-geometry.d.ts +2 -2
  61. package/dist/board/{core → model}/arrow-geometry.js +2 -2
  62. package/dist/board/model/authoring.d.ts +20 -0
  63. package/dist/board/model/authoring.js +185 -0
  64. package/dist/board/{core → model}/draw-geometry.d.ts +2 -2
  65. package/dist/board/{core → model}/draw-geometry.js +1 -1
  66. package/dist/board/model/draw-input.d.ts +14 -0
  67. package/dist/board/model/draw-input.js +28 -0
  68. package/dist/board/{core → model}/export-assets.d.ts +1 -1
  69. package/dist/board/{core → model}/export-assets.js +1 -1
  70. package/dist/board/{core → model}/export-plan.d.ts +2 -2
  71. package/dist/board/{core → model}/export-plan.js +3 -2
  72. package/dist/board/{core → model}/file-preview.d.ts +1 -1
  73. package/dist/board/{core → model}/file-preview.js +2 -2
  74. package/dist/board/{core → model}/file-snapshot.d.ts +1 -1
  75. package/dist/board/{core → model}/file-snapshot.js +4 -3
  76. package/dist/board/{geometry.d.ts → model/geometry.d.ts} +3 -3
  77. package/dist/board/{geometry.js → model/geometry.js} +1 -1
  78. package/dist/board/{image-key.d.ts → model/image-key.d.ts} +2 -2
  79. package/dist/board/{image-key.js → model/image-key.js} +7 -3
  80. package/dist/board/model/index.d.ts +42 -0
  81. package/dist/board/model/index.js +39 -0
  82. package/dist/board/model/items/builtin.d.ts +5 -0
  83. package/dist/board/model/items/builtin.js +119 -0
  84. package/dist/board/model/items/create.d.ts +61 -0
  85. package/dist/board/model/items/create.js +272 -0
  86. package/dist/board/model/items/definition.d.ts +35 -0
  87. package/dist/board/model/items/definition.js +18 -0
  88. package/dist/board/model/items/id.d.ts +5 -0
  89. package/dist/board/model/items/id.js +11 -0
  90. package/dist/board/model/items/index.d.ts +6 -0
  91. package/dist/board/model/items/index.js +6 -0
  92. package/dist/board/model/items/registry.d.ts +35 -0
  93. package/dist/board/model/items/registry.js +84 -0
  94. package/dist/board/{media-playback.d.ts → model/media-playback.d.ts} +4 -3
  95. package/dist/board/{media-playback.js → model/media-playback.js} +15 -5
  96. package/dist/board/{media.d.ts → model/media.d.ts} +1 -1
  97. package/dist/board/{media.js → model/media.js} +8 -2
  98. package/dist/board/{core → model}/palette.d.ts +1 -1
  99. package/dist/board/{core → model}/palette.js +1 -1
  100. package/dist/board/{presets.d.ts → model/presets.d.ts} +3 -3
  101. package/dist/board/{presets.js → model/presets.js} +1 -1
  102. package/dist/board/{replay.d.ts → model/replay.d.ts} +5 -5
  103. package/dist/board/{replay.js → model/replay.js} +2 -2
  104. package/dist/board/model/sampling.d.ts +19 -0
  105. package/dist/board/model/sampling.js +96 -0
  106. package/dist/board/{core → model}/scene.d.ts +1 -1
  107. package/dist/board/{core → model}/scene.js +1 -1
  108. package/dist/board/model/script-example.d.ts +4 -0
  109. package/dist/board/model/script-example.js +21 -0
  110. package/dist/board/model/script-hit.d.ts +10 -0
  111. package/dist/board/model/script-hit.js +52 -0
  112. package/dist/board/model/script-index.d.ts +7 -0
  113. package/dist/board/model/script-index.js +15 -0
  114. package/dist/board/model/script-scene.d.ts +24 -0
  115. package/dist/board/model/script-scene.js +267 -0
  116. package/dist/board/model/script.d.ts +105 -0
  117. package/dist/board/model/script.js +1 -0
  118. package/dist/board/model/shape-types.d.ts +8 -0
  119. package/dist/board/model/shape-types.js +8 -0
  120. package/dist/board/{task.d.ts → model/task.d.ts} +4 -4
  121. package/dist/board/{task.js → model/task.js} +3 -3
  122. package/dist/board/{core → model}/text-metrics.d.ts +1 -1
  123. package/dist/board/{core → model}/text-metrics.js +1 -1
  124. package/dist/board/{core → model}/tool-styles.d.ts +1 -1
  125. package/dist/board/{core → model}/tool-styles.js +1 -1
  126. package/dist/board/{runtime/board-player.d.ts → player/index.d.ts} +2 -2
  127. package/dist/board/{runtime/board-player.js → player/index.js} +5 -4
  128. package/dist/board/render/board-background.d.ts +1 -1
  129. package/dist/board/render/clip.d.ts +1 -1
  130. package/dist/board/render/css-color.d.ts +6 -1
  131. package/dist/board/render/css-color.js +34 -20
  132. package/dist/board/render/diagnostics.d.ts +20 -0
  133. package/dist/board/render/diagnostics.js +117 -0
  134. package/dist/board/render/index.d.ts +9 -6
  135. package/dist/board/render/index.js +10 -7
  136. package/dist/board/render/media-interaction.d.ts +2 -2
  137. package/dist/board/render/media-interaction.js +1 -1
  138. package/dist/board/render/palette.d.ts +3 -2
  139. package/dist/board/render/palette.js +7 -3
  140. package/dist/board/render/renderers/arrow-card-renderer.js +4 -3
  141. package/dist/board/render/renderers/audio-card-renderer.js +2 -1
  142. package/dist/board/render/renderers/board-renderer-registry.d.ts +20 -10
  143. package/dist/board/render/renderers/board-renderer-registry.js +17 -17
  144. package/dist/board/render/renderers/custom-card-renderer.d.ts +5 -0
  145. package/dist/board/render/renderers/{sketch-card-renderer.js → custom-card-renderer.js} +16 -15
  146. package/dist/board/render/renderers/draw-card-renderer.js +4 -3
  147. package/dist/board/render/renderers/effect-card-renderer.js +22 -5
  148. package/dist/board/render/renderers/far-plate.js +1 -1
  149. package/dist/board/render/renderers/file-card-renderer.d.ts +1 -1
  150. package/dist/board/render/renderers/file-card-renderer.js +2 -2
  151. package/dist/board/render/renderers/frame-card-renderer.js +30 -14
  152. package/dist/board/render/renderers/image-card-renderer.d.ts +1 -1
  153. package/dist/board/render/renderers/image-card-renderer.js +43 -4
  154. package/dist/board/render/renderers/shape-card-renderer.js +11 -28
  155. package/dist/board/render/renderers/task-card-renderer.js +1 -1
  156. package/dist/board/render/renderers/text-card-renderer.js +6 -4
  157. package/dist/board/render/renderers/unknown-card-renderer.js +1 -0
  158. package/dist/board/render/renderers/video-card-renderer.d.ts +1 -1
  159. package/dist/board/render/renderers/video-card-renderer.js +2 -1
  160. package/dist/board/render/sampling.d.ts +22 -0
  161. package/dist/board/render/sampling.js +21 -0
  162. package/dist/board/render/script-export.d.ts +11 -0
  163. package/dist/board/render/script-export.js +86 -0
  164. package/dist/board/render/script-host.d.ts +31 -0
  165. package/dist/board/render/script-host.js +421 -0
  166. package/dist/board/render/script-modules.d.ts +2 -0
  167. package/dist/board/render/script-modules.js +2 -0
  168. package/dist/board/render/script-runtime.d.ts +29 -0
  169. package/dist/board/render/script-runtime.js +213 -0
  170. package/dist/board/render/script-sandbox.d.ts +4 -0
  171. package/dist/board/render/script-sandbox.js +173 -0
  172. package/dist/board/render/stroke.d.ts +3 -2
  173. package/dist/board/render/stroke.js +23 -2
  174. package/dist/board/render/text-measurement.js +2 -2
  175. package/dist/board/replica/index.d.ts +70 -0
  176. package/dist/board/replica/index.js +276 -0
  177. package/dist/board/stage/assets.d.ts +41 -0
  178. package/dist/board/stage/assets.js +355 -0
  179. package/dist/board/stage/index.d.ts +8 -0
  180. package/dist/board/stage/index.js +8 -0
  181. package/dist/board/stage/lru.d.ts +32 -0
  182. package/dist/board/stage/lru.js +29 -0
  183. package/dist/board/stage/maintenance.d.ts +5 -0
  184. package/dist/board/stage/maintenance.js +11 -0
  185. package/dist/board/stage/pointer.d.ts +8 -0
  186. package/dist/board/stage/pointer.js +33 -0
  187. package/dist/board/stage/scene.d.ts +85 -0
  188. package/dist/board/stage/scene.js +515 -0
  189. package/dist/board/stage/script-pointer.d.ts +19 -0
  190. package/dist/board/stage/script-pointer.js +35 -0
  191. package/dist/board/stage/stage.d.ts +76 -0
  192. package/dist/board/stage/stage.js +774 -0
  193. package/dist/board/stage/texture-pool.d.ts +24 -0
  194. package/dist/board/stage/texture-pool.js +153 -0
  195. package/dist/board/stage/views.d.ts +38 -0
  196. package/dist/board/stage/views.js +93 -0
  197. package/dist/chunks/environment.d.ts +289 -23
  198. package/dist/chunks/host-bridge.d.ts +2 -2
  199. package/dist/chunks/http.d.ts +185 -71
  200. package/dist/chunks/http.js +368 -269
  201. package/dist/chunks/transport.js +3 -1
  202. package/dist/chunks/websocket.d.ts +9 -1
  203. package/dist/chunks/websocket.js +16 -2
  204. package/dist/host-bridge.js +2 -1
  205. package/dist/http.d.ts +2 -2
  206. package/dist/index.d.ts +182 -4
  207. package/dist/index.js +1393 -129
  208. package/dist/media.d.ts +1 -10
  209. package/dist/media.js +16 -27
  210. package/dist/protocol/dist/board-assets.d.ts +1 -0
  211. package/dist/protocol/dist/board-constants.js +2 -2
  212. package/dist/protocol/dist/board-model.d.ts +201 -11
  213. package/dist/protocol/dist/board-model.js +33 -14
  214. package/dist/protocol/dist/board-patch.js +3 -2
  215. package/dist/protocol/dist/board-schema.d.ts +4 -2
  216. package/dist/protocol/dist/board-schema.js +18 -4
  217. package/dist/protocol/dist/board-script-modules.d.ts +25 -0
  218. package/dist/protocol/dist/board-script-modules.js +127 -0
  219. package/dist/protocol/dist/board.d.ts +28 -2
  220. package/dist/protocol/dist/board.js +3 -1
  221. package/dist/protocol/dist/core/media.d.ts +5 -0
  222. package/dist/protocol/dist/core/media.js +39 -0
  223. package/dist/protocol/dist/display/index.d.ts +1 -0
  224. package/dist/protocol/dist/index.d.ts +7 -5
  225. package/dist/protocol/dist/realtime/types.d.ts +1 -0
  226. package/dist/protocol/dist/rtc/index.d.ts +1 -0
  227. package/dist/types.d.ts +1 -1
  228. package/package.json +21 -8
  229. package/dist/board/core/shape-definition.d.ts +0 -23
  230. package/dist/board/core/shape-definition.js +0 -45
  231. package/dist/board/core/shape-types.d.ts +0 -38
  232. package/dist/board/core/shape-types.js +0 -22
  233. package/dist/board/headless/index.d.ts +0 -55
  234. package/dist/board/headless/sketch.d.ts +0 -19
  235. package/dist/board/headless/sketch.js +0 -146
  236. package/dist/board/index.d.ts +0 -30
  237. package/dist/board/index.js +0 -29
  238. package/dist/board/render/renderers/sketch-card-renderer.d.ts +0 -5
  239. package/dist/board/render/sketch-host.d.ts +0 -14
  240. package/dist/board/render/sketch-host.js +0 -216
@@ -0,0 +1,302 @@
1
+ import { IDENTITY_MATRIX, arrowBindings } from "../../protocol/dist/board-layout.js";
2
+ import { applyBoardPatchToDocument } from "../../protocol/dist/board-patch.js";
3
+ import { compileBoardAnimations, evaluateBoardAnimations } from "../model/animation.js";
4
+ import { buildBoardScene, placeItem, refreshBoardScene } from "../model/scene.js";
5
+ import { diffBoardEdits, isEmptyBoardPatch, routeBoardEdits, sameJson } from "./document-edits.js";
6
+ //#region src/board/editor/document.ts
7
+ function createDocumentModule(ctx) {
8
+ const { state, options } = ctx;
9
+ const draft = /* @__PURE__ */ new Map();
10
+ const draftOrigins = /* @__PURE__ */ new Map();
11
+ const recentlyAdded = /* @__PURE__ */ new Set();
12
+ let evaluated = /* @__PURE__ */ new Map();
13
+ let played = /* @__PURE__ */ new Map();
14
+ let scripted = /* @__PURE__ */ new Map();
15
+ let compiled = null;
16
+ function markAdded(ids) {
17
+ if (ids.length === 0) return;
18
+ recentlyAdded.clear();
19
+ for (const id of ids) recentlyAdded.add(id);
20
+ }
21
+ function consumeRecentlyAdded() {
22
+ const ids = [...recentlyAdded];
23
+ recentlyAdded.clear();
24
+ return ids;
25
+ }
26
+ function displayItem(id) {
27
+ if (draft.has(id)) return draft.get(id) ?? void 0;
28
+ return scripted.get(id) ?? evaluated.get(id) ?? played.get(id) ?? state.base.items[id];
29
+ }
30
+ function displayDocument(includeScripts = true) {
31
+ const base = state.base;
32
+ if (draft.size === 0 && evaluated.size === 0 && played.size === 0 && (!includeScripts || scripted.size === 0)) return base;
33
+ const items = { ...base.items };
34
+ for (const [id, item] of played) items[id] = item;
35
+ for (const [id, item] of evaluated) items[id] = item;
36
+ if (includeScripts) for (const [id, item] of scripted) items[id] = item;
37
+ for (const [id, item] of draft) if (item) items[id] = item;
38
+ else delete items[id];
39
+ return {
40
+ ...base,
41
+ items
42
+ };
43
+ }
44
+ function reevaluate() {
45
+ const { base, playhead } = state;
46
+ if (!playhead || !base.animations[playhead.animationId]) {
47
+ evaluated = /* @__PURE__ */ new Map();
48
+ return;
49
+ }
50
+ if (!compiled || compiled.animations !== base.animations || compiled.items !== base.items) compiled = {
51
+ animations: base.animations,
52
+ items: base.items,
53
+ value: compileBoardAnimations(base)
54
+ };
55
+ evaluated = evaluateBoardAnimations(compiled.value, { [playhead.animationId]: playhead.time }).items;
56
+ }
57
+ function setPlayedItems(items) {
58
+ const previous = played;
59
+ played = new Map([...items].filter(([id]) => state.base.items[id]));
60
+ const changed = /* @__PURE__ */ new Set([...previous.keys(), ...played.keys()]);
61
+ for (const id of changed) if (draft.has(id) || evaluated.has(id) || sameJson(previous.get(id), played.get(id))) changed.delete(id);
62
+ if (changed.size) rescene(changed);
63
+ }
64
+ function setScriptItems(items) {
65
+ const previous = scripted;
66
+ scripted = items;
67
+ const changed = [.../* @__PURE__ */ new Set([...previous.keys(), ...items.keys()])].filter((id) => !sameJson(previous.get(id), items.get(id)));
68
+ if (!changed.length) return;
69
+ rescene(changed.some((id) => {
70
+ const before = previous.get(id) ?? state.base.items[id];
71
+ const after = items.get(id) ?? state.base.items[id];
72
+ return !before || !after || before.parent !== after.parent || before.z !== after.z || !sameJson(arrowBindings(before), arrowBindings(after));
73
+ }) ? void 0 : changed);
74
+ }
75
+ function rescene(ids) {
76
+ if (ids) {
77
+ const changed = [...ids];
78
+ state.scene = refreshBoardScene(state.scene, displayItem, changed);
79
+ ctx.query.invalidate(changed);
80
+ } else {
81
+ state.scene = buildBoardScene(displayDocument(), state.scene);
82
+ ctx.query.invalidate();
83
+ state.structureVersion += 1;
84
+ }
85
+ state.geometryVersion += 1;
86
+ }
87
+ function reset(next) {
88
+ state.base = next;
89
+ draft.clear();
90
+ draftOrigins.clear();
91
+ played = /* @__PURE__ */ new Map();
92
+ scripted = /* @__PURE__ */ new Map();
93
+ reevaluate();
94
+ state.scene = buildBoardScene(next);
95
+ ctx.query.invalidate();
96
+ state.structureVersion += 1;
97
+ state.geometryVersion += 1;
98
+ }
99
+ function setDraftItem(id, item) {
100
+ if (!draft.has(id)) {
101
+ const shown = displayItem(id);
102
+ if (shown) draftOrigins.set(id, shown);
103
+ }
104
+ draft.set(id, item);
105
+ }
106
+ function draftItem(id) {
107
+ return draft.get(id);
108
+ }
109
+ function dropDraftItem(id) {
110
+ draft.delete(id);
111
+ }
112
+ function writeDraft(changes, structural = false) {
113
+ if (changes.size === 0) return;
114
+ for (const [id, item] of changes) setDraftItem(id, item);
115
+ if (!structural) for (const [id, item] of changes) {
116
+ const before = state.scene.get(id);
117
+ if (!item || !before || before.parent !== item.parent || before.z !== item.z || !sameJson(arrowBindings(before), arrowBindings(item))) {
118
+ structural = true;
119
+ break;
120
+ }
121
+ }
122
+ rescene(structural ? void 0 : changes.keys());
123
+ }
124
+ function discardDraft() {
125
+ draft.clear();
126
+ draftOrigins.clear();
127
+ reevaluate();
128
+ rescene();
129
+ }
130
+ function send(patch) {
131
+ if (options.readonly || isEmptyBoardPatch(patch)) return Promise.resolve(null);
132
+ state.pendingCommits += 1;
133
+ let completion;
134
+ try {
135
+ completion = Promise.resolve(options.onCommit(patch));
136
+ } catch (error) {
137
+ completion = Promise.reject(error);
138
+ }
139
+ return completion.then(() => {
140
+ state.saveError = null;
141
+ return null;
142
+ }).catch((error) => {
143
+ state.saveError = error instanceof Error ? error.message : "Failed to sync board";
144
+ return error instanceof Error ? error : new Error(state.saveError);
145
+ }).finally(() => {
146
+ state.pendingCommits -= 1;
147
+ });
148
+ }
149
+ function adopt(next, changedIds) {
150
+ const base = state.base;
151
+ const structural = played.size > 0 || !changedIds || next.animations !== base.animations || next.board !== base.board;
152
+ state.base = next;
153
+ played = /* @__PURE__ */ new Map();
154
+ draft.clear();
155
+ draftOrigins.clear();
156
+ reevaluate();
157
+ if (structural || state.playhead) {
158
+ rescene();
159
+ return;
160
+ }
161
+ const ids = [...changedIds];
162
+ rescene(ids.some((id) => {
163
+ const before = state.scene.get(id);
164
+ const after = next.items[id];
165
+ return !before || !after || before.parent !== after.parent || before.z !== after.z || !sameJson(arrowBindings(before), arrowBindings(after));
166
+ }) ? void 0 : ids);
167
+ }
168
+ function commit(extra = {}, record = true) {
169
+ const ids = [...draft.keys()];
170
+ const base = state.base;
171
+ let target = routeBoardEdits({
172
+ base,
173
+ evaluated,
174
+ draft,
175
+ playhead: state.playhead,
176
+ recording: state.recording,
177
+ displayed: draftOrigins
178
+ });
179
+ if (extra.board) target = {
180
+ ...target,
181
+ board: extra.board
182
+ };
183
+ if (extra.animations) target = {
184
+ ...target,
185
+ animations: extra.animations
186
+ };
187
+ const redo = diffBoardEdits(base, target, ids);
188
+ if (isEmptyBoardPatch(redo)) {
189
+ adopt(base);
190
+ return;
191
+ }
192
+ if (record) {
193
+ const undo = diffBoardEdits(target, base, ids);
194
+ state.undoStack = [...state.undoStack.slice(-199), {
195
+ undo,
196
+ redo
197
+ }];
198
+ state.redoStack = [];
199
+ }
200
+ adopt(target, ids);
201
+ send(redo);
202
+ }
203
+ function commitItems(changes, record = true) {
204
+ if (changes.size === 0) return;
205
+ for (const [id, item] of changes) setDraftItem(id, item);
206
+ commit({}, record);
207
+ }
208
+ function commitPatch(patch) {
209
+ if (options.readonly) throw new Error("Board is read-only.");
210
+ const before = state.base;
211
+ const result = applyBoardPatchToDocument(before, patch);
212
+ if (!result.ok) throw new Error(result.diagnostics[0]?.message ?? "Invalid board patch.");
213
+ const ids = Object.keys(patch.items ?? {});
214
+ const redo = diffBoardEdits(before, result.document, ids);
215
+ if (isEmptyBoardPatch(redo)) return;
216
+ state.undoStack = [...state.undoStack.slice(-199), {
217
+ undo: diffBoardEdits(result.document, before, ids),
218
+ redo
219
+ }];
220
+ state.redoStack = [];
221
+ adopt(result.document, ids);
222
+ return send(redo).then((error) => {
223
+ if (error) throw error;
224
+ });
225
+ }
226
+ function applyPatch(patch) {
227
+ const result = applyBoardPatchToDocument(state.base, patch);
228
+ if (!result.ok) {
229
+ state.saveError = result.diagnostics[0]?.message ?? "Could not apply the change";
230
+ return false;
231
+ }
232
+ adopt(result.document, Object.keys(patch.items ?? {}));
233
+ send(patch);
234
+ return true;
235
+ }
236
+ function undo() {
237
+ const entry = state.undoStack.at(-1);
238
+ if (!entry) return;
239
+ state.undoStack = state.undoStack.slice(0, -1);
240
+ if (applyPatch(entry.undo)) state.redoStack = [...state.redoStack, entry];
241
+ }
242
+ function redo() {
243
+ const entry = state.redoStack.at(-1);
244
+ if (!entry) return;
245
+ state.redoStack = state.redoStack.slice(0, -1);
246
+ if (applyPatch(entry.redo)) state.undoStack = [...state.undoStack, entry];
247
+ }
248
+ function previewSettings(settings) {
249
+ state.settingsPreview = settings;
250
+ }
251
+ function setSettings(settings) {
252
+ state.settingsPreview = null;
253
+ if (!sameJson(settings, state.base.board)) commit({ board: settings });
254
+ }
255
+ function reparent(item, frame, parent, box) {
256
+ const { parent: _previous, ...root } = item;
257
+ const orphan = root;
258
+ const next = parent ? {
259
+ ...orphan,
260
+ parent
261
+ } : orphan;
262
+ const matrix = parent ? state.scene.layout.matrix(parent) : IDENTITY_MATRIX;
263
+ return placeItem(next, frame, matrix, box);
264
+ }
265
+ function topZ(parent, scene = state.scene) {
266
+ let z = 0;
267
+ for (const id of scene.children(parent)) z = Math.max(z, scene.get(id)?.z ?? 0);
268
+ return z + 1;
269
+ }
270
+ return {
271
+ markAdded,
272
+ consumeRecentlyAdded,
273
+ displayItem,
274
+ copyScene: () => scripted.size ? buildBoardScene(displayDocument(false)) : state.scene,
275
+ reevaluate,
276
+ setPlayedItems,
277
+ get hasScriptItems() {
278
+ return scripted.size > 0;
279
+ },
280
+ setScriptItems,
281
+ animationItems: () => new Map([...played, ...evaluated]),
282
+ commitPatch,
283
+ rescene,
284
+ reset,
285
+ setDraftItem,
286
+ draftItem,
287
+ dropDraftItem,
288
+ writeDraft,
289
+ discardDraft,
290
+ adopt,
291
+ commit,
292
+ commitItems,
293
+ undo,
294
+ redo,
295
+ previewSettings,
296
+ setSettings,
297
+ reparent,
298
+ topZ
299
+ };
300
+ }
301
+ //#endregion
302
+ export { createDocumentModule };
@@ -0,0 +1,225 @@
1
+ import { BoardDocument, BoardItem, BoardMediaSnapshot, BoardPatch, BoardSettings, BoardTaskSnapshot } from "../../protocol/dist/board-model.js";
2
+ import { BoardFrame } from "../../protocol/dist/board-layout.js";
3
+ import { BoardViewport, Rect, ScreenPoint, WorldPoint } from "../model/geometry.js";
4
+ import { BoardScene, BoardSceneItem } from "../model/scene.js";
5
+ import { BoardChapter } from "../model/authoring.js";
6
+ import { BoardFileSnapshotFacts } from "../model/file-snapshot.js";
7
+ import { ShapeKind } from "../model/shape-types.js";
8
+ import { BoardItemEntry, BoardMediaItemKind } from "../model/items/create.js";
9
+ import { BoardItemInput, BoardRegistry } from "../model/items/registry.js";
10
+ import "../model/index.js";
11
+ import { AlignMode, DistributeAxis } from "./align.js";
12
+ import { BoardFocusOptions } from "./camera.js";
13
+ import { BoardSelectionTransform, BoardTransformControl } from "./selection-transform.js";
14
+ import { BoardInteraction, BoardPointerEvent } from "./interaction.js";
15
+ import { BoardAppMetadata, BoardTaskSource } from "./creation.js";
16
+ import { BoardClipboardPayload } from "./clipboard.js";
17
+ import { BoardNaturalSize } from "./snapshots.js";
18
+ import { SnapGuide } from "./snapping.js";
19
+ import { BoardEditorChannel, BoardEditorListener } from "./state.js";
20
+ import { BoardToolId } from "./tool.js";
21
+ import { BoardCameraPolicy, BoardEditorOptions, BoardPlayhead } from "./context.js";
22
+ //#region src/board/editor/editor.d.ts
23
+ declare function createBoardEditor(options: BoardEditorOptions): {
24
+ registry: BoardRegistry;
25
+ readonly: boolean;
26
+ subscribe: (channels: BoardEditorChannel | readonly BoardEditorChannel[], listener: BoardEditorListener) => () => void;
27
+ readonly hasScripts: boolean;
28
+ readonly document: BoardDocument;
29
+ readonly settings: {
30
+ title?: string | undefined;
31
+ background: {
32
+ kind: "dots" | "grid" | "image" | "solid";
33
+ color?: string | {
34
+ light: string;
35
+ dark: string;
36
+ } | undefined;
37
+ imageUrl?: string | undefined;
38
+ fit?: "contain" | "cover" | "repeat" | undefined;
39
+ opacity?: number | undefined;
40
+ };
41
+ grid?: {
42
+ visible: boolean;
43
+ size: number;
44
+ } | undefined;
45
+ enter?: {
46
+ preset: "deal" | "drop" | "fade-in" | "pop" | "rise";
47
+ duration?: number | undefined;
48
+ } | undefined;
49
+ };
50
+ readonly animations: Record<string, {
51
+ name?: string | undefined;
52
+ duration: number;
53
+ play: "always" | "auto" | "manual";
54
+ delay: number;
55
+ loop: boolean;
56
+ end: "hold" | "reset";
57
+ markers: {
58
+ at: number;
59
+ label?: string | undefined;
60
+ pause?: boolean | undefined;
61
+ }[];
62
+ tracks: Record<string, {
63
+ target: string;
64
+ property: string;
65
+ keyframes: {
66
+ at: number;
67
+ value: unknown;
68
+ ease?: string | undefined;
69
+ }[];
70
+ composite: "add" | "replace";
71
+ interpolation: "auto" | "spline" | "step";
72
+ orient?: boolean | undefined;
73
+ }>;
74
+ }>;
75
+ readonly scene: BoardScene;
76
+ readonly items: readonly BoardSceneItem[];
77
+ readonly hasContent: boolean;
78
+ readonly structureVersion: number;
79
+ readonly geometryVersion: number;
80
+ readonly selection: string[];
81
+ readonly selectedItems: BoardSceneItem[];
82
+ readonly hasFocusableSelection: boolean;
83
+ readonly selectionLocked: boolean;
84
+ readonly bounds: Rect | null;
85
+ readonly selectionTransform: BoardSelectionTransform | null;
86
+ readonly camera: BoardViewport;
87
+ readonly cameraPolicy: BoardCameraPolicy;
88
+ readonly playhead: BoardPlayhead | null;
89
+ readonly recording: boolean;
90
+ tool: BoardToolId;
91
+ activeColor: string;
92
+ activeShape: string;
93
+ activeStrokeSize: number;
94
+ readonly interaction: BoardInteraction;
95
+ readonly gestureActive: boolean;
96
+ readonly marquee: Rect | null;
97
+ readonly snapGuides: SnapGuide[];
98
+ spaceHeld: boolean;
99
+ readonly arrowDraft: {
100
+ from: WorldPoint;
101
+ to: WorldPoint;
102
+ size: number;
103
+ color: string;
104
+ targetFrame: BoardFrame | null;
105
+ } | null;
106
+ readonly bindTargetFrame: BoardFrame | null;
107
+ readonly hoverId: string | null;
108
+ readonly pointerType: string;
109
+ readonly hoveredTransformControl: BoardTransformControl | null;
110
+ readonly connectionPorts: {
111
+ itemId: string;
112
+ x: number;
113
+ y: number;
114
+ radius: number;
115
+ }[];
116
+ readonly hoveredConnectionPort: {
117
+ x: number;
118
+ y: number;
119
+ } | null;
120
+ editingId: string | null;
121
+ readonly canUndo: boolean;
122
+ readonly canRedo: boolean;
123
+ readonly saveError: string | null;
124
+ readonly saving: boolean;
125
+ surfaceSize: {
126
+ width: number;
127
+ height: number;
128
+ };
129
+ loadDocument: (next: BoardDocument, key?: string) => void;
130
+ undo: () => void;
131
+ redo: () => void;
132
+ retrySave: () => void;
133
+ setSettings: (settings: BoardSettings) => void;
134
+ previewSettings: (settings: BoardSettings) => void;
135
+ setPlayedItems: (items: ReadonlyMap<string, BoardItem>) => void;
136
+ setScriptItems: (items: ReadonlyMap<string, BoardItem>) => void;
137
+ animationItems: () => Map<string, BoardItem>;
138
+ commitPatch: (patch: BoardPatch) => Promise<void> | undefined;
139
+ consumeRecentlyAdded: () => string[];
140
+ itemAt: (point: WorldPoint, exclude?: ReadonlySet<string> | undefined, includeTemporary?: boolean | undefined) => BoardSceneItem | null;
141
+ itemById: (id: string) => BoardSceneItem | null;
142
+ labelItemAt: (point: WorldPoint) => BoardSceneItem | null;
143
+ idsInRect: (rect: Rect, includeTemporary?: boolean | undefined) => string[];
144
+ setCamera: (viewport: BoardViewport) => void;
145
+ setCameraPolicy: (policy: BoardCameraPolicy) => void;
146
+ takeCameraControl: () => void;
147
+ viewCenter: () => WorldPoint;
148
+ zoomAt: (point: ScreenPoint, factor: number, animate?: boolean) => void;
149
+ zoomIn: () => void;
150
+ zoomOut: () => void;
151
+ resetZoom: () => void;
152
+ fitView: (focus?: BoardFocusOptions) => void;
153
+ focusRect: (rect: Rect, focus?: BoardFocusOptions) => void;
154
+ focusItems: (ids: Iterable<string>, focus?: BoardFocusOptions) => void;
155
+ focusNode: (id: string, focus?: BoardFocusOptions) => void;
156
+ focusSelection: (focus?: BoardFocusOptions) => void;
157
+ wheel: (point: ScreenPoint, deltaX: number, deltaY: number, zoomKey: boolean, deltaMode?: number) => void;
158
+ setSelection: (ids: string[]) => void;
159
+ clearSelection: () => void;
160
+ selectAll: () => void;
161
+ nudgeSelection: (dx: number, dy: number, large: boolean) => void;
162
+ alignSelection: (mode: AlignMode) => void;
163
+ distributeSelection: (axis: DistributeAxis) => void;
164
+ toggleSelectionLock: () => void;
165
+ setSelectionColor: (color: string) => void;
166
+ setSelectionStyle: (style: Partial<BoardItem["style"]>) => void;
167
+ setSelectionProps: (type: string, props: Record<string, unknown>) => void;
168
+ bringToFront: () => void;
169
+ sendToBack: () => void;
170
+ addItem: (type: string, input: BoardItemInput) => string | null;
171
+ addItems: (entries: BoardItemEntry[], { select, enter }?: {
172
+ select?: boolean;
173
+ enter?: boolean;
174
+ }) => void;
175
+ addApp: (app: BoardAppMetadata, at: WorldPoint) => string;
176
+ addFile: (path: string, at: WorldPoint, snapshot?: BoardMediaSnapshot & BoardFileSnapshotFacts) => string;
177
+ addMedia: (src: string, at: WorldPoint, options?: {
178
+ kind?: BoardMediaItemKind;
179
+ snapshot?: BoardMediaSnapshot;
180
+ }) => string;
181
+ addTask: (taskRunId: string, snapshot: BoardTaskSnapshot, at: WorldPoint, metadata?: Record<string, unknown>) => string;
182
+ addTaskWithSources: (taskRunId: string, snapshot: BoardTaskSnapshot, at: WorldPoint, sources: BoardTaskSource[], metadata?: Record<string, unknown>) => string | null;
183
+ addText: (text: string, at: WorldPoint) => void;
184
+ addShape: (at: WorldPoint, geometry?: ShapeKind) => void;
185
+ addFrame: (at: WorldPoint) => void;
186
+ beginTextDraft: (at: WorldPoint) => void;
187
+ commitTextEdit: (id: string, text: string) => void;
188
+ updateText: (id: string, text: string, created?: boolean) => void;
189
+ previewTextLayout: (id: string, text: string) => void;
190
+ deleteSelection: () => void;
191
+ deleteItem: (id: string) => void;
192
+ duplicateSelection: () => void;
193
+ copySelection: () => BoardClipboardPayload | null;
194
+ cutSelection: () => BoardClipboardPayload | null;
195
+ pasteClipboard: (raw?: unknown, at?: WorldPoint) => void;
196
+ applyMediaFileChange: (path: string, change: {
197
+ size?: number;
198
+ mtimeMs?: number;
199
+ removed?: boolean;
200
+ }) => void;
201
+ adoptMediaNaturalSizes: (sizes: BoardNaturalSize[]) => void;
202
+ applyFileSnapshots: (snapshots: Array<{
203
+ id: string;
204
+ snapshot: BoardFileSnapshotFacts;
205
+ replace?: boolean;
206
+ }>) => void;
207
+ applyTaskSnapshots: (snapshots: ReadonlyMap<string, BoardTaskSnapshot>) => void;
208
+ setPlayhead: (next: BoardPlayhead | null) => void;
209
+ setRecording: (value: boolean) => void;
210
+ keyframeState: (property: string) => "animated" | "keyframe" | "none";
211
+ toggleKeyframe: (property: string) => void;
212
+ removeKeyframe: (trackId: string, at: number) => void;
213
+ setKeyframeEase: (trackId: string, at: number, ease: string | null) => void;
214
+ createAnimation: (name: string, duration?: number) => string;
215
+ createSequence: (name: string, chapters: BoardChapter[]) => string | null;
216
+ pointerDown: (event: BoardPointerEvent) => void;
217
+ pointerMove: (event: BoardPointerEvent) => void;
218
+ pointerUp: (event: BoardPointerEvent) => void;
219
+ pointerLeave: () => void;
220
+ cancelPointerInteraction: () => void;
221
+ destroy(): void;
222
+ };
223
+ type BoardEditor = ReturnType<typeof createBoardEditor>;
224
+ //#endregion
225
+ export { BoardEditor, createBoardEditor };