@oh-just-another/state 0.57.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 (269) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +21 -0
  3. package/README.md +60 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/actions/actionClipboard.d.ts +6 -0
  6. package/dist/actions/actionClipboard.d.ts.map +1 -0
  7. package/dist/actions/actionClipboard.js +26 -0
  8. package/dist/actions/actionClipboard.js.map +1 -0
  9. package/dist/actions/actionGrouping.d.ts +5 -0
  10. package/dist/actions/actionGrouping.d.ts.map +1 -0
  11. package/dist/actions/actionGrouping.js +26 -0
  12. package/dist/actions/actionGrouping.js.map +1 -0
  13. package/dist/actions/actionHistory.d.ts +5 -0
  14. package/dist/actions/actionHistory.d.ts.map +1 -0
  15. package/dist/actions/actionHistory.js +25 -0
  16. package/dist/actions/actionHistory.js.map +1 -0
  17. package/dist/actions/actionKeyboard.d.ts +3 -0
  18. package/dist/actions/actionKeyboard.d.ts.map +1 -0
  19. package/dist/actions/actionKeyboard.js +130 -0
  20. package/dist/actions/actionKeyboard.js.map +1 -0
  21. package/dist/actions/actionLayout.d.ts +3 -0
  22. package/dist/actions/actionLayout.d.ts.map +1 -0
  23. package/dist/actions/actionLayout.js +65 -0
  24. package/dist/actions/actionLayout.js.map +1 -0
  25. package/dist/actions/actionMode.d.ts +13 -0
  26. package/dist/actions/actionMode.d.ts.map +1 -0
  27. package/dist/actions/actionMode.js +116 -0
  28. package/dist/actions/actionMode.js.map +1 -0
  29. package/dist/actions/actionSelection.d.ts +9 -0
  30. package/dist/actions/actionSelection.d.ts.map +1 -0
  31. package/dist/actions/actionSelection.js +57 -0
  32. package/dist/actions/actionSelection.js.map +1 -0
  33. package/dist/actions/actionView.d.ts +7 -0
  34. package/dist/actions/actionView.d.ts.map +1 -0
  35. package/dist/actions/actionView.js +14 -0
  36. package/dist/actions/actionView.js.map +1 -0
  37. package/dist/actions/actionZOrder.d.ts +7 -0
  38. package/dist/actions/actionZOrder.d.ts.map +1 -0
  39. package/dist/actions/actionZOrder.js +42 -0
  40. package/dist/actions/actionZOrder.js.map +1 -0
  41. package/dist/actions/actionZoom.d.ts +8 -0
  42. package/dist/actions/actionZoom.d.ts.map +1 -0
  43. package/dist/actions/actionZoom.js +61 -0
  44. package/dist/actions/actionZoom.js.map +1 -0
  45. package/dist/actions/index.d.ts +12 -0
  46. package/dist/actions/index.d.ts.map +1 -0
  47. package/dist/actions/index.js +11 -0
  48. package/dist/actions/index.js.map +1 -0
  49. package/dist/actions/registry.d.ts +68 -0
  50. package/dist/actions/registry.d.ts.map +1 -0
  51. package/dist/actions/registry.js +300 -0
  52. package/dist/actions/registry.js.map +1 -0
  53. package/dist/actions/types.d.ts +103 -0
  54. package/dist/actions/types.d.ts.map +1 -0
  55. package/dist/actions/types.js +10 -0
  56. package/dist/actions/types.js.map +1 -0
  57. package/dist/animation-tick.d.ts +28 -0
  58. package/dist/animation-tick.d.ts.map +1 -0
  59. package/dist/animation-tick.js +50 -0
  60. package/dist/animation-tick.js.map +1 -0
  61. package/dist/auto-compact.d.ts +27 -0
  62. package/dist/auto-compact.d.ts.map +1 -0
  63. package/dist/auto-compact.js +46 -0
  64. package/dist/auto-compact.js.map +1 -0
  65. package/dist/auto-layout-scheduler.d.ts +50 -0
  66. package/dist/auto-layout-scheduler.d.ts.map +1 -0
  67. package/dist/auto-layout-scheduler.js +94 -0
  68. package/dist/auto-layout-scheduler.js.map +1 -0
  69. package/dist/built-in-handlers.d.ts +24 -0
  70. package/dist/built-in-handlers.d.ts.map +1 -0
  71. package/dist/built-in-handlers.js +210 -0
  72. package/dist/built-in-handlers.js.map +1 -0
  73. package/dist/clipboard.d.ts +51 -0
  74. package/dist/clipboard.d.ts.map +1 -0
  75. package/dist/clipboard.js +105 -0
  76. package/dist/clipboard.js.map +1 -0
  77. package/dist/constants.d.ts +544 -0
  78. package/dist/constants.d.ts.map +1 -0
  79. package/dist/constants.js +537 -0
  80. package/dist/constants.js.map +1 -0
  81. package/dist/dom-events.d.ts +13 -0
  82. package/dist/dom-events.d.ts.map +1 -0
  83. package/dist/dom-events.js +70 -0
  84. package/dist/dom-events.js.map +1 -0
  85. package/dist/editor/anchor-points.d.ts +22 -0
  86. package/dist/editor/anchor-points.d.ts.map +1 -0
  87. package/dist/editor/anchor-points.js +28 -0
  88. package/dist/editor/anchor-points.js.map +1 -0
  89. package/dist/editor/applies/create.d.ts +60 -0
  90. package/dist/editor/applies/create.d.ts.map +1 -0
  91. package/dist/editor/applies/create.js +107 -0
  92. package/dist/editor/applies/create.js.map +1 -0
  93. package/dist/editor/applies/edge.d.ts +32 -0
  94. package/dist/editor/applies/edge.d.ts.map +1 -0
  95. package/dist/editor/applies/edge.js +44 -0
  96. package/dist/editor/applies/edge.js.map +1 -0
  97. package/dist/editor/applies/link-move.d.ts +53 -0
  98. package/dist/editor/applies/link-move.d.ts.map +1 -0
  99. package/dist/editor/applies/link-move.js +160 -0
  100. package/dist/editor/applies/link-move.js.map +1 -0
  101. package/dist/editor/applies/move.d.ts +38 -0
  102. package/dist/editor/applies/move.d.ts.map +1 -0
  103. package/dist/editor/applies/move.js +83 -0
  104. package/dist/editor/applies/move.js.map +1 -0
  105. package/dist/editor/applies/resize.d.ts +68 -0
  106. package/dist/editor/applies/resize.d.ts.map +1 -0
  107. package/dist/editor/applies/resize.js +199 -0
  108. package/dist/editor/applies/resize.js.map +1 -0
  109. package/dist/editor/applies/selection.d.ts +34 -0
  110. package/dist/editor/applies/selection.d.ts.map +1 -0
  111. package/dist/editor/applies/selection.js +65 -0
  112. package/dist/editor/applies/selection.js.map +1 -0
  113. package/dist/editor/applies/snap-grid.d.ts +45 -0
  114. package/dist/editor/applies/snap-grid.d.ts.map +1 -0
  115. package/dist/editor/applies/snap-grid.js +90 -0
  116. package/dist/editor/applies/snap-grid.js.map +1 -0
  117. package/dist/editor/container-ops.d.ts +74 -0
  118. package/dist/editor/container-ops.d.ts.map +1 -0
  119. package/dist/editor/container-ops.js +262 -0
  120. package/dist/editor/container-ops.js.map +1 -0
  121. package/dist/editor/event-fanout.d.ts +48 -0
  122. package/dist/editor/event-fanout.d.ts.map +1 -0
  123. package/dist/editor/event-fanout.js +53 -0
  124. package/dist/editor/event-fanout.js.map +1 -0
  125. package/dist/editor/gesture-tx.d.ts +77 -0
  126. package/dist/editor/gesture-tx.d.ts.map +1 -0
  127. package/dist/editor/gesture-tx.js +93 -0
  128. package/dist/editor/gesture-tx.js.map +1 -0
  129. package/dist/editor/hit-test.d.ts +178 -0
  130. package/dist/editor/hit-test.d.ts.map +1 -0
  131. package/dist/editor/hit-test.js +460 -0
  132. package/dist/editor/hit-test.js.map +1 -0
  133. package/dist/editor/long-press.d.ts +34 -0
  134. package/dist/editor/long-press.d.ts.map +1 -0
  135. package/dist/editor/long-press.js +58 -0
  136. package/dist/editor/long-press.js.map +1 -0
  137. package/dist/editor/pinch.d.ts +37 -0
  138. package/dist/editor/pinch.d.ts.map +1 -0
  139. package/dist/editor/pinch.js +90 -0
  140. package/dist/editor/pinch.js.map +1 -0
  141. package/dist/editor/pointer-binding.d.ts +18 -0
  142. package/dist/editor/pointer-binding.d.ts.map +1 -0
  143. package/dist/editor/pointer-binding.js +1087 -0
  144. package/dist/editor/pointer-binding.js.map +1 -0
  145. package/dist/editor/public/annotations.d.ts +54 -0
  146. package/dist/editor/public/annotations.d.ts.map +1 -0
  147. package/dist/editor/public/annotations.js +106 -0
  148. package/dist/editor/public/annotations.js.map +1 -0
  149. package/dist/editor/public/arrange-group.d.ts +81 -0
  150. package/dist/editor/public/arrange-group.d.ts.map +1 -0
  151. package/dist/editor/public/arrange-group.js +193 -0
  152. package/dist/editor/public/arrange-group.js.map +1 -0
  153. package/dist/editor/public/brush.d.ts +33 -0
  154. package/dist/editor/public/brush.d.ts.map +1 -0
  155. package/dist/editor/public/brush.js +54 -0
  156. package/dist/editor/public/brush.js.map +1 -0
  157. package/dist/editor/public/clipboard.d.ts +31 -0
  158. package/dist/editor/public/clipboard.d.ts.map +1 -0
  159. package/dist/editor/public/clipboard.js +35 -0
  160. package/dist/editor/public/clipboard.js.map +1 -0
  161. package/dist/editor/public/image-insert.d.ts +30 -0
  162. package/dist/editor/public/image-insert.d.ts.map +1 -0
  163. package/dist/editor/public/image-insert.js +57 -0
  164. package/dist/editor/public/image-insert.js.map +1 -0
  165. package/dist/editor/public/layers.d.ts +56 -0
  166. package/dist/editor/public/layers.d.ts.map +1 -0
  167. package/dist/editor/public/layers.js +104 -0
  168. package/dist/editor/public/layers.js.map +1 -0
  169. package/dist/editor/public/link.d.ts +25 -0
  170. package/dist/editor/public/link.d.ts.map +1 -0
  171. package/dist/editor/public/link.js +74 -0
  172. package/dist/editor/public/link.js.map +1 -0
  173. package/dist/editor/public/placement.d.ts +60 -0
  174. package/dist/editor/public/placement.d.ts.map +1 -0
  175. package/dist/editor/public/placement.js +111 -0
  176. package/dist/editor/public/placement.js.map +1 -0
  177. package/dist/editor/public/selection-ops.d.ts +78 -0
  178. package/dist/editor/public/selection-ops.d.ts.map +1 -0
  179. package/dist/editor/public/selection-ops.js +226 -0
  180. package/dist/editor/public/selection-ops.js.map +1 -0
  181. package/dist/editor/public/text-edit.d.ts +17 -0
  182. package/dist/editor/public/text-edit.d.ts.map +1 -0
  183. package/dist/editor/public/text-edit.js +28 -0
  184. package/dist/editor/public/text-edit.js.map +1 -0
  185. package/dist/editor/public/z-order.d.ts +47 -0
  186. package/dist/editor/public/z-order.d.ts.map +1 -0
  187. package/dist/editor/public/z-order.js +151 -0
  188. package/dist/editor/public/z-order.js.map +1 -0
  189. package/dist/editor/public/zoom-pan.d.ts +44 -0
  190. package/dist/editor/public/zoom-pan.d.ts.map +1 -0
  191. package/dist/editor/public/zoom-pan.js +116 -0
  192. package/dist/editor/public/zoom-pan.js.map +1 -0
  193. package/dist/editor/render-orchestrator.d.ts +11 -0
  194. package/dist/editor/render-orchestrator.d.ts.map +1 -0
  195. package/dist/editor/render-orchestrator.js +473 -0
  196. package/dist/editor/render-orchestrator.js.map +1 -0
  197. package/dist/editor/resize-helpers.d.ts +30 -0
  198. package/dist/editor/resize-helpers.d.ts.map +1 -0
  199. package/dist/editor/resize-helpers.js +121 -0
  200. package/dist/editor/resize-helpers.js.map +1 -0
  201. package/dist/editor/shape-filters.d.ts +11 -0
  202. package/dist/editor/shape-filters.d.ts.map +1 -0
  203. package/dist/editor/shape-filters.js +19 -0
  204. package/dist/editor/shape-filters.js.map +1 -0
  205. package/dist/editor/shape-traits.d.ts +16 -0
  206. package/dist/editor/shape-traits.d.ts.map +1 -0
  207. package/dist/editor/shape-traits.js +29 -0
  208. package/dist/editor/shape-traits.js.map +1 -0
  209. package/dist/editor/viewport-helpers.d.ts +24 -0
  210. package/dist/editor/viewport-helpers.d.ts.map +1 -0
  211. package/dist/editor/viewport-helpers.js +63 -0
  212. package/dist/editor/viewport-helpers.js.map +1 -0
  213. package/dist/editor-events.d.ts +33 -0
  214. package/dist/editor-events.d.ts.map +1 -0
  215. package/dist/editor-events.js +2 -0
  216. package/dist/editor-events.js.map +1 -0
  217. package/dist/editor.d.ts +1841 -0
  218. package/dist/editor.d.ts.map +1 -0
  219. package/dist/editor.js +4803 -0
  220. package/dist/editor.js.map +1 -0
  221. package/dist/file-drop.d.ts +99 -0
  222. package/dist/file-drop.d.ts.map +1 -0
  223. package/dist/file-drop.js +198 -0
  224. package/dist/file-drop.js.map +1 -0
  225. package/dist/frame-helpers.d.ts +30 -0
  226. package/dist/frame-helpers.d.ts.map +1 -0
  227. package/dist/frame-helpers.js +105 -0
  228. package/dist/frame-helpers.js.map +1 -0
  229. package/dist/group-helpers.d.ts +39 -0
  230. package/dist/group-helpers.d.ts.map +1 -0
  231. package/dist/group-helpers.js +116 -0
  232. package/dist/group-helpers.js.map +1 -0
  233. package/dist/handle.d.ts +73 -0
  234. package/dist/handle.d.ts.map +1 -0
  235. package/dist/handle.js +184 -0
  236. package/dist/handle.js.map +1 -0
  237. package/dist/index.d.ts +26 -0
  238. package/dist/index.d.ts.map +1 -0
  239. package/dist/index.js +16 -0
  240. package/dist/index.js.map +1 -0
  241. package/dist/interactive.d.ts +21 -0
  242. package/dist/interactive.d.ts.map +1 -0
  243. package/dist/interactive.js +11 -0
  244. package/dist/interactive.js.map +1 -0
  245. package/dist/link-selection.d.ts +21 -0
  246. package/dist/link-selection.d.ts.map +1 -0
  247. package/dist/link-selection.js +37 -0
  248. package/dist/link-selection.js.map +1 -0
  249. package/dist/machine.d.ts +322 -0
  250. package/dist/machine.d.ts.map +1 -0
  251. package/dist/machine.js +568 -0
  252. package/dist/machine.js.map +1 -0
  253. package/dist/modes.d.ts +24 -0
  254. package/dist/modes.d.ts.map +1 -0
  255. package/dist/modes.js +2 -0
  256. package/dist/modes.js.map +1 -0
  257. package/dist/overlay.d.ts +262 -0
  258. package/dist/overlay.d.ts.map +1 -0
  259. package/dist/overlay.js +673 -0
  260. package/dist/overlay.js.map +1 -0
  261. package/dist/platform.d.ts +70 -0
  262. package/dist/platform.d.ts.map +1 -0
  263. package/dist/platform.js +115 -0
  264. package/dist/platform.js.map +1 -0
  265. package/dist/selection.d.ts +18 -0
  266. package/dist/selection.d.ts.map +1 -0
  267. package/dist/selection.js +31 -0
  268. package/dist/selection.js.map +1 -0
  269. package/package.json +59 -0
