@jbpark/live-editor 1.8.0 → 1.8.1
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/index.d.mts +2 -0
- package/dist/index.mjs +66 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -49,6 +49,7 @@ interface Props$6 {
|
|
|
49
49
|
children: React$1.ReactNode;
|
|
50
50
|
fallback?: (message?: string) => React$1.ReactNode;
|
|
51
51
|
onError?: (e: Error, info: React$1.ErrorInfo) => void;
|
|
52
|
+
resetKeys?: readonly unknown[];
|
|
52
53
|
}
|
|
53
54
|
interface State {
|
|
54
55
|
hasError: boolean;
|
|
@@ -58,6 +59,7 @@ declare class ErrorBoundary extends React$1.Component<Props$6, State> {
|
|
|
58
59
|
constructor(props: Props$6);
|
|
59
60
|
static getDerivedStateFromError(error: Error): State;
|
|
60
61
|
componentDidCatch(error: Error, errorInfo: React$1.ErrorInfo): void;
|
|
62
|
+
componentDidUpdate(prevProps: Props$6): void;
|
|
61
63
|
render(): string | number | bigint | boolean | react_jsx_runtime0.JSX.Element | Iterable<React$1.ReactNode> | Promise<string | number | bigint | boolean | React$1.ReactPortal | React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined> | null | undefined;
|
|
62
64
|
}
|
|
63
65
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -44,8 +44,12 @@ const useError = () => {
|
|
|
44
44
|
//#endregion
|
|
45
45
|
//#region src/components/context/context.tsx
|
|
46
46
|
const ContextProvider = ({ children }) => {
|
|
47
|
-
const [code,
|
|
47
|
+
const [code, setCodeState] = useState(DEFAULT_TEMPLATE);
|
|
48
48
|
const [error, setError] = useState(null);
|
|
49
|
+
const setCode = useCallback((next) => {
|
|
50
|
+
setError(null);
|
|
51
|
+
setCodeState(next);
|
|
52
|
+
}, []);
|
|
49
53
|
useEffect(() => {
|
|
50
54
|
return () => {
|
|
51
55
|
clearCompilationCache();
|
|
@@ -72,7 +76,9 @@ const EMPTY_STRING_ARRAY = [];
|
|
|
72
76
|
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 }) => {
|
|
73
77
|
const iframeRef = useRef(null);
|
|
74
78
|
const [mountNode, setMountNode] = useState(null);
|
|
75
|
-
const
|
|
79
|
+
const loadedScriptsRef = useRef(/* @__PURE__ */ new Set());
|
|
80
|
+
const prevStyleCountRef = useRef(0);
|
|
81
|
+
const prevStylesheetCountRef = useRef(0);
|
|
76
82
|
const shouldAutoHeight = autoHeight && style.height == null;
|
|
77
83
|
const styleManagerRef = useRef({
|
|
78
84
|
copiedLinks: /* @__PURE__ */ new Set(),
|
|
@@ -129,9 +135,10 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
129
135
|
}
|
|
130
136
|
setMountNode(node);
|
|
131
137
|
applyStyle();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
const pendingScripts = scripts.filter((src) => !loadedScriptsRef.current.has(src));
|
|
139
|
+
if (pendingScripts.length) {
|
|
140
|
+
pendingScripts.forEach((src) => loadedScriptsRef.current.add(src));
|
|
141
|
+
Promise.all(pendingScripts.map(getCachedScriptBlob)).then((blobUrls) => {
|
|
135
142
|
if (!doc.head) return;
|
|
136
143
|
const fragment = doc.createDocumentFragment();
|
|
137
144
|
blobUrls.forEach((blobUrl) => {
|
|
@@ -184,6 +191,8 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
184
191
|
}
|
|
185
192
|
if (styleEl.textContent !== css) styleEl.textContent = css;
|
|
186
193
|
});
|
|
194
|
+
for (let index = styles.length; index < prevStyleCountRef.current; index++) doc.getElementById(`injected-style-${index}`)?.remove();
|
|
195
|
+
prevStyleCountRef.current = styles.length;
|
|
187
196
|
stylesheets.forEach((href, index) => {
|
|
188
197
|
const linkId = `injected-stylesheet-${index}`;
|
|
189
198
|
let linkEl = doc.getElementById(linkId);
|
|
@@ -195,6 +204,8 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
|
|
|
195
204
|
}
|
|
196
205
|
if (linkEl.href !== href) linkEl.href = href;
|
|
197
206
|
});
|
|
207
|
+
for (let index = stylesheets.length; index < prevStylesheetCountRef.current; index++) doc.getElementById(`injected-stylesheet-${index}`)?.remove();
|
|
208
|
+
prevStylesheetCountRef.current = stylesheets.length;
|
|
198
209
|
}, [styles, stylesheets]);
|
|
199
210
|
useEffect(() => {
|
|
200
211
|
if (!shouldAutoHeight || !mountNode || !iframeRef.current) return;
|
|
@@ -295,41 +306,6 @@ const Shadow = ({ children }) => {
|
|
|
295
306
|
renderTargetRef.current = target;
|
|
296
307
|
setRenderTarget(target);
|
|
297
308
|
}
|
|
298
|
-
const onClick = (e) => {
|
|
299
|
-
const eventInit = {
|
|
300
|
-
bubbles: true,
|
|
301
|
-
cancelable: true,
|
|
302
|
-
composed: true
|
|
303
|
-
};
|
|
304
|
-
let newEvent;
|
|
305
|
-
if (e instanceof MouseEvent) newEvent = new MouseEvent(e.type, {
|
|
306
|
-
...eventInit,
|
|
307
|
-
clientX: e.clientX,
|
|
308
|
-
clientY: e.clientY,
|
|
309
|
-
button: e.button
|
|
310
|
-
});
|
|
311
|
-
else if (e instanceof PointerEvent) newEvent = new PointerEvent(e.type, {
|
|
312
|
-
...eventInit,
|
|
313
|
-
clientX: e.clientX,
|
|
314
|
-
clientY: e.clientY,
|
|
315
|
-
pointerId: e.pointerId
|
|
316
|
-
});
|
|
317
|
-
else newEvent = new Event(e.type, eventInit);
|
|
318
|
-
hostRef.current?.dispatchEvent(newEvent);
|
|
319
|
-
};
|
|
320
|
-
const eventTypes = [
|
|
321
|
-
"click",
|
|
322
|
-
"pointerdown",
|
|
323
|
-
"pointerup"
|
|
324
|
-
];
|
|
325
|
-
eventTypes.forEach((type) => {
|
|
326
|
-
target.addEventListener(type, onClick, true);
|
|
327
|
-
});
|
|
328
|
-
return () => {
|
|
329
|
-
eventTypes.forEach((type) => {
|
|
330
|
-
target?.removeEventListener(type, onClick, true);
|
|
331
|
-
});
|
|
332
|
-
};
|
|
333
309
|
}, []);
|
|
334
310
|
useLayoutEffect(() => {
|
|
335
311
|
if (renderTargetRef.current && !renderTarget) setRenderTarget(renderTargetRef.current);
|
|
@@ -402,7 +378,16 @@ const Renderer = ({ preview, headers, modules, frame, provider }) => {
|
|
|
402
378
|
...baseModules,
|
|
403
379
|
...modules
|
|
404
380
|
}), [modules]);
|
|
405
|
-
const module = useMemo(() =>
|
|
381
|
+
const module = useMemo(() => {
|
|
382
|
+
try {
|
|
383
|
+
return compile(preview, memoizedModules);
|
|
384
|
+
} catch (e) {
|
|
385
|
+
return {
|
|
386
|
+
exports: {},
|
|
387
|
+
error: e instanceof Error ? e.message : "Module transformation error"
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
}, [preview, memoizedModules]);
|
|
406
391
|
const renderProvider = (component) => {
|
|
407
392
|
return provider ? provider(component) : component;
|
|
408
393
|
};
|
|
@@ -12935,6 +12920,15 @@ var ErrorBoundary = class extends React.Component {
|
|
|
12935
12920
|
console.error("🚨 [Boundary] Rendering error:", error, errorInfo);
|
|
12936
12921
|
this.props.onError?.(error, errorInfo);
|
|
12937
12922
|
}
|
|
12923
|
+
componentDidUpdate(prevProps) {
|
|
12924
|
+
if (!this.state.hasError) return;
|
|
12925
|
+
const prevKeys = prevProps.resetKeys ?? [];
|
|
12926
|
+
const nextKeys = this.props.resetKeys ?? [];
|
|
12927
|
+
if (prevKeys.length !== nextKeys.length || nextKeys.some((key, i) => key !== prevKeys[i])) this.setState({
|
|
12928
|
+
hasError: false,
|
|
12929
|
+
error: void 0
|
|
12930
|
+
});
|
|
12931
|
+
}
|
|
12938
12932
|
render() {
|
|
12939
12933
|
if (this.state.hasError) return this.props.fallback ? /* @__PURE__ */ jsx(Fragment, { children: this.props.fallback(this.state.error?.message) }) : /* @__PURE__ */ jsx(Error$2, {
|
|
12940
12934
|
message: this.state.error?.message,
|
|
@@ -13043,9 +13037,10 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13043
13037
|
...baseModules,
|
|
13044
13038
|
...modules
|
|
13045
13039
|
};
|
|
13040
|
+
const effectiveCode = _code || code;
|
|
13046
13041
|
let module = null;
|
|
13047
|
-
if (
|
|
13048
|
-
module = compile(
|
|
13042
|
+
if (effectiveCode) try {
|
|
13043
|
+
module = compile(effectiveCode, mergedModules);
|
|
13049
13044
|
} catch (e) {
|
|
13050
13045
|
module = {
|
|
13051
13046
|
exports: {},
|
|
@@ -13070,6 +13065,7 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13070
13065
|
children: /* @__PURE__ */ jsx(Frame, {
|
|
13071
13066
|
...frame,
|
|
13072
13067
|
children: (container) => /* @__PURE__ */ jsx(Error$1.Boundary, {
|
|
13068
|
+
resetKeys: [effectiveCode],
|
|
13073
13069
|
onError: (e) => setError(e.message),
|
|
13074
13070
|
children: renderProvider(/* @__PURE__ */ jsx(Error$1.Guard, {
|
|
13075
13071
|
onError: (e) => setError(e.message),
|
|
@@ -13088,6 +13084,7 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13088
13084
|
containerType: "inline-size"
|
|
13089
13085
|
},
|
|
13090
13086
|
children: /* @__PURE__ */ jsx(Error$1.Boundary, {
|
|
13087
|
+
resetKeys: [effectiveCode],
|
|
13091
13088
|
onError: (e) => setError(e.message),
|
|
13092
13089
|
children: renderProvider(/* @__PURE__ */ jsx(Error$1.Guard, {
|
|
13093
13090
|
onError: (e) => setError(e.message),
|
|
@@ -13102,12 +13099,23 @@ const Client = ({ code: _code = "", className, showError, props = {}, modules =
|
|
|
13102
13099
|
const Preview = ({ code, props = {}, modules = {}, dynamicTailwind = false, provider, ...restProps }) => {
|
|
13103
13100
|
const [runtimeError, setRuntimeError] = useState(null);
|
|
13104
13101
|
const [dynamicCSS, setDynamicCSS] = useState("");
|
|
13102
|
+
const [prevCode, setPrevCode] = useState(code);
|
|
13103
|
+
if (code !== prevCode) {
|
|
13104
|
+
setPrevCode(code);
|
|
13105
|
+
setRuntimeError(null);
|
|
13106
|
+
}
|
|
13105
13107
|
const renderProvider = (component) => {
|
|
13106
13108
|
return provider ? provider(component) : component;
|
|
13107
13109
|
};
|
|
13108
13110
|
useEffect(() => {
|
|
13109
13111
|
if (!code || !dynamicTailwind) return;
|
|
13110
|
-
|
|
13112
|
+
let cancelled = false;
|
|
13113
|
+
generateTailwindCSS(code).then((css) => {
|
|
13114
|
+
if (!cancelled) setDynamicCSS(css);
|
|
13115
|
+
});
|
|
13116
|
+
return () => {
|
|
13117
|
+
cancelled = true;
|
|
13118
|
+
};
|
|
13111
13119
|
}, [code, dynamicTailwind]);
|
|
13112
13120
|
if (runtimeError) return /* @__PURE__ */ jsx(Error$1, {
|
|
13113
13121
|
title: "Runtime Error",
|
|
@@ -13116,10 +13124,18 @@ const Preview = ({ code, props = {}, modules = {}, dynamicTailwind = false, prov
|
|
|
13116
13124
|
onReset: () => setRuntimeError(null)
|
|
13117
13125
|
});
|
|
13118
13126
|
if (code) {
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13127
|
+
let module;
|
|
13128
|
+
try {
|
|
13129
|
+
module = compile(code, {
|
|
13130
|
+
...baseModules,
|
|
13131
|
+
...modules
|
|
13132
|
+
});
|
|
13133
|
+
} catch (e) {
|
|
13134
|
+
module = {
|
|
13135
|
+
exports: {},
|
|
13136
|
+
error: e instanceof Error ? e.message : "Module transformation error"
|
|
13137
|
+
};
|
|
13138
|
+
}
|
|
13123
13139
|
if (module.error) return /* @__PURE__ */ jsx(Error$1, {
|
|
13124
13140
|
title: "Compile Error",
|
|
13125
13141
|
message: module.error,
|
|
@@ -13131,13 +13147,14 @@ const Preview = ({ code, props = {}, modules = {}, dynamicTailwind = false, prov
|
|
|
13131
13147
|
className: "mx-5 mt-25"
|
|
13132
13148
|
});
|
|
13133
13149
|
return /* @__PURE__ */ jsx(Error$1.Boundary, {
|
|
13150
|
+
resetKeys: [code],
|
|
13134
13151
|
fallback: (message) => /* @__PURE__ */ jsx(Error$1, {
|
|
13135
13152
|
title: "Rendering Error",
|
|
13136
13153
|
message
|
|
13137
13154
|
}),
|
|
13138
13155
|
children: renderProvider(/* @__PURE__ */ jsxs(Error$1.Guard, {
|
|
13139
13156
|
onError: (e) => setRuntimeError(e.message),
|
|
13140
|
-
children: [/* @__PURE__ */ jsx(Component, { ...props }), dynamicCSS && /* @__PURE__ */ jsx("style", { children: dynamicCSS })]
|
|
13157
|
+
children: [/* @__PURE__ */ jsx(Component, { ...props }), dynamicTailwind && dynamicCSS && /* @__PURE__ */ jsx("style", { children: dynamicCSS })]
|
|
13141
13158
|
}))
|
|
13142
13159
|
});
|
|
13143
13160
|
}
|