@ark-ui/solid
Version:
A collection of unstyled, accessible UI components for Solid, utilizing state machines for seamless interaction.
92 lines (87 loc) • 3 kB
JSX
import {
composeRefs
} from "./PT2CJE3O.jsx";
import {
EnvironmentProvider
} from "./E2L62MKC.jsx";
// src/components/frame/frame.tsx
import { Show, createEffect as createEffect2, createMemo, createSignal, onCleanup as onCleanup2, splitProps } from "solid-js";
import { Portal } from "solid-js/web";
// src/components/frame/frame-content.tsx
import { createEffect, onCleanup } from "solid-js";
var FrameContent = (props) => {
const { onMount, onUnmount, children } = props;
createEffect(() => {
onMount?.();
onCleanup(() => {
onUnmount?.();
});
});
return children;
};
// src/components/frame/frame.tsx
var resetStyle = "<style>*,*::before,*::after { margin: 0; padding: 0; box-sizing: border-box; }</style>";
var initialSrcDoc = `<html><head>${resetStyle}</head><body><div class="frame-root"></div></body></html>`;
function getMountNode(frame) {
const doc = frame.contentWindow?.document;
if (!doc) return null;
return doc.body.querySelector(".frame-root") || doc.body;
}
var Frame = (props) => {
const [frameProps, localProps] = splitProps(props, ["children", "head", "onMount", "onUnmount", "srcdoc"]);
const srcdoc = createMemo(() => frameProps.srcdoc ?? initialSrcDoc);
const [frameRef, setFrameRef] = createSignal(null);
const [mountNode, setMountNode] = createSignal(null);
createEffect2(() => {
const frame = frameRef();
if (!frame) return;
const doc = frame.contentWindow?.document;
if (!doc) return;
doc.open();
doc.write(srcdoc());
doc.close();
setMountNode(getMountNode(frame));
});
createEffect2(() => {
const frame = frameRef();
if (!frame || !frame.contentDocument) return;
const win = frame.contentWindow;
if (!win) return;
const node = getMountNode(frame);
if (!node) return;
const exec = () => {
const rootEl = frame.contentDocument?.documentElement;
if (!rootEl) return;
frame.style.setProperty("--width", `${node.scrollWidth}px`);
frame.style.setProperty("--height", `${node.scrollHeight}px`);
};
const resizeObserver = new win.ResizeObserver(exec);
exec();
if (frame.contentDocument) {
resizeObserver.observe(node);
}
onCleanup2(() => {
resizeObserver.disconnect();
});
});
return <EnvironmentProvider value={() => frameRef()?.contentDocument ?? document}>
<iframe {...localProps} ref={composeRefs(setFrameRef, localProps.ref)}>
<Show when={mountNode()}>
{(node) => <Portal mount={node()}>
<FrameContent onMount={frameProps.onMount} onUnmount={frameProps.onUnmount}>
{frameProps.children}
</FrameContent>
</Portal>}
</Show>
<Show when={mountNode()}>
{
/* biome-ignore lint/style/noNonNullAssertion: <explanation> */
}
<Portal mount={frameRef().contentDocument.head}>{frameProps.head}</Portal>
</Show>
</iframe>
</EnvironmentProvider>;
};
export {
Frame
};