@archireport/react-native-drawing 0.2.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 (323) hide show
  1. package/README.md +181 -0
  2. package/lib/commonjs/DrawingEditor.js +815 -0
  3. package/lib/commonjs/DrawingEditor.js.map +1 -0
  4. package/lib/commonjs/assets/toolbar-icons/arrow-disabled.png +0 -0
  5. package/lib/commonjs/assets/toolbar-icons/arrow-enabled.png +0 -0
  6. package/lib/commonjs/assets/toolbar-icons/arrow.png +0 -0
  7. package/lib/commonjs/assets/toolbar-icons/circle-disabled.png +0 -0
  8. package/lib/commonjs/assets/toolbar-icons/circle-enabled.png +0 -0
  9. package/lib/commonjs/assets/toolbar-icons/circle.png +0 -0
  10. package/lib/commonjs/assets/toolbar-icons/freehand-disabled.png +0 -0
  11. package/lib/commonjs/assets/toolbar-icons/freehand-enabled.png +0 -0
  12. package/lib/commonjs/assets/toolbar-icons/freehand.png +0 -0
  13. package/lib/commonjs/assets/toolbar-icons/line-disabled.png +0 -0
  14. package/lib/commonjs/assets/toolbar-icons/line-enabled.png +0 -0
  15. package/lib/commonjs/assets/toolbar-icons/line.png +0 -0
  16. package/lib/commonjs/assets/toolbar-icons/measure-disabled.png +0 -0
  17. package/lib/commonjs/assets/toolbar-icons/measure-enabled.png +0 -0
  18. package/lib/commonjs/assets/toolbar-icons/measure.png +0 -0
  19. package/lib/commonjs/assets/toolbar-icons/move-disabled.png +0 -0
  20. package/lib/commonjs/assets/toolbar-icons/move-enabled.png +0 -0
  21. package/lib/commonjs/assets/toolbar-icons/move.png +0 -0
  22. package/lib/commonjs/assets/toolbar-icons/polygon-disabled.png +0 -0
  23. package/lib/commonjs/assets/toolbar-icons/polygon-enabled.png +0 -0
  24. package/lib/commonjs/assets/toolbar-icons/polygon.png +0 -0
  25. package/lib/commonjs/assets/toolbar-icons/rectangle-disabled.png +0 -0
  26. package/lib/commonjs/assets/toolbar-icons/rectangle-enabled.png +0 -0
  27. package/lib/commonjs/assets/toolbar-icons/rectangle.png +0 -0
  28. package/lib/commonjs/assets/toolbar-icons/text-disabled.png +0 -0
  29. package/lib/commonjs/assets/toolbar-icons/text-enabled.png +0 -0
  30. package/lib/commonjs/assets/toolbar-icons/text.png +0 -0
  31. package/lib/commonjs/components/ColorPalette.js +379 -0
  32. package/lib/commonjs/components/ColorPalette.js.map +1 -0
  33. package/lib/commonjs/components/LineWidthSlider.js +70 -0
  34. package/lib/commonjs/components/LineWidthSlider.js.map +1 -0
  35. package/lib/commonjs/components/MeasurementEditModal.js +153 -0
  36. package/lib/commonjs/components/MeasurementEditModal.js.map +1 -0
  37. package/lib/commonjs/components/MiniMap.js +244 -0
  38. package/lib/commonjs/components/MiniMap.js.map +1 -0
  39. package/lib/commonjs/components/TextAnnotation.js +162 -0
  40. package/lib/commonjs/components/TextAnnotation.js.map +1 -0
  41. package/lib/commonjs/components/TextEditModal.js +133 -0
  42. package/lib/commonjs/components/TextEditModal.js.map +1 -0
  43. package/lib/commonjs/components/Toolbar.js +198 -0
  44. package/lib/commonjs/components/Toolbar.js.map +1 -0
  45. package/lib/commonjs/components/ZoomBadge.js +161 -0
  46. package/lib/commonjs/components/ZoomBadge.js.map +1 -0
  47. package/lib/commonjs/hooks/useFreehandGesture.js +173 -0
  48. package/lib/commonjs/hooks/useFreehandGesture.js.map +1 -0
  49. package/lib/commonjs/hooks/usePolygonGesture.js +109 -0
  50. package/lib/commonjs/hooks/usePolygonGesture.js.map +1 -0
  51. package/lib/commonjs/hooks/useSelectionGesture.js +236 -0
  52. package/lib/commonjs/hooks/useSelectionGesture.js.map +1 -0
  53. package/lib/commonjs/hooks/useShapeGesture.js +181 -0
  54. package/lib/commonjs/hooks/useShapeGesture.js.map +1 -0
  55. package/lib/commonjs/hooks/useViewportGesture.js +238 -0
  56. package/lib/commonjs/hooks/useViewportGesture.js.map +1 -0
  57. package/lib/commonjs/index.js +104 -0
  58. package/lib/commonjs/index.js.map +1 -0
  59. package/lib/commonjs/package.json +1 -0
  60. package/lib/commonjs/renderers/ArrowRenderer.js +118 -0
  61. package/lib/commonjs/renderers/ArrowRenderer.js.map +1 -0
  62. package/lib/commonjs/renderers/CircleRenderer.js +51 -0
  63. package/lib/commonjs/renderers/CircleRenderer.js.map +1 -0
  64. package/lib/commonjs/renderers/FreehandRenderer.js +31 -0
  65. package/lib/commonjs/renderers/FreehandRenderer.js.map +1 -0
  66. package/lib/commonjs/renderers/InProgressRenderer.js +174 -0
  67. package/lib/commonjs/renderers/InProgressRenderer.js.map +1 -0
  68. package/lib/commonjs/renderers/LineRenderer.js +27 -0
  69. package/lib/commonjs/renderers/LineRenderer.js.map +1 -0
  70. package/lib/commonjs/renderers/MeasurementRenderer.js +134 -0
  71. package/lib/commonjs/renderers/MeasurementRenderer.js.map +1 -0
  72. package/lib/commonjs/renderers/ObjectRenderer.js +65 -0
  73. package/lib/commonjs/renderers/ObjectRenderer.js.map +1 -0
  74. package/lib/commonjs/renderers/PolygonRenderer.js +46 -0
  75. package/lib/commonjs/renderers/PolygonRenderer.js.map +1 -0
  76. package/lib/commonjs/renderers/RectRenderer.js +51 -0
  77. package/lib/commonjs/renderers/RectRenderer.js.map +1 -0
  78. package/lib/commonjs/renderers/SelectedObjectRenderer.js +592 -0
  79. package/lib/commonjs/renderers/SelectedObjectRenderer.js.map +1 -0
  80. package/lib/commonjs/renderers/SelectionOverlay.js +120 -0
  81. package/lib/commonjs/renderers/SelectionOverlay.js.map +1 -0
  82. package/lib/commonjs/store/useDrawingStore.js +354 -0
  83. package/lib/commonjs/store/useDrawingStore.js.map +1 -0
  84. package/lib/commonjs/types.js +6 -0
  85. package/lib/commonjs/types.js.map +1 -0
  86. package/lib/commonjs/utils/colors.js +44 -0
  87. package/lib/commonjs/utils/colors.js.map +1 -0
  88. package/lib/commonjs/utils/coordinates.js +81 -0
  89. package/lib/commonjs/utils/coordinates.js.map +1 -0
  90. package/lib/commonjs/utils/hitTesting.js +181 -0
  91. package/lib/commonjs/utils/hitTesting.js.map +1 -0
  92. package/lib/commonjs/utils/serialization.js +42 -0
  93. package/lib/commonjs/utils/serialization.js.map +1 -0
  94. package/lib/commonjs/utils/shapeDetection.js +151 -0
  95. package/lib/commonjs/utils/shapeDetection.js.map +1 -0
  96. package/lib/commonjs/utils/smoothing.js +85 -0
  97. package/lib/commonjs/utils/smoothing.js.map +1 -0
  98. package/lib/module/DrawingEditor.js +811 -0
  99. package/lib/module/DrawingEditor.js.map +1 -0
  100. package/lib/module/assets/toolbar-icons/arrow-disabled.png +0 -0
  101. package/lib/module/assets/toolbar-icons/arrow-enabled.png +0 -0
  102. package/lib/module/assets/toolbar-icons/arrow.png +0 -0
  103. package/lib/module/assets/toolbar-icons/circle-disabled.png +0 -0
  104. package/lib/module/assets/toolbar-icons/circle-enabled.png +0 -0
  105. package/lib/module/assets/toolbar-icons/circle.png +0 -0
  106. package/lib/module/assets/toolbar-icons/freehand-disabled.png +0 -0
  107. package/lib/module/assets/toolbar-icons/freehand-enabled.png +0 -0
  108. package/lib/module/assets/toolbar-icons/freehand.png +0 -0
  109. package/lib/module/assets/toolbar-icons/line-disabled.png +0 -0
  110. package/lib/module/assets/toolbar-icons/line-enabled.png +0 -0
  111. package/lib/module/assets/toolbar-icons/line.png +0 -0
  112. package/lib/module/assets/toolbar-icons/measure-disabled.png +0 -0
  113. package/lib/module/assets/toolbar-icons/measure-enabled.png +0 -0
  114. package/lib/module/assets/toolbar-icons/measure.png +0 -0
  115. package/lib/module/assets/toolbar-icons/move-disabled.png +0 -0
  116. package/lib/module/assets/toolbar-icons/move-enabled.png +0 -0
  117. package/lib/module/assets/toolbar-icons/move.png +0 -0
  118. package/lib/module/assets/toolbar-icons/polygon-disabled.png +0 -0
  119. package/lib/module/assets/toolbar-icons/polygon-enabled.png +0 -0
  120. package/lib/module/assets/toolbar-icons/polygon.png +0 -0
  121. package/lib/module/assets/toolbar-icons/rectangle-disabled.png +0 -0
  122. package/lib/module/assets/toolbar-icons/rectangle-enabled.png +0 -0
  123. package/lib/module/assets/toolbar-icons/rectangle.png +0 -0
  124. package/lib/module/assets/toolbar-icons/text-disabled.png +0 -0
  125. package/lib/module/assets/toolbar-icons/text-enabled.png +0 -0
  126. package/lib/module/assets/toolbar-icons/text.png +0 -0
  127. package/lib/module/components/ColorPalette.js +374 -0
  128. package/lib/module/components/ColorPalette.js.map +1 -0
  129. package/lib/module/components/LineWidthSlider.js +64 -0
  130. package/lib/module/components/LineWidthSlider.js.map +1 -0
  131. package/lib/module/components/MeasurementEditModal.js +148 -0
  132. package/lib/module/components/MeasurementEditModal.js.map +1 -0
  133. package/lib/module/components/MiniMap.js +239 -0
  134. package/lib/module/components/MiniMap.js.map +1 -0
  135. package/lib/module/components/TextAnnotation.js +157 -0
  136. package/lib/module/components/TextAnnotation.js.map +1 -0
  137. package/lib/module/components/TextEditModal.js +128 -0
  138. package/lib/module/components/TextEditModal.js.map +1 -0
  139. package/lib/module/components/Toolbar.js +193 -0
  140. package/lib/module/components/Toolbar.js.map +1 -0
  141. package/lib/module/components/ZoomBadge.js +155 -0
  142. package/lib/module/components/ZoomBadge.js.map +1 -0
  143. package/lib/module/hooks/useFreehandGesture.js +169 -0
  144. package/lib/module/hooks/useFreehandGesture.js.map +1 -0
  145. package/lib/module/hooks/usePolygonGesture.js +106 -0
  146. package/lib/module/hooks/usePolygonGesture.js.map +1 -0
  147. package/lib/module/hooks/useSelectionGesture.js +232 -0
  148. package/lib/module/hooks/useSelectionGesture.js.map +1 -0
  149. package/lib/module/hooks/useShapeGesture.js +177 -0
  150. package/lib/module/hooks/useShapeGesture.js.map +1 -0
  151. package/lib/module/hooks/useViewportGesture.js +234 -0
  152. package/lib/module/hooks/useViewportGesture.js.map +1 -0
  153. package/lib/module/index.js +20 -0
  154. package/lib/module/index.js.map +1 -0
  155. package/lib/module/package.json +1 -0
  156. package/lib/module/renderers/ArrowRenderer.js +113 -0
  157. package/lib/module/renderers/ArrowRenderer.js.map +1 -0
  158. package/lib/module/renderers/CircleRenderer.js +46 -0
  159. package/lib/module/renderers/CircleRenderer.js.map +1 -0
  160. package/lib/module/renderers/FreehandRenderer.js +26 -0
  161. package/lib/module/renderers/FreehandRenderer.js.map +1 -0
  162. package/lib/module/renderers/InProgressRenderer.js +169 -0
  163. package/lib/module/renderers/InProgressRenderer.js.map +1 -0
  164. package/lib/module/renderers/LineRenderer.js +22 -0
  165. package/lib/module/renderers/LineRenderer.js.map +1 -0
  166. package/lib/module/renderers/MeasurementRenderer.js +129 -0
  167. package/lib/module/renderers/MeasurementRenderer.js.map +1 -0
  168. package/lib/module/renderers/ObjectRenderer.js +60 -0
  169. package/lib/module/renderers/ObjectRenderer.js.map +1 -0
  170. package/lib/module/renderers/PolygonRenderer.js +41 -0
  171. package/lib/module/renderers/PolygonRenderer.js.map +1 -0
  172. package/lib/module/renderers/RectRenderer.js +46 -0
  173. package/lib/module/renderers/RectRenderer.js.map +1 -0
  174. package/lib/module/renderers/SelectedObjectRenderer.js +587 -0
  175. package/lib/module/renderers/SelectedObjectRenderer.js.map +1 -0
  176. package/lib/module/renderers/SelectionOverlay.js +116 -0
  177. package/lib/module/renderers/SelectionOverlay.js.map +1 -0
  178. package/lib/module/store/useDrawingStore.js +350 -0
  179. package/lib/module/store/useDrawingStore.js.map +1 -0
  180. package/lib/module/types.js +4 -0
  181. package/lib/module/types.js.map +1 -0
  182. package/lib/module/utils/colors.js +40 -0
  183. package/lib/module/utils/colors.js.map +1 -0
  184. package/lib/module/utils/coordinates.js +71 -0
  185. package/lib/module/utils/coordinates.js.map +1 -0
  186. package/lib/module/utils/hitTesting.js +171 -0
  187. package/lib/module/utils/hitTesting.js.map +1 -0
  188. package/lib/module/utils/serialization.js +36 -0
  189. package/lib/module/utils/serialization.js.map +1 -0
  190. package/lib/module/utils/shapeDetection.js +147 -0
  191. package/lib/module/utils/shapeDetection.js.map +1 -0
  192. package/lib/module/utils/smoothing.js +80 -0
  193. package/lib/module/utils/smoothing.js.map +1 -0
  194. package/lib/typescript/DrawingEditor.d.ts +3 -0
  195. package/lib/typescript/DrawingEditor.d.ts.map +1 -0
  196. package/lib/typescript/components/ColorPalette.d.ts +9 -0
  197. package/lib/typescript/components/ColorPalette.d.ts.map +1 -0
  198. package/lib/typescript/components/LineWidthSlider.d.ts +11 -0
  199. package/lib/typescript/components/LineWidthSlider.d.ts.map +1 -0
  200. package/lib/typescript/components/MeasurementEditModal.d.ts +11 -0
  201. package/lib/typescript/components/MeasurementEditModal.d.ts.map +1 -0
  202. package/lib/typescript/components/MiniMap.d.ts +23 -0
  203. package/lib/typescript/components/MiniMap.d.ts.map +1 -0
  204. package/lib/typescript/components/TextAnnotation.d.ts +22 -0
  205. package/lib/typescript/components/TextAnnotation.d.ts.map +1 -0
  206. package/lib/typescript/components/TextEditModal.d.ts +10 -0
  207. package/lib/typescript/components/TextEditModal.d.ts.map +1 -0
  208. package/lib/typescript/components/Toolbar.d.ts +13 -0
  209. package/lib/typescript/components/Toolbar.d.ts.map +1 -0
  210. package/lib/typescript/components/ZoomBadge.d.ts +9 -0
  211. package/lib/typescript/components/ZoomBadge.d.ts.map +1 -0
  212. package/lib/typescript/hooks/useFreehandGesture.d.ts +47 -0
  213. package/lib/typescript/hooks/useFreehandGesture.d.ts.map +1 -0
  214. package/lib/typescript/hooks/usePolygonGesture.d.ts +47 -0
  215. package/lib/typescript/hooks/usePolygonGesture.d.ts.map +1 -0
  216. package/lib/typescript/hooks/useSelectionGesture.d.ts +32 -0
  217. package/lib/typescript/hooks/useSelectionGesture.d.ts.map +1 -0
  218. package/lib/typescript/hooks/useShapeGesture.d.ts +54 -0
  219. package/lib/typescript/hooks/useShapeGesture.d.ts.map +1 -0
  220. package/lib/typescript/hooks/useViewportGesture.d.ts +37 -0
  221. package/lib/typescript/hooks/useViewportGesture.d.ts.map +1 -0
  222. package/lib/typescript/index.d.ts +11 -0
  223. package/lib/typescript/index.d.ts.map +1 -0
  224. package/lib/typescript/renderers/ArrowRenderer.d.ts +9 -0
  225. package/lib/typescript/renderers/ArrowRenderer.d.ts.map +1 -0
  226. package/lib/typescript/renderers/CircleRenderer.d.ts +9 -0
  227. package/lib/typescript/renderers/CircleRenderer.d.ts.map +1 -0
  228. package/lib/typescript/renderers/FreehandRenderer.d.ts +9 -0
  229. package/lib/typescript/renderers/FreehandRenderer.d.ts.map +1 -0
  230. package/lib/typescript/renderers/InProgressRenderer.d.ts +32 -0
  231. package/lib/typescript/renderers/InProgressRenderer.d.ts.map +1 -0
  232. package/lib/typescript/renderers/LineRenderer.d.ts +9 -0
  233. package/lib/typescript/renderers/LineRenderer.d.ts.map +1 -0
  234. package/lib/typescript/renderers/MeasurementRenderer.d.ts +9 -0
  235. package/lib/typescript/renderers/MeasurementRenderer.d.ts.map +1 -0
  236. package/lib/typescript/renderers/ObjectRenderer.d.ts +12 -0
  237. package/lib/typescript/renderers/ObjectRenderer.d.ts.map +1 -0
  238. package/lib/typescript/renderers/PolygonRenderer.d.ts +13 -0
  239. package/lib/typescript/renderers/PolygonRenderer.d.ts.map +1 -0
  240. package/lib/typescript/renderers/RectRenderer.d.ts +9 -0
  241. package/lib/typescript/renderers/RectRenderer.d.ts.map +1 -0
  242. package/lib/typescript/renderers/SelectedObjectRenderer.d.ts +18 -0
  243. package/lib/typescript/renderers/SelectedObjectRenderer.d.ts.map +1 -0
  244. package/lib/typescript/renderers/SelectionOverlay.d.ts +21 -0
  245. package/lib/typescript/renderers/SelectionOverlay.d.ts.map +1 -0
  246. package/lib/typescript/store/useDrawingStore.d.ts +30 -0
  247. package/lib/typescript/store/useDrawingStore.d.ts.map +1 -0
  248. package/lib/typescript/types.d.ts +130 -0
  249. package/lib/typescript/types.d.ts.map +1 -0
  250. package/lib/typescript/utils/colors.d.ts +11 -0
  251. package/lib/typescript/utils/colors.d.ts.map +1 -0
  252. package/lib/typescript/utils/coordinates.d.ts +34 -0
  253. package/lib/typescript/utils/coordinates.d.ts.map +1 -0
  254. package/lib/typescript/utils/hitTesting.d.ts +18 -0
  255. package/lib/typescript/utils/hitTesting.d.ts.map +1 -0
  256. package/lib/typescript/utils/serialization.d.ts +17 -0
  257. package/lib/typescript/utils/serialization.d.ts.map +1 -0
  258. package/lib/typescript/utils/shapeDetection.d.ts +22 -0
  259. package/lib/typescript/utils/shapeDetection.d.ts.map +1 -0
  260. package/lib/typescript/utils/smoothing.d.ts +16 -0
  261. package/lib/typescript/utils/smoothing.d.ts.map +1 -0
  262. package/package.json +108 -0
  263. package/src/DrawingEditor.tsx +1071 -0
  264. package/src/assets/toolbar-icons/arrow-disabled.png +0 -0
  265. package/src/assets/toolbar-icons/arrow-enabled.png +0 -0
  266. package/src/assets/toolbar-icons/arrow.png +0 -0
  267. package/src/assets/toolbar-icons/circle-disabled.png +0 -0
  268. package/src/assets/toolbar-icons/circle-enabled.png +0 -0
  269. package/src/assets/toolbar-icons/circle.png +0 -0
  270. package/src/assets/toolbar-icons/freehand-disabled.png +0 -0
  271. package/src/assets/toolbar-icons/freehand-enabled.png +0 -0
  272. package/src/assets/toolbar-icons/freehand.png +0 -0
  273. package/src/assets/toolbar-icons/line-disabled.png +0 -0
  274. package/src/assets/toolbar-icons/line-enabled.png +0 -0
  275. package/src/assets/toolbar-icons/line.png +0 -0
  276. package/src/assets/toolbar-icons/measure-disabled.png +0 -0
  277. package/src/assets/toolbar-icons/measure-enabled.png +0 -0
  278. package/src/assets/toolbar-icons/measure.png +0 -0
  279. package/src/assets/toolbar-icons/move-disabled.png +0 -0
  280. package/src/assets/toolbar-icons/move-enabled.png +0 -0
  281. package/src/assets/toolbar-icons/move.png +0 -0
  282. package/src/assets/toolbar-icons/polygon-disabled.png +0 -0
  283. package/src/assets/toolbar-icons/polygon-enabled.png +0 -0
  284. package/src/assets/toolbar-icons/polygon.png +0 -0
  285. package/src/assets/toolbar-icons/rectangle-disabled.png +0 -0
  286. package/src/assets/toolbar-icons/rectangle-enabled.png +0 -0
  287. package/src/assets/toolbar-icons/rectangle.png +0 -0
  288. package/src/assets/toolbar-icons/text-disabled.png +0 -0
  289. package/src/assets/toolbar-icons/text-enabled.png +0 -0
  290. package/src/assets/toolbar-icons/text.png +0 -0
  291. package/src/components/ColorPalette.tsx +497 -0
  292. package/src/components/LineWidthSlider.tsx +87 -0
  293. package/src/components/MeasurementEditModal.tsx +163 -0
  294. package/src/components/MiniMap.tsx +275 -0
  295. package/src/components/TextAnnotation.tsx +198 -0
  296. package/src/components/TextEditModal.tsx +139 -0
  297. package/src/components/Toolbar.tsx +254 -0
  298. package/src/components/ZoomBadge.tsx +166 -0
  299. package/src/hooks/useFreehandGesture.ts +249 -0
  300. package/src/hooks/usePolygonGesture.ts +162 -0
  301. package/src/hooks/useSelectionGesture.ts +293 -0
  302. package/src/hooks/useShapeGesture.ts +256 -0
  303. package/src/hooks/useViewportGesture.ts +337 -0
  304. package/src/index.tsx +51 -0
  305. package/src/renderers/ArrowRenderer.tsx +123 -0
  306. package/src/renderers/CircleRenderer.tsx +60 -0
  307. package/src/renderers/FreehandRenderer.tsx +33 -0
  308. package/src/renderers/InProgressRenderer.tsx +217 -0
  309. package/src/renderers/LineRenderer.tsx +34 -0
  310. package/src/renderers/MeasurementRenderer.tsx +179 -0
  311. package/src/renderers/ObjectRenderer.tsx +42 -0
  312. package/src/renderers/PolygonRenderer.tsx +66 -0
  313. package/src/renderers/RectRenderer.tsx +60 -0
  314. package/src/renderers/SelectedObjectRenderer.tsx +738 -0
  315. package/src/renderers/SelectionOverlay.tsx +170 -0
  316. package/src/store/useDrawingStore.ts +357 -0
  317. package/src/types.ts +186 -0
  318. package/src/utils/colors.ts +98 -0
  319. package/src/utils/coordinates.ts +75 -0
  320. package/src/utils/hitTesting.ts +242 -0
  321. package/src/utils/serialization.ts +45 -0
  322. package/src/utils/shapeDetection.ts +160 -0
  323. package/src/utils/smoothing.ts +84 -0
