@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.
Files changed (145) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/a11y/contrast.d.ts +11 -0
  3. package/dist/a11y/contrast.d.ts.map +1 -0
  4. package/dist/a11y/live-region.d.ts +42 -0
  5. package/dist/a11y/live-region.d.ts.map +1 -0
  6. package/dist/a11y/reduced-motion.d.ts +55 -0
  7. package/dist/a11y/reduced-motion.d.ts.map +1 -0
  8. package/dist/a11y/static-representation-registry.d.ts +20 -0
  9. package/dist/a11y/static-representation-registry.d.ts.map +1 -0
  10. package/dist/bindings/binding-fixture.d.ts +3 -0
  11. package/dist/bindings/binding-fixture.d.ts.map +1 -0
  12. package/dist/bindings/binding-types.d.ts +52 -0
  13. package/dist/bindings/binding-types.d.ts.map +1 -0
  14. package/dist/bindings/color-ramp.d.ts +9 -0
  15. package/dist/bindings/color-ramp.d.ts.map +1 -0
  16. package/dist/bindings/transforms.d.ts +103 -0
  17. package/dist/bindings/transforms.d.ts.map +1 -0
  18. package/dist/constants-DMdpoOyH.js +4 -0
  19. package/dist/contracts/connection-renderer.d.ts +16 -0
  20. package/dist/contracts/connection-renderer.d.ts.map +1 -0
  21. package/dist/contracts/connection-state.d.ts +8 -0
  22. package/dist/contracts/connection-state.d.ts.map +1 -0
  23. package/dist/contracts/handles.d.ts +83 -0
  24. package/dist/contracts/handles.d.ts.map +1 -0
  25. package/dist/contracts/primitive.d.ts +37 -0
  26. package/dist/contracts/primitive.d.ts.map +1 -0
  27. package/dist/contracts/renderer.d.ts +34 -0
  28. package/dist/contracts/renderer.d.ts.map +1 -0
  29. package/dist/contracts/tag-value.d.ts +33 -0
  30. package/dist/contracts/tag-value.d.ts.map +1 -0
  31. package/dist/contracts/time-source.d.ts +14 -0
  32. package/dist/contracts/time-source.d.ts.map +1 -0
  33. package/dist/custom-elements.json +1068 -0
  34. package/dist/export/svg-export.d.ts +24 -0
  35. package/dist/export/svg-export.d.ts.map +1 -0
  36. package/dist/fsm/fsm.d.ts +45 -0
  37. package/dist/fsm/fsm.d.ts.map +1 -0
  38. package/dist/fsm/tween.d.ts +39 -0
  39. package/dist/fsm/tween.d.ts.map +1 -0
  40. package/dist/import/load-svg-import.d.ts +22 -0
  41. package/dist/import/load-svg-import.d.ts.map +1 -0
  42. package/dist/import/svg-source-registry.d.ts +4 -0
  43. package/dist/import/svg-source-registry.d.ts.map +1 -0
  44. package/dist/index.d.ts +61 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +4549 -0
  47. package/dist/interaction/gesture-arbiter.d.ts +20 -0
  48. package/dist/interaction/gesture-arbiter.d.ts.map +1 -0
  49. package/dist/interaction/hit-area.d.ts +44 -0
  50. package/dist/interaction/hit-area.d.ts.map +1 -0
  51. package/dist/interaction/pan-zoom-gestures.d.ts +43 -0
  52. package/dist/interaction/pan-zoom-gestures.d.ts.map +1 -0
  53. package/dist/interaction/pointer-pipeline.d.ts +38 -0
  54. package/dist/interaction/pointer-pipeline.d.ts.map +1 -0
  55. package/dist/license/console-notice.d.ts +15 -0
  56. package/dist/license/console-notice.d.ts.map +1 -0
  57. package/dist/license/format.d.ts +29 -0
  58. package/dist/license/format.d.ts.map +1 -0
  59. package/dist/license/state.d.ts +43 -0
  60. package/dist/license/state.d.ts.map +1 -0
  61. package/dist/license/vendor-keys.d.ts +12 -0
  62. package/dist/license/vendor-keys.d.ts.map +1 -0
  63. package/dist/license/verify-fallback.d.ts +31 -0
  64. package/dist/license/verify-fallback.d.ts.map +1 -0
  65. package/dist/license/verify-webcrypto.d.ts +4 -0
  66. package/dist/license/verify-webcrypto.d.ts.map +1 -0
  67. package/dist/license/watermark.d.ts +20 -0
  68. package/dist/license/watermark.d.ts.map +1 -0
  69. package/dist/media/registry.d.ts +97 -0
  70. package/dist/media/registry.d.ts.map +1 -0
  71. package/dist/registry/connection-registry.d.ts +5 -0
  72. package/dist/registry/connection-registry.d.ts.map +1 -0
  73. package/dist/registry/element-catalog.d.ts +805 -0
  74. package/dist/registry/element-catalog.d.ts.map +1 -0
  75. package/dist/registry/primitive-registry.d.ts +7 -0
  76. package/dist/registry/primitive-registry.d.ts.map +1 -0
  77. package/dist/registry/theme-registry.d.ts +6 -0
  78. package/dist/registry/theme-registry.d.ts.map +1 -0
  79. package/dist/registry.d.ts +8 -0
  80. package/dist/registry.d.ts.map +1 -0
  81. package/dist/scada-view.d.ts +322 -0
  82. package/dist/scada-view.d.ts.map +1 -0
  83. package/dist/scene/connection-geometry.d.ts +95 -0
  84. package/dist/scene/connection-geometry.d.ts.map +1 -0
  85. package/dist/scene/constants.d.ts +10 -0
  86. package/dist/scene/constants.d.ts.map +1 -0
  87. package/dist/scene/crossing-jumps.d.ts +85 -0
  88. package/dist/scene/crossing-jumps.d.ts.map +1 -0
  89. package/dist/scene/dev-validate.d.ts +24 -0
  90. package/dist/scene/dev-validate.d.ts.map +1 -0
  91. package/dist/scene/errors.d.ts +15 -0
  92. package/dist/scene/errors.d.ts.map +1 -0
  93. package/dist/scene/groups.d.ts +90 -0
  94. package/dist/scene/groups.d.ts.map +1 -0
  95. package/dist/scene/lane-offset.d.ts +69 -0
  96. package/dist/scene/lane-offset.d.ts.map +1 -0
  97. package/dist/scene/orthogonal-router.d.ts +63 -0
  98. package/dist/scene/orthogonal-router.d.ts.map +1 -0
  99. package/dist/scene/scene-schema.d.ts +881 -0
  100. package/dist/scene/scene-schema.d.ts.map +1 -0
  101. package/dist/scene/structural-validator.d.ts +25 -0
  102. package/dist/scene/structural-validator.d.ts.map +1 -0
  103. package/dist/scene/validate-scene.d.ts +26 -0
  104. package/dist/scene/validate-scene.d.ts.map +1 -0
  105. package/dist/scene-authoring.d.ts +12 -0
  106. package/dist/scene-authoring.d.ts.map +1 -0
  107. package/dist/scene-authoring.js +952 -0
  108. package/dist/scheduler/alarm-band.d.ts +33 -0
  109. package/dist/scheduler/alarm-band.d.ts.map +1 -0
  110. package/dist/scheduler/animation-registry.d.ts +38 -0
  111. package/dist/scheduler/animation-registry.d.ts.map +1 -0
  112. package/dist/scheduler/lod.d.ts +25 -0
  113. package/dist/scheduler/lod.d.ts.map +1 -0
  114. package/dist/scheduler/quality-overlay.d.ts +19 -0
  115. package/dist/scheduler/quality-overlay.d.ts.map +1 -0
  116. package/dist/scheduler/quality.d.ts +15 -0
  117. package/dist/scheduler/quality.d.ts.map +1 -0
  118. package/dist/scheduler/scheduler.d.ts +243 -0
  119. package/dist/scheduler/scheduler.d.ts.map +1 -0
  120. package/dist/scheduler/visual-state-resolver.d.ts +31 -0
  121. package/dist/scheduler/visual-state-resolver.d.ts.map +1 -0
  122. package/dist/store/value-store.d.ts +65 -0
  123. package/dist/store/value-store.d.ts.map +1 -0
  124. package/dist/tokens.d.ts +703 -0
  125. package/dist/tokens.d.ts.map +1 -0
  126. package/dist/topology/graph.d.ts +33 -0
  127. package/dist/topology/graph.d.ts.map +1 -0
  128. package/dist/topology/group-collapse.d.ts +15 -0
  129. package/dist/topology/group-collapse.d.ts.map +1 -0
  130. package/dist/topology/inference.d.ts +71 -0
  131. package/dist/topology/inference.d.ts.map +1 -0
  132. package/dist/topology/traversal.d.ts +29 -0
  133. package/dist/topology/traversal.d.ts.map +1 -0
  134. package/dist/topology/upstream-highlight.d.ts +75 -0
  135. package/dist/topology/upstream-highlight.d.ts.map +1 -0
  136. package/dist/units/formatter.d.ts +22 -0
  137. package/dist/units/formatter.d.ts.map +1 -0
  138. package/dist/units/registry.d.ts +21 -0
  139. package/dist/units/registry.d.ts.map +1 -0
  140. package/dist/view/group-view-state.d.ts +77 -0
  141. package/dist/view/group-view-state.d.ts.map +1 -0
  142. package/dist/view/viewport-state.d.ts +112 -0
  143. package/dist/view/viewport-state.d.ts.map +1 -0
  144. package/dist/vscada.umd.cjs +45 -0
  145. package/package.json +37 -0
