opencode-skills-collection 4.0.34 → 4.0.36

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 (59) hide show
  1. package/bundled-skills/.antigravity-install-manifest.json +7 -1
  2. package/bundled-skills/agent-evaluation-reporting/SKILL.md +136 -0
  3. package/bundled-skills/anti-ui-slop/SKILL.md +115 -0
  4. package/bundled-skills/cross-platform-contract-propagation-audit/SKILL.md +159 -0
  5. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  6. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  7. package/bundled-skills/docs/maintainers/repo-growth-seo.md +1 -1
  8. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  9. package/bundled-skills/docs/users/aas-core.md +1 -1
  10. package/bundled-skills/docs/users/bundles.md +1 -1
  11. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  12. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  13. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  14. package/bundled-skills/docs/users/usage.md +3 -3
  15. package/bundled-skills/docs/users/visual-guide.md +4 -4
  16. package/bundled-skills/dsh-deepread/SKILL.md +200 -0
  17. package/bundled-skills/liuguang-banlan-ui/SKILL.md +135 -0
  18. package/bundled-skills/liuguang-banlan-ui/assets/starter/favicon.svg +4 -0
  19. package/bundled-skills/liuguang-banlan-ui/assets/starter/index.html +32 -0
  20. package/bundled-skills/liuguang-banlan-ui/assets/starter/launcher.css +25 -0
  21. package/bundled-skills/liuguang-banlan-ui/assets/starter/obsidian/index.html +179 -0
  22. package/bundled-skills/liuguang-banlan-ui/assets/starter/obsidian/theme-config.js +105 -0
  23. package/bundled-skills/liuguang-banlan-ui/assets/starter/obsidian/theme.css +107 -0
  24. package/bundled-skills/liuguang-banlan-ui/assets/starter/opal/index.html +179 -0
  25. package/bundled-skills/liuguang-banlan-ui/assets/starter/opal/theme-config.js +105 -0
  26. package/bundled-skills/liuguang-banlan-ui/assets/starter/opal/theme.css +107 -0
  27. package/bundled-skills/liuguang-banlan-ui/assets/starter/shared/base.css +423 -0
  28. package/bundled-skills/liuguang-banlan-ui/assets/starter/shared/spectral-field.js +450 -0
  29. package/bundled-skills/liuguang-banlan-ui/assets/starter/shared/workbench.js +255 -0
  30. package/bundled-skills/liuguang-banlan-ui/references/style-contract.md +53 -0
  31. package/bundled-skills/liuguang-banlan-ui/references/verification.md +70 -0
  32. package/bundled-skills/liuguang-banlan-ui/scripts/measure_preview.py +144 -0
  33. package/bundled-skills/liuguang-banlan-ui/scripts/requirements.txt +2 -0
  34. package/bundled-skills/liuguang-banlan-ui/scripts/scaffold_template.py +43 -0
  35. package/bundled-skills/liuguang-banlan-ui/scripts/validate_manifest.py +173 -0
  36. package/bundled-skills/using-lwc/LICENSE +201 -0
  37. package/bundled-skills/using-lwc/README.md +926 -0
  38. package/bundled-skills/using-lwc/README.zh-CN.md +836 -0
  39. package/bundled-skills/using-lwc/SKILL.md +156 -0
  40. package/bundled-skills/using-lwc/agents/openai.yaml +4 -0
  41. package/bundled-skills/using-lwc/assets/global-purpose.md +17 -0
  42. package/bundled-skills/using-lwc/assets/global-schema.md +28 -0
  43. package/bundled-skills/using-lwc/references/active-memory.md +81 -0
  44. package/bundled-skills/using-lwc/references/agent-onboarding.md +84 -0
  45. package/bundled-skills/using-lwc/references/code-graph.md +60 -0
  46. package/bundled-skills/using-lwc/references/core-memory.md +51 -0
  47. package/bundled-skills/using-lwc/references/document-conversion.md +53 -0
  48. package/bundled-skills/using-lwc/references/document-graph.md +58 -0
  49. package/bundled-skills/using-lwc/references/llm-wiki.md +75 -0
  50. package/bundled-skills/using-lwc/references/memory-policy.md +551 -0
  51. package/bundled-skills/using-lwc/references/operations-manual.md +503 -0
  52. package/bundled-skills/using-lwc/references/recovery-maintenance.md +53 -0
  53. package/bundled-skills/using-lwc/references/strong-context.md +54 -0
  54. package/bundled-skills/using-lwc/references/trigger-playbook.md +53 -0
  55. package/bundled-skills/using-lwc/references/word-graph.md +45 -0
  56. package/bundled-skills/using-lwc/scripts/bootstrap.sh +359 -0
  57. package/bundled-skills/using-lwc/scripts/install-lwc.sh +172 -0
  58. package/package.json +1 -1
  59. package/skills_index.json +189 -0
