simple-circuit-engine 0.0.10 → 0.0.11

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/index.d.ts CHANGED
@@ -57,6 +57,7 @@ export declare abstract class AbstractCircuitController extends EventEmitter<Con
57
57
  get componentObject3Ds(): Map<UUID, THREE.Object3D>;
58
58
  get enodeObject3Ds(): Map<UUID, THREE.Object3D>;
59
59
  get wireObject3Ds(): Map<UUID, Line2>;
60
+ get visualContext(): VisualContext;
60
61
  protected get grid(): THREE.GridHelper | null;
61
62
  protected set grid(grid: THREE.GridHelper);
62
63
  /**
@@ -201,150 +202,6 @@ export declare abstract class AbstractCircuitController extends EventEmitter<Con
201
202
  protected onResize(_width: number, _height: number): void;
202
203
  }
203
204
 
204
- /**
205
- * Visual factory for AND gates components
206
- *
207
- * Creates:
208
- * - Gate mesh
209
- * - vcc, inputs and output pin groups
210
- * - Component hitbox for raycasting
211
- *
212
- * Animation:
213
- * - Emissive glow when Gate is high (based on simulation state)
214
- */
215
- export declare class And4GateVisualFactory extends AndGateVisualFactory {
216
- /** Shared open envelope geometry */
217
- protected readonly lowGeometry: THREE.ExtrudeGeometry;
218
- /** Shared transient envelope geometry */
219
- protected readonly transientGeometry: THREE.ExtrudeGeometry;
220
- /** Shared transient envelope geometry */
221
- protected readonly highGeometry: THREE.ExtrudeGeometry;
222
- /** Shared geometry for negative marker **/
223
- protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
224
- createVisual(component: Component): THREE.Object3D;
225
- /**
226
- * Get config form definition for Transistor (T026)
227
- *
228
- * @returns Form definition with activationLogic boolean field
229
- */
230
- getConfigFormDefinition(): ConfigFormDefinition | null;
231
- updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
232
- }
233
-
234
- /**
235
- * Visual factory for AND gates components
236
- *
237
- * Creates:
238
- * - Gate mesh
239
- * - vcc, inputs and output pin groups
240
- * - Component hitbox for raycasting
241
- *
242
- * Animation:
243
- * - Emissive glow when Gate is high (based on simulation state)
244
- */
245
- export declare class And8GateVisualFactory extends AndGateVisualFactory {
246
- /** Shared open envelope geometry */
247
- protected readonly lowGeometry: THREE.ExtrudeGeometry;
248
- /** Shared transient envelope geometry */
249
- protected readonly transientGeometry: THREE.ExtrudeGeometry;
250
- /** Shared transient envelope geometry */
251
- protected readonly highGeometry: THREE.ExtrudeGeometry;
252
- /** Shared geometry for negative marker **/
253
- protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
254
- createVisual(component: Component): THREE.Object3D;
255
- /**
256
- * Get config form definition for Transistor (T026)
257
- *
258
- * @returns Form definition with activationLogic boolean field
259
- */
260
- getConfigFormDefinition(): ConfigFormDefinition | null;
261
- updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
262
- }
263
-
264
- /**
265
- * Visual factory for AND gates components
266
- *
267
- * Creates:
268
- * - Gate mesh
269
- * - vcc, inputs and output pin groups
270
- * - Component hitbox for raycasting
271
- *
272
- * Animation:
273
- * - Emissive glow when Gate is high (based on simulation state)
274
- */
275
- export declare class AndGateVisualFactory extends ComponentVisualFactoryBase {
276
- /** Gate high color */
277
- protected static readonly HIGH_COLOR = 16777215;
278
- /** Gate high emissive intensity */
279
- protected static readonly HIGH_INTENSITY = 0.3;
280
- /** Shared open envelope geometry */
281
- protected readonly lowGeometry: THREE.ExtrudeGeometry;
282
- /** Shared transient envelope geometry */
283
- protected readonly transientGeometry: THREE.ExtrudeGeometry;
284
- /** Shared transient envelope geometry */
285
- protected readonly highGeometry: THREE.ExtrudeGeometry;
286
- /** Shared material for negative marker **/
287
- protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
288
- /** Shared geometry for negative marker **/
289
- protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
290
- defaultRotation(): number;
291
- createVisual(component: Component): THREE.Object3D;
292
- /**
293
- * Get config form definition for Transistor (T026)
294
- *
295
- * @returns Form definition with activationLogic boolean field
296
- */
297
- getConfigFormDefinition(): ConfigFormDefinition | null;
298
- /**
299
- * Map core config to form data
300
- * Converts "positive"/"negative" strings to boolean
301
- *
302
- * @param config - Core component config
303
- * @returns Form data with boolean activationLogic
304
- */
305
- mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
306
- /**
307
- * Map form data to core config
308
- * Converts boolean to "positive"/"negative" strings
309
- *
310
- * @param formData - Form data with boolean activationLogic
311
- * @returns Core config with string activationLogic
312
- */
313
- mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
314
- updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
315
- /**
316
- * Update animation based on simulation state
317
- *
318
- * @param object3D - The Object3D created by createVisual()
319
- * @param state - The component current simulation state
320
- */
321
- updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
322
- /**
323
- * Find the envelope mesh within the component group
324
- *
325
- * @param object3D - The Object3D group created by createVisual()
326
- * @returns The envelope mesh if found, null otherwise
327
- *
328
- * @remarks
329
- * Searches for a mesh with userData.part === 'envelope'
330
- */
331
- protected findEnvelopeMesh(object3D: THREE.Object3D): (THREE.Mesh & {
332
- material: THREE.MeshStandardMaterial;
333
- }) | null;
334
- /**
335
- * Find the negative marker mesh within the component group
336
- *
337
- * @param object3D - The Object3D group created by createVisual()
338
- * @returns The negative marker mesh if found, null otherwise
339
- *
340
- * @remarks
341
- * Searches for a mesh with userData.part === 'negativeMarker'
342
- */
343
- protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
344
- material: THREE.MeshStandardMaterial;
345
- }) | null;
346
- }
347
-
348
205
  /**
349
206
  * Visual factory for Battery components
350
207
  *
@@ -355,7 +212,8 @@ export declare class AndGateVisualFactory extends ComponentVisualFactoryBase {
355
212
  * - Component hitbox for raycasting
356
213
  */
357
214
  export declare class BatteryVisualFactory extends ComponentVisualFactoryBase {
358
- createVisual(component: Component): THREE.Object3D;
215
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
216
+ private createPinsVisual;
359
217
  }
360
218
 
361
219
  /**
@@ -381,21 +239,21 @@ declare class BehaviorRegistry {
381
239
  * @throws TypeError if behavior is null/undefined or componentType is empty
382
240
  * @returns The registry instance for chaining
383
241
  */
384
- register(behavior: ComponentBehavior): BehaviorRegistry;
242
+ register(behavior: IComponentBehavior): BehaviorRegistry;
385
243
  /**
386
244
  * Register multiple behaviors at once.
387
245
  * Convenience method for bulk registration.
388
246
  *
389
247
  * @param behaviors - Array of behaviors to register
390
248
  */
391
- registerAll(behaviors: ComponentBehavior[]): void;
249
+ registerAll(behaviors: IComponentBehavior[]): void;
392
250
  /**
393
251
  * Get the behavior for a component type.
394
252
  *
395
253
  * @param componentType - Type identifier (e.g., "battery", "led")
396
254
  * @returns The registered behavior, or undefined if not found
397
255
  */
398
- get(componentType: string): ComponentBehavior | undefined;
256
+ get(componentType: string): IComponentBehavior | undefined;
399
257
  /**
400
258
  * Check if a behavior is registered for a component type.
401
259
  *
@@ -428,28 +286,6 @@ declare class BehaviorRegistry {
428
286
  size(): number;
429
287
  }
430
288
 
431
- /**
432
- * Result returned by component behavior evaluation.
433
- * Describes state changes and future events to schedule.
434
- *
435
- * @public
436
- */
437
- declare interface BehaviorResult {
438
- /**
439
- * Updated component state
440
- */
441
- readonly componentState: ComponentState;
442
- /**
443
- * boolean indicating
444
- * if the component state has changed (or events scheduled ?)
445
- */
446
- hasChanged: boolean;
447
- /**
448
- * Events to schedule for future ticks (e.g., delayed transitions).
449
- */
450
- readonly scheduledEvents: ReadonlyArray<ScheduledEvent>;
451
- }
452
-
453
289
  /**
454
290
  * Sentinel value representing the "Branching Point" pseudo-component entry.
455
291
  * When selected, BuildTool creates a branching point instead of a component.
@@ -516,92 +352,6 @@ export declare class BranchingPointVisualFactory {
516
352
  private getColorForSourceType;
517
353
  }
518
354
 
519
- /**
520
- * Visual factory for Buffer/Inverter components
521
- *
522
- * Creates:
523
- * - Buffer trapezoid or Inverter triangle extrude geom mesh
524
- * - Vcc, input and output pin group
525
- * - Component hitbox for raycasting
526
- *
527
- * Animation:
528
- * - Emissive glow when component is high (based on simulation state)
529
- */
530
- export declare class BufferVisualFactory extends ComponentVisualFactoryBase {
531
- /** Buffer high color (white glow) */
532
- private static readonly HIGH_COLOR;
533
- /** Buffer high emissive intensity */
534
- private static readonly HIGH_INTENSITY;
535
- /** Shared low Buffer envelope geometry */
536
- private readonly bufferLowGeometry;
537
- /** Shared transient Buffer envelope geometry */
538
- private readonly bufferTransientGeometry;
539
- /** Shared high Buffer envelope geometry */
540
- private readonly bufferHighGeometry;
541
- /** Shared low Inverter envelope geometry */
542
- private readonly inverterLowGeometry;
543
- /** Shared transient Inverter envelope geometry */
544
- private readonly inverterTransientGeometry;
545
- /** Shared high Inverter envelope geometry */
546
- private readonly inverterHighGeometry;
547
- /** Shared geometry for negative marker **/
548
- protected readonly negativeMarkerGeometry: THREE.SphereGeometry;
549
- createVisual(component: Component): THREE.Object3D;
550
- private replaceEnvelope;
551
- /**
552
- * Get config form definition for Buffer
553
- *
554
- * @returns Form definition with activationLogic boolean field
555
- */
556
- getConfigFormDefinition(): ConfigFormDefinition | null;
557
- /**
558
- * Map core config to form data (T026)
559
- * Converts "positive"/"negative" strings to boolean
560
- *
561
- * @param config - Core component config
562
- * @returns Form data with boolean activationLogic
563
- */
564
- mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
565
- /**
566
- * Map form data to core config (T026)
567
- * Converts boolean to "positive"/"negative" strings
568
- *
569
- * @param formData - Form data with boolean activationLogic
570
- * @returns Core config with string activationLogic
571
- */
572
- mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
573
- updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
574
- /**
575
- * Update Buffer animation based on simulation state
576
- *
577
- * @param object3D - The Object3D created by createVisual()
578
- * @param state - The Buffer's current simulation state
579
- */
580
- updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
581
- /**
582
- * Find the envelope mesh within the component group
583
- *
584
- * @param object3D - The Object3D group created by createVisual()
585
- * @returns The envelope mesh if found, null otherwise
586
- *
587
- * @remarks
588
- * Searches for a mesh with userData.part === 'envelope'
589
- */
590
- private findEnvelopeMesh;
591
- /**
592
- * Find the negative marker mesh within the component group
593
- *
594
- * @param object3D - The Object3D group created by createVisual()
595
- * @returns The negative marker mesh if found, null otherwise
596
- *
597
- * @remarks
598
- * Searches for a mesh with userData.part === 'negativeMarker'
599
- */
600
- protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
601
- material: THREE.MeshStandardMaterial;
602
- }) | null;
603
- }
604
-
605
355
  /**
606
356
  * Unified tool for building circuits
607
357
  * Implements all circuit editing functionality in a single tool
@@ -1016,7 +766,7 @@ declare class Circuit {
1016
766
  /**
1017
767
  * Create a new empty circuit.
1018
768
  */
