@markdy/renderer-dom 1.0.20 → 1.0.22

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.
Files changed (2) hide show
  1. package/dist/index.js +91 -63
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -189,11 +189,24 @@ function toPathD(points, cornerRadius = 14, existingPaths = []) {
189
189
  }
190
190
  return parts.join(" ");
191
191
  }
192
- function selfLoopPath(rect) {
192
+ function selfLoopPath(rect, bounds) {
193
193
  const top = rect.y;
194
+ const loopHeight = 36;
195
+ if (bounds && top - loopHeight < 16) {
196
+ const bottom = rect.y + rect.height;
197
+ const left2 = rect.x + rect.width * 0.3;
198
+ const right2 = rect.x + rect.width * 0.7;
199
+ const apex2 = Math.min(bounds.height - 16, bottom + loopHeight);
200
+ return [
201
+ { x: round1(right2), y: round1(bottom) },
202
+ { x: round1(right2), y: round1(apex2) },
203
+ { x: round1(left2), y: round1(apex2) },
204
+ { x: round1(left2), y: round1(bottom) }
205
+ ];
206
+ }
194
207
  const left = rect.x + rect.width * 0.3;
195
208
  const right = rect.x + rect.width * 0.7;
196
- const apex = top - 40;
209
+ const apex = Math.max(12, top - loopHeight);
197
210
  return [
198
211
  { x: round1(left), y: round1(top) },
199
212
  { x: round1(left), y: round1(apex) },
@@ -737,7 +750,7 @@ function createEdgeRuntime(svg, from, to, kind, label, theme, sceneId, routeObst
737
750
  const color = theme.edges[kind];
738
751
  const style = EDGE_STYLES[kind];
739
752
  const isSelfLoop = from.id === to.id;
740
- const points = isSelfLoop ? dedupePoints(selfLoopPath(from)) : dedupePoints(routeEdgePoints(from, to, routeObstacles, bounds, lane));
753
+ const points = isSelfLoop ? dedupePoints(selfLoopPath(from, bounds)) : dedupePoints(routeEdgePoints(from, to, routeObstacles, bounds, lane));
741
754
  const d = toPathD(points, 14, existingPaths);
742
755
  const len = polylineLength(points);
743
756
  const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
@@ -1776,7 +1789,7 @@ function ensureNodeStyles(doc) {
1776
1789
  filter: drop-shadow(0 0 1px var(--md-hairline, rgba(15, 23, 42, 0.2))) drop-shadow(0 4px 12px var(--md-shadow, rgba(2, 6, 23, 0.15)));
1777
1790
  }
1778
1791
  .markdy-node[data-shape="diamond"][data-focal="1"] {
1779
- filter: drop-shadow(0 0 1.5px var(--md-accent)) drop-shadow(0 4px 16px color-mix(in srgb, var(--md-accent) 30%, transparent));
1792
+ filter: drop-shadow(0 0 1.5px var(--md-accent)) drop-shadow(0 4px 14px var(--md-shadow, rgba(2, 6, 23, 0.15)));
1780
1793
  }
1781
1794
  .markdy-node[data-shape="diamond"] .markdy-node__body {
1782
1795
  justify-content: center;
@@ -1868,13 +1881,10 @@ function ensureNodeStyles(doc) {
1868
1881
  background: var(--md-node-surface, var(--md-surface));
1869
1882
  }
1870
1883
  .markdy-node[data-focal="1"] {
1871
- background:
1872
- linear-gradient(180deg,
1873
- color-mix(in srgb, var(--md-accent) 12%, var(--md-node-surface-raised, var(--md-surface-raised, #ffffff))),
1874
- color-mix(in srgb, var(--md-accent) 6%, var(--md-node-surface, var(--md-surface, #ffffff))));
1875
1884
  box-shadow:
1876
- 0 2px 8px color-mix(in srgb, var(--md-accent) 20%, transparent),
1877
- inset 0 0 0 1.5px color-mix(in srgb, var(--md-accent) 60%, transparent);
1885
+ 0 2px 10px -2px var(--md-shadow, rgba(2, 6, 23, 0.18)),
1886
+ inset 0 0 0 1.5px var(--md-accent),
1887
+ 0 0 0 1px color-mix(in srgb, var(--md-accent) 25%, transparent);
1878
1888
  }
1879
1889
  .markdy-scene-root[data-markdy-theme="nebula"] .markdy-node {
1880
1890
  border: 1px solid color-mix(in srgb, var(--md-role-color, var(--md-accent)) 34%, transparent);
@@ -1885,7 +1895,7 @@ function ensureNodeStyles(doc) {
1885
1895
  .markdy-scene-root[data-markdy-theme="nebula"] .markdy-node[data-focal="1"] {
1886
1896
  box-shadow:
1887
1897
  0 0 34px -8px color-mix(in srgb, var(--md-accent) 78%, transparent),
1888
- inset 0 0 0 1px var(--md-accent);
1898
+ inset 0 0 0 1.5px var(--md-accent);
1889
1899
  }
1890
1900
  .markdy-scene-root[data-flat="1"] .markdy-node {
1891
1901
  box-shadow: inset 0 0 0 1px var(--md-hairline, color-mix(in srgb, var(--md-border) 50%, transparent));
@@ -1894,11 +1904,7 @@ function ensureNodeStyles(doc) {
1894
1904
  box-shadow: inset 0 0 0 1px var(--md-hairline, color-mix(in srgb, var(--md-border) 50%, transparent));
1895
1905
  }
1896
1906
  .markdy-scene-root[data-flat="1"] .markdy-node[data-focal="1"] {
1897
- box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--md-accent) 60%, transparent);
1898
- background:
1899
- linear-gradient(180deg,
1900
- color-mix(in srgb, var(--md-accent) 10%, var(--md-node-surface-raised, var(--md-surface-raised, #ffffff))),
1901
- color-mix(in srgb, var(--md-accent) 5%, var(--md-node-surface, var(--md-surface, #ffffff))));
1907
+ box-shadow: inset 0 0 0 1.5px var(--md-accent);
1902
1908
  }
1903
1909
  .markdy-node[data-kind="external"] {
1904
1910
  border: 1.2px dashed color-mix(in srgb, var(--md-ink, var(--md-text)) 30%, transparent);
@@ -2716,21 +2722,29 @@ function ensureSceneStyles(doc) {
2716
2722
  transform: translateY(8px);
2717
2723
  will-change: opacity, transform;
2718
2724
  }
2725
+ .markdy-diagram-root {
2726
+ position: relative;
2727
+ display: flex;
2728
+ flex-direction: column;
2729
+ box-sizing: border-box;
2730
+ width: 100%;
2731
+ }
2719
2732
  .markdy-footer {
2720
2733
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
2734
+ position: relative;
2721
2735
  width: 100%;
2722
2736
  box-sizing: border-box;
2723
2737
  display: flex;
2724
2738
  align-items: center;
2725
2739
  justify-content: space-between;
2726
2740
  gap: 8px;
2727
- padding: 6px 12px;
2741
+ padding: 8px 12px 4px;
2728
2742
  color: var(--md-text, #f8fafc);
2729
2743
  background: transparent;
2730
2744
  backdrop-filter: none;
2731
2745
  -webkit-backdrop-filter: none;
2732
2746
  border-top: none;
2733
- z-index: 20;
2747
+ z-index: 100;
2734
2748
  }
2735
2749
  .markdy-controls {
2736
2750
  display: flex;
@@ -2743,6 +2757,8 @@ function ensureSceneStyles(doc) {
2743
2757
  max-width: 100%;
2744
2758
  overflow-x: auto;
2745
2759
  scrollbar-width: none;
2760
+ padding: 4px 2px;
2761
+ margin: -4px -2px;
2746
2762
  }
2747
2763
  .markdy-controls::-webkit-scrollbar {
2748
2764
  display: none;
@@ -2804,6 +2820,8 @@ function ensureSceneStyles(doc) {
2804
2820
  transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
2805
2821
  }
2806
2822
  .markdy-controls button:hover:not([aria-pressed="true"]) {
2823
+ position: relative;
2824
+ z-index: 2;
2807
2825
  background: var(--md-control-hover-bg, rgba(255, 255, 255, 0.1));
2808
2826
  color: var(--md-control-hover-text, #f8fafc);
2809
2827
  border-color: var(--md-control-hover-border, rgba(148, 163, 184, 0.35));
@@ -2811,12 +2829,16 @@ function ensureSceneStyles(doc) {
2811
2829
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.12);
2812
2830
  }
2813
2831
  .markdy-controls button[aria-pressed="true"] {
2832
+ position: relative;
2833
+ z-index: 2;
2814
2834
  background: var(--accent, #10b981) !important;
2815
2835
  color: #ffffff !important;
2816
2836
  border-color: var(--accent, #10b981) !important;
2817
2837
  box-shadow: 0 0 10px var(--accent-glow, rgba(16, 185, 129, 0.4)) !important;
2818
2838
  }
2819
2839
  .markdy-controls button:focus-visible {
2840
+ position: relative;
2841
+ z-index: 3;
2820
2842
  outline: 2px solid var(--accent, #10b981);
2821
2843
  outline-offset: 1px;
2822
2844
  }
@@ -2910,10 +2932,10 @@ function ensureSceneStyles(doc) {
2910
2932
  .markdy-code-panel-overlay {
2911
2933
  position: fixed;
2912
2934
  inset: 0;
2913
- z-index: 9000;
2914
- background: rgba(2, 6, 23, 0.55);
2915
- backdrop-filter: blur(3px);
2916
- -webkit-backdrop-filter: blur(3px);
2935
+ z-index: 100000;
2936
+ background: rgba(2, 6, 23, 0.65);
2937
+ backdrop-filter: blur(4px);
2938
+ -webkit-backdrop-filter: blur(4px);
2917
2939
  display: flex;
2918
2940
  align-items: center;
2919
2941
  justify-content: center;
@@ -3176,37 +3198,13 @@ function ensureSceneStyles(doc) {
3176
3198
  color: #64748b !important;
3177
3199
  }
3178
3200
  /* Fullscreen & Fallback Pseudo-Fullscreen Views */
3201
+ .markdy-diagram-root:fullscreen,
3202
+ .markdy-diagram-root:-webkit-full-screen,
3203
+ .markdy-diagram-root:-moz-full-screen,
3204
+ .markdy-diagram-root:-ms-fullscreen,
3205
+ .markdy-viewport:fullscreen,
3206
+ .markdy-viewport:-webkit-full-screen,
3179
3207
  .markdy-fullscreen-host,
3180
- :fullscreen {
3181
- background-color: var(--md-canvas, #0b101b) !important;
3182
- width: 100vw !important;
3183
- height: 100vh !important;
3184
- max-width: 100vw !important;
3185
- max-height: 100vh !important;
3186
- box-sizing: border-box !important;
3187
- display: flex !important;
3188
- flex-direction: column !important;
3189
- justify-content: space-between !important;
3190
- align-items: center !important;
3191
- padding: 16px 20px 12px !important;
3192
- overflow: hidden !important;
3193
- }
3194
- .markdy-fullscreen-host .markdy-viewport,
3195
- :fullscreen .markdy-viewport {
3196
- flex: 1 1 auto !important;
3197
- width: 100% !important;
3198
- height: 100% !important;
3199
- max-width: 100% !important;
3200
- max-height: calc(100vh - 64px) !important;
3201
- }
3202
- .markdy-fullscreen-host .markdy-footer,
3203
- :fullscreen .markdy-footer {
3204
- flex-shrink: 0 !important;
3205
- width: 100% !important;
3206
- max-width: 1400px !important;
3207
- margin: 0 auto !important;
3208
- padding: 8px 12px 4px !important;
3209
- }
3210
3208
  .markdy--pseudo-fullscreen {
3211
3209
  position: fixed !important;
3212
3210
  inset: 0 !important;
@@ -3216,21 +3214,34 @@ function ensureSceneStyles(doc) {
3216
3214
  max-width: 100vw !important;
3217
3215
  max-height: 100vh !important;
3218
3216
  background-color: var(--md-canvas, #0b101b) !important;
3217
+ box-sizing: border-box !important;
3219
3218
  display: flex !important;
3220
3219
  flex-direction: column !important;
3221
3220
  justify-content: space-between !important;
3222
3221
  align-items: center !important;
3223
3222
  padding: 16px 20px 12px !important;
3224
- box-sizing: border-box !important;
3225
3223
  overflow: hidden !important;
3226
3224
  }
3225
+ .markdy-diagram-root:fullscreen .markdy-viewport,
3226
+ .markdy-diagram-root:-webkit-full-screen .markdy-viewport,
3227
+ .markdy-diagram-root:-moz-full-screen .markdy-viewport,
3228
+ .markdy-diagram-root:-ms-fullscreen .markdy-viewport,
3229
+ .markdy-fullscreen-host .markdy-viewport,
3227
3230
  .markdy--pseudo-fullscreen .markdy-viewport {
3228
3231
  flex: 1 1 auto !important;
3229
3232
  width: 100% !important;
3230
3233
  height: 100% !important;
3231
3234
  max-width: 100% !important;
3232
3235
  max-height: calc(100vh - 64px) !important;
3236
+ display: flex !important;
3237
+ align-items: center !important;
3238
+ justify-content: center !important;
3233
3239
  }
3240
+ .markdy-diagram-root:fullscreen .markdy-footer,
3241
+ .markdy-diagram-root:-webkit-full-screen .markdy-footer,
3242
+ .markdy-diagram-root:-moz-full-screen .markdy-footer,
3243
+ .markdy-diagram-root:-ms-fullscreen .markdy-footer,
3244
+ .markdy-fullscreen-host .markdy-footer,
3234
3245
  .markdy--pseudo-fullscreen .markdy-footer {
3235
3246
  flex-shrink: 0 !important;
3236
3247
  width: 100% !important;
@@ -3432,6 +3443,16 @@ function createDiagram(opts) {
3432
3443
  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%)";
3433
3444
  const totalDurationMs = plan.duration * 1e3;
3434
3445
  const durationSeconds = plan.duration;
3446
+ container.classList.add("markdy-diagram-root");
3447
+ Object.assign(container.style, {
3448
+ position: "relative",
3449
+ display: "flex",
3450
+ flexDirection: "column",
3451
+ boxSizing: "border-box",
3452
+ width: "100%"
3453
+ });
3454
+ if (container.style.aspectRatio) container.style.aspectRatio = "unset";
3455
+ if (container.style.overflow === "hidden") container.style.overflow = "visible";
3435
3456
  const viewport = document.createElement("div");
3436
3457
  viewport.className = "markdy-viewport";
3437
3458
  Object.assign(viewport.style, {
@@ -3448,6 +3469,7 @@ function createDiagram(opts) {
3448
3469
  let progressEl = null;
3449
3470
  if (showProgress) {
3450
3471
  progressEl = document.createElement("div");
3472
+ progressEl.className = progressMode === "bar" ? "markdy-progress-bar" : "markdy-boundary-progress";
3451
3473
  Object.assign(progressEl.style, {
3452
3474
  position: "absolute",
3453
3475
  ...progressMode === "bar" ? { left: "0", right: "0", bottom: "0", height: "3px" } : { inset: "0" },
@@ -3483,6 +3505,8 @@ function createDiagram(opts) {
3483
3505
  footer.className = "markdy-footer";
3484
3506
  applyThemeVariables(footer, plan.theme);
3485
3507
  Object.assign(footer.style, {
3508
+ position: "relative",
3509
+ zIndex: "100",
3486
3510
  display: "flex",
3487
3511
  alignItems: "center",
3488
3512
  justifyContent: "space-between",
@@ -3490,11 +3514,10 @@ function createDiagram(opts) {
3490
3514
  gap: "6px",
3491
3515
  width: "100%",
3492
3516
  boxSizing: "border-box",
3493
- padding: "4px 6px 0",
3517
+ padding: "6px 8px 2px",
3494
3518
  background: "transparent"
3495
3519
  });
3496
- if (container.parentNode) container.parentNode.insertBefore(footer, container.nextSibling);
3497
- else container.appendChild(footer);
3520
+ container.appendChild(footer);
3498
3521
  return footer;
3499
3522
  }
3500
3523
  let badge = null;
@@ -4039,8 +4062,11 @@ function createDiagram(opts) {
4039
4062
  removeFullscreenListeners?.();
4040
4063
  closeCodePanel?.();
4041
4064
  closeCodePanel = null;
4065
+ container.classList.remove("markdy-diagram-root");
4066
+ container.classList.remove("markdy-fullscreen-host");
4067
+ container.classList.remove("markdy--pseudo-fullscreen");
4042
4068
  if (progressEl?.parentNode === viewport) viewport.removeChild(progressEl);
4043
- if (footer?.parentNode) footer.parentNode.removeChild(footer);
4069
+ if (footer?.parentNode === container) container.removeChild(footer);
4044
4070
  if (viewport.parentNode === container) container.removeChild(viewport);
4045
4071
  }
4046
4072
  };
@@ -4299,7 +4325,8 @@ function createDiagram(opts) {
4299
4325
  body.appendChild(pre);
4300
4326
  panel.append(header, body);
4301
4327
  overlay.appendChild(panel);
4302
- document.body.appendChild(overlay);
4328
+ const mountHost = document.fullscreenElement ?? document.body;
4329
+ mountHost.appendChild(overlay);
4303
4330
  closeBtn.focus();
4304
4331
  let closing = false;
4305
4332
  function removePanel() {
@@ -4347,10 +4374,10 @@ function createDiagram(opts) {
4347
4374
  const button = makeControlButton("Full", "Toggle fullscreen view", ICONS2.fullscreen);
4348
4375
  button.className = "markdy-control-fullscreen";
4349
4376
  button.setAttribute("aria-pressed", "false");
4350
- const host = footer && footer.parentElement ? footer.parentElement : container.parentElement ?? container;
4377
+ const host = container;
4351
4378
  let isPseudoFull = false;
4352
4379
  function syncFullscreenState() {
4353
- const isFull = isPseudoFull || document.fullscreenElement === host || document.fullscreenElement === container || document.fullscreenElement === viewport || document.webkitFullscreenElement === host || document.webkitFullscreenElement === container;
4380
+ const isFull = isPseudoFull || document.fullscreenElement === host || document.fullscreenElement === viewport || document.webkitFullscreenElement === host || document.webkitFullscreenElement === viewport || document.mozFullScreenElement === host || document.msFullscreenElement === host;
4354
4381
  button.setAttribute("aria-pressed", isFull ? "true" : "false");
4355
4382
  button.title = isFull ? "Exit fullscreen" : "Toggle fullscreen view";
4356
4383
  button.innerHTML = isFull ? `${ICONS2.fullscreen}Exit` : `${ICONS2.fullscreen}Full`;
@@ -4361,15 +4388,16 @@ function createDiagram(opts) {
4361
4388
  host.classList.remove("markdy--pseudo-fullscreen");
4362
4389
  }
4363
4390
  requestAnimationFrame(() => {
4391
+ scaleScene();
4364
4392
  applyViewportTransform();
4365
4393
  syncControls();
4366
4394
  });
4367
4395
  }
4368
4396
  async function toggleFullscreen() {
4369
4397
  try {
4370
- const isCurrentlyFull = isPseudoFull || document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
4398
+ const isCurrentlyFull = isPseudoFull || document.fullscreenElement === host || document.fullscreenElement === viewport || document.webkitFullscreenElement === host || document.mozFullScreenElement === host || document.msFullscreenElement === host;
4371
4399
  if (!isCurrentlyFull) {
4372
- const req = host.requestFullscreen?.bind(host) || host.webkitRequestFullscreen?.bind(host) || host.mozRequestFullScreen?.bind(host) || host.msRequestFullscreen?.bind(host) || container.requestFullscreen?.bind(container) || container.webkitRequestFullscreen?.bind(container);
4400
+ const req = host.requestFullscreen?.bind(host) || host.webkitRequestFullscreen?.bind(host) || host.mozRequestFullScreen?.bind(host) || host.msRequestFullscreen?.bind(host) || viewport.requestFullscreen?.bind(viewport) || viewport.webkitRequestFullscreen?.bind(viewport);
4373
4401
  if (req) {
4374
4402
  try {
4375
4403
  await req();
@@ -4395,7 +4423,7 @@ function createDiagram(opts) {
4395
4423
  }
4396
4424
  }
4397
4425
  }
4398
- } catch (err) {
4426
+ } catch {
4399
4427
  if (!isPseudoFull) {
4400
4428
  isPseudoFull = true;
4401
4429
  host.classList.add("markdy--pseudo-fullscreen");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markdy/renderer-dom",
3
- "version": "1.0.20",
3
+ "version": "1.0.22",
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",
@@ -45,14 +45,14 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "html2canvas": "^1.4.1",
48
- "@markdy/core": "1.0.20"
48
+ "@markdy/core": "1.0.22"
49
49
  },
50
50
  "devDependencies": {
51
51
  "jsdom": "^29.1.1",
52
52
  "tsup": "^8.5.1",
53
53
  "typescript": "^5.9.3",
54
54
  "vitest": "^4.1.7",
55
- "@markdy/stdlib-systems": "1.0.20"
55
+ "@markdy/stdlib-systems": "1.0.22"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsup",