@nexart/ui-renderer 0.8.8 → 0.9.1
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/CHANGELOG.md +490 -0
- package/README.md +251 -285
- package/dist/capabilities.d.ts +1 -1
- package/dist/capabilities.js +2 -2
- package/dist/index.d.ts +36 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -21
- package/dist/preview/preview-engine.d.ts +13 -10
- package/dist/preview/preview-engine.d.ts.map +1 -1
- package/dist/preview/preview-engine.js +178 -39
- package/dist/preview/preview-types.d.ts +81 -2
- package/dist/preview/preview-types.d.ts.map +1 -1
- package/dist/preview/preview-types.js +13 -0
- package/examples/basic-preview.ts +92 -0
- package/examples/budget-demo.ts +161 -0
- package/package.json +22 -11
package/README.md
CHANGED
|
@@ -1,403 +1,371 @@
|
|
|
1
1
|
# @nexart/ui-renderer
|
|
2
2
|
|
|
3
|
-
Version: 0.
|
|
3
|
+
**Version: 0.9.1**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A browser-first bounded generative renderer for safe, fast, interactive visuals.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
>
|
|
11
|
-
> It provides fast, lightweight previews for development and prototyping.
|
|
12
|
-
>
|
|
13
|
-
> It is:
|
|
14
|
-
> - **NOT canonical** — Does not produce archival-quality output
|
|
15
|
-
> - **NOT archival** — Not for minting, export, or permanent storage
|
|
16
|
-
> - **NOT protocol-enforcing** — No validation errors, no pattern checking
|
|
17
|
-
>
|
|
18
|
-
> For canonical output, minting, or validation: use `@nexart/codemode-sdk`
|
|
9
|
+
## What This SDK Does
|
|
19
10
|
|
|
20
|
-
|
|
11
|
+
This SDK provides a **bounded execution environment** for running generative code safely in the browser. It renders p5-like sketches with built-in safety limits:
|
|
21
12
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- **Animations work**: Sketches see correct values on every frame
|
|
29
|
-
|
|
30
|
-
**Animation Semantics:**
|
|
31
|
-
In loop mode, all time variables update every frame:
|
|
32
|
-
- `frameCount`: Increments each frame
|
|
33
|
-
- `t`: Normalized time `(frameCount % totalFrames) / totalFrames` (range [0,1))
|
|
34
|
-
- `time`: Alias for `t`
|
|
35
|
-
- `tGlobal`: Alias for `t`
|
|
36
|
-
- `totalFrames`: Total frames in the loop (default 120)
|
|
37
|
-
|
|
38
|
-
**Test Sketch:**
|
|
39
|
-
```javascript
|
|
40
|
-
function draw() {
|
|
41
|
-
background(0);
|
|
42
|
-
fill(255);
|
|
43
|
-
circle(
|
|
44
|
-
width / 2 + sin(frameCount * 0.1) * 300,
|
|
45
|
-
height / 2,
|
|
46
|
-
120
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
Expected: Circle moves horizontally, motion is continuous.
|
|
13
|
+
- **Resolution cap** — Max 900px dimension for performance
|
|
14
|
+
- **Frame/time budgets** — Prevents runaway loops
|
|
15
|
+
- **Observable state** — Know exactly what the runtime is doing
|
|
16
|
+
- **Safe degradation** — Controlled behavior when limits hit
|
|
17
|
+
|
|
18
|
+
**Output is authoritative within bounded constraints.** What you see is what the sketch produces at preview resolution with preview budgets.
|
|
51
19
|
|
|
52
20
|
---
|
|
53
21
|
|
|
54
|
-
##
|
|
22
|
+
## Standalone Use Cases
|
|
55
23
|
|
|
56
|
-
|
|
24
|
+
This SDK is designed for:
|
|
57
25
|
|
|
58
|
-
- **
|
|
59
|
-
- **
|
|
60
|
-
- **
|
|
26
|
+
- **Generative art backgrounds** — Dynamic visuals for web pages
|
|
27
|
+
- **Interactive creative coding editors** — Live preview while users code
|
|
28
|
+
- **Dashboard visuals** — Procedural data visualizations
|
|
29
|
+
- **Mini-app visuals** — Embedded generative elements
|
|
30
|
+
- **Educational demos** — Safe sandbox for teaching creative coding
|
|
31
|
+
- **UI-embedded procedural patterns** — Decorative generative elements
|
|
61
32
|
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
RAF schedules → budget checks → draw executes (or skips) → repeat
|
|
65
|
-
Never: budget check → stop loop
|
|
66
|
-
```
|
|
33
|
+
For these use cases, ui-renderer is the complete solution. No other SDK required.
|
|
67
34
|
|
|
68
35
|
---
|
|
69
36
|
|
|
70
|
-
##
|
|
37
|
+
## When to Escalate to Canonical Rendering
|
|
71
38
|
|
|
72
|
-
|
|
39
|
+
Use `@nexart/codemode-sdk` when you need:
|
|
73
40
|
|
|
74
|
-
- **
|
|
75
|
-
- **
|
|
76
|
-
- **
|
|
41
|
+
- **Minting / export / archival** — Permanent, verifiable output
|
|
42
|
+
- **Reproducibility guarantees** — Exact same output every time, anywhere
|
|
43
|
+
- **Full resolution parity** — 1950×2400 or higher without scaling
|
|
44
|
+
- **Verification workflows** — Cryptographic digest matching
|
|
77
45
|
|
|
78
|
-
**
|
|
46
|
+
**ui-renderer → codemode-sdk is an escalation, not a requirement.**
|
|
79
47
|
|
|
80
|
-
|
|
48
|
+
Most interactive, preview, and display use cases are complete with ui-renderer alone.
|
|
81
49
|
|
|
82
|
-
|
|
50
|
+
---
|
|
83
51
|
|
|
84
|
-
|
|
52
|
+
## Authority Model
|
|
85
53
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
54
|
+
```
|
|
55
|
+
┌─────────────────────────────────────────────────────────┐
|
|
56
|
+
│ Your Application │
|
|
57
|
+
│ (React, Canvas, Three.js, editor, dashboard) │
|
|
58
|
+
└────────────────────────┬────────────────────────────────┘
|
|
59
|
+
│
|
|
60
|
+
▼
|
|
61
|
+
┌─────────────────────────────────────────────────────────┐
|
|
62
|
+
│ @nexart/ui-renderer │
|
|
63
|
+
│ Bounded browser runtime │
|
|
64
|
+
│ - Resolution scaling (max 900px) │
|
|
65
|
+
│ - Frame/time budgets │
|
|
66
|
+
│ - Observable stats │
|
|
67
|
+
│ - Controlled degradation │
|
|
68
|
+
└────────────────────────┬────────────────────────────────┘
|
|
69
|
+
│
|
|
70
|
+
▼
|
|
71
|
+
┌─────────────────────────────────────────────────────────┐
|
|
72
|
+
│ Output │
|
|
73
|
+
│ - Pixels on canvas │
|
|
74
|
+
│ - Runtime stats │
|
|
75
|
+
│ - Budget status │
|
|
76
|
+
│ │
|
|
77
|
+
│ ↳ Optional: toCanonicalRequest() for codemode-sdk │
|
|
78
|
+
└─────────────────────────────────────────────────────────┘
|
|
79
|
+
```
|
|
89
80
|
|
|
90
81
|
---
|
|
91
82
|
|
|
92
|
-
##
|
|
83
|
+
## For AI Coding Agents (Replit / Lovable / Claude Code)
|
|
93
84
|
|
|
94
|
-
|
|
85
|
+
### 20-Second Quickstart
|
|
95
86
|
|
|
96
|
-
|
|
87
|
+
```typescript
|
|
88
|
+
import { createPreviewRuntime } from '@nexart/ui-renderer';
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
90
|
+
const runtime = createPreviewRuntime({
|
|
91
|
+
canvas: document.getElementById('canvas'),
|
|
92
|
+
source: `
|
|
93
|
+
function draw() {
|
|
94
|
+
background(30);
|
|
95
|
+
circle(width/2 + sin(t * TWO_PI) * 200, height/2, 100);
|
|
96
|
+
}
|
|
97
|
+
`,
|
|
98
|
+
mode: 'loop',
|
|
99
|
+
width: 1950,
|
|
100
|
+
height: 2400,
|
|
101
|
+
seed: 12345,
|
|
102
|
+
vars: [50, 75, 25],
|
|
103
|
+
totalFrames: 120,
|
|
104
|
+
onBudgetExceeded: (info) => console.warn('Budget exceeded:', info),
|
|
105
|
+
});
|
|
103
106
|
|
|
104
|
-
|
|
107
|
+
runtime.startLoop();
|
|
108
|
+
```
|
|
105
109
|
|
|
106
|
-
|
|
110
|
+
### Detecting Runtime Mode
|
|
107
111
|
|
|
108
112
|
```typescript
|
|
109
|
-
|
|
110
|
-
MAX_FRAMES: 30, // Maximum frames before auto-stop
|
|
111
|
-
MAX_TOTAL_TIME_MS: 500, // Maximum execution time
|
|
112
|
-
FRAME_STRIDE: 3, // Render every 3rd frame
|
|
113
|
-
};
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
If limits exceeded: rendering stops silently (no throw).
|
|
113
|
+
const stats = runtime.getPreviewStats();
|
|
117
114
|
|
|
118
|
-
|
|
115
|
+
console.log('Mode:', stats.mode); // 'preview'
|
|
116
|
+
console.log('Scale:', stats.scale); // 0.46
|
|
117
|
+
console.log('Frames:', stats.frames); // current frame count
|
|
118
|
+
console.log('Budget OK:', !stats.budgetExceeded);
|
|
119
|
+
```
|
|
119
120
|
|
|
120
|
-
|
|
121
|
+
### Handling Budget Limits
|
|
121
122
|
|
|
122
123
|
```typescript
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
const stats = runtime.getPreviewStats();
|
|
125
|
+
|
|
126
|
+
if (stats.budgetExceeded) {
|
|
127
|
+
console.log('Reason:', stats.budgetExceeded.reason);
|
|
128
|
+
// Options:
|
|
129
|
+
// 1. Simplify sketch (fewer iterations)
|
|
130
|
+
// 2. Increase maxFrames or maxTimeMs
|
|
131
|
+
// 3. Use budgetBehavior: 'degrade' to continue with frame skipping
|
|
132
|
+
}
|
|
127
133
|
```
|
|
128
134
|
|
|
129
|
-
|
|
135
|
+
---
|
|
130
136
|
|
|
131
|
-
|
|
137
|
+
## Trust & Safety
|
|
132
138
|
|
|
133
|
-
|
|
139
|
+
### Budgets Prevent Runaway Code
|
|
134
140
|
|
|
135
141
|
```typescript
|
|
136
|
-
runtime
|
|
142
|
+
const runtime = createPreviewRuntime({
|
|
143
|
+
canvas,
|
|
144
|
+
source: sketchCode,
|
|
145
|
+
mode: 'loop',
|
|
146
|
+
width: 1950,
|
|
147
|
+
height: 2400,
|
|
148
|
+
|
|
149
|
+
maxFrames: 1800, // Max frames before stop (default)
|
|
150
|
+
maxTimeMs: 300000, // Max 5 minutes (default)
|
|
151
|
+
budgetBehavior: 'stop', // 'stop' or 'degrade'
|
|
152
|
+
showOverlay: true, // Visual indicator when stopped
|
|
153
|
+
|
|
154
|
+
onBudgetExceeded: (info) => {
|
|
155
|
+
// No silent failures — you always know
|
|
156
|
+
console.log('Stopped:', info.reason);
|
|
157
|
+
},
|
|
158
|
+
});
|
|
137
159
|
```
|
|
138
160
|
|
|
139
|
-
|
|
161
|
+
### Observable State
|
|
140
162
|
|
|
141
|
-
|
|
163
|
+
```typescript
|
|
164
|
+
const stats = runtime.getPreviewStats();
|
|
165
|
+
// {
|
|
166
|
+
// mode: 'preview',
|
|
167
|
+
// scale: 0.46,
|
|
168
|
+
// semanticWidth: 1950,
|
|
169
|
+
// semanticHeight: 2400,
|
|
170
|
+
// bufferWidth: 897,
|
|
171
|
+
// bufferHeight: 900,
|
|
172
|
+
// frames: 150,
|
|
173
|
+
// stride: 1,
|
|
174
|
+
// totalTimeMs: 18750,
|
|
175
|
+
// budgetExceeded?: { reason: 'frame_limit' | 'time_limit' }
|
|
176
|
+
// }
|
|
177
|
+
```
|
|
142
178
|
|
|
143
|
-
|
|
179
|
+
### What Can Differ vs Canonical
|
|
144
180
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
181
|
+
| Aspect | ui-renderer | codemode-sdk |
|
|
182
|
+
|--------|-------------|--------------|
|
|
183
|
+
| Resolution | Scaled to max 900px | Full resolution |
|
|
184
|
+
| Frame budget | 1800 frames / 5 min | Unlimited |
|
|
185
|
+
| Fine details | May be lost at scale | Pixel-perfect |
|
|
186
|
+
| Semantics | Consistent | Authoritative |
|
|
148
187
|
|
|
149
|
-
|
|
150
|
-
```html
|
|
151
|
-
<script type="module">
|
|
152
|
-
import { createSystem, previewSystem } from 'https://unpkg.com/@nexart/ui-renderer/dist/index.js';
|
|
153
|
-
</script>
|
|
154
|
-
```
|
|
188
|
+
**Scaling may change fine details. Budgets may skip work. Core semantics are preserved.**
|
|
155
189
|
|
|
156
190
|
---
|
|
157
191
|
|
|
158
|
-
##
|
|
192
|
+
## Bounded Execution vs Canonical
|
|
193
|
+
|
|
194
|
+
| Aspect | Preview (this SDK) | Canonical (@nexart/codemode-sdk) |
|
|
195
|
+
|--------|-------------------|----------------------------------|
|
|
196
|
+
| **Purpose** | Fast browser visuals | Authoritative rendering |
|
|
197
|
+
| **Resolution** | Max 900px | Full resolution |
|
|
198
|
+
| **Budget** | 1800 frames / 5 min | Unlimited |
|
|
199
|
+
| **Determinism** | Consistent | Guaranteed |
|
|
200
|
+
| **Use for** | Editors, dashboards, display | Minting, export, archival |
|
|
201
|
+
|
|
202
|
+
---
|
|
159
203
|
|
|
160
|
-
|
|
204
|
+
## Optional: Canonical Handoff
|
|
205
|
+
|
|
206
|
+
When you need to escalate to canonical rendering:
|
|
161
207
|
|
|
162
208
|
```typescript
|
|
163
|
-
import {
|
|
209
|
+
import { toCanonicalRequest } from '@nexart/ui-renderer';
|
|
210
|
+
|
|
211
|
+
const config = {
|
|
212
|
+
canvas,
|
|
213
|
+
source: sketchCode,
|
|
214
|
+
mode: 'loop',
|
|
215
|
+
width: 1950,
|
|
216
|
+
height: 2400,
|
|
217
|
+
seed: 12345
|
|
218
|
+
};
|
|
164
219
|
|
|
165
|
-
const
|
|
166
|
-
type: 'code',
|
|
167
|
-
mode: 'loop',
|
|
168
|
-
width: 1950,
|
|
169
|
-
height: 2400,
|
|
170
|
-
totalFrames: 120,
|
|
171
|
-
seed: 12345,
|
|
172
|
-
vars: [50, 75, 25], // VAR[0..9] — values 0-100, padded with zeros
|
|
173
|
-
source: `
|
|
174
|
-
function setup() {
|
|
175
|
-
noFill();
|
|
176
|
-
stroke(0);
|
|
177
|
-
}
|
|
178
|
-
function draw() {
|
|
179
|
-
background(246, 245, 242);
|
|
180
|
-
var count = int(map(VAR[0], 0, 100, 5, 30));
|
|
181
|
-
for (var i = 0; i < count; i++) {
|
|
182
|
-
var x = width / 2 + cos(t * TWO_PI + i * 0.5) * map(VAR[1], 0, 100, 50, 400);
|
|
183
|
-
var y = height / 2 + sin(t * TWO_PI + i * 0.3) * 200;
|
|
184
|
-
ellipse(x, y, 50);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
`
|
|
188
|
-
});
|
|
220
|
+
const req = toCanonicalRequest(config);
|
|
189
221
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
renderer.start();
|
|
222
|
+
// Pass to backend with @nexart/codemode-sdk:
|
|
223
|
+
// await fetch('/api/render', { body: JSON.stringify(req) });
|
|
193
224
|
```
|
|
194
225
|
|
|
195
|
-
|
|
226
|
+
---
|
|
196
227
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
height: 2400,
|
|
203
|
-
seed: 12345,
|
|
204
|
-
vars: [50, 50, 50],
|
|
205
|
-
source: `
|
|
206
|
-
function setup() {
|
|
207
|
-
background(246, 245, 242);
|
|
208
|
-
fill(0);
|
|
209
|
-
var count = int(map(VAR[0], 0, 100, 10, 200));
|
|
210
|
-
for (var i = 0; i < count; i++) {
|
|
211
|
-
ellipse(random(width), random(height), random(10, 50));
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
`
|
|
215
|
-
});
|
|
228
|
+
## Install
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm install @nexart/ui-renderer
|
|
232
|
+
```
|
|
216
233
|
|
|
217
|
-
|
|
234
|
+
Or use directly:
|
|
235
|
+
```html
|
|
236
|
+
<script type="module">
|
|
237
|
+
import { createPreviewRuntime } from 'https://unpkg.com/@nexart/ui-renderer/dist/index.js';
|
|
238
|
+
</script>
|
|
218
239
|
```
|
|
219
240
|
|
|
220
241
|
---
|
|
221
242
|
|
|
222
243
|
## API Reference
|
|
223
244
|
|
|
224
|
-
### `
|
|
245
|
+
### `createPreviewRuntime(config)` — Recommended
|
|
225
246
|
|
|
226
|
-
Create a
|
|
247
|
+
Create a bounded preview renderer.
|
|
227
248
|
|
|
228
249
|
```typescript
|
|
229
|
-
const
|
|
230
|
-
|
|
250
|
+
const runtime = createPreviewRuntime({
|
|
251
|
+
canvas: HTMLCanvasElement,
|
|
252
|
+
source: string, // p5-like sketch code
|
|
231
253
|
mode: 'static' | 'loop',
|
|
232
254
|
width: number,
|
|
233
255
|
height: number,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
totalFrames?: number,
|
|
237
|
-
|
|
256
|
+
seed?: number,
|
|
257
|
+
vars?: number[], // VAR[0..9] (0-100 range)
|
|
258
|
+
totalFrames?: number, // For loop mode (default: 120)
|
|
259
|
+
|
|
260
|
+
// Budget options
|
|
261
|
+
onBudgetExceeded?: (info: BudgetExceededInfo) => void,
|
|
262
|
+
budgetBehavior?: 'stop' | 'degrade',
|
|
263
|
+
showOverlay?: boolean,
|
|
264
|
+
maxFrames?: number,
|
|
265
|
+
maxTimeMs?: number,
|
|
238
266
|
});
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### `previewSystem(system, canvas, options?)`
|
|
242
|
-
|
|
243
|
-
Render a preview to canvas.
|
|
244
267
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
renderer.start(); // Start loop
|
|
252
|
-
renderer.stop(); // Stop loop
|
|
253
|
-
renderer.destroy(); // Cleanup
|
|
268
|
+
runtime.startLoop(); // Start animation
|
|
269
|
+
runtime.stopLoop(); // Stop animation
|
|
270
|
+
runtime.renderStatic(); // Render single frame
|
|
271
|
+
runtime.getPreviewStats(); // Get current stats
|
|
272
|
+
runtime.previewScale; // Canvas scale factor
|
|
273
|
+
runtime.destroy(); // Clean up
|
|
254
274
|
```
|
|
255
275
|
|
|
256
|
-
### `
|
|
276
|
+
### `toCanonicalRequest(config)`
|
|
257
277
|
|
|
258
|
-
|
|
278
|
+
Generate a handoff object for `@nexart/codemode-sdk`:
|
|
259
279
|
|
|
260
280
|
```typescript
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
console.log(result.errors); // Structural issues only
|
|
264
|
-
}
|
|
281
|
+
const req = toCanonicalRequest(config);
|
|
282
|
+
// { seed, vars, code, settings, renderer: 'preview', uiRendererVersion }
|
|
265
283
|
```
|
|
266
284
|
|
|
267
285
|
### `getCapabilities()`
|
|
268
286
|
|
|
269
|
-
Discover SDK capabilities
|
|
287
|
+
Discover SDK capabilities:
|
|
270
288
|
|
|
271
289
|
```typescript
|
|
272
|
-
import { getCapabilities } from '@nexart/ui-renderer';
|
|
273
|
-
|
|
274
290
|
const caps = getCapabilities();
|
|
275
|
-
// {
|
|
276
|
-
// version: '0.8.7',
|
|
277
|
-
// isCanonical: false,
|
|
278
|
-
// isArchival: false,
|
|
279
|
-
// previewBudget: { MAX_FRAMES: 30, MAX_TOTAL_TIME_MS: 500, FRAME_STRIDE: 3 },
|
|
280
|
-
// canvasLimits: { MAX_DIMENSION: 900 },
|
|
281
|
-
// ...
|
|
282
|
-
// }
|
|
291
|
+
// { version, isCanonical, previewBudget, canvasLimits, ... }
|
|
283
292
|
```
|
|
284
293
|
|
|
285
294
|
---
|
|
286
295
|
|
|
287
|
-
##
|
|
296
|
+
## Troubleshooting
|
|
288
297
|
|
|
289
|
-
|
|
298
|
+
### "My sketch stops animating"
|
|
290
299
|
|
|
291
|
-
|
|
292
|
-
|--------|-------------|
|
|
293
|
-
| `int(n)` | Convert to integer (Math.floor) |
|
|
294
|
-
| `fract(n)` | Fractional part of number |
|
|
295
|
-
| `sign(n)` | Sign of number |
|
|
296
|
-
| `vec(x, y)` | Create 2D vector |
|
|
297
|
-
| `polygon(x, y, r, n)` | Draw n-sided polygon |
|
|
298
|
-
| `star(x, y, r1, r2, n)` | Draw n-pointed star |
|
|
299
|
-
| `fbm(x, y, z, octaves)` | Fractal Brownian motion |
|
|
300
|
-
| `easeIn(t)`, `easeOut(t)`, etc. | Easing functions |
|
|
301
|
-
|
|
302
|
-
### Control Functions
|
|
303
|
-
|
|
304
|
-
| Function | Preview Behavior |
|
|
305
|
-
|----------|------------------|
|
|
306
|
-
| `noLoop()` | Stops preview loop (soft control) |
|
|
307
|
-
| `loop()` | No-op in preview |
|
|
308
|
-
|
|
309
|
-
---
|
|
310
|
-
|
|
311
|
-
## Supported Element Types
|
|
312
|
-
|
|
313
|
-
### `background`
|
|
314
|
-
|
|
315
|
-
Opinionated presets with guardrails.
|
|
300
|
+
Check `getPreviewStats().budgetExceeded`:
|
|
316
301
|
|
|
317
302
|
```typescript
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
palette: 'warm' // warm, cool, neutral, vibrant
|
|
303
|
+
const stats = runtime.getPreviewStats();
|
|
304
|
+
if (stats.budgetExceeded) {
|
|
305
|
+
console.log('Stopped because:', stats.budgetExceeded.reason);
|
|
322
306
|
}
|
|
323
307
|
```
|
|
324
308
|
|
|
325
|
-
|
|
309
|
+
**Solutions:**
|
|
310
|
+
1. Reduce sketch complexity
|
|
311
|
+
2. Increase budget: `maxFrames: 3600` or `maxTimeMs: 600000`
|
|
312
|
+
3. Use `budgetBehavior: 'degrade'` to continue with frame skipping
|
|
326
313
|
|
|
327
|
-
|
|
314
|
+
### "Canvas is too small"
|
|
328
315
|
|
|
329
|
-
|
|
330
|
-
- `basic` — dots, lines, waves, stripes, circles, grid
|
|
331
|
-
- `geometric` — polygons, diamonds, hexgrid, stars, concentricSquares
|
|
332
|
-
- `radial` — spirals, rays, orbits, rings, arcs, radialLines, petals
|
|
333
|
-
- `flow` — flow, particles, bubbles
|
|
334
|
-
- `patterns` — crosshatch, chevrons, zigzag, weave, moire
|
|
335
|
-
- `organic` — curves, noise, mesh, branches
|
|
316
|
+
Preview scales to max 900px for performance:
|
|
336
317
|
|
|
337
318
|
```typescript
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
count: 12,
|
|
342
|
-
color: '#ffffff',
|
|
343
|
-
motion: 'medium',
|
|
344
|
-
strokeWeight: 'thin',
|
|
345
|
-
opacity: 0.8
|
|
346
|
-
}
|
|
319
|
+
const stats = runtime.getPreviewStats();
|
|
320
|
+
console.log('Buffer:', stats.bufferWidth, 'x', stats.bufferHeight);
|
|
321
|
+
console.log('Semantic:', stats.semanticWidth, 'x', stats.semanticHeight);
|
|
347
322
|
```
|
|
348
323
|
|
|
349
|
-
|
|
324
|
+
Your sketch code sees original `width`/`height`. Canvas buffer is scaled.
|
|
350
325
|
|
|
351
|
-
|
|
326
|
+
### "Animation looks choppy"
|
|
352
327
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
code: `
|
|
357
|
-
function setup() { background(0); }
|
|
358
|
-
function draw() { ellipse(width/2, height/2, 100); }
|
|
359
|
-
`,
|
|
360
|
-
normalize: true
|
|
361
|
-
}
|
|
362
|
-
```
|
|
328
|
+
1. Check if in degraded mode (skipping frames)
|
|
329
|
+
2. Reduce sketch complexity
|
|
330
|
+
3. Check browser performance
|
|
363
331
|
|
|
364
332
|
---
|
|
365
333
|
|
|
366
|
-
##
|
|
367
|
-
|
|
368
|
-
VAR[0..9] is an array of 10 protocol variables.
|
|
334
|
+
## Available Helpers
|
|
369
335
|
|
|
370
|
-
|
|
371
|
-
- Input: 0-10 elements accepted (extras ignored with warning)
|
|
372
|
-
- Values: Clamped to 0-100 (not rejected)
|
|
373
|
-
- Invalid types: Replaced with 0 (not rejected)
|
|
374
|
-
- Runtime: Always 10 elements (padded with zeros)
|
|
375
|
-
- Access: Read-only
|
|
336
|
+
All standard p5-like functions included:
|
|
376
337
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
338
|
+
| Helper | Description |
|
|
339
|
+
|--------|-------------|
|
|
340
|
+
| `int(n)` | Convert to integer |
|
|
341
|
+
| `fract(n)` | Fractional part |
|
|
342
|
+
| `vec(x, y)` | Create 2D vector |
|
|
343
|
+
| `polygon(x, y, r, n)` | Draw n-sided polygon |
|
|
344
|
+
| `star(x, y, r1, r2, n)` | Draw n-pointed star |
|
|
345
|
+
| `fbm(x, y, z, octaves)` | Fractal Brownian motion |
|
|
346
|
+
| `easeIn(t)`, `easeOut(t)` | Easing functions |
|
|
380
347
|
|
|
381
|
-
|
|
382
|
-
vars: ['bad', 50, 50] // VAR[0] becomes 0
|
|
348
|
+
---
|
|
383
349
|
|
|
384
|
-
|
|
385
|
-
vars: [1,2,3,4,5,6,7,8,9,10,11,12] // Uses first 10
|
|
386
|
-
```
|
|
350
|
+
## Legacy API
|
|
387
351
|
|
|
388
|
-
|
|
352
|
+
Still supported for backward compatibility:
|
|
389
353
|
|
|
390
|
-
|
|
354
|
+
```typescript
|
|
355
|
+
import { createSystem, previewSystem } from '@nexart/ui-renderer';
|
|
391
356
|
|
|
392
|
-
|
|
357
|
+
const system = createSystem({
|
|
358
|
+
type: 'code',
|
|
359
|
+
mode: 'loop',
|
|
360
|
+
width: 1950,
|
|
361
|
+
height: 2400,
|
|
362
|
+
source: sketchCode,
|
|
363
|
+
seed: 12345,
|
|
364
|
+
});
|
|
393
365
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
| Canonical output | Use @nexart/codemode-sdk for minting |
|
|
398
|
-
| Determinism guarantee | Preview may vary slightly |
|
|
399
|
-
| Full frame count | Limited to 30 frames max |
|
|
400
|
-
| Full resolution | Limited to 900px max dimension |
|
|
366
|
+
const renderer = previewSystem(system, canvas);
|
|
367
|
+
renderer.start();
|
|
368
|
+
```
|
|
401
369
|
|
|
402
370
|
---
|
|
403
371
|
|
|
@@ -412,6 +380,4 @@ For strict validation, use `@nexart/codemode-sdk`.
|
|
|
412
380
|
|
|
413
381
|
## License
|
|
414
382
|
|
|
415
|
-
MIT License
|
|
416
|
-
|
|
417
|
-
Copyright (c) 2024-2026 NexArt
|
|
383
|
+
MIT License — Copyright (c) 2024-2026 NexArt
|
package/dist/capabilities.d.ts
CHANGED