Files
EpicNext-Cms/src/lib/theme-bg.ts
T
openhands d131124515 feat(theme): animate public background with aurora and particles, polish landing pages
Add background_effect (aurora/particles), background_overlay tint and
opacity to the theme manager, rendered site-wide by ThemeVars on every
public page. Polish the home and register pages (hero mascot, live stat
pulse, date pills, photo strip, CTA band, theme-aware register intro,
i18n for home/register section).
2026-09-18 12:44:39 +02:00

84 lines
2.2 KiB
TypeScript

// Site background settings shared by the Theme Manager, its server actions,
// and ThemeVars. Kept in a plain module because it is imported by client
// components and "use server" files.
export const BACKGROUND_KEYS = [
"background_image",
"background_position",
"background_size",
"background_repeat",
"background_effect",
"background_overlay",
"background_overlay_opacity",
] as const;
export type BackgroundKey = (typeof BACKGROUND_KEYS)[number];
/**
* Animated background effects rendered behind the public site. Purely
* decorative and CSS-driven (transform/opacity only) so they stay cheap on
* every device and respect `prefers-reduced-motion`.
*/
export const BACKGROUND_EFFECTS = [
"none",
"aurora",
"particles",
"aurora-particles",
] as const;
export type BackgroundEffect = (typeof BACKGROUND_EFFECTS)[number];
export const BACKGROUND_EFFECT_DEFAULT: BackgroundEffect = "none";
export const OVERLAY_PRESETS = [
{ label: "None", value: "" },
{ label: "Black", value: "#000000" },
{ label: "White", value: "#ffffff" },
{ label: "Navy", value: "#0b1220" },
{ label: "Slate", value: "#1e293b" },
] as const;
export const OVERLAY_OPACITY_MAX = 90;
export const BACKGROUND_POSITIONS = [
"center center",
"top center",
"top left",
"top right",
"center left",
"center right",
"bottom center",
"bottom left",
"bottom right",
] as const;
export const BACKGROUND_SIZES = ["cover", "contain", "auto"] as const;
export const BACKGROUND_REPEATS = [
"no-repeat",
"repeat",
"repeat-x",
"repeat-y",
] as const;
export const BACKGROUND_DEFAULTS: Record<BackgroundKey, string> = {
background_image: "",
background_position: "center center",
background_size: "cover",
background_repeat: "no-repeat",
background_effect: BACKGROUND_EFFECT_DEFAULT,
background_overlay: "",
background_overlay_opacity: "0",
};
/**
* A URL accepted as a custom site background. Blocks `javascript:`, data
* URIs and any character that could break out of CSS `url("...")` (quotes,
* backslashes, backticks, whitespace).
*/
export function isSafeBackgroundUrl(value: string): boolean {
const URL_SAFE = /^[a-zA-Z0-9/:_\-.?&=%~+#]+$/;
return (
(value.startsWith("/") || /^https?:\/\/[^\s"'`\\]+$/i.test(value)) &&
URL_SAFE.test(value)
);
}