@@ -0,0 +1,450 @@
1
+ (function () {
2
+ "use strict";
3
+
4
+ const MAX_COLORS = 12;
5
+
6
+ const VERTEX_SHADER = `
7
+ attribute vec2 aPosition;
8
+ void main() {
9
+ gl_Position = vec4(aPosition, 0.0, 1.0);
10
+ }
11
+ `;
12
+
13
+ const FRAGMENT_SHADER = `
14
+ precision highp float;
15
+
16
+ uniform vec2 uResolution;
17
+ uniform float uTime;
18
+ uniform float uSeed;
19
+ uniform float uMode;
20
+ uniform float uOverall;
21
+ uniform float uScale;
22
+ uniform float uOctaves;
23
+ uniform float uWarp;
24
+ uniform float uDither;
25
+ uniform float uLuminanceCap;
26
+ uniform vec3 uBase;
27
+ uniform vec3 uColors[12];
28
+ uniform float uStrengths[12];
29
+ uniform float uFieldScales[12];
30
+ uniform vec2 uPhases[12];
31
+ uniform float uColorCount;
32
+
33
+ float hash21(vec2 p) {
34
+ p = fract(p * vec2(123.34, 456.21));
35
+ p += dot(p, p + 45.32 + uSeed * 0.00013);
36
+ return fract(p.x * p.y);
37
+ }
38
+
39
+ float noise(vec2 p) {
40
+ vec2 i = floor(p);
41
+ vec2 f = fract(p);
42
+ vec2 u = f * f * (3.0 - 2.0 * f);
43
+ return mix(
44
+ mix(hash21(i), hash21(i + vec2(1.0, 0.0)), u.x),
45
+ mix(hash21(i + vec2(0.0, 1.0)), hash21(i + vec2(1.0, 1.0)), u.x),
46
+ u.y
47
+ );
48
+ }
49
+
50
+ float fbm(vec2 p) {
51
+ float value = 0.0;
52
+ float amplitude = 0.52;
53
+ mat2 rotation = mat2(0.80, 0.60, -0.60, 0.80);
54
+ for (int i = 0; i < 5; i++) {
55
+ float enabled = 1.0 - step(uOctaves, float(i) + 0.5);
56
+ value += amplitude * noise(p) * enabled;
57
+ p = rotation * p * 2.03 + vec2(13.1, 7.7);
58
+ amplitude *= 0.48;
59
+ }
60
+ return value;
61
+ }
62
+
63
+ float colorField(vec2 p, vec2 phase, float index, float fieldScale) {
64
+ float angle = 0.43 + index * 1.0472 + phase.x * 0.54;
65
+ vec2 direction = vec2(cos(angle), sin(angle));
66
+ float cloud = fbm(p * fieldScale + phase * 6.0);
67
+ float riverNoise = fbm(p * 0.48 + phase * 3.7);
68
+ float river = 0.5 + 0.5 * sin(
69
+ dot(p, direction) * (1.15 + fieldScale * 0.56)
70
+ + phase.y * 6.2832
71
+ + riverNoise * 3.4
72
+ );
73
+ return clamp(cloud * 0.54 + river * 0.62 - 0.12, 0.0, 1.0);
74
+ }
75
+
76
+ vec3 toneMap(vec3 c) {
77
+ return c / (1.0 + max(c - 1.0, 0.0));
78
+ }
79
+
80
+ void main() {
81
+ vec2 uv = gl_FragCoord.xy / uResolution.xy;
82
+ vec2 p = (uv - 0.5) * vec2(uResolution.x / uResolution.y, 1.0);
83
+ p *= uScale;
84
+
85
+ float time = uTime;
86
+ vec2 driftA = vec2(cos(time * 0.71), sin(time * 0.63)) * 0.11;
87
+ vec2 driftB = vec2(sin(time * 0.47), cos(time * 0.57)) * 0.09;
88
+ vec2 q = vec2(
89
+ fbm(p + vec2(0.0, 0.0) + driftA),
90
+ fbm(p + vec2(5.2, 1.3) - driftB)
91
+ );
92
+ vec2 r = vec2(
93
+ fbm(p + uWarp * q * 2.3 + vec2(1.7, 8.2) + driftB),
94
+ fbm(p + uWarp * q * 2.3 + vec2(8.3, 2.8) - driftA)
95
+ );
96
+ vec2 warped = p + uWarp * (q - 0.5) * 2.1 + uWarp * 0.72 * (r - 0.5);
97
+
98
+ vec3 colorSum = vec3(0.0);
99
+ float weightSum = 0.0;
100
+ float energySum = 0.0;
101
+ float strongestBand = 0.0;
102
+ float spectralFlow = fract(
103
+ fbm(warped * 0.92 + q * 0.42) * 2.05
104
+ + dot(warped, vec2(0.72, -0.49))
105
+ + uSeed * 0.000017
106
+ );
107
+ for (int i = 0; i < 12; i++) {
108
+ float field = colorField(
109
+ warped + q * (0.21 + float(i) * 0.025),
110
+ uPhases[i],
111
+ float(i),
112
+ uFieldScales[i]
113
+ );
114
+ float softBand = smoothstep(0.22, 0.78, field);
115
+ float active = step(float(i) + 0.5, uColorCount);
116
+ float hueStop = float(i) / max(uColorCount, 1.0);
117
+ float hueDistance = abs(spectralFlow - hueStop);
118
+ hueDistance = min(hueDistance, 1.0 - hueDistance);
119
+ float hueBand = 1.0 - smoothstep(0.035, 0.205, hueDistance);
120
+ float shapedBand = pow(hueBand, 2.2) * (0.64 + softBand * 0.36);
121
+ float weight = shapedBand * sqrt(max(uStrengths[i], 0.0)) * active;
122
+ colorSum += uColors[i] * weight;
123
+ weightSum += weight;
124
+ energySum += shapedBand * uStrengths[i] * active;
125
+ strongestBand = max(strongestBand, shapedBand);
126
+ }
127
+
128
+ vec3 palette = weightSum > 0.0001 ? colorSum / weightSum : uBase;
129
+ float globalField = fbm(warped * 0.58 + q * 0.3);
130
+ float fieldEnergy = clamp(energySum * 3.6 + strongestBand * 0.18 + globalField * 0.12, 0.0, 1.0);
131
+ float mixAmount;
132
+
133
+ if (uMode < 0.5) {
134
+ mixAmount = clamp(uOverall * (0.08 + fieldEnergy * 0.46), 0.0, 0.62);
135
+ } else {
136
+ mixAmount = clamp(uOverall * (0.10 + fieldEnergy * 0.92), 0.0, 0.92);
137
+ }
138
+
139
+ vec3 color = mix(uBase, palette, mixAmount);
140
+
141
+ if (uMode > 0.5) {
142
+ float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
143
+ if (luminance > uLuminanceCap) {
144
+ color *= uLuminanceCap / max(luminance, 0.0001);
145
+ }
146
+ }
147
+
148
+ float dither = hash21(floor(gl_FragCoord.xy) + vec2(uSeed, -uSeed)) - 0.5;
149
+ color += dither * (uDither / 255.0);
150
+ color = toneMap(max(color, 0.0));
151
+ color = pow(color, vec3(1.0 / 2.2));
152
+ gl_FragColor = vec4(color, 1.0);
153
+ }
154
+ `;
155
+
156
+ function oklchToLinearRgb(color) {
157
+ const angle = (color.h * Math.PI) / 180;
158
+ const a = color.c * Math.cos(angle);
159
+ const b = color.c * Math.sin(angle);
160
+ const l_ = color.l + 0.3963377774 * a + 0.2158037573 * b;
161
+ const m_ = color.l - 0.1055613458 * a - 0.0638541728 * b;
162
+ const s_ = color.l - 0.0894841775 * a - 1.291485548 * b;
163
+ const l = l_ * l_ * l_;
164
+ const m = m_ * m_ * m_;
165
+ const s = s_ * s_ * s_;
166
+ return [
167
+ Math.max(0, 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
168
+ Math.max(0, -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
169
+ Math.max(0, -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s)
170
+ ];
171
+ }
172
+
173
+ function clamp01(value) {
174
+ const number = Number(value);
175
+ return Number.isFinite(number) ? Math.min(1, Math.max(0, number)) : 0;
176
+ }
177
+
178
+ function hexToRgba(hex, alpha) {
179
+ const normalized = String(hex || "").replace("#", "");
180
+ if (!/^[0-9a-f]{6}$/i.test(normalized)) {
181
+ return "rgba(128, 128, 128, " + alpha.toFixed(3) + ")";
182
+ }
183
+ const red = parseInt(normalized.slice(0, 2), 16);
184
+ const green = parseInt(normalized.slice(2, 4), 16);
185
+ const blue = parseInt(normalized.slice(4, 6), 16);
186
+ return "rgba(" + [red, green, blue, alpha.toFixed(3)].join(", ") + ")";
187
+ }
188
+
189
+ function fallbackBackground(config) {
190
+ const colors = Array.isArray(config.colors) ? config.colors.slice(0, MAX_COLORS) : [];
191
+ const overall = clamp01(config.overallColorIntensity);
192
+ const seed = Number(config.seed) || 0;
193
+ const layers = [];
194
+
195
+ colors.forEach((entry, index) => {
196
+ const strength = clamp01(entry.intensity) * clamp01(entry.peakOpacity) * overall;
197
+ if (strength <= 0) return;
198
+ const angle = Math.round((index * 137.5) + (seed * 0.11));
199
+ const alpha = Math.min(0.82, strength * 0.95);
200
+ layers.push(
201
+ "linear-gradient(" + angle + "deg, transparent 6%, " +
202
+ hexToRgba(entry.srgbFallback, alpha * 0.35) + " 28%, " +
203
+ hexToRgba(entry.srgbFallback, alpha) + " 48%, " +
204
+ hexToRgba(entry.srgbFallback, alpha * 0.32) + " 68%, transparent 90%)"
205
+ );
206
+ });
207
+
208
+ layers.push("var(--app-canvas)");
209
+ return layers.join(", ");
210
+ }
211
+
212
+ function compileShader(gl, type, source) {
213
+ const shader = gl.createShader(type);
214
+ gl.shaderSource(shader, source);
215
+ gl.compileShader(shader);
216
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
217
+ const message = gl.getShaderInfoLog(shader);
218
+ gl.deleteShader(shader);
219
+ throw new Error(`Shader compilation failed: ${message}`);
220
+ }
221
+ return shader;
222
+ }
223
+
224
+ function createProgram(gl) {
225
+ const program = gl.createProgram();
226
+ gl.attachShader(program, compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER));
227
+ gl.attachShader(program, compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER));
228
+ gl.linkProgram(program);
229
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
230
+ throw new Error(`Shader link failed: ${gl.getProgramInfoLog(program)}`);
231
+ }
232
+ return program;
233
+ }
234
+
235
+ function uniform(gl, program, name) {
236
+ return gl.getUniformLocation(program, name);
237
+ }
238
+
239
+ class SpectralField {
240
+ constructor(canvas, config) {
241
+ this.canvas = canvas;
242
+ this.config = config;
243
+ this.applyFallbackConfig(config);
244
+ this.available = false;
245
+ this.error = null;
246
+ this.motionPreference = window.matchMedia("(prefers-reduced-motion: reduce)");
247
+ this.motionEnabled = !this.motionPreference.matches;
248
+ this.visible = !document.hidden;
249
+ this.startTime = performance.now();
250
+ this.phaseTime = null;
251
+ this.lastFrame = 0;
252
+ this.frameHandle = 0;
253
+ try {
254
+ this.gl = canvas.getContext("webgl", {
255
+ alpha: false,
256
+ antialias: false,
257
+ depth: false,
258
+ stencil: false,
259
+ powerPreference: "low-power",
260
+ preserveDrawingBuffer: true
261
+ });
262
+ if (!this.gl) throw new Error("WebGL context unavailable");
263
+
264
+ this.program = createProgram(this.gl);
265
+ this.gl.useProgram(this.program);
266
+ const buffer = this.gl.createBuffer();
267
+ if (!buffer) throw new Error("WebGL buffer creation failed");
268
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
269
+ this.gl.bufferData(
270
+ this.gl.ARRAY_BUFFER,
271
+ new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),
272
+ this.gl.STATIC_DRAW
273
+ );
274
+ const position = this.gl.getAttribLocation(this.program, "aPosition");
275
+ if (position < 0) throw new Error("WebGL position attribute unavailable");
276
+ this.gl.enableVertexAttribArray(position);
277
+ this.gl.vertexAttribPointer(position, 2, this.gl.FLOAT, false, 0, 0);
278
+
279
+ this.locations = {
280
+ resolution: uniform(this.gl, this.program, "uResolution"),
281
+ time: uniform(this.gl, this.program, "uTime"),
282
+ seed: uniform(this.gl, this.program, "uSeed"),
283
+ mode: uniform(this.gl, this.program, "uMode"),
284
+ overall: uniform(this.gl, this.program, "uOverall"),
285
+ colorCount: uniform(this.gl, this.program, "uColorCount"),
286
+ scale: uniform(this.gl, this.program, "uScale"),
287
+ octaves: uniform(this.gl, this.program, "uOctaves"),
288
+ warp: uniform(this.gl, this.program, "uWarp"),
289
+ dither: uniform(this.gl, this.program, "uDither"),
290
+ luminanceCap: uniform(this.gl, this.program, "uLuminanceCap"),
291
+ base: uniform(this.gl, this.program, "uBase"),
292
+ colors: uniform(this.gl, this.program, "uColors[0]"),
293
+ strengths: uniform(this.gl, this.program, "uStrengths[0]"),
294
+ fieldScales: uniform(this.gl, this.program, "uFieldScales[0]"),
295
+ phases: uniform(this.gl, this.program, "uPhases[0]")
296
+ };
297
+
298
+ this.onResize = () => this.resize();
299
+ this.onVisibility = () => {
300
+ const now = performance.now();
301
+ if (document.hidden) {
302
+ this.capturePhase(now);
303
+ this.visible = false;
304
+ if (this.frameHandle) {
305
+ cancelAnimationFrame(this.frameHandle);
306
+ this.frameHandle = 0;
307
+ }
308
+ return;
309
+ }
310
+
311
+ this.visible = true;
312
+ if (this.motionEnabled) {
313
+ const speed = this.config.field.motionSpeed;
314
+ this.startTime = speed > 0 && this.phaseTime !== null
315
+ ? now - (this.phaseTime / speed) * 1000
316
+ : now;
317
+ }
318
+ this.render(now, true);
319
+ this.schedule();
320
+ };
321
+ this.onMotionPreference = (event) => this.setMotion(!event.matches);
322
+ window.addEventListener("resize", this.onResize, { passive: true });
323
+ document.addEventListener("visibilitychange", this.onVisibility);
324
+ this.motionPreference.addEventListener("change", this.onMotionPreference);
325
+ this.available = true;
326
+ this.resize();
327
+ this.uploadConfig();
328
+ this.schedule();
329
+ } catch (error) {
330
+ this.error = error instanceof Error ? error.message : String(error);
331
+ this.available = false;
332
+ this.gl = null;
333
+ document.documentElement.classList.add("field-fallback");
334
+ }
335
+ }
336
+
337
+ resize() {
338
+ if (!this.available) return;
339
+ const pixelRatio = Math.min(window.devicePixelRatio || 1, 1.5);
340
+ const width = Math.max(1, Math.round(this.canvas.clientWidth * pixelRatio));
341
+ const height = Math.max(1, Math.round(this.canvas.clientHeight * pixelRatio));
342
+ if (this.canvas.width !== width || this.canvas.height !== height) {
343
+ this.canvas.width = width;
344
+ this.canvas.height = height;
345
+ this.gl.viewport(0, 0, width, height);
346
+ }
347
+ }
348
+
349
+ applyFallbackConfig(config) {
350
+ document.documentElement.style.setProperty("--field-fallback-background", fallbackBackground(config));
351
+ }
352
+
353
+ uploadConfig() {
354
+ if (!this.available) return;
355
+ const gl = this.gl;
356
+ const config = this.config;
357
+ const sourceColors = Array.isArray(config.colors) ? config.colors.slice(0, MAX_COLORS) : [];
358
+ const fallbackColor = sourceColors[0] || {
359
+ oklch: config.base.oklch,
360
+ intensity: 0,
361
+ peakOpacity: 0,
362
+ fieldScale: config.field.scale,
363
+ phase: [0, 0]
364
+ };
365
+ const colors = sourceColors.slice();
366
+ while (colors.length < MAX_COLORS) colors.push(fallbackColor);
367
+ const colorValues = colors.flatMap((entry) => oklchToLinearRgb(entry.oklch));
368
+ const strengthValues = colors.map((entry) => entry.intensity * entry.peakOpacity * 3.0);
369
+ const fieldScaleValues = colors.map((entry) => entry.fieldScale);
370
+ const phaseValues = colors.flatMap((entry) => entry.phase);
371
+ gl.useProgram(this.program);
372
+ gl.uniform1f(this.locations.seed, config.seed);
373
+ gl.uniform1f(this.locations.mode, config.mode === "obsidian" ? 1 : 0);
374
+ gl.uniform1f(this.locations.overall, config.overallColorIntensity);
375
+ gl.uniform1f(this.locations.colorCount, sourceColors.length);
376
+ gl.uniform1f(this.locations.scale, config.field.scale);
377
+ gl.uniform1f(this.locations.octaves, config.field.octaves);
378
+ gl.uniform1f(this.locations.warp, config.field.warpStrength);
379
+ gl.uniform1f(this.locations.dither, config.field.ditherStrength);
380
+ gl.uniform1f(this.locations.luminanceCap, config.field.luminanceCap);
381
+ gl.uniform3fv(this.locations.base, new Float32Array(oklchToLinearRgb(config.base.oklch)));
382
+ gl.uniform3fv(this.locations.colors, new Float32Array(colorValues));
383
+ gl.uniform1fv(this.locations.strengths, new Float32Array(strengthValues));
384
+ gl.uniform1fv(this.locations.fieldScales, new Float32Array(fieldScaleValues));
385
+ gl.uniform2fv(this.locations.phases, new Float32Array(phaseValues));
386
+ }
387
+
388
+ capturePhase(now) {
389
+ if (this.motionEnabled) {
390
+ this.phaseTime = ((now - this.startTime) / 1000) * this.config.field.motionSpeed;
391
+ } else if (this.phaseTime === null) {
392
+ this.phaseTime = this.config.field.staticTime;
393
+ }
394
+ return this.phaseTime;
395
+ }
396
+
397
+ updateConfig(config) {
398
+ const now = performance.now();
399
+ this.capturePhase(now);
400
+ this.config = config;
401
+ this.applyFallbackConfig(config);
402
+ this.uploadConfig();
403
+ this.render(now, true);
404
+ }
405
+
406
+ setMotion(enabled) {
407
+ if (enabled === this.motionEnabled) {
408
+ const now = performance.now();
409
+ if (!enabled) this.capturePhase(now);
410
+ this.render(now, true);
411
+ return;
412
+ }
413
+ const now = performance.now();
414
+ const phase = this.capturePhase(now);
415
+ this.motionEnabled = enabled;
416
+ if (enabled) {
417
+ const speed = this.config.field.motionSpeed;
418
+ this.startTime = speed > 0 ? now - (phase / speed) * 1000 : now;
419
+ this.schedule();
420
+ } else {
421
+ this.render(now, true);
422
+ }
423
+ }
424
+
425
+ schedule() {
426
+ if (!this.available || !this.visible || this.frameHandle) return;
427
+ this.frameHandle = requestAnimationFrame((now) => {
428
+ this.frameHandle = 0;
429
+ this.render(now, false);
430
+ if (this.motionEnabled) this.schedule();
431
+ });
432
+ }
433
+
434
+ render(now, force) {
435
+ if (!this.available) return;
436
+ if (!force && now - this.lastFrame < 50) {
437
+ this.schedule();
438
+ return;
439
+ }
440
+ this.lastFrame = now;
441
+ this.resize();
442
+ const elapsed = this.capturePhase(now);
443
+ this.gl.uniform2f(this.locations.resolution, this.canvas.width, this.canvas.height);
444
+ this.gl.uniform1f(this.locations.time, elapsed);
445
+ this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
446
+ }
447
+ }
448
+
449
+ window.SpectralField = SpectralField;
450
+ })();