@@ -0,0 +1,703 @@
1
+ import type { MediumTokens } from './media/registry';
2
+ /**
3
+ * Theme token schema (AD-7). Primitives reference tokens by name only —
4
+ * never literal colors. Grows per-primitive-group token sets as those
5
+ * primitives are built; `pipe` is the first (Story 1.4, §7.1).
6
+ */
7
+ export interface GradientStop {
8
+ /** 0–1, fraction along the gradient. */
9
+ offset: number;
10
+ color: string;
11
+ }
12
+ export interface PipeTokens {
13
+ /** Six-stop cross-section gradient, perpendicular to run direction (§7.1). */
14
+ gradient: readonly GradientStop[];
15
+ /** Stroke width in px at reference scale (22–26 per spec). */
16
+ strokeWidth: number;
17
+ flange: {
18
+ /** Multiple of strokeWidth for the flange band's width. */
19
+ widthFactor: number;
20
+ /** Flange length along the run, px. */
21
+ length: number;
22
+ outlineColor: string;
23
+ highlightColor: string;
24
+ ringColor: string;
25
+ /**
26
+ * AD-7 fix (architecture-code-audit-2026-08-27): the ring lines' own
27
+ * stroke width. Deliberately named `ringStrokeWidth`, NOT `strokeWidth`
28
+ * (Blind Hunter review pass finding) — this interface's top-level
29
+ * `strokeWidth` above is the pipe BODY's, a wholly different value; a
30
+ * same-named nested field would let `tokens.strokeWidth` typo its way
31
+ * into flange code and silently grab the wrong number with no compiler
32
+ * error. Optional — falls back to the pre-fix literal.
33
+ */
34
+ ringStrokeWidth?: number;
35
+ };
36
+ dash: {
37
+ color: string;
38
+ length: number;
39
+ gap: number;
40
+ opacity: number;
41
+ /** AD-7 fix (architecture-code-audit-2026-08-27): the dash line's own stroke width — named `lineStrokeWidth`, not `strokeWidth`, for the same collision-avoidance reason as `flange.ringStrokeWidth` above. Optional — falls back to the pre-fix literal. */
42
+ lineStrokeWidth?: number;
43
+ };
44
+ /**
45
+ * Which visual represents flow. `'dash'` (default when omitted — every
46
+ * existing theme is byte-identical without this field) is the spec's own
47
+ * industrial P&ID convention (§6.4: "dash offset animation speed").
48
+ * `'wave'` is an opt-in decorative alternative — a rippling sine-crest
49
+ * line for contexts that want a literal "moving water" read over the
50
+ * schematic dash idiom. Themes that don't set this, or that omit `wave`
51
+ * below, always render dashes.
52
+ */
53
+ flowStyle?: 'dash' | 'wave';
54
+ /** Only consulted when `flowStyle === 'wave'`. */
55
+ wave?: {
56
+ color: string;
57
+ /** Crest height, px. */
58
+ amplitude: number;
59
+ /** Wavelength along the run, px. */
60
+ period: number;
61
+ strokeWidth: number;
62
+ opacity: number;
63
+ };
64
+ }
65
+ export interface MediumFillStops {
66
+ top: string;
67
+ bottom: string;
68
+ }
69
+ /** §7.3 classic-hmi liquid: flat saturated fill (top→bottom gradient), bright surface line. */
70
+ export interface LiquidTokens {
71
+ surfaceColor: string;
72
+ /** Medium name -> fill gradient. */
73
+ media: Record<string, MediumFillStops>;
74
+ /** Used when an element's `medium` isn't in `media` (e.g. "water"). */
75
+ defaultMedium: string;
76
+ /**
77
+ * Story 3.2 — number of wave layers a vessel's liquid stacks (§7.3's
78
+ * amendment §B1: classic-hmi ships exactly ONE gentle wave layer; the
79
+ * future `realistic` theme's 2-3 layer stack with decreasing opacity is
80
+ * a token change, not a rewrite, because this is data, not code).
81
+ * Optional so every pre-3.2 theme/test fixture parses unchanged;
82
+ * consumers default to 1 (`?? 1`) when absent.
83
+ */
84
+ waveCount?: number;
85
+ }
86
+ /**
87
+ * §6.2 tank state model / AC2 (Story 3.3): threshold wall markers + the
88
+ * liquid surface line are colored by the currently-active alarm band —
89
+ * `normal` plus the four §5.3 threshold levels (`low`/`low-low`/`high`/
90
+ * `high-high`). Named fields (not a `Record`) so a theme can't accidentally
91
+ * omit a band — same "every state has a color" discipline `PumpTokens.states`
92
+ * already establishes, just fixed-shape here since the band set is closed.
93
+ */
94
+ export interface VesselAlarmTokens {
95
+ normalColor: string;
96
+ lowColor: string;
97
+ lowLowColor: string;
98
+ highColor: string;
99
+ highHighColor: string;
100
+ }
101
+ /**
102
+ * §7.2 vessel rendering recipe tokens (Story 3.3) — every layer's color (and,
103
+ * per the same convention `PipeTokens.strokeWidth` already set, its stroke
104
+ * width) is a named token here, never a literal in `recipe.ts`. Only
105
+ * `bodyStrokeColor`/`bodyFillColor` are required (Story 1.5's original
106
+ * two-field shape, kept non-breaking); every Story 3.3 addition is optional
107
+ * so a theme/test fixture predating this story still satisfies the type —
108
+ * `recipe.ts` degrades each missing field the same way `liquid`/`medium`
109
+ * already degrade (omit or flat-fallback, never a literal-color stand-in).
110
+ */
111
+ export interface VesselTokens {
112
+ bodyStrokeColor: string;
113
+ bodyFillColor: string;
114
+ /** §7.2 layer 1 — body base, vertical gradient mid-tone→darker. Falls back to the flat `bodyFillColor` when either stop is absent. */
115
+ bodyGradientTopColor?: string;
116
+ bodyGradientBottomColor?: string;
117
+ /** §7.2 layer 2 — cylindrical shading overlay stops (dark edge → light band ~35% → mid → dark edge); spheres reuse the same three stops as a radial highlight instead of the linear band. */
118
+ shadingDarkColor?: string;
119
+ shadingLightColor?: string;
120
+ shadingMidColor?: string;
121
+ /** §7.2 layer 4 — narrow near-white specular strip (opacity 0.12 per spec, in `recipe.ts`). */
122
+ specularColor?: string;
123
+ /** §7.2 layer 5 — rim ellipses: darker stroke + a lighter upper-edge arc/crown ribbing. */
124
+ rimStrokeColor?: string;
125
+ rimHighlightColor?: string;
126
+ /** §7.2 layer 6 — hardware (nozzles, manway, lugs, skirt) + weld seam lines. */
127
+ hardwareFillColor?: string;
128
+ hardwareStrokeColor?: string;
129
+ weldLineColor?: string;
130
+ /** §7.2 layer 7 — contact shadow at the base. */
131
+ contactShadowColor?: string;
132
+ /** Shared outline stroke width (px, reference scale) for body/rim/hardware/threshold-marker strokes. */
133
+ strokeWidth?: number;
134
+ /** AC2 — threshold wall markers + liquid surface-line coloring by alarm band. */
135
+ alarm?: VesselAlarmTokens;
136
+ }
137
+ /** §6.2 pump state visual: lamp color ALWAYS paired with a text/shape channel (AD-3). */
138
+ export interface PumpStateVisual {
139
+ lampColor: string;
140
+ blink: boolean;
141
+ label: string;
142
+ }
143
+ export interface PumpTokens {
144
+ /** Keyed by state name: stopped/starting/running/tripped/unavailable. */
145
+ states: Record<string, PumpStateVisual>;
146
+ bodyEnergizedColor: string;
147
+ bodyDeenergizedColor: string;
148
+ impellerColor: string;
149
+ }
150
+ /**
151
+ * §6.2 "every other control is a simpler version of the pump" (§15) — Story
152
+ * 3.4's driven-equipment batch (pump-positive-displacement, compressor,
153
+ * turbine, motor) shares the pump's exact 5-state set
154
+ * (stopped/starting/running/tripped/unavailable) and lamp/body-highlight
155
+ * visual language, so it gets its OWN token namespace with the same shape
156
+ * as `PumpTokens` rather than a risky rename of that already-consumed
157
+ * type/field (`pump-centrifugal` imports `theme.tokens.pump` today) —
158
+ * additive is safer. `rotorColor` is the generic "moving part" color each
159
+ * of those four primitives' own silhouette (lobes/rotor/shaft-fan) draws
160
+ * with; a primitive that needs a second tone reuses this same value twice
161
+ * rather than the token set growing per-primitive.
162
+ */
163
+ export interface DrivenEquipmentStateVisual {
164
+ lampColor: string;
165
+ blink: boolean;
166
+ label: string;
167
+ }
168
+ export interface DrivenEquipmentTokens {
169
+ /** Keyed by state name: stopped/starting/running/tripped/unavailable. */
170
+ states: Record<string, DrivenEquipmentStateVisual>;
171
+ bodyEnergizedColor: string;
172
+ bodyDeenergizedColor: string;
173
+ rotorColor: string;
174
+ /** AD-7 fix (architecture-code-audit-2026-08-27): compressor/turbine's rotor inset line, motor's shaft floor width. Optional — primitives fall back to the pre-fix literal when a theme doesn't override it. */
175
+ strokeWidth?: number;
176
+ }
177
+ /** §6.2 fan/blower state visual — lamp color ALWAYS paired with a text/shape channel (AD-3). */
178
+ export interface FanStateVisual {
179
+ lampColor: string;
180
+ blink: boolean;
181
+ label: string;
182
+ }
183
+ /**
184
+ * §6.2 Fan/blower — its OWN 3-state set (`off`/`running`/`fault`, distinct
185
+ * from the pump's 5-state set) and its own blur-disc crossover tokens
186
+ * (Story 3.4 Task 3): above `blurThresholdRpm`, the discrete blade group
187
+ * swaps for a semi-transparent ring rendered with `blurredDiscColor` /
188
+ * `blurredDiscOpacity`. Shared by both fan-axial and fan-centrifugal — the
189
+ * spec's single "Fan / blower" subsection covers both silhouettes with one
190
+ * state/blur model.
191
+ */
192
+ export interface FanTokens {
193
+ /** Keyed by state name: off/running/fault. */
194
+ states: Record<string, FanStateVisual>;
195
+ bodyEnergizedColor: string;
196
+ bodyDeenergizedColor: string;
197
+ bladeColor: string;
198
+ blurredDiscColor: string;
199
+ blurredDiscOpacity: number;
200
+ /** RPM threshold for the blur-disc crossover; Task 3's ±5% hysteresis band is computed FROM this value, not a separate token. */
201
+ blurThresholdRpm: number;
202
+ /** AD-7 fix (architecture-code-audit-2026-08-27): the streak-line detail's stroke width. Optional — falls back to the pre-fix literal. */
203
+ strokeWidth?: number;
204
+ }
205
+ /**
206
+ * §6.2 valve state visual (Story 3.5) — `fault` is the only state needing a
207
+ * distinct color, always paired with `label` text (AD-3: color never stands
208
+ * alone). `closed`/`opening`/`open`/`closing` don't get their own dot color
209
+ * here — their body-fill read comes from `ValveTokens.closedColor`/the
210
+ * resolved medium color, tracked continuously by position fraction, not a
211
+ * discrete per-state color swap.
212
+ */
213
+ export interface ValveStateVisual {
214
+ indicatorColor: string;
215
+ blink: boolean;
216
+ label: string;
217
+ }
218
+ /**
219
+ * §6.2 valve batch (Story 3.5) — shared by all six §6.1 valve types
220
+ * (gate/ball/butterfly/control/check/relief). `closedColor`/`openColor` are
221
+ * the body-fill fraction's two endpoints (grey closed -> medium color open,
222
+ * AC2); `openColor` is only the FALLBACK when the element has no resolved
223
+ * `medium` (AD-7: the medium registry's own color wins when present, same
224
+ * precedent as vessel liquid fill). `defaultStrokeMs` is the token-level
225
+ * fallback stroke duration (~5s, §6.2's "3-15s" range) used when a scene's
226
+ * `transitions` declares no `closed→open`/`open→closed` entry.
227
+ */
228
+ export interface ValveTokens {
229
+ states: Record<string, ValveStateVisual>;
230
+ closedColor: string;
231
+ openColor: string;
232
+ discColor: string;
233
+ arrowColor: string;
234
+ bodyOutlineColor: string;
235
+ defaultStrokeMs: number;
236
+ /** AD-7 fix (architecture-code-audit-2026-08-27): body/bonnet/shaft/actuator outline weight; relief's spring derives a thinner weight from it. Optional — falls back to the pre-fix literal. */
237
+ strokeWidth?: number;
238
+ }
239
+ /**
240
+ * §4.3 quality/staleness overlay (Story 1.6) — cross-primitive, core-owned
241
+ * (never per-primitive). Desaturation is a grey overlay + CSS-var muting,
242
+ * NEVER `filter: grayscale()` (C7 bans filters for determinism + perf).
243
+ */
244
+ export interface QualityTokens {
245
+ uncertainDashColor: string;
246
+ badHatchColor: string;
247
+ badHatchOpacity: number;
248
+ staleOverlayColor: string;
249
+ staleOverlayOpacity: number;
250
+ badgeTextColor: string;
251
+ badgeBackgroundColor: string;
252
+ }
253
+ /** §7.6 raised-panel bevel: light top/left, dark bottom/right, flat face. */
254
+ export interface PanelChromeTokens {
255
+ faceColor: string;
256
+ highlightColor: string;
257
+ shadowColor: string;
258
+ }
259
+ /** Discrete condition -> color; always paired with the alarm dot's text label (AD-3 — color never stands alone). */
260
+ export interface IndicatorStateTokens {
261
+ goodColor: string;
262
+ uncertainColor: string;
263
+ staleColor: string;
264
+ badColor: string;
265
+ }
266
+ /**
267
+ * §7.6 panel chrome (Story 2.5) — first consumer is the collapsed-group
268
+ * summary block (§5.5 AC1: label, summaryTag readouts, worst-of-children
269
+ * alarm indicator), named generically since raised-panel chrome applies to
270
+ * other widget-box elements too (§7.6's own wording), not just groups.
271
+ */
272
+ export interface PanelTokens {
273
+ raised: PanelChromeTokens;
274
+ labelColor: string;
275
+ readoutColor: string;
276
+ alarmIndicator: IndicatorStateTokens;
277
+ }
278
+ /** §5.6 off-page connector stub (Story 2.6) — labeled arrow/pennant per P&ID convention. */
279
+ export interface OffPageTokens {
280
+ fillColor: string;
281
+ strokeColor: string;
282
+ labelColor: string;
283
+ }
284
+ /** One stop in a `color-ramp` binding's interpolation (`offset` 0..1 along the scene binding's declared min..max). */
285
+ export interface ColorRampStop {
286
+ offset: number;
287
+ color: string;
288
+ }
289
+ /**
290
+ * §6.4 `color-ramp` binding tokens (Story 3.1) — AD-7: a scene/binding
291
+ * NEVER supplies a raw color, only threshold VALUES; the theme supplies
292
+ * every color. `stops` are NAMED colors a binding's optional `colors` list
293
+ * may reference by name (e.g. `["good","warn","critical"]`) — never by
294
+ * literal hex, so even a scene author who puts a hex string in `colors`
295
+ * simply fails the name lookup and falls back to `default`. `default` is
296
+ * the ordered ramp used when a binding doesn't name any stops at all.
297
+ */
298
+ export interface ColorRampTokens {
299
+ stops: Record<string, string>;
300
+ default: readonly ColorRampStop[];
301
+ }
302
+ /**
303
+ * §7.6 gauge-analog face chrome (Story 3.6 Task 2) — the raised orange-tan
304
+ * bevel face, distinct from `PanelTokens.raised`'s dark metal panel chrome
305
+ * (same "light top/left, dark bottom/right, flat face" bevel SHAPE, its
306
+ * own namespace per the `DrivenEquipmentTokens`-vs-`PumpTokens` precedent:
307
+ * additive/decoupled beats a risky shared type).
308
+ */
309
+ export interface GaugeFaceTokens {
310
+ faceColor: string;
311
+ bevelHighlightColor: string;
312
+ bevelShadowColor: string;
313
+ tickColor: string;
314
+ divisionLabelColor: string;
315
+ needleColor: string;
316
+ pivotColor: string;
317
+ captionColor: string;
318
+ /** AD-7 fix (architecture-code-audit-2026-08-27): face outline/needle weight; bevel/tick derive a thinner weight from it. Optional — falls back to the pre-fix literal. */
319
+ strokeWidth?: number;
320
+ }
321
+ /**
322
+ * Arc-segment + needle-color zones by alarm band (AC1: "arc segments and
323
+ * needle color reflect warning/alarm zones") — same fixed five-band shape
324
+ * as `VesselAlarmTokens` (Story 3.3 precedent: every §5.3 threshold level
325
+ * plus `normal`), driven by the SAME `element.thresholds` model.
326
+ *
327
+ * AD-12 fix (architecture-code-audit-2026-08-27): originally its own
328
+ * separately-declared interface, "same shape, own namespace" — that made
329
+ * `resolveAlarmColor` (`scheduler/alarm-band.ts`) accepting a
330
+ * `GaugeZoneTokens` value at gauge-analog's call site an accident of
331
+ * structural typing, not a guaranteed contract; if either interface's
332
+ * fields ever drifted independently, the break would surface as a type
333
+ * error at the call site instead of here, where the intent is stated. Now
334
+ * a true alias, so the compiler enforces what the comment used to only
335
+ * assert.
336
+ */
337
+ export type GaugeZoneTokens = VesselAlarmTokens;
338
+ export interface GaugeTokens {
339
+ face: GaugeFaceTokens;
340
+ zones: GaugeZoneTokens;
341
+ }
342
+ /**
343
+ * §6.2 indicator-lamp (Story 3.6 Task 3) — a STANDALONE primitive (pump/
344
+ * valve/rotating lamps stay internal to those primitives); color always
345
+ * paired with `label` text (AD-3). Keyed by state name:
346
+ * off/on/blink-slow/blink-fast. `fastBlinkHz`/`slowBlinkHz` are the
347
+ * ISA-18.2 named rates (fast = unacknowledged ~2-3Hz, slow = acknowledged
348
+ * active ~0.5-1Hz) — tokens, not buried literals, since a theme may need
349
+ * to retune them for a specific plant's alarm philosophy document.
350
+ */
351
+ export interface IndicatorLampStateVisual {
352
+ color: string;
353
+ label: string;
354
+ }
355
+ export interface IndicatorLampTokens {
356
+ states: Record<string, IndicatorLampStateVisual>;
357
+ fastBlinkHz: number;
358
+ slowBlinkHz: number;
359
+ }
360
+ /**
361
+ * Shared recessed-face bevel for the Task 4 instrument batch
362
+ * (gauge-digital/readout-panel/bargraph/trend-mini) — same token SHAPE as
363
+ * `GaugeFaceTokens`'s raised bevel and `PanelChromeTokens`'s raised bevel,
364
+ * own type per the same additive-namespace convention (this bevel reads
365
+ * recessed — highlight/shadow corners swap in the primitive's own
366
+ * rendering code, never in the token shape itself).
367
+ */
368
+ export interface InstrumentFaceTokens {
369
+ faceColor: string;
370
+ bevelHighlightColor: string;
371
+ bevelShadowColor: string;
372
+ }
373
+ /** gauge-digital (Story 3.6 Task 4) — 7-seg-style digit treatment; `----` on bad quality is core-owned (AD-12/`scheduler.ts`), not this primitive's concern. */
374
+ export interface GaugeDigitalTokens {
375
+ face: InstrumentFaceTokens;
376
+ digitColor: string;
377
+ labelColor: string;
378
+ }
379
+ /** readout-panel (Story 3.6 Task 4) — multi-tag grid using the shared display formatter. */
380
+ export interface ReadoutPanelTokens {
381
+ face: InstrumentFaceTokens;
382
+ labelColor: string;
383
+ valueColor: string;
384
+ }
385
+ /** bargraph (Story 3.6 Task 4) — vertical bar + threshold ticks (level-binding fraction reused, AC1's fraction math via `resolveLevelFraction`). */
386
+ export interface BargraphTokens {
387
+ face: InstrumentFaceTokens;
388
+ trackColor: string;
389
+ fillColor: string;
390
+ thresholdTickColor: string;
391
+ /** AD-7 fix (architecture-code-audit-2026-08-27): threshold tick stroke width. Optional — falls back to the pre-fix literal. */
392
+ strokeWidth?: number;
393
+ }
394
+ /**
395
+ * trend-mini (Story 3.6 Task 4) — rolling sparkline of ONE tag; the ring
396
+ * buffer itself is bounded DERIVED display state living in the primitive's
397
+ * own handle (AD-4: reconstructible, cleared on `clearValues()`) — the
398
+ * ONE sanctioned exception to no-history (Dev Notes), never persisted.
399
+ */
400
+ export interface TrendMiniTokens {
401
+ face: InstrumentFaceTokens;
402
+ lineColor: string;
403
+ axisColor: string;
404
+ /** Ring-buffer size (Dev Notes: "~60 points") — the ONE sanctioned bounded-history exception (AD-4: derived display state, reconstructible, cleared alongside the rest on a fresh element build). */
405
+ pointCount: number;
406
+ /** AD-7 fix (architecture-code-audit-2026-08-27): the line's stroke width; the axis derives a thinner weight from it. Optional — falls back to the pre-fix literal. */
407
+ strokeWidth?: number;
408
+ }
409
+ /**
410
+ * §6.2 boiler/furnace firing state visual (Story 3.7 Task 3) — glow color +
411
+ * opacity ALWAYS paired with a text label (AD-3: color never stands alone),
412
+ * shared `off`/`firing` two-state vocabulary between the two primitives that
413
+ * need it (Dev Notes Task 3: "boiler/furnace state machines via the shared
414
+ * FSM"). Its own namespace rather than reusing `PumpTokens`'s shape — the
415
+ * state SET is different (two states, not five) and the visual channel is a
416
+ * glow (opacity), not a lamp.
417
+ */
418
+ export interface HeatStateVisual {
419
+ glowColor: string;
420
+ glowOpacity: number;
421
+ label: string;
422
+ }
423
+ /**
424
+ * §6.1 heat batch (Story 3.7) — heat-exchanger-shell-tube/boiler/condenser
425
+ * lean on `VesselTokens` via `buildVesselRecipe` for their shell body (Dev
426
+ * Notes: "reuse over invention"); this namespace covers only what's NOT
427
+ * vessel-recipe shaped: the shared firing-state glow (boiler/furnace), the
428
+ * shell-tube's tube-bundle end detail, the condenser's condensate wells, and
429
+ * furnace/cooling-tower's own non-vessel silhouettes.
430
+ */
431
+ export interface HeatTokens {
432
+ /** Keyed by state name: off/firing. */
433
+ states: Record<string, HeatStateVisual>;
434
+ /** furnace/cooling-tower silhouette fill — neither reuses `VesselTokens`. */
435
+ bodyColor: string;
436
+ outlineColor: string;
437
+ /** heat-exchanger-shell-tube's tube-bundle end-detail circles. */
438
+ tubeBundleColor: string;
439
+ /** condenser's condensate-well detail at the shell's base. */
440
+ condensateColor: string;
441
+ /**
442
+ * heat-exchanger-coil's stroke width as a fraction of `PipeTokens.strokeWidth`
443
+ * (§7.6: "serpentine path using the pipe gradient at reduced width", AC2).
444
+ */
445
+ coilWidthFactor: number;
446
+ /** AD-7 fix (architecture-code-audit-2026-08-27): furnace/cooling-tower's own silhouette outline weight — unrelated to `coilWidthFactor` above, which derives from `PipeTokens.strokeWidth` instead. Optional — falls back to the pre-fix literal. */
447
+ strokeWidth?: number;
448
+ }
449
+ /**
450
+ * §6.1 filtration batch (Story 3.7 Task 2) — bag-filter/cyclone/scrubber/
451
+ * stack. Own namespace (additive-namespace convention, same precedent as
452
+ * every other batch): none of these silhouettes are vessel-recipe shaped.
453
+ */
454
+ export interface FiltrationTokens {
455
+ bodyColor: string;
456
+ outlineColor: string;
457
+ /** bag-filter's hopper-bottom detail. */
458
+ hopperColor: string;
459
+ /** scrubber's liquid-distributor bar detail. */
460
+ distributorColor: string;
461
+ /** Differential-pressure/temperature `readout` binding text (Task 3). */
462
+ readoutColor: string;
463
+ /** AD-7 fix (architecture-code-audit-2026-08-27): housing/body outline weight; bag-filter's bag hints derive a heavier weight from it. Optional — falls back to the pre-fix literal. */
464
+ strokeWidth?: number;
465
+ }
466
+ /**
467
+ * §6.1 conveyor state visual (Story 3.9 Task 1) — lamp color ALWAYS paired
468
+ * with a text label (AD-3). Deliberately its own namespace rather than
469
+ * reusing `PumpTokens`'s shape: the belt's state SET (running/stopped, no
470
+ * starting/tripped ramp) is simpler than the pump's 5-state vocabulary.
471
+ */
472
+ export interface ConveyorStateVisual {
473
+ lampColor: string;
474
+ blink: boolean;
475
+ label: string;
476
+ }
477
+ /** §6.1 conveyor (Story 3.9 Task 1) — belt run + rollers, `state`+`speed`(`rotate`-binding) driven belt-dash loop, optional `level`-bound material-load shading. */
478
+ export interface ConveyorTokens {
479
+ states: Record<string, ConveyorStateVisual>;
480
+ bodyColor: string;
481
+ rollerColor: string;
482
+ beltColor: string;
483
+ beltDashColor: string;
484
+ beltDashLength: number;
485
+ beltDashGap: number;
486
+ /** Material-load shading tint, driven by the optional `level`-style binding (Task 1). */
487
+ loadColor: string;
488
+ }
489
+ /** §16 waste-feed screw-feeder (Story 3.9 Task 1) — helix rotation only (no discrete state channel per Task 1's own wording). */
490
+ export interface ScrewFeederTokens {
491
+ bodyColor: string;
492
+ outlineColor: string;
493
+ helixColor: string;
494
+ /** AD-7 fix (architecture-code-audit-2026-08-27): helix line stroke width. Optional — falls back to the pre-fix literal. */
495
+ strokeWidth?: number;
496
+ }
497
+ /**
498
+ * duct (Story 3.9 Task 1) — rectangular-section variant of the §7.1 pipe
499
+ * treatment. Reuses `PipeTokens.gradient`/`strokeWidth` (`tokens.pipe`)
500
+ * wholesale (Dev Notes/Scope: "no new routing/geometry code for ducts");
501
+ * this namespace covers only the seam-line detail unique to ductwork.
502
+ */
503
+ export interface DuctTokens {
504
+ seamColor: string;
505
+ /** Spacing between seam lines along the run, px at reference scale. */
506
+ seamSpacing: number;
507
+ /** AD-7 fix (architecture-code-audit-2026-08-27): seam line stroke width. Optional — falls back to the pre-fix literal. */
508
+ strokeWidth?: number;
509
+ }
510
+ /**
511
+ * §7.6 pushbutton (Story 3.9 Task 2) — a READ-ONLY display of a command
512
+ * state (§1.2: never writes); its own vocabulary, distinct from
513
+ * `IndicatorLampTokens`'s ISA-18.2 alarm vocabulary, since a pushbutton
514
+ * mirrors a discrete command/feedback state rather than an alarm condition.
515
+ */
516
+ export interface PushbuttonStateVisual {
517
+ indicatorColor: string;
518
+ label: string;
519
+ }
520
+ /** pushbutton (Story 3.9 Task 2) — raised body + recessed indicator window (§7.6 bevel, both directions on one element). */
521
+ export interface PushbuttonTokens {
522
+ raised: PanelChromeTokens;
523
+ window: PanelChromeTokens;
524
+ states: Record<string, PushbuttonStateVisual>;
525
+ }
526
+ /** selector-switch (Story 3.9 Task 2) — knob position from a `state` map; each position is an angle (not a color — AD-3's color/label pairing doesn't apply to a purely mechanical position read), always paired with a text label. */
527
+ export interface SelectorSwitchStateVisual {
528
+ angleDeg: number;
529
+ label: string;
530
+ }
531
+ export interface SelectorSwitchTokens {
532
+ raised: PanelChromeTokens;
533
+ knobColor: string;
534
+ pointerColor: string;
535
+ states: Record<string, SelectorSwitchStateVisual>;
536
+ /** AD-7 fix (architecture-code-audit-2026-08-27): the pointer line's stroke width. Optional — falls back to the pre-fix literal. */
537
+ strokeWidth?: number;
538
+ }
539
+ /**
540
+ * motor-starter-panel (Story 3.9 Task 2, AC2) — mirrors a pump/driven-
541
+ * equipment element's state via a SHARED tag (Dev Notes: "panels are
542
+ * separate elements bound to shared tags", never a component-internal
543
+ * link). Keyed the SAME as `PumpTokens.states`/`DrivenEquipmentTokens.states`
544
+ * (stopped/starting/running/tripped/unavailable) so a scene can declare the
545
+ * panel's `state` binding with the identical `map` as the pump it mirrors.
546
+ */
547
+ export interface MotorStarterPanelStateVisual {
548
+ lampColor: string;
549
+ blink: boolean;
550
+ label: string;
551
+ }
552
+ export interface MotorStarterPanelTokens {
553
+ raised: PanelChromeTokens;
554
+ arrowColor: string;
555
+ states: Record<string, MotorStarterPanelStateVisual>;
556
+ }
557
+ /** §6.1 conveyance/controls batch (Story 3.9 Task 2) — pushbutton/selector-switch/motor-starter-panel share one namespace, the panel-chrome group. */
558
+ export interface ControlsTokens {
559
+ pushbutton: PushbuttonTokens;
560
+ selectorSwitch: SelectorSwitchTokens;
561
+ motorStarterPanel: MotorStarterPanelTokens;
562
+ }
563
+ /**
564
+ * §6.1 breaker (Story 3.10 Task 1/2) — three states. The topology-facing
565
+ * KEY for "contacts open, no current flows" is deliberately spelled
566
+ * `'closed'` — NOT `'open'` — because `_registerFlowStateTracking`
567
+ * (`scada-view.ts`, Story 2.4) already hardcodes that exact literal string
568
+ * as its isolation sentinel (a valve's OWN `'closed'` state means "blocks
569
+ * flow"; reusing the identical string is what makes a breaker cut its
570
+ * downstream topology edges with zero new inference code — Dev Notes:
571
+ * "breakers ARE valves to the topology"). `'energized'` is the real-world
572
+ * "contacts closed, current flows" condition (does NOT isolate).
573
+ * `'tripped'` is the fault-open visual (labeled distinctly) but is NOT
574
+ * wired to isolation — only ONE state name can carry the shared sentinel
575
+ * without a second, new inference path, and Task 2's own wording only
576
+ * requires "open breaker de-energizes downstream" (protection-relay-aware
577
+ * trip propagation is explicitly out of scope, Dev Notes Scope boundary).
578
+ * `label` decouples the operator-facing text ("Open"/"Closed"/"Tripped")
579
+ * from this key, same as every other `*StateVisual` in this file.
580
+ */
581
+ export interface BreakerStateVisual {
582
+ indicatorColor: string;
583
+ label: string;
584
+ }
585
+ export interface BreakerTokens {
586
+ /** Keyed by state name: closed (topology-isolating; real "open") / energized (real "closed") / tripped. */
587
+ states: Record<string, BreakerStateVisual>;
588
+ bodyColor: string;
589
+ bodyOutlineColor: string;
590
+ /** AD-7 fix (architecture-code-audit-2026-08-27): body outline weight; leads/bridge derive a heavier weight from it. Optional — falls back to the pre-fix literal. */
591
+ strokeWidth?: number;
592
+ }
593
+ /** §6.1 transformer/busbar shared two-state energized/de-energized visual — glow color+opacity ALWAYS paired with a text label (AD-3). */
594
+ export interface EnergizationStateVisual {
595
+ glowColor: string;
596
+ glowOpacity: number;
597
+ label: string;
598
+ }
599
+ /** transformer (Story 3.10 Task 1) — two-coil symbol; conductor leads style from the electrical medium (2.3), energized highlight glow behind the coils. */
600
+ export interface TransformerTokens {
601
+ coilColor: string;
602
+ outlineColor: string;
603
+ /** Keyed by state name: de-energized / energized. */
604
+ states: Record<string, EnergizationStateVisual>;
605
+ /** AD-7 fix (architecture-code-audit-2026-08-27): coil outline weight; leads derive a heavier weight from it. Optional — falls back to the pre-fix literal. */
606
+ strokeWidth?: number;
607
+ }
608
+ /** busbar (Story 3.10 Task 1) — heavy conductor bar; connection points are scene-authored ports along its length, not primitive-computed. */
609
+ export interface BusbarTokens {
610
+ deenergizedColor: string;
611
+ outlineColor: string;
612
+ /** Keyed by state name: de-energized / energized. */
613
+ states: Record<string, EnergizationStateVisual>;
614
+ /** AD-7 fix (architecture-code-audit-2026-08-27): the bar's own stroke width. Optional — falls back to the pre-fix literal. */
615
+ strokeWidth?: number;
616
+ }
617
+ /**
618
+ * generator (Story 3.10 Task 1) — reuses `rotation-drive/base.ts`'s
619
+ * `buildRotationDrive` verbatim (Dev Notes: "running state via rotating
620
+ * base's lamp pattern") — a flow SOURCE to the topology exactly like a
621
+ * pump, so its OWN "not generating" state must literally resolve to
622
+ * `'stopped'` (the SAME sentinel `_registerFlowStateTracking` already
623
+ * checks for a source) — a natural, non-inverted mapping (unlike breaker's
624
+ * `'closed'` above), since "generator stopped" and "generator not
625
+ * generating" already mean the same thing in both plain English and the
626
+ * topology's vocabulary. Same shape as `DrivenEquipmentTokens`, own
627
+ * namespace per that established convention (Story 3.4).
628
+ */
629
+ export interface GeneratorTokens {
630
+ /** Keyed by state name: stopped/starting/running/tripped/unavailable. */
631
+ states: Record<string, DrivenEquipmentStateVisual>;
632
+ bodyEnergizedColor: string;
633
+ bodyDeenergizedColor: string;
634
+ rotorColor: string;
635
+ /** AD-7 fix (architecture-code-audit-2026-08-27): body outline weight. Optional — falls back to the pre-fix literal. */
636
+ strokeWidth?: number;
637
+ }
638
+ /** §6.1 electrical batch (Story 3.10) — breaker/transformer/busbar/generator; `readoutColor` is generator's optional RPM/power `readout` binding site (§16). */
639
+ export interface ElectricalTokens {
640
+ breaker: BreakerTokens;
641
+ transformer: TransformerTokens;
642
+ busbar: BusbarTokens;
643
+ generator: GeneratorTokens;
644
+ readoutColor: string;
645
+ }
646
+ /** §11 keyboard focus ring (Story 4.4 Task 4) — resolved into CSS custom properties on the host element at scene-build time (AD-7: core resolves tokens into shared CSS vars, never a primitive-level hex); a high-contrast outline offset from the symbol, legible on the theme's own background. */
647
+ export interface FocusRingTokens {
648
+ color: string;
649
+ widthPx: number;
650
+ offsetPx: number;
651
+ }
652
+ export interface ThemeTokens {
653
+ /** Theme identifier, kebab-case (e.g. "classic-hmi"). */
654
+ name: string;
655
+ /** Named palette tokens (general-purpose). */
656
+ palette: Record<string, string>;
657
+ background?: string;
658
+ focusRing?: FocusRingTokens;
659
+ pipe?: PipeTokens;
660
+ liquid?: LiquidTokens;
661
+ vessel?: VesselTokens;
662
+ pump?: PumpTokens;
663
+ /** Story 3.4 — pump-positive-displacement/compressor/turbine/motor's shared 5-state driven-equipment token namespace. */
664
+ drivenEquipment?: DrivenEquipmentTokens;
665
+ /** Story 3.4 — fan-axial/fan-centrifugal's shared 3-state token namespace (incl. blur-disc crossover tokens). */
666
+ fan?: FanTokens;
667
+ /** Story 3.5 — the six §6.1 valve types' shared token namespace. */
668
+ valve?: ValveTokens;
669
+ quality?: QualityTokens;
670
+ /** §7.4 medium registry — styling half (Story 2.3): pipe color/dash/animation-speed by medium name. */
671
+ medium?: MediumTokens;
672
+ panel?: PanelTokens;
673
+ offPage?: OffPageTokens;
674
+ /** Story 3.1 — `color-ramp` binding's token-defined color stops (AD-7). */
675
+ colorRamp?: ColorRampTokens;
676
+ /** Story 3.6 — gauge-analog's raised §7.6 face + alarm-zone coloring. */
677
+ gauge?: GaugeTokens;
678
+ /** Story 3.6 — the standalone indicator-lamp's ISA-18.2 state/blink-rate vocabulary. */
679
+ indicatorLamp?: IndicatorLampTokens;
680
+ /** Story 3.6 — gauge-digital's recessed §7.6 face + digit color. */
681
+ gaugeDigital?: GaugeDigitalTokens;
682
+ /** Story 3.6 — readout-panel's recessed §7.6 face + label/value colors. */
683
+ readoutPanel?: ReadoutPanelTokens;
684
+ /** Story 3.6 — bargraph's recessed §7.6 face + track/fill/threshold colors. */
685
+ bargraph?: BargraphTokens;
686
+ /** Story 3.6 — trend-mini's recessed §7.6 face + sparkline/axis colors. */
687
+ trendMini?: TrendMiniTokens;
688
+ /** Story 3.7 — heat-exchanger-shell-tube/-coil/boiler/furnace/condenser/cooling-tower. */
689
+ heat?: HeatTokens;
690
+ /** Story 3.7 — bag-filter/cyclone/scrubber/stack. */
691
+ filtration?: FiltrationTokens;
692
+ /** Story 3.9 — conveyor belt run. */
693
+ conveyor?: ConveyorTokens;
694
+ /** Story 3.9 — waste-feed screw-feeder. */
695
+ screwFeeder?: ScrewFeederTokens;
696
+ /** Story 3.9 — rectangular-section duct (reuses `pipe`'s gradient/strokeWidth). */
697
+ duct?: DuctTokens;
698
+ /** Story 3.9 — pushbutton/selector-switch/motor-starter-panel. */
699
+ controls?: ControlsTokens;
700
+ /** Story 3.10 — breaker/transformer/busbar/generator. */
701
+ electrical?: ElectricalTokens;
702
+ }
703
+ //# sourceMappingURL=tokens.d.ts.map