@nexart/ui-renderer 0.8.2 → 0.8.3
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/README.md +18 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/preview/code-renderer.d.ts.map +1 -1
- package/dist/preview/code-renderer.js +12 -4
- package/dist/preview/preview-engine.d.ts.map +1 -1
- package/dist/preview/preview-engine.js +12 -5
- package/dist/preview/unified-renderer.d.ts.map +1 -1
- package/dist/preview/unified-renderer.js +12 -4
- package/dist/types.d.ts +2 -2
- package/dist/types.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @nexart/ui-renderer
|
|
2
2
|
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
4
4
|
|
|
5
5
|
**Lightweight Preview Runtime for NexArt Protocol**
|
|
6
6
|
|
|
@@ -19,6 +19,22 @@ Version: 0.8.2
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## v0.8.3 — Animation Loop Fix
|
|
23
|
+
|
|
24
|
+
Fixed critical bug where preview only rendered a single frame.
|
|
25
|
+
|
|
26
|
+
- **RAF unconditionally scheduled**: `requestAnimationFrame(loop)` is now called on every tick
|
|
27
|
+
- **Budget gates draw only**: Frame budget controls whether `draw()` runs, not whether the loop continues
|
|
28
|
+
- **Continuous animation**: Loop runs forever until explicitly stopped
|
|
29
|
+
|
|
30
|
+
**Animation Loop Invariant (locked for v0.x):**
|
|
31
|
+
```
|
|
32
|
+
RAF schedules → budget checks → draw executes (or skips) → repeat
|
|
33
|
+
Never: budget check → stop loop
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
22
38
|
## v0.8.2 — Runtime Dimensions Fix
|
|
23
39
|
|
|
24
40
|
Fixed critical bug where preview scaling affected `width`/`height` inside sketches.
|
|
@@ -225,7 +241,7 @@ import { getCapabilities } from '@nexart/ui-renderer';
|
|
|
225
241
|
|
|
226
242
|
const caps = getCapabilities();
|
|
227
243
|
// {
|
|
228
|
-
// version: '0.8.
|
|
244
|
+
// version: '0.8.3',
|
|
229
245
|
// isCanonical: false,
|
|
230
246
|
// isArchival: false,
|
|
231
247
|
// previewBudget: { MAX_FRAMES: 30, MAX_TOTAL_TIME_MS: 500, FRAME_STRIDE: 3 },
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @nexart/ui-renderer
|
|
3
|
-
* Version: 0.8.
|
|
3
|
+
* Version: 0.8.3
|
|
4
4
|
*
|
|
5
5
|
* Lightweight Preview Runtime for NexArt Protocol
|
|
6
6
|
*
|
|
@@ -46,7 +46,7 @@ export { calculateScaledDimensions, applyScaledDimensions, type ScaledDimensions
|
|
|
46
46
|
export type { NexArtSystemInput, NexArtSystem, DeclarativeSystemInput, DeclarativeSystem, CodeSystem, NexArtCodeSystem, UnifiedSystemInput, UnifiedSystem, UnifiedElement, BackgroundElement, PrimitiveElement, SketchElement, BackgroundPreset, PrimitiveName, ColorPalette, MotionSpeed, StrokeWeightAuto, LoopConfig, DeclarativeElement, SystemElement, DotsElement, LinesElement, WavesElement, GridElement, FlowFieldElement, OrbitsElement, BackgroundConfig, MotionConfig, PreviewOptions, ValidationResult, } from './types';
|
|
47
47
|
export { AESTHETIC_DEFAULTS, SDK_VERSION as TYPE_SDK_VERSION } from './types';
|
|
48
48
|
export type { Capabilities, PrimitiveCapability, ParameterSpec, } from './capabilities';
|
|
49
|
-
export declare const SDK_VERSION = "0.8.
|
|
49
|
+
export declare const SDK_VERSION = "0.8.3";
|
|
50
50
|
export declare const PROTOCOL_VERSION = "0.8";
|
|
51
51
|
export declare const IS_CANONICAL = false;
|
|
52
52
|
export declare const IS_ARCHIVAL = false;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @nexart/ui-renderer
|
|
3
|
-
* Version: 0.8.
|
|
3
|
+
* Version: 0.8.3
|
|
4
4
|
*
|
|
5
5
|
* Lightweight Preview Runtime for NexArt Protocol
|
|
6
6
|
*
|
|
@@ -44,7 +44,7 @@ export { PREVIEW_BUDGET, CANVAS_LIMITS, } from './preview/preview-types';
|
|
|
44
44
|
export { createFrameBudget, canRenderFrame, recordFrame, resetBudget, shouldSkipFrame, } from './preview/frame-budget';
|
|
45
45
|
export { calculateScaledDimensions, applyScaledDimensions, } from './preview/canvas-scaler';
|
|
46
46
|
export { AESTHETIC_DEFAULTS, SDK_VERSION as TYPE_SDK_VERSION } from './types';
|
|
47
|
-
export const SDK_VERSION = '0.8.
|
|
47
|
+
export const SDK_VERSION = '0.8.3';
|
|
48
48
|
export const PROTOCOL_VERSION = '0.8';
|
|
49
49
|
export const IS_CANONICAL = false;
|
|
50
50
|
export const IS_ARCHIVAL = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-renderer.d.ts","sourceRoot":"","sources":["../../src/preview/code-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA0BjE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC;CACnB;AAwBD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,cAAmB,GAC3B,YAAY,
|
|
1
|
+
{"version":3,"file":"code-renderer.d.ts","sourceRoot":"","sources":["../../src/preview/code-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA0BjE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC;CACnB;AAwBD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,cAAmB,GAC3B,YAAY,CAkQd"}
|
|
@@ -173,13 +173,22 @@ export function renderCodeModeSystem(system, canvas, options = {}) {
|
|
|
173
173
|
}
|
|
174
174
|
resetBudget(budget);
|
|
175
175
|
isRunning = true;
|
|
176
|
+
// ╔═══════════════════════════════════════════════════════════════════════╗
|
|
177
|
+
// ║ ANIMATION LOOP INVARIANT — DO NOT CHANGE ║
|
|
178
|
+
// ║ ║
|
|
179
|
+
// ║ requestAnimationFrame(loop) MUST be called on EVERY tick. ║
|
|
180
|
+
// ║ Budget gates ONLY whether draw() executes, NOT whether loop runs. ║
|
|
181
|
+
// ║ Never return before scheduling RAF. Never conditionally schedule. ║
|
|
182
|
+
// ╚═══════════════════════════════════════════════════════════════════════╝
|
|
176
183
|
const loop = () => {
|
|
184
|
+
// ALWAYS schedule next frame first — loop never terminates on its own
|
|
185
|
+
animationId = requestAnimationFrame(loop);
|
|
186
|
+
// Early exit checks (after RAF is scheduled)
|
|
177
187
|
if (!isRunning || isDestroyed)
|
|
178
188
|
return;
|
|
189
|
+
// Budget check — skip draw but keep loop alive
|
|
179
190
|
if (!canRenderFrame(budget)) {
|
|
180
|
-
|
|
181
|
-
isRunning = false;
|
|
182
|
-
return;
|
|
191
|
+
return; // Loop continues, just don't draw
|
|
183
192
|
}
|
|
184
193
|
frameCount++;
|
|
185
194
|
if (!shouldSkipFrame(frameCount)) {
|
|
@@ -200,7 +209,6 @@ export function renderCodeModeSystem(system, canvas, options = {}) {
|
|
|
200
209
|
console.warn('[UIRenderer] Draw error:', error);
|
|
201
210
|
}
|
|
202
211
|
}
|
|
203
|
-
animationId = requestAnimationFrame(loop);
|
|
204
212
|
};
|
|
205
213
|
animationId = requestAnimationFrame(loop);
|
|
206
214
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview-engine.d.ts","sourceRoot":"","sources":["../../src/preview/preview-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAErB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"preview-engine.d.ts","sourceRoot":"","sources":["../../src/preview/preview-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAErB,MAAM,iBAAiB,CAAC;AAqNzB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,eAAe,CAEhF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,mBAAmB,CAKpF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC"}
|
|
@@ -132,15 +132,23 @@ class PreviewEngine {
|
|
|
132
132
|
}
|
|
133
133
|
this.scheduleNextFrame();
|
|
134
134
|
}
|
|
135
|
+
// ╔═══════════════════════════════════════════════════════════════════════╗
|
|
136
|
+
// ║ ANIMATION LOOP INVARIANT — DO NOT CHANGE ║
|
|
137
|
+
// ║ ║
|
|
138
|
+
// ║ requestAnimationFrame MUST be called on EVERY tick. ║
|
|
139
|
+
// ║ Budget gates ONLY whether draw() executes, NOT whether loop runs. ║
|
|
140
|
+
// ║ Never return before scheduling RAF. Never conditionally schedule. ║
|
|
141
|
+
// ╚═══════════════════════════════════════════════════════════════════════╝
|
|
135
142
|
scheduleNextFrame() {
|
|
136
|
-
|
|
137
|
-
return;
|
|
143
|
+
// ALWAYS schedule next frame first — loop never terminates on its own
|
|
138
144
|
this.animationFrameId = requestAnimationFrame(() => {
|
|
145
|
+
this.scheduleNextFrame();
|
|
146
|
+
// Early exit checks (after RAF is scheduled)
|
|
139
147
|
if (!this.running)
|
|
140
148
|
return;
|
|
149
|
+
// Budget check — skip draw but keep loop alive
|
|
141
150
|
if (!canRenderFrame(this.budget)) {
|
|
142
|
-
|
|
143
|
-
return;
|
|
151
|
+
return; // Loop continues, just don't draw
|
|
144
152
|
}
|
|
145
153
|
this.internalFrameCount++;
|
|
146
154
|
if (!shouldSkipFrame(this.internalFrameCount)) {
|
|
@@ -161,7 +169,6 @@ class PreviewEngine {
|
|
|
161
169
|
console.warn('[PreviewEngine] Draw error:', error);
|
|
162
170
|
}
|
|
163
171
|
}
|
|
164
|
-
this.scheduleNextFrame();
|
|
165
172
|
});
|
|
166
173
|
}
|
|
167
174
|
stopLoop() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-renderer.d.ts","sourceRoot":"","sources":["../../src/preview/unified-renderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAkB,cAAc,EAAoE,MAAM,UAAU,CAAC;AAmBhJ,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC;CACnB;AA6ED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,cAAmB,GAC3B,eAAe,
|
|
1
|
+
{"version":3,"file":"unified-renderer.d.ts","sourceRoot":"","sources":["../../src/preview/unified-renderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAkB,cAAc,EAAoE,MAAM,UAAU,CAAC;AAmBhJ,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC;IACnB,UAAU,EAAE,KAAK,CAAC;CACnB;AA6ED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,cAAmB,GAC3B,eAAe,CA6QjB"}
|
|
@@ -237,13 +237,22 @@ export function renderUnifiedSystem(system, canvas, options = {}) {
|
|
|
237
237
|
runSetup(p);
|
|
238
238
|
resetBudget(budget);
|
|
239
239
|
isRunning = true;
|
|
240
|
+
// ╔═══════════════════════════════════════════════════════════════════════╗
|
|
241
|
+
// ║ ANIMATION LOOP INVARIANT — DO NOT CHANGE ║
|
|
242
|
+
// ║ ║
|
|
243
|
+
// ║ requestAnimationFrame(loop) MUST be called on EVERY tick. ║
|
|
244
|
+
// ║ Budget gates ONLY whether draw() executes, NOT whether loop runs. ║
|
|
245
|
+
// ║ Never return before scheduling RAF. Never conditionally schedule. ║
|
|
246
|
+
// ╚═══════════════════════════════════════════════════════════════════════╝
|
|
240
247
|
const loop = () => {
|
|
248
|
+
// ALWAYS schedule next frame first — loop never terminates on its own
|
|
249
|
+
animationId = requestAnimationFrame(loop);
|
|
250
|
+
// Early exit checks (after RAF is scheduled)
|
|
241
251
|
if (!isRunning || isDestroyed)
|
|
242
252
|
return;
|
|
253
|
+
// Budget check — skip draw but keep loop alive
|
|
243
254
|
if (!canRenderFrame(budget)) {
|
|
244
|
-
|
|
245
|
-
isRunning = false;
|
|
246
|
-
return;
|
|
255
|
+
return; // Loop continues, just don't draw
|
|
247
256
|
}
|
|
248
257
|
frameCount++;
|
|
249
258
|
if (!shouldSkipFrame(frameCount)) {
|
|
@@ -259,7 +268,6 @@ export function renderUnifiedSystem(system, canvas, options = {}) {
|
|
|
259
268
|
console.warn('[UIRenderer] Draw error:', error);
|
|
260
269
|
}
|
|
261
270
|
}
|
|
262
|
-
animationId = requestAnimationFrame(loop);
|
|
263
271
|
};
|
|
264
272
|
animationId = requestAnimationFrame(loop);
|
|
265
273
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @nexart/ui-renderer v0.8.
|
|
2
|
+
* @nexart/ui-renderer v0.8.3 - Type Definitions
|
|
3
3
|
*
|
|
4
4
|
* Lightweight Preview Runtime for NexArt Protocol.
|
|
5
5
|
* This SDK is non-canonical and for preview only.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - Max total time: 500ms
|
|
10
10
|
* - Max canvas dimension: 900px
|
|
11
11
|
*/
|
|
12
|
-
export declare const SDK_VERSION = "0.8.
|
|
12
|
+
export declare const SDK_VERSION = "0.8.3";
|
|
13
13
|
export declare const AESTHETIC_DEFAULTS: {
|
|
14
14
|
readonly background: {
|
|
15
15
|
readonly r: 246;
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @nexart/ui-renderer v0.8.
|
|
2
|
+
* @nexart/ui-renderer v0.8.3 - Type Definitions
|
|
3
3
|
*
|
|
4
4
|
* Lightweight Preview Runtime for NexArt Protocol.
|
|
5
5
|
* This SDK is non-canonical and for preview only.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - Max total time: 500ms
|
|
10
10
|
* - Max canvas dimension: 900px
|
|
11
11
|
*/
|
|
12
|
-
export const SDK_VERSION = '0.8.
|
|
12
|
+
export const SDK_VERSION = '0.8.3';
|
|
13
13
|
export const AESTHETIC_DEFAULTS = {
|
|
14
14
|
background: { r: 246, g: 245, b: 242 },
|
|
15
15
|
foreground: { r: 45, g: 45, b: 45 },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexart/ui-renderer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Lightweight Preview Runtime for NexArt Protocol. Non-canonical, performance-optimized with budget limits (max 30 frames, 500ms, 900px canvas).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|