@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,256 @@
1
+ import { useCallback } from "react";
2
+ import { Gesture } from "react-native-gesture-handler";
3
+ import {
4
+ useSharedValue,
5
+ useDerivedValue,
6
+ runOnJS,
7
+ } from "react-native-reanimated";
8
+ import type { TwoPointShapeType, DrawingObject, Size } from "../types";
9
+ import { normalize, screenToCanvas } from "../utils/coordinates";
10
+ import { generateId } from "../utils/serialization";
11
+ import { useDrawingStore } from "../store/useDrawingStore";
12
+
13
+ const MIN_GESTURE_DURATION_MS = 300;
14
+ const MIN_GESTURE_DISTANCE = 5;
15
+
16
+ interface UseShapeGestureOptions {
17
+ shapeType: TwoPointShapeType;
18
+ colorSV: { value: string };
19
+ lineWidthSV: { value: number };
20
+ fillColorSV: { value: string | null };
21
+ fillAlphaSV: { value: number };
22
+ canvasSize: Size;
23
+ enabled: boolean;
24
+ imageOffsetX: { value: number };
25
+ imageOffsetY: { value: number };
26
+ imageWidth: { value: number };
27
+ imageHeight: { value: number };
28
+ viewScale: { value: number };
29
+ viewTranslateX: { value: number };
30
+ viewTranslateY: { value: number };
31
+ onMeasureCreated?: (id: string) => void;
32
+ }
33
+
34
+ export function useShapeGesture({
35
+ shapeType,
36
+ colorSV,
37
+ lineWidthSV,
38
+ fillColorSV,
39
+ fillAlphaSV,
40
+ canvasSize,
41
+ enabled,
42
+ imageOffsetX,
43
+ imageOffsetY,
44
+ imageWidth,
45
+ imageHeight,
46
+ viewScale,
47
+ viewTranslateX,
48
+ viewTranslateY,
49
+ onMeasureCreated,
50
+ }: UseShapeGestureOptions) {
51
+ // Shared values for the in-progress shape (pixel coords)
52
+ const startX = useSharedValue(0);
53
+ const startY = useSharedValue(0);
54
+ const currentX = useSharedValue(0);
55
+ const currentY = useSharedValue(0);
56
+ const isDrawing = useSharedValue(false);
57
+ const gestureStartTime = useSharedValue(0);
58
+
59
+ const addObject = useDrawingStore((s) => s.addObject);
60
+
61
+ const inProgressColor = useDerivedValue(() => colorSV.value);
62
+ const inProgressWidth = useDerivedValue(() => lineWidthSV.value);
63
+ const inProgressFillColor = useDerivedValue(() => fillColorSV.value);
64
+ const inProgressFillAlpha = useDerivedValue(() => fillAlphaSV.value);
65
+
66
+ const commitShape = useCallback(
67
+ (
68
+ sx: number,
69
+ sy: number,
70
+ ex: number,
71
+ ey: number,
72
+ color: string,
73
+ lineWidth: number,
74
+ fillColor: string | null,
75
+ fillAlpha: number,
76
+ ) => {
77
+ const from = normalize({ x: sx, y: sy }, canvasSize);
78
+ const to = normalize({ x: ex, y: ey }, canvasSize);
79
+
80
+ let obj: DrawingObject;
81
+
82
+ switch (shapeType) {
83
+ case "line":
84
+ obj = {
85
+ id: generateId(),
86
+ type: "line",
87
+ from,
88
+ to,
89
+ color,
90
+ lineWidth,
91
+ };
92
+ break;
93
+ case "arrow":
94
+ obj = {
95
+ id: generateId(),
96
+ type: "arrow",
97
+ from,
98
+ to,
99
+ color,
100
+ lineWidth,
101
+ };
102
+ break;
103
+ case "rectangle":
104
+ obj = {
105
+ id: generateId(),
106
+ type: "rectangle",
107
+ from,
108
+ to,
109
+ color,
110
+ lineWidth,
111
+ backgroundColor: fillColor ?? undefined,
112
+ backgroundAlpha: fillColor ? fillAlpha : undefined,
113
+ };
114
+ break;
115
+ case "circle":
116
+ obj = {
117
+ id: generateId(),
118
+ type: "circle",
119
+ from,
120
+ to,
121
+ color,
122
+ lineWidth,
123
+ backgroundColor: fillColor ?? undefined,
124
+ backgroundAlpha: fillColor ? fillAlpha : undefined,
125
+ };
126
+ break;
127
+ case "measure": {
128
+ const measureId = generateId();
129
+ obj = {
130
+ id: measureId,
131
+ type: "measure",
132
+ from,
133
+ to,
134
+ color,
135
+ lineWidth,
136
+ text: "",
137
+ unit: "cm",
138
+ measureStyle: 0,
139
+ };
140
+ break;
141
+ }
142
+ }
143
+
144
+ addObject(obj);
145
+
146
+ if (shapeType === "measure" && onMeasureCreated) {
147
+ onMeasureCreated(obj.id);
148
+ }
149
+ },
150
+ [canvasSize, shapeType, addObject, onMeasureCreated],
151
+ );
152
+
153
+ const gesture = Gesture.Pan()
154
+ .enabled(enabled)
155
+ .maxPointers(1)
156
+ .minDistance(0)
157
+ .onBegin((e) => {
158
+ "worklet";
159
+ const canvas = screenToCanvas(
160
+ e.x,
161
+ e.y,
162
+ viewScale.value,
163
+ viewTranslateX.value,
164
+ viewTranslateY.value,
165
+ );
166
+ const x = Math.max(
167
+ 0,
168
+ Math.min(imageWidth.value, canvas.x - imageOffsetX.value),
169
+ );
170
+ const y = Math.max(
171
+ 0,
172
+ Math.min(imageHeight.value, canvas.y - imageOffsetY.value),
173
+ );
174
+ isDrawing.value = true;
175
+ gestureStartTime.value = Date.now();
176
+ startX.value = x;
177
+ startY.value = y;
178
+ currentX.value = x;
179
+ currentY.value = y;
180
+ })
181
+ .onUpdate((e) => {
182
+ "worklet";
183
+ const canvas = screenToCanvas(
184
+ e.x,
185
+ e.y,
186
+ viewScale.value,
187
+ viewTranslateX.value,
188
+ viewTranslateY.value,
189
+ );
190
+ currentX.value = Math.max(
191
+ 0,
192
+ Math.min(imageWidth.value, canvas.x - imageOffsetX.value),
193
+ );
194
+ currentY.value = Math.max(
195
+ 0,
196
+ Math.min(imageHeight.value, canvas.y - imageOffsetY.value),
197
+ );
198
+ })
199
+ .onEnd((e) => {
200
+ "worklet";
201
+ const canvas = screenToCanvas(
202
+ e.x,
203
+ e.y,
204
+ viewScale.value,
205
+ viewTranslateX.value,
206
+ viewTranslateY.value,
207
+ );
208
+ const clampedX = Math.max(
209
+ 0,
210
+ Math.min(imageWidth.value, canvas.x - imageOffsetX.value),
211
+ );
212
+ const clampedY = Math.max(
213
+ 0,
214
+ Math.min(imageHeight.value, canvas.y - imageOffsetY.value),
215
+ );
216
+ const duration = Date.now() - gestureStartTime.value;
217
+ const dx = clampedX - startX.value;
218
+ const dy = clampedY - startY.value;
219
+ const dist = Math.sqrt(dx * dx + dy * dy);
220
+
221
+ if (duration < MIN_GESTURE_DURATION_MS && dist < MIN_GESTURE_DISTANCE) {
222
+ isDrawing.value = false;
223
+ return;
224
+ }
225
+
226
+ const sx = startX.value;
227
+ const sy = startY.value;
228
+ const ex = currentX.value;
229
+ const ey = currentY.value;
230
+ const color = colorSV.value;
231
+ const lw = lineWidthSV.value;
232
+ const fc = fillColorSV.value;
233
+ const fa = fillAlphaSV.value;
234
+
235
+ isDrawing.value = false;
236
+
237
+ runOnJS(commitShape)(sx, sy, ex, ey, color, lw, fc, fa);
238
+ })
239
+ .onFinalize(() => {
240
+ "worklet";
241
+ isDrawing.value = false;
242
+ });
243
+
244
+ return {
245
+ gesture,
246
+ startX,
247
+ startY,
248
+ currentX,
249
+ currentY,
250
+ isDrawing,
251
+ inProgressColor,
252
+ inProgressWidth,
253
+ inProgressFillColor,
254
+ inProgressFillAlpha,
255
+ };
256
+ }
@@ -0,0 +1,337 @@
1
+ import { useCallback } from "react";
2
+ import { Gesture } from "react-native-gesture-handler";
3
+ import { useSharedValue, withTiming, runOnJS } from "react-native-reanimated";
4
+
5
+ const DEFAULT_MAX_ZOOM = 5;
6
+ const RESET_DURATION = 250;
7
+
8
+ interface UseViewportGestureOptions {
9
+ maxZoom?: number;
10
+ layoutWidth: { value: number };
11
+ layoutHeight: { value: number };
12
+ imageOffsetX: { value: number };
13
+ imageOffsetY: { value: number };
14
+ imageWidth: { value: number };
15
+ imageHeight: { value: number };
16
+ onPinchEnd?: () => void;
17
+ }
18
+
19
+ function clampTranslate(
20
+ tx: number,
21
+ ty: number,
22
+ scale: number,
23
+ _layoutW: number,
24
+ _layoutH: number,
25
+ imgOffX: number,
26
+ imgOffY: number,
27
+ imgW: number,
28
+ imgH: number,
29
+ ): [number, number] {
30
+ "worklet";
31
+ // The image occupies [imgOffX, imgOffY] to [imgOffX+imgW, imgOffY+imgH] in layout space.
32
+ // After zoom, the image spans imgW*scale in canvas coords, displayed from (imgOffX*scale + tx).
33
+ // We want the scaled image to cover its original area:
34
+ // - Left edge of scaled image <= left edge of original area: imgOffX*scale + tx <= imgOffX
35
+ // - Right edge of scaled image >= right edge of original area: imgOffX*scale + tx + imgW*scale >= imgOffX + imgW
36
+ // Simplify:
37
+ // tx <= imgOffX * (1 - scale)
38
+ // tx >= (imgOffX + imgW) * (1 - scale) + (layoutW - imgOffX - imgW) ... no, let's think differently.
39
+ //
40
+ // Viewport model: the canvas is rendered with transform [translate(tx,ty), scale(s)] applied from origin.
41
+ // A point at canvas coords (cx, cy) maps to screen (cx*s + tx, cy*s + ty).
42
+ // Image starts at canvas (imgOffX, imgOffY) with size (imgW, imgH).
43
+ // On screen, image top-left = (imgOffX*s + tx, imgOffY*s + ty).
44
+ // On screen, image bottom-right = ((imgOffX+imgW)*s + tx, (imgOffY+imgH)*s + ty).
45
+ //
46
+ // Constraint: image should fill the original viewport area [imgOffX..imgOffX+imgW] x [imgOffY..imgOffY+imgH]:
47
+ // imgOffX*s + tx <= imgOffX => tx <= imgOffX*(1-s)
48
+ // (imgOffX+imgW)*s + tx >= imgOffX+imgW => tx >= (imgOffX+imgW)*(1-s)
49
+ // same for Y.
50
+
51
+ const minTx = (imgOffX + imgW) * (1 - scale);
52
+ const maxTx = imgOffX * (1 - scale);
53
+ const minTy = (imgOffY + imgH) * (1 - scale);
54
+ const maxTy = imgOffY * (1 - scale);
55
+
56
+ const clampedTx = Math.min(maxTx, Math.max(minTx, tx));
57
+ const clampedTy = Math.min(maxTy, Math.max(minTy, ty));
58
+
59
+ return [clampedTx, clampedTy];
60
+ }
61
+
62
+ export function useViewportGesture({
63
+ maxZoom = DEFAULT_MAX_ZOOM,
64
+ layoutWidth,
65
+ layoutHeight,
66
+ imageOffsetX,
67
+ imageOffsetY,
68
+ imageWidth,
69
+ imageHeight,
70
+ onPinchEnd,
71
+ }: UseViewportGestureOptions) {
72
+ const scale = useSharedValue(1);
73
+ const translateX = useSharedValue(0);
74
+ const translateY = useSharedValue(0);
75
+
76
+ // Saved state at gesture start
77
+ const savedScale = useSharedValue(1);
78
+ const savedTranslateX = useSharedValue(0);
79
+ const savedTranslateY = useSharedValue(0);
80
+
81
+ // Saved focal point at pinch start (for stable zoom center)
82
+ const savedFocalX = useSharedValue(0);
83
+ const savedFocalY = useSharedValue(0);
84
+
85
+ // Flag to prevent 2-finger pan from interfering during pinch
86
+ const isPinching = useSharedValue(false);
87
+
88
+ // ─── Pinch-to-zoom ──────────────────────────────────────────────────────
89
+ const pinchGesture = Gesture.Pinch()
90
+ .onBegin((e) => {
91
+ "worklet";
92
+ isPinching.value = true;
93
+ savedScale.value = scale.value;
94
+ savedTranslateX.value = translateX.value;
95
+ savedTranslateY.value = translateY.value;
96
+ savedFocalX.value = e.focalX;
97
+ savedFocalY.value = e.focalY;
98
+ })
99
+ .onUpdate((e) => {
100
+ "worklet";
101
+ const newScale = Math.min(
102
+ maxZoom,
103
+ Math.max(1, savedScale.value * e.scale),
104
+ );
105
+
106
+ // Canvas point under initial focal at gesture start:
107
+ const canvasFocalX =
108
+ (savedFocalX.value - savedTranslateX.value) / savedScale.value;
109
+ const canvasFocalY =
110
+ (savedFocalY.value - savedTranslateY.value) / savedScale.value;
111
+
112
+ // Pan delta from finger movement since gesture start:
113
+ const focalDeltaX = e.focalX - savedFocalX.value;
114
+ const focalDeltaY = e.focalY - savedFocalY.value;
115
+
116
+ // New translate: zoom around initial focal + follow finger pan
117
+ const newTx = savedFocalX.value - canvasFocalX * newScale + focalDeltaX;
118
+ const newTy = savedFocalY.value - canvasFocalY * newScale + focalDeltaY;
119
+
120
+ scale.value = newScale;
121
+ const [cx, cy] = clampTranslate(
122
+ newTx,
123
+ newTy,
124
+ newScale,
125
+ layoutWidth.value,
126
+ layoutHeight.value,
127
+ imageOffsetX.value,
128
+ imageOffsetY.value,
129
+ imageWidth.value,
130
+ imageHeight.value,
131
+ );
132
+ translateX.value = cx;
133
+ translateY.value = cy;
134
+ })
135
+ .onEnd(() => {
136
+ "worklet";
137
+ isPinching.value = false;
138
+ if (scale.value <= 1.05) {
139
+ // Snap back to 1x if close enough
140
+ scale.value = withTiming(1, { duration: RESET_DURATION });
141
+ translateX.value = withTiming(0, { duration: RESET_DURATION });
142
+ translateY.value = withTiming(0, { duration: RESET_DURATION });
143
+ } else if (onPinchEnd) {
144
+ // Zoomed in — notify caller so it can deactivate the tool
145
+ runOnJS(onPinchEnd)();
146
+ }
147
+ })
148
+ .onFinalize(() => {
149
+ "worklet";
150
+ isPinching.value = false;
151
+ });
152
+
153
+ // ─── Two-finger pan (only when zoomed and NOT pinching) ─────────────────
154
+ const twoFingerPanGesture = Gesture.Pan()
155
+ .minPointers(2)
156
+ .maxPointers(2)
157
+ .onBegin(() => {
158
+ "worklet";
159
+ savedTranslateX.value = translateX.value;
160
+ savedTranslateY.value = translateY.value;
161
+ })
162
+ .onUpdate((e) => {
163
+ "worklet";
164
+ // Skip if pinch is active — pinch handles its own panning
165
+ if (isPinching.value) return;
166
+ if (scale.value <= 1) return;
167
+ const newTx = savedTranslateX.value + e.translationX;
168
+ const newTy = savedTranslateY.value + e.translationY;
169
+ const [cx, cy] = clampTranslate(
170
+ newTx,
171
+ newTy,
172
+ scale.value,
173
+ layoutWidth.value,
174
+ layoutHeight.value,
175
+ imageOffsetX.value,
176
+ imageOffsetY.value,
177
+ imageWidth.value,
178
+ imageHeight.value,
179
+ );
180
+ translateX.value = cx;
181
+ translateY.value = cy;
182
+ });
183
+
184
+ // ─── Single-finger pan (when zoomed with no active tool) ───────────────
185
+ const singleFingerPanGesture = Gesture.Pan()
186
+ .minPointers(1)
187
+ .maxPointers(1)
188
+ .minDistance(5)
189
+ .onBegin(() => {
190
+ "worklet";
191
+ savedTranslateX.value = translateX.value;
192
+ savedTranslateY.value = translateY.value;
193
+ })
194
+ .onUpdate((e) => {
195
+ "worklet";
196
+ if (scale.value <= 1) return;
197
+ const newTx = savedTranslateX.value + e.translationX;
198
+ const newTy = savedTranslateY.value + e.translationY;
199
+ const [cx, cy] = clampTranslate(
200
+ newTx,
201
+ newTy,
202
+ scale.value,
203
+ layoutWidth.value,
204
+ layoutHeight.value,
205
+ imageOffsetX.value,
206
+ imageOffsetY.value,
207
+ imageWidth.value,
208
+ imageHeight.value,
209
+ );
210
+ translateX.value = cx;
211
+ translateY.value = cy;
212
+ });
213
+
214
+ // ─── Double-tap two-finger reset ───────────────────────────────────────
215
+ const doubleTapResetGesture = Gesture.Tap()
216
+ .numberOfTaps(2)
217
+ .minPointers(2)
218
+ .maxDuration(500)
219
+ .onEnd(() => {
220
+ "worklet";
221
+ scale.value = withTiming(1, { duration: RESET_DURATION });
222
+ translateX.value = withTiming(0, { duration: RESET_DURATION });
223
+ translateY.value = withTiming(0, { duration: RESET_DURATION });
224
+ });
225
+
226
+ // ─── Programmatic reset ────────────────────────────────────────────────
227
+ const resetViewport = useCallback(() => {
228
+ scale.value = withTiming(1, { duration: RESET_DURATION });
229
+ translateX.value = withTiming(0, { duration: RESET_DURATION });
230
+ translateY.value = withTiming(0, { duration: RESET_DURATION });
231
+ }, [scale, translateX, translateY]);
232
+
233
+ const zoomAt = useCallback(
234
+ (screenX: number, screenY: number, scaleFactor: number) => {
235
+ if (imageWidth.value <= 0 || imageHeight.value <= 0) return;
236
+
237
+ const previousScale = scale.value;
238
+ const nextScale = Math.min(
239
+ maxZoom,
240
+ Math.max(1, previousScale * scaleFactor),
241
+ );
242
+
243
+ if (Math.abs(nextScale - previousScale) < 0.001) return;
244
+
245
+ if (nextScale <= 1.05) {
246
+ scale.value = withTiming(1, { duration: RESET_DURATION });
247
+ translateX.value = withTiming(0, { duration: RESET_DURATION });
248
+ translateY.value = withTiming(0, { duration: RESET_DURATION });
249
+ return;
250
+ }
251
+
252
+ const canvasFocalX = (screenX - translateX.value) / previousScale;
253
+ const canvasFocalY = (screenY - translateY.value) / previousScale;
254
+
255
+ const nextTranslateX = screenX - canvasFocalX * nextScale;
256
+ const nextTranslateY = screenY - canvasFocalY * nextScale;
257
+ const [clampedX, clampedY] = clampTranslate(
258
+ nextTranslateX,
259
+ nextTranslateY,
260
+ nextScale,
261
+ layoutWidth.value,
262
+ layoutHeight.value,
263
+ imageOffsetX.value,
264
+ imageOffsetY.value,
265
+ imageWidth.value,
266
+ imageHeight.value,
267
+ );
268
+
269
+ scale.value = nextScale;
270
+ translateX.value = clampedX;
271
+ translateY.value = clampedY;
272
+
273
+ if (previousScale <= 1.05 && onPinchEnd) {
274
+ onPinchEnd();
275
+ }
276
+ },
277
+ [
278
+ maxZoom,
279
+ onPinchEnd,
280
+ scale,
281
+ translateX,
282
+ translateY,
283
+ layoutWidth,
284
+ layoutHeight,
285
+ imageOffsetX,
286
+ imageOffsetY,
287
+ imageWidth,
288
+ imageHeight,
289
+ ],
290
+ );
291
+
292
+ // ─── Programmatic pan (for minimap drag) ────────────────────────────────
293
+ const panViewport = useCallback(
294
+ (dtx: number, dty: number) => {
295
+ const newTx = translateX.value + dtx;
296
+ const newTy = translateY.value + dty;
297
+ const [cx, cy] = clampTranslate(
298
+ newTx,
299
+ newTy,
300
+ scale.value,
301
+ layoutWidth.value,
302
+ layoutHeight.value,
303
+ imageOffsetX.value,
304
+ imageOffsetY.value,
305
+ imageWidth.value,
306
+ imageHeight.value,
307
+ );
308
+ translateX.value = cx;
309
+ translateY.value = cy;
310
+ },
311
+ [
312
+ scale,
313
+ translateX,
314
+ translateY,
315
+ layoutWidth,
316
+ layoutHeight,
317
+ imageOffsetX,
318
+ imageOffsetY,
319
+ imageWidth,
320
+ imageHeight,
321
+ ],
322
+ );
323
+
324
+ return {
325
+ pinchGesture,
326
+ twoFingerPanGesture,
327
+ singleFingerPanGesture,
328
+ doubleTapResetGesture,
329
+ scale,
330
+ translateX,
331
+ translateY,
332
+ isPinching,
333
+ resetViewport,
334
+ panViewport,
335
+ zoomAt,
336
+ };
337
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,51 @@
1
+ // ─── Main Component ──────────────────────────────────────────────────────────
2
+ export { DrawingEditor } from "./DrawingEditor";
3
+
4
+ // ─── Store ───────────────────────────────────────────────────────────────────
5
+ export { useDrawingStore } from "./store/useDrawingStore";
6
+ export type { DrawingState } from "./store/useDrawingStore";
7
+
8
+ // ─── Types ───────────────────────────────────────────────────────────────────
9
+ export type {
10
+ DrawingEditorProps,
11
+ DrawingEditorRef,
12
+ DrawingObject,
13
+ FreehandObject,
14
+ LineObject,
15
+ ArrowObject,
16
+ RectangleObject,
17
+ CircleObject,
18
+ PolygonObject,
19
+ MeasureObject,
20
+ TextObject,
21
+ TwoPointObject,
22
+ ToolType,
23
+ TwoPointShapeType,
24
+ MeasureStyle,
25
+ Point,
26
+ Size,
27
+ UndoAction,
28
+ UndoActionType,
29
+ ToolbarRenderProps,
30
+ ColorPaletteRenderProps,
31
+ } from "./types";
32
+
33
+ // ─── Utilities ───────────────────────────────────────────────────────────────
34
+ export {
35
+ normalize,
36
+ denormalize,
37
+ normalizePoints,
38
+ denormalizePoints,
39
+ screenToCanvas,
40
+ } from "./utils/coordinates";
41
+ export {
42
+ serializeObjects,
43
+ deserializeObjects,
44
+ generateId,
45
+ } from "./utils/serialization";
46
+ export { PRESET_COLORS, DEFAULT_STROKE_COLOR } from "./utils/colors";
47
+
48
+ // ─── Reusable UI Components ─────────────────────────────────────────────────
49
+ export { Toolbar } from "./components/Toolbar";
50
+ export { ColorPalette } from "./components/ColorPalette";
51
+ export { LineWidthSlider } from "./components/LineWidthSlider";