sketchmark 1.3.4 → 1.3.6
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 +33 -25
- package/dist/animation/index.d.ts +10 -0
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/ast/types.d.ts +6 -0
- package/dist/ast/types.d.ts.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.cjs +238 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +238 -67
- package/dist/index.js.map +1 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/renderer/canvas/index.d.ts.map +1 -1
- package/dist/renderer/shapes/icon.d.ts.map +1 -1
- package/dist/renderer/shapes/image.d.ts.map +1 -1
- package/dist/renderer/shapes/label-strip.d.ts +6 -0
- package/dist/renderer/shapes/label-strip.d.ts.map +1 -0
- package/dist/renderer/shapes/line.d.ts.map +1 -1
- package/dist/renderer/svg/index.d.ts.map +1 -1
- package/dist/scene/index.d.ts +6 -0
- package/dist/scene/index.d.ts.map +1 -1
- package/dist/sketchmark.iife.js +238 -67
- package/dist/ui/canvas.d.ts +1 -0
- package/dist/ui/canvas.d.ts.map +1 -1
- package/dist/ui/embed.d.ts +1 -0
- package/dist/ui/embed.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/sketchmark.iife.js
CHANGED
|
@@ -601,6 +601,12 @@ var AIDiagram = (function (exports) {
|
|
|
601
601
|
id,
|
|
602
602
|
shape,
|
|
603
603
|
label: props.label || "",
|
|
604
|
+
...(props["label-dx"] !== undefined
|
|
605
|
+
? { labelDx: parseFloat(props["label-dx"]) }
|
|
606
|
+
: {}),
|
|
607
|
+
...(props["label-dy"] !== undefined
|
|
608
|
+
? { labelDy: parseFloat(props["label-dy"]) }
|
|
609
|
+
: {}),
|
|
604
610
|
...(props.width ? { width: parseFloat(props.width) } : {}),
|
|
605
611
|
...(props.height ? { height: parseFloat(props.height) } : {}),
|
|
606
612
|
...(props.x ? { x: parseFloat(props.x) } : {}),
|
|
@@ -641,6 +647,12 @@ var AIDiagram = (function (exports) {
|
|
|
641
647
|
id,
|
|
642
648
|
shape: "note",
|
|
643
649
|
label: (props.label ?? "").replace(/\\n/g, "\n"),
|
|
650
|
+
...(props["label-dx"] !== undefined
|
|
651
|
+
? { labelDx: parseFloat(props["label-dx"]) }
|
|
652
|
+
: {}),
|
|
653
|
+
...(props["label-dy"] !== undefined
|
|
654
|
+
? { labelDy: parseFloat(props["label-dy"]) }
|
|
655
|
+
: {}),
|
|
644
656
|
theme: props.theme,
|
|
645
657
|
...(meta ? { meta } : {}),
|
|
646
658
|
style: propsToStyle(props),
|
|
@@ -689,6 +701,8 @@ var AIDiagram = (function (exports) {
|
|
|
689
701
|
kind: "group",
|
|
690
702
|
id,
|
|
691
703
|
label: props.label ?? "",
|
|
704
|
+
labelDx: props["label-dx"] !== undefined ? parseFloat(props["label-dx"]) : undefined,
|
|
705
|
+
labelDy: props["label-dy"] !== undefined ? parseFloat(props["label-dy"]) : undefined,
|
|
692
706
|
children: [],
|
|
693
707
|
layout: props.layout,
|
|
694
708
|
columns: props.columns !== undefined ? parseInt(props.columns, 10) : undefined,
|
|
@@ -733,6 +747,8 @@ var AIDiagram = (function (exports) {
|
|
|
733
747
|
to: toTok.value,
|
|
734
748
|
connector: connector,
|
|
735
749
|
label: props.label,
|
|
750
|
+
labelDx: props["label-dx"] !== undefined ? parseFloat(props["label-dx"]) : undefined,
|
|
751
|
+
labelDy: props["label-dy"] !== undefined ? parseFloat(props["label-dy"]) : undefined,
|
|
736
752
|
fromAnchor: props["anchor-from"],
|
|
737
753
|
toAnchor: props["anchor-to"],
|
|
738
754
|
dashed,
|
|
@@ -1234,6 +1250,7 @@ var AIDiagram = (function (exports) {
|
|
|
1234
1250
|
const NODE = {
|
|
1235
1251
|
minW: 90, // minimum auto-sized node width (px)
|
|
1236
1252
|
maxW: 300, // maximum auto-sized node width (px)
|
|
1253
|
+
mediaLabelH: 20, // reserved bottom strip for icon/image/line labels (px)
|
|
1237
1254
|
basePad: 26, // base padding added to label width (px)
|
|
1238
1255
|
};
|
|
1239
1256
|
// ── Shape-specific sizing ──────────────────────────────────
|
|
@@ -3557,6 +3574,8 @@ var AIDiagram = (function (exports) {
|
|
|
3557
3574
|
id: n.id,
|
|
3558
3575
|
shape: n.shape,
|
|
3559
3576
|
label: n.label,
|
|
3577
|
+
labelDx: n.labelDx,
|
|
3578
|
+
labelDy: n.labelDy,
|
|
3560
3579
|
style: { ...ast.styles[n.id], ...themeStyle, ...n.style },
|
|
3561
3580
|
groupId: nodeParentById.get(n.id),
|
|
3562
3581
|
width: n.width,
|
|
@@ -3582,6 +3601,8 @@ var AIDiagram = (function (exports) {
|
|
|
3582
3601
|
return {
|
|
3583
3602
|
id: g.id,
|
|
3584
3603
|
label: g.label,
|
|
3604
|
+
labelDx: g.labelDx,
|
|
3605
|
+
labelDy: g.labelDy,
|
|
3585
3606
|
parentId: groupParentById.get(g.id),
|
|
3586
3607
|
children: g.children,
|
|
3587
3608
|
layout: (g.layout ?? "column"),
|
|
@@ -3659,6 +3680,8 @@ var AIDiagram = (function (exports) {
|
|
|
3659
3680
|
to: e.to,
|
|
3660
3681
|
connector: e.connector,
|
|
3661
3682
|
label: e.label,
|
|
3683
|
+
labelDx: e.labelDx,
|
|
3684
|
+
labelDy: e.labelDy,
|
|
3662
3685
|
fromAnchor: e.fromAnchor,
|
|
3663
3686
|
toAnchor: e.toAnchor,
|
|
3664
3687
|
dashed: e.dashed ?? false,
|
|
@@ -4000,10 +4023,25 @@ var AIDiagram = (function (exports) {
|
|
|
4000
4023
|
},
|
|
4001
4024
|
};
|
|
4002
4025
|
|
|
4026
|
+
const MEDIA_LABEL_SHAPES = new Set(["icon", "image", "line"]);
|
|
4027
|
+
function usesBottomLabelStrip(shape) {
|
|
4028
|
+
return MEDIA_LABEL_SHAPES.has(shape);
|
|
4029
|
+
}
|
|
4030
|
+
function getBottomLabelStripHeight(node) {
|
|
4031
|
+
return usesBottomLabelStrip(node.shape) && node.label ? NODE.mediaLabelH : 0;
|
|
4032
|
+
}
|
|
4033
|
+
function getBottomLabelContentHeight(node) {
|
|
4034
|
+
return node.h - getBottomLabelStripHeight(node);
|
|
4035
|
+
}
|
|
4036
|
+
function getBottomLabelCenterY(node) {
|
|
4037
|
+
const stripH = getBottomLabelStripHeight(node);
|
|
4038
|
+
return stripH > 0 ? node.y + node.h - stripH / 2 : node.y + node.h / 2;
|
|
4039
|
+
}
|
|
4040
|
+
|
|
4003
4041
|
const iconShape = {
|
|
4004
4042
|
size(n, labelW) {
|
|
4005
4043
|
const iconBase = 48;
|
|
4006
|
-
const labelH = n
|
|
4044
|
+
const labelH = getBottomLabelStripHeight(n);
|
|
4007
4045
|
n.w = n.w || Math.max(iconBase, n.label ? labelW : 0);
|
|
4008
4046
|
n.h = n.h || (iconBase + labelH);
|
|
4009
4047
|
},
|
|
@@ -4016,8 +4054,7 @@ var AIDiagram = (function (exports) {
|
|
|
4016
4054
|
const iconColor = s.color
|
|
4017
4055
|
? encodeURIComponent(String(s.color))
|
|
4018
4056
|
: encodeURIComponent(String(palette.nodeStroke));
|
|
4019
|
-
const
|
|
4020
|
-
const iconAreaH = n.h - labelSpace;
|
|
4057
|
+
const iconAreaH = getBottomLabelContentHeight(n);
|
|
4021
4058
|
const iconSize = Math.min(n.w, iconAreaH) - 4;
|
|
4022
4059
|
const iconUrl = `https://api.iconify.design/${prefix}/${name}.svg?color=${iconColor}&width=${iconSize}&height=${iconSize}`;
|
|
4023
4060
|
const img = document.createElementNS(SVG_NS, "image");
|
|
@@ -4061,8 +4098,7 @@ var AIDiagram = (function (exports) {
|
|
|
4061
4098
|
const iconColor = s.color
|
|
4062
4099
|
? encodeURIComponent(String(s.color))
|
|
4063
4100
|
: encodeURIComponent(String(palette.nodeStroke));
|
|
4064
|
-
const
|
|
4065
|
-
const iconAreaH = n.h - iconLabelSpace;
|
|
4101
|
+
const iconAreaH = getBottomLabelContentHeight(n);
|
|
4066
4102
|
const iconSize = Math.min(n.w, iconAreaH) - 4;
|
|
4067
4103
|
const iconUrl = `https://api.iconify.design/${prefix}/${name}.svg?color=${iconColor}&width=${iconSize}&height=${iconSize}`;
|
|
4068
4104
|
const img = new Image();
|
|
@@ -4105,21 +4141,21 @@ var AIDiagram = (function (exports) {
|
|
|
4105
4141
|
const w = n.w || Math.max(MIN_W, Math.min(MAX_W, labelW));
|
|
4106
4142
|
n.w = w;
|
|
4107
4143
|
if (!n.h) {
|
|
4144
|
+
const labelH = getBottomLabelStripHeight(n);
|
|
4108
4145
|
if (labelW > w) {
|
|
4109
4146
|
const fontSize = Number(n.style?.fontSize ?? 14);
|
|
4110
4147
|
const lines = Math.ceil(labelW / (w - 16));
|
|
4111
|
-
n.h = Math.max(52, lines * fontSize * 1.5 +
|
|
4148
|
+
n.h = Math.max(52, lines * fontSize * 1.5 + labelH);
|
|
4112
4149
|
}
|
|
4113
4150
|
else {
|
|
4114
|
-
n.h = 52;
|
|
4151
|
+
n.h = 52 + labelH;
|
|
4115
4152
|
}
|
|
4116
4153
|
}
|
|
4117
4154
|
},
|
|
4118
4155
|
renderSVG(rc, n, _palette, opts) {
|
|
4119
4156
|
const s = n.style ?? {};
|
|
4120
4157
|
if (n.imageUrl) {
|
|
4121
|
-
const
|
|
4122
|
-
const imgAreaH = n.h - imgLabelSpace;
|
|
4158
|
+
const imgAreaH = getBottomLabelContentHeight(n);
|
|
4123
4159
|
const img = document.createElementNS(SVG_NS, "image");
|
|
4124
4160
|
img.setAttribute("href", n.imageUrl);
|
|
4125
4161
|
img.setAttribute("x", String(n.x + 1));
|
|
@@ -4151,8 +4187,7 @@ var AIDiagram = (function (exports) {
|
|
|
4151
4187
|
renderCanvas(rc, ctx, n, _palette, opts) {
|
|
4152
4188
|
const s = n.style ?? {};
|
|
4153
4189
|
if (n.imageUrl) {
|
|
4154
|
-
const
|
|
4155
|
-
const imgAreaH = n.h - imgLblSpace;
|
|
4190
|
+
const imgAreaH = getBottomLabelContentHeight(n);
|
|
4156
4191
|
const img = new Image();
|
|
4157
4192
|
img.crossOrigin = "anonymous";
|
|
4158
4193
|
img.onload = () => {
|
|
@@ -4329,17 +4364,17 @@ var AIDiagram = (function (exports) {
|
|
|
4329
4364
|
|
|
4330
4365
|
const lineShape = {
|
|
4331
4366
|
size(n, labelW) {
|
|
4332
|
-
const labelH = n
|
|
4367
|
+
const labelH = getBottomLabelStripHeight(n);
|
|
4333
4368
|
n.w = n.width ?? Math.max(MIN_W, labelW + 20);
|
|
4334
4369
|
n.h = n.height ?? (6 + labelH);
|
|
4335
4370
|
},
|
|
4336
4371
|
renderSVG(rc, n, _palette, opts) {
|
|
4337
|
-
const labelH = n
|
|
4372
|
+
const labelH = getBottomLabelStripHeight(n);
|
|
4338
4373
|
const lineY = n.y + (n.h - labelH) / 2;
|
|
4339
4374
|
return [rc.line(n.x, lineY, n.x + n.w, lineY, opts)];
|
|
4340
4375
|
},
|
|
4341
4376
|
renderCanvas(rc, _ctx, n, _palette, opts) {
|
|
4342
|
-
const labelH = n
|
|
4377
|
+
const labelH = getBottomLabelStripHeight(n);
|
|
4343
4378
|
const lineY = n.y + (n.h - labelH) / 2;
|
|
4344
4379
|
rc.line(n.x, lineY, n.x + n.w, lineY, opts);
|
|
4345
4380
|
},
|
|
@@ -5585,18 +5620,18 @@ var AIDiagram = (function (exports) {
|
|
|
5585
5620
|
stroke: bgStroke, strokeWidth: Number(s.strokeWidth ?? 1.2),
|
|
5586
5621
|
...(s.strokeDash ? { strokeLineDash: s.strokeDash } : {}),
|
|
5587
5622
|
}));
|
|
5623
|
+
const { px, py, pw, ph, titleH, cx, cy } = chartLayout(c);
|
|
5588
5624
|
// Title
|
|
5589
5625
|
if (c.label) {
|
|
5590
|
-
cg.appendChild(mkT(c.label, c.x + c.w / 2, c.y +
|
|
5626
|
+
cg.appendChild(mkT(c.label, c.x + c.w / 2, c.y + titleH / 2 + 2, cFontSize, cFontWeight, lc, 'middle', cFont));
|
|
5591
5627
|
}
|
|
5592
|
-
const { px, py, pw, ph, cx, cy } = chartLayout(c);
|
|
5593
5628
|
// ── Pie / Donut ──────────────────────────────────────────
|
|
5594
5629
|
if (c.chartType === 'pie' || c.chartType === 'donut') {
|
|
5595
5630
|
const { segments, total } = parsePie(c.data);
|
|
5596
|
-
const r = Math.min(c.w * 0.38, (c.h -
|
|
5631
|
+
const r = Math.min(c.w * 0.38, (c.h - titleH) * 0.44);
|
|
5597
5632
|
const ir = c.chartType === 'donut' ? r * 0.48 : 0;
|
|
5598
5633
|
const legendX = c.x + 8;
|
|
5599
|
-
const legendY = c.y +
|
|
5634
|
+
const legendY = c.y + titleH + 4;
|
|
5600
5635
|
let angle = -Math.PI / 2;
|
|
5601
5636
|
for (const seg of segments) {
|
|
5602
5637
|
const sweep = (seg.value / total) * Math.PI * 2;
|
|
@@ -5634,7 +5669,7 @@ var AIDiagram = (function (exports) {
|
|
|
5634
5669
|
strokeWidth: 1.2,
|
|
5635
5670
|
}));
|
|
5636
5671
|
});
|
|
5637
|
-
legend(cg, pts.map(p => p.label), CHART_COLORS, c.x + 8, c.y +
|
|
5672
|
+
legend(cg, pts.map(p => p.label), CHART_COLORS, c.x + 8, c.y + titleH + 4, lc, cFont);
|
|
5638
5673
|
return cg;
|
|
5639
5674
|
}
|
|
5640
5675
|
// ── Bar / Line / Area ─────────────────────────────────────
|
|
@@ -8380,9 +8415,10 @@ var AIDiagram = (function (exports) {
|
|
|
8380
8415
|
}));
|
|
8381
8416
|
// ── Group label typography ──────────────────────────
|
|
8382
8417
|
const gTypo = resolveTypography(gs, { fontSize: GROUP_LABEL.fontSize, fontWeight: GROUP_LABEL.fontWeight, textAlign: "left", padding: GROUP_LABEL.padding }, diagramFont, palette.groupLabel);
|
|
8383
|
-
const gTextX = computeTextX(gTypo, g.x, g.w);
|
|
8418
|
+
const gTextX = computeTextX(gTypo, g.x, g.w) + (g.labelDx ?? 0);
|
|
8419
|
+
const gTextY = g.y + gTypo.padding + (g.labelDy ?? 0);
|
|
8384
8420
|
if (g.label) {
|
|
8385
|
-
gg.appendChild(mkText(g.label, gTextX,
|
|
8421
|
+
gg.appendChild(mkText(g.label, gTextX, gTextY, gTypo.fontSize, gTypo.fontWeight, gTypo.textColor, gTypo.textAnchor, gTypo.font, gTypo.letterSpacing));
|
|
8386
8422
|
}
|
|
8387
8423
|
GL.appendChild(gg);
|
|
8388
8424
|
}
|
|
@@ -8434,8 +8470,8 @@ var AIDiagram = (function (exports) {
|
|
|
8434
8470
|
eg.appendChild(startHead);
|
|
8435
8471
|
}
|
|
8436
8472
|
if (e.label) {
|
|
8437
|
-
const mx = (x1 + x2) / 2 - ny * EDGE.labelOffset;
|
|
8438
|
-
const my = (y1 + y2) / 2 + nx * EDGE.labelOffset;
|
|
8473
|
+
const mx = (x1 + x2) / 2 - ny * EDGE.labelOffset + (e.labelDx ?? 0);
|
|
8474
|
+
const my = (y1 + y2) / 2 + nx * EDGE.labelOffset + (e.labelDy ?? 0);
|
|
8439
8475
|
const tw = Math.max(e.label.length * 7 + 12, 36);
|
|
8440
8476
|
const bg = se("rect");
|
|
8441
8477
|
bg.setAttribute("x", String(mx - tw / 2));
|
|
@@ -8503,7 +8539,7 @@ var AIDiagram = (function (exports) {
|
|
|
8503
8539
|
// ── Node / text typography ─────────────────────────
|
|
8504
8540
|
const isText = n.shape === "text";
|
|
8505
8541
|
const isNote = n.shape === "note";
|
|
8506
|
-
const
|
|
8542
|
+
const usesBottomStrip = usesBottomLabelStrip(n.shape);
|
|
8507
8543
|
const typo = resolveTypography(n.style, {
|
|
8508
8544
|
fontSize: isText ? 13 : isNote ? 12 : 14,
|
|
8509
8545
|
fontWeight: isText || isNote ? 400 : 500,
|
|
@@ -8521,20 +8557,22 @@ var AIDiagram = (function (exports) {
|
|
|
8521
8557
|
: n.x + typo.padding)
|
|
8522
8558
|
: computeTextX(typo, n.x, n.w);
|
|
8523
8559
|
const fontStr = buildFontStr(typo.fontSize, typo.fontWeight, typo.font);
|
|
8524
|
-
const shouldWrap = !
|
|
8560
|
+
const shouldWrap = !usesBottomStrip && !n.label.includes('\n');
|
|
8525
8561
|
const innerW = shapeInnerTextWidth(n.shape, n.w, typo.padding);
|
|
8526
8562
|
const lines = shouldWrap
|
|
8527
8563
|
? wrapText(n.label, innerW, typo.fontSize, fontStr)
|
|
8528
8564
|
: n.label.split('\n');
|
|
8529
|
-
const textCY =
|
|
8530
|
-
? n
|
|
8565
|
+
const textCY = usesBottomStrip
|
|
8566
|
+
? getBottomLabelCenterY(n)
|
|
8531
8567
|
: isNote
|
|
8532
8568
|
? computeTextCY(typo, n.y, n.h, lines.length, FOLD + typo.padding)
|
|
8533
8569
|
: computeTextCY(typo, n.y, n.h, lines.length);
|
|
8570
|
+
const labelX = textX + (n.labelDx ?? 0);
|
|
8571
|
+
const labelY = textCY + (n.labelDy ?? 0);
|
|
8534
8572
|
if (n.label) {
|
|
8535
8573
|
ng.appendChild(lines.length > 1
|
|
8536
|
-
? mkMultilineText(lines,
|
|
8537
|
-
: mkText(n.label,
|
|
8574
|
+
? mkMultilineText(lines, labelX, labelY, typo.fontSize, typo.fontWeight, typo.textColor, typo.textAnchor, typo.lineHeight, typo.font, typo.letterSpacing)
|
|
8575
|
+
: mkText(n.label, labelX, labelY, typo.fontSize, typo.fontWeight, typo.textColor, typo.textAnchor, typo.font, typo.letterSpacing));
|
|
8538
8576
|
}
|
|
8539
8577
|
if (options.interactive) {
|
|
8540
8578
|
ng.style.cursor = "pointer";
|
|
@@ -8848,6 +8886,7 @@ var AIDiagram = (function (exports) {
|
|
|
8848
8886
|
strokeWidth: Number(s.strokeWidth ?? 1.2),
|
|
8849
8887
|
...(s.strokeDash ? { strokeLineDash: s.strokeDash } : {}),
|
|
8850
8888
|
});
|
|
8889
|
+
const { px, py, pw, ph, titleH, cx, cy } = chartLayout(c);
|
|
8851
8890
|
// Title
|
|
8852
8891
|
if (c.label) {
|
|
8853
8892
|
ctx.save();
|
|
@@ -8855,17 +8894,16 @@ var AIDiagram = (function (exports) {
|
|
|
8855
8894
|
ctx.fillStyle = lc;
|
|
8856
8895
|
ctx.textAlign = 'center';
|
|
8857
8896
|
ctx.textBaseline = 'middle';
|
|
8858
|
-
ctx.fillText(c.label, c.x + c.w / 2, c.y +
|
|
8897
|
+
ctx.fillText(c.label, c.x + c.w / 2, c.y + titleH / 2 + 2);
|
|
8859
8898
|
ctx.restore();
|
|
8860
8899
|
}
|
|
8861
|
-
const { px, py, pw, ph, cx, cy } = chartLayout(c);
|
|
8862
8900
|
// ── Pie / Donut ──────────────────────────────────────────
|
|
8863
8901
|
if (c.chartType === 'pie' || c.chartType === 'donut') {
|
|
8864
8902
|
const { segments, total } = parsePie(c.data);
|
|
8865
|
-
const r = Math.min(c.w * 0.38, (c.h -
|
|
8903
|
+
const r = Math.min(c.w * 0.38, (c.h - titleH) * 0.44);
|
|
8866
8904
|
const ir = c.chartType === 'donut' ? r * 0.48 : 0;
|
|
8867
8905
|
const legendX = c.x + 8;
|
|
8868
|
-
const legendY = c.y +
|
|
8906
|
+
const legendY = c.y + titleH + 4;
|
|
8869
8907
|
let angle = -Math.PI / 2;
|
|
8870
8908
|
segments.forEach((seg, i) => {
|
|
8871
8909
|
const sweep = (seg.value / total) * Math.PI * 2;
|
|
@@ -8893,7 +8931,7 @@ var AIDiagram = (function (exports) {
|
|
|
8893
8931
|
strokeWidth: 1.2,
|
|
8894
8932
|
});
|
|
8895
8933
|
});
|
|
8896
|
-
drawLegend(ctx, pts.map(p => p.label), CHART_COLORS, c.x + 8, c.y +
|
|
8934
|
+
drawLegend(ctx, pts.map(p => p.label), CHART_COLORS, c.x + 8, c.y + titleH + 4, lc, cFont);
|
|
8897
8935
|
ctx.globalAlpha = 1;
|
|
8898
8936
|
return;
|
|
8899
8937
|
}
|
|
@@ -9128,8 +9166,9 @@ var AIDiagram = (function (exports) {
|
|
|
9128
9166
|
});
|
|
9129
9167
|
if (g.label) {
|
|
9130
9168
|
const gTypo = resolveTypography(gs, { fontSize: GROUP_LABEL.fontSize, fontWeight: GROUP_LABEL.fontWeight, textAlign: "left", padding: GROUP_LABEL.padding }, diagramFont, palette.groupLabel);
|
|
9131
|
-
const gTextX = computeTextX(gTypo, g.x, g.w);
|
|
9132
|
-
|
|
9169
|
+
const gTextX = computeTextX(gTypo, g.x, g.w) + (g.labelDx ?? 0);
|
|
9170
|
+
const gTextY = g.y + gTypo.padding + 2 + (g.labelDy ?? 0);
|
|
9171
|
+
drawText(ctx, g.label, gTextX, gTextY, gTypo.fontSize, gTypo.fontWeight, gTypo.textColor, gTypo.textAlign, gTypo.font, gTypo.letterSpacing);
|
|
9133
9172
|
}
|
|
9134
9173
|
if (gs.opacity != null)
|
|
9135
9174
|
ctx.globalAlpha = 1;
|
|
@@ -9167,8 +9206,8 @@ var AIDiagram = (function (exports) {
|
|
|
9167
9206
|
if (arrowAt === 'start' || arrowAt === 'both')
|
|
9168
9207
|
drawArrowHead(rc, x1, y1, Math.atan2(y1 - y2, x1 - x2), ecol, hashStr$3(e.from + 'back'));
|
|
9169
9208
|
if (e.label) {
|
|
9170
|
-
const mx = (x1 + x2) / 2 - ny * EDGE.labelOffset;
|
|
9171
|
-
const my = (y1 + y2) / 2 + nx * EDGE.labelOffset;
|
|
9209
|
+
const mx = (x1 + x2) / 2 - ny * EDGE.labelOffset + (e.labelDx ?? 0);
|
|
9210
|
+
const my = (y1 + y2) / 2 + nx * EDGE.labelOffset + (e.labelDy ?? 0);
|
|
9172
9211
|
// ── Edge label: font, font-size, letter-spacing ──
|
|
9173
9212
|
// always center-anchored (single line)
|
|
9174
9213
|
const eFontSize = Number(e.style?.fontSize ?? EDGE.labelFontSize);
|
|
@@ -9208,7 +9247,7 @@ var AIDiagram = (function (exports) {
|
|
|
9208
9247
|
// ── Node / text typography ─────────────────────────
|
|
9209
9248
|
const isText = n.shape === 'text';
|
|
9210
9249
|
const isNote = n.shape === 'note';
|
|
9211
|
-
const
|
|
9250
|
+
const usesBottomStrip = usesBottomLabelStrip(n.shape);
|
|
9212
9251
|
const typo = resolveTypography(n.style, {
|
|
9213
9252
|
fontSize: isText ? 13 : isNote ? 12 : 14,
|
|
9214
9253
|
fontWeight: isText || isNote ? 400 : 500,
|
|
@@ -9226,23 +9265,25 @@ var AIDiagram = (function (exports) {
|
|
|
9226
9265
|
: n.x + typo.padding)
|
|
9227
9266
|
: computeTextX(typo, n.x, n.w);
|
|
9228
9267
|
const fontStr = buildFontStr(typo.fontSize, typo.fontWeight, typo.font);
|
|
9229
|
-
const shouldWrap = !
|
|
9268
|
+
const shouldWrap = !usesBottomStrip && !n.label.includes('\n');
|
|
9230
9269
|
const innerW = shapeInnerTextWidth(n.shape, n.w, typo.padding);
|
|
9231
9270
|
const rawLines = n.label.split('\n');
|
|
9232
9271
|
const lines = shouldWrap && rawLines.length === 1
|
|
9233
9272
|
? wrapText(n.label, innerW, typo.fontSize, fontStr)
|
|
9234
9273
|
: rawLines;
|
|
9235
|
-
const textCY =
|
|
9236
|
-
? n
|
|
9274
|
+
const textCY = usesBottomStrip
|
|
9275
|
+
? getBottomLabelCenterY(n)
|
|
9237
9276
|
: isNote
|
|
9238
9277
|
? computeTextCY(typo, n.y, n.h, lines.length, FOLD + typo.padding)
|
|
9239
9278
|
: computeTextCY(typo, n.y, n.h, lines.length);
|
|
9279
|
+
const labelX = textX + (n.labelDx ?? 0);
|
|
9280
|
+
const labelY = textCY + (n.labelDy ?? 0);
|
|
9240
9281
|
if (n.label) {
|
|
9241
9282
|
if (lines.length > 1) {
|
|
9242
|
-
drawMultilineText(ctx, lines,
|
|
9283
|
+
drawMultilineText(ctx, lines, labelX, labelY, typo.fontSize, typo.fontWeight, typo.textColor, typo.textAlign, typo.lineHeight, typo.font, typo.letterSpacing);
|
|
9243
9284
|
}
|
|
9244
9285
|
else {
|
|
9245
|
-
drawText(ctx, lines[0] ?? '',
|
|
9286
|
+
drawText(ctx, lines[0] ?? '', labelX, labelY, typo.fontSize, typo.fontWeight, typo.textColor, typo.textAlign, typo.font, typo.letterSpacing);
|
|
9246
9287
|
}
|
|
9247
9288
|
}
|
|
9248
9289
|
if (hasTx)
|
|
@@ -9580,7 +9621,7 @@ var AIDiagram = (function (exports) {
|
|
|
9580
9621
|
[x + 1, y + h - 1],
|
|
9581
9622
|
]);
|
|
9582
9623
|
case "line": {
|
|
9583
|
-
const labelH = el.querySelector("text") ?
|
|
9624
|
+
const labelH = el.querySelector("text") ? NODE.mediaLabelH : 0;
|
|
9584
9625
|
const lineY = y + (h - labelH) / 2;
|
|
9585
9626
|
return `M ${x} ${lineY} L ${x + w} ${lineY}`;
|
|
9586
9627
|
}
|
|
@@ -9951,8 +9992,12 @@ var AIDiagram = (function (exports) {
|
|
|
9951
9992
|
this._rc = _rc;
|
|
9952
9993
|
this._config = _config;
|
|
9953
9994
|
this._step = -1;
|
|
9995
|
+
this._isPlaying = false;
|
|
9996
|
+
this._playRunId = 0;
|
|
9954
9997
|
this._pendingStepTimers = new Set();
|
|
9955
9998
|
this._pendingNarrationTimers = new Set();
|
|
9999
|
+
this._playbackDelayTimerId = null;
|
|
10000
|
+
this._resolvePlaybackDelay = null;
|
|
9956
10001
|
this._transforms = new Map();
|
|
9957
10002
|
this._listeners = [];
|
|
9958
10003
|
// ── Narration caption ──
|
|
@@ -9968,6 +10013,7 @@ var AIDiagram = (function (exports) {
|
|
|
9968
10013
|
// ── TTS ──
|
|
9969
10014
|
this._tts = false;
|
|
9970
10015
|
this._speechDone = null;
|
|
10016
|
+
this._resolveSpeechDone = null;
|
|
9971
10017
|
this.drawTargetEdges = getDrawTargetEdgeIds(steps);
|
|
9972
10018
|
this.drawTargetNodes = getDrawTargetNodeIds(steps);
|
|
9973
10019
|
// Groups: non-edge draw steps whose target has a #group-{id} element in the SVG.
|
|
@@ -10191,6 +10237,9 @@ var AIDiagram = (function (exports) {
|
|
|
10191
10237
|
get atEnd() {
|
|
10192
10238
|
return this._step === this.steps.length - 1;
|
|
10193
10239
|
}
|
|
10240
|
+
get isPlaying() {
|
|
10241
|
+
return this._isPlaying;
|
|
10242
|
+
}
|
|
10194
10243
|
on(listener) {
|
|
10195
10244
|
this._listeners.push(listener);
|
|
10196
10245
|
return () => {
|
|
@@ -10208,12 +10257,14 @@ var AIDiagram = (function (exports) {
|
|
|
10208
10257
|
l(e);
|
|
10209
10258
|
}
|
|
10210
10259
|
reset() {
|
|
10260
|
+
this.stop();
|
|
10211
10261
|
this._step = -1;
|
|
10212
10262
|
this._clearAll();
|
|
10213
10263
|
this.emit("animation-reset");
|
|
10214
10264
|
}
|
|
10215
10265
|
/** Remove caption and annotation layer from the DOM */
|
|
10216
10266
|
destroy() {
|
|
10267
|
+
this.stop();
|
|
10217
10268
|
this._clearAll();
|
|
10218
10269
|
this._captionEl?.remove();
|
|
10219
10270
|
this._captionEl = null;
|
|
@@ -10224,16 +10275,11 @@ var AIDiagram = (function (exports) {
|
|
|
10224
10275
|
this._pointerEl = null;
|
|
10225
10276
|
}
|
|
10226
10277
|
next() {
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
this._step++;
|
|
10230
|
-
this._applyStep(this._step, false);
|
|
10231
|
-
this.emit("step-change");
|
|
10232
|
-
if (!this.canNext)
|
|
10233
|
-
this.emit("animation-end");
|
|
10234
|
-
return true;
|
|
10278
|
+
this.stop();
|
|
10279
|
+
return this._advanceNext();
|
|
10235
10280
|
}
|
|
10236
10281
|
prev() {
|
|
10282
|
+
this.stop();
|
|
10237
10283
|
if (!this.canPrev)
|
|
10238
10284
|
return false;
|
|
10239
10285
|
this._step--;
|
|
@@ -10244,18 +10290,33 @@ var AIDiagram = (function (exports) {
|
|
|
10244
10290
|
return true;
|
|
10245
10291
|
}
|
|
10246
10292
|
async play(msPerStep = 900) {
|
|
10293
|
+
if (this._isPlaying || !this.canNext)
|
|
10294
|
+
return;
|
|
10295
|
+
const runId = ++this._playRunId;
|
|
10296
|
+
this._isPlaying = true;
|
|
10247
10297
|
this.emit("animation-start");
|
|
10248
|
-
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
10298
|
+
try {
|
|
10299
|
+
while (this.canNext && this._playRunId === runId) {
|
|
10300
|
+
const nextStep = this.steps[this._step + 1];
|
|
10301
|
+
if (!this._advanceNext())
|
|
10302
|
+
break;
|
|
10303
|
+
if (this._playRunId !== runId)
|
|
10304
|
+
break;
|
|
10305
|
+
await Promise.all([
|
|
10306
|
+
this._waitForPlaybackDelay(this._playbackWaitMs(nextStep, msPerStep)),
|
|
10307
|
+
this._speechDone ?? Promise.resolve(),
|
|
10308
|
+
]);
|
|
10309
|
+
}
|
|
10310
|
+
}
|
|
10311
|
+
finally {
|
|
10312
|
+
if (this._playRunId === runId) {
|
|
10313
|
+
this._isPlaying = false;
|
|
10314
|
+
this._cancelPlaybackDelay();
|
|
10315
|
+
}
|
|
10256
10316
|
}
|
|
10257
10317
|
}
|
|
10258
10318
|
goTo(index) {
|
|
10319
|
+
this.stop();
|
|
10259
10320
|
index = Math.max(-1, Math.min(this.steps.length - 1, index));
|
|
10260
10321
|
if (index === this._step)
|
|
10261
10322
|
return;
|
|
@@ -10269,6 +10330,30 @@ var AIDiagram = (function (exports) {
|
|
|
10269
10330
|
}
|
|
10270
10331
|
this.emit("step-change");
|
|
10271
10332
|
}
|
|
10333
|
+
stop() {
|
|
10334
|
+
if (!this._isPlaying && !this._resolvePlaybackDelay) {
|
|
10335
|
+
this._clearPendingStepTimers();
|
|
10336
|
+
this._cancelNarrationTyping();
|
|
10337
|
+
this._cancelSpeech();
|
|
10338
|
+
return;
|
|
10339
|
+
}
|
|
10340
|
+
this._isPlaying = false;
|
|
10341
|
+
this._playRunId += 1;
|
|
10342
|
+
this._cancelPlaybackDelay();
|
|
10343
|
+
this._clearPendingStepTimers();
|
|
10344
|
+
this._cancelNarrationTyping();
|
|
10345
|
+
this._cancelSpeech();
|
|
10346
|
+
}
|
|
10347
|
+
_advanceNext() {
|
|
10348
|
+
if (!this.canNext)
|
|
10349
|
+
return false;
|
|
10350
|
+
this._step++;
|
|
10351
|
+
this._applyStep(this._step, false);
|
|
10352
|
+
this.emit("step-change");
|
|
10353
|
+
if (!this.canNext)
|
|
10354
|
+
this.emit("animation-end");
|
|
10355
|
+
return true;
|
|
10356
|
+
}
|
|
10272
10357
|
_clearTimerBucket(bucket) {
|
|
10273
10358
|
bucket.forEach((id) => window.clearTimeout(id));
|
|
10274
10359
|
bucket.clear();
|
|
@@ -10294,6 +10379,34 @@ var AIDiagram = (function (exports) {
|
|
|
10294
10379
|
_scheduleStep(fn, delayMs) {
|
|
10295
10380
|
this._scheduleTimer(fn, delayMs, this._pendingStepTimers);
|
|
10296
10381
|
}
|
|
10382
|
+
_waitForPlaybackDelay(delayMs) {
|
|
10383
|
+
this._cancelPlaybackDelay();
|
|
10384
|
+
return new Promise((resolve) => {
|
|
10385
|
+
let settled = false;
|
|
10386
|
+
const finish = () => {
|
|
10387
|
+
if (settled)
|
|
10388
|
+
return;
|
|
10389
|
+
settled = true;
|
|
10390
|
+
if (this._playbackDelayTimerId !== null) {
|
|
10391
|
+
window.clearTimeout(this._playbackDelayTimerId);
|
|
10392
|
+
this._playbackDelayTimerId = null;
|
|
10393
|
+
}
|
|
10394
|
+
if (this._resolvePlaybackDelay === finish) {
|
|
10395
|
+
this._resolvePlaybackDelay = null;
|
|
10396
|
+
}
|
|
10397
|
+
resolve();
|
|
10398
|
+
};
|
|
10399
|
+
this._resolvePlaybackDelay = finish;
|
|
10400
|
+
if (delayMs <= 0) {
|
|
10401
|
+
finish();
|
|
10402
|
+
return;
|
|
10403
|
+
}
|
|
10404
|
+
this._playbackDelayTimerId = window.setTimeout(finish, delayMs);
|
|
10405
|
+
});
|
|
10406
|
+
}
|
|
10407
|
+
_cancelPlaybackDelay() {
|
|
10408
|
+
this._resolvePlaybackDelay?.();
|
|
10409
|
+
}
|
|
10297
10410
|
_stepWaitMs(step, fallbackMs) {
|
|
10298
10411
|
const delay = Math.max(0, step.delay ?? 0);
|
|
10299
10412
|
const duration = Math.max(0, step.duration ?? 0);
|
|
@@ -10335,6 +10448,7 @@ var AIDiagram = (function (exports) {
|
|
|
10335
10448
|
return this._stepWaitMs(step, fallbackMs);
|
|
10336
10449
|
}
|
|
10337
10450
|
_clearAll() {
|
|
10451
|
+
this._cancelPlaybackDelay();
|
|
10338
10452
|
this._clearPendingStepTimers();
|
|
10339
10453
|
this._cancelNarrationTyping();
|
|
10340
10454
|
this._cancelSpeech();
|
|
@@ -10946,16 +11060,30 @@ var AIDiagram = (function (exports) {
|
|
|
10946
11060
|
utter.rate = 0.95;
|
|
10947
11061
|
utter.pitch = 1;
|
|
10948
11062
|
utter.lang = "en-US";
|
|
10949
|
-
// Track when speech actually finishes
|
|
11063
|
+
// Track when speech actually finishes so play() can block until the utterance ends.
|
|
10950
11064
|
this._speechDone = new Promise((resolve) => {
|
|
10951
|
-
|
|
10952
|
-
|
|
11065
|
+
let settled = false;
|
|
11066
|
+
const finish = () => {
|
|
11067
|
+
if (settled)
|
|
11068
|
+
return;
|
|
11069
|
+
settled = true;
|
|
11070
|
+
if (this._resolveSpeechDone === finish) {
|
|
11071
|
+
this._resolveSpeechDone = null;
|
|
11072
|
+
this._speechDone = null;
|
|
11073
|
+
}
|
|
11074
|
+
resolve();
|
|
11075
|
+
};
|
|
11076
|
+
this._resolveSpeechDone = finish;
|
|
11077
|
+
utter.onend = finish;
|
|
11078
|
+
utter.onerror = finish;
|
|
10953
11079
|
});
|
|
10954
11080
|
speechSynthesis.speak(utter);
|
|
10955
11081
|
}
|
|
10956
11082
|
_cancelSpeech() {
|
|
10957
11083
|
if (typeof speechSynthesis !== "undefined")
|
|
10958
11084
|
speechSynthesis.cancel();
|
|
11085
|
+
this._resolveSpeechDone?.();
|
|
11086
|
+
this._resolveSpeechDone = null;
|
|
10959
11087
|
this._speechDone = null;
|
|
10960
11088
|
}
|
|
10961
11089
|
/** Pre-warm the speech engine with a silent utterance to eliminate cold-start delay */
|
|
@@ -11764,7 +11892,13 @@ var AIDiagram = (function (exports) {
|
|
|
11764
11892
|
this.resetButton.addEventListener("click", () => this.resetAnimation());
|
|
11765
11893
|
this.prevButton.addEventListener("click", () => this.prevStep());
|
|
11766
11894
|
this.nextButton.addEventListener("click", () => this.nextStep());
|
|
11767
|
-
this.playButton.addEventListener("click", () =>
|
|
11895
|
+
this.playButton.addEventListener("click", () => {
|
|
11896
|
+
if (this.playInFlight) {
|
|
11897
|
+
this.stopPlayback();
|
|
11898
|
+
return;
|
|
11899
|
+
}
|
|
11900
|
+
void this.play();
|
|
11901
|
+
});
|
|
11768
11902
|
this.captionButton.addEventListener("click", () => this.setCaptionVisible(!this.showCaption));
|
|
11769
11903
|
this.ttsButton.addEventListener("click", () => this.setTtsEnabled(!this.getTtsEnabled()));
|
|
11770
11904
|
this.viewport.addEventListener("pointerdown", this.onPointerDown);
|
|
@@ -11828,6 +11962,7 @@ var AIDiagram = (function (exports) {
|
|
|
11828
11962
|
this.dsl = normalizeNewlines(nextDsl);
|
|
11829
11963
|
this.clearError();
|
|
11830
11964
|
this.mirroredEditor?.clearError();
|
|
11965
|
+
this.playInFlight = false;
|
|
11831
11966
|
this.animUnsub?.();
|
|
11832
11967
|
this.animUnsub = null;
|
|
11833
11968
|
this.instance?.anim?.destroy();
|
|
@@ -11898,9 +12033,16 @@ var AIDiagram = (function (exports) {
|
|
|
11898
12033
|
this.syncAnimationUi();
|
|
11899
12034
|
}
|
|
11900
12035
|
}
|
|
12036
|
+
stopPlayback() {
|
|
12037
|
+
this.playInFlight = false;
|
|
12038
|
+
if (this.renderer === "svg")
|
|
12039
|
+
this.instance?.anim.stop();
|
|
12040
|
+
this.syncAnimationUi();
|
|
12041
|
+
}
|
|
11901
12042
|
nextStep() {
|
|
11902
12043
|
if (!this.instance || this.renderer !== "svg")
|
|
11903
12044
|
return;
|
|
12045
|
+
this.playInFlight = false;
|
|
11904
12046
|
this.instance.anim.next();
|
|
11905
12047
|
this.syncAnimationUi();
|
|
11906
12048
|
this.focusCurrentStep();
|
|
@@ -11908,6 +12050,7 @@ var AIDiagram = (function (exports) {
|
|
|
11908
12050
|
prevStep() {
|
|
11909
12051
|
if (!this.instance || this.renderer !== "svg")
|
|
11910
12052
|
return;
|
|
12053
|
+
this.playInFlight = false;
|
|
11911
12054
|
this.instance.anim.prev();
|
|
11912
12055
|
this.syncAnimationUi();
|
|
11913
12056
|
this.focusCurrentStep();
|
|
@@ -11915,6 +12058,7 @@ var AIDiagram = (function (exports) {
|
|
|
11915
12058
|
resetAnimation() {
|
|
11916
12059
|
if (!this.instance || this.renderer !== "svg")
|
|
11917
12060
|
return;
|
|
12061
|
+
this.playInFlight = false;
|
|
11918
12062
|
this.instance.anim.reset();
|
|
11919
12063
|
this.syncAnimationUi();
|
|
11920
12064
|
}
|
|
@@ -11943,6 +12087,7 @@ var AIDiagram = (function (exports) {
|
|
|
11943
12087
|
this.render();
|
|
11944
12088
|
}
|
|
11945
12089
|
destroy() {
|
|
12090
|
+
this.playInFlight = false;
|
|
11946
12091
|
this.editorCleanup?.();
|
|
11947
12092
|
this.animUnsub?.();
|
|
11948
12093
|
this.instance?.anim?.destroy();
|
|
@@ -12017,6 +12162,9 @@ var AIDiagram = (function (exports) {
|
|
|
12017
12162
|
this.prevButton.disabled = true;
|
|
12018
12163
|
this.nextButton.disabled = true;
|
|
12019
12164
|
this.resetButton.disabled = true;
|
|
12165
|
+
this.playButton.textContent = "Play";
|
|
12166
|
+
this.playButton.classList.remove("is-active");
|
|
12167
|
+
this.playButton.setAttribute("aria-pressed", "false");
|
|
12020
12168
|
this.playButton.disabled = true;
|
|
12021
12169
|
this.syncToggleUi();
|
|
12022
12170
|
return;
|
|
@@ -12026,7 +12174,10 @@ var AIDiagram = (function (exports) {
|
|
|
12026
12174
|
this.prevButton.disabled = !anim.canPrev;
|
|
12027
12175
|
this.nextButton.disabled = !anim.canNext;
|
|
12028
12176
|
this.resetButton.disabled = false;
|
|
12029
|
-
this.playButton.
|
|
12177
|
+
this.playButton.textContent = this.playInFlight ? "Stop" : "Play";
|
|
12178
|
+
this.playButton.classList.toggle("is-active", this.playInFlight);
|
|
12179
|
+
this.playButton.setAttribute("aria-pressed", this.playInFlight ? "true" : "false");
|
|
12180
|
+
this.playButton.disabled = this.playInFlight ? false : !anim.canNext;
|
|
12030
12181
|
this.syncToggleUi();
|
|
12031
12182
|
}
|
|
12032
12183
|
getStepTarget(stepItem) {
|
|
@@ -12932,6 +13083,10 @@ var AIDiagram = (function (exports) {
|
|
|
12932
13083
|
this.btnPrev.addEventListener("click", () => this.prevStep());
|
|
12933
13084
|
this.btnNext.addEventListener("click", () => this.nextStep());
|
|
12934
13085
|
this.btnPlay.addEventListener("click", () => {
|
|
13086
|
+
if (this.playInFlight) {
|
|
13087
|
+
this.stopPlayback();
|
|
13088
|
+
return;
|
|
13089
|
+
}
|
|
12935
13090
|
void this.play();
|
|
12936
13091
|
});
|
|
12937
13092
|
this.btnCaption.addEventListener("click", () => this.setCaptionVisible(!this.showCaption));
|
|
@@ -12989,6 +13144,7 @@ var AIDiagram = (function (exports) {
|
|
|
12989
13144
|
}
|
|
12990
13145
|
this.clearError();
|
|
12991
13146
|
this.stopMotion();
|
|
13147
|
+
this.playInFlight = false;
|
|
12992
13148
|
this.animUnsub?.();
|
|
12993
13149
|
this.animUnsub = null;
|
|
12994
13150
|
this.instance?.anim?.destroy();
|
|
@@ -13061,9 +13217,15 @@ var AIDiagram = (function (exports) {
|
|
|
13061
13217
|
this.syncControls();
|
|
13062
13218
|
}
|
|
13063
13219
|
}
|
|
13220
|
+
stopPlayback() {
|
|
13221
|
+
this.playInFlight = false;
|
|
13222
|
+
this.instance?.anim.stop();
|
|
13223
|
+
this.syncControls();
|
|
13224
|
+
}
|
|
13064
13225
|
nextStep() {
|
|
13065
13226
|
if (!this.instance)
|
|
13066
13227
|
return;
|
|
13228
|
+
this.playInFlight = false;
|
|
13067
13229
|
this.instance.anim.next();
|
|
13068
13230
|
this.syncControls();
|
|
13069
13231
|
if (this.options.autoFocus !== false && this.options.autoFocusOnStep !== false) {
|
|
@@ -13073,6 +13235,7 @@ var AIDiagram = (function (exports) {
|
|
|
13073
13235
|
prevStep() {
|
|
13074
13236
|
if (!this.instance)
|
|
13075
13237
|
return;
|
|
13238
|
+
this.playInFlight = false;
|
|
13076
13239
|
this.instance.anim.prev();
|
|
13077
13240
|
this.syncControls();
|
|
13078
13241
|
if (this.options.autoFocus !== false && this.options.autoFocusOnStep !== false) {
|
|
@@ -13082,6 +13245,7 @@ var AIDiagram = (function (exports) {
|
|
|
13082
13245
|
resetAnimation() {
|
|
13083
13246
|
if (!this.instance)
|
|
13084
13247
|
return;
|
|
13248
|
+
this.playInFlight = false;
|
|
13085
13249
|
this.instance.anim.reset();
|
|
13086
13250
|
this.syncControls();
|
|
13087
13251
|
}
|
|
@@ -13108,6 +13272,7 @@ var AIDiagram = (function (exports) {
|
|
|
13108
13272
|
}
|
|
13109
13273
|
destroy() {
|
|
13110
13274
|
this.stopMotion();
|
|
13275
|
+
this.playInFlight = false;
|
|
13111
13276
|
this.animUnsub?.();
|
|
13112
13277
|
this.instance?.anim?.destroy();
|
|
13113
13278
|
this.instance = null;
|
|
@@ -13140,6 +13305,9 @@ var AIDiagram = (function (exports) {
|
|
|
13140
13305
|
this.btnRestart.disabled = true;
|
|
13141
13306
|
this.btnPrev.disabled = true;
|
|
13142
13307
|
this.btnNext.disabled = true;
|
|
13308
|
+
this.btnPlay.textContent = "Play";
|
|
13309
|
+
this.btnPlay.classList.remove("is-active");
|
|
13310
|
+
this.btnPlay.setAttribute("aria-pressed", "false");
|
|
13143
13311
|
this.btnPlay.disabled = true;
|
|
13144
13312
|
return;
|
|
13145
13313
|
}
|
|
@@ -13148,7 +13316,10 @@ var AIDiagram = (function (exports) {
|
|
|
13148
13316
|
this.btnRestart.disabled = false;
|
|
13149
13317
|
this.btnPrev.disabled = !anim.canPrev;
|
|
13150
13318
|
this.btnNext.disabled = !anim.canNext;
|
|
13151
|
-
this.btnPlay.
|
|
13319
|
+
this.btnPlay.textContent = this.playInFlight ? "Stop" : "Play";
|
|
13320
|
+
this.btnPlay.classList.toggle("is-active", this.playInFlight);
|
|
13321
|
+
this.btnPlay.setAttribute("aria-pressed", this.playInFlight ? "true" : "false");
|
|
13322
|
+
this.btnPlay.disabled = this.playInFlight ? false : !anim.canNext;
|
|
13152
13323
|
}
|
|
13153
13324
|
syncViewControls() {
|
|
13154
13325
|
const hasView = !!this.instance?.svg;
|