/* 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; level?: number | 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.45, bezel: 17, thickness: 24, edge: 0.75, glint: 0.4 } as const; const DEFAULT_LEVEL = 0.5; 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); } /** The options that differ from the defaults, as [name, JSX value, object value]. */ function entries(options: PlaygroundOptions): [string, string, string][] { const out: [string, string, string][] = [["appearance", '"class"', '"class"']]; if (options.variant === "clear") out.push(["variant", '"clear"', '"clear"']); if (options.variant !== "clear" && options.level !== undefined && round(options.level) !== DEFAULT_LEVEL) { out.push(["level", `{${round(options.level)}}`, String(round(options.level))]); } if (options.floating === "dialog") out.push(["floating", '"dialog"', '"dialog"']); else if (options.floating) out.push(["floating", "", "true"]); if (options.interactive) out.push(["interactive", "", "true"]); // Interactive glass swells unless told not to. const swell = options.swell ?? Boolean(options.interactive); if (swell !== Boolean(options.interactive)) out.push(["swell", swell ? "" : "{false}", String(swell)]); if (options.hue) out.push(["hue", `"${options.hue}"`, `"${options.hue}"`]); if (options.hue && options.hueStrength !== undefined) out.push(["hueStrength", `{${round(options.hueStrength)}}`, String(round(options.hueStrength))]); if (options.refraction === false) out.push(["refraction", "{false}", "false"]); if (options.samples === 1) out.push(["samples", "{1}", "1"]); const geometry = geometryEntries(options); if (geometry.length) { const literal = `{ ${geometry.map(([key, value]) => `${key}: ${value}`).join(", ")} }`; out.push(["geometry", `{${literal}}`, literal]); } return out; } /** JSX props for the options, in a stable order. */ export function jsxProps(options: PlaygroundOptions) { return entries(options).map(([name, value]) => (value ? `${name}=${value}` : name)); } function objectLiteral(options: PlaygroundOptions) { return entries(options).map(([name, , value]) => `${name}: ${value}`); } 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 literal = objectLiteral(options); return `import { createLiquidGlass } from "${PACKAGE}"; import "${PACKAGE}/styles.css"; const glass = createLiquidGlass(element, { ${literal.join(",\n ")}, });`; }