@oh-just-another/state 0.58.0 → 0.60.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 (272) hide show
  1. package/CHANGELOG.md +158 -0
  2. package/README.md +78 -27
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/actions/actionArrange.d.ts +13 -0
  5. package/dist/actions/actionArrange.d.ts.map +1 -0
  6. package/dist/actions/actionArrange.js +130 -0
  7. package/dist/actions/actionArrange.js.map +1 -0
  8. package/dist/actions/actionClipboard.d.ts +2 -0
  9. package/dist/actions/actionClipboard.d.ts.map +1 -1
  10. package/dist/actions/actionClipboard.js +32 -1
  11. package/dist/actions/actionClipboard.js.map +1 -1
  12. package/dist/actions/actionKeyboard.d.ts.map +1 -1
  13. package/dist/actions/actionKeyboard.js +77 -9
  14. package/dist/actions/actionKeyboard.js.map +1 -1
  15. package/dist/actions/actionMode.d.ts +4 -0
  16. package/dist/actions/actionMode.d.ts.map +1 -1
  17. package/dist/actions/actionMode.js +54 -0
  18. package/dist/actions/actionMode.js.map +1 -1
  19. package/dist/actions/actionSelection.d.ts.map +1 -1
  20. package/dist/actions/actionSelection.js +1 -0
  21. package/dist/actions/actionSelection.js.map +1 -1
  22. package/dist/actions/actionText.d.ts +5 -0
  23. package/dist/actions/actionText.d.ts.map +1 -0
  24. package/dist/actions/actionText.js +37 -0
  25. package/dist/actions/actionText.js.map +1 -0
  26. package/dist/actions/actionView.d.ts +6 -0
  27. package/dist/actions/actionView.d.ts.map +1 -1
  28. package/dist/actions/actionView.js +20 -2
  29. package/dist/actions/actionView.js.map +1 -1
  30. package/dist/actions/actionZoom.d.ts.map +1 -1
  31. package/dist/actions/actionZoom.js +5 -0
  32. package/dist/actions/actionZoom.js.map +1 -1
  33. package/dist/actions/index.d.ts +6 -4
  34. package/dist/actions/index.d.ts.map +1 -1
  35. package/dist/actions/index.js +6 -4
  36. package/dist/actions/index.js.map +1 -1
  37. package/dist/actions/registry.d.ts.map +1 -1
  38. package/dist/actions/registry.js +17 -0
  39. package/dist/actions/registry.js.map +1 -1
  40. package/dist/actions/types.d.ts +10 -1
  41. package/dist/actions/types.d.ts.map +1 -1
  42. package/dist/actions/types.js.map +1 -1
  43. package/dist/auto-layout-scheduler.d.ts +1 -3
  44. package/dist/auto-layout-scheduler.d.ts.map +1 -1
  45. package/dist/auto-layout-scheduler.js +1 -2
  46. package/dist/auto-layout-scheduler.js.map +1 -1
  47. package/dist/built-in-handlers.d.ts.map +1 -1
  48. package/dist/built-in-handlers.js +14 -1
  49. package/dist/built-in-handlers.js.map +1 -1
  50. package/dist/clipboard.d.ts +0 -14
  51. package/dist/clipboard.d.ts.map +1 -1
  52. package/dist/clipboard.js +1 -1
  53. package/dist/clipboard.js.map +1 -1
  54. package/dist/constants.d.ts +208 -41
  55. package/dist/constants.d.ts.map +1 -1
  56. package/dist/constants.js +210 -25
  57. package/dist/constants.js.map +1 -1
  58. package/dist/dom-events.d.ts +8 -2
  59. package/dist/dom-events.d.ts.map +1 -1
  60. package/dist/dom-events.js +12 -0
  61. package/dist/dom-events.js.map +1 -1
  62. package/dist/editor/animation-scene.d.ts +36 -0
  63. package/dist/editor/animation-scene.d.ts.map +1 -0
  64. package/dist/editor/animation-scene.js +194 -0
  65. package/dist/editor/animation-scene.js.map +1 -0
  66. package/dist/editor/animation.d.ts +43 -0
  67. package/dist/editor/animation.d.ts.map +1 -0
  68. package/dist/editor/animation.js +80 -0
  69. package/dist/editor/animation.js.map +1 -0
  70. package/dist/editor/applies/arrange.d.ts +46 -0
  71. package/dist/editor/applies/arrange.d.ts.map +1 -0
  72. package/dist/editor/applies/arrange.js +162 -0
  73. package/dist/editor/applies/arrange.js.map +1 -0
  74. package/dist/editor/applies/create.d.ts +0 -6
  75. package/dist/editor/applies/create.d.ts.map +1 -1
  76. package/dist/editor/applies/create.js +1 -1
  77. package/dist/editor/applies/create.js.map +1 -1
  78. package/dist/editor/applies/edge.d.ts +8 -1
  79. package/dist/editor/applies/edge.d.ts.map +1 -1
  80. package/dist/editor/applies/edge.js +31 -1
  81. package/dist/editor/applies/edge.js.map +1 -1
  82. package/dist/editor/applies/link-move.d.ts +0 -8
  83. package/dist/editor/applies/link-move.d.ts.map +1 -1
  84. package/dist/editor/applies/link-move.js +1 -1
  85. package/dist/editor/applies/link-move.js.map +1 -1
  86. package/dist/editor/applies/move.d.ts +6 -0
  87. package/dist/editor/applies/move.d.ts.map +1 -1
  88. package/dist/editor/applies/move.js +6 -0
  89. package/dist/editor/applies/move.js.map +1 -1
  90. package/dist/editor/applies/resize.d.ts +26 -5
  91. package/dist/editor/applies/resize.d.ts.map +1 -1
  92. package/dist/editor/applies/resize.js +91 -13
  93. package/dist/editor/applies/resize.js.map +1 -1
  94. package/dist/editor/caret-blink.d.ts +18 -0
  95. package/dist/editor/caret-blink.d.ts.map +1 -0
  96. package/dist/editor/caret-blink.js +42 -0
  97. package/dist/editor/caret-blink.js.map +1 -0
  98. package/dist/editor/container-ops.d.ts.map +1 -1
  99. package/dist/editor/container-ops.js +2 -2
  100. package/dist/editor/container-ops.js.map +1 -1
  101. package/dist/editor/dirty-rect.d.ts +23 -0
  102. package/dist/editor/dirty-rect.d.ts.map +1 -0
  103. package/dist/editor/dirty-rect.js +115 -0
  104. package/dist/editor/dirty-rect.js.map +1 -0
  105. package/dist/editor/gif-playback.d.ts +45 -0
  106. package/dist/editor/gif-playback.d.ts.map +1 -0
  107. package/dist/editor/gif-playback.js +125 -0
  108. package/dist/editor/gif-playback.js.map +1 -0
  109. package/dist/editor/hit-test.d.ts +3 -3
  110. package/dist/editor/hit-test.d.ts.map +1 -1
  111. package/dist/editor/hit-test.js +40 -15
  112. package/dist/editor/hit-test.js.map +1 -1
  113. package/dist/editor/interaction-state.d.ts +184 -0
  114. package/dist/editor/interaction-state.d.ts.map +1 -0
  115. package/dist/editor/interaction-state.js +139 -0
  116. package/dist/editor/interaction-state.js.map +1 -0
  117. package/dist/editor/link-handle-drag.d.ts +152 -0
  118. package/dist/editor/link-handle-drag.d.ts.map +1 -0
  119. package/dist/editor/link-handle-drag.js +300 -0
  120. package/dist/editor/link-handle-drag.js.map +1 -0
  121. package/dist/editor/long-press.d.ts.map +1 -1
  122. package/dist/editor/long-press.js +2 -2
  123. package/dist/editor/long-press.js.map +1 -1
  124. package/dist/editor/pinch.d.ts.map +1 -1
  125. package/dist/editor/pinch.js +6 -6
  126. package/dist/editor/pinch.js.map +1 -1
  127. package/dist/editor/pointer-binding.d.ts +9 -11
  128. package/dist/editor/pointer-binding.d.ts.map +1 -1
  129. package/dist/editor/pointer-binding.js +1191 -890
  130. package/dist/editor/pointer-binding.js.map +1 -1
  131. package/dist/editor/public/arrange-group.d.ts +3 -9
  132. package/dist/editor/public/arrange-group.d.ts.map +1 -1
  133. package/dist/editor/public/arrange-group.js +4 -6
  134. package/dist/editor/public/arrange-group.js.map +1 -1
  135. package/dist/editor/public/brush.d.ts +31 -12
  136. package/dist/editor/public/brush.d.ts.map +1 -1
  137. package/dist/editor/public/brush.js +66 -17
  138. package/dist/editor/public/brush.js.map +1 -1
  139. package/dist/editor/public/clipboard.d.ts +2 -4
  140. package/dist/editor/public/clipboard.d.ts.map +1 -1
  141. package/dist/editor/public/clipboard.js +2 -4
  142. package/dist/editor/public/clipboard.js.map +1 -1
  143. package/dist/editor/public/cursor.d.ts +29 -0
  144. package/dist/editor/public/cursor.d.ts.map +1 -0
  145. package/dist/editor/public/cursor.js +146 -0
  146. package/dist/editor/public/cursor.js.map +1 -0
  147. package/dist/editor/public/eraser.d.ts +55 -0
  148. package/dist/editor/public/eraser.d.ts.map +1 -0
  149. package/dist/editor/public/eraser.js +65 -0
  150. package/dist/editor/public/eraser.js.map +1 -0
  151. package/dist/editor/public/frame-name.d.ts +20 -0
  152. package/dist/editor/public/frame-name.d.ts.map +1 -0
  153. package/dist/editor/public/frame-name.js +54 -0
  154. package/dist/editor/public/frame-name.js.map +1 -0
  155. package/dist/editor/public/image-insert.d.ts +1 -1
  156. package/dist/editor/public/image-insert.d.ts.map +1 -1
  157. package/dist/editor/public/laser.d.ts +38 -0
  158. package/dist/editor/public/laser.d.ts.map +1 -0
  159. package/dist/editor/public/laser.js +42 -0
  160. package/dist/editor/public/laser.js.map +1 -0
  161. package/dist/editor/public/layers.d.ts.map +1 -1
  162. package/dist/editor/public/layers.js +2 -2
  163. package/dist/editor/public/layers.js.map +1 -1
  164. package/dist/editor/public/link.d.ts +11 -2
  165. package/dist/editor/public/link.d.ts.map +1 -1
  166. package/dist/editor/public/link.js +70 -2
  167. package/dist/editor/public/link.js.map +1 -1
  168. package/dist/editor/public/placement.d.ts +60 -2
  169. package/dist/editor/public/placement.d.ts.map +1 -1
  170. package/dist/editor/public/placement.js +193 -2
  171. package/dist/editor/public/placement.js.map +1 -1
  172. package/dist/editor/public/selection-ops.d.ts +35 -1
  173. package/dist/editor/public/selection-ops.d.ts.map +1 -1
  174. package/dist/editor/public/selection-ops.js +97 -2
  175. package/dist/editor/public/selection-ops.js.map +1 -1
  176. package/dist/editor/public/stroke-eraser-coverage.d.ts +37 -0
  177. package/dist/editor/public/stroke-eraser-coverage.d.ts.map +1 -0
  178. package/dist/editor/public/stroke-eraser-coverage.js +168 -0
  179. package/dist/editor/public/stroke-eraser-coverage.js.map +1 -0
  180. package/dist/editor/public/stroke-eraser.d.ts +50 -0
  181. package/dist/editor/public/stroke-eraser.d.ts.map +1 -0
  182. package/dist/editor/public/stroke-eraser.js +176 -0
  183. package/dist/editor/public/stroke-eraser.js.map +1 -0
  184. package/dist/editor/public/stroke-smoothing.d.ts +21 -0
  185. package/dist/editor/public/stroke-smoothing.d.ts.map +1 -0
  186. package/dist/editor/public/stroke-smoothing.js +37 -0
  187. package/dist/editor/public/stroke-smoothing.js.map +1 -0
  188. package/dist/editor/public/text-edit.d.ts +1 -10
  189. package/dist/editor/public/text-edit.d.ts.map +1 -1
  190. package/dist/editor/public/text-edit.js +2 -16
  191. package/dist/editor/public/text-edit.js.map +1 -1
  192. package/dist/editor/public/tool-ops.d.ts +130 -0
  193. package/dist/editor/public/tool-ops.d.ts.map +1 -0
  194. package/dist/editor/public/tool-ops.js +392 -0
  195. package/dist/editor/public/tool-ops.js.map +1 -0
  196. package/dist/editor/public/z-order.d.ts +1 -12
  197. package/dist/editor/public/z-order.d.ts.map +1 -1
  198. package/dist/editor/public/z-order.js +5 -5
  199. package/dist/editor/public/z-order.js.map +1 -1
  200. package/dist/editor/public/zoom-pan.d.ts +15 -4
  201. package/dist/editor/public/zoom-pan.d.ts.map +1 -1
  202. package/dist/editor/public/zoom-pan.js +39 -7
  203. package/dist/editor/public/zoom-pan.js.map +1 -1
  204. package/dist/editor/render-orchestrator.d.ts +177 -5
  205. package/dist/editor/render-orchestrator.d.ts.map +1 -1
  206. package/dist/editor/render-orchestrator.js +519 -358
  207. package/dist/editor/render-orchestrator.js.map +1 -1
  208. package/dist/editor/resize-helpers.d.ts +21 -5
  209. package/dist/editor/resize-helpers.d.ts.map +1 -1
  210. package/dist/editor/resize-helpers.js +59 -19
  211. package/dist/editor/resize-helpers.js.map +1 -1
  212. package/dist/editor/text-edit.d.ts +136 -0
  213. package/dist/editor/text-edit.d.ts.map +1 -0
  214. package/dist/editor/text-edit.js +328 -0
  215. package/dist/editor/text-edit.js.map +1 -0
  216. package/dist/editor/viewport-helpers.d.ts.map +1 -1
  217. package/dist/editor/viewport-helpers.js +3 -3
  218. package/dist/editor/viewport-helpers.js.map +1 -1
  219. package/dist/editor-events.d.ts +1 -1
  220. package/dist/editor-events.d.ts.map +1 -1
  221. package/dist/editor.d.ts +603 -346
  222. package/dist/editor.d.ts.map +1 -1
  223. package/dist/editor.js +1843 -1630
  224. package/dist/editor.js.map +1 -1
  225. package/dist/file-drop.d.ts.map +1 -1
  226. package/dist/file-drop.js +1 -2
  227. package/dist/file-drop.js.map +1 -1
  228. package/dist/frame-helpers.d.ts.map +1 -1
  229. package/dist/frame-helpers.js +5 -5
  230. package/dist/frame-helpers.js.map +1 -1
  231. package/dist/group-helpers.d.ts.map +1 -1
  232. package/dist/group-helpers.js +4 -4
  233. package/dist/group-helpers.js.map +1 -1
  234. package/dist/handle.d.ts +59 -6
  235. package/dist/handle.d.ts.map +1 -1
  236. package/dist/handle.js +99 -7
  237. package/dist/handle.js.map +1 -1
  238. package/dist/hotkeys-binding.d.ts +26 -0
  239. package/dist/hotkeys-binding.d.ts.map +1 -0
  240. package/dist/hotkeys-binding.js +35 -0
  241. package/dist/hotkeys-binding.js.map +1 -0
  242. package/dist/index.d.ts +9 -3
  243. package/dist/index.d.ts.map +1 -1
  244. package/dist/index.js +10 -3
  245. package/dist/index.js.map +1 -1
  246. package/dist/link-selection.d.ts +3 -5
  247. package/dist/link-selection.d.ts.map +1 -1
  248. package/dist/link-selection.js +3 -12
  249. package/dist/link-selection.js.map +1 -1
  250. package/dist/machine.d.ts +27 -1
  251. package/dist/machine.d.ts.map +1 -1
  252. package/dist/machine.js +38 -0
  253. package/dist/machine.js.map +1 -1
  254. package/dist/modes.d.ts +15 -1
  255. package/dist/modes.d.ts.map +1 -1
  256. package/dist/modes.js.map +1 -1
  257. package/dist/overlay.d.ts +92 -6
  258. package/dist/overlay.d.ts.map +1 -1
  259. package/dist/overlay.js +582 -125
  260. package/dist/overlay.js.map +1 -1
  261. package/dist/search.d.ts +37 -0
  262. package/dist/search.d.ts.map +1 -0
  263. package/dist/search.js +45 -0
  264. package/dist/search.js.map +1 -0
  265. package/dist/selection.d.ts.map +1 -1
  266. package/dist/selection.js +2 -10
  267. package/dist/selection.js.map +1 -1
  268. package/dist/util.d.ts +8 -0
  269. package/dist/util.d.ts.map +1 -0
  270. package/dist/util.js +17 -0
  271. package/dist/util.js.map +1 -0
  272. package/package.json +7 -7
