UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

272 lines (267 loc) 7.65 kB
'use client'; import { jsx as f, jsxs as O } from "react/jsx-runtime"; import { useReducer as k, useMemo as A, useCallback as c, useEffect as u, createContext as I, useContext as V } from "react"; import { createThemeManager as w } from "../config/theme.js"; import { DEFAULT_THEME_CONFIG as y } from "../config/defaults.js"; const E = I(null); function D(s, o) { switch (o.type) { case "SET_THEME": return { ...s, theme: o.payload, isCustomized: !0 }; case "SET_MODE": return { ...s, mode: o.payload, isSystemMode: o.payload === "system" }; case "SET_EFFECTIVE_MODE": return { ...s, effectiveMode: o.payload }; case "SET_SYSTEM_MODE": return { ...s, isSystemMode: o.payload }; case "SET_CSS_VARIABLES": return { ...s, cssVariables: o.payload }; case "SET_CUSTOMIZED": return { ...s, isCustomized: o.payload }; case "SET_ORGANIZATION_BRANDING": return { ...s, organizationBranding: o.payload, isCustomized: !!o.payload }; case "RESET_THEME": return { ...T }; default: return s; } } const T = { theme: y, mode: "system", effectiveMode: "light", isSystemMode: !0, cssVariables: {}, isCustomized: !1 }; function x({ children: s, theme: o, mode: r = "system", organizationBranding: a, onThemeChange: n }) { const [t, i] = k(D, { ...T, theme: o ? { ...y, ...o } : y, mode: r, isSystemMode: r === "system" }), d = A(() => w(t.theme), []), l = c(() => typeof window > "u" ? "light" : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light", []), p = c(() => { let e; t.mode === "system" ? e = l() : e = t.mode, e !== t.effectiveMode && i({ type: "SET_EFFECTIVE_MODE", payload: e }); }, [t.mode, t.effectiveMode, l]); u(() => { if (typeof window > "u") return; const e = window.matchMedia("(prefers-color-scheme: dark)"), m = () => { t.mode === "system" && p(); }; return e.addEventListener("change", m), p(), () => { e.removeEventListener("change", m); }; }, [t.mode, p]), u(() => { d.setTheme(t.theme), d.setMode(t.effectiveMode); const e = d.generateCSSVariables(); i({ type: "SET_CSS_VARIABLES", payload: e }), n?.(t.theme); }, [d, t.theme, t.effectiveMode, n]), u(() => { a && (i({ type: "SET_ORGANIZATION_BRANDING", payload: a }), d.applyBranding({ logo: { url: a.logo, alt: "Organization Logo" }, colors: { primary: a.primaryColor || "#3b82f6", secondary: a.secondaryColor || "#64748b" }, fonts: { primary: a.fonts?.primary || "Inter, ui-sans-serif, system-ui, sans-serif", secondary: a.fonts?.secondary }, customCSS: a.customCSS })); }, [a, d]), u(() => { if (typeof document > "u") return; const e = document.documentElement; Object.entries(t.cssVariables).forEach(([m, S]) => { e.style.setProperty(m, S); }), e.classList.remove("light", "dark"), e.classList.add(t.effectiveMode), e.setAttribute("data-theme", t.effectiveMode), e.setAttribute("data-theme-mode", t.mode), e.setAttribute("data-theme-customized", t.isCustomized.toString()); }, [t.cssVariables, t.effectiveMode, t.mode, t.isCustomized]); const C = c((e) => { const m = { ...t.theme, ...e }; i({ type: "SET_THEME", payload: m }); }, [t.theme]), g = c((e) => { if (i({ type: "SET_MODE", payload: e }), e !== "system") i({ type: "SET_EFFECTIVE_MODE", payload: e }); else { const m = l(); i({ type: "SET_EFFECTIVE_MODE", payload: m }); } }, [l]), M = c((e) => { i({ type: "SET_ORGANIZATION_BRANDING", payload: e }), d.applyBranding({ logo: { url: e.logo, alt: "Organization Logo" }, colors: { primary: e.primaryColor || t.theme.colors.primary.DEFAULT, secondary: e.secondaryColor || t.theme.colors.secondary.DEFAULT }, fonts: { primary: e.fonts?.primary || t.theme.typography.fontFamily.sans[0], secondary: e.fonts?.secondary }, customCSS: e.customCSS }); }, [d, t.theme]), _ = c(() => { d.setTheme(y), i({ type: "RESET_THEME" }); }, [d]), b = c(() => { let e = `:root { `; return Object.entries(t.cssVariables).forEach(([m, S]) => { e += ` ${m}: ${S}; `; }), e += `} `, e += `[data-theme="light"] { `, e += ` color-scheme: light; `, e += `} `, e += `[data-theme="dark"] { `, e += ` color-scheme: dark; `, e += `} `, t.organizationBranding?.customCSS && (e += `/* Organization Custom CSS */ `, e += t.organizationBranding.customCSS, e += ` `), e; }, [t.cssVariables, t.organizationBranding]), v = { // State ...t, // Methods setTheme: C, setMode: g, applyBranding: M, resetTheme: _, generateCSS: b }; return /* @__PURE__ */ f(E.Provider, { value: v, children: s }); } function h() { const s = V(E); if (!s) throw new Error("useTheme must be used within a ThemeProvider"); return s; } function N() { const { mode: s, effectiveMode: o, setMode: r, isSystemMode: a } = h(); return { mode: s, effectiveMode: o, isSystemMode: a, setMode: r, toggleMode: () => { r(s === "light" ? "dark" : s === "dark" ? "light" : o === "light" ? "dark" : "light"); }, setLightMode: () => r("light"), setDarkMode: () => r("dark"), setSystemMode: () => r("system") }; } function G() { const { organizationBranding: s, applyBranding: o, isCustomized: r } = h(), a = c((n) => { if (n.settings?.branding) { const t = { primaryColor: n.settings.branding.primaryColor, secondaryColor: n.settings.branding.secondaryColor, logo: n.logoUrl, favicon: n.settings.branding.favicon, customCSS: n.settings.branding.customCSS }; o(t); } }, [o]); return { branding: s, isCustomBranded: r, applyOrganizationBranding: a, applyBranding: o, hasLogo: !!s?.logo, hasCustomCSS: !!s?.customCSS, primaryColor: s?.primaryColor, secondaryColor: s?.secondaryColor }; } function P() { const { cssVariables: s, generateCSS: o } = h(); return { variables: s, getVariable: (r) => s[r], generateCSS: o, applyToElement: (r) => { Object.entries(s).forEach(([a, n]) => { r.style.setProperty(a, n); }); } }; } function j(s) { const o = (r) => { const a = h(); return /* @__PURE__ */ f(s, { ...r, theme: a }); }; return o.displayName = `withTheme(${s.displayName || s.name})`, o; } function z({ className: s, iconClassName: o, showLabel: r = !1, ...a }) { const { mode: n, effectiveMode: t, toggleMode: i } = N(), d = () => n === "system" ? t === "dark" ? "🌙" : "☀️" : n === "dark" ? "🌙" : "☀️", l = () => n === "system" ? `System (${t})` : n === "dark" ? "Dark" : "Light"; return /* @__PURE__ */ O( "button", { type: "button", onClick: i, className: s, title: `Switch to ${t === "dark" ? "light" : "dark"} mode`, ...a, children: [ /* @__PURE__ */ f("span", { className: o, children: d() }), r && /* @__PURE__ */ f("span", { children: l() }) ] } ); } export { E as ThemeContext, x as ThemeProvider, z as ThemeSwitcher, G as useOrganizationBranding, h as useTheme, N as useThemeMode, P as useThemeVariables, j as withTheme }; //# sourceMappingURL=theme-provider.js.map