Make useGetClassName not a hook

This commit is contained in:
Joseph Garrone 2024-06-08 18:54:27 +02:00
parent 8d365dae53
commit 77e32aad2a

View File

@ -1,24 +1,63 @@
import { clsx } from "keycloakify/tools/clsx"; import { clsx } from "keycloakify/tools/clsx";
import { useConstCallback } from "keycloakify/tools/useConstCallback"; import type { Param0 } from "tsafe";
// NOTE: Note for people trying to implement Keycloakify in other frontend
// frameworks. This can be used outside of React, useGetClassName isn't actually a hook.
export function createUseClassName<ClassKey extends string>(params: { export function createUseClassName<ClassKey extends string>(params: {
defaultClasses: Record<ClassKey, string | undefined>; defaultClasses: Record<ClassKey, string | undefined>;
}) { }) {
const { defaultClasses } = params; const { defaultClasses } = params;
function areSameParams(
params1: Param0<typeof useGetClassName>,
params2: Param0<typeof useGetClassName>
): boolean {
if (params1.doUseDefaultCss !== params2.doUseDefaultCss) {
return false;
}
if (params1.classes === params2.classes) {
return true;
}
return JSON.stringify(params1.classes) === JSON.stringify(params2.classes);
}
let cache:
| {
params: Param0<typeof useGetClassName>;
result: ReturnType<typeof useGetClassName>;
}
| undefined = undefined;
function useGetClassName(params: { function useGetClassName(params: {
doUseDefaultCss: boolean; doUseDefaultCss: boolean;
classes: Partial<Record<ClassKey, string>> | undefined; classes: Partial<Record<ClassKey, string>> | undefined;
}) { }): { getClassName: (classKey: ClassKey) => string } {
const { classes, doUseDefaultCss } = params; // NOTE: We implement a cache here only so that getClassName can be stable across renders.
// We don't want to use useConstCallback because we want this to be useable outside of React.
use_cache: {
if (cache === undefined) {
break use_cache;
}
const getClassName = useConstCallback((classKey: ClassKey): string => { if (!areSameParams(cache.params, params)) {
break use_cache;
}
return cache.result;
}
function getClassName(classKey: ClassKey): string {
return clsx( return clsx(
classKey, classKey,
doUseDefaultCss ? defaultClasses[classKey] : undefined, params.doUseDefaultCss ? defaultClasses[classKey] : undefined,
classes?.[classKey] params.classes?.[classKey]
); );
}); }
cache = { params, result: { getClassName } };
return { getClassName }; return { getClassName };
} }