@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
272 lines (267 loc) • 7.65 kB
JavaScript
'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