@tscircuit/core 0.0.133 → 0.0.134
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 +12 -0
- package/dist/index.js +95 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ type RenderPhase = (typeof orderedRenderPhases)[number];
|
|
|
13
13
|
type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
|
|
14
14
|
type RenderPhaseStates = Record<RenderPhase, {
|
|
15
15
|
initialized: boolean;
|
|
16
|
+
dirty: boolean;
|
|
16
17
|
}>;
|
|
17
18
|
type RenderPhaseFunctions = {
|
|
18
19
|
[T in RenderPhaseFn]?: () => void;
|
|
@@ -34,7 +35,12 @@ declare abstract class Renderable implements IRenderable {
|
|
|
34
35
|
/** Schematic-only, lines, boxes, indicators etc. */
|
|
35
36
|
isSchematicPrimitive: boolean;
|
|
36
37
|
_renderId: string;
|
|
38
|
+
_currentRenderPhase: RenderPhase | null;
|
|
39
|
+
private _asyncEffects;
|
|
37
40
|
constructor(props: any);
|
|
41
|
+
protected _markDirty(phase: RenderPhase): void;
|
|
42
|
+
protected _queueAsyncEffect(effect: () => Promise<void>): void;
|
|
43
|
+
_hasIncompleteAsyncEffects(): boolean;
|
|
38
44
|
runRenderCycle(): void;
|
|
39
45
|
/**
|
|
40
46
|
* This runs all the render methods for a given phase, calling one of:
|
|
@@ -53,6 +59,7 @@ type ReactSubtree = {
|
|
|
53
59
|
component: NormalComponent;
|
|
54
60
|
};
|
|
55
61
|
|
|
62
|
+
type RootCircuitEventName = "asyncEffectComplete";
|
|
56
63
|
declare class Circuit {
|
|
57
64
|
firstChild: PrimitiveComponent | null;
|
|
58
65
|
children: PrimitiveComponent[];
|
|
@@ -71,6 +78,8 @@ declare class Circuit {
|
|
|
71
78
|
};
|
|
72
79
|
_guessRootComponent(): void;
|
|
73
80
|
render(): void;
|
|
81
|
+
renderUntilSettled(): Promise<void>;
|
|
82
|
+
private _hasIncompleteAsyncEffects;
|
|
74
83
|
getSoup(): AnyCircuitElement[];
|
|
75
84
|
getCircuitJson(): AnyCircuitElement[];
|
|
76
85
|
toJson(): AnyCircuitElement[];
|
|
@@ -88,6 +97,9 @@ declare class Circuit {
|
|
|
88
97
|
selectOne(selector: string, opts?: {
|
|
89
98
|
type?: "component" | "port";
|
|
90
99
|
}): PrimitiveComponent | null;
|
|
100
|
+
_eventListeners: Record<RootCircuitEventName, Array<(...args: any[]) => void>>;
|
|
101
|
+
emit(event: RootCircuitEventName, ...args: any[]): void;
|
|
102
|
+
on(event: RootCircuitEventName, listener: (...args: any[]) => void): void;
|
|
91
103
|
}
|
|
92
104
|
/**
|
|
93
105
|
* @deprecated
|
package/dist/index.js
CHANGED
|
@@ -87,14 +87,61 @@ var Renderable = class {
|
|
|
87
87
|
/** Schematic-only, lines, boxes, indicators etc. */
|
|
88
88
|
isSchematicPrimitive = false;
|
|
89
89
|
_renderId;
|
|
90
|
+
_currentRenderPhase = null;
|
|
91
|
+
_asyncEffects = [];
|
|
90
92
|
constructor(props) {
|
|
91
93
|
this._renderId = `${globalRenderCounter++}`;
|
|
92
94
|
this.children = [];
|
|
93
95
|
this.renderPhaseStates = {};
|
|
94
96
|
for (const phase of orderedRenderPhases) {
|
|
95
|
-
this.renderPhaseStates[phase] = {
|
|
97
|
+
this.renderPhaseStates[phase] = {
|
|
98
|
+
initialized: false,
|
|
99
|
+
dirty: false
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
_markDirty(phase) {
|
|
104
|
+
this.renderPhaseStates[phase].dirty = true;
|
|
105
|
+
const phaseIndex = orderedRenderPhases.indexOf(phase);
|
|
106
|
+
for (let i = phaseIndex + 1; i < orderedRenderPhases.length; i++) {
|
|
107
|
+
this.renderPhaseStates[orderedRenderPhases[i]].dirty = true;
|
|
96
108
|
}
|
|
97
109
|
}
|
|
110
|
+
_queueAsyncEffect(effect) {
|
|
111
|
+
const asyncEffect = {
|
|
112
|
+
promise: effect(),
|
|
113
|
+
// TODO don't start effects until end of render cycle
|
|
114
|
+
phase: this._currentRenderPhase,
|
|
115
|
+
complete: false
|
|
116
|
+
};
|
|
117
|
+
this._asyncEffects.push(asyncEffect);
|
|
118
|
+
asyncEffect.promise.then(() => {
|
|
119
|
+
asyncEffect.complete = true;
|
|
120
|
+
if ("root" in this && this.root) {
|
|
121
|
+
;
|
|
122
|
+
this.root.emit("asyncEffectComplete", {
|
|
123
|
+
component: this,
|
|
124
|
+
asyncEffect
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}).catch((error) => {
|
|
128
|
+
console.error(
|
|
129
|
+
`Async effect error in ${this._currentRenderPhase}:`,
|
|
130
|
+
error
|
|
131
|
+
);
|
|
132
|
+
asyncEffect.complete = true;
|
|
133
|
+
if ("root" in this && this.root) {
|
|
134
|
+
;
|
|
135
|
+
this.root.emit("asyncEffectComplete", {
|
|
136
|
+
component: this,
|
|
137
|
+
asyncEffect
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
_hasIncompleteAsyncEffects() {
|
|
143
|
+
return this._asyncEffects.some((effect) => !effect.complete);
|
|
144
|
+
}
|
|
98
145
|
runRenderCycle() {
|
|
99
146
|
for (const renderPhase of orderedRenderPhases) {
|
|
100
147
|
this.runRenderPhaseForChildren(renderPhase);
|
|
@@ -109,22 +156,35 @@ var Renderable = class {
|
|
|
109
156
|
* ...depending on the current state of the component.
|
|
110
157
|
*/
|
|
111
158
|
runRenderPhase(phase) {
|
|
112
|
-
|
|
159
|
+
this._currentRenderPhase = phase;
|
|
160
|
+
const phaseState = this.renderPhaseStates[phase];
|
|
161
|
+
const isInitialized = phaseState.initialized;
|
|
162
|
+
const isDirty = phaseState.dirty;
|
|
113
163
|
if (!isInitialized && this.shouldBeRemoved) return;
|
|
114
164
|
if (this.shouldBeRemoved && isInitialized) {
|
|
115
165
|
;
|
|
116
166
|
this?.[`remove${phase}`]?.();
|
|
117
|
-
|
|
167
|
+
phaseState.initialized = false;
|
|
168
|
+
phaseState.dirty = false;
|
|
118
169
|
return;
|
|
119
170
|
}
|
|
171
|
+
const prevPhaseIndex = orderedRenderPhases.indexOf(phase) - 1;
|
|
172
|
+
if (prevPhaseIndex >= 0) {
|
|
173
|
+
const prevPhase = orderedRenderPhases[prevPhaseIndex];
|
|
174
|
+
const hasIncompleteEffects = this._asyncEffects.filter((e) => e.phase === prevPhase).some((e) => !e.complete);
|
|
175
|
+
if (hasIncompleteEffects) return;
|
|
176
|
+
}
|
|
120
177
|
if (isInitialized) {
|
|
121
|
-
|
|
122
|
-
|
|
178
|
+
if (isDirty) {
|
|
179
|
+
;
|
|
180
|
+
this?.[`update${phase}`]?.();
|
|
181
|
+
phaseState.dirty = false;
|
|
182
|
+
}
|
|
123
183
|
return;
|
|
124
184
|
}
|
|
125
|
-
;
|
|
185
|
+
phaseState.dirty = false;
|
|
126
186
|
this?.[`doInitial${phase}`]?.();
|
|
127
|
-
|
|
187
|
+
phaseState.initialized = true;
|
|
128
188
|
}
|
|
129
189
|
runRenderPhaseForChildren(phase) {
|
|
130
190
|
for (const child of this.children) {
|
|
@@ -4396,6 +4456,21 @@ var Circuit = class {
|
|
|
4396
4456
|
firstChild.runRenderCycle();
|
|
4397
4457
|
this._hasRenderedAtleastOnce = true;
|
|
4398
4458
|
}
|
|
4459
|
+
async renderUntilSettled() {
|
|
4460
|
+
this.render();
|
|
4461
|
+
while (this._hasIncompleteAsyncEffects()) {
|
|
4462
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4463
|
+
this.render();
|
|
4464
|
+
}
|
|
4465
|
+
}
|
|
4466
|
+
_hasIncompleteAsyncEffects() {
|
|
4467
|
+
return this.children.some((child) => {
|
|
4468
|
+
if (child._hasIncompleteAsyncEffects()) return true;
|
|
4469
|
+
return child.children.some(
|
|
4470
|
+
(grandchild) => grandchild._hasIncompleteAsyncEffects()
|
|
4471
|
+
);
|
|
4472
|
+
});
|
|
4473
|
+
}
|
|
4399
4474
|
getSoup() {
|
|
4400
4475
|
if (!this._hasRenderedAtleastOnce) this.render();
|
|
4401
4476
|
return this.db.toArray();
|
|
@@ -4432,6 +4507,19 @@ var Circuit = class {
|
|
|
4432
4507
|
selectOne(selector, opts) {
|
|
4433
4508
|
return this.firstChild?.selectOne(selector, opts) ?? null;
|
|
4434
4509
|
}
|
|
4510
|
+
_eventListeners = { asyncEffectComplete: [] };
|
|
4511
|
+
emit(event, ...args) {
|
|
4512
|
+
if (!this._eventListeners[event]) return;
|
|
4513
|
+
for (const listener of this._eventListeners[event]) {
|
|
4514
|
+
listener(...args);
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
on(event, listener) {
|
|
4518
|
+
if (!this._eventListeners[event]) {
|
|
4519
|
+
this._eventListeners[event] = [];
|
|
4520
|
+
}
|
|
4521
|
+
this._eventListeners[event].push(listener);
|
|
4522
|
+
}
|
|
4435
4523
|
};
|
|
4436
4524
|
var Project = Circuit;
|
|
4437
4525
|
|