1019
- constructor(name?: string);
769
+ constructor(options: CircuitOptions);
1020
770
  get name(): string;
1021
771
  set name(value: string);
1022
772
  /**
@@ -1047,6 +797,13 @@ declare class Circuit {
1047
797
  * ```
1048
798
  */
1049
799
  addComponent(type: ComponentType, position: Position, rotation: Rotation, config?: Map<string, string> | undefined): Component;
800
+ /**
801
+ * Resolve and update the transitionSpan config for a component
802
+ * if automatic resolution returns undefined nothing is done on the component
803
+ *
804
+ * @param component - Component to resolve transitionSpan for
805
+ */
806
+ resolveTransitionSpan(component: Component): void;
1050
807
  /**
1051
808
  * Remove a component from the circuit.
1052
809
  *
@@ -1343,12 +1100,7 @@ declare class Circuit {
1343
1100
  * localStorage.setItem('my-circuit', JSON.stringify(json));
1344
1101
  * ```
1345
1102
  */
1346
- toJSON(): {
1347
- metadata: object;
1348
- components: object[];
1349
- enodes: object[];
1350
- wires: object[];
1351
- };
1103
+ toJSON(): ICircuit;
1352
1104
  /**
1353
1105
  * Deserialize circuit from JSON.
1354
1106
  *
@@ -1363,12 +1115,7 @@ declare class Circuit {
1363
1115
  * const circuit = Circuit.fromJSON(json);
1364
1116
  * ```
1365
1117
  */
1366
- static fromJSON(json: {
1367
- metadata: ICircuitMetadata;
1368
- components: object[];
1369
- enodes: object[];
1370
- wires?: object[];
1371
- }): Circuit;
1118
+ static fromJSON(json: ICircuit): Circuit;
1372
1119
  }
1373
1120
 
