@reekon-tools/boldr-cad 0.1.0 → 1.0.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 (547) hide show
  1. package/README.md +81 -9
  2. package/dist/app/edit.d.ts +12 -1
  3. package/dist/app/edit.js +96 -11
  4. package/dist/app/edit.js.map +1 -1
  5. package/dist/app/state.d.ts +31 -4
  6. package/dist/app/state.js +31 -2
  7. package/dist/app/state.js.map +1 -1
  8. package/dist/data/memory.d.ts +5 -0
  9. package/dist/data/memory.js +2 -2
  10. package/dist/data/memory.js.map +1 -1
  11. package/dist/data/provider.d.ts +19 -7
  12. package/dist/data/sync.d.ts +7 -2
  13. package/dist/data/sync.js +115 -64
  14. package/dist/data/sync.js.map +1 -1
  15. package/dist/editor/actions.d.ts +1 -2
  16. package/dist/editor/actions.js +391 -113
  17. package/dist/editor/actions.js.map +1 -1
  18. package/dist/editor/confirm.d.ts +23 -0
  19. package/dist/editor/confirm.js +35 -0
  20. package/dist/editor/confirm.js.map +1 -0
  21. package/dist/editor/elevation.d.ts +191 -90
  22. package/dist/editor/elevation.js +812 -616
  23. package/dist/editor/elevation.js.map +1 -1
  24. package/dist/editor/face.d.ts +73 -0
  25. package/dist/editor/face.js +269 -0
  26. package/dist/editor/face.js.map +1 -0
  27. package/dist/editor/files.d.ts +6 -0
  28. package/dist/editor/files.js +50 -4
  29. package/dist/editor/files.js.map +1 -1
  30. package/dist/editor/gestures.d.ts +18 -3
  31. package/dist/editor/gestures.js +145 -30
  32. package/dist/editor/gestures.js.map +1 -1
  33. package/dist/editor/keypad.d.ts +19 -4
  34. package/dist/editor/keypad.js +39 -9
  35. package/dist/editor/keypad.js.map +1 -1
  36. package/dist/editor/keys.js +36 -4
  37. package/dist/editor/keys.js.map +1 -1
  38. package/dist/editor/laser.d.ts +20 -4
  39. package/dist/editor/laser.js +104 -21
  40. package/dist/editor/laser.js.map +1 -1
  41. package/dist/editor/linkActions.d.ts +49 -0
  42. package/dist/editor/linkActions.js +210 -0
  43. package/dist/editor/linkActions.js.map +1 -0
  44. package/dist/editor/linkFollow.d.ts +2 -0
  45. package/dist/editor/linkFollow.js +53 -0
  46. package/dist/editor/linkFollow.js.map +1 -0
  47. package/dist/editor/linkWrite.d.ts +13 -0
  48. package/dist/editor/linkWrite.js +84 -0
  49. package/dist/editor/linkWrite.js.map +1 -0
  50. package/dist/editor/links.d.ts +84 -0
  51. package/dist/editor/links.js +130 -0
  52. package/dist/editor/links.js.map +1 -0
  53. package/dist/editor/markup.d.ts +29 -3
  54. package/dist/editor/markup.js +95 -10
  55. package/dist/editor/markup.js.map +1 -1
  56. package/dist/editor/mode.d.ts +40 -2
  57. package/dist/editor/mode.js +71 -4
  58. package/dist/editor/mode.js.map +1 -1
  59. package/dist/editor/ports.d.ts +36 -6
  60. package/dist/editor/ports.js +10 -1
  61. package/dist/editor/ports.js.map +1 -1
  62. package/dist/editor/project.d.ts +38 -6
  63. package/dist/editor/project.js +167 -27
  64. package/dist/editor/project.js.map +1 -1
  65. package/dist/editor/selection.d.ts +10 -0
  66. package/dist/editor/selection.js +62 -8
  67. package/dist/editor/selection.js.map +1 -1
  68. package/dist/editor/status.js +3 -0
  69. package/dist/editor/status.js.map +1 -1
  70. package/dist/editor/tooltips.d.ts +5 -0
  71. package/dist/editor/tooltips.js +48 -0
  72. package/dist/editor/tooltips.js.map +1 -0
  73. package/dist/editor/view3d.d.ts +17 -0
  74. package/dist/editor/view3d.js +135 -0
  75. package/dist/editor/view3d.js.map +1 -0
  76. package/dist/editor/view3dState.d.ts +39 -0
  77. package/dist/editor/view3dState.js +44 -0
  78. package/dist/editor/view3dState.js.map +1 -0
  79. package/dist/export/dxf.js +1 -1
  80. package/dist/export/dxf.js.map +1 -1
  81. package/dist/export/pdf.js +17 -12
  82. package/dist/export/pdf.js.map +1 -1
  83. package/dist/export/plan.d.ts +23 -6
  84. package/dist/export/plan.js +127 -44
  85. package/dist/export/plan.js.map +1 -1
  86. package/dist/index.d.ts +5 -0
  87. package/dist/index.js +2 -0
  88. package/dist/index.js.map +1 -1
  89. package/dist/model/constraints.js +15 -4
  90. package/dist/model/constraints.js.map +1 -1
  91. package/dist/model/demo.js +3 -3
  92. package/dist/model/demo.js.map +1 -1
  93. package/dist/model/elevation.d.ts +6 -9
  94. package/dist/model/elevation.js +5 -13
  95. package/dist/model/elevation.js.map +1 -1
  96. package/dist/model/faces.d.ts +58 -0
  97. package/dist/model/faces.js +197 -0
  98. package/dist/model/faces.js.map +1 -0
  99. package/dist/model/facesolve.d.ts +72 -0
  100. package/dist/model/facesolve.js +369 -0
  101. package/dist/model/facesolve.js.map +1 -0
  102. package/dist/model/history.d.ts +3 -2
  103. package/dist/model/history.js +17 -11
  104. package/dist/model/history.js.map +1 -1
  105. package/dist/model/images.d.ts +18 -0
  106. package/dist/model/images.js +26 -0
  107. package/dist/model/images.js.map +1 -0
  108. package/dist/model/links.d.ts +46 -0
  109. package/dist/model/links.js +73 -0
  110. package/dist/model/links.js.map +1 -0
  111. package/dist/model/markup.d.ts +46 -0
  112. package/dist/model/markup.js +71 -0
  113. package/dist/model/markup.js.map +1 -0
  114. package/dist/model/measurement.d.ts +11 -0
  115. package/dist/model/measurement.js +24 -0
  116. package/dist/model/measurement.js.map +1 -0
  117. package/dist/model/openings.d.ts +4 -0
  118. package/dist/model/openings.js +4 -0
  119. package/dist/model/openings.js.map +1 -1
  120. package/dist/model/planGeom.d.ts +72 -2
  121. package/dist/model/planGeom.js +184 -10
  122. package/dist/model/planGeom.js.map +1 -1
  123. package/dist/model/project.js +3 -2
  124. package/dist/model/project.js.map +1 -1
  125. package/dist/model/projectfile.js +2 -1
  126. package/dist/model/projectfile.js.map +1 -1
  127. package/dist/model/rooms.js +2 -2
  128. package/dist/model/rooms.js.map +1 -1
  129. package/dist/model/settings.d.ts +6 -0
  130. package/dist/model/settings.js +2 -2
  131. package/dist/model/settings.js.map +1 -1
  132. package/dist/model/sketch.d.ts +14 -0
  133. package/dist/model/sketch.js +143 -24
  134. package/dist/model/sketch.js.map +1 -1
  135. package/dist/model/smooth.d.ts +6 -0
  136. package/dist/model/smooth.js +52 -0
  137. package/dist/model/smooth.js.map +1 -0
  138. package/dist/model/store.d.ts +12 -0
  139. package/dist/model/store.js +35 -3
  140. package/dist/model/store.js.map +1 -1
  141. package/dist/model/types.d.ts +173 -8
  142. package/dist/model/wallfaces.d.ts +32 -0
  143. package/dist/model/wallfaces.js +133 -20
  144. package/dist/model/wallfaces.js.map +1 -1
  145. package/dist/model/wallshape.d.ts +15 -0
  146. package/dist/model/wallshape.js +89 -0
  147. package/dist/model/wallshape.js.map +1 -0
  148. package/dist/react/BottomBar.d.ts +9 -5
  149. package/dist/react/BottomBar.js +213 -24
  150. package/dist/react/BottomBar.js.map +1 -1
  151. package/dist/react/Buttons.d.ts +13 -2
  152. package/dist/react/Buttons.js +37 -5
  153. package/dist/react/Buttons.js.map +1 -1
  154. package/dist/react/CadEditor.d.ts +46 -3
  155. package/dist/react/CadEditor.js +77 -20
  156. package/dist/react/CadEditor.js.map +1 -1
  157. package/dist/react/ConfirmSheet.d.ts +4 -0
  158. package/dist/react/ConfirmSheet.js +31 -0
  159. package/dist/react/ConfirmSheet.js.map +1 -0
  160. package/dist/react/ConflictSheet.d.ts +2 -1
  161. package/dist/react/ConflictSheet.js +16 -8
  162. package/dist/react/ConflictSheet.js.map +1 -1
  163. package/dist/react/Drawer.d.ts +8 -2
  164. package/dist/react/Drawer.js +167 -38
  165. package/dist/react/Drawer.js.map +1 -1
  166. package/dist/react/Duck.d.ts +13 -0
  167. package/dist/react/Duck.js +45 -0
  168. package/dist/react/Duck.js.map +1 -0
  169. package/dist/react/Empty3D.d.ts +2 -0
  170. package/dist/react/Empty3D.js +39 -0
  171. package/dist/react/Empty3D.js.map +1 -0
  172. package/dist/react/FitScroll.d.ts +6 -0
  173. package/dist/react/FitScroll.js +14 -0
  174. package/dist/react/FitScroll.js.map +1 -0
  175. package/dist/react/Icon.native.d.ts +6 -0
  176. package/dist/react/Icon.native.js +4 -0
  177. package/dist/react/Icon.native.js.map +1 -1
  178. package/dist/react/Icon.web.d.ts +6 -0
  179. package/dist/react/Icon.web.js +4 -0
  180. package/dist/react/Icon.web.js.map +1 -1
  181. package/dist/react/KeypadSheet.d.ts +9 -2
  182. package/dist/react/KeypadSheet.js +174 -42
  183. package/dist/react/KeypadSheet.js.map +1 -1
  184. package/dist/react/LaserTray.js +8 -5
  185. package/dist/react/LaserTray.js.map +1 -1
  186. package/dist/react/MarkupPanel.d.ts +8 -0
  187. package/dist/react/MarkupPanel.js +67 -0
  188. package/dist/react/MarkupPanel.js.map +1 -0
  189. package/dist/react/PageThumb.native.d.ts +7 -2
  190. package/dist/react/PageThumb.native.js +19 -7
  191. package/dist/react/PageThumb.native.js.map +1 -1
  192. package/dist/react/PageThumb.web.d.ts +3 -2
  193. package/dist/react/PageThumb.web.js +4 -4
  194. package/dist/react/PageThumb.web.js.map +1 -1
  195. package/dist/react/PlanCanvas.native.d.ts +1 -1
  196. package/dist/react/PlanCanvas.native.js +134 -36
  197. package/dist/react/PlanCanvas.native.js.map +1 -1
  198. package/dist/react/PlanCanvas.web.js +16 -5
  199. package/dist/react/PlanCanvas.web.js.map +1 -1
  200. package/dist/react/Popovers.d.ts +12 -6
  201. package/dist/react/Popovers.js +53 -26
  202. package/dist/react/Popovers.js.map +1 -1
  203. package/dist/react/Rail.d.ts +24 -0
  204. package/dist/react/Rail.js +324 -34
  205. package/dist/react/Rail.js.map +1 -1
  206. package/dist/react/ShapeMenu.d.ts +7 -0
  207. package/dist/react/ShapeMenu.js +58 -0
  208. package/dist/react/ShapeMenu.js.map +1 -0
  209. package/dist/react/Sheet.d.ts +14 -4
  210. package/dist/react/Sheet.js +54 -9
  211. package/dist/react/Sheet.js.map +1 -1
  212. package/dist/react/Slider.d.ts +18 -0
  213. package/dist/react/Slider.js +27 -0
  214. package/dist/react/Slider.js.map +1 -0
  215. package/dist/react/Toast.js +14 -6
  216. package/dist/react/Toast.js.map +1 -1
  217. package/dist/react/ToolTip.d.ts +7 -0
  218. package/dist/react/ToolTip.js +43 -0
  219. package/dist/react/ToolTip.js.map +1 -0
  220. package/dist/react/TopBar.d.ts +6 -3
  221. package/dist/react/TopBar.js +48 -17
  222. package/dist/react/TopBar.js.map +1 -1
  223. package/dist/react/Tween.d.ts +7 -0
  224. package/dist/react/Tween.js +26 -0
  225. package/dist/react/Tween.js.map +1 -0
  226. package/dist/react/Tween.native.d.ts +6 -0
  227. package/dist/react/Tween.native.js +43 -0
  228. package/dist/react/Tween.native.js.map +1 -0
  229. package/dist/react/View3D.native.d.ts +4 -0
  230. package/dist/react/View3D.native.js +103 -0
  231. package/dist/react/View3D.native.js.map +1 -0
  232. package/dist/react/View3D.web.d.ts +4 -0
  233. package/dist/react/View3D.web.js +151 -0
  234. package/dist/react/View3D.web.js.map +1 -0
  235. package/dist/react/View3DHost.d.ts +143 -0
  236. package/dist/react/View3DHost.js +377 -0
  237. package/dist/react/View3DHost.js.map +1 -0
  238. package/dist/react/corners.d.ts +7 -0
  239. package/dist/react/corners.js +51 -0
  240. package/dist/react/corners.js.map +1 -0
  241. package/dist/react/easing.d.ts +15 -0
  242. package/dist/react/easing.js +10 -0
  243. package/dist/react/easing.js.map +1 -0
  244. package/dist/react/host.d.ts +7 -2
  245. package/dist/react/host.js +8 -3
  246. package/dist/react/host.js.map +1 -1
  247. package/dist/react/hostKeypad.d.ts +56 -0
  248. package/dist/react/hostKeypad.js +5 -0
  249. package/dist/react/hostKeypad.js.map +1 -0
  250. package/dist/react/motion.d.ts +77 -0
  251. package/dist/react/motion.js +173 -0
  252. package/dist/react/motion.js.map +1 -0
  253. package/dist/react/ports.js +90 -8
  254. package/dist/react/ports.js.map +1 -1
  255. package/dist/react/saving.d.ts +15 -0
  256. package/dist/react/saving.js +76 -0
  257. package/dist/react/saving.js.map +1 -0
  258. package/dist/react/store.d.ts +38 -1
  259. package/dist/react/store.js +31 -1
  260. package/dist/react/store.js.map +1 -1
  261. package/dist/react/theme.d.ts +10 -0
  262. package/dist/react/theme.js +8 -0
  263. package/dist/react/theme.js.map +1 -1
  264. package/dist/react/topRow.d.ts +22 -0
  265. package/dist/react/topRow.js +61 -0
  266. package/dist/react/topRow.js.map +1 -0
  267. package/dist/react/touch.d.ts +6 -0
  268. package/dist/react/touch.js +9 -0
  269. package/dist/react/touch.js.map +1 -0
  270. package/dist/render/ctx.d.ts +8 -0
  271. package/dist/render/draw.d.ts +33 -1
  272. package/dist/render/draw.js +593 -215
  273. package/dist/render/draw.js.map +1 -1
  274. package/dist/render/elevation.d.ts +65 -43
  275. package/dist/render/elevation.js +414 -140
  276. package/dist/render/elevation.js.map +1 -1
  277. package/dist/render/figmaIcons.d.ts +12 -0
  278. package/dist/render/figmaIcons.js +21 -0
  279. package/dist/render/figmaIcons.js.map +1 -0
  280. package/dist/render/hit.d.ts +22 -2
  281. package/dist/render/hit.js +168 -25
  282. package/dist/render/hit.js.map +1 -1
  283. package/dist/render/icons.js +69 -10
  284. package/dist/render/icons.js.map +1 -1
  285. package/dist/render/linkTile.d.ts +15 -0
  286. package/dist/render/linkTile.js +369 -0
  287. package/dist/render/linkTile.js.map +1 -0
  288. package/dist/render/markup.d.ts +11 -0
  289. package/dist/render/markup.js +112 -0
  290. package/dist/render/markup.js.map +1 -0
  291. package/dist/render/navigate.d.ts +88 -0
  292. package/dist/render/navigate.js +100 -0
  293. package/dist/render/navigate.js.map +1 -0
  294. package/dist/render/snap.d.ts +20 -1
  295. package/dist/render/snap.js +118 -25
  296. package/dist/render/snap.js.map +1 -1
  297. package/dist/render/squircle.d.ts +8 -0
  298. package/dist/render/squircle.js +71 -0
  299. package/dist/render/squircle.js.map +1 -0
  300. package/dist/render/view.d.ts +115 -2
  301. package/dist/render/view.js +244 -19
  302. package/dist/render/view.js.map +1 -1
  303. package/dist/skia/SkiaDrawCtx.d.ts +30 -2
  304. package/dist/skia/SkiaDrawCtx.js +198 -43
  305. package/dist/skia/SkiaDrawCtx.js.map +1 -1
  306. package/dist/skia/host.d.ts +18 -2
  307. package/dist/skia/host.js +46 -1
  308. package/dist/skia/host.js.map +1 -1
  309. package/dist/solver/equations.js +37 -2
  310. package/dist/solver/equations.js.map +1 -1
  311. package/dist/solver/gauss-newton.d.ts +17 -0
  312. package/dist/solver/gauss-newton.js +144 -36
  313. package/dist/solver/gauss-newton.js.map +1 -1
  314. package/dist/solver/linalg.d.ts +45 -2
  315. package/dist/solver/linalg.js +164 -10
  316. package/dist/solver/linalg.js.map +1 -1
  317. package/dist/solver/types.d.ts +5 -0
  318. package/dist/tools/annotate.d.ts +57 -1
  319. package/dist/tools/annotate.js +64 -43
  320. package/dist/tools/annotate.js.map +1 -1
  321. package/dist/tools/chamfer.d.ts +12 -0
  322. package/dist/tools/chamfer.js +114 -0
  323. package/dist/tools/chamfer.js.map +1 -0
  324. package/dist/tools/corner.d.ts +38 -0
  325. package/dist/tools/corner.js +99 -0
  326. package/dist/tools/corner.js.map +1 -0
  327. package/dist/tools/dim.d.ts +86 -9
  328. package/dist/tools/dim.js +581 -96
  329. package/dist/tools/dim.js.map +1 -1
  330. package/dist/tools/elevation.js +1 -1
  331. package/dist/tools/elevation.js.map +1 -1
  332. package/dist/tools/fillet.d.ts +9 -0
  333. package/dist/tools/fillet.js +86 -0
  334. package/dist/tools/fillet.js.map +1 -0
  335. package/dist/tools/freehand.d.ts +3 -2
  336. package/dist/tools/freehand.js +19 -12
  337. package/dist/tools/freehand.js.map +1 -1
  338. package/dist/tools/index.js +14 -4
  339. package/dist/tools/index.js.map +1 -1
  340. package/dist/tools/line.d.ts +8 -3
  341. package/dist/tools/line.js +66 -30
  342. package/dist/tools/line.js.map +1 -1
  343. package/dist/tools/modify.d.ts +13 -0
  344. package/dist/tools/modify.js +105 -25
  345. package/dist/tools/modify.js.map +1 -1
  346. package/dist/tools/openings.js +22 -15
  347. package/dist/tools/openings.js.map +1 -1
  348. package/dist/tools/registry.d.ts +8 -0
  349. package/dist/tools/registry.js +42 -2
  350. package/dist/tools/registry.js.map +1 -1
  351. package/dist/tools/select.d.ts +77 -3
  352. package/dist/tools/select.js +560 -74
  353. package/dist/tools/select.js.map +1 -1
  354. package/dist/tools/shapes.d.ts +14 -0
  355. package/dist/tools/shapes.js +154 -75
  356. package/dist/tools/shapes.js.map +1 -1
  357. package/dist/units/format.d.ts +10 -2
  358. package/dist/units/format.js +18 -3
  359. package/dist/units/format.js.map +1 -1
  360. package/dist/view3d/build.d.ts +35 -0
  361. package/dist/view3d/build.js +630 -0
  362. package/dist/view3d/build.js.map +1 -0
  363. package/dist/view3d/camera.d.ts +60 -0
  364. package/dist/view3d/camera.js +84 -0
  365. package/dist/view3d/camera.js.map +1 -0
  366. package/dist/view3d/fatLines.d.ts +11 -0
  367. package/dist/view3d/fatLines.js +83 -0
  368. package/dist/view3d/fatLines.js.map +1 -0
  369. package/dist/view3d/lines.d.ts +17 -0
  370. package/dist/view3d/lines.js +271 -0
  371. package/dist/view3d/lines.js.map +1 -0
  372. package/dist/view3d/mesh.d.ts +51 -0
  373. package/dist/view3d/mesh.js +101 -0
  374. package/dist/view3d/mesh.js.map +1 -0
  375. package/dist/view3d/poly.d.ts +16 -0
  376. package/dist/view3d/poly.js +109 -0
  377. package/dist/view3d/poly.js.map +1 -0
  378. package/dist/view3d/viewer.d.ts +86 -0
  379. package/dist/view3d/viewer.js +350 -0
  380. package/dist/view3d/viewer.js.map +1 -0
  381. package/package.json +15 -2
  382. package/src/app/edit.ts +83 -12
  383. package/src/app/main.ts +11 -5
  384. package/src/app/state.ts +38 -5
  385. package/src/data/memory.ts +2 -2
  386. package/src/data/provider.ts +15 -7
  387. package/src/data/sync.ts +87 -50
  388. package/src/editor/actions.ts +292 -83
  389. package/src/editor/confirm.ts +58 -0
  390. package/src/editor/elevation.ts +698 -478
  391. package/src/editor/face.ts +227 -0
  392. package/src/editor/files.ts +40 -4
  393. package/src/editor/gestures.ts +147 -31
  394. package/src/editor/keypad.ts +43 -11
  395. package/src/editor/keys.ts +25 -5
  396. package/src/editor/laser.ts +98 -20
  397. package/src/editor/linkActions.ts +194 -0
  398. package/src/editor/linkFollow.ts +43 -0
  399. package/src/editor/linkWrite.ts +77 -0
  400. package/src/editor/links.ts +181 -0
  401. package/src/editor/markup.ts +92 -8
  402. package/src/editor/mode.ts +83 -7
  403. package/src/editor/ports.ts +37 -6
  404. package/src/editor/project.ts +155 -26
  405. package/src/editor/selection.ts +54 -8
  406. package/src/editor/status.ts +2 -0
  407. package/src/editor/tooltips.ts +47 -0
  408. package/src/editor/view3d.ts +119 -0
  409. package/src/editor/view3dState.ts +61 -0
  410. package/src/export/dxf.ts +1 -1
  411. package/src/export/pdf.ts +15 -7
  412. package/src/export/plan.ts +119 -35
  413. package/src/index.ts +5 -0
  414. package/src/input/keyboard.ts +2 -4
  415. package/src/model/constraints.ts +13 -4
  416. package/src/model/demo.ts +3 -3
  417. package/src/model/elevation.ts +6 -16
  418. package/src/model/faces.ts +153 -0
  419. package/src/model/facesolve.ts +322 -0
  420. package/src/model/history.ts +19 -11
  421. package/src/model/images.ts +35 -0
  422. package/src/model/links.ts +77 -0
  423. package/src/model/markup.ts +80 -0
  424. package/src/model/measurement.ts +26 -0
  425. package/src/model/openings.ts +6 -0
  426. package/src/model/planGeom.ts +174 -8
  427. package/src/model/project.ts +3 -2
  428. package/src/model/projectfile.ts +2 -1
  429. package/src/model/rooms.ts +1 -1
  430. package/src/model/settings.ts +8 -2
  431. package/src/model/sketch.ts +101 -14
  432. package/src/model/smooth.ts +51 -0
  433. package/src/model/store.ts +35 -4
  434. package/src/model/types.ts +170 -8
  435. package/src/model/wallfaces.ts +126 -17
  436. package/src/model/wallshape.ts +97 -0
  437. package/src/react/BottomBar.tsx +263 -46
  438. package/src/react/Buttons.tsx +50 -9
  439. package/src/react/CadEditor.tsx +133 -30
  440. package/src/react/ConfirmSheet.tsx +38 -0
  441. package/src/react/ConflictSheet.tsx +19 -12
  442. package/src/react/Drawer.tsx +213 -110
  443. package/src/react/Duck.tsx +50 -0
  444. package/src/react/Empty3D.tsx +32 -0
  445. package/src/react/FitScroll.tsx +19 -0
  446. package/src/react/Icon.native.tsx +5 -0
  447. package/src/react/Icon.web.tsx +5 -0
  448. package/src/react/KeypadSheet.tsx +253 -60
  449. package/src/react/LaserTray.tsx +12 -8
  450. package/src/react/MarkupPanel.tsx +150 -0
  451. package/src/react/PageThumb.native.tsx +18 -7
  452. package/src/react/PageThumb.web.tsx +4 -4
  453. package/src/react/PlanCanvas.native.tsx +151 -34
  454. package/src/react/PlanCanvas.web.tsx +15 -5
  455. package/src/react/Popovers.tsx +116 -51
  456. package/src/react/Rail.tsx +360 -27
  457. package/src/react/ShapeMenu.tsx +66 -0
  458. package/src/react/Sheet.tsx +56 -11
  459. package/src/react/Slider.tsx +48 -0
  460. package/src/react/Toast.tsx +16 -9
  461. package/src/react/ToolTip.tsx +49 -0
  462. package/src/react/TopBar.tsx +97 -39
  463. package/src/react/Tween.native.tsx +36 -0
  464. package/src/react/Tween.tsx +24 -0
  465. package/src/react/View3D.native.tsx +131 -0
  466. package/src/react/View3D.web.tsx +131 -0
  467. package/src/react/View3DHost.ts +367 -0
  468. package/src/react/corners.ts +52 -0
  469. package/src/react/easing.ts +14 -0
  470. package/src/react/host.ts +8 -3
  471. package/src/react/hostKeypad.ts +66 -0
  472. package/src/react/motion.tsx +239 -0
  473. package/src/react/ports.ts +78 -9
  474. package/src/react/saving.ts +80 -0
  475. package/src/react/store.ts +35 -3
  476. package/src/react/theme.ts +8 -0
  477. package/src/react/topRow.ts +71 -0
  478. package/src/react/touch.ts +10 -0
  479. package/src/render/ctx.ts +8 -0
  480. package/src/render/draw.ts +437 -175
  481. package/src/render/elevation.ts +349 -143
  482. package/src/render/figmaIcons.ts +22 -0
  483. package/src/render/hit.ts +140 -21
  484. package/src/render/icons.ts +69 -10
  485. package/src/render/linkTile.ts +297 -0
  486. package/src/render/markup.ts +91 -0
  487. package/src/render/navigate.ts +114 -0
  488. package/src/render/snap.ts +105 -22
  489. package/src/render/squircle.ts +73 -0
  490. package/src/render/view.ts +255 -19
  491. package/src/skia/SkiaDrawCtx.ts +163 -41
  492. package/src/skia/host.ts +46 -1
  493. package/src/solver/equations.ts +37 -2
  494. package/src/solver/gauss-newton.ts +125 -28
  495. package/src/solver/linalg.ts +141 -5
  496. package/src/solver/types.ts +5 -0
  497. package/src/styles.css +91 -42
  498. package/src/tools/annotate.ts +58 -29
  499. package/src/tools/chamfer.ts +103 -0
  500. package/src/tools/corner.ts +99 -0
  501. package/src/tools/dim.ts +524 -92
  502. package/src/tools/elevation.ts +1 -1
  503. package/src/tools/fillet.ts +82 -0
  504. package/src/tools/freehand.ts +20 -16
  505. package/src/tools/index.ts +17 -4
  506. package/src/tools/line.ts +59 -23
  507. package/src/tools/modify.ts +86 -24
  508. package/src/tools/openings.ts +8 -13
  509. package/src/tools/registry.ts +27 -2
  510. package/src/tools/select.ts +424 -75
  511. package/src/tools/shapes.ts +119 -58
  512. package/src/ui/ctx.ts +2 -1
  513. package/src/ui/domPorts.ts +23 -4
  514. package/src/ui/drawer.ts +6 -26
  515. package/src/ui/elevation.ts +10 -101
  516. package/src/ui/keypad.ts +8 -14
  517. package/src/ui/laser.ts +2 -2
  518. package/src/ui/menu.ts +63 -17
  519. package/src/ui/noteinput.ts +3 -3
  520. package/src/ui/opacity.ts +108 -0
  521. package/src/ui/palette.ts +67 -12
  522. package/src/ui/rail.ts +21 -7
  523. package/src/ui/topbar.ts +4 -14
  524. package/src/units/format.ts +18 -3
  525. package/src/view3d/build.ts +607 -0
  526. package/src/view3d/camera.ts +113 -0
  527. package/src/view3d/fatLines.ts +83 -0
  528. package/src/view3d/lines.ts +258 -0
  529. package/src/view3d/mesh.ts +111 -0
  530. package/src/view3d/poly.ts +104 -0
  531. package/src/view3d/viewer.ts +348 -0
  532. package/dist/react/ElevCanvas.native.d.ts +0 -3
  533. package/dist/react/ElevCanvas.native.js +0 -58
  534. package/dist/react/ElevCanvas.native.js.map +0 -1
  535. package/dist/react/ElevCanvas.web.d.ts +0 -4
  536. package/dist/react/ElevCanvas.web.js +0 -44
  537. package/dist/react/ElevCanvas.web.js.map +0 -1
  538. package/dist/react/ElevationSheet.d.ts +0 -2
  539. package/dist/react/ElevationSheet.js +0 -38
  540. package/dist/react/ElevationSheet.js.map +0 -1
  541. package/dist/render/elevationView.d.ts +0 -3
  542. package/dist/render/elevationView.js +0 -100
  543. package/dist/render/elevationView.js.map +0 -1
  544. package/src/react/ElevCanvas.native.tsx +0 -68
  545. package/src/react/ElevCanvas.web.tsx +0 -42
  546. package/src/react/ElevationSheet.tsx +0 -88
  547. package/src/render/elevationView.ts +0 -73
