@yuzhouu/canvas-kit 0.1.2

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 (263) hide show
  1. package/README.md +145 -0
  2. package/_vendor/canvas-core/bindings/BindingUtil.ts +92 -0
  3. package/_vendor/canvas-core/bindings/BindingUtilRegistry.ts +22 -0
  4. package/_vendor/canvas-core/bindings/arrow/arrowBindingHelpers.ts +52 -0
  5. package/_vendor/canvas-core/contextMenu.ts +85 -0
  6. package/_vendor/canvas-core/editor/Editor.ts +2614 -0
  7. package/_vendor/canvas-core/editor/HistoryManager.ts +83 -0
  8. package/_vendor/canvas-core/editor/StateNode.ts +162 -0
  9. package/_vendor/canvas-core/editor/camera.ts +6 -0
  10. package/_vendor/canvas-core/editor/clipboard.ts +478 -0
  11. package/_vendor/canvas-core/editor/commands.ts +833 -0
  12. package/_vendor/canvas-core/editor/edgeScroll.ts +37 -0
  13. package/_vendor/canvas-core/editor/editorComputedHelpers.ts +257 -0
  14. package/_vendor/canvas-core/editor/editorSelectionTransforms.ts +116 -0
  15. package/_vendor/canvas-core/editor/events.ts +93 -0
  16. package/_vendor/canvas-core/editor/index.ts +12 -0
  17. package/_vendor/canvas-core/editor/interactions.ts +101 -0
  18. package/_vendor/canvas-core/editor/internal.ts +22 -0
  19. package/_vendor/canvas-core/editor/managers/BindingManager.ts +262 -0
  20. package/_vendor/canvas-core/editor/managers/CameraManager.ts +147 -0
  21. package/_vendor/canvas-core/editor/managers/ClipboardManager.ts +32 -0
  22. package/_vendor/canvas-core/editor/managers/DocumentSnapshotManager.ts +256 -0
  23. package/_vendor/canvas-core/editor/managers/InputsManager.ts +319 -0
  24. package/_vendor/canvas-core/editor/managers/InteractionTransientManager.ts +218 -0
  25. package/_vendor/canvas-core/editor/managers/QueryManager.ts +837 -0
  26. package/_vendor/canvas-core/editor/managers/RenderWindowManager.ts +347 -0
  27. package/_vendor/canvas-core/editor/managers/SelectionLayoutManager.ts +196 -0
  28. package/_vendor/canvas-core/editor/managers/SelectionManager.ts +98 -0
  29. package/_vendor/canvas-core/editor/managers/SelectionOverlayManager.ts +308 -0
  30. package/_vendor/canvas-core/editor/managers/ShapeEditingManager.ts +226 -0
  31. package/_vendor/canvas-core/editor/managers/ShapeGeometryManager.ts +162 -0
  32. package/_vendor/canvas-core/editor/managers/ShapeHierarchyManager.ts +797 -0
  33. package/_vendor/canvas-core/editor/managers/SideEffectManager.ts +83 -0
  34. package/_vendor/canvas-core/editor/managers/SnapManager.ts +433 -0
  35. package/_vendor/canvas-core/editor/managers/SnapSnapshotBuilder.ts +430 -0
  36. package/_vendor/canvas-core/editor/managers/SpatialIndexManager.ts +354 -0
  37. package/_vendor/canvas-core/editor/managers/ToolManager.ts +81 -0
  38. package/_vendor/canvas-core/editor/managers/queryState.ts +583 -0
  39. package/_vendor/canvas-core/editor/managers/selectionGeometry.ts +287 -0
  40. package/_vendor/canvas-core/editor/managers/shapeOrder.ts +350 -0
  41. package/_vendor/canvas-core/editor/managers/shapeReparenting.ts +160 -0
  42. package/_vendor/canvas-core/editor/managers/snapCalculations.ts +412 -0
  43. package/_vendor/canvas-core/editor/managers/snapGeometry.ts +202 -0
  44. package/_vendor/canvas-core/editor/managers/snapIndicators.ts +403 -0
  45. package/_vendor/canvas-core/editor/managers/snapTypes.ts +122 -0
  46. package/_vendor/canvas-core/editor/queries/shapeTransforms.ts +171 -0
  47. package/_vendor/canvas-core/editor/renderWindow.ts +439 -0
  48. package/_vendor/canvas-core/editor/resizeGeometry.ts +654 -0
  49. package/_vendor/canvas-core/editor/selection.ts +489 -0
  50. package/_vendor/canvas-core/editor/selectionHandleInteractions.ts +43 -0
  51. package/_vendor/canvas-core/editor/selectionOverlay.ts +567 -0
  52. package/_vendor/canvas-core/exports/integrity.ts +174 -0
  53. package/_vendor/canvas-core/exports/svg.ts +494 -0
  54. package/_vendor/canvas-core/geometry/Box.ts +80 -0
  55. package/_vendor/canvas-core/geometry/Ellipse2d.ts +67 -0
  56. package/_vendor/canvas-core/geometry/Geometry2d.ts +52 -0
  57. package/_vendor/canvas-core/geometry/Mat.ts +92 -0
  58. package/_vendor/canvas-core/geometry/Polyline2d.ts +63 -0
  59. package/_vendor/canvas-core/geometry/Rectangle2d.ts +64 -0
  60. package/_vendor/canvas-core/geometry/Vec.ts +123 -0
  61. package/_vendor/canvas-core/geometry/index.ts +13 -0
  62. package/_vendor/canvas-core/geometry/segments.ts +65 -0
  63. package/_vendor/canvas-core/index.ts +391 -0
  64. package/_vendor/canvas-core/plugins/index.ts +5 -0
  65. package/_vendor/canvas-core/plugins/types.ts +53 -0
  66. package/_vendor/canvas-core/reactivity.ts +16 -0
  67. package/_vendor/canvas-core/schema/records.ts +221 -0
  68. package/_vendor/canvas-core/schema/snapshots.ts +527 -0
  69. package/_vendor/canvas-core/shapes/ShapeUtil.ts +516 -0
  70. package/_vendor/canvas-core/shapes/ShapeUtilRegistry.ts +26 -0
  71. package/_vendor/canvas-core/shapes/capabilities.ts +67 -0
  72. package/_vendor/canvas-core/shapes/types.ts +20 -0
  73. package/_vendor/canvas-core/toolbar.ts +148 -0
  74. package/_vendor/canvas-core/tools/hand/HandTool.ts +75 -0
  75. package/_vendor/canvas-core/tools/index.ts +2 -0
  76. package/_vendor/canvas-core/tools/select/SelectTool.ts +33 -0
  77. package/_vendor/canvas-core/tools/select/selectContainment.ts +104 -0
  78. package/_vendor/canvas-core/tools/select/selectToolHelpers.ts +801 -0
  79. package/_vendor/canvas-core/tools/select/states/BrushingState.ts +145 -0
  80. package/_vendor/canvas-core/tools/select/states/DraggingSelectionHandleInteractionState.ts +116 -0
  81. package/_vendor/canvas-core/tools/select/states/IdleState.ts +159 -0
  82. package/_vendor/canvas-core/tools/select/states/PointingCanvasState.ts +41 -0
  83. package/_vendor/canvas-core/tools/select/states/PointingResizeHandleState.ts +78 -0
  84. package/_vendor/canvas-core/tools/select/states/PointingRotateHandleState.ts +64 -0
  85. package/_vendor/canvas-core/tools/select/states/PointingSelectionHandleInteractionState.ts +34 -0
  86. package/_vendor/canvas-core/tools/select/states/PointingShapeState.ts +140 -0
  87. package/_vendor/canvas-core/tools/select/states/ResizingState.ts +171 -0
  88. package/_vendor/canvas-core/tools/select/states/RotatingState.ts +124 -0
  89. package/_vendor/canvas-core/tools/select/states/SelectStateNode.ts +128 -0
  90. package/_vendor/canvas-core/tools/select/states/TranslatingState.ts +139 -0
  91. package/_vendor/canvas-core/tools/select/states/index.ts +11 -0
  92. package/_vendor/canvas-plugin-api/feature.ts +204 -0
  93. package/_vendor/canvas-plugin-api/index.ts +142 -0
  94. package/_vendor/canvas-product-react/api/apiRegistry.ts +35 -0
  95. package/_vendor/canvas-product-react/api/canvasProductApi.ts +422 -0
  96. package/_vendor/canvas-product-react/api/index.ts +31 -0
  97. package/_vendor/canvas-product-react/capabilities/clipboard/clipboardService.ts +36 -0
  98. package/_vendor/canvas-product-react/capabilities/clipboard/systemClipboard.ts +245 -0
  99. package/_vendor/canvas-product-react/capabilities/context-menu/systemContextMenu.ts +396 -0
  100. package/_vendor/canvas-product-react/capabilities/context-menu/useContextMenuSurface.ts +59 -0
  101. package/_vendor/canvas-product-react/capabilities/export/useSvgExport.ts +156 -0
  102. package/_vendor/canvas-product-react/capabilities/history/useHistoryControls.ts +23 -0
  103. package/_vendor/canvas-product-react/capabilities/pages/usePageControls.ts +41 -0
  104. package/_vendor/canvas-product-react/capabilities/toolbar/systemToolbar.ts +490 -0
  105. package/_vendor/canvas-product-react/capabilities/toolbar/useToolbarSurfaces.ts +92 -0
  106. package/_vendor/canvas-product-react/capabilities/zoom/useZoomControls.ts +27 -0
  107. package/_vendor/canvas-product-react/index.ts +84 -0
  108. package/_vendor/canvas-product-react/persistence/index.ts +18 -0
  109. package/_vendor/canvas-product-react/persistence/localSnapshotPersistence.ts +294 -0
  110. package/_vendor/canvas-product-react/runtime/CanvasProductRoot.tsx +250 -0
  111. package/_vendor/canvas-product-react/runtime/productDefinition.ts +72 -0
  112. package/_vendor/canvas-product-react/runtime/productServices.ts +96 -0
  113. package/_vendor/canvas-react/components/CanvasView.tsx +796 -0
  114. package/_vendor/canvas-react/components/OverlayLayer.tsx +879 -0
  115. package/_vendor/canvas-react/components/PageSpace.tsx +34 -0
  116. package/_vendor/canvas-react/components/ShapeLayer.tsx +428 -0
  117. package/_vendor/canvas-react/components/index.ts +4 -0
  118. package/_vendor/canvas-react/hooks/useEditor.ts +11 -0
  119. package/_vendor/canvas-react/hooks/useValue.ts +14 -0
  120. package/_vendor/canvas-react/host/CanvasRendererRegistryContext.tsx +14 -0
  121. package/_vendor/canvas-react/host/contextMenuRegistry.ts +61 -0
  122. package/_vendor/canvas-react/host/domEventGuards.ts +61 -0
  123. package/_vendor/canvas-react/host/index.ts +38 -0
  124. package/_vendor/canvas-react/host/pluginHost.ts +635 -0
  125. package/_vendor/canvas-react/host/rendererRegistry.tsx +58 -0
  126. package/_vendor/canvas-react/host/toolbarRegistry.ts +100 -0
  127. package/_vendor/canvas-react/index.ts +3 -0
  128. package/_vendor/plugin-arrow/ArrowBindingUtil.ts +239 -0
  129. package/_vendor/plugin-arrow/ArrowShapeUtil.ts +311 -0
  130. package/_vendor/plugin-arrow/ArrowTool.ts +208 -0
  131. package/_vendor/plugin-arrow/arrowGeometry.ts +441 -0
  132. package/_vendor/plugin-arrow/arrowTerminalBindingResolver.ts +253 -0
  133. package/_vendor/plugin-arrow/arrowTerminalCommands.ts +230 -0
  134. package/_vendor/plugin-arrow/canvas.tsx +92 -0
  135. package/_vendor/plugin-arrow/core.ts +409 -0
  136. package/_vendor/plugin-arrow/feature.ts +20 -0
  137. package/_vendor/plugin-arrow/index.ts +28 -0
  138. package/_vendor/plugin-arrow/selectionHandleInteractions.ts +154 -0
  139. package/_vendor/plugin-arrow/types.ts +63 -0
  140. package/_vendor/plugin-draw/DrawShapeRenderer.tsx +60 -0
  141. package/_vendor/plugin-draw/DrawShapeUtil.ts +372 -0
  142. package/_vendor/plugin-draw/DrawTool.ts +444 -0
  143. package/_vendor/plugin-draw/canvas.tsx +24 -0
  144. package/_vendor/plugin-draw/core.ts +515 -0
  145. package/_vendor/plugin-draw/drawGeometry.ts +491 -0
  146. package/_vendor/plugin-draw/drawHitTest.ts +271 -0
  147. package/_vendor/plugin-draw/drawInterpolation.ts +250 -0
  148. package/_vendor/plugin-draw/drawPath.ts +550 -0
  149. package/_vendor/plugin-draw/drawSegments.ts +106 -0
  150. package/_vendor/plugin-draw/drawSelectionTransform.ts +67 -0
  151. package/_vendor/plugin-draw/drawShapeGeometry.ts +307 -0
  152. package/_vendor/plugin-draw/drawStrokeGeometry.ts +454 -0
  153. package/_vendor/plugin-draw/feature.ts +20 -0
  154. package/_vendor/plugin-draw/index.ts +31 -0
  155. package/_vendor/plugin-draw/types.ts +36 -0
  156. package/_vendor/plugin-eraser/EraserTool.ts +297 -0
  157. package/_vendor/plugin-eraser/canvas.tsx +616 -0
  158. package/_vendor/plugin-eraser/core.ts +49 -0
  159. package/_vendor/plugin-eraser/feature.ts +20 -0
  160. package/_vendor/plugin-eraser/index.ts +4 -0
  161. package/_vendor/plugin-frame/FrameShapeUtil.ts +173 -0
  162. package/_vendor/plugin-frame/FrameTool.ts +225 -0
  163. package/_vendor/plugin-frame/canvas.tsx +75 -0
  164. package/_vendor/plugin-frame/core.ts +534 -0
  165. package/_vendor/plugin-frame/feature.ts +20 -0
  166. package/_vendor/plugin-frame/index.ts +6 -0
  167. package/_vendor/plugin-geo/GeoShapeUtil.ts +463 -0
  168. package/_vendor/plugin-geo/GeoTools.ts +247 -0
  169. package/_vendor/plugin-geo/canvas.tsx +90 -0
  170. package/_vendor/plugin-geo/core.ts +495 -0
  171. package/_vendor/plugin-geo/feature.ts +20 -0
  172. package/_vendor/plugin-geo/index.ts +7 -0
  173. package/_vendor/plugin-geo/types.ts +27 -0
  174. package/_vendor/plugin-group/GroupShapeUtil.ts +59 -0
  175. package/_vendor/plugin-group/canvas.tsx +59 -0
  176. package/_vendor/plugin-group/core.ts +40 -0
  177. package/_vendor/plugin-group/feature.ts +20 -0
  178. package/_vendor/plugin-group/index.ts +5 -0
  179. package/_vendor/plugin-image/ImageShapeUtil.ts +95 -0
  180. package/_vendor/plugin-image/canvas.tsx +212 -0
  181. package/_vendor/plugin-image/core.ts +542 -0
  182. package/_vendor/plugin-image/crop.ts +770 -0
  183. package/_vendor/plugin-image/cropInteractions.ts +350 -0
  184. package/_vendor/plugin-image/cropSession.ts +38 -0
  185. package/_vendor/plugin-image/feature.ts +20 -0
  186. package/_vendor/plugin-image/index.ts +29 -0
  187. package/_vendor/plugin-image/types.ts +55 -0
  188. package/_vendor/plugin-image-product-react/ImageImportController.tsx +143 -0
  189. package/_vendor/plugin-image-product-react/imageAssetService.ts +52 -0
  190. package/_vendor/plugin-image-product-react/imageBlobStore.ts +315 -0
  191. package/_vendor/plugin-image-product-react/imageHostActions.ts +438 -0
  192. package/_vendor/plugin-image-product-react/imageProductApi.ts +88 -0
  193. package/_vendor/plugin-image-product-react/imageToolbarHostBridge.ts +48 -0
  194. package/_vendor/plugin-image-product-react/imageToolbarRuntime.ts +21 -0
  195. package/_vendor/plugin-image-product-react/index.ts +60 -0
  196. package/_vendor/plugin-image-product-react/snapshotGuards.ts +33 -0
  197. package/_vendor/plugin-image-product-react/svgImageAssetInliner.ts +54 -0
  198. package/_vendor/plugin-image-product-react/useImageImport.ts +64 -0
  199. package/_vendor/plugin-laser/LaserTool.ts +154 -0
  200. package/_vendor/plugin-laser/canvas.tsx +645 -0
  201. package/_vendor/plugin-laser/core.ts +49 -0
  202. package/_vendor/plugin-laser/feature.ts +20 -0
  203. package/_vendor/plugin-laser/index.ts +4 -0
  204. package/_vendor/plugin-text/ArrowLabelBindingUtil.ts +336 -0
  205. package/_vendor/plugin-text/GeoLabelBindingUtil.ts +391 -0
  206. package/_vendor/plugin-text/TextShapeSvgExporter.ts +101 -0
  207. package/_vendor/plugin-text/TextShapeUtil.ts +284 -0
  208. package/_vendor/plugin-text/TextTool.ts +228 -0
  209. package/_vendor/plugin-text/canvas.tsx +115 -0
  210. package/_vendor/plugin-text/core.ts +422 -0
  211. package/_vendor/plugin-text/feature.ts +20 -0
  212. package/_vendor/plugin-text/host/RichTextEditingBox.tsx +144 -0
  213. package/_vendor/plugin-text/host/RichTextToolbar.tsx +266 -0
  214. package/_vendor/plugin-text/host/TiptapTextEditor.tsx +191 -0
  215. package/_vendor/plugin-text/host/richTextRendering.tsx +49 -0
  216. package/_vendor/plugin-text/host/textDomSelection.ts +93 -0
  217. package/_vendor/plugin-text/host/textEditingBoxStyle.ts +36 -0
  218. package/_vendor/plugin-text/host/textEntryFocus.ts +307 -0
  219. package/_vendor/plugin-text/host/textFontLoader.ts +149 -0
  220. package/_vendor/plugin-text/host/textMeasurement.ts +258 -0
  221. package/_vendor/plugin-text/host/textMeasurementSync.ts +77 -0
  222. package/_vendor/plugin-text/host/textRangeSelection.ts +134 -0
  223. package/_vendor/plugin-text/host/textShapeRendererRuntime.tsx +89 -0
  224. package/_vendor/plugin-text/host/textShapeSync.ts +173 -0
  225. package/_vendor/plugin-text/host/tiptapTextEditorController.ts +148 -0
  226. package/_vendor/plugin-text/index.ts +18 -0
  227. package/_vendor/plugin-text/richTextUtils.ts +259 -0
  228. package/_vendor/plugin-text/textInteractions.ts +366 -0
  229. package/_vendor/plugin-text/textLabelHelpers.ts +235 -0
  230. package/_vendor/plugin-text/textShapeHelpers.ts +123 -0
  231. package/_vendor/plugin-text/textStyle.ts +96 -0
  232. package/_vendor/plugin-text/textTypes.ts +48 -0
  233. package/_vendor/signals/atom.ts +74 -0
  234. package/_vendor/signals/computed.ts +132 -0
  235. package/_vendor/signals/core.ts +130 -0
  236. package/_vendor/signals/effect.ts +117 -0
  237. package/_vendor/signals/index.ts +9 -0
  238. package/_vendor/signals/types.ts +17 -0
  239. package/_vendor/store/Store.ts +171 -0
  240. package/_vendor/store/diff.ts +229 -0
  241. package/_vendor/store/history.ts +177 -0
  242. package/_vendor/store/index.ts +32 -0
  243. package/_vendor/store/types.ts +37 -0
  244. package/api/canvasKitApi.d.ts +29 -0
  245. package/index.css +3 -0
  246. package/index.d.ts +16 -0
  247. package/index.mjs +1 -0
  248. package/internal-modules.d.ts +187 -0
  249. package/package.json +48 -0
  250. package/product/Shell.d.ts +19 -0
  251. package/product/chromeContext.d.ts +70 -0
  252. package/product/createCanvasKitEditor.d.ts +6 -0
  253. package/product/index.d.ts +7 -0
  254. package/product/persistence.d.ts +3 -0
  255. package/product/product.d.ts +22 -0
  256. package/product/useCanvasClipboardShortcuts.d.ts +6 -0
  257. package/product-iyBbEPIs.mjs +4 -0
  258. package/product.mjs +1 -0
  259. package/standard/extensions.d.ts +1 -0
  260. package/standard/index.d.ts +3 -0
  261. package/standard/standardApi.d.ts +91 -0
  262. package/standard-BmrxwqpJ.mjs +44 -0
  263. package/standard.mjs +1 -0
