@oh-just-another/state 0.57.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/CHANGELOG.md +18 -0
- package/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/actions/actionClipboard.d.ts +6 -0
- package/dist/actions/actionClipboard.d.ts.map +1 -0
- package/dist/actions/actionClipboard.js +26 -0
- package/dist/actions/actionClipboard.js.map +1 -0
- package/dist/actions/actionGrouping.d.ts +5 -0
- package/dist/actions/actionGrouping.d.ts.map +1 -0
- package/dist/actions/actionGrouping.js +26 -0
- package/dist/actions/actionGrouping.js.map +1 -0
- package/dist/actions/actionHistory.d.ts +5 -0
- package/dist/actions/actionHistory.d.ts.map +1 -0
- package/dist/actions/actionHistory.js +25 -0
- package/dist/actions/actionHistory.js.map +1 -0
- package/dist/actions/actionKeyboard.d.ts +3 -0
- package/dist/actions/actionKeyboard.d.ts.map +1 -0
- package/dist/actions/actionKeyboard.js +130 -0
- package/dist/actions/actionKeyboard.js.map +1 -0
- package/dist/actions/actionLayout.d.ts +3 -0
- package/dist/actions/actionLayout.d.ts.map +1 -0
- package/dist/actions/actionLayout.js +65 -0
- package/dist/actions/actionLayout.js.map +1 -0
- package/dist/actions/actionMode.d.ts +13 -0
- package/dist/actions/actionMode.d.ts.map +1 -0
- package/dist/actions/actionMode.js +116 -0
- package/dist/actions/actionMode.js.map +1 -0
- package/dist/actions/actionSelection.d.ts +9 -0
- package/dist/actions/actionSelection.d.ts.map +1 -0
- package/dist/actions/actionSelection.js +57 -0
- package/dist/actions/actionSelection.js.map +1 -0
- package/dist/actions/actionView.d.ts +7 -0
- package/dist/actions/actionView.d.ts.map +1 -0
- package/dist/actions/actionView.js +14 -0
- package/dist/actions/actionView.js.map +1 -0
- package/dist/actions/actionZOrder.d.ts +7 -0
- package/dist/actions/actionZOrder.d.ts.map +1 -0
- package/dist/actions/actionZOrder.js +42 -0
- package/dist/actions/actionZOrder.js.map +1 -0
- package/dist/actions/actionZoom.d.ts +8 -0
- package/dist/actions/actionZoom.d.ts.map +1 -0
- package/dist/actions/actionZoom.js +61 -0
- package/dist/actions/actionZoom.js.map +1 -0
- package/dist/actions/index.d.ts +12 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +11 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/actions/registry.d.ts +68 -0
- package/dist/actions/registry.d.ts.map +1 -0
- package/dist/actions/registry.js +300 -0
- package/dist/actions/registry.js.map +1 -0
- package/dist/actions/types.d.ts +103 -0
- package/dist/actions/types.d.ts.map +1 -0
- package/dist/actions/types.js +10 -0
- package/dist/actions/types.js.map +1 -0
- package/dist/animation-tick.d.ts +28 -0
- package/dist/animation-tick.d.ts.map +1 -0
- package/dist/animation-tick.js +50 -0
- package/dist/animation-tick.js.map +1 -0
- package/dist/auto-compact.d.ts +27 -0
- package/dist/auto-compact.d.ts.map +1 -0
- package/dist/auto-compact.js +46 -0
- package/dist/auto-compact.js.map +1 -0
- package/dist/auto-layout-scheduler.d.ts +50 -0
- package/dist/auto-layout-scheduler.d.ts.map +1 -0
- package/dist/auto-layout-scheduler.js +94 -0
- package/dist/auto-layout-scheduler.js.map +1 -0
- package/dist/built-in-handlers.d.ts +24 -0
- package/dist/built-in-handlers.d.ts.map +1 -0
- package/dist/built-in-handlers.js +210 -0
- package/dist/built-in-handlers.js.map +1 -0
- package/dist/clipboard.d.ts +51 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +105 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/constants.d.ts +544 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +537 -0
- package/dist/constants.js.map +1 -0
- package/dist/dom-events.d.ts +13 -0
- package/dist/dom-events.d.ts.map +1 -0
- package/dist/dom-events.js +70 -0
- package/dist/dom-events.js.map +1 -0
- package/dist/editor/anchor-points.d.ts +22 -0
- package/dist/editor/anchor-points.d.ts.map +1 -0
- package/dist/editor/anchor-points.js +28 -0
- package/dist/editor/anchor-points.js.map +1 -0
- package/dist/editor/applies/create.d.ts +60 -0
- package/dist/editor/applies/create.d.ts.map +1 -0
- package/dist/editor/applies/create.js +107 -0
- package/dist/editor/applies/create.js.map +1 -0
- package/dist/editor/applies/edge.d.ts +32 -0
- package/dist/editor/applies/edge.d.ts.map +1 -0
- package/dist/editor/applies/edge.js +44 -0
- package/dist/editor/applies/edge.js.map +1 -0
- package/dist/editor/applies/link-move.d.ts +53 -0
- package/dist/editor/applies/link-move.d.ts.map +1 -0
- package/dist/editor/applies/link-move.js +160 -0
- package/dist/editor/applies/link-move.js.map +1 -0
- package/dist/editor/applies/move.d.ts +38 -0
- package/dist/editor/applies/move.d.ts.map +1 -0
- package/dist/editor/applies/move.js +83 -0
- package/dist/editor/applies/move.js.map +1 -0
- package/dist/editor/applies/resize.d.ts +68 -0
- package/dist/editor/applies/resize.d.ts.map +1 -0
- package/dist/editor/applies/resize.js +199 -0
- package/dist/editor/applies/resize.js.map +1 -0
- package/dist/editor/applies/selection.d.ts +34 -0
- package/dist/editor/applies/selection.d.ts.map +1 -0
- package/dist/editor/applies/selection.js +65 -0
- package/dist/editor/applies/selection.js.map +1 -0
- package/dist/editor/applies/snap-grid.d.ts +45 -0
- package/dist/editor/applies/snap-grid.d.ts.map +1 -0
- package/dist/editor/applies/snap-grid.js +90 -0
- package/dist/editor/applies/snap-grid.js.map +1 -0
- package/dist/editor/container-ops.d.ts +74 -0
- package/dist/editor/container-ops.d.ts.map +1 -0
- package/dist/editor/container-ops.js +262 -0
- package/dist/editor/container-ops.js.map +1 -0
- package/dist/editor/event-fanout.d.ts +48 -0
- package/dist/editor/event-fanout.d.ts.map +1 -0
- package/dist/editor/event-fanout.js +53 -0
- package/dist/editor/event-fanout.js.map +1 -0
- package/dist/editor/gesture-tx.d.ts +77 -0
- package/dist/editor/gesture-tx.d.ts.map +1 -0
- package/dist/editor/gesture-tx.js +93 -0
- package/dist/editor/gesture-tx.js.map +1 -0
- package/dist/editor/hit-test.d.ts +178 -0
- package/dist/editor/hit-test.d.ts.map +1 -0
- package/dist/editor/hit-test.js +460 -0
- package/dist/editor/hit-test.js.map +1 -0
- package/dist/editor/long-press.d.ts +34 -0
- package/dist/editor/long-press.d.ts.map +1 -0
- package/dist/editor/long-press.js +58 -0
- package/dist/editor/long-press.js.map +1 -0
- package/dist/editor/pinch.d.ts +37 -0
- package/dist/editor/pinch.d.ts.map +1 -0
- package/dist/editor/pinch.js +90 -0
- package/dist/editor/pinch.js.map +1 -0
- package/dist/editor/pointer-binding.d.ts +18 -0
- package/dist/editor/pointer-binding.d.ts.map +1 -0
- package/dist/editor/pointer-binding.js +1087 -0
- package/dist/editor/pointer-binding.js.map +1 -0
- package/dist/editor/public/annotations.d.ts +54 -0
- package/dist/editor/public/annotations.d.ts.map +1 -0
- package/dist/editor/public/annotations.js +106 -0
- package/dist/editor/public/annotations.js.map +1 -0
- package/dist/editor/public/arrange-group.d.ts +81 -0
- package/dist/editor/public/arrange-group.d.ts.map +1 -0
- package/dist/editor/public/arrange-group.js +193 -0
- package/dist/editor/public/arrange-group.js.map +1 -0
- package/dist/editor/public/brush.d.ts +33 -0
- package/dist/editor/public/brush.d.ts.map +1 -0
- package/dist/editor/public/brush.js +54 -0
- package/dist/editor/public/brush.js.map +1 -0
- package/dist/editor/public/clipboard.d.ts +31 -0
- package/dist/editor/public/clipboard.d.ts.map +1 -0
- package/dist/editor/public/clipboard.js +35 -0
- package/dist/editor/public/clipboard.js.map +1 -0
- package/dist/editor/public/image-insert.d.ts +30 -0
- package/dist/editor/public/image-insert.d.ts.map +1 -0
- package/dist/editor/public/image-insert.js +57 -0
- package/dist/editor/public/image-insert.js.map +1 -0
- package/dist/editor/public/layers.d.ts +56 -0
- package/dist/editor/public/layers.d.ts.map +1 -0
- package/dist/editor/public/layers.js +104 -0
- package/dist/editor/public/layers.js.map +1 -0
- package/dist/editor/public/link.d.ts +25 -0
- package/dist/editor/public/link.d.ts.map +1 -0
- package/dist/editor/public/link.js +74 -0
- package/dist/editor/public/link.js.map +1 -0
- package/dist/editor/public/placement.d.ts +60 -0
- package/dist/editor/public/placement.d.ts.map +1 -0
- package/dist/editor/public/placement.js +111 -0
- package/dist/editor/public/placement.js.map +1 -0
- package/dist/editor/public/selection-ops.d.ts +78 -0
- package/dist/editor/public/selection-ops.d.ts.map +1 -0
- package/dist/editor/public/selection-ops.js +226 -0
- package/dist/editor/public/selection-ops.js.map +1 -0
- package/dist/editor/public/text-edit.d.ts +17 -0
- package/dist/editor/public/text-edit.d.ts.map +1 -0
- package/dist/editor/public/text-edit.js +28 -0
- package/dist/editor/public/text-edit.js.map +1 -0
- package/dist/editor/public/z-order.d.ts +47 -0
- package/dist/editor/public/z-order.d.ts.map +1 -0
- package/dist/editor/public/z-order.js +151 -0
- package/dist/editor/public/z-order.js.map +1 -0
- package/dist/editor/public/zoom-pan.d.ts +44 -0
- package/dist/editor/public/zoom-pan.d.ts.map +1 -0
- package/dist/editor/public/zoom-pan.js +116 -0
- package/dist/editor/public/zoom-pan.js.map +1 -0
- package/dist/editor/render-orchestrator.d.ts +11 -0
- package/dist/editor/render-orchestrator.d.ts.map +1 -0
- package/dist/editor/render-orchestrator.js +473 -0
- package/dist/editor/render-orchestrator.js.map +1 -0
- package/dist/editor/resize-helpers.d.ts +30 -0
- package/dist/editor/resize-helpers.d.ts.map +1 -0
- package/dist/editor/resize-helpers.js +121 -0
- package/dist/editor/resize-helpers.js.map +1 -0
- package/dist/editor/shape-filters.d.ts +11 -0
- package/dist/editor/shape-filters.d.ts.map +1 -0
- package/dist/editor/shape-filters.js +19 -0
- package/dist/editor/shape-filters.js.map +1 -0
- package/dist/editor/shape-traits.d.ts +16 -0
- package/dist/editor/shape-traits.d.ts.map +1 -0
- package/dist/editor/shape-traits.js +29 -0
- package/dist/editor/shape-traits.js.map +1 -0
- package/dist/editor/viewport-helpers.d.ts +24 -0
- package/dist/editor/viewport-helpers.d.ts.map +1 -0
- package/dist/editor/viewport-helpers.js +63 -0
- package/dist/editor/viewport-helpers.js.map +1 -0
- package/dist/editor-events.d.ts +33 -0
- package/dist/editor-events.d.ts.map +1 -0
- package/dist/editor-events.js +2 -0
- package/dist/editor-events.js.map +1 -0
- package/dist/editor.d.ts +1841 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +4803 -0
- package/dist/editor.js.map +1 -0
- package/dist/file-drop.d.ts +99 -0
- package/dist/file-drop.d.ts.map +1 -0
- package/dist/file-drop.js +198 -0
- package/dist/file-drop.js.map +1 -0
- package/dist/frame-helpers.d.ts +30 -0
- package/dist/frame-helpers.d.ts.map +1 -0
- package/dist/frame-helpers.js +105 -0
- package/dist/frame-helpers.js.map +1 -0
- package/dist/group-helpers.d.ts +39 -0
- package/dist/group-helpers.d.ts.map +1 -0
- package/dist/group-helpers.js +116 -0
- package/dist/group-helpers.js.map +1 -0
- package/dist/handle.d.ts +73 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/handle.js +184 -0
- package/dist/handle.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive.d.ts +21 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +11 -0
- package/dist/interactive.js.map +1 -0
- package/dist/link-selection.d.ts +21 -0
- package/dist/link-selection.d.ts.map +1 -0
- package/dist/link-selection.js +37 -0
- package/dist/link-selection.js.map +1 -0
- package/dist/machine.d.ts +322 -0
- package/dist/machine.d.ts.map +1 -0
- package/dist/machine.js +568 -0
- package/dist/machine.js.map +1 -0
- package/dist/modes.d.ts +24 -0
- package/dist/modes.d.ts.map +1 -0
- package/dist/modes.js +2 -0
- package/dist/modes.js.map +1 -0
- package/dist/overlay.d.ts +262 -0
- package/dist/overlay.d.ts.map +1 -0
- package/dist/overlay.js +673 -0
- package/dist/overlay.js.map +1 -0
- package/dist/platform.d.ts +70 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +115 -0
- package/dist/platform.js.map +1 -0
- package/dist/selection.d.ts +18 -0
- package/dist/selection.d.ts.map +1 -0
- package/dist/selection.js +31 -0
- package/dist/selection.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type Scene, type Element, type Patch } from "@oh-just-another/scene";
|
|
2
|
+
import type { Bounds, ElementId } from "@oh-just-another/types";
|
|
3
|
+
import type { HandleId } from "../handle.js";
|
|
4
|
+
/**
|
|
5
|
+
* Pure: fraction of `child`'s area that lies inside `zone`.
|
|
6
|
+
* Returns 0 when either bbox is degenerate or they don't
|
|
7
|
+
* intersect. Used by the container drop handler to decide between
|
|
8
|
+
* "child still belongs to the lane" and "user dragged it out".
|
|
9
|
+
*/
|
|
10
|
+
export declare const coverageRatio: (child: Bounds, zone: Bounds) => number;
|
|
11
|
+
/**
|
|
12
|
+
* Pure: union of every direct child's world-space AABB. Returns
|
|
13
|
+
* `null` when the container has no children. Only direct children
|
|
14
|
+
* are constrained because container resize doesn't cascade into
|
|
15
|
+
* nested containers (the inner one self-constrains via its own
|
|
16
|
+
* clamp call).
|
|
17
|
+
*/
|
|
18
|
+
export declare const childrenWorldUnion: (scene: Scene, containerId: ElementId) => Bounds | null;
|
|
19
|
+
/**
|
|
20
|
+
* Pure: floor the proposed container bounds to whatever is
|
|
21
|
+
* required to keep every child fully inside the drop-zone. The
|
|
22
|
+
* expansion is applied at the edges touched by `handle`, so the
|
|
23
|
+
* dragged corner / side keeps controlling direction — the shape
|
|
24
|
+
* just refuses to go smaller than the children mandate.
|
|
25
|
+
*
|
|
26
|
+
* Works for any shape with a `ContainerSpec` (template-driven or
|
|
27
|
+
* static metadata). Returns `raw` unchanged when the shape has no
|
|
28
|
+
* children or isn't a container.
|
|
29
|
+
*/
|
|
30
|
+
export declare const clampContainerToChildren: (scene: Scene, shape: Element, raw: Bounds, handle: HandleId) => Bounds;
|
|
31
|
+
/**
|
|
32
|
+
* Narrow editor surface used by `ContainerController`. The
|
|
33
|
+
* controller writes patches back through `applyPatch` and the
|
|
34
|
+
* gesture-transaction callbacks instead of carrying its own
|
|
35
|
+
* scene / history references — keeps the call sites local to
|
|
36
|
+
* Editor (and the transaction model untouched).
|
|
37
|
+
*/
|
|
38
|
+
export interface ContainerOpsRef {
|
|
39
|
+
readonly scene: Scene;
|
|
40
|
+
readonly dragElementId: ElementId | null;
|
|
41
|
+
readonly containerHover: {
|
|
42
|
+
readonly id: ElementId;
|
|
43
|
+
} | null;
|
|
44
|
+
/** Apply the patch to the editor's scene + record into the open gesture tx. */
|
|
45
|
+
applyPatch(patch: Patch, nextScene: Scene): void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* End-of-drag container hookup: reparent into hovered container,
|
|
49
|
+
* grow the parent to fit the dropped child, or drag-out when the
|
|
50
|
+
* coverage check fails. All patches go through the same gesture
|
|
51
|
+
* transaction so the reparent + auto-grow land in one undo step.
|
|
52
|
+
*
|
|
53
|
+
* Rules:
|
|
54
|
+
* - hovering a container that's NOT the current parent → reparent
|
|
55
|
+
* + bump to top z-order of the layer, then grow zone to fit;
|
|
56
|
+
* - hovering the same container that IS the current parent →
|
|
57
|
+
* auto-grow if the child overflowed during the drag;
|
|
58
|
+
* - no hover but had a parent → coverage check; ≥ keep threshold
|
|
59
|
+
* stays parented (with grow), else drag-out (remove parentId).
|
|
60
|
+
* - `group` parents are special: logical wrappers, never drag-out.
|
|
61
|
+
*
|
|
62
|
+
* `_worldPoint` is unused; kept on the signature for the exact
|
|
63
|
+
* release coordinates.
|
|
64
|
+
*/
|
|
65
|
+
export declare const applyContainerDrop: (ref: ContainerOpsRef, _worldPoint: unknown) => void;
|
|
66
|
+
/**
|
|
67
|
+
* If `childId` no longer fits inside `containerId`'s drop-zone,
|
|
68
|
+
* expand the zone + the container's outer size. Single patch
|
|
69
|
+
* added through `ref.applyPatch` (and therefore into the running
|
|
70
|
+
* gesture transaction). Skips no-op cases (already fits,
|
|
71
|
+
* container has no width/height field, no container spec).
|
|
72
|
+
*/
|
|
73
|
+
export declare const maybeGrowContainer: (ref: ContainerOpsRef, containerId: ElementId, childId: ElementId) => void;
|
|
74
|
+
//# sourceMappingURL=container-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container-ops.d.ts","sourceRoot":"","sources":["../../src/editor/container-ops.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,KAAG,MAW3D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,KAAK,EAAE,aAAa,SAAS,KAAG,MAAM,GAAG,IAQlF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,KAAK,EACZ,OAAO,OAAO,EACd,KAAK,MAAM,EACX,QAAQ,QAAQ,KACf,MAmDF,CAAC;AAsCF;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3D,+EAA+E;IAC/E,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,GAC7B,KAAK,eAAe,EACpB,aAAa,OAAO,KACnB,IA0DF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,KAAK,eAAe,EACpB,aAAa,SAAS,EACtB,SAAS,SAAS,KACjB,IA0CF,CAAC"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { containerSizeForZone, expandDropZoneToFit, getAutoLayoutSpec, getContainerSpec, getDropZoneWorld, getElement, getElementWorldBounds, isContainer, measureWrap, orderForTop, updateElement, } from "@oh-just-another/scene";
|
|
2
|
+
import { bounds as B } from "@oh-just-another/math";
|
|
3
|
+
import { CONTAINER_KEEP_THRESHOLD } from "../constants.js";
|
|
4
|
+
import { hasWidthHeight } from "./shape-traits.js";
|
|
5
|
+
/**
|
|
6
|
+
* Pure: fraction of `child`'s area that lies inside `zone`.
|
|
7
|
+
* Returns 0 when either bbox is degenerate or they don't
|
|
8
|
+
* intersect. Used by the container drop handler to decide between
|
|
9
|
+
* "child still belongs to the lane" and "user dragged it out".
|
|
10
|
+
*/
|
|
11
|
+
export const coverageRatio = (child, zone) => {
|
|
12
|
+
const area = child.width * child.height;
|
|
13
|
+
if (area <= 0)
|
|
14
|
+
return 0;
|
|
15
|
+
const ix = Math.max(child.x, zone.x);
|
|
16
|
+
const iy = Math.max(child.y, zone.y);
|
|
17
|
+
const ix2 = Math.min(child.x + child.width, zone.x + zone.width);
|
|
18
|
+
const iy2 = Math.min(child.y + child.height, zone.y + zone.height);
|
|
19
|
+
const iw = ix2 - ix;
|
|
20
|
+
const ih = iy2 - iy;
|
|
21
|
+
if (iw <= 0 || ih <= 0)
|
|
22
|
+
return 0;
|
|
23
|
+
return (iw * ih) / area;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Pure: union of every direct child's world-space AABB. Returns
|
|
27
|
+
* `null` when the container has no children. Only direct children
|
|
28
|
+
* are constrained because container resize doesn't cascade into
|
|
29
|
+
* nested containers (the inner one self-constrains via its own
|
|
30
|
+
* clamp call).
|
|
31
|
+
*/
|
|
32
|
+
export const childrenWorldUnion = (scene, containerId) => {
|
|
33
|
+
let acc = null;
|
|
34
|
+
for (const s of scene.elements.values()) {
|
|
35
|
+
if (s.parentId !== containerId)
|
|
36
|
+
continue;
|
|
37
|
+
const b = getElementWorldBounds(s);
|
|
38
|
+
acc = acc ? B.union(acc, b) : b;
|
|
39
|
+
}
|
|
40
|
+
return acc;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Pure: floor the proposed container bounds to whatever is
|
|
44
|
+
* required to keep every child fully inside the drop-zone. The
|
|
45
|
+
* expansion is applied at the edges touched by `handle`, so the
|
|
46
|
+
* dragged corner / side keeps controlling direction — the shape
|
|
47
|
+
* just refuses to go smaller than the children mandate.
|
|
48
|
+
*
|
|
49
|
+
* Works for any shape with a `ContainerSpec` (template-driven or
|
|
50
|
+
* static metadata). Returns `raw` unchanged when the shape has no
|
|
51
|
+
* children or isn't a container.
|
|
52
|
+
*/
|
|
53
|
+
export const clampContainerToChildren = (scene, shape, raw, handle) => {
|
|
54
|
+
if (!isContainer(shape) || !hasWidthHeight(shape))
|
|
55
|
+
return raw;
|
|
56
|
+
// Wrap containers REFLOW on resize: the width may shrink down to the widest
|
|
57
|
+
// single child (children re-wrap into more rows); the height is floored to
|
|
58
|
+
// the wrapped content height and grows down. The children-union clamp below
|
|
59
|
+
// would forbid narrowing, so handle wrap separately.
|
|
60
|
+
if (getAutoLayoutSpec(shape)?.kind === "wrap") {
|
|
61
|
+
return clampWrapContainer(scene, shape, raw, handle);
|
|
62
|
+
}
|
|
63
|
+
const childrenBox = childrenWorldUnion(scene, shape.id);
|
|
64
|
+
if (!childrenBox)
|
|
65
|
+
return raw;
|
|
66
|
+
// Compose a hypothetical container with the proposed bounds, then
|
|
67
|
+
// ask the resolver where the drop-zone lands at that size. Chrome
|
|
68
|
+
// (header / margin / padding) stays constant across resize, so a
|
|
69
|
+
// single-pass expansion is sound for typical templates.
|
|
70
|
+
const hypothetical = {
|
|
71
|
+
...shape,
|
|
72
|
+
position: { x: raw.x, y: raw.y },
|
|
73
|
+
width: raw.width,
|
|
74
|
+
height: raw.height,
|
|
75
|
+
};
|
|
76
|
+
const dropZoneWorld = getDropZoneWorld(hypothetical);
|
|
77
|
+
if (!dropZoneWorld)
|
|
78
|
+
return raw;
|
|
79
|
+
let { x, y, width, height } = raw;
|
|
80
|
+
const dx0 = dropZoneWorld.x;
|
|
81
|
+
const dy0 = dropZoneWorld.y;
|
|
82
|
+
const dx1 = dropZoneWorld.x + dropZoneWorld.width;
|
|
83
|
+
const dy1 = dropZoneWorld.y + dropZoneWorld.height;
|
|
84
|
+
const cx0 = childrenBox.x;
|
|
85
|
+
const cy0 = childrenBox.y;
|
|
86
|
+
const cx1 = childrenBox.x + childrenBox.width;
|
|
87
|
+
const cy1 = childrenBox.y + childrenBox.height;
|
|
88
|
+
if (handle.includes("e") && dx1 < cx1) {
|
|
89
|
+
width += cx1 - dx1;
|
|
90
|
+
}
|
|
91
|
+
if (handle.includes("s") && dy1 < cy1) {
|
|
92
|
+
height += cy1 - dy1;
|
|
93
|
+
}
|
|
94
|
+
if (handle.includes("w") && dx0 > cx0) {
|
|
95
|
+
const shift = dx0 - cx0;
|
|
96
|
+
x -= shift;
|
|
97
|
+
width += shift;
|
|
98
|
+
}
|
|
99
|
+
if (handle.includes("n") && dy0 > cy0) {
|
|
100
|
+
const shift = dy0 - cy0;
|
|
101
|
+
y -= shift;
|
|
102
|
+
height += shift;
|
|
103
|
+
}
|
|
104
|
+
return { x, y, width, height };
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Resize clamp for a wrap (flex-wrap) container: width floors at the widest
|
|
108
|
+
* single child (+padding) — narrower has nowhere to wrap; height floors at the
|
|
109
|
+
* wrapped content height at the resulting width and grows DOWN. The dragged
|
|
110
|
+
* edge keeps controlling direction (west/north shift the opposite edge).
|
|
111
|
+
*/
|
|
112
|
+
const clampWrapContainer = (scene, shape, raw, handle) => {
|
|
113
|
+
const pad = getContainerSpec(shape)?.padding ?? 0;
|
|
114
|
+
const rawInner = Math.max(0, raw.width - 2 * pad);
|
|
115
|
+
const m = measureWrap(scene, shape.id, rawInner);
|
|
116
|
+
if (!m)
|
|
117
|
+
return raw; // no children → no constraint
|
|
118
|
+
let { x, y, width, height } = raw;
|
|
119
|
+
const minWidth = m.widest + 2 * pad;
|
|
120
|
+
if (width < minWidth) {
|
|
121
|
+
const deficit = minWidth - width;
|
|
122
|
+
width = minWidth;
|
|
123
|
+
if (handle.includes("w"))
|
|
124
|
+
x -= deficit; // keep the east edge fixed
|
|
125
|
+
}
|
|
126
|
+
// Content height at the FINAL width (narrower ⇒ more rows ⇒ taller).
|
|
127
|
+
const finalInner = Math.max(0, width - 2 * pad);
|
|
128
|
+
const mh = finalInner === rawInner ? m : (measureWrap(scene, shape.id, finalInner) ?? m);
|
|
129
|
+
const minHeight = mh.contentHeight + 2 * pad;
|
|
130
|
+
if (height < minHeight) {
|
|
131
|
+
const deficit = minHeight - height;
|
|
132
|
+
height = minHeight;
|
|
133
|
+
if (handle.includes("n"))
|
|
134
|
+
y -= deficit; // keep the south edge fixed
|
|
135
|
+
}
|
|
136
|
+
return { x, y, width, height };
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* End-of-drag container hookup: reparent into hovered container,
|
|
140
|
+
* grow the parent to fit the dropped child, or drag-out when the
|
|
141
|
+
* coverage check fails. All patches go through the same gesture
|
|
142
|
+
* transaction so the reparent + auto-grow land in one undo step.
|
|
143
|
+
*
|
|
144
|
+
* Rules:
|
|
145
|
+
* - hovering a container that's NOT the current parent → reparent
|
|
146
|
+
* + bump to top z-order of the layer, then grow zone to fit;
|
|
147
|
+
* - hovering the same container that IS the current parent →
|
|
148
|
+
* auto-grow if the child overflowed during the drag;
|
|
149
|
+
* - no hover but had a parent → coverage check; ≥ keep threshold
|
|
150
|
+
* stays parented (with grow), else drag-out (remove parentId).
|
|
151
|
+
* - `group` parents are special: logical wrappers, never drag-out.
|
|
152
|
+
*
|
|
153
|
+
* `_worldPoint` is unused; kept on the signature for the exact
|
|
154
|
+
* release coordinates.
|
|
155
|
+
*/
|
|
156
|
+
export const applyContainerDrop = (ref, _worldPoint) => {
|
|
157
|
+
const dragId = ref.dragElementId;
|
|
158
|
+
if (!dragId)
|
|
159
|
+
return;
|
|
160
|
+
const shape = getElement(ref.scene, dragId);
|
|
161
|
+
if (!shape)
|
|
162
|
+
return;
|
|
163
|
+
const hover = ref.containerHover;
|
|
164
|
+
if (hover && hover.id !== shape.parentId) {
|
|
165
|
+
// Reparent into hovered container. Bump the dropped shape to
|
|
166
|
+
// top z-order of its layer so it lands ABOVE the container's
|
|
167
|
+
// visual body (otherwise the container's fill obscures it).
|
|
168
|
+
const topOrder = orderForTop([...ref.scene.elements.values()]
|
|
169
|
+
.filter((s) => s.layerId === shape.layerId && s.id !== dragId)
|
|
170
|
+
.map((s) => s.order));
|
|
171
|
+
const r = updateElement(ref.scene, dragId, (s) => ({
|
|
172
|
+
...s,
|
|
173
|
+
parentId: hover.id,
|
|
174
|
+
order: topOrder,
|
|
175
|
+
}));
|
|
176
|
+
ref.applyPatch(r.patch, r.scene);
|
|
177
|
+
maybeGrowContainer(ref, hover.id, dragId);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (hover && hover.id === shape.parentId) {
|
|
181
|
+
// Drag-within: cursor still over the same parent. If the
|
|
182
|
+
// child's bounds overflow the drop-zone, grow the parent.
|
|
183
|
+
maybeGrowContainer(ref, shape.parentId, dragId);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (shape.parentId) {
|
|
187
|
+
const parent = getElement(ref.scene, shape.parentId);
|
|
188
|
+
// Group parents have no drop-zone — they're logical wrappers,
|
|
189
|
+
// not spatial containers. The drag-out / coverage logic is for
|
|
190
|
+
// proper containers (swimlane, frame, template); a group child
|
|
191
|
+
// must stay parented to its group regardless of its world bounds.
|
|
192
|
+
if (parent?.type === "group")
|
|
193
|
+
return;
|
|
194
|
+
// hover = null: cursor left the parent's zone, but the child
|
|
195
|
+
// itself may still be mostly inside. Coverage check decides:
|
|
196
|
+
// ≥ CONTAINER_KEEP_THRESHOLD → keep parent + grow zone to fit.
|
|
197
|
+
// < threshold → un-parent (drag-out).
|
|
198
|
+
const parentZone = parent ? getDropZoneWorld(parent) : null;
|
|
199
|
+
const childBounds = getElementWorldBounds(shape);
|
|
200
|
+
const coverage = parentZone ? coverageRatio(childBounds, parentZone) : 0;
|
|
201
|
+
if (parentZone && coverage >= CONTAINER_KEEP_THRESHOLD) {
|
|
202
|
+
maybeGrowContainer(ref, shape.parentId, dragId);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const r = updateElement(ref.scene, dragId, (s) => {
|
|
206
|
+
const next = { ...s };
|
|
207
|
+
delete next.parentId;
|
|
208
|
+
return next;
|
|
209
|
+
});
|
|
210
|
+
ref.applyPatch(r.patch, r.scene);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* If `childId` no longer fits inside `containerId`'s drop-zone,
|
|
215
|
+
* expand the zone + the container's outer size. Single patch
|
|
216
|
+
* added through `ref.applyPatch` (and therefore into the running
|
|
217
|
+
* gesture transaction). Skips no-op cases (already fits,
|
|
218
|
+
* container has no width/height field, no container spec).
|
|
219
|
+
*/
|
|
220
|
+
export const maybeGrowContainer = (ref, containerId, childId) => {
|
|
221
|
+
const container = getElement(ref.scene, containerId);
|
|
222
|
+
const child = getElement(ref.scene, childId);
|
|
223
|
+
if (!container || !child)
|
|
224
|
+
return;
|
|
225
|
+
const spec = getContainerSpec(container);
|
|
226
|
+
if (!spec)
|
|
227
|
+
return;
|
|
228
|
+
const childWorld = getElementWorldBounds(child);
|
|
229
|
+
const expanded = expandDropZoneToFit(container, childWorld);
|
|
230
|
+
if (!expanded)
|
|
231
|
+
return;
|
|
232
|
+
if (hasWidthHeight(container)) {
|
|
233
|
+
const sized = containerSizeForZone({ width: container.width, height: container.height, spec }, expanded);
|
|
234
|
+
const r = updateElement(ref.scene, containerId, (s) => ({
|
|
235
|
+
...s,
|
|
236
|
+
position: {
|
|
237
|
+
x: s.position.x + sized.positionOffset.x,
|
|
238
|
+
y: s.position.y + sized.positionOffset.y,
|
|
239
|
+
},
|
|
240
|
+
width: sized.width,
|
|
241
|
+
height: sized.height,
|
|
242
|
+
metadata: {
|
|
243
|
+
...(s.metadata ?? {}),
|
|
244
|
+
container: { ...spec, dropZone: expanded },
|
|
245
|
+
},
|
|
246
|
+
}));
|
|
247
|
+
ref.applyPatch(r.patch, r.scene);
|
|
248
|
+
// Children are stored in absolute world coords — translating
|
|
249
|
+
// the container's `position` does NOT visually move them, so
|
|
250
|
+
// no compensating patch is needed.
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const r = updateElement(ref.scene, containerId, (s) => ({
|
|
254
|
+
...s,
|
|
255
|
+
metadata: {
|
|
256
|
+
...(s.metadata ?? {}),
|
|
257
|
+
container: { ...spec, dropZone: expanded },
|
|
258
|
+
},
|
|
259
|
+
}));
|
|
260
|
+
ref.applyPatch(r.patch, r.scene);
|
|
261
|
+
};
|
|
262
|
+
//# sourceMappingURL=container-ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container-ops.js","sourceRoot":"","sources":["../../src/editor/container-ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Scene } from "@oh-just-another/scene";
|
|
2
|
+
import type { Emitter } from "@oh-just-another/events";
|
|
3
|
+
import type * as Selection from "../selection.js";
|
|
4
|
+
import type { Mode } from "../modes.js";
|
|
5
|
+
import type { EditorEvents } from "../editor-events.js";
|
|
6
|
+
/**
|
|
7
|
+
* Holds the last-emitted snapshot of every observable Editor slice
|
|
8
|
+
* so `fanOutEvents` can decide which typed events to fire on the
|
|
9
|
+
* next `notify()`. Created once per Editor and primed in the
|
|
10
|
+
* constructor with the initial state so the *first* user-driven
|
|
11
|
+
* update only fires on a real flip.
|
|
12
|
+
*/
|
|
13
|
+
export interface EditorEventCache {
|
|
14
|
+
mode: Mode | null;
|
|
15
|
+
selection: Selection.Selection | null;
|
|
16
|
+
scene: Scene | null;
|
|
17
|
+
viewport: Scene["viewport"] | null;
|
|
18
|
+
canUndo: boolean;
|
|
19
|
+
canRedo: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare const createEventCache: () => EditorEventCache;
|
|
22
|
+
/**
|
|
23
|
+
* Snapshot of the editor's observable state at a single moment.
|
|
24
|
+
* Passed to `fanOutEvents` instead of the live editor so this
|
|
25
|
+
* module doesn't import the Editor class (would create a cycle).
|
|
26
|
+
*/
|
|
27
|
+
export interface EditorObservableSnapshot {
|
|
28
|
+
readonly mode: Mode;
|
|
29
|
+
readonly selection: Selection.Selection;
|
|
30
|
+
readonly scene: Scene;
|
|
31
|
+
readonly canUndo: boolean;
|
|
32
|
+
readonly canRedo: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Compare each slice against the cached last-emitted value and
|
|
36
|
+
* fire only the typed events that actually flipped — then fire
|
|
37
|
+
* the umbrella `change` once. Returns nothing; mutates `cache` in
|
|
38
|
+
* place to the new values. Side-effect free apart from the emit
|
|
39
|
+
* calls themselves.
|
|
40
|
+
*
|
|
41
|
+
* Scene / viewport are compared by identity (scene structures use
|
|
42
|
+
* structural sharing — a new reference iff something inside
|
|
43
|
+
* changed).
|
|
44
|
+
*/
|
|
45
|
+
export declare const fanOutEvents: (cache: EditorEventCache, events: Emitter<EditorEvents>, snapshot: EditorObservableSnapshot) => void;
|
|
46
|
+
/** Seed the cache with initial editor state — call once after construction. */
|
|
47
|
+
export declare const primeEventCache: (cache: EditorEventCache, snapshot: EditorObservableSnapshot) => void;
|
|
48
|
+
//# sourceMappingURL=event-fanout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-fanout.d.ts","sourceRoot":"","sources":["../../src/editor/event-fanout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC;IACtC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,gBAAgB,QAAO,gBAOlC,CAAC;AAEH;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GACvB,OAAO,gBAAgB,EACvB,QAAQ,OAAO,CAAC,YAAY,CAAC,EAC7B,UAAU,wBAAwB,KACjC,IAuBF,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,eAAe,GAC1B,OAAO,gBAAgB,EACvB,UAAU,wBAAwB,KACjC,IAOF,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export const createEventCache = () => ({
|
|
2
|
+
mode: null,
|
|
3
|
+
selection: null,
|
|
4
|
+
scene: null,
|
|
5
|
+
viewport: null,
|
|
6
|
+
canUndo: false,
|
|
7
|
+
canRedo: false,
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* Compare each slice against the cached last-emitted value and
|
|
11
|
+
* fire only the typed events that actually flipped — then fire
|
|
12
|
+
* the umbrella `change` once. Returns nothing; mutates `cache` in
|
|
13
|
+
* place to the new values. Side-effect free apart from the emit
|
|
14
|
+
* calls themselves.
|
|
15
|
+
*
|
|
16
|
+
* Scene / viewport are compared by identity (scene structures use
|
|
17
|
+
* structural sharing — a new reference iff something inside
|
|
18
|
+
* changed).
|
|
19
|
+
*/
|
|
20
|
+
export const fanOutEvents = (cache, events, snapshot) => {
|
|
21
|
+
if (snapshot.mode !== cache.mode) {
|
|
22
|
+
cache.mode = snapshot.mode;
|
|
23
|
+
events.emit("mode", snapshot.mode);
|
|
24
|
+
}
|
|
25
|
+
if (snapshot.selection !== cache.selection) {
|
|
26
|
+
cache.selection = snapshot.selection;
|
|
27
|
+
events.emit("selection", snapshot.selection);
|
|
28
|
+
}
|
|
29
|
+
if (snapshot.scene !== cache.scene) {
|
|
30
|
+
cache.scene = snapshot.scene;
|
|
31
|
+
events.emit("scene", snapshot.scene);
|
|
32
|
+
}
|
|
33
|
+
if (snapshot.scene.viewport !== cache.viewport) {
|
|
34
|
+
cache.viewport = snapshot.scene.viewport;
|
|
35
|
+
events.emit("viewport", snapshot.scene);
|
|
36
|
+
}
|
|
37
|
+
if (snapshot.canUndo !== cache.canUndo || snapshot.canRedo !== cache.canRedo) {
|
|
38
|
+
cache.canUndo = snapshot.canUndo;
|
|
39
|
+
cache.canRedo = snapshot.canRedo;
|
|
40
|
+
events.emit("history", { canUndo: snapshot.canUndo, canRedo: snapshot.canRedo });
|
|
41
|
+
}
|
|
42
|
+
events.emit("change");
|
|
43
|
+
};
|
|
44
|
+
/** Seed the cache with initial editor state — call once after construction. */
|
|
45
|
+
export const primeEventCache = (cache, snapshot) => {
|
|
46
|
+
cache.mode = snapshot.mode;
|
|
47
|
+
cache.selection = snapshot.selection;
|
|
48
|
+
cache.scene = snapshot.scene;
|
|
49
|
+
cache.viewport = snapshot.scene.viewport;
|
|
50
|
+
cache.canUndo = snapshot.canUndo;
|
|
51
|
+
cache.canRedo = snapshot.canRedo;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=event-fanout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-fanout.js","sourceRoot":"","sources":["../../src/editor/event-fanout.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAqB,EAAE,CAAC,CAAC;IACvD,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;CACf,CAAC,CAAC;AAeH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAuB,EACvB,MAA6B,EAC7B,QAAkC,EAC5B,EAAE;IACR,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,EAAE,CAAC;QAC3C,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;QACnC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC/C,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7E,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QACjC,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAAuB,EACvB,QAAkC,EAC5B,EAAE;IACR,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;IACrC,KAAK,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC7B,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;IACzC,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACjC,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;AACnC,CAAC,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Link, Patch } from "@oh-just-another/scene";
|
|
2
|
+
import type { Bounds, ElementId, LinkId, Vec2 } from "@oh-just-another/types";
|
|
3
|
+
import type { HistoryProvider, TransactionHandle } from "@oh-just-another/history";
|
|
4
|
+
import type { Mode } from "../modes.js";
|
|
5
|
+
/**
|
|
6
|
+
* Narrow editor surface that `GestureController` needs. Editor
|
|
7
|
+
* implements this implicitly by exposing the listed fields and
|
|
8
|
+
* methods to the controller through a thin internal-only bridge
|
|
9
|
+
* object — this module never imports the full `Editor` class so
|
|
10
|
+
* it stays small and acycle-free.
|
|
11
|
+
*
|
|
12
|
+
* Fields are written by the controller (`gestureTx`;
|
|
13
|
+
* `groupMoveOrigin` etc. are cleared on every commit) and are
|
|
14
|
+
* internal — not exposed externally.
|
|
15
|
+
*/
|
|
16
|
+
export interface GestureRef {
|
|
17
|
+
readonly history: HistoryProvider;
|
|
18
|
+
gestureTx: TransactionHandle | null;
|
|
19
|
+
groupMoveOrigin: ReadonlyMap<ElementId, Vec2> | null;
|
|
20
|
+
groupLinkMoveOrigin: ReadonlyMap<LinkId, Link> | null;
|
|
21
|
+
groupResizeOrigin: {
|
|
22
|
+
readonly combined: Bounds;
|
|
23
|
+
readonly elements: ReadonlyMap<ElementId, {
|
|
24
|
+
readonly position: Vec2;
|
|
25
|
+
readonly bounds: Bounds;
|
|
26
|
+
readonly scale: Vec2;
|
|
27
|
+
}>;
|
|
28
|
+
readonly links: ReadonlyMap<LinkId, Link>;
|
|
29
|
+
} | null;
|
|
30
|
+
dragElementId: ElementId | null;
|
|
31
|
+
containerHover: {
|
|
32
|
+
id: ElementId;
|
|
33
|
+
dropZone: Bounds;
|
|
34
|
+
} | null;
|
|
35
|
+
readonly toolLocked: boolean;
|
|
36
|
+
readonly mode: Mode;
|
|
37
|
+
setMode(mode: Mode): void;
|
|
38
|
+
notify(): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Gesture lifecycle controller. Wraps the open-transaction model
|
|
42
|
+
* — drag / resize / multi-step operations open a `TransactionHandle`
|
|
43
|
+
* on first move, append patches as they arrive, commit on
|
|
44
|
+
* POINTER_UP. `commit` also clears the drag-target scratch fields
|
|
45
|
+
* and unconditionally fires a final notify so downstream
|
|
46
|
+
* subscribers (Undo/Redo button, mode toggle) update even when
|
|
47
|
+
* intermediate xstate re-entrancy queued events that only drained
|
|
48
|
+
* after the outer event handler returned.
|
|
49
|
+
*/
|
|
50
|
+
export declare class GestureController {
|
|
51
|
+
private readonly ref;
|
|
52
|
+
constructor(ref: GestureRef);
|
|
53
|
+
/**
|
|
54
|
+
* Open a gesture transaction on the first drag-emitted patch,
|
|
55
|
+
* then add subsequent patches to it. POINTER_UP commits it as
|
|
56
|
+
* one history record.
|
|
57
|
+
*/
|
|
58
|
+
record(patch: Patch): void;
|
|
59
|
+
commit(): void;
|
|
60
|
+
cancel(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Defensive cleanup invoked by public commands (paste, etc.)
|
|
63
|
+
* that open their own history transaction. A real gesture-in-
|
|
64
|
+
* flight gets committed (preserving user work); a stale tx that
|
|
65
|
+
* survived an earlier exception gets cancelled. Either way the
|
|
66
|
+
* next `transaction()` call lands on a clean slot, so pressing
|
|
67
|
+
* Cmd+V mid-drag doesn't throw "A transaction is already open".
|
|
68
|
+
*/
|
|
69
|
+
finalize(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Internal hook — called from `applyCreate` / `applyCreateLink`
|
|
72
|
+
* after a successful shape / edge instantiation. Reverts the
|
|
73
|
+
* active mode to `select` unless `toolLocked` is on.
|
|
74
|
+
*/
|
|
75
|
+
maybeRevertModeAfterCreate(): void;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=gesture-tx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture-tx.d.ts","sourceRoot":"","sources":["../../src/editor/gesture-tx.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC,eAAe,EAAE,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;IACrD,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;IACtD,iBAAiB,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAC5B,SAAS,EACT;YAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;SAAE,CAC3E,CAAC;QACF,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;KAC3C,GAAG,IAAI,CAAC;IACT,aAAa,EAAE,SAAS,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE;QAAE,EAAE,EAAE,SAAS,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,UAAU;IAE5C;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAK1B,MAAM,IAAI,IAAI;IA4Bd,MAAM,IAAI,IAAI;IASd;;;;;;;OAOG;IACH,QAAQ,IAAI,IAAI;IAUhB;;;;OAIG;IACH,0BAA0B,IAAI,IAAI;CAKnC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gesture lifecycle controller. Wraps the open-transaction model
|
|
3
|
+
* — drag / resize / multi-step operations open a `TransactionHandle`
|
|
4
|
+
* on first move, append patches as they arrive, commit on
|
|
5
|
+
* POINTER_UP. `commit` also clears the drag-target scratch fields
|
|
6
|
+
* and unconditionally fires a final notify so downstream
|
|
7
|
+
* subscribers (Undo/Redo button, mode toggle) update even when
|
|
8
|
+
* intermediate xstate re-entrancy queued events that only drained
|
|
9
|
+
* after the outer event handler returned.
|
|
10
|
+
*/
|
|
11
|
+
export class GestureController {
|
|
12
|
+
ref;
|
|
13
|
+
constructor(ref) {
|
|
14
|
+
this.ref = ref;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Open a gesture transaction on the first drag-emitted patch,
|
|
18
|
+
* then add subsequent patches to it. POINTER_UP commits it as
|
|
19
|
+
* one history record.
|
|
20
|
+
*/
|
|
21
|
+
record(patch) {
|
|
22
|
+
this.ref.gestureTx ??= this.ref.history.transaction();
|
|
23
|
+
this.ref.gestureTx.add(patch);
|
|
24
|
+
}
|
|
25
|
+
commit() {
|
|
26
|
+
this.ref.groupMoveOrigin = null;
|
|
27
|
+
this.ref.groupLinkMoveOrigin = null;
|
|
28
|
+
this.ref.groupResizeOrigin = null;
|
|
29
|
+
this.ref.dragElementId = null;
|
|
30
|
+
if (this.ref.containerHover !== null) {
|
|
31
|
+
this.ref.containerHover = null;
|
|
32
|
+
}
|
|
33
|
+
if (this.ref.gestureTx) {
|
|
34
|
+
this.ref.gestureTx.commit();
|
|
35
|
+
this.ref.gestureTx = null;
|
|
36
|
+
}
|
|
37
|
+
// Notify unconditionally on gesture end. Two reasons:
|
|
38
|
+
// 1. Committing the transaction (drag / resize) flips
|
|
39
|
+
// canUndo / canRedo, so Undo/Redo toolbar buttons need a
|
|
40
|
+
// final notify to reflect the new state.
|
|
41
|
+
// 2. CREATE_SHAPE / CREATE_EDGE path: `maybeRevertModeAfterCreate`
|
|
42
|
+
// enqueues a `SET_MODE` event on the xstate actor while
|
|
43
|
+
// still inside an `actor.on("*")` handler. xstate v5
|
|
44
|
+
// drains the queue before the outer `actor.send` returns;
|
|
45
|
+
// `commit` runs AFTER that outer send, so the `mode`
|
|
46
|
+
// getter here already shows the freshly-applied "select".
|
|
47
|
+
// The intermediate notify from inside `applyCreate` reads
|
|
48
|
+
// the pre-drain mode; this final notify gives subscribers
|
|
49
|
+
// the correct value.
|
|
50
|
+
this.ref.notify();
|
|
51
|
+
}
|
|
52
|
+
cancel() {
|
|
53
|
+
this.ref.groupMoveOrigin = null;
|
|
54
|
+
this.ref.groupLinkMoveOrigin = null;
|
|
55
|
+
this.ref.groupResizeOrigin = null;
|
|
56
|
+
if (!this.ref.gestureTx)
|
|
57
|
+
return;
|
|
58
|
+
this.ref.gestureTx.cancel();
|
|
59
|
+
this.ref.gestureTx = null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Defensive cleanup invoked by public commands (paste, etc.)
|
|
63
|
+
* that open their own history transaction. A real gesture-in-
|
|
64
|
+
* flight gets committed (preserving user work); a stale tx that
|
|
65
|
+
* survived an earlier exception gets cancelled. Either way the
|
|
66
|
+
* next `transaction()` call lands on a clean slot, so pressing
|
|
67
|
+
* Cmd+V mid-drag doesn't throw "A transaction is already open".
|
|
68
|
+
*/
|
|
69
|
+
finalize() {
|
|
70
|
+
if (!this.ref.gestureTx)
|
|
71
|
+
return;
|
|
72
|
+
try {
|
|
73
|
+
this.ref.gestureTx.commit();
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
this.ref.gestureTx.cancel();
|
|
77
|
+
}
|
|
78
|
+
this.ref.gestureTx = null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Internal hook — called from `applyCreate` / `applyCreateLink`
|
|
82
|
+
* after a successful shape / edge instantiation. Reverts the
|
|
83
|
+
* active mode to `select` unless `toolLocked` is on.
|
|
84
|
+
*/
|
|
85
|
+
maybeRevertModeAfterCreate() {
|
|
86
|
+
if (this.ref.toolLocked)
|
|
87
|
+
return;
|
|
88
|
+
if (this.ref.mode === "select" || this.ref.mode === "hand")
|
|
89
|
+
return;
|
|
90
|
+
this.ref.setMode("select");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=gesture-tx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture-tx.js","sourceRoot":"","sources":["../../src/editor/gesture-tx.ts"],"names":[],"mappings":"AAqCA;;;;;;;;;GASG;AACH,MAAM,OAAO,iBAAiB;IACC;IAA7B,YAA6B,GAAe;QAAf,QAAG,GAAH,GAAG,CAAY;IAAG,CAAC;IAEhD;;;;OAIG;IACH,MAAM,CAAC,KAAY;QACjB,IAAI,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACtD,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,mBAAmB,GAAG,IAAI,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;QAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC;QACjC,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;QAC5B,CAAC;QACD,sDAAsD;QACtD,wDAAwD;QACxD,8DAA8D;QAC9D,8CAA8C;QAC9C,qEAAqE;QACrE,6DAA6D;QAC7D,0DAA0D;QAC1D,+DAA+D;QAC/D,0DAA0D;QAC1D,+DAA+D;QAC/D,+DAA+D;QAC/D,+DAA+D;QAC/D,0BAA0B;QAC1B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;IACpB,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,mBAAmB,GAAG,IAAI,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,OAAO;QAChC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED;;;;;;;OAOG;IACH,QAAQ;QACN,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS;YAAE,OAAO;QAChC,IAAI,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,0BAA0B;QACxB,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU;YAAE,OAAO;QAChC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO;QACnE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;CACF"}
|