@floegence/floe-webapp-core 0.86.73 → 0.86.75

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.
@@ -1,96 +1,159 @@
1
- const o = (i) => ({ type: "pane", id: i });
2
- function x(i) {
3
- return i ? i.type === "pane" ? [i.id] : [...x(i.first), ...x(i.second)] : [];
1
+ const w = (t) => ({ type: "pane", id: t });
2
+ function M(t) {
3
+ return t ? t.type === "pane" ? [t.id] : [...M(t.first), ...M(t.second)] : [];
4
4
  }
5
- function u(i) {
6
- const s = /* @__PURE__ */ new Set();
7
- let n = 0;
8
- const r = (t, c) => {
9
- if (!t || typeof t != "object" || c > 32 || ++n > 127) return !1;
10
- const e = t;
11
- return typeof e.id != "string" || !e.id.trim() || s.has(e.id) ? !1 : (s.add(e.id), e.type === "pane" ? !0 : e.type === "split" && (e.axis === "x" || e.axis === "y") && typeof e.ratio == "number" && Number.isFinite(e.ratio) && e.ratio >= 0.15 && e.ratio <= 0.85 && r(e.first, c + 1) && r(e.second, c + 1));
5
+ function v(t) {
6
+ const e = /* @__PURE__ */ new Set();
7
+ let r = 0;
8
+ const n = (i, f) => {
9
+ if (!i || typeof i != "object" || f > 32 || ++r > 127) return !1;
10
+ const c = i;
11
+ return typeof c.id != "string" || !c.id.trim() || e.has(c.id) ? !1 : (e.add(c.id), c.type === "pane" ? !0 : c.type === "split" && (c.axis === "x" || c.axis === "y") && typeof c.ratio == "number" && Number.isFinite(c.ratio) && c.ratio >= 0.15 && c.ratio <= 0.85 && n(c.first, f + 1) && n(c.second, f + 1));
12
12
  };
13
- return r(i, 0);
13
+ return n(t, 0);
14
14
  }
15
- function a(i, s, n) {
16
- if (i.id === s) return n(i);
17
- if (i.type === "pane") return i;
18
- const r = a(i.first, s, n), t = a(i.second, s, n);
19
- return r === i.first && t === i.second ? i : { ...i, first: r, second: t };
15
+ function k(t, e, r) {
16
+ if (t.id === e) return r(t);
17
+ if (t.type === "pane") return t;
18
+ const n = k(t.first, e, r), i = k(t.second, e, r);
19
+ return n === t.first && i === t.second ? t : { ...t, first: n, second: i };
20
20
  }
21
- function m(i, s) {
22
- if (!i || i.id === s) return null;
23
- if (i.type === "pane") return i;
24
- const n = m(i.first, s), r = m(i.second, s);
25
- return n ? r ? n === i.first && r === i.second ? i : { ...i, first: n, second: r } : n : r;
21
+ function W(t, e) {
22
+ if (!t || t.id === e) return null;
23
+ if (t.type === "pane") return t;
24
+ const r = W(t.first, e), n = W(t.second, e);
25
+ return r ? n ? r === t.first && n === t.second ? t : { ...t, first: r, second: n } : r : n;
26
26
  }
27
- function k(i, s) {
28
- const n = new Set(s);
29
- return x(i).reduce(
30
- (r, t) => n.has(t) ? r : m(r, t),
31
- i
27
+ function b(t, e) {
28
+ const r = new Set(e);
29
+ return M(t).reduce(
30
+ (n, i) => r.has(i) ? n : W(n, i),
31
+ t
32
32
  );
33
33
  }
34
- function w(i, s, n) {
35
- return Number.isFinite(n) ? a(
36
- i,
37
- s,
38
- (r) => r.type === "split" ? { ...r, ratio: Math.max(0.15, Math.min(0.85, n)) } : r
39
- ) : i;
34
+ function N(t, e, r) {
35
+ return Number.isFinite(r) ? k(
36
+ t,
37
+ e,
38
+ (n) => n.type === "split" ? { ...n, ratio: Math.max(0.15, Math.min(0.85, r)) } : n
39
+ ) : t;
40
40
  }
41
- function S(i, s, n, r, t) {
42
- if (!i || s === n || !x(i).includes(n))
43
- return i;
44
- const c = x(i).includes(s);
45
- if (r === "center") {
46
- const p = (f) => f.type === "pane" ? f.id === n ? o(s) : c && f.id === s ? o(n) : f : { ...f, first: p(f.first), second: p(f.second) };
47
- return p(i);
41
+ function q(t, e, r, n, i) {
42
+ if (!t || e === r || !M(t).includes(r))
43
+ return t;
44
+ const f = M(t).includes(e);
45
+ if (n === "center") {
46
+ const h = (o) => o.type === "pane" ? o.id === r ? w(e) : f && o.id === e ? w(r) : o : { ...o, first: h(o.first), second: h(o.second) };
47
+ return h(t);
48
48
  }
49
- const e = m(i, s);
50
- return e ? a(e, n, (p) => ({
49
+ const c = W(t, e);
50
+ return c ? k(c, r, (h) => ({
51
51
  type: "split",
52
- id: t,
53
- axis: r === "left" || r === "right" ? "x" : "y",
52
+ id: i,
53
+ axis: n === "left" || n === "right" ? "x" : "y",
54
54
  ratio: 0.5,
55
- first: r === "left" || r === "top" ? o(s) : p,
56
- second: r === "left" || r === "top" ? p : o(s)
57
- })) : i;
55
+ first: n === "left" || n === "top" ? w(e) : h,
56
+ second: n === "left" || n === "top" ? h : w(e)
57
+ })) : t;
58
58
  }
59
- function W(i, s, n) {
60
- const r = i === "single" ? 1 : i === "grid" ? 4 : i === "columns" || i === "rows" ? 2 : 3, t = [...new Set(s)].slice(0, r).map(o), c = (e, p, f, h = 0.5) => ({ type: "split", id: n(), axis: e, ratio: h, first: p, second: f });
61
- return t.length ? t.length === 1 ? t[0] : t.length === 2 ? c(i === "rows" ? "y" : "x", t[0], t[1]) : i === "grid" && t.length === 4 ? c("x", c("y", t[0], t[2]), c("y", t[1], t[3])) : c(
59
+ function A(t, e, r) {
60
+ const n = t === "single" ? 1 : t === "grid" ? 4 : t === "columns" || t === "rows" ? 2 : 3, i = [...new Set(e)].slice(0, n).map(w), f = (c, h, o, m = 0.5) => ({ type: "split", id: r(), axis: c, ratio: m, first: h, second: o });
61
+ return i.length ? i.length === 1 ? i[0] : i.length === 2 ? f(t === "rows" ? "y" : "x", i[0], i[1]) : t === "grid" && i.length === 4 ? f("x", f("y", i[0], i[2]), f("y", i[1], i[3])) : f(
62
62
  "x",
63
- t[0],
64
- c(i === "three-columns" ? "x" : "y", t[1], t[2]),
65
- i === "three-columns" ? 1 / 3 : 0.5
63
+ i[0],
64
+ f(t === "three-columns" ? "x" : "y", i[1], i[2]),
65
+ t === "three-columns" ? 1 / 3 : 0.5
66
66
  ) : null;
67
67
  }
68
- function l(i) {
69
- const s = /* @__PURE__ */ new Map(), n = [], r = (t, c) => {
70
- if (t.type === "pane") {
71
- s.set(t.id, c);
68
+ function z(t) {
69
+ const e = /* @__PURE__ */ new Map(), r = [], n = (i, f) => {
70
+ if (i.type === "pane") {
71
+ e.set(i.id, f);
72
72
  return;
73
73
  }
74
- n.push({ ...c, id: t.id, axis: t.axis, ratio: t.ratio });
75
- const { x: e, y: p, width: f, height: h } = c;
76
- t.axis === "x" ? (r(t.first, { x: e, y: p, width: f * t.ratio, height: h }), r(t.second, { x: e + f * t.ratio, y: p, width: f * (1 - t.ratio), height: h })) : (r(t.first, { x: e, y: p, width: f, height: h * t.ratio }), r(t.second, {
77
- x: e,
78
- y: p + h * t.ratio,
79
- width: f,
80
- height: h * (1 - t.ratio)
74
+ r.push({ ...f, id: i.id, axis: i.axis, ratio: i.ratio });
75
+ const { x: c, y: h, width: o, height: m } = f;
76
+ i.axis === "x" ? (n(i.first, { x: c, y: h, width: o * i.ratio, height: m }), n(i.second, { x: c + o * i.ratio, y: h, width: o * (1 - i.ratio), height: m })) : (n(i.first, { x: c, y: h, width: o, height: m * i.ratio }), n(i.second, {
77
+ x: c,
78
+ y: h + m * i.ratio,
79
+ width: o,
80
+ height: m * (1 - i.ratio)
81
81
  }));
82
82
  };
83
- return i && r(i, { x: 0, y: 0, width: 100, height: 100 }), { panes: s, dividers: n };
83
+ return t && n(t, { x: 0, y: 0, width: 100, height: 100 }), { panes: e, dividers: r };
84
+ }
85
+ function F(t, e) {
86
+ const r = t.length;
87
+ if (r < 2 || r > 32 || new Set(t).size !== r || t.some((s) => !s.trim()))
88
+ return [];
89
+ const n = (s, a, l, u) => ({ type: "split", id: e(), axis: s, ratio: u, first: a, second: l }), i = (s, a) => {
90
+ if (s.length === 1) return s[0];
91
+ const l = Math.ceil(s.length / 2);
92
+ return n(
93
+ a,
94
+ i(s.slice(0, l), a),
95
+ i(s.slice(l), a),
96
+ l / s.length
97
+ );
98
+ }, f = (s, a, l) => {
99
+ let u = 0;
100
+ const x = Array.from({ length: a }, (y, S) => {
101
+ const p = Math.floor(s.length / a) + (S < s.length % a ? 1 : 0), g = s.slice(u, u + p).map(w);
102
+ return u += p, i(g, l === "x" ? "y" : "x");
103
+ });
104
+ return i(x, l);
105
+ }, c = [], h = /* @__PURE__ */ new Set(), o = (s, a, l) => {
106
+ const u = [...z(l).panes.entries()].sort(
107
+ ([, p], [, g]) => Math.round(p.y * 1e6) - Math.round(g.y * 1e6) || p.x - g.x
108
+ ), x = JSON.stringify(
109
+ u.map(
110
+ ([, p]) => [p.x, p.y, p.width, p.height].map((g) => Math.round(g * 1e6))
111
+ )
112
+ );
113
+ if (h.has(x)) return;
114
+ h.add(x);
115
+ const y = new Map(u.map(([p], g) => [p, t[g]])), S = (p) => p.type === "pane" ? w(y.get(p.id)) : { ...p, first: S(p.first), second: S(p.second) };
116
+ c.push({ id: s, kind: a, layout: S(l) });
117
+ }, m = [.../* @__PURE__ */ new Set([Math.ceil(Math.sqrt(r)), 1, 2, 3, 4, r])].filter(
118
+ (s) => s <= r
119
+ );
120
+ for (const s of m)
121
+ o(
122
+ "rows-" + s,
123
+ s === 1 ? "columns" : s === r ? "rows" : "grid",
124
+ f(t, s, "y")
125
+ );
126
+ for (const s of [2, 3])
127
+ s < r && o("columns-" + s, "grid", f(t, s, "x"));
128
+ for (const s of ["left", "right", "top", "bottom"]) {
129
+ const a = s === "left" || s === "right", l = w(t[0]), u = f(
130
+ t.slice(1),
131
+ Math.ceil(Math.sqrt((r - 1) / 2)),
132
+ a ? "x" : "y"
133
+ ), x = s === "left" || s === "top";
134
+ o(
135
+ "main-" + s,
136
+ "main-" + s,
137
+ n(
138
+ a ? "x" : "y",
139
+ x ? l : u,
140
+ x ? u : l,
141
+ x ? 0.62 : 0.38
142
+ )
143
+ );
144
+ }
145
+ return c;
84
146
  }
85
147
  export {
86
- S as dockSplitWorkspaceItem,
87
- u as isSplitWorkspaceLayout,
88
- a as mapSplitWorkspace,
89
- l as measureSplitWorkspace,
90
- W as presetSplitWorkspace,
91
- k as reconcileSplitWorkspace,
92
- m as removeSplitWorkspaceItem,
93
- w as resizeSplitWorkspace,
94
- x as splitWorkspaceItems,
95
- o as splitWorkspacePane
148
+ F as createSplitWorkspaceArrangements,
149
+ q as dockSplitWorkspaceItem,
150
+ v as isSplitWorkspaceLayout,
151
+ k as mapSplitWorkspace,
152
+ z as measureSplitWorkspace,
153
+ A as presetSplitWorkspace,
154
+ b as reconcileSplitWorkspace,
155
+ W as removeSplitWorkspaceItem,
156
+ N as resizeSplitWorkspace,
157
+ M as splitWorkspaceItems,
158
+ w as splitWorkspacePane
96
159
  };
@@ -0,0 +1,30 @@
1
+ import { type Component } from 'solid-js';
2
+ import { type DiagramRenderOptions, type DiagramRenderResult } from './render';
3
+ export interface DiagramLabels {
4
+ diagram: string;
5
+ loading: string;
6
+ unavailable: string;
7
+ retry: string;
8
+ source: string;
9
+ preview: string;
10
+ copy: string;
11
+ copied: string;
12
+ copyFailed: string;
13
+ expand: string;
14
+ close: string;
15
+ zoomIn: string;
16
+ zoomOut: string;
17
+ fit: string;
18
+ }
19
+ export declare const diagramLabelsEnUS: DiagramLabels;
20
+ export interface DiagramProps {
21
+ source: string;
22
+ labels: DiagramLabels;
23
+ class?: string;
24
+ onCopy?: (source: string) => Promise<void>;
25
+ onOpenLink?: (href: string) => void | Promise<void>;
26
+ /** Explicit renderer injection for existing hosts; never an error fallback. */
27
+ render?: (source: string, options: DiagramRenderOptions) => Promise<DiagramRenderResult>;
28
+ }
29
+ /** Shared diagram controls. The host owns source identity, localization and navigation. */
30
+ export declare const Diagram: Component<DiagramProps>;
@@ -0,0 +1,224 @@
1
+ import { insert as d, memo as V, createComponent as y, mergeProps as H, effect as N, setAttribute as D, className as J, template as S, use as G, setStyleProperty as U, delegateEvents as K } from "solid-js/web";
2
+ import { createSignal as m, onCleanup as Z, Show as O, createMemo as Q, createEffect as j, onMount as X, on as Y } from "solid-js";
3
+ import { Dialog as p } from "../components/ui/Dialog.js";
4
+ import { renderDiagram as ee, sanitizeDiagramSvg as te } from "./render.js";
5
+ var ne = /* @__PURE__ */ S("<div class=floe-diagram-viewport data-floe-workbench-text-selection-surface=true><div class=floe-diagram-svg>"), oe = /* @__PURE__ */ S("<div class=floe-diagram-status role=status>"), re = /* @__PURE__ */ S("<div class=floe-diagram-error role=alert><strong></strong><pre></pre><pre><code>"), ie = /* @__PURE__ */ S("<button type=button>"), ae = /* @__PURE__ */ S("<pre class=floe-diagram-source data-floe-workbench-text-selection-surface=true><code>"), le = /* @__PURE__ */ S("<div class=floe-diagram><div class=floe-diagram-toolbar><button type=button>−</button><button type=button></button><button type=button>+"), se = /* @__PURE__ */ S("<section><div class=floe-diagram-toolbar><button type=button></button><button type=button></button><span class=floe-diagram-feedback role=status></span><button type=button>⤢</button></div><div>");
6
+ const me = {
7
+ diagram: "Diagram",
8
+ loading: "Rendering diagram…",
9
+ unavailable: "Diagram unavailable",
10
+ retry: "Retry",
11
+ source: "Source",
12
+ preview: "Preview",
13
+ copy: "Copy source",
14
+ copied: "Copied",
15
+ copyFailed: "Could not copy",
16
+ expand: "Expand diagram",
17
+ close: "Close",
18
+ zoomIn: "Zoom in",
19
+ zoomOut: "Zoom out",
20
+ fit: "Fit"
21
+ }, B = (e) => {
22
+ let s;
23
+ const [A, R] = m(!1), [T, I] = m(0), [v, P] = m(0), [x, $] = m("loading"), [W, w] = m(""), L = Q(() => e.source);
24
+ j(() => e.onStatus?.(x())), X(() => {
25
+ const o = new ResizeObserver((n) => {
26
+ const l = Math.round(n[0]?.contentRect.width ?? s.clientWidth);
27
+ l > 0 && I(l);
28
+ });
29
+ o.observe(s);
30
+ const r = new IntersectionObserver((n) => {
31
+ n.some((l) => l.isIntersecting) && (R(!0), r.disconnect());
32
+ }, {
33
+ rootMargin: "200px"
34
+ });
35
+ r.observe(s);
36
+ const c = s.ownerDocument.fonts, i = () => P((n) => n + 1);
37
+ c?.addEventListener("loadingdone", i), Z(() => {
38
+ o.disconnect(), r.disconnect(), c?.removeEventListener("loadingdone", i);
39
+ });
40
+ }), j(Y([L, T, A, v, () => e.revision], ([o, r, c]) => {
41
+ if (!c || !r) return;
42
+ const i = new AbortController(), n = s.ownerDocument, l = getComputedStyle(s);
43
+ $("loading"), w("");
44
+ const g = (u) => {
45
+ if (i.signal.aborted || !s.isConnected) return;
46
+ const b = n.getSelection();
47
+ for (let C = 0; b && C < b.rangeCount; C++)
48
+ if (b.getRangeAt(C).intersectsNode(s)) {
49
+ const t = () => {
50
+ n.removeEventListener("selectionchange", t), g(u);
51
+ };
52
+ n.addEventListener("selectionchange", t, {
53
+ once: !0,
54
+ signal: i.signal
55
+ });
56
+ return;
57
+ }
58
+ const f = n.createElement("template");
59
+ f.innerHTML = te(u.svg, n);
60
+ const M = f.content.querySelector("svg");
61
+ M && e.expanded && (M.style.maxWidth = "none"), s.replaceChildren(f.content), $("ready");
62
+ };
63
+ (e.render ?? ee)(o, {
64
+ signal: i.signal,
65
+ maxWidth: r,
66
+ document: n,
67
+ fontFamily: l.fontFamily,
68
+ fontFamilyMono: l.getPropertyValue("--font-mono").trim() || "monospace",
69
+ fontSize: parseFloat(l.fontSize) || 16,
70
+ links: !!e.onOpenLink
71
+ }).then(g).catch((u) => {
72
+ i.signal.aborted || (s.replaceChildren(), w(u instanceof Error ? u.message : String(u)), $("error"));
73
+ }), Z(() => i.abort());
74
+ }));
75
+ const z = (o) => {
76
+ const r = o.target instanceof Element ? o.target.closest("a") : null;
77
+ if (!r) return;
78
+ o.preventDefault();
79
+ const c = r.getAttribute("href");
80
+ !c || !/^(?:https?:\/\/|mailto:)/i.test(c) || !e.onOpenLink || Promise.resolve(e.onOpenLink(c)).catch(() => {
81
+ w(e.labels.unavailable), $("error");
82
+ });
83
+ };
84
+ return [(() => {
85
+ var o = ne(), r = o.firstChild;
86
+ r.$$click = z;
87
+ var c = s;
88
+ return typeof c == "function" ? G(c, r) : s = r, N((i) => {
89
+ var n = e.expanded ? "true" : void 0, l = e.expanded ? "auto" : "hidden", g = !!e.expanded, u = x() === "loading", b = e.scale ?? 1;
90
+ return n !== i.e && D(o, "data-floe-local-interaction-surface", i.e = n), l !== i.t && U(o, "overflow", i.t = l), g !== i.a && r.classList.toggle("floe-diagram-zoomed", i.a = g), u !== i.o && D(r, "aria-busy", i.o = u), b !== i.i && U(r, "--floe-diagram-scale", i.i = b), i;
91
+ }, {
92
+ e: void 0,
93
+ t: void 0,
94
+ a: void 0,
95
+ o: void 0,
96
+ i: void 0
97
+ }), o;
98
+ })(), y(O, {
99
+ get when() {
100
+ return x() === "loading";
101
+ },
102
+ get children() {
103
+ var o = oe();
104
+ return d(o, () => e.labels.loading), o;
105
+ }
106
+ }), y(O, {
107
+ get when() {
108
+ return x() === "error";
109
+ },
110
+ get children() {
111
+ var o = re(), r = o.firstChild, c = r.nextSibling, i = c.nextSibling, n = i.firstChild;
112
+ return d(r, () => e.labels.unavailable), d(c, W), d(n, () => e.source), o;
113
+ }
114
+ })];
115
+ }, fe = (e) => {
116
+ const [s, A] = m(!1), [R, T] = m(!1), [I, v] = m(1), [P, x] = m(0), [$, W] = m("loading"), [w, L] = m("idle");
117
+ let z, o = !1, r;
118
+ Z(() => {
119
+ o = !0, clearTimeout(z);
120
+ });
121
+ const c = async () => {
122
+ try {
123
+ await (e.onCopy ? e.onCopy(e.source) : navigator.clipboard.writeText(e.source)), o || L("copied");
124
+ } catch {
125
+ o || L("error");
126
+ }
127
+ o || (clearTimeout(z), z = setTimeout(() => L("idle"), 1600));
128
+ }, i = (n) => {
129
+ const l = typeof document < "u" ? document.activeElement : null, g = l instanceof Element && !!l.closest('[role="dialog"]');
130
+ T(n), !n && g && r?.isConnected && r.focus({
131
+ preventScroll: !0
132
+ });
133
+ };
134
+ return (() => {
135
+ var n = se(), l = n.firstChild, g = l.firstChild, u = g.nextSibling, b = u.nextSibling, f = b.nextSibling, M = l.nextSibling;
136
+ g.$$click = () => A((t) => !t), d(g, (() => {
137
+ var t = V(() => !!s());
138
+ return () => t() ? e.labels.preview : e.labels.source;
139
+ })()), u.$$click = () => {
140
+ c();
141
+ }, d(u, () => e.labels.copy), d(b, (() => {
142
+ var t = V(() => w() === "copied");
143
+ return () => t() ? e.labels.copied : V(() => w() === "error")() ? e.labels.copyFailed : "";
144
+ })()), d(l, y(O, {
145
+ get when() {
146
+ return $() === "error";
147
+ },
148
+ get children() {
149
+ var t = ie();
150
+ return t.$$click = () => x((h) => h + 1), d(t, () => e.labels.retry), t;
151
+ }
152
+ }), f), f.$$click = () => {
153
+ v(1), T(!0);
154
+ };
155
+ var C = r;
156
+ return typeof C == "function" ? G(C, f) : r = f, d(M, y(B, H(e, {
157
+ get revision() {
158
+ return P();
159
+ },
160
+ onStatus: W
161
+ }))), d(n, y(O, {
162
+ get when() {
163
+ return s();
164
+ },
165
+ get children() {
166
+ var t = ae(), h = t.firstChild;
167
+ return d(h, () => e.source), t;
168
+ }
169
+ }), null), d(n, y(p, {
170
+ get open() {
171
+ return R();
172
+ },
173
+ onOpenChange: i,
174
+ get title() {
175
+ return e.labels.diagram;
176
+ },
177
+ get closeLabel() {
178
+ return e.labels.close;
179
+ },
180
+ class: "floe-diagram-dialog",
181
+ get children() {
182
+ var t = le(), h = t.firstChild, k = h.firstChild, _ = k.nextSibling, F = _.nextSibling;
183
+ return t.$$keydown = (a) => {
184
+ a.target instanceof Element && a.target.closest("button,input,textarea") || ((a.key === "+" || a.key === "=") && (a.preventDefault(), v((E) => Math.min(4, E + 0.25))), a.key === "-" && (a.preventDefault(), v((E) => Math.max(0.5, E - 0.25))), a.key === "0" && (a.preventDefault(), v(1)));
185
+ }, k.$$click = () => v((a) => Math.max(0.5, a - 0.25)), _.$$click = () => v(1), d(_, () => e.labels.fit), F.$$click = () => v((a) => Math.min(4, a + 0.25)), d(t, y(O, {
186
+ get when() {
187
+ return R();
188
+ },
189
+ get children() {
190
+ return y(B, H(e, {
191
+ expanded: !0,
192
+ get scale() {
193
+ return I();
194
+ },
195
+ get revision() {
196
+ return P();
197
+ }
198
+ }));
199
+ }
200
+ }), null), N((a) => {
201
+ var E = e.labels.zoomOut, q = e.labels.zoomIn;
202
+ return E !== a.e && D(k, "aria-label", a.e = E), q !== a.t && D(F, "aria-label", a.t = q), a;
203
+ }, {
204
+ e: void 0,
205
+ t: void 0
206
+ }), t;
207
+ }
208
+ }), null), N((t) => {
209
+ var h = "floe-diagram " + (e.class ?? ""), k = s(), _ = $() !== "ready", F = e.labels.expand, a = s();
210
+ return h !== t.e && J(n, t.e = h), k !== t.t && D(g, "aria-pressed", t.t = k), _ !== t.a && (f.disabled = t.a = _), F !== t.o && D(f, "aria-label", t.o = F), a !== t.i && (M.hidden = t.i = a), t;
211
+ }, {
212
+ e: void 0,
213
+ t: void 0,
214
+ a: void 0,
215
+ o: void 0,
216
+ i: void 0
217
+ }), n;
218
+ })();
219
+ };
220
+ K(["click", "keydown"]);
221
+ export {
222
+ fe as Diagram,
223
+ me as diagramLabelsEnUS
224
+ };
@@ -0,0 +1,27 @@
1
+ export type DiagramErrorCode = 'syntax' | 'semantic' | 'limit' | 'unsupported-diagram' | 'unavailable';
2
+ export declare class DiagramError extends Error {
3
+ readonly code: DiagramErrorCode;
4
+ readonly line: number;
5
+ readonly column: number;
6
+ constructor(code: DiagramErrorCode, message: string, line?: number, column?: number);
7
+ }
8
+ export interface DiagramRenderOptions {
9
+ signal?: AbortSignal;
10
+ /** The owner supplies actual local CSS width, never transformed screen width. */
11
+ maxWidth?: number;
12
+ fontFamily?: string;
13
+ fontFamilyMono?: string;
14
+ fontSize?: number;
15
+ document?: Document;
16
+ /** Links remain inert unless the host explicitly owns navigation. */
17
+ links?: boolean;
18
+ }
19
+ export interface DiagramRenderResult {
20
+ svg: string;
21
+ width: number;
22
+ height: number;
23
+ type: string;
24
+ }
25
+ export declare function sanitizeDiagramSvg(svg: string, doc?: Document): string;
26
+ /** One lazy renderer for all Mermaid syntax surfaces. Never retries another engine. */
27
+ export declare function renderDiagram(source: string, options?: DiagramRenderOptions): Promise<DiagramRenderResult>;
@@ -0,0 +1,107 @@
1
+ import d from "../node_modules/.pnpm/dompurify@3.4.17/node_modules/dompurify/dist/purify.es.js";
2
+ import { secureRandomUUID as y } from "../utils/secureRandom.js";
3
+ class c extends Error {
4
+ constructor(t, l, n = 0, e = 0) {
5
+ super(l), this.code = t, this.line = n, this.column = e, this.name = "DiagramError";
6
+ }
7
+ code;
8
+ line;
9
+ column;
10
+ }
11
+ let p = Promise.resolve(), f = 0;
12
+ const u = (o) => {
13
+ if (o?.aborted) throw new DOMException("Aborted", "AbortError");
14
+ };
15
+ function S(o, t = document) {
16
+ const l = t.defaultView?.DOMParser ?? DOMParser, n = new l().parseFromString(o, "image/svg+xml"), e = [];
17
+ for (const r of Array.from(n.querySelectorAll("foreignObject"))) {
18
+ const i = r.querySelector("math");
19
+ if (!i) {
20
+ r.remove();
21
+ continue;
22
+ }
23
+ const h = t.createElement("template");
24
+ h.innerHTML = d.sanitize(i.outerHTML, { USE_PROFILES: { mathMl: !0 }, FORBID_TAGS: ["annotation-xml"], FORBID_ATTR: ["href", "style"] });
25
+ const g = h.content.querySelector("math");
26
+ if (!g) {
27
+ r.remove();
28
+ continue;
29
+ }
30
+ r.replaceChildren(), r.setAttribute("data-floe-formula", String(e.length)), e.push(g);
31
+ }
32
+ const m = d.sanitize(new XMLSerializer().serializeToString(n.documentElement), {
33
+ USE_PROFILES: { svg: !0, svgFilters: !0, mathMl: !0 },
34
+ ADD_TAGS: ["foreignObject"],
35
+ ADD_ATTR: ["role"],
36
+ FORBID_TAGS: ["script", "style", "image", "iframe", "object", "embed", "animate", "set"]
37
+ }), a = new l().parseFromString(m, "image/svg+xml"), s = a.documentElement;
38
+ if (s.localName !== "svg" || a.querySelector("parsererror")) throw new c("unavailable", "Invalid diagram SVG.");
39
+ for (const r of [s, ...Array.from(s.querySelectorAll("*"))])
40
+ for (const i of Array.from(r.attributes))
41
+ /^on/i.test(i.name) && r.removeAttribute(i.name), i.localName === "href" && !/^(?:#|https?:\/\/|mailto:)/i.test(i.value.trim()) && r.removeAttribute(i.name), /url\s*\(/i.test(i.value) && !/^url\(#[\w-]+\)$/.test(i.value.trim()) && r.removeAttribute(i.name);
42
+ for (const r of Array.from(s.querySelectorAll("foreignObject"))) {
43
+ const i = e[Number(r.getAttribute("data-floe-formula"))];
44
+ r.removeAttribute("data-floe-formula"), i ? r.append(a.importNode(i, !0)) : r.remove();
45
+ }
46
+ return new XMLSerializer().serializeToString(s);
47
+ }
48
+ async function w(o, t, l) {
49
+ if (!o.includes("$$")) return { dispose() {
50
+ } };
51
+ const { default: n } = await import("katex"), e = t.createElement("span");
52
+ return e.style.cssText = "position:fixed;left:-99999px;top:0;visibility:hidden;display:inline-block;white-space:nowrap;", e.style.fontSize = l + "px", t.body.append(e), {
53
+ dispose: () => e.remove(),
54
+ math(m, a) {
55
+ e.style.fontSize = a + "px", e.innerHTML = d.sanitize(n.renderToString(m, { output: "mathml", throwOnError: !0, trust: !1, strict: "error" }), { USE_PROFILES: { html: !0, mathMl: !0 } });
56
+ const s = e.querySelector("math");
57
+ if (!s) throw new c("semantic", "The diagram formula could not be typeset.");
58
+ const { width: r, height: i } = s.getBoundingClientRect();
59
+ return { html: s.outerHTML, width: r, height: i };
60
+ }
61
+ };
62
+ }
63
+ function A(o, t = {}) {
64
+ if (o.length > 5e4 || f >= 128) return Promise.reject(new c("limit", "Diagram rendering limit exceeded."));
65
+ f++;
66
+ const l = p.then(async () => {
67
+ await new Promise((a) => setTimeout(a, 0)), u(t.signal);
68
+ const n = t.document ?? document, { renderAsync: e } = await import("pele/lazy");
69
+ u(t.signal);
70
+ const m = await w(o, n, t.fontSize ?? 16);
71
+ try {
72
+ u(t.signal);
73
+ const a = await e(o, {
74
+ idPrefix: "floe-diagram-" + y(),
75
+ autoDirection: !1,
76
+ maxWidth: t.maxWidth,
77
+ fontFamily: t.fontFamily ?? "Inter, system-ui, sans-serif",
78
+ fontFamilyMono: t.fontFamilyMono ?? "monospace",
79
+ fontSize: t.fontSize ?? 16,
80
+ links: t.links === !0,
81
+ images: !1,
82
+ linkSchemes: ["https", "http", "mailto"],
83
+ linkRel: "noopener noreferrer",
84
+ limit: 5e4,
85
+ maxEdges: 500,
86
+ outputLimit: 4e6,
87
+ math: m.math
88
+ });
89
+ return u(t.signal), { svg: S(a.svg, n), width: a.width, height: a.height, type: a.type };
90
+ } finally {
91
+ m.dispose();
92
+ }
93
+ }).catch((n) => {
94
+ if (n instanceof c || n instanceof DOMException && n.name === "AbortError") throw n;
95
+ const e = n;
96
+ throw new c(e.code ?? "unavailable", e.message ?? "Diagram rendering failed.", e.line, e.column);
97
+ });
98
+ return p = l.catch(() => {
99
+ }).finally(() => {
100
+ f--;
101
+ }), l;
102
+ }
103
+ export {
104
+ c as DiagramError,
105
+ A as renderDiagram,
106
+ S as sanitizeDiagramSvg
107
+ };
@@ -0,0 +1,29 @@
1
+ .floe-diagram {
2
+ --pele-bg: var(--background); --pele-fg: var(--foreground);
3
+ --pele-muted: var(--muted-foreground); --pele-line: var(--muted-foreground);
4
+ --pele-surface: var(--card); --pele-surface-alt: var(--muted);
5
+ --pele-border: var(--border); --pele-accent: var(--primary);
6
+ --pele-font: var(--font-sans, Inter, system-ui, sans-serif);
7
+ --pele-font-mono: var(--font-mono, monospace);
8
+ --pele-fg-on-light: #171717; --pele-fg-on-dark: #fafafa;
9
+ min-width: 0; background:var(--background); color: var(--foreground); font: 14px/1.5 var(--pele-font);
10
+ border: 1px solid var(--border); border-radius: .5rem; overflow: hidden;
11
+ }
12
+ .floe-diagram-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:.25rem; padding:.375rem; border-bottom:1px solid var(--border); }
13
+ .floe-diagram-toolbar button { font:inherit; white-space:nowrap; border:0; border-radius:.25rem; padding:.25rem .5rem; background:transparent; color:inherit; cursor:pointer; }
14
+ .floe-diagram-toolbar button:hover,.floe-diagram-toolbar button[aria-pressed=true] { background:var(--accent); }
15
+ .floe-diagram-toolbar button:focus-visible { outline:2px solid var(--ring); outline-offset:-2px; }
16
+ .floe-diagram-feedback { flex:1; min-width:0; font-size:.85em; }
17
+ .floe-diagram-viewport { padding:.75rem; min-width:0; max-height:65vh; }
18
+ .floe-diagram-svg { min-height:2rem; width:100%; }
19
+ .floe-diagram-svg > svg { display:block; max-width:100%; height:auto; margin:auto; }
20
+ .floe-diagram-source,.floe-diagram-error pre { white-space:pre-wrap; overflow-wrap:anywhere; margin:0; padding:.75rem; font:12px/1.6 var(--pele-font-mono); }
21
+ .floe-diagram-status,.floe-diagram-error { padding:.75rem; }
22
+ .floe-diagram-error { color:var(--error,var(--foreground)); }
23
+ .floe-diagram-dialog { width:min(94vw,1100px); max-width:94vw; }
24
+ @media (forced-colors:active) { .floe-diagram { --pele-fg:CanvasText; --pele-line:CanvasText; --pele-bg:Canvas; --pele-surface:Canvas; --pele-surface-alt:Canvas; --pele-border:CanvasText; --pele-accent:Highlight; } }
25
+
26
+ .floe-diagram-zoomed > svg { width:calc(100% * var(--floe-diagram-scale,1)); max-width:none; }
27
+ .floe-diagram-toolbar button:disabled { opacity:.5; cursor:default; }
28
+
29
+ .floe-diagram-svg:not(.floe-diagram-zoomed) > svg { max-height:60vh; }