@dxos/react-ui-canvas 0.13.0 → 0.14.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 +1 -1
- package/dist/lib/index.mjs +9044 -1135
- package/dist/lib/index.mjs.map +1 -1
- package/dist/types/src/components/About/About.d.ts +13 -0
- package/dist/types/src/components/About/About.d.ts.map +1 -0
- package/dist/types/src/components/About/About.stories.d.ts +7 -0
- package/dist/types/src/components/About/About.stories.d.ts.map +1 -0
- package/dist/types/src/components/About/index.d.ts +2 -0
- package/dist/types/src/components/About/index.d.ts.map +1 -0
- package/dist/types/src/components/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/types/src/components/ControlFrame/ControlFrame.d.ts +8 -2
- package/dist/types/src/components/ControlFrame/ControlFrame.d.ts.map +1 -1
- package/dist/types/src/components/Layers/Layers.d.ts +30 -0
- package/dist/types/src/components/Layers/Layers.d.ts.map +1 -0
- package/dist/types/src/components/Layers/Layers.stories.d.ts +11 -0
- package/dist/types/src/components/Layers/Layers.stories.d.ts.map +1 -0
- package/dist/types/src/components/Layers/index.d.ts +2 -0
- package/dist/types/src/components/Layers/index.d.ts.map +1 -0
- package/dist/types/src/components/Palette/Palette.d.ts +20 -4
- package/dist/types/src/components/Palette/Palette.d.ts.map +1 -1
- package/dist/types/src/components/Palette/Palette.stories.d.ts +22 -0
- package/dist/types/src/components/Palette/Palette.stories.d.ts.map +1 -0
- package/dist/types/src/components/PartEditor/PartEditor.d.ts.map +1 -1
- package/dist/types/src/components/Properties/AlignField.d.ts +23 -0
- package/dist/types/src/components/Properties/AlignField.d.ts.map +1 -0
- package/dist/types/src/components/Properties/ClassField.d.ts +23 -0
- package/dist/types/src/components/Properties/ClassField.d.ts.map +1 -0
- package/dist/types/src/components/Properties/FontField.d.ts +7 -0
- package/dist/types/src/components/Properties/FontField.d.ts.map +1 -0
- package/dist/types/src/components/Properties/LayerField.d.ts +17 -0
- package/dist/types/src/components/Properties/LayerField.d.ts.map +1 -0
- package/dist/types/src/components/Properties/Properties.d.ts +27 -3
- package/dist/types/src/components/Properties/Properties.d.ts.map +1 -1
- package/dist/types/src/components/Properties/Properties.stories.d.ts +20 -0
- package/dist/types/src/components/Properties/Properties.stories.d.ts.map +1 -0
- package/dist/types/src/components/Properties/SceneField.d.ts +8 -0
- package/dist/types/src/components/Properties/SceneField.d.ts.map +1 -0
- package/dist/types/src/components/Properties/StyleGrid.d.ts +15 -5
- package/dist/types/src/components/Properties/StyleGrid.d.ts.map +1 -1
- package/dist/types/src/components/Properties/StyleGrid.stories.d.ts +7 -0
- package/dist/types/src/components/Properties/StyleGrid.stories.d.ts.map +1 -0
- package/dist/types/src/components/SceneLayer/SceneLayer.d.ts +31 -7
- package/dist/types/src/components/SceneLayer/SceneLayer.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/Dock.d.ts +22 -0
- package/dist/types/src/components/SceneView/Dock.d.ts.map +1 -0
- package/dist/types/src/components/SceneView/Dock.stories.d.ts +15 -0
- package/dist/types/src/components/SceneView/Dock.stories.d.ts.map +1 -0
- package/dist/types/src/components/SceneView/SceneView.d.ts +33 -7
- package/dist/types/src/components/SceneView/SceneView.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/SceneView.stories.d.ts +16 -6
- package/dist/types/src/components/SceneView/SceneView.stories.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/SceneViewContext.d.ts +36 -4
- package/dist/types/src/components/SceneView/SceneViewContext.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/Scored.stories.d.ts +4 -4
- package/dist/types/src/components/SceneView/Scored.stories.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/usePointerMachine.d.ts +3 -1
- package/dist/types/src/components/SceneView/usePointerMachine.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/useSceneCamera.d.ts +2 -2
- package/dist/types/src/components/SceneView/useSceneCamera.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/useSceneClipboard.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/useSceneKeys.d.ts.map +1 -1
- package/dist/types/src/components/SceneView/useSceneNavigation.d.ts +7 -4
- package/dist/types/src/components/SceneView/useSceneNavigation.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +2 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useWheel.d.ts +5 -0
- package/dist/types/src/hooks/useWheel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +4 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/atoms.d.ts +21 -3
- package/dist/types/src/model/atoms.d.ts.map +1 -1
- package/dist/types/src/model/projection.d.ts.map +1 -1
- package/dist/types/src/model/projections/constrained.d.ts +2 -1
- package/dist/types/src/model/projections/constrained.d.ts.map +1 -1
- package/dist/types/src/model/projections/dynamic.d.ts.map +1 -1
- package/dist/types/src/model/projections/lattice.d.ts.map +1 -1
- package/dist/types/src/model/registry.d.ts +21 -3
- package/dist/types/src/model/registry.d.ts.map +1 -1
- package/dist/types/src/model/store.d.ts +10 -2
- package/dist/types/src/model/store.d.ts.map +1 -1
- package/dist/types/src/model/types.d.ts +699 -338
- package/dist/types/src/model/types.d.ts.map +1 -1
- package/dist/types/src/playwright/SceneManager.d.ts +1 -1
- package/dist/types/src/playwright/SceneManager.d.ts.map +1 -1
- package/dist/types/src/utils/builder.d.ts +22 -41
- package/dist/types/src/utils/builder.d.ts.map +1 -1
- package/dist/types/src/utils/camera.d.ts +19 -10
- package/dist/types/src/utils/camera.d.ts.map +1 -1
- package/dist/types/src/utils/clipboard.d.ts +4 -2
- package/dist/types/src/utils/clipboard.d.ts.map +1 -1
- package/dist/types/src/utils/diagram.d.ts.map +1 -1
- package/dist/types/src/utils/group.d.ts +14 -0
- package/dist/types/src/utils/group.d.ts.map +1 -0
- package/dist/types/src/utils/group.test.d.ts +2 -0
- package/dist/types/src/utils/group.test.d.ts.map +1 -0
- package/dist/types/src/utils/gutter-route.d.ts +7 -0
- package/dist/types/src/utils/gutter-route.d.ts.map +1 -1
- package/dist/types/src/utils/hit.d.ts +3 -20
- package/dist/types/src/utils/hit.d.ts.map +1 -1
- package/dist/types/src/utils/index.d.ts +3 -0
- package/dist/types/src/utils/index.d.ts.map +1 -1
- package/dist/types/src/utils/lattice.d.ts +5 -0
- package/dist/types/src/utils/lattice.d.ts.map +1 -1
- package/dist/types/src/utils/layers.d.ts +35 -0
- package/dist/types/src/utils/layers.d.ts.map +1 -0
- package/dist/types/src/utils/layers.test.d.ts +2 -0
- package/dist/types/src/utils/layers.test.d.ts.map +1 -0
- package/dist/types/src/utils/parts.d.ts +25 -9
- package/dist/types/src/utils/parts.d.ts.map +1 -1
- package/dist/types/src/utils/ports.d.ts +2 -0
- package/dist/types/src/utils/ports.d.ts.map +1 -1
- package/dist/types/src/utils/properties.d.ts +4 -3
- package/dist/types/src/utils/properties.d.ts.map +1 -1
- package/dist/types/src/utils/route.d.ts +5 -0
- package/dist/types/src/utils/route.d.ts.map +1 -1
- package/dist/types/src/utils/scenes.d.ts +14 -0
- package/dist/types/src/utils/scenes.d.ts.map +1 -0
- package/dist/types/src/utils/scenes.test.d.ts +2 -0
- package/dist/types/src/utils/scenes.test.d.ts.map +1 -0
- package/dist/types/src/utils/shapes.d.ts +23 -9
- package/dist/types/src/utils/shapes.d.ts.map +1 -1
- package/dist/types/src/utils/style.d.ts +29 -6
- package/dist/types/src/utils/style.d.ts.map +1 -1
- package/dist/types/src/utils/style.test.d.ts +2 -0
- package/dist/types/src/utils/style.test.d.ts.map +1 -0
- package/dist/types/src/utils/testing.d.ts +2 -2
- package/dist/types/src/utils/testing.d.ts.map +1 -1
- package/dist/types/src/utils/undo.d.ts +15 -4
- package/dist/types/src/utils/undo.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -26
- package/src/components/About/About.stories.tsx +32 -0
- package/src/components/About/About.tsx +38 -0
- package/src/components/About/index.ts +5 -0
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +17 -3
- package/src/components/ControlFrame/ControlFrame.tsx +138 -82
- package/src/components/Grid/Grid.stories.tsx +1 -1
- package/src/components/Layers/Layers.stories.tsx +131 -0
- package/src/components/Layers/Layers.tsx +216 -0
- package/src/components/Layers/index.ts +5 -0
- package/src/components/Palette/Palette.stories.tsx +135 -0
- package/src/components/Palette/Palette.tsx +230 -39
- package/src/components/PartEditor/PartEditor.tsx +4 -3
- package/src/components/Properties/AlignField.tsx +117 -0
- package/src/components/Properties/ClassField.tsx +44 -0
- package/src/components/Properties/FontField.tsx +73 -0
- package/src/components/Properties/LayerField.tsx +61 -0
- package/src/components/Properties/Properties.stories.tsx +113 -0
- package/src/components/Properties/Properties.tsx +240 -60
- package/src/components/Properties/SceneField.tsx +22 -0
- package/src/components/Properties/StyleGrid.stories.tsx +50 -0
- package/src/components/Properties/StyleGrid.tsx +54 -26
- package/src/components/SceneLayer/SceneLayer.tsx +497 -188
- package/src/components/SceneView/Constrained.stories.tsx +1 -1
- package/src/components/SceneView/Dock.stories.tsx +95 -0
- package/src/components/SceneView/Dock.tsx +146 -0
- package/src/components/SceneView/Dynamic.stories.tsx +1 -1
- package/src/components/SceneView/SceneView.stories.tsx +170 -18
- package/src/components/SceneView/SceneView.tsx +565 -151
- package/src/components/SceneView/SceneViewContext.ts +23 -2
- package/src/components/SceneView/Scored.stories.tsx +11 -11
- package/src/components/SceneView/usePointerMachine.ts +80 -20
- package/src/components/SceneView/useSceneCamera.ts +15 -8
- package/src/components/SceneView/useSceneClipboard.ts +4 -0
- package/src/components/SceneView/useSceneKeys.ts +6 -4
- package/src/components/SceneView/useSceneNavigation.ts +44 -33
- package/src/components/Toolbar/Toolbar.stories.tsx +14 -15
- package/src/components/Toolbar/Toolbar.tsx +15 -4
- package/src/components/index.ts +2 -0
- package/src/hooks/useWheel.ts +35 -0
- package/src/index.ts +4 -3
- package/src/model/atoms.ts +27 -3
- package/src/model/projection.ts +5 -0
- package/src/model/projections/constrained.test.ts +18 -10
- package/src/model/projections/constrained.ts +19 -8
- package/src/model/projections/dynamic.ts +5 -2
- package/src/model/projections/lattice.ts +15 -3
- package/src/model/registry.test.ts +14 -9
- package/src/model/registry.ts +39 -34
- package/src/model/store.ts +12 -2
- package/src/model/types.ts +124 -36
- package/src/playwright/SceneManager.ts +2 -2
- package/src/playwright/create.spec.ts +5 -3
- package/src/playwright/demo.spec.ts +2 -2
- package/src/playwright/lattice.spec.ts +4 -5
- package/src/playwright/scene.spec.ts +27 -25
- package/src/utils/builder.test.ts +46 -9
- package/src/utils/builder.ts +42 -18
- package/src/utils/camera.test.ts +22 -51
- package/src/utils/camera.ts +39 -32
- package/src/utils/clipboard.test.ts +23 -2
- package/src/utils/clipboard.ts +8 -4
- package/src/utils/diagram.test.ts +3 -1
- package/src/utils/diagram.ts +3 -25
- package/src/utils/group.test.ts +69 -0
- package/src/utils/group.ts +94 -0
- package/src/utils/gutter-route.test.ts +49 -0
- package/src/utils/gutter-route.ts +142 -16
- package/src/utils/hit.test.ts +4 -38
- package/src/utils/hit.ts +4 -26
- package/src/utils/index.ts +3 -0
- package/src/utils/lattice.ts +7 -1
- package/src/utils/layers.test.ts +139 -0
- package/src/utils/layers.ts +175 -0
- package/src/utils/parts.test.ts +66 -32
- package/src/utils/parts.ts +63 -41
- package/src/utils/ports.ts +7 -4
- package/src/utils/properties.test.ts +23 -6
- package/src/utils/properties.ts +66 -16
- package/src/utils/route.test.ts +51 -2
- package/src/utils/route.ts +133 -23
- package/src/utils/scenes.test.ts +38 -0
- package/src/utils/scenes.ts +54 -0
- package/src/utils/shapes.test.ts +33 -8
- package/src/utils/shapes.ts +51 -35
- package/src/utils/style.test.ts +54 -0
- package/src/utils/style.ts +153 -40
- package/src/utils/testing.test.ts +3 -3
- package/src/utils/testing.ts +21 -30
- package/src/utils/undo.test.ts +25 -2
- package/src/utils/undo.ts +50 -13
- package/dist/lib/chunk-Grid.mjs +0 -99
- package/dist/lib/chunk-Grid.mjs.map +0 -1
- package/dist/lib/scene.mjs +0 -6835
- package/dist/lib/scene.mjs.map +0 -1
- package/dist/lib/types.mjs +0 -16
- package/dist/lib/types.mjs.map +0 -1
- package/dist/types/src/archive/components/Canvas/Canvas.d.ts +0 -15
- package/dist/types/src/archive/components/Canvas/Canvas.d.ts.map +0 -1
- package/dist/types/src/archive/components/Canvas/Canvas.stories.d.ts +0 -18
- package/dist/types/src/archive/components/Canvas/Canvas.stories.d.ts.map +0 -1
- package/dist/types/src/archive/components/Canvas/index.d.ts +0 -2
- package/dist/types/src/archive/components/Canvas/index.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/CellGrid.d.ts +0 -21
- package/dist/types/src/archive/components/CellGrid/CellGrid.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/CellGrid.stories.d.ts +0 -21
- package/dist/types/src/archive/components/CellGrid/CellGrid.stories.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/headers/Ruler.d.ts +0 -15
- package/dist/types/src/archive/components/CellGrid/headers/Ruler.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/headers/TrackHeader.d.ts +0 -19
- package/dist/types/src/archive/components/CellGrid/headers/TrackHeader.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/headers/index.d.ts +0 -3
- package/dist/types/src/archive/components/CellGrid/headers/index.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/index.d.ts +0 -6
- package/dist/types/src/archive/components/CellGrid/index.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/input/index.d.ts +0 -3
- package/dist/types/src/archive/components/CellGrid/input/index.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/input/pointer.d.ts +0 -33
- package/dist/types/src/archive/components/CellGrid/input/pointer.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/input/wheel.d.ts +0 -14
- package/dist/types/src/archive/components/CellGrid/input/wheel.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/render/index.d.ts +0 -3
- package/dist/types/src/archive/components/CellGrid/render/index.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/render/overlay-layer.d.ts +0 -21
- package/dist/types/src/archive/components/CellGrid/render/overlay-layer.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/render/static-layer.d.ts +0 -36
- package/dist/types/src/archive/components/CellGrid/render/static-layer.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/state/atoms.d.ts +0 -23
- package/dist/types/src/archive/components/CellGrid/state/atoms.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/state/index.d.ts +0 -4
- package/dist/types/src/archive/components/CellGrid/state/index.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/state/types.d.ts +0 -39
- package/dist/types/src/archive/components/CellGrid/state/types.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/state/viewport.d.ts +0 -52
- package/dist/types/src/archive/components/CellGrid/state/viewport.d.ts.map +0 -1
- package/dist/types/src/archive/components/CellGrid/state/viewport.test.d.ts +0 -2
- package/dist/types/src/archive/components/CellGrid/state/viewport.test.d.ts.map +0 -1
- package/dist/types/src/archive/components/FPS.d.ts +0 -9
- package/dist/types/src/archive/components/FPS.d.ts.map +0 -1
- package/dist/types/src/archive/components/Grid/Grid.d.ts +0 -6
- package/dist/types/src/archive/components/Grid/Grid.d.ts.map +0 -1
- package/dist/types/src/archive/components/Grid/index.d.ts +0 -2
- package/dist/types/src/archive/components/Grid/index.d.ts.map +0 -1
- package/dist/types/src/archive/components/index.d.ts +0 -5
- package/dist/types/src/archive/components/index.d.ts.map +0 -1
- package/dist/types/src/archive/hooks/index.d.ts +0 -5
- package/dist/types/src/archive/hooks/index.d.ts.map +0 -1
- package/dist/types/src/archive/hooks/projection.d.ts +0 -60
- package/dist/types/src/archive/hooks/projection.d.ts.map +0 -1
- package/dist/types/src/archive/hooks/useCanvasContext.d.ts +0 -13
- package/dist/types/src/archive/hooks/useCanvasContext.d.ts.map +0 -1
- package/dist/types/src/archive/hooks/useDrag.d.ts +0 -6
- package/dist/types/src/archive/hooks/useDrag.d.ts.map +0 -1
- package/dist/types/src/archive/hooks/useWheel.d.ts +0 -8
- package/dist/types/src/archive/hooks/useWheel.d.ts.map +0 -1
- package/dist/types/src/archive/index.d.ts +0 -5
- package/dist/types/src/archive/index.d.ts.map +0 -1
- package/dist/types/src/archive/types.d.ts +0 -19
- package/dist/types/src/archive/types.d.ts.map +0 -1
- package/dist/types/src/archive/util/index.d.ts +0 -4
- package/dist/types/src/archive/util/index.d.ts.map +0 -1
- package/dist/types/src/archive/util/svg-path.d.ts +0 -4
- package/dist/types/src/archive/util/svg-path.d.ts.map +0 -1
- package/dist/types/src/archive/util/svg.d.ts +0 -32
- package/dist/types/src/archive/util/svg.d.ts.map +0 -1
- package/dist/types/src/archive/util/svg.stories.d.ts +0 -15
- package/dist/types/src/archive/util/svg.stories.d.ts.map +0 -1
- package/dist/types/src/archive/util/util.d.ts +0 -17
- package/dist/types/src/archive/util/util.d.ts.map +0 -1
- package/dist/types/src/scene.d.ts +0 -5
- package/dist/types/src/scene.d.ts.map +0 -1
- package/src/archive/components/Canvas/Canvas.stories.tsx +0 -111
- package/src/archive/components/Canvas/Canvas.tsx +0 -87
- package/src/archive/components/Canvas/index.ts +0 -5
- package/src/archive/components/CellGrid/CellGrid.stories.tsx +0 -239
- package/src/archive/components/CellGrid/CellGrid.tsx +0 -270
- package/src/archive/components/CellGrid/headers/Ruler.tsx +0 -71
- package/src/archive/components/CellGrid/headers/TrackHeader.tsx +0 -58
- package/src/archive/components/CellGrid/headers/index.ts +0 -6
- package/src/archive/components/CellGrid/index.ts +0 -9
- package/src/archive/components/CellGrid/input/index.ts +0 -6
- package/src/archive/components/CellGrid/input/pointer.ts +0 -236
- package/src/archive/components/CellGrid/input/wheel.ts +0 -68
- package/src/archive/components/CellGrid/render/index.ts +0 -6
- package/src/archive/components/CellGrid/render/overlay-layer.ts +0 -66
- package/src/archive/components/CellGrid/render/static-layer.ts +0 -112
- package/src/archive/components/CellGrid/state/atoms.ts +0 -43
- package/src/archive/components/CellGrid/state/index.ts +0 -7
- package/src/archive/components/CellGrid/state/types.ts +0 -40
- package/src/archive/components/CellGrid/state/viewport.test.ts +0 -50
- package/src/archive/components/CellGrid/state/viewport.ts +0 -94
- package/src/archive/components/FPS.tsx +0 -98
- package/src/archive/components/Grid/Grid.tsx +0 -17
- package/src/archive/components/Grid/index.ts +0 -5
- package/src/archive/components/index.ts +0 -8
- package/src/archive/hooks/index.ts +0 -8
- package/src/archive/hooks/projection.tsx +0 -156
- package/src/archive/hooks/useCanvasContext.ts +0 -32
- package/src/archive/hooks/useDrag.tsx +0 -96
- package/src/archive/hooks/useWheel.tsx +0 -80
- package/src/archive/index.ts +0 -8
- package/src/archive/types.ts +0 -14
- package/src/archive/util/index.ts +0 -7
- package/src/archive/util/svg-path.ts +0 -13
- package/src/archive/util/svg.stories.tsx +0 -46
- package/src/archive/util/svg.tsx +0 -128
- package/src/archive/util/util.ts +0 -50
- package/src/scene.ts +0 -9
package/src/utils/testing.ts
CHANGED
|
@@ -7,16 +7,17 @@ import { portId } from './ports.ts';
|
|
|
7
7
|
import { DEFAULT_SIZES } from './shapes.ts';
|
|
8
8
|
|
|
9
9
|
//
|
|
10
|
-
// A three-level
|
|
11
|
-
// model rather than one of every element type. The domain is invented — a document editor —
|
|
12
|
-
// stays readable without tracking any package's actual classes.
|
|
10
|
+
// A three-level model diagram, one box per class: the fixture for anything that needs a scene tree to look
|
|
11
|
+
// like a real model rather than one of every element type. The domain is invented — a document editor —
|
|
12
|
+
// so it stays readable without tracking any package's actual classes. (The UML class shape itself is
|
|
13
|
+
// plugin-uml's; the engine fixture draws each class as a labelled rectangle.)
|
|
13
14
|
//
|
|
14
15
|
|
|
15
16
|
/** The class fixture's unit: a major cell, so every box lands on the grid move and resize snap to. */
|
|
16
17
|
const cell = (units: number) => units * 64;
|
|
17
18
|
|
|
18
19
|
const CLASS_SIZE = { width: cell(4), height: cell(3) };
|
|
19
|
-
const PORTAL_SIZE = DEFAULT_SIZES.
|
|
20
|
+
const PORTAL_SIZE = DEFAULT_SIZES.frame;
|
|
20
21
|
|
|
21
22
|
type ClassDef = { key: string; name: string; attributes: string[]; methods: string[] };
|
|
22
23
|
type LevelDef = { key: string; title: string; classes: ClassDef[]; children?: LevelDef[] };
|
|
@@ -73,26 +74,24 @@ const MODEL: LevelDef = {
|
|
|
73
74
|
};
|
|
74
75
|
|
|
75
76
|
/**
|
|
76
|
-
* A three-level
|
|
77
|
+
* A three-level model diagram over {@link MODEL}: one scene per subsystem, each holding a box per class
|
|
77
78
|
* in a row joined by an association, with a portal per child subsystem below them. Ids are
|
|
78
79
|
* deterministic (`scene:app/editor`, `scene:app/editor/view`) so tests and stories can name elements.
|
|
79
80
|
*/
|
|
80
|
-
export const
|
|
81
|
+
export const createModelSceneTree = (prefix = 'app'): SceneTree => classLevel(MODEL, prefix).build();
|
|
81
82
|
|
|
82
83
|
const classLevel = (level: LevelDef, path: string): SceneElement => {
|
|
83
84
|
const id = `scene:${path}`;
|
|
84
85
|
// Classes sit in a row; each child subsystem gets a portal in the row below, under its own column.
|
|
85
|
-
const classes = level.classes.map(({ key, name
|
|
86
|
-
SceneBuilder.
|
|
87
|
-
name,
|
|
88
|
-
attributes,
|
|
89
|
-
methods,
|
|
86
|
+
const classes = level.classes.map(({ key, name }, index) =>
|
|
87
|
+
SceneBuilder.rect(`${id}/${key}`, { x: cell(2) + index * cell(6), y: cell(2), ...CLASS_SIZE }).properties({
|
|
88
|
+
label: name,
|
|
90
89
|
}),
|
|
91
90
|
);
|
|
92
91
|
const associations = level.classes.slice(1).map((current, index) =>
|
|
93
92
|
SceneBuilder.link('line', `${id}/${level.classes[index].key}#${portId('e')}`, `${id}/${current.key}#${portId('w')}`)
|
|
94
93
|
.id(`${id}/assoc${index + 1}`)
|
|
95
|
-
.properties({
|
|
94
|
+
.properties({ ends: { end: 'arrow' } }),
|
|
96
95
|
);
|
|
97
96
|
const children = (level.children ?? []).map((child, index) =>
|
|
98
97
|
classLevel(child, `${path}/${child.key}`).at({ x: cell(2) + index * cell(10), y: cell(7), ...PORTAL_SIZE }),
|
|
@@ -114,7 +113,7 @@ export const createSceneTree = (depth: number, prefix = 'root'): SceneTree => tr
|
|
|
114
113
|
/** The fixture's unit: every point and size is written as a count of these, never as raw pixels. */
|
|
115
114
|
const scale = (units: number) => units * 32;
|
|
116
115
|
|
|
117
|
-
const PORTAL = DEFAULT_SIZES.
|
|
116
|
+
const PORTAL = DEFAULT_SIZES.frame;
|
|
118
117
|
|
|
119
118
|
/** Child scene variants, chosen by nesting level and side so siblings differ. */
|
|
120
119
|
const VARIANTS = ['flow', 'model', 'cycle', 'note'] as const;
|
|
@@ -161,13 +160,11 @@ const rootElements = (name: string, elementId: (suffix: string) => string): Buil
|
|
|
161
160
|
SceneBuilder.note(elementId('t'), units(-10, 8, 12, 4)).properties({
|
|
162
161
|
text: `Scene "${name}". Pinch to zoom, drag to pan, double-click a portal.`,
|
|
163
162
|
}),
|
|
164
|
-
SceneBuilder.
|
|
165
|
-
name: `${name} · C`,
|
|
166
|
-
attributes: ['id: string', 'name: string'],
|
|
167
|
-
methods: ['save(): void'],
|
|
168
|
-
}),
|
|
163
|
+
labelled(SceneBuilder.rect, elementId('c'), units(-22, 6, 8, 6), `${name} · C`),
|
|
169
164
|
SceneBuilder.link('curve', elementId('a'), elementId('b')).id(elementId('ab')),
|
|
170
|
-
SceneBuilder.link('line', elementId('a'), elementId('c'))
|
|
165
|
+
SceneBuilder.link('line', elementId('a'), elementId('c'))
|
|
166
|
+
.id(elementId('ac'))
|
|
167
|
+
.properties({ ends: { end: 'arrow' } }),
|
|
171
168
|
// Pinned ports rather than automatic ones, so the spline leaves and arrives where its corners turn.
|
|
172
169
|
SceneBuilder.link('spline', `${elementId('b')}#${portId('s')}`, `${elementId('c')}#${portId('n', 3)}`)
|
|
173
170
|
.id(elementId('bc'))
|
|
@@ -181,7 +178,9 @@ const rootElements = (name: string, elementId: (suffix: string) => string): Buil
|
|
|
181
178
|
|
|
182
179
|
const childElements = (name: string, elementId: (suffix: string) => string, variant: Variant): BuilderElement[] => {
|
|
183
180
|
const directed = (id: string, from: string, to: string) =>
|
|
184
|
-
SceneBuilder.link('line', from, to)
|
|
181
|
+
SceneBuilder.link('line', from, to)
|
|
182
|
+
.id(elementId(id))
|
|
183
|
+
.properties({ ends: { end: 'arrow' } });
|
|
185
184
|
switch (variant) {
|
|
186
185
|
case 'flow':
|
|
187
186
|
return [
|
|
@@ -193,16 +192,8 @@ const childElements = (name: string, elementId: (suffix: string) => string, vari
|
|
|
193
192
|
];
|
|
194
193
|
case 'model':
|
|
195
194
|
return [
|
|
196
|
-
SceneBuilder.
|
|
197
|
-
|
|
198
|
-
attributes: ['name: string'],
|
|
199
|
-
methods: ['greet()'],
|
|
200
|
-
}),
|
|
201
|
-
SceneBuilder.class(elementId('org'), units(-4, -4, 8, 8)).properties({
|
|
202
|
-
name: 'Organization',
|
|
203
|
-
attributes: ['title: string'],
|
|
204
|
-
methods: ['hire(person)'],
|
|
205
|
-
}),
|
|
195
|
+
labelled(SceneBuilder.rect, elementId('person'), units(-20, -4, 8, 8), 'Person'),
|
|
196
|
+
labelled(SceneBuilder.rect, elementId('org'), units(-4, -4, 8, 8), 'Organization'),
|
|
206
197
|
SceneBuilder.link('curve', `${elementId('person')}#e2`, `${elementId('org')}#w2`).id(elementId('works')),
|
|
207
198
|
];
|
|
208
199
|
case 'cycle':
|
package/src/utils/undo.test.ts
CHANGED
|
@@ -9,8 +9,9 @@ import { describe, test } from 'vitest';
|
|
|
9
9
|
import { createFreehandProjection } from '../model/projection.ts';
|
|
10
10
|
import { type ConstrainedModel, createConstrainedProjection } from '../model/projections/constrained.ts';
|
|
11
11
|
import { createMemoryStore } from '../model/store.ts';
|
|
12
|
+
import { groupIntoScene } from './group.ts';
|
|
12
13
|
import { createSceneTree } from './testing.ts';
|
|
13
|
-
import { type UndoState, emptyUndo, redo, undo, withUndo } from './undo.ts';
|
|
14
|
+
import { type UndoState, emptyUndo, recordScenes, redo, undo, withUndo } from './undo.ts';
|
|
14
15
|
|
|
15
16
|
const setup = () => {
|
|
16
17
|
const registry = Registry.make();
|
|
@@ -19,7 +20,7 @@ const setup = () => {
|
|
|
19
20
|
const atom = Atom.keepAlive(Atom.make<UndoState>(emptyUndo()));
|
|
20
21
|
const projection = withUndo(createFreehandProjection({ registry, store, sceneId: root }), registry, atom, root);
|
|
21
22
|
const centerOf = (id: string) => registry.get(projection.scene).nodes[id]?.center;
|
|
22
|
-
return { registry, root, atom, projection, centerOf };
|
|
23
|
+
return { registry, root, store, atom, projection, centerOf };
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
describe('undo', () => {
|
|
@@ -55,6 +56,28 @@ describe('undo', () => {
|
|
|
55
56
|
expect(undo(projection, registry, atom, root)).toBe(true);
|
|
56
57
|
});
|
|
57
58
|
|
|
59
|
+
test('grouping into a new scene is one step: undo takes the scene away, redo returns it', ({ expect }) => {
|
|
60
|
+
const { registry, root, store, atom, projection } = setup();
|
|
61
|
+
const group = groupIntoScene(registry.get(projection.scene), ['scene:r/a'], 'g');
|
|
62
|
+
expect(group).toBeDefined();
|
|
63
|
+
if (!group) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const before = registry.get(store.scenes);
|
|
67
|
+
registry.set(store.scenes, { ...before, g: group.child });
|
|
68
|
+
projection.apply({ kind: 'batch', intents: group.intents });
|
|
69
|
+
recordScenes(registry, atom, root, before);
|
|
70
|
+
expect(registry.get(projection.scene).nodes.g).toBeDefined();
|
|
71
|
+
|
|
72
|
+
expect(undo(projection, registry, atom, root, store)).toBe(true);
|
|
73
|
+
expect(registry.get(store.scenes).g).toBeUndefined();
|
|
74
|
+
expect(registry.get(projection.scene).nodes['scene:r/a']).toBeDefined();
|
|
75
|
+
|
|
76
|
+
expect(redo(projection, registry, atom, root, store)).toBe(true);
|
|
77
|
+
expect(registry.get(store.scenes).g).toEqual(group.child);
|
|
78
|
+
expect(registry.get(projection.scene).nodes.g).toBeDefined();
|
|
79
|
+
});
|
|
80
|
+
|
|
58
81
|
test('a constrained projection restores its constraint model', ({ expect }) => {
|
|
59
82
|
const registry = Registry.make();
|
|
60
83
|
const model = Atom.keepAlive(
|
package/src/utils/undo.ts
CHANGED
|
@@ -12,15 +12,22 @@ import type * as Atom from 'effect/reactivity/Atom';
|
|
|
12
12
|
import type * as Registry from 'effect/reactivity/AtomRegistry';
|
|
13
13
|
|
|
14
14
|
import { type Projection } from '../model/projection.ts';
|
|
15
|
+
import { type SceneMap, type SceneStore } from '../model/store.ts';
|
|
15
16
|
|
|
16
17
|
/** Entries older than this are dropped rather than growing without bound. */
|
|
17
18
|
export const UNDO_LIMIT = 100;
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* One undo step: the projection's snapshot from before it, and, for a step that also added or removed scenes (a
|
|
22
|
+
* group into a new scene), the store's scenes from before it, so undo takes the new scene away and redo returns it.
|
|
23
|
+
*/
|
|
24
|
+
export type UndoEntry = { model: unknown; scenes?: SceneMap };
|
|
25
|
+
|
|
19
26
|
export type UndoState = {
|
|
20
27
|
/** Which projection the snapshots belong to; a different one starts an empty log. */
|
|
21
28
|
key: string;
|
|
22
|
-
past:
|
|
23
|
-
future:
|
|
29
|
+
past: UndoEntry[];
|
|
30
|
+
future: UndoEntry[];
|
|
24
31
|
};
|
|
25
32
|
|
|
26
33
|
export const emptyUndo = (key = ''): UndoState => ({ key, past: [], future: [] });
|
|
@@ -48,24 +55,54 @@ export const withUndo = (
|
|
|
48
55
|
return;
|
|
49
56
|
}
|
|
50
57
|
const state = stateFor(registry, atom, key);
|
|
51
|
-
registry.set(atom, { key, past: [...state.past.slice(-(UNDO_LIMIT - 1)), before], future: [] });
|
|
58
|
+
registry.set(atom, { key, past: [...state.past.slice(-(UNDO_LIMIT - 1)), { model: before }], future: [] });
|
|
52
59
|
},
|
|
53
60
|
});
|
|
54
61
|
|
|
62
|
+
/** Marks the step just recorded as one that also changed the store's scenes, which were `scenes` before it. */
|
|
63
|
+
export const recordScenes = (
|
|
64
|
+
registry: Registry.AtomRegistry,
|
|
65
|
+
atom: Atom.Writable<UndoState>,
|
|
66
|
+
key: string,
|
|
67
|
+
scenes: SceneMap,
|
|
68
|
+
): void => {
|
|
69
|
+
const state = stateFor(registry, atom, key);
|
|
70
|
+
const last = state.past[state.past.length - 1];
|
|
71
|
+
if (last) {
|
|
72
|
+
registry.set(atom, { ...state, past: [...state.past.slice(0, -1), { ...last, scenes }] });
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** Swaps the model (and the store's scenes, for a step that changed them) for `entry`, returning what it replaced. */
|
|
77
|
+
const swap = (
|
|
78
|
+
projection: Projection,
|
|
79
|
+
registry: Registry.AtomRegistry,
|
|
80
|
+
store: SceneStore | undefined,
|
|
81
|
+
entry: UndoEntry,
|
|
82
|
+
): UndoEntry => {
|
|
83
|
+
const scenes = entry.scenes && store ? registry.get(store.scenes) : undefined;
|
|
84
|
+
const replaced: UndoEntry = { model: projection.snapshot(), ...(scenes ? { scenes } : {}) };
|
|
85
|
+
if (entry.scenes && store) {
|
|
86
|
+
registry.set(store.scenes, entry.scenes);
|
|
87
|
+
}
|
|
88
|
+
projection.restore(entry.model);
|
|
89
|
+
return replaced;
|
|
90
|
+
};
|
|
91
|
+
|
|
55
92
|
export const undo = (
|
|
56
93
|
projection: Projection,
|
|
57
94
|
registry: Registry.AtomRegistry,
|
|
58
95
|
atom: Atom.Writable<UndoState>,
|
|
59
96
|
key: string,
|
|
97
|
+
store?: SceneStore,
|
|
60
98
|
): boolean => {
|
|
61
99
|
const state = stateFor(registry, atom, key);
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
100
|
+
const entry = state.past[state.past.length - 1];
|
|
101
|
+
if (!entry) {
|
|
64
102
|
return false;
|
|
65
103
|
}
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
registry.set(atom, { key, past: state.past.slice(0, -1), future: [...state.future, current] });
|
|
104
|
+
const replaced = swap(projection, registry, store, entry);
|
|
105
|
+
registry.set(atom, { key, past: state.past.slice(0, -1), future: [...state.future, replaced] });
|
|
69
106
|
return true;
|
|
70
107
|
};
|
|
71
108
|
|
|
@@ -74,14 +111,14 @@ export const redo = (
|
|
|
74
111
|
registry: Registry.AtomRegistry,
|
|
75
112
|
atom: Atom.Writable<UndoState>,
|
|
76
113
|
key: string,
|
|
114
|
+
store?: SceneStore,
|
|
77
115
|
): boolean => {
|
|
78
116
|
const state = stateFor(registry, atom, key);
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
117
|
+
const entry = state.future[state.future.length - 1];
|
|
118
|
+
if (!entry) {
|
|
81
119
|
return false;
|
|
82
120
|
}
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
registry.set(atom, { key, past: [...state.past, current], future: state.future.slice(0, -1) });
|
|
121
|
+
const replaced = swap(projection, registry, store, entry);
|
|
122
|
+
registry.set(atom, { key, past: [...state.past, replaced], future: state.future.slice(0, -1) });
|
|
86
123
|
return true;
|
|
87
124
|
};
|
package/dist/lib/chunk-Grid.mjs
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { forwardRef, useId, useMemo } from "react";
|
|
2
|
-
import { mx } from "@dxos/ui-theme";
|
|
3
|
-
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
import * as Hooks from "@dxos/react-ui/Hooks";
|
|
5
|
-
//#region src/components/Grid/Grid.tsx
|
|
6
|
-
var gridRatios = [
|
|
7
|
-
1 / 4,
|
|
8
|
-
1,
|
|
9
|
-
4,
|
|
10
|
-
16
|
|
11
|
-
];
|
|
12
|
-
var defaultGridSize = 16;
|
|
13
|
-
var defaultOffset = {
|
|
14
|
-
x: 0,
|
|
15
|
-
y: 0
|
|
16
|
-
};
|
|
17
|
-
var defaultRange = [defaultGridSize, 128];
|
|
18
|
-
var createId = (parent, grid) => `dx-canvas-grid-${parent}-${grid}`;
|
|
19
|
-
/**
|
|
20
|
-
* A level's line opacity from its on-screen spacing alone: faint at the finest drawn spacing, a step
|
|
21
|
-
* darker per fourfold. A level then fades in as the view zooms rather than popping, and a scene swap
|
|
22
|
-
* that keeps every spacing (drilling through a grid-aligned portal) keeps every line as it was. The
|
|
23
|
-
* step is small and the ceiling low: the grid is a guide under the diagram, so the coarse levels in
|
|
24
|
-
* particular must not read as content.
|
|
25
|
-
*/
|
|
26
|
-
var levelOpacity = (size, min) => Math.min(.12, .04 + .02 * Math.log(size / min) / Math.log(4));
|
|
27
|
-
/** Multi-level grid in screen space, fed the camera's scale and offset. */
|
|
28
|
-
var GridComponent = forwardRef(({ size: gridSize = defaultGridSize, scale = 1, offset = defaultOffset, showAxes = true, ratios = gridRatios, range = defaultRange, classNames }, forwardedRef) => {
|
|
29
|
-
const svgRef = Hooks.useForwardedRef(forwardedRef);
|
|
30
|
-
const { width = 0, height = 0 } = svgRef.current?.getBoundingClientRect() ?? {};
|
|
31
|
-
const instanceId = useId();
|
|
32
|
-
const [min, max] = range;
|
|
33
|
-
const grids = useMemo(() => ratios.map((ratio) => ({
|
|
34
|
-
id: ratio,
|
|
35
|
-
size: ratio * gridSize * scale
|
|
36
|
-
})).filter(({ size }) => size >= min && size <= max), [
|
|
37
|
-
ratios,
|
|
38
|
-
gridSize,
|
|
39
|
-
scale,
|
|
40
|
-
min,
|
|
41
|
-
max
|
|
42
|
-
]);
|
|
43
|
-
return /* @__PURE__ */ jsxs("svg", {
|
|
44
|
-
"data-testid": "dx-canvas-grid",
|
|
45
|
-
ref: svgRef,
|
|
46
|
-
className: mx("dx-cover w-full h-full pointer-events-none touch-none select-none", "stroke-neutral-500", classNames),
|
|
47
|
-
children: [
|
|
48
|
-
/* @__PURE__ */ jsx("defs", { children: grids.map(({ id, size }) => /* @__PURE__ */ jsx(GridPattern, {
|
|
49
|
-
id: createId(instanceId, id),
|
|
50
|
-
offset,
|
|
51
|
-
size
|
|
52
|
-
}, id)) }),
|
|
53
|
-
showAxes && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("line", {
|
|
54
|
-
x1: 0,
|
|
55
|
-
y1: offset.y,
|
|
56
|
-
x2: width,
|
|
57
|
-
y2: offset.y,
|
|
58
|
-
className: "stroke-neutral-500 opacity-40"
|
|
59
|
-
}), /* @__PURE__ */ jsx("line", {
|
|
60
|
-
x1: offset.x,
|
|
61
|
-
y1: 0,
|
|
62
|
-
x2: offset.x,
|
|
63
|
-
y2: height,
|
|
64
|
-
className: "stroke-neutral-500 opacity-40"
|
|
65
|
-
})] }),
|
|
66
|
-
/* @__PURE__ */ jsx("g", { children: grids.map(({ id, size }) => /* @__PURE__ */ jsx("rect", {
|
|
67
|
-
opacity: levelOpacity(size, min),
|
|
68
|
-
fill: `url(#${createId(instanceId, id)})`,
|
|
69
|
-
width: "100%",
|
|
70
|
-
height: "100%"
|
|
71
|
-
}, id)) })
|
|
72
|
-
]
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
GridComponent.displayName = "GridComponent";
|
|
76
|
-
/** One grid level as an SVG pattern of crossing lines, offset so a line sits on the origin. */
|
|
77
|
-
var GridPattern = ({ id, size, offset }) => /* @__PURE__ */ jsxs("pattern", {
|
|
78
|
-
id,
|
|
79
|
-
x: (size / 2 + offset.x) % size,
|
|
80
|
-
y: (size / 2 + offset.y) % size,
|
|
81
|
-
width: size,
|
|
82
|
-
height: size,
|
|
83
|
-
patternUnits: "userSpaceOnUse",
|
|
84
|
-
children: [/* @__PURE__ */ jsx("line", {
|
|
85
|
-
x1: 0,
|
|
86
|
-
y1: size / 2,
|
|
87
|
-
x2: size,
|
|
88
|
-
y2: size / 2
|
|
89
|
-
}), /* @__PURE__ */ jsx("line", {
|
|
90
|
-
x1: size / 2,
|
|
91
|
-
y1: 0,
|
|
92
|
-
x2: size / 2,
|
|
93
|
-
y2: size
|
|
94
|
-
})]
|
|
95
|
-
});
|
|
96
|
-
//#endregion
|
|
97
|
-
export { GridComponent as t };
|
|
98
|
-
|
|
99
|
-
//# sourceMappingURL=chunk-Grid.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-Grid.mjs","names":[],"sources":["../../src/components/Grid/Grid.tsx"],"sourcesContent":["//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { forwardRef, useId, useMemo } from 'react';\n\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport type * as Util from '@dxos/react-ui/Util';\nimport { mx } from '@dxos/ui-theme';\n\nimport { type Point } from '../../model/types.ts';\n\nconst gridRatios = [1 / 4, 1, 4, 16];\n\nconst defaultGridSize = 16;\nconst defaultOffset: Point = { x: 0, y: 0 };\nconst defaultRange = [defaultGridSize, 128] as const;\n\nconst createId = (parent: string, grid: number) => `dx-canvas-grid-${parent}-${grid}`;\n\n/**\n * A level's line opacity from its on-screen spacing alone: faint at the finest drawn spacing, a step\n * darker per fourfold. A level then fades in as the view zooms rather than popping, and a scene swap\n * that keeps every spacing (drilling through a grid-aligned portal) keeps every line as it was. The\n * step is small and the ceiling low: the grid is a guide under the diagram, so the coarse levels in\n * particular must not read as content.\n */\nconst levelOpacity = (size: number, min: number) => Math.min(0.12, 0.04 + (0.02 * Math.log(size / min)) / Math.log(4));\n\nexport type GridProps = Util.ThemedClassName<{\n size?: number;\n scale?: number;\n offset?: Point;\n showAxes?: boolean;\n /** Grid levels as multiples of `size`, finest first. */\n ratios?: readonly number[];\n /** On-screen cell size (px) outside which a level is not drawn. */\n range?: readonly [min: number, max: number];\n}>;\n\n/** Multi-level grid in screen space, fed the camera's scale and offset. */\nexport const GridComponent = forwardRef<SVGSVGElement, GridProps>(\n (\n {\n size: gridSize = defaultGridSize,\n scale = 1,\n offset = defaultOffset,\n showAxes = true,\n ratios = gridRatios,\n range = defaultRange,\n classNames,\n },\n forwardedRef,\n ) => {\n const svgRef = Hooks.useForwardedRef(forwardedRef);\n const { width = 0, height = 0 } = svgRef.current?.getBoundingClientRect() ?? {};\n\n const instanceId = useId();\n const [min, max] = range;\n const grids = useMemo(\n () =>\n ratios\n .map((ratio) => ({ id: ratio, size: ratio * gridSize * scale }))\n .filter(({ size }) => size >= min && size <= max),\n [ratios, gridSize, scale, min, max],\n );\n\n return (\n <svg\n data-testid='dx-canvas-grid'\n ref={svgRef}\n // `dx-cover` (absolute inset-0) does not stretch a replaced <svg> element — without an explicit\n // size it falls back to the intrinsic 300x150, clipping the 100%-sized grid rects. Force full size.\n className={mx(\n 'dx-cover w-full h-full pointer-events-none touch-none select-none',\n 'stroke-neutral-500',\n classNames,\n )}\n >\n {/* NOTE: The pattern is offset so that the middle of the pattern aligns with the grid. */}\n <defs>\n {grids.map(({ id, size }) => (\n <GridPattern key={id} id={createId(instanceId, id)} offset={offset} size={size} />\n ))}\n </defs>\n {showAxes && (\n <>\n <line x1={0} y1={offset.y} x2={width} y2={offset.y} className='stroke-neutral-500 opacity-40' />\n <line x1={offset.x} y1={0} x2={offset.x} y2={height} className='stroke-neutral-500 opacity-40' />\n </>\n )}\n <g>\n {grids.map(({ id, size }) => (\n <rect\n key={id}\n opacity={levelOpacity(size, min)}\n fill={`url(#${createId(instanceId, id)})`}\n width='100%'\n height='100%'\n />\n ))}\n </g>\n </svg>\n );\n },\n);\n\nGridComponent.displayName = 'GridComponent';\n\n/** One grid level as an SVG pattern of crossing lines, offset so a line sits on the origin. */\nconst GridPattern = ({ id, size, offset }: { id: string; size: number; offset: Point }) => (\n <pattern\n id={id}\n x={(size / 2 + offset.x) % size}\n y={(size / 2 + offset.y) % size}\n width={size}\n height={size}\n patternUnits='userSpaceOnUse'\n >\n <line x1={0} y1={size / 2} x2={size} y2={size / 2} />\n <line x1={size / 2} y1={0} x2={size / 2} y2={size} />\n </pattern>\n);\n"],"mappings":";;;;;AAYA,IAAM,aAAa;CAAC,IAAI;CAAG;CAAG;CAAG;AAAE;AAEnC,IAAM,kBAAkB;AACxB,IAAM,gBAAuB;CAAE,GAAG;CAAG,GAAG;AAAE;AAC1C,IAAM,eAAe,CAAC,iBAAiB,GAAG;AAE1C,IAAM,YAAY,QAAgB,SAAiB,kBAAkB,OAAO,GAAG;;;;;;;;AAS/E,IAAM,gBAAgB,MAAc,QAAgB,KAAK,IAAI,KAAM,MAAQ,MAAO,KAAK,IAAI,OAAO,GAAG,IAAK,KAAK,IAAI,CAAC,CAAC;;AAcrH,IAAa,gBAAgB,YAEzB,EACE,MAAM,WAAW,iBACjB,QAAQ,GACR,SAAS,eACT,WAAW,MACX,SAAS,YACT,QAAQ,cACR,cAEF,iBACG;CACH,MAAM,SAAS,MAAM,gBAAgB,YAAY;CACjD,MAAM,EAAE,QAAQ,GAAG,SAAS,MAAM,OAAO,SAAS,sBAAsB,KAAK,CAAC;CAE9E,MAAM,aAAa,MAAM;CACzB,MAAM,CAAC,KAAK,OAAO;CACnB,MAAM,QAAQ,cAEV,OACG,KAAK,WAAW;EAAE,IAAI;EAAO,MAAM,QAAQ,WAAW;CAAM,EAAE,CAAA,CAC9D,QAAQ,EAAE,WAAW,QAAQ,OAAO,QAAQ,GAAG,GACpD;EAAC;EAAQ;EAAU;EAAO;EAAK;CAAG,CACpC;CAEA,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,KAAK;EAGL,WAAW,GACT,qEACA,sBACA,UACF;EATF,UAAA;GAYE,oBAAC,QAAD,EAAA,UACG,MAAM,KAAK,EAAE,IAAI,WAChB,oBAAC,aAAD;IAAsB,IAAI,SAAS,YAAY,EAAE;IAAW;IAAc;GAAO,GAA/D,EAA+D,CAClF,EACG,CAAA;GACL,YACC,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,QAAD;IAAM,IAAI;IAAG,IAAI,OAAO;IAAG,IAAI;IAAO,IAAI,OAAO;IAAG,WAAU;GAAiC,CAAA,GAC/F,oBAAC,QAAD;IAAM,IAAI,OAAO;IAAG,IAAI;IAAG,IAAI,OAAO;IAAG,IAAI;IAAQ,WAAU;GAAiC,CAAA,CAChG,EAAA,CAAA;GAEJ,oBAAC,KAAD,EAAA,UACG,MAAM,KAAK,EAAE,IAAI,WAChB,oBAAC,QAAD;IAEE,SAAS,aAAa,MAAM,GAAG;IAC/B,MAAM,QAAQ,SAAS,YAAY,EAAE,EAAE;IACvC,OAAM;IACN,QAAO;GACR,GALM,EAKN,CACF,EACA,CAAA;EACA;;AAET,CACF;AAEA,cAAc,cAAc;;AAG5B,IAAM,eAAe,EAAE,IAAI,MAAM,aAC/B,qBAAC,WAAD;CACM;CACJ,IAAI,OAAO,IAAI,OAAO,KAAK;CAC3B,IAAI,OAAO,IAAI,OAAO,KAAK;CAC3B,OAAO;CACP,QAAQ;CACR,cAAa;CANf,UAAA,CAQE,oBAAC,QAAD;EAAM,IAAI;EAAG,IAAI,OAAO;EAAG,IAAI;EAAM,IAAI,OAAO;CAAI,CAAA,GACpD,oBAAC,QAAD;EAAM,IAAI,OAAO;EAAG,IAAI;EAAG,IAAI,OAAO;EAAG,IAAI;CAAO,CAAA,CAC7C"}
|