sketchmark 1.1.4 → 1.1.5
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 +55 -35
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/index.cjs +134 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +134 -4
- package/dist/index.js.map +1 -1
- package/dist/render.d.ts +1 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/sketchmark.iife.js +134 -4
- package/dist/ui/canvas.d.ts +12 -0
- package/dist/ui/canvas.d.ts.map +1 -1
- package/dist/ui/embed.d.ts +12 -0
- package/dist/ui/embed.d.ts.map +1 -1
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -84,9 +84,11 @@ end
|
|
|
84
84
|
`.trim(),
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
const canvas = new SketchmarkCanvas({
|
|
88
|
-
container: document.getElementById('viewport'),
|
|
89
|
-
|
|
87
|
+
const canvas = new SketchmarkCanvas({
|
|
88
|
+
container: document.getElementById('viewport'),
|
|
89
|
+
showCaption: false,
|
|
90
|
+
tts: true,
|
|
91
|
+
});
|
|
90
92
|
|
|
91
93
|
canvas.bindEditor(editor);
|
|
92
94
|
```
|
|
@@ -100,13 +102,15 @@ const embed = new SketchmarkEmbed({
|
|
|
100
102
|
width: 960,
|
|
101
103
|
height: 540,
|
|
102
104
|
playStepDelay: 700,
|
|
105
|
+
showCaption: false,
|
|
106
|
+
tts: true,
|
|
103
107
|
fitPadding: 24,
|
|
104
108
|
zoomMin: 0.08,
|
|
105
109
|
zoomMax: 4,
|
|
106
110
|
});
|
|
107
111
|
```
|
|
108
112
|
|
|
109
|
-
Use `SketchmarkCanvas` for the full playground-style surface, and `SketchmarkEmbed` for fixed-size embeds that clip overflow, auto-fit large diagrams, and expose built-in
|
|
113
|
+
Use `SketchmarkCanvas` for the full playground-style surface, and `SketchmarkEmbed` for fixed-size embeds that clip overflow, auto-fit large diagrams, and expose built-in zoom, playback, caption, and TTS controls.
|
|
110
114
|
|
|
111
115
|
---
|
|
112
116
|
|
|
@@ -661,9 +665,11 @@ step narrate "Plants need sunlight to make food"
|
|
|
661
665
|
step narrate "This is the most important step" pace=slow
|
|
662
666
|
```
|
|
663
667
|
|
|
664
|
-
- Caption is rendered as a fixed-position `<div>` on `document.body` (independent of diagram pan/zoom).
|
|
665
|
-
- Access via `anim.captionElement` to reparent it anywhere.
|
|
666
|
-
-
|
|
668
|
+
- Caption is rendered as a fixed-position `<div>` on `document.body` (independent of diagram pan/zoom).
|
|
669
|
+
- Access via `anim.captionElement` to reparent it anywhere.
|
|
670
|
+
- `SketchmarkCanvas` and `SketchmarkEmbed` support `showCaption: false` to hide the caption bar UI.
|
|
671
|
+
- Both widget UIs also include a built-in caption toggle button by default.
|
|
672
|
+
- Supports built-in browser text-to-speech (see [TTS](#text-to-speech)).
|
|
667
673
|
|
|
668
674
|
### Annotations
|
|
669
675
|
|
|
@@ -799,10 +805,14 @@ anim.destroy() // remove caption, annotations, pointer from DOM
|
|
|
799
805
|
|
|
800
806
|
// Toggle TTS programmatically
|
|
801
807
|
anim.tts = true; // enable browser speech
|
|
802
|
-
anim.tts = false; // disable (stops current speech)
|
|
803
|
-
|
|
804
|
-
// Reparent the narration caption to a custom container
|
|
805
|
-
myDiv.appendChild(anim.captionElement);
|
|
808
|
+
anim.tts = false; // disable (stops current speech)
|
|
809
|
+
|
|
810
|
+
// Reparent the narration caption to a custom container
|
|
811
|
+
myDiv.appendChild(anim.captionElement);
|
|
812
|
+
|
|
813
|
+
// UI widgets can suppress the visible caption bar
|
|
814
|
+
const embed = new SketchmarkEmbed({ container, dsl, showCaption: false });
|
|
815
|
+
embed.setCaptionVisible(true);
|
|
806
816
|
|
|
807
817
|
// Event listener
|
|
808
818
|
const unsub = anim.on((event) => {
|
|
@@ -814,22 +824,31 @@ const unsub = anim.on((event) => {
|
|
|
814
824
|
unsub(); // unsubscribe
|
|
815
825
|
```
|
|
816
826
|
|
|
817
|
-
### Text-to-Speech
|
|
818
|
-
|
|
819
|
-
Enable browser-native speech synthesis for narrate steps
|
|
820
|
-
|
|
821
|
-
```
|
|
822
|
-
# In DSL
|
|
823
|
-
config tts=on
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
```javascript
|
|
827
|
-
//
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
//
|
|
831
|
-
|
|
832
|
-
|
|
827
|
+
### Text-to-Speech
|
|
828
|
+
|
|
829
|
+
Enable browser-native speech synthesis for narrate steps. You can drive it from the diagram config or from the JS API. If both are provided, the JS option wins. `SketchmarkCanvas` and `SketchmarkEmbed` also include a built-in TTS toggle button by default.
|
|
830
|
+
|
|
831
|
+
```
|
|
832
|
+
# In DSL
|
|
833
|
+
config tts=on
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
```javascript
|
|
837
|
+
// Direct render option
|
|
838
|
+
const instance = render({ container, dsl, tts: true });
|
|
839
|
+
|
|
840
|
+
// Widget options
|
|
841
|
+
const canvas = new SketchmarkCanvas({ container, dsl, tts: true });
|
|
842
|
+
const embed = new SketchmarkEmbed({ container, dsl, tts: true });
|
|
843
|
+
|
|
844
|
+
// Or toggle at runtime
|
|
845
|
+
anim.tts = true;
|
|
846
|
+
canvas.setTtsEnabled(false);
|
|
847
|
+
embed.setTtsEnabled(true);
|
|
848
|
+
|
|
849
|
+
// Custom TTS (e.g. ElevenLabs) via event listener
|
|
850
|
+
anim.tts = false; // disable built-in
|
|
851
|
+
anim.on((e) => {
|
|
833
852
|
if (e.step?.kind === 'step' && e.step.action === 'narrate') {
|
|
834
853
|
myTTSService.speak(e.step.value);
|
|
835
854
|
}
|
|
@@ -1211,14 +1230,15 @@ end
|
|
|
1211
1230
|
```typescript
|
|
1212
1231
|
render(options: RenderOptions): DiagramInstance
|
|
1213
1232
|
|
|
1214
|
-
interface RenderOptions {
|
|
1215
|
-
container: string | HTMLElement | SVGSVGElement; // CSS selector or element
|
|
1216
|
-
dsl: string; // DSL source text
|
|
1217
|
-
renderer?: 'svg' | 'canvas'; // default: 'svg'
|
|
1218
|
-
injectCSS?: boolean; // inject animation CSS (default: true)
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1233
|
+
interface RenderOptions {
|
|
1234
|
+
container: string | HTMLElement | SVGSVGElement; // CSS selector or element
|
|
1235
|
+
dsl: string; // DSL source text
|
|
1236
|
+
renderer?: 'svg' | 'canvas'; // default: 'svg'
|
|
1237
|
+
injectCSS?: boolean; // inject animation CSS (default: true)
|
|
1238
|
+
tts?: boolean; // override diagram TTS config
|
|
1239
|
+
svgOptions?: SVGRendererOptions;
|
|
1240
|
+
canvasOptions?: CanvasRendererOptions;
|
|
1241
|
+
onNodeClick?: (nodeId: string) => void; // click handler
|
|
1222
1242
|
onReady?: (anim, svg?) => void; // callback after render
|
|
1223
1243
|
}
|
|
1224
1244
|
|
|
@@ -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
|
@@ -9443,8 +9443,17 @@ class AnimationController {
|
|
|
9443
9443
|
}
|
|
9444
9444
|
/** Enable/disable browser text-to-speech for narrate steps */
|
|
9445
9445
|
get tts() { return this._tts; }
|
|
9446
|
-
set tts(on) {
|
|
9447
|
-
|
|
9446
|
+
set tts(on) {
|
|
9447
|
+
const next = !!on;
|
|
9448
|
+
const changed = next !== this._tts;
|
|
9449
|
+
this._tts = next;
|
|
9450
|
+
if (!next) {
|
|
9451
|
+
this._cancelSpeech();
|
|
9452
|
+
return;
|
|
9453
|
+
}
|
|
9454
|
+
if (changed)
|
|
9455
|
+
this._warmUpSpeech();
|
|
9456
|
+
}
|
|
9448
9457
|
get currentStep() {
|
|
9449
9458
|
return this._step;
|
|
9450
9459
|
}
|
|
@@ -10723,7 +10732,7 @@ class EventEmitter {
|
|
|
10723
10732
|
}
|
|
10724
10733
|
|
|
10725
10734
|
function render(options) {
|
|
10726
|
-
const { container: rawContainer, dsl, renderer = "svg", injectCSS = true, svgOptions = {}, canvasOptions = {}, onNodeClick, onReady, } = options;
|
|
10735
|
+
const { container: rawContainer, dsl, renderer = "svg", injectCSS = true, tts, svgOptions = {}, canvasOptions = {}, onNodeClick, onReady, } = options;
|
|
10727
10736
|
if (injectCSS && !document.getElementById("ai-diagram-css")) {
|
|
10728
10737
|
const style = document.createElement("style");
|
|
10729
10738
|
style.id = "ai-diagram-css";
|
|
@@ -10772,6 +10781,9 @@ function render(options) {
|
|
|
10772
10781
|
const containerEl = el instanceof SVGSVGElement ? undefined : el;
|
|
10773
10782
|
anim = new AnimationController(svg, ast.steps, containerEl, rc, ast.config);
|
|
10774
10783
|
}
|
|
10784
|
+
if (typeof tts === "boolean") {
|
|
10785
|
+
anim.tts = tts;
|
|
10786
|
+
}
|
|
10775
10787
|
onReady?.(anim, svg);
|
|
10776
10788
|
return {
|
|
10777
10789
|
scene,
|
|
@@ -10823,13 +10835,14 @@ function toError(error) {
|
|
|
10823
10835
|
const CANVAS_STYLE_ID = "sketchmark-canvas-ui";
|
|
10824
10836
|
const CANVAS_CSS = `
|
|
10825
10837
|
.skm-canvas{display:flex;flex-direction:column;width:100%;height:100%;min-height:320px;overflow:hidden;border:1px solid #caba98;border-radius:10px;background:#f8f4ea;color:#3a2010;font-family:"Courier New",monospace}
|
|
10826
|
-
.skm-canvas__animbar{display:flex;align-items:center;gap:6px;padding:6px 10px;background:#eee7d8;border-bottom:1px solid #caba98;flex-shrink:0}
|
|
10838
|
+
.skm-canvas__animbar{display:flex;align-items:center;gap:6px;padding:6px 10px;background:#eee7d8;border-bottom:1px solid #caba98;flex-shrink:0;flex-wrap:wrap}
|
|
10827
10839
|
.skm-canvas__status{min-width:96px;text-align:center;color:#6a4820;font-size:11px}
|
|
10828
10840
|
.skm-canvas__label{color:#8a6040;font-size:11px;font-style:italic}
|
|
10829
10841
|
.skm-canvas__spacer{flex:1}
|
|
10830
10842
|
.skm-canvas__stats{color:#9a7848;font-size:10px}
|
|
10831
10843
|
.skm-canvas__button{border:1px solid #caba98;background:#f5eedd;color:#3a2010;border-radius:6px;padding:4px 9px;font:inherit;font-size:11px;cursor:pointer;transition:background .12s ease,border-color .12s ease,color .12s ease}
|
|
10832
10844
|
.skm-canvas__button:hover:not(:disabled){background:#c8a060;border-color:#c8a060;color:#fff}
|
|
10845
|
+
.skm-canvas__button.is-active{background:#c8a060;border-color:#c8a060;color:#fff}
|
|
10833
10846
|
.skm-canvas__button:disabled{opacity:.45;cursor:default}
|
|
10834
10847
|
.skm-canvas__error{display:none;padding:8px 12px;background:#280a0a;border-bottom:1px solid #5a1818;color:#f07070;font-size:11px;line-height:1.4;white-space:pre-wrap;flex-shrink:0}
|
|
10835
10848
|
.skm-canvas__error.is-visible{display:block}
|
|
@@ -10851,6 +10864,8 @@ class SketchmarkCanvas {
|
|
|
10851
10864
|
this.instance = null;
|
|
10852
10865
|
this.emitter = new EventEmitter();
|
|
10853
10866
|
this.dsl = "";
|
|
10867
|
+
this.showCaption = true;
|
|
10868
|
+
this.ttsOverride = null;
|
|
10854
10869
|
this.panX = 60;
|
|
10855
10870
|
this.panY = 60;
|
|
10856
10871
|
this.zoom = 1;
|
|
@@ -10938,6 +10953,8 @@ class SketchmarkCanvas {
|
|
|
10938
10953
|
this.options = options;
|
|
10939
10954
|
this.renderer = options.renderer ?? "svg";
|
|
10940
10955
|
this.theme = options.theme ?? "light";
|
|
10956
|
+
this.showCaption = options.showCaption !== false;
|
|
10957
|
+
this.ttsOverride = typeof options.tts === "boolean" ? options.tts : null;
|
|
10941
10958
|
this.dsl = normalizeNewlines(options.dsl ?? "");
|
|
10942
10959
|
injectStyleOnce(CANVAS_STYLE_ID, CANVAS_CSS);
|
|
10943
10960
|
const host = resolveContainer(options.container);
|
|
@@ -10956,6 +10973,8 @@ class SketchmarkCanvas {
|
|
|
10956
10973
|
<span class="skm-canvas__status">No steps</span>
|
|
10957
10974
|
<button type="button" class="skm-canvas__button" data-action="next">Next</button>
|
|
10958
10975
|
<button type="button" class="skm-canvas__button" data-action="play">Play</button>
|
|
10976
|
+
<button type="button" class="skm-canvas__button" data-action="toggle-caption">Caption On</button>
|
|
10977
|
+
<button type="button" class="skm-canvas__button" data-action="toggle-tts">TTS Off</button>
|
|
10959
10978
|
<span class="skm-canvas__label"></span>
|
|
10960
10979
|
<span class="skm-canvas__spacer"></span>
|
|
10961
10980
|
<span class="skm-canvas__stats"></span>
|
|
@@ -10990,6 +11009,8 @@ class SketchmarkCanvas {
|
|
|
10990
11009
|
this.prevButton = this.root.querySelector('[data-action="prev"]');
|
|
10991
11010
|
this.nextButton = this.root.querySelector('[data-action="next"]');
|
|
10992
11011
|
this.resetButton = this.root.querySelector('[data-action="reset"]');
|
|
11012
|
+
this.captionButton = this.root.querySelector('[data-action="toggle-caption"]');
|
|
11013
|
+
this.ttsButton = this.root.querySelector('[data-action="toggle-tts"]');
|
|
10993
11014
|
this.gridPattern = this.root.querySelector(`#${patternId}`);
|
|
10994
11015
|
this.gridDot = this.gridPattern.querySelector("circle");
|
|
10995
11016
|
this.root.querySelector('[data-action="fit"]')?.addEventListener("click", () => this.fitContent());
|
|
@@ -11000,6 +11021,8 @@ class SketchmarkCanvas {
|
|
|
11000
11021
|
this.prevButton.addEventListener("click", () => this.prevStep());
|
|
11001
11022
|
this.nextButton.addEventListener("click", () => this.nextStep());
|
|
11002
11023
|
this.playButton.addEventListener("click", () => void this.play());
|
|
11024
|
+
this.captionButton.addEventListener("click", () => this.setCaptionVisible(!this.showCaption));
|
|
11025
|
+
this.ttsButton.addEventListener("click", () => this.setTtsEnabled(!this.getTtsEnabled()));
|
|
11003
11026
|
this.viewport.addEventListener("pointerdown", this.onPointerDown);
|
|
11004
11027
|
this.viewport.addEventListener("pointermove", this.onPointerMove);
|
|
11005
11028
|
this.viewport.addEventListener("pointerup", this.onStopPanning);
|
|
@@ -11021,6 +11044,16 @@ class SketchmarkCanvas {
|
|
|
11021
11044
|
if (renderNow)
|
|
11022
11045
|
this.render();
|
|
11023
11046
|
}
|
|
11047
|
+
setCaptionVisible(visible) {
|
|
11048
|
+
this.showCaption = visible;
|
|
11049
|
+
this.applyCaptionVisibility(this.instance);
|
|
11050
|
+
this.syncToggleUi();
|
|
11051
|
+
}
|
|
11052
|
+
setTtsEnabled(enabled) {
|
|
11053
|
+
this.ttsOverride = enabled;
|
|
11054
|
+
this.applyTtsSetting(this.instance);
|
|
11055
|
+
this.syncToggleUi();
|
|
11056
|
+
}
|
|
11024
11057
|
bindEditor(editor, options = {}) {
|
|
11025
11058
|
this.editorCleanup?.();
|
|
11026
11059
|
const renderOnRun = options.renderOnRun !== false;
|
|
@@ -11065,6 +11098,8 @@ class SketchmarkCanvas {
|
|
|
11065
11098
|
onNodeClick: this.options.onNodeClick,
|
|
11066
11099
|
});
|
|
11067
11100
|
this.instance = instance;
|
|
11101
|
+
this.applyCaptionVisibility(instance);
|
|
11102
|
+
this.applyTtsSetting(instance);
|
|
11068
11103
|
this.statsLabel.textContent = `${instance.scene.nodes.length}n / ${instance.scene.edges.length}e / ${instance.scene.groups.length}g`;
|
|
11069
11104
|
if (this.renderer === "svg") {
|
|
11070
11105
|
this.animUnsub = instance.anim.on((event) => {
|
|
@@ -11197,6 +11232,37 @@ class SketchmarkCanvas {
|
|
|
11197
11232
|
this.zoom = clampedZoom;
|
|
11198
11233
|
this.applyTransform();
|
|
11199
11234
|
}
|
|
11235
|
+
applyCaptionVisibility(instance) {
|
|
11236
|
+
const caption = instance?.anim.captionElement;
|
|
11237
|
+
if (!caption)
|
|
11238
|
+
return;
|
|
11239
|
+
caption.style.display = this.showCaption ? "" : "none";
|
|
11240
|
+
caption.setAttribute("aria-hidden", this.showCaption ? "false" : "true");
|
|
11241
|
+
}
|
|
11242
|
+
applyTtsSetting(instance) {
|
|
11243
|
+
if (!instance || this.ttsOverride === null)
|
|
11244
|
+
return;
|
|
11245
|
+
instance.anim.tts = this.ttsOverride;
|
|
11246
|
+
}
|
|
11247
|
+
getTtsEnabled() {
|
|
11248
|
+
if (this.ttsOverride !== null)
|
|
11249
|
+
return this.ttsOverride;
|
|
11250
|
+
return !!this.instance?.anim.tts;
|
|
11251
|
+
}
|
|
11252
|
+
syncToggleUi() {
|
|
11253
|
+
const canToggleCaption = this.renderer === "svg" && !!this.instance;
|
|
11254
|
+
const canToggleTts = canToggleCaption &&
|
|
11255
|
+
typeof speechSynthesis !== "undefined";
|
|
11256
|
+
const ttsEnabled = this.getTtsEnabled();
|
|
11257
|
+
this.captionButton.textContent = this.showCaption ? "Caption On" : "Caption Off";
|
|
11258
|
+
this.captionButton.classList.toggle("is-active", this.showCaption);
|
|
11259
|
+
this.captionButton.setAttribute("aria-pressed", this.showCaption ? "true" : "false");
|
|
11260
|
+
this.captionButton.disabled = !canToggleCaption;
|
|
11261
|
+
this.ttsButton.textContent = ttsEnabled ? "TTS On" : "TTS Off";
|
|
11262
|
+
this.ttsButton.classList.toggle("is-active", ttsEnabled);
|
|
11263
|
+
this.ttsButton.setAttribute("aria-pressed", ttsEnabled ? "true" : "false");
|
|
11264
|
+
this.ttsButton.disabled = !canToggleTts;
|
|
11265
|
+
}
|
|
11200
11266
|
syncAnimationUi() {
|
|
11201
11267
|
const anim = this.instance?.anim;
|
|
11202
11268
|
const canAnimate = this.renderer === "svg" && !!anim && anim.total > 0;
|
|
@@ -11207,6 +11273,7 @@ class SketchmarkCanvas {
|
|
|
11207
11273
|
this.nextButton.disabled = true;
|
|
11208
11274
|
this.resetButton.disabled = true;
|
|
11209
11275
|
this.playButton.disabled = true;
|
|
11276
|
+
this.syncToggleUi();
|
|
11210
11277
|
return;
|
|
11211
11278
|
}
|
|
11212
11279
|
this.stepDisplay.textContent = anim.currentStep < 0 ? `${anim.total} steps` : `${anim.currentStep + 1} / ${anim.total}`;
|
|
@@ -11215,6 +11282,7 @@ class SketchmarkCanvas {
|
|
|
11215
11282
|
this.nextButton.disabled = !anim.canNext;
|
|
11216
11283
|
this.resetButton.disabled = false;
|
|
11217
11284
|
this.playButton.disabled = this.playInFlight || !anim.canNext;
|
|
11285
|
+
this.syncToggleUi();
|
|
11218
11286
|
}
|
|
11219
11287
|
getStepTarget(stepItem) {
|
|
11220
11288
|
if (!stepItem)
|
|
@@ -11914,6 +11982,12 @@ const EMBED_CSS = `
|
|
|
11914
11982
|
color: #fff;
|
|
11915
11983
|
}
|
|
11916
11984
|
|
|
11985
|
+
.skm-embed__button.is-active {
|
|
11986
|
+
background: #c8a060;
|
|
11987
|
+
border-color: #c8a060;
|
|
11988
|
+
color: #fff;
|
|
11989
|
+
}
|
|
11990
|
+
|
|
11917
11991
|
.skm-embed--dark .skm-embed__button {
|
|
11918
11992
|
border-color: #4a3520;
|
|
11919
11993
|
background: #22190e;
|
|
@@ -11960,6 +12034,8 @@ class SketchmarkEmbed {
|
|
|
11960
12034
|
this.emitter = new EventEmitter();
|
|
11961
12035
|
this.animUnsub = null;
|
|
11962
12036
|
this.playInFlight = false;
|
|
12037
|
+
this.showCaption = true;
|
|
12038
|
+
this.ttsOverride = null;
|
|
11963
12039
|
this.zoom = 1;
|
|
11964
12040
|
this.offsetX = 0;
|
|
11965
12041
|
this.offsetY = 0;
|
|
@@ -11969,6 +12045,8 @@ class SketchmarkEmbed {
|
|
|
11969
12045
|
this.options = options;
|
|
11970
12046
|
this.dsl = normalizeNewlines(options.dsl);
|
|
11971
12047
|
this.theme = options.theme ?? "light";
|
|
12048
|
+
this.showCaption = options.showCaption !== false;
|
|
12049
|
+
this.ttsOverride = typeof options.tts === "boolean" ? options.tts : null;
|
|
11972
12050
|
injectStyleOnce(EMBED_STYLE_ID, EMBED_CSS);
|
|
11973
12051
|
const host = resolveContainer(options.container);
|
|
11974
12052
|
host.innerHTML = "";
|
|
@@ -11996,6 +12074,10 @@ class SketchmarkEmbed {
|
|
|
11996
12074
|
<button type="button" class="skm-embed__button" data-action="next">Next</button>
|
|
11997
12075
|
<button type="button" class="skm-embed__button" data-action="play">Play</button>
|
|
11998
12076
|
</div>
|
|
12077
|
+
<div class="skm-embed__controls-group">
|
|
12078
|
+
<button type="button" class="skm-embed__button" data-action="toggle-caption">Caption On</button>
|
|
12079
|
+
<button type="button" class="skm-embed__button" data-action="toggle-tts">TTS Off</button>
|
|
12080
|
+
</div>
|
|
11999
12081
|
<span class="skm-embed__step">No steps</span>
|
|
12000
12082
|
</div>
|
|
12001
12083
|
`;
|
|
@@ -12013,6 +12095,8 @@ class SketchmarkEmbed {
|
|
|
12013
12095
|
this.btnPrev = this.root.querySelector('[data-action="prev"]');
|
|
12014
12096
|
this.btnNext = this.root.querySelector('[data-action="next"]');
|
|
12015
12097
|
this.btnPlay = this.root.querySelector('[data-action="play"]');
|
|
12098
|
+
this.btnCaption = this.root.querySelector('[data-action="toggle-caption"]');
|
|
12099
|
+
this.btnTts = this.root.querySelector('[data-action="toggle-tts"]');
|
|
12016
12100
|
this.controlsElement.classList.toggle("is-hidden", options.showControls === false);
|
|
12017
12101
|
this.btnFit.addEventListener("click", () => this.resetView());
|
|
12018
12102
|
this.btnZoomIn.addEventListener("click", () => this.zoomIn());
|
|
@@ -12023,6 +12107,8 @@ class SketchmarkEmbed {
|
|
|
12023
12107
|
this.btnPlay.addEventListener("click", () => {
|
|
12024
12108
|
void this.play();
|
|
12025
12109
|
});
|
|
12110
|
+
this.btnCaption.addEventListener("click", () => this.setCaptionVisible(!this.showCaption));
|
|
12111
|
+
this.btnTts.addEventListener("click", () => this.setTtsEnabled(!this.getTtsEnabled()));
|
|
12026
12112
|
if (typeof ResizeObserver !== "undefined") {
|
|
12027
12113
|
this.resizeObserver = new ResizeObserver(() => {
|
|
12028
12114
|
this.positionViewport(false);
|
|
@@ -12040,6 +12126,16 @@ class SketchmarkEmbed {
|
|
|
12040
12126
|
if (renderNow)
|
|
12041
12127
|
this.render();
|
|
12042
12128
|
}
|
|
12129
|
+
setCaptionVisible(visible) {
|
|
12130
|
+
this.showCaption = visible;
|
|
12131
|
+
this.applyCaptionVisibility(this.instance);
|
|
12132
|
+
this.syncToggleControls();
|
|
12133
|
+
}
|
|
12134
|
+
setTtsEnabled(enabled) {
|
|
12135
|
+
this.ttsOverride = enabled;
|
|
12136
|
+
this.applyTtsSetting(this.instance);
|
|
12137
|
+
this.syncToggleControls();
|
|
12138
|
+
}
|
|
12043
12139
|
setSize(width, height) {
|
|
12044
12140
|
this.applySize(width, height);
|
|
12045
12141
|
this.positionViewport(false);
|
|
@@ -12084,6 +12180,8 @@ class SketchmarkEmbed {
|
|
|
12084
12180
|
onNodeClick: this.options.onNodeClick,
|
|
12085
12181
|
});
|
|
12086
12182
|
this.instance = instance;
|
|
12183
|
+
this.applyCaptionVisibility(instance);
|
|
12184
|
+
this.applyTtsSetting(instance);
|
|
12087
12185
|
this.animUnsub = instance.anim.on((event) => {
|
|
12088
12186
|
this.syncControls();
|
|
12089
12187
|
if (event.type === "step-change") {
|
|
@@ -12188,6 +12286,7 @@ class SketchmarkEmbed {
|
|
|
12188
12286
|
syncControls() {
|
|
12189
12287
|
this.syncAnimationControls();
|
|
12190
12288
|
this.syncViewControls();
|
|
12289
|
+
this.syncToggleControls();
|
|
12191
12290
|
}
|
|
12192
12291
|
syncAnimationControls() {
|
|
12193
12292
|
const anim = this.instance?.anim;
|
|
@@ -12349,6 +12448,37 @@ class SketchmarkEmbed {
|
|
|
12349
12448
|
this.applyTransform();
|
|
12350
12449
|
this.syncViewControls();
|
|
12351
12450
|
}
|
|
12451
|
+
applyCaptionVisibility(instance) {
|
|
12452
|
+
const caption = instance?.anim.captionElement;
|
|
12453
|
+
if (!caption)
|
|
12454
|
+
return;
|
|
12455
|
+
caption.style.display = this.showCaption ? "" : "none";
|
|
12456
|
+
caption.setAttribute("aria-hidden", this.showCaption ? "false" : "true");
|
|
12457
|
+
}
|
|
12458
|
+
applyTtsSetting(instance) {
|
|
12459
|
+
if (!instance || this.ttsOverride === null)
|
|
12460
|
+
return;
|
|
12461
|
+
instance.anim.tts = this.ttsOverride;
|
|
12462
|
+
}
|
|
12463
|
+
getTtsEnabled() {
|
|
12464
|
+
if (this.ttsOverride !== null)
|
|
12465
|
+
return this.ttsOverride;
|
|
12466
|
+
return !!this.instance?.anim.tts;
|
|
12467
|
+
}
|
|
12468
|
+
syncToggleControls() {
|
|
12469
|
+
const hasView = !!this.instance?.svg;
|
|
12470
|
+
const canToggleTts = hasView &&
|
|
12471
|
+
typeof speechSynthesis !== "undefined";
|
|
12472
|
+
const ttsEnabled = this.getTtsEnabled();
|
|
12473
|
+
this.btnCaption.textContent = this.showCaption ? "Caption On" : "Caption Off";
|
|
12474
|
+
this.btnCaption.classList.toggle("is-active", this.showCaption);
|
|
12475
|
+
this.btnCaption.setAttribute("aria-pressed", this.showCaption ? "true" : "false");
|
|
12476
|
+
this.btnCaption.disabled = !hasView;
|
|
12477
|
+
this.btnTts.textContent = ttsEnabled ? "TTS On" : "TTS Off";
|
|
12478
|
+
this.btnTts.classList.toggle("is-active", ttsEnabled);
|
|
12479
|
+
this.btnTts.setAttribute("aria-pressed", ttsEnabled ? "true" : "false");
|
|
12480
|
+
this.btnTts.disabled = !canToggleTts;
|
|
12481
|
+
}
|
|
12352
12482
|
getTargetBox(target, viewportRect) {
|
|
12353
12483
|
if (target instanceof SVGGraphicsElement) {
|
|
12354
12484
|
try {
|