@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,51 @@
1
+ import { BoardArrowEnd, BoardDrawPoint, BoardItem, BoardMediaSnapshot, BoardTaskSnapshot } from "../../protocol/dist/board-model.js";
2
+ import { BoardMatrix } from "../../protocol/dist/board-layout.js";
3
+ import { WorldPoint } from "../model/geometry.js";
4
+ import { BoardFileSnapshotFacts } from "../model/file-snapshot.js";
5
+ import { ShapeKind } from "../model/shape-types.js";
6
+ import { BoardItemEntry, BoardMediaItemKind, createAppBoardItem } from "../model/items/create.js";
7
+ import { BoardItemInput } from "../model/items/registry.js";
8
+ import "../model/index.js";
9
+ import { BoardInteraction } from "./interaction.js";
10
+ import { EditorContext } from "./context.js";
11
+ //#region src/board/editor/creation.d.ts
12
+ type BoardAppMetadata = Parameters<typeof createAppBoardItem>[0];
13
+ type BoardTaskSource = {
14
+ itemId: string;
15
+ sourcePortId: string;
16
+ targetPortId: string;
17
+ };
18
+ declare function createCreationModule(ctx: EditorContext): {
19
+ placeNew: (entries: readonly BoardItemEntry[]) => Map<string, BoardItem>;
20
+ add: (entries: BoardItemEntry[], { select, enter }?: {
21
+ select?: boolean;
22
+ enter?: boolean;
23
+ }) => void;
24
+ addItem: (type: string, input: BoardItemInput) => string | null;
25
+ addApp: (app: BoardAppMetadata, at: WorldPoint) => string;
26
+ addMedia: (src: string, at: WorldPoint, options?: {
27
+ kind?: BoardMediaItemKind;
28
+ snapshot?: BoardMediaSnapshot;
29
+ }) => string;
30
+ addFile: (path: string, at: WorldPoint, snapshot?: BoardMediaSnapshot & BoardFileSnapshotFacts) => string;
31
+ addTask: (taskRunId: string, snapshot: BoardTaskSnapshot, at: WorldPoint, metadata?: Record<string, unknown>) => string;
32
+ addTaskWithSources: (taskRunId: string, snapshot: BoardTaskSnapshot, at: WorldPoint, sources: BoardTaskSource[], metadata?: Record<string, unknown>) => string | null;
33
+ addText: (text: string, at: WorldPoint) => void;
34
+ addShape: (at: WorldPoint, geometry?: ShapeKind) => void;
35
+ addFrame: (at: WorldPoint) => void;
36
+ commitBox: (gesture: Extract<BoardInteraction, {
37
+ type: "creatingBox";
38
+ }>) => void;
39
+ commitDraw: (id: string, points: BoardDrawPoint[], color: string, size: number) => void;
40
+ commitArrow: (gesture: Extract<BoardInteraction, {
41
+ type: "creatingArrow";
42
+ }>, cancelled: boolean) => void;
43
+ arrowEnd: (point: WorldPoint, targetItemId: string | null, arrowMatrix?: BoardMatrix) => BoardArrowEnd;
44
+ beginTextDraft: (at: WorldPoint) => void;
45
+ previewTextLayout: (id: string, text: string) => void;
46
+ updateText: (id: string, text: string, created?: boolean) => void;
47
+ commitTextEdit: (id: string, text: string) => void;
48
+ };
49
+ type CreationModule = ReturnType<typeof createCreationModule>;
50
+ //#endregion
51
+ export { BoardAppMetadata, BoardTaskSource, CreationModule, createCreationModule };
@@ -0,0 +1,225 @@
1
+ import { IDENTITY_MATRIX, applyMatrix, invertMatrix } from "../../protocol/dist/board-layout.js";
2
+ import { rectCenter } from "../model/geometry.js";
3
+ import { buildBoardScene } from "../model/scene.js";
4
+ import { isShapeKind } from "../model/shape-types.js";
5
+ import { createBoardItemId } from "../model/items/id.js";
6
+ import { createAppBoardItem, createArrowBoardItem, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTextBoardItem } from "../model/items/create.js";
7
+ import { sameJson } from "./document-edits.js";
8
+ import { isContinuousBoardTool } from "./tool.js";
9
+ //#region src/board/editor/creation.ts
10
+ function createCreationModule(ctx) {
11
+ const { state, options } = ctx;
12
+ function placeNew(entries) {
13
+ const created = new Set(entries.map((entry) => entry.id));
14
+ const probe = buildBoardScene({
15
+ ...state.base,
16
+ items: Object.fromEntries(entries.map((entry) => [entry.id, entry.item]))
17
+ });
18
+ const nextZ = /* @__PURE__ */ new Map();
19
+ const changes = /* @__PURE__ */ new Map();
20
+ for (const { id, item } of entries) {
21
+ if (item.parent && created.has(item.parent)) {
22
+ changes.set(id, item);
23
+ continue;
24
+ }
25
+ const shown = probe.get(id);
26
+ const container = shown && item.type !== "frame" && item.type !== "arrow" ? ctx.query.frameAt(rectCenter(shown.frame), created) : null;
27
+ const value = container && shown ? ctx.document.reparent(item, shown.frame, container.id, probe.layout.box(id)) : item;
28
+ const z = nextZ.get(container?.id) ?? ctx.document.topZ(container?.id);
29
+ nextZ.set(container?.id, z + 1);
30
+ changes.set(id, {
31
+ ...value,
32
+ z
33
+ });
34
+ }
35
+ return changes;
36
+ }
37
+ function returnToSelect() {
38
+ if (!isContinuousBoardTool(state.tool)) state.tool = "select";
39
+ }
40
+ function add(entries, { select = !isContinuousBoardTool(state.tool), enter = true } = {}) {
41
+ if (options.readonly || entries.length === 0) return;
42
+ const changes = placeNew(entries);
43
+ if (enter) ctx.document.markAdded([...changes.keys()]);
44
+ state.selection = select ? [...changes.keys()] : [];
45
+ ctx.document.commitItems(changes);
46
+ returnToSelect();
47
+ }
48
+ function addOne(entry) {
49
+ add([entry]);
50
+ return entry.id;
51
+ }
52
+ function addItem(type, input) {
53
+ if (options.readonly) return null;
54
+ return addOne(ctx.registry.create(type, input));
55
+ }
56
+ function addTaskWithSources(taskRunId, snapshot, at, sources, metadata) {
57
+ if (options.readonly) return null;
58
+ const { arrow } = state.toolStyles;
59
+ const task = createTaskBoardItem(taskRunId, snapshot, at.x, at.y, metadata);
60
+ add([task, ...sources.filter((source) => source.itemId !== task.id && state.scene.get(source.itemId)).map((source) => {
61
+ const entry = createArrowBoardItem({
62
+ x: 0,
63
+ y: 0
64
+ }, { item: task.id }, arrow.color, createBoardItemId(), arrow.size, { item: source.itemId });
65
+ const props = entry.item.props;
66
+ return {
67
+ id: entry.id,
68
+ item: {
69
+ ...entry.item,
70
+ metadata: { boardFlow: {
71
+ version: 1,
72
+ kind: "content",
73
+ sourcePortId: source.sourcePortId,
74
+ targetPortId: source.targetPortId
75
+ } },
76
+ props: {
77
+ ...props,
78
+ start: {
79
+ item: source.itemId,
80
+ anchor: "auto",
81
+ port: source.sourcePortId
82
+ },
83
+ end: {
84
+ item: task.id,
85
+ anchor: "auto",
86
+ port: source.targetPortId
87
+ },
88
+ relation: "input"
89
+ }
90
+ }
91
+ };
92
+ })], { select: false });
93
+ state.selection = [task.id];
94
+ return task.id;
95
+ }
96
+ function commitBox(gesture) {
97
+ const dx = gesture.current.x - gesture.start.x;
98
+ const dy = gesture.current.y - gesture.start.y;
99
+ const click = Math.hypot(dx, dy) <= 6 / Math.max(state.camera.zoom, 1e-4);
100
+ const minimum = gesture.kind === "frame" ? 48 : 24;
101
+ const box = click ? void 0 : {
102
+ x: Math.min(gesture.start.x, gesture.current.x),
103
+ y: Math.min(gesture.start.y, gesture.current.y),
104
+ width: Math.max(minimum, Math.abs(dx)),
105
+ height: Math.max(minimum, Math.abs(dy))
106
+ };
107
+ const geometry = isShapeKind(gesture.geometry) ? gesture.geometry : "rectangle";
108
+ const { x, y } = gesture.start;
109
+ add([gesture.kind === "shape" ? createShapeBoardItem(geometry, x, y, gesture.color, gesture.id, box) : createFrameBoardItem(x, y, gesture.color, "Frame", gesture.id, box)], { enter: false });
110
+ }
111
+ function commitDraw(id, points, color, size) {
112
+ if (points.length === 0) return;
113
+ add([createDrawBoardItem(points, color, size, id)], { enter: false });
114
+ }
115
+ function arrowEnd(point, targetItemId, arrowMatrix = IDENTITY_MATRIX) {
116
+ if (targetItemId) return {
117
+ item: targetItemId,
118
+ anchor: "auto"
119
+ };
120
+ const local = applyMatrix(invertMatrix(arrowMatrix), point);
121
+ return {
122
+ x: local.x,
123
+ y: local.y
124
+ };
125
+ }
126
+ function commitArrow(gesture, cancelled) {
127
+ const { start, current, startItemId, targetItemId } = gesture;
128
+ const bound = !cancelled && targetItemId && targetItemId !== startItemId ? targetItemId : null;
129
+ if (!bound && Math.hypot(current.x - start.x, current.y - start.y) < 2 / state.camera.zoom) return;
130
+ add([createArrowBoardItem(start, bound ? { item: bound } : current, gesture.color, gesture.id, gesture.size, startItemId ? {
131
+ item: startItemId,
132
+ ...gesture.startSide ? { anchor: {
133
+ side: gesture.startSide,
134
+ offset: .5
135
+ } } : {}
136
+ } : void 0)], { enter: false });
137
+ }
138
+ function beginTextDraft(at) {
139
+ const entry = createTextBoardItem("", at.x, at.y, state.toolStyles.text.color);
140
+ ctx.document.writeDraft(placeNew([entry]), true);
141
+ state.draftTextId = entry.id;
142
+ state.selection = [entry.id];
143
+ state.editingId = entry.id;
144
+ }
145
+ function previewTextLayout(id, text) {
146
+ const item = ctx.document.displayItem(id);
147
+ if (item?.type !== "text" || item.props.text === text) return;
148
+ ctx.document.writeDraft(/* @__PURE__ */ new Map([[id, {
149
+ ...item,
150
+ props: {
151
+ ...item.props,
152
+ text
153
+ }
154
+ }]]));
155
+ }
156
+ function updateText(id, text, created = false) {
157
+ const item = ctx.document.displayItem(id);
158
+ if (!item || item.type !== "text" && item.type !== "shape" && item.type !== "arrow" && item.type !== "frame") return;
159
+ const next = item.type === "arrow" || item.type === "frame" ? {
160
+ ...item,
161
+ props: {
162
+ ...item.props,
163
+ label: text
164
+ }
165
+ } : {
166
+ ...item,
167
+ props: {
168
+ ...item.props,
169
+ text
170
+ }
171
+ };
172
+ if (!created && sameJson(next, state.base.items[id])) {
173
+ ctx.document.dropDraftItem(id);
174
+ ctx.document.rescene([id]);
175
+ return;
176
+ }
177
+ ctx.document.commitItems(/* @__PURE__ */ new Map([[id, next]]));
178
+ }
179
+ function commitTextEdit(id, text) {
180
+ const isDraft = id === state.draftTextId;
181
+ const target = ctx.document.displayItem(id);
182
+ const empty = text.trim() === "" && (isDraft || target?.type === "text");
183
+ state.editingId = null;
184
+ state.draftTextId = null;
185
+ if (empty) {
186
+ if (isDraft) {
187
+ ctx.document.dropDraftItem(id);
188
+ ctx.document.rescene();
189
+ } else ctx.deletion.deleteItem(id);
190
+ } else updateText(id, text, isDraft);
191
+ if (state.tool === "text") state.tool = "select";
192
+ ctx.remote.flushPending();
193
+ }
194
+ const styles = () => state.toolStyles;
195
+ return {
196
+ placeNew,
197
+ add,
198
+ addItem,
199
+ addApp: (app, at) => addOne(createAppBoardItem(app, at.x, at.y)),
200
+ addMedia: (src, at, options = {}) => addOne(createMediaBoardItem(src, at.x, at.y, options.snapshot, void 0, options.kind)),
201
+ addFile: (path, at, snapshot) => addOne(createFileNodeForPath(path, at.x, at.y, snapshot)),
202
+ addTask: (taskRunId, snapshot, at, metadata) => addOne(createTaskBoardItem(taskRunId, snapshot, at.x, at.y, metadata)),
203
+ addTaskWithSources,
204
+ addText: (text, at) => {
205
+ add([createTextBoardItem(text, at.x, at.y, styles().text.color)]);
206
+ },
207
+ addShape: (at, geometry) => {
208
+ const { shape } = styles();
209
+ add([createShapeBoardItem(geometry ?? shape.geometry, at.x, at.y, shape.color)]);
210
+ },
211
+ addFrame: (at) => {
212
+ add([createFrameBoardItem(at.x, at.y, styles().frame.color)]);
213
+ },
214
+ commitBox,
215
+ commitDraw,
216
+ commitArrow,
217
+ arrowEnd,
218
+ beginTextDraft,
219
+ previewTextLayout,
220
+ updateText,
221
+ commitTextEdit
222
+ };
223
+ }
224
+ //#endregion
225
+ export { createCreationModule };
@@ -0,0 +1,9 @@
1
+ import { EditorContext } from "./context.js";
2
+ //#region src/board/editor/deletion.d.ts
3
+ declare function createDeletionModule(ctx: EditorContext): {
4
+ deleteSelection: () => void;
5
+ deleteItem: (id: string) => void;
6
+ };
7
+ type DeletionModule = ReturnType<typeof createDeletionModule>;
8
+ //#endregion
9
+ export { DeletionModule, createDeletionModule };
@@ -0,0 +1,90 @@
1
+ import { applyMatrix, invertMatrix, isArrowBinding } from "../../protocol/dist/board-layout.js";
2
+ import { pruneBoardTrack } from "../../protocol/dist/board-patch.js";
3
+ import { resolveSceneArrow } from "../model/arrow-geometry.js";
4
+ //#region src/board/editor/deletion.ts
5
+ function createDeletionModule(ctx) {
6
+ const { state } = ctx;
7
+ function changesFor(ids) {
8
+ const { scene, base } = state;
9
+ const doomed = /* @__PURE__ */ new Set();
10
+ for (const id of ids) {
11
+ if (!base.items[id]) continue;
12
+ doomed.add(id);
13
+ for (const child of scene.descendants(id)) if (base.items[child]) doomed.add(child);
14
+ }
15
+ const changes = /* @__PURE__ */ new Map();
16
+ for (const id of doomed) changes.set(id, null);
17
+ for (const id of doomed) for (const arrowId of scene.binders(id)) {
18
+ if (!base.items[arrowId] || doomed.has(arrowId) || changes.has(arrowId)) continue;
19
+ const arrow = scene.get(arrowId);
20
+ if (!arrow) continue;
21
+ const resolved = resolveSceneArrow(arrow, scene);
22
+ const toLocal = invertMatrix(scene.layout.matrix(arrowId));
23
+ const free = (end, point) => {
24
+ if (!isArrowBinding(end) || !doomed.has(end.item)) return end;
25
+ const local = applyMatrix(toLocal, point);
26
+ return {
27
+ x: local.x,
28
+ y: local.y
29
+ };
30
+ };
31
+ const { id: _id, frame: _frame, ...stored } = arrow;
32
+ changes.set(arrowId, {
33
+ ...stored,
34
+ props: {
35
+ ...arrow.props,
36
+ start: free(arrow.props.start, resolved.start.point),
37
+ end: free(arrow.props.end, resolved.end.point)
38
+ }
39
+ });
40
+ }
41
+ let animations;
42
+ for (const [animationId, animation] of Object.entries(base.animations)) {
43
+ const tracks = { ...animation.tracks };
44
+ let changed = false;
45
+ for (const [id, track] of Object.entries(tracks)) {
46
+ const next = pruneBoardTrack(track, doomed);
47
+ if (next === track) continue;
48
+ changed = true;
49
+ if (next) tracks[id] = next;
50
+ else delete tracks[id];
51
+ }
52
+ if (!changed) continue;
53
+ animations ??= { ...base.animations };
54
+ animations[animationId] = {
55
+ ...animation,
56
+ tracks
57
+ };
58
+ }
59
+ return {
60
+ items: changes,
61
+ ...animations ? { animations } : {}
62
+ };
63
+ }
64
+ function deleteIds(ids) {
65
+ const { items: changes, animations } = changesFor(ids);
66
+ if (changes.size === 0) return;
67
+ for (const [id, item] of changes) ctx.document.setDraftItem(id, item);
68
+ ctx.document.commit(animations ? { animations } : {});
69
+ state.selection = state.selection.filter((id) => !changes.has(id) || changes.get(id) !== null);
70
+ if (state.editingId && changes.get(state.editingId) === null) state.editingId = null;
71
+ }
72
+ function deleteSelection() {
73
+ const ids = ctx.query.unlockedIds(state.selection);
74
+ if (ids.length === 0) return;
75
+ deleteIds(ids);
76
+ state.selection = [];
77
+ state.editingId = null;
78
+ }
79
+ function deleteItem(id) {
80
+ const target = state.scene.get(id);
81
+ if (!target || ctx.query.isLocked(target)) return;
82
+ deleteIds([id]);
83
+ }
84
+ return {
85
+ deleteSelection,
86
+ deleteItem
87
+ };
88
+ }
89
+ //#endregion
90
+ export { createDeletionModule };
@@ -0,0 +1,22 @@
1
+ import { BoardDocument, BoardItem, BoardPatch } from "../../protocol/dist/board-model.js";
2
+ import "../model/index.js";
3
+ //#region src/board/editor/document-edits.d.ts
4
+ declare function sameJson(a: unknown, b: unknown): boolean;
5
+ declare function readPath(value: unknown, path: readonly string[]): unknown;
6
+ declare function writePath<T>(value: T, path: readonly string[], next: unknown): T;
7
+ type BoardEditPlayhead = {
8
+ animationId: string;
9
+ time: number;
10
+ };
11
+ declare function routeBoardEdits(input: {
12
+ base: BoardDocument;
13
+ evaluated: ReadonlyMap<string, BoardItem>;
14
+ draft: ReadonlyMap<string, BoardItem | null>;
15
+ displayed?: ReadonlyMap<string, BoardItem>;
16
+ playhead: BoardEditPlayhead | null;
17
+ recording: boolean;
18
+ }): BoardDocument;
19
+ declare function isEmptyBoardPatch(patch: BoardPatch): boolean;
20
+ declare function diffBoardEdits(from: BoardDocument, to: BoardDocument, ids: Iterable<string>): BoardPatch;
21
+ //#endregion
22
+ export { BoardEditPlayhead, diffBoardEdits, isEmptyBoardPatch, readPath, routeBoardEdits, sameJson, writePath };
@@ -0,0 +1,193 @@
1
+ import { scaleVector } from "../../protocol/dist/board-layout.js";
2
+ import { diffMergePatch, listBoardProperties } from "../../protocol/dist/board-patch.js";
3
+ import { createBoardEntityId } from "../model/items/id.js";
4
+ //#region src/board/editor/document-edits.ts
5
+ function sameJson(a, b) {
6
+ if (a === b) return true;
7
+ if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
8
+ if (Array.isArray(a) || Array.isArray(b)) {
9
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
10
+ for (let index = 0; index < a.length; index += 1) if (!sameJson(a[index], b[index])) return false;
11
+ return true;
12
+ }
13
+ const left = a;
14
+ const right = b;
15
+ let members = 0;
16
+ for (const key of Object.keys(left)) {
17
+ if (left[key] === void 0) continue;
18
+ members += 1;
19
+ if (!sameJson(left[key], right[key])) return false;
20
+ }
21
+ for (const key of Object.keys(right)) if (right[key] !== void 0) members -= 1;
22
+ return members === 0;
23
+ }
24
+ function readPath(value, path) {
25
+ let current = value;
26
+ for (const segment of path) {
27
+ if (!current || typeof current !== "object") return void 0;
28
+ current = current[segment];
29
+ }
30
+ return current;
31
+ }
32
+ function writePath(value, path, next) {
33
+ const [head, ...rest] = path;
34
+ if (head === void 0) return next;
35
+ const record = value && typeof value === "object" ? value : {};
36
+ return {
37
+ ...record,
38
+ [head]: writePath(record[head], rest, next)
39
+ };
40
+ }
41
+ const KEYFRAMABLE_KINDS = /* @__PURE__ */ new Set([
42
+ "number",
43
+ "vec2",
44
+ "scale",
45
+ "color"
46
+ ]);
47
+ const STRUCTURAL_KEYS = [
48
+ "parent",
49
+ "z",
50
+ "locked",
51
+ "metadata"
52
+ ];
53
+ function keyframe(animations, playhead, recording, id, property, value, storedValue) {
54
+ const animation = animations[playhead.animationId];
55
+ if (!animation) return false;
56
+ const time = Math.round(playhead.time);
57
+ const existing = Object.entries(animation.tracks).find(([, track]) => track.target === id && track.property === property && track.composite === "replace");
58
+ if (!existing && !recording) return false;
59
+ const candidateId = `${id}-${property.replaceAll(".", "-")}`;
60
+ const newId = candidateId.length <= 160 && !Object.hasOwn(animation.tracks, candidateId) ? candidateId : createBoardEntityId();
61
+ const [trackId, track] = existing ?? [newId, {
62
+ target: id,
63
+ property,
64
+ keyframes: time > 0 ? [{
65
+ at: 0,
66
+ value: storedValue
67
+ }] : [],
68
+ composite: "replace",
69
+ interpolation: "auto"
70
+ }];
71
+ const keyframes = [...track.keyframes.filter((entry) => entry.at !== time), {
72
+ at: time,
73
+ value
74
+ }].sort((a, b) => a.at - b.at);
75
+ animations[playhead.animationId] = {
76
+ ...animation,
77
+ duration: Math.max(animation.duration, time),
78
+ tracks: {
79
+ ...animation.tracks,
80
+ [trackId]: {
81
+ ...track,
82
+ keyframes
83
+ }
84
+ }
85
+ };
86
+ return true;
87
+ }
88
+ function authoredValue(stored, shown, next, property = "") {
89
+ if (sameJson(shown, next)) return stored;
90
+ if (property === "scale" && stored !== void 0 && shown !== void 0 && next !== void 0 && [
91
+ stored,
92
+ shown,
93
+ next
94
+ ].some((value) => typeof value === "object")) return authoredValue(scaleVector(stored), scaleVector(shown), scaleVector(next), "scale.vector");
95
+ if (typeof stored === "number" && typeof shown === "number" && typeof next === "number") {
96
+ if (property === "opacity") return Math.max(0, Math.min(1, shown ? stored * next / shown : next));
97
+ if (property === "scale" || property.startsWith("scale.")) return shown ? stored * next / shown : next;
98
+ return stored + next - shown;
99
+ }
100
+ const record = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
101
+ if (record(stored) && record(shown) && record(next)) {
102
+ const result = { ...stored };
103
+ for (const key of /* @__PURE__ */ new Set([...Object.keys(shown), ...Object.keys(next)])) {
104
+ if (sameJson(shown[key], next[key])) continue;
105
+ if (!(key in next)) delete result[key];
106
+ else result[key] = authoredValue(stored[key], shown[key], next[key], property ? `${property}.${key}` : key);
107
+ }
108
+ return result;
109
+ }
110
+ return next;
111
+ }
112
+ function routeBoardEdits(input) {
113
+ const { base, evaluated, draft, playhead, recording } = input;
114
+ if (draft.size === 0) return base;
115
+ const items = { ...base.items };
116
+ const animations = { ...base.animations };
117
+ let keyed = false;
118
+ for (const [id, next] of draft) {
119
+ const stored = base.items[id];
120
+ if (!next) {
121
+ delete items[id];
122
+ continue;
123
+ }
124
+ if (!stored || next.type !== stored.type) {
125
+ items[id] = next;
126
+ continue;
127
+ }
128
+ const shown = input.displayed?.get(id) ?? evaluated.get(id) ?? stored;
129
+ if (!playhead) {
130
+ items[id] = authoredValue(stored, shown, next);
131
+ continue;
132
+ }
133
+ const properties = listBoardProperties(next.type);
134
+ let item = stored;
135
+ for (const { property, kind } of properties) {
136
+ const path = property.split(".");
137
+ const value = readPath(next, path);
138
+ if (sameJson(value, readPath(shown, path))) continue;
139
+ if (KEYFRAMABLE_KINDS.has(kind) && keyframe(animations, playhead, recording, id, property, value, readPath(stored, path))) keyed = true;
140
+ else item = writePath(item, path, authoredValue(readPath(stored, path), readPath(shown, path), value, property));
141
+ }
142
+ for (const key of STRUCTURAL_KEYS) if (!sameJson(next[key], shown[key])) {
143
+ const copy = { ...item };
144
+ if (next[key] === void 0) delete copy[key];
145
+ else copy[key] = next[key];
146
+ item = copy;
147
+ }
148
+ items[id] = item;
149
+ }
150
+ return {
151
+ ...base,
152
+ items,
153
+ animations: keyed ? animations : base.animations
154
+ };
155
+ }
156
+ function isEmptyBoardPatch(patch) {
157
+ return !patch.board && !patch.items && !patch.animations;
158
+ }
159
+ function diffBoardEdits(from, to, ids) {
160
+ const patch = {};
161
+ if (from.board !== to.board && !sameJson(from.board, to.board)) patch.board = diffMergePatch(from.board, to.board);
162
+ const itemPatch = {};
163
+ for (const id of new Set(ids)) {
164
+ const before = from.items[id];
165
+ const after = to.items[id];
166
+ if (before === after) continue;
167
+ if (!after) {
168
+ if (before) itemPatch[id] = null;
169
+ } else if (!before || before.type !== after.type) itemPatch[id] = after;
170
+ else {
171
+ const change = diffMergePatch(before, after);
172
+ if (change && typeof change === "object" && Object.keys(change).length) itemPatch[id] = change;
173
+ }
174
+ }
175
+ if (Object.keys(itemPatch).length) patch.items = itemPatch;
176
+ if (from.animations !== to.animations) {
177
+ const animationPatch = {};
178
+ for (const id of /* @__PURE__ */ new Set([...Object.keys(from.animations), ...Object.keys(to.animations)])) {
179
+ const before = from.animations[id];
180
+ const after = to.animations[id];
181
+ if (before === after) continue;
182
+ if (!after) animationPatch[id] = null;
183
+ else {
184
+ const change = diffMergePatch(before ?? {}, after);
185
+ if (change && typeof change === "object" && Object.keys(change).length) animationPatch[id] = change;
186
+ }
187
+ }
188
+ if (Object.keys(animationPatch).length) patch.animations = animationPatch;
189
+ }
190
+ return patch;
191
+ }
192
+ //#endregion
193
+ export { diffBoardEdits, isEmptyBoardPatch, readPath, routeBoardEdits, sameJson, writePath };
@@ -0,0 +1,41 @@
1
+ import { BoardAnimation, BoardDocument, BoardItem, BoardPatch, BoardSettings } from "../../protocol/dist/board-model.js";
2
+ import { BoardFrame } from "../../protocol/dist/board-layout.js";
3
+ import { Rect } from "../model/geometry.js";
4
+ import { BoardScene } from "../model/scene.js";
5
+ import "../model/index.js";
6
+ import { EditorContext } from "./context.js";
7
+ //#region src/board/editor/document.d.ts
8
+ declare function createDocumentModule(ctx: EditorContext): {
9
+ markAdded: (ids: readonly string[]) => void;
10
+ consumeRecentlyAdded: () => string[];
11
+ displayItem: (id: string) => BoardItem | undefined;
12
+ copyScene: () => BoardScene;
13
+ reevaluate: () => void;
14
+ setPlayedItems: (items: ReadonlyMap<string, BoardItem>) => void;
15
+ readonly hasScriptItems: boolean;
16
+ setScriptItems: (items: ReadonlyMap<string, BoardItem>) => void;
17
+ animationItems: () => Map<string, BoardItem>;
18
+ commitPatch: (patch: BoardPatch) => Promise<void> | undefined;
19
+ rescene: (ids?: Iterable<string>) => void;
20
+ reset: (next: BoardDocument) => void;
21
+ setDraftItem: (id: string, item: BoardItem | null) => void;
22
+ draftItem: (id: string) => BoardItem | null | undefined;
23
+ dropDraftItem: (id: string) => void;
24
+ writeDraft: (changes: ReadonlyMap<string, BoardItem | null>, structural?: boolean) => void;
25
+ discardDraft: () => void;
26
+ adopt: (next: BoardDocument, changedIds?: Iterable<string>) => void;
27
+ commit: (extra?: {
28
+ board?: BoardSettings;
29
+ animations?: Record<string, BoardAnimation>;
30
+ }, record?: boolean) => void;
31
+ commitItems: (changes: ReadonlyMap<string, BoardItem | null>, record?: boolean) => void;
32
+ undo: () => void;
33
+ redo: () => void;
34
+ previewSettings: (settings: BoardSettings) => void;
35
+ setSettings: (settings: BoardSettings) => void;
36
+ reparent: (item: BoardItem, frame: BoardFrame, parent: string | undefined, box: Rect) => BoardItem;
37
+ topZ: (parent: string | undefined, scene?: BoardScene) => number;
38
+ };
39
+ type DocumentModule = ReturnType<typeof createDocumentModule>;
40
+ //#endregion
41
+ export { DocumentModule, createDocumentModule };