/* The code for a set of glass options, as the playground shows it and the
`liquid-glass.snippet` tool returns it. */
import { PACKAGE } from "./api";
export type PlaygroundOptions = {
variant?: "regular" | "clear" | undefined;
floating?: boolean | "dialog" | undefined;
interactive?: boolean | undefined;
swell?: boolean | undefined;
hue?: string | null | undefined;
hueStrength?: number | undefined;
refraction?: boolean | undefined;
samples?: 1 | 4 | undefined;
geometry?: { maxFall?: number; bezel?: number; thickness?: number; edge?: number; glint?: number } | undefined;
shape?: "capsule" | "card" | "circle" | undefined;
};
/** Defaults the snippet leaves out. */
const DEFAULTS = { maxFall: 0.8, bezel: 17, thickness: 24, edge: 0.75, glint: 0.4 } as const;
const round = (value: number) => Number(value.toFixed(2));
function geometryEntries(options: PlaygroundOptions) {
const geometry = options.geometry ?? {};
return (Object.keys(DEFAULTS) as (keyof typeof DEFAULTS)[])
.filter(key => geometry[key] !== undefined && round(geometry[key]!) !== DEFAULTS[key])
.map(key => [key, round(geometry[key]!)] as const);
}
/** JSX props for the options, in a stable order. */
export function jsxProps(options: PlaygroundOptions) {
const props: string[] = ['appearance="class"'];
if (options.variant === "clear") props.push('variant="clear"');
if (options.floating === "dialog") props.push('floating="dialog"');
else if (options.floating) props.push("floating");
if (options.interactive) props.push("interactive");
if (options.swell) props.push("swell");
if (options.hue) props.push(`hue="${options.hue}"`);
if (options.hue && options.hueStrength !== undefined) props.push(`hueStrength={${round(options.hueStrength)}}`);
if (options.refraction === false) props.push("refraction={false}");
if (options.samples === 4) props.push("samples={4}");
const geometry = geometryEntries(options);
if (geometry.length) props.push(`geometry={{ ${geometry.map(([key, value]) => `${key}: ${value}`).join(", ")} }}`);
return props;
}
function objectLiteral(options: PlaygroundOptions) {
const entries: string[] = ['appearance: "class"'];
if (options.variant === "clear") entries.push('variant: "clear"');
if (options.floating === "dialog") entries.push('floating: "dialog"');
else if (options.floating) entries.push("floating: true");
if (options.interactive) entries.push("interactive: true");
if (options.swell) entries.push("swell: true");
if (options.hue) entries.push(`hue: "${options.hue}"`);
if (options.hue && options.hueStrength !== undefined) entries.push(`hueStrength: ${round(options.hueStrength)}`);
if (options.refraction === false) entries.push("refraction: false");
if (options.samples === 4) entries.push("samples: 4");
const geometry = geometryEntries(options);
if (geometry.length) entries.push(`geometry: { ${geometry.map(([key, value]) => `${key}: ${value}`).join(", ")} }`);
return entries;
}
const SHAPE_CLASSES = {
capsule: "relative rounded-full px-6 py-3",
card: "relative rounded-[32px] p-6",
circle: "relative size-40 rounded-full",
} as const;
export function reactSnippet(options: PlaygroundOptions) {
const props = jsxProps(options);
const glass = props.join(" ").length > 56 ? `