@markdy/renderer-dom 1.0.16 → 1.0.18

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 +172 -38
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -2626,28 +2626,37 @@ function ensureSceneStyles(doc) {
2626
2626
  transform: translateY(-1px) scale(1.02);
2627
2627
  }
2628
2628
  .markdy-badge {
2629
+ position: absolute;
2630
+ top: 10px;
2631
+ right: 12px;
2632
+ z-index: 25;
2629
2633
  display: inline-flex;
2630
2634
  align-items: center;
2631
2635
  gap: 4px;
2632
2636
  font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
2633
- font-size: 11px;
2634
- font-weight: 600;
2635
- color: var(--md-control-text, #94a3b8);
2637
+ font-size: 10px;
2638
+ font-weight: 500;
2639
+ letter-spacing: 0.02em;
2640
+ color: var(--md-text-muted, #94a3b8);
2636
2641
  text-decoration: none;
2637
- padding: 3px 8px;
2638
- border-radius: 999px;
2639
- background: var(--md-control-bg, rgba(255, 255, 255, 0.05));
2640
- border: 1px solid var(--md-control-border, rgba(148, 163, 184, 0.18));
2641
- margin-left: auto;
2642
- flex-shrink: 0;
2643
- transition: all 0.15s ease;
2644
- white-space: nowrap;
2642
+ padding: 2.5px 7px;
2643
+ border-radius: 5px;
2644
+ background: var(--md-surface, rgba(15, 23, 42, 0.45));
2645
+ border: 1px solid var(--md-border, rgba(148, 163, 184, 0.15));
2646
+ backdrop-filter: blur(4px);
2647
+ -webkit-backdrop-filter: blur(4px);
2648
+ opacity: 0.65;
2649
+ transition: all 0.2s ease;
2650
+ pointer-events: auto;
2651
+ user-select: none;
2645
2652
  }
2646
2653
  .markdy-badge:hover {
2654
+ opacity: 1;
2647
2655
  color: var(--accent, #10b981);
2648
- background: var(--accent-light, rgba(16, 185, 129, 0.12));
2649
2656
  border-color: var(--accent, #10b981);
2657
+ background: var(--md-surface-raised, rgba(15, 23, 42, 0.75));
2650
2658
  transform: translateY(-1px);
2659
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
2651
2660
  }
2652
2661
  .markdy-speed-group {
2653
2662
  display: inline-flex;
@@ -2997,6 +3006,69 @@ function ensureSceneStyles(doc) {
2997
3006
  opacity: 1 !important;
2998
3007
  color: #64748b !important;
2999
3008
  }
3009
+ /* Fullscreen & Fallback Pseudo-Fullscreen Views */
3010
+ .markdy-fullscreen-host,
3011
+ :fullscreen {
3012
+ background-color: var(--md-canvas, #0b101b) !important;
3013
+ width: 100vw !important;
3014
+ height: 100vh !important;
3015
+ max-width: 100vw !important;
3016
+ max-height: 100vh !important;
3017
+ box-sizing: border-box !important;
3018
+ display: flex !important;
3019
+ flex-direction: column !important;
3020
+ justify-content: space-between !important;
3021
+ align-items: center !important;
3022
+ padding: 16px 20px 12px !important;
3023
+ overflow: hidden !important;
3024
+ }
3025
+ .markdy-fullscreen-host .markdy-viewport,
3026
+ :fullscreen .markdy-viewport {
3027
+ flex: 1 1 auto !important;
3028
+ width: 100% !important;
3029
+ height: 100% !important;
3030
+ max-width: 100% !important;
3031
+ max-height: calc(100vh - 64px) !important;
3032
+ }
3033
+ .markdy-fullscreen-host .markdy-footer,
3034
+ :fullscreen .markdy-footer {
3035
+ flex-shrink: 0 !important;
3036
+ width: 100% !important;
3037
+ max-width: 1400px !important;
3038
+ margin: 0 auto !important;
3039
+ padding: 8px 12px 4px !important;
3040
+ }
3041
+ .markdy--pseudo-fullscreen {
3042
+ position: fixed !important;
3043
+ inset: 0 !important;
3044
+ z-index: 999999 !important;
3045
+ width: 100vw !important;
3046
+ height: 100vh !important;
3047
+ max-width: 100vw !important;
3048
+ max-height: 100vh !important;
3049
+ background-color: var(--md-canvas, #0b101b) !important;
3050
+ display: flex !important;
3051
+ flex-direction: column !important;
3052
+ justify-content: space-between !important;
3053
+ align-items: center !important;
3054
+ padding: 16px 20px 12px !important;
3055
+ box-sizing: border-box !important;
3056
+ overflow: hidden !important;
3057
+ }
3058
+ .markdy--pseudo-fullscreen .markdy-viewport {
3059
+ flex: 1 1 auto !important;
3060
+ width: 100% !important;
3061
+ height: 100% !important;
3062
+ max-width: 100% !important;
3063
+ max-height: calc(100vh - 64px) !important;
3064
+ }
3065
+ .markdy--pseudo-fullscreen .markdy-footer {
3066
+ flex-shrink: 0 !important;
3067
+ width: 100% !important;
3068
+ max-width: 1400px !important;
3069
+ margin: 0 auto !important;
3070
+ padding: 8px 12px 4px !important;
3071
+ }
3000
3072
  @media (prefers-reduced-motion: reduce) {
3001
3073
  .markdy-node,
3002
3074
  .markdy-beat-caption,
@@ -3238,18 +3310,6 @@ function createDiagram(opts) {
3238
3310
  else container.appendChild(footer);
3239
3311
  return footer;
3240
3312
  }
3241
- let badge = null;
3242
- if (copyright) {
3243
- badge = document.createElement("a");
3244
- badge.className = "markdy-badge";
3245
- badge.href = `${MARKDY_PLAYGROUND_URL}#code=${encodeCodeForPlaygroundHash(code)}`;
3246
- badge.target = "_blank";
3247
- badge.rel = "noopener noreferrer";
3248
- badge.title = "Open and edit in Markdy Playground";
3249
- badge.style.marginLeft = "auto";
3250
- badge.innerHTML = `<span style="opacity:0.9">\u26A1</span> Markdy`;
3251
- ensureFooter().appendChild(badge);
3252
- }
3253
3313
  ensureSceneStyles(document);
3254
3314
  ensureNodeStyles(document);
3255
3315
  const scene = document.createElement("div");
@@ -3266,6 +3326,17 @@ function createDiagram(opts) {
3266
3326
  });
3267
3327
  applyThemeToScene(scene, plan.theme);
3268
3328
  viewport.appendChild(scene);
3329
+ let badge = null;
3330
+ if (copyright) {
3331
+ badge = document.createElement("a");
3332
+ badge.className = "markdy-badge";
3333
+ badge.href = "https://markdy.com";
3334
+ badge.target = "_blank";
3335
+ badge.rel = "noopener noreferrer";
3336
+ badge.title = "Powered by Markdy - Diagram as Code";
3337
+ badge.textContent = "Powered by Markdy";
3338
+ viewport.appendChild(badge);
3339
+ }
3269
3340
  const viewportTransform = document.createElement("div");
3270
3341
  viewportTransform.className = "markdy-viewport-transform";
3271
3342
  Object.assign(viewportTransform.style, {
@@ -3695,6 +3766,7 @@ function createDiagram(opts) {
3695
3766
  }
3696
3767
  for (const anim of allAnims) anim.cancel();
3697
3768
  resizeObserver?.disconnect();
3769
+ removeFullscreenListeners?.();
3698
3770
  if (progressEl?.parentNode === viewport) viewport.removeChild(progressEl);
3699
3771
  if (badge?.parentNode) badge.parentNode.removeChild(badge);
3700
3772
  if (footer?.parentNode) footer.parentNode.removeChild(footer);
@@ -3978,37 +4050,99 @@ function createDiagram(opts) {
3978
4050
  button.addEventListener("click", resetViewportTransform);
3979
4051
  toolbar.appendChild(button);
3980
4052
  }
4053
+ let removeFullscreenListeners = null;
3981
4054
  function mountFullscreenControl(toolbar) {
3982
4055
  if (!fullscreenButton) return;
3983
4056
  const button = makeControlButton("Full", "Toggle fullscreen view", ICONS2.fullscreen);
3984
4057
  button.className = "markdy-control-fullscreen";
3985
4058
  button.setAttribute("aria-pressed", "false");
3986
- const host = container.parentElement ?? container;
4059
+ const host = footer && footer.parentElement ? footer.parentElement : container.parentElement ?? container;
4060
+ let isPseudoFull = false;
3987
4061
  function syncFullscreenState() {
3988
- const isFull = document.fullscreenElement === host || document.fullscreenElement === container || document.fullscreenElement === viewport;
4062
+ const isFull = isPseudoFull || document.fullscreenElement === host || document.fullscreenElement === container || document.fullscreenElement === viewport || document.webkitFullscreenElement === host || document.webkitFullscreenElement === container;
3989
4063
  button.setAttribute("aria-pressed", isFull ? "true" : "false");
3990
4064
  button.title = isFull ? "Exit fullscreen" : "Toggle fullscreen view";
4065
+ button.innerHTML = isFull ? `${ICONS2.fullscreen}Exit` : `${ICONS2.fullscreen}Full`;
4066
+ if (isFull) {
4067
+ host.classList.add("markdy-fullscreen-host");
4068
+ } else {
4069
+ host.classList.remove("markdy-fullscreen-host");
4070
+ host.classList.remove("markdy--pseudo-fullscreen");
4071
+ }
4072
+ requestAnimationFrame(() => {
4073
+ applyViewportTransform();
4074
+ syncControls();
4075
+ });
3991
4076
  }
3992
- button.addEventListener("click", async () => {
4077
+ async function toggleFullscreen() {
3993
4078
  try {
3994
- if (!document.fullscreenElement) {
3995
- if (host.requestFullscreen) {
3996
- await host.requestFullscreen();
3997
- } else if (host.webkitRequestFullscreen) {
3998
- await host.webkitRequestFullscreen();
4079
+ const isCurrentlyFull = isPseudoFull || document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
4080
+ if (!isCurrentlyFull) {
4081
+ 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);
4082
+ if (req) {
4083
+ try {
4084
+ await req();
4085
+ } catch {
4086
+ isPseudoFull = true;
4087
+ host.classList.add("markdy--pseudo-fullscreen");
4088
+ syncFullscreenState();
4089
+ }
4090
+ } else {
4091
+ isPseudoFull = true;
4092
+ host.classList.add("markdy--pseudo-fullscreen");
4093
+ syncFullscreenState();
3999
4094
  }
4000
4095
  } else {
4001
- if (document.exitFullscreen) {
4002
- await document.exitFullscreen();
4003
- } else if (document.webkitExitFullscreen) {
4004
- await document.webkitExitFullscreen();
4096
+ if (isPseudoFull) {
4097
+ isPseudoFull = false;
4098
+ host.classList.remove("markdy--pseudo-fullscreen");
4099
+ syncFullscreenState();
4100
+ } else {
4101
+ const exit = document.exitFullscreen?.bind(document) || document.webkitExitFullscreen?.bind(document) || document.mozCancelFullScreen?.bind(document) || document.msExitFullscreen?.bind(document);
4102
+ if (exit) {
4103
+ await exit();
4104
+ }
4005
4105
  }
4006
4106
  }
4007
4107
  } catch (err) {
4008
- onWarning({ severity: "warning", message: `Fullscreen toggle failed: ${String(err)}`, line: 0 });
4108
+ if (!isPseudoFull) {
4109
+ isPseudoFull = true;
4110
+ host.classList.add("markdy--pseudo-fullscreen");
4111
+ syncFullscreenState();
4112
+ } else {
4113
+ isPseudoFull = false;
4114
+ host.classList.remove("markdy--pseudo-fullscreen");
4115
+ syncFullscreenState();
4116
+ }
4009
4117
  }
4118
+ }
4119
+ button.addEventListener("click", (e) => {
4120
+ e.stopPropagation();
4121
+ toggleFullscreen();
4010
4122
  });
4123
+ const handleEscKey = (e) => {
4124
+ if (e.key === "Escape" && isPseudoFull) {
4125
+ isPseudoFull = false;
4126
+ host.classList.remove("markdy--pseudo-fullscreen");
4127
+ syncFullscreenState();
4128
+ }
4129
+ };
4011
4130
  document.addEventListener("fullscreenchange", syncFullscreenState);
4131
+ document.addEventListener("webkitfullscreenchange", syncFullscreenState);
4132
+ document.addEventListener("mozfullscreenchange", syncFullscreenState);
4133
+ document.addEventListener("MSFullscreenChange", syncFullscreenState);
4134
+ window.addEventListener("keydown", handleEscKey);
4135
+ removeFullscreenListeners = () => {
4136
+ document.removeEventListener("fullscreenchange", syncFullscreenState);
4137
+ document.removeEventListener("webkitfullscreenchange", syncFullscreenState);
4138
+ document.removeEventListener("mozfullscreenchange", syncFullscreenState);
4139
+ document.removeEventListener("MSFullscreenChange", syncFullscreenState);
4140
+ window.removeEventListener("keydown", handleEscKey);
4141
+ if (isPseudoFull) {
4142
+ host.classList.remove("markdy--pseudo-fullscreen");
4143
+ host.classList.remove("markdy-fullscreen-host");
4144
+ }
4145
+ };
4012
4146
  toolbar.appendChild(button);
4013
4147
  }
4014
4148
  function handleKeyDown(event) {
@@ -4104,7 +4238,7 @@ function createDiagram(opts) {
4104
4238
  mountCodeControl(toolsGroup);
4105
4239
  }
4106
4240
  if (toolsGroup.children.length > 0) toolbar.appendChild(toolsGroup);
4107
- ensureFooter().insertBefore(toolbar, badge ?? null);
4241
+ ensureFooter().appendChild(toolbar);
4108
4242
  syncControls();
4109
4243
  }
4110
4244
  viewport.style.cursor = interactiveViewport ? "grab" : "pointer";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markdy/renderer-dom",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
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.16"
48
+ "@markdy/core": "1.0.18"
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.16"
55
+ "@markdy/stdlib-systems": "1.0.18"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsup",