@markdy/renderer-dom 0.8.18 → 0.8.20
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 +11 -8
- package/dist/index.d.ts +7 -3
- package/dist/index.js +103 -42
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -70,18 +70,21 @@ diagram.destroy(); // clean up DOM + cancel animations
|
|
|
70
70
|
|---|---|---|---|
|
|
71
71
|
| `container` | `HTMLElement` | *(required)* | DOM element to mount the scene into |
|
|
72
72
|
| `code` | `string` | *(required)* | MarkdyScript source code |
|
|
73
|
-
| `autoplay` | `boolean` | `true` | Start playing immediately |
|
|
74
|
-
| `loop` | `boolean` | `true` | Loop the animation when it reaches the end |
|
|
75
|
-
| `copyright` | `boolean` | `true` | Show a small "Powered by Markdy" badge below the animation |
|
|
76
|
-
| `progressBar` | `boolean` | `true` | Deprecated compatibility flag for the
|
|
77
|
-
| `sceneBoundaryProgress` | `boolean` | `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
73
|
+
| `autoplay` | `boolean` | `plan.meta.autoplay ?? true` | Start playing immediately |
|
|
74
|
+
| `loop` | `boolean` | `plan.meta.loop ?? true` | Loop the animation when it reaches the end |
|
|
75
|
+
| `copyright` | `boolean` | `plan.meta.copyright ?? true` | Show a small "Powered by Markdy" badge below the animation |
|
|
76
|
+
| `progressBar` | `boolean \| string` | `true` | Deprecated compatibility flag for the scene-boundary progress bar |
|
|
77
|
+
| `sceneBoundaryProgress` | `boolean \| string` | `true` | Show boundary progress bar, or pass a custom color/gradient string |
|
|
78
|
+
| `progressColor` | `string` | `plan.meta.progressColor ?? "rainbow"` | Custom progress bar color (e.g. `"#3b82f6"`) or gradient (e.g. `"#ec4899, #8b5cf6"`) |
|
|
79
|
+
| `playbackRate` | `number` | `plan.meta.playbackRate ?? 1` | Normalized timeline speed multiplier; `1` is Markdy's normal pace |
|
|
80
|
+
| `interactiveViewport` | `boolean` | `controls \|\| plan.meta.interactiveViewport` | Enable wheel zoom and drag pan on the rendered viewport |
|
|
81
|
+
| `controls` | `boolean` | `plan.meta.controls ?? false` | Show left-aligned footer controls toolbar (play/pause, restart, speed, reset view); also enables viewport interaction |
|
|
81
82
|
| `onWarning` | `(warning: Diagnostic) => void` | `console.warn` | Called for each soft parse warning |
|
|
82
83
|
| `onTimeUpdate` | `(seconds: number, durationSeconds: number) => void` | — | Called whenever playback or seek changes the current time |
|
|
83
84
|
| `onPlayStateChange` | `(playing: boolean) => void` | — | Called when playback starts or pauses |
|
|
84
85
|
|
|
86
|
+
> **Note:** Directives declared inside the MarkdyScript code (e.g. `controls true`, `interactive true`, `progressColor "#3b82f6"`) apply automatically if the corresponding JavaScript option is omitted (`undefined`). Options passed to `createDiagram()` override the in-script declarations.
|
|
87
|
+
|
|
85
88
|
### `Diagram`
|
|
86
89
|
|
|
87
90
|
| Method | Description |
|
package/dist/index.d.ts
CHANGED
|
@@ -17,9 +17,13 @@ interface DiagramOptions {
|
|
|
17
17
|
*/
|
|
18
18
|
assets?: Record<string, string>;
|
|
19
19
|
/** @deprecated Prefer sceneBoundaryProgress. */
|
|
20
|
-
progressBar?: boolean;
|
|
21
|
-
/** Show rainbow progress around scene boundary. Defaults to true. */
|
|
22
|
-
sceneBoundaryProgress?: boolean;
|
|
20
|
+
progressBar?: boolean | string;
|
|
21
|
+
/** Show rainbow progress around scene boundary, or specify a custom color/gradient. Defaults to true. */
|
|
22
|
+
sceneBoundaryProgress?: boolean | string;
|
|
23
|
+
/** Custom progress bar color or gradient. Defaults to rainbow. */
|
|
24
|
+
progressColor?: string;
|
|
25
|
+
/** @deprecated Prefer progressColor. */
|
|
26
|
+
progressBarColor?: string;
|
|
23
27
|
/** Playback speed multiplier. Defaults to 1, where 1 is Markdy's normal pace. */
|
|
24
28
|
playbackRate?: number;
|
|
25
29
|
/** Enable wheel zoom and drag pan on the rendered viewport. Defaults to false. */
|
package/dist/index.js
CHANGED
|
@@ -1769,6 +1769,34 @@ function ensureSceneStyles(doc) {
|
|
|
1769
1769
|
transform: translateY(8px);
|
|
1770
1770
|
will-change: opacity, transform;
|
|
1771
1771
|
}
|
|
1772
|
+
.markdy-footer {
|
|
1773
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
1774
|
+
}
|
|
1775
|
+
.markdy-controls button {
|
|
1776
|
+
touch-action: manipulation;
|
|
1777
|
+
user-select: none;
|
|
1778
|
+
-webkit-user-select: none;
|
|
1779
|
+
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.05s ease;
|
|
1780
|
+
}
|
|
1781
|
+
.markdy-controls button:hover:not([aria-pressed="true"]) {
|
|
1782
|
+
background: rgba(241, 245, 249, 1);
|
|
1783
|
+
color: #1e293b;
|
|
1784
|
+
border-color: rgba(100, 116, 139, 0.6);
|
|
1785
|
+
}
|
|
1786
|
+
.markdy-controls button:focus-visible {
|
|
1787
|
+
outline: 2px solid #3b82f6;
|
|
1788
|
+
outline-offset: 1px;
|
|
1789
|
+
}
|
|
1790
|
+
.markdy-controls button:active {
|
|
1791
|
+
transform: scale(0.96);
|
|
1792
|
+
}
|
|
1793
|
+
.markdy-footer a {
|
|
1794
|
+
transition: opacity 0.15s ease, color 0.15s ease;
|
|
1795
|
+
}
|
|
1796
|
+
.markdy-footer a:hover {
|
|
1797
|
+
opacity: 1 !important;
|
|
1798
|
+
color: #64748b !important;
|
|
1799
|
+
}
|
|
1772
1800
|
`;
|
|
1773
1801
|
doc.head.appendChild(style);
|
|
1774
1802
|
}
|
|
@@ -1856,24 +1884,36 @@ function createDiagram(opts) {
|
|
|
1856
1884
|
const {
|
|
1857
1885
|
container,
|
|
1858
1886
|
code,
|
|
1859
|
-
autoplay = true,
|
|
1860
|
-
loop = true,
|
|
1861
|
-
copyright = true,
|
|
1862
1887
|
assets,
|
|
1863
1888
|
progressBar,
|
|
1864
1889
|
sceneBoundaryProgress,
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1890
|
+
progressColor,
|
|
1891
|
+
progressBarColor,
|
|
1892
|
+
playbackRate: initialPlaybackRate,
|
|
1893
|
+
controls: explicitControls,
|
|
1894
|
+
interactiveViewport: explicitInteractiveViewport,
|
|
1895
|
+
autoplay: explicitAutoplay,
|
|
1896
|
+
loop: explicitLoop,
|
|
1897
|
+
copyright: explicitCopyright,
|
|
1868
1898
|
onWarning = (w) => console.warn(`[markdy] line ${w.line}: ${w.message}`),
|
|
1869
1899
|
onTimeUpdate,
|
|
1870
1900
|
onPlayStateChange
|
|
1871
1901
|
} = opts;
|
|
1872
|
-
const showSceneBoundaryProgress = sceneBoundaryProgress ?? progressBar ?? true;
|
|
1873
1902
|
const { ast, plan } = parseAndCompile(code);
|
|
1874
1903
|
for (const w of ast.diagnostics) {
|
|
1875
1904
|
if (w.severity === "warning") onWarning(w);
|
|
1876
1905
|
}
|
|
1906
|
+
const controls = explicitControls ?? plan.meta.controls ?? false;
|
|
1907
|
+
const interactiveViewport = explicitInteractiveViewport ?? (explicitControls !== void 0 ? explicitControls : plan.meta.interactiveViewport ?? plan.meta.controls ?? false);
|
|
1908
|
+
const autoplay = explicitAutoplay ?? plan.meta.autoplay ?? true;
|
|
1909
|
+
const loop = explicitLoop ?? plan.meta.loop ?? true;
|
|
1910
|
+
const copyright = explicitCopyright ?? plan.meta.copyright ?? true;
|
|
1911
|
+
const rawPlaybackRate = initialPlaybackRate ?? plan.meta.playbackRate ?? DEFAULT_PLAYBACK_RATE;
|
|
1912
|
+
let playbackRate = Number.isFinite(rawPlaybackRate) && rawPlaybackRate > 0 ? rawPlaybackRate : DEFAULT_PLAYBACK_RATE;
|
|
1913
|
+
const showSceneBoundaryProgress = sceneBoundaryProgress === false || sceneBoundaryProgress === void 0 && progressBar === false ? false : plan.meta.progressColor === "none" ? false : true;
|
|
1914
|
+
const rawColor = progressColor ?? progressBarColor ?? (typeof sceneBoundaryProgress === "string" && sceneBoundaryProgress !== "true" && sceneBoundaryProgress !== "false" ? sceneBoundaryProgress : typeof progressBar === "string" && progressBar !== "true" && progressBar !== "false" ? progressBar : void 0) ?? (plan.meta.progressColor && plan.meta.progressColor !== "none" ? plan.meta.progressColor : void 0);
|
|
1915
|
+
const customColor = rawColor && rawColor.trim() !== "rainbow" ? rawColor.trim() : null;
|
|
1916
|
+
const DEFAULT_RAINBOW = "hsl(0,90%,60%), hsl(45,90%,55%), hsl(90,80%,50%), hsl(180,80%,50%), hsl(270,80%,55%), hsl(330,90%,60%)";
|
|
1877
1917
|
const totalDurationMs = plan.duration * 1e3;
|
|
1878
1918
|
const durationSeconds = plan.duration;
|
|
1879
1919
|
const viewport = document.createElement("div");
|
|
@@ -1901,14 +1941,33 @@ function createDiagram(opts) {
|
|
|
1901
1941
|
function updateProgressBar(pct) {
|
|
1902
1942
|
if (!progressEl) return;
|
|
1903
1943
|
const deg = pct * 360;
|
|
1904
|
-
const
|
|
1905
|
-
progressEl.style.background = `conic-gradient(from ${tlAngleNorm}deg, ${
|
|
1944
|
+
const colorStops = customColor ? customColor.includes(",") ? customColor : `${customColor} 0deg, ${customColor}` : DEFAULT_RAINBOW;
|
|
1945
|
+
progressEl.style.background = `conic-gradient(from ${tlAngleNorm}deg, ${colorStops} ${deg}deg, transparent ${deg}deg)`;
|
|
1906
1946
|
progressEl.style.mask = "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)";
|
|
1907
1947
|
progressEl.style.webkitMask = progressEl.style.mask;
|
|
1908
1948
|
progressEl.style.maskComposite = "exclude";
|
|
1909
1949
|
progressEl.style.webkitMaskComposite = "xor";
|
|
1910
1950
|
progressEl.style.padding = "2px";
|
|
1911
1951
|
}
|
|
1952
|
+
let footer = null;
|
|
1953
|
+
function ensureFooter() {
|
|
1954
|
+
if (footer) return footer;
|
|
1955
|
+
footer = document.createElement("div");
|
|
1956
|
+
footer.className = "markdy-footer";
|
|
1957
|
+
Object.assign(footer.style, {
|
|
1958
|
+
display: "flex",
|
|
1959
|
+
alignItems: "center",
|
|
1960
|
+
justifyContent: "space-between",
|
|
1961
|
+
flexWrap: "wrap",
|
|
1962
|
+
gap: "6px",
|
|
1963
|
+
width: "100%",
|
|
1964
|
+
boxSizing: "border-box",
|
|
1965
|
+
padding: "4px 6px 0"
|
|
1966
|
+
});
|
|
1967
|
+
if (container.parentNode) container.parentNode.insertBefore(footer, container.nextSibling);
|
|
1968
|
+
else container.appendChild(footer);
|
|
1969
|
+
return footer;
|
|
1970
|
+
}
|
|
1912
1971
|
let badge = null;
|
|
1913
1972
|
if (copyright) {
|
|
1914
1973
|
badge = document.createElement("a");
|
|
@@ -1917,17 +1976,18 @@ function createDiagram(opts) {
|
|
|
1917
1976
|
badge.rel = "noopener noreferrer";
|
|
1918
1977
|
badge.textContent = "Powered by Markdy";
|
|
1919
1978
|
Object.assign(badge.style, {
|
|
1920
|
-
display: "
|
|
1979
|
+
display: "inline-flex",
|
|
1980
|
+
alignItems: "center",
|
|
1921
1981
|
textAlign: "right",
|
|
1922
1982
|
fontSize: "10px",
|
|
1923
1983
|
fontFamily: "system-ui, sans-serif",
|
|
1924
1984
|
color: "#999",
|
|
1925
1985
|
textDecoration: "none",
|
|
1926
|
-
padding: "
|
|
1927
|
-
opacity: "0.7"
|
|
1986
|
+
padding: "0",
|
|
1987
|
+
opacity: "0.7",
|
|
1988
|
+
marginLeft: "auto"
|
|
1928
1989
|
});
|
|
1929
|
-
|
|
1930
|
-
else container.appendChild(badge);
|
|
1990
|
+
ensureFooter().appendChild(badge);
|
|
1931
1991
|
}
|
|
1932
1992
|
ensureSceneStyles(document);
|
|
1933
1993
|
ensureNodeStyles(document);
|
|
@@ -2061,7 +2121,6 @@ function createDiagram(opts) {
|
|
|
2061
2121
|
anim.currentTime = 0;
|
|
2062
2122
|
}
|
|
2063
2123
|
let sceneMs = 0;
|
|
2064
|
-
let playbackRate = Number.isFinite(initialPlaybackRate) && initialPlaybackRate > 0 ? initialPlaybackRate : DEFAULT_PLAYBACK_RATE;
|
|
2065
2124
|
let lastRafTs = null;
|
|
2066
2125
|
let isPlaying = false;
|
|
2067
2126
|
let rafId = null;
|
|
@@ -2139,15 +2198,19 @@ function createDiagram(opts) {
|
|
|
2139
2198
|
}
|
|
2140
2199
|
function syncControls() {
|
|
2141
2200
|
if (controlsPlayButton) {
|
|
2142
|
-
|
|
2143
|
-
controlsPlayButton.
|
|
2201
|
+
const playing = isPlaying;
|
|
2202
|
+
controlsPlayButton.textContent = playing ? "Pause" : "Play";
|
|
2203
|
+
const playLabel = playing ? "Pause diagram" : "Play diagram";
|
|
2204
|
+
controlsPlayButton.setAttribute("aria-label", playLabel);
|
|
2205
|
+
controlsPlayButton.title = playLabel;
|
|
2144
2206
|
}
|
|
2145
2207
|
for (const button of controlsRateButtons) {
|
|
2146
2208
|
const rate = Number(button.dataset.rate ?? "1");
|
|
2147
2209
|
const active = Math.abs(rate - playbackRate) < 1e-3;
|
|
2148
2210
|
button.setAttribute("aria-pressed", active ? "true" : "false");
|
|
2149
|
-
button.style.background = active ? "
|
|
2150
|
-
button.style.color = active ? "#ffffff" : "#
|
|
2211
|
+
button.style.background = active ? "#1e293b" : "rgba(248, 250, 252, 0.92)";
|
|
2212
|
+
button.style.color = active ? "#ffffff" : "#475569";
|
|
2213
|
+
button.style.borderColor = active ? "#0f172a" : "rgba(148, 163, 184, 0.55)";
|
|
2151
2214
|
}
|
|
2152
2215
|
}
|
|
2153
2216
|
function emitPlayStateChange(playing) {
|
|
@@ -2228,6 +2291,7 @@ function createDiagram(opts) {
|
|
|
2228
2291
|
resizeObserver.disconnect();
|
|
2229
2292
|
if (progressEl?.parentNode === viewport) viewport.removeChild(progressEl);
|
|
2230
2293
|
if (badge?.parentNode) badge.parentNode.removeChild(badge);
|
|
2294
|
+
if (footer?.parentNode) footer.parentNode.removeChild(footer);
|
|
2231
2295
|
if (viewport.parentNode === container) container.removeChild(viewport);
|
|
2232
2296
|
}
|
|
2233
2297
|
};
|
|
@@ -2246,16 +2310,16 @@ function createDiagram(opts) {
|
|
|
2246
2310
|
button.title = ariaLabel;
|
|
2247
2311
|
Object.assign(button.style, {
|
|
2248
2312
|
appearance: "none",
|
|
2249
|
-
border: "1px solid rgba(
|
|
2250
|
-
borderRadius: "
|
|
2251
|
-
background: "rgba(
|
|
2252
|
-
color: "#
|
|
2313
|
+
border: "1px solid rgba(148, 163, 184, 0.55)",
|
|
2314
|
+
borderRadius: "5px",
|
|
2315
|
+
background: "rgba(248, 250, 252, 0.92)",
|
|
2316
|
+
color: "#475569",
|
|
2253
2317
|
cursor: "pointer",
|
|
2254
|
-
font: "600
|
|
2255
|
-
padding: "6px
|
|
2256
|
-
minWidth: "
|
|
2318
|
+
font: "600 10px/1.1 system-ui, sans-serif",
|
|
2319
|
+
padding: "4px 6px",
|
|
2320
|
+
minWidth: "28px",
|
|
2257
2321
|
whiteSpace: "nowrap",
|
|
2258
|
-
boxShadow: "
|
|
2322
|
+
boxShadow: "none"
|
|
2259
2323
|
});
|
|
2260
2324
|
return button;
|
|
2261
2325
|
}
|
|
@@ -2265,23 +2329,20 @@ function createDiagram(opts) {
|
|
|
2265
2329
|
toolbar.setAttribute("role", "toolbar");
|
|
2266
2330
|
toolbar.setAttribute("aria-label", "Diagram controls");
|
|
2267
2331
|
Object.assign(toolbar.style, {
|
|
2268
|
-
position: "
|
|
2269
|
-
left: "50%",
|
|
2270
|
-
bottom: "10px",
|
|
2271
|
-
zIndex: "10000",
|
|
2332
|
+
position: "static",
|
|
2272
2333
|
display: "flex",
|
|
2273
2334
|
alignItems: "center",
|
|
2274
|
-
justifyContent: "
|
|
2335
|
+
justifyContent: "flex-start",
|
|
2275
2336
|
flexWrap: "wrap",
|
|
2276
|
-
gap: "
|
|
2277
|
-
maxWidth: "
|
|
2278
|
-
padding: "
|
|
2279
|
-
border: "
|
|
2280
|
-
borderRadius: "
|
|
2281
|
-
background: "
|
|
2282
|
-
boxShadow: "
|
|
2283
|
-
backdropFilter: "
|
|
2284
|
-
transform: "
|
|
2337
|
+
gap: "4px",
|
|
2338
|
+
maxWidth: "100%",
|
|
2339
|
+
padding: "0",
|
|
2340
|
+
border: "0",
|
|
2341
|
+
borderRadius: "0",
|
|
2342
|
+
background: "transparent",
|
|
2343
|
+
boxShadow: "none",
|
|
2344
|
+
backdropFilter: "none",
|
|
2345
|
+
transform: "none",
|
|
2285
2346
|
pointerEvents: "auto"
|
|
2286
2347
|
});
|
|
2287
2348
|
for (const eventName of ["click", "dblclick", "pointerdown", "pointermove", "pointerup", "wheel"]) {
|
|
@@ -2313,7 +2374,7 @@ function createDiagram(opts) {
|
|
|
2313
2374
|
resetButton.addEventListener("click", resetViewportTransform);
|
|
2314
2375
|
toolbar.appendChild(resetButton);
|
|
2315
2376
|
}
|
|
2316
|
-
|
|
2377
|
+
ensureFooter().insertBefore(toolbar, badge ?? null);
|
|
2317
2378
|
syncControls();
|
|
2318
2379
|
}
|
|
2319
2380
|
viewport.style.cursor = interactiveViewport ? "grab" : "pointer";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markdy/renderer-dom",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.20",
|
|
4
4
|
"description": "Browser renderer for diagram-native animated MarkdyScript architecture diagrams, built on the Web Animations API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,14 +44,14 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@markdy/core": "0.8.
|
|
47
|
+
"@markdy/core": "0.8.20"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"jsdom": "^29.1.1",
|
|
51
51
|
"tsup": "^8.5.1",
|
|
52
52
|
"typescript": "^5.9.3",
|
|
53
53
|
"vitest": "^4.1.7",
|
|
54
|
-
"@markdy/stdlib-systems": "0.8.
|
|
54
|
+
"@markdy/stdlib-systems": "0.8.20"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "tsup",
|