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.
Potentially problematic release.
This version of sketchmark might be problematic. Click here for more details.
- 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/dist/index.js
CHANGED
|
@@ -9441,8 +9441,17 @@ class AnimationController {
|
|
|
9441
9441
|
}
|
|
9442
9442
|
/** Enable/disable browser text-to-speech for narrate steps */
|
|
9443
9443
|
get tts() { return this._tts; }
|
|
9444
|
-
set tts(on) {
|
|
9445
|
-
|
|
9444
|
+
set tts(on) {
|
|
9445
|
+
const next = !!on;
|
|
9446
|
+
const changed = next !== this._tts;
|
|
9447
|
+
this._tts = next;
|
|
9448
|
+
if (!next) {
|
|
9449
|
+
this._cancelSpeech();
|
|
9450
|
+
return;
|
|
9451
|
+
}
|
|
9452
|
+
if (changed)
|
|
9453
|
+
this._warmUpSpeech();
|
|
9454
|
+
}
|
|
9446
9455
|
get currentStep() {
|
|
9447
9456
|
return this._step;
|
|
9448
9457
|
}
|
|
@@ -10721,7 +10730,7 @@ class EventEmitter {
|
|
|
10721
10730
|
}
|
|
10722
10731
|
|
|
10723
10732
|
function render(options) {
|
|
10724
|
-
const { container: rawContainer, dsl, renderer = "svg", injectCSS = true, svgOptions = {}, canvasOptions = {}, onNodeClick, onReady, } = options;
|
|
10733
|
+
const { container: rawContainer, dsl, renderer = "svg", injectCSS = true, tts, svgOptions = {}, canvasOptions = {}, onNodeClick, onReady, } = options;
|
|
10725
10734
|
if (injectCSS && !document.getElementById("ai-diagram-css")) {
|
|
10726
10735
|
const style = document.createElement("style");
|
|
10727
10736
|
style.id = "ai-diagram-css";
|
|
@@ -10770,6 +10779,9 @@ function render(options) {
|
|
|
10770
10779
|
const containerEl = el instanceof SVGSVGElement ? undefined : el;
|
|
10771
10780
|
anim = new AnimationController(svg, ast.steps, containerEl, rc, ast.config);
|
|
10772
10781
|
}
|
|
10782
|
+
if (typeof tts === "boolean") {
|
|
10783
|
+
anim.tts = tts;
|
|
10784
|
+
}
|
|
10773
10785
|
onReady?.(anim, svg);
|
|
10774
10786
|
return {
|
|
10775
10787
|
scene,
|
|
@@ -10821,13 +10833,14 @@ function toError(error) {
|
|
|
10821
10833
|
const CANVAS_STYLE_ID = "sketchmark-canvas-ui";
|
|
10822
10834
|
const CANVAS_CSS = `
|
|
10823
10835
|
.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}
|
|
10824
|
-
.skm-canvas__animbar{display:flex;align-items:center;gap:6px;padding:6px 10px;background:#eee7d8;border-bottom:1px solid #caba98;flex-shrink:0}
|
|
10836
|
+
.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}
|
|
10825
10837
|
.skm-canvas__status{min-width:96px;text-align:center;color:#6a4820;font-size:11px}
|
|
10826
10838
|
.skm-canvas__label{color:#8a6040;font-size:11px;font-style:italic}
|
|
10827
10839
|
.skm-canvas__spacer{flex:1}
|
|
10828
10840
|
.skm-canvas__stats{color:#9a7848;font-size:10px}
|
|
10829
10841
|
.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}
|
|
10830
10842
|
.skm-canvas__button:hover:not(:disabled){background:#c8a060;border-color:#c8a060;color:#fff}
|
|
10843
|
+
.skm-canvas__button.is-active{background:#c8a060;border-color:#c8a060;color:#fff}
|
|
10831
10844
|
.skm-canvas__button:disabled{opacity:.45;cursor:default}
|
|
10832
10845
|
.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}
|
|
10833
10846
|
.skm-canvas__error.is-visible{display:block}
|
|
@@ -10849,6 +10862,8 @@ class SketchmarkCanvas {
|
|
|
10849
10862
|
this.instance = null;
|
|
10850
10863
|
this.emitter = new EventEmitter();
|
|
10851
10864
|
this.dsl = "";
|
|
10865
|
+
this.showCaption = true;
|
|
10866
|
+
this.ttsOverride = null;
|
|
10852
10867
|
this.panX = 60;
|
|
10853
10868
|
this.panY = 60;
|
|
10854
10869
|
this.zoom = 1;
|
|
@@ -10936,6 +10951,8 @@ class SketchmarkCanvas {
|
|
|
10936
10951
|
this.options = options;
|
|
10937
10952
|
this.renderer = options.renderer ?? "svg";
|
|
10938
10953
|
this.theme = options.theme ?? "light";
|
|
10954
|
+
this.showCaption = options.showCaption !== false;
|
|
10955
|
+
this.ttsOverride = typeof options.tts === "boolean" ? options.tts : null;
|
|
10939
10956
|
this.dsl = normalizeNewlines(options.dsl ?? "");
|
|
10940
10957
|
injectStyleOnce(CANVAS_STYLE_ID, CANVAS_CSS);
|
|
10941
10958
|
const host = resolveContainer(options.container);
|
|
@@ -10954,6 +10971,8 @@ class SketchmarkCanvas {
|
|
|
10954
10971
|
<span class="skm-canvas__status">No steps</span>
|
|
10955
10972
|
<button type="button" class="skm-canvas__button" data-action="next">Next</button>
|
|
10956
10973
|
<button type="button" class="skm-canvas__button" data-action="play">Play</button>
|
|
10974
|
+
<button type="button" class="skm-canvas__button" data-action="toggle-caption">Caption On</button>
|
|
10975
|
+
<button type="button" class="skm-canvas__button" data-action="toggle-tts">TTS Off</button>
|
|
10957
10976
|
<span class="skm-canvas__label"></span>
|
|
10958
10977
|
<span class="skm-canvas__spacer"></span>
|
|
10959
10978
|
<span class="skm-canvas__stats"></span>
|
|
@@ -10988,6 +11007,8 @@ class SketchmarkCanvas {
|
|
|
10988
11007
|
this.prevButton = this.root.querySelector('[data-action="prev"]');
|
|
10989
11008
|
this.nextButton = this.root.querySelector('[data-action="next"]');
|
|
10990
11009
|
this.resetButton = this.root.querySelector('[data-action="reset"]');
|
|
11010
|
+
this.captionButton = this.root.querySelector('[data-action="toggle-caption"]');
|
|
11011
|
+
this.ttsButton = this.root.querySelector('[data-action="toggle-tts"]');
|
|
10991
11012
|
this.gridPattern = this.root.querySelector(`#${patternId}`);
|
|
10992
11013
|
this.gridDot = this.gridPattern.querySelector("circle");
|
|
10993
11014
|
this.root.querySelector('[data-action="fit"]')?.addEventListener("click", () => this.fitContent());
|
|
@@ -10998,6 +11019,8 @@ class SketchmarkCanvas {
|
|
|
10998
11019
|
this.prevButton.addEventListener("click", () => this.prevStep());
|
|
10999
11020
|
this.nextButton.addEventListener("click", () => this.nextStep());
|
|
11000
11021
|
this.playButton.addEventListener("click", () => void this.play());
|
|
11022
|
+
this.captionButton.addEventListener("click", () => this.setCaptionVisible(!this.showCaption));
|
|
11023
|
+
this.ttsButton.addEventListener("click", () => this.setTtsEnabled(!this.getTtsEnabled()));
|
|
11001
11024
|
this.viewport.addEventListener("pointerdown", this.onPointerDown);
|
|
11002
11025
|
this.viewport.addEventListener("pointermove", this.onPointerMove);
|
|
11003
11026
|
this.viewport.addEventListener("pointerup", this.onStopPanning);
|
|
@@ -11019,6 +11042,16 @@ class SketchmarkCanvas {
|
|
|
11019
11042
|
if (renderNow)
|
|
11020
11043
|
this.render();
|
|
11021
11044
|
}
|
|
11045
|
+
setCaptionVisible(visible) {
|
|
11046
|
+
this.showCaption = visible;
|
|
11047
|
+
this.applyCaptionVisibility(this.instance);
|
|
11048
|
+
this.syncToggleUi();
|
|
11049
|
+
}
|
|
11050
|
+
setTtsEnabled(enabled) {
|
|
11051
|
+
this.ttsOverride = enabled;
|
|
11052
|
+
this.applyTtsSetting(this.instance);
|
|
11053
|
+
this.syncToggleUi();
|
|
11054
|
+
}
|
|
11022
11055
|
bindEditor(editor, options = {}) {
|
|
11023
11056
|
this.editorCleanup?.();
|
|
11024
11057
|
const renderOnRun = options.renderOnRun !== false;
|
|
@@ -11063,6 +11096,8 @@ class SketchmarkCanvas {
|
|
|
11063
11096
|
onNodeClick: this.options.onNodeClick,
|
|
11064
11097
|
});
|
|
11065
11098
|
this.instance = instance;
|
|
11099
|
+
this.applyCaptionVisibility(instance);
|
|
11100
|
+
this.applyTtsSetting(instance);
|
|
11066
11101
|
this.statsLabel.textContent = `${instance.scene.nodes.length}n / ${instance.scene.edges.length}e / ${instance.scene.groups.length}g`;
|
|
11067
11102
|
if (this.renderer === "svg") {
|
|
11068
11103
|
this.animUnsub = instance.anim.on((event) => {
|
|
@@ -11195,6 +11230,37 @@ class SketchmarkCanvas {
|
|
|
11195
11230
|
this.zoom = clampedZoom;
|
|
11196
11231
|
this.applyTransform();
|
|
11197
11232
|
}
|
|
11233
|
+
applyCaptionVisibility(instance) {
|
|
11234
|
+
const caption = instance?.anim.captionElement;
|
|
11235
|
+
if (!caption)
|
|
11236
|
+
return;
|
|
11237
|
+
caption.style.display = this.showCaption ? "" : "none";
|
|
11238
|
+
caption.setAttribute("aria-hidden", this.showCaption ? "false" : "true");
|
|
11239
|
+
}
|
|
11240
|
+
applyTtsSetting(instance) {
|
|
11241
|
+
if (!instance || this.ttsOverride === null)
|
|
11242
|
+
return;
|
|
11243
|
+
instance.anim.tts = this.ttsOverride;
|
|
11244
|
+
}
|
|
11245
|
+
getTtsEnabled() {
|
|
11246
|
+
if (this.ttsOverride !== null)
|
|
11247
|
+
return this.ttsOverride;
|
|
11248
|
+
return !!this.instance?.anim.tts;
|
|
11249
|
+
}
|
|
11250
|
+
syncToggleUi() {
|
|
11251
|
+
const canToggleCaption = this.renderer === "svg" && !!this.instance;
|
|
11252
|
+
const canToggleTts = canToggleCaption &&
|
|
11253
|
+
typeof speechSynthesis !== "undefined";
|
|
11254
|
+
const ttsEnabled = this.getTtsEnabled();
|
|
11255
|
+
this.captionButton.textContent = this.showCaption ? "Caption On" : "Caption Off";
|
|
11256
|
+
this.captionButton.classList.toggle("is-active", this.showCaption);
|
|
11257
|
+
this.captionButton.setAttribute("aria-pressed", this.showCaption ? "true" : "false");
|
|
11258
|
+
this.captionButton.disabled = !canToggleCaption;
|
|
11259
|
+
this.ttsButton.textContent = ttsEnabled ? "TTS On" : "TTS Off";
|
|
11260
|
+
this.ttsButton.classList.toggle("is-active", ttsEnabled);
|
|
11261
|
+
this.ttsButton.setAttribute("aria-pressed", ttsEnabled ? "true" : "false");
|
|
11262
|
+
this.ttsButton.disabled = !canToggleTts;
|
|
11263
|
+
}
|
|
11198
11264
|
syncAnimationUi() {
|
|
11199
11265
|
const anim = this.instance?.anim;
|
|
11200
11266
|
const canAnimate = this.renderer === "svg" && !!anim && anim.total > 0;
|
|
@@ -11205,6 +11271,7 @@ class SketchmarkCanvas {
|
|
|
11205
11271
|
this.nextButton.disabled = true;
|
|
11206
11272
|
this.resetButton.disabled = true;
|
|
11207
11273
|
this.playButton.disabled = true;
|
|
11274
|
+
this.syncToggleUi();
|
|
11208
11275
|
return;
|
|
11209
11276
|
}
|
|
11210
11277
|
this.stepDisplay.textContent = anim.currentStep < 0 ? `${anim.total} steps` : `${anim.currentStep + 1} / ${anim.total}`;
|
|
@@ -11213,6 +11280,7 @@ class SketchmarkCanvas {
|
|
|
11213
11280
|
this.nextButton.disabled = !anim.canNext;
|
|
11214
11281
|
this.resetButton.disabled = false;
|
|
11215
11282
|
this.playButton.disabled = this.playInFlight || !anim.canNext;
|
|
11283
|
+
this.syncToggleUi();
|
|
11216
11284
|
}
|
|
11217
11285
|
getStepTarget(stepItem) {
|
|
11218
11286
|
if (!stepItem)
|
|
@@ -11912,6 +11980,12 @@ const EMBED_CSS = `
|
|
|
11912
11980
|
color: #fff;
|
|
11913
11981
|
}
|
|
11914
11982
|
|
|
11983
|
+
.skm-embed__button.is-active {
|
|
11984
|
+
background: #c8a060;
|
|
11985
|
+
border-color: #c8a060;
|
|
11986
|
+
color: #fff;
|
|
11987
|
+
}
|
|
11988
|
+
|
|
11915
11989
|
.skm-embed--dark .skm-embed__button {
|
|
11916
11990
|
border-color: #4a3520;
|
|
11917
11991
|
background: #22190e;
|
|
@@ -11958,6 +12032,8 @@ class SketchmarkEmbed {
|
|
|
11958
12032
|
this.emitter = new EventEmitter();
|
|
11959
12033
|
this.animUnsub = null;
|
|
11960
12034
|
this.playInFlight = false;
|
|
12035
|
+
this.showCaption = true;
|
|
12036
|
+
this.ttsOverride = null;
|
|
11961
12037
|
this.zoom = 1;
|
|
11962
12038
|
this.offsetX = 0;
|
|
11963
12039
|
this.offsetY = 0;
|
|
@@ -11967,6 +12043,8 @@ class SketchmarkEmbed {
|
|
|
11967
12043
|
this.options = options;
|
|
11968
12044
|
this.dsl = normalizeNewlines(options.dsl);
|
|
11969
12045
|
this.theme = options.theme ?? "light";
|
|
12046
|
+
this.showCaption = options.showCaption !== false;
|
|
12047
|
+
this.ttsOverride = typeof options.tts === "boolean" ? options.tts : null;
|
|
11970
12048
|
injectStyleOnce(EMBED_STYLE_ID, EMBED_CSS);
|
|
11971
12049
|
const host = resolveContainer(options.container);
|
|
11972
12050
|
host.innerHTML = "";
|
|
@@ -11994,6 +12072,10 @@ class SketchmarkEmbed {
|
|
|
11994
12072
|
<button type="button" class="skm-embed__button" data-action="next">Next</button>
|
|
11995
12073
|
<button type="button" class="skm-embed__button" data-action="play">Play</button>
|
|
11996
12074
|
</div>
|
|
12075
|
+
<div class="skm-embed__controls-group">
|
|
12076
|
+
<button type="button" class="skm-embed__button" data-action="toggle-caption">Caption On</button>
|
|
12077
|
+
<button type="button" class="skm-embed__button" data-action="toggle-tts">TTS Off</button>
|
|
12078
|
+
</div>
|
|
11997
12079
|
<span class="skm-embed__step">No steps</span>
|
|
11998
12080
|
</div>
|
|
11999
12081
|
`;
|
|
@@ -12011,6 +12093,8 @@ class SketchmarkEmbed {
|
|
|
12011
12093
|
this.btnPrev = this.root.querySelector('[data-action="prev"]');
|
|
12012
12094
|
this.btnNext = this.root.querySelector('[data-action="next"]');
|
|
12013
12095
|
this.btnPlay = this.root.querySelector('[data-action="play"]');
|
|
12096
|
+
this.btnCaption = this.root.querySelector('[data-action="toggle-caption"]');
|
|
12097
|
+
this.btnTts = this.root.querySelector('[data-action="toggle-tts"]');
|
|
12014
12098
|
this.controlsElement.classList.toggle("is-hidden", options.showControls === false);
|
|
12015
12099
|
this.btnFit.addEventListener("click", () => this.resetView());
|
|
12016
12100
|
this.btnZoomIn.addEventListener("click", () => this.zoomIn());
|
|
@@ -12021,6 +12105,8 @@ class SketchmarkEmbed {
|
|
|
12021
12105
|
this.btnPlay.addEventListener("click", () => {
|
|
12022
12106
|
void this.play();
|
|
12023
12107
|
});
|
|
12108
|
+
this.btnCaption.addEventListener("click", () => this.setCaptionVisible(!this.showCaption));
|
|
12109
|
+
this.btnTts.addEventListener("click", () => this.setTtsEnabled(!this.getTtsEnabled()));
|
|
12024
12110
|
if (typeof ResizeObserver !== "undefined") {
|
|
12025
12111
|
this.resizeObserver = new ResizeObserver(() => {
|
|
12026
12112
|
this.positionViewport(false);
|
|
@@ -12038,6 +12124,16 @@ class SketchmarkEmbed {
|
|
|
12038
12124
|
if (renderNow)
|
|
12039
12125
|
this.render();
|
|
12040
12126
|
}
|
|
12127
|
+
setCaptionVisible(visible) {
|
|
12128
|
+
this.showCaption = visible;
|
|
12129
|
+
this.applyCaptionVisibility(this.instance);
|
|
12130
|
+
this.syncToggleControls();
|
|
12131
|
+
}
|
|
12132
|
+
setTtsEnabled(enabled) {
|
|
12133
|
+
this.ttsOverride = enabled;
|
|
12134
|
+
this.applyTtsSetting(this.instance);
|
|
12135
|
+
this.syncToggleControls();
|
|
12136
|
+
}
|
|
12041
12137
|
setSize(width, height) {
|
|
12042
12138
|
this.applySize(width, height);
|
|
12043
12139
|
this.positionViewport(false);
|
|
@@ -12082,6 +12178,8 @@ class SketchmarkEmbed {
|
|
|
12082
12178
|
onNodeClick: this.options.onNodeClick,
|
|
12083
12179
|
});
|
|
12084
12180
|
this.instance = instance;
|
|
12181
|
+
this.applyCaptionVisibility(instance);
|
|
12182
|
+
this.applyTtsSetting(instance);
|
|
12085
12183
|
this.animUnsub = instance.anim.on((event) => {
|
|
12086
12184
|
this.syncControls();
|
|
12087
12185
|
if (event.type === "step-change") {
|
|
@@ -12186,6 +12284,7 @@ class SketchmarkEmbed {
|
|
|
12186
12284
|
syncControls() {
|
|
12187
12285
|
this.syncAnimationControls();
|
|
12188
12286
|
this.syncViewControls();
|
|
12287
|
+
this.syncToggleControls();
|
|
12189
12288
|
}
|
|
12190
12289
|
syncAnimationControls() {
|
|
12191
12290
|
const anim = this.instance?.anim;
|
|
@@ -12347,6 +12446,37 @@ class SketchmarkEmbed {
|
|
|
12347
12446
|
this.applyTransform();
|
|
12348
12447
|
this.syncViewControls();
|
|
12349
12448
|
}
|
|
12449
|
+
applyCaptionVisibility(instance) {
|
|
12450
|
+
const caption = instance?.anim.captionElement;
|
|
12451
|
+
if (!caption)
|
|
12452
|
+
return;
|
|
12453
|
+
caption.style.display = this.showCaption ? "" : "none";
|
|
12454
|
+
caption.setAttribute("aria-hidden", this.showCaption ? "false" : "true");
|
|
12455
|
+
}
|
|
12456
|
+
applyTtsSetting(instance) {
|
|
12457
|
+
if (!instance || this.ttsOverride === null)
|
|
12458
|
+
return;
|
|
12459
|
+
instance.anim.tts = this.ttsOverride;
|
|
12460
|
+
}
|
|
12461
|
+
getTtsEnabled() {
|
|
12462
|
+
if (this.ttsOverride !== null)
|
|
12463
|
+
return this.ttsOverride;
|
|
12464
|
+
return !!this.instance?.anim.tts;
|
|
12465
|
+
}
|
|
12466
|
+
syncToggleControls() {
|
|
12467
|
+
const hasView = !!this.instance?.svg;
|
|
12468
|
+
const canToggleTts = hasView &&
|
|
12469
|
+
typeof speechSynthesis !== "undefined";
|
|
12470
|
+
const ttsEnabled = this.getTtsEnabled();
|
|
12471
|
+
this.btnCaption.textContent = this.showCaption ? "Caption On" : "Caption Off";
|
|
12472
|
+
this.btnCaption.classList.toggle("is-active", this.showCaption);
|
|
12473
|
+
this.btnCaption.setAttribute("aria-pressed", this.showCaption ? "true" : "false");
|
|
12474
|
+
this.btnCaption.disabled = !hasView;
|
|
12475
|
+
this.btnTts.textContent = ttsEnabled ? "TTS On" : "TTS Off";
|
|
12476
|
+
this.btnTts.classList.toggle("is-active", ttsEnabled);
|
|
12477
|
+
this.btnTts.setAttribute("aria-pressed", ttsEnabled ? "true" : "false");
|
|
12478
|
+
this.btnTts.disabled = !canToggleTts;
|
|
12479
|
+
}
|
|
12350
12480
|
getTargetBox(target, viewportRect) {
|
|
12351
12481
|
if (target instanceof SVGGraphicsElement) {
|
|
12352
12482
|
try {
|