@@ -0,0 +1,170 @@
1
+ import React, { useMemo } from "react";
2
+ import { Circle, Group } from "@shopify/react-native-skia";
3
+ import { useDerivedValue } from "react-native-reanimated";
4
+ import type { SharedValue } from "react-native-reanimated";
5
+ import type {
6
+ DrawingObject,
7
+ FreehandObject,
8
+ PolygonObject,
9
+ TwoPointObject,
10
+ Size,
11
+ Point,
12
+ } from "../types";
13
+ import { denormalize, denormalizePoints } from "../utils/coordinates";
14
+
15
+ interface SelectionOverlayProps {
16
+ object: DrawingObject;
17
+ canvasSize: Size;
18
+ color?: string;
19
+ draggingAnchorIndex?: SharedValue<number>;
20
+ dragOffsetX?: SharedValue<number>;
21
+ dragOffsetY?: SharedValue<number>;
22
+ isDragging?: SharedValue<boolean>;
23
+ }
24
+
25
+ export const ANCHOR_RADIUS = 8;
26
+ const ANCHOR_HIT_RADIUS = 24;
27
+ const DEFAULT_ANCHOR_COLOR = "rgba(0, 122, 255, 0.5)";
28
+
29
+ /**
30
+ * Get the anchor points (in pixel coordinates) for a drawing object.
31
+ */
32
+ export function getAnchorPoints(
33
+ object: DrawingObject,
34
+ canvasSize: Size,
35
+ ): Point[] {
36
+ switch (object.type) {
37
+ case "freehand": {
38
+ const pts = denormalizePoints(
39
+ (object as FreehandObject).points,
40
+ canvasSize,
41
+ );
42
+ if (pts.length === 0) return [];
43
+ return [pts[0]!, pts[pts.length - 1]!];
44
+ }
45
+ case "polygon": {
46
+ return denormalizePoints(
47
+ (object as PolygonObject).points,
48
+ canvasSize,
49
+ );
50
+ }
51
+ case "text":
52
+ return [
53
+ denormalize(object.position, canvasSize),
54
+ denormalize(
55
+ {
56
+ x: object.position.x + object.width,
57
+ y: object.position.y + object.height,
58
+ },
59
+ canvasSize,
60
+ ),
61
+ ];
62
+ default: {
63
+ const twoPoint = object as TwoPointObject;
64
+ return [
65
+ denormalize(twoPoint.from, canvasSize),
66
+ denormalize(twoPoint.to, canvasSize),
67
+ ];
68
+ }
69
+ }
70
+ }
71
+
72
+ export { ANCHOR_HIT_RADIUS };
73
+
74
+ /**
75
+ * An anchor circle that can animate its position when being dragged.
76
+ */
77
+ function AnimatedAnchor({
78
+ baseX,
79
+ baseY,
80
+ index,
81
+ draggingAnchorIndex,
82
+ dragOffsetX,
83
+ dragOffsetY,
84
+ isDragging,
85
+ radius,
86
+ color,
87
+ }: {
88
+ baseX: number;
89
+ baseY: number;
90
+ index: number;
91
+ draggingAnchorIndex: SharedValue<number>;
92
+ dragOffsetX: SharedValue<number>;
93
+ dragOffsetY: SharedValue<number>;
94
+ isDragging: SharedValue<boolean>;
95
+ radius: number;
96
+ color: string;
97
+ }) {
98
+ const cx = useDerivedValue(() => {
99
+ if (isDragging.value) {
100
+ if (draggingAnchorIndex.value < 0) {
101
+ // Moving whole object: all anchors move
102
+ return baseX + dragOffsetX.value;
103
+ } else if (draggingAnchorIndex.value === index) {
104
+ // Resizing: only this anchor moves
105
+ return baseX + dragOffsetX.value;
106
+ }
107
+ }
108
+ return baseX;
109
+ });
110
+ const cy = useDerivedValue(() => {
111
+ if (isDragging.value) {
112
+ if (draggingAnchorIndex.value < 0) {
113
+ return baseY + dragOffsetY.value;
114
+ } else if (draggingAnchorIndex.value === index) {
115
+ return baseY + dragOffsetY.value;
116
+ }
117
+ }
118
+ return baseY;
119
+ });
120
+
121
+ return <Circle cx={cx} cy={cy} r={radius} color={color} style="fill" />;
122
+ }
123
+
124
+ export const SelectionOverlay = React.memo(function SelectionOverlay({
125
+ object,
126
+ canvasSize,
127
+ color = DEFAULT_ANCHOR_COLOR,
128
+ draggingAnchorIndex,
129
+ dragOffsetX,
130
+ dragOffsetY,
131
+ isDragging,
132
+ }: SelectionOverlayProps) {
133
+ const anchors = useMemo(
134
+ () => getAnchorPoints(object, canvasSize),
135
+ [object, canvasSize],
136
+ );
137
+
138
+ const hasAnimatedProps =
139
+ draggingAnchorIndex && dragOffsetX && dragOffsetY && isDragging;
140
+
141
+ return (
142
+ <Group>
143
+ {anchors.map((point, index) =>
144
+ hasAnimatedProps ? (
145
+ <AnimatedAnchor
146
+ key={`anchor-${index}`}
147
+ baseX={point.x}
148
+ baseY={point.y}
149
+ index={index}
150
+ draggingAnchorIndex={draggingAnchorIndex}
151
+ dragOffsetX={dragOffsetX}
152
+ dragOffsetY={dragOffsetY}
153
+ isDragging={isDragging}
154
+ radius={ANCHOR_RADIUS}
155
+ color={color}
156
+ />
157
+ ) : (
158
+ <Circle
159
+ key={`anchor-${index}`}
160
+ cx={point.x}
161
+ cy={point.y}
162
+ r={ANCHOR_RADIUS}
163
+ color={color}
164
+ style="fill"
165
+ />
166
+ ),
167
+ )}
168
+ </Group>
169
+ );
170
+ });
@@ -0,0 +1,357 @@
1
+ import { create } from "zustand";
2
+ import type {
3
+ DrawingObject,
4
+ FreehandObject,
5
+ PolygonObject,
6
+ ToolType,
7
+ UndoAction,
8
+ Size,
9
+ TwoPointObject,
10
+ } from "../types";
11
+ import { DEFAULT_STROKE_COLOR, DEFAULT_LINE_WIDTH } from "../utils/colors";
12
+ import { generateId } from "../utils/serialization";
13
+
14
+ export interface DrawingState {
15
+ // ─── State ──────────────────────────────────────────────────────────────────
16
+ objects: DrawingObject[];
17
+ currentTool: ToolType | null;
18
+ strokeColor: string;
19
+ fillColor: string | null;
20
+ fillAlpha: number;
21
+ lineWidth: number;
22
+ selectedObjectId: string | null;
23
+ canvasSize: Size;
24
+ undoStack: UndoAction[];
25
+
26
+ // ─── Actions ────────────────────────────────────────────────────────────────
27
+ setTool: (tool: ToolType | null) => void;
28
+ setStrokeColor: (color: string) => void;
29
+ setFillColor: (color: string | null) => void;
30
+ setFillAlpha: (alpha: number) => void;
31
+ setLineWidth: (width: number) => void;
32
+ setCanvasSize: (size: Size) => void;
33
+
34
+ addObject: (obj: DrawingObject) => void;
35
+ updateObject: (id: string, updates: Partial<DrawingObject>) => void;
36
+ deleteObject: (id: string) => void;
37
+ deleteSelectedObject: () => void;
38
+ selectObject: (id: string | null) => void;
39
+ moveObject: (id: string, dx: number, dy: number) => void;
40
+ resizeObject: (
41
+ id: string,
42
+ anchorIndex: number,
43
+ dx: number,
44
+ dy: number,
45
+ ) => void;
46
+ undo: () => void;
47
+ clearAll: () => void;
48
+ loadObjects: (objects: DrawingObject[]) => void;
49
+ }
50
+
51
+ function cloneObject(obj: DrawingObject): DrawingObject {
52
+ return JSON.parse(JSON.stringify(obj)) as DrawingObject;
53
+ }
54
+
55
+ function movePoints(obj: DrawingObject, dx: number, dy: number): DrawingObject {
56
+ const moved = cloneObject(obj);
57
+ switch (moved.type) {
58
+ case "freehand": {
59
+ const freehand = moved as FreehandObject;
60
+ freehand.points = freehand.points.map((p) => ({
61
+ x: p.x + dx,
62
+ y: p.y + dy,
63
+ }));
64
+ break;
65
+ }
66
+ case "polygon": {
67
+ const polygon = moved as PolygonObject;
68
+ polygon.points = polygon.points.map((p) => ({
69
+ x: p.x + dx,
70
+ y: p.y + dy,
71
+ }));
72
+ break;
73
+ }
74
+ case "text": {
75
+ moved.position = {
76
+ x: moved.position.x + dx,
77
+ y: moved.position.y + dy,
78
+ };
79
+ break;
80
+ }
81
+ default: {
82
+ const twoPoint = moved as TwoPointObject;
83
+ twoPoint.from = { x: twoPoint.from.x + dx, y: twoPoint.from.y + dy };
84
+ twoPoint.to = { x: twoPoint.to.x + dx, y: twoPoint.to.y + dy };
85
+ break;
86
+ }
87
+ }
88
+ return moved;
89
+ }
90
+
91
+ export const useDrawingStore = create<DrawingState>((set, get) => ({
92
+ // ─── Initial State ────────────────────────────────────────────────────────
93
+ objects: [],
94
+ currentTool: "freehand",
95
+ strokeColor: DEFAULT_STROKE_COLOR,
96
+ fillColor: null,
97
+ fillAlpha: 0.5,
98
+ lineWidth: DEFAULT_LINE_WIDTH,
99
+ selectedObjectId: null,
100
+ canvasSize: { width: 0, height: 0 },
101
+ undoStack: [],
102
+
103
+ // ─── Tool & Style ─────────────────────────────────────────────────────────
104
+ setTool: (tool) => set({ currentTool: tool, selectedObjectId: null }),
105
+
106
+ setStrokeColor: (color) => {
107
+ const { selectedObjectId, objects, undoStack } = get();
108
+ if (selectedObjectId) {
109
+ const obj = objects.find((o) => o.id === selectedObjectId);
110
+ if (obj) {
111
+ const prevState = cloneObject(obj);
112
+ set({
113
+ strokeColor: color,
114
+ objects: objects.map((o) =>
115
+ o.id === selectedObjectId ? { ...o, color } : o,
116
+ ),
117
+ undoStack: [
118
+ ...undoStack,
119
+ {
120
+ type: "edit",
121
+ objectId: selectedObjectId,
122
+ previousState: prevState,
123
+ },
124
+ ],
125
+ });
126
+ return;
127
+ }
128
+ }
129
+ set({ strokeColor: color });
130
+ },
131
+
132
+ setFillColor: (color) => set({ fillColor: color }),
133
+ setFillAlpha: (alpha) => set({ fillAlpha: alpha }),
134
+
135
+ setLineWidth: (width) => {
136
+ const { selectedObjectId, objects, undoStack } = get();
137
+ if (selectedObjectId) {
138
+ const obj = objects.find((o) => o.id === selectedObjectId);
139
+ if (obj) {
140
+ const prevState = cloneObject(obj);
141
+ set({
142
+ lineWidth: width,
143
+ objects: objects.map((o) =>
144
+ o.id === selectedObjectId ? { ...o, lineWidth: width } : o,
145
+ ),
146
+ undoStack: [
147
+ ...undoStack,
148
+ {
149
+ type: "edit",
150
+ objectId: selectedObjectId,
151
+ previousState: prevState,
152
+ },
153
+ ],
154
+ });
155
+ return;
156
+ }
157
+ }
158
+ set({ lineWidth: width });
159
+ },
160
+
161
+ setCanvasSize: (size) => set({ canvasSize: size }),
162
+
163
+ // ─── Object Management ────────────────────────────────────────────────────
164
+ addObject: (obj) => {
165
+ const id = obj.id || generateId();
166
+ const withId = { ...obj, id };
167
+ set((state) => ({
168
+ objects: [...state.objects, withId],
169
+ undoStack: [...state.undoStack, { type: "add", objectId: id }],
170
+ }));
171
+ },
172
+
173
+ updateObject: (id, updates) => {
174
+ const { objects, undoStack } = get();
175
+ const obj = objects.find((o) => o.id === id);
176
+ if (!obj) return;
177
+ const prevState = cloneObject(obj);
178
+ set({
179
+ objects: objects.map((o) =>
180
+ o.id === id ? ({ ...o, ...updates } as DrawingObject) : o,
181
+ ),
182
+ undoStack: [
183
+ ...undoStack,
184
+ { type: "edit", objectId: id, previousState: prevState },
185
+ ],
186
+ });
187
+ },
188
+
189
+ deleteObject: (id) => {
190
+ const { objects, undoStack } = get();
191
+ const obj = objects.find((o) => o.id === id);
192
+ if (!obj) return;
193
+ const prevState = cloneObject(obj);
194
+ set({
195
+ objects: objects.filter((o) => o.id !== id),
196
+ selectedObjectId: null,
197
+ undoStack: [
198
+ ...undoStack,
199
+ { type: "delete", objectId: id, previousState: prevState },
200
+ ],
201
+ });
202
+ },
203
+
204
+ deleteSelectedObject: () => {
205
+ const { selectedObjectId } = get();
206
+ if (selectedObjectId) {
207
+ get().deleteObject(selectedObjectId);
208
+ }
209
+ },
210
+
211
+ selectObject: (id) => set({ selectedObjectId: id }),
212
+
213
+ moveObject: (id, dx, dy) => {
214
+ const { objects, undoStack } = get();
215
+ const obj = objects.find((o) => o.id === id);
216
+ if (!obj) return;
217
+ const prevState = cloneObject(obj);
218
+ const moved = movePoints(obj, dx, dy);
219
+ set({
220
+ objects: objects.map((o) => (o.id === id ? moved : o)),
221
+ undoStack: [
222
+ ...undoStack,
223
+ { type: "move", objectId: id, previousState: prevState },
224
+ ],
225
+ });
226
+ },
227
+
228
+ resizeObject: (id, anchorIndex, dx, dy) => {
229
+ const { objects, undoStack } = get();
230
+ const obj = objects.find((o) => o.id === id);
231
+ if (!obj) return;
232
+ const prevState = cloneObject(obj);
233
+ const resized = cloneObject(obj);
234
+
235
+ switch (resized.type) {
236
+ case "freehand": {
237
+ const freehand = resized as FreehandObject;
238
+ if (freehand.points.length === 0) break;
239
+ if (anchorIndex === 0) {
240
+ freehand.points[0] = {
241
+ x: freehand.points[0]!.x + dx,
242
+ y: freehand.points[0]!.y + dy,
243
+ };
244
+ } else if (anchorIndex === 1) {
245
+ const last = freehand.points.length - 1;
246
+ freehand.points[last] = {
247
+ x: freehand.points[last]!.x + dx,
248
+ y: freehand.points[last]!.y + dy,
249
+ };
250
+ }
251
+ break;
252
+ }
253
+ case "polygon": {
254
+ const polygon = resized as PolygonObject;
255
+ if (anchorIndex >= 0 && anchorIndex < polygon.points.length) {
256
+ polygon.points[anchorIndex] = {
257
+ x: polygon.points[anchorIndex]!.x + dx,
258
+ y: polygon.points[anchorIndex]!.y + dy,
259
+ };
260
+ }
261
+ break;
262
+ }
263
+ case "text": {
264
+ if (anchorIndex === 0) {
265
+ resized.position = {
266
+ x: resized.position.x + dx,
267
+ y: resized.position.y + dy,
268
+ };
269
+ } else if (anchorIndex === 1) {
270
+ resized.width = Math.max(0.02, resized.width + dx);
271
+ resized.height = Math.max(0.02, resized.height + dy);
272
+ }
273
+ break;
274
+ }
275
+ default: {
276
+ const twoPoint = resized as TwoPointObject;
277
+ if (anchorIndex === 0) {
278
+ twoPoint.from = {
279
+ x: twoPoint.from.x + dx,
280
+ y: twoPoint.from.y + dy,
281
+ };
282
+ } else if (anchorIndex === 1) {
283
+ twoPoint.to = {
284
+ x: twoPoint.to.x + dx,
285
+ y: twoPoint.to.y + dy,
286
+ };
287
+ }
288
+ break;
289
+ }
290
+ }
291
+
292
+ set({
293
+ objects: objects.map((o) => (o.id === id ? resized : o)),
294
+ undoStack: [
295
+ ...undoStack,
296
+ { type: "edit", objectId: id, previousState: prevState },
297
+ ],
298
+ });
299
+ },
300
+
301
+ // ─── Undo ─────────────────────────────────────────────────────────────────
302
+ undo: () => {
303
+ const { undoStack, objects } = get();
304
+ if (undoStack.length === 0) return;
305
+
306
+ const action = undoStack[undoStack.length - 1]!;
307
+ const newStack = undoStack.slice(0, -1);
308
+
309
+ switch (action.type) {
310
+ case "add":
311
+ // Remove the added object
312
+ set({
313
+ objects: objects.filter((o) => o.id !== action.objectId),
314
+ undoStack: newStack,
315
+ selectedObjectId: null,
316
+ });
317
+ break;
318
+
319
+ case "delete":
320
+ // Re-insert the deleted object
321
+ if (action.previousState) {
322
+ set({
323
+ objects: [...objects, action.previousState],
324
+ undoStack: newStack,
325
+ });
326
+ }
327
+ break;
328
+
329
+ case "edit":
330
+ case "move":
331
+ // Restore previous state
332
+ if (action.previousState) {
333
+ set({
334
+ objects: objects.map((o) =>
335
+ o.id === action.objectId ? action.previousState! : o,
336
+ ),
337
+ undoStack: newStack,
338
+ });
339
+ }
340
+ break;
341
+ }
342
+ },
343
+
344
+ clearAll: () =>
345
+ set({
346
+ objects: [],
347
+ undoStack: [],
348
+ selectedObjectId: null,
349
+ }),
350
+
351
+ loadObjects: (objects) =>
352
+ set({
353
+ objects,
354
+ undoStack: [],
355
+ selectedObjectId: null,
356
+ }),
357
+ }));
package/src/types.ts ADDED
@@ -0,0 +1,186 @@
1
+ import type { ReactNode } from "react";
2
+ import type { ViewStyle } from "react-native";
3
+
4
+ // ─── Tool Types ──────────────────────────────────────────────────────────────
5
+
6
+ export type ToolType =
7
+ | "freehand"
8
+ | "line"
9
+ | "arrow"
10
+ | "rectangle"
11
+ | "circle"
12
+ | "polygon"
13
+ | "measure"
14
+ | "text";
15
+
16
+ export type MeasureStyle = 0 | 1 | 2; // EXT_STYLE | INT_STYLE | PIPE_STYLE
17
+
18
+ // ─── Geometry ────────────────────────────────────────────────────────────────
19
+
20
+ /** Normalized point: x and y are in [0, 1] relative to canvas size */
21
+ export interface Point {
22
+ x: number;
23
+ y: number;
24
+ }
25
+
26
+ export interface Size {
27
+ width: number;
28
+ height: number;
29
+ }
30
+
31
+ // ─── Drawing Objects ─────────────────────────────────────────────────────────
32
+
33
+ interface BaseDrawingObject {
34
+ id: string;
35
+ color: string;
36
+ lineWidth: number;
37
+ }
38
+
39
+ export interface FreehandObject extends BaseDrawingObject {
40
+ type: "freehand";
41
+ points: Point[];
42
+ }
43
+
44
+ export interface LineObject extends BaseDrawingObject {
45
+ type: "line";
46
+ from: Point;
47
+ to: Point;
48
+ }
49
+
50
+ export interface ArrowObject extends BaseDrawingObject {
51
+ type: "arrow";
52
+ from: Point;
53
+ to: Point;
54
+ }
55
+
56
+ export interface RectangleObject extends BaseDrawingObject {
57
+ type: "rectangle";
58
+ from: Point;
59
+ to: Point;
60
+ backgroundColor?: string;
61
+ backgroundAlpha?: number;
62
+ }
63
+
64
+ export interface CircleObject extends BaseDrawingObject {
65
+ type: "circle";
66
+ from: Point;
67
+ to: Point;
68
+ backgroundColor?: string;
69
+ backgroundAlpha?: number;
70
+ }
71
+
72
+ export interface MeasureObject extends BaseDrawingObject {
73
+ type: "measure";
74
+ from: Point;
75
+ to: Point;
76
+ text: string;
77
+ unit: string;
78
+ measureStyle: MeasureStyle;
79
+ }
80
+
81
+ export interface PolygonObject extends BaseDrawingObject {
82
+ type: "polygon";
83
+ points: Point[];
84
+ closed: boolean;
85
+ backgroundColor?: string;
86
+ backgroundAlpha?: number;
87
+ }
88
+
89
+ export interface TextObject extends BaseDrawingObject {
90
+ type: "text";
91
+ position: Point;
92
+ width: number;
93
+ height: number;
94
+ value: string;
95
+ backgroundColor?: string;
96
+ backgroundAlpha?: number;
97
+ }
98
+
99
+ export type DrawingObject =
100
+ | FreehandObject
101
+ | LineObject
102
+ | ArrowObject
103
+ | RectangleObject
104
+ | CircleObject
105
+ | PolygonObject
106
+ | MeasureObject
107
+ | TextObject;
108
+
109
+ export type TwoPointShapeType =
110
+ | "line"
111
+ | "arrow"
112
+ | "rectangle"
113
+ | "circle"
114
+ | "measure";
115
+
116
+ export type TwoPointObject =
117
+ | LineObject
118
+ | ArrowObject
119
+ | RectangleObject
120
+ | CircleObject
121
+ | MeasureObject;
122
+
123
+ // ─── Undo ────────────────────────────────────────────────────────────────────
124
+
125
+ export type UndoActionType = "add" | "delete" | "edit" | "move";
126
+
127
+ export interface UndoAction {
128
+ type: UndoActionType;
129
+ objectId: string;
130
+ previousState?: DrawingObject;
131
+ }
132
+
133
+ // ─── Component Props ─────────────────────────────────────────────────────────
134
+
135
+ export interface DrawingEditorProps {
136
+ /** URI string or require() for the background image */
137
+ imageSource: string | number;
138
+ /** Pre-existing objects to restore */
139
+ initialObjects?: DrawingObject[];
140
+ /** Maximum zoom level (default: 5) */
141
+ maxZoom?: number;
142
+ /** Called when the user saves */
143
+ onSave?: (result: {
144
+ image: Uint8Array;
145
+ objects: DrawingObject[];
146
+ canvasSize: Size;
147
+ }) => void;
148
+ /** Called when the user dismisses the editor */
149
+ onDismiss?: () => void;
150
+ /** Custom style for the root container */
151
+ style?: ViewStyle;
152
+ /** Override the default toolbar */
153
+ renderToolbar?: (props: ToolbarRenderProps) => ReactNode;
154
+ /** Override the default color palette */
155
+ renderColorPalette?: (props: ColorPaletteRenderProps) => ReactNode;
156
+ }
157
+
158
+ export interface ToolbarRenderProps {
159
+ currentTool: ToolType | null;
160
+ onSelectTool: (tool: ToolType | null) => void;
161
+ onUndo: () => void;
162
+ canUndo: boolean;
163
+ /** Whether the canvas is currently zoomed in (scale > 1) */
164
+ isZoomed: boolean;
165
+ /** Reset zoom to 1x */
166
+ onResetZoom: () => void;
167
+ }
168
+
169
+ export interface ColorPaletteRenderProps {
170
+ strokeColor: string;
171
+ fillColor: string | null;
172
+ fillAlpha: number;
173
+ onSelectStrokeColor: (color: string) => void;
174
+ onSelectFillColor: (color: string | null) => void;
175
+ onSelectFillAlpha: (alpha: number) => void;
176
+ }
177
+
178
+ export interface DrawingEditorRef {
179
+ undo: () => void;
180
+ setTool: (tool: ToolType) => void;
181
+ exportImage: () => Promise<Uint8Array | null>;
182
+ exportImageBase64: () => Promise<string | null>;
183
+ getObjects: () => DrawingObject[];
184
+ clearAll: () => void;
185
+ resetZoom: () => void;
186
+ }