@vibecook/ice 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/chunk-5S7GSXJG.js +6003 -0
- package/dist/chunk-5S7GSXJG.js.map +1 -0
- package/dist/chunk-BCJ47SX7.js +550 -0
- package/dist/chunk-BCJ47SX7.js.map +1 -0
- package/dist/chunk-FIAXPNNY.js +1446 -0
- package/dist/chunk-FIAXPNNY.js.map +1 -0
- package/dist/devtools.js +417 -0
- package/dist/devtools.js.map +1 -0
- package/dist/dom.js +41 -0
- package/dist/dom.js.map +1 -0
- package/dist/index.js +450 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel.js +63 -0
- package/dist/kernel.js.map +1 -0
- package/dist/r3f.js +1101 -0
- package/dist/r3f.js.map +1 -0
- package/dist/react.js +440 -0
- package/dist/react.js.map +1 -0
- package/dist/types/packages/core/src/boot/hmr.d.ts +12 -0
- package/dist/types/packages/core/src/catalog/camera-derived.d.ts +144 -0
- package/dist/types/packages/core/src/catalog/gesture.d.ts +254 -0
- package/dist/types/packages/core/src/catalog/graph.d.ts +55 -0
- package/dist/types/packages/core/src/catalog/index.d.ts +32 -0
- package/dist/types/packages/core/src/catalog/pointer.d.ts +111 -0
- package/dist/types/packages/core/src/catalog/scene.d.ts +34 -0
- package/dist/types/packages/core/src/catalog/selection-presence.d.ts +53 -0
- package/dist/types/packages/core/src/catalog/settings-resources.d.ts +46 -0
- package/dist/types/packages/core/src/doc/autosave.d.ts +69 -0
- package/dist/types/packages/core/src/doc/bootstrap.d.ts +74 -0
- package/dist/types/packages/core/src/doc/broadcast-relay.d.ts +52 -0
- package/dist/types/packages/core/src/doc/channels.d.ts +49 -0
- package/dist/types/packages/core/src/doc/doc-commit-sink.d.ts +22 -0
- package/dist/types/packages/core/src/doc/doc-kit.d.ts +50 -0
- package/dist/types/packages/core/src/doc/envelope.d.ts +36 -0
- package/dist/types/packages/core/src/doc/migrate.d.ts +69 -0
- package/dist/types/packages/core/src/doc/version-gate.d.ts +49 -0
- package/dist/types/packages/core/src/engine/commit-sink.d.ts +61 -0
- package/dist/types/packages/core/src/engine/engine.d.ts +62 -0
- package/dist/types/packages/core/src/engine/frame-info.d.ts +16 -0
- package/dist/types/packages/core/src/engine/instantiate.d.ts +45 -0
- package/dist/types/packages/core/src/engine/pipeline.d.ts +17 -0
- package/dist/types/packages/core/src/engine/reflectors.d.ts +56 -0
- package/dist/types/packages/core/src/facade/create-canvas-engine.d.ts +120 -0
- package/dist/types/packages/core/src/guards/dev.d.ts +2 -0
- package/dist/types/packages/core/src/guards/guarded-tx.d.ts +51 -0
- package/dist/types/packages/core/src/guards/live-writer.d.ts +33 -0
- package/dist/types/packages/core/src/guards/resource-writer.d.ts +17 -0
- package/dist/types/packages/core/src/helpers/phase-set.d.ts +70 -0
- package/dist/types/packages/core/src/helpers/version-stamps.d.ts +55 -0
- package/dist/types/packages/core/src/index.d.ts +63 -0
- package/dist/types/packages/core/src/input/measure-queue.d.ts +30 -0
- package/dist/types/packages/core/src/input/queue.d.ts +60 -0
- package/dist/types/packages/core/src/interaction/install.d.ts +58 -0
- package/dist/types/packages/core/src/nav/nested-canvas.d.ts +62 -0
- package/dist/types/packages/core/src/ops/cascade.d.ts +18 -0
- package/dist/types/packages/core/src/ops/claims.d.ts +15 -0
- package/dist/types/packages/core/src/ops/gestures.d.ts +10 -0
- package/dist/types/packages/core/src/ops/point-pick.d.ts +42 -0
- package/dist/types/packages/core/src/ops/port-geometry.d.ts +17 -0
- package/dist/types/packages/core/src/ops/selection.d.ts +14 -0
- package/dist/types/packages/core/src/presence/index.d.ts +7 -0
- package/dist/types/packages/core/src/presence/presence-kit.d.ts +39 -0
- package/dist/types/packages/core/src/presence/publish.d.ts +14 -0
- package/dist/types/packages/core/src/presence/remote-cursors.d.ts +18 -0
- package/dist/types/packages/core/src/schema/meta.d.ts +43 -0
- package/dist/types/packages/core/src/schema/prefab.d.ts +69 -0
- package/dist/types/packages/core/src/settings/defaults.d.ts +56 -0
- package/dist/types/packages/core/src/systems/camera-sim.d.ts +19 -0
- package/dist/types/packages/core/src/systems/chrome.d.ts +48 -0
- package/dist/types/packages/core/src/systems/cleanup.d.ts +19 -0
- package/dist/types/packages/core/src/systems/l0-input.d.ts +31 -0
- package/dist/types/packages/core/src/systems/l1-pick.d.ts +44 -0
- package/dist/types/packages/core/src/systems/l1-wires.d.ts +30 -0
- package/dist/types/packages/core/src/systems/l2-arbitrate.d.ts +40 -0
- package/dist/types/packages/core/src/systems/l2-recognize.d.ts +45 -0
- package/dist/types/packages/core/src/systems/l3-behave.d.ts +24 -0
- package/dist/types/packages/core/src/systems/l3-claim.d.ts +26 -0
- package/dist/types/packages/core/src/systems/l3-connect.d.ts +57 -0
- package/dist/types/packages/core/src/systems/l3-draw.d.ts +21 -0
- package/dist/types/packages/core/src/systems/l3-drop.d.ts +21 -0
- package/dist/types/packages/core/src/systems/l3-marquee.d.ts +35 -0
- package/dist/types/packages/core/src/systems/l3-ports.d.ts +30 -0
- package/dist/types/packages/core/src/systems/l3-resize.d.ts +17 -0
- package/dist/types/packages/core/src/systems/l3-snap.d.ts +19 -0
- package/dist/types/packages/core/src/systems/l4-cursor.d.ts +24 -0
- package/dist/types/packages/core/src/systems/measure-ingest.d.ts +26 -0
- package/dist/types/packages/core/src/tools/define-tool.d.ts +79 -0
- package/dist/types/packages/core/src/widget/define-widget.d.ts +124 -0
- package/dist/types/packages/core/src/widget/equip.d.ts +14 -0
- package/dist/types/packages/core/src/widget/mount-store.d.ts +47 -0
- package/dist/types/packages/core/src/widget/props.d.ts +98 -0
- package/dist/types/packages/core/src/widget/spawn.d.ts +30 -0
- package/dist/types/packages/devtools/src/index.d.ts +8 -0
- package/dist/types/packages/devtools/src/panel.d.ts +48 -0
- package/dist/types/packages/dom/src/host.d.ts +24 -0
- package/dist/types/packages/dom/src/index.d.ts +19 -0
- package/dist/types/packages/dom/src/loop.d.ts +11 -0
- package/dist/types/packages/dom/src/measure-adapter.d.ts +31 -0
- package/dist/types/packages/dom/src/measure-wiring.d.ts +49 -0
- package/dist/types/packages/dom/src/planes.d.ts +33 -0
- package/dist/types/packages/dom/src/pointer-adapter.d.ts +48 -0
- package/dist/types/packages/dom/src/reflectors/chrome.d.ts +33 -0
- package/dist/types/packages/dom/src/reflectors/cursor.d.ts +21 -0
- package/dist/types/packages/dom/src/reflectors/dom-widgets.d.ts +54 -0
- package/dist/types/packages/dom/src/reflectors/graybox.d.ts +31 -0
- package/dist/types/packages/dom/src/reflectors/grid.d.ts +63 -0
- package/dist/types/packages/dom/src/reflectors/plane-transform.d.ts +38 -0
- package/dist/types/packages/dom/src/reflectors/remote-cursors.d.ts +20 -0
- package/dist/types/packages/dom/src/reflectors/wires.d.ts +88 -0
- package/dist/types/packages/ice/src/devtools.d.ts +1 -0
- package/dist/types/packages/ice/src/dom.d.ts +1 -0
- package/dist/types/packages/ice/src/index.d.ts +1 -0
- package/dist/types/packages/ice/src/kernel.d.ts +1 -0
- package/dist/types/packages/ice/src/r3f.d.ts +1 -0
- package/dist/types/packages/ice/src/react.d.ts +1 -0
- package/dist/types/packages/kernel/src/anchors.d.ts +18 -0
- package/dist/types/packages/kernel/src/bezier.d.ts +38 -0
- package/dist/types/packages/kernel/src/coords.d.ts +67 -0
- package/dist/types/packages/kernel/src/eviction.d.ts +23 -0
- package/dist/types/packages/kernel/src/index.d.ts +13 -0
- package/dist/types/packages/kernel/src/shapes.d.ts +22 -0
- package/dist/types/packages/kernel/src/snap.d.ts +44 -0
- package/dist/types/packages/kernel/src/spatial-index.d.ts +16 -0
- package/dist/types/packages/kernel/src/zoom-bands.d.ts +19 -0
- package/dist/types/packages/r3f/src/bridge.d.ts +68 -0
- package/dist/types/packages/r3f/src/composite-material.d.ts +17 -0
- package/dist/types/packages/r3f/src/compositor-pass.d.ts +83 -0
- package/dist/types/packages/r3f/src/dev-write-trap.d.ts +30 -0
- package/dist/types/packages/r3f/src/gl-root.d.ts +21 -0
- package/dist/types/packages/r3f/src/gl-router.d.ts +60 -0
- package/dist/types/packages/r3f/src/index.d.ts +16 -0
- package/dist/types/packages/r3f/src/island-state.d.ts +68 -0
- package/dist/types/packages/r3f/src/island.d.ts +13 -0
- package/dist/types/packages/r3f/src/pool.d.ts +56 -0
- package/dist/types/packages/r3f/src/resource-registry.d.ts +30 -0
- package/dist/types/packages/r3f/src/use-island-frame.d.ts +24 -0
- package/dist/types/packages/react/src/engine-context.d.ts +31 -0
- package/dist/types/packages/react/src/hooks.d.ts +40 -0
- package/dist/types/packages/react/src/index.d.ts +14 -0
- package/dist/types/packages/react/src/infinite-canvas.d.ts +71 -0
- package/dist/types/packages/react/src/keymap.d.ts +42 -0
- package/dist/types/packages/react/src/use-commit.d.ts +35 -0
- package/dist/types/packages/react/src/use-presence.d.ts +23 -0
- package/dist/types/packages/react/src/use-tool.d.ts +4 -0
- package/dist/types/packages/react/src/widget-root.d.ts +33 -0
- package/package.json +112 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chrome derive systems (design-004 §5 chrome plane, §8 LOD; `derive` phase).
|
|
3
|
+
*
|
|
4
|
+
* Two systems, both derive-scheduled, both write change-only:
|
|
5
|
+
*
|
|
6
|
+
* `selectionChrome` — maintains POOLED chrome entities mirroring the current
|
|
7
|
+
* `Selected` set: ONE selection-box entity + 8 resize-handle entities. The box
|
|
8
|
+
* entity carries ONLY the `SelectionBox` value (x,y,w,h = the union bbox); the
|
|
9
|
+
* handles carry Position + Size + `HandleSpec{anchor}` + `VisualOf → box`.
|
|
10
|
+
*
|
|
11
|
+
* HANDLE PICKING (the point of the design): handles carry a world AABB, so the
|
|
12
|
+
* `react`-phase `spatialSync` indexes them automatically and `picking` resolves
|
|
13
|
+
* a corner grab to the handle (HandleSpec has pick priority) → `dragRoute`
|
|
14
|
+
* routes `RoutedResize` → `resizeBehavior` runs. Nothing here touches the index.
|
|
15
|
+
*
|
|
16
|
+
* HANDLES ARE SCREEN-CONSTANT: a handle's world size is `HANDLE_PICK_PX / zoom`
|
|
17
|
+
* so its on-screen hit target stays ~constant across zoom. The tradeoff: the
|
|
18
|
+
* handles must be recomputed whenever the camera zoom changes, so this system
|
|
19
|
+
* runs every frame a selection exists and rewrites the 8 handles' Position/Size
|
|
20
|
+
* change-only (a zoom change restamps 8 entities — small, bounded N; §5's
|
|
21
|
+
* "screen-space, recomputed on camera dirt, small N").
|
|
22
|
+
*
|
|
23
|
+
* THE BOX IS DELIBERATELY NOT PICKABLE. It stores its rect in the `SelectionBox`
|
|
24
|
+
* value, NOT in Position/Size, so `spatialSync` (which indexes [Position,Size])
|
|
25
|
+
* never sees it. design-003 §3's pick priority lists ONLY HandleSpec chrome as
|
|
26
|
+
* pickable; indexing the box would make it a widget-class pick (it has Position)
|
|
27
|
+
* and let a center-of-selection click be grabbed by `moveClaim`. (This diverges
|
|
28
|
+
* from a literal reading of the M6 brief's "Position+Size+SelectionBox" — the
|
|
29
|
+
* box's geometry lives on the `SelectionBox` value instead; the chrome reflector
|
|
30
|
+
* reads it from there.)
|
|
31
|
+
*
|
|
32
|
+
* POOL LIFECYCLE: entities spawn once via `ctx` (runtime prefab class) when a
|
|
33
|
+
* selection appears and are reaped via `ctx.destroy` when it empties. On the
|
|
34
|
+
* spawn frame the handles are still identity-only (placement defers to the
|
|
35
|
+
* phase boundary), so their initial geometry rides the `ctx.spawn` payload and
|
|
36
|
+
* the change-only `edit().set` updates begin the next frame.
|
|
37
|
+
*
|
|
38
|
+
* `breakpoint` — `WidgetBreakpoint{tier,w,h}` from a widget's EFFECTIVE size
|
|
39
|
+
* (`MeasuredSize` where auto-sized and >0, else `Size`), width-thresholded into
|
|
40
|
+
* 5 tiers with ±10% boundary hysteresis. Added lazily (on `WidgetEquipped`
|
|
41
|
+
* widgets, once measured) and thereafter written ONLY when the tier changes —
|
|
42
|
+
* the LOD signal must be stable within a tier so the measure→tier→content→
|
|
43
|
+
* measure loop converges (§2). The stored w,h are the effective size at the
|
|
44
|
+
* tier transition (what the tier "was computed from").
|
|
45
|
+
*/
|
|
46
|
+
import type { System, TickSystem, World } from "@vibecook/strata-ecs";
|
|
47
|
+
export declare function createSelectionChromeSystem(world: World): TickSystem;
|
|
48
|
+
export declare function createBreakpointSystem(_world: World): System;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cleanup phase — nothing transient crosses frames (design-002 §2; design-003
|
|
3
|
+
* §4.1 reap, §8 CancelRequest one-tick rule).
|
|
4
|
+
*
|
|
5
|
+
* `recognizerReap` destroys terminal recognizers at terminal +1 frame: a Just*
|
|
6
|
+
* marker means the transition happened THIS tick (markers clear later this
|
|
7
|
+
* phase, but ctx reads are pre-flush) — no marker means the tag has lingered a
|
|
8
|
+
* full frame and every edge-triggered consumer has run. `ClaimedBy`/`Watches`/
|
|
9
|
+
* `Captures`/`Drags` edges auto-clear with the despawn.
|
|
10
|
+
*
|
|
11
|
+
* `oneTickClear` then clears pointer transition tags, zeroes wheel deltas,
|
|
12
|
+
* clears all Just* markers, and consumes CancelRequest (a latched cancel would
|
|
13
|
+
* kill every future gesture forever).
|
|
14
|
+
*/
|
|
15
|
+
import { type System, type World } from "@vibecook/strata-ecs";
|
|
16
|
+
export declare function createCleanupSystems(world: World): {
|
|
17
|
+
recognizerReap: System;
|
|
18
|
+
oneTickClear: System;
|
|
19
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L0 — pointers & ingest (design-003 §2; `input` phase).
|
|
3
|
+
*
|
|
4
|
+
* Order inside the phase is load-bearing:
|
|
5
|
+
*
|
|
6
|
+
* `pointerLifecycle` runs BEFORE `pointerIngest` and reads only immediate
|
|
7
|
+
* values: a touch pointer whose buttons are still 0 at the top of a frame has
|
|
8
|
+
* been idle-up for a full frame (ingest zeroed buttons on the up frame), so its
|
|
9
|
+
* `ctx.destroy` lands at the input flush of frame up+1 — recognizers saw the up
|
|
10
|
+
* frame's `WentUp` in full. Tag-based detection cannot work in-phase (ingest's
|
|
11
|
+
* one-tick tags are deferred to the flush), hence values.
|
|
12
|
+
*
|
|
13
|
+
* `pointerIngest` is scheduled on the CANVAS-SURFACE anchor query (exactly one
|
|
14
|
+
* such entity, guaranteed by install) because a system body only runs when its
|
|
15
|
+
* query matches — and ingest must run on frames where no pointer entity exists
|
|
16
|
+
* yet (the first down CREATES the pointer). It drains the queue once per tick
|
|
17
|
+
* in two passes: fold events into per-pointer samples, then apply — existing
|
|
18
|
+
* pointers get immediate value writes + deferred one-tick tags; NEW pointers
|
|
19
|
+
* spawn once with their folded final state (an identity-only `ctx.spawn` handle
|
|
20
|
+
* cannot take `edit().set`). Facts are always true: `surfaceHandled` events
|
|
21
|
+
* still land, but carry the one-tick `HandledByWidget` tag L1/L2 read (the
|
|
22
|
+
* pinned widget-event contract, design-002 §8).
|
|
23
|
+
*/
|
|
24
|
+
import type { System, TickSystem, World } from "@vibecook/strata-ecs";
|
|
25
|
+
import type { InputQueue } from "../input/queue";
|
|
26
|
+
export interface L0Systems {
|
|
27
|
+
pointerLifecycle: System;
|
|
28
|
+
pointerIngest: TickSystem;
|
|
29
|
+
pointerWorldSync: System;
|
|
30
|
+
}
|
|
31
|
+
export declare function createL0Systems(world: World, queue: InputQueue): L0Systems;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L1 — spatial sync + targeting (design-003 §3; `react` phase).
|
|
3
|
+
*
|
|
4
|
+
* Two systems, run in this order:
|
|
5
|
+
*
|
|
6
|
+
* `spatialSync` maintains the kernel `SpatialIndex` over every Position+Size
|
|
7
|
+
* entity (widgets AND HandleSpec chrome — both carry a world AABB). It is a
|
|
8
|
+
* TICK system (strata 0.5.0) so the body runs EVERY frame — it is the writer
|
|
9
|
+
* that bumps
|
|
10
|
+
* `SpatialVersion`, and its own writes have no version stamp to gate on
|
|
11
|
+
* (design-002 §4), so it must run eagerly and stays cheap via a private
|
|
12
|
+
* last-known cache: an entity is re-`upsert`ed only when its AABB actually
|
|
13
|
+
* changed, and a cache-sweep removes entries no longer matched (despawns, or a
|
|
14
|
+
* lost Position/Size). Materialized ports are M8 — skipped.
|
|
15
|
+
*
|
|
16
|
+
* `picking` runs the dual pick (design-003 §3), gated by a version guard over
|
|
17
|
+
* `PointerVersion ∨ SpatialVersion`. `CameraVersion` does not exist — camera
|
|
18
|
+
* motion alone does not re-pick, an accepted staleness (design-002 §2). Pointer
|
|
19
|
+
* world position is derived from PointerScreen × Camera rather than the
|
|
20
|
+
* PointerWorld cell: PointerWorld lags a frame on the pointer's spawn (the
|
|
21
|
+
* pointerWorldSync writer cannot see a pointer spawned in the same input phase),
|
|
22
|
+
* which would mis-capture on the down frame — screen×camera is exact here.
|
|
23
|
+
* - `Targets` = radiused disc-vs-box pick with a screen-px release
|
|
24
|
+
* dead-band (hover is forgiving; hold the current target
|
|
25
|
+
* while the pointer stays within its expanded bounds).
|
|
26
|
+
* - `TouchesExact` = r=0 point pick (grab is precise; no dead-band).
|
|
27
|
+
* Pick priority is plane priority: HandleSpec chrome first, then widgets by
|
|
28
|
+
* StackZ descending, then the CanvasSurface entity as the guaranteed fallback
|
|
29
|
+
* (design-001 §4). Relations are written change-only (design-002 §4 hygiene).
|
|
30
|
+
* Wires/ports are M8 — skipped.
|
|
31
|
+
*/
|
|
32
|
+
import type { Entity, System, TickSystem, World } from "@vibecook/strata-ecs";
|
|
33
|
+
import { SpatialIndex } from "@ice/kernel";
|
|
34
|
+
import { type WirePickSource } from "../ops/point-pick";
|
|
35
|
+
export interface PickingSystems {
|
|
36
|
+
spatialSync: TickSystem;
|
|
37
|
+
picking: System;
|
|
38
|
+
/** The shared spatial index — snap/drop/marquee consume the SAME instance. */
|
|
39
|
+
index: SpatialIndex<Entity>;
|
|
40
|
+
/** Nav-op seam (design-004 §7): forget every last-known AABB so the next
|
|
41
|
+
* spatialSync pass repopulates the cleared index from the new Active set. */
|
|
42
|
+
clearCaches(): void;
|
|
43
|
+
}
|
|
44
|
+
export declare function createPickingSystems(world: World, index?: SpatialIndex<Entity>, wires?: WirePickSource): PickingSystems;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L1 — wire geometry sync (design-004 §6 ports & wires runtime; `react` phase,
|
|
3
|
+
* AFTER `spatialSync`).
|
|
4
|
+
*
|
|
5
|
+
* A wire is a durable reified edge (Wire tag + WireFrom/WireTo → widgets +
|
|
6
|
+
* WirePorts ids). Its RENDER + PICK geometry is a pure function of the two
|
|
7
|
+
* endpoint widget rects and their port declarations (design-001 §5.3: geometry
|
|
8
|
+
* never reads a port entity — culled endpoints resolve by construction). This
|
|
9
|
+
* TICK system (strata 0.5.0) recomputes each wire's cubic once per frame and
|
|
10
|
+
* keeps a private cache so the shared spatial index only churns on real
|
|
11
|
+
* movement — exactly the `spatialSync` idiom, and the reason it must run every
|
|
12
|
+
* frame: it is a `SpatialVersion` writer and cannot gate on the version it bumps.
|
|
13
|
+
*
|
|
14
|
+
* Per wire: resolve WireFrom/WireTo → endpoint Position+Size + the port slot
|
|
15
|
+
* (PrefabId → widget registry → decl → kernel `portAnchor`) → `wireCubic` →
|
|
16
|
+
* `cubicAABB`. Endpoint or declaration unresolvable (mid-projection, a despawned
|
|
17
|
+
* widget, a removed port id) ⇒ the wire leaves the index (invisible to picking;
|
|
18
|
+
* the renderer draws nothing for it). The cache also feeds the `WirePickSource`
|
|
19
|
+
* the point-pick narrow-phases against (`ops/point-pick`), and exposes the
|
|
20
|
+
* screen-constant pick slop as `slopWorld = wirePickSlopPx / zoom`.
|
|
21
|
+
*/
|
|
22
|
+
import type { Entity, TickSystem, World } from "@vibecook/strata-ecs";
|
|
23
|
+
import { type SpatialIndex } from "@ice/kernel";
|
|
24
|
+
import type { WirePickSource } from "../ops/point-pick";
|
|
25
|
+
export interface WireSyncSystem {
|
|
26
|
+
wireSync: TickSystem;
|
|
27
|
+
/** The narrow-phase source `pickTopAt` consults for wire entries. */
|
|
28
|
+
wires: WirePickSource;
|
|
29
|
+
}
|
|
30
|
+
export declare function createWireSync(world: World, index: SpatialIndex<Entity>): WireSyncSystem;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L2 — arbitration + routing (design-003 §4.3–§4.4; `ctl:arbitrate`).
|
|
3
|
+
*
|
|
4
|
+
* Arbitration rule (v2-proven, generalized): the first recognizer to enter a
|
|
5
|
+
* claiming phase (`Active` for continuous, `Recognized` for discrete) claims
|
|
6
|
+
* every pointer it watches; same-frame ties resolve by priority
|
|
7
|
+
* Pinch > Drag > LongPress > Tap; every other non-terminal, non-`Simultaneous`,
|
|
8
|
+
* non-suspended recognizer watching a claimed pointer → `Failed`. The claim is
|
|
9
|
+
* world state: `ClaimedBy(pointer → recognizer)` (Law 4). DEV asserts at most
|
|
10
|
+
* one ClaimedBy write per pointer per pass (`setRelation` is silent last-wins —
|
|
11
|
+
* a mis-ordered arbitration would otherwise be undetectable).
|
|
12
|
+
*
|
|
13
|
+
* `dragRoute` — the ONE pan/marquee/move decision, latched at Drag activation
|
|
14
|
+
* via route tags; the route never changes mid-gesture (design-003 §4.4).
|
|
15
|
+
*/
|
|
16
|
+
import type { System } from "@vibecook/strata-ecs";
|
|
17
|
+
export declare function createArbitrationSystems(): {
|
|
18
|
+
arbitration: System;
|
|
19
|
+
dragRoute: System;
|
|
20
|
+
};
|
|
21
|
+
/** Wheel recognizers never claim; exported so tests can assert the invariant set. */
|
|
22
|
+
export declare const NEVER_CLAIMS: readonly [import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
23
|
+
readonly dx: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
24
|
+
readonly dy: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
25
|
+
readonly anchorX: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
26
|
+
readonly anchorY: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
27
|
+
}>, {
|
|
28
|
+
readonly dx: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
29
|
+
readonly dy: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
30
|
+
readonly anchorX: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
31
|
+
readonly anchorY: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
32
|
+
}>, import("@vibecook/strata-ecs").Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
33
|
+
readonly pinch: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
34
|
+
readonly anchorX: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
35
|
+
readonly anchorY: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
36
|
+
}>, {
|
|
37
|
+
readonly pinch: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
38
|
+
readonly anchorX: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
39
|
+
readonly anchorY: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
40
|
+
}>];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L2 — recognizer lifecycle + per-kind FSMs (design-003 §4.1–§4.2).
|
|
3
|
+
*
|
|
4
|
+
* `ctl:spawn` — cancelSweep (consumes the one-tick CancelRequest) →
|
|
5
|
+
* recognizerSpawn (tool profiles; pinch on 2nd touch suspends
|
|
6
|
+
* singles; wheel recognizers are `Simultaneous`) →
|
|
7
|
+
* recognizerIntegrity (requiredWatches counts, capture death,
|
|
8
|
+
* suspension lift). Newborns are identity-only until the
|
|
9
|
+
* ctl:spawn flush, so integrity naturally skips them until the
|
|
10
|
+
* next frame — by which time their edges are placed.
|
|
11
|
+
* `ctl:recognize` — per-kind systems. Transitions go through the PhaseSet via
|
|
12
|
+
* `ctx` (visible at this phase's flush — arbitration reads them
|
|
13
|
+
* the same frame); field updates are immediate `edit().set`
|
|
14
|
+
* under declared `access.write`.
|
|
15
|
+
*
|
|
16
|
+
* All timing reads FrameInfo.now (the engine clock); all thresholds read
|
|
17
|
+
* the GestureSettings RESOURCE (live-tunable, design-005 §4) with the
|
|
18
|
+
* GESTURE_DEFAULTS constants as the unset fallback. Gesture math is screen-space totals + zoom-at-claim — never
|
|
19
|
+
* live PointerWorld (design-002 §2 staleness rule).
|
|
20
|
+
*/
|
|
21
|
+
import type { World } from "@vibecook/strata-ecs";
|
|
22
|
+
import { type System } from "@vibecook/strata-ecs";
|
|
23
|
+
export type SingleKindName = "tap" | "longPress" | "drag";
|
|
24
|
+
/** Tool id → single-pointer recognizer set spawned per down (design-003 §4.1). */
|
|
25
|
+
export type SpawnProfiles = Readonly<Record<string, readonly SingleKindName[]>>;
|
|
26
|
+
export declare const DEFAULT_SPAWN_PROFILES: SpawnProfiles;
|
|
27
|
+
export interface L2Deps {
|
|
28
|
+
readonly world: World;
|
|
29
|
+
readonly profiles?: SpawnProfiles;
|
|
30
|
+
}
|
|
31
|
+
export interface L2Systems {
|
|
32
|
+
cancelSweep: System;
|
|
33
|
+
recognizerSpawn: System;
|
|
34
|
+
/** Same design slot as recognizerSpawn (design-002 §2) over the wheel-source query. */
|
|
35
|
+
wheelSpawn: System;
|
|
36
|
+
recognizerIntegrity: System;
|
|
37
|
+
tapSystem: System;
|
|
38
|
+
longPressSystem: System;
|
|
39
|
+
dragSystem: System;
|
|
40
|
+
pinchSystem: System;
|
|
41
|
+
wheelSystem: System;
|
|
42
|
+
/** Resolves Pending `Sequence`/`RequiresFail` edges; last in `ctl:recognize`. */
|
|
43
|
+
dependencySystem: System;
|
|
44
|
+
}
|
|
45
|
+
export declare function createL2Systems({ world, profiles }: L2Deps): L2Systems;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — select + move behaviors (design-003 §5 items 1, 3, 5; `ctl:behave`).
|
|
3
|
+
*
|
|
4
|
+
* The behavior contract (design-003 §5): read riders/edges attached at
|
|
5
|
+
* ctl:claim; per frame (persistent `Active`) apply ABSOLUTE live writes from
|
|
6
|
+
* rider origins + gesture totals; on `JustEnded` emit ONE commit (through the
|
|
7
|
+
* CommitSink seam — M5 swaps in the doc transaction); on `JustCancelled`
|
|
8
|
+
* restore from riders — Position AND StackZ (a forgotten StackZ restore leaves
|
|
9
|
+
* the cell diverged forever); remove riders and gesture-scoped edges on every
|
|
10
|
+
* terminal path. Discrete actions edge-trigger on `Just*` markers only.
|
|
11
|
+
*
|
|
12
|
+
* Move outcome tree (design-003 §5.5, three-way via dropSystem's signals):
|
|
13
|
+
* DropTarget + OverlapCandidate on the container → CONSUME (reparent intent);
|
|
14
|
+
* DropTarget without OverlapCandidate → FLY-BACK (no commit; TransformTween
|
|
15
|
+
* rider per widget — the tween HOLDS the claim, design-001 §3 amended);
|
|
16
|
+
* no DropTarget → COMMIT (final Position + StackZ per live Drags edge).
|
|
17
|
+
* Without dropSystem installed no DropTarget ever exists ⇒ plain commits.
|
|
18
|
+
*/
|
|
19
|
+
import type { System, World } from "@vibecook/strata-ecs";
|
|
20
|
+
import type { CommitSink } from "../engine/commit-sink";
|
|
21
|
+
export declare function createSelectMoveBehaviors(world: World, sink: CommitSink): {
|
|
22
|
+
selectBehavior: System;
|
|
23
|
+
moveBehavior: System;
|
|
24
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ctl:claim — the rider settle point (design-003 §4.5).
|
|
3
|
+
*
|
|
4
|
+
* This sub-phase exists for exactly one reason: riders (`Grab`) and edges
|
|
5
|
+
* (`Drags`) attached via `ctx` must be readable by the behaviors that consume
|
|
6
|
+
* them ON THE CLAIM FRAME — without it, the first mutation lags a frame and a
|
|
7
|
+
* claim-frame `read(w, Grab)` throws (design-003 review C1).
|
|
8
|
+
*
|
|
9
|
+
* `moveClaim` (JustActive × RoutedMove): select-on-grab, `Drags` edges over the
|
|
10
|
+
* dragged set, `Grab` per widget with the CURRENT Position/Size/StackZ embedded
|
|
11
|
+
* in the command payload, and the StackZ elevate (an immediate value write —
|
|
12
|
+
* part of the gesture divergence, restored from `Grab.z` on cancel).
|
|
13
|
+
*
|
|
14
|
+
* `resizeClaim` (JustActive × RoutedResize): `Drags` + `Grab` over the Selected
|
|
15
|
+
* ∧ Resizable set; the anchor lives on the captured handle's `HandleSpec` — no
|
|
16
|
+
* extra state.
|
|
17
|
+
*
|
|
18
|
+
* Same-widget double-grab guard: a widget already in another recognizer's
|
|
19
|
+
* `Drags` set is skipped (first gesture owns it) — two `ctx.addComponent(Grab)`
|
|
20
|
+
* for one widget in one frame would hit strata's flush-time duplicate policy.
|
|
21
|
+
*/
|
|
22
|
+
import type { System, World } from "@vibecook/strata-ecs";
|
|
23
|
+
export declare function createClaimSystems(world: World): {
|
|
24
|
+
moveClaim: System;
|
|
25
|
+
resizeClaim: System;
|
|
26
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — connect behavior (design-003 §5 item 8, §4.5 connectClaim; design-004 §6;
|
|
3
|
+
* `ctl:claim` + `ctl:behave`). The node-editor core gesture: drag from a source
|
|
4
|
+
* port to a compatible target port, commit ONE wire.
|
|
5
|
+
*
|
|
6
|
+
* `connectClaim` (JustActive × RoutedConnect): latch the source port — the
|
|
7
|
+
* recognizer's `Captures` target must be a Port entity (dragRoute guarantees it,
|
|
8
|
+
* or the connect tool started the drag). Recognizer field-sets are per-kind
|
|
9
|
+
* (Drag), so per-gesture claim state lives in a closure Map keyed by recognizer
|
|
10
|
+
* (the `tweenStart`/camera-sim precedent), holding the source WIDGET + port id +
|
|
11
|
+
* world anchor + accepts-keys. The preview buffer arms here.
|
|
12
|
+
*
|
|
13
|
+
* `connectBehavior` (a TICK system, like marquee, so it can CLEAR the preview the
|
|
14
|
+
* frame after the gesture ends): per Active frame it writes the out-of-ECS
|
|
15
|
+
* `WirePreviewBuffer` (source anchor → pointer world, snapped to a COMPATIBLE
|
|
16
|
+
* port anchor when the watched pointer `Targets` one; type check via the widgets'
|
|
17
|
+
* port decls; self-wire never compatible). On `JustEnded` over a compatible port
|
|
18
|
+
* it commits `{kind:"connect", wires:[{from,to,fromPort,toPort}]}` (the doc sink
|
|
19
|
+
* spawns the wire); elsewhere it commits nothing.
|
|
20
|
+
*
|
|
21
|
+
* PREVIEW CONTINUITY — SIMPLIFICATION ACCEPTED (design-003 §5.8 / design-002 §8):
|
|
22
|
+
* the preview clears on JustEnded+1 (one linger frame) rather than persisting
|
|
23
|
+
* until the projected wire entity places (the promote-sweep analog). Full
|
|
24
|
+
* continuity — hand the preview off to the freshly-synced wire with no blink —
|
|
25
|
+
* is polish deferred; the one-frame gap is invisible in practice.
|
|
26
|
+
*/
|
|
27
|
+
import type { Entity, System, TickSystem, World } from "@vibecook/strata-ecs";
|
|
28
|
+
import { type SpatialIndex } from "@ice/kernel";
|
|
29
|
+
import type { CommitSink } from "../engine/commit-sink";
|
|
30
|
+
import type { WirePickSource } from "../ops/point-pick";
|
|
31
|
+
/**
|
|
32
|
+
* The out-of-ECS connect preview (design-004 §6; the marquee-buffer precedent).
|
|
33
|
+
* `sx,sy` = source port world anchor; `tx,ty` = the projected endpoint (pointer
|
|
34
|
+
* world, or a snapped compatible-port anchor); `compatible` gates the landing.
|
|
35
|
+
*/
|
|
36
|
+
export interface WirePreviewBuffer {
|
|
37
|
+
active: boolean;
|
|
38
|
+
compatible: boolean;
|
|
39
|
+
sx: number;
|
|
40
|
+
sy: number;
|
|
41
|
+
tx: number;
|
|
42
|
+
ty: number;
|
|
43
|
+
}
|
|
44
|
+
export interface ConnectSystems {
|
|
45
|
+
connectClaim: System;
|
|
46
|
+
connectBehavior: TickSystem;
|
|
47
|
+
previewBuffer: WirePreviewBuffer;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Signature carries the full graph-slice wiring (design brief) though connect
|
|
51
|
+
* reads only `Targets` today:
|
|
52
|
+
* @param _world reserved (systems reach world state via `ctx`).
|
|
53
|
+
* @param _index reserved (future: a fresh event-time port pick to drop the
|
|
54
|
+
* one-frame `Targets` staleness on snapping — the router's pattern).
|
|
55
|
+
* @param _wires reserved (the wire narrow-phase source; connect reads `Targets`).
|
|
56
|
+
*/
|
|
57
|
+
export declare function createConnectSystems(_world: World, sink: CommitSink, _index: SpatialIndex<Entity>, _wires: WirePickSource): ConnectSystems;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — draw behavior (design-005 §3 `draw(widgetType)` tool; `ctl:behave`,
|
|
3
|
+
* after connect, before camera — design-003 §5 order).
|
|
4
|
+
*
|
|
5
|
+
* A `RoutedDraw` drag creates ONE widget from the release rect: at
|
|
6
|
+
* `JustEnded`, screen start+total → world rect (Camera at release), floored
|
|
7
|
+
* at the widget's `minSize`; a sub-slop release (a click) places the
|
|
8
|
+
* widget's DEFAULT size centered on the point. Commit is one `create`
|
|
9
|
+
* intent through the sink — the doc sink spawns via the same override
|
|
10
|
+
* builder as `ops.spawnWidget`, so the two paths can never diverge.
|
|
11
|
+
* Cancel/fail commit nothing. The widget type comes from the ACTIVE tool's
|
|
12
|
+
* `draw` config (latched per drag at claim would be stricter; tools switch
|
|
13
|
+
* via `ops.setTool` which cancels active gestures first, so the active
|
|
14
|
+
* tool is stable for a live drag by construction).
|
|
15
|
+
*
|
|
16
|
+
* Mid-drag rect preview is recorded polish (design-001 §3's full
|
|
17
|
+
* draft→promote protocol is the vNext shape); v1 draws nothing until release.
|
|
18
|
+
*/
|
|
19
|
+
import type { System, World } from "@vibecook/strata-ecs";
|
|
20
|
+
import type { CommitSink } from "../engine/commit-sink";
|
|
21
|
+
export declare function createDrawBehavior(world: World, sink: CommitSink): System;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — drop candidate detection (design-003 §5 item 4; `ctl:behave`, ordered
|
|
3
|
+
* AFTER moveBehavior so it tests POST-move bounds).
|
|
4
|
+
*
|
|
5
|
+
* For Active `RoutedMove` drags: spatial-query the dragged union bounds for
|
|
6
|
+
* `Container` widgets (∉dragged), pick the topmost by StackZ, and publish two
|
|
7
|
+
* signals the move-outcome tree consumes (l3-behave §5.5):
|
|
8
|
+
* - `DropTarget(recognizer → container)` — set for the container under the
|
|
9
|
+
* bounds REGARDLESS of an accepts-match (so the outcome tree can distinguish
|
|
10
|
+
* a rejected drop from a plain move).
|
|
11
|
+
* - `OverlapCandidate` on the container — ONLY when the container's `Accepts`
|
|
12
|
+
* intersects the dragged set's `Provides` (a widget with no `Provides` never
|
|
13
|
+
* matches; RFC-004 contracts).
|
|
14
|
+
* BOTH are strictly change-only: `setRelation`/`addTag` bump the GLOBAL tag/
|
|
15
|
+
* relation version, and any churn wakes every row-filtered observer world-wide
|
|
16
|
+
* (design-002 §4). Both clear when no container is under the bounds; the move
|
|
17
|
+
* behavior clears them on every terminal path.
|
|
18
|
+
*/
|
|
19
|
+
import type { Entity, System, World } from "@vibecook/strata-ecs";
|
|
20
|
+
import type { SpatialIndex } from "@ice/kernel";
|
|
21
|
+
export declare function createDropSystem(world: World, index: SpatialIndex<Entity>): System;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — marquee behavior (design-003 §5 item 7, §5.7; `ctl:behave`). Rider-free.
|
|
3
|
+
*
|
|
4
|
+
* Two entry paths, one system (anchored on the CanvasSurface entity so the body
|
|
5
|
+
* runs EVERY frame — the preview must clear the frame the gesture ends):
|
|
6
|
+
* - desktop: an Active `RoutedMarquee` Drag — rect from `Drag.start + total`
|
|
7
|
+
* (screen), both corners converted to world via the kernel seam.
|
|
8
|
+
* - touch: a Recognized `LongPress` capturing the canvas, riding its
|
|
9
|
+
* continuous tail — rect from `start → cur` (§4.2, v2's proven path; no
|
|
10
|
+
* `Sequence` machinery).
|
|
11
|
+
* Per frame the hit ENTITY SET goes into an out-of-ECS render buffer
|
|
12
|
+
* (`MarqueeBuffer`, recomputed each frame — preview-as-tags would churn the
|
|
13
|
+
* global tag version, design-003 §5.7). Selection commits ONCE at terminal
|
|
14
|
+
* (`JustEnded`): replace with the hits, or union when the watched pointer holds
|
|
15
|
+
* shift; `SelectionVersion` bumps once (the v1 marquee lesson). No `access.write`
|
|
16
|
+
* — reads + the buffer + ctx selection tags only.
|
|
17
|
+
*
|
|
18
|
+
* Camera staleness: both corners convert with the CURRENT camera, so a mid-
|
|
19
|
+
* marquee camera move re-projects the rect (accepted — design-002 §2).
|
|
20
|
+
*/
|
|
21
|
+
import type { Entity, TickSystem, World } from "@vibecook/strata-ecs";
|
|
22
|
+
import { type SpatialIndex } from "@ice/kernel";
|
|
23
|
+
/** The out-of-ECS marquee preview (design-003 §5.7): rect + hit set, recomputed each frame. */
|
|
24
|
+
export interface MarqueeBuffer {
|
|
25
|
+
rect: {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
w: number;
|
|
29
|
+
h: number;
|
|
30
|
+
} | null;
|
|
31
|
+
hits: Entity[];
|
|
32
|
+
}
|
|
33
|
+
export declare function createMarqueeBehavior(world: World, index: SpatialIndex<Entity>): TickSystem & {
|
|
34
|
+
buffer: MarqueeBuffer;
|
|
35
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — port materialization (design-004 §6 ports & wires runtime; `derive`
|
|
3
|
+
* phase, BEFORE `selectionChrome`). The LOCKED gating from design-004 §6 /
|
|
4
|
+
* design-001 §5.3: port ENTITIES are runtime and on-demand, so steady-state
|
|
5
|
+
* pan/zoom with the select tool spawns ZERO ports.
|
|
6
|
+
*
|
|
7
|
+
* Three triggers materialize a widget's declared ports (registry decl → kernel
|
|
8
|
+
* `portAnchor`; a port carries Port + PortAnchor + PortOf → widget, and NO
|
|
9
|
+
* Position/Size — `spatialSync` must never see it; design-004 §6, the
|
|
10
|
+
* SelectionBox precedent). Because ports carry no Position/Size, this system
|
|
11
|
+
* gives them their OWN tiny world AABB in the shared spatial index so they are
|
|
12
|
+
* pickable (design-003 §3 port tier):
|
|
13
|
+
* (a) connect tool → widgets in viewport+overscan (`200/zoom`); materialize at
|
|
14
|
+
* the overscan band, keep across a ×1.5 hysteresis band;
|
|
15
|
+
* (b) any local pointer `Targets` a ported widget → that widget's ports;
|
|
16
|
+
* (c) an Active `RoutedConnect` drag → COMPATIBLE ports (accepts-key
|
|
17
|
+
* intersection with the source port; empty accepts = wildcard) light up
|
|
18
|
+
* STAGED by distance-to-pointer, capped to the nearest 256 within the
|
|
19
|
+
* `portLightUpRadiusPx` screen radius (rev 2: "all visible" at a 10k
|
|
20
|
+
* zoomed-out view meant multi-second fills + sustained pick churn).
|
|
21
|
+
*
|
|
22
|
+
* Spawn budget ≤ `portSpawnPerFrame` (64) per frame — staging spreads a big
|
|
23
|
+
* light-up across frames. A widget's ports reap when every trigger lapsed for
|
|
24
|
+
* `portReapGraceMs`, or immediately if the widget died. Anchors recompute each
|
|
25
|
+
* frame and rewrite Port entities + index entries CHANGE-ONLY (a still widget
|
|
26
|
+
* churns nothing). `SpatialVersion` bumps only on a real index change.
|
|
27
|
+
*/
|
|
28
|
+
import type { Entity, TickSystem, World } from "@vibecook/strata-ecs";
|
|
29
|
+
import { type SpatialIndex } from "@ice/kernel";
|
|
30
|
+
export declare function createPortMaterialize(world: World, index: SpatialIndex<Entity>): TickSystem;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — resize behavior (design-003 §5 item 6; `ctl:behave`).
|
|
3
|
+
*
|
|
4
|
+
* A drag captured on a `HandleSpec` chrome entity (route `RoutedResize`, riders
|
|
5
|
+
* attached by `resizeClaim` §4.5). Per Active frame it writes ABSOLUTE Position+
|
|
6
|
+
* Size for every live `Drags` target from its `Grab` origin + `Drag.total /
|
|
7
|
+
* zoomAtClaim`, resized about the FIXED opposite edge/corner of the grabbed
|
|
8
|
+
* handle (`n`/`s` height-only, `e`/`w` width-only, corners both). Modifiers ride
|
|
9
|
+
* the watched pointer's `PointerMods`: `alt` = resize about center, `shift` =
|
|
10
|
+
* preserve aspect (corner handles). Min size clamps to 1×1. `JustEnded` emits ONE
|
|
11
|
+
* `resize` commit (Position+Size per live target); `JustCancelled`/`JustFailed`
|
|
12
|
+
* restore from `Grab`. Every terminal path removes `Grab` and the `Drags` edges
|
|
13
|
+
* (mirrors l3-behave's clearGestureState; resize has no DropTarget).
|
|
14
|
+
*/
|
|
15
|
+
import type { System, World } from "@vibecook/strata-ecs";
|
|
16
|
+
import type { CommitSink } from "../engine/commit-sink";
|
|
17
|
+
export declare function createResizeBehavior(world: World, sink: CommitSink): System;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L3 — snap (design-003 §5 item 2, §6; `ctl:behave`, ordered BEFORE moveBehavior).
|
|
3
|
+
*
|
|
4
|
+
* For Active `RoutedMove` drags whose dragged set is a `SnapSource`: compute the
|
|
5
|
+
* intended PRE-SNAP rect as `Grab.origin + Drag.total / zoomAtClaim`, unioned
|
|
6
|
+
* over the dragged widgets — NEVER last-applied `Position` (one frame stale ⇒
|
|
7
|
+
* guide-chasing oscillation, design-003 §5.2 red-team; `Grab` is readable here
|
|
8
|
+
* thanks to the ctl:claim settle point, §4.5). Candidates come from the SHARED
|
|
9
|
+
* spatial index (rect query = intended bounds expanded by threshold, filtered to
|
|
10
|
+
* `SnapTarget ∧ ∉dragged`; Visible filtering waits for cull). Threshold is
|
|
11
|
+
* `thresholdPx / zoomAtClaim` (screen-constant). The kernel `computeSnapGuides`
|
|
12
|
+
* does the Figma math; we write `SnapState{dx,dy}` on the recognizer (moveBehavior
|
|
13
|
+
* adds it to the absolute write). Guide CHROME entities (`GuideLine`) are deferred
|
|
14
|
+
* to the chrome-reflector milestone — SnapState only here. SnapState clears to 0,0
|
|
15
|
+
* when snap is off / no source / no candidate.
|
|
16
|
+
*/
|
|
17
|
+
import type { Entity, System, World } from "@vibecook/strata-ecs";
|
|
18
|
+
import { type SpatialIndex } from "@ice/kernel";
|
|
19
|
+
export declare function createSnapSystem(world: World, index: SpatialIndex<Entity>): System;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L4 — cursor projection (design-003 §7; `derive` phase).
|
|
3
|
+
*
|
|
4
|
+
* Memoryless: resolved fresh every run from live world state, priority order
|
|
5
|
+
* (1) any LOCAL pointer with a live `ClaimedBy` — Drag+RoutedMove or a
|
|
6
|
+
* LongPress in Recognized → "grabbing"; RoutedResize → directional resize by
|
|
7
|
+
* the captured handle's `HandleSpec.anchor`; RoutedPan → "grabbing";
|
|
8
|
+
* (2) `ActiveTool` override — pan tool → "grab"; (3) else the mouse pointer's
|
|
9
|
+
* `Targets` kind — a `HandleSpec` → directional resize, an entity with
|
|
10
|
+
* `Position` (widget) → "default", `CanvasSurface`/none → "default".
|
|
11
|
+
*
|
|
12
|
+
* Scheduled on the `CanvasSurface` anchor query (exactly one such entity,
|
|
13
|
+
* guaranteed by install — the same idiom `pointerIngest` uses in l0-input.ts)
|
|
14
|
+
* so the body runs every frame even on tool switches with no pointer motion;
|
|
15
|
+
* `world.query(...)` inside then does the actual local-pointer scan (mirrors
|
|
16
|
+
* `oneTickClear`'s marker sweep in cleanup.ts).
|
|
17
|
+
*
|
|
18
|
+
* The resolved string is closure state; `readCursor()` exposes it — the DOM
|
|
19
|
+
* cursor reflector is the only consumer (core never touches DOM).
|
|
20
|
+
*/
|
|
21
|
+
import type { System, World } from "@vibecook/strata-ecs";
|
|
22
|
+
export declare function createCursorSync(world: World): System & {
|
|
23
|
+
readCursor(): string;
|
|
24
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Measurement ingest (design-004 §2; `input` phase).
|
|
3
|
+
*
|
|
4
|
+
* Drains the {@link MeasureQueue} once per tick and folds each auto-sized
|
|
5
|
+
* widget's latest content-box measurement into the `MeasuredSize` session rider
|
|
6
|
+
* — the effective-size source cull/hit/breakpoint consume where a widget is
|
|
7
|
+
* auto-sized (`MeasuredSize` where present and >0, else `Size`). Auto-sized
|
|
8
|
+
* widgets never commit `Size`; the doc stores authorial intent only.
|
|
9
|
+
*
|
|
10
|
+
* Scheduled on the CANVAS-SURFACE anchor query (exactly one such entity,
|
|
11
|
+
* guaranteed by install) — like `pointerIngest` — because the body must run on
|
|
12
|
+
* frames where no measured widget exists yet, and a tag-only query matches every
|
|
13
|
+
* archetype-independent (a tick system, strata 0.5.0): the drain runs exactly
|
|
14
|
+
* once per frame BY CONSTRUCTION.
|
|
15
|
+
*
|
|
16
|
+
* Two guards keep a hidden widget's `display:none` collapse out of the rider
|
|
17
|
+
* (the §2 double wall): the adapter never enqueues a `0×0` sample, and ingest
|
|
18
|
+
* skips `w===0 && h===0` again here. Real changes clear a **±1 px dead-band**
|
|
19
|
+
* against the current rider so sub-pixel RO jitter never restamps (which would
|
|
20
|
+
* churn breakpoint/cull downstream). Within one drain, samples fold last-wins
|
|
21
|
+
* per entity so a same-tick pair never double-`addComponent`s (strata's
|
|
22
|
+
* flush-time duplicate policy).
|
|
23
|
+
*/
|
|
24
|
+
import type { TickSystem, World } from "@vibecook/strata-ecs";
|
|
25
|
+
import type { MeasureQueue } from "../input/measure-queue";
|
|
26
|
+
export declare function createMeasureIngest(world: World, queue: MeasureQueue): TickSystem;
|