@@ -1,28 +1,14 @@
1
- import { getElement, updateElement } from "@oh-just-another/scene";
1
+ import { getElement, isText } from "@oh-just-another/scene";
2
2
  /**
3
3
  * Precondition check for `beginTextEdit`. Returns `true` when the
4
4
  * shape exists, is a text shape, and lives on an unlocked layer.
5
5
  */
6
6
  export const canBeginTextEdit = (scene, id, isLayerLocked) => {
7
7
  const shape = getElement(scene, id);
8
- if (shape?.type !== "text")
8
+ if (shape === undefined || !isText(shape))
9
9
  return false;
10
10
  if (isLayerLocked(shape.layerId))
11
11
  return false;
12
12
  return true;
13
13
  };
14
- /**
15
- * Compute the patch for replacing a text shape's body. Returns `null`
16
- * when the shape disappeared or the text didn't actually change (the
17
- * caller still clears `_editingTextElement` and notifies on null).
18
- */
19
- export const computeCommitTextEdit = (scene, id, next) => {
20
- const shape = getElement(scene, id);
21
- if (shape?.type !== "text")
22
- return null;
23
- if (shape.text === next)
24
- return null;
25
- const r = updateElement(scene, id, (s) => ({ ...s, text: next }));
26
- return { scene: r.scene, patch: r.patch };
27
- };
28
14
  //# sourceMappingURL=text-edit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"text-edit.js","sourceRoot":"","sources":["../../../src/editor/public/text-edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAA0B,MAAM,wBAAwB,CAAC;AAG3F;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAY,EACZ,EAAa,EACb,aAAuC,EAC9B,EAAE;IACX,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,KAAY,EACZ,EAAa,EACb,IAAY,EAC6C,EAAE;IAC3D,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACxC,IAAK,KAA2B,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC5D,MAAM,CAAC,GAAG,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;AAC5C,CAAC,CAAC"}
