/* 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 ? `` : ``; return `import { LiquidGlass } from "${PACKAGE}/react"; import "${PACKAGE}/styles.css";
${glass} …
`; } export function vanillaSnippet(options: PlaygroundOptions) { const entries = objectLiteral(options); return `import { createLiquidGlass } from "${PACKAGE}"; import "${PACKAGE}/styles.css"; const glass = createLiquidGlass(element, { ${entries.join(",\n ")}, });`; }