UNPKG

@formkit/themes

Version:
298 lines (296 loc) 11.1 kB
import { FORMKIT_VERSION } from '@formkit/core'; // packages/themes/src/index.ts function generateClasses(classes) { const classesBySectionKey = {}; Object.keys(classes).forEach((type) => { Object.keys(classes[type]).forEach((sectionKey) => { if (!classesBySectionKey[sectionKey]) { classesBySectionKey[sectionKey] = { [type]: classes[type][sectionKey] }; } else { classesBySectionKey[sectionKey][type] = classes[type][sectionKey]; } }); }); Object.keys(classesBySectionKey).forEach((sectionKey) => { const classesObject = classesBySectionKey[sectionKey]; classesBySectionKey[sectionKey] = function(node, sectionKey2) { return addClassesBySection(node, sectionKey2, classesObject); }; }); return classesBySectionKey; } function addClassesBySection(node, _sectionKey, classesByType) { const type = node.props.type; const family = node.props.family; let classList = ""; if (classesByType.global) { classList += classesByType.global + " "; } if (classesByType[`family:${family}`]) { classList += classesByType[`family:${family}`] + " "; } if (classesByType[type]) { classList += classesByType[type]; } const listParts = classList.split("$reset"); if (listParts.length > 1) { return `$reset ${listParts[listParts.length - 1].trim()}`; } return listParts[0].trim(); } var documentStyles = void 0; var documentThemeLinkTag = null; var themeDidLoad; var themeHasLoaded = false; var themeWasRequested = false; var themeLoaded = /* @__PURE__ */ new Promise((res) => { themeDidLoad = () => { themeHasLoaded = true; res(); }; }); var isClient = typeof window !== "undefined" && typeof fetch !== "undefined"; documentStyles = isClient ? /* @__PURE__ */ getComputedStyle(document.documentElement) : void 0; var iconRegistry = {}; var iconRequests = {}; var iconPattern = /^[a-zA-Z-]+(?:-icon|Icon)$/; var observedIconProps = /* @__PURE__ */ new WeakMap(); function normalizeIconProp(sectionKey) { return sectionKey.replace( /-([a-zA-Z])/g, (_, char) => char.toUpperCase() ); } function createThemePlugin(theme, icons, iconLoaderUrl, iconLoader) { if (icons) { Object.assign(iconRegistry, icons); } if (isClient && !themeWasRequested && documentStyles?.getPropertyValue("--formkit-theme")) { themeDidLoad(); themeWasRequested = true; } else if (theme && !themeWasRequested && isClient) { loadTheme(theme); } else if (!themeWasRequested && isClient) { themeDidLoad(); } const themePlugin = function themePlugin2(node) { node.addProps(["iconLoader", "iconLoaderUrl"]); node.props.iconHandler = createIconHandler( node.props?.iconLoader ? node.props.iconLoader : iconLoader, node.props?.iconLoaderUrl ? node.props.iconLoaderUrl : iconLoaderUrl ); loadIconPropIcons(node, node.props.iconHandler); node.on("added-props", ({ payload }) => { if (!node.props.iconHandler) return; const props = Array.isArray(payload) ? payload : Object.keys(payload ?? {}); props.forEach((prop) => { if (typeof prop === "string" && iconPattern.test(prop)) { observeIconProp(node, node.props.iconHandler, prop); } }); }); node.on("prop", ({ payload }) => { if (!node.props.iconHandler || typeof payload?.prop !== "string") return; if (iconPattern.test(payload.prop)) { observeIconProp(node, node.props.iconHandler, payload.prop); } }); node.on("created", () => { if (node?.context?.handlers) { const iconClick = (sectionKey) => { const clickHandlerProp = `on${sectionKey.charAt(0).toUpperCase()}${sectionKey.slice(1)}IconClick`; const handlerFunction = node.props[clickHandlerProp]; if (handlerFunction && typeof handlerFunction === "function") { return (e) => { return handlerFunction(node, e); }; } return void 0; }; node.context.handlers.iconClick = iconClick; node.context.handlers.iconKeydown = (sectionKey) => { if (!iconClick(sectionKey)) return void 0; return (e) => { if (isKeyboardClick(e)) { e.preventDefault(); if (e.currentTarget instanceof HTMLElement) { e.currentTarget.click(); } } }; }; } if (node?.context?.fns) { node.context.fns.iconRole = (sectionKey) => { const clickHandlerProp = `on${sectionKey.charAt(0).toUpperCase()}${sectionKey.slice(1)}IconClick`; return typeof node.props[clickHandlerProp] === "function" ? "button" : null; }; } }); }; themePlugin.iconHandler = createIconHandler(iconLoader, iconLoaderUrl); return themePlugin; } function isKeyboardClick(e) { return e.key === "Enter" || e.key === " " || e.key === "Spacebar"; } function loadTheme(theme) { if (!theme || !isClient || typeof getComputedStyle !== "function") { return; } themeWasRequested = true; documentThemeLinkTag = document.getElementById("formkit-theme"); if (theme && // if we have a window object isClient && // we don't have an existing theme OR the theme being set up is different (!documentStyles?.getPropertyValue("--formkit-theme") && !documentThemeLinkTag || documentThemeLinkTag?.getAttribute("data-theme") && documentThemeLinkTag?.getAttribute("data-theme") !== theme)) { const formkitVersion = FORMKIT_VERSION.startsWith("__") ? "latest" : FORMKIT_VERSION; const themeUrl = `https://cdn.jsdelivr.net/npm/@formkit/themes@${formkitVersion}/dist/${theme}/theme.css`; const link = document.createElement("link"); link.type = "text/css"; link.rel = "stylesheet"; link.id = "formkit-theme"; link.setAttribute("data-theme", theme); link.onload = () => { documentStyles = getComputedStyle(document.documentElement); themeDidLoad(); }; document.head.appendChild(link); link.href = themeUrl; if (documentThemeLinkTag) { documentThemeLinkTag.remove(); } } } function createIconHandler(iconLoader, iconLoaderUrl) { return (iconName) => { if (typeof iconName !== "string") return; if (iconName.startsWith("<svg")) { return iconName; } const isDefault = iconName.startsWith("default:"); iconName = isDefault ? iconName.split(":")[1] : iconName; const defaultRegistryKey = `default:${iconName}`; const iconWasAlreadyLoaded = iconName in iconRegistry || isDefault && defaultRegistryKey in iconRegistry; const iconRequestKey = isDefault && typeof iconLoader !== "function" ? defaultRegistryKey : iconName; let loadedIcon = void 0; if (iconWasAlreadyLoaded) { return iconRegistry[iconName] ?? iconRegistry[defaultRegistryKey]; } else if (!iconRequests[iconRequestKey]) { loadedIcon = getIconFromStylesheet(iconName); loadedIcon = isClient && typeof loadedIcon === "undefined" ? Promise.resolve(loadedIcon) : loadedIcon; if (loadedIcon instanceof Promise) { iconRequests[iconRequestKey] = loadedIcon.then((iconValue) => { if (!iconValue && typeof iconName === "string") { if (typeof iconLoader === "function") { return loadedIcon = iconLoader(iconName); } else if (!isDefault) { return loadedIcon = getRemoteIcon(iconName, iconLoaderUrl); } } return iconValue; }).then((finalIcon) => { if (typeof iconName === "string") { iconRegistry[isDefault && typeof iconLoader !== "function" ? defaultRegistryKey : iconName] = finalIcon; } return finalIcon; }); } else if (typeof loadedIcon === "string") { iconRegistry[isDefault ? defaultRegistryKey : iconName] = loadedIcon; return loadedIcon; } } return iconRequests[iconRequestKey]; }; } function getIconFromStylesheet(iconName) { if (!isClient) return; if (themeHasLoaded) { return loadStylesheetIcon(iconName); } else { return themeLoaded.then(() => { return loadStylesheetIcon(iconName); }); } } function loadStylesheetIcon(iconName) { const cssVarIcon = documentStyles?.getPropertyValue(`--fk-icon-${iconName}`); if (cssVarIcon) { const icon = atob(cssVarIcon); if (icon.startsWith("<svg")) { iconRegistry[iconName] = icon; return icon; } } return void 0; } function getRemoteIcon(iconName, iconLoaderUrl) { const formkitVersion = FORMKIT_VERSION.startsWith("__") ? "latest" : FORMKIT_VERSION; const fetchUrl = typeof iconLoaderUrl === "function" ? iconLoaderUrl(iconName) : `https://cdn.jsdelivr.net/npm/@formkit/icons@${formkitVersion}/dist/icons/${iconName}.svg`; if (!isClient) return void 0; return fetch(`${fetchUrl}`).then(async (r) => { const icon = await r.text(); if (icon.startsWith("<svg")) { return icon; } return void 0; }).catch((e) => { console.error(e); return void 0; }); } function loadIconPropIcons(node, iconHandler) { const iconProps = Object.keys(node.props).filter((prop) => { return iconPattern.test(prop); }); iconProps.forEach((sectionKey) => { return observeIconProp(node, iconHandler, sectionKey); }); } function observeIconProp(node, iconHandler, sectionKey) { const normalizedSectionKey = normalizeIconProp(sectionKey); if (!observedIconProps.has(node)) { observedIconProps.set(node, /* @__PURE__ */ new Set()); } const observedProps = observedIconProps.get(node); if (observedProps.has(normalizedSectionKey)) return; observedProps.add(normalizedSectionKey); loadPropIcon(node, iconHandler, normalizedSectionKey); } function loadPropIcon(node, iconHandler, sectionKey) { const iconName = node.props[sectionKey]; const loadedIcon = iconHandler(iconName); const rawIconProp = `_raw${sectionKey.charAt(0).toUpperCase()}${sectionKey.slice(1)}`; const clickHandlerProp = `on${sectionKey.charAt(0).toUpperCase()}${sectionKey.slice(1)}Click`; node.addProps([rawIconProp, clickHandlerProp]); node.on(`prop:${sectionKey}`, reloadIcon); if (loadedIcon instanceof Promise) { return loadedIcon.then((svg) => { node.props[rawIconProp] = svg; }); } else { node.props[rawIconProp] = loadedIcon; } return; } function reloadIcon(event) { const node = event.origin; const iconName = event.payload; const iconHandler = node?.props?.iconHandler; const sectionKey = event.name.split(":")[1]; const rawIconProp = `_raw${sectionKey.charAt(0).toUpperCase()}${sectionKey.slice(1)}`; if (iconHandler && typeof iconHandler === "function") { const loadedIcon = iconHandler(iconName); if (loadedIcon instanceof Promise) { return loadedIcon.then((svg) => { node.props[rawIconProp] = svg; }); } else { node.props[rawIconProp] = loadedIcon; } } } export { createIconHandler, createThemePlugin, generateClasses, iconRegistry }; //# sourceMappingURL=index.dev.mjs.map //# sourceMappingURL=index.dev.mjs.map