@sarmal/core 0.37.1 → 0.38.0
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 +4 -4
- package/dist/auto-init.cjs +111 -14
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.js +111 -14
- package/dist/auto-init.js.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/curves/artemis2.d.cts +1 -1
- package/dist/curves/artemis2.d.ts +1 -1
- package/dist/curves/astroid.d.cts +1 -1
- package/dist/curves/astroid.d.ts +1 -1
- package/dist/curves/deltoid.d.cts +1 -1
- package/dist/curves/deltoid.d.ts +1 -1
- package/dist/curves/epicycloid3.d.cts +1 -1
- package/dist/curves/epicycloid3.d.ts +1 -1
- package/dist/curves/epitrochoid7.d.cts +1 -1
- package/dist/curves/epitrochoid7.d.ts +1 -1
- package/dist/curves/index.d.cts +1 -1
- package/dist/curves/index.d.ts +1 -1
- package/dist/curves/lame.d.cts +1 -1
- package/dist/curves/lame.d.ts +1 -1
- package/dist/curves/lissajous32.d.cts +1 -1
- package/dist/curves/lissajous32.d.ts +1 -1
- package/dist/curves/lissajous43.d.cts +1 -1
- package/dist/curves/lissajous43.d.ts +1 -1
- package/dist/curves/rose3.d.cts +1 -1
- package/dist/curves/rose3.d.ts +1 -1
- package/dist/curves/rose5.d.cts +1 -1
- package/dist/curves/rose5.d.ts +1 -1
- package/dist/curves/rose52.d.cts +1 -1
- package/dist/curves/rose52.d.ts +1 -1
- package/dist/curves/star.d.cts +1 -1
- package/dist/curves/star.d.ts +1 -1
- package/dist/curves/star4.d.cts +1 -1
- package/dist/curves/star4.d.ts +1 -1
- package/dist/curves/star7.d.cts +1 -1
- package/dist/curves/star7.d.ts +1 -1
- package/dist/index.cjs +111 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -53
- package/dist/index.d.ts +12 -53
- package/dist/index.js +111 -14
- package/dist/index.js.map +1 -1
- package/dist/{renderer-shared-DWPVHjKZ.d.ts → renderer-shared-2tEwOWJm.d.ts} +1 -1
- package/dist/{renderer-shared-Bcc_1IaT.d.cts → renderer-shared-Bh33A5Av.d.cts} +1 -1
- package/dist/terminal.cjs.map +1 -1
- package/dist/terminal.d.cts +2 -2
- package/dist/terminal.d.ts +2 -2
- package/dist/terminal.js.map +1 -1
- package/dist/{types-B1XeFpuq.d.cts → types-CmPFR9U3.d.cts} +126 -2
- package/dist/{types-B1XeFpuq.d.ts → types-CmPFR9U3.d.ts} +126 -2
- package/package.json +5 -5
- package/skills/core/SKILL.md +3 -3
package/dist/auto-init.js
CHANGED
|
@@ -362,15 +362,42 @@ function computeBoundaries(pts, logicalWidth, logicalHeight, minPaddingPx = FIT_
|
|
|
362
362
|
offsetY: (logicalHeight - h * scale) / 2 - minY * scale
|
|
363
363
|
};
|
|
364
364
|
}
|
|
365
|
-
|
|
365
|
+
var DESTROYED_ERROR = "[sarmal] Instance has been destroyed and cannot be used again. Call pause() instead of destroy() for temporary suspension.";
|
|
366
|
+
function enginePassthroughs(engine, isDestroyed) {
|
|
367
|
+
function guard() {
|
|
368
|
+
if (isDestroyed()) {
|
|
369
|
+
throw new Error(DESTROYED_ERROR);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
366
372
|
return {
|
|
367
|
-
jump
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
373
|
+
jump(phase, options) {
|
|
374
|
+
guard();
|
|
375
|
+
engine.jump(phase, options);
|
|
376
|
+
},
|
|
377
|
+
seek(phase, options) {
|
|
378
|
+
guard();
|
|
379
|
+
engine.seek(phase, options);
|
|
380
|
+
},
|
|
381
|
+
setSpeed(speed) {
|
|
382
|
+
guard();
|
|
383
|
+
engine.setSpeed(speed);
|
|
384
|
+
},
|
|
385
|
+
getSpeed() {
|
|
386
|
+
guard();
|
|
387
|
+
return engine.getSpeed();
|
|
388
|
+
},
|
|
389
|
+
resetSpeed() {
|
|
390
|
+
guard();
|
|
391
|
+
engine.resetSpeed();
|
|
392
|
+
},
|
|
393
|
+
setSpeedOver(speed, duration) {
|
|
394
|
+
guard();
|
|
395
|
+
return engine.setSpeedOver(speed, duration);
|
|
396
|
+
},
|
|
397
|
+
getSarmalSkeleton() {
|
|
398
|
+
guard();
|
|
399
|
+
return engine.getSarmalSkeleton();
|
|
400
|
+
}
|
|
374
401
|
};
|
|
375
402
|
}
|
|
376
403
|
function hexToRgb(hex) {
|
|
@@ -729,6 +756,7 @@ function createRenderer(options) {
|
|
|
729
756
|
let animationId = null;
|
|
730
757
|
let lastTime = 0;
|
|
731
758
|
let pausedByVisibility = false;
|
|
759
|
+
let destroyed = false;
|
|
732
760
|
let morphResolve = null;
|
|
733
761
|
let morphReject = null;
|
|
734
762
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
@@ -900,6 +928,9 @@ function createRenderer(options) {
|
|
|
900
928
|
const shouldAutoStart = options.autoStart !== false;
|
|
901
929
|
const instance = {
|
|
902
930
|
play() {
|
|
931
|
+
if (destroyed) {
|
|
932
|
+
throw new Error(DESTROYED_ERROR);
|
|
933
|
+
}
|
|
903
934
|
if (animationId !== null) {
|
|
904
935
|
return;
|
|
905
936
|
}
|
|
@@ -907,6 +938,9 @@ function createRenderer(options) {
|
|
|
907
938
|
loop();
|
|
908
939
|
},
|
|
909
940
|
pause() {
|
|
941
|
+
if (destroyed) {
|
|
942
|
+
throw new Error(DESTROYED_ERROR);
|
|
943
|
+
}
|
|
910
944
|
if (animationId === null) {
|
|
911
945
|
return;
|
|
912
946
|
}
|
|
@@ -915,24 +949,36 @@ function createRenderer(options) {
|
|
|
915
949
|
engine.cancelSpeedTransition();
|
|
916
950
|
},
|
|
917
951
|
reset() {
|
|
952
|
+
if (destroyed) {
|
|
953
|
+
throw new Error(DESTROYED_ERROR);
|
|
954
|
+
}
|
|
918
955
|
engine.reset();
|
|
919
956
|
trail = [];
|
|
920
957
|
head = null;
|
|
921
958
|
},
|
|
922
959
|
destroy() {
|
|
960
|
+
if (destroyed) {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
destroyed = true;
|
|
923
964
|
if (animationId !== null) {
|
|
924
965
|
cancelAnimationFrame(animationId);
|
|
925
966
|
animationId = null;
|
|
926
967
|
}
|
|
927
968
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
969
|
+
engine.cancelSpeedTransition();
|
|
928
970
|
if (morphReject !== null) {
|
|
929
|
-
morphReject(new Error("Instance destroyed during morph"));
|
|
971
|
+
morphReject(new Error("[sarmal] Instance destroyed during morph"));
|
|
930
972
|
morphResolve = null;
|
|
931
973
|
morphReject = null;
|
|
932
974
|
}
|
|
975
|
+
ctx.clearRect(0, 0, logicalWidth, logicalHeight);
|
|
933
976
|
},
|
|
934
|
-
...enginePassthroughs(engine),
|
|
977
|
+
...enginePassthroughs(engine, () => destroyed),
|
|
935
978
|
morphTo(target, options2) {
|
|
979
|
+
if (destroyed) {
|
|
980
|
+
throw new Error(DESTROYED_ERROR);
|
|
981
|
+
}
|
|
936
982
|
if (morphResolve !== null) {
|
|
937
983
|
engine.completeMorph();
|
|
938
984
|
morphResolve();
|
|
@@ -949,6 +995,9 @@ function createRenderer(options) {
|
|
|
949
995
|
});
|
|
950
996
|
},
|
|
951
997
|
setRenderOptions(partial) {
|
|
998
|
+
if (destroyed) {
|
|
999
|
+
throw new Error(DESTROYED_ERROR);
|
|
1000
|
+
}
|
|
952
1001
|
validateRenderOptions(partial);
|
|
953
1002
|
if (partial.trailColor !== void 0) {
|
|
954
1003
|
trailColor = partial.trailColor;
|
|
@@ -1203,6 +1252,7 @@ function createSVGRenderer(options) {
|
|
|
1203
1252
|
let animationId = null;
|
|
1204
1253
|
let lastTime = 0;
|
|
1205
1254
|
let pausedByVisibility = false;
|
|
1255
|
+
let destroyed = false;
|
|
1206
1256
|
const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1207
1257
|
let morphResolve = null;
|
|
1208
1258
|
let morphReject = null;
|
|
@@ -1271,6 +1321,9 @@ function createSVGRenderer(options) {
|
|
|
1271
1321
|
const shouldAutoStart = options.autoStart !== false;
|
|
1272
1322
|
const instance = {
|
|
1273
1323
|
play() {
|
|
1324
|
+
if (destroyed) {
|
|
1325
|
+
throw new Error(DESTROYED_ERROR);
|
|
1326
|
+
}
|
|
1274
1327
|
if (animationId !== null) {
|
|
1275
1328
|
return;
|
|
1276
1329
|
}
|
|
@@ -1278,6 +1331,9 @@ function createSVGRenderer(options) {
|
|
|
1278
1331
|
loop();
|
|
1279
1332
|
},
|
|
1280
1333
|
pause() {
|
|
1334
|
+
if (destroyed) {
|
|
1335
|
+
throw new Error(DESTROYED_ERROR);
|
|
1336
|
+
}
|
|
1281
1337
|
if (animationId === null) {
|
|
1282
1338
|
return;
|
|
1283
1339
|
}
|
|
@@ -1286,23 +1342,34 @@ function createSVGRenderer(options) {
|
|
|
1286
1342
|
engine.cancelSpeedTransition();
|
|
1287
1343
|
},
|
|
1288
1344
|
reset() {
|
|
1345
|
+
if (destroyed) {
|
|
1346
|
+
throw new Error(DESTROYED_ERROR);
|
|
1347
|
+
}
|
|
1289
1348
|
engine.reset();
|
|
1290
1349
|
},
|
|
1291
1350
|
destroy() {
|
|
1351
|
+
if (destroyed) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
destroyed = true;
|
|
1292
1355
|
if (animationId !== null) {
|
|
1293
1356
|
cancelAnimationFrame(animationId);
|
|
1294
1357
|
animationId = null;
|
|
1295
1358
|
}
|
|
1296
1359
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1360
|
+
engine.cancelSpeedTransition();
|
|
1297
1361
|
if (morphReject !== null) {
|
|
1298
|
-
morphReject(new Error("Instance destroyed during morph"));
|
|
1362
|
+
morphReject(new Error("[sarmal] Instance destroyed during morph"));
|
|
1299
1363
|
morphResolve = null;
|
|
1300
1364
|
morphReject = null;
|
|
1301
1365
|
}
|
|
1302
1366
|
group.remove();
|
|
1303
1367
|
},
|
|
1304
|
-
...enginePassthroughs(engine),
|
|
1368
|
+
...enginePassthroughs(engine, () => destroyed),
|
|
1305
1369
|
morphTo(target, options2) {
|
|
1370
|
+
if (destroyed) {
|
|
1371
|
+
throw new Error(DESTROYED_ERROR);
|
|
1372
|
+
}
|
|
1306
1373
|
if (morphResolve !== null) {
|
|
1307
1374
|
engine.completeMorph();
|
|
1308
1375
|
morphResolve();
|
|
@@ -1328,6 +1395,9 @@ function createSVGRenderer(options) {
|
|
|
1328
1395
|
});
|
|
1329
1396
|
},
|
|
1330
1397
|
setRenderOptions(partial) {
|
|
1398
|
+
if (destroyed) {
|
|
1399
|
+
throw new Error(DESTROYED_ERROR);
|
|
1400
|
+
}
|
|
1331
1401
|
validateRenderOptions(partial);
|
|
1332
1402
|
const prevTrailStyle = trailStyle;
|
|
1333
1403
|
if (partial.trailColor !== void 0) {
|
|
@@ -1457,6 +1527,7 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1457
1527
|
let animationId = null;
|
|
1458
1528
|
let lastTime = 0;
|
|
1459
1529
|
let pausedByVisibility = false;
|
|
1530
|
+
let destroyed = false;
|
|
1460
1531
|
let morphResolve = null;
|
|
1461
1532
|
let morphReject = null;
|
|
1462
1533
|
let morphDurationMs = DEFAULT_MORPH_DURATION_MS;
|
|
@@ -1710,6 +1781,9 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1710
1781
|
const instance = {
|
|
1711
1782
|
/** Starts the animation loop. Does nothing if already running. */
|
|
1712
1783
|
play() {
|
|
1784
|
+
if (destroyed) {
|
|
1785
|
+
throw new Error(DESTROYED_ERROR);
|
|
1786
|
+
}
|
|
1713
1787
|
if (animationId !== null) {
|
|
1714
1788
|
return;
|
|
1715
1789
|
}
|
|
@@ -1718,6 +1792,9 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1718
1792
|
},
|
|
1719
1793
|
/** Pauses the animation loop. Preserves current trail state. */
|
|
1720
1794
|
pause() {
|
|
1795
|
+
if (destroyed) {
|
|
1796
|
+
throw new Error(DESTROYED_ERROR);
|
|
1797
|
+
}
|
|
1721
1798
|
if (animationId === null) {
|
|
1722
1799
|
return;
|
|
1723
1800
|
}
|
|
@@ -1727,29 +1804,46 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1727
1804
|
},
|
|
1728
1805
|
/** Resets the animation to the start of the curve and clears the grid. */
|
|
1729
1806
|
reset() {
|
|
1807
|
+
if (destroyed) {
|
|
1808
|
+
throw new Error(DESTROYED_ERROR);
|
|
1809
|
+
}
|
|
1730
1810
|
engine.reset();
|
|
1731
1811
|
grid.fill(0);
|
|
1732
1812
|
},
|
|
1733
|
-
/**
|
|
1813
|
+
/**
|
|
1814
|
+
* Permanently stops the animation and clears the visual output.
|
|
1815
|
+
* Calling any method on a destroyed instance throws an error.
|
|
1816
|
+
* `destroy()` is idempotent — calling it multiple times is safe.
|
|
1817
|
+
*/
|
|
1734
1818
|
destroy() {
|
|
1819
|
+
if (destroyed) {
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
destroyed = true;
|
|
1735
1823
|
if (animationId !== null) {
|
|
1736
1824
|
cancelAnimationFrame(animationId);
|
|
1737
1825
|
animationId = null;
|
|
1738
1826
|
}
|
|
1739
1827
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
1828
|
+
engine.cancelSpeedTransition();
|
|
1740
1829
|
if (morphReject !== null) {
|
|
1741
1830
|
morphReject(new Error("[sarmal] Instance destroyed during morph"));
|
|
1742
1831
|
morphResolve = null;
|
|
1743
1832
|
morphReject = null;
|
|
1744
1833
|
}
|
|
1834
|
+
grid.fill(0);
|
|
1835
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1745
1836
|
},
|
|
1746
|
-
...enginePassthroughs(engine),
|
|
1837
|
+
...enginePassthroughs(engine, () => destroyed),
|
|
1747
1838
|
/**
|
|
1748
1839
|
* Smoothly transitions from the current curve to `target`.
|
|
1749
1840
|
* If a morph is already in progress, it is snapped to completion before the new one starts.
|
|
1750
1841
|
* @returns A Promise that resolves when the transition finishes.
|
|
1751
1842
|
*/
|
|
1752
1843
|
morphTo(target, opts) {
|
|
1844
|
+
if (destroyed) {
|
|
1845
|
+
throw new Error(DESTROYED_ERROR);
|
|
1846
|
+
}
|
|
1753
1847
|
if (morphResolve !== null) {
|
|
1754
1848
|
completeMorphNow();
|
|
1755
1849
|
}
|
|
@@ -1769,6 +1863,9 @@ function createSarmalDotMatrix(canvas, curveDef, options) {
|
|
|
1769
1863
|
* ! Validation fails the entire call if any field is invalid, leaving options unchanged.
|
|
1770
1864
|
*/
|
|
1771
1865
|
setRenderOptions(partial) {
|
|
1866
|
+
if (destroyed) {
|
|
1867
|
+
throw new Error(DESTROYED_ERROR);
|
|
1868
|
+
}
|
|
1772
1869
|
validateBaseRenderOptions(partial);
|
|
1773
1870
|
let needsRebuildBg = false;
|
|
1774
1871
|
if (partial.trailColor !== void 0) {
|