@@ -0,0 +1,37 @@
1
+ import { Vec } from "../geometry/Vec";
2
+
3
+ const EDGE_SCROLL_MARGIN_SCREEN = 96;
4
+ const EDGE_SCROLL_MAX_SPEED_SCREEN = 1.25;
5
+ const EDGE_SCROLL_MAX_ELAPSED = 32;
6
+
7
+ function getEdgeScrollFactor(distance: number): number {
8
+ return Math.min(
9
+ 1,
10
+ Math.max(
11
+ 0,
12
+ (EDGE_SCROLL_MARGIN_SCREEN - distance) / EDGE_SCROLL_MARGIN_SCREEN,
13
+ ),
14
+ );
15
+ }
16
+
17
+ export function getEdgeScrollDelta(
18
+ screenPoint: Vec,
19
+ viewportSize: { w: number; h: number },
20
+ elapsed: number,
21
+ ): Vec {
22
+ if (viewportSize.w <= 0 || viewportSize.h <= 0 || elapsed <= 0) {
23
+ return Vec.Zero();
24
+ }
25
+
26
+ const clampedElapsed = Math.min(elapsed, EDGE_SCROLL_MAX_ELAPSED);
27
+ const leftFactor = getEdgeScrollFactor(screenPoint.x);
28
+ const rightFactor = getEdgeScrollFactor(viewportSize.w - screenPoint.x);
29
+ const topFactor = getEdgeScrollFactor(screenPoint.y);
30
+ const bottomFactor = getEdgeScrollFactor(viewportSize.h - screenPoint.y);
31
+ const deltaX =
32
+ (rightFactor - leftFactor) * EDGE_SCROLL_MAX_SPEED_SCREEN * clampedElapsed;
33
+ const deltaY =
34
+ (bottomFactor - topFactor) * EDGE_SCROLL_MAX_SPEED_SCREEN * clampedElapsed;
35
+
36
+ return deltaX === 0 && deltaY === 0 ? Vec.Zero() : new Vec(deltaX, deltaY);
37
+ }
@@ -0,0 +1,257 @@
1
+ import type { Box } from "../geometry/Box";
2
+ import type { Vec } from "../geometry/Vec";
3
+ import type {
4
+ AssetId,
5
+ PageId,
6
+ ShapeId,
7
+ ShapeRecord,
8
+ } from "../schema/records";
9
+ import type { ArrowBindingPreviewState } from "./selection";
10
+ import type {
11
+ EditorOverlayDebugState,
12
+ EditorRenderHostDebugState,
13
+ RenderItem,
14
+ } from "./Editor";
15
+
16
+ export function areShapeIdArraysEqual(a: ShapeId[], b: ShapeId[]): boolean {
17
+ if (a === b) return true;
18
+ if (a.length !== b.length) return false;
19
+ for (let i = 0; i < a.length; i++) {
20
+ if (a[i] !== b[i]) return false;
21
+ }
22
+ return true;
23
+ }
24
+
25
+ export function areVecsEqual(a: Vec | null, b: Vec | null): boolean {
26
+ if (a === b) return true;
27
+ if (!a || !b) return a === b;
28
+ return a.x === b.x && a.y === b.y;
29
+ }
30
+
31
+ export function areVecArraysEqual(a: readonly Vec[], b: readonly Vec[]): boolean {
32
+ if (a === b) return true;
33
+ if (a.length !== b.length) return false;
34
+ for (let index = 0; index < a.length; index += 1) {
35
+ const left = a[index];
36
+ const right = b[index];
37
+ if (!left || !right || left.x !== right.x || left.y !== right.y) {
38
+ return false;
39
+ }
40
+ }
41
+ return true;
42
+ }
43
+
44
+ export function areBoxesEqual(a: Box | null, b: Box | null): boolean {
45
+ if (a === b) return true;
46
+ if (!a || !b) return a === b;
47
+ return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
48
+ }
49
+
50
+ export function isValidBox(box: Box): boolean {
51
+ return (
52
+ Number.isFinite(box.x) &&
53
+ Number.isFinite(box.y) &&
54
+ Number.isFinite(box.w) &&
55
+ Number.isFinite(box.h) &&
56
+ box.w >= 0 &&
57
+ box.h >= 0
58
+ );
59
+ }
60
+
61
+ export function areRenderHostDebugStatesEqual(
62
+ a: EditorRenderHostDebugState,
63
+ b: EditorRenderHostDebugState,
64
+ ): boolean {
65
+ return (
66
+ a.culledCount === b.culledCount &&
67
+ a.visibleCount === b.visibleCount &&
68
+ a.retainedCount === b.retainedCount &&
69
+ a.retainedBaseCount === b.retainedBaseCount &&
70
+ a.culledRangeCount === b.culledRangeCount &&
71
+ a.culledRangeSpan === b.culledRangeSpan &&
72
+ a.culledRangesSummary === b.culledRangesSummary &&
73
+ a.retainedBaseRangeCount === b.retainedBaseRangeCount &&
74
+ a.retainedBaseRangeSpan === b.retainedBaseRangeSpan &&
75
+ a.retainedBaseRangesSummary === b.retainedBaseRangesSummary &&
76
+ a.retainedRangeCount === b.retainedRangeCount &&
77
+ a.retainedRangeSpan === b.retainedRangeSpan &&
78
+ a.retainedRangesSummary === b.retainedRangesSummary &&
79
+ a.retainedChangeCount === b.retainedChangeCount &&
80
+ a.retainedAddedCount === b.retainedAddedCount &&
81
+ a.retainedRemovedCount === b.retainedRemovedCount &&
82
+ a.selectedOutsideCulledCount === b.selectedOutsideCulledCount
83
+ );
84
+ }
85
+
86
+ export function areOverlayDebugStatesEqual(
87
+ a: EditorOverlayDebugState,
88
+ b: EditorOverlayDebugState,
89
+ ): boolean {
90
+ return (
91
+ a.selectionFrameActive === b.selectionFrameActive &&
92
+ a.selectionHandlesActive === b.selectionHandlesActive &&
93
+ a.bindingPreviewActive === b.bindingPreviewActive &&
94
+ a.brushBoxActive === b.brushBoxActive &&
95
+ a.selectionFrameChangeCount === b.selectionFrameChangeCount &&
96
+ a.selectionHandlesChangeCount === b.selectionHandlesChangeCount &&
97
+ a.resizeHandleCount === b.resizeHandleCount &&
98
+ a.rotateHandleCount === b.rotateHandleCount &&
99
+ a.terminalHandleCount === b.terminalHandleCount &&
100
+ a.middleHandleCount === b.middleHandleCount &&
101
+ a.customHandleCount === b.customHandleCount &&
102
+ a.boundsSummary === b.boundsSummary &&
103
+ a.rotation === b.rotation &&
104
+ a.strokeWidth === b.strokeWidth
105
+ );
106
+ }
107
+
108
+ export function getBoxDebugSummary(box: Box | null): string {
109
+ if (!box) {
110
+ return "none";
111
+ }
112
+ return `${Math.round(box.x)},${Math.round(box.y)},${Math.round(
113
+ box.w,
114
+ )},${Math.round(box.h)}`;
115
+ }
116
+
117
+ export function getShapePageIdFromParentChain(
118
+ shape: ShapeRecord,
119
+ shapeById: ReadonlyMap<ShapeId, ShapeRecord>,
120
+ pageIds: ReadonlySet<PageId>,
121
+ ): PageId | null {
122
+ const seen = new Set<ShapeId>([shape.id]);
123
+ let parentId = shape.parentId;
124
+
125
+ while (parentId.startsWith("shape:")) {
126
+ const parentShapeId = parentId as ShapeId;
127
+ if (seen.has(parentShapeId)) {
128
+ return null;
129
+ }
130
+ seen.add(parentShapeId);
131
+
132
+ const parentShape = shapeById.get(parentShapeId);
133
+ if (!parentShape) {
134
+ return null;
135
+ }
136
+ parentId = parentShape.parentId;
137
+ }
138
+
139
+ return pageIds.has(parentId as PageId) ? (parentId as PageId) : null;
140
+ }
141
+
142
+ export function areBindingPreviewStatesEqual(
143
+ a: ArrowBindingPreviewState | null,
144
+ b: ArrowBindingPreviewState | null,
145
+ ): boolean {
146
+ if (a === b) return true;
147
+ if (!a || !b) return a === b;
148
+ return (
149
+ a.terminal === b.terminal &&
150
+ a.targetShapeId === b.targetShapeId &&
151
+ areVecsEqual(a.rawPagePoint, b.rawPagePoint) &&
152
+ areVecsEqual(a.resolvedPagePoint, b.resolvedPagePoint)
153
+ );
154
+ }
155
+
156
+ export function areRenderItemsEqual(a: RenderItem[], b: RenderItem[]): boolean {
157
+ if (a === b) return true;
158
+ if (a.length !== b.length) return false;
159
+ for (let i = 0; i < a.length; i += 1) {
160
+ const left = a[i];
161
+ const right = b[i];
162
+ if (!left || !right) {
163
+ return false;
164
+ }
165
+ if (
166
+ left.id !== right.id ||
167
+ left.shape !== right.shape ||
168
+ left.isSelected !== right.isSelected ||
169
+ !areBoxesEqual(left.bounds, right.bounds)
170
+ ) {
171
+ return false;
172
+ }
173
+ }
174
+ return true;
175
+ }
176
+
177
+ export function areShapeIdSetsEqual(a: Set<ShapeId>, b: Set<ShapeId>): boolean {
178
+ if (a === b) return true;
179
+ if (a.size !== b.size) return false;
180
+ for (const id of a) {
181
+ if (!b.has(id)) {
182
+ return false;
183
+ }
184
+ }
185
+ return true;
186
+ }
187
+
188
+ export function getCommonShapeType(
189
+ shapes: readonly ShapeRecord[],
190
+ ): ShapeRecord["type"] | null {
191
+ let commonType: ShapeRecord["type"] | null = null;
192
+ for (const shape of shapes) {
193
+ if (commonType === null) {
194
+ commonType = shape.type;
195
+ continue;
196
+ }
197
+ if (commonType !== shape.type) {
198
+ return null;
199
+ }
200
+ }
201
+ return commonType;
202
+ }
203
+
204
+ export function getShapeAssetId(shape: ShapeRecord): AssetId | null {
205
+ const assetId = (shape.props as Record<string, unknown>).assetId;
206
+ return typeof assetId === "string" && assetId.startsWith("asset:")
207
+ ? (assetId as AssetId)
208
+ : null;
209
+ }
210
+
211
+ export function areSerializableValuesEqual(a: unknown, b: unknown): boolean {
212
+ if (Object.is(a, b)) return true;
213
+ if (typeof a !== typeof b) return false;
214
+ if (!a || !b || typeof a !== "object" || typeof b !== "object") {
215
+ return false;
216
+ }
217
+
218
+ if (Array.isArray(a) || Array.isArray(b)) {
219
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
220
+ return false;
221
+ }
222
+ return a.every((value, index) =>
223
+ areSerializableValuesEqual(value, b[index]),
224
+ );
225
+ }
226
+
227
+ const aRecord = a as Record<string, unknown>;
228
+ const bRecord = b as Record<string, unknown>;
229
+ const aKeys = Object.keys(aRecord);
230
+ const bKeys = Object.keys(bRecord);
231
+ if (aKeys.length !== bKeys.length) {
232
+ return false;
233
+ }
234
+ return aKeys.every(
235
+ (key) =>
236
+ Object.prototype.hasOwnProperty.call(bRecord, key) &&
237
+ areSerializableValuesEqual(aRecord[key], bRecord[key]),
238
+ );
239
+ }
240
+
241
+ export function areShapePropsPatchesEqual(
242
+ a: Readonly<Record<string, unknown>>,
243
+ b: Readonly<Record<string, unknown>>,
244
+ ): boolean {
245
+ if (a === b) return true;
246
+ const aEntries = Object.entries(a);
247
+ const bEntries = Object.entries(b);
248
+ if (aEntries.length !== bEntries.length) {
249
+ return false;
250
+ }
251
+ for (const [key, value] of aEntries) {
252
+ if (!areSerializableValuesEqual(value, b[key])) {
253
+ return false;
254
+ }
255
+ }
256
+ return true;
257
+ }
@@ -0,0 +1,116 @@
1
+ import type { ChangeSource } from "@land/store";
2
+ import { Box } from "../geometry/Box";
3
+ import type { ShapeRecord } from "../schema/records";
4
+ import type { ShapeSelectionFlipAxis } from "../shapes/ShapeUtil";
5
+ import type { ShapeUpdate } from "./commands";
6
+ import type { Editor } from "./Editor";
7
+ import {
8
+ flipSelectionLocalBounds,
9
+ getSelectionLocalBoundsFromPagePoints,
10
+ type SelectionFrame,
11
+ } from "./selection";
12
+
13
+ export function resetEditorSelectionRotation(
14
+ editor: Editor,
15
+ source: ChangeSource = "user",
16
+ ): void {
17
+ const selectedShapes = editor.getSelectedShapes().filter((shape) =>
18
+ editor.getShapeUtil(shape).contributesToSelectionFrame(shape, {
19
+ editor,
20
+ }),
21
+ );
22
+ if (selectedShapes.length === 0) {
23
+ return;
24
+ }
25
+ editor.commands.updateShapes(
26
+ selectedShapes.map((shape) => ({
27
+ id: shape.id,
28
+ rotation: 0,
29
+ })),
30
+ { source },
31
+ );
32
+ }
33
+
34
+ export function getEditorSelectionFlipUpdates(
35
+ editor: Editor,
36
+ axis: ShapeSelectionFlipAxis,
37
+ ): ShapeUpdate[] {
38
+ const selectedShapes = editor.getSelectionTransformTargetShapes();
39
+ const selectionFrame =
40
+ editor.getSelectionFrame() ?? getPointSelectionFrame(editor, selectedShapes);
41
+ if (!selectionFrame || selectedShapes.length === 0) {
42
+ return [];
43
+ }
44
+
45
+ return selectedShapes
46
+ .map((shape) => getFlippedShapeUpdate(editor, shape, selectionFrame, axis))
47
+ .filter((update): update is ShapeUpdate => update !== null);
48
+ }
49
+
50
+ function getFlippedShapeUpdate(
51
+ editor: Editor,
52
+ shape: ShapeRecord,
53
+ selectionFrame: SelectionFrame,
54
+ axis: ShapeSelectionFlipAxis,
55
+ ): ShapeUpdate | null {
56
+ const util = editor.getShapeUtil(shape);
57
+ const pointSelection = util.getSelectionPagePoints(shape);
58
+ if (
59
+ !pointSelection &&
60
+ !util.contributesToSelectionFrame(shape, {
61
+ editor,
62
+ })
63
+ ) {
64
+ return null;
65
+ }
66
+
67
+ const pagePoints =
68
+ pointSelection ?
69
+ [...pointSelection]
70
+ : util
71
+ .getPositionedOutlineVertices(shape)
72
+ .map((point) =>
73
+ editor
74
+ .computeShapePositionedToPageTransform(shape)
75
+ .applyToPoint(point),
76
+ );
77
+ const localBounds = getSelectionLocalBoundsFromPagePoints({
78
+ points: pagePoints,
79
+ transform: selectionFrame,
80
+ });
81
+ if (!localBounds) {
82
+ return null;
83
+ }
84
+
85
+ return util.flipSelectionBounds(shape, {
86
+ axis,
87
+ selectionBounds: selectionFrame.bounds,
88
+ selectionLocalBounds: flipSelectionLocalBounds({
89
+ axis,
90
+ bounds: localBounds,
91
+ selectionBounds: selectionFrame.bounds,
92
+ }),
93
+ selectionRotation: selectionFrame.rotation,
94
+ selectionRotationCenter: selectionFrame.rotationCenter,
95
+ });
96
+ }
97
+
98
+ function getPointSelectionFrame(
99
+ editor: Editor,
100
+ shapes: readonly ShapeRecord[],
101
+ ): SelectionFrame | null {
102
+ const points = shapes.flatMap(
103
+ (shape) => editor.getShapeUtil(shape).getSelectionPagePoints(shape) ?? [],
104
+ );
105
+ if (points.length === 0) {
106
+ return null;
107
+ }
108
+
109
+ const bounds = Box.FromPoints(points);
110
+ return {
111
+ bounds,
112
+ rotation: 0,
113
+ rotationCenter: bounds.center,
114
+ hasCompatibleRotation: true,
115
+ };
116
+ }
@@ -0,0 +1,93 @@
1
+ import type { Vec } from "../geometry/Vec";
2
+
3
+ export type EditorPointerType = "mouse" | "touch" | "pen";
4
+ export type EditorClickEventName = "double_click";
5
+
6
+ export interface PointerEditorEvent {
7
+ type: "pointer";
8
+ name: "pointer_down" | "pointer_move" | "pointer_up" | "pointer_cancel";
9
+ timestamp: number;
10
+ pointerId: number;
11
+ button: number;
12
+ buttons: number;
13
+ pointerType: EditorPointerType;
14
+ clickCount?: number;
15
+ screenPoint: Vec;
16
+ pagePoint: Vec;
17
+ pressure: number;
18
+ shiftKey: boolean;
19
+ altKey: boolean;
20
+ ctrlKey: boolean;
21
+ metaKey: boolean;
22
+ accelKey: boolean;
23
+ }
24
+
25
+ export interface ClickEditorEvent {
26
+ type: "click";
27
+ name: EditorClickEventName;
28
+ phase: "down" | "up";
29
+ timestamp: number;
30
+ pointerId: number;
31
+ button: number;
32
+ buttons: number;
33
+ pointerType: EditorPointerType;
34
+ screenPoint: Vec;
35
+ pagePoint: Vec;
36
+ pressure: number;
37
+ shiftKey: boolean;
38
+ altKey: boolean;
39
+ ctrlKey: boolean;
40
+ metaKey: boolean;
41
+ accelKey: boolean;
42
+ }
43
+
44
+ export interface KeyboardEditorEvent {
45
+ type: "keyboard";
46
+ name: "key_down" | "key_up";
47
+ key: string;
48
+ code: string;
49
+ shiftKey: boolean;
50
+ altKey: boolean;
51
+ ctrlKey: boolean;
52
+ metaKey: boolean;
53
+ accelKey: boolean;
54
+ }
55
+
56
+ export interface WheelEditorEvent {
57
+ type: "wheel";
58
+ screenPoint: Vec;
59
+ pagePoint: Vec;
60
+ delta: Vec;
61
+ shiftKey: boolean;
62
+ altKey: boolean;
63
+ ctrlKey: boolean;
64
+ metaKey: boolean;
65
+ accelKey: boolean;
66
+ }
67
+
68
+ export interface TickEditorEvent {
69
+ type: "tick";
70
+ timestamp: number;
71
+ elapsed: number;
72
+ }
73
+
74
+ export interface CancelEditorEvent {
75
+ type: "cancel";
76
+ reason:
77
+ | "escape"
78
+ | "pointer_cancel"
79
+ | "blur"
80
+ | "page_switch"
81
+ | "tool_switch"
82
+ | "dispose"
83
+ | "command"
84
+ | "restore";
85
+ }
86
+
87
+ export type EditorEvent =
88
+ | PointerEditorEvent
89
+ | ClickEditorEvent
90
+ | KeyboardEditorEvent
91
+ | WheelEditorEvent
92
+ | TickEditorEvent
93
+ | CancelEditorEvent;
@@ -0,0 +1,12 @@
1
+ export { Editor } from "./Editor";
2
+ export { StateNode } from "./StateNode";
3
+ export { HistoryManager } from "./HistoryManager";
4
+ export { InputsManager } from "./managers/InputsManager";
5
+ export { QueryManager } from "./managers/QueryManager";
6
+ export {
7
+ SpatialIndexManager,
8
+ type ShapeAtPointOptions,
9
+ type SpatialQueryOptions,
10
+ } from "./managers/SpatialIndexManager";
11
+ export { ToolManager } from "./managers/ToolManager";
12
+ export type { EditorEvent } from "./events";
@@ -0,0 +1,101 @@
1
+ import type { ChangeSource } from "@land/store";
2
+ import type { Vec } from "../geometry/Vec";
3
+ import type { ShapeId, ShapeRecord } from "../schema/records";
4
+ import type { Editor } from "./Editor";
5
+ import type { EditorEvent } from "./events";
6
+ import type { SelectionHandle } from "./selection";
7
+ import type {
8
+ HandleSnapContext,
9
+ HandleSnapMode,
10
+ } from "./managers/snapTypes";
11
+
12
+ export interface SelectionHandleInteractionInput {
13
+ handle: SelectionHandle;
14
+ shape: ShapeRecord;
15
+ originPagePoint: Vec;
16
+ }
17
+
18
+ export interface SelectionHandleInteractionSession {
19
+ readonly shapeId: ShapeId;
20
+ readonly historyMark: string;
21
+ readonly handleSnapMode?: HandleSnapMode;
22
+ readonly handleSnapContext?: HandleSnapContext;
23
+ readonly allowSelfSnap?: boolean;
24
+ readonly excludedSnapShapeIds?: readonly ShapeId[];
25
+ readonly shouldClearBindingPreviewOnExit?: boolean;
26
+ update(input: {
27
+ editor: Editor;
28
+ pagePoint: Vec;
29
+ accelKey: boolean;
30
+ source: ChangeSource;
31
+ }): "continue" | "stop" | SelectionHandleInteractionUpdateResult;
32
+ }
33
+
34
+ export interface SelectionHandleInteractionUpdateResult {
35
+ status: "continue" | "stop";
36
+ finalPagePoint?: Vec | null;
37
+ }
38
+
39
+ export interface SelectionHandleInteractionHandler {
40
+ createSession(
41
+ editor: Editor,
42
+ input: SelectionHandleInteractionInput,
43
+ ): SelectionHandleInteractionSession | null;
44
+ }
45
+
46
+ export type EditorEventInteractionDecision = "continue" | "handled";
47
+
48
+ export interface EditorEventInteractionHandler {
49
+ handleEvent(
50
+ editor: Editor,
51
+ event: EditorEvent,
52
+ ): EditorEventInteractionDecision;
53
+ }
54
+
55
+ export interface LandInteractionHandler {
56
+ id: string;
57
+ editorEvent?: EditorEventInteractionHandler;
58
+ selectionHandle?: SelectionHandleInteractionHandler;
59
+ }
60
+
61
+ export class InteractionHandlerRegistry {
62
+ private readonly handlers: LandInteractionHandler[] = [];
63
+ private readonly registeredIds = new Set<string>();
64
+
65
+ register(handler: LandInteractionHandler): void {
66
+ if (this.registeredIds.has(handler.id)) {
67
+ return;
68
+ }
69
+
70
+ this.handlers.push(handler);
71
+ this.registeredIds.add(handler.id);
72
+ }
73
+
74
+ getHandlers(): readonly LandInteractionHandler[] {
75
+ return this.handlers;
76
+ }
77
+
78
+ handleEvent(editor: Editor, event: EditorEvent): EditorEventInteractionDecision {
79
+ for (const handler of this.handlers) {
80
+ if (handler.editorEvent?.handleEvent(editor, event) === "handled") {
81
+ return "handled";
82
+ }
83
+ }
84
+
85
+ return "continue";
86
+ }
87
+
88
+ createSelectionHandleSession(
89
+ editor: Editor,
90
+ input: SelectionHandleInteractionInput,
91
+ ): SelectionHandleInteractionSession | null {
92
+ for (const handler of this.handlers) {
93
+ const session = handler.selectionHandle?.createSession(editor, input);
94
+ if (session) {
95
+ return session;
96
+ }
97
+ }
98
+
99
+ return null;
100
+ }
101
+ }
@@ -0,0 +1,22 @@
1
+ import type { Editor } from "./Editor";
2
+ import type { Store } from "@land/store";
3
+ import type { EditorRecord } from "../schema/records";
4
+
5
+ const editorStoreSymbol = Symbol("editorStore");
6
+
7
+ type EditorWithInternalStore = Editor & {
8
+ [editorStoreSymbol]: Store<EditorRecord>;
9
+ };
10
+
11
+ export function setEditorStore(
12
+ editor: Editor,
13
+ store: Store<EditorRecord>,
14
+ ): void {
15
+ (editor as EditorWithInternalStore)[editorStoreSymbol] = store;
16
+ }
17
+
18
+ export function getEditorStore(editor: Editor): Store<EditorRecord> {
19
+ return (editor as EditorWithInternalStore)[editorStoreSymbol];
20
+ }
21
+
22
+ export { editorStoreSymbol };