@vibecook/ice 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -2
- package/dist/chunk-2GUYATUM.js +643 -0
- package/dist/chunk-2GUYATUM.js.map +1 -0
- package/dist/{chunk-5S7GSXJG.js → chunk-5QY7HK6G.js} +3145 -1306
- package/dist/chunk-5QY7HK6G.js.map +1 -0
- package/dist/{chunk-BCJ47SX7.js → chunk-OR5FNVUE.js} +460 -1
- package/dist/chunk-OR5FNVUE.js.map +1 -0
- package/dist/{chunk-FIAXPNNY.js → chunk-PKK6GLSA.js} +143 -551
- package/dist/chunk-PKK6GLSA.js.map +1 -0
- package/dist/devtools.js +508 -372
- package/dist/devtools.js.map +1 -1
- package/dist/dom.js +3 -11
- package/dist/ground.js +715 -0
- package/dist/ground.js.map +1 -0
- package/dist/index.js +80 -2
- package/dist/kernel.js +31 -1
- package/dist/r3f.js +605 -62
- package/dist/r3f.js.map +1 -1
- package/dist/react.js +36 -418
- package/dist/react.js.map +1 -1
- package/dist/types/packages/core/src/catalog/camera-derived.d.ts +65 -3
- package/dist/types/packages/core/src/catalog/gesture.d.ts +40 -4
- package/dist/types/packages/core/src/catalog/graph.d.ts +7 -6
- package/dist/types/packages/core/src/catalog/index.d.ts +1 -0
- package/dist/types/packages/core/src/catalog/insert.d.ts +31 -0
- package/dist/types/packages/core/src/catalog/pointer.d.ts +11 -0
- package/dist/types/packages/core/src/catalog/scene.d.ts +37 -4
- package/dist/types/packages/core/src/catalog/selection-presence.d.ts +7 -0
- package/dist/types/packages/core/src/catalog/settings-resources.d.ts +21 -0
- package/dist/types/packages/core/src/doc/autosave.d.ts +49 -2
- package/dist/types/packages/core/src/doc/bootstrap.d.ts +29 -0
- package/dist/types/packages/core/src/doc/channels.d.ts +9 -0
- package/dist/types/packages/core/src/doc/doc-commit-sink.d.ts +2 -1
- package/dist/types/packages/core/src/doc/doc-kit.d.ts +16 -1
- package/dist/types/packages/core/src/doc/envelope.d.ts +2 -1
- package/dist/types/packages/core/src/doc/migrate.d.ts +8 -6
- package/dist/types/packages/core/src/doc/schema-migrate.d.ts +50 -0
- package/dist/types/packages/core/src/doc/version-gate.d.ts +3 -0
- package/dist/types/packages/core/src/engine/commit-sink.d.ts +24 -2
- package/dist/types/packages/core/src/engine/engine.d.ts +11 -0
- package/dist/types/packages/core/src/engine/frame-control.d.ts +71 -0
- package/dist/types/packages/core/src/engine/frame-info.d.ts +16 -1
- package/dist/types/packages/core/src/facade/create-canvas-engine.d.ts +79 -6
- package/dist/types/packages/core/src/guards/guarded-tx.d.ts +4 -2
- package/dist/types/packages/core/src/helpers/churn-guard.d.ts +40 -0
- package/dist/types/packages/core/src/index.d.ts +15 -7
- package/dist/types/packages/core/src/input/queue.d.ts +11 -0
- package/dist/types/packages/core/src/interaction/gesture-status.d.ts +13 -0
- package/dist/types/packages/core/src/nav/nested-canvas.d.ts +47 -11
- package/dist/types/packages/core/src/ops/arrange.d.ts +15 -0
- package/dist/types/packages/core/src/ops/insert.d.ts +62 -0
- package/dist/types/packages/core/src/ops/point-pick.d.ts +11 -7
- package/dist/types/packages/core/src/ops/sibling-order.d.ts +70 -0
- package/dist/types/packages/core/src/schema/meta.d.ts +1 -0
- package/dist/types/packages/core/src/settings/defaults.d.ts +45 -0
- package/dist/types/packages/core/src/settings/ground-config.d.ts +55 -0
- package/dist/types/packages/core/src/systems/chrome.d.ts +6 -2
- package/dist/types/packages/core/src/systems/insert-ghost.d.ts +25 -0
- package/dist/types/packages/core/src/systems/l1-pick.d.ts +25 -11
- package/dist/types/packages/core/src/systems/l2-recognize.d.ts +10 -4
- package/dist/types/packages/core/src/systems/l3-behave.d.ts +6 -4
- package/dist/types/packages/core/src/systems/l3-claim.d.ts +7 -3
- package/dist/types/packages/core/src/systems/l3-drop.d.ts +3 -1
- package/dist/types/packages/core/src/systems/l3-resize.d.ts +3 -1
- package/dist/types/packages/core/src/systems/l3-snap.d.ts +25 -7
- package/dist/types/packages/core/src/systems/nav-flight.d.ts +95 -0
- package/dist/types/packages/core/src/widget/define-widget.d.ts +39 -0
- package/dist/types/packages/core/src/widget/mount-store.d.ts +11 -3
- package/dist/types/packages/core/src/widget/set-props.d.ts +16 -0
- package/dist/types/packages/core/src/widget/spawn.d.ts +21 -1
- package/dist/types/packages/devtools/src/attach.d.ts +77 -0
- package/dist/types/packages/devtools/src/dock.d.ts +38 -0
- package/dist/types/packages/devtools/src/gl-panel.d.ts +69 -0
- package/dist/types/packages/devtools/src/index.d.ts +8 -6
- package/dist/types/packages/dom/src/index.d.ts +1 -3
- package/dist/types/packages/dom/src/loop.d.ts +11 -0
- package/dist/types/packages/dom/src/measure-wiring.d.ts +2 -2
- package/dist/types/packages/dom/src/pointer-adapter.d.ts +21 -1
- package/dist/types/packages/dom/src/reflectors/dom-widgets.d.ts +5 -0
- package/dist/types/packages/ground/src/index.d.ts +52 -0
- package/dist/types/packages/ground/src/layer.d.ts +40 -0
- package/dist/types/packages/ground/src/pass.d.ts +41 -0
- package/dist/types/packages/ground/src/passes/grid.d.ts +21 -0
- package/dist/types/packages/ground/src/passes/guides-collect.d.ts +14 -0
- package/dist/types/packages/ground/src/passes/guides.d.ts +3 -0
- package/dist/types/packages/ground/src/passes/soup-collect.d.ts +35 -0
- package/dist/types/packages/ground/src/passes/soup-mesh.d.ts +8 -0
- package/dist/types/packages/ground/src/passes/wires-collect.d.ts +31 -0
- package/dist/types/packages/ground/src/passes/wires.d.ts +10 -0
- package/dist/types/packages/ground/src/renderer.d.ts +15 -0
- package/dist/types/packages/ice/src/ground.d.ts +1 -0
- package/dist/types/packages/kernel/src/bezier.d.ts +15 -0
- package/dist/types/packages/kernel/src/coords.d.ts +15 -0
- package/dist/types/packages/kernel/src/easing.d.ts +11 -0
- package/dist/types/packages/kernel/src/index.d.ts +3 -0
- package/dist/types/packages/kernel/src/layout.d.ts +118 -0
- package/dist/types/packages/kernel/src/nav-flight.d.ts +93 -0
- package/dist/types/packages/r3f/src/bridge.d.ts +73 -12
- package/dist/types/packages/r3f/src/composite-material.d.ts +9 -0
- package/dist/types/packages/r3f/src/compositor-pass.d.ts +22 -0
- package/dist/types/packages/r3f/src/gl-root.d.ts +76 -1
- package/dist/types/packages/r3f/src/gl-router.d.ts +10 -0
- package/dist/types/packages/r3f/src/index.d.ts +3 -2
- package/dist/types/packages/r3f/src/island-state.d.ts +44 -0
- package/dist/types/packages/r3f/src/preview-capture.d.ts +19 -0
- package/dist/types/packages/r3f/src/self-sustain.d.ts +39 -0
- package/dist/types/packages/r3f/src/use-island-frame.d.ts +16 -1
- package/dist/types/packages/react/src/engine-context.d.ts +21 -0
- package/dist/types/packages/react/src/index.d.ts +4 -2
- package/dist/types/packages/react/src/infinite-canvas.d.ts +40 -6
- package/dist/types/packages/react/src/preview-snapshots.d.ts +17 -0
- package/dist/types/packages/react/src/widget-preview.d.ts +14 -0
- package/package.json +32 -61
- package/dist/chunk-5S7GSXJG.js.map +0 -1
- package/dist/chunk-BCJ47SX7.js.map +0 -1
- package/dist/chunk-FIAXPNNY.js.map +0 -1
- package/dist/types/packages/devtools/src/panel.d.ts +0 -48
- package/dist/types/packages/dom/src/reflectors/grid.d.ts +0 -63
- package/dist/types/packages/dom/src/reflectors/wires.d.ts +0 -88
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
* the tick are verified-unrestricted). One implementation so the two can
|
|
7
7
|
* never disagree on ordering.
|
|
8
8
|
*
|
|
9
|
-
* Priority: HandleSpec chrome first (nearest edge), then widgets by
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* Priority: HandleSpec chrome first (nearest edge), then widgets topmost by
|
|
10
|
+
* SIBLING ORDER (petition 8: the frame parent's ChildOf sequence, legacy
|
|
11
|
+
* (StackZ, entity) fallback for edge-less entities — compareStackOrder is the
|
|
12
|
+
* ONE comparator paint and pick share). Deliberately NOT plane-stratified:
|
|
13
|
+
* cross-plane z is stratified visually (P2 GL composites above P1 DOM), but
|
|
14
|
+
* pick order is sibling order across all surfaces — design-004 §1 names the
|
|
15
|
+
* mixed-overlap consequence and accepts it; do not "fix" it here.
|
|
14
16
|
*/
|
|
15
17
|
import type { Component, Entity } from "@vibecook/strata-ecs";
|
|
16
18
|
import type { Cubic, SpatialIndex } from "@ice/kernel";
|
|
@@ -33,10 +35,12 @@ export declare function distPointToBox(px: number, py: number, minX: number, min
|
|
|
33
35
|
* Top pick under a world point within `rWorld` (point-in-box when 0).
|
|
34
36
|
* Tier order (design-003 §3, amended for M8): HandleSpec chrome → PORT
|
|
35
37
|
* entities (interaction affordances sit atop their widget edge) → widgets by
|
|
36
|
-
*
|
|
38
|
+
* sibling order (topmost = compareStackOrder max; `ordinals` is the caller's
|
|
39
|
+
* frame ordinal map — SiblingOrderIndex — so paint and pick share one order)
|
|
40
|
+
* → WIRES (render in P0 under content; pick below widgets, above
|
|
37
41
|
* canvas — render order and pick order agree). The canvas fallback stays the
|
|
38
42
|
* caller's. Wires narrow-phase against their cached cubic (`wires` source;
|
|
39
43
|
* without one, wire entries are skipped — coarse AABB hits would make fat
|
|
40
44
|
* bounding boxes steal canvas taps).
|
|
41
45
|
*/
|
|
42
|
-
export declare function pickTopAt(reader: PickReader, index: SpatialIndex<Entity>, wx: number, wy: number, rWorld: number, wires?: WirePickSource): Entity | undefined;
|
|
46
|
+
export declare function pickTopAt(reader: PickReader, index: SpatialIndex<Entity>, wx: number, wy: number, rWorld: number, wires?: WirePickSource, ordinals?: ReadonlyMap<Entity, number>): Entity | undefined;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sibling order — THE per-frame stacking source (petition 8; design-004 §1
|
|
3
|
+
* amendment). Within a frame, paint/pick/drop order IS the frame parent's
|
|
4
|
+
* ordered `ChildOf` sibling sequence: index 0 paints first (bottom), the tail
|
|
5
|
+
* paints last (top). The frame parent is `currentNavFrame(world) ?? BoardRoot`
|
|
6
|
+
* — every renderer/pick consumer shares this module so the orders can never
|
|
7
|
+
* diverge (the point-pick lesson, extended to the comparator).
|
|
8
|
+
*
|
|
9
|
+
* LEGACY FALLBACK (must keep working): when the `BoardRoot` resource is absent
|
|
10
|
+
* (a pre-schema-2 doc opened read-only, or a doc-less runtime world) OR an
|
|
11
|
+
* entity carries no `ChildOf` edge (bare runtime spawns), stacking falls back
|
|
12
|
+
* to the legacy `(StackZ.z asc, entity asc)` comparator. This module is the
|
|
13
|
+
* ONLY sanctioned StackZ reader outside the schema migration.
|
|
14
|
+
*
|
|
15
|
+
* Mixed frames — some entities ordinal-mapped, some fallback — are nominally
|
|
16
|
+
* impossible (the 1→2 migration hangs an edge on every durable widget, and a
|
|
17
|
+
* pre-schema-2 read-only doc has no BoardRoot at all, so it is all-fallback).
|
|
18
|
+
* The comparator still totals them: ordinal-mapped entities sort BELOW the
|
|
19
|
+
* fallback set (ordinals first in paint order), each group internally ordered
|
|
20
|
+
* by its own rule — documented so a stray bare spawn lands somewhere stable
|
|
21
|
+
* rather than somewhere random.
|
|
22
|
+
*
|
|
23
|
+
* Invalidation is PULL-ONLY, the strata 0.8.0 contract: `world.orderStamp
|
|
24
|
+
* (parent, ChildOf)` is a monotonic per-parent version consumers poll after a
|
|
25
|
+
* reactive wake; the wake itself is an `observeQuery` whose grammar names the
|
|
26
|
+
* relation (`Related(ChildOf)` — pure reorders turn it over).
|
|
27
|
+
*/
|
|
28
|
+
import type { Component, Entity, World } from "@vibecook/strata-ecs";
|
|
29
|
+
/** Structural read both `World` and `SystemCtx` provide — all the comparator needs. */
|
|
30
|
+
export interface StackOrderReader {
|
|
31
|
+
get<S>(e: Entity, c: Component<S>): S | undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The frame parent — the entity whose `ChildOf` sibling sequence is the
|
|
35
|
+
* current frame's stacking order: the nav frame when inside a container, else
|
|
36
|
+
* the document's board root. `undefined` = a legacy world (pre-schema-2
|
|
37
|
+
* read-only doc / doc-less runtime) — everything is fallback-ordered.
|
|
38
|
+
*/
|
|
39
|
+
export declare function frameParent(world: World): Entity | undefined;
|
|
40
|
+
/** `parent`'s sibling sequence as entity → position (the renderers' sort key). */
|
|
41
|
+
export declare function buildOrdinals(world: World, parent: Entity): Map<Entity, number>;
|
|
42
|
+
/**
|
|
43
|
+
* THE stacking comparator (ascending = paint order; the pick tier takes the
|
|
44
|
+
* max). Ordinal-mapped entities order by sibling position; entities missing
|
|
45
|
+
* from the map use the legacy `(StackZ asc, entity asc)` fallback among
|
|
46
|
+
* themselves and sort ABOVE the ordinal-mapped set (see the header note on
|
|
47
|
+
* nominally-impossible mixed frames).
|
|
48
|
+
*/
|
|
49
|
+
export declare function compareStackOrder(reader: StackOrderReader, ordinals: ReadonlyMap<Entity, number>, a: Entity, b: Entity): number;
|
|
50
|
+
export interface SiblingOrderIndex {
|
|
51
|
+
/** The frame parent backing the current ordinal map (undefined = legacy world). */
|
|
52
|
+
parent(): Entity | undefined;
|
|
53
|
+
/** The stamp-checked ordinal map — rebuilt only when the frame parent or its `orderStamp` moved. */
|
|
54
|
+
ordinals(): ReadonlyMap<Entity, number>;
|
|
55
|
+
/** True when the next `ordinals()` would rebuild (cheap pull; no rebuild). */
|
|
56
|
+
stale(): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Arm the reorder wake: an `observeQuery` naming `ChildOf` (`Related`
|
|
59
|
+
* grammar — pure reorders and edge turnover both fire it). Callers pair it
|
|
60
|
+
* with `stale()`/`ordinals()` so other-frame churn stays a no-op.
|
|
61
|
+
*/
|
|
62
|
+
observe(cb: () => void): () => void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A pull-based ordinal cache over the CURRENT frame parent's sibling sequence.
|
|
66
|
+
* Consumers each hold their own instance (the cache is a cheap `getReverse`
|
|
67
|
+
* walk); correctness is shared through {@link compareStackOrder} and the
|
|
68
|
+
* stamp, never through instance identity.
|
|
69
|
+
*/
|
|
70
|
+
export declare function createSiblingOrderIndex(world: World): SiblingOrderIndex;
|
|
@@ -31,6 +31,7 @@ export declare function defineComponent<const Sch extends RawSchema>(name: strin
|
|
|
31
31
|
export declare function defineTag(name: string): Tag;
|
|
32
32
|
export declare function defineRelation(name: string, opts?: {
|
|
33
33
|
arity?: "one" | "many";
|
|
34
|
+
ordered?: boolean;
|
|
34
35
|
}): Relation;
|
|
35
36
|
export declare function defineResource<const Sch extends RawSchema>(name: string, schema: Sch, opts?: {
|
|
36
37
|
durable?: boolean;
|
|
@@ -15,6 +15,8 @@ export declare const GESTURE_DEFAULTS: {
|
|
|
15
15
|
readonly inertiaDecayMs: 325;
|
|
16
16
|
readonly multiTapWindowMs: 280;
|
|
17
17
|
readonly multiTapSlopPx: 20;
|
|
18
|
+
readonly wheelZoomSensitivity: 0.01;
|
|
19
|
+
readonly wheelZoomMaxStep: 10;
|
|
18
20
|
};
|
|
19
21
|
/** Pick radii + retarget dead-band (design-003 §3 L1 targeting). */
|
|
20
22
|
export declare const POINTER_DEFAULTS: {
|
|
@@ -39,12 +41,55 @@ export declare const SNAP_DEFAULTS: {
|
|
|
39
41
|
readonly enabled: true;
|
|
40
42
|
readonly thresholdPx: 5;
|
|
41
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Selection-chrome knobs (2026-07-17). `liftScale` mirrors the app's visual
|
|
46
|
+
* drag-lift scale (widgetlab CardShell: 1.05) so the union box can inflate a
|
|
47
|
+
* grabbed member's rect and keep WRAPPING the card it sees; 1 = no lift
|
|
48
|
+
* visual, no inflation.
|
|
49
|
+
*/
|
|
50
|
+
export declare const CHROME_DEFAULTS: {
|
|
51
|
+
readonly liftScale: 1;
|
|
52
|
+
};
|
|
42
53
|
/** Zoom clamp (design-003 §5 item 9 cameraControl) and frame dt clamp (design-002 §1). */
|
|
43
54
|
export declare const CAMERA_DEFAULTS: {
|
|
44
55
|
readonly minZoom: 0.1;
|
|
45
56
|
readonly maxZoom: 5;
|
|
46
57
|
readonly dtClampMs: 64;
|
|
47
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* The natural auto-framing band (2026-07-18, James: "not super zoomed in
|
|
61
|
+
* nor super zoomed out, should feel natural"): every DEFAULT framing —
|
|
62
|
+
* `ops.frameContent` at boot, the folder arrival camera, and the folder
|
|
63
|
+
* minis' portal affine (widgetlab keeps its preview in lockstep) — fits
|
|
64
|
+
* content via kernel `fitCamera` but never lands outside
|
|
65
|
+
* [fitMinZoom, fitMaxZoom], intersected with the session's hard
|
|
66
|
+
* CameraLimits. `ops.zoomToFit` stays UNCAPPED: an explicit "show me
|
|
67
|
+
* everything" beats natural.
|
|
68
|
+
*/
|
|
69
|
+
export declare const FIT_DEFAULTS: {
|
|
70
|
+
readonly pad: 80;
|
|
71
|
+
readonly minZoom: 0.5;
|
|
72
|
+
readonly maxZoom: 1;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Nav-transition motion constants (design-006 §4/§5, tuned in the approved
|
|
76
|
+
* 2026-07-15 mock). `responseMs` is the critically-damped spring response for
|
|
77
|
+
* ENTER; exit runs at `exitResponseFactor ×` (returning is lighter). Response
|
|
78
|
+
* scales `durationPerOctave` per zoom-octave beyond `baseOctaves` (Apple's
|
|
79
|
+
* duration-with-distance). Beyond `freezeOctaves` a flight cannot be presented
|
|
80
|
+
* geometrically (Chromium raster-scale swing — design-006 §5): the start depth
|
|
81
|
+
* caps at `capFactor ×` arrival and the transition presents as a crossfade.
|
|
82
|
+
*/
|
|
83
|
+
export declare const NAV_TRANSITION_DEFAULTS: {
|
|
84
|
+
readonly responseMs: 420;
|
|
85
|
+
readonly exitResponseFactor: 0.8;
|
|
86
|
+
readonly durationPerOctave: 0.12;
|
|
87
|
+
readonly baseOctaves: 3.5;
|
|
88
|
+
readonly freezeOctaves: 4.2;
|
|
89
|
+
readonly capFactor: 10;
|
|
90
|
+
readonly settleP: 0.999;
|
|
91
|
+
readonly settleV: 0.02;
|
|
92
|
+
};
|
|
48
93
|
/** Widget/FBO/port budgets (design-004 §2 host pipeline, §3 FBO pool, §6 port materialization; ported into design-005 §4 engine facade). */
|
|
49
94
|
export declare const RUNTIME_BUDGETS: {
|
|
50
95
|
readonly keepMountedWidgets: 256;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ground-layer (P0) pass configs — CANONICAL home (2026-07-16, the @ice/ground
|
|
3
|
+
* extraction): plain data shared by the ground renderer, the react facade's
|
|
4
|
+
* `grid` prop, and apps. They live in core because core is the vocabulary
|
|
5
|
+
* package every layer may import (ground cannot import react; react cannot
|
|
6
|
+
* import ground — design-002 §6). Values are verbatim from the original
|
|
7
|
+
* renderers: GridConfig from v1 GridRenderer.ts:5-35 (tuned to Apple
|
|
8
|
+
* Freeform / FigJam), wires + snap-guides from their 2026 dom reflectors.
|
|
9
|
+
*/
|
|
10
|
+
export interface GridConfig {
|
|
11
|
+
/** World-unit spacings for up to 3 grid levels [fine, medium, coarse]. */
|
|
12
|
+
spacings: [number, number, number];
|
|
13
|
+
/** Dot RGB color as [r, g, b] in 0-1 range. */
|
|
14
|
+
dotColor: [number, number, number];
|
|
15
|
+
/** Base dot opacity multiplier (0-1). */
|
|
16
|
+
dotAlpha: number;
|
|
17
|
+
/** CSS-pixel range where a grid level fades in: [start, end]. */
|
|
18
|
+
fadeIn: [number, number];
|
|
19
|
+
/** CSS-pixel range where a grid level fades out: [start, end]. */
|
|
20
|
+
fadeOut: [number, number];
|
|
21
|
+
/** Dot radius range in CSS pixels [min, max]. Scaled by DPR internally. */
|
|
22
|
+
dotRadius: [number, number];
|
|
23
|
+
/** Per-level opacity weight: level i gets (base + i * step). */
|
|
24
|
+
levelWeight: [number, number];
|
|
25
|
+
}
|
|
26
|
+
/** Verbatim from v1 GridRenderer.ts:27-35 (Apple Freeform / FigJam feel). */
|
|
27
|
+
export declare const DEFAULT_GRID_CONFIG: GridConfig;
|
|
28
|
+
/** Minimal-neutral wire styling (design-004 §6: chrome is subdued; wires defer to content). */
|
|
29
|
+
export interface WiresConfig {
|
|
30
|
+
/** Default wire stroke (CSS color). */
|
|
31
|
+
wireColor: string;
|
|
32
|
+
/** Accent stroke for a Selected wire. */
|
|
33
|
+
selectedColor: string;
|
|
34
|
+
wireWidth: number;
|
|
35
|
+
selectedWidth: number;
|
|
36
|
+
/** Materialized-port dot radius (CSS px) + colors (idle vs during a connect drag). */
|
|
37
|
+
portRadius: number;
|
|
38
|
+
portColor: string;
|
|
39
|
+
portActiveColor: string;
|
|
40
|
+
}
|
|
41
|
+
export declare const DEFAULT_WIRES_CONFIG: WiresConfig;
|
|
42
|
+
/** v1 `DEFAULT_SNAP_GUIDE_CONFIG` (SnapGuideRenderer.ts), field for field. */
|
|
43
|
+
export interface SnapGuidesConfig {
|
|
44
|
+
/** Guide line + spacing bar color as [r, g, b] in 0-1 range. */
|
|
45
|
+
color: [number, number, number];
|
|
46
|
+
/** Stroke width in screen px (constant across zoom). */
|
|
47
|
+
lineWidth: number;
|
|
48
|
+
/** Alignment-line alpha. */
|
|
49
|
+
guideAlpha: number;
|
|
50
|
+
/** Equal-spacing bar alpha. */
|
|
51
|
+
spacingAlpha: number;
|
|
52
|
+
/** End-tick half-length in screen px (v1 shader barHeight). */
|
|
53
|
+
tickPx: number;
|
|
54
|
+
}
|
|
55
|
+
export declare const DEFAULT_SNAP_GUIDES_CONFIG: SnapGuidesConfig;
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* `Selected` set: ONE selection-box entity + 8 resize-handle entities. The box
|
|
8
8
|
* entity carries ONLY the `SelectionBox` value (x,y,w,h = the union bbox); the
|
|
9
9
|
* handles carry Position + Size + `HandleSpec{anchor}` + `VisualOf → box`.
|
|
10
|
+
* Box policy (amended 2026-07-17): all-resizable selections get box + grips
|
|
11
|
+
* (v1 parity); a MULTI-selection gets the box (group bbox) even when
|
|
12
|
+
* non-resizable; a single non-resizable widget gets no engine chrome (the
|
|
13
|
+
* app owns its selection look).
|
|
10
14
|
*
|
|
11
15
|
* HANDLE PICKING (the point of the design): handles carry a world AABB, so the
|
|
12
16
|
* `react`-phase `spatialSync` indexes them automatically and `picking` resolves
|
|
@@ -43,6 +47,6 @@
|
|
|
43
47
|
* measure loop converges (§2). The stored w,h are the effective size at the
|
|
44
48
|
* tier transition (what the tier "was computed from").
|
|
45
49
|
*/
|
|
46
|
-
import type {
|
|
50
|
+
import type { TickSystem, World } from "@vibecook/strata-ecs";
|
|
47
51
|
export declare function createSelectionChromeSystem(world: World): TickSystem;
|
|
48
|
-
export declare function createBreakpointSystem(
|
|
52
|
+
export declare function createBreakpointSystem(world: World): TickSystem;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The insert-ghost reap (cleanup phase; catalog/insert.ts, 2026-07-19).
|
|
3
|
+
*
|
|
4
|
+
* Three exits for a tray-insert ghost, all owned here so nothing transient
|
|
5
|
+
* crosses frames unaccounted (design-002 §2 cleanup law):
|
|
6
|
+
*
|
|
7
|
+
* - PROMOTED (`GhostCommitted`, set by moveBehavior at the create commit):
|
|
8
|
+
* despawned ONE tick after the commit — the projected twin lands at the
|
|
9
|
+
* NEXT sync, so waiting one tick makes the swap happen inside a single
|
|
10
|
+
* reflect flush (twin mounts, ghost unmounts, same frame — no blink).
|
|
11
|
+
* Selection rides the same beat: the doc sink parked the twin ids in its
|
|
12
|
+
* out-of-ECS hand-off (`drainCreatedSelections`); they are drained on the
|
|
13
|
+
* commit tick and applied HERE one tick later, when the projection is
|
|
14
|
+
* alive — the select-on-grab the ghost held transfers to the real widget.
|
|
15
|
+
*
|
|
16
|
+
* - RETIRING (`GhostRetiring`, cancel / rejected drop): despawned when the
|
|
17
|
+
* fly-back `TransformTween` lands (camera-sim removes it on arrival).
|
|
18
|
+
*
|
|
19
|
+
* - STRANDED (no Grab, no tween, no live recognizer still capturing it): a
|
|
20
|
+
* clean click on a tray tile (the drag never formed), or an integrity
|
|
21
|
+
* cancel that raced the claim. Despawned silently — it never left the
|
|
22
|
+
* press point under the tray.
|
|
23
|
+
*/
|
|
24
|
+
import type { System, World } from "@vibecook/strata-ecs";
|
|
25
|
+
export declare function createInsertGhostReap(world: World): System;
|
|
@@ -5,13 +5,26 @@
|
|
|
5
5
|
*
|
|
6
6
|
* `spatialSync` maintains the kernel `SpatialIndex` over every Position+Size
|
|
7
7
|
* entity (widgets AND HandleSpec chrome — both carry a world AABB). It is a
|
|
8
|
-
* TICK system
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
8
|
+
* TICK system so the body runs every frame — it is the writer that bumps
|
|
9
|
+
* `SpatialVersion` — but as of strata 0.7.0 (petition 7 LANDED) the body is
|
|
10
|
+
* O(delta), not O(N): a `world.changes` collector journals exactly which
|
|
11
|
+
* entities were touched (Position/Size writes, Active/WidgetEquipped flips,
|
|
12
|
+
* spawns, destroys — same-frame, drained INSIDE the pipeline), and each is
|
|
13
|
+
* re-checked against `isIndexable` → upsert or remove. The 2026-07-13 walk
|
|
14
|
+
* machinery (last-known AABB cache, compare-and-skip, generation sweep) is
|
|
15
|
+
* RETIRED — the collector knows; the system no longer has to discover.
|
|
16
|
+
*
|
|
17
|
+
* The FULL WALK survives as exactly what petition 7 said it should be:
|
|
18
|
+
* - the SEED (a collector only journals writes made after its creation);
|
|
19
|
+
* - the `reset` route (world.reset / replace import / nav `clearCaches`);
|
|
20
|
+
* - the `coarse` fallback (some declared-raw-write system touched
|
|
21
|
+
* Position/Size rows the journal cannot attribute — rescan, never miss).
|
|
22
|
+
* Nav gating rides the walk QUERIES at archetype level: widgets match
|
|
23
|
+
* `[Position, Size, WidgetEquipped, Active]`, chrome matches
|
|
24
|
+
* `[Position, Size, Not(WidgetEquipped)]` — the union is exactly
|
|
25
|
+
* `Position+Size ∧ (¬WidgetEquipped ∨ Active)`, and `isIndexable` is the
|
|
26
|
+
* same predicate entity-wise for the delta path. Materialized ports are M8 —
|
|
27
|
+
* skipped.
|
|
15
28
|
*
|
|
16
29
|
* `picking` runs the dual pick (design-003 §3), gated by a version guard over
|
|
17
30
|
* `PointerVersion ∨ SpatialVersion`. `CameraVersion` does not exist — camera
|
|
@@ -24,10 +37,11 @@
|
|
|
24
37
|
* dead-band (hover is forgiving; hold the current target
|
|
25
38
|
* while the pointer stays within its expanded bounds).
|
|
26
39
|
* - `TouchesExact` = r=0 point pick (grab is precise; no dead-band).
|
|
27
|
-
* Pick priority is plane priority: HandleSpec chrome first, then widgets
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
40
|
+
* Pick priority is plane priority: HandleSpec chrome first, then widgets
|
|
41
|
+
* topmost by sibling order (petition 8 — the shared SiblingOrderIndex feeds
|
|
42
|
+
* pickTopAt, so pick can never diverge from paint), then the CanvasSurface
|
|
43
|
+
* entity as the guaranteed fallback (design-001 §4). Relations are written
|
|
44
|
+
* change-only (design-002 §4 hygiene). Wires/ports are M8 — skipped.
|
|
31
45
|
*/
|
|
32
46
|
import type { Entity, System, TickSystem, World } from "@vibecook/strata-ecs";
|
|
33
47
|
import { SpatialIndex } from "@ice/kernel";
|
|
@@ -13,10 +13,16 @@
|
|
|
13
13
|
* the same frame); field updates are immediate `edit().set`
|
|
14
14
|
* under declared `access.write`.
|
|
15
15
|
*
|
|
16
|
-
* All timing reads FrameInfo.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* All timing reads FrameInfo.CLOCK — the accumulated CLAMPED-dt gesture clock
|
|
17
|
+
* (2026-07-17, supersedes both raw FrameInfo.now and the 2026-07-12
|
|
18
|
+
* event-timestamp anchor): rAF `now` lags wall time by up to SECONDS under
|
|
19
|
+
* throttling/headless/software rendering while event.timeStamp does not, so
|
|
20
|
+
* any window mixing the two evaluates garbage; `clock` is monotonic, stalls
|
|
21
|
+
* contribute ≤ dtClampMs (the stall-protection intent), and no event
|
|
22
|
+
* timestamp ever enters window math. All thresholds read the GestureSettings
|
|
23
|
+
* RESOURCE (live-tunable, design-005 §4) with the GESTURE_DEFAULTS constants
|
|
24
|
+
* as the unset fallback. Gesture math is screen-space totals + zoom-at-claim
|
|
25
|
+
* — never live PointerWorld (design-002 §2 staleness rule).
|
|
20
26
|
*/
|
|
21
27
|
import type { World } from "@vibecook/strata-ecs";
|
|
22
28
|
import { type System } from "@vibecook/strata-ecs";
|
|
@@ -5,15 +5,17 @@
|
|
|
5
5
|
* ctl:claim; per frame (persistent `Active`) apply ABSOLUTE live writes from
|
|
6
6
|
* rider origins + gesture totals; on `JustEnded` emit ONE commit (through the
|
|
7
7
|
* CommitSink seam — M5 swaps in the doc transaction); on `JustCancelled`
|
|
8
|
-
* restore from riders — Position AND
|
|
9
|
-
* the
|
|
10
|
-
*
|
|
8
|
+
* restore from riders — Position AND sibling order (petition 8: a forgotten
|
|
9
|
+
* order restore leaves the sequence diverged forever, the old StackZ law);
|
|
10
|
+
* remove riders and gesture-scoped edges on every terminal path. Discrete
|
|
11
|
+
* actions edge-trigger on `Just*` markers only.
|
|
11
12
|
*
|
|
12
13
|
* Move outcome tree (design-003 §5.5, three-way via dropSystem's signals):
|
|
13
14
|
* DropTarget + OverlapCandidate on the container → CONSUME (reparent intent);
|
|
14
15
|
* DropTarget without OverlapCandidate → FLY-BACK (no commit; TransformTween
|
|
15
16
|
* rider per widget — the tween HOLDS the claim, design-001 §3 amended);
|
|
16
|
-
* no DropTarget → COMMIT (final Position
|
|
17
|
+
* no DropTarget → COMMIT (final Position per live Drags edge + the sibling
|
|
18
|
+
* placement as ORDER ops, so one gesture stays one transaction).
|
|
17
19
|
* Without dropSystem installed no DropTarget ever exists ⇒ plain commits.
|
|
18
20
|
*/
|
|
19
21
|
import type { System, World } from "@vibecook/strata-ecs";
|
|
@@ -7,9 +7,13 @@
|
|
|
7
7
|
* claim-frame `read(w, Grab)` throws (design-003 review C1).
|
|
8
8
|
*
|
|
9
9
|
* `moveClaim` (JustActive × RoutedMove): select-on-grab, `Drags` edges over the
|
|
10
|
-
* dragged set, `Grab` per widget with the CURRENT Position/Size
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* dragged set, `Grab` per widget with the CURRENT Position/Size + the ORDER
|
|
11
|
+
* MEMO embedded (petition 8: ChildOf parent, nearest non-dragged predecessor
|
|
12
|
+
* sibling, original sibling index), and the sibling elevate — `moveRelation(w,
|
|
13
|
+
* ChildOf, "last")`, frame-scoped, equivalent to the old global-top within the
|
|
14
|
+
* frame; part of the gesture divergence, restored from the memo on cancel.
|
|
15
|
+
* Edge-less widgets (legacy/runtime world) skip both memo and elevate — the
|
|
16
|
+
* move would be a strata no-op and there is no sequence to restore.
|
|
13
17
|
*
|
|
14
18
|
* `resizeClaim` (JustActive × RoutedResize): `Drags` + `Grab` over the Selected
|
|
15
19
|
* ∧ Resizable set; the anchor lives on the captured handle's `HandleSpec` — no
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* AFTER moveBehavior so it tests POST-move bounds).
|
|
4
4
|
*
|
|
5
5
|
* For Active `RoutedMove` drags: spatial-query the dragged union bounds for
|
|
6
|
-
* `Container` widgets (∉dragged), pick the topmost by
|
|
6
|
+
* `Container` widgets (∉dragged), pick the topmost by sibling order (petition
|
|
7
|
+
* 8 — compareStackOrder, the SAME comparator pick/paint use, so the drop
|
|
8
|
+
* candidate can never diverge from what the user sees on top), and publish two
|
|
7
9
|
* signals the move-outcome tree consumes (l3-behave §5.5):
|
|
8
10
|
* - `DropTarget(recognizer → container)` — set for the container under the
|
|
9
11
|
* bounds REGARDLESS of an accepts-match (so the outcome tree can distinguish
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* zoomAtClaim`, resized about the FIXED opposite edge/corner of the grabbed
|
|
8
8
|
* handle (`n`/`s` height-only, `e`/`w` width-only, corners both). Modifiers ride
|
|
9
9
|
* the watched pointer's `PointerMods`: `alt` = resize about center, `shift` =
|
|
10
|
-
* preserve aspect (corner handles). Min size clamps to
|
|
10
|
+
* preserve aspect (corner handles). Min size clamps to the target widget's
|
|
11
|
+
* `defineWidget` `minSize` (via `PrefabId`), or 1×1 for non-widget resizables.
|
|
12
|
+
* `JustEnded` emits ONE
|
|
11
13
|
* `resize` commit (Position+Size per live target); `JustCancelled`/`JustFailed`
|
|
12
14
|
* restore from `Grab`. Every terminal path removes `Grab` and the `Drags` edges
|
|
13
15
|
* (mirrors l3-behave's clearGestureState; resize has no DropTarget).
|
|
@@ -6,14 +6,32 @@
|
|
|
6
6
|
* over the dragged widgets — NEVER last-applied `Position` (one frame stale ⇒
|
|
7
7
|
* guide-chasing oscillation, design-003 §5.2 red-team; `Grab` is readable here
|
|
8
8
|
* thanks to the ctl:claim settle point, §4.5). Candidates come from the SHARED
|
|
9
|
-
* spatial index (rect query = intended bounds
|
|
10
|
-
*
|
|
9
|
+
* spatial index (rect query = intended bounds ∪ VIEWPORT, expanded by
|
|
10
|
+
* threshold — design-003 §5.2: a distant same-axis edge IN VIEW must
|
|
11
|
+
* contribute a guide, the Figma behavior; the widgetlab field check 2026-07-16
|
|
12
|
+
* caught the intended-rect-only query never seeing a card 115px above the
|
|
13
|
+
* drag). Filtered to `SnapTarget ∧ ¬Culled ∧ ∉dragged` — ¬Culled is the
|
|
14
|
+
* design's "Visible" scoping in cull-less rigs too (no cull system ⇒ nothing
|
|
15
|
+
* is Culled ⇒ all candidates pass). Threshold is
|
|
11
16
|
* `thresholdPx / zoomAtClaim` (screen-constant). The kernel `computeSnapGuides`
|
|
12
17
|
* does the Figma math; we write `SnapState{dx,dy}` on the recognizer (moveBehavior
|
|
13
|
-
* adds it to the absolute write).
|
|
14
|
-
*
|
|
15
|
-
*
|
|
18
|
+
* adds it to the absolute write). SnapState clears to 0,0 when snap is off / no
|
|
19
|
+
* source / no candidate.
|
|
20
|
+
*
|
|
21
|
+
* GUIDE CHROME (design-003 §6, as-built 2026-07-16 — the once-deferred half):
|
|
22
|
+
* the kernel result's `guides`/`spacings` become pooled runtime `GuideLine` /
|
|
23
|
+
* `SpacingBar` entities the P0 snap-guides reflector draws (design-004 §1
|
|
24
|
+
* amendment: ground stratum, under content — James's call). Pool mechanics
|
|
25
|
+
* mirror selectionChrome: a TICK system (exactly one pass per frame — spawn/
|
|
26
|
+
* destroy are not idempotent, and the pool must reap on the frame the last
|
|
27
|
+
* snapping drag ENDS, when the recognizer query is empty), `ctx.spawn` on
|
|
28
|
+
* grow, `ctx.destroy` on shrink, change-only `edit().set` in steady state
|
|
29
|
+
* (same guide held across frames ⇒ zero writes). Alignment guides write
|
|
30
|
+
* `from = to = 0` — the full-viewport sentinel (v1's full-canvas lines);
|
|
31
|
+
* spacing indicators flatten one entity per segment (v1 `u_spacings` parity).
|
|
32
|
+
* No silent caps: the pool grows to whatever the kernel returns (v1's
|
|
33
|
+
* MAX_GUIDES=16 truncation is banned).
|
|
16
34
|
*/
|
|
17
|
-
import type { Entity,
|
|
35
|
+
import type { Entity, TickSystem, World } from "@vibecook/strata-ecs";
|
|
18
36
|
import { type SpatialIndex } from "@ice/kernel";
|
|
19
|
-
export declare function createSnapSystem(world: World, index: SpatialIndex<Entity>):
|
|
37
|
+
export declare function createSnapSystem(world: World, index: SpatialIndex<Entity>): TickSystem;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nav-flight — the T1 camera-flight half of design-006 (portal zoom).
|
|
3
|
+
*
|
|
4
|
+
* CUT-FIRST, THEN FLY (§3): the nav ops perform the ECS cut synchronously
|
|
5
|
+
* (frame switch, membership resweep, index rebuild) and then hand presentation
|
|
6
|
+
* to this slice — `startNavFlight` snaps the camera to the continuity-solved
|
|
7
|
+
* start `c0` and arms the `NavTransition` resource; the `navFlight` tick
|
|
8
|
+
* system (simulate, beside cameraInertia) advances a closed-form critically-
|
|
9
|
+
* damped progress spring each frame and writes the camera along the log-zoom
|
|
10
|
+
* path until rest. The transition is PURE PRESENTATION: killing it at any
|
|
11
|
+
* moment leaves a fully consistent world in the destination frame.
|
|
12
|
+
*
|
|
13
|
+
* - `NavTransition` is a RESOURCE, not closure state (the CameraInertia
|
|
14
|
+
* pattern: devtools sees it, no hidden singleton — design-003 §9). Resources
|
|
15
|
+
* cannot be removed, so `active` is the liveness flag; `epoch` bumps on
|
|
16
|
+
* every (re)start so the T2 reflector can distinguish retarget from resume.
|
|
17
|
+
* - Camera writes are UNCLAMPED (design-006 §3.1): flight paths transit far
|
|
18
|
+
* outside the user-gesture zoom band; only the ARRIVAL camera (clamped by
|
|
19
|
+
* the nav op) bounds where the flight rests.
|
|
20
|
+
* - Gestures always win (§4): any active camera gesture — `Camera.gesturing`,
|
|
21
|
+
* stamped by cameraControl in ctl:behave, i.e. EARLIER this same frame —
|
|
22
|
+
* deactivates the flight without touching the camera.
|
|
23
|
+
* - The portal affine (`as/aox/aoy`, departed-frame → destination-frame) and
|
|
24
|
+
* `frozen` ride the resource for T2's departing-plane reflector; T1's camera
|
|
25
|
+
* math only needs c0/c1.
|
|
26
|
+
*/
|
|
27
|
+
import type { TickSystem, World } from "@vibecook/strata-ecs";
|
|
28
|
+
import type { CameraState, PortalAffine } from "@ice/kernel";
|
|
29
|
+
/** The one in-flight nav transition (design-006 §3.1). Inactive = at rest. */
|
|
30
|
+
export declare const NavTransition: import("@vibecook/strata-ecs").Resource<import("@vibecook/strata-ecs").ValueOf<{
|
|
31
|
+
readonly active: import("@vibecook/strata-ecs").FieldSpec<"bool", true>;
|
|
32
|
+
readonly kind: import("@vibecook/strata-ecs").FieldSpec<import("@vibecook/strata-ecs").EnumType<"enter" | "exit">, true>;
|
|
33
|
+
/** Progress spring state (closed-form critically damped, kernel springStep). */
|
|
34
|
+
readonly p: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
35
|
+
readonly v: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
36
|
+
/** Depth-capped flight — T2 presents it as a crossfade, not geometry (§5). */
|
|
37
|
+
readonly frozen: import("@vibecook/strata-ecs").FieldSpec<"bool", true>;
|
|
38
|
+
/** Bumps on every flight start; T2 distinguishes retarget from resume. */
|
|
39
|
+
readonly epoch: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
|
|
40
|
+
/** Response multiplier from octave distance (locked at start; §4). */
|
|
41
|
+
readonly durMul: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
42
|
+
readonly c0x: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
43
|
+
readonly c0y: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
44
|
+
readonly c0z: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
45
|
+
readonly c1x: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
46
|
+
readonly c1y: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
47
|
+
readonly c1z: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
48
|
+
/** Portal affine A: departed-frame coords → destination-frame coords (T2). */
|
|
49
|
+
readonly as: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
50
|
+
readonly aox: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
51
|
+
readonly aoy: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
52
|
+
}>, {
|
|
53
|
+
readonly active: import("@vibecook/strata-ecs").FieldSpec<"bool", true>;
|
|
54
|
+
readonly kind: import("@vibecook/strata-ecs").FieldSpec<import("@vibecook/strata-ecs").EnumType<"enter" | "exit">, true>;
|
|
55
|
+
/** Progress spring state (closed-form critically damped, kernel springStep). */
|
|
56
|
+
readonly p: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
57
|
+
readonly v: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
58
|
+
/** Depth-capped flight — T2 presents it as a crossfade, not geometry (§5). */
|
|
59
|
+
readonly frozen: import("@vibecook/strata-ecs").FieldSpec<"bool", true>;
|
|
60
|
+
/** Bumps on every flight start; T2 distinguishes retarget from resume. */
|
|
61
|
+
readonly epoch: import("@vibecook/strata-ecs").FieldSpec<"u32", true>;
|
|
62
|
+
/** Response multiplier from octave distance (locked at start; §4). */
|
|
63
|
+
readonly durMul: import("@vibecook/strata-ecs").FieldSpec<"f32", true>;
|
|
64
|
+
readonly c0x: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
65
|
+
readonly c0y: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
66
|
+
readonly c0z: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
67
|
+
readonly c1x: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
68
|
+
readonly c1y: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
69
|
+
readonly c1z: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
70
|
+
/** Portal affine A: departed-frame coords → destination-frame coords (T2). */
|
|
71
|
+
readonly as: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
72
|
+
readonly aox: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
73
|
+
readonly aoy: import("@vibecook/strata-ecs").FieldSpec<"f64", true>;
|
|
74
|
+
}>;
|
|
75
|
+
/**
|
|
76
|
+
* Arm a flight from the already-cut world: continuity-solve was done by the
|
|
77
|
+
* caller (`exact` = c0 in destination-frame coords), the arrival `c1` is
|
|
78
|
+
* already clamped. Applies the depth cap (§5), snaps the camera to c0, and
|
|
79
|
+
* activates the resource. Callers guarantee a live Viewport — headless/no-
|
|
80
|
+
* viewport paths snap to the arrival instead and never reach here.
|
|
81
|
+
*/
|
|
82
|
+
export declare function startNavFlight(world: World, kind: "enter" | "exit", A: PortalAffine, exact: CameraState, c1: CameraState): void;
|
|
83
|
+
/** Deactivate without touching the camera (integrity pops, gesture yields). */
|
|
84
|
+
export declare function abortNavFlight(world: World): void;
|
|
85
|
+
/**
|
|
86
|
+
* Is a nav flight driving the camera right now? THE gate for flight-time
|
|
87
|
+
* GPU/paint duty (design-006 §8.2, answered by field testing 2026-07-16):
|
|
88
|
+
* heavy-motion consumers treat `Camera.gesturing ∨ navFlightActive` as one
|
|
89
|
+
* "camera in transient motion" signal — composite DPR drop, band-repaint
|
|
90
|
+
* suppression, Hot-island freeze, breakpoint retier deferral. `gesturing`
|
|
91
|
+
* itself stays a pure user-gesture fact (the inertia precedent): flights
|
|
92
|
+
* never stamp it, consumers OR the two.
|
|
93
|
+
*/
|
|
94
|
+
export declare function navFlightActive(world: World): boolean;
|
|
95
|
+
export declare function createNavFlight(world: World): TickSystem;
|
|
@@ -20,6 +20,12 @@ export interface WidgetInteraction {
|
|
|
20
20
|
readonly solid?: boolean;
|
|
21
21
|
/** "longPress": hold-to-lift dragging (iOS home-screen model); default "press". */
|
|
22
22
|
readonly dragOn?: "press" | "longPress";
|
|
23
|
+
/**
|
|
24
|
+
* UE-Blueprint comment-box drag (2026-07-18): a move claim on this widget
|
|
25
|
+
* also claims every widget FULLY INSIDE its bounds at claim time (spatial
|
|
26
|
+
* membership — never reparenting). Default false.
|
|
27
|
+
*/
|
|
28
|
+
readonly sweepContained?: boolean;
|
|
23
29
|
}
|
|
24
30
|
export interface WidgetDef {
|
|
25
31
|
readonly type: string;
|
|
@@ -34,6 +40,16 @@ export interface WidgetDef {
|
|
|
34
40
|
readonly surface: WidgetSurface;
|
|
35
41
|
/** Framework component (opaque to core — the react package narrows it). */
|
|
36
42
|
readonly component: unknown;
|
|
43
|
+
/**
|
|
44
|
+
* GL only: a DOM chrome component portaled into the widget's CONTENT-plane
|
|
45
|
+
* host (P1), which stacks UNDER the GL canvas (P2) — v1's proven
|
|
46
|
+
* CardChrome-beneath-the-canvas sandwich. The island renders ONLY the 3D
|
|
47
|
+
* content; the card body (gradient, radius, ring, shadow, lift spring,
|
|
48
|
+
* hover/overlap glow) is DOM and shares the app's CSS with DOM widgets.
|
|
49
|
+
* Opaque to core — the react package narrows it. Ignored for dom-surface
|
|
50
|
+
* widgets (their component IS the chrome).
|
|
51
|
+
*/
|
|
52
|
+
readonly chrome?: unknown;
|
|
37
53
|
readonly sizeMode?: SizeMode;
|
|
38
54
|
readonly defaultSize?: {
|
|
39
55
|
readonly w: number;
|
|
@@ -57,6 +73,23 @@ export interface WidgetDef {
|
|
|
57
73
|
* the compatibility key list the connect gesture checks.
|
|
58
74
|
*/
|
|
59
75
|
readonly ports?: readonly WidgetPortDecl[];
|
|
76
|
+
/**
|
|
77
|
+
* Palette/tray preview (design-005 §2 amendment, 2026-07-19). ENGINE-FREE
|
|
78
|
+
* BY CONTRACT: a preview renders with no world, no entity, no ops — a pure
|
|
79
|
+
* picture the host mounts inert (that is what makes it portable: trays,
|
|
80
|
+
* docs sites, a widget store). Authored at `defaultSize`; hosts scale.
|
|
81
|
+
* Three tiers, least effort first:
|
|
82
|
+
* - absent → the REAL component mounts with default props in
|
|
83
|
+
* the framework's preview sandbox (dom surfaces;
|
|
84
|
+
* truthful by construction);
|
|
85
|
+
* - `{ props: {…} }` → same sandbox mount with curated props;
|
|
86
|
+
* - a component, or `{ component }` → author-owned preview (a static
|
|
87
|
+
* mockup, a live self-ticking clock — the author's call). In P1 all
|
|
88
|
+
* declared previews are DOM components — the sanctioned escape hatch
|
|
89
|
+
* for GL widgets too (P2 adds the r3f snapshot pipeline).
|
|
90
|
+
* Opaque to core — the react package narrows it (`component` precedent).
|
|
91
|
+
*/
|
|
92
|
+
readonly preview?: unknown;
|
|
60
93
|
readonly container?: {
|
|
61
94
|
readonly accepts: readonly string[];
|
|
62
95
|
readonly provides?: readonly string[];
|
|
@@ -96,6 +129,8 @@ export interface WidgetType {
|
|
|
96
129
|
readonly propToGroup: Readonly<Record<string, string>>;
|
|
97
130
|
readonly surface: WidgetSurface;
|
|
98
131
|
readonly component: unknown;
|
|
132
|
+
/** GL widgets: DOM chrome under the canvas (see WidgetDef.chrome). */
|
|
133
|
+
readonly chrome: unknown;
|
|
99
134
|
readonly sizeMode: SizeMode;
|
|
100
135
|
readonly defaultSize: {
|
|
101
136
|
readonly w: number;
|
|
@@ -112,6 +147,10 @@ export interface WidgetType {
|
|
|
112
147
|
/** Runtime capability tags the equip system stamps at projection. */
|
|
113
148
|
readonly capabilityTags: readonly Tag[];
|
|
114
149
|
readonly migrate: Readonly<Record<number, (prev: Record<string, unknown>) => Record<string, unknown>>>;
|
|
150
|
+
/** Normalized author preview component (opaque; react narrows). null = none declared. */
|
|
151
|
+
readonly previewComponent: unknown;
|
|
152
|
+
/** Prop overrides for the default real-component preview mount (validated names). */
|
|
153
|
+
readonly previewProps?: Readonly<Record<string, unknown>>;
|
|
115
154
|
}
|
|
116
155
|
/** Stamped by the equip system once a projected widget carries its capability tags. */
|
|
117
156
|
export declare const WidgetEquipped: Tag;
|