@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/README.md
CHANGED
|
@@ -21,9 +21,10 @@ Peer dependencies:
|
|
|
21
21
|
| `react-native` | `>=0.74` | always (react-native-web in a browser) |
|
|
22
22
|
| `@shopify/react-native-skia` | `>=2.5` | the editor on iOS and Android |
|
|
23
23
|
| `react-native-gesture-handler`| `>=2.31` | the editor on iOS and Android |
|
|
24
|
+
| `react-native-reanimated` | `>=4` | the editor on iOS and Android (pan and zoom run on the UI thread; its Babel plugin must be in the app's config) |
|
|
24
25
|
| `react-native-svg` | `>=15` | the editor's icons on iOS and Android |
|
|
25
26
|
|
|
26
|
-
Only `./core` (see below) runs without the
|
|
27
|
+
Only `./core` (see below) runs without the four native packages.
|
|
27
28
|
|
|
28
29
|
## How it resolves
|
|
29
30
|
|
|
@@ -101,14 +102,15 @@ lives in the browser's own storage, which is what the dev harness uses.
|
|
|
101
102
|
| ------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
102
103
|
| `sync` | `CadSync` | The drawing, from `openCadDrawing`. Saved there as it changes. |
|
|
103
104
|
| `onBack` | `() => void` | The top bar's back button. Without it, Back opens the project's pages. |
|
|
104
|
-
| `headerRight` | `ReactNode`
|
|
105
|
+
| `headerRight` | `ReactNode \| (buttonSize: number) => ReactNode` | The host's own buttons in the top bar, such as a Bluetooth status icon. As a function it gets the bar's round-button size (42 pt on a phone, 46 otherwise). |
|
|
105
106
|
| `theme` | `'light' \| 'dark'` | Canvas colors. The chrome is dark either way. Without it, the person's Theme setting decides. |
|
|
106
|
-
| `units` | `{ format: (inches: number) => string; metric: boolean; denom?: number }` | Lengths the host's way.
|
|
107
|
+
| `units` | `{ format: (inches: number) => string; metric: boolean; unit?: Unit; fractions?: boolean; denom?: number }` | Lengths the host's way: how to write one, the unit a bare number is typed in (`unit`: `ftin`, `in`, `ft`, `mm`, `cm` or `m`; `metric` alone means `mm`), whether they're typed with fractions, and the fraction precision. Settings' Units then offers Account beside the editor's own. |
|
|
107
108
|
| `fonts` | `SkiaFonts` | Typefaces for text on the plan by CSS weight, with a fallback. Device only. |
|
|
108
109
|
| `pickImage` | `() => Promise<{ dataUrl: string; w: number; h: number } \| null>` | A photo or plan to trace. In a browser a file picker is the default. |
|
|
109
110
|
| `saveFile` | `(name: string, mime: string, data: string) => void` | How exports (PDF, DXF, project file) reach the person, e.g. a share sheet. In a browser they download. |
|
|
110
|
-
| `readOnly` | `boolean` | Pan and zoom only, nothing saved.
|
|
111
|
+
| `readOnly` | `boolean` | Pan and zoom only, nothing saved. A tap on a link's tile asks, then opens it. |
|
|
111
112
|
| `devTools` | `boolean` | Reset to the demo, open and save project files, in Settings. Default `true`; turn off in production. |
|
|
113
|
+
| `links` | `CadLinks` | The job's files to link on the drawing, and its lengths for lines (see below). Without it there's nothing to link. |
|
|
112
114
|
|
|
113
115
|
Fonts on a device, with react-native-skia:
|
|
114
116
|
|
|
@@ -130,8 +132,8 @@ taken in when they aren't being edited locally.
|
|
|
130
132
|
|
|
131
133
|
```ts
|
|
132
134
|
interface CadDataProvider {
|
|
133
|
-
subscribeFile(cb: (file: { name: string; meta: CadFileMeta | null } | null) => void): () => void;
|
|
134
|
-
subscribePages(cb: (pages: Record<string, CadPageDoc
|
|
135
|
+
subscribeFile(cb: (file: { name: string; meta: CadFileMeta | null } | null, meta?: CadSnapshotMeta) => void): () => void;
|
|
136
|
+
subscribePages(cb: (pages: Record<string, CadPageDoc>, meta?: CadSnapshotMeta) => void): () => void;
|
|
135
137
|
writeMeta(meta: CadFileMeta): Promise<void>;
|
|
136
138
|
writePage(id: string, page: CadPageDoc): Promise<void>;
|
|
137
139
|
deletePage(id: string): Promise<void>;
|
|
@@ -148,19 +150,100 @@ page document per page (`name`, the sketch, the underlay, and the `rev` of
|
|
|
148
150
|
the session that wrote it last). Storage paths are relative to the drawing's
|
|
149
151
|
own folder, so copying or moving a drawing with its folder keeps it working.
|
|
150
152
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
`CadSnapshotMeta` says whether a snapshot is the local cache's word
|
|
154
|
+
(`fromCache: true`) or the server's. Firestore answers from the cache first
|
|
155
|
+
when it's offline, and for a drawing never opened on that device the cache has
|
|
156
|
+
no pages: the editor then waits for the server rather than starting a blank
|
|
157
|
+
first page over the real one. Pass `snapshot.metadata.fromCache` from both
|
|
158
|
+
listeners and subscribe with `includeMetadataChanges: true`, so the server's
|
|
159
|
+
confirmation of an empty collection still arrives.
|
|
160
|
+
|
|
161
|
+
Options: `initialize: true` says the file was just created here, so its first
|
|
162
|
+
page is made without waiting for the server (and starts a new drawing when the
|
|
163
|
+
file has no drawing record yet); `onError` hears about failed writes and
|
|
164
|
+
uploads; `signal` (an `AbortSignal`) closes the drawing while it's still
|
|
165
|
+
opening, rejecting with `Error('closed')`. The promise rejects with
|
|
166
|
+
`NotACadDrawing` whose `reason` is `'missing'` (no such file) or `'legacy'` (a
|
|
167
|
+
file from the retired layout tool).
|
|
155
168
|
|
|
156
169
|
The returned `CadSync` has `stop()`, `idle()` (resolves once every write so
|
|
157
170
|
far has finished), `saveThumbnail(pngDataUrl)` and `imageUrl(ref)`.
|
|
158
171
|
|
|
159
|
-
**Measurements.**
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
172
|
+
**Measurements.** A dimension drawn in the editor is the drawing's alone: no
|
|
173
|
+
measurement is made for it. The person saves one to the drawing's group from
|
|
174
|
+
its bar (Save to group, through `links.saveMeasurement`), and it's linked to
|
|
175
|
+
that measurement from then on. Drawings made by earlier versions kept every
|
|
176
|
+
driving dimension as a measurement of the drawing's file; when the provider
|
|
177
|
+
supplies `measurements`, those still follow their dimensions both ways
|
|
178
|
+
(`create` is no longer called). `setPlaced(ids, linked)` hears every
|
|
179
|
+
measurement the drawing shows: its own, and the job's it's linked to, each with
|
|
180
|
+
its group (and a form's column). `measurementOf(constraint)` gives a
|
|
181
|
+
constraint's value as BOLDR keeps it — lengths in micrometres, angles in
|
|
182
|
+
degrees — or `null` for reference and print dimensions and linked ones.
|
|
183
|
+
|
|
184
|
+
### Linking the job's files and measurements
|
|
185
|
+
|
|
186
|
+
With `links`, Annotate gets a yellow + (under the rail; a phone's in the
|
|
187
|
+
trash's corner while nothing's selected) that puts the job's files on the plan
|
|
188
|
+
as tiles, with leaders, opened from the bar. A measurement comes into a drawing
|
|
189
|
+
only as the dimension it drives: in Draft, a line's length keypad (select the
|
|
190
|
+
line, tap +) offers the job's lengths (a page it swipes to on a touch screen,
|
|
191
|
+
Select from list on a desktop), and the one picked sets the line, linked to
|
|
192
|
+
it. A dimension is saved to the group from its bar (Save to group). A new length for a linked dimension asks first: Change both, Only this
|
|
193
|
+
drawing (unlinks), or Cancel.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
interface CadLinks {
|
|
197
|
+
pick(req: { want: 'files'; linked: LinkTarget[] }): Promise<LinkTarget[]>; // [] for nothing
|
|
198
|
+
measurements?(cb: (list: LinkTarget[]) => void): () => void; // the job's lengths and angles, in the order to show them
|
|
199
|
+
pickMeasurement?(req: { kind: 'length' | 'angle' }): Promise<LinkTarget | null>; // the host's own list (a side drawer)
|
|
200
|
+
subscribe(targets: LinkTarget[], cb: (info: Record<string, LinkInfo>) => void): () => void;
|
|
201
|
+
open(target: LinkTarget): void;
|
|
202
|
+
update?(target: LinkTarget, value: number, capture?: unknown): void; // µm or degrees, the person having said so
|
|
203
|
+
saveMeasurement?(m: { kind: 'length' | 'angle'; value: number; capture?: unknown }): Promise<LinkTarget | null>;
|
|
204
|
+
canSave?: boolean; // false where a measurement can't be saved (a form's group)
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- A `LinkTarget` is `{ kind: 'file' | 'measurement', id, groupId, columnId? }`
|
|
209
|
+
plus what it was when it was linked (`name`, `groupName`, `fileType`,
|
|
210
|
+
`mkind`, `value`, `text`). Resolve it by `groupId` and `id` in the job open
|
|
211
|
+
now, never by a stored path, so copied and moved jobs keep working.
|
|
212
|
+
- `pick` offers the job's files to pick. BOLDR's pickers show the measurements
|
|
213
|
+
too, greyed out, and a tap on one says they're added in Draft; anything but
|
|
214
|
+
a file handed back is dropped.
|
|
215
|
+
- A line's length keypad and a dimension's angle keypad take the job's
|
|
216
|
+
measurements. On a touch screen the keypad swipes to a page of them; on a
|
|
217
|
+
desktop it has Select from list, which calls `pickMeasurement` (the host's
|
|
218
|
+
own list, those of `kind` pickable and the rest greyed out), or shows that
|
|
219
|
+
page when the host has none. `measurements` calls back with the job's
|
|
220
|
+
lengths and angles as measurement targets (with `mkind`, `value` in
|
|
221
|
+
micrometres or degrees, and `text`), again as they change, and not until
|
|
222
|
+
the whole job's been heard from; the keypad greys out those that aren't its
|
|
223
|
+
kind. A host keypad (`keypad`) gets `measurementKind` and `pickMeasurement`
|
|
224
|
+
on such a request: show the job's measurements a swipe away, greying out
|
|
225
|
+
the other kind, and hand back the one tapped.
|
|
226
|
+
- To draw that page itself, so the list looks as it does everywhere else in
|
|
227
|
+
the host, pass `measurementList` to `CadEditor`: a function of
|
|
228
|
+
`{ kind, pick, width, height }` that returns the list's element (for
|
|
229
|
+
example `page => <JobList {...page} />`). It's rendered as a component of its
|
|
230
|
+
own from when the page is first shown, and again when what it's given
|
|
231
|
+
changes. List the job's measurements at that size, grey out the other kind,
|
|
232
|
+
and call `pick` with the one tapped. BOLDR does on a tablet, with its phone
|
|
233
|
+
keypad's list. Without it the page is the editor's own grid, made from
|
|
234
|
+
`measurements`. Either way the page is there only when `links` has
|
|
235
|
+
`measurements` or `pickMeasurement`, and a desktop shows it only without
|
|
236
|
+
`pickMeasurement`.
|
|
237
|
+
- `subscribe` answers by `linkKey(target)`, and again whenever that changes.
|
|
238
|
+
Say `exists: false` only once it's known to be gone, never while loading.
|
|
239
|
+
`text` is the value written the host's way; `thumbUrl` a picture to show.
|
|
240
|
+
- Pass one `links` object for as long as the drawing is open (memoize it).
|
|
241
|
+
|
|
242
|
+
**Laser readings.** `laserReading(inches, capture)` takes the host's own record
|
|
243
|
+
of a reading (anything JSON: its device, its number). It's kept on the
|
|
244
|
+
dimension the reading sets and handed back with `saveMeasurement`, or with
|
|
245
|
+
`update` for a linked one, so a measurement saved from a reading records its
|
|
246
|
+
device. A value typed over it isn't the reading's.
|
|
164
247
|
|
|
165
248
|
For tests and prototypes, `memoryProvider()` is an in-memory provider with
|
|
166
249
|
`remote()` and `remoteMeasurement()` to change things as another device would.
|
|
@@ -171,7 +254,7 @@ For tests and prototypes, `memoryProvider()` is an in-memory provider with
|
|
|
171
254
|
import { setLaserConnected, laserReading } from '@reekon-tools/boldr-cad';
|
|
172
255
|
|
|
173
256
|
setLaserConnected(true); // shows the reading tray, enables the keypad's Laser key
|
|
174
|
-
laserReading(inches);
|
|
257
|
+
laserReading(inches, capture); // into an open keypad, onto the selected wall, or into the tray
|
|
175
258
|
```
|
|
176
259
|
|
|
177
260
|
`laserReading` returns `false` when no drawing is open to take the value, so
|
package/dist/app/edit.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import type { Constraint, SelItem } from '../model/types';
|
|
1
|
+
import type { Constraint, SelItem, Sketch } from '../model/types';
|
|
2
2
|
import { type AddResult, type SolveResult } from '../solver';
|
|
3
3
|
export declare function analyze(): void;
|
|
4
4
|
export declare const solveSketch: (heavy?: string[]) => SolveResult;
|
|
5
5
|
export declare function solveOrRevert(): SolveResult;
|
|
6
|
+
/**
|
|
7
|
+
* Walls made thicker or thinner, or lines turned into walls: what's measured on walls' faces holds, their centrelines
|
|
8
|
+
* moving to keep it (a face's length depends on the walls at its corners as well as its own). False — and nothing
|
|
9
|
+
* moved — when it can't hold.
|
|
10
|
+
*/
|
|
11
|
+
export declare function holdFaces(): boolean;
|
|
6
12
|
/** Re-place locked doors/windows from their dimensions (after any geometry change). */
|
|
7
13
|
export declare function resolveOpeningsNow(): void;
|
|
8
14
|
export declare function existsSel(s: SelItem): boolean;
|
|
@@ -10,6 +16,11 @@ export declare function existsSel(s: SelItem): boolean;
|
|
|
10
16
|
export declare function afterEdit(): void;
|
|
11
17
|
export declare function undo(): void;
|
|
12
18
|
export declare function redo(): void;
|
|
19
|
+
/**
|
|
20
|
+
* The things a constraint ties together, each as the points to hold for it: a cabinet (its corners, when it's one of
|
|
21
|
+
* its edges or corners), a line (its ends), a point.
|
|
22
|
+
*/
|
|
23
|
+
export declare function holdGroups(sk: Sketch, c: Constraint): string[][];
|
|
13
24
|
/**
|
|
14
25
|
* Add a constraint through the solver and explain the outcome:
|
|
15
26
|
* reference dimension → toast, conflict → conflict sheet (unless silent).
|
package/dist/app/edit.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
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';
|
|
9
|
+
import { page, planSK, saveSoon, SK } from '../model/store';
|
|
10
|
+
import { cabOfPoint, cabPoints } from '../model/faces';
|
|
7
11
|
import { requestDraw } from '../render/view';
|
|
8
12
|
import { solver } from '../solver';
|
|
9
13
|
import { cancelTool } from '../tools/registry';
|
|
10
14
|
import { fmtLen } from '../units';
|
|
11
15
|
import { ed } from './state';
|
|
12
16
|
import { refreshDrawerSoon, renderElevation, showConflict, toast, updateCtx, updateStatus } from '../editor/ports';
|
|
17
|
+
import { refreshLinks } from '../editor/links';
|
|
18
|
+
import { followLinked } from '../editor/linkFollow';
|
|
13
19
|
export function analyze() {
|
|
14
20
|
ed.ana = solver.analyzeDOF(SK());
|
|
15
21
|
}
|
|
@@ -21,9 +27,19 @@ export function solveOrRevert() {
|
|
|
21
27
|
restorePos(sk, snap);
|
|
22
28
|
return s;
|
|
23
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Walls made thicker or thinner, or lines turned into walls: what's measured on walls' faces holds, their centrelines
|
|
32
|
+
* moving to keep it (a face's length depends on the walls at its corners as well as its own). False — and nothing
|
|
33
|
+
* moved — when it can't hold.
|
|
34
|
+
*/
|
|
35
|
+
export function holdFaces() {
|
|
36
|
+
if (!Object.values(SK().cons).some(c => c.face || c.faces))
|
|
37
|
+
return true;
|
|
38
|
+
return solveOrRevert().ok;
|
|
39
|
+
}
|
|
24
40
|
/** Re-place locked doors/windows from their dimensions (after any geometry change). */
|
|
25
41
|
export function resolveOpeningsNow() {
|
|
26
|
-
ed.badOpeningDims = resolveOpenings(
|
|
42
|
+
ed.badOpeningDims = resolveOpenings(planSK());
|
|
27
43
|
}
|
|
28
44
|
export function existsSel(s) {
|
|
29
45
|
const sk = SK();
|
|
@@ -35,21 +51,28 @@ export function existsSel(s) {
|
|
|
35
51
|
case 'cons':
|
|
36
52
|
case 'dim': return !!sk.cons[s.id];
|
|
37
53
|
case 'room': return !!sk.rooms[s.id];
|
|
38
|
-
case 'opening': return !!
|
|
54
|
+
case 'opening': return !!planSK().openings[s.id];
|
|
55
|
+
case 'cab': return !!sk.cabs?.[s.id];
|
|
56
|
+
case 'elev': return true;
|
|
57
|
+
case 'oanchor': return !!planSK().openings[s.id.split('|')[0]];
|
|
58
|
+
case 'wface': return !!wallOf(sk, edgeOf(s.id)[0]);
|
|
39
59
|
case 'odim': {
|
|
40
|
-
const [op, part] = s.id.split('|'), o =
|
|
41
|
-
return !!o && (part.startsWith('d:') ? (o.dims || []).some(d => d.id === part.slice(2)) : !drivingDim(o));
|
|
60
|
+
const [op, part] = s.id.split('|'), o = planSK().openings[op];
|
|
61
|
+
return !!o && (part === 'w' || (part.startsWith('d:') ? (o.dims || []).some(d => d.id === part.slice(2)) : !drivingDim(o)));
|
|
42
62
|
}
|
|
43
63
|
case 'note': return sk.notes.some(n => n.id === s.id);
|
|
44
|
-
case 'underlay': return
|
|
64
|
+
case 'underlay': return page().underlays.some(u => u.id === s.id);
|
|
45
65
|
}
|
|
46
66
|
return false;
|
|
47
67
|
}
|
|
48
68
|
/** Run after every model change: clean up, re-analyze, refresh UI, autosave. */
|
|
49
69
|
export function afterEdit() {
|
|
50
70
|
ed.editSeq++;
|
|
51
|
-
gc(
|
|
71
|
+
gc(planSK()); // the plan, and each wall face
|
|
52
72
|
resolveOpeningsNow();
|
|
73
|
+
// what's drawn on wall faces follows the plan's corners, doors and windows
|
|
74
|
+
ed.badFaceCons = syncFaces(planSK());
|
|
75
|
+
elevSyncFrame(); // the open wall's frame (its length, its corners) as the plan has it now
|
|
53
76
|
ed.sel = ed.sel.filter(s => existsSel(s));
|
|
54
77
|
analyze();
|
|
55
78
|
updateCtx();
|
|
@@ -57,11 +80,13 @@ export function afterEdit() {
|
|
|
57
80
|
refreshDrawerSoon();
|
|
58
81
|
requestDraw();
|
|
59
82
|
renderElevation();
|
|
83
|
+
refreshLinks(); // (what's linked may have changed: the host is asked about it)
|
|
84
|
+
followLinked(); // (and an undo may have put a linked dimension at something else than the job says)
|
|
60
85
|
saveSoon();
|
|
61
86
|
}
|
|
62
87
|
export function undo() {
|
|
63
88
|
if (!HS().u.length) {
|
|
64
|
-
toast('Nothing to undo');
|
|
89
|
+
toast('Nothing to undo', { warn: true });
|
|
65
90
|
return;
|
|
66
91
|
}
|
|
67
92
|
cancelTool();
|
|
@@ -75,7 +100,7 @@ export function redo() {
|
|
|
75
100
|
if (!h.u.length && !h.r.length)
|
|
76
101
|
return;
|
|
77
102
|
if (!h.r.length) {
|
|
78
|
-
toast('Nothing to redo');
|
|
103
|
+
toast('Nothing to redo', { warn: true });
|
|
79
104
|
return;
|
|
80
105
|
}
|
|
81
106
|
cancelTool();
|
|
@@ -84,12 +109,72 @@ export function redo() {
|
|
|
84
109
|
afterEdit();
|
|
85
110
|
toast('Redone');
|
|
86
111
|
}
|
|
112
|
+
/** Solve with these points held exactly where they are (fixed for the solve, then as they were). */
|
|
113
|
+
function solveHolding(sk, hold) {
|
|
114
|
+
const pts = hold.map(id => sk.points[id]).filter(Boolean), had = pts.map(p => p.fixed);
|
|
115
|
+
pts.forEach(p => { p.fixed = true; });
|
|
116
|
+
const s = solver.solve(sk);
|
|
117
|
+
pts.forEach((p, i) => { if (had[i])
|
|
118
|
+
p.fixed = true;
|
|
119
|
+
else
|
|
120
|
+
delete p.fixed; });
|
|
121
|
+
return s;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The things a constraint ties together, each as the points to hold for it: a cabinet (its corners, when it's one of
|
|
125
|
+
* its edges or corners), a line (its ends), a point.
|
|
126
|
+
*/
|
|
127
|
+
export function holdGroups(sk, c) {
|
|
128
|
+
const face = sk, groups = [], seen = new Set();
|
|
129
|
+
const add = (key, pts) => { if (!seen.has(key) && pts.length) {
|
|
130
|
+
seen.add(key);
|
|
131
|
+
groups.push(pts);
|
|
132
|
+
} };
|
|
133
|
+
const point = (pid) => {
|
|
134
|
+
if (!pid || !sk.points[pid])
|
|
135
|
+
return;
|
|
136
|
+
const cab = cabOfPoint(sk, pid);
|
|
137
|
+
if (cab)
|
|
138
|
+
add('cab:' + cab, cabPoints(face.cabs[cab]));
|
|
139
|
+
else
|
|
140
|
+
add('pt:' + pid, [pid]);
|
|
141
|
+
};
|
|
142
|
+
for (const lid of [c.l, c.l1, c.l2, c.line]) {
|
|
143
|
+
const l = lid ? sk.lines[lid] : undefined;
|
|
144
|
+
if (!l)
|
|
145
|
+
continue;
|
|
146
|
+
if (l.cab && face.cabs?.[l.cab])
|
|
147
|
+
add('cab:' + l.cab, cabPoints(face.cabs[l.cab]));
|
|
148
|
+
else
|
|
149
|
+
add('line:' + lid, [l.a, l.b]);
|
|
150
|
+
}
|
|
151
|
+
for (const pid of [c.a, c.b, c.p])
|
|
152
|
+
point(pid);
|
|
153
|
+
return groups;
|
|
154
|
+
}
|
|
87
155
|
/**
|
|
88
156
|
* Add a constraint through the solver and explain the outcome:
|
|
89
157
|
* reference dimension → toast, conflict → conflict sheet (unless silent).
|
|
90
158
|
*/
|
|
91
159
|
export function tryAddConstraint(c, { silent = false, onResolved = null } = {}) {
|
|
92
|
-
|
|
160
|
+
// nothing may be pushed past its wall (in the wall view, past the wall; in the plan, a wall made shorter than
|
|
161
|
+
// what's on it): a constraint that would is taken back
|
|
162
|
+
const sk = SK(), was = overflow(sk), held = fitState(sk);
|
|
163
|
+
const r = solver.addConstraint(sk, c, { explain: !silent });
|
|
164
|
+
// met by moving everything a little, it ran past the wall: try keeping each thing it ties still in turn, so the
|
|
165
|
+
// 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)
|
|
166
|
+
if (r.ok && r.id && !r.ref && pushedOut(was, overflow(sk))) {
|
|
167
|
+
for (const hold of holdGroups(sk, c)) {
|
|
168
|
+
restoreFit(sk, held);
|
|
169
|
+
if (solveHolding(sk, hold).ok && !pushedOut(was, overflow(sk)))
|
|
170
|
+
return r;
|
|
171
|
+
}
|
|
172
|
+
delete sk.cons[r.id];
|
|
173
|
+
restoreFit(sk, held);
|
|
174
|
+
if (!silent)
|
|
175
|
+
toast(pastWallMsg(), { warn: true });
|
|
176
|
+
return { ok: false };
|
|
177
|
+
}
|
|
93
178
|
if (silent)
|
|
94
179
|
return r;
|
|
95
180
|
if (r.ref) {
|
|
@@ -98,7 +183,7 @@ export function tryAddConstraint(c, { silent = false, onResolved = null } = {})
|
|
|
98
183
|
: 'Kept as a reference dimension (' + fmtLen(c.value) + '). Other constraints already set this value — remove one to drive it.', { warn: !r.refSame });
|
|
99
184
|
}
|
|
100
185
|
else if (r.redundant) {
|
|
101
|
-
toast(CONS_LABEL[c.type] + ' is already true — other constraints set it.');
|
|
186
|
+
toast(CONS_LABEL[c.type] + ' is already true — other constraints set it.', { warn: true });
|
|
102
187
|
}
|
|
103
188
|
else if (r.conflict === 'dependent') {
|
|
104
189
|
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 });
|
package/dist/app/edit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/app/edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/app/edit.ts"],"names":[],"mappings":"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"}
|
package/dist/app/state.d.ts
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
|
+
import { type NoteStyle } from '../model/markup';
|
|
1
2
|
import type { Analysis, OpeningEdge, SelItem, SelType } from '../model/types';
|
|
2
3
|
import type { Xform } from '../render/view';
|
|
3
4
|
import type { DrawCtx } from '../render/ctx';
|
|
4
5
|
export type Mode = 'draft' | 'annotate';
|
|
5
6
|
/** Something under the pointer: geometry, or a chip/badge drawn on the canvas. */
|
|
6
7
|
export interface Hit {
|
|
7
|
-
|
|
8
|
+
/** 'cabfoot': a cabinet's footprint in the plan (id: its wall face's key, '#', its id) */
|
|
9
|
+
type: SelType | 'odim' | 'oanchor' | 'uhandle' | 'nhandle' | 'cabfoot';
|
|
8
10
|
id: string;
|
|
9
11
|
/** a print dimension label */
|
|
10
12
|
print?: boolean;
|
|
11
13
|
/** low-priority hit (room fill) */
|
|
12
14
|
weak?: boolean;
|
|
13
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* 'odim': 'w' width, 'a'/'b' distance to a wall end, or 'd:<id>' a placed dimension. 'oanchor': 's0'/'s1' edge.
|
|
17
|
+
* 'note', a link's tile: 'tip' its leader's tip, 'leader' along its leader (unset: its card).
|
|
18
|
+
*/
|
|
14
19
|
part?: string;
|
|
20
|
+
/** 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) */
|
|
21
|
+
side?: 1 | -1;
|
|
15
22
|
}
|
|
16
23
|
export type OpeningDimPart = 'w' | 'a' | 'b' | `d:${string}`;
|
|
17
24
|
export interface Guide {
|
|
@@ -37,7 +44,8 @@ export interface Snap {
|
|
|
37
44
|
}
|
|
38
45
|
/** Screen-space hit region registered while drawing chips, badges and labels. */
|
|
39
46
|
export interface HitChip {
|
|
40
|
-
|
|
47
|
+
/** 'elev': one of the wall view's dimension chips (id: what it measures, as JSON) */
|
|
48
|
+
kind: 'dim' | 'pdim' | 'cons' | 'room' | 'odim' | 'elev';
|
|
41
49
|
part?: string;
|
|
42
50
|
id: string;
|
|
43
51
|
x: number;
|
|
@@ -69,11 +77,20 @@ export declare const ed: {
|
|
|
69
77
|
ana: Analysis;
|
|
70
78
|
lastPointerTouch: boolean;
|
|
71
79
|
drawConstr: boolean;
|
|
80
|
+
/** the rail's Walls toggle: what's drawn (lines, rectangles, circles, arcs, Draw to shape) is walls */
|
|
81
|
+
drawWalls: boolean;
|
|
72
82
|
dimLayer: 'drive' | 'print';
|
|
73
83
|
openingType: 'door' | 'window';
|
|
84
|
+
/** new markup's look (the stroke panel sets them; selected markup changes with them) */
|
|
74
85
|
noteColor: string;
|
|
86
|
+
noteWidth: number;
|
|
87
|
+
noteStyle: NoteStyle;
|
|
88
|
+
/** new text notes' letter height on the drawing, inches */
|
|
89
|
+
noteTextIn: number;
|
|
75
90
|
/** opening dimensions that can't be met (drawn red) */
|
|
76
91
|
badOpeningDims: Set<string>;
|
|
92
|
+
/** wall-face constraints that can't be met (drawn red in the elevation) */
|
|
93
|
+
badFaceCons: Set<string>;
|
|
77
94
|
/** dimension tool: an opening edge picked as the first end */
|
|
78
95
|
/** body: the opening itself was tapped (not an edge square), so the edge is chosen from what it's measured to */
|
|
79
96
|
pickedAnchor: {
|
|
@@ -83,9 +100,19 @@ export declare const ed: {
|
|
|
83
100
|
} | null;
|
|
84
101
|
/** bumped on every model change (so a double tap can't span an edit) */
|
|
85
102
|
editSeq: number;
|
|
103
|
+
/** the side a wall was last tapped on, picking it whole: between two spaces, its length is measured on that side */
|
|
104
|
+
wallTap: {
|
|
105
|
+
id: string;
|
|
106
|
+
side: 1 | -1;
|
|
107
|
+
} | null;
|
|
86
108
|
/** recently hovered points, used for alignment guides */
|
|
87
109
|
recentPts: string[];
|
|
88
110
|
/** view only: pan and zoom, no tools, nothing saved (people who can't edit this job) */
|
|
89
111
|
readOnly: boolean;
|
|
90
112
|
};
|
|
91
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Whether something is selected. Drawing asks it of everything on the plan, every frame: with many things selected (a
|
|
115
|
+
* double tap takes in every wall joined to one) that was each against each, so a larger selection is looked up in a
|
|
116
|
+
* set, made again only when the selection changes (it's replaced, or added to).
|
|
117
|
+
*/
|
|
118
|
+
export declare function isSel(type: string, id: string): boolean;
|
package/dist/app/state.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { emptyAnalysis } from '../model/constraints';
|
|
2
|
+
import { DEFAULT_NOTE_COLOR, DEFAULT_NOTE_WIDTH, NOTE_TEXT_IN } from '../model/markup';
|
|
2
3
|
import { sessionState } from '../model/session';
|
|
3
4
|
/** Shared editor state (the prototype's module-level `let`s). */
|
|
4
5
|
export const ed = sessionState(() => ({
|
|
@@ -16,20 +17,48 @@ export const ed = sessionState(() => ({
|
|
|
16
17
|
ana: emptyAnalysis(),
|
|
17
18
|
lastPointerTouch: false,
|
|
18
19
|
drawConstr: false,
|
|
20
|
+
/** the rail's Walls toggle: what's drawn (lines, rectangles, circles, arcs, Draw to shape) is walls */
|
|
21
|
+
drawWalls: false,
|
|
19
22
|
dimLayer: 'drive',
|
|
20
23
|
openingType: 'door',
|
|
21
|
-
|
|
24
|
+
/** new markup's look (the stroke panel sets them; selected markup changes with them) */
|
|
25
|
+
noteColor: DEFAULT_NOTE_COLOR,
|
|
26
|
+
noteWidth: DEFAULT_NOTE_WIDTH,
|
|
27
|
+
noteStyle: 'solid',
|
|
28
|
+
/** new text notes' letter height on the drawing, inches */
|
|
29
|
+
noteTextIn: NOTE_TEXT_IN,
|
|
22
30
|
/** opening dimensions that can't be met (drawn red) */
|
|
23
31
|
badOpeningDims: new Set(),
|
|
32
|
+
/** wall-face constraints that can't be met (drawn red in the elevation) */
|
|
33
|
+
badFaceCons: new Set(),
|
|
24
34
|
/** dimension tool: an opening edge picked as the first end */
|
|
25
35
|
/** body: the opening itself was tapped (not an edge square), so the edge is chosen from what it's measured to */
|
|
26
36
|
pickedAnchor: null,
|
|
27
37
|
/** bumped on every model change (so a double tap can't span an edit) */
|
|
28
38
|
editSeq: 0,
|
|
39
|
+
/** the side a wall was last tapped on, picking it whole: between two spaces, its length is measured on that side */
|
|
40
|
+
wallTap: null,
|
|
29
41
|
/** recently hovered points, used for alignment guides */
|
|
30
42
|
recentPts: [],
|
|
31
43
|
/** view only: pan and zoom, no tools, nothing saved (people who can't edit this job) */
|
|
32
44
|
readOnly: false,
|
|
33
45
|
}));
|
|
34
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Whether something is selected. Drawing asks it of everything on the plan, every frame: with many things selected (a
|
|
48
|
+
* double tap takes in every wall joined to one) that was each against each, so a larger selection is looked up in a
|
|
49
|
+
* set, made again only when the selection changes (it's replaced, or added to).
|
|
50
|
+
*/
|
|
51
|
+
export function isSel(type, id) {
|
|
52
|
+
const sel = ed.sel;
|
|
53
|
+
if (sel.length < 8) {
|
|
54
|
+
for (const s of sel)
|
|
55
|
+
if (s.type === type && s.id === id)
|
|
56
|
+
return true;
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (!selKeys || selKeys.sel !== sel || selKeys.n !== sel.length)
|
|
60
|
+
selKeys = { sel, n: sel.length, keys: new Set(sel.map(s => s.type + ' ' + s.id)) };
|
|
61
|
+
return selKeys.keys.has(type + ' ' + id);
|
|
62
|
+
}
|
|
63
|
+
let selKeys = null;
|
|
35
64
|
//# sourceMappingURL=state.js.map
|
package/dist/app/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/app/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/app/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,YAAY,EAAkB,MAAM,iBAAiB,CAAC;AAGvG,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA0DhD,iEAAiE;AACjE,MAAM,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC;IACpC,IAAI,EAAE,OAAe;IACrB,IAAI,EAAE,QAAQ;IACd,GAAG,EAAE,EAAe;IACpB,KAAK,EAAE,IAAkB;IACzB,SAAS,EAAE,IAAmB;IAC9B,MAAM,EAAE,IAAqB;IAC7B,OAAO,EAAE,IAAsB;IAC/B,SAAS,EAAE,IAAI,GAAG,EAAU;IAC5B,YAAY,EAAE,KAAK;IACnB,+FAA+F;IAC/F,QAAQ,EAAE,EAAe;IACzB,GAAG,EAAE,aAAa,EAAc;IAChC,gBAAgB,EAAE,KAAK;IACvB,UAAU,EAAE,KAAK;IACjB,uGAAuG;IACvG,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,OAA4B;IACtC,WAAW,EAAE,MAA2B;IACxC,wFAAwF;IACxF,SAAS,EAAE,kBAAkB;IAC7B,SAAS,EAAE,kBAAkB;IAC7B,SAAS,EAAE,OAAoB;IAC/B,2DAA2D;IAC3D,UAAU,EAAE,YAAY;IACxB,uDAAuD;IACvD,cAAc,EAAE,IAAI,GAAG,EAAU;IACjC,2EAA2E;IAC3E,WAAW,EAAE,IAAI,GAAG,EAAU;IAC9B,8DAA8D;IAC9D,iHAAiH;IACjH,YAAY,EAAE,IAAgE;IAC9E,wEAAwE;IACxE,OAAO,EAAE,CAAC;IACV,oHAAoH;IACpH,OAAO,EAAE,IAA2C;IACpD,yDAAyD;IACzD,SAAS,EAAE,EAAc;IACzB,wFAAwF;IACxF,QAAQ,EAAE,KAAK;CAChB,CAAC,CAAC,CAAC;AAEJ;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY,EAAE,EAAU;IAC5C,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC;IACnB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,GAAG;YAAE,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE;gBAAE,OAAO,IAAI,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM;QAAE,OAAO,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACpJ,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;AAC3C,CAAC;AACD,IAAI,OAAO,GAA4D,IAAI,CAAC"}
|
package/dist/data/memory.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { CadDataProvider, CadFileMeta, CadMeasurementValue, CadPageDoc } from './provider';
|
|
2
|
-
export declare function memoryProvider(name?: string, meta?: CadFileMeta | null, pages?: Record<string, CadPageDoc
|
|
2
|
+
export declare function memoryProvider(name?: string, meta?: CadFileMeta | null, pages?: Record<string, CadPageDoc>, opts?: {
|
|
3
|
+
fromCache?: boolean;
|
|
4
|
+
}): {
|
|
3
5
|
provider: CadDataProvider;
|
|
4
6
|
state: {
|
|
5
7
|
name: string;
|
|
@@ -11,7 +13,13 @@ export declare function memoryProvider(name?: string, meta?: CadFileMeta | null,
|
|
|
11
13
|
files: Record<string, string>;
|
|
12
14
|
measurements: Record<string, CadMeasurementValue>;
|
|
13
15
|
placed: string[];
|
|
16
|
+
placedLinked: {
|
|
17
|
+
groupId: string;
|
|
18
|
+
id: string;
|
|
19
|
+
columnId?: string;
|
|
20
|
+
}[];
|
|
14
21
|
};
|
|
15
22
|
remote: (id: string, p: CadPageDoc) => void;
|
|
16
23
|
remoteMeasurement: (id: string, value: number) => void;
|
|
24
|
+
confirm: () => void;
|
|
17
25
|
};
|
package/dist/data/memory.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
/* A drawing kept in memory: for tests and the dev harness. `remote` changes it as another device would. */
|
|
2
2
|
const copy = (v) => JSON.parse(JSON.stringify(v));
|
|
3
|
-
export function memoryProvider(name = 'Test drawing', meta = null, pages = {}) {
|
|
3
|
+
export function memoryProvider(name = 'Test drawing', meta = null, pages = {}, opts = {}) {
|
|
4
|
+
// (fromCache: what's here is the cache's word, as a device offline hears it, until confirm() brings the server's)
|
|
5
|
+
let fromCache = !!opts.fromCache;
|
|
6
|
+
const snap = () => ({ fromCache });
|
|
4
7
|
const fileSubs = new Set();
|
|
5
8
|
const pageSubs = new Set();
|
|
6
|
-
const state = { name, meta: meta && copy(meta), pages: copy(pages), writes: 0, uploads: 0, thumbnail: null, files: {}, measurements: {}, placed: [] };
|
|
9
|
+
const state = { name, meta: meta && copy(meta), pages: copy(pages), writes: 0, uploads: 0, thumbnail: null, files: {}, measurements: {}, placed: [], placedLinked: [] };
|
|
7
10
|
const measSubs = new Set();
|
|
8
11
|
const emitMeas = () => measSubs.forEach(cb => cb(copy(state.measurements)));
|
|
9
|
-
const emitFile = () => fileSubs.forEach(cb => cb({ name: state.name, meta: state.meta && copy(state.meta) }));
|
|
10
|
-
const emitPages = () => pageSubs.forEach(cb => cb(copy(state.pages)));
|
|
12
|
+
const emitFile = () => fileSubs.forEach(cb => cb({ name: state.name, meta: state.meta && copy(state.meta) }, snap()));
|
|
13
|
+
const emitPages = () => pageSubs.forEach(cb => cb(copy(state.pages), snap()));
|
|
11
14
|
const provider = {
|
|
12
|
-
subscribeFile(cb) { fileSubs.add(cb); queueMicrotask(() => cb({ name: state.name, meta: state.meta && copy(state.meta) })); return () => { fileSubs.delete(cb); }; },
|
|
13
|
-
subscribePages(cb) { pageSubs.add(cb); queueMicrotask(() => cb(copy(state.pages))); return () => { pageSubs.delete(cb); }; },
|
|
15
|
+
subscribeFile(cb) { fileSubs.add(cb); queueMicrotask(() => cb({ name: state.name, meta: state.meta && copy(state.meta) }, snap())); return () => { fileSubs.delete(cb); }; },
|
|
16
|
+
subscribePages(cb) { pageSubs.add(cb); queueMicrotask(() => cb(copy(state.pages), snap())); return () => { pageSubs.delete(cb); }; },
|
|
14
17
|
async writeMeta(m) { state.meta = copy(m); state.writes++; emitFile(); },
|
|
15
18
|
async writePage(id, p) { state.pages[id] = copy(p); state.writes++; emitPages(); },
|
|
16
19
|
async deletePage(id) { delete state.pages[id]; state.writes++; emitPages(); },
|
|
@@ -23,13 +26,15 @@ export function memoryProvider(name = 'Test drawing', meta = null, pages = {}) {
|
|
|
23
26
|
async create(m) { const id = 'm' + (Object.keys(state.measurements).length + 1); state.measurements[id] = copy(m); emitMeas(); return id; },
|
|
24
27
|
async update(id, value) { state.measurements[id] = { ...state.measurements[id], value }; emitMeas(); },
|
|
25
28
|
subscribe(cb) { measSubs.add(cb); queueMicrotask(() => cb(copy(state.measurements))); return () => { measSubs.delete(cb); }; },
|
|
26
|
-
async setPlaced(ids) { state.placed = ids.slice(); },
|
|
29
|
+
async setPlaced(ids, linked = []) { state.placed = ids.slice(); state.placedLinked = copy(linked); },
|
|
27
30
|
},
|
|
28
31
|
};
|
|
29
32
|
/** Change a page as another device would. */
|
|
30
33
|
const remote = (id, p) => { state.pages[id] = copy(p); emitPages(); };
|
|
31
34
|
/** Change a measurement as someone else would (e.g. in the job's measurement list). */
|
|
32
35
|
const remoteMeasurement = (id, value) => { state.measurements[id] = { ...state.measurements[id], value }; emitMeas(); };
|
|
33
|
-
|
|
36
|
+
/** The server's word after a start from the cache: everything is sent again, confirmed. */
|
|
37
|
+
const confirm = () => { fromCache = false; emitFile(); emitPages(); };
|
|
38
|
+
return { provider, state, remote, remoteMeasurement, confirm };
|
|
34
39
|
}
|
|
35
40
|
//# sourceMappingURL=memory.js.map
|