@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,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The measurement queue — the ONE ingest path for auto-sized widget sizes
|
|
3
|
+
* (design-004 §2 host pipeline). Mirrors {@link ../input/queue.ts} exactly:
|
|
4
|
+
* pre-ingest TRANSPORT, not world state. A DOM `ResizeObserver` adapter (the
|
|
5
|
+
* `measure-adapter` in @ice/dom) enqueues normalized `{ entity, w, h }` samples
|
|
6
|
+
* as content boxes resize; `measureIngest` drains once per tick and folds them
|
|
7
|
+
* into the `MeasuredSize` session rider. No system reads it, nothing observes
|
|
8
|
+
* it, it holds nothing across a drain.
|
|
9
|
+
*
|
|
10
|
+
* Measurements are content-box sizes in CSS px (screen == world here — the
|
|
11
|
+
* host's content plane carries the camera transform, so a widget's content is
|
|
12
|
+
* laid out in world units). The adapter NEVER enqueues a `0×0` sample (from a
|
|
13
|
+
* `display:none` host) and ingest skips it a second time — the §2 double wall
|
|
14
|
+
* against a full→0 collapse corrupting bounds/cull on re-entry.
|
|
15
|
+
*/
|
|
16
|
+
import type { Entity } from "@vibecook/strata-ecs";
|
|
17
|
+
export interface MeasureEvent {
|
|
18
|
+
/** The widget entity whose content element resized (a runtime handle). */
|
|
19
|
+
readonly entity: Entity;
|
|
20
|
+
readonly w: number;
|
|
21
|
+
readonly h: number;
|
|
22
|
+
}
|
|
23
|
+
export interface MeasureQueue {
|
|
24
|
+
enqueue(event: MeasureEvent): void;
|
|
25
|
+
/** Drain in arrival order. Called ONLY by `measureIngest`, once per tick. */
|
|
26
|
+
drain(): readonly MeasureEvent[];
|
|
27
|
+
/** Samples waiting (telemetry / the ingest `runIf` guard). */
|
|
28
|
+
size(): number;
|
|
29
|
+
}
|
|
30
|
+
export declare function createMeasureQueue(): MeasureQueue;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The input queue — the ONE input path's front door (Law 2, design-003 §2).
|
|
3
|
+
*
|
|
4
|
+
* Adapters (DOM pointer/wheel/keyboard, R3F router verdicts, test drivers) ONLY
|
|
5
|
+
* enqueue normalized {@link InputEvent}s; `pointerIngest` drains the queue once
|
|
6
|
+
* per tick and turns events into world facts. Handlers run mid-frame at
|
|
7
|
+
* arbitrary times — the queue is what keeps every world write inside the frame
|
|
8
|
+
* contract (design-002 §3). It is pre-ingest TRANSPORT, not world state: no
|
|
9
|
+
* system reads it, nothing observes it, it holds nothing across a drain.
|
|
10
|
+
*
|
|
11
|
+
* Pointer identity: `pointerId` is the adapter's stable string for a device
|
|
12
|
+
* pointer — `"mouse"` for the one mouse, `"touch:<n>"` per touch contact,
|
|
13
|
+
* `"pen"` for a stylus. Ingest keys pointer entities off it (`Pointer.id`).
|
|
14
|
+
*/
|
|
15
|
+
export type InputEventKind = "down" | "move" | "up" | "cancel" | "wheel" | "key";
|
|
16
|
+
export interface InputMods {
|
|
17
|
+
readonly shift: boolean;
|
|
18
|
+
readonly ctrl: boolean;
|
|
19
|
+
readonly alt: boolean;
|
|
20
|
+
readonly meta: boolean;
|
|
21
|
+
/** Space-held (pan gesture modifier, design-003 §4.4) — not a PointerMods field. */
|
|
22
|
+
readonly space: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface InputEvent {
|
|
25
|
+
readonly kind: InputEventKind;
|
|
26
|
+
/** Stable adapter pointer id ("mouse" | "touch:<n>" | "pen"). Empty for kind:"key". */
|
|
27
|
+
readonly pointerId: string;
|
|
28
|
+
readonly device: "mouse" | "touch" | "pen";
|
|
29
|
+
/** Canvas-container-relative CSS px (the kernel screen space). */
|
|
30
|
+
readonly screenX: number;
|
|
31
|
+
readonly screenY: number;
|
|
32
|
+
/** Button bitmask as of this event (PointerEvent.buttons semantics). */
|
|
33
|
+
readonly buttons: number;
|
|
34
|
+
readonly mods: InputMods;
|
|
35
|
+
/** Wheel deltas for kind:"wheel" (`pinch` = ctrl-wheel / trackpad zoom signal). */
|
|
36
|
+
readonly wheel?: {
|
|
37
|
+
readonly dx: number;
|
|
38
|
+
readonly dy: number;
|
|
39
|
+
readonly pinch: number;
|
|
40
|
+
};
|
|
41
|
+
/** GL-island opt-out (pinned widget-event contract, design-002 §8): fact still lands, recognizers skip. */
|
|
42
|
+
readonly surfaceHandled?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Event timestamp (DOMHighResTimeStamp — the same clock rAF hands
|
|
45
|
+
* `engine.step`). Gesture timing anchors on THIS, not the processing frame:
|
|
46
|
+
* a stalled main thread (GC, cold paints) otherwise eats into hold windows —
|
|
47
|
+
* a 640 ms stall at pointerdown made long-press unreachable (2026-07-12
|
|
48
|
+
* field debugging). Absent ⇒ the processing frame's now.
|
|
49
|
+
*/
|
|
50
|
+
readonly tMs?: number;
|
|
51
|
+
}
|
|
52
|
+
export declare const NO_MODS: InputMods;
|
|
53
|
+
export interface InputQueue {
|
|
54
|
+
enqueue(event: InputEvent): void;
|
|
55
|
+
/** Drain in arrival order. Called ONLY by `pointerIngest`, once per tick. */
|
|
56
|
+
drain(): readonly InputEvent[];
|
|
57
|
+
/** Events waiting (telemetry/tests). */
|
|
58
|
+
size(): number;
|
|
59
|
+
}
|
|
60
|
+
export declare function createInputQueue(): InputQueue;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interaction-stack installation (design-002 §2 phase layout × design-003).
|
|
3
|
+
*
|
|
4
|
+
* Composable: `installInteractionCore` wires the M4 spine (L0 ingest, L2
|
|
5
|
+
* lifecycle + kinds + arbitration, ctl:claim, select/move behaviors, cleanup).
|
|
6
|
+
* Later slices (picking, snap, drop, resize, marquee, camera) install through
|
|
7
|
+
* their own module functions into the same phase groups — group order is the
|
|
8
|
+
* only ordering contract between them; within-group order is the design-003 §5
|
|
9
|
+
* in-phase order, so later installers pass explicit `before`-free appends in
|
|
10
|
+
* the documented sequence.
|
|
11
|
+
*
|
|
12
|
+
* The canvas-surface anchor entity is guaranteed here (design-001 §4: picking
|
|
13
|
+
* always resolves to SOMETHING; L0 ingest schedules on it).
|
|
14
|
+
*/
|
|
15
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
16
|
+
import { SpatialIndex } from "@ice/kernel";
|
|
17
|
+
import { type CommitSink } from "../engine/commit-sink";
|
|
18
|
+
import type { Engine } from "../engine/engine";
|
|
19
|
+
import type { InputQueue } from "../input/queue";
|
|
20
|
+
import { type SpawnProfiles } from "../systems/l2-recognize";
|
|
21
|
+
import { type WirePreviewBuffer } from "../systems/l3-connect";
|
|
22
|
+
import { type MarqueeBuffer } from "../systems/l3-marquee";
|
|
23
|
+
/** Ensure the guaranteed pick-fallback entity exists (idempotent; outside tick). */
|
|
24
|
+
export declare function ensureCanvasSurface(world: World): Entity;
|
|
25
|
+
export interface InteractionCoreOpts {
|
|
26
|
+
readonly queue?: InputQueue;
|
|
27
|
+
readonly sink?: CommitSink;
|
|
28
|
+
readonly profiles?: SpawnProfiles;
|
|
29
|
+
}
|
|
30
|
+
export interface InteractionCore {
|
|
31
|
+
readonly queue: InputQueue;
|
|
32
|
+
readonly sink: CommitSink;
|
|
33
|
+
readonly canvasSurface: Entity;
|
|
34
|
+
/** Remove every installed system (HMR / doc switch). */
|
|
35
|
+
uninstall(): void;
|
|
36
|
+
}
|
|
37
|
+
export declare function installInteractionCore(engine: Engine, opts?: InteractionCoreOpts): InteractionCore;
|
|
38
|
+
export interface InteractionStack extends InteractionCore {
|
|
39
|
+
/** The one spatial index (picking/snap/drop/marquee/wires/ports share it). */
|
|
40
|
+
readonly index: SpatialIndex<Entity>;
|
|
41
|
+
/** Marquee preview render buffer (out-of-ECS by design — design-003 §5.7). */
|
|
42
|
+
readonly marqueeBuffer: MarqueeBuffer;
|
|
43
|
+
/** Connect preview render buffer (out-of-ECS — design-004 §6; M8). */
|
|
44
|
+
readonly wirePreview: WirePreviewBuffer;
|
|
45
|
+
/** Nav-op seam (design-004 §7): forget spatialSync's last-known AABBs. */
|
|
46
|
+
clearCaches(): void;
|
|
47
|
+
/** L4 cursor readout for the DOM cursor reflector. */
|
|
48
|
+
readCursor(): string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The FULL M4 stack. Not a wrapper over `installInteractionCore`: within-group
|
|
52
|
+
* order is registration order and design-003 §5's in-phase sequence
|
|
53
|
+
* (select → snap → move → drop → resize → marquee → camera) interleaves spine
|
|
54
|
+
* and non-spine systems, so the full installer registers everything itself in
|
|
55
|
+
* the documented order. `installInteractionCore` remains the spine-only slice
|
|
56
|
+
* (what the spine traces run against).
|
|
57
|
+
*/
|
|
58
|
+
export declare function installInteractionStack(engine: Engine, opts?: InteractionCoreOpts): InteractionStack;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nested canvas (design-004 §7 rev 2 — "the missing systems"; design-001
|
|
3
|
+
* §5.7/§5.8 catalog).
|
|
4
|
+
*
|
|
5
|
+
* - `Active` = derived membership tag: a widget is Active iff the FIRST
|
|
6
|
+
* container ancestor on its `ChildOf` chain is the current nav frame
|
|
7
|
+
* (at root: no container ancestor at all). Children of a deeper container
|
|
8
|
+
* are that container's content — not Active until you enter it.
|
|
9
|
+
* - `activeMembership` (derive tick, before cull): recomputes membership and
|
|
10
|
+
* flips Active/Visible/Culled CHANGE-ONLY. A nav switch is O(frame
|
|
11
|
+
* content) tag flips — bounded, rare, migration-free. Boards without
|
|
12
|
+
* containers converge to "everything Active" on the first pass and never
|
|
13
|
+
* write again (M3–M7 demos unaffected).
|
|
14
|
+
* - Nav stack = SESSION entities: `NavEntry` rows carry NavDepth + NavCamera
|
|
15
|
+
* (the camera to restore on exit) + NavFrame(entry→container). Root =
|
|
16
|
+
* empty stack. Current frame = deepest live entry's NavFrame target.
|
|
17
|
+
* - `enterContainer`/`exitContainer` ops own the SPATIAL INDEX REBUILD:
|
|
18
|
+
* membership flips don't move Transforms, so the incremental spatialSync
|
|
19
|
+
* cache never fires on nav — the ops clear the index + caches and bump
|
|
20
|
+
* `SpatialVersion`; spatialSync repopulates from the new Active set on the
|
|
21
|
+
* next tick (its sweep-by-`seen` semantics make clear+repopulate exact).
|
|
22
|
+
* - `navIntegrity` (react tick, before picking): if the current frame's
|
|
23
|
+
* container died (undo/remote — NavFrame edge auto-cleared), pop to the
|
|
24
|
+
* nearest LIVE ancestor entry (skipping dead ones) or root, restore that
|
|
25
|
+
* camera, rebuild. The recognizer-integrity pattern applied to nav.
|
|
26
|
+
* - Camera memory: enter saves the live camera on the pushed entry
|
|
27
|
+
* (NavCamera) and applies the container's `ContainerCamera` rider (else
|
|
28
|
+
* zoom-to-fit over the frame's content, else identity); exit writes the
|
|
29
|
+
* rider back (per-user view memory; lost on undo-despawn — accepted) and
|
|
30
|
+
* restores the entry's NavCamera.
|
|
31
|
+
*/
|
|
32
|
+
import type { Entity, TickSystem, World } from "@vibecook/strata-ecs";
|
|
33
|
+
import type { SpatialIndex } from "@ice/kernel";
|
|
34
|
+
/** Deepest live nav entry, or undefined at root. */
|
|
35
|
+
export declare function currentNavEntry(world: World): Entity | undefined;
|
|
36
|
+
/** The container the user is inside, or undefined at root. */
|
|
37
|
+
export declare function currentNavFrame(world: World): Entity | undefined;
|
|
38
|
+
export interface NestedCanvas {
|
|
39
|
+
readonly activeMembership: TickSystem;
|
|
40
|
+
readonly navIntegrity: TickSystem;
|
|
41
|
+
enterContainer(container: Entity): void;
|
|
42
|
+
exitContainer(): void;
|
|
43
|
+
/** Depth of the nav stack (0 = root). */
|
|
44
|
+
depth(): number;
|
|
45
|
+
}
|
|
46
|
+
export interface NestedCanvasOpts {
|
|
47
|
+
/** THE spatial index (nav ops clear it; spatialSync repopulates). */
|
|
48
|
+
readonly index: SpatialIndex<Entity>;
|
|
49
|
+
/**
|
|
50
|
+
* Clear spatialSync's private last-known cache alongside the index (the
|
|
51
|
+
* install seam wires this; without it the compare-and-skip would believe
|
|
52
|
+
* stale entries still exist).
|
|
53
|
+
*/
|
|
54
|
+
readonly clearSpatialCaches: () => void;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The membership stamper alone — installed by `installWidgetRuntime` (before
|
|
58
|
+
* cull) so EVERY app partitions correctly, containers or not: a board with no
|
|
59
|
+
* containers converges to all-Active on the first pass and never writes again.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createActiveMembership(world: World): TickSystem;
|
|
62
|
+
export declare function createNestedCanvas(world: World, opts: NestedCanvasOpts): NestedCanvas;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine-owned destroy cascade (design-001 §5.1, §5.3, design-003 §5).
|
|
3
|
+
*
|
|
4
|
+
* strata clears an entity's edges on `tx.destroy` but does NOT recurse, so the
|
|
5
|
+
* engine walks containment itself: depth-first over `getReverse(e, ChildOf)`,
|
|
6
|
+
* destroying descendants before their parent, then the root. Wires are reified
|
|
7
|
+
* edge entities, so a wire whose `WireFrom`/`WireTo` endpoint dies is destroyed
|
|
8
|
+
* with it (reverse-index lookup, same transaction).
|
|
9
|
+
*
|
|
10
|
+
* The walk reads runtime world state via `getReverse`; `tx.destroy` only RECORDS
|
|
11
|
+
* (applied at seal / projection), so the reverse indices stay whole for the whole
|
|
12
|
+
* walk. A `visited` set guards against cycles and double-destroying a wire that
|
|
13
|
+
* touches two doomed endpoints.
|
|
14
|
+
*/
|
|
15
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
16
|
+
import type { Mutator } from "@vibecook/strata-ecs/durable";
|
|
17
|
+
/** Depth-first destroy `root` and its `ChildOf` subtree + any wires bound to a destroyed entity. */
|
|
18
|
+
export declare function cascadeDestroy(tx: Mutator, world: World, root: Entity): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The DEFAULT divergence predicate for the live-write guard (design-001 §3):
|
|
3
|
+
* an entity's doc cells may diverge iff
|
|
4
|
+
* - some recognizer in `GestureActive` currently `Captures` or `Drags` it, or
|
|
5
|
+
* - it carries a live `TransformTween` (fly-back holds the claim after the
|
|
6
|
+
* recognizer is reaped — design-003 review M3 / design-001 §3 amendment).
|
|
7
|
+
*
|
|
8
|
+
* This replaces the "inject a stub" posture (review finding A2): engines wire
|
|
9
|
+
* `createLiveWriter(world, { keyOf, mayDiverge: makeDefaultMayDiverge(world), … })`
|
|
10
|
+
* by default; tests and special hosts may still inject their own predicate.
|
|
11
|
+
* Discrete claims (`GestureRecognized`) deliberately do NOT grant divergence —
|
|
12
|
+
* design-001 §3 live-writes happen only under continuous Active gestures.
|
|
13
|
+
*/
|
|
14
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
15
|
+
export declare function makeDefaultMayDiverge(world: World): (e: Entity) => boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gesture ops — app-handler write paths (design-003 §2/§8).
|
|
3
|
+
*
|
|
4
|
+
* `cancelActiveGestures` sets the ONE-TICK CancelRequest resource: escape, tool
|
|
5
|
+
* switch, and doc detach all converge here; the ctl:spawn sweep transitions
|
|
6
|
+
* every non-terminal recognizer → Cancelled next tick, behaviors restore from
|
|
7
|
+
* riders, and cleanup clears the flag.
|
|
8
|
+
*/
|
|
9
|
+
import type { World } from "@vibecook/strata-ecs";
|
|
10
|
+
export declare function cancelActiveGestures(world: World): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE point-pick (Law 15: the spatial index is the only hit path; this
|
|
3
|
+
* function is its only narrow-phase). Shared verbatim by the in-tick
|
|
4
|
+
* `picking` system (L1, via SystemCtx) and the pointer router's synchronous
|
|
5
|
+
* event-time pick (design-004 §4 GL path, via World — world reads outside
|
|
6
|
+
* the tick are verified-unrestricted). One implementation so the two can
|
|
7
|
+
* never disagree on ordering.
|
|
8
|
+
*
|
|
9
|
+
* Priority: HandleSpec chrome first (nearest edge), then widgets by StackZ
|
|
10
|
+
* descending. Deliberately NOT plane-stratified: cross-plane z is stratified
|
|
11
|
+
* visually (P2 GL composites above P1 DOM), but pick order is StackZ across
|
|
12
|
+
* all surfaces — design-004 §1 names the mixed-overlap consequence and
|
|
13
|
+
* accepts it; do not "fix" it here.
|
|
14
|
+
*/
|
|
15
|
+
import type { Component, Entity } from "@vibecook/strata-ecs";
|
|
16
|
+
import type { Cubic, SpatialIndex } from "@ice/kernel";
|
|
17
|
+
/** Structural reads both `World` and `SystemCtx` provide. */
|
|
18
|
+
export interface PickReader {
|
|
19
|
+
isAlive(e: Entity): boolean;
|
|
20
|
+
has(e: Entity, c: Component): boolean;
|
|
21
|
+
hasTag(e: Entity, t: import("@vibecook/strata-ecs").Tag): boolean;
|
|
22
|
+
get<S>(e: Entity, c: Component<S>): S | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Wire narrow-phase source: cached cubics from wireSync (M8). */
|
|
25
|
+
export interface WirePickSource {
|
|
26
|
+
cubicOf(e: Entity): Cubic | undefined;
|
|
27
|
+
/** Pick slop in WORLD units (screen slop / zoom, caller-converted). */
|
|
28
|
+
readonly slopWorld: number;
|
|
29
|
+
}
|
|
30
|
+
/** Distance from a point to the nearest edge of an AABB (0 iff inside). */
|
|
31
|
+
export declare function distPointToBox(px: number, py: number, minX: number, minY: number, maxX: number, maxY: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Top pick under a world point within `rWorld` (point-in-box when 0).
|
|
34
|
+
* Tier order (design-003 §3, amended for M8): HandleSpec chrome → PORT
|
|
35
|
+
* entities (interaction affordances sit atop their widget edge) → widgets by
|
|
36
|
+
* StackZ → WIRES (render in P0 under content; pick below widgets, above
|
|
37
|
+
* canvas — render order and pick order agree). The canvas fallback stays the
|
|
38
|
+
* caller's. Wires narrow-phase against their cached cubic (`wires` source;
|
|
39
|
+
* without one, wire entries are skipped — coarse AABB hits would make fat
|
|
40
|
+
* bounding boxes steal canvas taps).
|
|
41
|
+
*/
|
|
42
|
+
export declare function pickTopAt(reader: PickReader, index: SpatialIndex<Entity>, wx: number, wy: number, rWorld: number, wires?: WirePickSource): Entity | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port-slot resolution: a widget's port DECLARATIONS (from the widget registry,
|
|
3
|
+
* design-005 §2) → kernel `PortSlot`s (side + even-distribution index/count).
|
|
4
|
+
*
|
|
5
|
+
* The single source of a port's world anchor is the kernel's pure
|
|
6
|
+
* `portAnchor(widgetRect, slot)` — geometry NEVER reads a port ENTITY (design-001
|
|
7
|
+
* §5.3), so wires, the connect preview, and materialized-port anchors all agree
|
|
8
|
+
* by construction and culled endpoints resolve for free. Ports sharing a side are
|
|
9
|
+
* numbered by their declared `index` when given, else by declaration order; the
|
|
10
|
+
* side's `count` drives the even spacing.
|
|
11
|
+
*/
|
|
12
|
+
import type { PortSlot } from "@ice/kernel";
|
|
13
|
+
import type { WidgetPortDecl } from "../widget/define-widget";
|
|
14
|
+
/** Map every declared port id → its `PortSlot` (side/index/count for even spacing). */
|
|
15
|
+
export declare function portSlots(decls: readonly WidgetPortDecl[]): Map<string, PortSlot>;
|
|
16
|
+
/** The `PortSlot` for one port id (undefined if the widget declares no such port). */
|
|
17
|
+
export declare function portSlotOf(decls: readonly WidgetPortDecl[], portId: string): PortSlot | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
2
|
+
export type SelectionMode = "replace" | "toggle" | "add";
|
|
3
|
+
/** All entities currently carrying the `Selected` rider. */
|
|
4
|
+
export declare function selectedEntities(world: World): Entity[];
|
|
5
|
+
/**
|
|
6
|
+
* Apply a selection.
|
|
7
|
+
* - `replace`: exactly `entities` end up selected (others cleared).
|
|
8
|
+
* - `toggle`: flip each of `entities`.
|
|
9
|
+
* - `add`: union `entities` into the current selection.
|
|
10
|
+
* `onChange` fires once, only if a tag actually flipped.
|
|
11
|
+
*/
|
|
12
|
+
export declare function setSelection(world: World, entities: Iterable<Entity>, mode: SelectionMode, onChange?: () => void): void;
|
|
13
|
+
/** Clear the whole selection. `onChange` fires once, only if something was selected. */
|
|
14
|
+
export declare function clearSelection(world: World, onChange?: () => void): void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ice/core presence layer (design-005 §6.5, design-001 §5.6) — attach, publish,
|
|
3
|
+
* remote-cursor projection, and the install seam.
|
|
4
|
+
*/
|
|
5
|
+
export { attachPresence, DEFAULT_PRESENCE_TTL_MS, type PresenceOpts, type PresenceSession, } from "./presence-kit";
|
|
6
|
+
export { createPresencePublish, type PresencePublishOpts } from "./publish";
|
|
7
|
+
export { createRemoteCursorsSystem, installPresence, type InstallPresenceOpts, } from "./remote-cursors";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
2
|
+
import { type EphemeralSource, type EphemeralStore } from "@vibecook/strata-ecs/ephemeral";
|
|
3
|
+
/** Default per-entry TTL — a presence entity self-expires this long after its last keepalive. */
|
|
4
|
+
export declare const DEFAULT_PRESENCE_TTL_MS = 5000;
|
|
5
|
+
export interface PresenceOpts {
|
|
6
|
+
/** SESSION-unique peer id (006 B5). Defaults to `crypto.randomUUID()`. */
|
|
7
|
+
readonly peerId?: string;
|
|
8
|
+
/** Display name — must be real (bare, no default). */
|
|
9
|
+
readonly name: string;
|
|
10
|
+
/** Display color — must be real (bare, no default). */
|
|
11
|
+
readonly color: string;
|
|
12
|
+
/** Per-entry TTL (design §15.3), default {@link DEFAULT_PRESENCE_TTL_MS}. */
|
|
13
|
+
readonly ttlMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface PresenceSession {
|
|
16
|
+
/** This session's peer id (the ephemeral partition prefix). */
|
|
17
|
+
readonly peerId: string;
|
|
18
|
+
/** The writer-partitioned Mutator for this peer's own presence entities. */
|
|
19
|
+
readonly eph: EphemeralStore;
|
|
20
|
+
/** The local peer entity (facets: PresenceInfo + PresencePeer + Local; cursor/selection added by publish). */
|
|
21
|
+
readonly localPeer: Entity;
|
|
22
|
+
/**
|
|
23
|
+
* The LoroEphemeralSnapshot surface. INBOUND presence bytes go through
|
|
24
|
+
* `wire.apply(bytes)`; the encoders (`encodeChanged`/`encodeKeys`/…) are
|
|
25
|
+
* driven by the binding's own timers — do not call them externally.
|
|
26
|
+
*/
|
|
27
|
+
readonly wire: EphemeralSource;
|
|
28
|
+
/** Subscribe to the binding's OUTBOUND presence bytes (its two timers). Returns an unsubscribe. */
|
|
29
|
+
onOutbound(fn: (bytes: Uint8Array) => void): () => void;
|
|
30
|
+
/** Leave (ship tombstones) then tear down the binding + destroy the owned Loro store. Idempotent. */
|
|
31
|
+
detach(): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Attach an ephemeral presence layer to `world`. The returned session owns the
|
|
35
|
+
* Loro store; the app (or the bootstrap kit) wires `wire.apply` / `onOutbound`
|
|
36
|
+
* to a byte channel and installs the publish hook + remote-cursor system via
|
|
37
|
+
* {@link installPresence}.
|
|
38
|
+
*/
|
|
39
|
+
export declare function attachPresence(world: World, opts: PresenceOpts): PresenceSession;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Entity, World } from "@vibecook/strata-ecs";
|
|
2
|
+
import type { PublishHook } from "../engine/engine";
|
|
3
|
+
import type { PresenceSession } from "./presence-kit";
|
|
4
|
+
export interface PresencePublishOpts {
|
|
5
|
+
/** Durable key for a selected entity — the doc session's `store.keyOf`. Absent ⇒ no keys carried. */
|
|
6
|
+
readonly keyOf?: (e: Entity) => string | undefined;
|
|
7
|
+
/** Max selection keys carried (default {@link SELECTION_KEY_CAP}). */
|
|
8
|
+
readonly maxKeys?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Build the publish hook that maintains `session.localPeer`'s cursor + selection
|
|
12
|
+
* facets. Register it with `engine.onPublish` (installPresence does this).
|
|
13
|
+
*/
|
|
14
|
+
export declare function createPresencePublish(world: World, session: PresenceSession, opts?: PresencePublishOpts): PublishHook;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TickSystem, World } from "@vibecook/strata-ecs";
|
|
2
|
+
import type { Engine } from "../engine/engine";
|
|
3
|
+
import { type PresencePublishOpts } from "./publish";
|
|
4
|
+
import type { PresenceSession } from "./presence-kit";
|
|
5
|
+
/**
|
|
6
|
+
* The derive tick system that pools + reaps remote cursor entities. `world` is
|
|
7
|
+
* unused directly (iteration goes through `ctx`), kept for factory symmetry with
|
|
8
|
+
* the other `create*System(world)` builders.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createRemoteCursorsSystem(_world: World): TickSystem;
|
|
11
|
+
export type InstallPresenceOpts = PresencePublishOpts;
|
|
12
|
+
/**
|
|
13
|
+
* Wire a presence session into an engine: the publish hook (outbound facet
|
|
14
|
+
* derivation) + the remote-cursor derive system. Returns an uninstall that
|
|
15
|
+
* removes both. Does NOT own the session's lifecycle — call `session.detach()`
|
|
16
|
+
* separately.
|
|
17
|
+
*/
|
|
18
|
+
export declare function installPresence(engine: Engine, session: PresenceSession, opts?: InstallPresenceOpts): () => void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema metadata registry (design-001 §2, design-005 §1).
|
|
3
|
+
*
|
|
4
|
+
* Components/tags/relations stay PURE (rev-2 sovereignty) — but prefab
|
|
5
|
+
* validation (eid ban, required-field defaults) and devtools badges need to
|
|
6
|
+
* know what a component's fields look like. strata does not expose schema
|
|
7
|
+
* introspection publicly, so ALL engine + userland definitions go through
|
|
8
|
+
* these thin wrappers: they record the raw schema in a side registry, then
|
|
9
|
+
* delegate to strata unchanged. The returned handles are strata's own.
|
|
10
|
+
*/
|
|
11
|
+
import { defineComponent as strataDefineComponent, defineResource as strataDefineResource, type Component, type FieldInput, type Relation, type Resource, type Tag } from "@vibecook/strata-ecs";
|
|
12
|
+
export type RawSchema = Record<string, FieldInput>;
|
|
13
|
+
export interface ComponentMeta {
|
|
14
|
+
name: string;
|
|
15
|
+
schema: RawSchema;
|
|
16
|
+
/** Field names whose type is `eid` (runtime-local handles — banned in durable cells). */
|
|
17
|
+
eidFields: string[];
|
|
18
|
+
/** Field names with no default (strata requires them at spawn). */
|
|
19
|
+
requiredFields: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface RelationMeta {
|
|
22
|
+
name: string;
|
|
23
|
+
arity: "one" | "many";
|
|
24
|
+
}
|
|
25
|
+
export interface ResourceMeta {
|
|
26
|
+
name: string;
|
|
27
|
+
/** design-001 §2 rule 7: resources declare durable|runtime at definition. */
|
|
28
|
+
durable: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function defineComponent<const Sch extends RawSchema>(name: string, schema: Sch): ReturnType<typeof strataDefineComponent<Sch>>;
|
|
31
|
+
export declare function defineTag(name: string): Tag;
|
|
32
|
+
export declare function defineRelation(name: string, opts?: {
|
|
33
|
+
arity?: "one" | "many";
|
|
34
|
+
}): Relation;
|
|
35
|
+
export declare function defineResource<const Sch extends RawSchema>(name: string, schema: Sch, opts?: {
|
|
36
|
+
durable?: boolean;
|
|
37
|
+
}): ReturnType<typeof strataDefineResource<Sch>>;
|
|
38
|
+
export declare const schemaMeta: {
|
|
39
|
+
component(c: Component): ComponentMeta | undefined;
|
|
40
|
+
tagName(t: Tag): string | undefined;
|
|
41
|
+
relation(r: Relation): RelationMeta | undefined;
|
|
42
|
+
resource(r: Resource): ResourceMeta | undefined;
|
|
43
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prefabs — sovereignty at the entity level (design-001 §2, rev 2).
|
|
3
|
+
*
|
|
4
|
+
* A prefab declares an entity kind's ESSENTIAL component set, its
|
|
5
|
+
* durable-ELIGIBLE extras, and its class; the class IS the spawn path:
|
|
6
|
+
* durable → tx.spawn · runtime → world/ctx.spawn · ephemeral → eph.spawn
|
|
7
|
+
*
|
|
8
|
+
* Validation set (design-005 §1, all DEV-throw at definition time):
|
|
9
|
+
* - eligible components eid-free (durable prefabs)
|
|
10
|
+
* - every essential component's required fields supplied by its init value
|
|
11
|
+
* - ephemeral prefabs: components + tags only (no relations)
|
|
12
|
+
* - owner:"derive" only on runtime prefabs
|
|
13
|
+
* - prefab ids unique
|
|
14
|
+
*/
|
|
15
|
+
import type { Component, Entity, EntityKey, Relation, Tag } from "@vibecook/strata-ecs";
|
|
16
|
+
/** Durable identity stamp (design-001 §2 rule 5) — subsumes WidgetType. */
|
|
17
|
+
export declare const PrefabId: Component<import("@vibecook/strata-ecs").ValueOf<{
|
|
18
|
+
readonly id: "string";
|
|
19
|
+
}>, {
|
|
20
|
+
readonly id: "string";
|
|
21
|
+
}>;
|
|
22
|
+
export type PrefabClass = "durable" | "runtime" | "ephemeral";
|
|
23
|
+
/** Scalar shapes strata accepts as field writes at spawn. */
|
|
24
|
+
export type FieldWrite = string | number | boolean | Entity | EntityKey | null;
|
|
25
|
+
export type ComponentInit = readonly [Component, Record<string, FieldWrite>];
|
|
26
|
+
/**
|
|
27
|
+
* Typed component-init pair: `init(Position, { x: 0, y: 0 })` gets full
|
|
28
|
+
* compile-time field checking (missing/extra/mistyped fields error) before
|
|
29
|
+
* erasing to the registry's loose `ComponentInit`. Prefer this in every
|
|
30
|
+
* prefab definition and instantiate override; raw pairs remain legal for
|
|
31
|
+
* dynamic construction (review finding B4).
|
|
32
|
+
*/
|
|
33
|
+
export declare function init<S extends Record<string, FieldWrite>>(c: Component<S>, v: S): ComponentInit;
|
|
34
|
+
export interface PrefabDef {
|
|
35
|
+
store: PrefabClass;
|
|
36
|
+
/** Essential set: spawned with, committed for durable prefabs. */
|
|
37
|
+
components: readonly ComponentInit[];
|
|
38
|
+
tags?: readonly Tag[];
|
|
39
|
+
/** Durable-eligible beyond essential (attachable later via tx); facets for ephemeral. */
|
|
40
|
+
optional?: readonly Component[];
|
|
41
|
+
/** Eligible outgoing relations (durable prefabs; runtime relations are unrestricted). */
|
|
42
|
+
relations?: readonly Relation[];
|
|
43
|
+
/** Write-ownership badge (devtools) — runtime prefabs only. */
|
|
44
|
+
owner?: "derive";
|
|
45
|
+
/**
|
|
46
|
+
* Pack version for the document version gate (design-001 §5.2, design-005
|
|
47
|
+
* §6.3): stamped as an `engine.pack.<id>.<v>` marker key at doc creation and
|
|
48
|
+
* compared at open. Bump when the prefab's durable shape changes. Default 1.
|
|
49
|
+
*/
|
|
50
|
+
version?: number;
|
|
51
|
+
}
|
|
52
|
+
export interface Prefab extends PrefabDef {
|
|
53
|
+
id: string;
|
|
54
|
+
/** Eligible component set = essential ∪ optional ∪ {PrefabId}. */
|
|
55
|
+
eligible: ReadonlySet<Component>;
|
|
56
|
+
eligibleRelations: ReadonlySet<Relation>;
|
|
57
|
+
}
|
|
58
|
+
export declare function definePrefab(id: string, def: PrefabDef): Prefab;
|
|
59
|
+
export declare const prefabs: {
|
|
60
|
+
get(id: string): Prefab | undefined;
|
|
61
|
+
/** Every registered prefab (the version gate stamps/compares the full set). */
|
|
62
|
+
all(): Prefab[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* TEST-ONLY registry wipe. Deliberately a standalone export that the public
|
|
66
|
+
* barrel does NOT re-export (review finding A8) — tests import it from this
|
|
67
|
+
* module path directly.
|
|
68
|
+
*/
|
|
69
|
+
export declare function __resetPrefabsForTests(): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime default constants transcribed from the reviewed design docs.
|
|
3
|
+
* Not exported from the package barrel yet (design-005 §4 engine facade wires these in later).
|
|
4
|
+
*/
|
|
5
|
+
/** Recognizer timing/slop defaults (design-003 §4.2 kind table; inertia constants from §5 item 9; multi-tap from v2 gesture.ts). */
|
|
6
|
+
export declare const GESTURE_DEFAULTS: {
|
|
7
|
+
readonly tapMaxMs: 250;
|
|
8
|
+
readonly tapSlopPx: 8;
|
|
9
|
+
readonly longPressMs: 500;
|
|
10
|
+
readonly longPressSlopPx: 10;
|
|
11
|
+
readonly dragSlopPx: 10;
|
|
12
|
+
readonly pinchSlopPx: 6;
|
|
13
|
+
readonly wheelEndSilenceMs: 150;
|
|
14
|
+
readonly inertiaMinVelocityPxPerS: 120;
|
|
15
|
+
readonly inertiaDecayMs: 325;
|
|
16
|
+
readonly multiTapWindowMs: 280;
|
|
17
|
+
readonly multiTapSlopPx: 20;
|
|
18
|
+
};
|
|
19
|
+
/** Pick radii + retarget dead-band (design-003 §3 L1 targeting). */
|
|
20
|
+
export declare const POINTER_DEFAULTS: {
|
|
21
|
+
readonly radiusMousePx: 0;
|
|
22
|
+
readonly radiusTouchPx: 12;
|
|
23
|
+
readonly radiusPenPx: 4;
|
|
24
|
+
readonly hoverReleaseDeadBandPx: 4;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Wire/port picking geometry (design-003 §3 wires-below-widgets; design-004 §6).
|
|
28
|
+
* `wirePickSlopPx` is added to the pointer radius (screen px, `/zoom` at use) so a
|
|
29
|
+
* thin bezier stays grab-able; `portIndexHalfWorld` is the half-extent of the tiny
|
|
30
|
+
* world AABB a materialized port occupies in the spatial index (design-004 §6 —
|
|
31
|
+
* ports are pickable but carry no Position/Size, so spatialSync never sees them).
|
|
32
|
+
*/
|
|
33
|
+
export declare const GRAPH_PICK_DEFAULTS: {
|
|
34
|
+
readonly wirePickSlopPx: 8;
|
|
35
|
+
readonly portIndexHalfWorld: 6;
|
|
36
|
+
};
|
|
37
|
+
/** SnapConfig resource defaults (design-005 §4 engine facade). */
|
|
38
|
+
export declare const SNAP_DEFAULTS: {
|
|
39
|
+
readonly enabled: true;
|
|
40
|
+
readonly thresholdPx: 5;
|
|
41
|
+
};
|
|
42
|
+
/** Zoom clamp (design-003 §5 item 9 cameraControl) and frame dt clamp (design-002 §1). */
|
|
43
|
+
export declare const CAMERA_DEFAULTS: {
|
|
44
|
+
readonly minZoom: 0.1;
|
|
45
|
+
readonly maxZoom: 5;
|
|
46
|
+
readonly dtClampMs: 64;
|
|
47
|
+
};
|
|
48
|
+
/** Widget/FBO/port budgets (design-004 §2 host pipeline, §3 FBO pool, §6 port materialization; ported into design-005 §4 engine facade). */
|
|
49
|
+
export declare const RUNTIME_BUDGETS: {
|
|
50
|
+
readonly keepMountedWidgets: 256;
|
|
51
|
+
readonly fboBytes: 268435456;
|
|
52
|
+
readonly portSpawnPerFrame: 64;
|
|
53
|
+
readonly portLightUpRadiusPx: 600;
|
|
54
|
+
readonly portReapGraceMs: 1000;
|
|
55
|
+
readonly cullOverscanWorldPerZoom: 200;
|
|
56
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { System, TickSystem, World } from "@vibecook/strata-ecs";
|
|
2
|
+
/**
|
|
3
|
+
* Runtime pan-inertia velocity (screen px/s), seeded by `cameraControl` at pan
|
|
4
|
+
* release and decayed by `cameraInertia`. A resource (not closure state) so
|
|
5
|
+
* devtools sees it and there is no hidden singleton (design-003 §9).
|
|
6
|
+
*/
|
|
7
|
+
export declare const CameraInertia: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
|
|
8
|
+
readonly vx: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
9
|
+
readonly vy: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
10
|
+
}>, {
|
|
11
|
+
readonly vx: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
12
|
+
readonly vy: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
13
|
+
}>;
|
|
14
|
+
export interface CameraSystems {
|
|
15
|
+
cameraControl: TickSystem;
|
|
16
|
+
cameraInertia: TickSystem;
|
|
17
|
+
tweenSystem: System;
|
|
18
|
+
}
|
|
19
|
+
export declare function createCameraSystems(world: World): CameraSystems;
|