@jbpark/live-editor 4.6.1 → 5.0.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/README.ko.md +2 -2
- package/README.md +2 -2
- package/dist/{boundary-BLB80tyw.js → boundary-6_nTsWxP.js} +2 -2
- package/dist/{boundary-BLB80tyw.js.map → boundary-6_nTsWxP.js.map} +1 -1
- package/dist/{compile-Dxas-D05.js → compile-DwOyWrmI.js} +8 -7
- package/dist/compile-DwOyWrmI.js.map +1 -0
- package/dist/constants-D-XKuEY2.js +58 -0
- package/dist/constants-D-XKuEY2.js.map +1 -0
- package/dist/{context-B8MzP7_p.js → context-DDR1xVKo.js} +3 -3
- package/dist/{context-B8MzP7_p.js.map → context-DDR1xVKo.js.map} +1 -1
- package/dist/{core-Bgfek364.js → core-CKazr4tT.js} +2 -2
- package/dist/core-CKazr4tT.js.map +1 -0
- package/dist/{detect-typescript-Dr_oLniM.js → detect-typescript-CoAO-QUJ.js} +2 -2
- package/dist/{detect-typescript-Dr_oLniM.js.map → detect-typescript-CoAO-QUJ.js.map} +1 -1
- package/dist/dnd/index.d.ts +2 -2
- package/dist/dnd/index.js +2 -2
- package/dist/{dnd-V8NAxd_R.js → dnd-BlC1gqUy.js} +2558 -867
- package/dist/dnd-BlC1gqUy.js.map +1 -0
- package/dist/document-BQhb7YR8.d.ts +17 -0
- package/dist/{document-CHO215iP.js → document-DcwIEHRV.js} +189 -104
- package/dist/document-DcwIEHRV.js.map +1 -0
- package/dist/editor/index.js +2 -2
- package/dist/{editor-CMElfHer.js → editor-Bty5XzpV.js} +2 -2
- package/dist/{editor-CMElfHer.js.map → editor-Bty5XzpV.js.map} +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/error/index.js +2 -2
- package/dist/{error-CN_GCnXB.js → error-DyYx2NQ2.js} +17 -31
- package/dist/error-DyYx2NQ2.js.map +1 -0
- package/dist/{index-CiWB0zFb.d.ts → index-0VB5C3Jk.d.ts} +28 -50
- package/dist/{index-DpDU1IAw.d.ts → index-92L7F440.d.ts} +2 -2
- package/dist/index-C8h8TcIl.d.ts +15 -0
- package/dist/{index-DQkL37eL.d.ts → index-Cl79M7ZJ.d.ts} +6 -4
- package/dist/{index-CRwEhJ7w.d.ts → index-kKUjo9lr.d.ts} +2 -2
- package/dist/{index-DrWtSKXu.d.ts → index-tAiuHZsC.d.ts} +2 -2
- package/dist/index.d.ts +9 -9
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/{messages-CSrMI4Rm.js → messages-Bt5WXKTE.js} +5 -2
- package/dist/messages-Bt5WXKTE.js.map +1 -0
- package/dist/{messages-IBPs4TkZ.d.ts → messages-Yb3b7YJt.d.ts} +5 -2
- package/dist/preview/index.d.ts +1 -1
- package/dist/preview/index.js +2 -2
- package/dist/{preview-CtyG5UbH.js → preview-DC0pyOdu.js} +4 -4
- package/dist/preview-DC0pyOdu.js.map +1 -0
- package/dist/provider/index.d.ts +2 -2
- package/dist/provider/index.js +2 -2
- package/dist/{sections-jYuqS4KB.js → sections-4uirsXRU.js} +4 -7
- package/dist/sections-4uirsXRU.js.map +1 -0
- package/dist/style.css +776 -346
- package/dist/{validate-DB59Z_Nx.d.ts → types-Czps1Txy.d.ts} +12 -28
- package/dist/update-2PJbwoS8.d.ts +68 -0
- package/dist/{items-BXXtMUNI.js → update-DNInQSM7.js} +143 -392
- package/dist/update-DNInQSM7.js.map +1 -0
- package/dist/{use-dynamic-tailwind-BP1toJkW.js → use-dynamic-tailwind-CSYKXDmX.js} +301 -273
- package/dist/use-dynamic-tailwind-CSYKXDmX.js.map +1 -0
- package/dist/utils/ast/index.d.ts +47 -4
- package/dist/utils/ast/index.js +4 -64
- package/dist/utils/ast/index.js.map +1 -1
- package/dist/utils/index.d.ts +13 -32
- package/dist/utils/index.js +4 -26
- package/dist/validate-CZz30Pnb.js +122 -0
- package/dist/validate-CZz30Pnb.js.map +1 -0
- package/dist/validate-CiA1LF6S.d.ts +33 -0
- package/package.json +9 -9
- package/dist/compile-Dxas-D05.js.map +0 -1
- package/dist/constants-DU17Tdwo.js +0 -1459
- package/dist/constants-DU17Tdwo.js.map +0 -1
- package/dist/core-Bgfek364.js.map +0 -1
- package/dist/dnd-V8NAxd_R.js.map +0 -1
- package/dist/document-CHO215iP.js.map +0 -1
- package/dist/document-DqRSCtsx.d.ts +0 -1614
- package/dist/error-CN_GCnXB.js.map +0 -1
- package/dist/index-C_PfR4X9.d.ts +0 -734
- package/dist/items-BXXtMUNI.js.map +0 -1
- package/dist/messages-CSrMI4Rm.js.map +0 -1
- package/dist/preview-CtyG5UbH.js.map +0 -1
- package/dist/sections-jYuqS4KB.js.map +0 -1
- package/dist/use-dynamic-tailwind-BP1toJkW.js.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/validate-iLo8IONY.js +0 -64
- package/dist/validate-iLo8IONY.js.map +0 -1
|
@@ -1,26 +1,12 @@
|
|
|
1
|
-
import { i as useLiveMessages } from "./messages-
|
|
2
|
-
import {
|
|
1
|
+
import { i as useLiveMessages } from "./messages-Bt5WXKTE.js";
|
|
2
|
+
import { i as withScriptBlobs, n as compile } from "./compile-DwOyWrmI.js";
|
|
3
3
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useDebouncedCallback, useEventListener, useMutationObserver, useResizeObserver, useStableValue } from "@jbpark/use-hooks";
|
|
5
6
|
import * as ui from "@jbpark/ui-kit";
|
|
6
|
-
import { useEventListener, useMutationObserver, useResizeObserver } from "@jbpark/use-hooks";
|
|
7
7
|
import { createPortal } from "react-dom";
|
|
8
8
|
import * as utils from "@jbpark/ui-kit/utils";
|
|
9
|
-
//#region src/components/
|
|
10
|
-
const sameModules = (a, b) => {
|
|
11
|
-
if (a === b) return true;
|
|
12
|
-
if (!a || !b) return false;
|
|
13
|
-
const keys = Object.keys(a);
|
|
14
|
-
return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]));
|
|
15
|
-
};
|
|
16
|
-
const useStableModules = (modules) => {
|
|
17
|
-
const [stable, setStable] = useState(modules);
|
|
18
|
-
if (sameModules(stable, modules)) return stable;
|
|
19
|
-
setStable(modules);
|
|
20
|
-
return modules;
|
|
21
|
-
};
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region src/components/frame/measure.ts
|
|
9
|
+
//#region src/components/frame/auto-height/measure.ts
|
|
24
10
|
const verticalInsets = (style) => [
|
|
25
11
|
style.marginTop,
|
|
26
12
|
style.marginBottom,
|
|
@@ -40,85 +26,13 @@ const positionedElementBottom = (top, bottom, probeHeight) => {
|
|
|
40
26
|
return Math.min(bottom, probeHeight);
|
|
41
27
|
};
|
|
42
28
|
//#endregion
|
|
43
|
-
//#region src/components/frame/
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
if (attribute.name !== SYNCED_STYLE_ATTR && !source.hasAttribute(attribute.name)) clone.removeAttribute(attribute.name);
|
|
51
|
-
});
|
|
52
|
-
Array.from(source.attributes).forEach((attribute) => {
|
|
53
|
-
clone.setAttribute(attribute.name, attribute.value);
|
|
54
|
-
});
|
|
55
|
-
if (source.tagName === "LINK" && clone.tagName === "LINK") clone.disabled = source.disabled;
|
|
56
|
-
clone.textContent = source.tagName === "STYLE" ? transformStyle(source.textContent || "") : source.textContent;
|
|
57
|
-
};
|
|
58
|
-
const createClone = (source, target, transformStyle) => {
|
|
59
|
-
const clone = (isDocument(target) ? target : target.ownerDocument).createElement(source.tagName.toLowerCase());
|
|
60
|
-
clone.setAttribute(SYNCED_STYLE_ATTR, "");
|
|
61
|
-
copyAttributes(source, clone, transformStyle);
|
|
62
|
-
return clone;
|
|
63
|
-
};
|
|
64
|
-
const targetContainer = (target) => isDocument(target) ? target.head : target;
|
|
65
|
-
const isSyncedStyle = (node) => {
|
|
66
|
-
const element = node;
|
|
67
|
-
return (element.tagName === "LINK" || element.tagName === "STYLE") && element.hasAttribute(SYNCED_STYLE_ATTR);
|
|
68
|
-
};
|
|
69
|
-
const removeClone = (clone) => {
|
|
70
|
-
clone.remove();
|
|
71
|
-
};
|
|
72
|
-
const reconcileStyles = (sourceDocument, target, manager, enabled, transformStyle = (content) => content, anchor = null) => {
|
|
73
|
-
if (!enabled) {
|
|
74
|
-
manager.clones.forEach(removeClone);
|
|
75
|
-
manager.clones.clear();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const sources = sourceStyles(sourceDocument);
|
|
79
|
-
const sourceSet = new Set(sources);
|
|
80
|
-
const container = targetContainer(target);
|
|
81
|
-
manager.clones.forEach((clone, source) => {
|
|
82
|
-
if (!sourceSet.has(source)) {
|
|
83
|
-
removeClone(clone);
|
|
84
|
-
manager.clones.delete(source);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
let previous = null;
|
|
88
|
-
sources.forEach((source) => {
|
|
89
|
-
let clone = manager.clones.get(source);
|
|
90
|
-
if (!clone) {
|
|
91
|
-
clone = createClone(source, target, transformStyle);
|
|
92
|
-
manager.clones.set(source, clone);
|
|
93
|
-
} else copyAttributes(source, clone, transformStyle);
|
|
94
|
-
const nextSibling = previous ? previous.nextSibling : Array.from(container.childNodes).find(isSyncedStyle) ?? (anchor?.parentNode === container ? anchor : null);
|
|
95
|
-
if (clone !== nextSibling) container.insertBefore(clone, nextSibling);
|
|
96
|
-
previous = clone;
|
|
97
|
-
});
|
|
98
|
-
};
|
|
99
|
-
const createRootAttributeSync = () => ({
|
|
100
|
-
attributes: /* @__PURE__ */ new Set(),
|
|
101
|
-
classes: /* @__PURE__ */ new Set()
|
|
102
|
-
});
|
|
103
|
-
const isMirroredAttribute = (name) => name.startsWith("data-");
|
|
104
|
-
const reconcileRootAttributes = (source, target, sync, enabled) => {
|
|
105
|
-
const attributes = enabled ? Array.from(source.attributes).filter(({ name }) => isMirroredAttribute(name)) : [];
|
|
106
|
-
const classes = enabled ? Array.from(source.classList) : [];
|
|
107
|
-
const attributeNames = new Set(attributes.map(({ name }) => name));
|
|
108
|
-
const classNames = new Set(classes);
|
|
109
|
-
sync.attributes.forEach((name) => {
|
|
110
|
-
if (!attributeNames.has(name)) target.removeAttribute(name);
|
|
111
|
-
});
|
|
112
|
-
attributes.forEach(({ name, value }) => {
|
|
113
|
-
if (target.getAttribute(name) !== value) target.setAttribute(name, value);
|
|
114
|
-
});
|
|
115
|
-
sync.classes.forEach((name) => {
|
|
116
|
-
if (!classNames.has(name)) target.classList.remove(name);
|
|
117
|
-
});
|
|
118
|
-
classes.forEach((name) => target.classList.add(name));
|
|
119
|
-
if (!target.classList.length) target.removeAttribute("class");
|
|
120
|
-
sync.attributes = attributeNames;
|
|
121
|
-
sync.classes = classNames;
|
|
29
|
+
//#region src/components/frame/auto-height/animations.ts
|
|
30
|
+
const isCssAnimation = (win, animation) => typeof win.CSSAnimation === "function" && animation instanceof win.CSSAnimation;
|
|
31
|
+
const isCssTransition = (win, animation) => typeof win.CSSTransition === "function" && animation instanceof win.CSSTransition;
|
|
32
|
+
const hasActiveAnimation = (el) => typeof el.getAnimations === "function" && el.getAnimations().some((animation) => isAnimationActive(animation.playState));
|
|
33
|
+
const neverFinishes = (animation) => {
|
|
34
|
+
const timing = animation.effect?.getComputedTiming();
|
|
35
|
+
return timing?.iterations === Infinity || timing?.duration === Infinity;
|
|
122
36
|
};
|
|
123
37
|
//#endregion
|
|
124
38
|
//#region src/components/frame/viewport-units.ts
|
|
@@ -148,16 +62,8 @@ const rewriteInlineViewportUnits = (root) => {
|
|
|
148
62
|
});
|
|
149
63
|
};
|
|
150
64
|
//#endregion
|
|
151
|
-
//#region src/components/frame/
|
|
65
|
+
//#region src/components/frame/auto-height/auto-height.ts
|
|
152
66
|
const CONTAINER_STYLE_ID = "autoheight-container";
|
|
153
|
-
const EMPTY_STRING_ARRAY = [];
|
|
154
|
-
const isCssAnimation = (win, animation) => typeof win.CSSAnimation === "function" && animation instanceof win.CSSAnimation;
|
|
155
|
-
const isCssTransition = (win, animation) => typeof win.CSSTransition === "function" && animation instanceof win.CSSTransition;
|
|
156
|
-
const hasActiveAnimation = (el) => typeof el.getAnimations === "function" && el.getAnimations().some((animation) => isAnimationActive(animation.playState));
|
|
157
|
-
const neverFinishes = (animation) => {
|
|
158
|
-
const timing = animation.effect?.getComputedTiming();
|
|
159
|
-
return timing?.iterations === Infinity || timing?.duration === Infinity;
|
|
160
|
-
};
|
|
161
67
|
const MEASUREMENT_OVERRIDE_STYLE_ID = "autoheight-measurement-overrides";
|
|
162
68
|
const SCROLLBAR_OVERRIDE_RULES = ["html, body { scrollbar-width: none !important; }", "html::-webkit-scrollbar, body::-webkit-scrollbar { display: none !important; }"];
|
|
163
69
|
const FREEZE_TRANSITIONS_RULE = "*, *::before, *::after { transition: none !important; }";
|
|
@@ -175,130 +81,54 @@ const withMeasurementOverrides = (doc, freezeTransitions, measure) => {
|
|
|
175
81
|
measure();
|
|
176
82
|
styleEl.media = "not all";
|
|
177
83
|
};
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
84
|
+
const HIDE_SCROLLBAR_STYLE_ID = "autoheight-hide-scrollbar";
|
|
85
|
+
const ensureContainerStyle = (doc, probeHeight) => {
|
|
86
|
+
let styleEl = doc.getElementById(CONTAINER_STYLE_ID);
|
|
87
|
+
if (!styleEl) {
|
|
88
|
+
styleEl = doc.createElement("style");
|
|
89
|
+
styleEl.id = CONTAINER_STYLE_ID;
|
|
90
|
+
doc.head?.appendChild(styleEl);
|
|
91
|
+
}
|
|
92
|
+
const text = `html { container-type: size !important; height: ${probeHeight}px !important; }`;
|
|
93
|
+
if (styleEl.textContent !== text) styleEl.textContent = text;
|
|
94
|
+
};
|
|
95
|
+
const getProbeHeight = (iframe, win) => {
|
|
96
|
+
const scrollParent = iframe.closest("[data-frame-container]");
|
|
97
|
+
if (!scrollParent) return 812;
|
|
98
|
+
const scrollParentStyle = win.getComputedStyle(scrollParent);
|
|
99
|
+
let wrapperInsets = (parseFloat(scrollParentStyle.paddingTop) || 0) + (parseFloat(scrollParentStyle.paddingBottom) || 0);
|
|
100
|
+
let node = iframe;
|
|
101
|
+
while (node && node !== scrollParent) {
|
|
102
|
+
wrapperInsets += verticalInsets(win.getComputedStyle(node));
|
|
103
|
+
node = node.parentElement;
|
|
104
|
+
}
|
|
105
|
+
return computeProbeHeight(scrollParent.clientHeight, wrapperInsets);
|
|
106
|
+
};
|
|
107
|
+
const measureContentHeight = (mountNode, doc, win, probeHeight, freezeTransitions) => {
|
|
108
|
+
let contentHeight = 0;
|
|
109
|
+
withMeasurementOverrides(doc, freezeTransitions, () => {
|
|
110
|
+
ensureContainerStyle(doc, probeHeight);
|
|
111
|
+
rewriteInlineViewportUnits(mountNode);
|
|
112
|
+
contentHeight = mountNode.scrollHeight;
|
|
113
|
+
mountNode.querySelectorAll("*").forEach((el) => {
|
|
114
|
+
const style = win.getComputedStyle(el);
|
|
115
|
+
const isAnimating = style.opacity === "0" && hasActiveAnimation(el);
|
|
116
|
+
if (isVisuallyHidden(style, isAnimating)) return;
|
|
117
|
+
if ((style.position === "fixed" || style.position === "absolute") && el.offsetHeight > 0) {
|
|
118
|
+
const rect = el.getBoundingClientRect();
|
|
119
|
+
const bottom = positionedElementBottom(rect.top, rect.bottom, probeHeight);
|
|
120
|
+
if (bottom !== null) contentHeight = Math.max(contentHeight, bottom);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
return contentHeight;
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/components/frame/auto-height/use-auto-height.ts
|
|
128
|
+
const useAutoHeight = (iframeRef, mountNode, shouldAutoHeight) => {
|
|
185
129
|
const trackedAnimationsRef = useRef(/* @__PURE__ */ new WeakSet());
|
|
186
130
|
const updateHeightRef = useRef(null);
|
|
187
131
|
const lastProbeHeightRef = useRef(void 0);
|
|
188
|
-
const shouldAutoHeight = autoHeight && style.height == null;
|
|
189
|
-
const styleManagerRef = useRef(createStyleSyncManager());
|
|
190
|
-
const rootAttributeSyncRef = useRef(createRootAttributeSync());
|
|
191
|
-
const applyStyle = useCallback(() => {
|
|
192
|
-
const doc = iframeRef.current?.contentDocument;
|
|
193
|
-
if (!doc) return;
|
|
194
|
-
reconcileStyles(document, doc, styleManagerRef.current, syncStyle, convertViewportUnits, doc.getElementById(CONTAINER_STYLE_ID));
|
|
195
|
-
reconcileRootAttributes(document.documentElement, doc.documentElement, rootAttributeSyncRef.current, syncStyle);
|
|
196
|
-
}, [syncStyle]);
|
|
197
|
-
const applyStyleTimeoutRef = useRef(void 0);
|
|
198
|
-
const debouncedApplyStyle = useCallback(() => {
|
|
199
|
-
clearTimeout(applyStyleTimeoutRef.current);
|
|
200
|
-
applyStyleTimeoutRef.current = window.setTimeout(applyStyle, 50);
|
|
201
|
-
}, [applyStyle]);
|
|
202
|
-
useEffect(() => {
|
|
203
|
-
return () => clearTimeout(applyStyleTimeoutRef.current);
|
|
204
|
-
}, []);
|
|
205
|
-
useMutationObserver(document.head, debouncedApplyStyle, {
|
|
206
|
-
enabled: syncStyle,
|
|
207
|
-
childList: true,
|
|
208
|
-
subtree: true,
|
|
209
|
-
attributes: true
|
|
210
|
-
});
|
|
211
|
-
useMutationObserver(document.documentElement, debouncedApplyStyle, {
|
|
212
|
-
enabled: syncStyle,
|
|
213
|
-
attributes: true
|
|
214
|
-
});
|
|
215
|
-
useEffect(() => {
|
|
216
|
-
const $iframe = iframeRef.current;
|
|
217
|
-
if (!$iframe) return;
|
|
218
|
-
const onLoad = () => {
|
|
219
|
-
const doc = $iframe.contentDocument;
|
|
220
|
-
if (!doc) return;
|
|
221
|
-
if (loadedScriptsDocRef.current !== doc) {
|
|
222
|
-
loadedScriptsDocRef.current = doc;
|
|
223
|
-
loadedScriptsRef.current = /* @__PURE__ */ new Set();
|
|
224
|
-
}
|
|
225
|
-
doc.body.style.overflowX = "hidden";
|
|
226
|
-
doc.body.style.margin = "0";
|
|
227
|
-
let node = doc.getElementById("iframe-root");
|
|
228
|
-
if (!node) {
|
|
229
|
-
node = doc.createElement("div");
|
|
230
|
-
node.id = "iframe-root";
|
|
231
|
-
doc.body.appendChild(node);
|
|
232
|
-
}
|
|
233
|
-
setMountNode(node);
|
|
234
|
-
applyStyle();
|
|
235
|
-
const pendingScripts = scripts.filter((src) => !loadedScriptsRef.current.has(src));
|
|
236
|
-
if (pendingScripts.length) {
|
|
237
|
-
pendingScripts.forEach((src) => loadedScriptsRef.current.add(src));
|
|
238
|
-
withScriptBlobs(pendingScripts, (blobUrls) => {
|
|
239
|
-
if (!doc.head) return;
|
|
240
|
-
const fragment = doc.createDocumentFragment();
|
|
241
|
-
blobUrls.forEach((blobUrl) => {
|
|
242
|
-
const script = doc.createElement("script");
|
|
243
|
-
script.src = blobUrl;
|
|
244
|
-
fragment.appendChild(script);
|
|
245
|
-
});
|
|
246
|
-
doc.head.appendChild(fragment);
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
onLoaded?.();
|
|
250
|
-
};
|
|
251
|
-
$iframe.addEventListener("load", onLoad);
|
|
252
|
-
if ($iframe.contentDocument?.readyState === "complete") onLoad();
|
|
253
|
-
return () => {
|
|
254
|
-
$iframe.removeEventListener("load", onLoad);
|
|
255
|
-
};
|
|
256
|
-
}, [
|
|
257
|
-
scripts,
|
|
258
|
-
onLoaded,
|
|
259
|
-
applyStyle
|
|
260
|
-
]);
|
|
261
|
-
useEffect(() => {
|
|
262
|
-
const doc = iframeRef.current?.contentDocument;
|
|
263
|
-
if (!doc?.head) return;
|
|
264
|
-
styles.forEach((css, index) => {
|
|
265
|
-
const styleId = `injected-style-${index}`;
|
|
266
|
-
let styleEl = doc.getElementById(styleId);
|
|
267
|
-
if (!styleEl) {
|
|
268
|
-
styleEl = doc.createElement("style");
|
|
269
|
-
styleEl.id = styleId;
|
|
270
|
-
doc.head.appendChild(styleEl);
|
|
271
|
-
}
|
|
272
|
-
const convertedCss = convertViewportUnits(css);
|
|
273
|
-
if (styleEl.textContent !== convertedCss) styleEl.textContent = convertedCss;
|
|
274
|
-
});
|
|
275
|
-
for (let index = styles.length; index < prevStyleCountRef.current; index++) doc.getElementById(`injected-style-${index}`)?.remove();
|
|
276
|
-
prevStyleCountRef.current = styles.length;
|
|
277
|
-
stylesheets.forEach((href, index) => {
|
|
278
|
-
const linkId = `injected-stylesheet-${index}`;
|
|
279
|
-
let linkEl = doc.getElementById(linkId);
|
|
280
|
-
if (!linkEl) {
|
|
281
|
-
linkEl = doc.createElement("link");
|
|
282
|
-
linkEl.id = linkId;
|
|
283
|
-
linkEl.rel = "stylesheet";
|
|
284
|
-
doc.head.appendChild(linkEl);
|
|
285
|
-
}
|
|
286
|
-
if (linkEl.href !== href) linkEl.href = href;
|
|
287
|
-
});
|
|
288
|
-
for (let index = stylesheets.length; index < prevStylesheetCountRef.current; index++) doc.getElementById(`injected-stylesheet-${index}`)?.remove();
|
|
289
|
-
prevStylesheetCountRef.current = stylesheets.length;
|
|
290
|
-
}, [styles, stylesheets]);
|
|
291
|
-
const HIDE_SCROLLBAR_STYLE_ID = "autoheight-hide-scrollbar";
|
|
292
|
-
const ensureContainerStyle = (doc, probeHeight) => {
|
|
293
|
-
let styleEl = doc.getElementById(CONTAINER_STYLE_ID);
|
|
294
|
-
if (!styleEl) {
|
|
295
|
-
styleEl = doc.createElement("style");
|
|
296
|
-
styleEl.id = CONTAINER_STYLE_ID;
|
|
297
|
-
doc.head?.appendChild(styleEl);
|
|
298
|
-
}
|
|
299
|
-
const text = `html { container-type: size !important; height: ${probeHeight}px !important; }`;
|
|
300
|
-
if (styleEl.textContent !== text) styleEl.textContent = text;
|
|
301
|
-
};
|
|
302
132
|
const trackScriptAnimations = useCallback((doc, win) => {
|
|
303
133
|
if (typeof doc.getAnimations !== "function") return;
|
|
304
134
|
doc.getAnimations().forEach((animation) => {
|
|
@@ -313,44 +143,17 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
313
143
|
const doc = iframe.contentDocument;
|
|
314
144
|
const win = doc?.defaultView;
|
|
315
145
|
if (!doc || !win) return;
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
if (!scrollParent) probeHeight = 812;
|
|
319
|
-
else {
|
|
320
|
-
const scrollParentStyle = win.getComputedStyle(scrollParent);
|
|
321
|
-
let wrapperInsets = (parseFloat(scrollParentStyle.paddingTop) || 0) + (parseFloat(scrollParentStyle.paddingBottom) || 0);
|
|
322
|
-
let node = iframe;
|
|
323
|
-
while (node && node !== scrollParent) {
|
|
324
|
-
wrapperInsets += verticalInsets(win.getComputedStyle(node));
|
|
325
|
-
node = node.parentElement;
|
|
326
|
-
}
|
|
327
|
-
const computed = computeProbeHeight(scrollParent.clientHeight, wrapperInsets);
|
|
328
|
-
if (computed === null) return;
|
|
329
|
-
probeHeight = computed;
|
|
330
|
-
}
|
|
331
|
-
let contentHeight = 0;
|
|
146
|
+
const probeHeight = getProbeHeight(iframe, win);
|
|
147
|
+
if (probeHeight === null) return;
|
|
332
148
|
const freezeTransitions = probeHeight !== lastProbeHeightRef.current;
|
|
333
149
|
lastProbeHeightRef.current = probeHeight;
|
|
334
150
|
const previousHeight = iframe.style.height;
|
|
335
151
|
iframe.style.height = `${probeHeight}px`;
|
|
336
|
-
|
|
337
|
-
ensureContainerStyle(doc, probeHeight);
|
|
338
|
-
rewriteInlineViewportUnits(mountNode);
|
|
339
|
-
contentHeight = mountNode.scrollHeight;
|
|
340
|
-
mountNode.querySelectorAll("*").forEach((el) => {
|
|
341
|
-
const style = win.getComputedStyle(el);
|
|
342
|
-
const isAnimating = style.opacity === "0" && hasActiveAnimation(el);
|
|
343
|
-
if (isVisuallyHidden(style, isAnimating)) return;
|
|
344
|
-
if ((style.position === "fixed" || style.position === "absolute") && el.offsetHeight > 0) {
|
|
345
|
-
const rect = el.getBoundingClientRect();
|
|
346
|
-
const bottom = positionedElementBottom(rect.top, rect.bottom, probeHeight);
|
|
347
|
-
if (bottom !== null) contentHeight = Math.max(contentHeight, bottom);
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
});
|
|
152
|
+
const contentHeight = measureContentHeight(mountNode, doc, win, probeHeight, freezeTransitions);
|
|
351
153
|
iframe.style.height = contentHeight > 0 ? `${Math.ceil(contentHeight)}px` : previousHeight;
|
|
352
154
|
trackScriptAnimations(doc, win);
|
|
353
155
|
}, [
|
|
156
|
+
iframeRef,
|
|
354
157
|
shouldAutoHeight,
|
|
355
158
|
mountNode,
|
|
356
159
|
trackScriptAnimations
|
|
@@ -361,13 +164,17 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
361
164
|
useEffect(() => {
|
|
362
165
|
if (shouldAutoHeight) return;
|
|
363
166
|
iframeRef.current?.contentDocument?.getElementById(CONTAINER_STYLE_ID)?.remove();
|
|
364
|
-
}, [shouldAutoHeight]);
|
|
167
|
+
}, [iframeRef, shouldAutoHeight]);
|
|
365
168
|
useEffect(() => {
|
|
366
169
|
const body = iframeRef.current?.contentDocument?.body;
|
|
367
170
|
if (!body || !mountNode) return;
|
|
368
171
|
if (shouldAutoHeight) body.style.removeProperty("overflow-y");
|
|
369
172
|
else body.style.setProperty("overflow-y", "auto");
|
|
370
|
-
}, [
|
|
173
|
+
}, [
|
|
174
|
+
iframeRef,
|
|
175
|
+
shouldAutoHeight,
|
|
176
|
+
mountNode
|
|
177
|
+
]);
|
|
371
178
|
useEffect(() => {
|
|
372
179
|
const doc = iframeRef.current?.contentDocument;
|
|
373
180
|
if (!doc?.head) return;
|
|
@@ -379,9 +186,13 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
379
186
|
if (existing) return;
|
|
380
187
|
const styleEl = doc.createElement("style");
|
|
381
188
|
styleEl.id = HIDE_SCROLLBAR_STYLE_ID;
|
|
382
|
-
styleEl.textContent =
|
|
189
|
+
styleEl.textContent = SCROLLBAR_OVERRIDE_RULES.join("\n");
|
|
383
190
|
doc.head.appendChild(styleEl);
|
|
384
|
-
}, [
|
|
191
|
+
}, [
|
|
192
|
+
iframeRef,
|
|
193
|
+
shouldAutoHeight,
|
|
194
|
+
mountNode
|
|
195
|
+
]);
|
|
385
196
|
useEffect(() => {
|
|
386
197
|
updateHeight();
|
|
387
198
|
}, [updateHeight]);
|
|
@@ -423,6 +234,227 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
423
234
|
target: mountNodeRef,
|
|
424
235
|
enabled: settleListenerEnabled
|
|
425
236
|
});
|
|
237
|
+
};
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/components/frame/iframe/inject-assets.ts
|
|
240
|
+
const syncInjectedElements = (doc, idPrefix, values, previousCount, create, update) => {
|
|
241
|
+
values.forEach((value, index) => {
|
|
242
|
+
const id = `${idPrefix}${index}`;
|
|
243
|
+
let el = doc.getElementById(id);
|
|
244
|
+
if (!el) {
|
|
245
|
+
el = create();
|
|
246
|
+
el.id = id;
|
|
247
|
+
doc.head.appendChild(el);
|
|
248
|
+
}
|
|
249
|
+
update(el, value);
|
|
250
|
+
});
|
|
251
|
+
for (let index = values.length; index < previousCount; index++) doc.getElementById(`${idPrefix}${index}`)?.remove();
|
|
252
|
+
};
|
|
253
|
+
const syncInjectedAssets = (doc, styles, stylesheets, previous) => {
|
|
254
|
+
syncInjectedElements(doc, "injected-style-", styles, previous.styles, () => doc.createElement("style"), (styleEl, css) => {
|
|
255
|
+
const convertedCss = convertViewportUnits(css);
|
|
256
|
+
if (styleEl.textContent !== convertedCss) styleEl.textContent = convertedCss;
|
|
257
|
+
});
|
|
258
|
+
syncInjectedElements(doc, "injected-stylesheet-", stylesheets, previous.stylesheets, () => {
|
|
259
|
+
const linkEl = doc.createElement("link");
|
|
260
|
+
linkEl.rel = "stylesheet";
|
|
261
|
+
return linkEl;
|
|
262
|
+
}, (linkEl, href) => {
|
|
263
|
+
if (linkEl.href !== href) linkEl.href = href;
|
|
264
|
+
});
|
|
265
|
+
return {
|
|
266
|
+
styles: styles.length,
|
|
267
|
+
stylesheets: stylesheets.length
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
//#endregion
|
|
271
|
+
//#region src/components/frame/style-sync.ts
|
|
272
|
+
const SYNCED_STYLE_ATTR = "data-live-editor-synced-style";
|
|
273
|
+
const createStyleSyncManager = () => ({ clones: /* @__PURE__ */ new Map() });
|
|
274
|
+
const isDocument = (target) => target.nodeType === Node.DOCUMENT_NODE;
|
|
275
|
+
const sourceStyles = (document) => Array.from(document.head.querySelectorAll("link[rel=\"stylesheet\"], style"));
|
|
276
|
+
const copyAttributes = (source, clone, transformStyle) => {
|
|
277
|
+
Array.from(clone.attributes).forEach((attribute) => {
|
|
278
|
+
if (attribute.name !== SYNCED_STYLE_ATTR && !source.hasAttribute(attribute.name)) clone.removeAttribute(attribute.name);
|
|
279
|
+
});
|
|
280
|
+
Array.from(source.attributes).forEach((attribute) => {
|
|
281
|
+
clone.setAttribute(attribute.name, attribute.value);
|
|
282
|
+
});
|
|
283
|
+
if (source.tagName === "LINK" && clone.tagName === "LINK") clone.disabled = source.disabled;
|
|
284
|
+
clone.textContent = source.tagName === "STYLE" ? transformStyle(source.textContent || "") : source.textContent;
|
|
285
|
+
};
|
|
286
|
+
const createClone = (source, target, transformStyle) => {
|
|
287
|
+
const clone = (isDocument(target) ? target : target.ownerDocument).createElement(source.tagName.toLowerCase());
|
|
288
|
+
clone.setAttribute(SYNCED_STYLE_ATTR, "");
|
|
289
|
+
copyAttributes(source, clone, transformStyle);
|
|
290
|
+
return clone;
|
|
291
|
+
};
|
|
292
|
+
const targetContainer = (target) => isDocument(target) ? target.head : target;
|
|
293
|
+
const isSyncedStyle = (node) => {
|
|
294
|
+
const element = node;
|
|
295
|
+
return (element.tagName === "LINK" || element.tagName === "STYLE") && element.hasAttribute(SYNCED_STYLE_ATTR);
|
|
296
|
+
};
|
|
297
|
+
const removeClone = (clone) => {
|
|
298
|
+
clone.remove();
|
|
299
|
+
};
|
|
300
|
+
const reconcileStyles = (sourceDocument, target, manager, enabled, transformStyle = (content) => content, anchor = null) => {
|
|
301
|
+
if (!enabled) {
|
|
302
|
+
manager.clones.forEach(removeClone);
|
|
303
|
+
manager.clones.clear();
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const sources = sourceStyles(sourceDocument);
|
|
307
|
+
const sourceSet = new Set(sources);
|
|
308
|
+
const container = targetContainer(target);
|
|
309
|
+
manager.clones.forEach((clone, source) => {
|
|
310
|
+
if (!sourceSet.has(source)) {
|
|
311
|
+
removeClone(clone);
|
|
312
|
+
manager.clones.delete(source);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
let previous = null;
|
|
316
|
+
sources.forEach((source) => {
|
|
317
|
+
let clone = manager.clones.get(source);
|
|
318
|
+
if (!clone) {
|
|
319
|
+
clone = createClone(source, target, transformStyle);
|
|
320
|
+
manager.clones.set(source, clone);
|
|
321
|
+
} else copyAttributes(source, clone, transformStyle);
|
|
322
|
+
const nextSibling = previous ? previous.nextSibling : Array.from(container.childNodes).find(isSyncedStyle) ?? (anchor?.parentNode === container ? anchor : null);
|
|
323
|
+
if (clone !== nextSibling) container.insertBefore(clone, nextSibling);
|
|
324
|
+
previous = clone;
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
const createRootAttributeSync = () => ({
|
|
328
|
+
attributes: /* @__PURE__ */ new Set(),
|
|
329
|
+
classes: /* @__PURE__ */ new Set()
|
|
330
|
+
});
|
|
331
|
+
const isMirroredAttribute = (name) => name.startsWith("data-");
|
|
332
|
+
const reconcileRootAttributes = (source, target, sync, enabled) => {
|
|
333
|
+
const attributes = enabled ? Array.from(source.attributes).filter(({ name }) => isMirroredAttribute(name)) : [];
|
|
334
|
+
const classes = enabled ? Array.from(source.classList) : [];
|
|
335
|
+
const attributeNames = new Set(attributes.map(({ name }) => name));
|
|
336
|
+
const classNames = new Set(classes);
|
|
337
|
+
sync.attributes.forEach((name) => {
|
|
338
|
+
if (!attributeNames.has(name)) target.removeAttribute(name);
|
|
339
|
+
});
|
|
340
|
+
attributes.forEach(({ name, value }) => {
|
|
341
|
+
if (target.getAttribute(name) !== value) target.setAttribute(name, value);
|
|
342
|
+
});
|
|
343
|
+
sync.classes.forEach((name) => {
|
|
344
|
+
if (!classNames.has(name)) target.classList.remove(name);
|
|
345
|
+
});
|
|
346
|
+
classes.forEach((name) => target.classList.add(name));
|
|
347
|
+
if (!target.classList.length) target.removeAttribute("class");
|
|
348
|
+
sync.attributes = attributeNames;
|
|
349
|
+
sync.classes = classNames;
|
|
350
|
+
};
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region src/components/frame/iframe/use-host-style-sync.ts
|
|
353
|
+
const useHostStyleSync = (iframeRef, syncStyle) => {
|
|
354
|
+
const styleManagerRef = useRef(createStyleSyncManager());
|
|
355
|
+
const rootAttributeSyncRef = useRef(createRootAttributeSync());
|
|
356
|
+
const applyStyle = useCallback(() => {
|
|
357
|
+
const doc = iframeRef.current?.contentDocument;
|
|
358
|
+
if (!doc) return;
|
|
359
|
+
reconcileStyles(document, doc, styleManagerRef.current, syncStyle, convertViewportUnits, doc.getElementById(CONTAINER_STYLE_ID));
|
|
360
|
+
reconcileRootAttributes(document.documentElement, doc.documentElement, rootAttributeSyncRef.current, syncStyle);
|
|
361
|
+
}, [iframeRef, syncStyle]);
|
|
362
|
+
const debouncedApplyStyle = useDebouncedCallback(applyStyle, {
|
|
363
|
+
delay: 50,
|
|
364
|
+
autoInvoke: false
|
|
365
|
+
});
|
|
366
|
+
useMutationObserver(document.head, debouncedApplyStyle, {
|
|
367
|
+
enabled: syncStyle,
|
|
368
|
+
childList: true,
|
|
369
|
+
subtree: true,
|
|
370
|
+
attributes: true
|
|
371
|
+
});
|
|
372
|
+
useMutationObserver(document.documentElement, debouncedApplyStyle, {
|
|
373
|
+
enabled: syncStyle,
|
|
374
|
+
attributes: true
|
|
375
|
+
});
|
|
376
|
+
return applyStyle;
|
|
377
|
+
};
|
|
378
|
+
//#endregion
|
|
379
|
+
//#region src/components/frame/iframe/use-iframe-document.ts
|
|
380
|
+
const injectScripts = (doc, srcs) => {
|
|
381
|
+
withScriptBlobs(srcs, (blobUrls) => {
|
|
382
|
+
if (!doc.head) return;
|
|
383
|
+
const fragment = doc.createDocumentFragment();
|
|
384
|
+
blobUrls.forEach((blobUrl) => {
|
|
385
|
+
const script = doc.createElement("script");
|
|
386
|
+
script.src = blobUrl;
|
|
387
|
+
fragment.appendChild(script);
|
|
388
|
+
});
|
|
389
|
+
doc.head.appendChild(fragment);
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
const useIframeDocument = (iframeRef, { scripts, onLoaded, applyStyle }) => {
|
|
393
|
+
const [mountNode, setMountNode] = useState(null);
|
|
394
|
+
const loadedScriptsRef = useRef(/* @__PURE__ */ new Set());
|
|
395
|
+
const loadedScriptsDocRef = useRef(null);
|
|
396
|
+
useEffect(() => {
|
|
397
|
+
const $iframe = iframeRef.current;
|
|
398
|
+
if (!$iframe) return;
|
|
399
|
+
const onLoad = () => {
|
|
400
|
+
const doc = $iframe.contentDocument;
|
|
401
|
+
if (!doc) return;
|
|
402
|
+
if (loadedScriptsDocRef.current !== doc) {
|
|
403
|
+
loadedScriptsDocRef.current = doc;
|
|
404
|
+
loadedScriptsRef.current = /* @__PURE__ */ new Set();
|
|
405
|
+
}
|
|
406
|
+
doc.body.style.overflowX = "hidden";
|
|
407
|
+
doc.body.style.margin = "0";
|
|
408
|
+
let node = doc.getElementById("iframe-root");
|
|
409
|
+
if (!node) {
|
|
410
|
+
node = doc.createElement("div");
|
|
411
|
+
node.id = "iframe-root";
|
|
412
|
+
doc.body.appendChild(node);
|
|
413
|
+
}
|
|
414
|
+
setMountNode(node);
|
|
415
|
+
applyStyle();
|
|
416
|
+
const pendingScripts = scripts.filter((src) => !loadedScriptsRef.current.has(src));
|
|
417
|
+
if (pendingScripts.length) {
|
|
418
|
+
pendingScripts.forEach((src) => loadedScriptsRef.current.add(src));
|
|
419
|
+
injectScripts(doc, pendingScripts);
|
|
420
|
+
}
|
|
421
|
+
onLoaded?.();
|
|
422
|
+
};
|
|
423
|
+
$iframe.addEventListener("load", onLoad);
|
|
424
|
+
if ($iframe.contentDocument?.readyState === "complete") onLoad();
|
|
425
|
+
return () => {
|
|
426
|
+
$iframe.removeEventListener("load", onLoad);
|
|
427
|
+
};
|
|
428
|
+
}, [
|
|
429
|
+
iframeRef,
|
|
430
|
+
scripts,
|
|
431
|
+
onLoaded,
|
|
432
|
+
applyStyle
|
|
433
|
+
]);
|
|
434
|
+
return mountNode;
|
|
435
|
+
};
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/components/frame/iframe/iframe.tsx
|
|
438
|
+
const EMPTY_STRING_ARRAY = [];
|
|
439
|
+
const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_STRING_ARRAY, styles = EMPTY_STRING_ARRAY, stylesheets = EMPTY_STRING_ARRAY, autoHeight = false, syncStyle = false, children, onLoaded, ...props }) => {
|
|
440
|
+
const iframeRef = useRef(null);
|
|
441
|
+
const shouldAutoHeight = autoHeight && style.height == null;
|
|
442
|
+
const applyStyle = useHostStyleSync(iframeRef, syncStyle);
|
|
443
|
+
const mountNode = useIframeDocument(iframeRef, {
|
|
444
|
+
scripts,
|
|
445
|
+
onLoaded,
|
|
446
|
+
applyStyle
|
|
447
|
+
});
|
|
448
|
+
const injectedCountsRef = useRef({
|
|
449
|
+
styles: 0,
|
|
450
|
+
stylesheets: 0
|
|
451
|
+
});
|
|
452
|
+
useEffect(() => {
|
|
453
|
+
const doc = iframeRef.current?.contentDocument;
|
|
454
|
+
if (!doc?.head) return;
|
|
455
|
+
injectedCountsRef.current = syncInjectedAssets(doc, styles, stylesheets, injectedCountsRef.current);
|
|
456
|
+
}, [styles, stylesheets]);
|
|
457
|
+
useAutoHeight(iframeRef, mountNode, shouldAutoHeight);
|
|
426
458
|
const content = mountNode ? createPortal(children(mountNode), mountNode) : null;
|
|
427
459
|
return /* @__PURE__ */ jsx("iframe", {
|
|
428
460
|
ref: iframeRef,
|
|
@@ -480,14 +512,10 @@ const Shadow = ({ syncStyle = false, children }) => {
|
|
|
480
512
|
if (!shadowRoot) return;
|
|
481
513
|
reconcileStyles(document, shadowRoot, styleManagerRef.current, syncStyle);
|
|
482
514
|
}, [syncStyle]);
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}, [applyStyle]);
|
|
488
|
-
useEffect(() => {
|
|
489
|
-
return () => clearTimeout(applyStyleTimeoutRef.current);
|
|
490
|
-
}, []);
|
|
515
|
+
const debouncedApplyStyle = useDebouncedCallback(applyStyle, {
|
|
516
|
+
delay: 50,
|
|
517
|
+
autoInvoke: false
|
|
518
|
+
});
|
|
491
519
|
useMutationObserver(document.head, debouncedApplyStyle, {
|
|
492
520
|
enabled: syncStyle,
|
|
493
521
|
childList: true,
|
|
@@ -542,7 +570,7 @@ const baseModules = {
|
|
|
542
570
|
//#endregion
|
|
543
571
|
//#region src/components/preview/use-compiled-module.ts
|
|
544
572
|
const useCompiledModule = (code, _modules) => {
|
|
545
|
-
const modules =
|
|
573
|
+
const modules = useStableValue(_modules);
|
|
546
574
|
const { unknown } = useLiveMessages().errors;
|
|
547
575
|
const mergedModules = useMemo(() => ({
|
|
548
576
|
...baseModules,
|
|
@@ -592,6 +620,6 @@ const useDynamicTailwind = (code, enabled) => {
|
|
|
592
620
|
};
|
|
593
621
|
};
|
|
594
622
|
//#endregion
|
|
595
|
-
export {
|
|
623
|
+
export { Frame as i, useCompiledModule as n, baseModules as r, useDynamicTailwind as t };
|
|
596
624
|
|
|
597
|
-
//# sourceMappingURL=use-dynamic-tailwind-
|
|
625
|
+
//# sourceMappingURL=use-dynamic-tailwind-CSYKXDmX.js.map
|