markdown-flow-ui 0.1.92 → 0.1.93-beta.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/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.cjs.js.map +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/@braintree_sanitize-url@7.1.1/node_modules/@braintree/sanitize-url/dist/index.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.cjs.js +6 -0
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.cjs.js.map +1 -0
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.es.js +350 -0
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/diff@5.2.0/node_modules/diff/lib/index.es.js.map +1 -0
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/c4Diagram-YG6GDRKO.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-S3R3BYOJ.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/chunk-TZMSLE5B.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/ganttDiagram-LVOFAZNH.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/mermaid@11.12.1/node_modules/mermaid/dist/chunks/mermaid.core/sequenceDiagram-WL72ISMW.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-input@1.8.0_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-input/es/BaseInput.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-input@1.8.0_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-input/es/BaseInput.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/ResizableTextArea.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/ResizableTextArea.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/TextArea.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/TextArea.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/rc-textarea@1.10.2_react-dom@19.0.1_react@19.0.1__react@19.0.1/node_modules/rc-textarea/es/index.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/index.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-custom-variable.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-custom-variable.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-interaction.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/remark-flow@0.1.6/node_modules/remark-flow/dist/remark-interaction.es.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.cjs.js +1 -1
- package/dist/Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/style-to-object@1.0.11/node_modules/style-to-object/cjs/index.es.js +1 -1
- package/dist/_virtual/index.cjs10.js +1 -1
- package/dist/_virtual/index.cjs2.js +1 -1
- package/dist/_virtual/index.cjs3.js +1 -1
- package/dist/_virtual/index.cjs4.js +1 -1
- package/dist/_virtual/index.cjs7.js +1 -1
- package/dist/_virtual/index.cjs8.js +1 -1
- package/dist/_virtual/index.es10.js +2 -2
- package/dist/_virtual/index.es2.js +5 -2
- package/dist/_virtual/index.es2.js.map +1 -1
- package/dist/_virtual/index.es3.js +2 -4
- package/dist/_virtual/index.es3.js.map +1 -1
- package/dist/_virtual/index.es4.js +4 -5
- package/dist/_virtual/index.es4.js.map +1 -1
- package/dist/_virtual/index.es7.js +2 -3
- package/dist/_virtual/index.es7.js.map +1 -1
- package/dist/_virtual/index.es8.js +3 -2
- package/dist/_virtual/index.es8.js.map +1 -1
- package/dist/components/ContentRender/ContentRender.cjs.js +2 -2
- package/dist/components/ContentRender/ContentRender.cjs.js.map +1 -1
- package/dist/components/ContentRender/ContentRender.es.js +111 -104
- package/dist/components/ContentRender/ContentRender.es.js.map +1 -1
- package/dist/components/ContentRender/ContentRender.stories.d.ts +1 -0
- package/dist/components/ContentRender/IframeSandbox.cjs.js +6 -5
- package/dist/components/ContentRender/IframeSandbox.cjs.js.map +1 -1
- package/dist/components/ContentRender/IframeSandbox.es.js +104 -98
- package/dist/components/ContentRender/IframeSandbox.es.js.map +1 -1
- package/dist/components/ContentRender/SandboxApp.cjs.js +3 -2
- package/dist/components/ContentRender/SandboxApp.cjs.js.map +1 -1
- package/dist/components/ContentRender/SandboxApp.es.js +92 -84
- package/dist/components/ContentRender/SandboxApp.es.js.map +1 -1
- package/dist/components/ContentRender/blackboard/blackboard-runtime.cjs.js +5 -0
- package/dist/components/ContentRender/blackboard/blackboard-runtime.cjs.js.map +1 -0
- package/dist/components/ContentRender/blackboard/blackboard-runtime.d.ts +18 -0
- package/dist/components/ContentRender/blackboard/blackboard-runtime.es.js +137 -0
- package/dist/components/ContentRender/blackboard/blackboard-runtime.es.js.map +1 -0
- package/dist/components/ContentRender/blackboard/diff-parser.cjs.js +2 -0
- package/dist/components/ContentRender/blackboard/diff-parser.cjs.js.map +1 -0
- package/dist/components/ContentRender/blackboard/diff-parser.d.ts +8 -0
- package/dist/components/ContentRender/blackboard/diff-parser.es.js +132 -0
- package/dist/components/ContentRender/blackboard/diff-parser.es.js.map +1 -0
- package/dist/components/ContentRender/blackboard/diff-parser.test.d.ts +1 -0
- package/dist/components/ContentRender/blackboard-vendor.cjs.js +2 -0
- package/dist/components/ContentRender/blackboard-vendor.cjs.js.map +1 -0
- package/dist/components/ContentRender/blackboard-vendor.d.ts +5 -0
- package/dist/components/ContentRender/blackboard-vendor.es.js +15 -0
- package/dist/components/ContentRender/blackboard-vendor.es.js.map +1 -0
- package/dist/components/ContentRender/index.cjs.js +1 -1
- package/dist/components/ContentRender/index.es.js +1 -0
- package/dist/components/ContentRender/index.es.js.map +1 -1
- package/dist/components/ContentRender/utils/split-content.cjs.js +2 -2
- package/dist/components/ContentRender/utils/split-content.cjs.js.map +1 -1
- package/dist/components/ContentRender/utils/split-content.es.js +118 -109
- package/dist/components/ContentRender/utils/split-content.es.js.map +1 -1
- package/dist/components/ContentRender/vendor/daisyui-v4.min.css.cjs.js +22 -0
- package/dist/components/ContentRender/vendor/daisyui-v4.min.css.cjs.js.map +1 -0
- package/dist/components/ContentRender/vendor/daisyui-v4.min.css.es.js +25 -0
- package/dist/components/ContentRender/vendor/daisyui-v4.min.css.es.js.map +1 -0
- package/dist/components/ContentRender/vendor/gsap-v3.min.cjs.js +12 -0
- package/dist/components/ContentRender/vendor/gsap-v3.min.cjs.js.map +1 -0
- package/dist/components/ContentRender/vendor/gsap-v3.min.es.js +15 -0
- package/dist/components/ContentRender/vendor/gsap-v3.min.es.js.map +1 -0
- package/dist/components/ContentRender/vendor/tailwindcss-v3.min.cjs.js +2 -0
- package/dist/components/ContentRender/vendor/tailwindcss-v3.min.cjs.js.map +1 -0
- package/dist/components/ContentRender/vendor/tailwindcss-v3.min.es.js +5 -0
- package/dist/components/ContentRender/vendor/tailwindcss-v3.min.es.js.map +1 -0
- package/dist/components/MarkdownFlow/MarkdownFlow.cjs.js +1 -1
- package/dist/components/MarkdownFlow/MarkdownFlow.cjs.js.map +1 -1
- package/dist/components/MarkdownFlow/MarkdownFlow.es.js +3 -2
- package/dist/components/MarkdownFlow/MarkdownFlow.es.js.map +1 -1
- package/dist/components/ui/inputGroup/textarea.cjs.js +1 -1
- package/dist/components/ui/inputGroup/textarea.es.js +1 -1
- package/dist/markdown-flow-ui-lib.css +1 -1
- package/package.json +4 -1
|
@@ -1,106 +1,112 @@
|
|
|
1
|
-
import { j as
|
|
2
|
-
import
|
|
3
|
-
import { createRoot as
|
|
4
|
-
import
|
|
5
|
-
import { splitContentSegments as
|
|
6
|
-
import
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import { j as m } from "../../_virtual/jsx-runtime.es.js";
|
|
2
|
+
import D, { useRef as d, useState as F, useEffect as x } from "react";
|
|
3
|
+
import { createRoot as K } from "react-dom/client";
|
|
4
|
+
import G from "./SandboxApp.es.js";
|
|
5
|
+
import { splitContentSegments as T } from "./utils/split-content.es.js";
|
|
6
|
+
import Y from "./ContentRender.es.js";
|
|
7
|
+
const Z = () => import("./blackboard-vendor.es.js").then((c) => c.injectBlackboardLibraries), L = /!\+\+\+[\s\S]*?!\+\+\+/g, J = (c) => {
|
|
8
|
+
const l = c.trim();
|
|
9
|
+
return !l || !l.match(L)?.length ? !1 : l.replace(L, "").trim().length === 0;
|
|
10
|
+
}, nt = ({
|
|
11
|
+
content: c,
|
|
12
|
+
type: l,
|
|
13
|
+
className: O,
|
|
14
|
+
loadingText: v,
|
|
15
|
+
styleLoadingText: j,
|
|
16
|
+
scriptLoadingText: A,
|
|
17
|
+
fullScreenButtonText: w,
|
|
18
|
+
hideFullScreen: M = !1,
|
|
19
|
+
mode: r = "content"
|
|
17
20
|
}) => {
|
|
18
|
-
const N =
|
|
19
|
-
}), [
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
const N = d(null), u = d(null), R = d(null), z = d(null), y = d(() => {
|
|
22
|
+
}), [_, $] = F(480), [B, q] = F(0), [I, P] = F(!1), k = d(""), i = D.useMemo(() => {
|
|
23
|
+
if (r === "blackboard" && l === "sandbox")
|
|
24
|
+
return c || "";
|
|
25
|
+
const t = T(c).filter((n) => n.type === "sandbox");
|
|
26
|
+
return (r === "blackboard" ? t[t.length - 1]?.value || "" : t.map((n) => n.value).join(`
|
|
22
27
|
`)) || "";
|
|
23
|
-
}, [
|
|
24
|
-
const e =
|
|
28
|
+
}, [c, r, l]), S = D.useMemo(() => {
|
|
29
|
+
const e = i.trim();
|
|
25
30
|
if (!e) return !1;
|
|
26
31
|
const t = e.match(/^<([a-zA-Z][\w:-]*)(\s[^>]*?)?>/);
|
|
27
32
|
if (!t) return !1;
|
|
28
|
-
const
|
|
29
|
-
if (
|
|
33
|
+
const o = t[2] || "", n = o.match(/\bheight\s*=\s*["']([^"']+)["']/i);
|
|
34
|
+
if (n && /vh$/i.test(n[1].trim()))
|
|
30
35
|
return !0;
|
|
31
|
-
const
|
|
32
|
-
return
|
|
33
|
-
}, [
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
|
|
36
|
+
const b = o.match(/\bstyle\s*=\s*["']([^"']+)["']/i);
|
|
37
|
+
return b ? /height\s*:\s*[^;]*vh\b/i.test(b[1]) : !1;
|
|
38
|
+
}, [i]);
|
|
39
|
+
x(() => {
|
|
40
|
+
if (r !== "blackboard" || l !== "sandbox") {
|
|
41
|
+
k.current = i;
|
|
37
42
|
return;
|
|
38
43
|
}
|
|
39
|
-
const e =
|
|
40
|
-
!
|
|
41
|
-
}, [
|
|
42
|
-
const e =
|
|
44
|
+
const e = k.current, t = e && i.startsWith(e), o = J(i);
|
|
45
|
+
!t && e && !o && q((n) => n + 1), k.current = i;
|
|
46
|
+
}, [i, r, l]), x(() => {
|
|
47
|
+
const e = u.current;
|
|
43
48
|
if (!e) return;
|
|
44
49
|
const t = e.contentDocument;
|
|
45
50
|
if (!t) return;
|
|
46
51
|
t.open(), t.write(`<!DOCTYPE html>
|
|
47
|
-
<html>
|
|
52
|
+
<html${r === "blackboard" ? ' style="height: 100%;"' : ""}>
|
|
48
53
|
<head>
|
|
49
54
|
<meta charset="utf-8" />
|
|
55
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
50
56
|
<style>
|
|
51
|
-
html, body { margin: 0; padding: 0; }
|
|
57
|
+
html, body { margin: 0; padding: 0;${r === "blackboard" ? " width: 100%; height: 100%; overflow: auto;" : ""} }
|
|
52
58
|
*, *::before, *::after { box-sizing: border-box; }
|
|
53
59
|
</style>
|
|
54
60
|
</head>
|
|
55
61
|
<body>
|
|
56
62
|
<div id="root"></div>
|
|
57
63
|
</body>
|
|
58
|
-
</html>`), t.close(), z.current = t;
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
66
|
-
const
|
|
67
|
-
return Number.isNaN(
|
|
68
|
-
},
|
|
69
|
-
if (!
|
|
70
|
-
const
|
|
64
|
+
</html>`), t.close(), r === "blackboard" && Z().then((h) => h(t)), z.current = t;
|
|
65
|
+
const o = t.getElementById("root");
|
|
66
|
+
if (!o) return;
|
|
67
|
+
const n = K(o);
|
|
68
|
+
R.current = n;
|
|
69
|
+
const b = (h, f) => {
|
|
70
|
+
const s = h.trim().toLowerCase();
|
|
71
|
+
if (!s) return null;
|
|
72
|
+
const a = Number.parseFloat(s);
|
|
73
|
+
return Number.isNaN(a) ? null : s.endsWith("vh") ? a / 100 * f : s.endsWith("px") || /^[0-9.]+$/.test(s) ? a : null;
|
|
74
|
+
}, W = () => {
|
|
75
|
+
if (!u.current || !t.body) return null;
|
|
76
|
+
const f = t.body.querySelector(
|
|
71
77
|
".sandbox-wrapper"
|
|
72
78
|
)?.firstElementChild;
|
|
73
|
-
if (!
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
const
|
|
77
|
-
if (!
|
|
78
|
-
const C =
|
|
79
|
-
return
|
|
80
|
-
},
|
|
81
|
-
if (!
|
|
82
|
-
const
|
|
79
|
+
if (!f) return null;
|
|
80
|
+
const s = Array.from(f.children);
|
|
81
|
+
if (s.length !== 1) return null;
|
|
82
|
+
const a = s[0], g = a.style.height || a.getAttribute("height");
|
|
83
|
+
if (!g) return null;
|
|
84
|
+
const C = u.current.ownerDocument?.documentElement?.clientHeight || window.innerHeight, p = b(g, C);
|
|
85
|
+
return p ? Math.ceil(p) : null;
|
|
86
|
+
}, E = () => {
|
|
87
|
+
if (!u.current || !t.body) return;
|
|
88
|
+
const h = t.body.getBoundingClientRect(), f = t.documentElement?.getBoundingClientRect(), s = h.height, a = f?.height || 0, g = Math.max(s, a), C = W(), p = Math.max(
|
|
83
89
|
200,
|
|
84
|
-
C ?? Math.ceil(
|
|
90
|
+
C ?? Math.ceil(g)
|
|
85
91
|
);
|
|
86
|
-
|
|
92
|
+
$(p);
|
|
87
93
|
};
|
|
88
|
-
|
|
89
|
-
const H = new ResizeObserver(() =>
|
|
90
|
-
return H.observe(t.body),
|
|
94
|
+
y.current = E, E();
|
|
95
|
+
const H = new ResizeObserver(() => E());
|
|
96
|
+
return H.observe(t.body), o && H.observe(o), () => {
|
|
91
97
|
H.disconnect(), setTimeout(() => {
|
|
92
|
-
|
|
98
|
+
n.unmount(), R.current = null, z.current = null, y.current = () => {
|
|
93
99
|
};
|
|
94
100
|
}, 0);
|
|
95
101
|
};
|
|
96
|
-
}, []),
|
|
102
|
+
}, []), x(() => {
|
|
97
103
|
const e = () => {
|
|
98
|
-
|
|
104
|
+
P(!!document.fullscreenElement);
|
|
99
105
|
};
|
|
100
106
|
return document.addEventListener("fullscreenchange", e), () => document.removeEventListener("fullscreenchange", e);
|
|
101
107
|
}, []);
|
|
102
|
-
const
|
|
103
|
-
const e = N.current ||
|
|
108
|
+
const V = () => {
|
|
109
|
+
const e = N.current || u.current;
|
|
104
110
|
if (e) {
|
|
105
111
|
if (document.fullscreenElement) {
|
|
106
112
|
document.exitFullscreen().catch(() => {
|
|
@@ -111,59 +117,59 @@ const ee = ({
|
|
|
111
117
|
});
|
|
112
118
|
}
|
|
113
119
|
};
|
|
114
|
-
return
|
|
115
|
-
const e =
|
|
120
|
+
return x(() => {
|
|
121
|
+
const e = R.current;
|
|
116
122
|
e && (e.render(
|
|
117
|
-
/* @__PURE__ */
|
|
118
|
-
|
|
123
|
+
/* @__PURE__ */ m.jsx(
|
|
124
|
+
G,
|
|
119
125
|
{
|
|
120
|
-
html:
|
|
121
|
-
loadingText:
|
|
122
|
-
styleLoadingText:
|
|
123
|
-
scriptLoadingText:
|
|
124
|
-
fullScreenButtonText:
|
|
125
|
-
hideFullScreen:
|
|
126
|
-
resetToken:
|
|
127
|
-
hasRootVhHeight:
|
|
128
|
-
mode:
|
|
126
|
+
html: i,
|
|
127
|
+
loadingText: v,
|
|
128
|
+
styleLoadingText: j,
|
|
129
|
+
scriptLoadingText: A,
|
|
130
|
+
fullScreenButtonText: w,
|
|
131
|
+
hideFullScreen: M,
|
|
132
|
+
resetToken: B,
|
|
133
|
+
hasRootVhHeight: S,
|
|
134
|
+
mode: r
|
|
129
135
|
}
|
|
130
136
|
)
|
|
131
|
-
), requestAnimationFrame(() =>
|
|
137
|
+
), requestAnimationFrame(() => y.current?.()));
|
|
132
138
|
}, [
|
|
133
|
-
m,
|
|
134
139
|
c,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
x,
|
|
140
|
+
i,
|
|
141
|
+
v,
|
|
142
|
+
j,
|
|
139
143
|
A,
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
w,
|
|
145
|
+
B,
|
|
146
|
+
r
|
|
147
|
+
]), /* @__PURE__ */ m.jsxs(
|
|
142
148
|
"div",
|
|
143
149
|
{
|
|
144
150
|
ref: N,
|
|
145
|
-
"data-root-vh":
|
|
151
|
+
"data-root-vh": S ? "true" : "false",
|
|
146
152
|
className: "w-full h-full overflow-auto relative flex flex-col content-render-iframe-sandbox",
|
|
147
153
|
children: [
|
|
148
|
-
!
|
|
154
|
+
!M && /* @__PURE__ */ m.jsx(
|
|
149
155
|
"button",
|
|
150
156
|
{
|
|
151
157
|
type: "button",
|
|
152
|
-
onClick:
|
|
158
|
+
onClick: V,
|
|
153
159
|
className: "absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer",
|
|
154
|
-
children:
|
|
160
|
+
children: I ? "退出全屏" : w || "全屏浏览"
|
|
155
161
|
}
|
|
156
162
|
),
|
|
157
|
-
|
|
163
|
+
r === "blackboard" && l === "markdown" ? /* @__PURE__ */ m.jsx(Y, { content: c }) : /* @__PURE__ */ m.jsx(
|
|
158
164
|
"iframe",
|
|
159
165
|
{
|
|
160
|
-
ref:
|
|
166
|
+
ref: u,
|
|
161
167
|
sandbox: "allow-scripts allow-same-origin",
|
|
162
168
|
allow: "fullscreen",
|
|
163
169
|
allowFullScreen: !0,
|
|
164
170
|
className: "w-full",
|
|
165
171
|
style: {
|
|
166
|
-
height:
|
|
172
|
+
height: r === "blackboard" ? "100%" : `${_}px`
|
|
167
173
|
// height: `${height}px`,
|
|
168
174
|
// margin: "16px 0",
|
|
169
175
|
}
|
|
@@ -174,6 +180,6 @@ const ee = ({
|
|
|
174
180
|
);
|
|
175
181
|
};
|
|
176
182
|
export {
|
|
177
|
-
|
|
183
|
+
nt as default
|
|
178
184
|
};
|
|
179
185
|
//# sourceMappingURL=IframeSandbox.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IframeSandbox.es.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport { splitContentSegments } from \"./utils/split-content\";\nimport ContentRender from \"./ContentRender\";\nexport interface IframeSandboxProps {\n content: string;\n className?: string;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n fullScreenButtonText?: string;\n hideFullScreen?: boolean;\n mode?: \"content\" | \"blackboard\";\n type: \"sandbox\" | \"markdown\";\n}\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const docRef = useRef<Document | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [height, setHeight] = useState(480);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(() => {\n const segments = splitContentSegments(content);\n // console.log('segments=====', segments);\n const sandboxSegments = segments.filter((seg) => seg.type === \"sandbox\");\n const sandboxContent =\n mode === \"blackboard\"\n ? sandboxSegments[sandboxSegments.length - 1]?.value || \"\"\n : sandboxSegments.map((seg) => seg.value).join(\"\\n\");\n return sandboxContent || \"\";\n }, [content, mode]);\n const hasRootVhHeight = React.useMemo(() => {\n const normalized = htmlContent.trim();\n if (!normalized) return false;\n const rootMatch = normalized.match(/^<([a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/);\n if (!rootMatch) return false;\n const attrs = rootMatch[2] || \"\";\n const heightAttrMatch = attrs.match(/\\bheight\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (heightAttrMatch && /vh$/i.test(heightAttrMatch[1].trim())) {\n return true;\n }\n const styleAttrMatch = attrs.match(/\\bstyle\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (!styleAttrMatch) return false;\n return /height\\s*:\\s*[^;]*vh\\b/i.test(styleAttrMatch[1]);\n }, [htmlContent]);\n useEffect(() => {\n if (mode !== \"blackboard\") {\n prevHtmlRef.current = htmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && htmlContent.startsWith(prev);\n if (!isContinuation && prev) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = htmlContent;\n }, [htmlContent, mode]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe) return undefined;\n\n const doc = iframe.contentDocument;\n if (!doc) return undefined;\n\n doc.open();\n doc.write(`<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <style>\n html, body { margin: 0; padding: 0; }\n *, *::before, *::after { box-sizing: border-box; }\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n </body>\n</html>`);\n doc.close();\n docRef.current = doc;\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n\n const parseExplicitHeight = (\n value: string,\n parentViewportHeight: number\n ) => {\n const normalized = value.trim().toLowerCase();\n if (!normalized) return null;\n const numeric = Number.parseFloat(normalized);\n if (Number.isNaN(numeric)) return null;\n if (normalized.endsWith(\"vh\")) {\n return (numeric / 100) * parentViewportHeight;\n }\n if (normalized.endsWith(\"px\") || /^[0-9.]+$/.test(normalized)) {\n return numeric;\n }\n return null;\n };\n\n const resolveExplicitHeight = () => {\n if (!iframeRef.current || !doc.body) return null;\n const wrapper = doc.body.querySelector(\n \".sandbox-wrapper\"\n ) as HTMLElement | null;\n const container = wrapper?.firstElementChild as HTMLElement | null;\n if (!container) return null;\n const elements = Array.from(container.children) as HTMLElement[];\n if (elements.length !== 1) return null;\n const target = elements[0];\n const heightValue = target.style.height || target.getAttribute(\"height\");\n if (!heightValue) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n const parsed = parseExplicitHeight(heightValue, parentViewportHeight);\n return parsed ? Math.ceil(parsed) : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n const bodyRect = doc.body.getBoundingClientRect();\n const htmlRect = doc.documentElement?.getBoundingClientRect();\n const bodyHeight = bodyRect.height;\n const htmlHeight = htmlRect?.height || 0;\n const contentHeight = Math.max(bodyHeight, htmlHeight);\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(contentHeight)\n );\n setHeight(nextHeight);\n };\n updateHeightRef.current = updateHeight;\n\n updateHeight();\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n return () => {\n resizeObserver.disconnect();\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n docRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={htmlContent}\n loadingText={loadingText}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n fullScreenButtonText={fullScreenButtonText}\n hideFullScreen={hideFullScreen}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n />\n );\n requestAnimationFrame(() => updateHeightRef.current?.());\n }, [\n content,\n htmlContent,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n resetToken,\n mode,\n ]);\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={\n \"w-full h-full overflow-auto relative flex flex-col content-render-iframe-sandbox\"\n }\n >\n {!hideFullScreen && (\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n className={\n \"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer\"\n }\n >\n {isFullscreen ? \"退出全屏\" : fullScreenButtonText || \"全屏浏览\"}\n </button>\n )}\n {mode === \"blackboard\" && type === \"markdown\" ? (\n <ContentRender content={content} />\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin\"\n allow=\"fullscreen\"\n allowFullScreen\n className={(className, \"w-full\")}\n style={{\n height: mode === \"blackboard\" ? \"100%\" : `${height}px`,\n // height: `${height}px`,\n // margin: \"16px 0\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["IframeSandbox","content","type","className","loadingText","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","containerRef","useRef","iframeRef","rootRef","docRef","updateHeightRef","height","setHeight","useState","resetToken","setResetToken","isFullscreen","setIsFullscreen","prevHtmlRef","htmlContent","React","sandboxSegments","splitContentSegments","seg","hasRootVhHeight","normalized","rootMatch","attrs","heightAttrMatch","styleAttrMatch","useEffect","prev","token","iframe","doc","rootEl","root","createRoot","parseExplicitHeight","value","parentViewportHeight","numeric","resolveExplicitHeight","container","elements","target","heightValue","parsed","updateHeight","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","explicitHeight","nextHeight","resizeObserver","onFullscreenChange","toggleFullscreen","jsx","SandboxApp","jsxs","ContentRender"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IframeSandbox.es.js","sources":["../../../src/components/ContentRender/IframeSandbox.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createRoot, Root } from \"react-dom/client\";\nimport SandboxApp from \"./SandboxApp\";\nimport { splitContentSegments } from \"./utils/split-content\";\nimport ContentRender from \"./ContentRender\";\n// Lazy-loaded to avoid bundling ~3.3 MB of vendor libs for non-blackboard consumers\nconst loadBlackboardVendor = () =>\n import(\"./blackboard-vendor\").then((m) => m.injectBlackboardLibraries);\nexport interface IframeSandboxProps {\n content: string;\n className?: string;\n loadingText?: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n fullScreenButtonText?: string;\n hideFullScreen?: boolean;\n mode?: \"content\" | \"blackboard\";\n type: \"sandbox\" | \"markdown\";\n}\n\nconst DIFF_BLOCK_GLOBAL_PATTERN = /!\\+\\+\\+[\\s\\S]*?!\\+\\+\\+/g;\n\nconst isPureDiffPayload = (raw: string) => {\n const normalized = raw.trim();\n if (!normalized) {\n return false;\n }\n\n const matchedBlocks = normalized.match(DIFF_BLOCK_GLOBAL_PATTERN);\n if (!matchedBlocks?.length) {\n return false;\n }\n\n const rest = normalized.replace(DIFF_BLOCK_GLOBAL_PATTERN, \"\").trim();\n return rest.length === 0;\n};\n\nconst IframeSandbox: React.FC<IframeSandboxProps> = ({\n content,\n type,\n className,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n hideFullScreen = false,\n mode = \"content\",\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const rootRef = useRef<Root | null>(null);\n const docRef = useRef<Document | null>(null);\n const updateHeightRef = useRef<() => void>(() => {});\n const [height, setHeight] = useState(480);\n const [resetToken, setResetToken] = useState(0);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const prevHtmlRef = useRef<string>(\"\");\n const htmlContent = React.useMemo(() => {\n if (mode === \"blackboard\" && type === \"sandbox\") {\n return content || \"\";\n }\n\n const segments = splitContentSegments(content);\n // console.log('segments=====', segments);\n const sandboxSegments = segments.filter((seg) => seg.type === \"sandbox\");\n const sandboxContent =\n mode === \"blackboard\"\n ? sandboxSegments[sandboxSegments.length - 1]?.value || \"\"\n : sandboxSegments.map((seg) => seg.value).join(\"\\n\");\n return sandboxContent || \"\";\n }, [content, mode, type]);\n const hasRootVhHeight = React.useMemo(() => {\n const normalized = htmlContent.trim();\n if (!normalized) return false;\n const rootMatch = normalized.match(/^<([a-zA-Z][\\w:-]*)(\\s[^>]*?)?>/);\n if (!rootMatch) return false;\n const attrs = rootMatch[2] || \"\";\n const heightAttrMatch = attrs.match(/\\bheight\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (heightAttrMatch && /vh$/i.test(heightAttrMatch[1].trim())) {\n return true;\n }\n const styleAttrMatch = attrs.match(/\\bstyle\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (!styleAttrMatch) return false;\n return /height\\s*:\\s*[^;]*vh\\b/i.test(styleAttrMatch[1]);\n }, [htmlContent]);\n useEffect(() => {\n if (mode !== \"blackboard\" || type !== \"sandbox\") {\n prevHtmlRef.current = htmlContent;\n return;\n }\n const prev = prevHtmlRef.current;\n const isContinuation = prev && htmlContent.startsWith(prev);\n const shouldKeepState = isPureDiffPayload(htmlContent);\n if (!isContinuation && prev && !shouldKeepState) {\n setResetToken((token) => token + 1);\n }\n prevHtmlRef.current = htmlContent;\n }, [htmlContent, mode, type]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe) return undefined;\n\n const doc = iframe.contentDocument;\n if (!doc) return undefined;\n\n doc.open();\n doc.write(`<!DOCTYPE html>\n<html${mode === \"blackboard\" ? ' style=\"height: 100%;\"' : \"\"}>\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n html, body { margin: 0; padding: 0;${mode === \"blackboard\" ? \" width: 100%; height: 100%; overflow: auto;\" : \"\"} }\n *, *::before, *::after { box-sizing: border-box; }\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n </body>\n</html>`);\n doc.close();\n\n // Inject Tailwind/DaisyUI/GSAP into iframe for blackboard mode.\n // Dynamic import keeps ~3.3 MB of vendor libs out of the main bundle.\n // Tailwind's MutationObserver ensures styles apply even if content renders first.\n if (mode === \"blackboard\") {\n loadBlackboardVendor().then((inject) => inject(doc));\n }\n\n docRef.current = doc;\n\n const rootEl = doc.getElementById(\"root\");\n if (!rootEl) return undefined;\n\n const root = createRoot(rootEl);\n rootRef.current = root;\n\n const parseExplicitHeight = (\n value: string,\n parentViewportHeight: number\n ) => {\n const normalized = value.trim().toLowerCase();\n if (!normalized) return null;\n const numeric = Number.parseFloat(normalized);\n if (Number.isNaN(numeric)) return null;\n if (normalized.endsWith(\"vh\")) {\n return (numeric / 100) * parentViewportHeight;\n }\n if (normalized.endsWith(\"px\") || /^[0-9.]+$/.test(normalized)) {\n return numeric;\n }\n return null;\n };\n\n const resolveExplicitHeight = () => {\n if (!iframeRef.current || !doc.body) return null;\n const wrapper = doc.body.querySelector(\n \".sandbox-wrapper\"\n ) as HTMLElement | null;\n const container = wrapper?.firstElementChild as HTMLElement | null;\n if (!container) return null;\n const elements = Array.from(container.children) as HTMLElement[];\n if (elements.length !== 1) return null;\n const target = elements[0];\n const heightValue = target.style.height || target.getAttribute(\"height\");\n if (!heightValue) return null;\n const parentViewportHeight =\n iframeRef.current.ownerDocument?.documentElement?.clientHeight ||\n window.innerHeight;\n const parsed = parseExplicitHeight(heightValue, parentViewportHeight);\n return parsed ? Math.ceil(parsed) : null;\n };\n\n const updateHeight = () => {\n if (!iframeRef.current || !doc.body) return;\n const bodyRect = doc.body.getBoundingClientRect();\n const htmlRect = doc.documentElement?.getBoundingClientRect();\n const bodyHeight = bodyRect.height;\n const htmlHeight = htmlRect?.height || 0;\n const contentHeight = Math.max(bodyHeight, htmlHeight);\n const explicitHeight = resolveExplicitHeight();\n const nextHeight = Math.max(\n 200,\n explicitHeight ?? Math.ceil(contentHeight)\n );\n setHeight(nextHeight);\n };\n updateHeightRef.current = updateHeight;\n\n updateHeight();\n\n const resizeObserver = new ResizeObserver(() => updateHeight());\n resizeObserver.observe(doc.body);\n if (rootEl) {\n resizeObserver.observe(rootEl);\n }\n\n return () => {\n resizeObserver.disconnect();\n // Defer unmount to avoid React warning when parent is mid-render\n setTimeout(() => {\n root.unmount();\n rootRef.current = null;\n docRef.current = null;\n updateHeightRef.current = () => {};\n }, 0);\n };\n }, []);\n\n useEffect(() => {\n const onFullscreenChange = () => {\n setIsFullscreen(Boolean(document.fullscreenElement));\n };\n document.addEventListener(\"fullscreenchange\", onFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", onFullscreenChange);\n }, []);\n\n const toggleFullscreen = () => {\n const target = containerRef.current || iframeRef.current;\n if (!target) return;\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n return;\n }\n if (target.requestFullscreen) {\n target.requestFullscreen().catch(() => {});\n }\n };\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n root.render(\n <SandboxApp\n html={htmlContent}\n loadingText={loadingText}\n styleLoadingText={styleLoadingText}\n scriptLoadingText={scriptLoadingText}\n fullScreenButtonText={fullScreenButtonText}\n hideFullScreen={hideFullScreen}\n resetToken={resetToken}\n hasRootVhHeight={hasRootVhHeight}\n mode={mode}\n />\n );\n requestAnimationFrame(() => updateHeightRef.current?.());\n }, [\n content,\n htmlContent,\n loadingText,\n styleLoadingText,\n scriptLoadingText,\n fullScreenButtonText,\n resetToken,\n mode,\n ]);\n\n return (\n <div\n ref={containerRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className={\n \"w-full h-full overflow-auto relative flex flex-col content-render-iframe-sandbox\"\n }\n >\n {!hideFullScreen && (\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n className={\n \"absolute top-2 right-2 z-50 p-1.5 bg-black/75 text-white rounded-md cursor-pointer\"\n }\n >\n {isFullscreen ? \"退出全屏\" : fullScreenButtonText || \"全屏浏览\"}\n </button>\n )}\n {mode === \"blackboard\" && type === \"markdown\" ? (\n <ContentRender content={content} />\n ) : (\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin\"\n allow=\"fullscreen\"\n allowFullScreen\n className={(className, \"w-full\")}\n style={{\n height: mode === \"blackboard\" ? \"100%\" : `${height}px`,\n // height: `${height}px`,\n // margin: \"16px 0\",\n }}\n />\n )}\n </div>\n );\n};\n\nexport default IframeSandbox;\n"],"names":["loadBlackboardVendor","m","DIFF_BLOCK_GLOBAL_PATTERN","isPureDiffPayload","raw","normalized","IframeSandbox","content","type","className","loadingText","styleLoadingText","scriptLoadingText","fullScreenButtonText","hideFullScreen","mode","containerRef","useRef","iframeRef","rootRef","docRef","updateHeightRef","height","setHeight","useState","resetToken","setResetToken","isFullscreen","setIsFullscreen","prevHtmlRef","htmlContent","React","sandboxSegments","splitContentSegments","seg","hasRootVhHeight","rootMatch","attrs","heightAttrMatch","styleAttrMatch","useEffect","prev","isContinuation","shouldKeepState","token","iframe","doc","inject","rootEl","root","createRoot","parseExplicitHeight","value","parentViewportHeight","numeric","resolveExplicitHeight","container","elements","target","heightValue","parsed","updateHeight","bodyRect","htmlRect","bodyHeight","htmlHeight","contentHeight","explicitHeight","nextHeight","resizeObserver","onFullscreenChange","toggleFullscreen","jsx","SandboxApp","jsxs","ContentRender"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const S=require("../../_virtual/jsx-runtime.cjs.js"),t=require("react"),J=require("./blackboard/blackboard-runtime.cjs.js"),K=require("../../Documents/ai-shifu/markdown-flow-ui/node_modules/.pnpm/lucide-react@0.525.0_react@19.0.1/node_modules/lucide-react/dist/esm/icons/loader-circle.cjs.js"),U=({html:l,styleLoadingText:D,scriptLoadingText:G,resetToken:m=0,mode:w="content",hasRootVhHeight:F=!1})=>{const _=t.useRef(null),C=t.useRef(null),[,j]=t.useState(!0),[z,N]=t.useState(!1),[W,A]=t.useState(!1),f=t.useRef([]),d=t.useRef([]),I=t.useRef(0),M=t.useRef(0),h=t.useRef(null),x=t.useRef(null),y=t.useRef(!1),b=t.useRef(!1),g=t.useRef(!1),L=t.useRef(m),o=t.useRef(null),H=200,c=n=>{n.current&&(clearTimeout(n.current),n.current=null)},T=(n,s,a,v)=>{const u=performance.now()-a.current,E=Math.max(0,H-u);c(s),s.current=window.setTimeout(()=>{n(!1),v?.(),s.current=null},E)};t.useEffect(()=>{const n=C.current?.ownerDocument;if(!n)return;const s="sandbox-spinner-style";let a=n.getElementById(s);a||(a=n.createElement("style"),a.id=s,n.head?.appendChild(a)),a.textContent=`
|
|
2
2
|
@keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }
|
|
3
3
|
.sandbox-wrapper { align-items: center; }
|
|
4
4
|
.sandbox-container { width: 100%; }
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
@media (max-width: 640px) {
|
|
8
8
|
.sandbox-wrapper { align-items: stretch; }
|
|
9
9
|
.sandbox-wrapper[data-root-vh="true"] .sandbox-container > :first-child { height: auto !important; }
|
|
10
|
+
.sandbox-wrapper[data-root-vh="true"] .sandbox-container > #ppt-container > :first-child { height: auto !important; }
|
|
10
11
|
}
|
|
11
|
-
`},[]),t.useEffect(()=>{
|
|
12
|
+
`},[]),t.useEffect(()=>{const n=C.current;if(!n)return;if(m!==L.current&&(g.current=!1,L.current=m,o.current?.reset()),c(h),c(x),y.current=!1,b.current=!1,N(!1),A(!1),w==="blackboard"){f.current.forEach(r=>r.remove()),f.current=[],d.current.forEach(r=>r.remove()),d.current=[],o.current||(o.current=new J.BlackboardRuntime(n)),o.current.update(l);const e=o.current.hasRenderedContent();g.current=e,j(!e);return}o.current&&(o.current.reset(),o.current=null);const s=n.ownerDocument,a=s?.body;if(!a)return;f.current.forEach(e=>e.remove()),f.current=[],d.current.forEach(e=>e.remove()),d.current=[];const v=g.current;j(!v),n.innerHTML="";const u=document.createElement("div");u.innerHTML=l;const E=(l.match(/<script[\s>]/gi)||[]).length,V=(l.match(/<\/script>/gi)||[]).length,P=E>0&&E===V,p=[];Array.from(u.querySelectorAll("style, script")).forEach(e=>{if(e.tagName.toLowerCase()==="style"){const r=s.createElement("style");r.textContent=e.textContent||"",Array.from(e.attributes).forEach(i=>{r.setAttribute(i.name,i.value)}),p.push(r)}else{const r=s.createElement("script");Array.from(e.attributes).forEach(i=>{r.setAttribute(i.name,i.value)}),r.textContent=e.textContent||"",p.push(r)}e.remove()});const k=p.some(e=>e.tagName.toLowerCase()==="style"),q=p.some(e=>e.tagName.toLowerCase()==="script");k&&(y.current=!0,I.current=performance.now(),c(h),N(!0)),q&&(b.current=!0,M.current=performance.now(),c(x),A(!0));const B=!!u.firstElementChild;j(!B&&!v),B&&(g.current=!0);const Q=Array.from(u.childNodes);n.append(...Q),p.forEach(e=>{if(e.tagName.toLowerCase()==="style"){s.head?.appendChild(e),f.current.push(e);return}if(P){const r=e,i=r.textContent||"";if(!r.src)try{new Function(i)}catch{r.remove();return}try{a.appendChild(r),d.current.push(r)}catch{r.remove()}}else e.remove()}),requestAnimationFrame(()=>{k&&T(N,h,I,()=>{y.current=!1}),q&&T(A,x,M,()=>{b.current=!1})})},[l,w,m]),t.useEffect(()=>()=>{c(h),c(x),o.current=null},[]);const R=W||b.current?G||"Building scripts cache...":z||y.current?D||"Building styles...":null,O=w==="blackboard";return S.jsxRuntimeExports.jsxs("div",{ref:_,"data-root-vh":F?"true":"false",className:"sandbox-wrapper",style:{position:"relative",width:"100%",height:O?"100dvh":void 0,display:"flex",flexDirection:"column",justifyContent:"space-around"},"aria-busy":!!R,children:[S.jsxRuntimeExports.jsx("div",{ref:C,className:"sandbox-container",style:{pointerEvents:R?"none":void 0}}),R&&S.jsxRuntimeExports.jsxs("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(51, 51, 51, 0.80)",color:"#ffffff",fontSize:16,fontWeight:700,gap:10,pointerEvents:"auto",zIndex:20},children:[S.jsxRuntimeExports.jsx(K.default,{"aria-hidden":!0,size:20,style:{animation:"sandbox-spin 1s linear infinite"}}),R]})]})};exports.default=U;
|
|
12
13
|
//# sourceMappingURL=SandboxApp.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SandboxApp.cjs.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\n\nexport interface SandboxAppProps {\n html: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n hasRootVhHeight?: boolean;\n}\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n hasRootVhHeight = false,\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [, setIsWaitingFirstDiv] = useState(true);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const hasRenderedContentRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n doc.head?.appendChild(styleEl);\n }\n styleEl.textContent = `\n @keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }\n .sandbox-wrapper { align-items: center; }\n .sandbox-container { width: 100%; }\n .sandbox-container svg,\n .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }\n @media (max-width: 640px) {\n .sandbox-wrapper { align-items: stretch; }\n .sandbox-wrapper[data-root-vh=\"true\"] .sandbox-container > :first-child { height: auto !important; }\n }\n `;\n }, []);\n\n useEffect(() => {\n if (resetToken !== prevResetTokenRef.current) {\n hasRenderedContentRef.current = false;\n prevResetTokenRef.current = resetToken;\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n\n const container = containerRef.current;\n if (!container) return;\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n const hasRenderedBefore = hasRenderedContentRef.current;\n setIsWaitingFirstDiv(!hasRenderedBefore);\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n container.innerHTML = \"\";\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = html;\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const hasFirstElement = !!wrapper.firstElementChild;\n setIsWaitingFirstDiv(!hasFirstElement && !hasRenderedBefore);\n if (hasFirstElement) {\n hasRenderedContentRef.current = true;\n }\n\n const contentNodes = Array.from(wrapper.childNodes);\n container.append(...contentNodes);\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n }, [html, resetToken]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n },\n []\n );\n\n const overlayMessage = (() => {\n if (isGeneratingScripts || hasScriptsRef.current)\n return scriptLoadingText || \"Building scripts cache...\";\n if (isGeneratingStyles || hasStylesRef.current)\n return styleLoadingText || \"Building styles...\";\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n\n return (\n <div\n ref={wrapperRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className=\"sandbox-wrapper\"\n style={{\n position: \"relative\",\n width: \"100%\",\n height: isBlackboard ? \"100vh\" : undefined,\n display: \"flex\",\n flexDirection: \"column\",\n // if use center, too long iframe wont see header\n justifyContent: \"space-around\",\n }}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n className=\"sandbox-container\"\n style={{\n pointerEvents: overlayMessage ? \"none\" : undefined,\n }}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"rgba(51, 51, 51, 0.80)\",\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: 700,\n gap: 10,\n pointerEvents: \"auto\",\n zIndex: 20,\n }}\n >\n <Loader2\n aria-hidden\n size={20}\n style={{ animation: \"sandbox-spin 1s linear infinite\" }}\n />\n {overlayMessage}\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["SandboxApp","html","styleLoadingText","scriptLoadingText","resetToken","mode","hasRootVhHeight","wrapperRef","useRef","containerRef","setIsWaitingFirstDiv","useState","isGeneratingStyles","setIsGeneratingStyles","isGeneratingScripts","setIsGeneratingScripts","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","hasRenderedContentRef","prevResetTokenRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","body","node","hasRenderedBefore","wrapper","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","hasFirstElement","contentNodes","scriptNode","scriptText","overlayMessage","isBlackboard","jsxs","jsx","Loader2"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SandboxApp.cjs.js","sources":["../../../src/components/ContentRender/SandboxApp.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { Loader2 } from \"lucide-react\";\nimport { BlackboardRuntime } from \"./blackboard/blackboard-runtime\";\n\nexport interface SandboxAppProps {\n html: string;\n styleLoadingText?: string;\n scriptLoadingText?: string;\n resetToken?: number;\n mode?: \"content\" | \"blackboard\";\n hasRootVhHeight?: boolean;\n}\n\nconst SandboxApp: React.FC<SandboxAppProps> = ({\n html,\n styleLoadingText,\n scriptLoadingText,\n resetToken = 0,\n mode = \"content\",\n hasRootVhHeight = false,\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [, setIsWaitingFirstDiv] = useState(true);\n const [isGeneratingStyles, setIsGeneratingStyles] = useState(false);\n const [isGeneratingScripts, setIsGeneratingScripts] = useState(false);\n const appendedStylesRef = useRef<HTMLStyleElement[]>([]);\n const appendedScriptsRef = useRef<HTMLScriptElement[]>([]);\n const styleStartRef = useRef(0);\n const scriptStartRef = useRef(0);\n const styleTimerRef = useRef<number | null>(null);\n const scriptTimerRef = useRef<number | null>(null);\n const hasStylesRef = useRef(false);\n const hasScriptsRef = useRef(false);\n const hasRenderedContentRef = useRef(false);\n const prevResetTokenRef = useRef(resetToken);\n const runtimeRef = useRef<BlackboardRuntime | null>(null);\n const MIN_LOADING_MS = 200;\n\n const clearTimer = (timerRef: React.MutableRefObject<number | null>) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const settleStateWithMinimumDelay = (\n setter: React.Dispatch<React.SetStateAction<boolean>>,\n timerRef: React.MutableRefObject<number | null>,\n startRef: React.MutableRefObject<number>,\n onDone?: () => void\n ) => {\n const elapsed = performance.now() - startRef.current;\n const delay = Math.max(0, MIN_LOADING_MS - elapsed);\n clearTimer(timerRef);\n timerRef.current = window.setTimeout(() => {\n setter(false);\n onDone?.();\n timerRef.current = null;\n }, delay);\n };\n\n useEffect(() => {\n const doc = containerRef.current?.ownerDocument;\n if (!doc) return;\n const styleId = \"sandbox-spinner-style\";\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n if (!styleEl) {\n styleEl = doc.createElement(\"style\");\n styleEl.id = styleId;\n doc.head?.appendChild(styleEl);\n }\n styleEl.textContent = `\n @keyframes sandbox-spin { from { transform: rotate(0deg);} to { transform: rotate(360deg);} }\n .sandbox-wrapper { align-items: center; }\n .sandbox-container { width: 100%; }\n .sandbox-container svg,\n .sandbox-container img { display: block; margin-left: auto; margin-right: auto; }\n @media (max-width: 640px) {\n .sandbox-wrapper { align-items: stretch; }\n .sandbox-wrapper[data-root-vh=\"true\"] .sandbox-container > :first-child { height: auto !important; }\n .sandbox-wrapper[data-root-vh=\"true\"] .sandbox-container > #ppt-container > :first-child { height: auto !important; }\n }\n `;\n }, []);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n if (resetToken !== prevResetTokenRef.current) {\n hasRenderedContentRef.current = false;\n prevResetTokenRef.current = resetToken;\n runtimeRef.current?.reset();\n }\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n hasStylesRef.current = false;\n hasScriptsRef.current = false;\n setIsGeneratingStyles(false);\n setIsGeneratingScripts(false);\n\n if (mode === \"blackboard\") {\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n if (!runtimeRef.current) {\n runtimeRef.current = new BlackboardRuntime(container);\n }\n\n runtimeRef.current.update(html);\n const hasRendered = runtimeRef.current.hasRenderedContent();\n hasRenderedContentRef.current = hasRendered;\n setIsWaitingFirstDiv(!hasRendered);\n return;\n }\n\n if (runtimeRef.current) {\n runtimeRef.current.reset();\n runtimeRef.current = null;\n }\n\n const doc = container.ownerDocument;\n const body = doc?.body;\n if (!body) return;\n\n appendedStylesRef.current.forEach((node) => node.remove());\n appendedStylesRef.current = [];\n appendedScriptsRef.current.forEach((node) => node.remove());\n appendedScriptsRef.current = [];\n\n const hasRenderedBefore = hasRenderedContentRef.current;\n setIsWaitingFirstDiv(!hasRenderedBefore);\n container.innerHTML = \"\";\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = html;\n\n const openScriptCount = (html.match(/<script[\\s>]/gi) || []).length;\n const closeScriptCount = (html.match(/<\\/script>/gi) || []).length;\n const shouldExecuteScripts =\n openScriptCount > 0 && openScriptCount === closeScriptCount;\n\n const resourceQueue: HTMLElement[] = [];\n\n Array.from(wrapper.querySelectorAll(\"style, script\")).forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n const cloned = doc.createElement(\"style\");\n cloned.textContent = node.textContent || \"\";\n Array.from(node.attributes).forEach((attr) => {\n cloned.setAttribute(attr.name, attr.value);\n });\n resourceQueue.push(cloned);\n } else {\n const replacement = doc.createElement(\"script\");\n Array.from(node.attributes).forEach((attr) => {\n replacement.setAttribute(attr.name, attr.value);\n });\n replacement.textContent = node.textContent || \"\";\n resourceQueue.push(replacement);\n }\n node.remove();\n });\n\n const hasStyles = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"style\"\n );\n const hasScripts = resourceQueue.some(\n (node) => node.tagName.toLowerCase() === \"script\"\n );\n if (hasStyles) {\n hasStylesRef.current = true;\n styleStartRef.current = performance.now();\n clearTimer(styleTimerRef);\n setIsGeneratingStyles(true);\n }\n if (hasScripts) {\n hasScriptsRef.current = true;\n scriptStartRef.current = performance.now();\n clearTimer(scriptTimerRef);\n setIsGeneratingScripts(true);\n }\n\n const hasFirstElement = !!wrapper.firstElementChild;\n setIsWaitingFirstDiv(!hasFirstElement && !hasRenderedBefore);\n if (hasFirstElement) {\n hasRenderedContentRef.current = true;\n }\n\n const contentNodes = Array.from(wrapper.childNodes);\n container.append(...contentNodes);\n\n resourceQueue.forEach((node) => {\n if (node.tagName.toLowerCase() === \"style\") {\n doc.head?.appendChild(node);\n appendedStylesRef.current.push(node as HTMLStyleElement);\n return;\n }\n\n if (shouldExecuteScripts) {\n const scriptNode = node as HTMLScriptElement;\n const scriptText = scriptNode.textContent || \"\";\n const shouldValidate = !scriptNode.src;\n\n if (shouldValidate) {\n try {\n // Validate script is syntactically complete before executing\n\n new Function(scriptText);\n } catch {\n scriptNode.remove();\n return;\n }\n }\n\n try {\n body.appendChild(scriptNode);\n appendedScriptsRef.current.push(scriptNode);\n } catch {\n scriptNode.remove();\n }\n } else {\n // Defer execution until all script tags are fully received\n node.remove();\n }\n });\n requestAnimationFrame(() => {\n if (hasStyles) {\n settleStateWithMinimumDelay(\n setIsGeneratingStyles,\n styleTimerRef,\n styleStartRef,\n () => {\n hasStylesRef.current = false;\n }\n );\n }\n if (hasScripts) {\n settleStateWithMinimumDelay(\n setIsGeneratingScripts,\n scriptTimerRef,\n scriptStartRef,\n () => {\n hasScriptsRef.current = false;\n }\n );\n }\n });\n }, [html, mode, resetToken]);\n\n useEffect(\n () => () => {\n clearTimer(styleTimerRef);\n clearTimer(scriptTimerRef);\n runtimeRef.current = null;\n },\n []\n );\n\n const overlayMessage = (() => {\n if (isGeneratingScripts || hasScriptsRef.current)\n return scriptLoadingText || \"Building scripts cache...\";\n if (isGeneratingStyles || hasStylesRef.current)\n return styleLoadingText || \"Building styles...\";\n return null;\n })();\n\n const isBlackboard = mode === \"blackboard\";\n\n return (\n <div\n ref={wrapperRef}\n data-root-vh={hasRootVhHeight ? \"true\" : \"false\"}\n className=\"sandbox-wrapper\"\n style={{\n position: \"relative\",\n width: \"100%\",\n height: isBlackboard ? \"100dvh\" : undefined,\n display: \"flex\",\n flexDirection: \"column\",\n // if use center, too long iframe wont see header\n justifyContent: \"space-around\",\n }}\n aria-busy={!!overlayMessage}\n >\n <div\n ref={containerRef}\n className=\"sandbox-container\"\n style={{\n pointerEvents: overlayMessage ? \"none\" : undefined,\n }}\n />\n {overlayMessage && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"rgba(51, 51, 51, 0.80)\",\n color: \"#ffffff\",\n fontSize: 16,\n fontWeight: 700,\n gap: 10,\n pointerEvents: \"auto\",\n zIndex: 20,\n }}\n >\n <Loader2\n aria-hidden\n size={20}\n style={{ animation: \"sandbox-spin 1s linear infinite\" }}\n />\n {overlayMessage}\n </div>\n )}\n </div>\n );\n};\n\nexport default SandboxApp;\n"],"names":["SandboxApp","html","styleLoadingText","scriptLoadingText","resetToken","mode","hasRootVhHeight","wrapperRef","useRef","containerRef","setIsWaitingFirstDiv","useState","isGeneratingStyles","setIsGeneratingStyles","isGeneratingScripts","setIsGeneratingScripts","appendedStylesRef","appendedScriptsRef","styleStartRef","scriptStartRef","styleTimerRef","scriptTimerRef","hasStylesRef","hasScriptsRef","hasRenderedContentRef","prevResetTokenRef","runtimeRef","MIN_LOADING_MS","clearTimer","timerRef","settleStateWithMinimumDelay","setter","startRef","onDone","elapsed","delay","useEffect","doc","styleId","styleEl","container","node","BlackboardRuntime","hasRendered","body","hasRenderedBefore","wrapper","openScriptCount","closeScriptCount","shouldExecuteScripts","resourceQueue","cloned","attr","replacement","hasStyles","hasScripts","hasFirstElement","contentNodes","scriptNode","scriptText","overlayMessage","isBlackboard","jsxs","jsx","Loader2"],"mappings":"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"}
|