package/src/render/hit.ts CHANGED
@@ -1,14 +1,17 @@
1
- import { ed, isSel, type Hit } from '../app/state';
1
+ import { ed, type Hit } from '../app/state';
2
2
  import { distSeg, hyp, normAng, pointInPoly } from '../model/geom';
3
3
  import { settings } from '../model/settings';
4
4
  import { roomGeom } from '../model/rooms';
5
5
  import { roomValid } from '../model/sketch';
6
6
  import { page, SK } from '../model/store';
7
7
  import { edgePoint } from '../model/openings';
8
+ import { elevOpen, wallBodyAt } from '../editor/elevation';
8
9
  import type { Note, OpeningEdge } from '../model/types';
9
- import { arcAngles, OPENING_TICK_EXT, openingFrame } from '../model/planGeom';
10
- import { FONT } from './theme';
11
- import { cvs, mainT, noteHandles, S, s2w, underlayH, underlayHandles, type Xform } from './view';
10
+ import { cabinetFootprints } from '../model/facesolve';
11
+ import { arcAngles, curveFrame, edgeId, OPENING_TICK_EXT, openingFrame, wallThick } from '../model/planGeom';
12
+ import { noteLook, shapeOutline } from '../model/markup';
13
+ import { smoothPolyline } from '../model/smooth';
14
+ import { leaderPath, linkBox, mainT, noteHandles, noteTextBox, S, s2w, underlayH, underlayHandles, underlayLocal, type Xform } from './view';
12
15
 
