@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,139 @@
1
+ import React, { useState, useCallback } from "react";
2
+ import {
3
+ Modal,
4
+ View,
5
+ TextInput,
6
+ TouchableOpacity,
7
+ Text,
8
+ StyleSheet,
9
+ KeyboardAvoidingView,
10
+ Platform,
11
+ } from "react-native";
12
+
13
+ interface TextEditModalProps {
14
+ visible: boolean;
15
+ initialValue: string;
16
+ onSubmit: (value: string) => void;
17
+ onCancel: () => void;
18
+ }
19
+
20
+ export const TextEditModal = React.memo(function TextEditModal({
21
+ visible,
22
+ initialValue,
23
+ onSubmit,
24
+ onCancel,
25
+ }: TextEditModalProps) {
26
+ const [text, setText] = useState(initialValue);
27
+
28
+ const handleSubmit = useCallback(() => {
29
+ if (text.trim()) {
30
+ onSubmit(text.trim());
31
+ }
32
+ }, [text, onSubmit]);
33
+
34
+ // Reset text when modal becomes visible
35
+ React.useEffect(() => {
36
+ if (visible) {
37
+ setText(initialValue);
38
+ }
39
+ }, [visible, initialValue]);
40
+
41
+ return (
42
+ <Modal
43
+ visible={visible}
44
+ transparent
45
+ animationType="fade"
46
+ onRequestClose={onCancel}
47
+ >
48
+ <KeyboardAvoidingView
49
+ style={styles.overlay}
50
+ behavior={Platform.OS === "ios" ? "padding" : "height"}
51
+ >
52
+ <View style={styles.dialog}>
53
+ <Text style={styles.title}>Edit Text</Text>
54
+ <TextInput
55
+ style={styles.input}
56
+ value={text}
57
+ onChangeText={setText}
58
+ placeholder="Enter text..."
59
+ placeholderTextColor="#999"
60
+ multiline
61
+ autoFocus
62
+ textAlignVertical="top"
63
+ />
64
+ <View style={styles.buttons}>
65
+ <TouchableOpacity style={styles.cancelButton} onPress={onCancel}>
66
+ <Text style={styles.cancelText}>Cancel</Text>
67
+ </TouchableOpacity>
68
+ <TouchableOpacity
69
+ style={styles.submitButton}
70
+ onPress={handleSubmit}
71
+ >
72
+ <Text style={styles.submitText}>Done</Text>
73
+ </TouchableOpacity>
74
+ </View>
75
+ </View>
76
+ </KeyboardAvoidingView>
77
+ </Modal>
78
+ );
79
+ });
80
+
81
+ const styles = StyleSheet.create({
82
+ overlay: {
83
+ flex: 1,
84
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
85
+ justifyContent: "center",
86
+ alignItems: "center",
87
+ padding: 24,
88
+ },
89
+ dialog: {
90
+ backgroundColor: "#2C2C2E",
91
+ borderRadius: 14,
92
+ padding: 20,
93
+ width: "100%",
94
+ maxWidth: 400,
95
+ },
96
+ title: {
97
+ color: "#FFFFFF",
98
+ fontSize: 18,
99
+ fontWeight: "600",
100
+ marginBottom: 16,
101
+ textAlign: "center",
102
+ },
103
+ input: {
104
+ backgroundColor: "#1C1C1E",
105
+ borderRadius: 10,
106
+ padding: 12,
107
+ color: "#FFFFFF",
108
+ fontSize: 16,
109
+ minHeight: 100,
110
+ marginBottom: 16,
111
+ },
112
+ buttons: {
113
+ flexDirection: "row",
114
+ gap: 12,
115
+ },
116
+ cancelButton: {
117
+ flex: 1,
118
+ paddingVertical: 12,
119
+ borderRadius: 10,
120
+ backgroundColor: "#3A3A3C",
121
+ alignItems: "center",
122
+ },
123
+ cancelText: {
124
+ color: "#FFFFFF",
125
+ fontSize: 16,
126
+ },
127
+ submitButton: {
128
+ flex: 1,
129
+ paddingVertical: 12,
130
+ borderRadius: 10,
131
+ backgroundColor: "#007AFF",
132
+ alignItems: "center",
133
+ },
134
+ submitText: {
135
+ color: "#FFFFFF",
136
+ fontSize: 16,
137
+ fontWeight: "600",
138
+ },
139
+ });
@@ -0,0 +1,254 @@
1
+ import React, { useCallback } from "react";
2
+ import {
3
+ View,
4
+ TouchableOpacity,
5
+ ScrollView,
6
+ StyleSheet,
7
+ Text,
8
+ Image,
9
+ useWindowDimensions,
10
+ type ImageSourcePropType,
11
+ } from "react-native";
12
+ import type { ToolType } from "../types";
13
+
14
+ interface ToolbarProps {
15
+ currentTool: ToolType | null;
16
+ onSelectTool: (tool: ToolType | null) => void;
17
+ onUndo: () => void;
18
+ canUndo: boolean;
19
+ isZoomed: boolean;
20
+ onResetZoom: () => void;
21
+ }
22
+
23
+ interface ToolIconSet {
24
+ default: ImageSourcePropType;
25
+ active: ImageSourcePropType;
26
+ }
27
+
28
+ interface ToolDefinition {
29
+ type: ToolType;
30
+ label: string;
31
+ icons: ToolIconSet;
32
+ }
33
+
34
+ const BUTTON_SIZE = 44;
35
+ const BUTTON_GAP = 4;
36
+ const TOOLBAR_HORIZONTAL_PADDING = 12;
37
+
38
+ const TOOLS: ToolDefinition[] = [
39
+ {
40
+ type: "freehand",
41
+ label: "Pen",
42
+ icons: {
43
+ default: require("../assets/toolbar-icons/freehand.png"),
44
+ active: require("../assets/toolbar-icons/freehand-enabled.png"),
45
+ },
46
+ },
47
+ {
48
+ type: "line",
49
+ label: "Line",
50
+ icons: {
51
+ default: require("../assets/toolbar-icons/line.png"),
52
+ active: require("../assets/toolbar-icons/line-enabled.png"),
53
+ },
54
+ },
55
+ {
56
+ type: "arrow",
57
+ label: "Arrow",
58
+ icons: {
59
+ default: require("../assets/toolbar-icons/arrow.png"),
60
+ active: require("../assets/toolbar-icons/arrow-enabled.png"),
61
+ },
62
+ },
63
+ {
64
+ type: "rectangle",
65
+ label: "Rect",
66
+ icons: {
67
+ default: require("../assets/toolbar-icons/rectangle.png"),
68
+ active: require("../assets/toolbar-icons/rectangle-enabled.png"),
69
+ },
70
+ },
71
+ {
72
+ type: "circle",
73
+ label: "Circle",
74
+ icons: {
75
+ default: require("../assets/toolbar-icons/circle.png"),
76
+ active: require("../assets/toolbar-icons/circle-enabled.png"),
77
+ },
78
+ },
79
+ {
80
+ type: "polygon",
81
+ label: "Polygon",
82
+ icons: {
83
+ default: require("../assets/toolbar-icons/polygon.png"),
84
+ active: require("../assets/toolbar-icons/polygon-enabled.png"),
85
+ },
86
+ },
87
+ {
88
+ type: "measure",
89
+ label: "Measure",
90
+ icons: {
91
+ default: require("../assets/toolbar-icons/measure.png"),
92
+ active: require("../assets/toolbar-icons/measure-enabled.png"),
93
+ },
94
+ },
95
+ {
96
+ type: "text",
97
+ label: "Text",
98
+ icons: {
99
+ default: require("../assets/toolbar-icons/text.png"),
100
+ active: require("../assets/toolbar-icons/text-enabled.png"),
101
+ },
102
+ },
103
+ ];
104
+
105
+ const FULL_TOOLBAR_WIDTH =
106
+ TOOLS.length * BUTTON_SIZE +
107
+ BUTTON_SIZE * 2 + // undo + reset
108
+ BUTTON_GAP * (TOOLS.length + 1) +
109
+ TOOLBAR_HORIZONTAL_PADDING * 2;
110
+
111
+ export const Toolbar = React.memo(function Toolbar({
112
+ currentTool,
113
+ onSelectTool,
114
+ onUndo,
115
+ canUndo,
116
+ isZoomed,
117
+ onResetZoom,
118
+ }: ToolbarProps) {
119
+ const { width } = useWindowDimensions();
120
+ const availableWidth = Math.max(width - 24, BUTTON_SIZE * 4);
121
+ const shellWidth = Math.min(availableWidth, 560);
122
+ const shouldCenterContent = shellWidth >= FULL_TOOLBAR_WIDTH;
123
+
124
+ return (
125
+ <View style={styles.container}>
126
+ <View style={[styles.shell, { width: shellWidth }]}>
127
+ <ScrollView
128
+ horizontal
129
+ bounces={false}
130
+ showsHorizontalScrollIndicator={false}
131
+ contentContainerStyle={[
132
+ styles.scrollContent,
133
+ shouldCenterContent && styles.scrollContentCentered,
134
+ ]}
135
+ >
136
+ {TOOLS.map((tool) => (
137
+ <ToolButton
138
+ key={tool.type}
139
+ tool={tool}
140
+ isActive={currentTool === tool.type}
141
+ onPress={onSelectTool}
142
+ />
143
+ ))}
144
+ <TouchableOpacity
145
+ accessibilityLabel="Undo"
146
+ style={[styles.button, !canUndo && styles.buttonDisabled]}
147
+ onPress={onUndo}
148
+ disabled={!canUndo}
149
+ activeOpacity={0.7}
150
+ >
151
+ <Text style={[styles.undoIcon, !canUndo && styles.iconDisabled]}>
152
+
153
+ </Text>
154
+ </TouchableOpacity>
155
+
156
+ {/* Reset zoom */}
157
+ {isZoomed && (
158
+ <TouchableOpacity
159
+ accessibilityLabel="Reset zoom"
160
+ style={styles.button}
161
+ onPress={onResetZoom}
162
+ activeOpacity={0.7}
163
+ >
164
+ <Text style={styles.undoIcon}>⊙</Text>
165
+ </TouchableOpacity>
166
+ )}
167
+ </ScrollView>
168
+ </View>
169
+ </View>
170
+ );
171
+ });
172
+
173
+ interface ToolButtonProps {
174
+ tool: ToolDefinition;
175
+ isActive: boolean;
176
+ onPress: (tool: ToolType) => void;
177
+ }
178
+
179
+ const ToolButton = React.memo(function ToolButton({
180
+ tool,
181
+ isActive,
182
+ onPress,
183
+ }: ToolButtonProps) {
184
+ const handlePress = useCallback(() => {
185
+ onPress(tool.type);
186
+ }, [onPress, tool.type]);
187
+
188
+ return (
189
+ <TouchableOpacity
190
+ accessibilityLabel={tool.label}
191
+ style={styles.button}
192
+ onPress={handlePress}
193
+ activeOpacity={0.7}
194
+ >
195
+ <Image
196
+ source={isActive ? tool.icons.active : tool.icons.default}
197
+ style={[styles.iconImage, isActive && styles.iconImageActive]}
198
+ resizeMode="contain"
199
+ />
200
+ </TouchableOpacity>
201
+ );
202
+ });
203
+
204
+ const styles = StyleSheet.create({
205
+ container: {
206
+ width: "100%",
207
+ alignItems: "center",
208
+ paddingHorizontal: 12,
209
+ paddingVertical: 8,
210
+ },
211
+ shell: {
212
+ backgroundColor: "rgba(0, 0, 0, 0.88)",
213
+ borderRadius: 18,
214
+ borderWidth: StyleSheet.hairlineWidth,
215
+ borderColor: "rgba(255, 255, 255, 0.16)",
216
+ },
217
+ scrollContent: {
218
+ alignItems: "center",
219
+ flexGrow: 1,
220
+ paddingHorizontal: TOOLBAR_HORIZONTAL_PADDING,
221
+ paddingVertical: 10,
222
+ gap: BUTTON_GAP,
223
+ },
224
+ scrollContentCentered: {
225
+ justifyContent: "center",
226
+ },
227
+ button: {
228
+ width: BUTTON_SIZE,
229
+ height: BUTTON_SIZE,
230
+ borderRadius: BUTTON_SIZE / 2,
231
+ justifyContent: "center",
232
+ alignItems: "center",
233
+ backgroundColor: "transparent",
234
+ },
235
+ buttonDisabled: {
236
+ opacity: 0.4,
237
+ },
238
+ iconImage: {
239
+ width: 26,
240
+ height: 26,
241
+ },
242
+ iconImageActive: {
243
+ width: 36,
244
+ height: 36,
245
+ },
246
+ iconDisabled: {
247
+ color: "#666666",
248
+ },
249
+ undoIcon: {
250
+ fontSize: 24,
251
+ lineHeight: 24,
252
+ color: "#FFFFFF",
253
+ },
254
+ });
@@ -0,0 +1,166 @@
1
+ import React from "react";
2
+ import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
3
+ import Animated, {
4
+ useAnimatedStyle,
5
+ useDerivedValue,
6
+ withTiming,
7
+ type SharedValue,
8
+ } from "react-native-reanimated";
9
+
10
+ const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity);
11
+
12
+ const HINT_DURATION = 3000;
13
+ const FADE_DURATION = 400;
14
+
15
+ interface ZoomBadgeProps {
16
+ scale: SharedValue<number>;
17
+ onPress: () => void;
18
+ }
19
+
20
+ export const ZoomBadge = React.memo(function ZoomBadge({
21
+ scale,
22
+ onPress,
23
+ }: ZoomBadgeProps) {
24
+ const isZoomed = useDerivedValue(() => scale.value > 1.02);
25
+ const [hintExpired, setHintExpired] = React.useState(false);
26
+ const [mounted, setMounted] = React.useState(true);
27
+ const [zoomed, setZoomed] = React.useState(false);
28
+
29
+ // Start fade-out after HINT_DURATION, then unmount after animation
30
+ React.useEffect(() => {
31
+ const fadeTimer = setTimeout(() => setHintExpired(true), HINT_DURATION);
32
+ const unmountTimer = setTimeout(
33
+ () => setMounted(false),
34
+ HINT_DURATION + FADE_DURATION,
35
+ );
36
+ return () => {
37
+ clearTimeout(fadeTimer);
38
+ clearTimeout(unmountTimer);
39
+ };
40
+ }, []);
41
+
42
+ // Track zoom state on JS thread
43
+ React.useEffect(() => {
44
+ const id = setInterval(() => {
45
+ setZoomed(isZoomed.value);
46
+ }, 100);
47
+ return () => clearInterval(id);
48
+ }, [isZoomed]);
49
+
50
+ const animatedStyle = useAnimatedStyle(() => {
51
+ const show = isZoomed.value || !hintExpired;
52
+ return {
53
+ opacity: withTiming(show ? 1 : 0, { duration: FADE_DURATION }),
54
+ transform: [
55
+ { scale: withTiming(show ? 1 : 0.85, { duration: FADE_DURATION }) },
56
+ ],
57
+ };
58
+ }, [hintExpired]);
59
+
60
+ const zoomText = useDerivedValue(() => {
61
+ const s = Math.round(scale.value * 10) / 10;
62
+ return `${s}x`;
63
+ });
64
+
65
+ // Keep mounted while hint is visible OR zoomed
66
+ if (!mounted && !zoomed) return null;
67
+
68
+ return (
69
+ <AnimatedTouchable
70
+ style={[styles.badge, animatedStyle]}
71
+ onPress={onPress}
72
+ activeOpacity={0.7}
73
+ >
74
+ {zoomed ? (
75
+ <ZoomLabel zoomText={zoomText} />
76
+ ) : (
77
+ <View style={styles.iconRow}>
78
+ <MagnifyIcon />
79
+ <Text style={styles.hintText}>Pinch to zoom</Text>
80
+ </View>
81
+ )}
82
+ </AnimatedTouchable>
83
+ );
84
+ });
85
+
86
+ function ZoomLabel({ zoomText }: { zoomText: SharedValue<string> }) {
87
+ const [text, setText] = React.useState("1x");
88
+
89
+ React.useEffect(() => {
90
+ const id = setInterval(() => {
91
+ const val = zoomText.value;
92
+ setText((prev) => (prev !== val ? val : prev));
93
+ }, 100);
94
+ return () => clearInterval(id);
95
+ }, [zoomText]);
96
+
97
+ return <Text style={styles.text}>{text}</Text>;
98
+ }
99
+
100
+ function MagnifyIcon() {
101
+ return (
102
+ <View style={styles.magnifyIcon}>
103
+ {/* Lens circle */}
104
+ <View style={styles.lens} />
105
+ {/* Handle */}
106
+ <View style={styles.handle} />
107
+ </View>
108
+ );
109
+ }
110
+
111
+ const styles = StyleSheet.create({
112
+ badge: {
113
+ position: "absolute",
114
+ top: 12,
115
+ alignSelf: "center",
116
+ backgroundColor: "rgba(0, 0, 0, 0.55)",
117
+ borderRadius: 14,
118
+ paddingHorizontal: 10,
119
+ paddingVertical: 5,
120
+ borderWidth: StyleSheet.hairlineWidth,
121
+ borderColor: "rgba(255, 255, 255, 0.25)",
122
+ flexDirection: "row",
123
+ alignItems: "center",
124
+ },
125
+ text: {
126
+ color: "#FFFFFF",
127
+ fontSize: 13,
128
+ fontWeight: "600",
129
+ fontVariant: ["tabular-nums"],
130
+ },
131
+ iconRow: {
132
+ flexDirection: "row",
133
+ alignItems: "center",
134
+ gap: 5,
135
+ },
136
+ hintText: {
137
+ color: "rgba(255, 255, 255, 0.9)",
138
+ fontSize: 12,
139
+ fontWeight: "500",
140
+ },
141
+ magnifyIcon: {
142
+ width: 14,
143
+ height: 14,
144
+ position: "relative",
145
+ },
146
+ lens: {
147
+ width: 9,
148
+ height: 9,
149
+ borderRadius: 5,
150
+ borderWidth: 1.5,
151
+ borderColor: "#FFFFFF",
152
+ position: "absolute",
153
+ top: 0,
154
+ left: 0,
155
+ },
156
+ handle: {
157
+ width: 5,
158
+ height: 1.5,
159
+ backgroundColor: "#FFFFFF",
160
+ borderRadius: 1,
161
+ position: "absolute",
162
+ bottom: 1.5,
163
+ right: 0,
164
+ transform: [{ rotate: "45deg" }],
165
+ },
166
+ });