@@ -0,0 +1,30 @@
1
+ import type { Bounds, ElementId } from "@oh-just-another/types";
2
+ import { type Scene } from "@oh-just-another/scene";
3
+ import type { HistoryProvider } from "@oh-just-another/history";
4
+ /**
5
+ * Next free `Frame N` auto-name — finds the highest existing `Frame <number>`
6
+ * in the scene and returns the increment. New frames default to this when the
7
+ * host doesn't supply a name.
8
+ */
9
+ export declare const nextFrameName: (scene: Scene) => string;
10
+ /**
11
+ * Assign `frameId` to every shape (except the frame itself) whose centre
12
+ * falls inside `frameBounds`. Already-owned shapes are left alone; the user
13
+ * has to drag them in explicitly to reassign.
14
+ *
15
+ * Mutates `history` (push per change) and returns the new scene. Caller
16
+ * decides whether to wrap in a single transaction (Editor already does for
17
+ * the gesture).
18
+ */
19
+ export declare const assignFrameMembers: (scene: Scene, history: HistoryProvider, frameId: ElementId, frameBounds: Bounds) => Scene;
20
+ /**
21
+ * Re-evaluate frame membership for EVERY non-frame element against the
22
+ * current frames — run at the end of a move / resize gesture. An element
23
+ * joins the top-most frame whose world bounds contain its centre, and is
24
+ * released (`frameId` cleared) when its centre is over no frame. Idempotent:
25
+ * pushes a patch only when an element's owning frame actually changed, so a
26
+ * plain click / no-op drag costs nothing. Mutates `history`; returns the new
27
+ * scene.
28
+ */
29
+ export declare const reconcileFrameMembership: (scene: Scene, history: HistoryProvider) => Scene;
30
+ //# sourceMappingURL=frame-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-helpers.d.ts","sourceRoot":"","sources":["../src/frame-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAGL,KAAK,KAAK,EACX,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAWhE;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,KAAG,MAQ5C,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,KAAK,EACZ,SAAS,eAAe,EACxB,SAAS,SAAS,EAClB,aAAa,MAAM,KAClB,KAmBF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GAAI,OAAO,KAAK,EAAE,SAAS,eAAe,KAAG,KAkCjF,CAAC"}
@@ -0,0 +1,105 @@
1
+ import { getElementWorldBounds, updateElement, } from "@oh-just-another/scene";
2
+ /**
3
+ * Frame helpers. Two distinct concerns: choosing a free auto-name
4
+ * (`Frame N+1`) and assigning ownership when a frame is freshly drawn over
5
+ * existing shapes. Both are bounded by scene contents; the second threads
6
+ * scene + history mutations the same way Editor does internally.
7
+ */
8
+ const FRAME_NAME_PATTERN = /^Frame (\d+)$/;
9
+ /**
10
+ * Next free `Frame N` auto-name — finds the highest existing `Frame <number>`
11
+ * in the scene and returns the increment. New frames default to this when the
12
+ * host doesn't supply a name.
13
+ */
14
+ export const nextFrameName = (scene) => {
15
+ let max = 0;
16
+ for (const s of scene.elements.values()) {
17
+ if (s.type !== "frame")
18
+ continue;
19
+ const m = FRAME_NAME_PATTERN.exec(s.name ?? "");
20
+ if (m)
21
+ max = Math.max(max, Number(m[1]));
22
+ }
23
+ return `Frame ${max + 1}`;
24
+ };
25
+ /**
26
+ * Assign `frameId` to every shape (except the frame itself) whose centre
27
+ * falls inside `frameBounds`. Already-owned shapes are left alone; the user
28
+ * has to drag them in explicitly to reassign.
29
+ *
30
+ * Mutates `history` (push per change) and returns the new scene. Caller
31
+ * decides whether to wrap in a single transaction (Editor already does for
32
+ * the gesture).
33
+ */
34
+ export const assignFrameMembers = (scene, history, frameId, frameBounds) => {
35
+ const left = frameBounds.x;
36
+ const top = frameBounds.y;
37
+ const right = frameBounds.x + frameBounds.width;
38
+ const bottom = frameBounds.y + frameBounds.height;
39
+ let next = scene;
40
+ for (const shape of scene.elements.values()) {
41
+ if (shape.id === frameId)
42
+ continue;
43
+ if (shape.type === "frame")
44
+ continue;
45
+ if (shape.frameId !== undefined)
46
+ continue;
47
+ const b = getElementWorldBounds(shape);
48
+ const cx = b.x + b.width / 2;
49
+ const cy = b.y + b.height / 2;
50
+ if (cx < left || cx > right || cy < top || cy > bottom)
51
+ continue;
52
+ const r = updateElement(next, shape.id, (s) => ({ ...s, frameId }));
53
+ next = r.scene;
54
+ history.push(r.patch);
55
+ }
56
+ return next;
57
+ };
58
+ /**
59
+ * Re-evaluate frame membership for EVERY non-frame element against the
60
+ * current frames — run at the end of a move / resize gesture. An element
61
+ * joins the top-most frame whose world bounds contain its centre, and is
62
+ * released (`frameId` cleared) when its centre is over no frame. Idempotent:
63
+ * pushes a patch only when an element's owning frame actually changed, so a
64
+ * plain click / no-op drag costs nothing. Mutates `history`; returns the new
65
+ * scene.
66
+ */
67
+ export const reconcileFrameMembership = (scene, history) => {
68
+ // Frames top-most first — highest z-order (fractional-index string) wins
69
+ // when frames overlap.
70
+ const frames = [...scene.elements.values()]
71
+ .filter((s) => s.type === "frame")
72
+ .sort((a, b) => (a.order < b.order ? 1 : a.order > b.order ? -1 : 0))
73
+ .map((f) => ({ id: f.id, b: getElementWorldBounds(f) }));
74
+ let next = scene;
75
+ for (const shape of scene.elements.values()) {
76
+ if (shape.type === "frame")
77
+ continue;
78
+ const b = getElementWorldBounds(shape);
79
+ const cx = b.x + b.width / 2;
80
+ const cy = b.y + b.height / 2;
81
+ let owner;
82
+ for (const f of frames) {
83
+ if (cx >= f.b.x && cx <= f.b.x + f.b.width && cy >= f.b.y && cy <= f.b.y + f.b.height) {
84
+ owner = f.id;
85
+ break;
86
+ }
87
+ }
88
+ if (shape.frameId === owner)
89
+ continue;
90
+ const r = updateElement(next, shape.id, (s) => {
91
+ const copy = { ...s };
92
+ // `exactOptionalPropertyTypes`: omit the key on release rather than
93
+ // setting it to `undefined`.
94
+ if (owner === undefined)
95
+ delete copy.frameId;
96
+ else
97
+ copy.frameId = owner;
98
+ return copy;
99
+ });
100
+ next = r.scene;
101
+ history.push(r.patch);
102
+ }
103
+ return next;
104
+ };
105
+ //# sourceMappingURL=frame-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-helpers.js","sourceRoot":"","sources":["../src/frame-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { ElementId } from "@oh-just-another/types";
2
+ import { type Scene, type Element } from "@oh-just-another/scene";
3
+ /**
4
+ * Topmost group ancestor of `shape` — walks the `parentId` chain and
5
+ * remembers the last parent typed `"group"`. Returns `null` when no ancestor
6
+ * is a group.
7
+ */
8
+ export declare const topGroupAncestor: (scene: Scene, shape: Element) => Element | null;
9
+ /**
10
+ * `true` when `elementId`'s parent chain contains `groupId` (or
11
+ * `elementId === groupId`). Bounded walk so a corrupted scene with a parentId
12
+ * cycle returns false instead of looping forever.
13
+ */
14
+ export declare const isDescendantOfGroup: (scene: Scene, elementId: ElementId, groupId: ElementId) => boolean;
15
+ /**
16
+ * Walk the parent chain of `shape` upward, promoting through groups until
17
+ * either:
18
+ * • the next parent is the editor's currently-entered group (drill-in mode
19
+ * lets the user pick the group's children);
20
+ * • the parent is no longer a group (containers / templates intentionally
21
+ * let click hits land on their children).
22
+ */
23
+ export declare const promoteToGroupRoot: (scene: Scene, shape: Element, enteredGroup: ElementId | null) => Element;
24
+ /**
25
+ * Compute the dim set for isolation rendering — every shape whose parent chain
26
+ * does NOT pass through `enteredGroupId`. Selection always stays opaque even
27
+ * when somehow not in the descendant set.
28
+ */
29
+ export declare const computeDimElements: (scene: Scene, selection: Iterable<ElementId>, enteredGroupId: ElementId) => ReadonlySet<ElementId>;
30
+ /**
31
+ * Decide which group `raw` should drill into on a double-click.
32
+ *
33
+ * • No group ancestor → null (drill doesn't apply).
34
+ * • Top group not yet entered → enter top.
35
+ * • Top group already entered → walk down the chain and pick the next inner
36
+ * group (drill one level deeper).
37
+ */
38
+ export declare const pickDrillTarget: (scene: Scene, raw: Element, top: Element | null, enteredGroup: ElementId | null) => Element | null;
39
+ //# sourceMappingURL=group-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-helpers.d.ts","sourceRoot":"","sources":["../src/group-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAc,KAAK,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAU9E;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,KAAK,EAAE,OAAO,OAAO,KAAG,OAAO,GAAG,IAYzE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,KAAK,EACZ,WAAW,SAAS,EACpB,SAAS,SAAS,KACjB,OAUF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,KAAK,EACZ,OAAO,OAAO,EACd,cAAc,SAAS,GAAG,IAAI,KAC7B,OAYF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,KAAK,EACZ,WAAW,QAAQ,CAAC,SAAS,CAAC,EAC9B,gBAAgB,SAAS,KACxB,WAAW,CAAC,SAAS,CAUvB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,KAAK,EACZ,KAAK,OAAO,EACZ,KAAK,OAAO,GAAG,IAAI,EACnB,cAAc,SAAS,GAAG,IAAI,KAC7B,OAAO,GAAG,IAeZ,CAAC"}
@@ -0,0 +1,116 @@
1
+ import { getElement } from "@oh-just-another/scene";
2
+ /**
3
+ * Group / isolation helpers — pure functions over Scene + ElementId with no
4
+ * Editor back-reference, so the test suite can drive them directly. Editor
5
+ * keeps wrapper methods that forward to these.
6
+ */
7
+ const MAX_PARENT_DEPTH = 64;
8
+ /**
9
+ * Topmost group ancestor of `shape` — walks the `parentId` chain and
10
+ * remembers the last parent typed `"group"`. Returns `null` when no ancestor
11
+ * is a group.
12
+ */
13
+ export const topGroupAncestor = (scene, shape) => {
14
+ let topGroup = null;
15
+ let cursor = shape;
16
+ let depth = 0;
17
+ while (cursor.parentId && depth < MAX_PARENT_DEPTH) {
18
+ const parent = getElement(scene, cursor.parentId);
19
+ if (!parent)
20
+ break;
21
+ if (parent.type === "group")
22
+ topGroup = parent;
23
+ cursor = parent;
24
+ depth++;
25
+ }
26
+ return topGroup;
27
+ };
28
+ /**
29
+ * `true` when `elementId`'s parent chain contains `groupId` (or
30
+ * `elementId === groupId`). Bounded walk so a corrupted scene with a parentId
31
+ * cycle returns false instead of looping forever.
32
+ */
33
+ export const isDescendantOfGroup = (scene, elementId, groupId) => {
34
+ let cursor = getElement(scene, elementId);
35
+ let depth = 0;
36
+ while (cursor && depth < MAX_PARENT_DEPTH) {
37
+ if (cursor.id === groupId)
38
+ return true;
39
+ if (!cursor.parentId)
40
+ return false;
41
+ cursor = getElement(scene, cursor.parentId);
42
+ depth++;
43
+ }
44
+ return false;
45
+ };
46
+ /**
47
+ * Walk the parent chain of `shape` upward, promoting through groups until
48
+ * either:
49
+ * • the next parent is the editor's currently-entered group (drill-in mode
50
+ * lets the user pick the group's children);
51
+ * • the parent is no longer a group (containers / templates intentionally
52
+ * let click hits land on their children).
53
+ */
54
+ export const promoteToGroupRoot = (scene, shape, enteredGroup) => {
55
+ let current = shape;
56
+ let depth = 0;
57
+ while (current.parentId && depth < MAX_PARENT_DEPTH) {
58
+ if (enteredGroup === current.parentId)
59
+ break;
60
+ const parent = getElement(scene, current.parentId);
61
+ if (!parent)
62
+ break;
63
+ if (parent.type !== "group")
64
+ break;
65
+ current = parent;
66
+ depth++;
67
+ }
68
+ return current;
69
+ };
70
+ /**
71
+ * Compute the dim set for isolation rendering — every shape whose parent chain
72
+ * does NOT pass through `enteredGroupId`. Selection always stays opaque even
73
+ * when somehow not in the descendant set.
74
+ */
75
+ export const computeDimElements = (scene, selection, enteredGroupId) => {
76
+ const dim = new Set();
77
+ const selectionSet = new Set(selection);
78
+ for (const s of scene.elements.values()) {
79
+ if (selectionSet.has(s.id))
80
+ continue;
81
+ if (!isDescendantOfGroup(scene, s.id, enteredGroupId)) {
82
+ dim.add(s.id);
83
+ }
84
+ }
85
+ return dim;
86
+ };
87
+ /**
88
+ * Decide which group `raw` should drill into on a double-click.
89
+ *
90
+ * • No group ancestor → null (drill doesn't apply).
91
+ * • Top group not yet entered → enter top.
92
+ * • Top group already entered → walk down the chain and pick the next inner
93
+ * group (drill one level deeper).
94
+ */
95
+ export const pickDrillTarget = (scene, raw, top, enteredGroup) => {
96
+ if (!top)
97
+ return null;
98
+ if (enteredGroup !== top.id)
99
+ return top;
100
+ let cursor = raw;
101
+ let next = null;
102
+ let depth = 0;
103
+ while (cursor.parentId && depth < MAX_PARENT_DEPTH) {
104
+ const parent = getElement(scene, cursor.parentId);
105
+ if (!parent)
106
+ break;
107
+ if (parent.id === top.id)
108
+ break;
109
+ if (parent.type === "group")
110
+ next = parent;
111
+ cursor = parent;
112
+ depth++;
113
+ }
114
+ return next;
115
+ };
116
+ //# sourceMappingURL=group-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-helpers.js","sourceRoot":"","sources":["../src/group-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import type { Bounds, Vec2 } from "@oh-just-another/types";
2
+ import { HANDLE_HIT_SLOP, HANDLE_OUTSET, HANDLE_SIZE } from "./constants.js";
3
+ /**
4
+ * Eight resize-handle positions arranged around the shape's AABB. `nw` is
5
+ * top-left, `ne` top-right, etc. `n`/`s`/`e`/`w` are edge midpoints.
6
+ */
7
+ export type HandleId = "nw" | "n" | "ne" | "e" | "se" | "s" | "sw" | "w";
8
+ export declare const ALL_HANDLES: readonly HandleId[];
9
+ /**
10
+ * Subset of `ALL_HANDLES` containing only the four corner positions. Used for
11
+ * aspect-locked resize (groups, fixed-ratio media) — only corner drags carry
12
+ * the diagonal that the resize math projects onto a single scale factor.
13
+ */
14
+ export declare const CORNER_HANDLES: readonly HandleId[];
15
+ /**
16
+ * CSS `cursor` for a resize handle — the bidirectional arrow aligned with the
17
+ * handle's resize axis. Opposite handles share a cursor (e.g. `nw`/`se` →
18
+ * `nwse-resize`). Used by the editor's context-cursor logic.
19
+ *
20
+ * Ignores element rotation — a rotated shape's handles technically want a
21
+ * rotated cursor, but CSS only offers the 8 fixed arrows; we map by handle id.
22
+ */
23
+ export declare const cursorForHandle: (handle: HandleId) => string;
24
+ /**
25
+ * Re-exports handle geometry/hit-target constants from `constants.ts`.
26
+ * `HANDLE_HIT_SLOP` is decoupled from `HANDLE_SIZE`/`HANDLE_OUTSET` — the grab
27
+ * area grows independently of the drawn square. Re-exported so consumers
28
+ * (`overlay`, `editor`, `index`, tests) keep importing from `./handle.js`.
29
+ */
30
+ export { HANDLE_HIT_SLOP, HANDLE_OUTSET, HANDLE_SIZE };
31
+ /**
32
+ * Position (in world coordinates) of a handle on the given bounds. The
33
+ * position is offset outward by `HANDLE_OUTSET` screen pixels so the handle
34
+ * sits outside the shape's bbox — the hit area never overlaps the shape body,
35
+ * making the handle reliably grabable even when the shape covers most of the
36
+ * click target.
37
+ *
38
+ * `zoom` defaults to 1 for callers that need world-coordinate positions
39
+ * (resize math), but the rendering / hit-test path should pass the current
40
+ * viewport zoom so the outset stays constant on screen across zoom levels.
41
+ */
42
+ export declare const handlePosition: (handle: HandleId, b: Bounds, zoom?: number) => Vec2;
43
+ /**
44
+ * Find which resize handle the point is over, given the shape's world bounds
45
+ * and the current view zoom (hit area stays constant in screen pixels).
46
+ * Returns `null` if nothing is hit.
47
+ *
48
+ * Two grab shapes, so the edge-midpoint dots can be removed from the chrome
49
+ * while edge resize stays available (drag the selection-box side itself):
50
+ *
51
+ * • Corners (`nw/ne/se/sw`) — a square grab at the drawn corner dot (offset
52
+ * outward by `HANDLE_OUTSET`). Checked first so a near-corner point
53
+ * resolves to the diagonal, not an edge.
54
+ * • Edges (`n/s/e/w`) — the WHOLE side of the box: a slop band along the
55
+ * corresponding bounds edge, spanning between the corners. No dot is drawn
56
+ * for these; the side line is the target.
57
+ *
58
+ * Edges only participate when present in `handleSet` (e.g. aspect-locked
59
+ * resize passes `CORNER_HANDLES`, so only corners hit). The returned id feeds
60
+ * the same `resizeBounds` / resize dispatch.
61
+ *
62
+ * `screenHalfSize` defaults to `HANDLE_HIT_SLOP` (mouse); touch hosts pass
63
+ * `TOUCH_HANDLE_HIT_SLOP` so a finger can grab without precision-pointing.
64
+ */
65
+ export declare const hitHandle: (point: Vec2, b: Bounds, zoom: number, screenHalfSize?: number, handleSet?: readonly HandleId[]) => HandleId | null;
66
+ /**
67
+ * Apply a delta in world coordinates to bounds, using the given handle as the
68
+ * grab point. Anchor (opposite corner) stays fixed. The result may have
69
+ * negative width/height while dragging — `bounds.normalize` in `@math` flips
70
+ * it on commit.
71
+ */
72
+ export declare const resizeBounds: (b: Bounds, handle: HandleId, delta: Vec2) => Bounds;
73
+ //# sourceMappingURL=handle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle.d.ts","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7E;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;AAEzE,eAAO,MAAM,WAAW,EAAE,SAAS,QAAQ,EAAiD,CAAC;AAE7F;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,QAAQ,EAA6B,CAAC;AAE5E;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,QAAQ,KAAG,MAelD,CAAC;AAEF;;;;;GAKG;AACH,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,QAAQ,EAAE,GAAG,MAAM,EAAE,aAAQ,KAAG,IAwBtE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,SAAS,GACpB,OAAO,IAAI,EACX,GAAG,MAAM,EACT,MAAM,MAAM,EACZ,iBAAgB,MAAwB,EACxC,YAAW,SAAS,QAAQ,EAAgB,KAC3C,QAAQ,GAAG,IAkCb,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,EAAE,QAAQ,QAAQ,EAAE,OAAO,IAAI,KAAG,MAuCvE,CAAC"}
package/dist/handle.js ADDED
@@ -0,0 +1,184 @@
1
+ import { HANDLE_HIT_SLOP, HANDLE_OUTSET, HANDLE_SIZE } from "./constants.js";
2
+ export const ALL_HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
3
+ /**
4
+ * Subset of `ALL_HANDLES` containing only the four corner positions. Used for
5
+ * aspect-locked resize (groups, fixed-ratio media) — only corner drags carry
6
+ * the diagonal that the resize math projects onto a single scale factor.
7
+ */
8
+ export const CORNER_HANDLES = ["nw", "ne", "se", "sw"];
9
+ /**
10
+ * CSS `cursor` for a resize handle — the bidirectional arrow aligned with the
11
+ * handle's resize axis. Opposite handles share a cursor (e.g. `nw`/`se` →
12
+ * `nwse-resize`). Used by the editor's context-cursor logic.
13
+ *
14
+ * Ignores element rotation — a rotated shape's handles technically want a
15
+ * rotated cursor, but CSS only offers the 8 fixed arrows; we map by handle id.
16
+ */
17
+ export const cursorForHandle = (handle) => {
18
+ switch (handle) {
19
+ case "nw":
20
+ case "se":
21
+ return "nwse-resize";
22
+ case "ne":
23
+ case "sw":
24
+ return "nesw-resize";
25
+ case "n":
26
+ case "s":
27
+ return "ns-resize";
28
+ case "e":
29
+ case "w":
30
+ return "ew-resize";
31
+ }
32
+ };
33
+ /**
34
+ * Re-exports handle geometry/hit-target constants from `constants.ts`.
35
+ * `HANDLE_HIT_SLOP` is decoupled from `HANDLE_SIZE`/`HANDLE_OUTSET` — the grab
36
+ * area grows independently of the drawn square. Re-exported so consumers
37
+ * (`overlay`, `editor`, `index`, tests) keep importing from `./handle.js`.
38
+ */
39
+ export { HANDLE_HIT_SLOP, HANDLE_OUTSET, HANDLE_SIZE };
40
+ /**
41
+ * Position (in world coordinates) of a handle on the given bounds. The
42
+ * position is offset outward by `HANDLE_OUTSET` screen pixels so the handle
43
+ * sits outside the shape's bbox — the hit area never overlaps the shape body,
44
+ * making the handle reliably grabable even when the shape covers most of the
45
+ * click target.
46
+ *
47
+ * `zoom` defaults to 1 for callers that need world-coordinate positions
48
+ * (resize math), but the rendering / hit-test path should pass the current
49
+ * viewport zoom so the outset stays constant on screen across zoom levels.
50
+ */
51
+ export const handlePosition = (handle, b, zoom = 1) => {
52
+ const cx = b.x + b.width / 2;
53
+ const cy = b.y + b.height / 2;
54
+ const maxX = b.x + b.width;
55
+ const maxY = b.y + b.height;
56
+ const o = HANDLE_OUTSET / zoom;
57
+ switch (handle) {
58
+ case "nw":
59
+ return { x: b.x - o, y: b.y - o };
60
+ case "n":
61
+ return { x: cx, y: b.y - o };
62
+ case "ne":
63
+ return { x: maxX + o, y: b.y - o };
64
+ case "e":
65
+ return { x: maxX + o, y: cy };
66
+ case "se":
67
+ return { x: maxX + o, y: maxY + o };
68
+ case "s":
69
+ return { x: cx, y: maxY + o };
70
+ case "sw":
71
+ return { x: b.x - o, y: maxY + o };
72
+ case "w":
73
+ return { x: b.x - o, y: cy };
74
+ }
75
+ };
76
+ /**
77
+ * Find which resize handle the point is over, given the shape's world bounds
78
+ * and the current view zoom (hit area stays constant in screen pixels).
79
+ * Returns `null` if nothing is hit.
80
+ *
81
+ * Two grab shapes, so the edge-midpoint dots can be removed from the chrome
82
+ * while edge resize stays available (drag the selection-box side itself):
83
+ *
84
+ * • Corners (`nw/ne/se/sw`) — a square grab at the drawn corner dot (offset
85
+ * outward by `HANDLE_OUTSET`). Checked first so a near-corner point
86
+ * resolves to the diagonal, not an edge.
87
+ * • Edges (`n/s/e/w`) — the WHOLE side of the box: a slop band along the
88
+ * corresponding bounds edge, spanning between the corners. No dot is drawn
89
+ * for these; the side line is the target.
90
+ *
91
+ * Edges only participate when present in `handleSet` (e.g. aspect-locked
92
+ * resize passes `CORNER_HANDLES`, so only corners hit). The returned id feeds
93
+ * the same `resizeBounds` / resize dispatch.
94
+ *
95
+ * `screenHalfSize` defaults to `HANDLE_HIT_SLOP` (mouse); touch hosts pass
96
+ * `TOUCH_HANDLE_HIT_SLOP` so a finger can grab without precision-pointing.
97
+ */
98
+ export const hitHandle = (point, b, zoom, screenHalfSize = HANDLE_HIT_SLOP, handleSet = ALL_HANDLES) => {
99
+ const slop = screenHalfSize / zoom;
100
+ // Corners — point-grab at each drawn dot.
101
+ for (const id of handleSet) {
102
+ if (id.length !== 2)
103
+ continue; // skip edges this pass
104
+ const p = handlePosition(id, b, zoom);
105
+ if (Math.abs(point.x - p.x) <= slop && Math.abs(point.y - p.y) <= slop) {
106
+ return id;
107
+ }
108
+ }
109
+ // Edges — slop band along the selection-box side, between the corners.
110
+ const minX = b.x;
111
+ const maxX = b.x + b.width;
112
+ const minY = b.y;
113
+ const maxY = b.y + b.height;
114
+ const onX = point.x >= minX - slop && point.x <= maxX + slop;
115
+ const onY = point.y >= minY - slop && point.y <= maxY + slop;
116
+ for (const id of handleSet) {
117
+ switch (id) {
118
+ case "n":
119
+ if (onX && Math.abs(point.y - minY) <= slop)
120
+ return "n";
121
+ break;
122
+ case "s":
123
+ if (onX && Math.abs(point.y - maxY) <= slop)
124
+ return "s";
125
+ break;
126
+ case "w":
127
+ if (onY && Math.abs(point.x - minX) <= slop)
128
+ return "w";
129
+ break;
130
+ case "e":
131
+ if (onY && Math.abs(point.x - maxX) <= slop)
132
+ return "e";
133
+ break;
134
+ }
135
+ }
136
+ return null;
137
+ };
138
+ /**
139
+ * Apply a delta in world coordinates to bounds, using the given handle as the
140
+ * grab point. Anchor (opposite corner) stays fixed. The result may have
141
+ * negative width/height while dragging — `bounds.normalize` in `@math` flips
142
+ * it on commit.
143
+ */
144
+ export const resizeBounds = (b, handle, delta) => {
145
+ let { x, y, width, height } = b;
146
+ switch (handle) {
147
+ case "nw":
148
+ x += delta.x;
149
+ y += delta.y;
150
+ width -= delta.x;
151
+ height -= delta.y;
152
+ break;
153
+ case "n":
154
+ y += delta.y;
155
+ height -= delta.y;
156
+ break;
157
+ case "ne":
158
+ y += delta.y;
159
+ width += delta.x;
160
+ height -= delta.y;
161
+ break;
162
+ case "e":
163
+ width += delta.x;
164
+ break;
165
+ case "se":
166
+ width += delta.x;
167
+ height += delta.y;
168
+ break;
169
+ case "s":
170
+ height += delta.y;
171
+ break;
172
+ case "sw":
173
+ x += delta.x;
174
+ width -= delta.x;
175
+ height += delta.y;
176
+ break;
177
+ case "w":
178
+ x += delta.x;
179
+ width -= delta.x;
180
+ break;
181
+ }
182
+ return { x, y, width, height };
183
+ };
184
+ //# sourceMappingURL=handle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle.js","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export type { Mode } from "./modes.js";
2
+ export { DEFAULT_MODE } from "./modes.js";
3
+ export type { Selection } from "./selection.js";
4
+ export * as selection from "./selection.js";
5
+ export type { HandleId } from "./handle.js";
6
+ export { ALL_HANDLES, HANDLE_SIZE, handlePosition, hitHandle, resizeBounds } from "./handle.js";
7
+ export type { InteractionContext, InteractionEvent, InteractionEmit, PressTarget, PointerDownEvent, PointerMoveEvent, PointerUpEvent, PointerCancelEvent, SetModeEvent, } from "./machine.js";
8
+ export { interactionMachine, interpretPressEnd, DRAG_THRESHOLD, boundsFromPoints, } from "./machine.js";
9
+ export type { OverlayStyle, PeerCursor, PeerSelection } from "./overlay.js";
10
+ export { renderOverlay, DEFAULT_OVERLAY_STYLE } from "./overlay.js";
11
+ export { PEER_CURSOR_BROADCAST_INTERVAL_MS } from "./constants.js";
12
+ export { fromPointerEvent, fromKeyboardEvent, fromWheelEvent } from "./dom-events.js";
13
+ export type { InteractiveHitTester } from "./interactive.js";
14
+ export { registerInteractiveHitTester, getInteractiveHitTester } from "./interactive.js";
15
+ export type { EditorOptions, LoadSceneOptions, CursorRole, CursorSpec } from "./editor.js";
16
+ export { Editor } from "./editor.js";
17
+ export type { EditorEvents } from "./editor-events.js";
18
+ export { normalizeHref, safeHref } from "./editor/public/link.js";
19
+ export type { FileDropHandler, FileDropContext, WalkOptions } from "./file-drop.js";
20
+ export { FileDropRegistry, IMAGE_MIME_TYPES, VIDEO_MIME_TYPES, isImageFile, isVideoFile, isSceneJsonFile, readFileAsDataURL, readFileAsText, walkDataTransfer, } from "./file-drop.js";
21
+ export type { Action, ActionCategory, ActionContext, HotkeyMatcher } from "./actions/index.js";
22
+ export { ActionRegistry, defaultActionRegistry, registerBuiltinActions, hasSelection, hasSelectionOrLink, actionUndo, actionRedo, historyActions, actionSelectAll, actionDeleteSelection, actionDuplicateSelection, selectionActions, actionCopy, actionCut, actionPaste, clipboardActions, actionBringToFront, actionSendToBack, zOrderActions, actionGroupSelection, actionUngroupSelection, groupingActions, actionZoomIn, actionZoomOut, actionZoomReset, actionZoomToFit, zoomActions, actionModeSelect, actionModeHand, actionModeRect, actionModeEllipse, actionModeText, actionModeLink, actionModeBrush, actionModeFrame, actionToggleToolLock, actionCancel, modeActions, } from "./actions/index.js";
23
+ export type { PrettyHotkeyDesc } from "./platform.js";
24
+ export { isMac, isWindows, isAndroid, isIOS, isLinux, isFirefox, isSafari, CTRL_OR_CMD_KEY, getDevicePixelRatio, formatHotkey, formatHotkeyParts, } from "./platform.js";
25
+ export type { Annotation, Comment } from "@oh-just-another/scene";
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ export { DEFAULT_MODE } from "./modes.js";
2
+ export * as selection from "./selection.js";
3
+ export { ALL_HANDLES, HANDLE_SIZE, handlePosition, hitHandle, resizeBounds } from "./handle.js";
4
+ export { interactionMachine, interpretPressEnd, DRAG_THRESHOLD, boundsFromPoints, } from "./machine.js";
5
+ export { renderOverlay, DEFAULT_OVERLAY_STYLE } from "./overlay.js";
6
+ export { PEER_CURSOR_BROADCAST_INTERVAL_MS } from "./constants.js";
7
+ export { fromPointerEvent, fromKeyboardEvent, fromWheelEvent } from "./dom-events.js";
8
+ export { registerInteractiveHitTester, getInteractiveHitTester } from "./interactive.js";
9
+ export { Editor } from "./editor.js";
10
+ export { normalizeHref, safeHref } from "./editor/public/link.js";
11
+ export { FileDropRegistry, IMAGE_MIME_TYPES, VIDEO_MIME_TYPES, isImageFile, isVideoFile, isSceneJsonFile, readFileAsDataURL, readFileAsText, walkDataTransfer, } from "./file-drop.js";
12
+ export { ActionRegistry, defaultActionRegistry, registerBuiltinActions, hasSelection, hasSelectionOrLink,
13
+ // Re-export individual built-ins so hosts can replace / compose.
14
+ actionUndo, actionRedo, historyActions, actionSelectAll, actionDeleteSelection, actionDuplicateSelection, selectionActions, actionCopy, actionCut, actionPaste, clipboardActions, actionBringToFront, actionSendToBack, zOrderActions, actionGroupSelection, actionUngroupSelection, groupingActions, actionZoomIn, actionZoomOut, actionZoomReset, actionZoomToFit, zoomActions, actionModeSelect, actionModeHand, actionModeRect, actionModeEllipse, actionModeText, actionModeLink, actionModeBrush, actionModeFrame, actionToggleToolLock, actionCancel, modeActions, } from "./actions/index.js";
15
+ export { isMac, isWindows, isAndroid, isIOS, isLinux, isFirefox, isSafari, CTRL_OR_CMD_KEY, getDevicePixelRatio, formatHotkey, formatHotkeyParts, } from "./platform.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAahG,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,iCAAiC,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtF,OAAO,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAGzF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAIlE,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,kBAAkB;AAClB,iEAAiE;AACjE,UAAU,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,YAAY,EACZ,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,SAAS,EACT,QAAQ,EACR,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,GAClB,MAAM,eAAe,CAAC"}