@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,815 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DrawingEditor = void 0;
7
+ var _react = require("react");
8
+ var _reactNative = require("react-native");
9
+ var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
10
+ var _reactNativeSkia = require("@shopify/react-native-skia");
11
+ var _reactNativeGestureHandler = require("react-native-gesture-handler");
12
+ var _reactNativeReanimated = require("react-native-reanimated");
13
+ var _useDrawingStore = require("./store/useDrawingStore");
14
+ var _useFreehandGesture = require("./hooks/useFreehandGesture");
15
+ var _useShapeGesture = require("./hooks/useShapeGesture");
16
+ var _usePolygonGesture = require("./hooks/usePolygonGesture");
17
+ var _useSelectionGesture = require("./hooks/useSelectionGesture");
18
+ var _useViewportGesture = require("./hooks/useViewportGesture");
19
+ var _ObjectRenderer = require("./renderers/ObjectRenderer");
20
+ var _SelectionOverlay = require("./renderers/SelectionOverlay");
21
+ var _SelectedObjectRenderer = require("./renderers/SelectedObjectRenderer");
22
+ var _InProgressRenderer = require("./renderers/InProgressRenderer");
23
+ var _Toolbar = require("./components/Toolbar");
24
+ var _ColorPalette = require("./components/ColorPalette");
25
+ var _LineWidthSlider = require("./components/LineWidthSlider");
26
+ var _TextAnnotation = require("./components/TextAnnotation");
27
+ var _TextEditModal = require("./components/TextEditModal");
28
+ var _MeasurementEditModal = require("./components/MeasurementEditModal");
29
+ var _ZoomBadge = require("./components/ZoomBadge");
30
+ var _MiniMap = require("./components/MiniMap");
31
+ var _coordinates = require("./utils/coordinates");
32
+ var _serialization = require("./utils/serialization");
33
+ var _jsxRuntime = require("react/jsx-runtime");
34
+ const TWO_POINT_TOOLS = ["line", "arrow", "rectangle", "circle", "measure"];
35
+ const WEB_CURSOR_STYLES = {
36
+ default: {
37
+ cursor: "default"
38
+ },
39
+ crosshair: {
40
+ cursor: "crosshair"
41
+ },
42
+ grab: {
43
+ cursor: "grab"
44
+ },
45
+ grabbing: {
46
+ cursor: "grabbing"
47
+ },
48
+ text: {
49
+ cursor: "text"
50
+ }
51
+ };
52
+ const DrawingEditor = exports.DrawingEditor = /*#__PURE__*/(0, _react.forwardRef)(function DrawingEditor({
53
+ imageSource,
54
+ initialObjects,
55
+ maxZoom,
56
+ onSave: _onSave,
57
+ onDismiss: _onDismiss,
58
+ style,
59
+ renderToolbar,
60
+ renderColorPalette
61
+ }, ref) {
62
+ // ─── Phone vs tablet detection ───────────────────────────────────────────
63
+ const {
64
+ width: winWidth,
65
+ height: winHeight
66
+ } = (0, _reactNative.useWindowDimensions)();
67
+ const isPhone = Math.min(winWidth, winHeight) < 768;
68
+ const insets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
69
+
70
+ // ─── Store ───────────────────────────────────────────────────────────────
71
+ const currentTool = (0, _useDrawingStore.useDrawingStore)(s => s.currentTool);
72
+ const strokeColor = (0, _useDrawingStore.useDrawingStore)(s => s.strokeColor);
73
+ const fillColor = (0, _useDrawingStore.useDrawingStore)(s => s.fillColor);
74
+ const fillAlpha = (0, _useDrawingStore.useDrawingStore)(s => s.fillAlpha);
75
+ const lineWidth = (0, _useDrawingStore.useDrawingStore)(s => s.lineWidth);
76
+ const objects = (0, _useDrawingStore.useDrawingStore)(s => s.objects);
77
+ const selectedObjectId = (0, _useDrawingStore.useDrawingStore)(s => s.selectedObjectId);
78
+ const canvasSize = (0, _useDrawingStore.useDrawingStore)(s => s.canvasSize);
79
+ const undoStack = (0, _useDrawingStore.useDrawingStore)(s => s.undoStack);
80
+ const setTool = (0, _useDrawingStore.useDrawingStore)(s => s.setTool);
81
+ const setStrokeColor = (0, _useDrawingStore.useDrawingStore)(s => s.setStrokeColor);
82
+ const setLineWidth = (0, _useDrawingStore.useDrawingStore)(s => s.setLineWidth);
83
+ const setCanvasSize = (0, _useDrawingStore.useDrawingStore)(s => s.setCanvasSize);
84
+ const addObject = (0, _useDrawingStore.useDrawingStore)(s => s.addObject);
85
+ const updateObject = (0, _useDrawingStore.useDrawingStore)(s => s.updateObject);
86
+ const deleteObject = (0, _useDrawingStore.useDrawingStore)(s => s.deleteObject);
87
+ const selectObject = (0, _useDrawingStore.useDrawingStore)(s => s.selectObject);
88
+ const moveObject = (0, _useDrawingStore.useDrawingStore)(s => s.moveObject);
89
+ const undo = (0, _useDrawingStore.useDrawingStore)(s => s.undo);
90
+ const clearAll = (0, _useDrawingStore.useDrawingStore)(s => s.clearAll);
91
+ const loadObjects = (0, _useDrawingStore.useDrawingStore)(s => s.loadObjects);
92
+
93
+ // ─── Image ───────────────────────────────────────────────────────────────
94
+ const skiaImage = (0, _reactNativeSkia.useImage)(typeof imageSource === "string" ? imageSource : imageSource, err => console.warn("[DrawingEditor] Failed to load image:", err.message));
95
+ const canvasRef = (0, _reactNativeSkia.useCanvasRef)();
96
+
97
+ // ─── Layout ──────────────────────────────────────────────────────────────
98
+ const [layoutSize, setLayoutSize] = (0, _react.useState)({
99
+ width: 0,
100
+ height: 0
101
+ });
102
+ const [isPointerDown, setIsPointerDown] = (0, _react.useState)(false);
103
+ const wheelTargetRef = (0, _react.useRef)(null);
104
+ const setWheelTargetRef = (0, _react.useCallback)(node => {
105
+ wheelTargetRef.current = node;
106
+ }, []);
107
+ const handleLayout = (0, _react.useCallback)(event => {
108
+ const {
109
+ width,
110
+ height
111
+ } = event.nativeEvent.layout;
112
+ setLayoutSize({
113
+ width,
114
+ height
115
+ });
116
+ }, []);
117
+
118
+ // Reset store when component mounts (new image selected)
119
+ (0, _react.useEffect)(() => {
120
+ clearAll();
121
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
122
+
123
+ // Load initial objects once canvas is sized
124
+ (0, _react.useEffect)(() => {
125
+ if (initialObjects && canvasSize.width > 0) {
126
+ loadObjects(initialObjects);
127
+ }
128
+ }, [canvasSize.width > 0]); // eslint-disable-line react-hooks/exhaustive-deps
129
+
130
+ // ─── Shared values synced with store ─────────────────────────────────────
131
+ const colorSV = (0, _reactNativeReanimated.useSharedValue)(strokeColor);
132
+ const lineWidthSV = (0, _reactNativeReanimated.useSharedValue)(lineWidth);
133
+ const fillColorSV = (0, _reactNativeReanimated.useSharedValue)(fillColor);
134
+ const fillAlphaSV = (0, _reactNativeReanimated.useSharedValue)(fillAlpha);
135
+ const toolSV = (0, _reactNativeReanimated.useSharedValue)(currentTool);
136
+ (0, _react.useEffect)(() => {
137
+ colorSV.value = strokeColor;
138
+ }, [strokeColor]);
139
+ (0, _react.useEffect)(() => {
140
+ lineWidthSV.value = lineWidth;
141
+ }, [lineWidth]);
142
+ (0, _react.useEffect)(() => {
143
+ fillColorSV.value = fillColor;
144
+ }, [fillColor]);
145
+ (0, _react.useEffect)(() => {
146
+ fillAlphaSV.value = fillAlpha;
147
+ }, [fillAlpha]);
148
+ (0, _react.useEffect)(() => {
149
+ toolSV.value = currentTool;
150
+ }, [currentTool]);
151
+
152
+ // ─── Determine active tool shape type ───────────────────────────────────
153
+ const isFreehand = currentTool === "freehand";
154
+ const isPolygon = currentTool === "polygon";
155
+ const isTwoPointShape = TWO_POINT_TOOLS.includes(currentTool);
156
+ const isTextMode = currentTool === "text";
157
+
158
+ // ─── Image fit calculation ───────────────────────────────────────────────
159
+ const imageRect = (0, _react.useMemo)(() => {
160
+ if (!skiaImage || layoutSize.width === 0 || layoutSize.height === 0) {
161
+ return {
162
+ x: 0,
163
+ y: 0,
164
+ width: layoutSize.width,
165
+ height: layoutSize.height
166
+ };
167
+ }
168
+ const imgW = skiaImage.width();
169
+ const imgH = skiaImage.height();
170
+ const scaleX = layoutSize.width / imgW;
171
+ const scaleY = layoutSize.height / imgH;
172
+ const scale = Math.min(scaleX, scaleY);
173
+ const w = imgW * scale;
174
+ const h = imgH * scale;
175
+ return {
176
+ x: (layoutSize.width - w) / 2,
177
+ y: (layoutSize.height - h) / 2,
178
+ width: w,
179
+ height: h
180
+ };
181
+ }, [skiaImage, layoutSize]);
182
+
183
+ // ─── Effective canvas size = image rect ─────────────────────────────────
184
+ const effectiveCanvasSize = (0, _react.useMemo)(() => ({
185
+ width: imageRect.width,
186
+ height: imageRect.height
187
+ }), [imageRect.width, imageRect.height]);
188
+
189
+ // Sync to store for external consumers
190
+ (0, _react.useEffect)(() => {
191
+ if (imageRect.width > 0 && imageRect.height > 0) {
192
+ setCanvasSize({
193
+ width: imageRect.width,
194
+ height: imageRect.height
195
+ });
196
+ }
197
+ }, [imageRect.width, imageRect.height, setCanvasSize]);
198
+
199
+ // ─── Image bounds shared values (for worklet access) ─────────────────────
200
+ const imageOffsetXSV = (0, _reactNativeReanimated.useSharedValue)(0);
201
+ const imageOffsetYSV = (0, _reactNativeReanimated.useSharedValue)(0);
202
+ const imageWidthSV = (0, _reactNativeReanimated.useSharedValue)(0);
203
+ const imageHeightSV = (0, _reactNativeReanimated.useSharedValue)(0);
204
+ (0, _react.useEffect)(() => {
205
+ imageOffsetXSV.value = imageRect.x;
206
+ imageOffsetYSV.value = imageRect.y;
207
+ imageWidthSV.value = imageRect.width;
208
+ imageHeightSV.value = imageRect.height;
209
+ }, [imageRect]);
210
+
211
+ // ─── Viewport (zoom/pan) ─────────────────────────────────────────────────
212
+ const [isZoomed, setIsZoomed] = (0, _react.useState)(false);
213
+ const layoutWidthSV = (0, _reactNativeReanimated.useSharedValue)(0);
214
+ const layoutHeightSV = (0, _reactNativeReanimated.useSharedValue)(0);
215
+ (0, _react.useEffect)(() => {
216
+ layoutWidthSV.value = layoutSize.width;
217
+ layoutHeightSV.value = layoutSize.height;
218
+ }, [layoutSize]);
219
+ const handlePinchEnd = (0, _react.useCallback)(() => {
220
+ setTool(null);
221
+ }, [setTool]);
222
+ const viewport = (0, _useViewportGesture.useViewportGesture)({
223
+ maxZoom,
224
+ layoutWidth: layoutWidthSV,
225
+ layoutHeight: layoutHeightSV,
226
+ imageOffsetX: imageOffsetXSV,
227
+ imageOffsetY: imageOffsetYSV,
228
+ imageWidth: imageWidthSV,
229
+ imageHeight: imageHeightSV,
230
+ onPinchEnd: handlePinchEnd
231
+ });
232
+
233
+ // Track isZoomed state for UI.
234
+ // Only tracks zoom level — tool deactivation is handled by onPinchEnd.
235
+ (0, _react.useEffect)(() => {
236
+ const id = setInterval(() => {
237
+ const zoomed = viewport.scale.value > 1.01;
238
+ setIsZoomed(prev => {
239
+ if (prev !== zoomed) return zoomed;
240
+ return prev;
241
+ });
242
+ }, 200);
243
+ return () => clearInterval(id);
244
+ }, [viewport.scale, viewport.isPinching]);
245
+
246
+ // ─── Measurement editing modal ───────────────────────────────────────────
247
+ const [measureEditVisible, setMeasureEditVisible] = (0, _react.useState)(false);
248
+ const [measureEditTarget, setMeasureEditTarget] = (0, _react.useState)(null);
249
+ const lastUsedUnit = (0, _react.useRef)("cm");
250
+ const handleMeasureCreated = (0, _react.useCallback)(id => {
251
+ setMeasureEditTarget(id);
252
+ setMeasureEditVisible(true);
253
+ }, []);
254
+ const handleMeasureSubmit = (0, _react.useCallback)((value, unit) => {
255
+ if (measureEditTarget) {
256
+ updateObject(measureEditTarget, {
257
+ text: value,
258
+ unit
259
+ });
260
+ }
261
+ lastUsedUnit.current = unit;
262
+ setMeasureEditVisible(false);
263
+ setMeasureEditTarget(null);
264
+ }, [measureEditTarget, updateObject]);
265
+ const handleMeasureCancel = (0, _react.useCallback)(() => {
266
+ if (measureEditTarget) {
267
+ deleteObject(measureEditTarget);
268
+ }
269
+ setMeasureEditVisible(false);
270
+ setMeasureEditTarget(null);
271
+ }, [measureEditTarget, deleteObject]);
272
+
273
+ // ─── Gesture: Freehand ───────────────────────────────────────────────────
274
+ const freehand = (0, _useFreehandGesture.useFreehandGesture)({
275
+ colorSV,
276
+ lineWidthSV,
277
+ fillColorSV,
278
+ fillAlphaSV,
279
+ canvasSize: effectiveCanvasSize,
280
+ enabled: isFreehand && !selectedObjectId,
281
+ imageOffsetX: imageOffsetXSV,
282
+ imageOffsetY: imageOffsetYSV,
283
+ imageWidth: imageWidthSV,
284
+ imageHeight: imageHeightSV,
285
+ viewScale: viewport.scale,
286
+ viewTranslateX: viewport.translateX,
287
+ viewTranslateY: viewport.translateY
288
+ });
289
+
290
+ // ─── Gesture: Shape ──────────────────────────────────────────────────────
291
+ const shape = (0, _useShapeGesture.useShapeGesture)({
292
+ shapeType: isTwoPointShape ? currentTool : "line",
293
+ colorSV,
294
+ lineWidthSV,
295
+ fillColorSV,
296
+ fillAlphaSV,
297
+ canvasSize: effectiveCanvasSize,
298
+ enabled: isTwoPointShape && !selectedObjectId,
299
+ imageOffsetX: imageOffsetXSV,
300
+ imageOffsetY: imageOffsetYSV,
301
+ imageWidth: imageWidthSV,
302
+ imageHeight: imageHeightSV,
303
+ viewScale: viewport.scale,
304
+ viewTranslateX: viewport.translateX,
305
+ viewTranslateY: viewport.translateY,
306
+ onMeasureCreated: handleMeasureCreated
307
+ });
308
+
309
+ // ─── Gesture: Polygon ────────────────────────────────────────────────────
310
+ const polygon = (0, _usePolygonGesture.usePolygonGesture)({
311
+ colorSV,
312
+ lineWidthSV,
313
+ fillColorSV,
314
+ fillAlphaSV,
315
+ canvasSize: effectiveCanvasSize,
316
+ enabled: isPolygon && !selectedObjectId,
317
+ imageOffsetX: imageOffsetXSV,
318
+ imageOffsetY: imageOffsetYSV,
319
+ imageWidth: imageWidthSV,
320
+ imageHeight: imageHeightSV,
321
+ viewScale: viewport.scale,
322
+ viewTranslateX: viewport.translateX,
323
+ viewTranslateY: viewport.translateY
324
+ });
325
+
326
+ // Cancel polygon construction when switching away from polygon tool
327
+ const prevToolRef = (0, _react.useRef)(currentTool);
328
+ (0, _react.useEffect)(() => {
329
+ if (prevToolRef.current === "polygon" && currentTool !== "polygon") {
330
+ polygon.cancel();
331
+ }
332
+ prevToolRef.current = currentTool;
333
+ }, [currentTool]); // eslint-disable-line react-hooks/exhaustive-deps
334
+
335
+ // ─── Gesture: Text placement (on empty space tap) ────────────────────────
336
+ const handleTextTap = (0, _react.useCallback)((x, y) => {
337
+ const pos = (0, _coordinates.normalize)({
338
+ x,
339
+ y
340
+ }, effectiveCanvasSize);
341
+ const newText = {
342
+ id: (0, _serialization.generateId)(),
343
+ type: "text",
344
+ position: pos,
345
+ width: 0.2,
346
+ // 20% of canvas
347
+ height: 0.08,
348
+ value: "Text",
349
+ color: strokeColor,
350
+ lineWidth
351
+ };
352
+ addObject(newText);
353
+ setTextEditTarget(newText.id);
354
+ setTextEditValue("Text");
355
+ setTextEditVisible(true);
356
+ }, [effectiveCanvasSize, strokeColor, lineWidth, addObject]);
357
+
358
+ // ─── Handle tap on empty space (deselect or place text) ──────────────────
359
+ const handleTapEmpty = (0, _react.useCallback)((x, y) => {
360
+ if (isTextMode) {
361
+ handleTextTap(x, y);
362
+ } else {
363
+ selectObject(null);
364
+ }
365
+ }, [isTextMode, handleTextTap, selectObject]);
366
+
367
+ // ─── Gesture: Selection (always active) ──────────────────────────────────
368
+ const selection = (0, _useSelectionGesture.useSelectionGesture)({
369
+ canvasSize: effectiveCanvasSize,
370
+ imageOffsetX: imageOffsetXSV,
371
+ imageOffsetY: imageOffsetYSV,
372
+ viewScale: viewport.scale,
373
+ viewTranslateX: viewport.translateX,
374
+ viewTranslateY: viewport.translateY,
375
+ onTapEmpty: handleTapEmpty
376
+ });
377
+
378
+ // ─── Compose all gestures ────────────────────────────────────────────────
379
+ const composedGesture = (0, _react.useMemo)(() => {
380
+ // Navigation gestures (pinch + two-finger pan) run simultaneously
381
+ const navigationGestures = _reactNativeGestureHandler.Gesture.Simultaneous(viewport.pinchGesture, viewport.twoFingerPanGesture);
382
+
383
+ // Drawing/selection pan gestures — these must NOT be delayed by tap recognition
384
+ const noToolActive = currentTool === null;
385
+ const drawingPanGestures = selectedObjectId ? selection.panGesture : noToolActive && isZoomed ? viewport.singleFingerPanGesture : isFreehand ? freehand.gesture : isTwoPointShape ? shape.gesture : selection.panGesture;
386
+
387
+ // Tap gestures (double-tap and single-tap) — run in Exclusive so
388
+ // double-tap has priority over single-tap, but they don't block pan
389
+ const tapGestures = _reactNativeGestureHandler.Gesture.Exclusive(viewport.doubleTapResetGesture,
390
+ // Polygon tap has priority over selection tap when polygon tool is active
391
+ ...(isPolygon ? [polygon.gesture] : [selection.doubleTapGesture, selection.tapGesture]));
392
+
393
+ // Pan and tap gestures run simultaneously — pan starts immediately
394
+ // without waiting for tap recognition timeout
395
+ const interactionGestures = _reactNativeGestureHandler.Gesture.Simultaneous(drawingPanGestures, tapGestures);
396
+
397
+ // Navigation and interaction run simultaneously
398
+ return _reactNativeGestureHandler.Gesture.Simultaneous(navigationGestures, interactionGestures);
399
+ }, [viewport.pinchGesture, viewport.twoFingerPanGesture, viewport.doubleTapResetGesture, viewport.singleFingerPanGesture, selection.doubleTapGesture, selection.panGesture, selection.tapGesture, polygon.gesture, freehand.gesture, shape.gesture, currentTool, selectedObjectId, isZoomed, isFreehand, isTwoPointShape, isPolygon]);
400
+
401
+ // ─── Text editing modal ──────────────────────────────────────────────────
402
+ const [textEditVisible, setTextEditVisible] = (0, _react.useState)(false);
403
+ const [textEditTarget, setTextEditTarget] = (0, _react.useState)(null);
404
+ const [textEditValue, setTextEditValue] = (0, _react.useState)("");
405
+ const handleTextSubmit = (0, _react.useCallback)(value => {
406
+ if (textEditTarget) {
407
+ updateObject(textEditTarget, {
408
+ value
409
+ });
410
+ }
411
+ setTextEditVisible(false);
412
+ setTextEditTarget(null);
413
+ }, [textEditTarget, updateObject]);
414
+ const handleTextDoubleTap = (0, _react.useCallback)(id => {
415
+ const obj = objects.find(o => o.id === id);
416
+ if (obj?.type === "text") {
417
+ setTextEditTarget(id);
418
+ setTextEditValue(obj.value);
419
+ setTextEditVisible(true);
420
+ }
421
+ }, [objects]);
422
+
423
+ // ─── Computed values ─────────────────────────────────────────────────────
424
+ const selectedObject = (0, _react.useMemo)(() => selectedObjectId ? objects.find(o => o.id === selectedObjectId) ?? null : null, [objects, selectedObjectId]);
425
+ const textObjects = (0, _react.useMemo)(() => objects.filter(o => o.type === "text"), [objects]);
426
+ const nonTextObjects = (0, _react.useMemo)(() => objects.filter(o => o.type !== "text"), [objects]);
427
+ const unselectedNonTextObjects = (0, _react.useMemo)(() => nonTextObjects.filter(o => o.id !== selectedObjectId), [nonTextObjects, selectedObjectId]);
428
+
429
+ // ─── Imperative ref ──────────────────────────────────────────────────────
430
+ (0, _react.useImperativeHandle)(ref, () => ({
431
+ undo,
432
+ setTool,
433
+ exportImage: async () => {
434
+ // Reset viewport to identity for a clean capture
435
+ const prevScale = viewport.scale.value;
436
+ const prevTx = viewport.translateX.value;
437
+ const prevTy = viewport.translateY.value;
438
+ viewport.scale.value = 1;
439
+ viewport.translateX.value = 0;
440
+ viewport.translateY.value = 0;
441
+
442
+ // Wait a frame for Skia to re-render
443
+ await new Promise(r => requestAnimationFrame(r));
444
+ const bounds = {
445
+ x: Math.round(imageRect.x),
446
+ y: Math.round(imageRect.y),
447
+ width: Math.round(imageRect.width),
448
+ height: Math.round(imageRect.height)
449
+ };
450
+ const image = canvasRef.current?.makeImageSnapshot(bounds);
451
+
452
+ // Restore viewport
453
+ viewport.scale.value = prevScale;
454
+ viewport.translateX.value = prevTx;
455
+ viewport.translateY.value = prevTy;
456
+ if (!image) return null;
457
+ return image.encodeToBytes();
458
+ },
459
+ exportImageBase64: async () => {
460
+ // Reset viewport to identity for a clean capture
461
+ const prevScale = viewport.scale.value;
462
+ const prevTx = viewport.translateX.value;
463
+ const prevTy = viewport.translateY.value;
464
+ viewport.scale.value = 1;
465
+ viewport.translateX.value = 0;
466
+ viewport.translateY.value = 0;
467
+ await new Promise(r => requestAnimationFrame(r));
468
+ const bounds = {
469
+ x: Math.round(imageRect.x),
470
+ y: Math.round(imageRect.y),
471
+ width: Math.round(imageRect.width),
472
+ height: Math.round(imageRect.height)
473
+ };
474
+ const image = canvasRef.current?.makeImageSnapshot(bounds);
475
+ viewport.scale.value = prevScale;
476
+ viewport.translateX.value = prevTx;
477
+ viewport.translateY.value = prevTy;
478
+ if (!image) return null;
479
+ return image.encodeToBase64();
480
+ },
481
+ getObjects: () => objects,
482
+ clearAll,
483
+ resetZoom: viewport.resetViewport
484
+ }), [undo, setTool, objects, clearAll, imageRect, viewport]);
485
+
486
+ // ─── Toolbar callbacks ───────────────────────────────────────────────────
487
+ const handleSelectTool = (0, _react.useCallback)(tool => {
488
+ setTool(tool);
489
+ }, [setTool]);
490
+ const handleUndo = (0, _react.useCallback)(() => {
491
+ undo();
492
+ }, [undo]);
493
+ const handleResetZoom = (0, _react.useCallback)(() => {
494
+ viewport.resetViewport();
495
+ }, [viewport]);
496
+
497
+ // ─── Viewport transform for Skia (animated) ─────────────────────────────
498
+ const viewportTransform = (0, _reactNativeReanimated.useDerivedValue)(() => [{
499
+ translateX: viewport.translateX.value
500
+ }, {
501
+ translateY: viewport.translateY.value
502
+ }, {
503
+ scale: viewport.scale.value
504
+ }]);
505
+ const usesMoveCursor = selectedObjectId !== null || currentTool === null;
506
+ const handlePointerDown = (0, _react.useCallback)(() => {
507
+ if (_reactNative.Platform.OS === "web" && usesMoveCursor) {
508
+ setIsPointerDown(true);
509
+ }
510
+ }, [usesMoveCursor]);
511
+ const handlePointerRelease = (0, _react.useCallback)(() => {
512
+ if (_reactNative.Platform.OS === "web") {
513
+ setIsPointerDown(false);
514
+ }
515
+ }, []);
516
+ const handleWheel = (0, _react.useCallback)(event => {
517
+ const wheelEvent = event.nativeEvent ?? event;
518
+ if (!wheelEvent.ctrlKey || wheelEvent.deltaY === undefined) return;
519
+ event.preventDefault?.();
520
+ wheelEvent.preventDefault?.();
521
+ const bounds = event.currentTarget?.getBoundingClientRect?.();
522
+ if (!bounds) return;
523
+ const clientX = wheelEvent.clientX ?? event.clientX;
524
+ const clientY = wheelEvent.clientY ?? event.clientY;
525
+ if (clientX === undefined || clientY === undefined) return;
526
+ const localX = clientX - bounds.left;
527
+ const localY = clientY - bounds.top;
528
+ const scaleFactor = Math.min(1.25, Math.max(0.8, Math.exp(-wheelEvent.deltaY * 0.01)));
529
+ viewport.zoomAt(localX, localY, scaleFactor);
530
+ }, [viewport]);
531
+ (0, _react.useEffect)(() => {
532
+ if (_reactNative.Platform.OS !== "web") return;
533
+ const target = wheelTargetRef.current;
534
+ if (!target?.addEventListener || !target.removeEventListener) return;
535
+ const options = {
536
+ passive: false
537
+ };
538
+ target.addEventListener("wheel", handleWheel, options);
539
+ return () => {
540
+ target.removeEventListener?.("wheel", handleWheel, options);
541
+ };
542
+ }, [handleWheel]);
543
+ const webPointerHandlers = _reactNative.Platform.OS === "web" ? {
544
+ onPointerDown: handlePointerDown,
545
+ onPointerUp: handlePointerRelease,
546
+ onPointerCancel: handlePointerRelease,
547
+ onPointerLeave: handlePointerRelease
548
+ } : undefined;
549
+ const canvasCursorStyle = (0, _react.useMemo)(() => {
550
+ if (_reactNative.Platform.OS !== "web") return undefined;
551
+ if (usesMoveCursor && isPointerDown) {
552
+ return WEB_CURSOR_STYLES.grabbing;
553
+ }
554
+ if (usesMoveCursor) {
555
+ return WEB_CURSOR_STYLES.grab;
556
+ }
557
+ if (isTextMode) return WEB_CURSOR_STYLES.text;
558
+ if (currentTool) return WEB_CURSOR_STYLES.crosshair;
559
+ return WEB_CURSOR_STYLES.default;
560
+ }, [currentTool, isPointerDown, isTextMode, usesMoveCursor]);
561
+
562
+ // ─── Render ──────────────────────────────────────────────────────────────
563
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeGestureHandler.GestureHandlerRootView, {
564
+ style: [styles.root, style],
565
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
566
+ style: [styles.editorContainer, isPhone ? styles.editorContainerPhone : styles.editorContainerTablet],
567
+ children: [!isPhone && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
568
+ style: styles.sidebarLeft,
569
+ children: renderColorPalette ? renderColorPalette({
570
+ strokeColor,
571
+ fillColor,
572
+ fillAlpha,
573
+ onSelectStrokeColor: setStrokeColor,
574
+ onSelectFillColor: _useDrawingStore.useDrawingStore.getState().setFillColor,
575
+ onSelectFillAlpha: _useDrawingStore.useDrawingStore.getState().setFillAlpha
576
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_ColorPalette.ColorPalette, {
577
+ strokeColor: strokeColor,
578
+ onSelectColor: setStrokeColor,
579
+ direction: "vertical"
580
+ })
581
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
582
+ style: styles.canvasContainer,
583
+ onLayout: handleLayout,
584
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
585
+ gesture: composedGesture,
586
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
587
+ ...webPointerHandlers,
588
+ ref: setWheelTargetRef,
589
+ style: [_reactNative.StyleSheet.absoluteFill, canvasCursorStyle],
590
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSkia.Canvas
591
+ // On web, the Skia <canvas> element must not capture pointer events.
592
+ // RNGH attaches its listeners to the parent View and calls
593
+ // setPointerCapture on event.target; if the <canvas> is the topmost
594
+ // hit target it grabs the pointer and starves the gesture of the move
595
+ // stream (only stray points get through).
596
+ // The Skia web view drops the `pointerEvents` prop, so we must deliver
597
+ // `pointer-events: none` through `style` instead — it is inherited by
598
+ // the inner <canvas>, making it click-through.
599
+ , {
600
+ style: _reactNative.Platform.OS === "web" ? {
601
+ ..._reactNative.StyleSheet.absoluteFillObject,
602
+ pointerEvents: "none"
603
+ } : _reactNative.StyleSheet.absoluteFill,
604
+ ref: canvasRef,
605
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSkia.Fill, {
606
+ color: "black"
607
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSkia.Group, {
608
+ transform: viewportTransform,
609
+ children: [skiaImage && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSkia.Image, {
610
+ image: skiaImage,
611
+ x: imageRect.x,
612
+ y: imageRect.y,
613
+ width: imageRect.width,
614
+ height: imageRect.height,
615
+ fit: "contain"
616
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSkia.Group, {
617
+ transform: [{
618
+ translateX: imageRect.x
619
+ }, {
620
+ translateY: imageRect.y
621
+ }],
622
+ clip: (0, _reactNativeSkia.rect)(0, 0, imageRect.width, imageRect.height),
623
+ children: [unselectedNonTextObjects.map(obj => /*#__PURE__*/(0, _jsxRuntime.jsx)(_ObjectRenderer.ObjectRenderer, {
624
+ object: obj,
625
+ canvasSize: effectiveCanvasSize
626
+ }, obj.id)), selectedObject && selectedObject.type !== "text" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
627
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_SelectedObjectRenderer.SelectedObjectRenderer, {
628
+ object: selectedObject,
629
+ canvasSize: effectiveCanvasSize,
630
+ isDragging: selection.isDragging,
631
+ draggingAnchorIndex: selection.draggingAnchorIndex,
632
+ dragOffsetX: selection.dragOffsetX,
633
+ dragOffsetY: selection.dragOffsetY
634
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SelectionOverlay.SelectionOverlay, {
635
+ object: selectedObject,
636
+ canvasSize: effectiveCanvasSize,
637
+ draggingAnchorIndex: selection.draggingAnchorIndex,
638
+ dragOffsetX: selection.dragOffsetX,
639
+ dragOffsetY: selection.dragOffsetY,
640
+ isDragging: selection.isDragging
641
+ })]
642
+ }), isFreehand && /*#__PURE__*/(0, _jsxRuntime.jsx)(_InProgressRenderer.FreehandInProgress, {
643
+ path: freehand.inProgressPath,
644
+ color: freehand.inProgressColor,
645
+ lineWidth: freehand.inProgressWidth,
646
+ isDrawing: freehand.isDrawing
647
+ }), isTwoPointShape && /*#__PURE__*/(0, _jsxRuntime.jsx)(_InProgressRenderer.ShapeInProgress, {
648
+ shapeType: currentTool,
649
+ startX: shape.startX,
650
+ startY: shape.startY,
651
+ currentX: shape.currentX,
652
+ currentY: shape.currentY,
653
+ color: shape.inProgressColor,
654
+ lineWidth: shape.inProgressWidth,
655
+ fillColor: shape.inProgressFillColor,
656
+ fillAlpha: shape.inProgressFillAlpha,
657
+ isDrawing: shape.isDrawing
658
+ }), isPolygon && /*#__PURE__*/(0, _jsxRuntime.jsx)(_InProgressRenderer.PolygonInProgress, {
659
+ pointsFlat: polygon.pointsFlat,
660
+ pointCount: polygon.pointCount,
661
+ isActive: polygon.isActive
662
+ })]
663
+ })]
664
+ })]
665
+ }), textObjects.map(textObj => /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextAnnotation.TextAnnotation, {
666
+ object: textObj,
667
+ canvasSize: effectiveCanvasSize,
668
+ imageOffset: {
669
+ x: imageRect.x,
670
+ y: imageRect.y
671
+ },
672
+ isSelected: selectedObjectId === textObj.id,
673
+ onSelect: selectObject,
674
+ onMove: moveObject,
675
+ onDoubleTap: handleTextDoubleTap,
676
+ onDelete: deleteObject,
677
+ viewScale: viewport.scale,
678
+ viewTranslateX: viewport.translateX,
679
+ viewTranslateY: viewport.translateY
680
+ }, textObj.id))]
681
+ })
682
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ZoomBadge.ZoomBadge, {
683
+ scale: viewport.scale,
684
+ onPress: handleResetZoom
685
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_MiniMap.MiniMap, {
686
+ image: skiaImage,
687
+ imageRect: imageRect,
688
+ scale: viewport.scale,
689
+ translateX: viewport.translateX,
690
+ translateY: viewport.translateY,
691
+ visible: isZoomed,
692
+ onPanViewport: viewport.panViewport
693
+ })]
694
+ }), !isPhone && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
695
+ style: styles.sidebarRight,
696
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_LineWidthSlider.LineWidthSlider, {
697
+ value: lineWidth,
698
+ onValueChange: setLineWidth,
699
+ orientation: "vertical"
700
+ })
701
+ })]
702
+ }), isPhone ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
703
+ style: [styles.phoneBottomArea, {
704
+ paddingBottom: insets.bottom
705
+ }],
706
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
707
+ style: styles.phoneControlsBar,
708
+ children: [renderColorPalette ? renderColorPalette({
709
+ strokeColor,
710
+ fillColor,
711
+ fillAlpha,
712
+ onSelectStrokeColor: setStrokeColor,
713
+ onSelectFillColor: _useDrawingStore.useDrawingStore.getState().setFillColor,
714
+ onSelectFillAlpha: _useDrawingStore.useDrawingStore.getState().setFillAlpha
715
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_ColorPalette.ColorPalette, {
716
+ strokeColor: strokeColor,
717
+ onSelectColor: setStrokeColor,
718
+ direction: "horizontal"
719
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_LineWidthSlider.LineWidthSlider, {
720
+ value: lineWidth,
721
+ onValueChange: setLineWidth,
722
+ orientation: "horizontal"
723
+ })]
724
+ }), renderToolbar ? renderToolbar({
725
+ currentTool,
726
+ onSelectTool: handleSelectTool,
727
+ onUndo: handleUndo,
728
+ canUndo: undoStack.length > 0,
729
+ isZoomed,
730
+ onResetZoom: handleResetZoom
731
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbar.Toolbar, {
732
+ currentTool: currentTool,
733
+ onSelectTool: handleSelectTool,
734
+ onUndo: handleUndo,
735
+ canUndo: undoStack.length > 0,
736
+ isZoomed: isZoomed,
737
+ onResetZoom: handleResetZoom
738
+ })]
739
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
740
+ pointerEvents: "box-none",
741
+ style: styles.toolbarOverlay,
742
+ children: renderToolbar ? renderToolbar({
743
+ currentTool,
744
+ onSelectTool: handleSelectTool,
745
+ onUndo: handleUndo,
746
+ canUndo: undoStack.length > 0,
747
+ isZoomed,
748
+ onResetZoom: handleResetZoom
749
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbar.Toolbar, {
750
+ currentTool: currentTool,
751
+ onSelectTool: handleSelectTool,
752
+ onUndo: handleUndo,
753
+ canUndo: undoStack.length > 0,
754
+ isZoomed: isZoomed,
755
+ onResetZoom: handleResetZoom
756
+ })
757
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextEditModal.TextEditModal, {
758
+ visible: textEditVisible,
759
+ initialValue: textEditValue,
760
+ onSubmit: handleTextSubmit,
761
+ onCancel: () => setTextEditVisible(false)
762
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_MeasurementEditModal.MeasurementEditModal, {
763
+ visible: measureEditVisible,
764
+ initialValue: "",
765
+ initialUnit: lastUsedUnit.current,
766
+ onSubmit: handleMeasureSubmit,
767
+ onCancel: handleMeasureCancel
768
+ })]
769
+ });
770
+ });
771
+ const styles = _reactNative.StyleSheet.create({
772
+ root: {
773
+ flex: 1,
774
+ backgroundColor: "#000000",
775
+ position: "relative"
776
+ },
777
+ editorContainer: {
778
+ flex: 1,
779
+ flexDirection: "row"
780
+ },
781
+ editorContainerTablet: {
782
+ paddingBottom: 92
783
+ },
784
+ editorContainerPhone: {
785
+ flexDirection: "column"
786
+ },
787
+ sidebarLeft: {
788
+ justifyContent: "center",
789
+ paddingHorizontal: 4
790
+ },
791
+ canvasContainer: {
792
+ flex: 1
793
+ },
794
+ sidebarRight: {
795
+ justifyContent: "center",
796
+ paddingHorizontal: 4
797
+ },
798
+ phoneBottomArea: {
799
+ backgroundColor: "#000000"
800
+ },
801
+ phoneControlsBar: {
802
+ flexDirection: "row",
803
+ alignItems: "center",
804
+ justifyContent: "center",
805
+ paddingHorizontal: 4
806
+ },
807
+ toolbarOverlay: {
808
+ position: "absolute",
809
+ left: 0,
810
+ right: 0,
811
+ bottom: 12,
812
+ alignItems: "center"
813
+ }
814
+ });
815
+ //# sourceMappingURL=DrawingEditor.js.map