@open-draw/canvas 0.0.0-stage → 0.1.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 (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -2
  3. package/dist/camera.d.ts +96 -0
  4. package/dist/camera.d.ts.map +1 -0
  5. package/dist/camera.js +208 -0
  6. package/dist/camera.js.map +1 -0
  7. package/dist/capabilities/clipping/defs.d.ts +7 -0
  8. package/dist/capabilities/clipping/defs.d.ts.map +1 -0
  9. package/dist/capabilities/clipping/defs.js +2 -0
  10. package/dist/capabilities/clipping/defs.js.map +1 -0
  11. package/dist/capabilities/clipping/index.d.ts +3 -0
  12. package/dist/capabilities/clipping/index.d.ts.map +1 -0
  13. package/dist/capabilities/clipping/index.js +3 -0
  14. package/dist/capabilities/clipping/index.js.map +1 -0
  15. package/dist/capabilities/clipping/manager.d.ts +14 -0
  16. package/dist/capabilities/clipping/manager.d.ts.map +1 -0
  17. package/dist/capabilities/clipping/manager.js +75 -0
  18. package/dist/capabilities/clipping/manager.js.map +1 -0
  19. package/dist/capabilities/connector/defs.d.ts +9 -0
  20. package/dist/capabilities/connector/defs.d.ts.map +1 -0
  21. package/dist/capabilities/connector/defs.js +2 -0
  22. package/dist/capabilities/connector/defs.js.map +1 -0
  23. package/dist/capabilities/connector/index.d.ts +3 -0
  24. package/dist/capabilities/connector/index.d.ts.map +1 -0
  25. package/dist/capabilities/connector/index.js +3 -0
  26. package/dist/capabilities/connector/index.js.map +1 -0
  27. package/dist/capabilities/connector/manager.d.ts +19 -0
  28. package/dist/capabilities/connector/manager.d.ts.map +1 -0
  29. package/dist/capabilities/connector/manager.js +108 -0
  30. package/dist/capabilities/connector/manager.js.map +1 -0
  31. package/dist/capabilities/text-editing/defs.d.ts +2 -0
  32. package/dist/capabilities/text-editing/defs.d.ts.map +1 -0
  33. package/dist/capabilities/text-editing/defs.js +2 -0
  34. package/dist/capabilities/text-editing/defs.js.map +1 -0
  35. package/dist/capabilities/text-editing/index.d.ts +3 -0
  36. package/dist/capabilities/text-editing/index.d.ts.map +1 -0
  37. package/dist/capabilities/text-editing/index.js +3 -0
  38. package/dist/capabilities/text-editing/index.js.map +1 -0
  39. package/dist/capabilities/text-editing/manager.d.ts +20 -0
  40. package/dist/capabilities/text-editing/manager.d.ts.map +1 -0
  41. package/dist/capabilities/text-editing/manager.js +135 -0
  42. package/dist/capabilities/text-editing/manager.js.map +1 -0
  43. package/dist/editor.d.ts +94 -0
  44. package/dist/editor.d.ts.map +1 -0
  45. package/dist/editor.js +240 -0
  46. package/dist/editor.js.map +1 -0
  47. package/dist/eraser/eraser.d.ts +21 -0
  48. package/dist/eraser/eraser.d.ts.map +1 -0
  49. package/dist/eraser/eraser.js +147 -0
  50. package/dist/eraser/eraser.js.map +1 -0
  51. package/dist/eraser/index.d.ts +2 -0
  52. package/dist/eraser/index.d.ts.map +1 -0
  53. package/dist/eraser/index.js +2 -0
  54. package/dist/eraser/index.js.map +1 -0
  55. package/dist/export/index.d.ts +2 -0
  56. package/dist/export/index.d.ts.map +1 -0
  57. package/dist/export/index.js +2 -0
  58. package/dist/export/index.js.map +1 -0
  59. package/dist/export/png.d.ts +17 -0
  60. package/dist/export/png.d.ts.map +1 -0
  61. package/dist/export/png.js +130 -0
  62. package/dist/export/png.js.map +1 -0
  63. package/dist/gesture/gesture.d.ts +36 -0
  64. package/dist/gesture/gesture.d.ts.map +1 -0
  65. package/dist/gesture/gesture.js +268 -0
  66. package/dist/gesture/gesture.js.map +1 -0
  67. package/dist/gesture/index.d.ts +2 -0
  68. package/dist/gesture/index.d.ts.map +1 -0
  69. package/dist/gesture/index.js +2 -0
  70. package/dist/gesture/index.js.map +1 -0
  71. package/dist/index.d.ts +36 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +37 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/input/commands.d.ts +12 -0
  76. package/dist/input/commands.d.ts.map +1 -0
  77. package/dist/input/commands.js +195 -0
  78. package/dist/input/commands.js.map +1 -0
  79. package/dist/input/index.d.ts +5 -0
  80. package/dist/input/index.d.ts.map +1 -0
  81. package/dist/input/index.js +5 -0
  82. package/dist/input/index.js.map +1 -0
  83. package/dist/input/keyboard.d.ts +13 -0
  84. package/dist/input/keyboard.d.ts.map +1 -0
  85. package/dist/input/keyboard.js +83 -0
  86. package/dist/input/keyboard.js.map +1 -0
  87. package/dist/input/keymap.d.ts +10 -0
  88. package/dist/input/keymap.d.ts.map +1 -0
  89. package/dist/input/keymap.js +75 -0
  90. package/dist/input/keymap.js.map +1 -0
  91. package/dist/input/utils.d.ts +5 -0
  92. package/dist/input/utils.d.ts.map +1 -0
  93. package/dist/input/utils.js +4 -0
  94. package/dist/input/utils.js.map +1 -0
  95. package/dist/interaction.d.ts +29 -0
  96. package/dist/interaction.d.ts.map +1 -0
  97. package/dist/interaction.js +248 -0
  98. package/dist/interaction.js.map +1 -0
  99. package/dist/perf/index.d.ts +2 -0
  100. package/dist/perf/index.d.ts.map +1 -0
  101. package/dist/perf/index.js +2 -0
  102. package/dist/perf/index.js.map +1 -0
  103. package/dist/perf/telemetry.d.ts +33 -0
  104. package/dist/perf/telemetry.d.ts.map +1 -0
  105. package/dist/perf/telemetry.js +145 -0
  106. package/dist/perf/telemetry.js.map +1 -0
  107. package/dist/registry.d.ts +68 -0
  108. package/dist/registry.d.ts.map +1 -0
  109. package/dist/registry.js +34 -0
  110. package/dist/registry.js.map +1 -0
  111. package/dist/renderer.d.ts +29 -0
  112. package/dist/renderer.d.ts.map +1 -0
  113. package/dist/renderer.js +252 -0
  114. package/dist/renderer.js.map +1 -0
  115. package/dist/selection/defs.d.ts +6 -0
  116. package/dist/selection/defs.d.ts.map +1 -0
  117. package/dist/selection/defs.js +2 -0
  118. package/dist/selection/defs.js.map +1 -0
  119. package/dist/selection/group.d.ts +7 -0
  120. package/dist/selection/group.d.ts.map +1 -0
  121. package/dist/selection/group.js +25 -0
  122. package/dist/selection/group.js.map +1 -0
  123. package/dist/selection/handles.d.ts +9 -0
  124. package/dist/selection/handles.d.ts.map +1 -0
  125. package/dist/selection/handles.js +19 -0
  126. package/dist/selection/handles.js.map +1 -0
  127. package/dist/selection/handlesView.d.ts +4 -0
  128. package/dist/selection/handlesView.d.ts.map +1 -0
  129. package/dist/selection/handlesView.js +94 -0
  130. package/dist/selection/handlesView.js.map +1 -0
  131. package/dist/selection/index.d.ts +10 -0
  132. package/dist/selection/index.d.ts.map +1 -0
  133. package/dist/selection/index.js +10 -0
  134. package/dist/selection/index.js.map +1 -0
  135. package/dist/selection/manager.d.ts +29 -0
  136. package/dist/selection/manager.d.ts.map +1 -0
  137. package/dist/selection/manager.js +195 -0
  138. package/dist/selection/manager.js.map +1 -0
  139. package/dist/selection/marquee.d.ts +11 -0
  140. package/dist/selection/marquee.d.ts.map +1 -0
  141. package/dist/selection/marquee.js +52 -0
  142. package/dist/selection/marquee.js.map +1 -0
  143. package/dist/selection/reparent.d.ts +12 -0
  144. package/dist/selection/reparent.d.ts.map +1 -0
  145. package/dist/selection/reparent.js +57 -0
  146. package/dist/selection/reparent.js.map +1 -0
  147. package/dist/selection/resize.d.ts +10 -0
  148. package/dist/selection/resize.d.ts.map +1 -0
  149. package/dist/selection/resize.js +66 -0
  150. package/dist/selection/resize.js.map +1 -0
  151. package/dist/selection/rotate.d.ts +18 -0
  152. package/dist/selection/rotate.d.ts.map +1 -0
  153. package/dist/selection/rotate.js +39 -0
  154. package/dist/selection/rotate.js.map +1 -0
  155. package/dist/shapes/arrow/defs.d.ts +17 -0
  156. package/dist/shapes/arrow/defs.d.ts.map +1 -0
  157. package/dist/shapes/arrow/defs.js +7 -0
  158. package/dist/shapes/arrow/defs.js.map +1 -0
  159. package/dist/shapes/arrow/geometry.d.ts +11 -0
  160. package/dist/shapes/arrow/geometry.d.ts.map +1 -0
  161. package/dist/shapes/arrow/geometry.js +77 -0
  162. package/dist/shapes/arrow/geometry.js.map +1 -0
  163. package/dist/shapes/arrow/index.d.ts +7 -0
  164. package/dist/shapes/arrow/index.d.ts.map +1 -0
  165. package/dist/shapes/arrow/index.js +23 -0
  166. package/dist/shapes/arrow/index.js.map +1 -0
  167. package/dist/shapes/arrow/render.d.ts +6 -0
  168. package/dist/shapes/arrow/render.d.ts.map +1 -0
  169. package/dist/shapes/arrow/render.js +84 -0
  170. package/dist/shapes/arrow/render.js.map +1 -0
  171. package/dist/shapes/ellipse/defs.d.ts +8 -0
  172. package/dist/shapes/ellipse/defs.d.ts.map +1 -0
  173. package/dist/shapes/ellipse/defs.js +2 -0
  174. package/dist/shapes/ellipse/defs.js.map +1 -0
  175. package/dist/shapes/ellipse/geometry.d.ts +9 -0
  176. package/dist/shapes/ellipse/geometry.d.ts.map +1 -0
  177. package/dist/shapes/ellipse/geometry.js +74 -0
  178. package/dist/shapes/ellipse/geometry.js.map +1 -0
  179. package/dist/shapes/ellipse/index.d.ts +7 -0
  180. package/dist/shapes/ellipse/index.d.ts.map +1 -0
  181. package/dist/shapes/ellipse/index.js +21 -0
  182. package/dist/shapes/ellipse/index.js.map +1 -0
  183. package/dist/shapes/ellipse/render.d.ts +6 -0
  184. package/dist/shapes/ellipse/render.d.ts.map +1 -0
  185. package/dist/shapes/ellipse/render.js +39 -0
  186. package/dist/shapes/ellipse/render.js.map +1 -0
  187. package/dist/shapes/frame/defs.d.ts +9 -0
  188. package/dist/shapes/frame/defs.d.ts.map +1 -0
  189. package/dist/shapes/frame/defs.js +8 -0
  190. package/dist/shapes/frame/defs.js.map +1 -0
  191. package/dist/shapes/frame/geometry.d.ts +4 -0
  192. package/dist/shapes/frame/geometry.d.ts.map +1 -0
  193. package/dist/shapes/frame/geometry.js +66 -0
  194. package/dist/shapes/frame/geometry.js.map +1 -0
  195. package/dist/shapes/frame/index.d.ts +7 -0
  196. package/dist/shapes/frame/index.d.ts.map +1 -0
  197. package/dist/shapes/frame/index.js +20 -0
  198. package/dist/shapes/frame/index.js.map +1 -0
  199. package/dist/shapes/frame/render.d.ts +6 -0
  200. package/dist/shapes/frame/render.d.ts.map +1 -0
  201. package/dist/shapes/frame/render.js +73 -0
  202. package/dist/shapes/frame/render.js.map +1 -0
  203. package/dist/shapes/group/defs.d.ts +6 -0
  204. package/dist/shapes/group/defs.d.ts.map +1 -0
  205. package/dist/shapes/group/defs.js +2 -0
  206. package/dist/shapes/group/defs.js.map +1 -0
  207. package/dist/shapes/group/geometry.d.ts +8 -0
  208. package/dist/shapes/group/geometry.d.ts.map +1 -0
  209. package/dist/shapes/group/geometry.js +19 -0
  210. package/dist/shapes/group/geometry.js.map +1 -0
  211. package/dist/shapes/group/index.d.ts +7 -0
  212. package/dist/shapes/group/index.d.ts.map +1 -0
  213. package/dist/shapes/group/index.js +23 -0
  214. package/dist/shapes/group/index.js.map +1 -0
  215. package/dist/shapes/group/render.d.ts +6 -0
  216. package/dist/shapes/group/render.d.ts.map +1 -0
  217. package/dist/shapes/group/render.js +9 -0
  218. package/dist/shapes/group/render.js.map +1 -0
  219. package/dist/shapes/image/defs.d.ts +10 -0
  220. package/dist/shapes/image/defs.d.ts.map +1 -0
  221. package/dist/shapes/image/defs.js +2 -0
  222. package/dist/shapes/image/defs.js.map +1 -0
  223. package/dist/shapes/image/geometry.d.ts +21 -0
  224. package/dist/shapes/image/geometry.d.ts.map +1 -0
  225. package/dist/shapes/image/geometry.js +79 -0
  226. package/dist/shapes/image/geometry.js.map +1 -0
  227. package/dist/shapes/image/handlers.d.ts +10 -0
  228. package/dist/shapes/image/handlers.d.ts.map +1 -0
  229. package/dist/shapes/image/handlers.js +85 -0
  230. package/dist/shapes/image/handlers.js.map +1 -0
  231. package/dist/shapes/image/index.d.ts +8 -0
  232. package/dist/shapes/image/index.d.ts.map +1 -0
  233. package/dist/shapes/image/index.js +21 -0
  234. package/dist/shapes/image/index.js.map +1 -0
  235. package/dist/shapes/image/render.d.ts +6 -0
  236. package/dist/shapes/image/render.d.ts.map +1 -0
  237. package/dist/shapes/image/render.js +28 -0
  238. package/dist/shapes/image/render.js.map +1 -0
  239. package/dist/shapes/ink/defs.d.ts +10 -0
  240. package/dist/shapes/ink/defs.d.ts.map +1 -0
  241. package/dist/shapes/ink/defs.js +13 -0
  242. package/dist/shapes/ink/defs.js.map +1 -0
  243. package/dist/shapes/ink/geometry.d.ts +4 -0
  244. package/dist/shapes/ink/geometry.d.ts.map +1 -0
  245. package/dist/shapes/ink/geometry.js +67 -0
  246. package/dist/shapes/ink/geometry.js.map +1 -0
  247. package/dist/shapes/ink/index.d.ts +9 -0
  248. package/dist/shapes/ink/index.d.ts.map +1 -0
  249. package/dist/shapes/ink/index.js +22 -0
  250. package/dist/shapes/ink/index.js.map +1 -0
  251. package/dist/shapes/ink/rdp.d.ts +2 -0
  252. package/dist/shapes/ink/rdp.d.ts.map +1 -0
  253. package/dist/shapes/ink/rdp.js +37 -0
  254. package/dist/shapes/ink/rdp.js.map +1 -0
  255. package/dist/shapes/ink/render.d.ts +7 -0
  256. package/dist/shapes/ink/render.d.ts.map +1 -0
  257. package/dist/shapes/ink/render.js +81 -0
  258. package/dist/shapes/ink/render.js.map +1 -0
  259. package/dist/shapes/note/defs.d.ts +7 -0
  260. package/dist/shapes/note/defs.d.ts.map +1 -0
  261. package/dist/shapes/note/defs.js +2 -0
  262. package/dist/shapes/note/defs.js.map +1 -0
  263. package/dist/shapes/note/geometry.d.ts +11 -0
  264. package/dist/shapes/note/geometry.d.ts.map +1 -0
  265. package/dist/shapes/note/geometry.js +70 -0
  266. package/dist/shapes/note/geometry.js.map +1 -0
  267. package/dist/shapes/note/index.d.ts +7 -0
  268. package/dist/shapes/note/index.d.ts.map +1 -0
  269. package/dist/shapes/note/index.js +41 -0
  270. package/dist/shapes/note/index.js.map +1 -0
  271. package/dist/shapes/note/render.d.ts +6 -0
  272. package/dist/shapes/note/render.d.ts.map +1 -0
  273. package/dist/shapes/note/render.js +38 -0
  274. package/dist/shapes/note/render.js.map +1 -0
  275. package/dist/shapes/rect/defs.d.ts +9 -0
  276. package/dist/shapes/rect/defs.d.ts.map +1 -0
  277. package/dist/shapes/rect/defs.js +2 -0
  278. package/dist/shapes/rect/defs.js.map +1 -0
  279. package/dist/shapes/rect/geometry.d.ts +9 -0
  280. package/dist/shapes/rect/geometry.d.ts.map +1 -0
  281. package/dist/shapes/rect/geometry.js +68 -0
  282. package/dist/shapes/rect/geometry.js.map +1 -0
  283. package/dist/shapes/rect/index.d.ts +7 -0
  284. package/dist/shapes/rect/index.d.ts.map +1 -0
  285. package/dist/shapes/rect/index.js +22 -0
  286. package/dist/shapes/rect/index.js.map +1 -0
  287. package/dist/shapes/rect/render.d.ts +6 -0
  288. package/dist/shapes/rect/render.d.ts.map +1 -0
  289. package/dist/shapes/rect/render.js +42 -0
  290. package/dist/shapes/rect/render.js.map +1 -0
  291. package/dist/shapes/text/defs.d.ts +9 -0
  292. package/dist/shapes/text/defs.d.ts.map +1 -0
  293. package/dist/shapes/text/defs.js +2 -0
  294. package/dist/shapes/text/defs.js.map +1 -0
  295. package/dist/shapes/text/geometry.d.ts +9 -0
  296. package/dist/shapes/text/geometry.d.ts.map +1 -0
  297. package/dist/shapes/text/geometry.js +68 -0
  298. package/dist/shapes/text/geometry.js.map +1 -0
  299. package/dist/shapes/text/index.d.ts +7 -0
  300. package/dist/shapes/text/index.d.ts.map +1 -0
  301. package/dist/shapes/text/index.js +43 -0
  302. package/dist/shapes/text/index.js.map +1 -0
  303. package/dist/shapes/text/render.d.ts +6 -0
  304. package/dist/shapes/text/render.d.ts.map +1 -0
  305. package/dist/shapes/text/render.js +23 -0
  306. package/dist/shapes/text/render.js.map +1 -0
  307. package/dist/store/index.d.ts +5 -0
  308. package/dist/store/index.d.ts.map +1 -0
  309. package/dist/store/index.js +5 -0
  310. package/dist/store/index.js.map +1 -0
  311. package/dist/store/snapshot.d.ts +5 -0
  312. package/dist/store/snapshot.d.ts.map +1 -0
  313. package/dist/store/snapshot.js +76 -0
  314. package/dist/store/snapshot.js.map +1 -0
  315. package/dist/store/store.d.ts +52 -0
  316. package/dist/store/store.d.ts.map +1 -0
  317. package/dist/store/store.js +252 -0
  318. package/dist/store/store.js.map +1 -0
  319. package/dist/store/types.d.ts +13 -0
  320. package/dist/store/types.d.ts.map +1 -0
  321. package/dist/store/types.js +2 -0
  322. package/dist/store/types.js.map +1 -0
  323. package/dist/store/zorder.d.ts +4 -0
  324. package/dist/store/zorder.d.ts.map +1 -0
  325. package/dist/store/zorder.js +53 -0
  326. package/dist/store/zorder.js.map +1 -0
  327. package/package.json +29 -4
@@ -0,0 +1,108 @@
1
+ import { getAnchorPoint } from '../../shapes/arrow/index.js';
2
+ export class ConnectorManager {
3
+ unbindListeners = new Set();
4
+ onTargetUnbound(listener) {
5
+ this.unbindListeners.add(listener);
6
+ return () => this.unbindListeners.delete(listener);
7
+ }
8
+ emitUnbound(event) {
9
+ for (const listener of this.unbindListeners) {
10
+ try {
11
+ listener(event);
12
+ }
13
+ catch (err) {
14
+ console.error('Target unbound listener error:', err);
15
+ }
16
+ }
17
+ }
18
+ handleTargetDeletion(deletedShapeId, deletedShapeRecord, store, registry) {
19
+ const arrowsToUpdate = [];
20
+ for (const shape of store.listShapes()) {
21
+ const def = registry.get(shape.type);
22
+ if (!def?.capabilities?.connector)
23
+ continue;
24
+ const props = shape.props;
25
+ const patchProps = {};
26
+ const events = [];
27
+ const startBinding = props.startBinding;
28
+ if (startBinding && startBinding.shapeId === deletedShapeId) {
29
+ let fallbackPoint = props.startPoint ?? { x: shape.x, y: shape.y };
30
+ if (deletedShapeRecord) {
31
+ const targetDef = registry.get(deletedShapeRecord.type);
32
+ if (targetDef) {
33
+ fallbackPoint = getAnchorPoint(targetDef.geometry.bounds(deletedShapeRecord), startBinding.anchor);
34
+ }
35
+ }
36
+ patchProps.startBinding = undefined;
37
+ patchProps.startPoint = fallbackPoint;
38
+ events.push({
39
+ arrowId: shape.id,
40
+ which: 'start',
41
+ previousTargetId: deletedShapeId,
42
+ fallbackPoint,
43
+ });
44
+ }
45
+ const endBinding = props.endBinding;
46
+ if (endBinding && endBinding.shapeId === deletedShapeId) {
47
+ let fallbackPoint = props.endPoint ?? { x: shape.x + 100, y: shape.y };
48
+ if (deletedShapeRecord) {
49
+ const targetDef = registry.get(deletedShapeRecord.type);
50
+ if (targetDef) {
51
+ fallbackPoint = getAnchorPoint(targetDef.geometry.bounds(deletedShapeRecord), endBinding.anchor);
52
+ }
53
+ }
54
+ patchProps.endBinding = undefined;
55
+ patchProps.endPoint = fallbackPoint;
56
+ events.push({
57
+ arrowId: shape.id,
58
+ which: 'end',
59
+ previousTargetId: deletedShapeId,
60
+ fallbackPoint,
61
+ });
62
+ }
63
+ if (events.length > 0) {
64
+ arrowsToUpdate.push({ arrow: shape, patchProps, events });
65
+ }
66
+ }
67
+ if (arrowsToUpdate.length === 0)
68
+ return;
69
+ store.transact(() => {
70
+ for (const item of arrowsToUpdate) {
71
+ store.updateShape(item.arrow.id, {
72
+ props: {
73
+ ...item.arrow.props,
74
+ ...item.patchProps,
75
+ },
76
+ });
77
+ for (const ev of item.events) {
78
+ this.emitUnbound(ev);
79
+ }
80
+ }
81
+ });
82
+ }
83
+ findSnapTarget(pointerPagePt, shapes, registry, camera, excludeId) {
84
+ const anchors = ['top', 'right', 'bottom', 'left', 'center'];
85
+ let closestTarget = null;
86
+ let minDistance = 12;
87
+ const screenPointer = camera ? camera.pageToScreen(pointerPagePt) : pointerPagePt;
88
+ for (const shape of shapes) {
89
+ if (shape.id === excludeId)
90
+ continue;
91
+ const def = registry.get(shape.type);
92
+ if (!def || def.capabilities?.connector)
93
+ continue;
94
+ const bounds = def.geometry.bounds(shape);
95
+ for (const anchor of anchors) {
96
+ const pt = getAnchorPoint(bounds, anchor);
97
+ const screenAnchor = camera ? camera.pageToScreen(pt) : pt;
98
+ const dist = Math.hypot(screenPointer.x - screenAnchor.x, screenPointer.y - screenAnchor.y);
99
+ if (dist <= minDistance) {
100
+ minDistance = dist;
101
+ closestTarget = { shapeId: shape.id, anchor, point: pt };
102
+ }
103
+ }
104
+ }
105
+ return closestTarget;
106
+ }
107
+ }
108
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/capabilities/connector/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export type EditorMode = 'none' | 'editing';
2
+ //# sourceMappingURL=defs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/capabilities/text-editing/defs.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=defs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defs.js","sourceRoot":"","sources":["../../../src/capabilities/text-editing/defs.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export * from './defs.js';
2
+ export * from './manager.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/capabilities/text-editing/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './defs.js';
2
+ export * from './manager.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/capabilities/text-editing/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ShapeId } from '@open-draw/schema';
2
+ import type { CanvasEditor } from '../../editor.js';
3
+ export declare class TextEditingManager {
4
+ private activeShapeId;
5
+ private foreignObject;
6
+ private textarea;
7
+ private initialText;
8
+ private currentEditor;
9
+ private isCommitting;
10
+ isEditing(): boolean;
11
+ getActiveShapeId(): ShapeId | null;
12
+ startEditing(shapeId: ShapeId, editor: CanvasEditor): boolean;
13
+ commit(): void;
14
+ cancel(): void;
15
+ private onKeyDown;
16
+ private onBlur;
17
+ private cleanupDOM;
18
+ private resetState;
19
+ }
20
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/capabilities/text-editing/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,YAAY,CAAS;IAE7B,SAAS,IAAI,OAAO,CAEnB;IAED,gBAAgB,IAAI,OAAO,GAAG,IAAI,CAEjC;IAED,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CA+D5D;IAED,MAAM,IAAI,IAAI,CAkCb;IAED,MAAM,IAAI,IAAI,CAKb;IAED,OAAO,CAAC,SAAS,CAMf;IAEF,OAAO,CAAC,MAAM,CAEZ;IAEF,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;CAOnB"}
@@ -0,0 +1,135 @@
1
+ export class TextEditingManager {
2
+ activeShapeId = null;
3
+ foreignObject = null;
4
+ textarea = null;
5
+ initialText = '';
6
+ currentEditor = null;
7
+ isCommitting = false;
8
+ isEditing() {
9
+ return this.activeShapeId !== null;
10
+ }
11
+ getActiveShapeId() {
12
+ return this.activeShapeId;
13
+ }
14
+ startEditing(shapeId, editor) {
15
+ if (this.activeShapeId) {
16
+ this.commit();
17
+ }
18
+ const shape = editor.store.getShape(shapeId);
19
+ if (!shape)
20
+ return false;
21
+ const def = editor.registry.get(shape.type);
22
+ if (!def?.capabilities?.text?.canEditText(shape)) {
23
+ return false;
24
+ }
25
+ const slot = editor.getOverlaySlot(shapeId);
26
+ if (!slot)
27
+ return false;
28
+ this.activeShapeId = shapeId;
29
+ this.currentEditor = editor;
30
+ editor.mode = 'editing';
31
+ const textCap = def.capabilities.text;
32
+ this.initialText = textCap.getText(shape);
33
+ const bounds = def.geometry.bounds(shape);
34
+ const fo = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
35
+ fo.setAttribute('class', 'od-text-editing-fo');
36
+ fo.setAttribute('x', '0');
37
+ fo.setAttribute('y', '0');
38
+ fo.setAttribute('width', String(Math.max(bounds.width, 100)));
39
+ fo.setAttribute('height', String(Math.max(bounds.height, 60)));
40
+ fo.style.pointerEvents = 'auto';
41
+ const textarea = document.createElement('textarea');
42
+ textarea.className = 'od-text-editor';
43
+ textarea.value = this.initialText;
44
+ textarea.style.width = '100%';
45
+ textarea.style.height = '100%';
46
+ textarea.style.pointerEvents = 'auto';
47
+ textarea.style.background = 'rgba(255, 255, 255, 0.9)';
48
+ textarea.style.border = '1px solid #3b82f6';
49
+ textarea.style.borderRadius = '3px';
50
+ textarea.style.padding = '4px 8px';
51
+ textarea.style.boxSizing = 'border-box';
52
+ textarea.style.outline = 'none';
53
+ textarea.style.resize = 'none';
54
+ textarea.style.font = 'inherit';
55
+ textarea.style.color = 'inherit';
56
+ textarea.addEventListener('keydown', this.onKeyDown);
57
+ textarea.addEventListener('blur', this.onBlur);
58
+ fo.appendChild(textarea);
59
+ slot.appendChild(fo);
60
+ this.foreignObject = fo;
61
+ this.textarea = textarea;
62
+ setTimeout(() => {
63
+ textarea.focus();
64
+ textarea.select();
65
+ }, 0);
66
+ return true;
67
+ }
68
+ commit() {
69
+ if (this.isCommitting || !this.activeShapeId || !this.currentEditor)
70
+ return;
71
+ this.isCommitting = true;
72
+ const shapeId = this.activeShapeId;
73
+ const editor = this.currentEditor;
74
+ const newText = this.textarea?.value ?? '';
75
+ const initialText = this.initialText;
76
+ this.cleanupDOM();
77
+ const shape = editor.store.getShape(shapeId);
78
+ if (!shape) {
79
+ this.resetState(editor);
80
+ return;
81
+ }
82
+ const def = editor.registry.get(shape.type);
83
+ const textCap = def?.capabilities?.text;
84
+ if (newText.trim() === '') {
85
+ // Empty text on commit -> shape deleted in one transaction
86
+ editor.store.transact(() => {
87
+ editor.deleteShape(shapeId);
88
+ });
89
+ }
90
+ else if (newText !== initialText && textCap) {
91
+ // Apply updated text and auto-grown bounds in single transaction
92
+ const patch = textCap.setText(shape, newText);
93
+ editor.store.transact(() => {
94
+ editor.store.updateShape(shapeId, patch);
95
+ });
96
+ }
97
+ this.resetState(editor);
98
+ }
99
+ cancel() {
100
+ if (!this.activeShapeId || !this.currentEditor)
101
+ return;
102
+ const editor = this.currentEditor;
103
+ this.cleanupDOM();
104
+ this.resetState(editor);
105
+ }
106
+ onKeyDown = (e) => {
107
+ if (e.key === 'Escape') {
108
+ e.preventDefault();
109
+ e.stopPropagation();
110
+ this.cancel();
111
+ }
112
+ };
113
+ onBlur = () => {
114
+ this.commit();
115
+ };
116
+ cleanupDOM() {
117
+ if (this.textarea) {
118
+ this.textarea.removeEventListener('keydown', this.onKeyDown);
119
+ this.textarea.removeEventListener('blur', this.onBlur);
120
+ }
121
+ if (this.foreignObject && this.foreignObject.parentNode) {
122
+ this.foreignObject.parentNode.removeChild(this.foreignObject);
123
+ }
124
+ this.foreignObject = null;
125
+ this.textarea = null;
126
+ }
127
+ resetState(editor) {
128
+ this.activeShapeId = null;
129
+ this.currentEditor = null;
130
+ this.initialText = '';
131
+ this.isCommitting = false;
132
+ editor.mode = 'none';
133
+ }
134
+ }
135
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/capabilities/text-editing/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import type { Camera, Point, ShapeId, ShapeRecord, Snapshot } from '@open-draw/schema';
2
+ import { CameraController, type ZoomOptions } from './camera.js';
3
+ import { ShapeRegistry, type ShapeDefinition } from './registry.js';
4
+ import { SVGRenderer } from './renderer.js';
5
+ import { CanvasStore } from './store/index.js';
6
+ import { PointerInteractionController } from './interaction.js';
7
+ import { TextEditingManager, type EditorMode } from './capabilities/text-editing/index.js';
8
+ import { ClippingManager } from './capabilities/clipping/index.js';
9
+ import { ConnectorManager } from './capabilities/connector/index.js';
10
+ import { SelectionManager } from './selection/index.js';
11
+ import { KeyboardDispatcher, type KeyBinding } from './input/index.js';
12
+ import { GestureController } from './gesture/index.js';
13
+ import { FrameTelemetry } from './perf/index.js';
14
+ import { type ExportPngOptions } from './export/index.js';
15
+ export interface CanvasEditorOptions {
16
+ readonly readonly?: boolean;
17
+ readonly keymap?: readonly KeyBinding[];
18
+ }
19
+ /**
20
+ * OpenDraw Canvas Editor
21
+ * Composition point for camera, store, registry, renderer, and privileged capabilities.
22
+ */
23
+ export declare class CanvasEditor {
24
+ readonly store: CanvasStore;
25
+ readonly camera: CameraController;
26
+ readonly options: CanvasEditorOptions;
27
+ readonly registry: ShapeRegistry;
28
+ readonly renderer: SVGRenderer;
29
+ readonly interaction: PointerInteractionController;
30
+ readonly textEditing: TextEditingManager;
31
+ readonly clipping: ClippingManager;
32
+ readonly connector: ConnectorManager;
33
+ readonly selectionManager: SelectionManager;
34
+ readonly keyboard: KeyboardDispatcher;
35
+ readonly gesture: GestureController;
36
+ readonly telemetry: FrameTelemetry;
37
+ mode: EditorMode;
38
+ private isMounted;
39
+ private container;
40
+ private unsubscribeCamera;
41
+ private unsubscribeStore;
42
+ private detachImageTransfer;
43
+ private activeTool;
44
+ constructor(options?: CanvasEditorOptions);
45
+ registerShape<P = Record<string, unknown>>(definition: ShapeDefinition<P>): void;
46
+ mount(container: HTMLElement): void;
47
+ destroy(): void;
48
+ getContainer(): HTMLElement | null;
49
+ setTool(toolId: string): void;
50
+ getTool(): string;
51
+ get selection(): readonly ShapeId[];
52
+ getSelection(): readonly ShapeId[];
53
+ setSelection(ids: readonly ShapeId[]): void;
54
+ selectShape(shapeId: ShapeId | null): void;
55
+ getSelectedShapeId(): ShapeId | null;
56
+ toggleSelection(shapeId: ShapeId): void;
57
+ addToSelection(ids: readonly ShapeId[]): void;
58
+ clearSelection(): void;
59
+ selectAll(): void;
60
+ isSelected(id: ShapeId): boolean;
61
+ cycleSelection(direction?: 'forward' | 'backward'): void;
62
+ bringToFront(ids?: readonly ShapeId[]): void;
63
+ sendToBack(ids?: readonly ShapeId[]): void;
64
+ bringForward(ids?: readonly ShapeId[]): void;
65
+ sendBackward(ids?: readonly ShapeId[]): void;
66
+ createShape(record: {
67
+ readonly id?: ShapeId;
68
+ readonly type: string;
69
+ readonly x: number;
70
+ readonly y: number;
71
+ readonly rotation?: number;
72
+ readonly hidden?: boolean;
73
+ readonly meta?: Record<string, unknown>;
74
+ readonly props?: Record<string, unknown>;
75
+ }): ShapeRecord;
76
+ updateShape(id: ShapeId, patch: Partial<Omit<ShapeRecord, 'id' | 'type'>>): ShapeRecord;
77
+ deleteShape(id: ShapeId): boolean;
78
+ getShape(id: ShapeId): ShapeRecord | undefined;
79
+ canUndo(): boolean;
80
+ canRedo(): boolean;
81
+ clearHistory(): void;
82
+ undo(): boolean;
83
+ redo(): boolean;
84
+ loadSnapshot(snapshot: Snapshot): void;
85
+ getSnapshot(): Snapshot;
86
+ pan(dx: number, dy: number): Camera;
87
+ zoomAroundPoint(screenPoint: Point, factor: number, options?: ZoomOptions): Camera;
88
+ setCamera(camera: Camera): void;
89
+ getOverlaySlot(id: ShapeId): SVGGElement | null;
90
+ getShapeWrapper(id: ShapeId): SVGGElement | null;
91
+ exportPNG(options?: ExportPngOptions): Promise<Blob>;
92
+ private onDblClick;
93
+ }
94
+ //# sourceMappingURL=editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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"}
package/dist/editor.js ADDED
@@ -0,0 +1,240 @@
1
+ import { CameraController } from './camera.js';
2
+ import { ShapeRegistry } from './registry.js';
3
+ import { SVGRenderer } from './renderer.js';
4
+ import { groupDefinition } from './shapes/group/index.js';
5
+ import { rectDefinition } from './shapes/rect/index.js';
6
+ import { ellipseDefinition } from './shapes/ellipse/index.js';
7
+ import { noteDefinition } from './shapes/note/index.js';
8
+ import { imageDefinition, attachImageTransferHandlers } from './shapes/image/index.js';
9
+ import { textDefinition } from './shapes/text/index.js';
10
+ import { frameDefinition } from './shapes/frame/index.js';
11
+ import { arrowDefinition } from './shapes/arrow/index.js';
12
+ import { inkDefinition, highlighterDefinition } from './shapes/ink/index.js';
13
+ import { CanvasStore } from './store/index.js';
14
+ import { PointerInteractionController } from './interaction.js';
15
+ import { TextEditingManager } from './capabilities/text-editing/index.js';
16
+ import { ClippingManager } from './capabilities/clipping/index.js';
17
+ import { ConnectorManager } from './capabilities/connector/index.js';
18
+ import { SelectionManager } from './selection/index.js';
19
+ import { KeyboardDispatcher } from './input/index.js';
20
+ import { GestureController } from './gesture/index.js';
21
+ import { FrameTelemetry } from './perf/index.js';
22
+ import { exportPNG } from './export/index.js';
23
+ /**
24
+ * OpenDraw Canvas Editor
25
+ * Composition point for camera, store, registry, renderer, and privileged capabilities.
26
+ */
27
+ export class CanvasEditor {
28
+ store;
29
+ camera;
30
+ options;
31
+ registry;
32
+ renderer;
33
+ interaction;
34
+ textEditing;
35
+ clipping;
36
+ connector;
37
+ selectionManager;
38
+ keyboard;
39
+ gesture;
40
+ telemetry;
41
+ mode = 'none';
42
+ isMounted = false;
43
+ container = null;
44
+ unsubscribeCamera = null;
45
+ unsubscribeStore = null;
46
+ detachImageTransfer = null;
47
+ activeTool = 'select';
48
+ constructor(options = {}) {
49
+ this.options = options;
50
+ this.store = new CanvasStore();
51
+ this.camera = new CameraController();
52
+ this.registry = new ShapeRegistry();
53
+ this.renderer = new SVGRenderer(this.registry);
54
+ this.gesture = new GestureController(this);
55
+ this.telemetry = new FrameTelemetry();
56
+ this.interaction = new PointerInteractionController(this);
57
+ this.textEditing = new TextEditingManager();
58
+ this.clipping = new ClippingManager();
59
+ this.connector = new ConnectorManager();
60
+ this.selectionManager = new SelectionManager();
61
+ this.keyboard = new KeyboardDispatcher(this, options.keymap);
62
+ const builtins = [
63
+ rectDefinition, ellipseDefinition, noteDefinition, imageDefinition,
64
+ textDefinition, frameDefinition, arrowDefinition, inkDefinition,
65
+ highlighterDefinition, groupDefinition,
66
+ ];
67
+ for (const def of builtins)
68
+ this.registerShape(def);
69
+ }
70
+ registerShape(definition) {
71
+ this.registry.register(definition);
72
+ }
73
+ mount(container) {
74
+ if (this.isMounted)
75
+ return;
76
+ this.container = container;
77
+ this.isMounted = true;
78
+ this.renderer.mount(container, this.camera.camera);
79
+ this.renderer.renderAll(this.store.listShapes());
80
+ this.unsubscribeCamera = this.camera.subscribe((cam) => {
81
+ this.renderer.updateCamera(cam);
82
+ this.selectionManager.updateVisuals(this.renderer, this.store, this.registry, cam);
83
+ });
84
+ this.unsubscribeStore = this.store.listen((diff) => {
85
+ if (diff.deleted.size > 0)
86
+ this.selectionManager.remove(Array.from(diff.deleted));
87
+ for (const deletedId of diff.deleted) {
88
+ const lastRecord = this.renderer.getShapeRecord(deletedId);
89
+ this.clipping.handleParentDeletion(deletedId, this.store);
90
+ this.connector.handleTargetDeletion(deletedId, lastRecord, this.store, this.registry);
91
+ }
92
+ this.renderer.applyDiff(diff, this.store);
93
+ this.renderer.reorderDOM(this.store.listShapes());
94
+ if (diff.updated.size > 0) {
95
+ this.selectionManager.updateVisuals(this.renderer, this.store, this.registry, this.camera.camera);
96
+ }
97
+ });
98
+ this.selectionManager.subscribe(() => {
99
+ this.selectionManager.updateVisuals(this.renderer, this.store, this.registry, this.camera.camera);
100
+ });
101
+ this.interaction.attach(container);
102
+ this.keyboard.attach(window);
103
+ container.addEventListener('dblclick', this.onDblClick);
104
+ this.detachImageTransfer = attachImageTransferHandlers(container, this);
105
+ }
106
+ destroy() {
107
+ if (this.container) {
108
+ this.container.removeEventListener('dblclick', this.onDblClick);
109
+ }
110
+ this.interaction.detach();
111
+ this.keyboard.detach();
112
+ if (this.detachImageTransfer) {
113
+ this.detachImageTransfer();
114
+ this.detachImageTransfer = null;
115
+ }
116
+ if (this.unsubscribeCamera) {
117
+ this.unsubscribeCamera();
118
+ this.unsubscribeCamera = null;
119
+ }
120
+ if (this.unsubscribeStore) {
121
+ this.unsubscribeStore();
122
+ this.unsubscribeStore = null;
123
+ }
124
+ this.renderer.destroy();
125
+ this.isMounted = false;
126
+ this.container = null;
127
+ }
128
+ getContainer() {
129
+ return this.container;
130
+ }
131
+ setTool(toolId) {
132
+ this.activeTool = toolId;
133
+ }
134
+ getTool() {
135
+ return this.activeTool;
136
+ }
137
+ get selection() { return this.selectionManager.selection; }
138
+ getSelection() { return this.selectionManager.selection; }
139
+ setSelection(ids) { this.selectionManager.setSelection(ids); }
140
+ selectShape(shapeId) { shapeId ? this.setSelection([shapeId]) : this.clearSelection(); }
141
+ getSelectedShapeId() {
142
+ const sel = this.selection;
143
+ return sel.length > 0 ? sel[sel.length - 1] : null;
144
+ }
145
+ toggleSelection(shapeId) { this.selectionManager.toggle(shapeId); }
146
+ addToSelection(ids) { this.selectionManager.add(ids); }
147
+ clearSelection() { this.selectionManager.clear(); }
148
+ selectAll() { this.selectionManager.selectAll(this.store.listShapes()); }
149
+ isSelected(id) { return this.selectionManager.isSelected(id); }
150
+ cycleSelection(direction = 'forward') {
151
+ this.selectionManager.cycleZOrder(this.store.listShapes(), direction);
152
+ }
153
+ bringToFront(ids) { this.store.reorderShapes('front', ids ?? this.selection); }
154
+ sendToBack(ids) { this.store.reorderShapes('back', ids ?? this.selection); }
155
+ bringForward(ids) { this.store.reorderShapes('forward', ids ?? this.selection); }
156
+ sendBackward(ids) { this.store.reorderShapes('backward', ids ?? this.selection); }
157
+ createShape(record) {
158
+ const id = record.id ?? `shape-${Date.now()}-${Math.random().toString(36).substring(2, 7)}`;
159
+ return this.store.createShape({
160
+ ...record,
161
+ id,
162
+ });
163
+ }
164
+ updateShape(id, patch) {
165
+ return this.store.updateShape(id, patch);
166
+ }
167
+ deleteShape(id) {
168
+ this.selectionManager.remove([id]);
169
+ const lastRecord = this.store.getShape(id);
170
+ if (!lastRecord)
171
+ return false;
172
+ let res = false;
173
+ this.store.transact(() => {
174
+ this.clipping.handleParentDeletion(id, this.store);
175
+ this.connector.handleTargetDeletion(id, lastRecord, this.store, this.registry);
176
+ res = this.store.deleteShape(id);
177
+ });
178
+ return res;
179
+ }
180
+ getShape(id) {
181
+ return this.store.getShape(id);
182
+ }
183
+ canUndo() {
184
+ return this.store.canUndo();
185
+ }
186
+ canRedo() {
187
+ return this.store.canRedo();
188
+ }
189
+ clearHistory() {
190
+ this.store.clearHistory();
191
+ }
192
+ undo() {
193
+ return this.store.undo();
194
+ }
195
+ redo() {
196
+ return this.store.redo();
197
+ }
198
+ loadSnapshot(snapshot) {
199
+ this.store.loadSnapshot(snapshot);
200
+ if (snapshot.camera) {
201
+ this.camera.setCamera(snapshot.camera);
202
+ }
203
+ if (this.isMounted) {
204
+ this.renderer.renderAll(this.store.listShapes());
205
+ }
206
+ }
207
+ getSnapshot() {
208
+ return {
209
+ ...this.store.getSnapshot(),
210
+ camera: this.camera.camera,
211
+ };
212
+ }
213
+ pan(dx, dy) {
214
+ return this.camera.pan(dx, dy);
215
+ }
216
+ zoomAroundPoint(screenPoint, factor, options) {
217
+ return this.camera.zoomAroundPoint(screenPoint, factor, options);
218
+ }
219
+ setCamera(camera) {
220
+ this.camera.setCamera(camera);
221
+ }
222
+ getOverlaySlot(id) {
223
+ return this.renderer.getOverlaySlot(id);
224
+ }
225
+ getShapeWrapper(id) {
226
+ return this.renderer.getShapeWrapper(id);
227
+ }
228
+ async exportPNG(options) {
229
+ return exportPNG(this, options);
230
+ }
231
+ onDblClick = (e) => {
232
+ const target = e.target;
233
+ const shapeWrapper = target?.closest('.od-shape');
234
+ const shapeId = shapeWrapper?.getAttribute('data-id');
235
+ if (!shapeId)
236
+ return;
237
+ this.textEditing.startEditing(shapeId, this);
238
+ };
239
+ }
240
+ //# sourceMappingURL=editor.js.map