@vscada/core 0.0.1
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/dist/.tsbuildinfo +1 -0
- package/dist/a11y/contrast.d.ts +11 -0
- package/dist/a11y/contrast.d.ts.map +1 -0
- package/dist/a11y/live-region.d.ts +42 -0
- package/dist/a11y/live-region.d.ts.map +1 -0
- package/dist/a11y/reduced-motion.d.ts +55 -0
- package/dist/a11y/reduced-motion.d.ts.map +1 -0
- package/dist/a11y/static-representation-registry.d.ts +20 -0
- package/dist/a11y/static-representation-registry.d.ts.map +1 -0
- package/dist/bindings/binding-fixture.d.ts +3 -0
- package/dist/bindings/binding-fixture.d.ts.map +1 -0
- package/dist/bindings/binding-types.d.ts +52 -0
- package/dist/bindings/binding-types.d.ts.map +1 -0
- package/dist/bindings/color-ramp.d.ts +9 -0
- package/dist/bindings/color-ramp.d.ts.map +1 -0
- package/dist/bindings/transforms.d.ts +103 -0
- package/dist/bindings/transforms.d.ts.map +1 -0
- package/dist/constants-DMdpoOyH.js +4 -0
- package/dist/contracts/connection-renderer.d.ts +16 -0
- package/dist/contracts/connection-renderer.d.ts.map +1 -0
- package/dist/contracts/connection-state.d.ts +8 -0
- package/dist/contracts/connection-state.d.ts.map +1 -0
- package/dist/contracts/handles.d.ts +83 -0
- package/dist/contracts/handles.d.ts.map +1 -0
- package/dist/contracts/primitive.d.ts +37 -0
- package/dist/contracts/primitive.d.ts.map +1 -0
- package/dist/contracts/renderer.d.ts +34 -0
- package/dist/contracts/renderer.d.ts.map +1 -0
- package/dist/contracts/tag-value.d.ts +33 -0
- package/dist/contracts/tag-value.d.ts.map +1 -0
- package/dist/contracts/time-source.d.ts +14 -0
- package/dist/contracts/time-source.d.ts.map +1 -0
- package/dist/custom-elements.json +1068 -0
- package/dist/export/svg-export.d.ts +24 -0
- package/dist/export/svg-export.d.ts.map +1 -0
- package/dist/fsm/fsm.d.ts +45 -0
- package/dist/fsm/fsm.d.ts.map +1 -0
- package/dist/fsm/tween.d.ts +39 -0
- package/dist/fsm/tween.d.ts.map +1 -0
- package/dist/import/load-svg-import.d.ts +22 -0
- package/dist/import/load-svg-import.d.ts.map +1 -0
- package/dist/import/svg-source-registry.d.ts +4 -0
- package/dist/import/svg-source-registry.d.ts.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4549 -0
- package/dist/interaction/gesture-arbiter.d.ts +20 -0
- package/dist/interaction/gesture-arbiter.d.ts.map +1 -0
- package/dist/interaction/hit-area.d.ts +44 -0
- package/dist/interaction/hit-area.d.ts.map +1 -0
- package/dist/interaction/pan-zoom-gestures.d.ts +43 -0
- package/dist/interaction/pan-zoom-gestures.d.ts.map +1 -0
- package/dist/interaction/pointer-pipeline.d.ts +38 -0
- package/dist/interaction/pointer-pipeline.d.ts.map +1 -0
- package/dist/license/console-notice.d.ts +15 -0
- package/dist/license/console-notice.d.ts.map +1 -0
- package/dist/license/format.d.ts +29 -0
- package/dist/license/format.d.ts.map +1 -0
- package/dist/license/state.d.ts +43 -0
- package/dist/license/state.d.ts.map +1 -0
- package/dist/license/vendor-keys.d.ts +12 -0
- package/dist/license/vendor-keys.d.ts.map +1 -0
- package/dist/license/verify-fallback.d.ts +31 -0
- package/dist/license/verify-fallback.d.ts.map +1 -0
- package/dist/license/verify-webcrypto.d.ts +4 -0
- package/dist/license/verify-webcrypto.d.ts.map +1 -0
- package/dist/license/watermark.d.ts +20 -0
- package/dist/license/watermark.d.ts.map +1 -0
- package/dist/media/registry.d.ts +97 -0
- package/dist/media/registry.d.ts.map +1 -0
- package/dist/registry/connection-registry.d.ts +5 -0
- package/dist/registry/connection-registry.d.ts.map +1 -0
- package/dist/registry/element-catalog.d.ts +805 -0
- package/dist/registry/element-catalog.d.ts.map +1 -0
- package/dist/registry/primitive-registry.d.ts +7 -0
- package/dist/registry/primitive-registry.d.ts.map +1 -0
- package/dist/registry/theme-registry.d.ts +6 -0
- package/dist/registry/theme-registry.d.ts.map +1 -0
- package/dist/registry.d.ts +8 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/scada-view.d.ts +322 -0
- package/dist/scada-view.d.ts.map +1 -0
- package/dist/scene/connection-geometry.d.ts +95 -0
- package/dist/scene/connection-geometry.d.ts.map +1 -0
- package/dist/scene/constants.d.ts +10 -0
- package/dist/scene/constants.d.ts.map +1 -0
- package/dist/scene/crossing-jumps.d.ts +85 -0
- package/dist/scene/crossing-jumps.d.ts.map +1 -0
- package/dist/scene/dev-validate.d.ts +24 -0
- package/dist/scene/dev-validate.d.ts.map +1 -0
- package/dist/scene/errors.d.ts +15 -0
- package/dist/scene/errors.d.ts.map +1 -0
- package/dist/scene/groups.d.ts +90 -0
- package/dist/scene/groups.d.ts.map +1 -0
- package/dist/scene/lane-offset.d.ts +69 -0
- package/dist/scene/lane-offset.d.ts.map +1 -0
- package/dist/scene/orthogonal-router.d.ts +63 -0
- package/dist/scene/orthogonal-router.d.ts.map +1 -0
- package/dist/scene/scene-schema.d.ts +881 -0
- package/dist/scene/scene-schema.d.ts.map +1 -0
- package/dist/scene/structural-validator.d.ts +25 -0
- package/dist/scene/structural-validator.d.ts.map +1 -0
- package/dist/scene/validate-scene.d.ts +26 -0
- package/dist/scene/validate-scene.d.ts.map +1 -0
- package/dist/scene-authoring.d.ts +12 -0
- package/dist/scene-authoring.d.ts.map +1 -0
- package/dist/scene-authoring.js +952 -0
- package/dist/scheduler/alarm-band.d.ts +33 -0
- package/dist/scheduler/alarm-band.d.ts.map +1 -0
- package/dist/scheduler/animation-registry.d.ts +38 -0
- package/dist/scheduler/animation-registry.d.ts.map +1 -0
- package/dist/scheduler/lod.d.ts +25 -0
- package/dist/scheduler/lod.d.ts.map +1 -0
- package/dist/scheduler/quality-overlay.d.ts +19 -0
- package/dist/scheduler/quality-overlay.d.ts.map +1 -0
- package/dist/scheduler/quality.d.ts +15 -0
- package/dist/scheduler/quality.d.ts.map +1 -0
- package/dist/scheduler/scheduler.d.ts +243 -0
- package/dist/scheduler/scheduler.d.ts.map +1 -0
- package/dist/scheduler/visual-state-resolver.d.ts +31 -0
- package/dist/scheduler/visual-state-resolver.d.ts.map +1 -0
- package/dist/store/value-store.d.ts +65 -0
- package/dist/store/value-store.d.ts.map +1 -0
- package/dist/tokens.d.ts +703 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/topology/graph.d.ts +33 -0
- package/dist/topology/graph.d.ts.map +1 -0
- package/dist/topology/group-collapse.d.ts +15 -0
- package/dist/topology/group-collapse.d.ts.map +1 -0
- package/dist/topology/inference.d.ts +71 -0
- package/dist/topology/inference.d.ts.map +1 -0
- package/dist/topology/traversal.d.ts +29 -0
- package/dist/topology/traversal.d.ts.map +1 -0
- package/dist/topology/upstream-highlight.d.ts +75 -0
- package/dist/topology/upstream-highlight.d.ts.map +1 -0
- package/dist/units/formatter.d.ts +22 -0
- package/dist/units/formatter.d.ts.map +1 -0
- package/dist/units/registry.d.ts +21 -0
- package/dist/units/registry.d.ts.map +1 -0
- package/dist/view/group-view-state.d.ts +77 -0
- package/dist/view/group-view-state.d.ts.map +1 -0
- package/dist/view/viewport-state.d.ts +112 -0
- package/dist/view/viewport-state.d.ts.map +1 -0
- package/dist/vscada.umd.cjs +45 -0
- package/package.json +37 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type Gesture = 'tap' | 'drag';
|
|
2
|
+
/** CSS px slop — a pointerup within this distance of its pointerdown counts as a tap, not a drag (§D5). */
|
|
3
|
+
export declare const TAP_SLOP_PX = 10;
|
|
4
|
+
/**
|
|
5
|
+
* Story 4.2 Task 2 — the shared single-pointer tap/drag classifier. This
|
|
6
|
+
* is the "shared gesture arbiter" Story 4.3's pan/pinch handling plugs
|
|
7
|
+
* into alongside (multi-pointer pinch detection is explicitly out of this
|
|
8
|
+
* story's scope, per Dev Notes — see the story file). Per-pointer state is
|
|
9
|
+
* tracked by `pointerId` so concurrent pointers (e.g. a two-finger pinch
|
|
10
|
+
* starting) don't interfere with each other's classification.
|
|
11
|
+
*/
|
|
12
|
+
export interface GestureArbiter {
|
|
13
|
+
onPointerDown(pointerId: number, x: number, y: number): void;
|
|
14
|
+
/** 'tap' if the pointer never moved past the slop threshold since its pointerdown, 'drag' otherwise (including an untracked pointerId — e.g. one already discarded by `onPointerCancel`). */
|
|
15
|
+
onPointerUp(pointerId: number, x: number, y: number): Gesture;
|
|
16
|
+
/** Discards tracking for a pointer without classifying it (pointercancel — a resolved gesture must never look like a tap). */
|
|
17
|
+
onPointerCancel(pointerId: number): void;
|
|
18
|
+
}
|
|
19
|
+
export declare function createGestureArbiter(slopPx?: number): GestureArbiter;
|
|
20
|
+
//# sourceMappingURL=gesture-arbiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture-arbiter.d.ts","sourceRoot":"","sources":["../../src/interaction/gesture-arbiter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAErC,2GAA2G;AAC3G,eAAO,MAAM,WAAW,KAAK,CAAC;AAO9B;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,6LAA6L;IAC7L,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9D,8HAA8H;IAC9H,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,MAAoB,GAAG,cAAc,CAiBjF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Minimum tappable target, CSS px (§D5, NFR6 — iPad-size touch). */
|
|
2
|
+
export declare const MIN_HIT_AREA_CSS_PX = 44;
|
|
3
|
+
export interface HitAreaBox {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
w: number;
|
|
7
|
+
h: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Scale-aware hit-area geometry (Story 4.2 Task 1). `zoom` is the
|
|
11
|
+
* scene-units-to-CSS-px multiplier (`ScadaView.zoom`, default 1 — Story
|
|
12
|
+
* 4.3 wires pinch gestures to it; this story only consumes it). The
|
|
13
|
+
* physical 44px floor is converted to SCENE units by dividing by zoom, so
|
|
14
|
+
* the rendered hit rect always covers at least `minCssPx` of screen space
|
|
15
|
+
* regardless of how far the view is zoomed. Centered over the symbol's
|
|
16
|
+
* own local (0,0-origin) w×h bounding box — a symbol already at/above the
|
|
17
|
+
* floor is left untouched (never shrunk).
|
|
18
|
+
*/
|
|
19
|
+
export declare function computeHitAreaBox(symbolW: number, symbolH: number, zoom: number, minCssPx?: number): HitAreaBox;
|
|
20
|
+
/**
|
|
21
|
+
* Invisible rect catching taps (AC1). `fill="transparent"` (not `none` —
|
|
22
|
+
* a `fill:none` rect has an empty hit-test region despite
|
|
23
|
+
* `pointer-events:all`). `ScadaView.interactive` gates whether a click
|
|
24
|
+
* ever gets DISPATCHED (see `pointer-pipeline.ts`), not whether this rect
|
|
25
|
+
* exists — it is always built as part of structure (AD-2).
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildHitArea(symbolW: number, symbolH: number, zoom: number, origin?: {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
}): SVGRectElement;
|
|
31
|
+
/**
|
|
32
|
+
* Story 4.3 Task 1 — recomputes an ALREADY-BUILT hit rect's box for a NEW
|
|
33
|
+
* zoom, in place (four attribute writes, no rebuild). This is the "hit
|
|
34
|
+
* areas recompute per 4.2, that's all" half of the Dev Notes' zoom design
|
|
35
|
+
* decision: the root viewport `<g>` transform (`ScadaView`'s own doc)
|
|
36
|
+
* handles the visual scale of everything else; only the hit-area's
|
|
37
|
+
* SCENE-UNIT size needs to keep tracking zoom to hold its physical
|
|
38
|
+
* on-screen floor constant, since it lives inside that SAME scaled group.
|
|
39
|
+
*/
|
|
40
|
+
export declare function updateHitAreaBox(rect: SVGRectElement, symbolW: number, symbolH: number, zoom: number, origin?: {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
}): void;
|
|
44
|
+
//# sourceMappingURL=hit-area.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hit-area.d.ts","sourceRoot":"","sources":["../../src/interaction/hit-area.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAA4B,GAAG,UAAU,CAUpI;AAID;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAmB,GAAG,cAAc,CAoB9I;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAmB,GAChD,IAAI,CAMN"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multiplicative zoom-per-wheel-delta-px — a documented default, not
|
|
3
|
+
* spec-pinned (same convention as `wave-layer.ts`'s `BASE_WAVE_DURATION_MS`):
|
|
4
|
+
* `factor = exp(-deltaY * sensitivity)` gives a smooth, runaway-free
|
|
5
|
+
* multiplicative zoom from the browser's native wheel `deltaY` (positive =
|
|
6
|
+
* scroll away from the user = zoom out, matching the platform default).
|
|
7
|
+
*/
|
|
8
|
+
export declare const WHEEL_ZOOM_SENSITIVITY = 0.0015;
|
|
9
|
+
export interface PanZoomCallbacks {
|
|
10
|
+
/** Pans the viewport by a screen-px delta (drag-pan / pinch-pan). */
|
|
11
|
+
onPan(dx: number, dy: number): void;
|
|
12
|
+
/** Zooms to an ABSOLUTE target while keeping `(centerX, centerY)` stationary (pinch centroid / wheel cursor position). */
|
|
13
|
+
onZoomAboutPoint(target: number, centerX: number, centerY: number): void;
|
|
14
|
+
/** Current zoom — read fresh on every pinch/wheel step so the gesture composes correctly with an externally-driven `.zoom = x` animation running concurrently. */
|
|
15
|
+
getZoom(): number;
|
|
16
|
+
}
|
|
17
|
+
export interface PanZoomGestureController {
|
|
18
|
+
onPointerDown(pointerId: number, x: number, y: number): void;
|
|
19
|
+
onPointerMove(pointerId: number, x: number, y: number): void;
|
|
20
|
+
onPointerUp(pointerId: number): void;
|
|
21
|
+
onPointerCancel(pointerId: number): void;
|
|
22
|
+
onWheel(deltaY: number, x: number, y: number): void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Story 4.3 Task 1 — pinch (two-pointer) + drag-pan (single-pointer, past
|
|
26
|
+
* the SAME slop `GestureArbiter` uses) + wheel-zoom, all driving
|
|
27
|
+
* `ViewportStateController` via the callbacks above. Deliberately its OWN
|
|
28
|
+
* per-pointer tracking, separate from `GestureArbiter` (whose job stays
|
|
29
|
+
* tap-vs-drag classification for `element-click`, per pointer, at
|
|
30
|
+
* pointerup) — "tap yields to gestures" falls out for free: any pointer
|
|
31
|
+
* this controller pans has, by construction, moved past the identical
|
|
32
|
+
* slop threshold, so `GestureArbiter`'s own independent distance check on
|
|
33
|
+
* that same pointerup already classifies it 'drag', never 'tap'. No
|
|
34
|
+
* coupling between the two is needed.
|
|
35
|
+
*
|
|
36
|
+
* Attach this controller's callbacks to pointer events on the SVG ROOT
|
|
37
|
+
* (not per-element) — Pointer Events bubble, so it observes every pointer
|
|
38
|
+
* including ones that started over an element's hit area; this component
|
|
39
|
+
* has no drag-to-reposition affordance, so any drag anywhere pans the
|
|
40
|
+
* camera.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createPanZoomGestures(callbacks: PanZoomCallbacks, slopPx?: number): PanZoomGestureController;
|
|
43
|
+
//# sourceMappingURL=pan-zoom-gestures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pan-zoom-gestures.d.ts","sourceRoot":"","sources":["../../src/interaction/pan-zoom-gestures.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,0HAA0H;IAC1H,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACzE,kKAAkK;IAClK,OAAO,IAAI,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrD;AAkBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,GAAE,MAAoB,GAAG,wBAAwB,CA4EzH"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { GestureArbiter } from './gesture-arbiter';
|
|
2
|
+
export interface ElementClickDetail {
|
|
3
|
+
elementId: string;
|
|
4
|
+
tags: string[];
|
|
5
|
+
elementType: string;
|
|
6
|
+
}
|
|
7
|
+
/** `element-hover` event detail (§3.4) — fine-pointer-only, see `ScadaView._dispatchElementHover`. */
|
|
8
|
+
export interface ElementHoverDetail {
|
|
9
|
+
elementId: string;
|
|
10
|
+
tags: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface ElementInteractionOptions {
|
|
13
|
+
elementId: string;
|
|
14
|
+
elementType: string;
|
|
15
|
+
/** The element's bound tag names (Task 2 — `element-click`'s `tags` field). */
|
|
16
|
+
tags: string[];
|
|
17
|
+
/** Shared across every attached element on one `<scada-view>` instance (persists across rebuilds so a drag begun before a rebuild still resolves correctly). */
|
|
18
|
+
arbiter: GestureArbiter;
|
|
19
|
+
/** Re-checked on every pointerup — `ScadaView.interactive`'s "cheap global toggle" (AC3), no rebuild needed to flip it. */
|
|
20
|
+
isInteractive(): boolean;
|
|
21
|
+
onClick(detail: ElementClickDetail): void;
|
|
22
|
+
/** Omit for targets with no hover behavior (e.g. this story doesn't require hover on plain elements — connections/groups may choose not to pass this). */
|
|
23
|
+
onHoverChange?(hovering: boolean): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Story 4.2 Task 2 — one Pointer Events pipeline, no separate touch/mouse
|
|
27
|
+
* handlers (the story's own design decision: forking is how tap/hover bugs
|
|
28
|
+
* breed). A tap is a pointerdown+pointerup pair the shared `arbiter`
|
|
29
|
+
* classifies as within slop; a pan/pinch gesture (Story 4.3) fails that
|
|
30
|
+
* check for free since it reuses the same arbiter instance, so it never
|
|
31
|
+
* produces a spurious click. `element-hover` is gated to
|
|
32
|
+
* `pointerType === 'mouse'` — the identical fine-pointer gate Story 2.4's
|
|
33
|
+
* upstream highlight already applies (`isFinePointerHover` in
|
|
34
|
+
* `topology/upstream-highlight.ts`), so touch never triggers hover-only
|
|
35
|
+
* behavior (AC2).
|
|
36
|
+
*/
|
|
37
|
+
export declare function attachElementInteraction(target: Element, options: ElementInteractionOptions): void;
|
|
38
|
+
//# sourceMappingURL=pointer-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-pipeline.d.ts","sourceRoot":"","sources":["../../src/interaction/pointer-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,sGAAsG;AACtG,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,gKAAgK;IAChK,OAAO,EAAE,cAAc,CAAC;IACxB,2HAA2H;IAC3H,aAAa,IAAI,OAAO,CAAC;IACzB,OAAO,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC1C,0JAA0J;IAC1J,aAAa,CAAC,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CACzC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,yBAAyB,GAAG,IAAI,CAwClG"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story 6.3 Task 3 — the SOLE production console output permitted
|
|
3
|
+
* anywhere in this library. Fires at most once per page load, not once
|
|
4
|
+
* per `<scada-view>` instance.
|
|
5
|
+
*
|
|
6
|
+
* AC1's literal wording is "one console notice per instance"; this
|
|
7
|
+
* deliberately deviates. N instances on a multi-view dashboard each
|
|
8
|
+
* logging their own copy is noise, not a notice — six identical lines is
|
|
9
|
+
* worse UX than one. Decision (recorded per Dev Notes' instruction):
|
|
10
|
+
* once per page, mentioning the affected instance count when >1.
|
|
11
|
+
*/
|
|
12
|
+
export declare function maybeLogUnlicensedNotice(instanceCount: number): void;
|
|
13
|
+
/** Test-only: resets the once-flag between test files. */
|
|
14
|
+
export declare function __resetConsoleNoticeForTests(): void;
|
|
15
|
+
//# sourceMappingURL=console-notice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-notice.d.ts","sourceRoot":"","sources":["../../src/license/console-notice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAQpE;AAED,0DAA0D;AAC1D,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirrors `tools/license-cli/KEY-FORMAT.md` (Story 6.1) — core only ever
|
|
3
|
+
* VERIFIES license keys, never issues them, so only the parse half of
|
|
4
|
+
* that contract lives here. Deliberately duplicated rather than imported:
|
|
5
|
+
* AD-10 forbids any `packages/*` → `tools/*` dependency (vendor tooling
|
|
6
|
+
* must never ship in a customer bundle). Keep both sides in sync by hand
|
|
7
|
+
* on a format-version bump; the committed fixtures in
|
|
8
|
+
* `tools/license-cli/fixtures/` are the cross-check that they still agree.
|
|
9
|
+
*/
|
|
10
|
+
export interface LicensePayload {
|
|
11
|
+
company: string;
|
|
12
|
+
/** ISO calendar date, `YYYY-MM-DD`. */
|
|
13
|
+
expiry: string;
|
|
14
|
+
tier: string;
|
|
15
|
+
keyId: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ParsedLicenseKey {
|
|
18
|
+
version: string;
|
|
19
|
+
encodedPayload: string;
|
|
20
|
+
payload: LicensePayload;
|
|
21
|
+
signature: Uint8Array<ArrayBuffer>;
|
|
22
|
+
}
|
|
23
|
+
/** Web-standard `atob`/`TextEncoder`/`TextDecoder` only — this runs in the browser, unlike 6.1's Node-side CLI. */
|
|
24
|
+
export declare function base64UrlToBytes(text: string): Uint8Array<ArrayBuffer> | null;
|
|
25
|
+
/** Returns `null` on any malformed input rather than throwing — a bad key is never a code path into an error, only ever an "unlicensed" verdict. */
|
|
26
|
+
export declare function parseLicenseKey(key: string): ParsedLicenseKey | null;
|
|
27
|
+
/** The exact byte sequence that was signed — see KEY-FORMAT.md. */
|
|
28
|
+
export declare function licenseSigningMessage(version: string, encodedPayload: string): Uint8Array<ArrayBuffer>;
|
|
29
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/license/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;CACpC;AAID,mHAAmH;AACnH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,CAW7E;AAaD,oJAAoJ;AACpJ,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAoBpE;AAED,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAEtG"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type LicensePayload } from './format';
|
|
2
|
+
export type LicenseStatus = 'unlicensed' | 'pending' | 'licensed';
|
|
3
|
+
export interface LicenseVerdict {
|
|
4
|
+
status: LicenseStatus;
|
|
5
|
+
payload?: LicensePayload;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Pure resolution logic — fully testable against 6.1's committed fixtures
|
|
9
|
+
* without touching module-level state. `setLicenseKey` below is the thin,
|
|
10
|
+
* stateful, cached wrapper real consumers call.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveLicenseVerdict(key: string, publicKeys: Record<string, JsonWebKey>, now: number, buildReleaseDate: string): Promise<LicenseVerdict>;
|
|
13
|
+
export declare function registerScadaViewInstance(): void;
|
|
14
|
+
export declare function unregisterScadaViewInstance(): void;
|
|
15
|
+
export declare function getConnectedInstanceCount(): number;
|
|
16
|
+
/**
|
|
17
|
+
* Module-level `setLicenseKey()` (AC1/Design Decisions) — one call
|
|
18
|
+
* licenses every `<scada-view>` instance on the page, matching
|
|
19
|
+
* per-company (not per-view) licensing. Verification is async and never
|
|
20
|
+
* blocks or throws into a render path (Design Decisions: "verification
|
|
21
|
+
* is advisory to rendering, authoritative to watermark" — 6.3 owns what a
|
|
22
|
+
* `pending`/`unlicensed` verdict does visually; this module only produces
|
|
23
|
+
* the verdict and caches it per key string).
|
|
24
|
+
*
|
|
25
|
+
* AD-4 note (architecture-code-audit-2026-08-27): the call below reads
|
|
26
|
+
* outside the injected `TimeSource` — already reviewed and allow-listed
|
|
27
|
+
* by `core/test/no-date-now.test.ts` (see that file's own rationale: a
|
|
28
|
+
* calendar-date expiry comparison needs real wall-clock time, and
|
|
29
|
+
* `TimeSource.now()`'s relative/replayable tick is the wrong unit and
|
|
30
|
+
* would let playback mode fool license expiry). This module-level
|
|
31
|
+
* function also has no single natural `TimeSource` to inject regardless
|
|
32
|
+
* (page-global state, zero-to-many `<scada-view>` instances). Testability
|
|
33
|
+
* doesn't depend on it either: `resolveLicenseVerdict` just below already
|
|
34
|
+
* takes `now` as an explicit parameter, which is what `license.test.ts`'s
|
|
35
|
+
* expiry-matrix tests call directly, bypassing this wrapper.
|
|
36
|
+
*/
|
|
37
|
+
export declare function setLicenseKey(key: string): void;
|
|
38
|
+
export declare function getLicenseVerdict(): LicenseVerdict;
|
|
39
|
+
/** Returns an unsubscribe function; fires immediately with the current verdict on subscribe (6.3's watermark consumes this). */
|
|
40
|
+
export declare function onLicenseVerdict(listener: (verdict: LicenseVerdict) => void): () => void;
|
|
41
|
+
/** Test-only: clears module-level license state between test files. */
|
|
42
|
+
export declare function __resetLicenseStateForTests(): void;
|
|
43
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/license/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,cAAc,EAAmB,MAAM,UAAU,CAAC;AAcvF,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAsBD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACtC,GAAG,EAAE,MAAM,EACX,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,CAAC,CAkBzB;AAgBD,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAOD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAe/C;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAElD;AAED,gIAAgI;AAChI,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI,CAIxF;AAED,uEAAuE;AACvE,wBAAgB,2BAA2B,IAAI,IAAI,CAMlD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* keyId → public JWK, embedded in core at build time by hand-editing this
|
|
3
|
+
* file. Empty until the vendor generates its first production keypair
|
|
4
|
+
* (`tools/license-cli` `keygen`) — see `tools/license-cli/RUNBOOK.md`'s
|
|
5
|
+
* rotation procedure, step 3, which is exactly this file. An empty map
|
|
6
|
+
* means every key is `UNKNOWN_KEY_ID` (safe default: nothing verifies
|
|
7
|
+
* until a real vendor keypair is deliberately embedded here).
|
|
8
|
+
*
|
|
9
|
+
* Never put a private key anywhere near this file or this package.
|
|
10
|
+
*/
|
|
11
|
+
export declare const VENDOR_PUBLIC_KEYS: Record<string, JsonWebKey>;
|
|
12
|
+
//# sourceMappingURL=vendor-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vendor-keys.d.ts","sourceRoot":"","sources":["../../src/license/vendor-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAM,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback verifier (AC1, AD-9) — used when `crypto.subtle` is absent
|
|
3
|
+
* (insecure contexts are normal on intranet HMIs). `@noble/curves` v2.2.0,
|
|
4
|
+
* MIT, audited (Trail of Bits/Kudelski/Cure53 across its history, no open
|
|
5
|
+
* advisories as of this story — checked on the web at implementation
|
|
6
|
+
* time per the Dev Notes instruction; see Dev Agent Record). Chosen over
|
|
7
|
+
* a hand-rolled P-256 verifier: raw elliptic-curve point arithmetic is
|
|
8
|
+
* exactly the kind of code where a subtle bug is a silent security hole,
|
|
9
|
+
* not a visible bug — an audited library is the correct trade for ~a few
|
|
10
|
+
* KB of bundle size.
|
|
11
|
+
*
|
|
12
|
+
* `p256.verify(signature, message, publicKey)` hashes `message` with
|
|
13
|
+
* SHA-256 internally by default — the same default WebCrypto's
|
|
14
|
+
* `{name:'ECDSA', hash:'SHA-256'}` and Node's `dsaEncoding:'ieee-p1363'`
|
|
15
|
+
* use, confirmed empirically against 6.1's fixtures (not just asserted
|
|
16
|
+
* from docs) before this file was written. No separate hashing step, no
|
|
17
|
+
* extra `@noble/hashes` dependency needed here.
|
|
18
|
+
*
|
|
19
|
+
* `{ lowS: false }` is required: noble enforces low-S canonical
|
|
20
|
+
* signatures by default and REJECTS a mathematically valid signature
|
|
21
|
+
* whose `s` happens to be > curve-order/2. Neither Node's `crypto.sign`
|
|
22
|
+
* (6.1's issuer) nor WebCrypto's `subtle.sign`/`subtle.verify`
|
|
23
|
+
* (`verify-webcrypto.ts`) normalize to or require low-S — ECDSA doesn't
|
|
24
|
+
* mandate it, only some ecosystems (e.g. Bitcoin) add it as policy — so
|
|
25
|
+
* roughly half of all real signatures would silently and incorrectly
|
|
26
|
+
* fail here without this option. Found by 6.1's own fixture set failing
|
|
27
|
+
* against this file specifically (passing on the WebCrypto path) — see
|
|
28
|
+
* Dev Agent Record and the KEY-FORMAT.md addendum.
|
|
29
|
+
*/
|
|
30
|
+
export declare function verifyWithFallback(message: Uint8Array<ArrayBuffer>, signature: Uint8Array<ArrayBuffer>, publicKeyJwk: JsonWebKey): boolean;
|
|
31
|
+
//# sourceMappingURL=verify-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-fallback.d.ts","sourceRoot":"","sources":["../../src/license/verify-fallback.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,UAAU,GAAG,OAAO,CAQ1I"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Primary verifier path (AC1) — used whenever `crypto.subtle` exists. Never throws: any failure (missing subtle, malformed JWK, wrong signature) resolves `false`. */
|
|
2
|
+
export declare function isWebCryptoAvailable(): boolean;
|
|
3
|
+
export declare function verifyWithWebCrypto(message: Uint8Array<ArrayBuffer>, signature: Uint8Array<ArrayBuffer>, publicKeyJwk: JsonWebKey): Promise<boolean>;
|
|
4
|
+
//# sourceMappingURL=verify-webcrypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-webcrypto.d.ts","sourceRoot":"","sources":["../../src/license/verify-webcrypto.ts"],"names":[],"mappings":"AAAA,uKAAuK;AAEvK,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAS1J"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface WatermarkOverlay {
|
|
2
|
+
/** Insert as the FIRST child of the canvas — below every scene element, so equipment visually "erases" the pattern over itself (non-obstruction via z-order). */
|
|
3
|
+
repeat: SVGGElement;
|
|
4
|
+
/** Insert as the LAST child — a fixed corner badge, always legible (non-obstruction via position: real schematics rarely put equipment in a canvas corner). */
|
|
5
|
+
badge: SVGGElement;
|
|
6
|
+
setVisible(visible: boolean): void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fail-soft trial watermark (Story 6.3, AC1). Philosophy — an honesty
|
|
10
|
+
* mechanism, not DRM: client-side enforcement is legal-teeth-plus-
|
|
11
|
+
* friction, nothing more (session decision, spec-amendments C1). Do NOT
|
|
12
|
+
* escalate this file into a MutationObserver arms race or add
|
|
13
|
+
* obfuscation/re-assertion-on-tamper logic beyond "rebuilt whenever the
|
|
14
|
+
* scene rebuilds" if a future ticket asks for "harder" enforcement —
|
|
15
|
+
* that contradicts SPEC C5/AD-9's fail-soft safety posture (a lapsed
|
|
16
|
+
* subscription must never darken a control-room screen) and should be
|
|
17
|
+
* refused at review, not implemented.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildWatermarkOverlay(canvasWidth: number, canvasHeight: number, defs: SVGDefsElement): WatermarkOverlay;
|
|
20
|
+
//# sourceMappingURL=watermark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watermark.d.ts","sourceRoot":"","sources":["../../src/license/watermark.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,iKAAiK;IACjK,MAAM,EAAE,WAAW,CAAC;IACpB,+JAA+J;IAC/J,KAAK,EAAE,WAAW,CAAC;IACnB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,gBAAgB,CAkDvH"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { TopologyGraph } from '../topology/graph';
|
|
2
|
+
/**
|
|
3
|
+
* Medium registry — styling half (§7.4, Story 2.3 Task 3). TypeScript
|
|
4
|
+
* shape only: real per-medium values (color/dash/speed) live in theme
|
|
5
|
+
* packages (classic-hmi ships water, steam, flue-gas, ash, condensate,
|
|
6
|
+
* electrical), resolved the same way every other token group is (AD-7).
|
|
7
|
+
*
|
|
8
|
+
* Deliberately narrow today — `MediumStyle` is the STYLING half only.
|
|
9
|
+
* Story 3.2 extends it additively with wave/visual params (amplitude,
|
|
10
|
+
* period, speed, specular, meniscus, bubbles, per §7.4's full table); this
|
|
11
|
+
* shape is designed so that extension never needs a breaking change here,
|
|
12
|
+
* so it stays a flat, easily-widened interface rather than something
|
|
13
|
+
* pre-built with unused fields now.
|
|
14
|
+
*/
|
|
15
|
+
export interface MediumDashSignature {
|
|
16
|
+
/** Dash length, px, at reference scale. */
|
|
17
|
+
length: number;
|
|
18
|
+
/** Gap length, px. */
|
|
19
|
+
gap: number;
|
|
20
|
+
opacity: number;
|
|
21
|
+
}
|
|
22
|
+
/** §7.4's `specular` field — how the medium's surface highlight reads (Story 3.2). */
|
|
23
|
+
export type SpecularStyle = 'sharp' | 'diffuse' | 'none';
|
|
24
|
+
/**
|
|
25
|
+
* Vapor-media plume parameters (steam, flue-gas) — §7.4's table row for
|
|
26
|
+
* those two rows says "plume, drifting opacity" with no liquid wave at
|
|
27
|
+
* all. Defined now so the registry shape is complete per the spec table;
|
|
28
|
+
* consumed by a future Story 3.8 plume renderer, no rendering here.
|
|
29
|
+
*/
|
|
30
|
+
export interface MediumPlumeStyle {
|
|
31
|
+
opacity: number;
|
|
32
|
+
driftSpeed: number;
|
|
33
|
+
}
|
|
34
|
+
export interface MediumStyle {
|
|
35
|
+
color: string;
|
|
36
|
+
dashSignature: MediumDashSignature;
|
|
37
|
+
/**
|
|
38
|
+
* Multiplier applied to the pipe's registered flow-dash animation (1 =
|
|
39
|
+
* reference speed). This scales the SAME AD-5-registered animation
|
|
40
|
+
* handle the pipe primitive already creates — never a second,
|
|
41
|
+
* medium-driven control path.
|
|
42
|
+
*/
|
|
43
|
+
animationSpeedFactor: number;
|
|
44
|
+
/**
|
|
45
|
+
* Story 3.2 — the motion/visual half of §7.4 (vessel liquid wave/surface
|
|
46
|
+
* character). All optional: Story 2.3's pipe-only media (`ash`,
|
|
47
|
+
* `electrical`) never declare them, and the pipe primitive never reads
|
|
48
|
+
* them — additive extension, no existing consumer's meaning changes.
|
|
49
|
+
*/
|
|
50
|
+
opacity?: number;
|
|
51
|
+
/** Wave crest height, px at reference scale. */
|
|
52
|
+
waveAmplitude?: number;
|
|
53
|
+
/** Wave horizontal period, px at reference scale — the seamless-loop translate distance (§7.3). */
|
|
54
|
+
wavePeriod?: number;
|
|
55
|
+
/** Multiplier applied to the wave loop's registered WAAPI playbackRate (1 = reference speed; oil ≈ 0.5 — "viscosity reads as slowness"). */
|
|
56
|
+
waveSpeed?: number;
|
|
57
|
+
specular?: SpecularStyle;
|
|
58
|
+
/** Darker/lighter tint at the vessel walls where the surface meets glass (§7.4's table; boolean flag — no geometry implied). */
|
|
59
|
+
meniscus?: boolean;
|
|
60
|
+
/** Steam/flue-gas only — see `MediumPlumeStyle`. */
|
|
61
|
+
plume?: MediumPlumeStyle;
|
|
62
|
+
}
|
|
63
|
+
export interface MediumTokens {
|
|
64
|
+
/** Medium name (kebab-case, e.g. "flue-gas") -> style. */
|
|
65
|
+
styles: Record<string, MediumStyle>;
|
|
66
|
+
/** Fallback medium name used when a pipe's resolved medium isn't registered, or has none at all. */
|
|
67
|
+
defaultMedium?: string;
|
|
68
|
+
}
|
|
69
|
+
/** Looks up a medium's style with graceful, literal-color-free degradation (AD-3/AD-7): unregistered theme or unknown medium name both resolve to `undefined`, never a hardcoded fallback color. */
|
|
70
|
+
export declare function resolveMediumStyle(mediaTokens: MediumTokens | undefined, mediumName: string | undefined): MediumStyle | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Story 3.2 Task 2 — §7.4: "Clients pick a name; power users override
|
|
73
|
+
* fields." A scene's `media` block (Story 1.2's `MediaSchema`, keyed by
|
|
74
|
+
* medium NAME, each value a record of per-field overrides) always wins
|
|
75
|
+
* over the theme-registered preset for that same medium name; fields the
|
|
76
|
+
* override doesn't mention keep the preset's value. This is a MERGE on top
|
|
77
|
+
* of `resolveMediumStyle`'s existing name/defaultMedium resolution — never
|
|
78
|
+
* a second, parallel medium-lookup path. Returns `undefined` under the
|
|
79
|
+
* exact same conditions `resolveMediumStyle` would (no tokens, unknown
|
|
80
|
+
* medium with no default) — overrides can refine a resolved style, never
|
|
81
|
+
* conjure one out of nothing.
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveEffectiveMediumStyle(mediaTokens: MediumTokens | undefined, mediumName: string | undefined, sceneMediaOverrides: Record<string, Record<string, unknown>> | undefined): MediumStyle | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Medium inheritance precedence (Task 3): a connection's own `medium` field
|
|
86
|
+
* always wins; otherwise fall back to its topology edge's medium (matched
|
|
87
|
+
* by id — a topology edge's `id` corresponds to the connection it
|
|
88
|
+
* describes, §5.4). A connection with no topology edge at all (or no
|
|
89
|
+
* medium anywhere) resolves to `undefined` — the pipe primitive/theme
|
|
90
|
+
* layer handles that via `resolveMediumStyle`'s own default-medium
|
|
91
|
+
* fallback, not here.
|
|
92
|
+
*/
|
|
93
|
+
export declare function resolveEffectiveMedium(connection: {
|
|
94
|
+
id: string;
|
|
95
|
+
medium?: string;
|
|
96
|
+
}, graph: TopologyGraph): string | undefined;
|
|
97
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/media/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,sFAAsF;AACtF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,mBAAmB,CAAC;IACnC;;;;;OAKG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4IAA4I;IAC5I,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,gIAAgI;IAChI,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,oGAAoG;IACpG,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,oMAAoM;AACpM,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,YAAY,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAKjI;AAgCD;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,YAAY,GAAG,SAAS,EACrC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,GACvE,WAAW,GAAG,SAAS,CAMzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAG5H"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ConnectionRenderModule } from '../contracts/connection-renderer';
|
|
2
|
+
export declare function registerConnectionRenderer(module: ConnectionRenderModule): void;
|
|
3
|
+
export declare function getConnectionRenderer(): ConnectionRenderModule | undefined;
|
|
4
|
+
export declare function __resetConnectionRegistryForTests(): void;
|
|
5
|
+
//# sourceMappingURL=connection-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-registry.d.ts","sourceRoot":"","sources":["../../src/registry/connection-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAS/E,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAE/E;AAED,wBAAgB,qBAAqB,IAAI,sBAAsB,GAAG,SAAS,CAE1E;AAED,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
|