Files
shadcn-ui/apps/v4/app/(create)/hooks/use-iframe-sync.tsx
2026-03-06 16:05:01 +04:00

70 lines
1.5 KiB
TypeScript

"use client"
import * as React from "react"
import type { DesignSystemSearchParams } from "@/app/(create)/lib/search-params"
type ParentToIframeMessage = {
type: "design-system-params"
data: DesignSystemSearchParams
}
export const isInIframe = () => {
if (typeof window === "undefined") {
return false
}
return window.self !== window.top
}
export function useIframeMessageListener<
Message extends ParentToIframeMessage,
MessageType extends Message["type"],
>(
messageType: MessageType,
onMessage: (data: Extract<Message, { type: MessageType }>["data"]) => void
) {
const onMessageRef = React.useRef(onMessage)
React.useEffect(() => {
onMessageRef.current = onMessage
}, [onMessage])
React.useEffect(() => {
if (!isInIframe()) {
return
}
const handleMessage = (event: MessageEvent) => {
if (event.data.type === messageType) {
onMessageRef.current(event.data.data)
}
}
window.addEventListener("message", handleMessage)
return () => {
window.removeEventListener("message", handleMessage)
}
}, [messageType])
}
export function sendToIframe<
Message extends ParentToIframeMessage,
MessageType extends Message["type"],
>(
iframe: HTMLIFrameElement | null,
messageType: MessageType,
data: Extract<Message, { type: MessageType }>["data"]
) {
if (!iframe?.contentWindow) {
return
}
iframe.contentWindow.postMessage(
{
type: messageType,
data,
},
"*"
)
}