13
16
  /** The handle closest to (sx, sy) within `tol` px (small boxes put handles close together; take the nearest, not the first). */
14
17
  function nearestHandle<H extends { x: number; y: number }>(hs: H[], sx: number, sy: number, tol: number): H | null {
@@ -17,35 +20,101 @@ function nearestHandle<H extends { x: number; y: number }>(hs: H[], sx: number,
17
20
  return best;
18
21
  }
19
22
 
23
+ /** Which part of tile `n` screen point sx, sy picks: its card (a little round it), its leader's tip, or along its leader. */
24
+ export function linkHit(T: Xform, n: Note, sx: number, sy: number, tol: number): 'card' | 'tip' | 'leader' | null {
25
+ const b = linkBox(T, n), pad = tol / 2;
26
+ if (sx >= b.x - pad && sx <= b.x + b.s + pad && sy >= b.y - pad && sy <= b.y + b.s + pad) return 'card';
27
+ const lp = leaderPath(T, n, b);
28
+ if (!lp) return null;
29
+ // (its tip, as its handle is: that end alone moves, even before the tile's selected)
30
+ if (hyp(sx - lp[1][0], sy - lp[1][1]) < tol + 2) return 'tip';
31
+ return distSeg({ x: sx, y: sy }, { x: lp[0][0], y: lp[0][1] }, { x: lp[1][0], y: lp[1][1] }) < tol + noteLook(n).width / 2 ? 'leader' : null;
32
+ }
33
+
34
+ /** The link tile under a screen point on the plan, in any mode (a view-only tap opens what it's for); the top one. */
35
+ export function linkAt(sx: number, sy: number, touch = false): (Note & { link: NonNullable<Note['link']> }) | null {
36
+ if (!settings.layers.annot || elevOpen()) return null;
37
+ const sk = SK(), T = mainT(), tol = touch ? 20 : 10;
38
+ for (let i = sk.notes.length - 1; i >= 0; i--) {
39
+ const n = sk.notes[i];
40
+ if (n.type === 'link' && n.link && linkHit(T, n, sx, sy, tol)) return n as Note & { link: NonNullable<Note['link']> };
41
+ }
42
+ return null;
43
+ }
44
+
20
45
  function notePointHit(n: Note, sx: number, sy: number, T: Xform, tol: number): boolean {
46
+ if (n.type === 'link') return !!linkHit(T, n, sx, sy, tol);
21
47
  if (n.type === 'text') {
22
- const [x, y] = S(T, n.x!, n.y!);
23
- cvs.ctx.font = '600 14px ' + FONT;
24
- const w = cvs.ctx.measureText(n.text!).width + 16;
25
- return sx >= x - 4 && sx <= x + w + 4 && sy >= y - 18 && sy <= y + 18;
48
+ const b = noteTextBox(T, n);
49
+ return sx >= b.x - 4 && sx <= b.x + b.w + 4 && sy >= b.y - 4 && sy <= b.y + b.h + 4;
50
+ }
51
+ const outline = shapeOutline(n);
52
+ if (outline) {
53
+ // on its outline (as thick as it's drawn), or anywhere inside it
54
+ const sp = outline.map(p => S(T, p[0], p[1])), reach = tol + noteLook(n).width / 2;
55
+ if (pointInPoly({ x: sx, y: sy }, sp.map(([x, y]) => ({ x, y })))) return true;
56
+ return sp.some(([ax, ay], i) => { const [bx, by] = sp[(i + 1) % sp.length]; return distSeg({ x: sx, y: sy }, { x: ax, y: ay }, { x: bx, y: by }) < reach; });
26
57
  }
27
58
  const pts = n.pts!;
28
59
  if (n.type === 'cloud') {
29
60
  const [x1, y1] = S(T, pts[0][0], pts[0][1]), [x2, y2] = S(T, pts[1][0], pts[1][1]);
30
61
  return sx >= Math.min(x1, x2) - tol && sx <= Math.max(x1, x2) + tol && sy >= Math.min(y1, y2) - tol && sy <= Math.max(y1, y2) + tol;
31
62
  }
32
- for (let i = 1; i < pts.length; i++) {
33
- const [ax, ay] = S(T, pts[i - 1][0], pts[i - 1][1]), [bx, by] = S(T, pts[i][0], pts[i][1]);
34
- if (distSeg({ x: sx, y: sy }, { x: ax, y: ay }, { x: bx, y: by }) < tol) return true;
63
+ // a thick stroke is as easy to hit from its edge as a thin one from its middle; a pen stroke along its curve, as drawn
64
+ const reach = tol + noteLook(n).width / 2, sp = smoothPolyline(pts.map(p => S(T, p[0], p[1])), 0.5);
65
+ for (let i = 1; i < sp.length; i++) {
66
+ const [ax, ay] = sp[i - 1], [bx, by] = sp[i];
67
+ if (distSeg({ x: sx, y: sy }, { x: ax, y: ay }, { x: bx, y: by }) < reach) return true;
35
68
  }
36
69
  return false;
37
70
  }
38
71
 
39
- /** What's under a screen point. Chips win, then points, openings, lines/curves, then room fills. */
40
- export function hitAny(sx: number, sy: number, { touch = false, only = null as string | null } = {}): Hit | null {
72
+ /**
73
+ * The least a wall's thickness can be on screen (px) for its two edges to be picked apart from it: a finger's width,
74
+ * or a mouse's. Thinner, it's picked whole.
75
+ */
76
+ export const EDGE_MIN_PX = { touch: 24, mouse: 12 };
77
+
78
+ /**
79
+ * A wall picked at (sx, sy): one of its edges (faces) when `faces` asks for them, it's wide enough on screen to tell
80
+ * them apart, and the pointer is on the outer quarter of its width either side (or just past its face); otherwise the
81
+ * wall, with the side of its centreline the pointer was on.
82
+ */
83
+ function wallHit(id: string, sx: number, sy: number, touch: boolean, faces: boolean): Hit {
84
+ const sk = SK(), l = sk.lines[id], T = mainT();
85
+ if (l.kind !== 'wall' || l.anchor) return { type: 'line', id };
86
+ const A = sk.points[l.a], B = sk.points[l.b], [wx, wy] = s2w(sx, sy);
87
+ // (how far off its centreline, + to the left of A → B)
88
+ const k = ((B.x - A.x) * (wy - A.y) - (B.y - A.y) * (wx - A.x)) / (hyp(B.x - A.x, B.y - A.y) || 1);
89
+ const side: 1 | -1 = k >= 0 ? 1 : -1;
90
+ if (faces && !l.constr && l.thick * T.s >= (touch ? EDGE_MIN_PX.touch : EDGE_MIN_PX.mouse) && Math.abs(k) >= l.thick / 4) return { type: 'wface', id: edgeId(id, side) };
91
+ return { type: 'line', id, side };
92
+ }
93
+
94
+ /** A curved wall picked at (sx, sy): its outer (+1) or inner (−1) edge as wallHit picks a straight wall's, or the wall. */
95
+ function curveHit(type: 'circle' | 'arc', id: string, sx: number, sy: number, touch: boolean, faces: boolean): Hit {
96
+ const sk = SK(), T = mainT(), w = sk.circles[id] ?? sk.arcs[id], f = curveFrame(sk, id);
97
+ if (!w || !f || w.kind !== 'wall') return { type, id };
98
+ // (how far off its centreline, + outside it)
99
+ const [wx, wy] = s2w(sx, sy), k = hyp(wx - f.o.x, wy - f.o.y) - f.r, side: 1 | -1 = k >= 0 ? 1 : -1, t = wallThick(w);
100
+ if (faces && !w.constr && t * T.s >= (touch ? EDGE_MIN_PX.touch : EDGE_MIN_PX.mouse) && Math.abs(k) >= t / 4) return { type: 'wface', id: edgeId(id, side) };
101
+ return { type, id, side };
102
+ }
103
+
104
+ /**
105
+ * What's under a screen point. Chips win, then points, openings, lines/curves, then room fills. `faces`: a wall's
106
+ * edges can be picked on their own (see wallHit).
107
+ */
108
+ export function hitAny(sx: number, sy: number, { touch = false, only = null as string | null, faces = false } = {}): Hit | null {
41
109
  const sk = SK(), T = mainT(), tol = touch ? 20 : 10;
42
110
  if (ed.mode === 'annotate') {
43
111
  // image underlay (annotate mode only, so it never gets in the way of drafting):
44
112
  // handles of the selected image first, then markup on top of it, then the image itself
45
- const u = page().underlay, showU = !!u && settings.layers.underlay;
46
- if (showU && !u!.locked && !only && isSel('underlay', 'u')) {
47
- const hd = nearestHandle(underlayHandles(T, u!), sx, sy, tol + 4);
48
- if (hd) return { type: 'uhandle', id: 'u', part: hd.part };
113
+ const ims = settings.layers.underlay ? page().underlays : [];
114
+ const selIm = ed.sel.length === 1 && ed.sel[0].type === 'underlay' ? ims.find(u => u.id === ed.sel[0].id) : undefined;
115
+ if (selIm && !selIm.locked && !only) {
116
+ const hd = nearestHandle(underlayHandles(T, selIm), sx, sy, tol + 4);
117
+ if (hd) return { type: 'uhandle', id: selIm.id, part: hd.part };
49
118
  }
50
119
  // handles of the one selected arrow / cloud / pen stroke
51
120
  if (!only && settings.layers.annot && ed.sel.length === 1 && ed.sel[0].type === 'note') {
@@ -53,10 +122,20 @@ export function hitAny(sx: number, sy: number, { touch = false, only = null as s
53
122
  const hd = n && nearestHandle(noteHandles(T, n), sx, sy, tol + 4);
54
123
  if (hd) return { type: 'nhandle', id: n!.id, part: hd.part };
55
124
  }
56
- for (let i = sk.notes.length - 1; i >= 0; i--) if (notePointHit(sk.notes[i], sx, sy, T, tol)) return { type: 'note', id: sk.notes[i].id };
57
- if (showU && !only) {
125
+ for (let i = sk.notes.length - 1; i >= 0; i--) {
126
+ const n = sk.notes[i];
127
+ // (a link's tile: which part, as dragging it moves the card, its leader's tip, or the two together)
128
+ if (n.type === 'link') { const part = linkHit(T, n, sx, sy, tol); if (part) return part === 'card' ? { type: 'note', id: n.id } : { type: 'note', id: n.id, part }; continue; }
129
+ if (notePointHit(n, sx, sy, T, tol)) return { type: 'note', id: n.id };
130
+ }
131
+ if (!only) {
132
+ // the topmost image under the point
58
133
  const [wx, wy] = s2w(sx, sy);
59
- if (wx >= u!.x && wx <= u!.x + u!.w && wy <= u!.y && wy >= u!.y - underlayH(u!)) return { type: 'underlay', id: 'u' };
134
+ for (let i = ims.length - 1; i >= 0; i--) {
135
+ // (in its own frame: a turned image is tapped where it's drawn)
136
+ const u = ims[i], q = underlayLocal(u, wx, wy);
137
+ if (Math.abs(q.x) <= u.w / 2 && Math.abs(q.y) <= underlayH(u) / 2) return { type: 'underlay', id: u.id };
138
+ }
60
139
  }
61
140
  return null;
62
141
  }
@@ -70,11 +149,13 @@ export function hitAny(sx: number, sy: number, { touch = false, only = null as s
70
149
  if (h.kind === 'cons') return { type: 'cons', id: h.id };
71
150
  if (h.kind === 'odim') return { type: 'odim', id: h.id, part: h.part };
72
151
  if (h.kind === 'room') return { type: 'room', id: h.id };
152
+ if (h.kind === 'elev') return { type: 'elev', id: h.id };
73
153
  }
74
154
  }
75
155
  }
76
156
  let best: { type: Hit['type']; id: string; d: number } | null = null;
77
157
  const consider = (type: Hit['type'], id: string, d: number) => { if (d < tol && (!best || d < best.d)) best = { type, id, d }; };
158
+ // a cabinet's corners can be picked, like a window's (to dimension or constrain to; dragging one moves the cabinet)
78
159
  for (const id in sk.points) { const p = sk.points[id]; const [x, y] = S(T, p.x, p.y); consider('point', id, hyp(x - sx, y - sy) - 4); }
79
160
  if (best) return { type: (best as { type: Hit['type'] }).type, id: (best as { id: string }).id };
80
161
  // door/window edge anchors behave like points for geometry picks (the dimension tool)
@@ -90,6 +171,22 @@ export function hitAny(sx: number, sy: number, { touch = false, only = null as s
90
171
  }
91
172
  if (bestA) return { type: 'oanchor', id: bestA.id, part: bestA.edge };
92
173
  }
174
+ // the ends of a door or window that's picked (or has an end picked): pickable on their own — not before, so a
175
+ // first tap near an end still grabs the door or window itself
176
+ if (!only) {
177
+ let bestE: { id: string; edge: OpeningEdge; d: number } | null = null;
178
+ for (const id in sk.openings) {
179
+ const shown = ed.sel.some(x => (x.type === 'opening' && x.id === id) || (x.type === 'oanchor' && x.id.startsWith(id + '|')));
180
+ if (!shown) continue;
181
+ for (const edge of ['s0', 's1'] as const) {
182
+ const p = edgePoint(sk, id, edge);
183
+ if (!p) continue;
184
+ const [x, y] = S(T, p.x, p.y), d = hyp(x - sx, y - sy) - 4;
185
+ if (d < tol && (!bestE || d < bestE.d)) bestE = { id, edge, d };
186
+ }
187
+ }
188
+ if (bestE) return { type: 'oanchor', id: bestE.id, part: bestE.edge };
189
+ }
93
190
  // openings: anywhere over the span (plus a margin), out to the jamb ticks across the wall
94
191
  if (!only) {
95
192
  for (const id in sk.openings) {
@@ -104,6 +201,7 @@ export function hitAny(sx: number, sy: number, { touch = false, only = null as s
104
201
  }
105
202
  for (const id in sk.lines) {
106
203
  const l = sk.lines[id];
204
+ if (l.anchor || (l.cab && !only)) continue; // a wall face's edges from the plan: after what's drawn on it
107
205
  if (l.constr && !settings.layers.construction) continue;
108
206
  const A = sk.points[l.a], B = sk.points[l.b];
109
207
  const [ax, ay] = S(T, A.x, A.y), [bx, by] = S(T, B.x, B.y);
@@ -125,7 +223,28 @@ export function hitAny(sx: number, sy: number, { touch = false, only = null as s
125
223
  const tw = sk.arcs[id].kind === 'wall' ? Math.max(0, ((sk.arcs[id].thick || 4.5) * T.s) / 2 - tol / 2) : 0;
126
224
  if (at <= sweep) consider('arc', id, Math.abs(hyp(x - sx, y - sy) - g.r * T.s) - tw);
127
225
  }
128
- if (best) return { type: (best as { type: Hit['type'] }).type, id: (best as { id: string }).id };
226
+ if (best) {
227
+ const b = best as { type: Hit['type']; id: string };
228
+ if (b.type === 'line') return wallHit(b.id, sx, sy, touch, faces);
229
+ return b.type === 'circle' || b.type === 'arc' ? curveHit(b.type, b.id, sx, sy, touch, faces) : { type: b.type, id: b.id };
230
+ }
231
+ if (elevOpen()) {
232
+ // the wall view: a cabinet or a door/window under the pointer, then the plan's edges (floor, ceiling, corners, openings' sides)
233
+ if (!only) { const [wx, wy] = s2w(sx, sy), b = wallBodyAt(wx, wy, tol / T.s); if (b) return b; }
234
+ for (const id in sk.lines) {
235
+ const l = sk.lines[id];
236
+ if (!l.anchor && !l.cab) continue; // (and a cabinet's edges, as a window's)
237
+ const A = sk.points[l.a], B = sk.points[l.b], [ax, ay] = S(T, A.x, A.y), [bx, by] = S(T, B.x, B.y);
238
+ consider('line', id, distSeg({ x: sx, y: sy }, { x: ax, y: ay }, { x: bx, y: by }));
239
+ }
240
+ if (best) return { type: (best as { type: Hit['type'] }).type, id: (best as { id: string }).id };
241
+ return null;
242
+ }
243
+ // a cabinet's footprint (the plan only shows it: tapping it opens its wall)
244
+ if (!only && settings.layers.cabinets) {
245
+ const [wx, wy] = s2w(sx, sy);
246
+ for (const fp of cabinetFootprints(sk)) if (pointInPoly({ x: wx, y: wy }, fp.pts)) return { type: 'cabfoot', id: fp.key + '#' + fp.id };
247
+ }
129
248
  if (!only && settings.layers.rooms) {
130
249
  const [wx, wy] = s2w(sx, sy);
131
250
  for (const id in sk.rooms) {
@@ -2,15 +2,21 @@
2
2
  export const IC: Record<string, string> = {
3
3
  select: '<path d="M6 3.5l12.5 7.2-5.6 1.4-2.6 5.4z"/>',
4
4
  line: '<path d="M6.6 17.4L17.4 6.6"/><circle cx="5" cy="19" r="2"/><circle cx="19" cy="5" r="2"/>',
5
- freehand: '<path d="M3 7.5c1.6-3 3.4-3 5 0s3.4 3 5 0 3.4-3 5 0"/><path d="M12 11v3M10.5 12.5L12 14l1.5-1.5" stroke-width="1.6"/><path d="M3 20l5-4 5 3 6-5"/>',
6
- wall: '<path d="M3 8.5h18M3 15.5h18M3 8.5v7M21 8.5v7"/>',
5
+ // a freehand squiggle beside a pen nib (a stroke made into a shape)
6
+ freehand: '<path d="M3.6 2c1.8 2 2.6 4 2.2 6.2-.4 2.2-2.6 4.4-2.9 6.8-.2 1.8.4 3.2 1.8 4.4"/><path d="M7.2 20.4l1.9-9.9 5.1-.9 4.6 4.4-.9 4.6z"/><path d="M14.2 9.6l2.2-3.3M18.8 14l3.6-2M7.2 20.4l5.2-4.4"/>',
7
+ // a corner rounded off (Figma 2523:101119)
8
+ fillet: '<path d="M2 22V12.91C2 6.88 6.88 2 12.91 2H22"/>',
9
+ // a corner cut off straight, its corners sharp (Figma 2523:101121)
10
+ chamfer: '<path d="M2 22V11.79L9.45 2H22" stroke-linejoin="miter"/>',
11
+ // a corner of wall as drawn in plan: an L-shaped band, hatched (not a box, so it isn't taken for the Rectangle)
12
+ wall: '<path d="M4 20V4h16v5H9v11z"/><path d="M4 16.5l5-5M4 10.5L10.5 4M12.5 9l5-5" stroke-width="1.3"/>',
7
13
  rect: '<rect x="4.5" y="6" width="15" height="12" rx="1"/>',
8
14
  circle: '<circle cx="12" cy="12" r="7.5"/><circle cx="12" cy="12" r="1" fill="currentColor"/>',
9
- arc: '<path d="M4.5 17a8.5 8.5 0 0 1 15 0"/><circle cx="4.5" cy="17" r="1.6"/><circle cx="19.5" cy="17" r="1.6"/>',
15
+ arc: '<path d="M4.5 13.5a8.5 8.5 0 0 1 15 0"/><circle cx="4.5" cy="13.5" r="1.6"/><circle cx="19.5" cy="13.5" r="1.6"/>', // (centred in the box: y 9–15)
10
16
  dim: '<path d="M4 7v10M20 7v10M4 12h16M7.5 9.5L4.5 12l3 2.5M16.5 9.5l3 2.5-3 2.5"/>',
11
17
  trim: '<circle cx="6.5" cy="7" r="2.6"/><circle cx="6.5" cy="17" r="2.6"/><path d="M8.6 8.6L20 18M8.6 15.4L20 6"/>',
12
18
  offset: '<path d="M4 15L15 4M9 20L20 9"/><path d="M11 9l2.5 2.5"/>',
13
- split: '<path d="M3 12h6.5M14.5 12H21"/><circle cx="12" cy="12" r="2.2" fill="currentColor"/><path d="M12 4.5v3M12 16.5v3"/>',
19
+ split: '<path d="M3 12H9.5M14.5 12H21"/><path d="M12 14.1969C13.2151 14.1969 14.2 13.2119 14.2 11.9969C14.2 10.7818 13.2151 9.79688 12 9.79688C10.785 9.79688 9.80005 10.7818 9.80005 11.9969C9.80005 13.2119 10.785 14.1969 12 14.1969Z" fill="currentColor"/><path d="M12 4V7M12 17V20"/>',
14
20
  opening: '<path d="M5 20V6"/><path d="M5 6a14 14 0 0 1 14 14"/><path d="M3 20h18"/>',
15
21
  room: '<path d="M4 5h9v6h7v8H4z"/>',
16
22
  constr: '<path d="M5 19L19 5" stroke-dasharray="2.5 3"/>',
@@ -18,7 +24,13 @@ export const IC: Record<string, string> = {
18
24
  redo: '<path d="M15 14l5-5-5-5"/><path d="M20 9H9.5a5.5 5.5 0 0 0 0 11H13"/>',
19
25
  pen: '<path d="M4 20l1-4.5L16 4.5l3.5 3.5L8.5 19z"/><path d="M13.5 7l3.5 3.5"/>',
20
26
  arrow: '<path d="M5 19L18 6"/><path d="M10 6h8v8"/>',
21
- image: '<rect x="3.5" y="5" width="13" height="13" rx="1.5"/><path d="M3.5 15l4-4 5 5"/><path d="M19 3v6M16 6h6"/>',
27
+ // the markup shapes beside Arrow (its Line drawn as Draft's)
28
+ mline: '<path d="M6.6 17.4L17.4 6.6"/><circle cx="5" cy="19" r="2"/><circle cx="19" cy="5" r="2"/>',
29
+ mrect: '<rect x="4.5" y="6" width="15" height="12" rx="1"/>',
30
+ mtri: '<path d="M12 4.5L20.5 19h-17z" stroke-linejoin="round"/>',
31
+ mcircle: '<circle cx="12" cy="12" r="7.5"/>',
32
+ // BOLDR's annotation editors' Add image (Lucide's image-plus)
33
+ image: '<path d="M16 5h6"/><path d="M19 2v6"/><path d="M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/><circle cx="9" cy="9" r="2"/>',
22
34
  text: '<path d="M5 6h14M12 6v13M9 19h6"/>',
23
35
  cloud: '<path d="M7 18a3 3 0 0 1-.4-6A4.5 4.5 0 0 1 15 9.6 3.5 3.5 0 1 1 17.5 18z"/>',
24
36
  calib: '<path d="M3 15l12-12 6 6-12 12z"/><path d="M7 11l2 2M10 8l2 2M13 5l2 2"/>',
@@ -31,17 +43,27 @@ export const IC: Record<string, string> = {
31
43
  eyeoff: '<path d="M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12z"/><circle cx="12" cy="12" r="2.8"/><path d="M4 20L20 4"/>',
32
44
  auto: '<path d="M12 3l1.8 4.6L18.5 9l-4.7 1.6L12 15l-1.8-4.4L5.5 9l4.7-1.4z"/><path d="M18 15l.8 2 2 .8-2 .8-.8 2-.8-2-2-.8 2-.8z"/>',
33
45
  layers: '<path d="M12 3l9 5-9 5-9-5z"/><path d="M3 13l9 5 9-5"/>',
46
+ // a plan sheet unrolling from its roll, rooms drawn on it (the pages and spaces)
47
+ spaces: '<path d="M10 5.50353H21V20.5035H6.1C5.14522 20.5035 4.22955 20.1242 3.55442 19.4491C2.87928 18.774 2.5 17.8583 2.5 16.9035M2.5 16.9035V5.50353C2.5 5.50353 2.5 3 5 3C7.5 3 7.5 5.00353 7.5 5.00353V16.0035C7.5 16.0035 6.99996 14.5 4.99996 14.5C2.5 14.5 2.5 16.9035 2.5 16.9035Z"/><path stroke-width="1" d="M14.0188 9L14.0188 11.2622M14.0188 14.7405V16.9144M10.2797 13H12.2797M15.758 13H17.7579M10.2797 9H17.7579V17H10.2797V9Z"/>',
34
48
  back: '<path d="M15 4.5L7.5 12l7.5 7.5"/>',
49
+ // a turn clockwise (Lucide's rotate-cw): how far an image is turned
50
+ rotate: '<path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/>',
51
+ // a circle half filled: how see-through
52
+ opacity: '<circle cx="12" cy="12" r="8"/><path d="M12 4a8 8 0 0 1 0 16z" fill="currentColor" stroke="none"/>',
53
+ // two overlapping sheets: the front one solid (bring to front), or the back one (send to back)
54
+ tofront: '<path d="M13 3.5H5C4.17157 3.5 3.5 4.17157 3.5 5V13C3.5 13.8284 4.17157 14.5 5 14.5H13C13.8284 14.5 14.5 13.8284 14.5 13V5C14.5 4.17157 13.8284 3.5 13 3.5Z" stroke-width="1.5" stroke-dasharray="2.75 2.5"/><path d="M19 9.5H11C10.1716 9.5 9.5 10.1716 9.5 11V19C9.5 19.8284 10.1716 20.5 11 20.5H19C19.8284 20.5 20.5 19.8284 20.5 19V11C20.5 10.1716 19.8284 9.5 19 9.5Z" fill="currentColor" fill-opacity="0.35"/>',
55
+ toback: '<path d="M19 9.5H11C10.1716 9.5 9.5 10.1716 9.5 11V19C9.5 19.8284 10.1716 20.5 11 20.5H19C19.8284 20.5 20.5 19.8284 20.5 19V11C20.5 10.1716 19.8284 9.5 19 9.5Z" stroke-width="1.5" stroke-dasharray="2.75 2.5"/><path d="M13 3.5H5C4.17157 3.5 3.5 4.17157 3.5 5V13C3.5 13.8284 4.17157 14.5 5 14.5H13C13.8284 14.5 14.5 13.8284 14.5 13V5C14.5 4.17157 13.8284 3.5 13 3.5Z" fill="currentColor" fill-opacity="0.35"/>',
35
56
  share: '<circle cx="6" cy="12" r="2.4"/><circle cx="18" cy="6" r="2.4"/><circle cx="18" cy="18" r="2.4"/><path d="M8.2 10.9l7.6-3.8M8.2 13.1l7.6 3.8"/>',
36
57
  dots: '<circle cx="5" cy="12" r="1.6" fill="currentColor"/><circle cx="12" cy="12" r="1.6" fill="currentColor"/><circle cx="19" cy="12" r="1.6" fill="currentColor"/>',
37
- save: '<path d="M5 4h11l3 3v13H5z"/><path d="M8 4v5h7V4M8 20v-6h8v6"/>',
58
+ // BOLDR's save (Figma 2247:138414): a filled disk, the full 24 box
59
+ save: '<path transform="translate(-25.5 -12.5)" fill="currentColor" stroke="none" d="M44.0271 12.5H27.374C26.3412 12.5 25.5 13.3412 25.5 14.374V34.626C25.5 35.6588 26.3305 36.5 27.374 36.5H47.626C48.6588 36.5 49.5 35.6695 49.5 34.626V17.9729L44.0271 12.5ZM37.5 33.1886C35.4024 33.1886 33.6988 31.4849 33.6988 29.3873C33.6988 27.2897 35.4024 25.5861 37.5 25.5861C39.5976 25.5861 41.3012 27.2897 41.3012 29.3873C41.3012 31.4849 39.5976 33.1886 37.5 33.1886ZM41.4184 20.2622H29.4503V15.8434H41.4184V20.2622Z"/>',
38
60
  bt: '<path d="M7 18H6a5 5 0 0 1-.6-10A7 7 0 0 1 18.5 6.6 5.5 5.5 0 0 1 18.5 18H17"/><path d="M9.5 11l5 4-2.5 2V8.5l2.5 2-5 4"/>',
39
61
  h: '<path d="M4 12h16"/><circle cx="4" cy="12" r="1.8" fill="currentColor"/><circle cx="20" cy="12" r="1.8" fill="currentColor"/>',
40
62
  v: '<path d="M12 4v16"/><circle cx="12" cy="4" r="1.8" fill="currentColor"/><circle cx="12" cy="20" r="1.8" fill="currentColor"/>',
41
63
  par: '<path d="M5 18L13 6M11 18L19 6"/>',
42
- perp: '<path d="M4 19h16M10 19V5"/><path d="M10 15h4v4"/>',
64
+ perp: '<path d="M4 19H20M10 19V5"/><path d="M10 14H15V19"/>',
43
65
  tan: '<circle cx="12" cy="14" r="6"/><path d="M3 8h18"/>',
44
- col: '<path d="M3 20l6-6M15 8l6-6"/><path d="M10.5 12.5l3-3" stroke-dasharray="1.5 2"/>',
66
+ col: '<path d="M3 20L8.5 14.5M15.5 7.5L21 2"/><path d="M10.5 12.5L13.5 9.5" stroke-dasharray="1.5 2"/>',
45
67
  eq: '<path d="M5 9h14M5 15h14"/>',
46
68
  mid: '<path d="M3.5 17L20.5 7"/><circle cx="12" cy="12" r="2.6" fill="currentColor"/>',
47
69
  online: '<path d="M3.5 17L20.5 7"/><circle cx="15.5" cy="9.6" r="2.4"/>',
@@ -50,11 +72,33 @@ export const IC: Record<string, string> = {
50
72
  unlock: '<rect x="5.5" y="10.5" width="13" height="9.5" rx="2"/><path d="M8.5 10.5V8a3.5 3.5 0 0 1 6.8-1.2"/>',
51
73
  angle: '<path d="M4 19h16M4 19L15 5"/><path d="M10.5 19a6.5 6.5 0 0 0-2.6-5.2"/>',
52
74
  diam: '<circle cx="12" cy="12" r="7.5"/><path d="M6.7 17.3L17.3 6.7"/>',
53
- merge: '<circle cx="6" cy="12" r="2.2"/><circle cx="18" cy="12" r="2.2"/><path d="M9 12h6M12.5 9.5L15 12l-2.5 2.5"/>',
75
+ merge: '<path d="M4.2 14.1969C5.41503 14.1969 6.4 13.2119 6.4 11.9969C6.4 10.7818 5.41503 9.79688 4.2 9.79688C2.98497 9.79688 2 10.7818 2 11.9969C2 13.2119 2.98497 14.1969 4.2 14.1969Z"/><path d="M18 14.1969C19.2151 14.1969 20.2 13.2119 20.2 11.9969C20.2 10.7818 19.2151 9.79688 18 9.79688C16.785 9.79688 15.8 10.7818 15.8 11.9969C15.8 13.2119 16.785 14.1969 18 14.1969Z"/><path d="M6.5 12H14.5M12 14.5L14.5 12L12 9.5" stroke-width="1.5"/>',
54
76
  chain: '<path d="M9 7H6a5 5 0 0 0 0 10h3M15 7h3a5 5 0 0 1 0 10h-3M8 12h8"/>',
55
77
  thick: '<path d="M3 7h18M3 17h18"/><path d="M12 9.5v5M10.3 11l1.7-1.7 1.7 1.7M10.3 13l1.7 1.7 1.7-1.7"/>',
78
+ // a wall's length measured on its face on top, at the bottom, left or right (as the page shows the wall), or along its
79
+ // centerline (a level wall's, a plumb one's): a wall dimension's choices
80
+ faceT: '<path d="M3 16h18" stroke-width="1.3"/><path d="M3 8h18M6 5.5L3 8l3 2.5M18 5.5L21 8l-3 2.5"/>',
81
+ faceB: '<path d="M3 8h18" stroke-width="1.3"/><path d="M3 16h18M6 13.5L3 16l3 2.5M18 13.5L21 16l-3 2.5"/>',
82
+ faceL: '<path d="M16 3v18" stroke-width="1.3"/><path d="M8 3v18M5.5 6L8 3l2.5 3M5.5 18L8 21l2.5-3"/>',
83
+ faceR: '<path d="M8 3v18" stroke-width="1.3"/><path d="M16 3v18M13.5 6L16 3l2.5 3M13.5 18L16 21l2.5-3"/>',
84
+ faceMidH: '<path d="M3 6h18M3 18h18" stroke-width="1.3"/><path d="M3 12h18M6 9.5L3 12l3 2.5M18 9.5L21 12l-3 2.5"/>',
85
+ faceMidV: '<path d="M6 3v18M18 3v18" stroke-width="1.3"/><path d="M12 3v18M9.5 6L12 3l2.5 3M9.5 18L12 21l2.5-3"/>',
86
+ // the distance between two walls (plumb ones; H: level): between their faces toward each other, their centerlines,
87
+ // their far faces
88
+ spanIn: '<path d="M2.5 4v16M7 4v16M17 4v16M21.5 4v16" stroke-width="1.3"/><path d="M7 12h10M9.5 9.5L7 12l2.5 2.5M14.5 9.5L17 12l-2.5 2.5"/>',
89
+ spanMid: '<path d="M2.5 4v16M7 4v16M17 4v16M21.5 4v16" stroke-width="1.3"/><path d="M4.75 4v16M19.25 4v16" stroke-width="1" stroke-dasharray="1.5 2"/><path d="M4.75 12h14.5M7.25 9.5L4.75 12l2.5 2.5M16.75 9.5l2.5 2.5-2.5 2.5"/>',
90
+ spanOut: '<path d="M2.5 3v12M7 3v12M17 3v12M21.5 3v12" stroke-width="1.3"/><path d="M2.5 19.5h19M5 17L2.5 19.5 5 22M19 17l2.5 2.5L19 22"/>',
91
+ spanInH: '<path d="M4 2.5h16M4 7h16M4 17h16M4 21.5h16" stroke-width="1.3"/><path d="M12 7v10M9.5 9.5L12 7l2.5 2.5M9.5 14.5L12 17l2.5-2.5"/>',
92
+ spanMidH: '<path d="M4 2.5h16M4 7h16M4 17h16M4 21.5h16" stroke-width="1.3"/><path d="M4 4.75h16M4 19.25h16" stroke-width="1" stroke-dasharray="1.5 2"/><path d="M12 4.75v14.5M9.5 7.25L12 4.75l2.5 2.5M9.5 16.75l2.5 2.5 2.5-2.5"/>',
93
+ spanOutH: '<path d="M3 2.5h12M3 7h12M3 17h12M3 21.5h12" stroke-width="1.3"/><path d="M19.5 2.5v19M17 5L19.5 2.5 22 5M17 19l2.5 2.5L22 19"/>',
94
+ // a curved wall's diameter across its inner face, its centerline, its outer face
95
+ ringIn: '<circle cx="12" cy="12" r="5.5" stroke-width="1.3"/><circle cx="12" cy="12" r="9.5" stroke-width="1.3"/><path d="M6.5 12h11M9 9.5L6.5 12 9 14.5M15 9.5l2.5 2.5L15 14.5"/>',
96
+ ringMid: '<circle cx="12" cy="12" r="5.5" stroke-width="1.3"/><circle cx="12" cy="12" r="9.5" stroke-width="1.3"/><circle cx="12" cy="12" r="7.5" stroke-width="1" stroke-dasharray="1.5 2"/><path d="M4.5 12h15M7 9.5L4.5 12 7 14.5M17 9.5l2.5 2.5L17 14.5"/>',
97
+ ringOut: '<circle cx="12" cy="12" r="5.5" stroke-width="1.3"/><circle cx="12" cy="12" r="9.5" stroke-width="1.3"/><path d="M2.5 12h19M5 9.5L2.5 12 5 14.5M19 9.5l2.5 2.5L19 14.5"/>',
56
98
  flip: '<path d="M12 3v18"/><path d="M8 7L3 12l5 5zM16 7l5 5-5 5z"/>',
57
99
  ref: '<path d="M8 4a12 12 0 0 0 0 16M16 4a12 12 0 0 1 0 16"/>',
100
+ hline: '<path d="M3 13h18"/><path d="M3 20h18" stroke-dasharray="2 3"/><path d="M17 4v6M15 8l2 2 2-2"/>',
101
+ cabinet: '<rect x="4" y="6" width="16" height="14" rx="1"/><path d="M12 6v14M10 11v3M14 11v3M3 20h18"/>',
58
102
  window: '<path d="M2.5 8.5v7M21.5 8.5v7M2.5 12h3M18.5 12h3"/><path d="M5.5 10h13M5.5 14h13M5.5 8.5v7M18.5 8.5v7"/>',
59
103
  door: '<path d="M5 20V6"/><path d="M5 6a14 14 0 0 1 14 14"/><path d="M3 20h18"/>',
60
104
  convert: '<path d="M4 17c3-6 4.5 1 7.5-4.5S16 9 20 6"/><path d="M4 21h16" stroke-dasharray="3 2.5"/>',
@@ -64,9 +108,24 @@ export const IC: Record<string, string> = {
64
108
  close: '<path d="M6 6l12 12M18 6L6 18"/>',
65
109
  closeShape: '<path d="M5 18V6h12"/><path d="M17 6l2 12H5" stroke-dasharray="2 2.5"/>',
66
110
  width: '<path d="M3 8v8M21 8v8M3 12h18M6 9.5L3.5 12 6 14.5M18 9.5l2.5 2.5-2.5 2.5"/>',
67
- elev: '<path d="M3 20h18"/><rect x="4.5" y="5" width="15" height="15"/><rect x="7.5" y="11" width="4" height="9"/><rect x="13.5" y="8.5" width="3.5" height="4"/>',
111
+ elev: '<path d="M2 20L22 20"/><path d="M20 5H4V20H20V5Z"/><path d="M11.5 11H7.5V20H11.5V11Z" stroke-width="1"/><path d="M17 9H14V13H17V9Z" stroke-width="1"/>',
68
112
  conc: '<circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="3.5"/>',
69
113
  color: '<circle cx="12" cy="12" r="7" fill="currentColor"/>',
114
+ // links: open what a tile is for (Lucide's external-link); a tile's leader (a card, its line out to an arrowhead);
115
+ // a measurement linked to a dimension, and let go of (Lucide's link and unlink); saved to the drawing's group
116
+ // (Lucide's folder-plus)
117
+ open: '<path d="M15 3h6v6"/><path d="M10 14L21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',
118
+ leader: '<rect x="3" y="3" width="8.5" height="8.5" rx="2"/><path d="M11.5 11.5L20 20"/><path d="M14.5 20H20v-5.5"/>',
119
+ link: '<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>',
120
+ unlink: '<path d="M18.84 12.25l1.72-1.71a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M5.17 11.75l-1.71 1.71a5 5 0 0 0 7.07 7.07l1.71-1.71"/><path d="M8 2v3M2 8h3M16 19v3M19 16h3"/>',
121
+ // the link tiles' size (Lucide's scaling)
122
+ tilesize: '<path d="M21 3L9 15"/><path d="M12 3H3v18h18v-9"/><path d="M16 3h5v5"/><path d="M14 15H9v-5"/>',
123
+ savegroup: '<path d="M12 10v6M9 13h6"/><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z"/>',
124
+ // the 3D tab's rail: the corner view (a block seen from a corner), from above (the block, its top filled in), cut away
125
+ // (a room whose front walls are low)
126
+ home3d: '<path d="M12 3l8 4.5v9L12 21l-8-4.5v-9z"/><path d="M4 7.5L12 12l8-4.5M12 12v9"/>',
127
+ top3d: '<path d="M12 3l8 4.5v9L12 21l-8-4.5v-9z"/><path d="M4 7.5L12 12l8-4.5M12 12v9"/><path d="M12 3l8 4.5-8 4.5-8-4.5z" fill="currentColor" fill-opacity="0.55"/>',
128
+ cutaway: '<path d="M3.5 14.5V6.5L12 2l8.5 4.5v8"/><path d="M12 2v8L3.5 14.5M12 10l8.5 4.5" stroke-width="1.5"/><path d="M3.5 12.5L12 17l8.5-4.5M3.5 14.5L12 19l8.5-4.5M12 17v2"/>',
70
129
  };
71
130
 
72
131
  export const icon = (k: string, s = 24): string =>