waygraph 0.12.22 → 0.12.23
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/cli.js +203 -22
- package/dist/highlights.d.ts +35 -1
- package/dist/highlights.js +42 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -224,6 +224,7 @@ import {
|
|
|
224
224
|
demoPaceIsSlow,
|
|
225
225
|
formatDemoPaceBadge,
|
|
226
226
|
formatDemoPaceLabel,
|
|
227
|
+
normalizeTodos,
|
|
227
228
|
} from "waygraph";
|
|
228
229
|
|
|
229
230
|
function walkDir(dir, pattern) {
|
|
@@ -507,6 +508,14 @@ const RING_CSS =
|
|
|
507
508
|
"#wg-panel .wg-pace[data-pace-kind=blitz] .wg-pace-badge{background:#22C55E;color:#052e16;}" +
|
|
508
509
|
"#wg-panel .wg-pace[data-pace-kind=ms] .wg-pace-badge{background:#3B82F6;color:#fff;}" +
|
|
509
510
|
"#wg-panel .wg-narration{margin:0 0 12px;font:italic 14px/1.4 system-ui,sans-serif;color:#f0e8ff;}" +
|
|
511
|
+
"#wg-todos{list-style:none;margin:0 0 12px;padding:8px 10px;background:#0f0620;border-radius:8px;" +
|
|
512
|
+
"border:1px solid #3a2a60;}" +
|
|
513
|
+
"#wg-todos li{display:flex;gap:8px;align-items:flex-start;margin:0 0 6px;font:600 12.5px/1.35 system-ui,sans-serif;}" +
|
|
514
|
+
"#wg-todos li:last-child{margin-bottom:0;}" +
|
|
515
|
+
"#wg-todos .wg-todo-mark{flex:0 0 auto;width:1.1em;text-align:center;}" +
|
|
516
|
+
"#wg-todos .wg-todo-done{color:#6ee7b7;text-decoration:line-through;opacity:.85;}" +
|
|
517
|
+
"#wg-todos .wg-todo-current{color:#fff;}" +
|
|
518
|
+
"#wg-todos .wg-todo-pending{color:#9a7ad1;}" +
|
|
510
519
|
"#wg-progress{height:4px;background:#2a1650;border-radius:2px;margin:0 0 12px;overflow:hidden;}" +
|
|
511
520
|
"#wg-progress-bar{height:100%;background:#7C3AED;border-radius:2px;transition:width .3s ease;}" +
|
|
512
521
|
// A real tab bar for episodes - the currently-active episode reads as
|
|
@@ -767,6 +776,31 @@ async function installOverlay(page, title) {
|
|
|
767
776
|
const ringLabel = document.getElementById("wg-ring-label");
|
|
768
777
|
if (ring) ring.style.opacity = "0";
|
|
769
778
|
if (ringLabel) ringLabel.style.opacity = "0";
|
|
779
|
+
if (window.__wgClearZoom) window.__wgClearZoom();
|
|
780
|
+
};
|
|
781
|
+
window.__wgClearZoom = () => {
|
|
782
|
+
document.querySelectorAll("[data-wg-zoomed=\\"1\\"]").forEach((el) => {
|
|
783
|
+
el.style.removeProperty("transform");
|
|
784
|
+
el.style.removeProperty("transform-origin");
|
|
785
|
+
el.style.removeProperty("transition");
|
|
786
|
+
el.style.removeProperty("z-index");
|
|
787
|
+
el.style.removeProperty("position");
|
|
788
|
+
delete el.dataset.wgZoomed;
|
|
789
|
+
});
|
|
790
|
+
};
|
|
791
|
+
window.__wgApplyZoom = (sel, scale) => {
|
|
792
|
+
if (window.__wgClearZoom) window.__wgClearZoom();
|
|
793
|
+
const n = Number(scale);
|
|
794
|
+
if (!Number.isFinite(n) || n <= 1.001) return;
|
|
795
|
+
const el = document.querySelector(sel);
|
|
796
|
+
if (!el) return;
|
|
797
|
+
const st = getComputedStyle(el);
|
|
798
|
+
if (st.position === "static") el.style.position = "relative";
|
|
799
|
+
el.style.zIndex = "2147483645";
|
|
800
|
+
el.style.transition = "transform .35s ease";
|
|
801
|
+
el.style.transformOrigin = "center center";
|
|
802
|
+
el.style.transform = "scale(" + n + ")";
|
|
803
|
+
el.dataset.wgZoomed = "1";
|
|
770
804
|
};
|
|
771
805
|
const POSITIONS = ["left", "center", "right"];
|
|
772
806
|
const applyPos = (el, pos) => {
|
|
@@ -988,7 +1022,8 @@ async function renderBeforeStep(page, info) {
|
|
|
988
1022
|
paceHtml +
|
|
989
1023
|
"<div id=\\"wg-modules\\" class=\\"" + modulesClass + "\\">" + modulesHtml + "</div>" +
|
|
990
1024
|
"<h3>Step " + (info.index + 1) + " / " + info.total + " - " + info.blockName + "</h3>" +
|
|
991
|
-
narrationHtml
|
|
1025
|
+
narrationHtml +
|
|
1026
|
+
todosHtmlFromInfo(info, esc);
|
|
992
1027
|
if (info.keys.length === 0) {
|
|
993
1028
|
html += "<div class=\\"wg-key\\">(no MemKeys required)</div>";
|
|
994
1029
|
}
|
|
@@ -1021,12 +1056,7 @@ async function renderBeforeStep(page, info) {
|
|
|
1021
1056
|
}
|
|
1022
1057
|
if (window.__wgWirePanelChrome) {
|
|
1023
1058
|
window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
|
|
1024
|
-
stepLabel:
|
|
1025
|
-
(info.index + 1) +
|
|
1026
|
-
" / " +
|
|
1027
|
-
info.total +
|
|
1028
|
-
(info.blockName ? " · " + info.blockName : "") +
|
|
1029
|
-
(info.paceBadge ? " · " + info.paceBadge : ""),
|
|
1059
|
+
stepLabel: miniStepLabel(info),
|
|
1030
1060
|
forceCollapsed: info.forceCollapsed === true ? true : info.forceCollapsed === false ? false : undefined,
|
|
1031
1061
|
});
|
|
1032
1062
|
}
|
|
@@ -1103,6 +1133,102 @@ async function renderBeforeStep(page, info) {
|
|
|
1103
1133
|
.catch(() => {});
|
|
1104
1134
|
}
|
|
1105
1135
|
|
|
1136
|
+
async function ensureSelectorInView(page, selector) {
|
|
1137
|
+
try {
|
|
1138
|
+
const loc = page.locator(selector).first();
|
|
1139
|
+
await loc.scrollIntoViewIfNeeded().catch(() => {});
|
|
1140
|
+
await page
|
|
1141
|
+
.evaluate((sel) => {
|
|
1142
|
+
const el = document.querySelector(sel);
|
|
1143
|
+
if (!el) return;
|
|
1144
|
+
try {
|
|
1145
|
+
el.scrollIntoView({ block: "center", inline: "center", behavior: "instant" });
|
|
1146
|
+
} catch {
|
|
1147
|
+
try {
|
|
1148
|
+
el.scrollIntoView(true);
|
|
1149
|
+
} catch {
|
|
1150
|
+
/* ignore */
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
let p = el.parentElement;
|
|
1154
|
+
while (p && p !== document.documentElement && p !== document.body) {
|
|
1155
|
+
const st = getComputedStyle(p);
|
|
1156
|
+
const ox = st.overflowX;
|
|
1157
|
+
const oy = st.overflowY;
|
|
1158
|
+
if (/(auto|scroll|overlay)/.test(ox) || /(auto|scroll|overlay)/.test(oy)) {
|
|
1159
|
+
const er = el.getBoundingClientRect();
|
|
1160
|
+
const pr = p.getBoundingClientRect();
|
|
1161
|
+
if (er.left < pr.left || er.right > pr.right || er.top < pr.top || er.bottom > pr.bottom) {
|
|
1162
|
+
p.scrollLeft += er.left + er.width / 2 - (pr.left + pr.width / 2);
|
|
1163
|
+
p.scrollTop += er.top + er.height / 2 - (pr.top + pr.height / 2);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
p = p.parentElement;
|
|
1167
|
+
}
|
|
1168
|
+
}, selector)
|
|
1169
|
+
.catch(() => {});
|
|
1170
|
+
} catch {
|
|
1171
|
+
/* best-effort */
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
async function applyHighlightZoom(page, selector, zoom) {
|
|
1176
|
+
const z = Number(zoom);
|
|
1177
|
+
if (!Number.isFinite(z) || z <= 1.001) {
|
|
1178
|
+
await page.evaluate(() => {
|
|
1179
|
+
if (window.__wgClearZoom) window.__wgClearZoom();
|
|
1180
|
+
}).catch(() => {});
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
await page
|
|
1184
|
+
.evaluate(
|
|
1185
|
+
({ sel, scale }) => {
|
|
1186
|
+
if (window.__wgApplyZoom) window.__wgApplyZoom(sel, scale);
|
|
1187
|
+
},
|
|
1188
|
+
{ sel: selector, scale: z },
|
|
1189
|
+
)
|
|
1190
|
+
.catch(() => {});
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
function todosHtmlFromInfo(info, escFn) {
|
|
1194
|
+
const list = info.todos || [];
|
|
1195
|
+
if (!list.length) return "";
|
|
1196
|
+
return (
|
|
1197
|
+
"<ul id=\\"wg-todos\\">" +
|
|
1198
|
+
list
|
|
1199
|
+
.map((t) => {
|
|
1200
|
+
const cls = t.current ? "wg-todo-current" : t.done ? "wg-todo-done" : "wg-todo-pending";
|
|
1201
|
+
const mark = t.done ? "\\u2713" : t.current ? "\\u2192" : "\\u25CB";
|
|
1202
|
+
return (
|
|
1203
|
+
"<li class=\\"" +
|
|
1204
|
+
cls +
|
|
1205
|
+
"\\"><span class=\\"wg-todo-mark\\">" +
|
|
1206
|
+
mark +
|
|
1207
|
+
"</span><span>" +
|
|
1208
|
+
escFn(t.text || "") +
|
|
1209
|
+
"</span></li>"
|
|
1210
|
+
);
|
|
1211
|
+
})
|
|
1212
|
+
.join("") +
|
|
1213
|
+
"</ul>"
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
function miniStepLabel(info) {
|
|
1218
|
+
const ep =
|
|
1219
|
+
info.episodeNumber !== undefined && info.episodeNumber !== null
|
|
1220
|
+
? "Ep " + info.episodeNumber + " \\u00b7 "
|
|
1221
|
+
: "";
|
|
1222
|
+
return (
|
|
1223
|
+
ep +
|
|
1224
|
+
(info.index + 1) +
|
|
1225
|
+
" / " +
|
|
1226
|
+
info.total +
|
|
1227
|
+
(info.blockName ? " \\u00b7 " + info.blockName : "") +
|
|
1228
|
+
(info.paceBadge ? " \\u00b7 " + info.paceBadge : "")
|
|
1229
|
+
);
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1106
1232
|
async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
1107
1233
|
const list = highlights || [];
|
|
1108
1234
|
// defaultHoldMs: when set (fail path), use instead of legacy 900/200 so BUG
|
|
@@ -1112,12 +1238,47 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1112
1238
|
for (let i = 0; i < list.length; i++) {
|
|
1113
1239
|
const h = list[i];
|
|
1114
1240
|
try {
|
|
1241
|
+
await ensureSelectorInView(page, h.selector);
|
|
1242
|
+
await applyHighlightZoom(page, h.selector, h.zoom);
|
|
1115
1243
|
const box = await page.locator(h.selector).first().boundingBox();
|
|
1116
1244
|
if (box) {
|
|
1117
1245
|
await showRing(page, box, h.label, h.tone || "planned", {
|
|
1118
1246
|
size: h.size,
|
|
1119
1247
|
weight: h.weight,
|
|
1120
1248
|
});
|
|
1249
|
+
if (h.todos && h.todos.length) {
|
|
1250
|
+
const rows = normalizeTodos(h.todos, h.todoIndex);
|
|
1251
|
+
await page
|
|
1252
|
+
.evaluate((todos) => {
|
|
1253
|
+
const ul = document.getElementById("wg-todos");
|
|
1254
|
+
if (!ul) return;
|
|
1255
|
+
ul.innerHTML = todos
|
|
1256
|
+
.map((t) => {
|
|
1257
|
+
const cls = t.current
|
|
1258
|
+
? "wg-todo-current"
|
|
1259
|
+
: t.done
|
|
1260
|
+
? "wg-todo-done"
|
|
1261
|
+
: "wg-todo-pending";
|
|
1262
|
+
const mark = t.done ? "\\u2713" : t.current ? "\\u2192" : "\\u25CB";
|
|
1263
|
+
const esc = (s) =>
|
|
1264
|
+
String(s)
|
|
1265
|
+
.replace(/&/g, "&")
|
|
1266
|
+
.replace(/</g, "<")
|
|
1267
|
+
.replace(/>/g, ">");
|
|
1268
|
+
return (
|
|
1269
|
+
"<li class=\\"" +
|
|
1270
|
+
cls +
|
|
1271
|
+
"\\"><span class=\\"wg-todo-mark\\">" +
|
|
1272
|
+
mark +
|
|
1273
|
+
"</span><span>" +
|
|
1274
|
+
esc(t.text || "") +
|
|
1275
|
+
"</span></li>"
|
|
1276
|
+
);
|
|
1277
|
+
})
|
|
1278
|
+
.join("");
|
|
1279
|
+
}, rows)
|
|
1280
|
+
.catch(() => {});
|
|
1281
|
+
}
|
|
1121
1282
|
const authored = resolveFixtureDwellMs(h, { gatesFast, pace });
|
|
1122
1283
|
const legacyMs = i === list.length - 1 ? 200 : 900;
|
|
1123
1284
|
const holdMs =
|
|
@@ -1261,6 +1422,7 @@ async function renderAfterStep(page, info) {
|
|
|
1261
1422
|
paceHtml +
|
|
1262
1423
|
"<div id=\\"wg-modules\\" class=\\"" + modulesClass + "\\">" + modulesHtml + "</div>" +
|
|
1263
1424
|
"<h3>" + heading + "</h3>" +
|
|
1425
|
+
todosHtmlFromInfo(info, escA) +
|
|
1264
1426
|
resultHtml +
|
|
1265
1427
|
gateHtml;
|
|
1266
1428
|
if (isNewPanel) {
|
|
@@ -1269,12 +1431,7 @@ async function renderAfterStep(page, info) {
|
|
|
1269
1431
|
}
|
|
1270
1432
|
if (window.__wgWirePanelChrome) {
|
|
1271
1433
|
window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
|
|
1272
|
-
stepLabel:
|
|
1273
|
-
(info.index + 1) +
|
|
1274
|
-
" / " +
|
|
1275
|
-
info.total +
|
|
1276
|
-
(info.blockName ? " · " + info.blockName : "") +
|
|
1277
|
-
(info.paceBadge ? " · " + info.paceBadge : ""),
|
|
1434
|
+
stepLabel: miniStepLabel(info),
|
|
1278
1435
|
forceCollapsed: info.forceCollapsed === true ? true : info.forceCollapsed === false ? false : undefined,
|
|
1279
1436
|
});
|
|
1280
1437
|
}
|
|
@@ -1376,12 +1533,7 @@ async function renderStepError(page, info) {
|
|
|
1376
1533
|
}
|
|
1377
1534
|
if (window.__wgWirePanelChrome) {
|
|
1378
1535
|
window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
|
|
1379
|
-
stepLabel:
|
|
1380
|
-
(info.index + 1) +
|
|
1381
|
-
" / " +
|
|
1382
|
-
info.total +
|
|
1383
|
-
(info.blockName ? " · " + info.blockName : "") +
|
|
1384
|
-
(info.paceBadge ? " · " + info.paceBadge : ""),
|
|
1536
|
+
stepLabel: miniStepLabel(info),
|
|
1385
1537
|
forceCollapsed: info.forceCollapsed === true ? true : info.forceCollapsed === false ? false : undefined,
|
|
1386
1538
|
});
|
|
1387
1539
|
}
|
|
@@ -1609,6 +1761,8 @@ async function presentSlides(page, slides, _gate, opts) {
|
|
|
1609
1761
|
await installOverlay(page, title);
|
|
1610
1762
|
if (s.selector) {
|
|
1611
1763
|
try {
|
|
1764
|
+
await ensureSelectorInView(page, s.selector);
|
|
1765
|
+
await applyHighlightZoom(page, s.selector, s.zoom);
|
|
1612
1766
|
const box = await page.locator(s.selector).first().boundingBox();
|
|
1613
1767
|
if (box) await showRing(page, box, caption, slideTone, slideStyle);
|
|
1614
1768
|
} catch {
|
|
@@ -1696,11 +1850,14 @@ async function presentSlides(page, slides, _gate, opts) {
|
|
|
1696
1850
|
if (window.__wgWirePanelChrome) {
|
|
1697
1851
|
window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
|
|
1698
1852
|
stepLabel:
|
|
1853
|
+
(info.episodeNumber !== undefined && info.episodeNumber !== null
|
|
1854
|
+
? "Ep " + info.episodeNumber + " \\u00b7 "
|
|
1855
|
+
: "") +
|
|
1699
1856
|
"Slide " +
|
|
1700
1857
|
(info.index + 1) +
|
|
1701
1858
|
" / " +
|
|
1702
1859
|
info.total +
|
|
1703
|
-
(info.blockName ? "
|
|
1860
|
+
(info.blockName ? " \\u00b7 " + info.blockName : ""),
|
|
1704
1861
|
forceCollapsed: false,
|
|
1705
1862
|
});
|
|
1706
1863
|
}
|
|
@@ -2416,6 +2573,12 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2416
2573
|
episodeTitle: r.episodeTitle,
|
|
2417
2574
|
stepperMode,
|
|
2418
2575
|
forceCollapsed,
|
|
2576
|
+
todos: (() => {
|
|
2577
|
+
for (const h of stubBeforeRef.current || []) {
|
|
2578
|
+
if (h.todos && h.todos.length) return normalizeTodos(h.todos, h.todoIndex);
|
|
2579
|
+
}
|
|
2580
|
+
return [];
|
|
2581
|
+
})(),
|
|
2419
2582
|
...paceSpeak,
|
|
2420
2583
|
});
|
|
2421
2584
|
const edits = await gate();
|
|
@@ -2487,6 +2650,9 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2487
2650
|
tone: styled.tone,
|
|
2488
2651
|
size: styled.size,
|
|
2489
2652
|
weight: styled.weight,
|
|
2653
|
+
todos: styled.todos,
|
|
2654
|
+
todoIndex: styled.todoIndex,
|
|
2655
|
+
zoom: styled.zoom,
|
|
2490
2656
|
};
|
|
2491
2657
|
});
|
|
2492
2658
|
await cycleHighlightRings(page, errHighlights, !!pacing.gatesFast, {
|
|
@@ -2569,6 +2735,9 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2569
2735
|
tone: styled.tone,
|
|
2570
2736
|
size: styled.size,
|
|
2571
2737
|
weight: styled.weight,
|
|
2738
|
+
todos: styled.todos,
|
|
2739
|
+
todoIndex: styled.todoIndex,
|
|
2740
|
+
zoom: styled.zoom,
|
|
2572
2741
|
};
|
|
2573
2742
|
},
|
|
2574
2743
|
);
|
|
@@ -2596,6 +2765,12 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2596
2765
|
episodeNumber: r.episodeNumber,
|
|
2597
2766
|
episodeTitle: r.episodeTitle,
|
|
2598
2767
|
stepperMode,
|
|
2768
|
+
todos: (() => {
|
|
2769
|
+
for (const h of highlights || []) {
|
|
2770
|
+
if (h.todos && h.todos.length) return normalizeTodos(h.todos, h.todoIndex);
|
|
2771
|
+
}
|
|
2772
|
+
return [];
|
|
2773
|
+
})(),
|
|
2599
2774
|
// After a nav under auto-next, stay compact until the next action block expands.
|
|
2600
2775
|
forceCollapsed: !!process.env.WAYGRAPH_VIDEO || ((await currentAutoplay()) && isNavBlock),
|
|
2601
2776
|
});
|
|
@@ -2690,7 +2865,7 @@ async function runChainedFlows(chainFlow, chainFlows, context, mem, page) {
|
|
|
2690
2865
|
/** Parses WAYGRAPH_VIDEO_VIEWPORT / --video-viewport: "1920x1080" or "1920,1080". */
|
|
2691
2866
|
function parseVideoViewport(raw) {
|
|
2692
2867
|
if (!raw || !raw.trim()) return null;
|
|
2693
|
-
const m = raw.trim().match(/^(
|
|
2868
|
+
const m = raw.trim().match(/^(\\d{3,5})[xX,](\\d{3,5})$/);
|
|
2694
2869
|
if (!m) return null;
|
|
2695
2870
|
const width = Number(m[1]);
|
|
2696
2871
|
const height = Number(m[2]);
|
|
@@ -2981,7 +3156,13 @@ async function main() {
|
|
|
2981
3156
|
...(executablePath ? { executablePath } : {}),
|
|
2982
3157
|
});
|
|
2983
3158
|
const contextOpts = fixedVideoViewport
|
|
2984
|
-
? {
|
|
3159
|
+
? {
|
|
3160
|
+
baseURL,
|
|
3161
|
+
viewport: fixedVideoViewport,
|
|
3162
|
+
// Lock DPR so --video-viewport 800x450 stays 800x450 in the .webm
|
|
3163
|
+
// (HiDPI hosts otherwise scale recordVideo to e.g. 1920x1080).
|
|
3164
|
+
deviceScaleFactor: 1,
|
|
3165
|
+
}
|
|
2985
3166
|
: step
|
|
2986
3167
|
? { baseURL, viewport: null }
|
|
2987
3168
|
: { baseURL, viewport: { width: 1280, height: 720 } };
|
package/dist/highlights.d.ts
CHANGED
|
@@ -24,6 +24,18 @@ export type FixtureDurationFields = {
|
|
|
24
24
|
*/
|
|
25
25
|
fastMode?: number;
|
|
26
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* One checklist row for episode planning (demo panel).
|
|
29
|
+
* Prefer {@link WaygraphHighlightStub.todoIndex} for sequential done/current.
|
|
30
|
+
*/
|
|
31
|
+
export type WaygraphTodoItem = {
|
|
32
|
+
text: string;
|
|
33
|
+
/** Explicit done. If omitted, derived from todoIndex (index < todoIndex). */
|
|
34
|
+
done?: boolean;
|
|
35
|
+
/** Explicit current. If omitted, derived from todoIndex (index === todoIndex). */
|
|
36
|
+
current?: boolean;
|
|
37
|
+
};
|
|
38
|
+
export type WaygraphTodoInput = string | WaygraphTodoItem;
|
|
27
39
|
/** One named highlight slot on a block (selector + caption). */
|
|
28
40
|
export interface WaygraphHighlightStub extends FixtureDurationFields {
|
|
29
41
|
selector: string;
|
|
@@ -50,9 +62,25 @@ export interface WaygraphHighlightStub extends FixtureDurationFields {
|
|
|
50
62
|
* Aliases: regular, strong.
|
|
51
63
|
*/
|
|
52
64
|
weight?: HighlightWeight;
|
|
65
|
+
/**
|
|
66
|
+
* Simple episode checklist (demo panel). Same lifecycle as this stub
|
|
67
|
+
* (stubBefore / stubAfter / stubOnError). Strings or `{ text, done?, current? }`.
|
|
68
|
+
*/
|
|
69
|
+
todos?: readonly WaygraphTodoInput[];
|
|
70
|
+
/**
|
|
71
|
+
* Which todo is current (0-based). Rows before = done, after = pending.
|
|
72
|
+
* Authored `done`/`current` on an item still win when set.
|
|
73
|
+
* Bump in a stub phase function for sequential plans.
|
|
74
|
+
*/
|
|
75
|
+
todoIndex?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Magnify the target element while this ring is shown (e.g. `1.35`).
|
|
78
|
+
* Cleared when the ring hides / next highlight starts. `1` or omit = off.
|
|
79
|
+
*/
|
|
80
|
+
zoom?: number;
|
|
53
81
|
}
|
|
54
82
|
/** Flow fixture patch: label required; selector optional (inherits from stub). */
|
|
55
|
-
export type WaygraphHighlightFixture = Partial<Pick<WaygraphHighlightStub, "selector">> & Required<Pick<WaygraphHighlightStub, "label">> & Pick<WaygraphHighlightStub, "detail" | "tag" | "tone" | "size" | "weight"> & FixtureDurationFields;
|
|
83
|
+
export type WaygraphHighlightFixture = Partial<Pick<WaygraphHighlightStub, "selector">> & Required<Pick<WaygraphHighlightStub, "label">> & Pick<WaygraphHighlightStub, "detail" | "tag" | "tone" | "size" | "weight" | "todos" | "todoIndex" | "zoom"> & FixtureDurationFields;
|
|
56
84
|
export type HighlightStubPhase = Record<string, WaygraphHighlightStub>;
|
|
57
85
|
export type HighlightStubPhaseOrFn<Out extends Checkpoint<string>> = HighlightStubPhase | ((out: Out) => HighlightStubPhase);
|
|
58
86
|
/**
|
|
@@ -69,6 +97,8 @@ export interface WaygraphSlide extends FixtureDurationFields {
|
|
|
69
97
|
tone?: HighlightTone;
|
|
70
98
|
size?: HighlightSize;
|
|
71
99
|
weight?: HighlightWeight;
|
|
100
|
+
/** Magnify selector target while this slide is showing (same as stub zoom). */
|
|
101
|
+
zoom?: number;
|
|
72
102
|
}
|
|
73
103
|
/**
|
|
74
104
|
* Demo ring tones (iconified).
|
|
@@ -188,6 +218,10 @@ export interface WaygraphHighlight {
|
|
|
188
218
|
tone?: HighlightTone;
|
|
189
219
|
}
|
|
190
220
|
export type ResolvedHighlight = WaygraphHighlightStub;
|
|
221
|
+
/**
|
|
222
|
+
* Normalize checklist rows; apply todoIndex for sequential done/current.
|
|
223
|
+
*/
|
|
224
|
+
export declare function normalizeTodos(todos: readonly WaygraphTodoInput[] | undefined, todoIndex?: number): WaygraphTodoItem[];
|
|
191
225
|
/**
|
|
192
226
|
* Resolve ordered highlight slots for a phase, merging flow fixtures over block stubs.
|
|
193
227
|
* Shim: empty stubAfter + legacy `instruction.highlights` -> auto-keyed stubAfter.
|
package/dist/highlights.js
CHANGED
|
@@ -289,11 +289,50 @@ function pickStyleFields(base, patch) {
|
|
|
289
289
|
out.weight = normalizeHighlightWeight(weight);
|
|
290
290
|
return out;
|
|
291
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* Normalize checklist rows; apply todoIndex for sequential done/current.
|
|
294
|
+
*/
|
|
295
|
+
export function normalizeTodos(todos, todoIndex) {
|
|
296
|
+
if (!todos || todos.length === 0)
|
|
297
|
+
return [];
|
|
298
|
+
const idx = todoIndex !== undefined && Number.isFinite(todoIndex) ? Math.floor(todoIndex) : undefined;
|
|
299
|
+
return todos.map((t, i) => {
|
|
300
|
+
const text = typeof t === "string" ? t.trim() : String(t?.text ?? "").trim();
|
|
301
|
+
const item = { text: text || `Item ${i + 1}` };
|
|
302
|
+
if (typeof t === "object" && t) {
|
|
303
|
+
if (t.done !== undefined)
|
|
304
|
+
item.done = !!t.done;
|
|
305
|
+
if (t.current !== undefined)
|
|
306
|
+
item.current = !!t.current;
|
|
307
|
+
}
|
|
308
|
+
if (idx !== undefined) {
|
|
309
|
+
if (item.done === undefined)
|
|
310
|
+
item.done = i < idx;
|
|
311
|
+
if (item.current === undefined)
|
|
312
|
+
item.current = i === idx;
|
|
313
|
+
}
|
|
314
|
+
return item;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
function pickTodoFields(base, patch) {
|
|
318
|
+
const out = {};
|
|
319
|
+
const todos = patch?.todos !== undefined ? patch.todos : base?.todos;
|
|
320
|
+
const todoIndex = patch?.todoIndex !== undefined ? patch.todoIndex : base?.todoIndex;
|
|
321
|
+
const zoom = patch?.zoom !== undefined ? patch.zoom : base?.zoom;
|
|
322
|
+
if (todos !== undefined)
|
|
323
|
+
out.todos = todos;
|
|
324
|
+
if (todoIndex !== undefined)
|
|
325
|
+
out.todoIndex = todoIndex;
|
|
326
|
+
if (zoom !== undefined && Number.isFinite(zoom) && zoom > 0)
|
|
327
|
+
out.zoom = zoom;
|
|
328
|
+
return out;
|
|
329
|
+
}
|
|
292
330
|
function mergeSlot(base, patch) {
|
|
293
331
|
if (!base && !patch)
|
|
294
332
|
return null;
|
|
295
333
|
const dwell = pickDurationFields(base, patch);
|
|
296
334
|
const style = pickStyleFields(base, patch);
|
|
335
|
+
const todos = pickTodoFields(base, patch);
|
|
297
336
|
if (!base && patch) {
|
|
298
337
|
if (!patch.selector)
|
|
299
338
|
return null;
|
|
@@ -304,6 +343,7 @@ function mergeSlot(base, patch) {
|
|
|
304
343
|
...(patch.tag ? { tag: patch.tag } : {}),
|
|
305
344
|
...style,
|
|
306
345
|
...dwell,
|
|
346
|
+
...todos,
|
|
307
347
|
};
|
|
308
348
|
}
|
|
309
349
|
if (base && !patch) {
|
|
@@ -312,6 +352,7 @@ function mergeSlot(base, patch) {
|
|
|
312
352
|
...(base.tone ? { tone: normalizeHighlightTone(base.tone) } : {}),
|
|
313
353
|
...(base.size ? { size: normalizeHighlightSize(base.size) } : {}),
|
|
314
354
|
...(base.weight ? { weight: normalizeHighlightWeight(base.weight) } : {}),
|
|
355
|
+
...pickTodoFields(base, undefined),
|
|
315
356
|
};
|
|
316
357
|
}
|
|
317
358
|
return {
|
|
@@ -325,6 +366,7 @@ function mergeSlot(base, patch) {
|
|
|
325
366
|
...(patch.tag !== undefined ? { tag: patch.tag } : base.tag ? { tag: base.tag } : {}),
|
|
326
367
|
...style,
|
|
327
368
|
...dwell,
|
|
369
|
+
...todos,
|
|
328
370
|
};
|
|
329
371
|
}
|
|
330
372
|
function phaseFromLegacyHighlights(highlights) {
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export { connect, checkpoint } from "./types.js";
|
|
|
3
3
|
export { MemKey, MemPage, key, keyGroup } from "./mem-page.js";
|
|
4
4
|
export { Trait, urlMatches, textEquals, visible } from "./trait.js";
|
|
5
5
|
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withDemoPace, withBlockPace, withHighlightStyle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
6
|
-
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
7
|
-
export type { WaygraphHighlightStub, WaygraphHighlightFixture, WaygraphSlide, FixtureDurationFields, HighlightStubPhase, HighlightStubPhaseName, HighlightFixtureMap, ResolvedHighlight, WaygraphHighlight, HighlightTone, HighlightSize, HighlightWeight, HighlightStyleDefaults, DemoPace, DemoPaceName, } from "./highlights.js";
|
|
6
|
+
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, normalizeTodos, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
7
|
+
export type { WaygraphHighlightStub, WaygraphHighlightFixture, WaygraphSlide, WaygraphTodoItem, WaygraphTodoInput, FixtureDurationFields, HighlightStubPhase, HighlightStubPhaseName, HighlightFixtureMap, ResolvedHighlight, WaygraphHighlight, HighlightTone, HighlightSize, HighlightWeight, HighlightStyleDefaults, DemoPace, DemoPaceName, } from "./highlights.js";
|
|
8
8
|
export type { Flow, EngineConfig, ComposedBlock, FastForwardComposedBlock, RunGraphOptions, BlockInfo, NavBlock, NavBlockOptions, NavClickBlock, NavClickBlockOptions, MethodBlock, ActionBlock, PageBlock, PageBlockOptions, PageMethodEntry, EffectBlock, MemEffectBlock, MemNavBlock, } from "./engine.js";
|
|
9
9
|
export type { ActionPage } from "./types.js";
|
|
10
10
|
export { discoverGraph, toMermaid, findOrphanBlocks, findBlockPath } from "./graph.js";
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { connect, checkpoint } from "./types.js";
|
|
|
2
2
|
export { MemKey, MemPage, key, keyGroup } from "./mem-page.js";
|
|
3
3
|
export { Trait, urlMatches, textEquals, visible } from "./trait.js";
|
|
4
4
|
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withDemoPace, withBlockPace, withHighlightStyle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
5
|
-
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
5
|
+
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, normalizeTodos, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
6
6
|
export { discoverGraph, toMermaid, findOrphanBlocks, findBlockPath } from "./graph.js";
|
|
7
7
|
export { isFileSelectToken, parseBlocksSelect, matchBlocksSelect, globToRegExp, } from "./blocks-select.js";
|
|
8
8
|
export { EdgeLeaseCoordinator } from "./traverse-lease.js";
|