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.
@@ -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":"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"}
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
- await new Promise((r) => setTimeout(r, this._playbackWaitMs(nextStep, msPerStep)));
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
- minNeeded = (step.value?.length ?? 0) * ANIMATION.narrationTypeMs + ANIMATION.narrationFadeMs;
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
- if (!this._container)
7898
- return;
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 first it has internal startup latency, so give it a head start
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
- const roughMod = window.rough ?? (typeof require !== 'undefined' ? require('roughjs/bin/rough') : null);
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 }));