UNPKG

@styleglide/theme-editor

Version:

Add the StyleGlide theme editor to any shadcn/ui app

629 lines (618 loc) 22.1 kB
'use strict'; // src/lib/origin.ts var STYLEGLIDE_ORIGIN = "https://www.styleglide.ai"; // src/lib/default-options.ts var defaultOptions = { origin: STYLEGLIDE_ORIGIN, cssColorFormat: "colorSpace", onChangeMode: () => { }, resolvedMode: "light", enabled: true }; // src/lib/hotkeys.ts var HOTKEYS = ["mod+z", "mod+shift+z", "t", "s", "e", "r", "g"]; var currentListeners = []; function initHotkeys({ origin }) { if (typeof window === "undefined") { return; } cleanupHotkeys(); function handleKeyDown(event) { if (isInputEvent(event)) { return; } const keyCombo = buildKeyCombo(event); if (HOTKEYS.includes(keyCombo)) { event.preventDefault(); const message = { action: "hotkey", payload: { keys: keyCombo } }; window.parent.postMessage(message, origin); } } window.addEventListener("keydown", handleKeyDown); currentListeners.push( () => window.removeEventListener("keydown", handleKeyDown) ); } function cleanupHotkeys() { currentListeners.forEach((cleanup) => cleanup()); currentListeners = []; } function buildKeyCombo(event) { const parts = []; if (event.ctrlKey || event.metaKey) { parts.push("mod"); } if (event.shiftKey) { parts.push("shift"); } const key = event.key.toLowerCase(); if (key !== "control" && key !== "meta" && key !== "shift") { parts.push(key); } return parts.join("+"); } function isInputEvent(event) { const element = event.target; return element.matches("input, select, textarea, [contenteditable]"); } // src/lib/logo.ts function createLogo(mode) { const container = document.createElement("div"); container.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" viewBox="0 0 922.18 197.54" shape-rendering="geometricPrecision" width="120" height="24" > <path d="m65.46 79.59-9.38 5.45-24.8-58.47c2.74-2.56 5.63-4.97 8.64-7.21l25.54 60.23Z" fill="#419ef9" /> <path d="m75.34 68.31-10.75 1.44-.53-63.53c3.49-1.31 7.07-2.43 10.73-3.34l.55 65.43Z" fill="#21b2f9" /> <path d="M113.3 1.01 88.77 61.66l-10.48-2.79L102.1 0c3.79.12 7.53.46 11.2 1.01Z" fill="#00c7f9" /> <path d="m149.62 14.01-45.88 46.65-8.62-6.58 44.54-45.3c3.43 1.56 6.75 3.31 9.96 5.23Z" fill="#2ab3f7" /> <path d="m178.18 39.91-60.23 25.55-5.44-9.38 58.47-24.8c2.56 2.74 4.96 5.61 7.21 8.63h-.01Z" fill="#52a0f5" /> <path d="m194.67 74.78-65.44.55-1.44-10.75 63.54-.53c1.31 3.49 2.43 7.07 3.34 10.73Z" fill="#7b8cf3" /> <path d="M197.54 102.1c-.12 3.8-.46 7.53-1.01 11.21l-60.65-24.53 2.78-10.49 58.88 23.81Z" fill="#a579f0" /> <path d="M188.77 139.66a98.137 98.137 0 0 1-5.24 9.95l-46.65-45.88 6.59-8.62 45.3 44.54Z" fill="#ce65ee" /> <path d="M166.26 170.97a99.38 99.38 0 0 1-8.64 7.21l-25.54-60.23 9.38-5.45 24.79 58.47h.01Z" fill="#f851ec" /> <path d="M133.49 191.32a97.424 97.424 0 0 1-10.73 3.34l-.55-65.43 10.75-1.45.53 63.54Z" fill="#e754ef" /> <path d="m119.25 138.66-23.81 58.88c-3.8-.12-7.53-.46-11.21-1.01l24.53-60.65 10.48 2.78Z" fill="#d657f1" /> <path d="m102.42 143.46-44.54 45.3c-3.42-1.55-6.75-3.3-9.94-5.23l45.87-46.65 8.62 6.59Z" fill="#c35bf4" /> <path d="m85.04 141.46-58.47 24.8c-2.56-2.74-4.96-5.62-7.21-8.64l60.23-25.55 5.44 9.38Z" fill="#b25ef6" /> <path d="m69.75 132.96-63.54.53a97.424 97.424 0 0 1-3.34-10.73l65.44-.55 1.44 10.75Z" fill="#a161f9" /> <path d="m61.66 108.76-2.78 10.49L0 95.44c.12-3.8.46-7.53 1.01-11.21l60.65 24.53Z" fill="#8175f9" /> <path d="m60.66 93.8-6.59 8.62-45.3-44.54c1.56-3.43 3.31-6.75 5.23-9.95L60.66 93.8Z" fill="#6289f9" /> <path d="M282.6 156.35c-9.78 0-17.97-1.51-24.57-4.54-6.6-3.02-11.57-7.26-14.89-12.7s-5.04-11.64-5.14-18.6h20.41c.1 4.13 1.03 7.71 2.8 10.73 1.76 3.02 4.46 5.39 8.09 7.11s8.32 2.57 14.06 2.57c6.85 0 12.35-1.28 16.48-3.85 4.13-2.57 6.2-6.37 6.2-11.41 0-2.92-.45-5.37-1.36-7.33-.91-1.97-2.42-3.6-4.54-4.91s-4.91-2.42-8.39-3.33c-3.48-.91-7.84-1.81-13.08-2.72-6.25-1.01-11.77-2.34-16.56-4.01s-8.79-3.7-12.02-6.12c-3.23-2.42-5.65-5.37-7.26-8.84-1.61-3.48-2.42-7.64-2.42-12.47 0-6.65 1.69-12.4 5.06-17.24s8.19-8.59 14.44-11.26 13.71-4.01 22.38-4.01 15.9 1.36 22 4.08c6.1 2.72 10.81 6.53 14.14 11.41 3.33 4.89 4.99 10.56 4.99 17.01h-20.11c-.2-3.93-1.26-7.18-3.17-9.75-1.92-2.57-4.46-4.46-7.64-5.67-3.17-1.21-6.83-1.81-10.96-1.81s-7.89.6-10.96 1.81c-3.08 1.21-5.42 2.9-7.03 5.06-1.61 2.17-2.42 4.76-2.42 7.79 0 3.73.93 6.58 2.8 8.54 1.86 1.96 4.89 3.5 9.07 4.61s9.6 2.22 16.25 3.33c4.74.81 9.35 1.81 13.83 3.02s8.52 3 12.1 5.37 6.43 5.59 8.54 9.68c2.12 4.08 3.17 9.35 3.17 15.8s-1.66 12.15-4.99 17.08c-3.33 4.94-8.27 8.77-14.82 11.49s-14.72 4.08-24.49 4.08h.01ZM362.88 154.98c-4.94 0-8.79-.73-11.57-2.19-2.77-1.46-4.71-3.55-5.82-6.27-1.11-2.72-1.66-6-1.66-9.83V89.82h-14.82V74.55h14.82V51.87l18.75-1.97v24.64h17.08v15.27h-17.08v43.39c0 2.52.55 4.21 1.66 5.06 1.11.86 2.82 1.29 5.14 1.29h10.28v15.42h-16.78ZM386.61 180.23v-15.57h8.92c2.42 0 4.43-.3 6.05-.91 1.61-.6 2.97-1.56 4.08-2.87 1.11-1.31 2.02-2.97 2.72-4.99l4.38-11.34v8.47l-32.81-78.47h20.71l16.48 45.96 3.02 9.07h.76l2.72-9.07 15.57-45.96h20.11l-32.51 85.72c-1.81 5.14-4.06 9.17-6.73 12.1-2.67 2.92-5.75 4.96-9.22 6.12-3.48 1.16-7.44 1.74-11.87 1.74h-12.4.02ZM463.87 154.98V44.76h18.9v110.22h-18.9ZM532.36 156.35c-8.27 0-15.32-1.71-21.17-5.14s-10.36-8.21-13.53-14.36c-3.18-6.15-4.76-13.35-4.76-21.62s1.56-16 4.69-22.3c3.12-6.3 7.61-11.19 13.46-14.67 5.84-3.48 12.7-5.22 20.56-5.22 9.17 0 16.68 2.02 22.53 6.05 5.84 4.03 10.05 9.48 12.62 16.33 2.57 6.86 3.4 14.67 2.49 23.43H511.5c0 4.84.88 8.97 2.65 12.4 1.76 3.43 4.21 6.05 7.33 7.86s6.75 2.72 10.88 2.72c4.84 0 8.92-1.08 12.25-3.25s5.44-5.07 6.35-8.69h17.99c-.71 5.24-2.72 9.85-6.05 13.83-3.33 3.98-7.61 7.08-12.85 9.3s-11.14 3.33-17.69 3.33Zm-20.86-47.78-1.66-2.42h42.79l-1.81 2.42c.2-4.84-.53-8.79-2.19-11.87-1.66-3.07-3.98-5.37-6.96-6.88-2.97-1.51-6.33-2.27-10.05-2.27-4.03 0-7.54.86-10.51 2.57-2.97 1.72-5.29 4.13-6.95 7.26-1.66 3.13-2.55 6.86-2.65 11.19ZM629.27 156.35c-8.47 0-16.05-1.34-22.75-4.01s-12.4-6.5-17.08-11.49-8.27-10.96-10.73-17.92c-2.47-6.96-3.7-14.67-3.7-23.13s1.33-16.76 4.01-23.66c2.67-6.9 6.43-12.8 11.26-17.69 4.84-4.89 10.63-8.62 17.39-11.19 6.75-2.57 14.26-3.86 22.53-3.86 9.57 0 17.99 1.59 25.25 4.76s13.08 7.61 17.46 13.3c4.38 5.7 7.03 12.37 7.94 20.03h-20.56c-.91-4.43-2.75-8.19-5.52-11.26s-6.25-5.44-10.43-7.11c-4.18-1.66-8.9-2.49-14.14-2.49-6.96 0-13.05 1.49-18.29 4.46-5.24 2.97-9.27 7.38-12.09 13.23s-4.23 13-4.23 21.47c0 6.35.78 12.02 2.34 17.01s3.86 9.15 6.88 12.47 6.63 5.87 10.81 7.64c4.18 1.76 8.84 2.65 13.98 2.65 6.75 0 12.6-1.23 17.54-3.7 4.94-2.47 8.77-6.05 11.49-10.73 2.72-4.69 4.08-10.25 4.08-16.71v-3.93l5.9 6.96H629.9V96.94h53.07v9.22c0 7.66-1.29 14.59-3.86 20.79-2.57 6.2-6.2 11.47-10.89 15.8s-10.33 7.69-16.93 10.05c-6.6 2.37-13.94 3.55-22 3.55h-.02ZM693.52 154.98V44.76h18.9v110.22h-18.9ZM727.54 63.21V44.77h18.9v18.44h-18.9Zm0 91.77V74.55h18.9v80.43h-18.9ZM788.92 156.35c-4.84 0-9.25-.88-13.23-2.65-3.98-1.76-7.41-4.41-10.28-7.94s-5.06-7.89-6.58-13.08c-1.51-5.19-2.27-11.16-2.27-17.92 0-9.17 1.33-16.86 4.01-23.06 2.67-6.2 6.45-10.86 11.34-13.99 4.89-3.12 10.56-4.69 17.01-4.69 4.43 0 8.39.68 11.87 2.04s6.48 3.25 9 5.67 4.43 5.29 5.75 8.62h1.06v-44.6h18.9l-.15 110.22h-18.14l-.6-14.97h-1.06c-1.92 4.94-5.19 8.9-9.83 11.87s-10.23 4.46-16.78 4.46l-.02.02Zm7.11-15.42c4.54 0 8.29-1.06 11.26-3.17 2.97-2.12 5.22-4.86 6.73-8.24s2.27-6.93 2.27-10.66v-8.32c0-2.92-.43-5.69-1.29-8.32-.86-2.62-2.12-4.96-3.78-7.03-1.66-2.06-3.78-3.7-6.35-4.91s-5.52-1.81-8.84-1.81c-4.03 0-7.56.96-10.58 2.87-3.02 1.92-5.39 4.81-7.11 8.69-1.71 3.88-2.57 8.79-2.57 14.74s.86 10.58 2.57 14.51 4.08 6.86 7.11 8.77c3.02 1.92 6.55 2.87 10.58 2.87ZM884.93 156.35c-8.27 0-15.32-1.71-21.17-5.14-5.85-3.43-10.36-8.21-13.53-14.36-3.17-6.15-4.76-13.35-4.76-21.62s1.56-16 4.69-22.3c3.12-6.3 7.61-11.19 13.46-14.67 5.84-3.48 12.7-5.22 20.56-5.22 9.17 0 16.68 2.02 22.53 6.05 5.84 4.03 10.05 9.48 12.62 16.33 2.57 6.86 3.4 14.67 2.49 23.43h-57.75c0 4.84.88 8.97 2.65 12.4 1.76 3.43 4.21 6.05 7.33 7.86s6.75 2.72 10.89 2.72c4.84 0 8.92-1.08 12.25-3.25s5.44-5.07 6.35-8.69h17.99c-.71 5.24-2.72 9.85-6.05 13.83-3.33 3.98-7.61 7.08-12.85 9.3s-11.14 3.33-17.69 3.33Zm-20.86-47.78-1.66-2.42h42.79l-1.81 2.42c.2-4.84-.53-8.79-2.19-11.87-1.66-3.07-3.98-5.37-6.96-6.88-2.97-1.51-6.33-2.27-10.05-2.27-4.03 0-7.54.86-10.51 2.57-2.97 1.72-5.29 4.13-6.95 7.26-1.66 3.13-2.55 6.86-2.65 11.19h-.01Z" fill="${mode === "dark" ? "#fff" : "#000"}" /> </svg> `; return container.firstElementChild; } // src/lib/utils.ts function isDesktop() { return typeof window !== "undefined" && window.innerWidth >= 1024; } function cleanupElement(element) { if (element) { element.remove(); } element = null; } function setStyles(element, ...styles) { Object.assign(element.style, ...styles); } // src/lib/buttons.ts function createOpenButton() { const button = document.createElement("button"); setStyles(button, style.base, style.hidden, style.open); setTimeout(() => { setStyles(button, style.visible); }, 2e3); return button; } function createCloseButton(resolvedMode) { const button = document.createElement("button"); button.innerHTML = "\u2715"; setStyles( button, style.base, style.hidden, style[resolvedMode], isDesktop() ? style.closeDesktop : style.close ); return button; } function updateOpenButton(button, resolvedMode) { if (!button) return; setStyles(button, style[resolvedMode]); updateOpenButtonLogo(button, resolvedMode); } function updateCloseButton(button, resolvedMode) { if (!button) return; setStyles(button, style[resolvedMode]); } function updateOpenButtonLogo(button, resolvedMode) { const logo = createLogo(resolvedMode); if (logo) { button.innerHTML = ""; button.appendChild(logo); } } function showOpenButton(button) { if (!button) return; setTimeout(() => { setStyles(button, style.visible, style.open); }, 400); } function hideOpenButton(button) { if (!button) return; setStyles(button, style.hidden); } function showCloseButton(button) { if (!button) return; setStyles( button, style.visible, isDesktop() ? style.closeDesktop : style.close ); } function hideCloseButton(button) { if (!button) return; setStyles(button, style.hidden); } function onClick(button, handler) { button.addEventListener("click", handler); } function findCustomOpenButton() { return document.querySelector("[data-theme-editor-open]"); } var style = { base: { position: "fixed", bottom: "1.825rem", left: "50%", padding: "0.5rem 0.875rem", borderWidth: "1px", borderStyle: "solid", borderRadius: "1.5rem", cursor: "pointer", zIndex: "2147483647", boxShadow: "0 4px 20px rgba(0,0,0,0.15)", userSelect: "none" }, light: { backgroundColor: "#fff", borderColor: "#E4E4E7" }, dark: { backgroundColor: "#17191A", borderColor: "#27272A" }, hidden: { opacity: "0", pointerEvents: "none", transition: "auto" }, visible: { opacity: "1", pointerEvents: "auto", transition: "opacity 0.3s ease" }, open: { transform: "translateX(-50%)" }, close: { transform: "translateX(-50%) translateY(-6.25rem)" }, closeDesktop: { transform: "translateX(calc(-50% + 18rem))" } }; // src/lib/iframe.ts var currentIframe = null; var currentCloseButton = null; var currentOpenButton = null; var currentResizeListener = null; var initialOverflow = null; var isCustomOpenButton = false; var open = false; function initIframe({ origin, cssColorFormat, resolvedMode }) { const isClient = typeof window !== "undefined"; const isEmbedded = isClient && window.location.search.includes("_embedded=1"); if (!isClient || isEmbedded) { return; } cleanupIframe(); const iframe = document.createElement("iframe"); const currentUrl = new URL(window.location.href); currentUrl.searchParams.set("_embedded", "1"); const iframeUrl = new URL(`${origin}/themes`); iframeUrl.searchParams.set("url", currentUrl.toString()); iframeUrl.searchParams.set("format", cssColorFormat); iframe.src = iframeUrl.toString(); iframe.allow = "clipboard-write"; iframe.addEventListener( "load", () => sendInitialMode(iframe, origin, resolvedMode) ); setStyles(iframe, style2.base, style2.closed); document.body.appendChild(iframe); const customOpenButton = findCustomOpenButton(); isCustomOpenButton = !!customOpenButton; const openButton = customOpenButton || createOpenButton(); onClick(openButton, () => openIframe(origin)); if (!isCustomOpenButton) { updateOpenButton(openButton, resolvedMode); document.body.appendChild(openButton); } const closeButton = createCloseButton(resolvedMode); onClick(closeButton, () => closeIframe(origin)); document.body.appendChild(closeButton); currentIframe = iframe; currentOpenButton = openButton; currentCloseButton = closeButton; hideCloseButton(closeButton); initResizeListener(); } function updateIframe({ resolvedMode }) { if (!isCustomOpenButton) { updateOpenButton(currentOpenButton, resolvedMode); } updateCloseButton(currentCloseButton, resolvedMode); } function cleanupIframe() { cleanupElement(currentIframe); cleanupElement(currentCloseButton); cleanupResizeListener(); restoreOverflow(); if (!isCustomOpenButton) { cleanupElement(currentOpenButton); } isCustomOpenButton = false; open = false; } function openIframe(origin) { if (!currentIframe) return; initialOverflow = document.body.style.overflow || null; setStyles(currentIframe, style2.open); setStyles(document.body, { overflow: "hidden" }); showCloseButton(currentCloseButton); if (!isCustomOpenButton) { hideOpenButton(currentOpenButton); } postMessage(currentIframe, origin, { action: "iframeEditorOpened" }); open = true; } function closeIframe(origin) { if (!currentIframe) return; postMessage(currentIframe, origin, { action: "iframeEditorClosed" }); if (!isCustomOpenButton) { showOpenButton(currentOpenButton); } hideCloseButton(currentCloseButton); open = false; const timeout = isDesktop() ? 350 : 0; setTimeout(() => { if (!currentIframe) return; setStyles(currentIframe, style2.closed); restoreOverflow(); }, timeout); } function sendInitialMode(iframe, origin, resolvedMode) { const message = { action: "modeToggled", payload: resolvedMode }; setTimeout(() => postMessage(iframe, origin, message), 100); } function postMessage(iframe, origin, message) { iframe.contentWindow?.postMessage(message, origin); } function initResizeListener() { currentResizeListener = () => { if (open) { showCloseButton(currentCloseButton); } }; window.addEventListener("resize", currentResizeListener); } function cleanupResizeListener() { if (!currentResizeListener) return; window.removeEventListener("resize", currentResizeListener); currentResizeListener = null; } function restoreOverflow() { if (initialOverflow) { setStyles(document.body, { overflow: initialOverflow }); } else { document.body.style.removeProperty("overflow"); } } var style2 = { base: { position: "fixed", top: "0", left: "0", width: "100vw", height: "100vh", border: "none" }, closed: { zIndex: "-1", opacity: "0", pointerEvents: "none" }, open: { zIndex: "2147483646", opacity: "1", pointerEvents: "auto" } }; // src/lib/theme-listener.ts var currentStylesheet = null; var currentResolvedMode = null; var currentOnChangeMode = null; var currentMessageListener = null; function initThemeListener({ origin, resolvedMode, onChangeMode }) { if (typeof window === "undefined") { return () => { }; } currentResolvedMode = resolvedMode; currentOnChangeMode = onChangeMode; cleanupThemeListener(); const themeListener = (event) => { if (event.origin !== origin) { return; } if (event.data.action === "styleKitUpdated") { const { css, displayFontUrl, textFontUrl, mode } = event.data?.payload || {}; loadThemeCss(css); loadFontLink(displayFontUrl); loadFontLink(textFontUrl); handleFontStyles(); if (mode !== currentResolvedMode && currentOnChangeMode) { currentOnChangeMode(mode); const root = document.documentElement; root.style.colorScheme = mode; } } }; currentMessageListener = themeListener; window.addEventListener("message", themeListener); } function updateThemeListener({ resolvedMode, onChangeMode }) { currentResolvedMode = resolvedMode; currentOnChangeMode = onChangeMode; } function cleanupThemeListener() { if (!currentMessageListener) return; window.removeEventListener("message", currentMessageListener); currentMessageListener = null; } function loadFontLink(url) { if (!url || isFontLinkLoaded(url)) return; const link = document.createElement("link"); link.href = url; link.rel = "stylesheet"; document.head.appendChild(link); } function isFontLinkLoaded(url) { return Array.from(document.head.getElementsByTagName("link")).some( (link) => link.href === url ); } function loadThemeCss(css) { if (!css) return; if (!currentStylesheet) { currentStylesheet = document.createElement("style"); currentStylesheet.id = "styleglide-theme"; document.head.appendChild(currentStylesheet); } currentStylesheet.textContent = css; } function hasClassNames(classNames) { return document.getElementsByClassName(classNames).length > 0; } function handleFontStyles() { if (!hasClassNames("font-text")) { const body = document.body; body.style.setProperty("font-family", "var(--text-family)", "important"); body.style.setProperty("font-weight", "var(--text-weight)", "important"); } if (!hasClassNames("font-display")) { const headings = document.querySelectorAll( "h1, h2, h3, h4, h5, h6" ); headings.forEach((heading) => { heading.style.setProperty( "font-family", "var(--display-family)", "important" ); heading.style.setProperty( "font-weight", "var(--display-weight)", "important" ); }); } } // src/lib/theme-editor.ts var prevProps = null; var isInitialized = false; var warnedOptions = /* @__PURE__ */ new Set(); function themeEditor(options = {}) { const props = setProps(options); const { enabled } = props; if (!enabled && prevProps?.enabled && isInitialized) { cleanupAll(); isInitialized = false; } if (!enabled) { return save(props); } if (!prevProps || !isInitialized) { initAll(props); isInitialized = true; return save(props); } function updated(...keys) { return keys.some((key) => prevProps?.[key] !== props[key]); } if (updated("origin")) { initAll(props); return save(props); } if (updated("resolvedMode", "onChangeMode")) { updateThemeListener(props); } if (updated("resolvedMode")) { updateIframe(props); } if (updated("cssColorFormat")) { cleanupIframe(); initIframe(props); } return save(props); } function initAll(props) { initHotkeys(props); initIframe(props); initThemeListener(props); } function cleanupAll() { cleanupHotkeys(); cleanupIframe(); cleanupThemeListener(); } function save(props) { prevProps = props; } function setProps(options = {}) { const validatedOptions = validateOptions(options); return { ...defaultOptions, ...validatedOptions }; } function validateOptions(options) { const validatedOptions = {}; for (const [key, value] of Object.entries(options)) { switch (key) { case "origin": if (typeof value === "string") { try { new URL(value); validatedOptions.origin = value; } catch { warnInvalidOption({ key, expected: "valid string URL", received: value }); } } else { warnInvalidOption({ key, expected: "valid string URL", received: value }); } break; case "cssColorFormat": if (value === "channels" || value === "colorSpace") { validatedOptions.cssColorFormat = value; } else { warnInvalidOption({ key, expected: "'channels' or 'colorSpace'", received: value }); } break; case "onChangeMode": if (typeof value === "function") { validatedOptions.onChangeMode = value; } else { warnInvalidOption({ key, expected: "function", received: value }); } break; case "resolvedMode": if (value === "light" || value === "dark") { validatedOptions.resolvedMode = value; } else { warnInvalidOption({ key, expected: "'light' or 'dark'", received: value }); } break; case "enabled": if (typeof value === "boolean") { validatedOptions.enabled = value; } else { warnInvalidOption({ key, expected: "boolean", received: value }); } break; default: console.warn( `[@styleglide/theme-editor]: Unknown option '${key}' provided. Ignoring.` ); } } return validatedOptions; } function warnInvalidOption({ key, expected, received }) { const isClient = typeof window !== "undefined"; const isEmbedded = isClient && window.location.search.includes("_embedded=1"); if (isEmbedded) { return; } if (!warnedOptions.has(key)) { warnedOptions.add(key); console.warn( `[@styleglide/theme-editor]: Invalid option '${key}': expected ${expected}, got ${typeof received === "string" ? `'${received}'` : typeof received}. Reverting to default.` ); } } exports.themeEditor = themeEditor;