Files
tm_panel/src/lib/lottie-theme.ts
T
AmirReza Jamali 25f8bde229 feat(dependencies): add Lottie animation libraries and refactor NotFoundPage
- Added `@lottiefiles/dotlottie-react` and `lottie-react` dependencies for enhanced animation capabilities.
- Refactored the NotFoundPage component to utilize a dedicated NotFoundContent component, improving code organization and readability.
- Updated package.json and pnpm-lock.yaml to reflect new dependencies and their versions.
2026-05-13 17:07:47 +03:30

67 lines
1.9 KiB
TypeScript

/**
* Brand-aligned Lottie tinting (Tailwind theme tokens → normalized RGBA).
* Primary: #5750F1 — slightly lifted in dark mode for contrast on `dark` bg.
*/
export type LottieThemeMode = "light" | "dark";
/** #5750F1 */
const PRIMARY_LIGHT = [87 / 255, 80 / 255, 241 / 255, 1] as const;
/** Brighter violet for fills on #111928 */
const PRIMARY_ON_DARK = [125 / 255, 118 / 255, 252 / 255, 1] as const;
function deepClone<T>(value: T): T {
return JSON.parse(JSON.stringify(value)) as T;
}
function colorsMatch(a: unknown, b: readonly number[]): boolean {
if (!Array.isArray(a) || a.length !== 4) return false;
return a.every(
(v, i) => typeof v === "number" && Math.abs(v - b[i]!) < 0.0001,
);
}
/**
* Replace exact RGBA quadruples anywhere in the JSON tree (Lottie uses nested `c.k`).
*/
function replaceRgbaEverywhere(
node: unknown,
from: readonly number[],
to: readonly number[],
): unknown {
if (node === null || typeof node !== "object") {
return node;
}
if (Array.isArray(node)) {
if (colorsMatch(node, from)) {
return [...to];
}
return node.map((item) => replaceRgbaEverywhere(item, from, to));
}
const out: Record<string, unknown> = {};
for (const [k, v] of Object.entries(node)) {
out[k] = replaceRgbaEverywhere(v, from, to);
}
return out;
}
/** Pure black fills/strokes → brand primary (loading spinner dots, etc.). */
export function applyLoadingLottieTheme<T extends object>(
data: T,
mode: LottieThemeMode,
): T {
const clone = deepClone(data);
const to = mode === "dark" ? PRIMARY_ON_DARK : PRIMARY_LIGHT;
return replaceRgbaEverywhere(clone, [0, 0, 0, 1], to) as T;
}
/**
* Full illustrations (e.g. 404): clone only until we add palette maps per asset.
*/
export function applyIllustrationLottieTheme<T extends object>(
data: T,
_mode: LottieThemeMode,
): T {
return deepClone(data);
}