sketchmark 1.0.0 → 1.0.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/dist/animation/index.d.ts +1 -0
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/index.cjs +24 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -10
- package/dist/index.js.map +1 -1
- package/dist/sketchmark.iife.js +24 -10
- package/package.json +1 -1
|
@@ -36,6 +36,7 @@ export declare class AnimationController {
|
|
|
36
36
|
private _pointerEl;
|
|
37
37
|
private _pointerType;
|
|
38
38
|
private _tts;
|
|
39
|
+
private _speechDone;
|
|
39
40
|
get drawTargets(): Set<string>;
|
|
40
41
|
constructor(svg: SVGSVGElement, steps: ASTStepItem[], _container?: HTMLElement | undefined, _rc?: any | undefined, _config?: Record<string, string | number | boolean> | undefined);
|
|
41
42
|
/** The narration caption element — mount it anywhere via `yourContainer.appendChild(anim.captionElement)` */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/animation/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAoB,WAAW,EAAE,MAAM,cAAc,CAAC;AAGlE,MAAM,MAAM,kBAAkB,GAC1B,aAAa,GACb,eAAe,GACf,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,CAAC;AACpB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;AAiX5D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAQtE;AACD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAOtE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAOvE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAOtE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAOvE;AAsKD,qBAAa,mBAAmB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/animation/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -7180,6 +7180,7 @@ class AnimationController {
|
|
|
7180
7180
|
this._pointerType = 'none';
|
|
7181
7181
|
// ── TTS ──
|
|
7182
7182
|
this._tts = false;
|
|
7183
|
+
this._speechDone = null;
|
|
7183
7184
|
this.drawTargetEdges = getDrawTargetEdgeIds(steps);
|
|
7184
7185
|
this.drawTargetNodes = getDrawTargetNodeIds(steps);
|
|
7185
7186
|
// Groups: non-edge draw steps whose target has a #group-{id} element in the SVG.
|
|
@@ -7310,7 +7311,11 @@ class AnimationController {
|
|
|
7310
7311
|
while (this.canNext) {
|
|
7311
7312
|
const nextStep = this.steps[this._step + 1];
|
|
7312
7313
|
this.next();
|
|
7313
|
-
|
|
7314
|
+
// Wait for timer AND speech to finish (whichever is longer)
|
|
7315
|
+
await Promise.all([
|
|
7316
|
+
new Promise((r) => setTimeout(r, this._playbackWaitMs(nextStep, msPerStep))),
|
|
7317
|
+
this._speechDone ?? Promise.resolve(),
|
|
7318
|
+
]);
|
|
7314
7319
|
}
|
|
7315
7320
|
}
|
|
7316
7321
|
goTo(index) {
|
|
@@ -7348,8 +7353,13 @@ class AnimationController {
|
|
|
7348
7353
|
// Compute minimum time the step actually needs to finish
|
|
7349
7354
|
let minNeeded = 0;
|
|
7350
7355
|
if (step.action === "narrate") {
|
|
7356
|
+
const text = step.value ?? "";
|
|
7351
7357
|
// Typing effect: chars × typeMs + fade buffer
|
|
7352
|
-
|
|
7358
|
+
const typingMs = text.length * ANIMATION.narrationTypeMs + ANIMATION.narrationFadeMs;
|
|
7359
|
+
// TTS estimate: ~150ms per word + 500ms buffer for engine latency
|
|
7360
|
+
const wordCount = text.split(/\s+/).filter(Boolean).length;
|
|
7361
|
+
const ttsMs = this._tts ? wordCount * 150 + 500 : 0;
|
|
7362
|
+
minNeeded = Math.max(typingMs, ttsMs);
|
|
7353
7363
|
}
|
|
7354
7364
|
else if (step.action === "circle" || step.action === "underline" ||
|
|
7355
7365
|
step.action === "crossout" || step.action === "bracket") {
|
|
@@ -7894,8 +7904,8 @@ class AnimationController {
|
|
|
7894
7904
|
}
|
|
7895
7905
|
// ── narration ───────────────────────────────────────────
|
|
7896
7906
|
_initCaption() {
|
|
7897
|
-
|
|
7898
|
-
|
|
7907
|
+
// Remove any leftover caption from a previous instance
|
|
7908
|
+
document.querySelector('.skm-caption')?.remove();
|
|
7899
7909
|
const cap = document.createElement("div");
|
|
7900
7910
|
cap.className = "skm-caption";
|
|
7901
7911
|
cap.style.cssText = `
|
|
@@ -7925,7 +7935,7 @@ class AnimationController {
|
|
|
7925
7935
|
this._captionTextEl.textContent = text;
|
|
7926
7936
|
return;
|
|
7927
7937
|
}
|
|
7928
|
-
// Fire TTS
|
|
7938
|
+
// Fire TTS as full sentence — play() waits for _speechDone
|
|
7929
7939
|
if (this._tts && text)
|
|
7930
7940
|
this._speak(text);
|
|
7931
7941
|
// Typing effect
|
|
@@ -7948,11 +7958,17 @@ class AnimationController {
|
|
|
7948
7958
|
utter.rate = 0.95;
|
|
7949
7959
|
utter.pitch = 1;
|
|
7950
7960
|
utter.lang = "en-US";
|
|
7961
|
+
// Track when speech actually finishes
|
|
7962
|
+
this._speechDone = new Promise((resolve) => {
|
|
7963
|
+
utter.onend = () => resolve();
|
|
7964
|
+
utter.onerror = () => resolve();
|
|
7965
|
+
});
|
|
7951
7966
|
speechSynthesis.speak(utter);
|
|
7952
7967
|
}
|
|
7953
7968
|
_cancelSpeech() {
|
|
7954
7969
|
if (typeof speechSynthesis !== "undefined")
|
|
7955
7970
|
speechSynthesis.cancel();
|
|
7971
|
+
this._speechDone = null;
|
|
7956
7972
|
}
|
|
7957
7973
|
/** Pre-warm the speech engine with a silent utterance to eliminate cold-start delay */
|
|
7958
7974
|
_warmUpSpeech() {
|
|
@@ -8459,12 +8475,10 @@ function render(options) {
|
|
|
8459
8475
|
interactive: true,
|
|
8460
8476
|
onNodeClick,
|
|
8461
8477
|
});
|
|
8462
|
-
// Create rough.js instance for annotations
|
|
8478
|
+
// Create rough.js instance for annotations (same import as SVG renderer)
|
|
8463
8479
|
let rc = null;
|
|
8464
8480
|
try {
|
|
8465
|
-
|
|
8466
|
-
if (roughMod?.svg)
|
|
8467
|
-
rc = roughMod.svg(svg);
|
|
8481
|
+
rc = rough.svg(svg);
|
|
8468
8482
|
}
|
|
8469
8483
|
catch { /* rough.js not available — annotations disabled */ }
|
|
8470
8484
|
const containerEl = el instanceof SVGSVGElement ? undefined : el;
|
|
@@ -8473,7 +8487,7 @@ function render(options) {
|
|
|
8473
8487
|
onReady?.(anim, svg);
|
|
8474
8488
|
const instance = {
|
|
8475
8489
|
scene, anim, svg, canvas,
|
|
8476
|
-
update: (newDsl) => render({ ...options, dsl: newDsl }),
|
|
8490
|
+
update: (newDsl) => { anim?.destroy(); return render({ ...options, dsl: newDsl }); },
|
|
8477
8491
|
exportSVG: (filename = 'diagram.svg') => {
|
|
8478
8492
|
if (svg) {
|
|
8479
8493
|
Promise.resolve().then(function () { return index; }).then(m => m.exportSVG(svg, { filename }));
|