1
+ {"version":3,"file":"text-edit.js","sourceRoot":"","sources":["../../../src/editor/public/text-edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAc,MAAM,wBAAwB,CAAC;AAGxE;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAY,EACZ,EAAa,EACb,aAAuC,EAC9B,EAAE;IACX,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
@@ -0,0 +1,130 @@
1
+ import { type Element, type ImageCrop, type Link, type Patch, type Scene } from "@oh-just-another/scene";
2
+ import type { Bounds, Color, ElementId, LinkId, Vec2 } from "@oh-just-another/types";
3
+ /**
4
+ * The style colour of the top-most shape under `point`, or `null` when the
5
+ * point is empty. `role` chooses which channel to sample: `"fill"` (default)
6
+ * falls back to the stroke when there is no fill, and `"stroke"` the other way
7
+ * round — so clicking a stroke-only outline still yields a usable colour.
8
+ */
9
+ export declare const pickColorAt: (scene: Scene, point: Vec2, role?: "fill" | "stroke") => Color | null;
10
+ /** Target types accepted by {@link computeConvertType}. `"polygon"` = diamond. */
11
+ export type ConvertTarget = "rectangle" | "ellipse" | "polygon";
12
+ /**
13
+ * Convert every convertible shape in `ids` to `target`, preserving
14
+ * position / rotation / scale / style and the on-canvas footprint. rectangle
15
+ * and ellipse carry `width` × `height`; `"polygon"` renders a diamond
16
+ * inscribed in that box. Shapes already of the target type, and non-convertible
17
+ * types (text, image, …), are skipped. One undo step (batched for 2+). Returns
18
+ * `null` when nothing changed.
19
+ */
20
+ export declare const computeConvertType: (scene: Scene, ids: Iterable<ElementId>, target: ConvertTarget) => {
21
+ readonly scene: Scene;
22
+ readonly patch: Patch;
23
+ } | null;
24
+ /** Clamp a crop rect into the valid `[0,1]` normalised range (non-empty). */
25
+ export declare const clampCrop: (crop: ImageCrop) => ImageCrop;
26
+ /**
27
+ * Set (or clear, with `null`) the normalised crop of the image `id`. No-op
28
+ * (returns `null`) when the shape is missing or not an image, or when the
29
+ * crop is unchanged. Setting a full-image crop (`0,0,1,1`) clears the field.
30
+ */
31
+ export declare const computeSetImageCrop: (scene: Scene, id: ElementId, crop: ImageCrop | null) => {
32
+ readonly scene: Scene;
33
+ readonly patch: Patch;
34
+ } | null;
35
+ /**
36
+ * Normalised crop rect covering the whole image. Equivalent to no crop.
37
+ */
38
+ export declare const FULL_CROP: ImageCrop;
39
+ /** The 8 crop-frame handles: 4 corners + 4 edge midpoints. */
40
+ export type CropHandle = "nw" | "n" | "ne" | "e" | "se" | "s" | "sw" | "w";
41
+ /** Ordered so corner handles win a tie against the adjacent edge midpoints. */
42
+ export declare const CROP_HANDLES: readonly CropHandle[];
43
+ /**
44
+ * Local-space rect the WHOLE (uncropped) bitmap would occupy, aligned so its
45
+ * current crop-window equals the element's box `{0,0,width,height}`. The
46
+ * element currently shows the sub-rectangle `crop` of this virtual full image.
47
+ * Used to draw the crop ghost and to clamp handle drags to the image extent.
48
+ */
49
+ export declare const cropFullImageLocalRect: (el: Element, crop: ImageCrop) => Bounds;
50
+ /**
51
+ * World-space positions of the 8 crop handles for the element's current box
52
+ * `{0,0,width,height}` (the visible crop window). Honours rotation / scale via
53
+ * `localToWorld`. The window always equals the element bounds, so the crop
54
+ * fraction is not needed here — pass the (pending) element whose `width` /
55
+ * `height` / `position` describe the window.
56
+ */
57
+ export declare const cropHandleWorldPoints: (el: Element) => Record<CropHandle, Vec2>;
58
+ /**
59
+ * Result of a crop handle / body drag: the pending normalised `crop` plus the
60
+ * element's new world `position` and local `width` × `height`. Rotation / scale
61
+ * are unchanged, so the caller keeps them.
62
+ */
63
+ export interface CropDragResult {
64
+ readonly crop: ImageCrop;
65
+ readonly position: Vec2;
66
+ readonly width: number;
67
+ readonly height: number;
68
+ }
69
+ /**
70
+ * Drag one crop handle to `worldPoint`. Moves the window edge(s) that handle
71
+ * controls (the opposite edge stays fixed), clamped so the window stays inside
72
+ * the virtual full image and never shrinks below {@link CROP_MIN_SIZE}. The
73
+ * source is never stretched: shrinking the window hides pixels rather than
74
+ * scaling them. `el` must be the ORIGINAL (unmutated) element so the reference
75
+ * frame stays stable across a multi-move drag.
76
+ */
77
+ export declare const computeCropHandleDrag: (el: Element, crop: ImageCrop, handle: CropHandle, worldPoint: Vec2) => CropDragResult;
78
+ /**
79
+ * Pan the source under a FIXED window: the element's box (position / size) is
80
+ * unchanged; only which region of the bitmap shows moves. `worldDelta` from
81
+ * `dragStartWorld` → `worldPoint` is projected into local space and converted
82
+ * to a crop shift, clamped so the window stays inside the image. `el` must be
83
+ * the ORIGINAL element and `crop` its ORIGINAL crop (drag-start snapshot).
84
+ */
85
+ export declare const computeCropBodyPan: (el: Element, crop: ImageCrop, dragStartWorld: Vec2, worldPoint: Vec2) => {
86
+ readonly crop: ImageCrop;
87
+ };
88
+ /**
89
+ * Commit a pending crop drag: write the normalised `crop` AND the new element
90
+ * `position` / `width` / `height` in a single patch (one undo step). A crop
91
+ * that covers the whole image is stored as no crop (field cleared). No-op
92
+ * (`null`) for a missing / non-image shape or when nothing changed.
93
+ */
94
+ export declare const computeCommitImageCrop: (scene: Scene, id: ElementId, next: CropDragResult) => {
95
+ readonly scene: Scene;
96
+ readonly patch: Patch;
97
+ } | null;
98
+ export type SpawnDirection = "left" | "right" | "up" | "down";
99
+ /**
100
+ * Create a clone of `sourceId` offset by {@link SPAWN_CONNECTED_GAP_PX} in
101
+ * `direction`, plus a link from the source to the new node. The clone keeps the
102
+ * source's type, size, style and rotation. Returns the next scene, both patches
103
+ * (element add + link add), and the new ids; `null` when the source is missing.
104
+ */
105
+ export declare const computeSpawnConnectedNode: (scene: Scene, sourceId: ElementId, direction: SpawnDirection, newElementId: ElementId, newLinkId: LinkId) => {
106
+ readonly scene: Scene;
107
+ readonly patches: readonly Patch[];
108
+ readonly newElementId: ElementId;
109
+ readonly linkId: LinkId;
110
+ } | null;
111
+ /**
112
+ * Pure geometry for a flowchart CREATE session: `count` clones of `sourceId`,
113
+ * each linked source→clone (floating). Does NOT mutate `scene` or history —
114
+ * returns the pending `elements` + `links` for a PREVIEW; the caller commits
115
+ * them later. Placement matches Excalidraw's `addNewNodes`:
116
+ *
117
+ * - `left` / `right` — the `count` siblings stack vertically, centred on the
118
+ * source (step = source height + {@link SPAWN_CONNECTED_GAP_PX}), all offset
119
+ * by one source-width + gap along the axis.
120
+ * - `up` / `down` — siblings spread horizontally, centred on the source
121
+ * (step = source width + gap), all offset by one source-height + gap.
122
+ *
123
+ * `count === 1` reproduces {@link computeSpawnConnectedNode}'s single placement
124
+ * (zero perpendicular offset). Returns empty arrays when the source is missing.
125
+ */
126
+ export declare const computeSpawnConnectedNodes: (scene: Scene, sourceId: ElementId, direction: SpawnDirection, count: number, makeElementId: () => ElementId, makeLinkId: () => LinkId) => {
127
+ readonly elements: Element[];
128
+ readonly links: Link[];
129
+ };
130
+ //# sourceMappingURL=tool-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-ops.d.ts","sourceRoot":"","sources":["../../../src/editor/public/tool-ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,392 @@
1
+ import { addElement, addLink, getElement, getElementAt, getElementLocalBounds, localToWorld, orderForTop, updateElement, worldToLocal, } from "@oh-just-another/scene";
2
+ import { DEFAULT_EDGE_STYLE } from "@oh-just-another/tokens";
3
+ import { CROP_MIN_SIZE, DEFAULT_LINK_ARROWHEAD, DEFAULT_LINK_ROUTING, SPAWN_CONNECTED_GAP_PX, } from "../../constants.js";
4
+ // ---------------------------------------------------------------------------
5
+ // F8 — Eyedropper: pick a colour from a shape on the canvas.
6
+ // ---------------------------------------------------------------------------
7
+ /**
8
+ * The style colour of the top-most shape under `point`, or `null` when the
9
+ * point is empty. `role` chooses which channel to sample: `"fill"` (default)
10
+ * falls back to the stroke when there is no fill, and `"stroke"` the other way
11
+ * round — so clicking a stroke-only outline still yields a usable colour.
12
+ */
13
+ export const pickColorAt = (scene, point, role = "fill") => {
14
+ const el = getElementAt(scene, point);
15
+ if (el === undefined)
16
+ return null;
17
+ const { fill, stroke } = el.style;
18
+ const primary = role === "fill" ? fill : stroke;
19
+ const secondary = role === "fill" ? stroke : fill;
20
+ return primary ?? secondary ?? null;
21
+ };
22
+ /** The convertible built-in types (share a width×height footprint). */
23
+ const CONVERTIBLE = new Set(["rectangle", "ellipse", "polygon"]);
24
+ /** Diamond corner points inscribed in a `w × h` box, anchored at the origin. */
25
+ const diamondPoints = (w, h) => [
26
+ { x: w / 2, y: 0 },
27
+ { x: w, y: h / 2 },
28
+ { x: w / 2, y: h },
29
+ { x: 0, y: h / 2 },
30
+ ];
31
+ /**
32
+ * Convert every convertible shape in `ids` to `target`, preserving
33
+ * position / rotation / scale / style and the on-canvas footprint. rectangle
34
+ * and ellipse carry `width` × `height`; `"polygon"` renders a diamond
35
+ * inscribed in that box. Shapes already of the target type, and non-convertible
36
+ * types (text, image, …), are skipped. One undo step (batched for 2+). Returns
37
+ * `null` when nothing changed.
38
+ */
39
+ export const computeConvertType = (scene, ids, target) => {
40
+ let s = scene;
41
+ const patches = [];
42
+ for (const id of ids) {
43
+ const el = getElement(s, id);
44
+ if (el === undefined || !CONVERTIBLE.has(el.type) || el.type === target)
45
+ continue;
46
+ const local = getElementLocalBounds(el);
47
+ const w = local.width;
48
+ const h = local.height;
49
+ const r = updateElement(s, id, (sh) => {
50
+ // Drop the source-shape-specific geometry fields so the result is a
51
+ // clean shape of the target type (no stale `points` / `width`).
52
+ const { width: _w, height: _h, points: _p, ...rest } = sh;
53
+ void _w;
54
+ void _h;
55
+ void _p;
56
+ const next = target === "polygon"
57
+ ? { ...rest, type: "polygon", points: diamondPoints(w, h) }
58
+ : { ...rest, type: target, width: w, height: h };
59
+ return next;
60
+ });
61
+ s = r.scene;
62
+ patches.push(r.patch);
63
+ }
64
+ const first = patches[0];
65
+ if (first === undefined)
66
+ return null;
67
+ return { scene: s, patch: patches.length === 1 ? first : { kind: "batch", patches } };
68
+ };
69
+ // ---------------------------------------------------------------------------
70
+ // F10 — Image crop model helpers.
71
+ // ---------------------------------------------------------------------------
72
+ /** Clamp a crop rect into the valid `[0,1]` normalised range (non-empty). */
73
+ export const clampCrop = (crop) => {
74
+ const x = Math.min(Math.max(crop.x, 0), 1);
75
+ const y = Math.min(Math.max(crop.y, 0), 1);
76
+ const width = Math.min(Math.max(crop.width, 0), 1 - x);
77
+ const height = Math.min(Math.max(crop.height, 0), 1 - y);
78
+ return { x, y, width, height };
79
+ };
80
+ /** True when two optional crops describe the same region (or both absent). */
81
+ const sameCrop = (a, b) => {
82
+ if (a === undefined || b === undefined)
83
+ return a === b;
84
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
85
+ };
86
+ /**
87
+ * Set (or clear, with `null`) the normalised crop of the image `id`. No-op
88
+ * (returns `null`) when the shape is missing or not an image, or when the
89
+ * crop is unchanged. Setting a full-image crop (`0,0,1,1`) clears the field.
90
+ */
91
+ export const computeSetImageCrop = (scene, id, crop) => {
92
+ const el = getElement(scene, id);
93
+ if (el?.type !== "image")
94
+ return null;
95
+ let next;
96
+ if (crop !== null) {
97
+ const c = clampCrop(crop);
98
+ const isFull = c.x === 0 && c.y === 0 && c.width === 1 && c.height === 1;
99
+ next = isFull ? undefined : c;
100
+ }
101
+ const current = el.crop;
102
+ if (sameCrop(next, current)) {
103
+ return null;
104
+ }
105
+ const r = updateElement(scene, id, (sh) => {
106
+ const { crop: _drop, ...rest } = sh;
107
+ void _drop;
108
+ return (next === undefined ? rest : { ...rest, crop: next });
109
+ });
110
+ return { scene: r.scene, patch: r.patch };
111
+ };
112
+ /**
113
+ * Normalised crop rect covering the whole image. Equivalent to no crop.
114
+ */
115
+ export const FULL_CROP = { x: 0, y: 0, width: 1, height: 1 };
116
+ /** Ordered so corner handles win a tie against the adjacent edge midpoints. */
117
+ export const CROP_HANDLES = ["nw", "ne", "se", "sw", "n", "e", "s", "w"];
118
+ const clampNum = (v, lo, hi) => Math.min(Math.max(v, lo), hi);
119
+ /**
120
+ * Local-space rect the WHOLE (uncropped) bitmap would occupy, aligned so its
121
+ * current crop-window equals the element's box `{0,0,width,height}`. The
122
+ * element currently shows the sub-rectangle `crop` of this virtual full image.
123
+ * Used to draw the crop ghost and to clamp handle drags to the image extent.
124
+ */
125
+ export const cropFullImageLocalRect = (el, crop) => {
126
+ const box = getElementLocalBounds(el);
127
+ const cw = crop.width || 1;
128
+ const ch = crop.height || 1;
129
+ const fullW = box.width / cw;
130
+ const fullH = box.height / ch;
131
+ return {
132
+ x: box.x - crop.x * fullW,
133
+ y: box.y - crop.y * fullH,
134
+ width: fullW,
135
+ height: fullH,
136
+ };
137
+ };
138
+ /**
139
+ * World-space positions of the 8 crop handles for the element's current box
140
+ * `{0,0,width,height}` (the visible crop window). Honours rotation / scale via
141
+ * `localToWorld`. The window always equals the element bounds, so the crop
142
+ * fraction is not needed here — pass the (pending) element whose `width` /
143
+ * `height` / `position` describe the window.
144
+ */
145
+ export const cropHandleWorldPoints = (el) => {
146
+ const box = getElementLocalBounds(el);
147
+ const { x, y, width: w, height: h } = box;
148
+ const L = (lx, ly) => localToWorld(el, { x: lx, y: ly });
149
+ return {
150
+ nw: L(x, y),
151
+ n: L(x + w / 2, y),
152
+ ne: L(x + w, y),
153
+ e: L(x + w, y + h / 2),
154
+ se: L(x + w, y + h),
155
+ s: L(x + w / 2, y + h),
156
+ sw: L(x, y + h),
157
+ w: L(x, y + h / 2),
158
+ };
159
+ };
160
+ const edgesOf = (handle) => ({
161
+ west: handle === "nw" || handle === "w" || handle === "sw",
162
+ east: handle === "ne" || handle === "e" || handle === "se",
163
+ north: handle === "nw" || handle === "n" || handle === "ne",
164
+ south: handle === "sw" || handle === "s" || handle === "se",
165
+ });
166
+ /**
167
+ * Drag one crop handle to `worldPoint`. Moves the window edge(s) that handle
168
+ * controls (the opposite edge stays fixed), clamped so the window stays inside
169
+ * the virtual full image and never shrinks below {@link CROP_MIN_SIZE}. The
170
+ * source is never stretched: shrinking the window hides pixels rather than
171
+ * scaling them. `el` must be the ORIGINAL (unmutated) element so the reference
172
+ * frame stays stable across a multi-move drag.
173
+ */
174
+ export const computeCropHandleDrag = (el, crop, handle, worldPoint) => {
175
+ const full = cropFullImageLocalRect(el, crop);
176
+ const box = getElementLocalBounds(el);
177
+ const p = worldToLocal(el, worldPoint);
178
+ // Current window edges (window == element box in the original local frame).
179
+ let left = box.x;
180
+ let top = box.y;
181
+ let right = box.x + box.width;
182
+ let bottom = box.y + box.height;
183
+ const { west, east, north, south } = edgesOf(handle);
184
+ const fullRight = full.x + full.width;
185
+ const fullBottom = full.y + full.height;
186
+ if (west)
187
+ left = clampNum(p.x, full.x, right - CROP_MIN_SIZE);
188
+ if (east)
189
+ right = clampNum(p.x, left + CROP_MIN_SIZE, fullRight);
190
+ if (north)
191
+ top = clampNum(p.y, full.y, bottom - CROP_MIN_SIZE);
192
+ if (south)
193
+ bottom = clampNum(p.y, top + CROP_MIN_SIZE, fullBottom);
194
+ const win = { x: left, y: top, width: right - left, height: bottom - top };
195
+ const nextCrop = clampCrop({
196
+ x: (win.x - full.x) / full.width,
197
+ y: (win.y - full.y) / full.height,
198
+ width: win.width / full.width,
199
+ height: win.height / full.height,
200
+ });
201
+ return {
202
+ crop: nextCrop,
203
+ position: localToWorld(el, { x: win.x, y: win.y }),
204
+ width: win.width,
205
+ height: win.height,
206
+ };
207
+ };
208
+ /**
209
+ * Pan the source under a FIXED window: the element's box (position / size) is
210
+ * unchanged; only which region of the bitmap shows moves. `worldDelta` from
211
+ * `dragStartWorld` → `worldPoint` is projected into local space and converted
212
+ * to a crop shift, clamped so the window stays inside the image. `el` must be
213
+ * the ORIGINAL element and `crop` its ORIGINAL crop (drag-start snapshot).
214
+ */
215
+ export const computeCropBodyPan = (el, crop, dragStartWorld, worldPoint) => {
216
+ const full = cropFullImageLocalRect(el, crop);
217
+ const start = worldToLocal(el, dragStartWorld);
218
+ const now = worldToLocal(el, worldPoint);
219
+ const dx = now.x - start.x;
220
+ const dy = now.y - start.y;
221
+ return {
222
+ crop: {
223
+ x: clampNum(crop.x - dx / full.width, 0, 1 - crop.width),
224
+ y: clampNum(crop.y - dy / full.height, 0, 1 - crop.height),
225
+ width: crop.width,
226
+ height: crop.height,
227
+ },
228
+ };
229
+ };
230
+ /** True when a crop rect is (within `eps`) the whole image — clears the field. */
231
+ const isFullCrop = (c, eps = 1e-4) => Math.abs(c.x) < eps &&
232
+ Math.abs(c.y) < eps &&
233
+ Math.abs(c.width - 1) < eps &&
234
+ Math.abs(c.height - 1) < eps;
235
+ /**
236
+ * Commit a pending crop drag: write the normalised `crop` AND the new element
237
+ * `position` / `width` / `height` in a single patch (one undo step). A crop
238
+ * that covers the whole image is stored as no crop (field cleared). No-op
239
+ * (`null`) for a missing / non-image shape or when nothing changed.
240
+ */
241
+ export const computeCommitImageCrop = (scene, id, next) => {
242
+ const el = getElement(scene, id);
243
+ if (el?.type !== "image")
244
+ return null;
245
+ const c = clampCrop(next.crop);
246
+ const cropField = isFullCrop(c) ? undefined : c;
247
+ const current = el.crop;
248
+ const unchanged = sameCrop(cropField, current) &&
249
+ el.position.x === next.position.x &&
250
+ el.position.y === next.position.y &&
251
+ el.width === next.width &&
252
+ el.height === next.height;
253
+ if (unchanged)
254
+ return null;
255
+ const r = updateElement(scene, id, (sh) => {
256
+ const { crop: _drop, ...rest } = sh;
257
+ void _drop;
258
+ const base = {
259
+ ...rest,
260
+ position: next.position,
261
+ width: next.width,
262
+ height: next.height,
263
+ };
264
+ return (cropField === undefined ? base : { ...base, crop: cropField });
265
+ });
266
+ return { scene: r.scene, patch: r.patch };
267
+ };
268
+ /**
269
+ * Create a clone of `sourceId` offset by {@link SPAWN_CONNECTED_GAP_PX} in
270
+ * `direction`, plus a link from the source to the new node. The clone keeps the
271
+ * source's type, size, style and rotation. Returns the next scene, both patches
272
+ * (element add + link add), and the new ids; `null` when the source is missing.
273
+ */
274
+ export const computeSpawnConnectedNode = (scene, sourceId, direction, newElementId, newLinkId) => {
275
+ const source = getElement(scene, sourceId);
276
+ if (source === undefined)
277
+ return null;
278
+ const local = getElementLocalBounds(source);
279
+ const w = local.width * source.scale.x;
280
+ const h = local.height * source.scale.y;
281
+ const dx = direction === "right"
282
+ ? w + SPAWN_CONNECTED_GAP_PX
283
+ : direction === "left"
284
+ ? -(w + SPAWN_CONNECTED_GAP_PX)
285
+ : 0;
286
+ const dy = direction === "down"
287
+ ? h + SPAWN_CONNECTED_GAP_PX
288
+ : direction === "up"
289
+ ? -(h + SPAWN_CONNECTED_GAP_PX)
290
+ : 0;
291
+ const order = orderForTop([...scene.elements.values()].filter((e) => e.layerId === source.layerId).map((e) => e.order));
292
+ // Clone the source, detaching any group / frame membership so the spawned
293
+ // node is free-standing.
294
+ const { parentId: _p, frameId: _f, ...bare } = source;
295
+ void _p;
296
+ void _f;
297
+ const clone = {
298
+ ...bare,
299
+ id: newElementId,
300
+ position: { x: source.position.x + dx, y: source.position.y + dy },
301
+ order,
302
+ };
303
+ const addEl = addElement(scene, clone);
304
+ const link = {
305
+ id: newLinkId,
306
+ layerId: source.layerId,
307
+ from: { kind: "floating", elementId: sourceId },
308
+ to: { kind: "floating", elementId: newElementId },
309
+ order: orderForTop([...addEl.scene.links.values()]
310
+ .filter((e) => e.layerId === source.layerId)
311
+ .map((e) => e.order)),
312
+ routing: DEFAULT_LINK_ROUTING,
313
+ style: { ...DEFAULT_EDGE_STYLE },
314
+ arrowheads: { to: DEFAULT_LINK_ARROWHEAD },
315
+ };
316
+ const addEdge = addLink(addEl.scene, link);
317
+ return {
318
+ scene: addEdge.scene,
319
+ patches: [addEl.patch, addEdge.patch],
320
+ newElementId,
321
+ linkId: newLinkId,
322
+ };
323
+ };
324
+ /**
325
+ * Pure geometry for a flowchart CREATE session: `count` clones of `sourceId`,
326
+ * each linked source→clone (floating). Does NOT mutate `scene` or history —
327
+ * returns the pending `elements` + `links` for a PREVIEW; the caller commits
328
+ * them later. Placement matches Excalidraw's `addNewNodes`:
329
+ *
330
+ * - `left` / `right` — the `count` siblings stack vertically, centred on the
331
+ * source (step = source height + {@link SPAWN_CONNECTED_GAP_PX}), all offset
332
+ * by one source-width + gap along the axis.
333
+ * - `up` / `down` — siblings spread horizontally, centred on the source
334
+ * (step = source width + gap), all offset by one source-height + gap.
335
+ *
336
+ * `count === 1` reproduces {@link computeSpawnConnectedNode}'s single placement
337
+ * (zero perpendicular offset). Returns empty arrays when the source is missing.
338
+ */
339
+ export const computeSpawnConnectedNodes = (scene, sourceId, direction, count, makeElementId, makeLinkId) => {
340
+ const source = getElement(scene, sourceId);
341
+ if (source === undefined || count < 1)
342
+ return { elements: [], links: [] };
343
+ const local = getElementLocalBounds(source);
344
+ const w = local.width * source.scale.x;
345
+ const h = local.height * source.scale.y;
346
+ const horizontal = direction === "left" || direction === "right";
347
+ // Along-axis offset: one source extent + gap in the spawn direction.
348
+ const alongX = direction === "right"
349
+ ? w + SPAWN_CONNECTED_GAP_PX
350
+ : direction === "left"
351
+ ? -(w + SPAWN_CONNECTED_GAP_PX)
352
+ : 0;
353
+ const alongY = direction === "down"
354
+ ? h + SPAWN_CONNECTED_GAP_PX
355
+ : direction === "up"
356
+ ? -(h + SPAWN_CONNECTED_GAP_PX)
357
+ : 0;
358
+ // Perpendicular step used to fan the siblings out, centred on the source.
359
+ const step = horizontal ? h + SPAWN_CONNECTED_GAP_PX : w + SPAWN_CONNECTED_GAP_PX;
360
+ const baseOrder = orderForTop([...scene.elements.values()].filter((e) => e.layerId === source.layerId).map((e) => e.order));
361
+ const baseLinkOrder = orderForTop([...scene.links.values()].filter((e) => e.layerId === source.layerId).map((e) => e.order));
362
+ // Detach any group / frame membership so spawned nodes are free-standing.
363
+ const { parentId: _p, frameId: _f, ...bare } = source;
364
+ void _p;
365
+ void _f;
366
+ const elements = [];
367
+ const links = [];
368
+ for (let i = 0; i < count; i++) {
369
+ const spread = (i - (count - 1) / 2) * step;
370
+ const dx = alongX + (horizontal ? 0 : spread);
371
+ const dy = alongY + (horizontal ? spread : 0);
372
+ const cloneId = makeElementId();
373
+ elements.push({
374
+ ...bare,
375
+ id: cloneId,
376
+ position: { x: source.position.x + dx, y: source.position.y + dy },
377
+ order: baseOrder,
378
+ });
379
+ links.push({
380
+ id: makeLinkId(),
381
+ layerId: source.layerId,
382
+ from: { kind: "floating", elementId: sourceId },
383
+ to: { kind: "floating", elementId: cloneId },
384
+ order: baseLinkOrder,
385
+ routing: DEFAULT_LINK_ROUTING,
386
+ style: { ...DEFAULT_EDGE_STYLE },
387
+ arrowheads: { to: DEFAULT_LINK_ARROWHEAD },
388
+ });
389
+ }
390
+ return { elements, links };
391
+ };
392
+ //# sourceMappingURL=tool-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-ops.js","sourceRoot":"","sources":["../../../src/editor/public/tool-ops.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type FractionalIndex, type Scene, type Patch } from "@oh-just-another/scene";
1
+ import { type Scene, type Patch } from "@oh-just-another/scene";
2
2
  import type { LayerId, ElementId } from "@oh-just-another/types";
3
3
  /** Move a shape to the top of its layer. */
4
4
  export declare const computeBringToFront: (scene: Scene, id: ElementId | undefined, selection: ReadonlySet<ElementId>) => {
@@ -27,17 +27,6 @@ export declare const computeSendBackward: (scene: Scene, id: ElementId | undefin
27
27
  readonly scene: Scene;
28
28
  readonly patch: Patch;
29
29
  } | null;
30
- /**
31
- * Rewrite the `order` field of every entity in `entities` to the i-th
32
- * key of `orderBetweenMany(null, null, n)`. Returns the count of
33
- * entities whose order actually changed.
34
- *
35
- * `apply` is the side-effect callback — the caller threads scene + tx
36
- * through it.
37
- */
38
- export declare const rewriteOrders: <T extends {
39
- readonly order: FractionalIndex;
40
- }>(entities: readonly T[], apply: (entity: T, order: FractionalIndex) => void) => number;
41
30
  /**
42
31
  * Run `rewriteOrders` over shapes + edges of every requested layer,
43
32
  * mutating the scene through the supplied `mutate` callback. Caller
@@ -1 +1 @@
1
- {"version":3,"file":"z-order.d.ts","sourceRoot":"","sources":["../../../src/editor/public/z-order.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,eAAe,EACpB,KAAK,KAAK,EACV,KAAK,KAAK,EACX,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAiBjE,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,GAC9B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAarD,CAAC;AAEF,+CAA+C;AAC/C,eAAO,MAAM,iBAAiB,GAC5B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAarD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAuBrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAmBrD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;CAAE,EACzE,UAAU,SAAS,CAAC,EAAE,EACtB,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,KAAK,IAAI,KACjD,MAYF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GACpC,OAAO,KAAK,EACZ,UAAU,SAAS,OAAO,EAAE,EAC5B,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,KAC/C,MAsBF,CAAC"}
1
+ {"version":3,"file":"z-order.d.ts","sourceRoot":"","sources":["../../../src/editor/public/z-order.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,KAAK,EACV,KAAK,KAAK,EACX,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAiBjE,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,GAC9B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAarD,CAAC;AAEF,+CAA+C;AAC/C,eAAO,MAAM,iBAAiB,GAC5B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAarD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAuBrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,KAAK,EACZ,IAAI,SAAS,GAAG,SAAS,EACzB,WAAW,WAAW,CAAC,SAAS,CAAC,KAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG,IAmBrD,CAAC;AA2BF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GACpC,OAAO,KAAK,EACZ,UAAU,SAAS,OAAO,EAAE,EAC5B,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,KAC/C,MAsBF,CAAC"}