@reekon-tools/boldr-cad 0.1.0 → 1.1.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.
- package/README.md +99 -16
- package/dist/app/edit.d.ts +12 -1
- package/dist/app/edit.js +96 -11
- package/dist/app/edit.js.map +1 -1
- package/dist/app/state.d.ts +31 -4
- package/dist/app/state.js +31 -2
- package/dist/app/state.js.map +1 -1
- package/dist/data/memory.d.ts +9 -1
- package/dist/data/memory.js +13 -8
- package/dist/data/memory.js.map +1 -1
- package/dist/data/provider.d.ts +30 -10
- package/dist/data/sync.d.ts +14 -3
- package/dist/data/sync.js +133 -66
- package/dist/data/sync.js.map +1 -1
- package/dist/editor/actions.d.ts +1 -2
- package/dist/editor/actions.js +391 -113
- package/dist/editor/actions.js.map +1 -1
- package/dist/editor/confirm.d.ts +23 -0
- package/dist/editor/confirm.js +35 -0
- package/dist/editor/confirm.js.map +1 -0
- package/dist/editor/elevation.d.ts +191 -90
- package/dist/editor/elevation.js +812 -616
- package/dist/editor/elevation.js.map +1 -1
- package/dist/editor/face.d.ts +73 -0
- package/dist/editor/face.js +269 -0
- package/dist/editor/face.js.map +1 -0
- package/dist/editor/files.d.ts +6 -0
- package/dist/editor/files.js +50 -4
- package/dist/editor/files.js.map +1 -1
- package/dist/editor/gestures.d.ts +18 -3
- package/dist/editor/gestures.js +145 -30
- package/dist/editor/gestures.js.map +1 -1
- package/dist/editor/keypad.d.ts +20 -5
- package/dist/editor/keypad.js +62 -15
- package/dist/editor/keypad.js.map +1 -1
- package/dist/editor/keys.js +36 -4
- package/dist/editor/keys.js.map +1 -1
- package/dist/editor/laser.d.ts +20 -4
- package/dist/editor/laser.js +104 -21
- package/dist/editor/laser.js.map +1 -1
- package/dist/editor/linkActions.d.ts +49 -0
- package/dist/editor/linkActions.js +210 -0
- package/dist/editor/linkActions.js.map +1 -0
- package/dist/editor/linkFollow.d.ts +2 -0
- package/dist/editor/linkFollow.js +53 -0
- package/dist/editor/linkFollow.js.map +1 -0
- package/dist/editor/linkWrite.d.ts +13 -0
- package/dist/editor/linkWrite.js +84 -0
- package/dist/editor/linkWrite.js.map +1 -0
- package/dist/editor/links.d.ts +84 -0
- package/dist/editor/links.js +130 -0
- package/dist/editor/links.js.map +1 -0
- package/dist/editor/markup.d.ts +29 -3
- package/dist/editor/markup.js +95 -10
- package/dist/editor/markup.js.map +1 -1
- package/dist/editor/mode.d.ts +40 -2
- package/dist/editor/mode.js +71 -4
- package/dist/editor/mode.js.map +1 -1
- package/dist/editor/ports.d.ts +38 -6
- package/dist/editor/ports.js +10 -1
- package/dist/editor/ports.js.map +1 -1
- package/dist/editor/project.d.ts +38 -6
- package/dist/editor/project.js +170 -27
- package/dist/editor/project.js.map +1 -1
- package/dist/editor/selection.d.ts +10 -0
- package/dist/editor/selection.js +62 -8
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/status.js +3 -0
- package/dist/editor/status.js.map +1 -1
- package/dist/editor/tooltips.d.ts +5 -0
- package/dist/editor/tooltips.js +48 -0
- package/dist/editor/tooltips.js.map +1 -0
- package/dist/editor/view3d.d.ts +17 -0
- package/dist/editor/view3d.js +135 -0
- package/dist/editor/view3d.js.map +1 -0
- package/dist/editor/view3dState.d.ts +39 -0
- package/dist/editor/view3dState.js +44 -0
- package/dist/editor/view3dState.js.map +1 -0
- package/dist/export/dxf.js +1 -1
- package/dist/export/dxf.js.map +1 -1
- package/dist/export/pdf.js +17 -12
- package/dist/export/pdf.js.map +1 -1
- package/dist/export/plan.d.ts +23 -6
- package/dist/export/plan.js +127 -44
- package/dist/export/plan.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/model/constraints.js +15 -4
- package/dist/model/constraints.js.map +1 -1
- package/dist/model/demo.js +3 -3
- package/dist/model/demo.js.map +1 -1
- package/dist/model/elevation.d.ts +6 -9
- package/dist/model/elevation.js +5 -13
- package/dist/model/elevation.js.map +1 -1
- package/dist/model/faces.d.ts +58 -0
- package/dist/model/faces.js +197 -0
- package/dist/model/faces.js.map +1 -0
- package/dist/model/facesolve.d.ts +72 -0
- package/dist/model/facesolve.js +369 -0
- package/dist/model/facesolve.js.map +1 -0
- package/dist/model/history.d.ts +3 -2
- package/dist/model/history.js +17 -11
- package/dist/model/history.js.map +1 -1
- package/dist/model/images.d.ts +18 -0
- package/dist/model/images.js +26 -0
- package/dist/model/images.js.map +1 -0
- package/dist/model/links.d.ts +46 -0
- package/dist/model/links.js +73 -0
- package/dist/model/links.js.map +1 -0
- package/dist/model/markup.d.ts +46 -0
- package/dist/model/markup.js +71 -0
- package/dist/model/markup.js.map +1 -0
- package/dist/model/measurement.d.ts +11 -0
- package/dist/model/measurement.js +24 -0
- package/dist/model/measurement.js.map +1 -0
- package/dist/model/openings.d.ts +4 -0
- package/dist/model/openings.js +4 -0
- package/dist/model/openings.js.map +1 -1
- package/dist/model/planGeom.d.ts +72 -2
- package/dist/model/planGeom.js +184 -10
- package/dist/model/planGeom.js.map +1 -1
- package/dist/model/project.js +3 -2
- package/dist/model/project.js.map +1 -1
- package/dist/model/projectfile.js +2 -1
- package/dist/model/projectfile.js.map +1 -1
- package/dist/model/rooms.js +2 -2
- package/dist/model/rooms.js.map +1 -1
- package/dist/model/settings.d.ts +6 -0
- package/dist/model/settings.js +2 -2
- package/dist/model/settings.js.map +1 -1
- package/dist/model/sketch.d.ts +14 -0
- package/dist/model/sketch.js +143 -24
- package/dist/model/sketch.js.map +1 -1
- package/dist/model/smooth.d.ts +6 -0
- package/dist/model/smooth.js +52 -0
- package/dist/model/smooth.js.map +1 -0
- package/dist/model/store.d.ts +12 -0
- package/dist/model/store.js +35 -3
- package/dist/model/store.js.map +1 -1
- package/dist/model/types.d.ts +173 -8
- package/dist/model/wallfaces.d.ts +32 -0
- package/dist/model/wallfaces.js +133 -20
- package/dist/model/wallfaces.js.map +1 -1
- package/dist/model/wallshape.d.ts +15 -0
- package/dist/model/wallshape.js +89 -0
- package/dist/model/wallshape.js.map +1 -0
- package/dist/react/BottomBar.d.ts +9 -5
- package/dist/react/BottomBar.js +213 -24
- package/dist/react/BottomBar.js.map +1 -1
- package/dist/react/Buttons.d.ts +13 -2
- package/dist/react/Buttons.js +37 -5
- package/dist/react/Buttons.js.map +1 -1
- package/dist/react/CadEditor.d.ts +54 -4
- package/dist/react/CadEditor.js +79 -21
- package/dist/react/CadEditor.js.map +1 -1
- package/dist/react/ConfirmSheet.d.ts +4 -0
- package/dist/react/ConfirmSheet.js +31 -0
- package/dist/react/ConfirmSheet.js.map +1 -0
- package/dist/react/ConflictSheet.d.ts +2 -1
- package/dist/react/ConflictSheet.js +16 -8
- package/dist/react/ConflictSheet.js.map +1 -1
- package/dist/react/Drawer.d.ts +8 -2
- package/dist/react/Drawer.js +167 -38
- package/dist/react/Drawer.js.map +1 -1
- package/dist/react/Duck.d.ts +13 -0
- package/dist/react/Duck.js +45 -0
- package/dist/react/Duck.js.map +1 -0
- package/dist/react/Empty3D.d.ts +2 -0
- package/dist/react/Empty3D.js +39 -0
- package/dist/react/Empty3D.js.map +1 -0
- package/dist/react/FitScroll.d.ts +6 -0
- package/dist/react/FitScroll.js +14 -0
- package/dist/react/FitScroll.js.map +1 -0
- package/dist/react/Icon.native.d.ts +6 -0
- package/dist/react/Icon.native.js +4 -0
- package/dist/react/Icon.native.js.map +1 -1
- package/dist/react/Icon.web.d.ts +6 -0
- package/dist/react/Icon.web.js +4 -0
- package/dist/react/Icon.web.js.map +1 -1
- package/dist/react/KeypadSheet.d.ts +9 -2
- package/dist/react/KeypadSheet.js +174 -42
- package/dist/react/KeypadSheet.js.map +1 -1
- package/dist/react/LaserTray.js +8 -5
- package/dist/react/LaserTray.js.map +1 -1
- package/dist/react/MarkupPanel.d.ts +8 -0
- package/dist/react/MarkupPanel.js +67 -0
- package/dist/react/MarkupPanel.js.map +1 -0
- package/dist/react/PageThumb.native.d.ts +7 -2
- package/dist/react/PageThumb.native.js +19 -7
- package/dist/react/PageThumb.native.js.map +1 -1
- package/dist/react/PageThumb.web.d.ts +3 -2
- package/dist/react/PageThumb.web.js +4 -4
- package/dist/react/PageThumb.web.js.map +1 -1
- package/dist/react/PlanCanvas.native.d.ts +1 -1
- package/dist/react/PlanCanvas.native.js +134 -36
- package/dist/react/PlanCanvas.native.js.map +1 -1
- package/dist/react/PlanCanvas.web.js +16 -5
- package/dist/react/PlanCanvas.web.js.map +1 -1
- package/dist/react/Popovers.d.ts +12 -6
- package/dist/react/Popovers.js +53 -26
- package/dist/react/Popovers.js.map +1 -1
- package/dist/react/Rail.d.ts +24 -0
- package/dist/react/Rail.js +324 -34
- package/dist/react/Rail.js.map +1 -1
- package/dist/react/ShapeMenu.d.ts +7 -0
- package/dist/react/ShapeMenu.js +58 -0
- package/dist/react/ShapeMenu.js.map +1 -0
- package/dist/react/Sheet.d.ts +14 -4
- package/dist/react/Sheet.js +54 -9
- package/dist/react/Sheet.js.map +1 -1
- package/dist/react/Slider.d.ts +18 -0
- package/dist/react/Slider.js +27 -0
- package/dist/react/Slider.js.map +1 -0
- package/dist/react/Toast.js +14 -6
- package/dist/react/Toast.js.map +1 -1
- package/dist/react/ToolTip.d.ts +7 -0
- package/dist/react/ToolTip.js +43 -0
- package/dist/react/ToolTip.js.map +1 -0
- package/dist/react/TopBar.d.ts +6 -3
- package/dist/react/TopBar.js +48 -17
- package/dist/react/TopBar.js.map +1 -1
- package/dist/react/Tween.d.ts +7 -0
- package/dist/react/Tween.js +26 -0
- package/dist/react/Tween.js.map +1 -0
- package/dist/react/Tween.native.d.ts +6 -0
- package/dist/react/Tween.native.js +43 -0
- package/dist/react/Tween.native.js.map +1 -0
- package/dist/react/View3D.native.d.ts +4 -0
- package/dist/react/View3D.native.js +103 -0
- package/dist/react/View3D.native.js.map +1 -0
- package/dist/react/View3D.web.d.ts +4 -0
- package/dist/react/View3D.web.js +151 -0
- package/dist/react/View3D.web.js.map +1 -0
- package/dist/react/View3DHost.d.ts +143 -0
- package/dist/react/View3DHost.js +377 -0
- package/dist/react/View3DHost.js.map +1 -0
- package/dist/react/corners.d.ts +7 -0
- package/dist/react/corners.js +51 -0
- package/dist/react/corners.js.map +1 -0
- package/dist/react/easing.d.ts +15 -0
- package/dist/react/easing.js +10 -0
- package/dist/react/easing.js.map +1 -0
- package/dist/react/host.d.ts +7 -2
- package/dist/react/host.js +8 -3
- package/dist/react/host.js.map +1 -1
- package/dist/react/hostKeypad.d.ts +56 -0
- package/dist/react/hostKeypad.js +5 -0
- package/dist/react/hostKeypad.js.map +1 -0
- package/dist/react/motion.d.ts +77 -0
- package/dist/react/motion.js +173 -0
- package/dist/react/motion.js.map +1 -0
- package/dist/react/ports.js +90 -8
- package/dist/react/ports.js.map +1 -1
- package/dist/react/saving.d.ts +15 -0
- package/dist/react/saving.js +76 -0
- package/dist/react/saving.js.map +1 -0
- package/dist/react/store.d.ts +38 -1
- package/dist/react/store.js +31 -1
- package/dist/react/store.js.map +1 -1
- package/dist/react/theme.d.ts +10 -0
- package/dist/react/theme.js +8 -0
- package/dist/react/theme.js.map +1 -1
- package/dist/react/topRow.d.ts +22 -0
- package/dist/react/topRow.js +61 -0
- package/dist/react/topRow.js.map +1 -0
- package/dist/react/touch.d.ts +6 -0
- package/dist/react/touch.js +9 -0
- package/dist/react/touch.js.map +1 -0
- package/dist/render/ctx.d.ts +8 -0
- package/dist/render/draw.d.ts +33 -1
- package/dist/render/draw.js +593 -215
- package/dist/render/draw.js.map +1 -1
- package/dist/render/elevation.d.ts +65 -43
- package/dist/render/elevation.js +414 -140
- package/dist/render/elevation.js.map +1 -1
- package/dist/render/figmaIcons.d.ts +12 -0
- package/dist/render/figmaIcons.js +21 -0
- package/dist/render/figmaIcons.js.map +1 -0
- package/dist/render/hit.d.ts +22 -2
- package/dist/render/hit.js +168 -25
- package/dist/render/hit.js.map +1 -1
- package/dist/render/icons.js +69 -10
- package/dist/render/icons.js.map +1 -1
- package/dist/render/linkTile.d.ts +15 -0
- package/dist/render/linkTile.js +369 -0
- package/dist/render/linkTile.js.map +1 -0
- package/dist/render/markup.d.ts +11 -0
- package/dist/render/markup.js +112 -0
- package/dist/render/markup.js.map +1 -0
- package/dist/render/navigate.d.ts +88 -0
- package/dist/render/navigate.js +100 -0
- package/dist/render/navigate.js.map +1 -0
- package/dist/render/snap.d.ts +20 -1
- package/dist/render/snap.js +118 -25
- package/dist/render/snap.js.map +1 -1
- package/dist/render/squircle.d.ts +8 -0
- package/dist/render/squircle.js +71 -0
- package/dist/render/squircle.js.map +1 -0
- package/dist/render/view.d.ts +115 -2
- package/dist/render/view.js +244 -19
- package/dist/render/view.js.map +1 -1
- package/dist/skia/SkiaDrawCtx.d.ts +30 -2
- package/dist/skia/SkiaDrawCtx.js +198 -43
- package/dist/skia/SkiaDrawCtx.js.map +1 -1
- package/dist/skia/host.d.ts +18 -2
- package/dist/skia/host.js +46 -1
- package/dist/skia/host.js.map +1 -1
- package/dist/solver/equations.js +37 -2
- package/dist/solver/equations.js.map +1 -1
- package/dist/solver/gauss-newton.d.ts +17 -0
- package/dist/solver/gauss-newton.js +144 -36
- package/dist/solver/gauss-newton.js.map +1 -1
- package/dist/solver/linalg.d.ts +45 -2
- package/dist/solver/linalg.js +164 -10
- package/dist/solver/linalg.js.map +1 -1
- package/dist/solver/types.d.ts +5 -0
- package/dist/tools/annotate.d.ts +57 -1
- package/dist/tools/annotate.js +64 -43
- package/dist/tools/annotate.js.map +1 -1
- package/dist/tools/chamfer.d.ts +12 -0
- package/dist/tools/chamfer.js +114 -0
- package/dist/tools/chamfer.js.map +1 -0
- package/dist/tools/corner.d.ts +38 -0
- package/dist/tools/corner.js +99 -0
- package/dist/tools/corner.js.map +1 -0
- package/dist/tools/dim.d.ts +86 -9
- package/dist/tools/dim.js +582 -97
- package/dist/tools/dim.js.map +1 -1
- package/dist/tools/elevation.js +5 -5
- package/dist/tools/elevation.js.map +1 -1
- package/dist/tools/fillet.d.ts +9 -0
- package/dist/tools/fillet.js +86 -0
- package/dist/tools/fillet.js.map +1 -0
- package/dist/tools/freehand.d.ts +3 -2
- package/dist/tools/freehand.js +19 -12
- package/dist/tools/freehand.js.map +1 -1
- package/dist/tools/index.js +14 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/line.d.ts +8 -3
- package/dist/tools/line.js +66 -30
- package/dist/tools/line.js.map +1 -1
- package/dist/tools/modify.d.ts +13 -0
- package/dist/tools/modify.js +105 -25
- package/dist/tools/modify.js.map +1 -1
- package/dist/tools/openings.js +25 -18
- package/dist/tools/openings.js.map +1 -1
- package/dist/tools/registry.d.ts +8 -0
- package/dist/tools/registry.js +42 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/select.d.ts +77 -3
- package/dist/tools/select.js +560 -74
- package/dist/tools/select.js.map +1 -1
- package/dist/tools/shapes.d.ts +14 -0
- package/dist/tools/shapes.js +154 -75
- package/dist/tools/shapes.js.map +1 -1
- package/dist/units/format.d.ts +11 -3
- package/dist/units/format.js +27 -6
- package/dist/units/format.js.map +1 -1
- package/dist/units/parse.d.ts +2 -1
- package/dist/units/parse.js +5 -4
- package/dist/units/parse.js.map +1 -1
- package/dist/units/prefs.d.ts +9 -1
- package/dist/units/prefs.js +6 -0
- package/dist/units/prefs.js.map +1 -1
- package/dist/view3d/build.d.ts +35 -0
- package/dist/view3d/build.js +630 -0
- package/dist/view3d/build.js.map +1 -0
- package/dist/view3d/camera.d.ts +60 -0
- package/dist/view3d/camera.js +84 -0
- package/dist/view3d/camera.js.map +1 -0
- package/dist/view3d/fatLines.d.ts +11 -0
- package/dist/view3d/fatLines.js +83 -0
- package/dist/view3d/fatLines.js.map +1 -0
- package/dist/view3d/lines.d.ts +17 -0
- package/dist/view3d/lines.js +271 -0
- package/dist/view3d/lines.js.map +1 -0
- package/dist/view3d/mesh.d.ts +51 -0
- package/dist/view3d/mesh.js +101 -0
- package/dist/view3d/mesh.js.map +1 -0
- package/dist/view3d/poly.d.ts +16 -0
- package/dist/view3d/poly.js +109 -0
- package/dist/view3d/poly.js.map +1 -0
- package/dist/view3d/viewer.d.ts +86 -0
- package/dist/view3d/viewer.js +350 -0
- package/dist/view3d/viewer.js.map +1 -0
- package/package.json +15 -2
- package/src/app/edit.ts +83 -12
- package/src/app/main.ts +11 -5
- package/src/app/state.ts +38 -5
- package/src/data/memory.ts +15 -10
- package/src/data/provider.ts +25 -10
- package/src/data/sync.ts +107 -53
- package/src/editor/actions.ts +292 -83
- package/src/editor/confirm.ts +58 -0
- package/src/editor/elevation.ts +698 -478
- package/src/editor/face.ts +227 -0
- package/src/editor/files.ts +40 -4
- package/src/editor/gestures.ts +147 -31
- package/src/editor/keypad.ts +67 -18
- package/src/editor/keys.ts +25 -5
- package/src/editor/laser.ts +98 -20
- package/src/editor/linkActions.ts +194 -0
- package/src/editor/linkFollow.ts +43 -0
- package/src/editor/linkWrite.ts +77 -0
- package/src/editor/links.ts +181 -0
- package/src/editor/markup.ts +92 -8
- package/src/editor/mode.ts +83 -7
- package/src/editor/ports.ts +39 -6
- package/src/editor/project.ts +157 -26
- package/src/editor/selection.ts +54 -8
- package/src/editor/status.ts +2 -0
- package/src/editor/tooltips.ts +47 -0
- package/src/editor/view3d.ts +119 -0
- package/src/editor/view3dState.ts +61 -0
- package/src/export/dxf.ts +1 -1
- package/src/export/pdf.ts +15 -7
- package/src/export/plan.ts +119 -35
- package/src/index.ts +7 -1
- package/src/input/keyboard.ts +2 -4
- package/src/model/constraints.ts +13 -4
- package/src/model/demo.ts +3 -3
- package/src/model/elevation.ts +6 -16
- package/src/model/faces.ts +153 -0
- package/src/model/facesolve.ts +322 -0
- package/src/model/history.ts +19 -11
- package/src/model/images.ts +35 -0
- package/src/model/links.ts +77 -0
- package/src/model/markup.ts +80 -0
- package/src/model/measurement.ts +26 -0
- package/src/model/openings.ts +6 -0
- package/src/model/planGeom.ts +174 -8
- package/src/model/project.ts +3 -2
- package/src/model/projectfile.ts +2 -1
- package/src/model/rooms.ts +1 -1
- package/src/model/settings.ts +8 -2
- package/src/model/sketch.ts +101 -14
- package/src/model/smooth.ts +51 -0
- package/src/model/store.ts +35 -4
- package/src/model/types.ts +170 -8
- package/src/model/wallfaces.ts +126 -17
- package/src/model/wallshape.ts +97 -0
- package/src/react/BottomBar.tsx +263 -46
- package/src/react/Buttons.tsx +50 -9
- package/src/react/CadEditor.tsx +142 -34
- package/src/react/ConfirmSheet.tsx +38 -0
- package/src/react/ConflictSheet.tsx +19 -12
- package/src/react/Drawer.tsx +213 -110
- package/src/react/Duck.tsx +50 -0
- package/src/react/Empty3D.tsx +32 -0
- package/src/react/FitScroll.tsx +19 -0
- package/src/react/Icon.native.tsx +5 -0
- package/src/react/Icon.web.tsx +5 -0
- package/src/react/KeypadSheet.tsx +253 -60
- package/src/react/LaserTray.tsx +12 -8
- package/src/react/MarkupPanel.tsx +150 -0
- package/src/react/PageThumb.native.tsx +18 -7
- package/src/react/PageThumb.web.tsx +4 -4
- package/src/react/PlanCanvas.native.tsx +151 -34
- package/src/react/PlanCanvas.web.tsx +15 -5
- package/src/react/Popovers.tsx +116 -51
- package/src/react/Rail.tsx +360 -27
- package/src/react/ShapeMenu.tsx +66 -0
- package/src/react/Sheet.tsx +56 -11
- package/src/react/Slider.tsx +48 -0
- package/src/react/Toast.tsx +16 -9
- package/src/react/ToolTip.tsx +49 -0
- package/src/react/TopBar.tsx +97 -39
- package/src/react/Tween.native.tsx +36 -0
- package/src/react/Tween.tsx +24 -0
- package/src/react/View3D.native.tsx +131 -0
- package/src/react/View3D.web.tsx +131 -0
- package/src/react/View3DHost.ts +367 -0
- package/src/react/corners.ts +52 -0
- package/src/react/easing.ts +14 -0
- package/src/react/host.ts +8 -3
- package/src/react/hostKeypad.ts +66 -0
- package/src/react/motion.tsx +239 -0
- package/src/react/ports.ts +78 -9
- package/src/react/saving.ts +80 -0
- package/src/react/store.ts +35 -3
- package/src/react/theme.ts +8 -0
- package/src/react/topRow.ts +71 -0
- package/src/react/touch.ts +10 -0
- package/src/render/ctx.ts +8 -0
- package/src/render/draw.ts +437 -175
- package/src/render/elevation.ts +349 -143
- package/src/render/figmaIcons.ts +22 -0
- package/src/render/hit.ts +140 -21
- package/src/render/icons.ts +69 -10
- package/src/render/linkTile.ts +297 -0
- package/src/render/markup.ts +91 -0
- package/src/render/navigate.ts +114 -0
- package/src/render/snap.ts +105 -22
- package/src/render/squircle.ts +73 -0
- package/src/render/view.ts +255 -19
- package/src/skia/SkiaDrawCtx.ts +163 -41
- package/src/skia/host.ts +46 -1
- package/src/solver/equations.ts +37 -2
- package/src/solver/gauss-newton.ts +125 -28
- package/src/solver/linalg.ts +141 -5
- package/src/solver/types.ts +5 -0
- package/src/styles.css +91 -42
- package/src/tools/annotate.ts +58 -29
- package/src/tools/chamfer.ts +103 -0
- package/src/tools/corner.ts +99 -0
- package/src/tools/dim.ts +525 -93
- package/src/tools/elevation.ts +5 -5
- package/src/tools/fillet.ts +82 -0
- package/src/tools/freehand.ts +20 -16
- package/src/tools/index.ts +17 -4
- package/src/tools/line.ts +59 -23
- package/src/tools/modify.ts +86 -24
- package/src/tools/openings.ts +11 -16
- package/src/tools/registry.ts +27 -2
- package/src/tools/select.ts +424 -75
- package/src/tools/shapes.ts +119 -58
- package/src/ui/ctx.ts +2 -1
- package/src/ui/domPorts.ts +23 -4
- package/src/ui/drawer.ts +6 -26
- package/src/ui/elevation.ts +10 -101
- package/src/ui/keypad.ts +8 -14
- package/src/ui/laser.ts +2 -2
- package/src/ui/menu.ts +63 -17
- package/src/ui/noteinput.ts +3 -3
- package/src/ui/opacity.ts +108 -0
- package/src/ui/palette.ts +67 -12
- package/src/ui/rail.ts +21 -7
- package/src/ui/topbar.ts +4 -14
- package/src/units/format.ts +24 -6
- package/src/units/parse.ts +4 -3
- package/src/units/prefs.ts +13 -1
- package/src/view3d/build.ts +607 -0
- package/src/view3d/camera.ts +113 -0
- package/src/view3d/fatLines.ts +83 -0
- package/src/view3d/lines.ts +258 -0
- package/src/view3d/mesh.ts +111 -0
- package/src/view3d/poly.ts +104 -0
- package/src/view3d/viewer.ts +348 -0
- package/dist/react/ElevCanvas.native.d.ts +0 -3
- package/dist/react/ElevCanvas.native.js +0 -58
- package/dist/react/ElevCanvas.native.js.map +0 -1
- package/dist/react/ElevCanvas.web.d.ts +0 -4
- package/dist/react/ElevCanvas.web.js +0 -44
- package/dist/react/ElevCanvas.web.js.map +0 -1
- package/dist/react/ElevationSheet.d.ts +0 -2
- package/dist/react/ElevationSheet.js +0 -38
- package/dist/react/ElevationSheet.js.map +0 -1
- package/dist/render/elevationView.d.ts +0 -3
- package/dist/render/elevationView.js +0 -100
- package/dist/render/elevationView.js.map +0 -1
- package/src/react/ElevCanvas.native.tsx +0 -68
- package/src/react/ElevCanvas.web.tsx +0 -42
- package/src/react/ElevationSheet.tsx +0 -88
- package/src/render/elevationView.ts +0 -73
package/src/app/edit.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { drivingDim } from '../model/openings';
|
|
2
|
+
import { edgeOf, wallOf } from '../model/planGeom';
|
|
2
3
|
import { CONS_LABEL } from '../model/constraints';
|
|
3
4
|
import { HS, stepRedo, stepUndo } from '../model/history';
|
|
5
|
+
import { pushedOut, syncFaces } from '../model/facesolve';
|
|
6
|
+
import { elevSyncFrame, fitState, overflow, pastWallMsg, restoreFit } from '../editor/elevation';
|
|
4
7
|
import { resolveOpenings } from '../model/openings';
|
|
5
8
|
import { gc, restorePos, snapshotPos } from '../model/sketch';
|
|
6
|
-
import { page, saveSoon, SK } from '../model/store';
|
|
7
|
-
import type { Constraint, SelItem } from '../model/types';
|
|
9
|
+
import { page, planSK, saveSoon, SK } from '../model/store';
|
|
10
|
+
import type { Constraint, SelItem, Sketch, WallFace } from '../model/types';
|
|
11
|
+
import { cabOfPoint, cabPoints } from '../model/faces';
|
|
8
12
|
import { requestDraw } from '../render/view';
|
|
9
13
|
import { solver, type AddResult, type SolveResult } from '../solver';
|
|
10
14
|
import { cancelTool } from '../tools/registry';
|
|
11
15
|
import { fmtLen } from '../units';
|
|
12
16
|
import { ed } from './state';
|
|
13
17
|
import { refreshDrawerSoon, renderElevation, showConflict, toast, updateCtx, updateStatus } from '../editor/ports';
|
|
18
|
+
import { refreshLinks } from '../editor/links';
|
|
19
|
+
import { followLinked } from '../editor/linkFollow';
|
|
14
20
|
|
|
15
21
|
export function analyze(): void {
|
|
16
22
|
ed.ana = solver.analyzeDOF(SK());
|
|
@@ -25,9 +31,19 @@ export function solveOrRevert(): SolveResult {
|
|
|
25
31
|
return s;
|
|
26
32
|
}
|
|
27
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Walls made thicker or thinner, or lines turned into walls: what's measured on walls' faces holds, their centrelines
|
|
36
|
+
* moving to keep it (a face's length depends on the walls at its corners as well as its own). False — and nothing
|
|
37
|
+
* moved — when it can't hold.
|
|
38
|
+
*/
|
|
39
|
+
export function holdFaces(): boolean {
|
|
40
|
+
if (!Object.values(SK().cons).some(c => c.face || c.faces)) return true;
|
|
41
|
+
return solveOrRevert().ok;
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
/** Re-place locked doors/windows from their dimensions (after any geometry change). */
|
|
29
45
|
export function resolveOpeningsNow(): void {
|
|
30
|
-
ed.badOpeningDims = resolveOpenings(
|
|
46
|
+
ed.badOpeningDims = resolveOpenings(planSK());
|
|
31
47
|
}
|
|
32
48
|
|
|
33
49
|
export function existsSel(s: SelItem): boolean {
|
|
@@ -39,13 +55,17 @@ export function existsSel(s: SelItem): boolean {
|
|
|
39
55
|
case 'arc': return !!sk.arcs[s.id];
|
|
40
56
|
case 'cons': case 'dim': return !!sk.cons[s.id];
|
|
41
57
|
case 'room': return !!sk.rooms[s.id];
|
|
42
|
-
case 'opening': return !!
|
|
58
|
+
case 'opening': return !!planSK().openings[s.id];
|
|
59
|
+
case 'cab': return !!(sk as WallFace).cabs?.[s.id];
|
|
60
|
+
case 'elev': return true;
|
|
61
|
+
case 'oanchor': return !!planSK().openings[s.id.split('|')[0]];
|
|
62
|
+
case 'wface': return !!wallOf(sk, edgeOf(s.id)[0]);
|
|
43
63
|
case 'odim': {
|
|
44
|
-
const [op, part] = s.id.split('|'), o =
|
|
45
|
-
return !!o && (part.startsWith('d:') ? (o.dims || []).some(d => d.id === part.slice(2)) : !drivingDim(o));
|
|
64
|
+
const [op, part] = s.id.split('|'), o = planSK().openings[op];
|
|
65
|
+
return !!o && (part === 'w' || (part.startsWith('d:') ? (o.dims || []).some(d => d.id === part.slice(2)) : !drivingDim(o)));
|
|
46
66
|
}
|
|
47
67
|
case 'note': return sk.notes.some(n => n.id === s.id);
|
|
48
|
-
case 'underlay': return
|
|
68
|
+
case 'underlay': return page().underlays.some(u => u.id === s.id);
|
|
49
69
|
}
|
|
50
70
|
return false;
|
|
51
71
|
}
|
|
@@ -53,8 +73,11 @@ export function existsSel(s: SelItem): boolean {
|
|
|
53
73
|
/** Run after every model change: clean up, re-analyze, refresh UI, autosave. */
|
|
54
74
|
export function afterEdit(): void {
|
|
55
75
|
ed.editSeq++;
|
|
56
|
-
gc(
|
|
76
|
+
gc(planSK()); // the plan, and each wall face
|
|
57
77
|
resolveOpeningsNow();
|
|
78
|
+
// what's drawn on wall faces follows the plan's corners, doors and windows
|
|
79
|
+
ed.badFaceCons = syncFaces(planSK());
|
|
80
|
+
elevSyncFrame(); // the open wall's frame (its length, its corners) as the plan has it now
|
|
58
81
|
ed.sel = ed.sel.filter(s => existsSel(s));
|
|
59
82
|
analyze();
|
|
60
83
|
updateCtx();
|
|
@@ -62,11 +85,13 @@ export function afterEdit(): void {
|
|
|
62
85
|
refreshDrawerSoon();
|
|
63
86
|
requestDraw();
|
|
64
87
|
renderElevation();
|
|
88
|
+
refreshLinks(); // (what's linked may have changed: the host is asked about it)
|
|
89
|
+
followLinked(); // (and an undo may have put a linked dimension at something else than the job says)
|
|
65
90
|
saveSoon();
|
|
66
91
|
}
|
|
67
92
|
|
|
68
93
|
export function undo(): void {
|
|
69
|
-
if (!HS().u.length) { toast('Nothing to undo'); return; }
|
|
94
|
+
if (!HS().u.length) { toast('Nothing to undo', { warn: true }); return; }
|
|
70
95
|
cancelTool();
|
|
71
96
|
stepUndo();
|
|
72
97
|
ed.sel = [];
|
|
@@ -77,7 +102,7 @@ export function undo(): void {
|
|
|
77
102
|
export function redo(): void {
|
|
78
103
|
const h = HS();
|
|
79
104
|
if (!h.u.length && !h.r.length) return;
|
|
80
|
-
if (!h.r.length) { toast('Nothing to redo'); return; }
|
|
105
|
+
if (!h.r.length) { toast('Nothing to redo', { warn: true }); return; }
|
|
81
106
|
cancelTool();
|
|
82
107
|
stepRedo();
|
|
83
108
|
ed.sel = [];
|
|
@@ -85,19 +110,65 @@ export function redo(): void {
|
|
|
85
110
|
toast('Redone');
|
|
86
111
|
}
|
|
87
112
|
|
|
113
|
+
/** Solve with these points held exactly where they are (fixed for the solve, then as they were). */
|
|
114
|
+
function solveHolding(sk: Sketch, hold: string[]): SolveResult {
|
|
115
|
+
const pts = hold.map(id => sk.points[id]).filter(Boolean), had = pts.map(p => p.fixed);
|
|
116
|
+
pts.forEach(p => { p.fixed = true; });
|
|
117
|
+
const s = solver.solve(sk);
|
|
118
|
+
pts.forEach((p, i) => { if (had[i]) p.fixed = true; else delete p.fixed; });
|
|
119
|
+
return s;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The things a constraint ties together, each as the points to hold for it: a cabinet (its corners, when it's one of
|
|
124
|
+
* its edges or corners), a line (its ends), a point.
|
|
125
|
+
*/
|
|
126
|
+
export function holdGroups(sk: Sketch, c: Constraint): string[][] {
|
|
127
|
+
const face = sk as WallFace, groups: string[][] = [], seen = new Set<string>();
|
|
128
|
+
const add = (key: string, pts: string[]) => { if (!seen.has(key) && pts.length) { seen.add(key); groups.push(pts); } };
|
|
129
|
+
const point = (pid: string | undefined) => {
|
|
130
|
+
if (!pid || !sk.points[pid]) return;
|
|
131
|
+
const cab = cabOfPoint(sk, pid);
|
|
132
|
+
if (cab) add('cab:' + cab, cabPoints(face.cabs[cab])); else add('pt:' + pid, [pid]);
|
|
133
|
+
};
|
|
134
|
+
for (const lid of [c.l, c.l1, c.l2, c.line]) {
|
|
135
|
+
const l = lid ? sk.lines[lid] : undefined;
|
|
136
|
+
if (!l) continue;
|
|
137
|
+
if (l.cab && face.cabs?.[l.cab]) add('cab:' + l.cab, cabPoints(face.cabs[l.cab]));
|
|
138
|
+
else add('line:' + lid, [l.a, l.b]);
|
|
139
|
+
}
|
|
140
|
+
for (const pid of [c.a, c.b, c.p]) point(pid);
|
|
141
|
+
return groups;
|
|
142
|
+
}
|
|
143
|
+
|
|
88
144
|
/**
|
|
89
145
|
* Add a constraint through the solver and explain the outcome:
|
|
90
146
|
* reference dimension → toast, conflict → conflict sheet (unless silent).
|
|
91
147
|
*/
|
|
92
148
|
export function tryAddConstraint(c: Constraint, { silent = false, onResolved = null as (() => void) | null } = {}): AddResult {
|
|
93
|
-
|
|
149
|
+
// nothing may be pushed past its wall (in the wall view, past the wall; in the plan, a wall made shorter than
|
|
150
|
+
// what's on it): a constraint that would is taken back
|
|
151
|
+
const sk = SK(), was = overflow(sk), held = fitState(sk);
|
|
152
|
+
const r = solver.addConstraint(sk, c, { explain: !silent });
|
|
153
|
+
// met by moving everything a little, it ran past the wall: try keeping each thing it ties still in turn, so the
|
|
154
|
+
// other one moves to meet it (a short cabinet lifted to line up with a tall one, not the tall one sunk into the floor)
|
|
155
|
+
if (r.ok && r.id && !r.ref && pushedOut(was, overflow(sk))) {
|
|
156
|
+
for (const hold of holdGroups(sk, c)) {
|
|
157
|
+
restoreFit(sk, held);
|
|
158
|
+
if (solveHolding(sk, hold).ok && !pushedOut(was, overflow(sk))) return r;
|
|
159
|
+
}
|
|
160
|
+
delete sk.cons[r.id];
|
|
161
|
+
restoreFit(sk, held);
|
|
162
|
+
if (!silent) toast(pastWallMsg(), { warn: true });
|
|
163
|
+
return { ok: false };
|
|
164
|
+
}
|
|
94
165
|
if (silent) return r;
|
|
95
166
|
if (r.ref) {
|
|
96
167
|
toast(r.refSame
|
|
97
168
|
? 'Added as a reference dimension. Other constraints already set this value.'
|
|
98
169
|
: 'Kept as a reference dimension (' + fmtLen(c.value!) + '). Other constraints already set this value — remove one to drive it.', { warn: !r.refSame });
|
|
99
170
|
} else if (r.redundant) {
|
|
100
|
-
toast(CONS_LABEL[c.type] + ' is already true — other constraints set it.');
|
|
171
|
+
toast(CONS_LABEL[c.type] + ' is already true — other constraints set it.', { warn: true });
|
|
101
172
|
} else if (r.conflict === 'dependent') {
|
|
102
173
|
showConflict({ title: 'Can’t add ' + (CONS_LABEL[c.type] || 'constraint').toLowerCase(), msg: 'It fights with constraints already on the drawing. Remove one of these to apply it.', ids: r.culprits || [], pending: c, onResolved });
|
|
103
174
|
} else if (r.conflict === 'unsatisfiable') {
|
package/src/app/main.ts
CHANGED
|
@@ -2,10 +2,10 @@ import '../styles.css';
|
|
|
2
2
|
import { initKeyboard } from '../input/keyboard';
|
|
3
3
|
import { initPointer } from '../input/pointer';
|
|
4
4
|
import { settings } from '../model/settings';
|
|
5
|
-
import { load, page, saveNow, saveSoon, SK } from '../model/store';
|
|
5
|
+
import { load, page, planSK, saveNow, saveSoon, SK } from '../model/store';
|
|
6
6
|
import { hitAny } from '../render/hit';
|
|
7
7
|
import { snapAt } from '../render/snap';
|
|
8
|
-
import { cvs, fitView, initCanvas, mainT, resize, S, s2w } from '../render/view';
|
|
8
|
+
import { cvs, fitView, initCanvas, mainT, noteHandles, resize, S, s2w } from '../render/view';
|
|
9
9
|
import { registerTools, setTool, tools } from '../tools';
|
|
10
10
|
import { initCtx, updateCtx } from '../ui/ctx';
|
|
11
11
|
import { $ } from '../ui/dom';
|
|
@@ -27,7 +27,7 @@ import { applyTheme, initTheme } from '../ui/theme';
|
|
|
27
27
|
import { initTopBar } from '../ui/topbar';
|
|
28
28
|
import { initUnderlay } from '../ui/underlay';
|
|
29
29
|
import { parseLen, fmtLen } from '../units';
|
|
30
|
-
import { analyze, undo } from './edit';
|
|
30
|
+
import { afterEdit, analyze, undo } from './edit';
|
|
31
31
|
import { ed } from './state';
|
|
32
32
|
import { resetSession } from '../model/session';
|
|
33
33
|
|
|
@@ -61,8 +61,10 @@ function init(): void {
|
|
|
61
61
|
// test/debug hook (same shape as the prototype's)
|
|
62
62
|
(window as unknown as { __boldr: unknown }).__boldr = {
|
|
63
63
|
get sk() { return SK(); },
|
|
64
|
-
get
|
|
65
|
-
|
|
64
|
+
get plan() { return planSK(); },
|
|
65
|
+
get underlay() { return page().underlays[0] ?? null; },
|
|
66
|
+
get images() { return page().underlays; },
|
|
67
|
+
analyze, afterEdit, tools, setTool, setMode,
|
|
66
68
|
get sel() { return ed.sel; },
|
|
67
69
|
set sel(v) { ed.sel = v; },
|
|
68
70
|
fitView, parseLen, fmtLen,
|
|
@@ -70,7 +72,11 @@ function init(): void {
|
|
|
70
72
|
get chips() { return ed.hitChips; },
|
|
71
73
|
s2w, undo, snapAt, hitAny,
|
|
72
74
|
w2s: (x: number, y: number) => S(mainT(), x, y),
|
|
75
|
+
/** a note's adjustment handles, on screen */
|
|
76
|
+
noteHandles: (id: string) => { const n = SK().notes.find(x => x.id === id); return n ? noteHandles(mainT(), n) : []; },
|
|
73
77
|
get snap() { return ed.snapState; },
|
|
78
|
+
/** something is being drawn (a tool's preview) */
|
|
79
|
+
get previewing() { return !!ed.preview; },
|
|
74
80
|
get elevHits() { return elevHits(); },
|
|
75
81
|
};
|
|
76
82
|
}
|
package/src/app/state.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { emptyAnalysis } from '../model/constraints';
|
|
2
|
+
import { DEFAULT_NOTE_COLOR, DEFAULT_NOTE_WIDTH, NOTE_TEXT_IN, type NoteStyle } from '../model/markup';
|
|
2
3
|
import type { Analysis, OpeningEdge, SelItem, SelType } from '../model/types';
|
|
3
4
|
import type { Xform } from '../render/view';
|
|
4
5
|
import { sessionState } from '../model/session';
|
|
@@ -8,14 +9,20 @@ export type Mode = 'draft' | 'annotate';
|
|
|
8
9
|
|
|
9
10
|
/** Something under the pointer: geometry, or a chip/badge drawn on the canvas. */
|
|
10
11
|
export interface Hit {
|
|
11
|
-
|
|
12
|
+
/** 'cabfoot': a cabinet's footprint in the plan (id: its wall face's key, '#', its id) */
|
|
13
|
+
type: SelType | 'odim' | 'oanchor' | 'uhandle' | 'nhandle' | 'cabfoot';
|
|
12
14
|
id: string;
|
|
13
15
|
/** a print dimension label */
|
|
14
16
|
print?: boolean;
|
|
15
17
|
/** low-priority hit (room fill) */
|
|
16
18
|
weak?: boolean;
|
|
17
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* 'odim': 'w' width, 'a'/'b' distance to a wall end, or 'd:<id>' a placed dimension. 'oanchor': 's0'/'s1' edge.
|
|
21
|
+
* 'note', a link's tile: 'tip' its leader's tip, 'leader' along its leader (unset: its card).
|
|
22
|
+
*/
|
|
18
23
|
part?: string;
|
|
24
|
+
/** a wall picked whole: the side of its centreline the pointer was on (+1 the left of its A → B; a curved one's, outside) */
|
|
25
|
+
side?: 1 | -1;
|
|
19
26
|
}
|
|
20
27
|
|
|
21
28
|
export type OpeningDimPart = 'w' | 'a' | 'b' | `d:${string}`;
|
|
@@ -42,7 +49,8 @@ export interface Snap {
|
|
|
42
49
|
|
|
43
50
|
/** Screen-space hit region registered while drawing chips, badges and labels. */
|
|
44
51
|
export interface HitChip {
|
|
45
|
-
|
|
52
|
+
/** 'elev': one of the wall view's dimension chips (id: what it measures, as JSON) */
|
|
53
|
+
kind: 'dim' | 'pdim' | 'cons' | 'room' | 'odim' | 'elev';
|
|
46
54
|
part?: string;
|
|
47
55
|
id: string;
|
|
48
56
|
x: number; y: number; w: number; h: number;
|
|
@@ -68,20 +76,45 @@ export const ed = sessionState(() => ({
|
|
|
68
76
|
ana: emptyAnalysis() as Analysis,
|
|
69
77
|
lastPointerTouch: false,
|
|
70
78
|
drawConstr: false,
|
|
79
|
+
/** the rail's Walls toggle: what's drawn (lines, rectangles, circles, arcs, Draw to shape) is walls */
|
|
80
|
+
drawWalls: false,
|
|
71
81
|
dimLayer: 'drive' as 'drive' | 'print',
|
|
72
82
|
openingType: 'door' as 'door' | 'window',
|
|
73
|
-
|
|
83
|
+
/** new markup's look (the stroke panel sets them; selected markup changes with them) */
|
|
84
|
+
noteColor: DEFAULT_NOTE_COLOR,
|
|
85
|
+
noteWidth: DEFAULT_NOTE_WIDTH,
|
|
86
|
+
noteStyle: 'solid' as NoteStyle,
|
|
87
|
+
/** new text notes' letter height on the drawing, inches */
|
|
88
|
+
noteTextIn: NOTE_TEXT_IN,
|
|
74
89
|
/** opening dimensions that can't be met (drawn red) */
|
|
75
90
|
badOpeningDims: new Set<string>(),
|
|
91
|
+
/** wall-face constraints that can't be met (drawn red in the elevation) */
|
|
92
|
+
badFaceCons: new Set<string>(),
|
|
76
93
|
/** dimension tool: an opening edge picked as the first end */
|
|
77
94
|
/** body: the opening itself was tapped (not an edge square), so the edge is chosen from what it's measured to */
|
|
78
95
|
pickedAnchor: null as { id: string; edge: OpeningEdge; body?: boolean } | null,
|
|
79
96
|
/** bumped on every model change (so a double tap can't span an edit) */
|
|
80
97
|
editSeq: 0,
|
|
98
|
+
/** the side a wall was last tapped on, picking it whole: between two spaces, its length is measured on that side */
|
|
99
|
+
wallTap: null as { id: string; side: 1 | -1 } | null,
|
|
81
100
|
/** recently hovered points, used for alignment guides */
|
|
82
101
|
recentPts: [] as string[],
|
|
83
102
|
/** view only: pan and zoom, no tools, nothing saved (people who can't edit this job) */
|
|
84
103
|
readOnly: false,
|
|
85
104
|
}));
|
|
86
105
|
|
|
87
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Whether something is selected. Drawing asks it of everything on the plan, every frame: with many things selected (a
|
|
108
|
+
* double tap takes in every wall joined to one) that was each against each, so a larger selection is looked up in a
|
|
109
|
+
* set, made again only when the selection changes (it's replaced, or added to).
|
|
110
|
+
*/
|
|
111
|
+
export function isSel(type: string, id: string): boolean {
|
|
112
|
+
const sel = ed.sel;
|
|
113
|
+
if (sel.length < 8) {
|
|
114
|
+
for (const s of sel) if (s.type === type && s.id === id) return true;
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (!selKeys || selKeys.sel !== sel || selKeys.n !== sel.length) selKeys = { sel, n: sel.length, keys: new Set(sel.map(s => s.type + ' ' + s.id)) };
|
|
118
|
+
return selKeys.keys.has(type + ' ' + id);
|
|
119
|
+
}
|
|
120
|
+
let selKeys: { sel: SelItem[]; n: number; keys: Set<string> } | null = null;
|
package/src/data/memory.ts
CHANGED
|
@@ -4,17 +4,20 @@ import type { CadDataProvider, CadFileMeta, CadMeasurementValue, CadPageDoc } fr
|
|
|
4
4
|
|
|
5
5
|
const copy = <T,>(v: T): T => JSON.parse(JSON.stringify(v)) as T;
|
|
6
6
|
|
|
7
|
-
export function memoryProvider(name = 'Test drawing', meta: CadFileMeta | null = null, pages: Record<string, CadPageDoc> = {}) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
7
|
+
export function memoryProvider(name = 'Test drawing', meta: CadFileMeta | null = null, pages: Record<string, CadPageDoc> = {}, opts: { fromCache?: boolean } = {}) {
|
|
8
|
+
// (fromCache: what's here is the cache's word, as a device offline hears it, until confirm() brings the server's)
|
|
9
|
+
let fromCache = !!opts.fromCache;
|
|
10
|
+
const snap = () => ({ fromCache });
|
|
11
|
+
const fileSubs = new Set<(f: { name: string; meta: CadFileMeta | null } | null, m?: { fromCache: boolean }) => void>();
|
|
12
|
+
const pageSubs = new Set<(p: Record<string, CadPageDoc>, m?: { fromCache: boolean }) => void>();
|
|
13
|
+
const state = { name, meta: meta && copy(meta), pages: copy(pages), writes: 0, uploads: 0, thumbnail: null as string | null, files: {} as Record<string, string>, measurements: {} as Record<string, CadMeasurementValue>, placed: [] as string[], placedLinked: [] as { groupId: string; id: string; columnId?: string }[] };
|
|
11
14
|
const measSubs = new Set<(v: Record<string, CadMeasurementValue>) => void>();
|
|
12
15
|
const emitMeas = () => measSubs.forEach(cb => cb(copy(state.measurements)));
|
|
13
|
-
const emitFile = () => fileSubs.forEach(cb => cb({ name: state.name, meta: state.meta && copy(state.meta) }));
|
|
14
|
-
const emitPages = () => pageSubs.forEach(cb => cb(copy(state.pages)));
|
|
16
|
+
const emitFile = () => fileSubs.forEach(cb => cb({ name: state.name, meta: state.meta && copy(state.meta) }, snap()));
|
|
17
|
+
const emitPages = () => pageSubs.forEach(cb => cb(copy(state.pages), snap()));
|
|
15
18
|
const provider: CadDataProvider = {
|
|
16
|
-
subscribeFile(cb) { fileSubs.add(cb); queueMicrotask(() => cb({ name: state.name, meta: state.meta && copy(state.meta) })); return () => { fileSubs.delete(cb); }; },
|
|
17
|
-
subscribePages(cb) { pageSubs.add(cb); queueMicrotask(() => cb(copy(state.pages))); return () => { pageSubs.delete(cb); }; },
|
|
19
|
+
subscribeFile(cb) { fileSubs.add(cb); queueMicrotask(() => cb({ name: state.name, meta: state.meta && copy(state.meta) }, snap())); return () => { fileSubs.delete(cb); }; },
|
|
20
|
+
subscribePages(cb) { pageSubs.add(cb); queueMicrotask(() => cb(copy(state.pages), snap())); return () => { pageSubs.delete(cb); }; },
|
|
18
21
|
async writeMeta(m) { state.meta = copy(m); state.writes++; emitFile(); },
|
|
19
22
|
async writePage(id, p) { state.pages[id] = copy(p); state.writes++; emitPages(); },
|
|
20
23
|
async deletePage(id) { delete state.pages[id]; state.writes++; emitPages(); },
|
|
@@ -26,12 +29,14 @@ export function memoryProvider(name = 'Test drawing', meta: CadFileMeta | null =
|
|
|
26
29
|
async create(m) { const id = 'm' + (Object.keys(state.measurements).length + 1); state.measurements[id] = copy(m); emitMeas(); return id; },
|
|
27
30
|
async update(id, value) { state.measurements[id] = { ...state.measurements[id], value }; emitMeas(); },
|
|
28
31
|
subscribe(cb) { measSubs.add(cb); queueMicrotask(() => cb(copy(state.measurements))); return () => { measSubs.delete(cb); }; },
|
|
29
|
-
async setPlaced(ids) { state.placed = ids.slice(); },
|
|
32
|
+
async setPlaced(ids, linked = []) { state.placed = ids.slice(); state.placedLinked = copy(linked); },
|
|
30
33
|
},
|
|
31
34
|
};
|
|
32
35
|
/** Change a page as another device would. */
|
|
33
36
|
const remote = (id: string, p: CadPageDoc) => { state.pages[id] = copy(p); emitPages(); };
|
|
34
37
|
/** Change a measurement as someone else would (e.g. in the job's measurement list). */
|
|
35
38
|
const remoteMeasurement = (id: string, value: number) => { state.measurements[id] = { ...state.measurements[id], value }; emitMeas(); };
|
|
36
|
-
|
|
39
|
+
/** The server's word after a start from the cache: everything is sent again, confirmed. */
|
|
40
|
+
const confirm = () => { fromCache = false; emitFile(); emitPages(); };
|
|
41
|
+
return { provider, state, remote, remoteMeasurement, confirm };
|
|
37
42
|
}
|
package/src/data/provider.ts
CHANGED
|
@@ -19,20 +19,30 @@ export interface CadFileMeta {
|
|
|
19
19
|
settings?: { wallH?: number; layers?: Partial<Layers> };
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/** One page as stored.
|
|
22
|
+
/** One page as stored. Its images' src are uploaded images' addresses, never inline image data. */
|
|
23
23
|
export interface CadPageDoc {
|
|
24
24
|
name: string;
|
|
25
25
|
sk: Sketch;
|
|
26
|
-
|
|
26
|
+
/** the page's photos and plans, bottom first */
|
|
27
|
+
underlays: Underlay[];
|
|
28
|
+
/** pages written when a page held one image: read as `underlays` of that one, never written */
|
|
29
|
+
underlay?: Underlay | null;
|
|
27
30
|
/** the editing session that wrote it last, and its write count (to recognise our own writes coming back) */
|
|
28
31
|
rev?: { clientId: string; seq: number };
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Where a snapshot came from: the local cache, which may be stale and, offline, empty for what was never read on this
|
|
36
|
+
* device, or the server. Unset: the server. Firestore delivers the cache's answer first when it's offline; subscribe
|
|
37
|
+
* with metadata changes included, so the server's confirmation of an empty collection still arrives.
|
|
38
|
+
*/
|
|
39
|
+
export interface CadSnapshotMeta { fromCache: boolean }
|
|
40
|
+
|
|
31
41
|
export interface CadDataProvider {
|
|
32
|
-
/** The file's name and drawing record (null record: not a drawing yet). Returns an unsubscribe function. */
|
|
33
|
-
subscribeFile(cb: (file: { name: string; meta: CadFileMeta | null } | null) => void): () => void;
|
|
42
|
+
/** The file's name and drawing record (null record: not a drawing yet; null file: no such file). Returns an unsubscribe function. */
|
|
43
|
+
subscribeFile(cb: (file: { name: string; meta: CadFileMeta | null } | null, meta?: CadSnapshotMeta) => void): () => void;
|
|
34
44
|
/** Every page of the drawing, by id. Returns an unsubscribe function. */
|
|
35
|
-
subscribePages(cb: (pages: Record<string, CadPageDoc
|
|
45
|
+
subscribePages(cb: (pages: Record<string, CadPageDoc>, meta?: CadSnapshotMeta) => void): () => void;
|
|
36
46
|
writeMeta(meta: CadFileMeta): Promise<void>;
|
|
37
47
|
writePage(id: string, page: CadPageDoc): Promise<void>;
|
|
38
48
|
deletePage(id: string): Promise<void>;
|
|
@@ -54,14 +64,19 @@ export interface CadDataProvider {
|
|
|
54
64
|
export interface CadMeasurementValue { kind: 'length' | 'angle'; value: number }
|
|
55
65
|
|
|
56
66
|
/**
|
|
57
|
-
* The drawing's measurements in BOLDR
|
|
58
|
-
*
|
|
67
|
+
* The drawing's own measurements in BOLDR (scoped to the drawing's file): the ones an earlier version kept for each
|
|
68
|
+
* driving dimension. They still follow their dimensions, and changing one elsewhere changes its dimension; no new ones
|
|
69
|
+
* are made (a dimension is saved to the group through CadEditorProps.links instead).
|
|
59
70
|
*/
|
|
60
71
|
export interface CadMeasurements {
|
|
61
|
-
|
|
72
|
+
/** No longer called: kept so an older host still type-checks. */
|
|
73
|
+
create?(m: CadMeasurementValue): Promise<string>;
|
|
62
74
|
update(id: string, value: number): Promise<void>;
|
|
63
75
|
/** The drawing's measurements, by id. Returns an unsubscribe function. */
|
|
64
76
|
subscribe(cb: (values: Record<string, CadMeasurementValue>) => void): () => void;
|
|
65
|
-
/**
|
|
66
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Record which measurements the drawing shows (for "Associated Files"): its own (`ids`, in the drawing's group), and
|
|
79
|
+
* the job's it's linked to (`linked`, each in its own group; a form's with its column). All of them, every time.
|
|
80
|
+
*/
|
|
81
|
+
setPlaced?(ids: string[], linked?: { groupId: string; id: string; columnId?: string }[]): Promise<void>;
|
|
67
82
|
}
|