@tscircuit/core 0.0.985 → 0.0.986

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +123 -109
  2. package/dist/index.js +71 -16
  3. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -16,115 +16,6 @@ import { CopperPourPipelineSolver } from '@tscircuit/copper-pour-solver';
16
16
  import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
17
17
  import { GraphicsObject } from 'graphics-debug';
18
18
 
19
- declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SchematicPrimitiveRender", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicTraceRender", "SchematicReplaceNetLabelsWithSymbols", "PanelBoardLayout", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbTraceHintRender", "PcbManualTraceRender", "PcbTraceRender", "PcbRouteNetIslands", "PcbCopperPourRender", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "SimulationSpiceEngineRender"];
20
- type RenderPhase = (typeof orderedRenderPhases)[number];
21
- declare const renderPhaseIndexMap: Map<"ReactSubtreesRender" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SchematicPrimitiveRender" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicTraceRender" | "SchematicReplaceNetLabelsWithSymbols" | "PanelBoardLayout" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbCopperPourRender" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "SimulationSpiceEngineRender", number>;
22
- type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
23
- type RenderPhaseStates = Record<RenderPhase, {
24
- initialized: boolean;
25
- dirty: boolean;
26
- }>;
27
- type AsyncEffect = {
28
- effectName: string;
29
- promise: Promise<void>;
30
- phase: RenderPhase;
31
- complete: boolean;
32
- };
33
- type RenderPhaseFunctions = {
34
- [T in RenderPhaseFn]?: () => void;
35
- };
36
- type IRenderable = RenderPhaseFunctions & {
37
- renderPhaseStates: RenderPhaseStates;
38
- runRenderPhase(phase: RenderPhase): void;
39
- runRenderPhaseForChildren(phase: RenderPhase): void;
40
- shouldBeRemoved: boolean;
41
- children: IRenderable[];
42
- runRenderCycle(): void;
43
- };
44
- declare abstract class Renderable implements IRenderable {
45
- renderPhaseStates: RenderPhaseStates;
46
- shouldBeRemoved: boolean;
47
- children: IRenderable[];
48
- /** PCB-only SMTPads, PlatedHoles, Holes, Silkscreen elements etc. */
49
- isPcbPrimitive: boolean;
50
- /** Schematic-only, lines, boxes, indicators etc. */
51
- isSchematicPrimitive: boolean;
52
- _renderId: string;
53
- _currentRenderPhase: RenderPhase | null;
54
- private _asyncEffects;
55
- parent: Renderable | null;
56
- constructor(props: any);
57
- _markDirty(phase: RenderPhase): void;
58
- _queueAsyncEffect(effectName: string, effect: () => Promise<void>): void;
59
- protected _emitRenderLifecycleEvent(phase: RenderPhase, startOrEnd: "start" | "end"): void;
60
- getString(): string;
61
- _hasIncompleteAsyncEffects(): boolean;
62
- _hasIncompleteAsyncEffectsInSubtreeForPhase(phase: RenderPhase): boolean;
63
- getCurrentRenderPhase(): RenderPhase | null;
64
- getRenderGraph(): Record<string, any>;
65
- getTopLevelRenderable(): Renderable;
66
- runRenderCycle(): void;
67
- /**
68
- * This runs all the render methods for a given phase, calling one of:
69
- * - doInitial*
70
- * - update*
71
- * -remove*
72
- * ...depending on the current state of the component.
73
- */
74
- runRenderPhase(phase: RenderPhase): void;
75
- runRenderPhaseForChildren(phase: RenderPhase): void;
76
- renderError(message: string | Omit<PcbTraceError, "pcb_error_id"> | Omit<PcbPlacementError, "pcb_error_id"> | Omit<PcbManualEditConflictWarning, "pcb_error_id"> | Omit<PcbViaClearanceError, "pcb_error_id">): void;
77
- }
78
-
79
- /**
80
- * This is how we render in React. This can be a confusing part of the codebase,
81
- * but here are some helpful reference implementations:
82
- *
83
- * https://github.com/diegomura/react-pdf/blob/fabecc56727dfb6d590a3fa1e11f50250ecbbea1/packages/reconciler/src/reconciler-31.js
84
- * https://github.com/pmndrs/react-three-fiber/blob/ec4f00bb61cc4f6e28b3a12b1dca9daa5594f10e/packages/fiber/src/core/renderer.ts
85
- *
86
- *
87
- */
88
-
89
- type ReactSubtree = {
90
- element: ReactElement;
91
- component: NormalComponent;
92
- };
93
-
94
- type SchematicBoxPortPositionWithMetadata = {
95
- trueIndex: number;
96
- pinNumber: number;
97
- side: "left" | "right" | "top" | "bottom";
98
- distanceFromOrthogonalEdge: number;
99
- x: number;
100
- y: number;
101
- };
102
- interface SchematicBoxDimensions {
103
- pinCount: number;
104
- getPortPositionByPinNumber(pinNumber: number): SchematicBoxPortPositionWithMetadata | null;
105
- getSize(): {
106
- width: number;
107
- height: number;
108
- };
109
- getSizeIncludingPins(): {
110
- width: number;
111
- height: number;
112
- };
113
- }
114
- interface SchematicBoxComponentDimensions {
115
- schWidth: number;
116
- schHeight: number;
117
- }
118
-
119
- interface BoardI {
120
- componentName: string;
121
- boardThickness: number;
122
- _connectedSchematicPortPairs: Set<string>;
123
- allLayers: ReadonlyArray<LayerRef>;
124
- _getBoardCalcVariables(): Record<string, number>;
125
- pcb_board_id?: string | null;
126
- }
127
-
128
19
  declare const SOLVERS: {
129
20
  PackSolver2: typeof PackSolver2;
130
21
  AutoroutingPipelineSolver: typeof AutoroutingPipelineSolver;
@@ -271,6 +162,124 @@ interface DebugLogOutputEvent {
271
162
  content: any;
272
163
  }
273
164
 
165
+ interface IRootCircuit {
166
+ emit(event: RootCircuitEventName, ...args: any[]): void;
167
+ on(event: RootCircuitEventName, listener: (...args: any[]) => void): void;
168
+ _hasIncompleteAsyncEffectsForPhase(phase: RenderPhase): boolean;
169
+ }
170
+
171
+ declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SchematicPrimitiveRender", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicTraceRender", "SchematicReplaceNetLabelsWithSymbols", "PanelBoardLayout", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbTraceHintRender", "PcbManualTraceRender", "PcbTraceRender", "PcbRouteNetIslands", "PcbCopperPourRender", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "SimulationSpiceEngineRender"];
172
+ type RenderPhase = (typeof orderedRenderPhases)[number];
173
+ declare const renderPhaseIndexMap: Map<"ReactSubtreesRender" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SchematicPrimitiveRender" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicTraceRender" | "SchematicReplaceNetLabelsWithSymbols" | "PanelBoardLayout" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbCopperPourRender" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "SimulationSpiceEngineRender", number>;
174
+ type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
175
+ type RenderPhaseStates = Record<RenderPhase, {
176
+ initialized: boolean;
177
+ dirty: boolean;
178
+ }>;
179
+ type AsyncEffect = {
180
+ asyncEffectId: string;
181
+ effectName: string;
182
+ promise: Promise<void>;
183
+ phase: RenderPhase;
184
+ complete: boolean;
185
+ };
186
+ type RenderPhaseFunctions = {
187
+ [T in RenderPhaseFn]?: () => void;
188
+ };
189
+ type IRenderable = RenderPhaseFunctions & {
190
+ renderPhaseStates: RenderPhaseStates;
191
+ runRenderPhase(phase: RenderPhase): void;
192
+ runRenderPhaseForChildren(phase: RenderPhase): void;
193
+ shouldBeRemoved: boolean;
194
+ children: IRenderable[];
195
+ runRenderCycle(): void;
196
+ };
197
+ declare abstract class Renderable implements IRenderable {
198
+ renderPhaseStates: RenderPhaseStates;
199
+ shouldBeRemoved: boolean;
200
+ children: IRenderable[];
201
+ /** PCB-only SMTPads, PlatedHoles, Holes, Silkscreen elements etc. */
202
+ isPcbPrimitive: boolean;
203
+ /** Schematic-only, lines, boxes, indicators etc. */
204
+ isSchematicPrimitive: boolean;
205
+ _renderId: string;
206
+ _currentRenderPhase: RenderPhase | null;
207
+ private _asyncEffects;
208
+ parent: Renderable | null;
209
+ constructor(props: any);
210
+ _markDirty(phase: RenderPhase): void;
211
+ _queueAsyncEffect(effectName: string, effect: () => Promise<void>): void;
212
+ protected _emitRenderLifecycleEvent(phase: RenderPhase, startOrEnd: "start" | "end"): void;
213
+ getString(): string;
214
+ _hasIncompleteAsyncEffects(): boolean;
215
+ _hasIncompleteAsyncEffectsInSubtreeForPhase(phase: RenderPhase): boolean;
216
+ _hasIncompleteAsyncEffectsForPhase(phase: RenderPhase): boolean;
217
+ getCurrentRenderPhase(): RenderPhase | null;
218
+ getRenderGraph(): Record<string, any>;
219
+ getTopLevelRenderable(): Renderable;
220
+ runRenderCycle(): void;
221
+ /**
222
+ * This runs all the render methods for a given phase, calling one of:
223
+ * - doInitial*
224
+ * - update*
225
+ * -remove*
226
+ * ...depending on the current state of the component.
227
+ */
228
+ runRenderPhase(phase: RenderPhase): void;
229
+ runRenderPhaseForChildren(phase: RenderPhase): void;
230
+ protected _getRootCircuit(): IRootCircuit | null;
231
+ renderError(message: string | Omit<PcbTraceError, "pcb_error_id"> | Omit<PcbPlacementError, "pcb_error_id"> | Omit<PcbManualEditConflictWarning, "pcb_error_id"> | Omit<PcbViaClearanceError, "pcb_error_id">): void;
232
+ }
233
+
234
+ /**
235
+ * This is how we render in React. This can be a confusing part of the codebase,
236
+ * but here are some helpful reference implementations:
237
+ *
238
+ * https://github.com/diegomura/react-pdf/blob/fabecc56727dfb6d590a3fa1e11f50250ecbbea1/packages/reconciler/src/reconciler-31.js
239
+ * https://github.com/pmndrs/react-three-fiber/blob/ec4f00bb61cc4f6e28b3a12b1dca9daa5594f10e/packages/fiber/src/core/renderer.ts
240
+ *
241
+ *
242
+ */
243
+
244
+ type ReactSubtree = {
245
+ element: ReactElement;
246
+ component: NormalComponent;
247
+ };
248
+
249
+ type SchematicBoxPortPositionWithMetadata = {
250
+ trueIndex: number;
251
+ pinNumber: number;
252
+ side: "left" | "right" | "top" | "bottom";
253
+ distanceFromOrthogonalEdge: number;
254
+ x: number;
255
+ y: number;
256
+ };
257
+ interface SchematicBoxDimensions {
258
+ pinCount: number;
259
+ getPortPositionByPinNumber(pinNumber: number): SchematicBoxPortPositionWithMetadata | null;
260
+ getSize(): {
261
+ width: number;
262
+ height: number;
263
+ };
264
+ getSizeIncludingPins(): {
265
+ width: number;
266
+ height: number;
267
+ };
268
+ }
269
+ interface SchematicBoxComponentDimensions {
270
+ schWidth: number;
271
+ schHeight: number;
272
+ }
273
+
274
+ interface BoardI {
275
+ componentName: string;
276
+ boardThickness: number;
277
+ _connectedSchematicPortPairs: Set<string>;
278
+ allLayers: ReadonlyArray<LayerRef>;
279
+ _getBoardCalcVariables(): Record<string, number>;
280
+ pcb_board_id?: string | null;
281
+ }
282
+
274
283
  declare function resolveStaticFileImport(path: string, platform?: PlatformConfig): Promise<string>;
275
284
 
276
285
  declare class RootCircuit {
@@ -299,6 +308,8 @@ declare class RootCircuit {
299
308
  */
300
309
  projectUrl?: string;
301
310
  _hasRenderedAtleastOnce: boolean;
311
+ private _asyncEffectIdsByPhase;
312
+ private _asyncEffectPhaseById;
302
313
  constructor({ platform, projectUrl, }?: {
303
314
  platform?: PlatformConfig;
304
315
  projectUrl?: string;
@@ -313,6 +324,7 @@ declare class RootCircuit {
313
324
  render(): void;
314
325
  renderUntilSettled(): Promise<void>;
315
326
  private _hasIncompleteAsyncEffects;
327
+ _hasIncompleteAsyncEffectsForPhase(phase: RenderPhase): boolean;
316
328
  getCircuitJson(): AnyCircuitElement[];
317
329
  toJson(): AnyCircuitElement[];
318
330
  getSvg(options: {
@@ -336,6 +348,8 @@ declare class RootCircuit {
336
348
  removeListener(event: RootCircuitEventName, listener: (...args: any[]) => void): void;
337
349
  enableDebug(debug: string | null | false): void;
338
350
  getClientOrigin(): string;
351
+ private _registerAsyncEffectStart;
352
+ private _registerAsyncEffectEnd;
339
353
  }
340
354
  /**
341
355
  * @deprecated
package/dist/index.js CHANGED
@@ -185,6 +185,7 @@ var asyncPhaseDependencies = {
185
185
  PcbComponentAnchorAlignment: ["PcbFootprintStringRender"]
186
186
  };
187
187
  var globalRenderCounter = 0;
188
+ var globalAsyncEffectCounter = 0;
188
189
  var Renderable = class _Renderable {
189
190
  renderPhaseStates;
190
191
  shouldBeRemoved = false;
@@ -219,7 +220,9 @@ var Renderable = class _Renderable {
219
220
  }
220
221
  }
221
222
  _queueAsyncEffect(effectName, effect) {
223
+ const asyncEffectId = `${this._renderId}:${globalAsyncEffectCounter++}`;
222
224
  const asyncEffect = {
225
+ asyncEffectId,
223
226
  promise: effect(),
224
227
  // TODO don't start effects until end of render cycle
225
228
  phase: this._currentRenderPhase,
@@ -227,9 +230,10 @@ var Renderable = class _Renderable {
227
230
  complete: false
228
231
  };
229
232
  this._asyncEffects.push(asyncEffect);
230
- if ("root" in this && this.root) {
231
- ;
232
- this.root.emit("asyncEffect:start", {
233
+ const root = this._getRootCircuit();
234
+ if (root) {
235
+ root.emit("asyncEffect:start", {
236
+ asyncEffectId,
233
237
  effectName,
234
238
  componentDisplayName: this.getString(),
235
239
  phase: asyncEffect.phase
@@ -237,9 +241,10 @@ var Renderable = class _Renderable {
237
241
  }
238
242
  asyncEffect.promise.then(() => {
239
243
  asyncEffect.complete = true;
240
- if ("root" in this && this.root) {
241
- ;
242
- this.root.emit("asyncEffect:end", {
244
+ const root2 = this._getRootCircuit();
245
+ if (root2) {
246
+ root2.emit("asyncEffect:end", {
247
+ asyncEffectId,
243
248
  effectName,
244
249
  componentDisplayName: this.getString(),
245
250
  phase: asyncEffect.phase
@@ -251,9 +256,10 @@ var Renderable = class _Renderable {
251
256
  ${error.stack}`
252
257
  );
253
258
  asyncEffect.complete = true;
254
- if ("root" in this && this.root) {
255
- ;
256
- this.root.emit("asyncEffect:end", {
259
+ const root2 = this._getRootCircuit();
260
+ if (root2) {
261
+ root2.emit("asyncEffect:end", {
262
+ asyncEffectId,
257
263
  effectName,
258
264
  componentDisplayName: this.getString(),
259
265
  phase: asyncEffect.phase,
@@ -270,10 +276,10 @@ ${error.stack}`
270
276
  componentDisplayName: this.getString(),
271
277
  type: granular_event_type
272
278
  };
273
- if ("root" in this && this.root) {
274
- ;
275
- this.root.emit(granular_event_type, eventPayload);
276
- this.root.emit("renderable:renderLifecycle:anyEvent", {
279
+ const root = this._getRootCircuit();
280
+ if (root) {
281
+ root.emit(granular_event_type, eventPayload);
282
+ root.emit("renderable:renderLifecycle:anyEvent", {
277
283
  ...eventPayload,
278
284
  type: granular_event_type
279
285
  });
@@ -299,6 +305,13 @@ ${error.stack}`
299
305
  }
300
306
  return false;
301
307
  }
308
+ _hasIncompleteAsyncEffectsForPhase(phase) {
309
+ const root = this._getRootCircuit();
310
+ if (root?._hasIncompleteAsyncEffectsForPhase) {
311
+ return root._hasIncompleteAsyncEffectsForPhase(phase);
312
+ }
313
+ return this._hasIncompleteAsyncEffectsInSubtreeForPhase(phase);
314
+ }
302
315
  getCurrentRenderPhase() {
303
316
  return this._currentRenderPhase;
304
317
  }
@@ -355,9 +368,8 @@ ${error.stack}`
355
368
  }
356
369
  const deps = asyncPhaseDependencies[phase] || [];
357
370
  if (deps.length > 0) {
358
- const root = this.getTopLevelRenderable();
359
371
  for (const depPhase of deps) {
360
- if (root._hasIncompleteAsyncEffectsInSubtreeForPhase(depPhase)) {
372
+ if (this._hasIncompleteAsyncEffectsForPhase(depPhase)) {
361
373
  return;
362
374
  }
363
375
  }
@@ -383,6 +395,12 @@ ${error.stack}`
383
395
  child.runRenderPhase(phase);
384
396
  }
385
397
  }
398
+ _getRootCircuit() {
399
+ if ("root" in this) {
400
+ return this.root ?? null;
401
+ }
402
+ return null;
403
+ }
386
404
  renderError(message) {
387
405
  if (typeof message === "string") {
388
406
  throw new Error(message);
@@ -21002,7 +21020,7 @@ import { identity as identity5 } from "transformation-matrix";
21002
21020
  var package_default = {
21003
21021
  name: "@tscircuit/core",
21004
21022
  type: "module",
21005
- version: "0.0.984",
21023
+ version: "0.0.985",
21006
21024
  types: "dist/index.d.ts",
21007
21025
  main: "dist/index.js",
21008
21026
  module: "dist/index.js",
@@ -21152,6 +21170,8 @@ var RootCircuit = class {
21152
21170
  */
21153
21171
  projectUrl;
21154
21172
  _hasRenderedAtleastOnce = false;
21173
+ _asyncEffectIdsByPhase = /* @__PURE__ */ new Map();
21174
+ _asyncEffectPhaseById = /* @__PURE__ */ new Map();
21155
21175
  constructor({
21156
21176
  platform,
21157
21177
  projectUrl
@@ -21244,8 +21264,12 @@ var RootCircuit = class {
21244
21264
  this.emit("renderComplete");
21245
21265
  }
21246
21266
  _hasIncompleteAsyncEffects() {
21267
+ if (this._asyncEffectPhaseById.size > 0) return true;
21247
21268
  return this.children.some((child) => child._hasIncompleteAsyncEffects());
21248
21269
  }
21270
+ _hasIncompleteAsyncEffectsForPhase(phase) {
21271
+ return (this._asyncEffectIdsByPhase.get(phase)?.size ?? 0) > 0;
21272
+ }
21249
21273
  getCircuitJson() {
21250
21274
  if (!this._hasRenderedAtleastOnce) this.render();
21251
21275
  return this.db.toArray();
@@ -21295,6 +21319,11 @@ var RootCircuit = class {
21295
21319
  }
21296
21320
  _eventListeners = {};
21297
21321
  emit(event, ...args) {
21322
+ if (event === "asyncEffect:start") {
21323
+ this._registerAsyncEffectStart(args[0]);
21324
+ } else if (event === "asyncEffect:end") {
21325
+ this._registerAsyncEffectEnd(args[0]);
21326
+ }
21298
21327
  if (!this._eventListeners[event]) return;
21299
21328
  for (const listener of this._eventListeners[event]) {
21300
21329
  listener(...args);
@@ -21328,6 +21357,32 @@ var RootCircuit = class {
21328
21357
  }
21329
21358
  return "";
21330
21359
  }
21360
+ _registerAsyncEffectStart(payload) {
21361
+ if (!payload?.asyncEffectId || !payload.phase) return;
21362
+ const { asyncEffectId, phase } = payload;
21363
+ const existingPhase = this._asyncEffectPhaseById.get(asyncEffectId);
21364
+ if (existingPhase && existingPhase !== phase) {
21365
+ this._asyncEffectIdsByPhase.get(existingPhase)?.delete(asyncEffectId);
21366
+ }
21367
+ if (!this._asyncEffectIdsByPhase.has(phase)) {
21368
+ this._asyncEffectIdsByPhase.set(phase, /* @__PURE__ */ new Set());
21369
+ }
21370
+ this._asyncEffectIdsByPhase.get(phase).add(asyncEffectId);
21371
+ this._asyncEffectPhaseById.set(asyncEffectId, phase);
21372
+ }
21373
+ _registerAsyncEffectEnd(payload) {
21374
+ if (!payload?.asyncEffectId) return;
21375
+ const { asyncEffectId } = payload;
21376
+ const phase = this._asyncEffectPhaseById.get(asyncEffectId) ?? payload.phase;
21377
+ if (phase) {
21378
+ const phaseSet = this._asyncEffectIdsByPhase.get(phase);
21379
+ phaseSet?.delete(asyncEffectId);
21380
+ if (phaseSet && phaseSet.size === 0) {
21381
+ this._asyncEffectIdsByPhase.delete(phase);
21382
+ }
21383
+ }
21384
+ this._asyncEffectPhaseById.delete(asyncEffectId);
21385
+ }
21331
21386
  };
21332
21387
  var Project = RootCircuit;
21333
21388
  var Circuit = RootCircuit;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.985",
4
+ "version": "0.0.986",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",