@tscircuit/core 0.0.1966 → 0.0.1967

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
@@ -358,6 +358,7 @@ interface DebugLogOutputEvent {
358
358
  }
359
359
 
360
360
  interface IIsolatedCircuit {
361
+ _hasRenderLifecycleListeners?: boolean;
361
362
  hasEventListener?(event: RootCircuitEventName): boolean;
362
363
  emit(event: RootCircuitEventName, ...args: any[]): void;
363
364
  on(event: RootCircuitEventName, listener: (...args: any[]) => void): void;
@@ -395,7 +396,10 @@ type IRenderable = RenderPhaseFunctions & {
395
396
  runRenderCycle(): void;
396
397
  };
397
398
  declare abstract class Renderable implements IRenderable {
398
- renderPhaseStates: RenderPhaseStates;
399
+ private _phaseStatesByName?;
400
+ private readonly _phaseStatesByIndex;
401
+ get renderPhaseStates(): RenderPhaseStates;
402
+ set renderPhaseStates(states: RenderPhaseStates);
399
403
  shouldBeRemoved: boolean;
400
404
  children: IRenderable[];
401
405
  /** PCB-only SMTPads, PlatedHoles, Holes, Silkscreen elements etc. */
@@ -595,6 +599,7 @@ declare class IsolatedCircuit {
595
599
  selectOne(selector: string, opts?: {
596
600
  type?: "component" | "port";
597
601
  }): PrimitiveComponent | null;
602
+ _hasRenderLifecycleListeners: boolean;
598
603
  _eventListeners: Record<RootCircuitEventName, Array<(...args: any[]) => void>>;
599
604
  emit(event: RootCircuitEventName, ...args: any[]): void;
600
605
  hasEventListener(event: RootCircuitEventName): boolean;
package/dist/index.js CHANGED
@@ -622,7 +622,21 @@ var asyncPhaseDependencies = {
622
622
  var globalRenderCounter = 0;
623
623
  var globalAsyncEffectCounter = 0;
624
624
  var Renderable = class _Renderable {
625
- renderPhaseStates;
625
+ _phaseStatesByName;
626
+ _phaseStatesByIndex;
627
+ // Build the named map once, sharing the state objects used by the render loop.
628
+ // Once exposed, use the map so callers can also replace individual entries.
629
+ get renderPhaseStates() {
630
+ return this._phaseStatesByName ??= Object.fromEntries(
631
+ orderedRenderPhases.map((phase, index) => [
632
+ phase,
633
+ this._phaseStatesByIndex[index]
634
+ ])
635
+ );
636
+ }
637
+ set renderPhaseStates(states) {
638
+ this._phaseStatesByName = states;
639
+ }
626
640
  shouldBeRemoved = false;
627
641
  children;
628
642
  /** PCB-only SMTPads, PlatedHoles, Holes, Silkscreen elements etc. */
@@ -637,19 +651,19 @@ var Renderable = class _Renderable {
637
651
  constructor(props) {
638
652
  this._renderId = `${globalRenderCounter++}`;
639
653
  this.children = [];
640
- this.renderPhaseStates = {};
641
- for (const phase of orderedRenderPhases) {
642
- this.renderPhaseStates[phase] = {
654
+ this._phaseStatesByIndex = Array.from(
655
+ { length: orderedRenderPhases.length },
656
+ () => ({
643
657
  initialized: false,
644
658
  dirty: false
645
- };
646
- }
659
+ })
660
+ );
647
661
  }
648
662
  _markDirty(phase) {
649
- this.renderPhaseStates[phase].dirty = true;
650
663
  const phaseIndex = renderPhaseIndexMap.get(phase);
651
- for (let i = phaseIndex + 1; i < orderedRenderPhases.length; i++) {
652
- this.renderPhaseStates[orderedRenderPhases[i]].dirty = true;
664
+ for (let i = phaseIndex; i < orderedRenderPhases.length; i++) {
665
+ const state = this._phaseStatesByName?.[orderedRenderPhases[i]] ?? this._phaseStatesByIndex[i];
666
+ state.dirty = true;
653
667
  }
654
668
  if (this.parent?._markDirty) {
655
669
  this.parent._markDirty(phase);
@@ -705,8 +719,9 @@ ${error.stack}`
705
719
  });
706
720
  }
707
721
  _emitRenderLifecycleEvent(phase, startOrEnd) {
708
- const granular_event_type = `renderable:renderLifecycle:${phase}:${startOrEnd}`;
709
722
  const root = this._getRootCircuit();
723
+ if (root?._hasRenderLifecycleListeners === false && !debug.enabled) return;
724
+ const granular_event_type = `renderable:renderLifecycle:${phase}:${startOrEnd}`;
710
725
  const hasListeners = root && (!root.hasEventListener || root.hasEventListener(granular_event_type) || root.hasEventListener("renderable:renderLifecycle:anyEvent"));
711
726
  if (!debug.enabled && !hasListeners) return;
712
727
  const componentDisplayName = this.getString();
@@ -786,9 +801,9 @@ ${error.stack}`
786
801
  */
787
802
  runRenderPhase(phase) {
788
803
  this._currentRenderPhase = phase;
789
- const phaseState = this.renderPhaseStates[phase];
790
- const isInitialized = phaseState.initialized;
791
- const isDirty = phaseState.dirty;
804
+ const phaseIndex = renderPhaseIndexMap.get(phase);
805
+ const phaseState = this._phaseStatesByName?.[phase] ?? this._phaseStatesByIndex[phaseIndex];
806
+ const { initialized: isInitialized, dirty: isDirty } = phaseState;
792
807
  if (!isInitialized && this.shouldBeRemoved) return;
793
808
  if (this.shouldBeRemoved && isInitialized) {
794
809
  this._emitRenderLifecycleEvent(phase, "start");
@@ -798,10 +813,12 @@ ${error.stack}`
798
813
  this._emitRenderLifecycleEvent(phase, "end");
799
814
  return;
800
815
  }
801
- const prevPhaseIndex = renderPhaseIndexMap.get(phase) - 1;
802
- if (prevPhaseIndex >= 0) {
816
+ const prevPhaseIndex = phaseIndex - 1;
817
+ if (this._asyncEffects.length > 0 && prevPhaseIndex >= 0) {
803
818
  const prevPhase = orderedRenderPhases[prevPhaseIndex];
804
- const hasIncompleteEffects = this._asyncEffects.filter((e) => e.phase === prevPhase).some((e) => !e.complete);
819
+ const hasIncompleteEffects = this._asyncEffects.some(
820
+ (e) => e.phase === prevPhase && !e.complete
821
+ );
805
822
  if (hasIncompleteEffects) return;
806
823
  }
807
824
  const deps = asyncPhaseDependencies[phase] || [];
@@ -829,7 +846,7 @@ ${error.stack}`
829
846
  }
830
847
  runRenderPhaseForChildren(phase) {
831
848
  for (const child of this.children) {
832
- if ("_isIsolatedSubcircuit" in this && this._isIsolatedSubcircuit && "doInitialRenderIsolatedSubcircuits" in this && phase === "RenderIsolatedSubcircuits") {
849
+ if (phase === "RenderIsolatedSubcircuits" && "_isIsolatedSubcircuit" in this && this._isIsolatedSubcircuit && "doInitialRenderIsolatedSubcircuits" in this) {
833
850
  continue;
834
851
  }
835
852
  child.runRenderPhaseForChildren(phase);
@@ -63783,7 +63800,7 @@ function Group_getRoutingPhasePlans(group) {
63783
63800
  var package_default = {
63784
63801
  name: "@tscircuit/core",
63785
63802
  type: "module",
63786
- version: "0.0.1965",
63803
+ version: "0.0.1966",
63787
63804
  types: "dist/index.d.ts",
63788
63805
  main: "dist/index.js",
63789
63806
  module: "dist/index.js",
@@ -68649,6 +68666,7 @@ var IsolatedCircuit = class {
68649
68666
  this._guessRootComponent();
68650
68667
  return this.firstChild?.selectOne(selector, opts) ?? null;
68651
68668
  }
68669
+ _hasRenderLifecycleListeners = false;
68652
68670
  _eventListeners = {};
68653
68671
  emit(event, ...args) {
68654
68672
  if (event === "asyncEffect:start") {
@@ -68669,12 +68687,22 @@ var IsolatedCircuit = class {
68669
68687
  this._eventListeners[event] = [];
68670
68688
  }
68671
68689
  this._eventListeners[event].push(listener);
68690
+ if (event.startsWith("renderable:renderLifecycle:")) {
68691
+ this._hasRenderLifecycleListeners = true;
68692
+ }
68672
68693
  }
68673
68694
  removeListener(event, listener) {
68674
68695
  if (!this._eventListeners[event]) return;
68675
68696
  this._eventListeners[event] = this._eventListeners[event].filter(
68676
68697
  (l) => l !== listener
68677
68698
  );
68699
+ if (event.startsWith("renderable:renderLifecycle:")) {
68700
+ this._hasRenderLifecycleListeners = Object.entries(
68701
+ this._eventListeners
68702
+ ).some(
68703
+ ([eventName, listeners]) => eventName.startsWith("renderable:renderLifecycle:") && listeners.length > 0
68704
+ );
68705
+ }
68678
68706
  }
68679
68707
  enableDebug(debug13) {
68680
68708
  if (typeof debug13 === "string") {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1966",
4
+ "version": "0.0.1967",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",