1374
1121
  /**
@@ -1837,39 +1584,42 @@ export declare interface CircuitEngineEventMap extends ControllerEventMap {
1837
1584
  modeChanged: ModeChangedEvent;
1838
1585
  }
1839
1586
 
1840
- /**
1841
- * Circuit metadata placeholder
1842
- */
1843
- declare class CircuitMetadata {
1844
- name: string;
1587
+ declare class CircuitMetadata implements ICircuitMetadata {
1588
+ version: string;
1589
+ options: CircuitOptions;
1845
1590
  size: number;
1846
1591
  divisions: number;
1847
1592
  cameraOptions: CameraOptions;
1848
1593
  /**
1849
1594
  * Create a new CircuitMetadata holding general information about the Circuit.
1850
1595
  *
1851
- * @param name - Name of the circuit
1596
+ * @param version - Circuit version
1597
+ * @param options - Circuit options
1852
1598
  * @param size - Size of the circuit grid
1853
1599
  * @param divisions - Divisions in the circuit grid
1854
1600
  * @param cameraOptions - Camera Options at startup
1855
1601
  * @throws {TypeError} If size or divisions are not integers
1856
1602
  */
1857
- constructor(name: string, size: number, divisions: number, cameraOptions: CameraOptions);
1858
- toJSON(): {
1859
- name: string;
1860
- size: number;
1861
- divisions: number;
1862
- cameraOptions: ICameraOptions;
1863
- };
1864
- static fromJSON(json: {
1865
- name: string;
1866
- size: number;
1867
- divisions: number;
1868
- cameraOptions: ICameraOptions;
1869
- }): CircuitMetadata;
1603
+ constructor(version: string, options: CircuitOptions, size: number, divisions: number, cameraOptions: CameraOptions);
1604
+ toJSON(): ICircuitMetadata;
1605
+ static fromJSON(json: ICircuitMetadata): CircuitMetadata;
1870
1606
  toString(): string;
1871
1607
  }
1872
1608
 
1609
+ declare class CircuitOptions implements ICircuitOptions {
1610
+ name: string;
1611
+ defaultLogicFamily: LogicFamily;
1612
+ /**
1613
+ * Create new circuit options.
1614
+ *
1615
+ * @param name - Circuit name (default: Untitled Circuit)
1616
+ * @param defaultLogicFamily - Circuit default logic family (default: CMOS1)
1617
+ */
1618
+ constructor(name?: string, defaultLogicFamily?: LogicFamily);
1619
+ toJSON(): ICircuitOptions;
1620
+ static fromJSON(json: ICircuitOptions): CircuitOptions;
1621
+ }
1622
+
1873
1623
  /**
1874
1624
  * Simulation Circuit Runner Controller Implementation
1875
1625
  *
@@ -2285,10 +2035,14 @@ declare class Component {
2285
2035
  * Configuration parameters for this component instance.
2286
2036
  *
2287
2037
  * This map holds key-value pairs representing configurable settings
2288
- * The available configuration keys depend on the component type see ComponentTypeMetadata for details.
2038
+ * The available configuration keys depend on the component type see IComponentTypeMetadata for details.
2289
2039
  *
2290
2040
  */
2291
2041
  config: Map<string, string>;
2042
+ /**
2043
+ * allow to flag a component as non editable (feature to implement)
2044
+ */
2045
+ editable: boolean;
2292
2046
  /**
2293
2047
  * Create a new component.
2294
2048
  *
@@ -2301,6 +2055,7 @@ declare class Component {
2301
2055
  * @param rotation - Orientation angle (integer degrees)
2302
2056
  * @param pins - Array of pin ENode UUIDs
2303
2057
  *
2058
+ * @param editable
2304
2059
  * @example
2305
2060
  * ```typescript
2306
2061
  * // Usually created via Circuit:
@@ -2319,7 +2074,7 @@ declare class Component {
2319
2074
  * );
2320
2075
  * ```
2321
2076
  */
2322
- constructor(type: ComponentType, position: Position, rotation: Rotation, pins: ReadonlyArray<UUID>);
2077
+ constructor(type: ComponentType, position: Position, rotation: Rotation, pins: ReadonlyArray<UUID>, editable?: boolean);
2323
2078
  getPinLabel(pinId: UUID): string | undefined;
2324
2079
  setAllParameters(config: Map<string, string>): void;
2325
2080
  setParameter(key: string, value: string): void;
@@ -2365,117 +2120,15 @@ declare class Component {
2365
2120
  * // }
2366
2121
  * ```
2367
2122
  */
2368
- toJSON(): {
2369
- id: UUID;
2370
- type: ComponentType;
2371
- position: {
2372
- x: number;
2373
- y: number;
2374
- };
2375
- rotation: number;
2376
- pins: UUID[];
2377
- config: {
2378
- [key: string]: string;
2379
- };
2380
- };
2123
+ toJSON(): IComponent;
2381
2124
  /**
2382
2125
  * Deserialize component from JSON.
2383
2126
  *
2384
2127
  * @param json - Component data
2385
2128
  * @returns Component instance
2386
2129
  *
2387
- * @example
2388
- * ```typescript
2389
- * const json = {
2390
- * id: "550e8400-...",
2391
- * type: "battery",
2392
- * position: { x: 10, y: 20 },
2393
- * rotation: 90,
2394
- * pins: ['1b4f6f3c-ce ....', '2c5e7g4d-df ...'],
2395
- * config: { "voltage": "5V" }
2396
- * };
2397
- *
2398
- * const component = Component.fromJSON(json);
2399
- * console.log(component.position.x); // 10
2400
- * ```
2401
- */
2402
- static fromJSON(json: {
2403
- id: UUID;
2404
- type: ComponentType;
2405
- position: {
2406
- x: number;
2407
- y: number;
2408
- };
2409
- rotation: number;
2410
- pins: UUID[];
2411
- config: {
2412
- [key: string]: string;
2413
- };
2414
- }): Component;
2415
- }
2416
-
2417
- /**
2418
- * Component behavior interface for registry-based extensibility.
2419
- * Each component type (Battery, LED, Switch, etc.) implements this interface.
2420
- *
2421
- * Behaviors are stateless - all state is stored in ComponentState and SimulationState.
2422
- * The behavior's job is to compute new states based on current inputs and component state.
2423
- *
2424
- * @public
2425
- */
2426
- declare interface ComponentBehavior {
2427
- /**
2428
- * Component type this behavior handles (e.g., "battery", "led", "switch").
2429
- * Used as the key in BehaviorRegistry.
2430
- */
2431
- readonly componentType: ComponentType;
2432
- /**
2433
- * Create initial state for a component instance.
2434
- * Called when simulation is initialized.
2435
- * Initial state may use component satic configuration (e.g., initial switch position).
2436
- *
2437
- * @param component - The component to initialize
2438
- * @returns Initial ComponentState for this component
2439
- */
2440
- createInitialState(component: Component): ComponentState;
2441
- /**
2442
- * Determine if conductivity is allowed between two pins of the component.
2443
- * Called during simulation when evaluating electrical connectivity.
2444
- * @param component
2445
- * @param state current component state
2446
- * @param conductivityType
2447
- * @param pinId
2448
- * @param otherPinId
2449
- */
2450
- allowConductivity(component: Component, state: ComponentState, conductivityType: ENodeSourceType, pinId: string, otherPinId: string): boolean;
2451
- /**
2452
- * Define component state change in response to its pins state change (after propagateConductivity)
2453
- *
2454
- * @param component - The component being evaluated
2455
- * @param state - component state prior to this evaluation
2456
- * @param nodeStates - Current electrical states of all ENodes in the simulation
2457
- * @param targetTick - target tick
2458
- * @returns Result containing updated state and scheduled events
2459
- */
2460
- onPinsChange(component: Component, state: ComponentState, nodeStates: ReadonlyMap<UUID, NodeElectricalState>, targetTick: number): BehaviorResult;
2461
- /**
2462
- * Define component state change in response to a User command being received
2463
- *
2464
- * @param component - The component being evaluated
2465
- * @param state - component state prior to this evaluation
2466
- * @param command - UserCommand to process
2467
- * @returns Result containing updated state and scheduled events
2468
- */
2469
- onUserCommand(component: Component, state: ComponentState, command: UserCommand): BehaviorResult;
2470
- /**
2471
- * Define component state change in response to a ScheduledEvent firing at ready
2472
- *
2473
- * @param component - The component being evaluated
2474
- * @param state - component state prior to this evaluation
2475
- * @param event - firing ScheduledEvent to process
2476
- * @returns Result containing updated state and scheduled events
2477
2130
  */
2478
- onEventFiring(component: Component, state: ComponentState, event: ScheduledEvent): BehaviorResult;
2131
+ static fromJSON(json: IComponent): Component;
2479
2132
  }
2480
2133
 
2481
2134
  /**
@@ -2602,37 +2255,31 @@ declare abstract class ComponentState {
2602
2255
  }
2603
2256
 
2604
2257
  /**
2605
- * Enumeration of available component types.
2258
+ * Enumeration of ALL available component types.
2606
2259
  *
2607
2260
  * Each component type represents a specific electrical element that can be
2608
2261
  * placed in a circuit (battery, LED, transistor, etc.).
2609
- *
2610
- * @example
2611
- * ```typescript
2612
- * const type = ComponentType.Battery;
2613
- * const metadata = COMPONENT_TYPE_METADATA[type];
2614
- * console.log(metadata.name); // "Battery"
2615
- * console.log(metadata.pins); // Map([["cathode", ENodeSourceType.Voltage], ["anode", ENodeSourceType.Current]])
2616
- * ```
2617
2262
  */
2618
2263
  declare enum ComponentType {
2619
2264
  Cube = "cube",// no pins component for testing purposes mainly
2620
2265
  Label = "label",// decorative text label with no pins
2621
2266
  Battery = "battery",
2622
2267
  Switch = "switch",
2268
+ DoubleThrowSwitch = "doubleThrowSwitch",
2623
2269
  Lightbulb = "lightbulb",
2624
2270
  Relay = "relay",
2625
- Transistor = "transistor",
2626
- Buffer = "buffer",
2627
2271
  SmallLED = "smallLED",
2628
2272
  RectangleLED = "rectangleLED",
2629
- AndGate = "andGate",
2630
- And4Gate = "and4Gate",
2631
- And8Gate = "and8Gate",
2632
- OrGate = "orGate",
2633
- Or4Gate = "or4Gate",
2634
- Or8Gate = "or8Gate",
2635
- XorGate = "xorGate"
2273
+ Inverter = "inverter",
2274
+ NandGate = "nandGate",
2275
+ Nand4Gate = "nand4Gate",
2276
+ Nand8Gate = "nand8Gate",
2277
+ NorGate = "norGate",
2278
+ Nor4Gate = "nor4Gate",
2279
+ Nor8Gate = "nor8Gate",
2280
+ XorGate = "xorGate",
2281
+ Xor4Gate = "xor4Gate",
2282
+ Xor8Gate = "xor8Gate"
2636
2283
  }
2637
2284
 
2638
2285
  /**
@@ -2656,7 +2303,7 @@ declare enum ComponentType {
2656
2303
  * @example
2657
2304
  * ```typescript
2658
2305
  * export class BatteryVisualFactory extends ComponentVisualFactoryBase {
2659
- * createVisual(component: Component): THREE.Object3D {
2306
+ * createVisual(component: Component, context?: VisualContext): THREE.Object3D {
2660
2307
  * const group = new THREE.Group();
2661
2308
  * // ... create battery-specific visual
2662
2309
  * return group;
@@ -2679,7 +2326,7 @@ declare abstract class ComponentVisualFactoryBase implements IComponentVisualFac
2679
2326
  * Create the Three.js visual representation for a component
2680
2327
  * Must be implemented by subclasses
2681
2328
  */
2682
- abstract createVisual(component: Component): THREE.Object3D;
2329
+ abstract createVisual(component: Component, context: VisualContext): THREE.Object3D;
2683
2330
  /**
2684
2331
  * By default no visual configuration-based updates is needed
2685
2332
  */
@@ -2716,6 +2363,10 @@ declare abstract class ComponentVisualFactoryBase implements IComponentVisualFac
2716
2363
  * @param object3D - The component's root Three.js object
2717
2364
  */
2718
2365
  removeSelection(object3D: THREE.Object3D): void;
2366
+ /**
2367
+ * @private
2368
+ */
2369
+ private pointPinGroupToward;
2719
2370
  /**
2720
2371
  * Create a pin group with hitbox and visual sphere
2721
2372
  *
@@ -2724,20 +2375,30 @@ declare abstract class ComponentVisualFactoryBase implements IComponentVisualFac
2724
2375
  * - Hemisphere visual (blue sphere)
2725
2376
  * - Hover callback in userData
2726
2377
  *
2727
- * @param componentId - UUID of the parent component
2728
- * @param pinId - UUID of this pin/enode
2729
- * @param label - Human-readable label (e.g., 'input', 'output', 'cathode')
2730
- * @param sourceType - Optional source type (voltage/current) : if provided this pin will be locked to that type
2378
+ * @param node - ENode to create as visual pin
2379
+ * @param pointsTo - rotate pin to make it point the wanted direction
2731
2380
  * @param visualRotation - if set rotate the visual of the pin to adjust display without affecting hitbox
2732
2381
  * @returns THREE.Group configured as pin group
2733
2382
  */
2734
- protected createPinGroup(componentId: string, pinId: string, label: string, sourceType?: ENodeSourceType | null, visualRotation?: THREE.Euler | null): THREE.Group;
2383
+ protected createPinGroup(node: ENode, pointsTo?: Direction2D, visualRotation?: THREE.Euler | null): THREE.Group;
2384
+ /**
2385
+ * Utility to create semi spheres visually closing pins
2386
+ * @param pinGroup
2387
+ * @param material
2388
+ * @protected
2389
+ */
2390
+ protected createPinCounterpart(pinGroup: THREE.Group, material: THREE.MeshStandardMaterial): THREE.Mesh | null;
2735
2391
  /**
2736
2392
  * Find pin group by label within a component Object3D
2737
2393
  * @param object3D
2738
2394
  * @param label
2739
2395
  */
2740
2396
  findPinGroup(object3D: THREE.Object3D, label: string): THREE.Group | null;
2397
+ /**
2398
+ * fin pin inner visual from within its pin group
2399
+ * @param pinGroup
2400
+ */
2401
+ findPinVisualFromGroup(pinGroup: THREE.Group): THREE.Mesh | null;
2741
2402
  /**
2742
2403
  * Find pin group visual by label within a component Object3D
2743
2404
  * @param object3D
@@ -2761,20 +2422,20 @@ declare abstract class ComponentVisualFactoryBase implements IComponentVisualFac
2761
2422
  protected pinColorForSourceType(sourceType: ENodeSourceType | null): number;
2762
2423
  protected pinColorForElectricalState(state: 'current' | 'voltage' | 'vc' | 'idle'): number;
2763
2424
  /**
2764
- * Updates the visual color of a component pin based on its source type.
2425
+ * Updates the visual color of a component pin based on its sourceType type.
2765
2426
  *
2766
- * This method changes the pin's material color to reflect the source type:
2767
- * - null/undefined: bronze (default pin color)
2427
+ * This method changes the pin's material color to reflect the sourceType type:
2428
+ * - null/undefined: copper (default pin color)
2768
2429
  * - Voltage: red
2769
2430
  * - Current: blue
2770
2431
  *
2771
2432
  * @param pinGroup - The THREE.Group containing the pin visual (created by createPinGroup)
2772
- * @param sourceType - The new source type (null for no source)
2433
+ * @param sourceType - The new sourceType (null for no sourceType)
2773
2434
  *
2774
2435
  * @remarks
2775
2436
  * - Searches for the child mesh with userData.type === 'enode'
2776
2437
  * - Updates both color and emissive properties for visual consistency
2777
- * - If sourceType is null/undefined, restores default bronze pin color
2438
+ * - If sourceType is null/undefined, restores default copper pin color
2778
2439
  * - Color scheme matches BranchingPointVisualFactory for consistency
2779
2440
  */
2780
2441
  updatePinSourceType(pinGroup: THREE.Object3D, sourceType: ENodeSourceType | null): void;
@@ -2798,7 +2459,7 @@ declare abstract class ComponentVisualFactoryBase implements IComponentVisualFac
2798
2459
  *
2799
2460
  * Override in subclasses that have configurable options.
2800
2461
  */
2801
- getConfigFormDefinition(): ConfigFormDefinition | null;
2462
+ getConfigFormDefinition(_config?: Map<string, string>): ConfigFormDefinition | null;
2802
2463
  /**
2803
2464
  * Map core config to form data (default: identity mapping)
2804
2465
  *
@@ -2836,6 +2497,8 @@ export declare interface ConfigFieldDefinition {
2836
2497
  max?: number;
2837
2498
  /** Step increment for number type */
2838
2499
  step?: number;
2500
+ /** Whether this field is read-only in the form */
2501
+ disabled?: boolean;
2839
2502
  }
2840
2503
 
2841
2504
  /**
@@ -2960,7 +2623,7 @@ export declare interface ControllerEventMap {
2960
2623
  tick: number;
2961
2624
  dirty: unknown;
2962
2625
  };
2963
- simulationUserCommand: UserCommand;
2626
+ simulationUserCommand: IUserCommand;
2964
2627
  simulationStopped: {
2965
2628
  tick: number;
2966
2629
  };
@@ -3049,6 +2712,79 @@ export declare class DefaultVisualFactory extends ComponentVisualFactoryBase {
3049
2712
  updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
3050
2713
  }
3051
2714
 
2715
+ /**
2716
+ * convenience to control standard rotations of meshes on X-Z plan
2717
+ */
2718
+ declare type Direction2D = 'right' | 'bottom' | 'left' | 'top';
2719
+
2720
+ /**
2721
+ * Visual factory for Double Switch components
2722
+ *
2723
+ * Creates:
2724
+ * - 2 * Input pole (sphere)
2725
+ * - Output pole (box)
2726
+ * - Contactor (cylinder, rotatable for animation)
2727
+ * - Input pin group
2728
+ * - Output pin group
2729
+ * - Component hitbox for raycasting
2730
+ *
2731
+ * Animation:
2732
+ * - Rotates contactor based on open/closed state
2733
+ */
2734
+ export declare class DoubleThrowSwitchVisualFactory extends ComponentVisualFactoryBase {
2735
+ /** Rotation for switch to input 1 */
2736
+ private readonly INPUT1_ROTATION;
2737
+ /** Rotation for switch toggling */
2738
+ private readonly INTERMEDIATE_ROTATION;
2739
+ /** Rotation for switch to input 2 */
2740
+ private readonly INPUT2_ROTATION;
2741
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
2742
+ private createPinsVisual;
2743
+ /**
2744
+ * Get config form definition for Double Switch
2745
+ *
2746
+ * @returns Form definition with initialState boolean field
2747
+ */
2748
+ getConfigFormDefinition(): ConfigFormDefinition | null;
2749
+ /**
2750
+ * Map core config to form data (T024)
2751
+ * Converts "input1"/"input2" strings to boolean
2752
+ *
2753
+ * @param config - Core component config
2754
+ * @returns Form data with boolean initialState
2755
+ */
2756
+ mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
2757
+ /**
2758
+ * Map form data to core config (T024)
2759
+ * Converts boolean to "input1"/"input2" strings
2760
+ *
2761
+ * @param formData - Form data with boolean initialState
2762
+ * @returns Core config with string initialState
2763
+ */
2764
+ mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
2765
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
2766
+ /**
2767
+ * Update switch animation based on simulation state
2768
+ *
2769
+ * @param object3D - The Object3D created by createVisual()
2770
+ * @param state - The Switch's current simulation state, or null in edition mode
2771
+ *
2772
+ * @remarks
2773
+ * Rotates the contactor group to visually represent input1/2 state
2774
+ */
2775
+ updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
2776
+ /**
2777
+ * Find the contactor group within the component group
2778
+ *
2779
+ * @param object3D - The Object3D group created by createVisual()
2780
+ * @returns The contactor's parent group if found, null otherwise
2781
+ *
2782
+ * @remarks
2783
+ * Searches for a mesh with userData.part === 'contactor' and returns its parent
2784
+ */
2785
+ private findContactorGroup;
2786
+ }
2787
+
3052
2788
  /**
3053
2789
  * Operating mode of the CircuitEngine
3054
2790
  * - 'edit': Static circuit editing mode (tools, selection, manipulation)
@@ -3073,7 +2809,7 @@ export declare interface EngineOptions {
3073
2809
  * Options passed to CircuitRunner when created
3074
2810
  * @default { enableHistory: false }
3075
2811
  */
3076
- runnerOptions?: RunnerOptions;
2812
+ runnerOptions?: IRunnerOptions;
3077
2813
  }
3078
2814
 
3079
2815
  /**
@@ -3152,6 +2888,11 @@ declare class ENode {
3152
2888
  * Is the ENode a source of voltage or current?
3153
2889
  */
3154
2890
  source: ENodeSourceType | undefined;
2891
+ /**
2892
+ * Pin role classification: free, mainVcc, vcc, mainGnd, gnd, logicInput, logicOutput.
2893
+ * @readonly
2894
+ */
2895
+ readonly subtype: string;
3155
2896
  /**
3156
2897
  * Create a new electrical node.
3157
2898
  *
@@ -3164,6 +2905,7 @@ declare class ENode {
3164
2905
  * @param position - Grid position (branching points only)
3165
2906
  * @param source - Source type (Voltage/Current) or undefined
3166
2907
  *
2908
+ * @param subtype
3167
2909
  * @example
3168
2910
  * ```typescript
3169
2911
  * // Pin node (internal to Circuit)
@@ -3185,7 +2927,7 @@ declare class ENode {
3185
2927
  * );
3186
2928
  * ```
3187
2929
  */
3188
- constructor(type: ENodeType, component: UUID | undefined, pinLabel: string | undefined, position: Position | undefined, source?: ENodeSourceType | undefined);
2930
+ constructor(type: ENodeType, component: UUID | undefined, pinLabel: string | undefined, position: Position | undefined, source?: ENodeSourceType | undefined, subtype?: string);
3189
2931
  /**
3190
2932
  * Get the position of this electrical node.
3191
2933
  *
@@ -3252,17 +2994,7 @@ declare class ENode {
3252
2994
  * // }
3253
2995
  * ```
3254
2996
  */
3255
- toJSON(): {
3256
- id: UUID;
3257
- type: ENodeType;
3258
- component?: UUID | null;
3259
- pinLabel?: string | null;
3260
- position?: {
3261
- x: number;
3262
- y: number;
3263
- } | null;
3264
- source?: ENodeSourceType | null;
3265
- };
2997
+ toJSON(): IENode;
3266
2998
  /**
3267
2999
  * Deserialize ENode from JSON.
3268
3000
  *
@@ -3281,17 +3013,7 @@ declare class ENode {
3281
3013
  * const enode = ENode.fromJSON(json);
3282
3014
  * ```
3283
3015
  */
3284
- static fromJSON(json: {
3285
- id: UUID;
3286
- type: ENodeType;
3287
- component?: UUID;
3288
- pinLabel?: string;
3289
- position?: {
3290
- x: number;
3291
- y: number;
3292
- };
3293
- source?: ENodeSourceType;
3294
- }): ENode;
3016
+ static fromJSON(json: IENode): ENode;
3295
3017
  }
3296
3018
 
3297
3019
  /**
@@ -3304,48 +3026,23 @@ export declare interface EnodeHitboxUserData {
3304
3026
  label: string | null;
3305
3027
  }
3306
3028
 
3307
- /**
3308
- * ENode Source Type Enumeration
3309
- *
3310
- * Defines the two types of electrical pinSources in the circuit model.
3311
- *
3312
- * @module core/types/ENodeSourceType
3313
- */
3314
3029
  /**
3315
3030
  * Type of electrical pinSources in the circuit.
3316
3031
  *
3317
3032
  * ENodes have a sourceType which can be undefined or one of the following:
3318
- *
3319
3033
  * - **Voltage**: ENode that provides a voltage source to the circuit. All Enodes of this type are considered at the same positive potential.
3320
- *
3321
3034
  * - **Current**: Ground/neutral ENodes that provides a current source to the circuit. All Enodes of this type are considered as points at
3322
- * the same 0V potential and are points from where electrons enters the circuit.
3323
- *
3324
- * playback modules use these properties to determine where to draw voltage/current from.
3325
- *
3035
+ * the same 0V-GROUND potential and are points from where electrons enters the circuit.
3326
3036
  */
3327
3037
  declare enum ENodeSourceType {
3328
- /**
3329
- * Voltage pinSources
3330
- */
3331
3038
  Voltage = "Voltage",
3332
- /**
3333
- * Current pinSources
3334
- */
3335
3039
  Current = "Current"
3336
3040
  }
3337
3041
 
3338
- /**
3339
- * ENode Type Enumeration
3340
- *
3341
- * Defines the two types of electrical connection points in the circuit model.
3342
- *
3343
- * @module core/types/ENodeType
3344
- */
3345
3042
  /**
3346
3043
  * Type of electrical node (ENode) in the circuit.
3347
3044
  *
3348
- * ENodes represent atomic electrical connection points and come in two variants (immutable after node creation):
3045
+ * ENodes represent atomic electrical connection points and come in two variants (immutable after node creation)
3349
3046
  *
3350
3047
  * - **Pin**: Connection point belonging to a Component. Position is derived
3351
3048
  * from the parent component's position, rotation, and pin index. Automatically
@@ -3354,19 +3051,6 @@ declare enum ENodeSourceType {
3354
3051
  * - **BranchingPoint**: Junction point where wires split. Has an independent
3355
3052
  * position on the grid. Automatically created when wires are split, deleted
3356
3053
  * when no wires remain connected (orphaned).
3357
- *
3358
- * @example
3359
- * ```typescript
3360
- * // Pin node (belongs to component)
3361
- * if (node.type === ENodeType.Pin) {
3362
- * console.log('Component pin with label', node.pinLabel);
3363
- * }
3364
- *
3365
- * // Branching point (wire junction)
3366
- * if (node.type === ENodeType.BranchingPoint) {
3367
- * console.log('Branch at position', node.position);
3368
- * }
3369
- * ```
3370
3054
  */
3371
3055
  declare enum ENodeType {
3372
3056
  /**
@@ -3882,6 +3566,36 @@ export declare class HoverManager {
3882
3566
  private _isSameHover;
3883
3567
  }
3884
3568
 
3569
+ /**
3570
+ * Result returned by component behavior evaluation.
3571
+ * Describes state changes and future events to schedule.
3572
+ *
3573
+ * @public
3574
+ */
3575
+ declare interface IBehaviorResult {
3576
+ /**
3577
+ * Updated component state
3578
+ */
3579
+ readonly componentState: ComponentState;
3580
+ /**
3581
+ * boolean indicating
3582
+ * if the component state has changed (or events scheduled ?)
3583
+ */
3584
+ hasChanged: boolean;
3585
+ /**
3586
+ * boolean indicating that all pending events on this component should be cancelled
3587
+ * (example change of input during the rising/falling state of a gate)
3588
+ */
3589
+ shouldCancelPending: boolean;
3590
+ /**
3591
+ * Events to schedule for future ticks (e.g., delayed transitions).
3592
+ */
3593
+ readonly scheduledEvents: ReadonlyArray<IScheduledEvent>;
3594
+ }
3595
+
3596
+ /**
3597
+ * Circuit camera options (used to position camera at startup)
3598
+ */
3885
3599
  declare type ICameraOptions = {
3886
3600
  position: IPosition3D;
3887
3601
  lookAtPosition: IPosition3D;
@@ -3890,13 +3604,108 @@ declare type ICameraOptions = {
3890
3604
  far: number;
3891
3605
  };
3892
3606
 
3607
+ /** circuit type */
3608
+ declare type ICircuit = {
3609
+ metadata: ICircuitMetadata;
3610
+ components: Iterable<IComponent>;
3611
+ enodes: Iterable<IENode>;
3612
+ wires: Iterable<IWire>;
3613
+ };
3614
+
3615
+ /** circuit metadata type — combines user writable options and managed metadata */
3893
3616
  declare type ICircuitMetadata = {
3894
- name: string;
3617
+ version: string;
3618
+ options: ICircuitOptions;
3619
+ cameraOptions: ICameraOptions;
3895
3620
  size: number;
3896
3621
  divisions: number;
3897
- cameraOptions: ICameraOptions;
3898
3622
  };
3899
3623
 
3624
+ /**
3625
+ * User editable options for a Circuit
3626
+ */
3627
+ declare type ICircuitOptions = {
3628
+ name: string;
3629
+ defaultLogicFamily: LogicFamily;
3630
+ };
3631
+
3632
+ /** Interface defining a Component **/
3633
+ declare interface IComponent {
3634
+ id: UUID;
3635
+ type: ComponentType;
3636
+ position: IPosition;
3637
+ rotation: number;
3638
+ pins: UUID[];
3639
+ config: {
3640
+ [key: string]: string;
3641
+ };
3642
+ editable: boolean;
3643
+ }
3644
+
3645
+ /**
3646
+ * Component behavior interface for registry-based extensibility.
3647
+ * Each component type (Battery, LED, Switch, etc.) implements this interface.
3648
+ *
3649
+ * Behaviors are stateless - all state is stored in ComponentState and SimulationState.
3650
+ * The behavior's job is to compute new states based on current inputs and component state.
3651
+ *
3652
+ * @public
3653
+ */
3654
+ declare interface IComponentBehavior {
3655
+ /**
3656
+ * Component type this behavior handles (e.g., "battery", "led", "switch").
3657
+ * Used as the key in BehaviorRegistry.
3658
+ */
3659
+ componentType: ComponentType;
3660
+ /**
3661
+ * Create initial state for a component instance.
3662
+ * Called when simulation is initialized.
3663
+ * Initial state may use component satic configuration (e.g., initial switch position).
3664
+ *
3665
+ * @param component - The component to initialize
3666
+ * @returns Initial ComponentState for this component
3667
+ */
3668
+ createInitialState(component: Component): ComponentState;
3669
+ /**
3670
+ * Determine if conductivity is allowed between two pins of the component.
3671
+ * Called during simulation when evaluating electrical connectivity.
3672
+ * @param component
3673
+ * @param state current component state
3674
+ * @param conductivityType
3675
+ * @param pinId
3676
+ * @param otherPinId
3677
+ */
3678
+ allowConductivity(component: Component, state: ComponentState, conductivityType: ENodeSourceType, pinId: string, otherPinId: string): boolean;
3679
+ /**
3680
+ * Define component state change in response to its pins state change (after propagateConductivity)
3681
+ *
3682
+ * @param component - The component being evaluated
3683
+ * @param state - component state prior to this evaluation
3684
+ * @param nodeStates - Current electrical states of all ENodes in the simulation
3685
+ * @param targetTick - target tick
3686
+ * @returns Result containing updated state and scheduled events
3687
+ */
3688
+ onPinsChange(component: Component, state: ComponentState, nodeStates: ReadonlyMap<UUID, INodeElectricalState>, targetTick: number): IBehaviorResult;
3689
+ /**
3690
+ * Define component state change in response to a User command being received
3691
+ *
3692
+ * @param component - The component being evaluated
3693
+ * @param state - component state prior to this evaluation
3694
+ * @param command - IUserCommand to process
3695
+ * @returns Result containing updated state and scheduled events
3696
+ */
3697
+ onUserCommand(component: Component, state: ComponentState, command: IUserCommand): IBehaviorResult;
3698
+ /**
3699
+ * Define component state change in response to a IScheduledEvent firing at ready
3700
+ *
3701
+ * @param component - The component being evaluated
3702
+ * @param state - component state prior to this evaluation
3703
+ * @param event - firing IScheduledEvent to process
3704
+ * @returns Result containing updated state and scheduled events
3705
+ */
3706
+ onEventFiring(component: Component, state: ComponentState, event: IScheduledEvent): IBehaviorResult;
3707
+ }
3708
+
3900
3709
  /**
3901
3710
  * Builder interface for adding components to a group.
3902
3711
  * Used as the callback parameter type in addGroup().
@@ -3926,7 +3735,7 @@ export declare interface IComponentGroupBuilder {
3926
3735
  * @example
3927
3736
  * ```typescript
3928
3737
  * class MyComponentFactory extends ComponentVisualFactoryBase {
3929
- * createVisual(component: Component): THREE.Object3D {
3738
+ * createVisual(component: Component, context?: VisualContext): THREE.Object3D {
3930
3739
  * const group = new THREE.Group();
3931
3740
  * // ... create visual elements
3932
3741
  * group.userData.componentId = component.id;
@@ -3945,6 +3754,7 @@ export declare interface IComponentVisualFactory {
3945
3754
  * Create the Three.js visual representation for a component
3946
3755
  *
3947
3756
  * @param component - The circuit component to visualize
3757
+ * @param context - Optional visual context providing access to ENode data
3948
3758
  * @returns THREE.Object3D (typically a Group) containing the visual
3949
3759
  *
3950
3760
  * @remarks
@@ -3955,7 +3765,7 @@ export declare interface IComponentVisualFactory {
3955
3765
  * - Create pin groups with enodes on HitboxLayers.ENODE layer
3956
3766
  * - Return objects positioned at origin (scene controllerType handles placement)
3957
3767
  */
3958
- createVisual(component: Component): THREE.Object3D;
3768
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
3959
3769
  /**
3960
3770
  * Update visual based on component configuration
3961
3771
  *
@@ -4043,13 +3853,16 @@ export declare interface IComponentVisualFactory {
4043
3853
  /**
4044
3854
  * Get the config form definition for this component type
4045
3855
  *
3856
+ * @param config - Optional current component config to compute field states (e.g., disabled)
4046
3857
  * @returns Form definition with field specifications, or null if no config
4047
3858
  *
4048
3859
  * @remarks
4049
3860
  * Defines the UI controls for editing component configuration.
4050
3861
  * Return null for components with no configurable options.
3862
+ * When config is provided, implementations may use it to set field.disabled
3863
+ * based on interdependencies (e.g., transitionSpan disabled when defaultLogicFamily != Sandbox).
4051
3864
  */
4052
- getConfigFormDefinition(): ConfigFormDefinition | null;
3865
+ getConfigFormDefinition(config?: Map<string, string>): ConfigFormDefinition | null;
4053
3866
  /**
4054
3867
  * Map core component config (string values) to form data (typed values)
4055
3868
  *
@@ -4134,6 +3947,17 @@ export declare interface IEditingTool {
4134
3947
  getPreviewObjects(): THREE.Object3D[];
4135
3948
  }
4136
3949
 
3950
+ /** Interface defining an ElectricalNode **/
3951
+ declare interface IENode {
3952
+ id: UUID;
3953
+ type: ENodeType;
3954
+ component?: UUID | null;
3955
+ pinLabel?: string | null;
3956
+ position?: IPosition | null;
3957
+ source?: ENodeSourceType | null;
3958
+ subtype: string;
3959
+ }
3960
+
4137
3961
  /**
4138
3962
  * Registry interface for managing component visual factories
4139
3963
  *
@@ -4213,12 +4037,127 @@ export declare interface IGroupedFactoryRegistry {
4213
4037
  }
4214
4038
 
4215
4039
  /**
4216
- * 3D Position Type
4040
+ * Binary electrical state for wires and enodes (connection points)
4041
+ * @module core/simulation/states
4042
+ * @public
4043
+ */
4044
+ declare interface INodeElectricalState {
4045
+ /**
4046
+ * True if voltage is present at this node (potential > 0V).
4047
+ * False if node is at ground potential or floating.
4048
+ */
4049
+ hasVoltage: boolean;
4050
+ /**
4051
+ * True if current is actively flowing through this node.
4052
+ * False if no current flow (open circuit or equilibrium).
4053
+ */
4054
+ hasCurrent: boolean;
4055
+ /**
4056
+ * True only if the node is locked from state changes at circuit build time (ex: battery pins or other fixed-voltage/current pinSources).
4057
+ * Important: Those nodes should never have their electrical state modified by the simulation controller!
4058
+ * Always false for wires
4059
+ */
4060
+ locked: boolean;
4061
+ }
4062
+
4063
+ /**
4064
+ * Visual factory for Inverter/Buffer components
4217
4065
  *
4218
- * Represents a 3D position. Used for:
4219
- * - Camera placement
4066
+ * Creates:
4067
+ * - Inverter triangle or Buffer trapezoid extrude geom mesh
4068
+ * - Vcc, input and output pin group
4069
+ * - Component hitbox for raycasting
4220
4070
  *
4221
- * @module core/types/Position3D
4071
+ * Animation:
4072
+ * - Emissive glow when component is high (based on simulation state)
4073
+ */
4074
+ export declare class InverterVisualFactory extends ComponentVisualFactoryBase {
4075
+ /** Inverter high color (white glow) */
4076
+ private static readonly HIGH_COLOR;
4077
+ /** Inverter high emissive intensity */
4078
+ private static readonly HIGH_INTENSITY;
4079
+ /** Shared low Inverter envelope geometry */
4080
+ private readonly inverterLowGeometry;
4081
+ /** Shared transient Inverter envelope geometry */
4082
+ private readonly inverterTransientGeometry;
4083
+ /** Shared high Inverter envelope geometry */
4084
+ private readonly inverterHighGeometry;
4085
+ /** Shared low Buffer envelope geometry */
4086
+ private readonly bufferLowGeometry;
4087
+ /** Shared transient Buffer envelope geometry */
4088
+ private readonly bufferTransientGeometry;
4089
+ /** Shared high Buffer envelope geometry */
4090
+ private readonly bufferHighGeometry;
4091
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4092
+ private createPinsVisual;
4093
+ private replaceEnvelope;
4094
+ /**
4095
+ * Get config form definition for Inverter
4096
+ *
4097
+ * @param config - Optional current config to determine disabled state of transitionSpan
4098
+ * @returns Form definition with defaultLogicFamily dropdown, activationLogic boolean, and transitionSpan number
4099
+ */
4100
+ getConfigFormDefinition(config?: Map<string, string>): ConfigFormDefinition | null;
4101
+ /**
4102
+ * Map core config to form data
4103
+ * Converts "positive"/"negative" strings to boolean
4104
+ *
4105
+ * @param config - Core component config
4106
+ * @returns Form data with boolean activationLogic
4107
+ */
4108
+ mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
4109
+ /**
4110
+ * Map form data to core config
4111
+ * Converts boolean to "positive"/"negative" strings
4112
+ *
4113
+ * @param formData - Form data with boolean activationLogic
4114
+ * @returns Core config with string activationLogic
4115
+ */
4116
+ mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
4117
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4118
+ /**
4119
+ * Update Inverter animation based on simulation state
4120
+ *
4121
+ * @param object3D - The Object3D created by createVisual()
4122
+ * @param state - The Inverter's current simulation state
4123
+ */
4124
+ updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
4125
+ /**
4126
+ * Find the envelope mesh within the component group
4127
+ *
4128
+ * @param object3D - The Object3D group created by createVisual()
4129
+ * @returns The envelope mesh if found, null otherwise
4130
+ *
4131
+ * @remarks
4132
+ * Searches for a mesh with userData.part === 'envelope'
4133
+ */
4134
+ private findEnvelopeMesh;
4135
+ /**
4136
+ * Find the negative marker mesh within the component group
4137
+ *
4138
+ * @param object3D - The Object3D group created by createVisual()
4139
+ * @returns The negative marker mesh if found, null otherwise
4140
+ *
4141
+ * @remarks
4142
+ * Searches for a mesh with userData.part === 'negativeMarker'
4143
+ */
4144
+ protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
4145
+ material: THREE.MeshStandardMaterial;
4146
+ }) | null;
4147
+ }
4148
+
4149
+ /**
4150
+ * 2D Position Type
4151
+ * Represents a 2D position on the circuit grid
4152
+ */
4153
+ declare type IPosition = {
4154
+ x: number;
4155
+ y: number;
4156
+ };
4157
+
4158
+ /**
4159
+ * 3D Position Type
4160
+ * Represents a 3D position. Used for Camera placement
4222
4161
  */
4223
4162
  declare type IPosition3D = {
4224
4163
  x: number;
@@ -4226,6 +4165,96 @@ declare type IPosition3D = {
4226
4165
  z: number;
4227
4166
  };
4228
4167
 
4168
+ /**
4169
+ * Configuration options for CircuitRunner
4170
+ */
4171
+ declare interface IRunnerOptions {
4172
+ /**
4173
+ * Enable historical state tracking.
4174
+ * When true, past simulation states are preserved up to historyLimit.
4175
+ * When false (default), only current state is retained for better performance.
4176
+ * @default false
4177
+ */
4178
+ enableHistory?: boolean;
4179
+ /**
4180
+ * Maximum number of historical states to retain when enableHistory is true.
4181
+ * Uses circular buffer—oldest states are overwritten when limit is reached.
4182
+ * Must be a positive integer.
4183
+ * @default 1000
4184
+ */
4185
+ historyLimit?: number;
4186
+ }
4187
+
4188
+ /**
4189
+ * Scheduled event for delayed component transitions.
4190
+ * Events are ordered by readyAtTick in a min-heap priority queue.
4191
+ * Events with same readyAtTick are processed in FIFO order (by scheduledAtTick).
4192
+ *
4193
+ * @public
4194
+ */
4195
+ declare interface IScheduledEvent {
4196
+ /**
4197
+ * UUID of target component.
4198
+ */
4199
+ readonly targetId: UUID;
4200
+ /**
4201
+ * Tick when this event was scheduled (for FIFO ordering).
4202
+ * @readonly
4203
+ */
4204
+ readonly scheduledAtTick: number;
4205
+ /**
4206
+ * Tick when this event should be processed.
4207
+ * @readonly
4208
+ */
4209
+ readonly readyAtTick: number;
4210
+ /**
4211
+ * Indicates the type of this event, eg 'ClosingEnd', 'OpeningEnd', etc.
4212
+ */
4213
+ readonly type: string;
4214
+ /**
4215
+ * extra parameters associated with this event.
4216
+ */
4217
+ readonly parameters?: Map<string, string> | undefined;
4218
+ }
4219
+
4220
+ /**
4221
+ * User command to be executed during simulation.
4222
+ * Commands can be queued for future ticks or executed immediately.
4223
+ *
4224
+ * @public
4225
+ */
4226
+ declare interface IUserCommand {
4227
+ /**
4228
+ * Type of command.
4229
+ */
4230
+ readonly type: 'toggle_switch';
4231
+ /**
4232
+ * UUID of target component.
4233
+ */
4234
+ readonly targetId: UUID;
4235
+ /**
4236
+ * tick when this command was scheduled.
4237
+ */
4238
+ scheduledAtTick: number;
4239
+ /**
4240
+ * Extra parameters associated with this command.
4241
+ *
4242
+ * For `toggle_switch` commands:
4243
+ * - `tickCount`: Number of ticks for the switch transition. Computed at toggle time
4244
+ * using the formula: `ceil(transitionUserSpan × simulationSpeed / 1000)` with minimum of 1.
4245
+ * If not provided, behavior uses default transition timing.
4246
+ */
4247
+ readonly parameters?: Map<string, string> | null;
4248
+ }
4249
+
4250
+ /** Interface defining a Wire (link between 2 ENodes supporting intermediate position to tune its path) **/
4251
+ declare interface IWire {
4252
+ id: UUID;
4253
+ node1: UUID;
4254
+ node2: UUID;
4255
+ intermediatePositions: IPosition[];
4256
+ }
4257
+
4229
4258
  /**
4230
4259
  * Visual factory for Label components
4231
4260
  *
@@ -4264,13 +4293,7 @@ export declare class LabelVisualFactory extends ComponentVisualFactoryBase {
4264
4293
  private static readonly BASE_FONT_SIZE;
4265
4294
  /** Padding around text in pixels */
4266
4295
  private static readonly PADDING;
4267
- /**
4268
- * Create the Three.js visual representation for a Label component
4269
- *
4270
- * @param component - The Label component to visualize
4271
- * @returns THREE.Group containing hitbox and text mesh
4272
- */
4273
- createVisual(component: Component): THREE.Object3D;
4296
+ createVisual(component: Component, _context: VisualContext): THREE.Object3D;
4274
4297
  /**
4275
4298
  * Create a canvas with rendered text
4276
4299
  *
@@ -4393,7 +4416,8 @@ export declare class LightbulbVisualFactory extends ComponentVisualFactoryBase {
4393
4416
  private static readonly BULB_LIT_COLOR;
4394
4417
  /** Lightbulb lit emissive intensity */
4395
4418
  private static readonly BULB_LIT_INTENSITY;
4396
- createVisual(component: Component): THREE.Object3D;
4419
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4420
+ private createPinsVisual;
4397
4421
  /**
4398
4422
  * Get config form definition for Lightbulb
4399
4423
  *
@@ -4438,6 +4462,15 @@ export { LineGeometry }
4438
4462
 
4439
4463
  export { LineMaterial }
4440
4464
 
4465
+ /**
4466
+ * Available logic families
4467
+ *
4468
+ * - `CMOS1`: CMOS technology, base unit 1 inverter = 1 tick
4469
+ * - `TTL1`: TTL technology, base unit 1 NAND2 = 1 tick
4470
+ * - `Sandbox`: User-defined delays, no technology constraints
4471
+ */
4472
+ declare type LogicFamily = 'CMOS1' | 'TTL1' | 'Sandbox';
4473
+
4441
4474
  /**
4442
4475
  * Configuration options for Controllers and Engine
4443
4476
  **/
@@ -4676,40 +4709,153 @@ export declare class MultiSelectTool implements IEditingTool {
4676
4709
  export declare type MultiSelectToolMode = 'idle' | 'selecting' | 'dragging';
4677
4710
 
4678
4711
  /**
4679
- * Binary electrical state for wires and enodes (connection points)
4680
- * @module core/simulation/states
4712
+ * Visual factory for NAND gates components
4713
+ *
4714
+ * Creates:
4715
+ * - Gate mesh
4716
+ * - vcc, gnd, inputs and output pin groups
4717
+ * - Component hitbox for raycasting
4718
+ *
4719
+ * Animation:
4720
+ * - Emissive glow when Gate is high (based on simulation state)
4681
4721
  */
4682
- declare interface NodeElectricalState {
4722
+ export declare class Nand4GateVisualFactory extends NandGateVisualFactory {
4723
+ /** Shared open envelope geometry */
4724
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
4725
+ /** Shared transient envelope geometry */
4726
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
4727
+ /** Shared transient envelope geometry */
4728
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
4729
+ /** Shared geometry for negative marker **/
4730
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4731
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4732
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
4733
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4734
+ }
4735
+
4736
+ /**
4737
+ * Visual factory for NAND gates components
4738
+ *
4739
+ * Creates:
4740
+ * - Gate mesh
4741
+ * - vcc, gnd, inputs and output pin groups
4742
+ * - Component hitbox for raycasting
4743
+ *
4744
+ * Animation:
4745
+ * - Emissive glow when Gate is high (based on simulation state)
4746
+ */
4747
+ export declare class Nand8GateVisualFactory extends NandGateVisualFactory {
4748
+ /** Shared open envelope geometry */
4749
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
4750
+ /** Shared transient envelope geometry */
4751
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
4752
+ /** Shared transient envelope geometry */
4753
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
4754
+ /** Shared geometry for negative marker **/
4755
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4756
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4757
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
4758
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4759
+ }
4760
+
4761
+ /**
4762
+ * Visual factory for NAND gates components
4763
+ *
4764
+ * Creates:
4765
+ * - Gate mesh
4766
+ * - vcc, gnd, inputs and output pin groups
4767
+ * - Component hitbox for raycasting
4768
+ *
4769
+ * Animation:
4770
+ * - Emissive glow when Gate is high (based on simulation state)
4771
+ */
4772
+ export declare class NandGateVisualFactory extends ComponentVisualFactoryBase {
4773
+ /** Gate high color */
4774
+ protected static readonly HIGH_COLOR = 16777215;
4775
+ /** Gate high emissive intensity */
4776
+ protected static readonly HIGH_INTENSITY = 0.3;
4777
+ /** Shared open envelope geometry */
4778
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
4779
+ /** Shared transient envelope geometry */
4780
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
4781
+ /** Shared transient envelope geometry */
4782
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
4783
+ /** Shared material for negative marker **/
4784
+ protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
4785
+ /** Shared geometry for negative marker **/
4786
+ protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4787
+ defaultRotation(): number;
4788
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4789
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
4683
4790
  /**
4684
- * True if voltage is present at this node (potential > 0V).
4685
- * False if node is at ground potential or floating.
4791
+ * Get config form definition
4792
+ *
4793
+ * @param config - Optional current config to determine disabled state of transitionSpan
4794
+ * @returns Form definition with defaultLogicFamily dropdown, activationLogic boolean, and transitionSpan number
4795
+ */
4796
+ getConfigFormDefinition(config?: Map<string, string>): ConfigFormDefinition | null;
4797
+ /**
4798
+ * Map core config to form data
4799
+ * Converts "positive"/"negative" strings to boolean
4800
+ *
4801
+ * @param config - Core component config
4802
+ * @returns Form data with boolean activationLogic
4803
+ */
4804
+ mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
4805
+ /**
4806
+ * Map form data to core config
4807
+ * Converts boolean to "positive"/"negative" strings
4808
+ *
4809
+ * @param formData - Form data with boolean activationLogic
4810
+ * @returns Core config with string activationLogic
4811
+ */
4812
+ mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
4813
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4814
+ /**
4815
+ * Update animation based on simulation state
4816
+ *
4817
+ * @param object3D - The Object3D created by createVisual()
4818
+ * @param state - The component current simulation state
4686
4819
  */
4687
- hasVoltage: boolean;
4820
+ updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
4688
4821
  /**
4689
- * True if current is actively flowing through this node.
4690
- * False if no current flow (open circuit or equilibrium).
4822
+ * Find the envelope mesh within the component group
4823
+ *
4824
+ * @param object3D - The Object3D group created by createVisual()
4825
+ * @returns The envelope mesh if found, null otherwise
4826
+ *
4827
+ * @remarks
4828
+ * Searches for a mesh with userData.part === 'envelope'
4691
4829
  */
4692
- hasCurrent: boolean;
4830
+ protected findEnvelopeMesh(object3D: THREE.Object3D): (THREE.Mesh & {
4831
+ material: THREE.MeshStandardMaterial;
4832
+ }) | null;
4693
4833
  /**
4694
- * True only if the node is locked from state changes at circuit build time (ex: battery pins or other fixed-voltage/current pinSources).
4695
- * Important: Those nodes should never have their electrical state modified by the simulation controller!
4696
- * Always false for wires
4834
+ * Find the negative marker mesh within the component group
4835
+ *
4836
+ * @param object3D - The Object3D group created by createVisual()
4837
+ * @returns The negative marker mesh if found, null otherwise
4838
+ *
4839
+ * @remarks
4840
+ * Searches for a mesh with userData.part === 'negativeMarker'
4697
4841
  */
4698
- locked: boolean;
4842
+ protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
4843
+ material: THREE.MeshStandardMaterial;
4844
+ }) | null;
4699
4845
  }
4700
4846
 
4701
4847
  /**
4702
- * Visual factory for OR gates components
4848
+ * Visual factory for NOR gates components
4703
4849
  *
4704
4850
  * Creates:
4705
4851
  * - Gate mesh
4706
- * - vcc, inputs and output pin groups
4852
+ * - vcc, gnd, inputs and output pin groups
4707
4853
  * - Component hitbox for raycasting
4708
4854
  *
4709
4855
  * Animation:
4710
4856
  * - Emissive glow when Gate is high (based on simulation state)
4711
4857
  */
4712
- export declare class Or4GateVisualFactory extends OrGateVisualFactory {
4858
+ export declare class Nor4GateVisualFactory extends NorGateVisualFactory {
4713
4859
  /** Shared open envelope geometry */
4714
4860
  protected readonly lowGeometry: THREE.ExtrudeGeometry;
4715
4861
  /** Shared transient envelope geometry */
@@ -4718,28 +4864,23 @@ export declare class Or4GateVisualFactory extends OrGateVisualFactory {
4718
4864
  protected readonly highGeometry: THREE.ExtrudeGeometry;
4719
4865
  /** Shared geometry for negative marker **/
4720
4866
  protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4721
- createVisual(component: Component): THREE.Object3D;
4722
- /**
4723
- * Get config form definition for Transistor (T026)
4724
- *
4725
- * @returns Form definition with activationLogic boolean field
4726
- */
4727
- getConfigFormDefinition(): ConfigFormDefinition | null;
4867
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4868
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
4728
4869
  updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4729
4870
  }
4730
4871
 
4731
4872
  /**
4732
- * Visual factory for OR gates components
4873
+ * Visual factory for NOR gates components
4733
4874
  *
4734
4875
  * Creates:
4735
4876
  * - Gate mesh
4736
- * - vcc, inputs and output pin groups
4877
+ * - vcc, gnd, inputs and output pin groups
4737
4878
  * - Component hitbox for raycasting
4738
4879
  *
4739
4880
  * Animation:
4740
4881
  * - Emissive glow when Gate is high (based on simulation state)
4741
4882
  */
4742
- export declare class Or8GateVisualFactory extends OrGateVisualFactory {
4883
+ export declare class Nor8GateVisualFactory extends NorGateVisualFactory {
4743
4884
  /** Shared open envelope geometry */
4744
4885
  protected readonly lowGeometry: THREE.ExtrudeGeometry;
4745
4886
  /** Shared transient envelope geometry */
@@ -4748,28 +4889,23 @@ export declare class Or8GateVisualFactory extends OrGateVisualFactory {
4748
4889
  protected readonly highGeometry: THREE.ExtrudeGeometry;
4749
4890
  /** Shared geometry for negative marker **/
4750
4891
  protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4751
- createVisual(component: Component): THREE.Object3D;
4752
- /**
4753
- * Get config form definition for Transistor (T026)
4754
- *
4755
- * @returns Form definition with activationLogic boolean field
4756
- */
4757
- getConfigFormDefinition(): ConfigFormDefinition | null;
4892
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4893
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
4758
4894
  updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
4759
4895
  }
4760
4896
 
4761
4897
  /**
4762
- * Visual factory for OR gates components
4898
+ * Visual factory for NOR gates components
4763
4899
  *
4764
4900
  * Creates:
4765
4901
  * - Gate mesh
4766
- * - vcc, inputs and output pin groups
4902
+ * - vcc, gnd, inputs and output pin groups
4767
4903
  * - Component hitbox for raycasting
4768
4904
  *
4769
4905
  * Animation:
4770
4906
  * - Emissive glow when Gate is high (based on simulation state)
4771
4907
  */
4772
- export declare class OrGateVisualFactory extends ComponentVisualFactoryBase {
4908
+ export declare class NorGateVisualFactory extends ComponentVisualFactoryBase {
4773
4909
  /** Gate high color */
4774
4910
  protected static readonly HIGH_COLOR = 16777215;
4775
4911
  /** Gate high emissive intensity */
@@ -4785,13 +4921,15 @@ export declare class OrGateVisualFactory extends ComponentVisualFactoryBase {
4785
4921
  /** Shared geometry for negative marker **/
4786
4922
  protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
4787
4923
  defaultRotation(): number;
4788
- createVisual(component: Component): THREE.Object3D;
4924
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
4925
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
4789
4926
  /**
4790
- * Get config form definition for OR Gate
4927
+ * Get config form definition
4791
4928
  *
4792
- * @returns Form definition with activationLogic boolean field
4929
+ * @param config - Optional current config to determine disabled state of transitionSpan
4930
+ * @returns Form definition with defaultLogicFamily dropdown, activationLogic boolean, and transitionSpan number
4793
4931
  */
4794
- getConfigFormDefinition(): ConfigFormDefinition | null;
4932
+ getConfigFormDefinition(config?: Map<string, string>): ConfigFormDefinition | null;
4795
4933
  /**
4796
4934
  * Map core config to form data
4797
4935
  * Converts "positive"/"negative" strings to boolean
@@ -4855,7 +4993,7 @@ export declare type PickerSelection = ComponentType | typeof BRANCHING_POINT_SEN
4855
4993
  * - Branching point ENode positions
4856
4994
  * - Wire intermediate waypoints
4857
4995
  *
4858
- * @module core/types/Position
4996
+ * @module core/utils
4859
4997
  */
4860
4998
  /**
4861
4999
  * Position on a 2D discrete grid with integer coordinates.
@@ -5037,7 +5175,8 @@ export declare class RectangleLEDVisualFactory extends ComponentVisualFactoryBas
5037
5175
  private static readonly LED_LIT_COLOR;
5038
5176
  /** LED lit emissive intensity */
5039
5177
  private static readonly LED_LIT_INTENSITY;
5040
- createVisual(component: Component): THREE.Object3D;
5178
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
5179
+ private createPinsVisual;
5041
5180
  /**
5042
5181
  * Get config form definition for SmallLED (T027)
5043
5182
  *
@@ -5096,7 +5235,7 @@ export declare class RectangleLEDVisualFactory extends ComponentVisualFactoryBas
5096
5235
 
5097
5236
  /**
5098
5237
  * Register all basic components visual factories in the basic group
5099
- * Basic components are : Battery, Label, Switch, Lightbulb, RectangleLED, Relay, SmallLED, Transistor
5238
+ * Basic components are : Battery, Label, Switches, Lightbulb, RectangleLED, Relay, SmallLED
5100
5239
  * @public
5101
5240
  * @param registry - A grouped factory registry to populate
5102
5241
  * @returns The input registry for chaining
@@ -5105,8 +5244,8 @@ export declare function registerBasicComponentsFactories(registry: IGroupedFacto
5105
5244
 
5106
5245
  /**
5107
5246
  * Register all logic gates components visual factories in the gates group
5108
- * gates are : AND (2,4,8,16 inputs), OR (2,4,8,16 inputs) and XOR
5109
- * NAND and NOR are gotten by changing the activationLogic of AND and OR
5247
+ * gates are : Inverter, NAND (2,4,8 inputs), NOR (2,4,8 inputs) and XOR (2,4,8 inputs)
5248
+ * AND/OR are gotten by changing the activationLogic of NAND/NOR
5110
5249
  * @public
5111
5250
  * @param registry - A grouped factory registry to populate
5112
5251
  * @returns The input registry for chaining
@@ -5116,26 +5255,37 @@ export declare function registerGatesComponentsFactories(registry: IGroupedFacto
5116
5255
  /**
5117
5256
  * Visual factory for Relay components
5118
5257
  *
5119
- * Creates:
5120
- * - Component hitbox for raycasting
5121
- * - Cylinder representing the coil with two poles
5122
- * - Output commanded switch with contactor
5123
- * - Contactor (cylinder, rotatable for animation)
5124
5258
  * Animation:
5125
5259
  * - Rotates contactor based on open/closed state
5126
5260
  */
5127
5261
  export declare class RelayVisualFactory extends ComponentVisualFactoryBase {
5262
+ /** Coil ring geometry */
5263
+ private readonly COIL_GEOM;
5264
+ /** Coil bar geometry */
5265
+ private readonly COIL_BAR_GEOM;
5266
+ private readonly COIL_BAR_Z_OPEN;
5267
+ private readonly COIL_BAR_Z_INTERMEDIATE;
5268
+ private readonly COIL_BAR_Z_CLOSED;
5269
+ private readonly COIL_BAR_Z_INV_INTERMEDIATE;
5270
+ private readonly COIL_BAR_Z_INV_OPEN;
5271
+ /** Power In bar geometry */
5272
+ private readonly PWIN_BAR_GEOM;
5273
+ /** normal contactor geom */
5274
+ private CONTACTOR_GEOM;
5128
5275
  /** Rotation for open relay (contactor misaligned) */
5129
- private static readonly OPEN_ROTATION;
5276
+ private readonly OPEN_ROTATION;
5130
5277
  /** Rotation for opening/closing relay */
5131
- private static readonly INTERMEDIATE_ROTATION;
5278
+ private readonly INTERMEDIATE_ROTATION;
5132
5279
  /** Rotation for closed relay (contactor aligned) */
5133
- private static readonly CLOSED_ROTATION;
5280
+ private readonly CLOSED_ROTATION;
5134
5281
  /** Rotation for opening/closing negative activation logic relay */
5135
- private static readonly INVERTED_INTERMEDIATE_ROTATION;
5282
+ private readonly INVERTED_INTERMEDIATE_ROTATION;
5136
5283
  /** Rotation for open negative activation logic relay (contactor misaligned toward the coil) */
5137
- private static readonly INVERTED_OPEN_ROTATION;
5138
- createVisual(component: Component): THREE.Object3D;
5284
+ private readonly INVERTED_OPEN_ROTATION;
5285
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
5286
+ private createPinsVisual;
5287
+ private createContactorGroup;
5288
+ private createCoilGroup;
5139
5289
  /**
5140
5290
  * Get config form definition for Relay (T025)
5141
5291
  *
@@ -5180,7 +5330,7 @@ export declare class RelayVisualFactory extends ComponentVisualFactoryBase {
5180
5330
  */
5181
5331
  private findContactorGroup;
5182
5332
  /**
5183
- * Find the coil within the component group
5333
+ * Find the coil bar within the component group
5184
5334
  *
5185
5335
  * @param object3D - The Object3D group created by createVisual()
5186
5336
  * @returns The contactor's parent group if found, null otherwise
@@ -5188,16 +5338,14 @@ export declare class RelayVisualFactory extends ComponentVisualFactoryBase {
5188
5338
  * @remarks
5189
5339
  * Searches for a mesh with userData.part === 'coil' and returns its parent
5190
5340
  */
5191
- private findCoil;
5341
+ private findCoilBar;
5192
5342
  }
5193
5343
 
5194
5344
  /**
5195
5345
  * Rotation Type for Component Orientation
5196
- *
5197
5346
  * Represents orientation angle for components on the 2D grid.
5198
5347
  * Uses integer degrees for discrete rotation values.
5199
- *
5200
- * @module core/types/Rotation
5348
+ * @module core/utils
5201
5349
  */
5202
5350
  /**
5203
5351
  * Rotation angle for component orientation.
@@ -5276,59 +5424,6 @@ declare class Rotation {
5276
5424
  toString(): string;
5277
5425
  }
5278
5426
 
5279
- /**
5280
- * Configuration options for CircuitRunner
5281
- * @module core/simulation/types
5282
- */
5283
- declare interface RunnerOptions {
5284
- /**
5285
- * Enable historical state tracking.
5286
- * When true, past simulation states are preserved up to historyLimit.
5287
- * When false (default), only current state is retained for better performance.
5288
- * @default false
5289
- */
5290
- enableHistory?: boolean;
5291
- /**
5292
- * Maximum number of historical states to retain when enableHistory is true.
5293
- * Uses circular buffer—oldest states are overwritten when limit is reached.
5294
- * Must be a positive integer.
5295
- * @default 1000
5296
- */
5297
- historyLimit?: number;
5298
- }
5299
-
5300
- /**
5301
- * Scheduled event for delayed component transitions.
5302
- * Events are ordered by readyAtTick in a min-heap priority queue.
5303
- * Events with same readyAtTick are processed in FIFO order (by scheduledAtTick).
5304
- *
5305
- * @public
5306
- */
5307
- declare interface ScheduledEvent {
5308
- /**
5309
- * UUID of target component.
5310
- */
5311
- readonly targetId: UUID;
5312
- /**
5313
- * Tick when this event was scheduled (for FIFO ordering).
5314
- * @readonly
5315
- */
5316
- readonly scheduledAtTick: number;
5317
- /**
5318
- * Tick when this event should be processed.
5319
- * @readonly
5320
- */
5321
- readonly readyAtTick: number;
5322
- /**
5323
- * Indicates the type of this event, eg 'ClosingEnd', 'OpeningEnd', etc.
5324
- */
5325
- readonly type: string;
5326
- /**
5327
- * extra parameters associated with this event.
5328
- */
5329
- readonly parameters?: Map<string, string> | undefined;
5330
- }
5331
-
5332
5427
  /**
5333
5428
  * Callback invoked when selection changes
5334
5429
  *
@@ -5536,7 +5631,8 @@ export declare class SmallLEDVisualFactory extends ComponentVisualFactoryBase {
5536
5631
  private static readonly LED_LIT_COLOR;
5537
5632
  /** LED lit emissive intensity */
5538
5633
  private static readonly LED_LIT_INTENSITY;
5539
- createVisual(component: Component): THREE.Object3D;
5634
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
5635
+ private createPinsVisual;
5540
5636
  /**
5541
5637
  * Get config form definition for SmallLED (T027)
5542
5638
  *
@@ -5609,12 +5705,13 @@ export declare class SmallLEDVisualFactory extends ComponentVisualFactoryBase {
5609
5705
  */
5610
5706
  export declare class SwitchVisualFactory extends ComponentVisualFactoryBase {
5611
5707
  /** Rotation for closed switch (contactor aligned) */
5612
- private static readonly CLOSED_ROTATION;
5708
+ private readonly CLOSED_ROTATION;
5613
5709
  /** Rotation for opening/closing switch */
5614
- private static readonly INTERMEDIATE_ROTATION;
5710
+ private readonly INTERMEDIATE_ROTATION;
5615
5711
  /** Rotation for open switch (contactor misaligned) */
5616
- private static readonly OPEN_ROTATION;
5617
- createVisual(component: Component): THREE.Object3D;
5712
+ private readonly OPEN_ROTATION;
5713
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
5714
+ private createPinsVisual;
5618
5715
  /**
5619
5716
  * Get config form definition for Switch (T024)
5620
5717
  *
@@ -5671,141 +5768,24 @@ export declare class SwitchVisualFactory extends ComponentVisualFactoryBase {
5671
5768
  export declare type ToolType = 'build' | 'multiSelect';
5672
5769
 
5673
5770
  /**
5674
- * Visual factory for Transistor components
5675
- *
5676
- * Creates:
5677
- * - Transistor Ring mesh
5678
- * - Collector, Base and Emitter pin group
5679
- * - Component hitbox for raycasting
5680
- *
5681
- * Animation:
5682
- * - Emissive glow when Transistor is closed (based on simulation state)
5771
+ * core utilities types definitions
5772
+ * @module core/utils
5683
5773
  */
5684
- export declare class TransistorVisualFactory extends ComponentVisualFactoryBase {
5685
- /** Transistor closed color (white glow) */
5686
- private static readonly TRANSISTOR_CLOSED_COLOR;
5687
- /** Transistor closed emissive intensity */
5688
- private static readonly TRANSISTOR_CLOSED_INTENSITY;
5689
- /** Shared open Transistor envelope geometry */
5690
- private readonly openGeometry;
5691
- /** Shared transient Transistor envelope geometry */
5692
- private readonly transientGeometry;
5693
- /** Shared transient Transistor envelope geometry */
5694
- private readonly closedGeometry;
5695
- /** Shared material for negative marker **/
5696
- protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
5697
- /** Shared geometry for negative marker **/
5698
- protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
5699
- createVisual(component: Component): THREE.Object3D;
5700
- /**
5701
- * Get config form definition for Transistor (T026)
5702
- *
5703
- * @returns Form definition with activationLogic boolean field
5704
- */
5705
- getConfigFormDefinition(): ConfigFormDefinition | null;
5706
- /**
5707
- * Map core config to form data (T026)
5708
- * Converts "positive"/"negative" strings to boolean
5709
- *
5710
- * @param config - Core component config
5711
- * @returns Form data with boolean activationLogic
5712
- */
5713
- mapCoreConfigToForm(config: Map<string, string>): Map<string, any>;
5714
- /**
5715
- * Map form data to core config (T026)
5716
- * Converts boolean to "positive"/"negative" strings
5717
- *
5718
- * @param formData - Form data with boolean activationLogic
5719
- * @returns Core config with string activationLogic
5720
- */
5721
- mapFormToCoreConfig(formData: Map<string, any>): Map<string, string>;
5722
- updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
5723
- /**
5724
- * Update Transistor animation based on simulation state
5725
- *
5726
- * @param object3D - The Object3D created by createVisual()
5727
- * @param state - The Transistor's current simulation state
5728
- */
5729
- updateAnimation(object3D: THREE.Object3D, state: ComponentState | null): void;
5730
- /**
5731
- * Find the envelope mesh within the component group
5732
- *
5733
- * @param object3D - The Object3D group created by createVisual()
5734
- * @returns The envelope mesh if found, null otherwise
5735
- *
5736
- * @remarks
5737
- * Searches for a mesh with userData.part === 'envelope'
5738
- */
5739
- private findEnvelopeMesh;
5740
- /**
5741
- * Find the negative marker mesh within the component group
5742
- *
5743
- * @param object3D - The Object3D group created by createVisual()
5744
- * @returns The negative marker mesh if found, null otherwise
5745
- *
5746
- * @remarks
5747
- * Searches for a mesh with userData.part === 'negativeMarker'
5748
- */
5749
- protected findNegativeMarkerMesh(object3D: THREE.Object3D): (THREE.Mesh & {
5750
- material: THREE.MeshStandardMaterial;
5751
- }) | null;
5752
- }
5753
-
5754
5774
  /**
5755
- * User command to be executed during simulation.
5756
- * Commands can be queued for future ticks or executed immediately.
5757
- *
5758
- * @public
5775
+ * Universally Unique Identifier (RFC 4122 UUID v4).
5759
5776
  */
5760
- declare interface UserCommand {
5761
- /**
5762
- * Type of command.
5763
- */
5764
- readonly type: 'toggle_switch';
5765
- /**
5766
- * UUID of target component.
5767
- */
5768
- readonly targetId: UUID;
5769
- /**
5770
- * tick when this command was scheduled.
5771
- */
5772
- scheduledAtTick: number;
5773
- /**
5774
- * Extra parameters associated with this command.
5775
- *
5776
- * For `toggle_switch` commands:
5777
- * - `tickCount`: Number of ticks for the switch transition. Computed at toggle time
5778
- * using the formula: `ceil(transitionUserSpan × simulationSpeed / 1000)` with minimum of 1.
5779
- * If not provided, behavior uses default transition timing.
5780
- */
5781
- readonly parameters?: Map<string, string> | null;
5782
- }
5777
+ declare type UUID = string;
5783
5778
 
5784
5779
  /**
5785
- * UUID Type and Generation Utilities
5786
- *
5787
- * Provides RFC 4122 UUID v4 identifiers for all entities in the circuit model.
5788
- * Uses native crypto.randomUUID() when available (modern browsers, Node 19+),
5789
- * with fallback for older environments.
5790
- *
5791
- * @module core/types/Identifier
5792
- */
5793
- /**
5794
- * Universally Unique Identifier (RFC 4122 UUID v4).
5795
- *
5796
- * Used as the primary identifier for all circuit entities:
5797
- * - Circuit
5798
- * - Component
5799
- * - ENode (electrical nodes)
5800
- * - Wire
5780
+ * Lightweight context passed to visual factories so they can access
5781
+ * ENode data (subtype, source, wires…) when creating pin visuals.
5801
5782
  *
5802
- * @example
5803
- * ```typescript
5804
- * const id: UUID = generateUUID();
5805
- * console.log(id); // "550e8400-e29b-41d4-a716-446655440000"
5806
- * ```
5783
+ * Circuit satisfies this interface structurally — controllers can pass
5784
+ * `this._circuit` directly without a wrapper.
5807
5785
  */
5808
- declare type UUID = string;
5786
+ export declare interface VisualContext {
5787
+ getENode(id: UUID): ENode | undefined;
5788
+ }
5809
5789
 
5810
5790
  /**
5811
5791
  * Electrical connection between two ENodes.
@@ -5914,15 +5894,7 @@ declare class Wire {
5914
5894
  * // }
5915
5895
  * ```
5916
5896
  */
5917
- toJSON(): {
5918
- id: UUID;
5919
- node1: UUID;
5920
- node2: UUID;
5921
- intermediatePositions: {
5922
- x: number;
5923
- y: number;
5924
- }[];
5925
- };
5897
+ toJSON(): IWire;
5926
5898
  /**
5927
5899
  * Deserialize wire from JSON.
5928
5900
  *
@@ -5941,15 +5913,7 @@ declare class Wire {
5941
5913
  * const wire = Wire.fromJSON(json);
5942
5914
  * ```
5943
5915
  */
5944
- static fromJSON(json: {
5945
- id: UUID;
5946
- node1: UUID;
5947
- node2: UUID;
5948
- intermediatePositions: {
5949
- x: number;
5950
- y: number;
5951
- }[];
5952
- }): Wire;
5916
+ static fromJSON(json: IWire): Wire;
5953
5917
  }
5954
5918
 
5955
5919
  /**
@@ -6202,7 +6166,61 @@ export declare class WireVisualManager {
6202
6166
  *
6203
6167
  * Creates:
6204
6168
  * - Gate mesh
6205
- * - vcc, inputs and output pin groups
6169
+ * - vcc, gnd, inputs and output pin groups
6170
+ * - Component hitbox for raycasting
6171
+ *
6172
+ * Animation:
6173
+ * - Emissive glow when Gate is high (based on simulation state)
6174
+ */
6175
+ export declare class Xor4GateVisualFactory extends XorGateVisualFactory {
6176
+ /** XOR tail geometry */
6177
+ protected readonly tailGeometry: THREE.ExtrudeGeometry;
6178
+ /** Shared open envelope geometry */
6179
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
6180
+ /** Shared transient envelope geometry */
6181
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
6182
+ /** Shared transient envelope geometry */
6183
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
6184
+ /** Shared geometry for negative marker **/
6185
+ protected readonly negativeMarkerGeometry: THREE.CylinderGeometry;
6186
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
6187
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
6188
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
6189
+ }
6190
+
6191
+ /**
6192
+ * Visual factory for XOR gates components
6193
+ *
6194
+ * Creates:
6195
+ * - Gate mesh
6196
+ * - vcc, gnd, inputs and output pin groups
6197
+ * - Component hitbox for raycasting
6198
+ *
6199
+ * Animation:
6200
+ * - Emissive glow when Gate is high (based on simulation state)
6201
+ */
6202
+ export declare class Xor8GateVisualFactory extends XorGateVisualFactory {
6203
+ /** XOR tail geometry */
6204
+ protected readonly tailGeometry: THREE.ExtrudeGeometry;
6205
+ /** Shared open envelope geometry */
6206
+ protected readonly lowGeometry: THREE.ExtrudeGeometry;
6207
+ /** Shared transient envelope geometry */
6208
+ protected readonly transientGeometry: THREE.ExtrudeGeometry;
6209
+ /** Shared transient envelope geometry */
6210
+ protected readonly highGeometry: THREE.ExtrudeGeometry;
6211
+ /** Shared geometry for negative marker **/
6212
+ protected readonly negativeMarkerGeometry: THREE.CylinderGeometry;
6213
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
6214
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
6215
+ updateFromConfiguration(object3D: THREE.Object3D, config: Map<string, string>): void;
6216
+ }
6217
+
6218
+ /**
6219
+ * Visual factory for XOR gates components
6220
+ *
6221
+ * Creates:
6222
+ * - Gate mesh
6223
+ * - vcc, gnd, inputs and output pin groups
6206
6224
  * - Component hitbox for raycasting
6207
6225
  *
6208
6226
  * Animation:
@@ -6214,7 +6232,7 @@ export declare class XorGateVisualFactory extends ComponentVisualFactoryBase {
6214
6232
  /** Gate high emissive intensity */
6215
6233
  protected static readonly HIGH_INTENSITY = 0.3;
6216
6234
  /** XOR tail geometry */
6217
- protected static readonly tailGeometry: THREE.ExtrudeGeometry;
6235
+ protected readonly tailGeometry: THREE.ExtrudeGeometry;
6218
6236
  /** Shared open envelope geometry */
6219
6237
  protected readonly lowGeometry: THREE.ExtrudeGeometry;
6220
6238
  /** Shared transient envelope geometry */
@@ -6222,17 +6240,19 @@ export declare class XorGateVisualFactory extends ComponentVisualFactoryBase {
6222
6240
  /** Shared transient envelope geometry */
6223
6241
  protected readonly highGeometry: THREE.ExtrudeGeometry;
6224
6242
  /** Shared material for negative marker **/
6225
- protected static readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
6243
+ protected readonly negativeMarkerMaterial: THREE.MeshStandardMaterial;
6226
6244
  /** Shared geometry for negative marker **/
6227
- protected static readonly negativeMarkerGeometry: THREE.CylinderGeometry;
6245
+ protected readonly negativeMarkerGeometry: THREE.CylinderGeometry;
6228
6246
  defaultRotation(): number;
6229
- createVisual(component: Component): THREE.Object3D;
6247
+ createVisual(component: Component, context: VisualContext): THREE.Object3D;
6248
+ protected createPinsVisual(component: Component, context: VisualContext, group: THREE.Group): void;
6230
6249
  /**
6231
- * Get config form definition for OR Gate
6250
+ * Get config form definition for XOR/XNOR Gate
6232
6251
  *
6233
- * @returns Form definition with activationLogic boolean field
6252
+ * @param config - Optional current config to determine disabled state of transitionSpan
6253
+ * @returns Form definition with defaultLogicFamily dropdown, activationLogic boolean, and transitionSpan number
6234
6254
  */
6235
- getConfigFormDefinition(): ConfigFormDefinition | null;
6255
+ getConfigFormDefinition(config?: Map<string, string>): ConfigFormDefinition | null;
6236
6256
  /**
6237
6257
  * Map core config to form data
6238
6258
  * Converts "positive"/"negative" strings to boolean