@diagrammo/dgmo 0.44.1 → 0.46.0

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/element.cjs CHANGED
@@ -5052,10 +5052,7 @@ function renderLegendD3(container, config, state, palette, isDark, callbacks, co
5052
5052
  legendG.selectAll("*").remove();
5053
5053
  if (currentLayout.height === 0) return;
5054
5054
  if (currentState.activeGroup) {
5055
- legendG.attr(
5056
- "data-legend-active",
5057
- currentState.activeGroup.toLowerCase()
5058
- );
5055
+ legendG.attr("data-legend-active", tagAttrKey(currentState.activeGroup));
5059
5056
  } else {
5060
5057
  legendG.attr("data-legend-active", null);
5061
5058
  }
@@ -5862,7 +5859,7 @@ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setu
5862
5859
  if (currentActiveGroup) {
5863
5860
  legendContainer.attr(
5864
5861
  "data-legend-active",
5865
- currentActiveGroup.toLowerCase()
5862
+ tagAttrKey(currentActiveGroup)
5866
5863
  );
5867
5864
  }
5868
5865
  const iconAddon = viewMode ? 0 : LG_ICON_W;
@@ -25559,7 +25556,7 @@ function renderLegendSvg(groups, options) {
25559
25556
  track(pill.x, pill.y, pill.width, pill.height);
25560
25557
  }
25561
25558
  const classAttr = className ? ` class="${esc(className)}"` : "";
25562
- const activeAttr = activeGroup ? ` data-legend-active="${esc(activeGroup.toLowerCase())}"` : "";
25559
+ const activeAttr = activeGroup ? ` data-legend-active="${esc(tagAttrKey(activeGroup))}"` : "";
25563
25560
  const svg = `<g${classAttr}${activeAttr}>${parts.join("")}</g>`;
25564
25561
  return {
25565
25562
  svg,
@@ -28040,7 +28037,7 @@ var init_renderer2 = __esm({
28040
28037
  COLLAPSED = "dgmo-evt-collapsed";
28041
28038
  OFF = "dgmo-evt-off";
28042
28039
  HIDDEN_ATTR = "data-evt-hidden";
28043
- HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{text-decoration:line-through;opacity:.5}`;
28040
+ HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{opacity:.5}`;
28044
28041
  DIMMABLE_SEL = ".dgmo-event-dot,.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era";
28045
28042
  PIN_ATTR = "data-evt-pin";
28046
28043
  }
@@ -30874,7 +30871,7 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
30874
30871
  if (fixedLegend) {
30875
30872
  const legendParent = svg.append("g").attr("class", "sitemap-legend-fixed").attr("transform", `translate(0, ${sDiagramPadding + fixedTitleH})`);
30876
30873
  if (activeTagGroup) {
30877
- legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
30874
+ legendParent.attr("data-legend-active", tagAttrKey(activeTagGroup));
30878
30875
  }
30879
30876
  renderLegend(
30880
30877
  legendParent,
@@ -37268,7 +37265,7 @@ function renderSwimlaneForExport(container, parsed, layout, palette, isDark, opt
37268
37265
  const titleOffset = parsed.title ? 40 : 0;
37269
37266
  const width = opts.exportDims?.width ?? layout.width;
37270
37267
  const height = (opts.exportDims?.height ?? layout.height) + 0;
37271
- const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).style("font-family", FONT_FAMILY);
37268
+ const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").style("font-family", FONT_FAMILY);
37272
37269
  const defs = svg.append("defs");
37273
37270
  const baseBg = themeBaseBg(palette, isDark);
37274
37271
  const ev = {
@@ -41296,7 +41293,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
41296
41293
  if (hasLegend) {
41297
41294
  const legendParent = fixedLegend ? svg.append("g").attr("class", "c4-legend-fixed").attr("transform", `translate(0, ${DIAGRAM_PADDING8 + titleHeight})`) : contentG.append("g").attr("class", "c4-legend");
41298
41295
  if (activeTagGroup) {
41299
- legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
41296
+ legendParent.attr("data-legend-active", tagAttrKey(activeTagGroup));
41300
41297
  }
41301
41298
  renderLegend2(
41302
41299
  legendParent,
@@ -41911,7 +41908,7 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
41911
41908
  if (hasLegend) {
41912
41909
  const legendParent = fixedLegend ? svg.append("g").attr("class", "c4-legend-fixed").attr("transform", `translate(0, ${DIAGRAM_PADDING8 + titleHeight})`) : contentG.append("g").attr("class", "c4-legend");
41913
41910
  if (activeTagGroup) {
41914
- legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
41911
+ legendParent.attr("data-legend-active", tagAttrKey(activeTagGroup));
41915
41912
  }
41916
41913
  renderLegend2(
41917
41914
  legendParent,
@@ -45584,7 +45581,7 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
45584
45581
  const appHostedPlayback = controlsHost === "app" && !!playback;
45585
45582
  const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
45586
45583
  if (activeGroup) {
45587
- legendG.attr("data-legend-active", activeGroup.toLowerCase());
45584
+ legendG.attr("data-legend-active", tagAttrKey(activeGroup));
45588
45585
  }
45589
45586
  const allGroups = legendGroups.map((g) => ({
45590
45587
  name: g.name,
@@ -68653,6 +68650,7 @@ async function exportVisualization(ctx) {
68653
68650
  init_charts_d3();
68654
68651
 
68655
68652
  // src/utils/hover-styles.ts
68653
+ init_tag_groups();
68656
68654
  var MAX_HOVER_GROUPS = 40;
68657
68655
  var DEFAULT_DIM_OPACITY = 0.4;
68658
68656
  var LIFT_DECL = "filter:saturate(1.4) brightness(1.06)";
@@ -69047,7 +69045,7 @@ function deriveFromSvg(svg, spec) {
69047
69045
  if (spec.groupAttrMode === "tag-active") {
69048
69046
  const slug = root.querySelector("[data-legend-active]")?.getAttribute("data-legend-active");
69049
69047
  if (slug) {
69050
- groupAttr = `data-tag-${slug}`;
69048
+ groupAttr = `data-tag-${tagAttrKey(slug)}`;
69051
69049
  } else {
69052
69050
  const names = /* @__PURE__ */ new Set();
69053
69051
  root.querySelectorAll(spec.markSelector).forEach((el) => {
@@ -69102,10 +69100,16 @@ var DOM_GLOBALS = [
69102
69100
  "HTMLElement",
69103
69101
  "SVGElement"
69104
69102
  ];
69105
- var domRefCount = 0;
69106
- var domInstallPromise = null;
69107
- var domInstalledByUs = false;
69108
- async function installDom() {
69103
+ var DOM_STATE_KEY = /* @__PURE__ */ Symbol.for("diagrammo.dgmo.dom-globals");
69104
+ function domState() {
69105
+ const g = globalThis;
69106
+ return g[DOM_STATE_KEY] ??= {
69107
+ refCount: 0,
69108
+ installPromise: null,
69109
+ installedByUs: false
69110
+ };
69111
+ }
69112
+ async function installDom(state) {
69109
69113
  const { JSDOM } = await loadJsdom();
69110
69114
  const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
69111
69115
  url: "http://localhost/"
@@ -69124,23 +69128,25 @@ async function installDom() {
69124
69128
  configurable: true
69125
69129
  });
69126
69130
  }
69127
- domInstalledByUs = true;
69131
+ state.installedByUs = true;
69128
69132
  }
69129
69133
  async function acquireDom() {
69130
- if (typeof document !== "undefined" && !domInstalledByUs) return;
69131
- domRefCount++;
69132
- if (!domInstallPromise) domInstallPromise = installDom();
69133
- await domInstallPromise;
69134
+ const state = domState();
69135
+ if (typeof document !== "undefined" && !state.installedByUs) return;
69136
+ state.refCount++;
69137
+ if (!state.installPromise) state.installPromise = installDom(state);
69138
+ await state.installPromise;
69134
69139
  }
69135
69140
  function releaseDom() {
69136
- if (!domInstalledByUs) return;
69137
- if (--domRefCount > 0) return;
69141
+ const state = domState();
69142
+ if (!state.installedByUs) return;
69143
+ if (--state.refCount > 0) return;
69138
69144
  for (const key of DOM_GLOBALS) {
69139
69145
  delete globalThis[key];
69140
69146
  }
69141
- domInstalledByUs = false;
69142
- domInstallPromise = null;
69143
- domRefCount = 0;
69147
+ state.installedByUs = false;
69148
+ state.installPromise = null;
69149
+ state.refCount = 0;
69144
69150
  }
69145
69151
  async function loadJsdom() {
69146
69152
  const spec = ["js", "dom"].join("");
@@ -69265,6 +69271,9 @@ function encodeDiagramUrl(dsl, options) {
69265
69271
  return { url: `${baseUrl}?${hash}#${hash}` };
69266
69272
  }
69267
69273
 
69274
+ // src/embed/index.ts
69275
+ init_palettes();
69276
+
69268
69277
  // src/editor/dgmo.grammar.js
69269
69278
  var import_lr = require("@lezer/lr");
69270
69279
 
@@ -69647,230 +69656,426 @@ function markTokensInRange(tokens, from, to, role) {
69647
69656
  }
69648
69657
  }
69649
69658
 
69650
- // src/auto/styles.ts
69651
- var CSS = `
69652
- /* anti-flash: hide source elements until either render swaps them out
69653
- or the error path explicitly un-hides them */
69654
- pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
69655
- .dgmo:not(svg *):not(.dgmo-rendered):not(.dgmo-rendered *) {
69656
- visibility: hidden;
69659
+ // src/embed/escape.ts
69660
+ var HTML_ENTITIES = {
69661
+ "&": "&amp;",
69662
+ "<": "&lt;",
69663
+ ">": "&gt;",
69664
+ '"': "&quot;",
69665
+ "'": "&#39;"
69666
+ };
69667
+ function escapeHtml3(s) {
69668
+ return s.replace(/[&<>"']/g, (ch) => HTML_ENTITIES[ch] ?? ch);
69657
69669
  }
69658
- .dgmo-rendered, .dgmo-rendered *,
69659
- .dgmo-error-banner, .dgmo-error-banner * {
69660
- visibility: visible !important;
69670
+ function escapeAttr(s) {
69671
+ return s.replace(/[&<>"']/g, (ch) => HTML_ENTITIES[ch] ?? ch);
69661
69672
  }
69662
69673
 
69663
- .dgmo-rendered {
69674
+ // src/embed/css.ts
69675
+ var BLOCK_CSS = `
69676
+ /* @diagrammo/dgmo block \u2014 standard embed chrome.
69677
+ * Override the [data-theme="dark"] selectors if your site uses .dark or
69678
+ * another color-mode convention. */
69679
+
69680
+ /* === Color-mode visibility (dual-render) === */
69681
+ .dgmo-dark {
69682
+ display: none;
69683
+ }
69684
+ [data-theme="dark"] .dgmo-light {
69685
+ display: none;
69686
+ }
69687
+ [data-theme="dark"] .dgmo-dark {
69664
69688
  display: block;
69665
- position: relative;
69666
- margin: 1em 0;
69667
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
69668
- Oxygen, Ubuntu, Cantarell, sans-serif;
69669
- font-size: 14px;
69670
- line-height: 1.4;
69671
- color-scheme: light dark;
69672
69689
  }
69673
- .dgmo-rendered svg {
69690
+
69691
+ /* === Diagram sizing ===
69692
+ * SVGs are emitted with viewBox only (no fixed width/height). Force them to
69693
+ * fill their wrapper so light and dark variants render at identical sizes. */
69694
+ .dgmo-light > svg,
69695
+ .dgmo-dark > svg,
69696
+ .dgmo-svg > svg {
69674
69697
  display: block;
69675
- max-width: 100%;
69698
+ width: 100%;
69676
69699
  height: auto;
69700
+ max-width: 100%;
69677
69701
  }
69678
69702
 
69679
- .dgmo-source-panel {
69680
- margin-top: 4px;
69681
- position: relative;
69703
+ /* === Toolbar ===
69704
+ * The diagram is the star: the toolbar is a slim reserved row below the SVG
69705
+ * (height always in flow \u2014 no layout shift) that stays fully transparent
69706
+ * until the block is hovered or focused, or the source panel is open. It is
69707
+ * the <summary> of the source <details>, so toggling works without any JS.
69708
+ * No text labels, no disclosure triangle \u2014 three wordless icon buttons. */
69709
+ .dgmo-source-wrap {
69710
+ margin: 0;
69711
+ }
69712
+ .dgmo-toolbar {
69713
+ display: flex;
69714
+ align-items: center;
69715
+ justify-content: flex-end;
69716
+ gap: 0.25em;
69717
+ min-height: 1.9em;
69718
+ padding: 0.15em 0;
69719
+ opacity: 0;
69720
+ transition: opacity 0.15s ease;
69721
+ cursor: pointer;
69722
+ list-style: none;
69723
+ user-select: none;
69724
+ color: rgba(127, 127, 127, 0.9);
69725
+ }
69726
+ .dgmo-toolbar::-webkit-details-marker {
69727
+ display: none;
69728
+ }
69729
+ /* Reveal is keyed to the diagram IMAGE (the svg wrappers), not the whole
69730
+ * figure \u2014 hovering the open code panel keeps the page quiet. The toolbar's
69731
+ * own :hover keeps it alive while the pointer travels down from the image
69732
+ * (they're adjacent, so there's no dead gap). focus-within covers keyboard
69733
+ * and touch-tap. */
69734
+ .dgmo-light:hover ~ .dgmo-source-wrap > .dgmo-toolbar,
69735
+ .dgmo-dark:hover ~ .dgmo-source-wrap > .dgmo-toolbar,
69736
+ .dgmo-svg:hover ~ .dgmo-source-wrap > .dgmo-toolbar,
69737
+ .dgmo-toolbar:hover,
69738
+ .dgmo:focus-within .dgmo-toolbar {
69739
+ opacity: 1;
69740
+ }
69741
+ /* Touch devices have no hover: keep the icons faintly visible so the
69742
+ * affordance is discoverable at all. */
69743
+ @media (hover: none) {
69744
+ .dgmo-toolbar {
69745
+ opacity: 0.5;
69746
+ }
69682
69747
  }
69683
69748
 
69684
- .dgmo-source-toggle {
69749
+ .dgmo-toggle,
69750
+ .dgmo-toolbar-btn {
69685
69751
  display: inline-flex;
69686
69752
  align-items: center;
69687
- gap: 4px;
69688
- /* Visual size is small; the 28px hit area + padding still meets
69689
- the 44 \xD7 44 minimum touch target across most stylesheets, and
69690
- we widen padding on coarse pointers below. */
69691
- min-height: 28px;
69692
- padding: 4px 6px;
69693
- background: transparent;
69753
+ justify-content: center;
69754
+ width: 1.9em;
69755
+ height: 1.9em;
69756
+ border-radius: 0.35em;
69757
+ background: none;
69694
69758
  border: 0;
69695
- font: inherit;
69696
- font-size: 11px;
69697
- font-weight: 500;
69698
- letter-spacing: 0.02em;
69699
- text-align: left;
69700
- cursor: pointer;
69759
+ padding: 0;
69701
69760
  color: inherit;
69702
- opacity: 0.45;
69703
- border-radius: 3px;
69704
- transition: opacity 120ms ease, background 120ms ease;
69705
- }
69706
- .dgmo-source-toggle:hover {
69707
- opacity: 0.85;
69708
- background: rgba(127, 127, 127, 0.08);
69761
+ cursor: pointer;
69762
+ opacity: 0.75;
69763
+ transition:
69764
+ opacity 0.15s ease,
69765
+ background-color 0.15s ease;
69709
69766
  }
69710
- .dgmo-source-toggle:focus-visible {
69767
+ .dgmo-toggle:hover,
69768
+ .dgmo-toolbar-btn:hover {
69711
69769
  opacity: 1;
69712
- outline: 2px solid currentColor;
69713
- outline-offset: 1px;
69770
+ background: rgba(127, 127, 127, 0.12);
69714
69771
  }
69715
- .dgmo-source-toggle[aria-expanded="true"] {
69716
- opacity: 0.7;
69772
+ .dgmo-toggle svg,
69773
+ .dgmo-toolbar-btn svg {
69774
+ width: 1em;
69775
+ height: 1em;
69717
69776
  }
69718
- .dgmo-source-toggle .dgmo-chevron {
69719
- display: inline-block;
69720
- width: 8px;
69721
- height: 8px;
69722
- font-size: 8px;
69723
- line-height: 1;
69724
- transition: transform 150ms ease-out;
69777
+ /* Active state while the source panel is open. */
69778
+ .dgmo-source-wrap[open] > .dgmo-toolbar .dgmo-toggle {
69779
+ opacity: 1;
69780
+ background: rgba(127, 127, 127, 0.15);
69725
69781
  }
69726
- .dgmo-source-toggle[aria-expanded="true"] .dgmo-chevron {
69727
- transform: rotate(90deg);
69782
+ .dgmo-copy--success {
69783
+ color: #5cba7a;
69784
+ opacity: 1;
69728
69785
  }
69729
- @media (pointer: coarse) {
69730
- /* Larger hit area on touch devices without making the visible
69731
- toggle bigger on the desktop. */
69732
- .dgmo-source-toggle {
69733
- min-height: 44px;
69734
- padding: 12px 10px;
69735
- }
69786
+
69787
+ /* === Open state: frame the whole block ===
69788
+ * When the source panel is open, diagram + toolbar + code get one shared
69789
+ * border so the code visibly belongs to the chart above it, not to the
69790
+ * surrounding prose. Closed blocks stay frameless. */
69791
+ .dgmo:has(> .dgmo-source-wrap[open]) {
69792
+ border: 1px solid rgba(127, 127, 127, 0.3);
69793
+ border-radius: 0.6em;
69794
+ padding: 0.75em 0.75em 0.5em;
69736
69795
  }
69737
69796
 
69738
- .dgmo-source-body {
69797
+ /* === Source panel (hidden until toggled) === */
69798
+ .dgmo-source-inner {
69799
+ border-top: 1px solid rgba(127, 127, 127, 0.25);
69800
+ background: rgba(127, 127, 127, 0.06);
69739
69801
  overflow: hidden;
69740
- max-height: 0;
69741
- transition: max-height 150ms ease-out;
69742
- position: relative;
69802
+ margin: 0 -0.75em -0.5em;
69803
+ border-radius: 0 0 0.6em 0.6em;
69804
+ }
69805
+ .dgmo-pre {
69806
+ white-space: pre;
69807
+ overflow-x: auto;
69808
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
69809
+ font-size: 0.85em;
69810
+ line-height: 1.5;
69811
+ margin: 0;
69812
+ padding: 1em;
69743
69813
  }
69744
- .dgmo-source-body.dgmo-open {
69745
- max-height: 60vh;
69746
- overflow: auto;
69747
- margin-top: 2px;
69748
- border-radius: 4px;
69749
- background: rgba(127, 127, 127, 0.04);
69814
+ .dgmo-code {
69815
+ display: block;
69750
69816
  }
69751
- .dgmo-rendered.dgmo-theme-dark .dgmo-source-body.dgmo-open {
69752
- background: rgba(255, 255, 255, 0.03);
69817
+
69818
+ /* === Error card === */
69819
+ .dgmo--error {
69820
+ border: 1px solid rgba(220, 80, 80, 0.5);
69821
+ border-radius: 0.5em;
69822
+ padding: 0.75em 1em;
69753
69823
  }
69754
- .dgmo-source-pre {
69755
- margin: 0;
69756
- /* Right padding leaves room for the floating action icons. */
69757
- padding: 10px 56px 10px 14px;
69758
- font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
69759
- font-size: 12px;
69760
- line-height: 1.45;
69824
+ .dgmo--error pre {
69761
69825
  white-space: pre;
69762
- overflow: auto;
69763
- background: transparent;
69764
- color: inherit;
69826
+ overflow-x: auto;
69827
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
69828
+ font-size: 0.85em;
69829
+ margin: 0.5em 0 0;
69765
69830
  }
69766
69831
 
69767
- .dgmo-source-actions {
69768
- position: absolute;
69769
- top: 6px;
69770
- right: 6px;
69771
- display: flex;
69772
- gap: 2px;
69773
- /* Inherit visibility:hidden when collapsed; pointer-events:none keeps
69774
- them off the tab order until the panel opens. */
69775
- pointer-events: none;
69832
+ /* === Source highlight roles ===
69833
+ * Light values mirror LIGHT_ROLE_STYLES; dark overrides mirror
69834
+ * NORD_ROLE_STYLES. Guarded by the parity test in tests/block.test.ts. */
69835
+ .dgmo-tok-keyword {
69836
+ color: #3b6ea5;
69837
+ font-weight: bold;
69776
69838
  }
69777
- .dgmo-source-body.dgmo-open .dgmo-source-actions {
69778
- pointer-events: auto;
69839
+ .dgmo-tok-controlKeyword {
69840
+ color: #7d5ba6;
69841
+ font-weight: bold;
69779
69842
  }
69780
- .dgmo-btn {
69781
- display: inline-flex;
69782
- align-items: center;
69783
- justify-content: center;
69784
- width: 26px;
69785
- height: 26px;
69786
- padding: 0;
69787
- background: transparent;
69788
- color: inherit;
69789
- border: 0;
69790
- border-radius: 3px;
69791
- cursor: pointer;
69792
- text-decoration: none;
69793
- opacity: 0.4;
69794
- transition: opacity 120ms ease, background 120ms ease, color 120ms ease;
69843
+ .dgmo-tok-definitionKeyword {
69844
+ color: #2f5a86;
69845
+ font-weight: bold;
69795
69846
  }
69796
- .dgmo-btn:hover {
69797
- opacity: 1;
69798
- background: rgba(127, 127, 127, 0.15);
69847
+ .dgmo-tok-modifier {
69848
+ color: #7d5ba6;
69799
69849
  }
69800
- .dgmo-btn:focus-visible {
69801
- opacity: 1;
69802
- outline: 2px solid currentColor;
69803
- outline-offset: 1px;
69850
+ .dgmo-tok-chartType {
69851
+ color: #b8691f;
69852
+ font-weight: bold;
69804
69853
  }
69805
- .dgmo-btn[aria-disabled="true"] {
69806
- opacity: 0.25;
69807
- cursor: not-allowed;
69854
+ .dgmo-tok-operator {
69855
+ color: #c0504d;
69856
+ font-weight: bold;
69808
69857
  }
69809
- .dgmo-btn[aria-disabled="true"]:hover {
69810
- background: transparent;
69858
+ .dgmo-tok-number {
69859
+ color: #7d5ba6;
69811
69860
  }
69812
- .dgmo-btn-copied {
69813
- opacity: 1 !important;
69814
- color: rgb(120, 200, 120);
69861
+ .dgmo-tok-comment {
69862
+ color: #677483;
69863
+ font-style: italic;
69815
69864
  }
69816
- .dgmo-btn svg {
69817
- width: 14px;
69818
- height: 14px;
69819
- display: block;
69865
+ .dgmo-tok-heading {
69866
+ color: #b8691f;
69867
+ font-weight: bold;
69868
+ }
69869
+ .dgmo-tok-bracket {
69870
+ color: #5b6672;
69871
+ }
69872
+ .dgmo-tok-separator {
69873
+ color: #2d7268;
69874
+ }
69875
+ .dgmo-tok-deprecatedSyntax {
69876
+ color: #c0504d;
69877
+ text-decoration: line-through;
69878
+ }
69879
+ .dgmo-tok-url {
69880
+ color: #3b6ea5;
69881
+ text-decoration: underline;
69882
+ }
69883
+ .dgmo-tok-colorAnnotation {
69884
+ color: #b8691f;
69885
+ font-style: italic;
69886
+ }
69887
+ .dgmo-tok-punctuation {
69888
+ color: #677483;
69889
+ }
69890
+ .dgmo-tok-propertyName {
69891
+ color: #2d7268;
69892
+ }
69893
+ .dgmo-tok-string {
69894
+ color: #3f7a3b;
69895
+ }
69896
+ .dgmo-tok-noteContent {
69897
+ color: #677483;
69898
+ font-style: italic;
69820
69899
  }
69821
69900
 
69822
- .dgmo-error-banner {
69901
+ [data-theme="dark"] .dgmo-tok-keyword {
69902
+ color: #81a1c1;
69903
+ font-weight: bold;
69904
+ }
69905
+ [data-theme="dark"] .dgmo-tok-controlKeyword {
69906
+ color: #b48ead;
69907
+ font-weight: bold;
69908
+ }
69909
+ [data-theme="dark"] .dgmo-tok-definitionKeyword {
69910
+ color: #5e81ac;
69911
+ font-weight: bold;
69912
+ }
69913
+ [data-theme="dark"] .dgmo-tok-modifier {
69914
+ color: #b48ead;
69915
+ }
69916
+ [data-theme="dark"] .dgmo-tok-chartType {
69917
+ color: #d08770;
69918
+ font-weight: bold;
69919
+ }
69920
+ [data-theme="dark"] .dgmo-tok-operator {
69921
+ color: #bf616a;
69922
+ font-weight: bold;
69923
+ }
69924
+ [data-theme="dark"] .dgmo-tok-number {
69925
+ color: #b48ead;
69926
+ }
69927
+ [data-theme="dark"] .dgmo-tok-comment {
69928
+ color: #616e88;
69929
+ font-style: italic;
69930
+ }
69931
+ [data-theme="dark"] .dgmo-tok-heading {
69932
+ color: #d08770;
69933
+ font-weight: bold;
69934
+ }
69935
+ [data-theme="dark"] .dgmo-tok-bracket {
69936
+ color: #5e81ac;
69937
+ }
69938
+ [data-theme="dark"] .dgmo-tok-separator {
69939
+ color: #88c0d0;
69940
+ }
69941
+ [data-theme="dark"] .dgmo-tok-deprecatedSyntax {
69942
+ color: #bf616a;
69943
+ text-decoration: line-through;
69944
+ }
69945
+ [data-theme="dark"] .dgmo-tok-url {
69946
+ color: #88c0d0;
69947
+ text-decoration: underline;
69948
+ }
69949
+ [data-theme="dark"] .dgmo-tok-colorAnnotation {
69950
+ color: #d08770;
69951
+ font-style: italic;
69952
+ }
69953
+ [data-theme="dark"] .dgmo-tok-punctuation {
69954
+ color: #616e88;
69955
+ }
69956
+ [data-theme="dark"] .dgmo-tok-propertyName {
69957
+ color: #88c0d0;
69958
+ }
69959
+ [data-theme="dark"] .dgmo-tok-string {
69960
+ color: #a3be8c;
69961
+ }
69962
+ [data-theme="dark"] .dgmo-tok-noteContent {
69963
+ color: #616e88;
69964
+ font-style: italic;
69965
+ }
69966
+ `;
69967
+
69968
+ // src/embed/index.ts
69969
+ var EDITOR_BASE_URL = "https://online.diagrammo.app";
69970
+ function resolveBlockOptions(opts) {
69971
+ const mode = opts.mode ?? "diagram";
69972
+ const showcase = mode === "showcase";
69973
+ return {
69974
+ mode,
69975
+ palette: opts.palette ?? "slate",
69976
+ colorMode: opts.colorMode ?? "auto",
69977
+ showSource: opts.showSource ?? showcase,
69978
+ showCopy: opts.showCopy ?? showcase,
69979
+ showOpenInEditor: opts.showOpenInEditor ?? showcase,
69980
+ editorBaseUrl: opts.editorBaseUrl ?? EDITOR_BASE_URL,
69981
+ wrapper: opts.wrapper ?? "figure",
69982
+ className: opts.className ?? "dgmo",
69983
+ legacyClassNames: opts.legacyClassNames ?? [],
69984
+ title: opts.title,
69985
+ onWarn: opts.onWarn ?? ((message) => console.warn(message))
69986
+ };
69987
+ }
69988
+ function buildDgmoBlockHtml(source, svgsHtml, options = {}) {
69989
+ return assembleBlock(source.trim(), svgsHtml, resolveBlockOptions(options));
69990
+ }
69991
+ function errorBlockHtml(err, source, options = {}) {
69992
+ const msg = err instanceof Error ? err.message : "Failed to render dgmo block.";
69993
+ const base = options.className ?? "dgmo";
69994
+ const legacy = (options.legacyClassNames ?? []).join(" ");
69995
+ const cls = legacy ? `${base} ${legacy} ${base}--error` : `${base} ${base}--error`;
69996
+ return `<div class="${escapeAttr(cls)}" role="alert"><strong>dgmo render error:</strong> ${escapeHtml3(msg)}<pre>${escapeHtml3(source)}</pre></div>`;
69997
+ }
69998
+ function wrapperClasses(opts, variant) {
69999
+ const base = `${opts.className} ${opts.className}--${variant}`;
70000
+ const legacy = opts.legacyClassNames.join(" ");
70001
+ return legacy ? `${base} ${legacy}` : base;
70002
+ }
70003
+ function assembleBlock(source, svgsHtml, opts) {
70004
+ const Wrapper = opts.wrapper;
70005
+ const showcase = opts.mode === "showcase";
70006
+ const variant = showcase ? "showcase" : "diagram";
70007
+ const ariaAttr = opts.title ? ` aria-label="${escapeAttr(opts.title)}"` : "";
70008
+ const sourceHtml = showcase ? sourceDisclosure(source, opts) : "";
70009
+ return `<${Wrapper} class="${escapeAttr(wrapperClasses(opts, variant))}"${ariaAttr}>` + svgsHtml + sourceHtml + `</${Wrapper}>`;
70010
+ }
70011
+ var CODE_ICON = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m10 4.5 4 3.5-4 3.5"/><path d="m6 4.5-4 3.5 4 3.5"/></svg>`;
70012
+ var COPY_ICON = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5.5" y="5.5" width="8" height="8" rx="1.5"/><path d="M10.5 5.5V3a1.5 1.5 0 0 0-1.5-1.5H3A1.5 1.5 0 0 0 1.5 3v6A1.5 1.5 0 0 0 3 10.5h2.5"/></svg>`;
70013
+ var EXTERNAL_ICON = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9.5 2.5h4v4"/><path d="M13.5 2.5 7 9"/><path d="M12.5 9.5v3a1 1 0 0 1-1 1h-8a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1h3"/></svg>`;
70014
+ function sourceDisclosure(source, opts) {
70015
+ if (!opts.showSource) return "";
70016
+ const toggle = `<span class="dgmo-toggle" title="View DGMO source">${CODE_ICON}</span>`;
70017
+ const copyButton = opts.showCopy ? `<button type="button" class="dgmo-toolbar-btn dgmo-copy" aria-label="Copy DGMO source" title="Copy source" data-dgmo-source="${escapeAttr(source)}">${COPY_ICON}</button>` : "";
70018
+ let openButton = "";
70019
+ if (opts.showOpenInEditor) {
70020
+ const encoded = encodeDiagramUrl(source, { baseUrl: opts.editorBaseUrl });
70021
+ if (encoded.url) {
70022
+ openButton = `<a href="${escapeAttr(encoded.url)}" target="_blank" rel="noopener noreferrer" class="dgmo-toolbar-btn dgmo-open" aria-label="Open in online editor" title="Open in online editor">${EXTERNAL_ICON}</a>`;
70023
+ }
70024
+ }
70025
+ const sourceHtml = highlightedSource(source);
70026
+ return `<details class="dgmo-source-wrap"><summary class="dgmo-toolbar" aria-label="View DGMO source">${toggle}${copyButton}${openButton}</summary><div class="dgmo-source-inner">${sourceHtml}</div></details>`;
70027
+ }
70028
+ function highlightedSource(source) {
70029
+ const tokens = highlightDgmo(source);
70030
+ const inner = tokens.map((t) => {
70031
+ const text = escapeHtml3(t.text);
70032
+ if (!t.role || t.role === "default") return text;
70033
+ return `<span class="dgmo-tok-${escapeAttr(t.role)}">${text}</span>`;
70034
+ }).join("");
70035
+ return `<pre class="dgmo-pre"><span class="dgmo-code">${inner}</span></pre>`;
70036
+ }
70037
+
70038
+ // src/auto/styles.ts
70039
+ var AUTO_BASE_CSS = `
70040
+ /* anti-flash: hide source elements until either render swaps them out
70041
+ or the error path replaces them with the standard error card */
70042
+ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
70043
+ .dgmo:not(svg *):not(.dgmo-rendered):not(.dgmo-rendered *):not(.dgmo--error):not(.dgmo--error *) {
70044
+ visibility: hidden;
70045
+ }
70046
+ .dgmo-rendered, .dgmo-rendered *,
70047
+ .dgmo--error, .dgmo--error * {
70048
+ visibility: visible !important;
70049
+ }
70050
+
70051
+ .dgmo-rendered {
69823
70052
  display: block;
69824
- margin: 0.5em 0;
69825
- padding: 10px 14px;
69826
- border-left: 4px solid #c44;
69827
- background: rgba(204, 68, 68, 0.08);
69828
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
69829
- font-size: 13px;
70053
+ position: relative;
70054
+ margin: 1em 0;
70055
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
70056
+ Oxygen, Ubuntu, Cantarell, sans-serif;
70057
+ font-size: 14px;
69830
70058
  line-height: 1.4;
69831
- color: inherit;
69832
- border-radius: 0 4px 4px 0;
69833
- }
69834
- .dgmo-error-banner-title {
69835
- font-weight: 600;
69836
- margin-bottom: 2px;
70059
+ color-scheme: light dark;
69837
70060
  }
69838
- .dgmo-error-banner-loc {
69839
- opacity: 0.7;
70061
+
70062
+ .dgmo--loading {
70063
+ opacity: 0.6;
69840
70064
  font-size: 12px;
69841
70065
  font-family: ui-monospace, monospace;
69842
70066
  }
69843
-
69844
- /* Token roles \u2014 fallback colors used when theme classes don't override */
69845
- .dgmo-source-pre .dgmo-tok-keyword { color: #5e81ac; font-weight: 600; }
69846
- .dgmo-source-pre .dgmo-tok-controlKeyword { color: #b48ead; font-weight: 600; }
69847
- .dgmo-source-pre .dgmo-tok-definitionKeyword { color: #5e81ac; font-weight: 600; }
69848
- .dgmo-source-pre .dgmo-tok-modifier { color: #b48ead; }
69849
- .dgmo-source-pre .dgmo-tok-chartType { color: #d08770; font-weight: 600; }
69850
- .dgmo-source-pre .dgmo-tok-operator { color: #bf616a; font-weight: 600; }
69851
- .dgmo-source-pre .dgmo-tok-number { color: #b48ead; }
69852
- .dgmo-source-pre .dgmo-tok-comment { color: #6c7a96; font-style: italic; }
69853
- .dgmo-source-pre .dgmo-tok-heading { color: #d08770; font-weight: 600; }
69854
- .dgmo-source-pre .dgmo-tok-bracket { color: #5e81ac; }
69855
- .dgmo-source-pre .dgmo-tok-separator { color: #88c0d0; }
69856
- .dgmo-source-pre .dgmo-tok-url { color: #88c0d0; text-decoration: underline; }
69857
- .dgmo-source-pre .dgmo-tok-colorAnnotation { color: #d08770; font-style: italic; }
69858
- .dgmo-source-pre .dgmo-tok-punctuation { color: #6c7a96; }
69859
- .dgmo-source-pre .dgmo-tok-noteContent { color: #6c7a96; font-style: italic; }
69860
-
69861
- .dgmo-rendered.dgmo-theme-dark .dgmo-source-pre .dgmo-tok-keyword,
69862
- .dgmo-rendered.dgmo-theme-dark .dgmo-source-pre .dgmo-tok-definitionKeyword { color: #81a1c1; }
69863
- .dgmo-rendered.dgmo-theme-dark .dgmo-source-pre .dgmo-tok-comment,
69864
- .dgmo-rendered.dgmo-theme-dark .dgmo-source-pre .dgmo-tok-noteContent,
69865
- .dgmo-rendered.dgmo-theme-dark .dgmo-source-pre .dgmo-tok-punctuation { color: #616e88; }
69866
70067
  `;
70068
+ function darkScopedBlockCss(css) {
70069
+ const rules = css.match(/\[data-theme="dark"\][^{]*\{[^}]*\}/g) ?? [];
70070
+ return rules.map((rule) => rule.replace(/\[data-theme="dark"\]/g, ".dgmo-theme-dark")).join("\n");
70071
+ }
70072
+ var CSS = AUTO_BASE_CSS + "\n" + BLOCK_CSS + "\n" + darkScopedBlockCss(BLOCK_CSS) + "\n";
69867
70073
 
69868
70074
  // src/auto/shared.ts
69869
70075
  init_safe_href();
69870
- var VERSION = "0.44.1";
69871
- var EDITOR_BASE_URL = "https://online.diagrammo.app";
70076
+ var VERSION = "0.46.0";
69872
70077
  var ARIA_LABEL_MAX = 200;
69873
- var COPIED_INTERACTION_MS = 1200;
70078
+ var COPIED_INTERACTION_MS = 1500;
69874
70079
  var LOG_PREFIX = "[dgmo]";
69875
70080
  var ARIA_STRIP_RE = /[\x00-\x1F‪-‮⁦-⁩]/g;
69876
70081
  var STYLE_FLAG = "dgmoAutoStyles";
@@ -69939,139 +70144,98 @@ function deriveAriaLabel(source) {
69939
70144
  if (!firstLine) return "DGMO diagram";
69940
70145
  return firstLine.replace(ARIA_STRIP_RE, "").slice(0, ARIA_LABEL_MAX);
69941
70146
  }
69942
- function buildHighlightedSource(source) {
69943
- const frag = document.createDocumentFragment();
69944
- let tokens;
69945
- try {
69946
- tokens = highlightDgmo(source);
69947
- } catch {
69948
- frag.appendChild(document.createTextNode(source));
69949
- return frag;
69950
- }
69951
- for (const tok of tokens) {
69952
- if (!tok.text) continue;
69953
- const span = document.createElement("span");
69954
- span.className = `dgmo-tok-${tok.role}`;
69955
- span.textContent = tok.text;
69956
- frag.appendChild(span);
69957
- }
69958
- return frag;
69959
- }
69960
- var COPY_ICON_SVG = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5.5" y="5.5" width="8" height="8" rx="1.5"/><path d="M10.5 5.5V3a1.5 1.5 0 0 0-1.5-1.5H3A1.5 1.5 0 0 0 1.5 3v6A1.5 1.5 0 0 0 3 10.5h2.5"/></svg>';
69961
- var CHECK_ICON_SVG = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="3 8.5 6.5 12 13 4.5"/></svg>';
69962
- var EXTERNAL_ICON_SVG = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 2h5v5"/><path d="M14 2L7 9"/><path d="M13 9v4a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h4"/></svg>';
69963
- function setIcon(el, svg) {
69964
- el.innerHTML = svg;
69965
- }
69966
- function buildSourcePanel(source, shareUrl, showEditorLink) {
69967
- const panel = document.createElement("div");
69968
- panel.className = "dgmo-source-panel";
69969
- const toggle = document.createElement("button");
69970
- toggle.type = "button";
69971
- toggle.className = "dgmo-source-toggle";
69972
- toggle.setAttribute("aria-expanded", "false");
69973
- const chevron = document.createElement("span");
69974
- chevron.className = "dgmo-chevron";
69975
- chevron.setAttribute("aria-hidden", "true");
69976
- chevron.textContent = "\u25B8";
69977
- toggle.appendChild(chevron);
69978
- const label = document.createElement("span");
69979
- label.textContent = "DGMO source";
69980
- toggle.appendChild(label);
69981
- const body = document.createElement("div");
69982
- body.className = "dgmo-source-body";
69983
- const pre = document.createElement("pre");
69984
- pre.className = "dgmo-source-pre";
69985
- pre.appendChild(buildHighlightedSource(source));
69986
- body.appendChild(pre);
69987
- const actions = document.createElement("div");
69988
- actions.className = "dgmo-source-actions";
69989
- const copyBtn = document.createElement("button");
69990
- copyBtn.type = "button";
69991
- copyBtn.className = "dgmo-btn dgmo-btn-copy";
69992
- copyBtn.setAttribute("aria-label", "Copy DGMO source");
69993
- copyBtn.title = "Copy source";
69994
- setIcon(copyBtn, COPY_ICON_SVG);
69995
- copyBtn.addEventListener("click", () => {
69996
- void copySource(source, copyBtn);
70147
+ function buildRenderedBlock(opts) {
70148
+ const html = buildDgmoBlockHtml(opts.source, '<div class="dgmo-svg"></div>', {
70149
+ mode: opts.showSource ? "showcase" : "diagram",
70150
+ showOpenInEditor: opts.showSource && opts.showEditorLink,
70151
+ // Keep the legacy `.dgmo-rendered` + theme hooks so the anti-flash CSS,
70152
+ // idempotency filters, and theme-scoped token colors keep working.
70153
+ legacyClassNames: ["dgmo-rendered", opts.themeClass]
69997
70154
  });
69998
- actions.appendChild(copyBtn);
69999
- if (showEditorLink) {
70000
- const editorBtn = document.createElement("a");
70001
- editorBtn.className = "dgmo-btn dgmo-btn-editor";
70002
- editorBtn.target = "_blank";
70003
- editorBtn.rel = "noopener noreferrer";
70004
- editorBtn.setAttribute("aria-label", "Open in editor");
70005
- setIcon(editorBtn, EXTERNAL_ICON_SVG);
70006
- if (shareUrl) {
70007
- editorBtn.href = shareUrl;
70008
- editorBtn.title = "Open in editor";
70009
- } else {
70010
- editorBtn.setAttribute("aria-disabled", "true");
70011
- editorBtn.title = "Diagram too large for share link; copy source and paste into editor";
70012
- editorBtn.addEventListener("click", (e) => e.preventDefault());
70013
- }
70014
- actions.appendChild(editorBtn);
70015
- }
70016
- body.appendChild(actions);
70017
- panel.appendChild(toggle);
70018
- panel.appendChild(body);
70019
- toggle.addEventListener("click", () => {
70020
- const open = body.classList.toggle("dgmo-open");
70021
- toggle.setAttribute("aria-expanded", open ? "true" : "false");
70155
+ const holder = document.createElement("div");
70156
+ holder.innerHTML = html;
70157
+ const wrapper = holder.firstElementChild;
70158
+ wrapper.querySelector(".dgmo-svg")?.appendChild(opts.svgEl);
70159
+ const open = wrapper.querySelector("a.dgmo-open");
70160
+ if (open) {
70161
+ if (opts.shareUrl) open.href = opts.shareUrl;
70162
+ else open.remove();
70163
+ }
70164
+ bindBlockToolbar(wrapper);
70165
+ return wrapper;
70166
+ }
70167
+ function bindBlockToolbar(wrapper) {
70168
+ wrapper.addEventListener("click", (e) => {
70169
+ void handleToolbarClick(e);
70022
70170
  });
70023
- return panel;
70024
70171
  }
70025
- async function copySource(source, btn) {
70026
- let copied = false;
70172
+ async function handleToolbarClick(e) {
70173
+ const target = e.target;
70174
+ if (!target || typeof target.closest !== "function") return;
70175
+ const btn = target.closest(".dgmo-toolbar-btn");
70176
+ if (!btn) return;
70177
+ const insideSummary = !!btn.closest("summary");
70178
+ if (insideSummary) e.preventDefault();
70179
+ if (btn.matches("button.dgmo-copy")) {
70180
+ const copied = await copyText(btn.dataset["dgmoSource"] ?? "");
70181
+ if (copied) {
70182
+ btn.classList.add("dgmo-copy--success");
70183
+ setTimeout(
70184
+ () => btn.classList.remove("dgmo-copy--success"),
70185
+ COPIED_INTERACTION_MS
70186
+ );
70187
+ } else {
70188
+ sharedWarn("clipboard write failed");
70189
+ }
70190
+ return;
70191
+ }
70192
+ if (insideSummary && btn.matches("a.dgmo-open")) {
70193
+ const anchor = btn;
70194
+ if (anchor.href) {
70195
+ window.open(
70196
+ anchor.href,
70197
+ anchor.target || "_blank",
70198
+ "noopener,noreferrer"
70199
+ );
70200
+ }
70201
+ }
70202
+ }
70203
+ async function copyText(text) {
70027
70204
  try {
70028
70205
  if (navigator?.clipboard?.writeText) {
70029
- await navigator.clipboard.writeText(source);
70030
- copied = true;
70206
+ await navigator.clipboard.writeText(text);
70207
+ return true;
70031
70208
  }
70032
70209
  } catch {
70033
70210
  }
70034
- if (!copied && typeof document !== "undefined") {
70211
+ if (typeof document !== "undefined") {
70035
70212
  try {
70036
70213
  const ta = document.createElement("textarea");
70037
- ta.value = source;
70214
+ ta.value = text;
70038
70215
  ta.setAttribute("readonly", "");
70039
70216
  ta.style.position = "absolute";
70040
70217
  ta.style.left = "-9999px";
70041
70218
  document.body.appendChild(ta);
70042
70219
  ta.select();
70043
- copied = document.execCommand("copy");
70220
+ const copied = document.execCommand("copy");
70044
70221
  document.body.removeChild(ta);
70222
+ return copied;
70045
70223
  } catch {
70046
- copied = false;
70224
+ return false;
70047
70225
  }
70048
70226
  }
70049
- if (copied) {
70050
- setIcon(btn, CHECK_ICON_SVG);
70051
- btn.classList.add("dgmo-btn-copied");
70052
- setTimeout(() => {
70053
- setIcon(btn, COPY_ICON_SVG);
70054
- btn.classList.remove("dgmo-btn-copied");
70055
- }, COPIED_INTERACTION_MS);
70056
- } else {
70057
- sharedWarn("clipboard write failed");
70058
- }
70227
+ return false;
70059
70228
  }
70060
- function buildErrorBanner(opts) {
70061
- const banner = document.createElement("div");
70062
- banner.className = "dgmo-error-banner";
70063
- banner.setAttribute("role", "alert");
70064
- const title = document.createElement("div");
70065
- title.className = "dgmo-error-banner-title";
70066
- title.textContent = `${opts.severity ?? "error"}: ${opts.message}`;
70067
- banner.appendChild(title);
70229
+ function buildErrorBlock(opts) {
70230
+ let message = opts.severity && opts.severity !== "error" ? `${opts.severity}: ${opts.message}` : opts.message;
70068
70231
  if (opts.line !== void 0 && opts.line > 0) {
70069
- const loc = document.createElement("div");
70070
- loc.className = "dgmo-error-banner-loc";
70071
- loc.textContent = opts.column !== void 0 ? `at ${opts.line}:${opts.column}` : `at line ${opts.line}`;
70072
- banner.appendChild(loc);
70232
+ message += opts.column !== void 0 ? ` (at ${opts.line}:${opts.column})` : ` (at line ${opts.line})`;
70073
70233
  }
70074
- return banner;
70234
+ const holder = document.createElement("div");
70235
+ holder.innerHTML = errorBlockHtml(new Error(message), opts.source);
70236
+ const card = holder.firstElementChild;
70237
+ card.setAttribute("data-dgmo-processed", "true");
70238
+ return card;
70075
70239
  }
70076
70240
  function buildShareUrl(source, opts) {
70077
70241
  const result = encodeDiagramUrl(source, {
@@ -70245,7 +70409,7 @@ var DgmoDiagram = class extends HTMLElement {
70245
70409
  this.container.appendChild(node);
70246
70410
  }
70247
70411
  showError(opts) {
70248
- this.mount(buildErrorBanner(opts), "dgmo dgmo--error");
70412
+ this.mount(buildErrorBlock({ ...opts, source: this.source ?? "" }), "");
70249
70413
  }
70250
70414
  async rerender() {
70251
70415
  const token = ++this.renderToken;
@@ -70255,9 +70419,8 @@ var DgmoDiagram = class extends HTMLElement {
70255
70419
  return;
70256
70420
  }
70257
70421
  const loading = document.createElement("div");
70258
- loading.className = "dgmo-error-banner-loc";
70259
70422
  loading.textContent = "Rendering diagram\u2026";
70260
- this.mount(loading, "dgmo dgmo--loading");
70423
+ this.mount(loading, "dgmo--loading");
70261
70424
  const themePref = this.themePreference();
70262
70425
  const resolvedTheme = themePref === "transparent" ? "transparent" : resolveTheme(themePref);
70263
70426
  const palette = this.palette();
@@ -70330,19 +70493,23 @@ var DgmoDiagram = class extends HTMLElement {
70330
70493
  svgEl.setAttribute("role", "img");
70331
70494
  svgEl.setAttribute("aria-label", deriveAriaLabel(src));
70332
70495
  const themeClass = resolvedTheme === "dark" ? "dgmo-theme-dark" : resolvedTheme === "transparent" ? "dgmo-theme-transparent" : "dgmo-theme-light";
70333
- const frag = document.createDocumentFragment();
70334
- frag.appendChild(svgEl);
70335
- if (this.isShowcase()) {
70336
- const shareUrl = buildShareUrl(src, {
70337
- palette,
70338
- theme: resolvedTheme === "dark" ? "dark" : "light",
70339
- editorBase: this.editorBase(),
70340
- campaign: VERSION,
70341
- utmSource: "element-embed"
70342
- });
70343
- frag.appendChild(buildSourcePanel(src, shareUrl, true));
70344
- }
70345
- this.mount(frag, `dgmo-rendered ${themeClass} dgmo--rendered`);
70496
+ const showcase = this.isShowcase();
70497
+ const shareUrl = showcase ? buildShareUrl(src, {
70498
+ palette,
70499
+ theme: resolvedTheme === "dark" ? "dark" : "light",
70500
+ editorBase: this.editorBase(),
70501
+ campaign: VERSION,
70502
+ utmSource: "element-embed"
70503
+ }) : null;
70504
+ const wrapper = buildRenderedBlock({
70505
+ source: src,
70506
+ svgEl,
70507
+ themeClass,
70508
+ showSource: showcase,
70509
+ showEditorLink: showcase,
70510
+ shareUrl
70511
+ });
70512
+ this.mount(wrapper, "dgmo--rendered");
70346
70513
  }
70347
70514
  };
70348
70515
  function defineDgmoDiagram() {