@jbpark/live-editor 4.6.1 → 6.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 +37 -35
- package/README.md +37 -35
- package/dist/{boundary-BLB80tyw.js → boundary-CySnDUs2.js} +5 -4
- package/dist/boundary-CySnDUs2.js.map +1 -0
- package/dist/{compile-Dxas-D05.js → compile-my0AjsCw.js} +8 -7
- package/dist/compile-my0AjsCw.js.map +1 -0
- package/dist/constants-st9gnJ5g.js +55 -0
- package/dist/constants-st9gnJ5g.js.map +1 -0
- package/dist/{context-B8MzP7_p.js → context-Bjq0CvBE.js} +3 -3
- package/dist/{context-B8MzP7_p.js.map → context-Bjq0CvBE.js.map} +1 -1
- package/dist/{core-Bgfek364.js → core-BNVuH8-l.js} +51 -14
- package/dist/core-BNVuH8-l.js.map +1 -0
- package/dist/{detect-typescript-Dr_oLniM.js → detect-typescript-CMF0FVKD.js} +2 -2
- package/dist/{detect-typescript-Dr_oLniM.js.map → detect-typescript-CMF0FVKD.js.map} +1 -1
- package/dist/dnd/index.d.ts +3 -2
- package/dist/dnd/index.js +3 -2
- package/dist/dnd-BvjEDo-x.js +4197 -0
- package/dist/dnd-BvjEDo-x.js.map +1 -0
- package/dist/document-BQhb7YR8.d.ts +17 -0
- package/dist/{document-CHO215iP.js → document-uHqw0mvr.js} +194 -109
- package/dist/document-uHqw0mvr.js.map +1 -0
- package/dist/edit-options-C_r9aCz4.d.ts +100 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +2 -2
- package/dist/{editor-CMElfHer.js → editor-CvnzrM9J.js} +2 -2
- package/dist/{editor-CMElfHer.js.map → editor-CvnzrM9J.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-CFzvnLCf.js} +18 -32
- package/dist/error-CFzvnLCf.js.map +1 -0
- package/dist/{index-DpDU1IAw.d.ts → index-92L7F440.d.ts} +2 -2
- package/dist/{index-DrWtSKXu.d.ts → index-BZpZwrxT.d.ts} +2 -2
- package/dist/index-C8h8TcIl.d.ts +15 -0
- package/dist/{index-13BDSrQc.d.ts → index-C93npmTU.d.ts} +4 -6
- package/dist/{index-DQkL37eL.d.ts → index-CqsS207F.d.ts} +6 -12
- package/dist/{index-CiWB0zFb.d.ts → index-DQcdHg_V.d.ts} +18 -136
- package/dist/{index-CRwEhJ7w.d.ts → index-DfIvkht8.d.ts} +3 -3
- package/dist/index.d.ts +12 -11
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/{messages-IBPs4TkZ.d.ts → messages-BpN3QIhj.d.ts} +8 -2
- package/dist/{messages-CSrMI4Rm.js → messages-DrINcRdG.js} +8 -2
- package/dist/messages-DrINcRdG.js.map +1 -0
- package/dist/preview/index.d.ts +2 -2
- package/dist/preview/index.js +2 -3
- package/dist/{preview-CtyG5UbH.js → preview-B05MkVIQ.js} +16 -13
- package/dist/preview-B05MkVIQ.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-DhH_aVf5.js} +4 -7
- package/dist/sections-DhH_aVf5.js.map +1 -0
- package/dist/style.css +809 -4950
- package/dist/{validate-DB59Z_Nx.d.ts → types-Czps1Txy.d.ts} +12 -28
- package/dist/ui-kit/index.d.ts +22 -0
- package/dist/{constants-DU17Tdwo.js → ui-kit/index.js} +147 -54
- package/dist/ui-kit/index.js.map +1 -0
- package/dist/ui-kit/style.css +5039 -0
- package/dist/update-2PJbwoS8.d.ts +68 -0
- package/dist/{items-BXXtMUNI.js → update-BuYQJqjq.js} +143 -392
- package/dist/update-BuYQJqjq.js.map +1 -0
- package/dist/{use-dynamic-tailwind-BP1toJkW.js → use-dynamic-tailwind-B3l1qZRW.js} +318 -287
- package/dist/use-dynamic-tailwind-B3l1qZRW.js.map +1 -0
- package/dist/use-field-state-iQGW0vc6.js +131 -0
- package/dist/use-field-state-iQGW0vc6.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 +20 -10
- package/dist/boundary-BLB80tyw.js.map +0 -1
- package/dist/compile-Dxas-D05.js.map +0 -1
- package/dist/constants-DU17Tdwo.js.map +0 -1
- package/dist/core-Bgfek364.js.map +0 -1
- package/dist/dnd-V8NAxd_R.js +0 -2755
- 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,10 @@
|
|
|
1
|
-
import { i as useLiveMessages } from "./messages-
|
|
2
|
-
import {
|
|
3
|
-
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
1
|
+
import { i as useLiveMessages } from "./messages-DrINcRdG.js";
|
|
2
|
+
import { i as withScriptBlobs, n as compile } from "./compile-my0AjsCw.js";
|
|
3
|
+
import { createElement, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
import
|
|
6
|
-
import { useEventListener, useMutationObserver, useResizeObserver } from "@jbpark/use-hooks";
|
|
5
|
+
import { useDebouncedCallback, useEventListener, useMutationObserver, useResizeObserver, useStableValue } from "@jbpark/use-hooks";
|
|
7
6
|
import { createPortal } from "react-dom";
|
|
8
|
-
|
|
9
|
-
//#region src/components/preview/use-stable-modules.ts
|
|
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
|
|
7
|
+
//#region src/components/frame/auto-height/measure.ts
|
|
24
8
|
const verticalInsets = (style) => [
|
|
25
9
|
style.marginTop,
|
|
26
10
|
style.marginBottom,
|
|
@@ -40,85 +24,13 @@ const positionedElementBottom = (top, bottom, probeHeight) => {
|
|
|
40
24
|
return Math.min(bottom, probeHeight);
|
|
41
25
|
};
|
|
42
26
|
//#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;
|
|
27
|
+
//#region src/components/frame/auto-height/animations.ts
|
|
28
|
+
const isCssAnimation = (win, animation) => typeof win.CSSAnimation === "function" && animation instanceof win.CSSAnimation;
|
|
29
|
+
const isCssTransition = (win, animation) => typeof win.CSSTransition === "function" && animation instanceof win.CSSTransition;
|
|
30
|
+
const hasActiveAnimation = (el) => typeof el.getAnimations === "function" && el.getAnimations().some((animation) => isAnimationActive(animation.playState));
|
|
31
|
+
const neverFinishes = (animation) => {
|
|
32
|
+
const timing = animation.effect?.getComputedTiming();
|
|
33
|
+
return timing?.iterations === Infinity || timing?.duration === Infinity;
|
|
122
34
|
};
|
|
123
35
|
//#endregion
|
|
124
36
|
//#region src/components/frame/viewport-units.ts
|
|
@@ -148,16 +60,8 @@ const rewriteInlineViewportUnits = (root) => {
|
|
|
148
60
|
});
|
|
149
61
|
};
|
|
150
62
|
//#endregion
|
|
151
|
-
//#region src/components/frame/
|
|
63
|
+
//#region src/components/frame/auto-height/auto-height.ts
|
|
152
64
|
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
65
|
const MEASUREMENT_OVERRIDE_STYLE_ID = "autoheight-measurement-overrides";
|
|
162
66
|
const SCROLLBAR_OVERRIDE_RULES = ["html, body { scrollbar-width: none !important; }", "html::-webkit-scrollbar, body::-webkit-scrollbar { display: none !important; }"];
|
|
163
67
|
const FREEZE_TRANSITIONS_RULE = "*, *::before, *::after { transition: none !important; }";
|
|
@@ -175,130 +79,54 @@ const withMeasurementOverrides = (doc, freezeTransitions, measure) => {
|
|
|
175
79
|
measure();
|
|
176
80
|
styleEl.media = "not all";
|
|
177
81
|
};
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
82
|
+
const HIDE_SCROLLBAR_STYLE_ID = "autoheight-hide-scrollbar";
|
|
83
|
+
const ensureContainerStyle = (doc, probeHeight) => {
|
|
84
|
+
let styleEl = doc.getElementById(CONTAINER_STYLE_ID);
|
|
85
|
+
if (!styleEl) {
|
|
86
|
+
styleEl = doc.createElement("style");
|
|
87
|
+
styleEl.id = CONTAINER_STYLE_ID;
|
|
88
|
+
doc.head?.appendChild(styleEl);
|
|
89
|
+
}
|
|
90
|
+
const text = `html { container-type: size !important; height: ${probeHeight}px !important; }`;
|
|
91
|
+
if (styleEl.textContent !== text) styleEl.textContent = text;
|
|
92
|
+
};
|
|
93
|
+
const getProbeHeight = (iframe, win) => {
|
|
94
|
+
const scrollParent = iframe.closest("[data-frame-container]");
|
|
95
|
+
if (!scrollParent) return 812;
|
|
96
|
+
const scrollParentStyle = win.getComputedStyle(scrollParent);
|
|
97
|
+
let wrapperInsets = (parseFloat(scrollParentStyle.paddingTop) || 0) + (parseFloat(scrollParentStyle.paddingBottom) || 0);
|
|
98
|
+
let node = iframe;
|
|
99
|
+
while (node && node !== scrollParent) {
|
|
100
|
+
wrapperInsets += verticalInsets(win.getComputedStyle(node));
|
|
101
|
+
node = node.parentElement;
|
|
102
|
+
}
|
|
103
|
+
return computeProbeHeight(scrollParent.clientHeight, wrapperInsets);
|
|
104
|
+
};
|
|
105
|
+
const measureContentHeight = (mountNode, doc, win, probeHeight, freezeTransitions) => {
|
|
106
|
+
let contentHeight = 0;
|
|
107
|
+
withMeasurementOverrides(doc, freezeTransitions, () => {
|
|
108
|
+
ensureContainerStyle(doc, probeHeight);
|
|
109
|
+
rewriteInlineViewportUnits(mountNode);
|
|
110
|
+
contentHeight = mountNode.scrollHeight;
|
|
111
|
+
mountNode.querySelectorAll("*").forEach((el) => {
|
|
112
|
+
const style = win.getComputedStyle(el);
|
|
113
|
+
const isAnimating = style.opacity === "0" && hasActiveAnimation(el);
|
|
114
|
+
if (isVisuallyHidden(style, isAnimating)) return;
|
|
115
|
+
if ((style.position === "fixed" || style.position === "absolute") && el.offsetHeight > 0) {
|
|
116
|
+
const rect = el.getBoundingClientRect();
|
|
117
|
+
const bottom = positionedElementBottom(rect.top, rect.bottom, probeHeight);
|
|
118
|
+
if (bottom !== null) contentHeight = Math.max(contentHeight, bottom);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
return contentHeight;
|
|
123
|
+
};
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/components/frame/auto-height/use-auto-height.ts
|
|
126
|
+
const useAutoHeight = (iframeRef, mountNode, shouldAutoHeight) => {
|
|
185
127
|
const trackedAnimationsRef = useRef(/* @__PURE__ */ new WeakSet());
|
|
186
128
|
const updateHeightRef = useRef(null);
|
|
187
129
|
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
130
|
const trackScriptAnimations = useCallback((doc, win) => {
|
|
303
131
|
if (typeof doc.getAnimations !== "function") return;
|
|
304
132
|
doc.getAnimations().forEach((animation) => {
|
|
@@ -313,44 +141,17 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
313
141
|
const doc = iframe.contentDocument;
|
|
314
142
|
const win = doc?.defaultView;
|
|
315
143
|
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;
|
|
144
|
+
const probeHeight = getProbeHeight(iframe, win);
|
|
145
|
+
if (probeHeight === null) return;
|
|
332
146
|
const freezeTransitions = probeHeight !== lastProbeHeightRef.current;
|
|
333
147
|
lastProbeHeightRef.current = probeHeight;
|
|
334
148
|
const previousHeight = iframe.style.height;
|
|
335
149
|
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
|
-
});
|
|
150
|
+
const contentHeight = measureContentHeight(mountNode, doc, win, probeHeight, freezeTransitions);
|
|
351
151
|
iframe.style.height = contentHeight > 0 ? `${Math.ceil(contentHeight)}px` : previousHeight;
|
|
352
152
|
trackScriptAnimations(doc, win);
|
|
353
153
|
}, [
|
|
154
|
+
iframeRef,
|
|
354
155
|
shouldAutoHeight,
|
|
355
156
|
mountNode,
|
|
356
157
|
trackScriptAnimations
|
|
@@ -361,13 +162,17 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
361
162
|
useEffect(() => {
|
|
362
163
|
if (shouldAutoHeight) return;
|
|
363
164
|
iframeRef.current?.contentDocument?.getElementById(CONTAINER_STYLE_ID)?.remove();
|
|
364
|
-
}, [shouldAutoHeight]);
|
|
165
|
+
}, [iframeRef, shouldAutoHeight]);
|
|
365
166
|
useEffect(() => {
|
|
366
167
|
const body = iframeRef.current?.contentDocument?.body;
|
|
367
168
|
if (!body || !mountNode) return;
|
|
368
169
|
if (shouldAutoHeight) body.style.removeProperty("overflow-y");
|
|
369
170
|
else body.style.setProperty("overflow-y", "auto");
|
|
370
|
-
}, [
|
|
171
|
+
}, [
|
|
172
|
+
iframeRef,
|
|
173
|
+
shouldAutoHeight,
|
|
174
|
+
mountNode
|
|
175
|
+
]);
|
|
371
176
|
useEffect(() => {
|
|
372
177
|
const doc = iframeRef.current?.contentDocument;
|
|
373
178
|
if (!doc?.head) return;
|
|
@@ -379,9 +184,13 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
379
184
|
if (existing) return;
|
|
380
185
|
const styleEl = doc.createElement("style");
|
|
381
186
|
styleEl.id = HIDE_SCROLLBAR_STYLE_ID;
|
|
382
|
-
styleEl.textContent =
|
|
187
|
+
styleEl.textContent = SCROLLBAR_OVERRIDE_RULES.join("\n");
|
|
383
188
|
doc.head.appendChild(styleEl);
|
|
384
|
-
}, [
|
|
189
|
+
}, [
|
|
190
|
+
iframeRef,
|
|
191
|
+
shouldAutoHeight,
|
|
192
|
+
mountNode
|
|
193
|
+
]);
|
|
385
194
|
useEffect(() => {
|
|
386
195
|
updateHeight();
|
|
387
196
|
}, [updateHeight]);
|
|
@@ -423,6 +232,227 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
423
232
|
target: mountNodeRef,
|
|
424
233
|
enabled: settleListenerEnabled
|
|
425
234
|
});
|
|
235
|
+
};
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/components/frame/iframe/inject-assets.ts
|
|
238
|
+
const syncInjectedElements = (doc, idPrefix, values, previousCount, create, update) => {
|
|
239
|
+
values.forEach((value, index) => {
|
|
240
|
+
const id = `${idPrefix}${index}`;
|
|
241
|
+
let el = doc.getElementById(id);
|
|
242
|
+
if (!el) {
|
|
243
|
+
el = create();
|
|
244
|
+
el.id = id;
|
|
245
|
+
doc.head.appendChild(el);
|
|
246
|
+
}
|
|
247
|
+
update(el, value);
|
|
248
|
+
});
|
|
249
|
+
for (let index = values.length; index < previousCount; index++) doc.getElementById(`${idPrefix}${index}`)?.remove();
|
|
250
|
+
};
|
|
251
|
+
const syncInjectedAssets = (doc, styles, stylesheets, previous) => {
|
|
252
|
+
syncInjectedElements(doc, "injected-style-", styles, previous.styles, () => doc.createElement("style"), (styleEl, css) => {
|
|
253
|
+
const convertedCss = convertViewportUnits(css);
|
|
254
|
+
if (styleEl.textContent !== convertedCss) styleEl.textContent = convertedCss;
|
|
255
|
+
});
|
|
256
|
+
syncInjectedElements(doc, "injected-stylesheet-", stylesheets, previous.stylesheets, () => {
|
|
257
|
+
const linkEl = doc.createElement("link");
|
|
258
|
+
linkEl.rel = "stylesheet";
|
|
259
|
+
return linkEl;
|
|
260
|
+
}, (linkEl, href) => {
|
|
261
|
+
if (linkEl.href !== href) linkEl.href = href;
|
|
262
|
+
});
|
|
263
|
+
return {
|
|
264
|
+
styles: styles.length,
|
|
265
|
+
stylesheets: stylesheets.length
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
//#endregion
|
|
269
|
+
//#region src/components/frame/style-sync.ts
|
|
270
|
+
const SYNCED_STYLE_ATTR = "data-live-editor-synced-style";
|
|
271
|
+
const createStyleSyncManager = () => ({ clones: /* @__PURE__ */ new Map() });
|
|
272
|
+
const isDocument = (target) => target.nodeType === Node.DOCUMENT_NODE;
|
|
273
|
+
const sourceStyles = (document) => Array.from(document.head.querySelectorAll("link[rel=\"stylesheet\"], style"));
|
|
274
|
+
const copyAttributes = (source, clone, transformStyle) => {
|
|
275
|
+
Array.from(clone.attributes).forEach((attribute) => {
|
|
276
|
+
if (attribute.name !== SYNCED_STYLE_ATTR && !source.hasAttribute(attribute.name)) clone.removeAttribute(attribute.name);
|
|
277
|
+
});
|
|
278
|
+
Array.from(source.attributes).forEach((attribute) => {
|
|
279
|
+
clone.setAttribute(attribute.name, attribute.value);
|
|
280
|
+
});
|
|
281
|
+
if (source.tagName === "LINK" && clone.tagName === "LINK") clone.disabled = source.disabled;
|
|
282
|
+
clone.textContent = source.tagName === "STYLE" ? transformStyle(source.textContent || "") : source.textContent;
|
|
283
|
+
};
|
|
284
|
+
const createClone = (source, target, transformStyle) => {
|
|
285
|
+
const clone = (isDocument(target) ? target : target.ownerDocument).createElement(source.tagName.toLowerCase());
|
|
286
|
+
clone.setAttribute(SYNCED_STYLE_ATTR, "");
|
|
287
|
+
copyAttributes(source, clone, transformStyle);
|
|
288
|
+
return clone;
|
|
289
|
+
};
|
|
290
|
+
const targetContainer = (target) => isDocument(target) ? target.head : target;
|
|
291
|
+
const isSyncedStyle = (node) => {
|
|
292
|
+
const element = node;
|
|
293
|
+
return (element.tagName === "LINK" || element.tagName === "STYLE") && element.hasAttribute(SYNCED_STYLE_ATTR);
|
|
294
|
+
};
|
|
295
|
+
const removeClone = (clone) => {
|
|
296
|
+
clone.remove();
|
|
297
|
+
};
|
|
298
|
+
const reconcileStyles = (sourceDocument, target, manager, enabled, transformStyle = (content) => content, anchor = null) => {
|
|
299
|
+
if (!enabled) {
|
|
300
|
+
manager.clones.forEach(removeClone);
|
|
301
|
+
manager.clones.clear();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const sources = sourceStyles(sourceDocument);
|
|
305
|
+
const sourceSet = new Set(sources);
|
|
306
|
+
const container = targetContainer(target);
|
|
307
|
+
manager.clones.forEach((clone, source) => {
|
|
308
|
+
if (!sourceSet.has(source)) {
|
|
309
|
+
removeClone(clone);
|
|
310
|
+
manager.clones.delete(source);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
let previous = null;
|
|
314
|
+
sources.forEach((source) => {
|
|
315
|
+
let clone = manager.clones.get(source);
|
|
316
|
+
if (!clone) {
|
|
317
|
+
clone = createClone(source, target, transformStyle);
|
|
318
|
+
manager.clones.set(source, clone);
|
|
319
|
+
} else copyAttributes(source, clone, transformStyle);
|
|
320
|
+
const nextSibling = previous ? previous.nextSibling : Array.from(container.childNodes).find(isSyncedStyle) ?? (anchor?.parentNode === container ? anchor : null);
|
|
321
|
+
if (clone !== nextSibling) container.insertBefore(clone, nextSibling);
|
|
322
|
+
previous = clone;
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
const createRootAttributeSync = () => ({
|
|
326
|
+
attributes: /* @__PURE__ */ new Set(),
|
|
327
|
+
classes: /* @__PURE__ */ new Set()
|
|
328
|
+
});
|
|
329
|
+
const isMirroredAttribute = (name) => name.startsWith("data-");
|
|
330
|
+
const reconcileRootAttributes = (source, target, sync, enabled) => {
|
|
331
|
+
const attributes = enabled ? Array.from(source.attributes).filter(({ name }) => isMirroredAttribute(name)) : [];
|
|
332
|
+
const classes = enabled ? Array.from(source.classList) : [];
|
|
333
|
+
const attributeNames = new Set(attributes.map(({ name }) => name));
|
|
334
|
+
const classNames = new Set(classes);
|
|
335
|
+
sync.attributes.forEach((name) => {
|
|
336
|
+
if (!attributeNames.has(name)) target.removeAttribute(name);
|
|
337
|
+
});
|
|
338
|
+
attributes.forEach(({ name, value }) => {
|
|
339
|
+
if (target.getAttribute(name) !== value) target.setAttribute(name, value);
|
|
340
|
+
});
|
|
341
|
+
sync.classes.forEach((name) => {
|
|
342
|
+
if (!classNames.has(name)) target.classList.remove(name);
|
|
343
|
+
});
|
|
344
|
+
classes.forEach((name) => target.classList.add(name));
|
|
345
|
+
if (!target.classList.length) target.removeAttribute("class");
|
|
346
|
+
sync.attributes = attributeNames;
|
|
347
|
+
sync.classes = classNames;
|
|
348
|
+
};
|
|
349
|
+
//#endregion
|
|
350
|
+
//#region src/components/frame/iframe/use-host-style-sync.ts
|
|
351
|
+
const useHostStyleSync = (iframeRef, syncStyle) => {
|
|
352
|
+
const styleManagerRef = useRef(createStyleSyncManager());
|
|
353
|
+
const rootAttributeSyncRef = useRef(createRootAttributeSync());
|
|
354
|
+
const applyStyle = useCallback(() => {
|
|
355
|
+
const doc = iframeRef.current?.contentDocument;
|
|
356
|
+
if (!doc) return;
|
|
357
|
+
reconcileStyles(document, doc, styleManagerRef.current, syncStyle, convertViewportUnits, doc.getElementById(CONTAINER_STYLE_ID));
|
|
358
|
+
reconcileRootAttributes(document.documentElement, doc.documentElement, rootAttributeSyncRef.current, syncStyle);
|
|
359
|
+
}, [iframeRef, syncStyle]);
|
|
360
|
+
const debouncedApplyStyle = useDebouncedCallback(applyStyle, {
|
|
361
|
+
delay: 50,
|
|
362
|
+
autoInvoke: false
|
|
363
|
+
});
|
|
364
|
+
useMutationObserver(document.head, debouncedApplyStyle, {
|
|
365
|
+
enabled: syncStyle,
|
|
366
|
+
childList: true,
|
|
367
|
+
subtree: true,
|
|
368
|
+
attributes: true
|
|
369
|
+
});
|
|
370
|
+
useMutationObserver(document.documentElement, debouncedApplyStyle, {
|
|
371
|
+
enabled: syncStyle,
|
|
372
|
+
attributes: true
|
|
373
|
+
});
|
|
374
|
+
return applyStyle;
|
|
375
|
+
};
|
|
376
|
+
//#endregion
|
|
377
|
+
//#region src/components/frame/iframe/use-iframe-document.ts
|
|
378
|
+
const injectScripts = (doc, srcs) => {
|
|
379
|
+
withScriptBlobs(srcs, (blobUrls) => {
|
|
380
|
+
if (!doc.head) return;
|
|
381
|
+
const fragment = doc.createDocumentFragment();
|
|
382
|
+
blobUrls.forEach((blobUrl) => {
|
|
383
|
+
const script = doc.createElement("script");
|
|
384
|
+
script.src = blobUrl;
|
|
385
|
+
fragment.appendChild(script);
|
|
386
|
+
});
|
|
387
|
+
doc.head.appendChild(fragment);
|
|
388
|
+
});
|
|
389
|
+
};
|
|
390
|
+
const useIframeDocument = (iframeRef, { scripts, onLoaded, applyStyle }) => {
|
|
391
|
+
const [mountNode, setMountNode] = useState(null);
|
|
392
|
+
const loadedScriptsRef = useRef(/* @__PURE__ */ new Set());
|
|
393
|
+
const loadedScriptsDocRef = useRef(null);
|
|
394
|
+
useEffect(() => {
|
|
395
|
+
const $iframe = iframeRef.current;
|
|
396
|
+
if (!$iframe) return;
|
|
397
|
+
const onLoad = () => {
|
|
398
|
+
const doc = $iframe.contentDocument;
|
|
399
|
+
if (!doc) return;
|
|
400
|
+
if (loadedScriptsDocRef.current !== doc) {
|
|
401
|
+
loadedScriptsDocRef.current = doc;
|
|
402
|
+
loadedScriptsRef.current = /* @__PURE__ */ new Set();
|
|
403
|
+
}
|
|
404
|
+
doc.body.style.overflowX = "hidden";
|
|
405
|
+
doc.body.style.margin = "0";
|
|
406
|
+
let node = doc.getElementById("iframe-root");
|
|
407
|
+
if (!node) {
|
|
408
|
+
node = doc.createElement("div");
|
|
409
|
+
node.id = "iframe-root";
|
|
410
|
+
doc.body.appendChild(node);
|
|
411
|
+
}
|
|
412
|
+
setMountNode(node);
|
|
413
|
+
applyStyle();
|
|
414
|
+
const pendingScripts = scripts.filter((src) => !loadedScriptsRef.current.has(src));
|
|
415
|
+
if (pendingScripts.length) {
|
|
416
|
+
pendingScripts.forEach((src) => loadedScriptsRef.current.add(src));
|
|
417
|
+
injectScripts(doc, pendingScripts);
|
|
418
|
+
}
|
|
419
|
+
onLoaded?.();
|
|
420
|
+
};
|
|
421
|
+
$iframe.addEventListener("load", onLoad);
|
|
422
|
+
if ($iframe.contentDocument?.readyState === "complete") onLoad();
|
|
423
|
+
return () => {
|
|
424
|
+
$iframe.removeEventListener("load", onLoad);
|
|
425
|
+
};
|
|
426
|
+
}, [
|
|
427
|
+
iframeRef,
|
|
428
|
+
scripts,
|
|
429
|
+
onLoaded,
|
|
430
|
+
applyStyle
|
|
431
|
+
]);
|
|
432
|
+
return mountNode;
|
|
433
|
+
};
|
|
434
|
+
//#endregion
|
|
435
|
+
//#region src/components/frame/iframe/iframe.tsx
|
|
436
|
+
const EMPTY_STRING_ARRAY = [];
|
|
437
|
+
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 }) => {
|
|
438
|
+
const iframeRef = useRef(null);
|
|
439
|
+
const shouldAutoHeight = autoHeight && style.height == null;
|
|
440
|
+
const applyStyle = useHostStyleSync(iframeRef, syncStyle);
|
|
441
|
+
const mountNode = useIframeDocument(iframeRef, {
|
|
442
|
+
scripts,
|
|
443
|
+
onLoaded,
|
|
444
|
+
applyStyle
|
|
445
|
+
});
|
|
446
|
+
const injectedCountsRef = useRef({
|
|
447
|
+
styles: 0,
|
|
448
|
+
stylesheets: 0
|
|
449
|
+
});
|
|
450
|
+
useEffect(() => {
|
|
451
|
+
const doc = iframeRef.current?.contentDocument;
|
|
452
|
+
if (!doc?.head) return;
|
|
453
|
+
injectedCountsRef.current = syncInjectedAssets(doc, styles, stylesheets, injectedCountsRef.current);
|
|
454
|
+
}, [styles, stylesheets]);
|
|
455
|
+
useAutoHeight(iframeRef, mountNode, shouldAutoHeight);
|
|
426
456
|
const content = mountNode ? createPortal(children(mountNode), mountNode) : null;
|
|
427
457
|
return /* @__PURE__ */ jsx("iframe", {
|
|
428
458
|
ref: iframeRef,
|
|
@@ -480,14 +510,10 @@ const Shadow = ({ syncStyle = false, children }) => {
|
|
|
480
510
|
if (!shadowRoot) return;
|
|
481
511
|
reconcileStyles(document, shadowRoot, styleManagerRef.current, syncStyle);
|
|
482
512
|
}, [syncStyle]);
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}, [applyStyle]);
|
|
488
|
-
useEffect(() => {
|
|
489
|
-
return () => clearTimeout(applyStyleTimeoutRef.current);
|
|
490
|
-
}, []);
|
|
513
|
+
const debouncedApplyStyle = useDebouncedCallback(applyStyle, {
|
|
514
|
+
delay: 50,
|
|
515
|
+
autoInvoke: false
|
|
516
|
+
});
|
|
491
517
|
useMutationObserver(document.head, debouncedApplyStyle, {
|
|
492
518
|
enabled: syncStyle,
|
|
493
519
|
childList: true,
|
|
@@ -534,24 +560,29 @@ const Frame = ({ mode, children, ...restProps }) => {
|
|
|
534
560
|
});
|
|
535
561
|
};
|
|
536
562
|
//#endregion
|
|
537
|
-
//#region src/components/preview/
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
};
|
|
563
|
+
//#region src/components/preview/stable-component.ts
|
|
564
|
+
const HOOK_CALL = /\buse(?:[A-Z0-9_]\w*)?\s*\(/g;
|
|
565
|
+
const hookSignature = (code) => (code.match(HOOK_CALL) ?? []).map((call) => call.replace(/\s*\($/, "")).join(",");
|
|
566
|
+
const isFunctionComponent = (component) => typeof component === "function" && !component.prototype?.isReactComponent;
|
|
567
|
+
const StableComponent = ({ render, props }) => render(props);
|
|
568
|
+
const renderStableComponent = (Component, code, props) => isFunctionComponent(Component) ? createElement(StableComponent, {
|
|
569
|
+
key: hookSignature(code),
|
|
570
|
+
render: Component,
|
|
571
|
+
props
|
|
572
|
+
}) : createElement(Component, props);
|
|
573
|
+
//#endregion
|
|
574
|
+
//#region src/components/preview/defaults.ts
|
|
575
|
+
const NO_PROPS = {};
|
|
576
|
+
const NO_MODULES = {};
|
|
542
577
|
//#endregion
|
|
543
578
|
//#region src/components/preview/use-compiled-module.ts
|
|
544
579
|
const useCompiledModule = (code, _modules) => {
|
|
545
|
-
const modules =
|
|
580
|
+
const modules = useStableValue(_modules);
|
|
546
581
|
const { unknown } = useLiveMessages().errors;
|
|
547
|
-
const mergedModules = useMemo(() => ({
|
|
548
|
-
...baseModules,
|
|
549
|
-
...modules
|
|
550
|
-
}), [modules]);
|
|
551
582
|
return useMemo(() => {
|
|
552
583
|
if (!code) return null;
|
|
553
584
|
try {
|
|
554
|
-
return compile(code,
|
|
585
|
+
return compile(code, modules ?? NO_MODULES);
|
|
555
586
|
} catch (e) {
|
|
556
587
|
return {
|
|
557
588
|
exports: {},
|
|
@@ -560,7 +591,7 @@ const useCompiledModule = (code, _modules) => {
|
|
|
560
591
|
}
|
|
561
592
|
}, [
|
|
562
593
|
code,
|
|
563
|
-
|
|
594
|
+
modules,
|
|
564
595
|
unknown
|
|
565
596
|
]);
|
|
566
597
|
};
|
|
@@ -592,6 +623,6 @@ const useDynamicTailwind = (code, enabled) => {
|
|
|
592
623
|
};
|
|
593
624
|
};
|
|
594
625
|
//#endregion
|
|
595
|
-
export {
|
|
626
|
+
export { renderStableComponent as a, NO_PROPS as i, useCompiledModule as n, Frame as o, NO_MODULES as r, useDynamicTailwind as t };
|
|
596
627
|
|
|
597
|
-
//# sourceMappingURL=use-dynamic-tailwind-
|
|
628
|
+
//# sourceMappingURL=use-dynamic-tailwind-B3l1qZRW.js.map
|