{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progress-liquid",
  "title": "Liquid progress",
  "description": "Styled progress: the Liquid set. 5 decorative progress variations (WaveProgress, BubbleProgress, TideProgress, DropProgress, FoamProgress) on the ai2 token system, powered by framer-motion, reduced-motion aware and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "motion@^12.42.2"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/progress-liquid.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Liquid progress family: the fill behaves like a liquid level - wave, bubble, tide, meniscus, foam. Colour comes ONLY from tokens (color-mix, oklab). The fill width always lands on value; the continuous wave and bubble motion stops under reduced-motion. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst track: Record<StyledSize, string> = {\n  sm: \"h-1\",\n  md: \"h-1.5\",\n  lg: \"h-2.5\",\n  xl: \"h-3.5\",\n}\n\nconst trackBase = \"relative w-56 max-w-full overflow-hidden rounded-full bg-secondary\"\n\ntype Props = React.ComponentProps<\"div\"> & { size?: StyledSize; value?: number; label?: string }\n\nfunction clamp(v: number) {\n  return Math.max(0, Math.min(100, v))\n}\n\n/* Wave: dolgunun ust kenari salinan bir sinus dalgasi (yatayda kayan SVG). */\nexport function WaveProgress({ className, size = \"md\", value = 60, label = \"Progress\", ...props }: Props) {\n  const reduce = useReducedMotion()\n  const v = clamp(value)\n  return (\n    <div\n      data-slot=\"styled-progress\"\n      role=\"progressbar\"\n      aria-valuenow={v}\n      aria-valuemin={0}\n      aria-valuemax={100}\n      aria-label={label}\n      className={cn(trackBase, track[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-y-0 left-0 overflow-hidden rounded-full bg-primary\"\n        initial={reduce ? false : { width: 0 }}\n        animate={{ width: `${v}%` }}\n        transition={reduce ? undefined : { duration: 0.8, ease: \"easeOut\" }}\n      >\n        <motion.svg\n          aria-hidden=\"true\"\n          viewBox=\"0 0 40 8\"\n          preserveAspectRatio=\"none\"\n          className=\"absolute inset-y-0 left-0 h-full w-[200%]\"\n          animate={reduce ? undefined : { x: [\"0%\", \"-50%\"] }}\n          transition={reduce ? undefined : { duration: 1.6, ease: \"linear\", repeat: Infinity }}\n        >\n          <path\n            d=\"M0 4 Q5 0 10 4 T20 4 T30 4 T40 4 V8 H0 Z\"\n            fill=\"color-mix(in oklab, var(--color-primary-foreground) 30%, transparent)\"\n          />\n        </motion.svg>\n      </motion.span>\n    </div>\n  )\n}\n\n/* Bubble: dolgu icinde yukselen token kabarciklar (deterministik konum/gecikme). */\nexport function BubbleProgress({ className, size = \"md\", value = 60, label = \"Progress\", ...props }: Props) {\n  const reduce = useReducedMotion()\n  const v = clamp(value)\n  const bubbles = [\n    { left: \"18%\", delay: 0, dur: 1.7 },\n    { left: \"42%\", delay: 0.5, dur: 2.1 },\n    { left: \"68%\", delay: 0.9, dur: 1.9 },\n    { left: \"85%\", delay: 0.3, dur: 2.3 },\n  ]\n  return (\n    <div\n      data-slot=\"styled-progress\"\n      role=\"progressbar\"\n      aria-valuenow={v}\n      aria-valuemin={0}\n      aria-valuemax={100}\n      aria-label={label}\n      className={cn(trackBase, track[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-y-0 left-0 overflow-hidden rounded-full bg-primary\"\n        initial={reduce ? false : { width: 0 }}\n        animate={{ width: `${v}%` }}\n        transition={reduce ? undefined : { duration: 0.8, ease: \"easeOut\" }}\n      >\n        {!reduce &&\n          bubbles.map((b, i) => (\n            <motion.span\n              key={i}\n              aria-hidden=\"true\"\n              className=\"absolute bottom-0 size-1 rounded-full bg-[color-mix(in_oklab,var(--color-primary-foreground)_45%,transparent)]\"\n              style={{ left: b.left }}\n              animate={{ y: [\"10%\", \"-120%\"], opacity: [0, 1, 0] }}\n              transition={{ duration: b.dur, ease: \"easeInOut\", repeat: Infinity, delay: b.delay }}\n            />\n          ))}\n      </motion.span>\n    </div>\n  )\n}\n\n/* Tide: sivi seviyesi + ustunde ince yatay token parilti (gel-git shimmer). */\nexport function TideProgress({ className, size = \"md\", value = 60, label = \"Progress\", ...props }: Props) {\n  const reduce = useReducedMotion()\n  const v = clamp(value)\n  return (\n    <div\n      data-slot=\"styled-progress\"\n      role=\"progressbar\"\n      aria-valuenow={v}\n      aria-valuemin={0}\n      aria-valuemax={100}\n      aria-label={label}\n      className={cn(trackBase, track[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-y-0 left-0 overflow-hidden rounded-full bg-primary\"\n        initial={reduce ? false : { width: 0 }}\n        animate={{ width: `${v}%` }}\n        transition={reduce ? undefined : { duration: 0.8, ease: \"easeOut\" }}\n      >\n        <motion.span\n          aria-hidden=\"true\"\n          className=\"absolute inset-0 [background-image:linear-gradient(90deg,transparent,color-mix(in_oklab,var(--color-primary-foreground)_35%,transparent),transparent)] [background-size:60%_100%] bg-no-repeat\"\n          animate={reduce ? undefined : { backgroundPositionX: [\"-60%\", \"160%\"] }}\n          transition={reduce ? undefined : { duration: 2.2, ease: \"easeInOut\", repeat: Infinity }}\n        />\n      </motion.span>\n    </div>\n  )\n}\n\n/* Drop: dolgunun ust yuzeyi yuvarlak bir meniskus; hafifce salinir. */\nexport function DropProgress({ className, size = \"md\", value = 60, label = \"Progress\", ...props }: Props) {\n  const reduce = useReducedMotion()\n  const v = clamp(value)\n  return (\n    <div\n      data-slot=\"styled-progress\"\n      role=\"progressbar\"\n      aria-valuenow={v}\n      aria-valuemin={0}\n      aria-valuemax={100}\n      aria-label={label}\n      className={cn(trackBase, track[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-y-0 left-0 overflow-hidden rounded-full bg-primary\"\n        initial={reduce ? false : { width: 0 }}\n        animate={{ width: `${v}%` }}\n        transition={reduce ? undefined : { duration: 0.8, ease: \"easeOut\" }}\n      >\n        <motion.span\n          aria-hidden=\"true\"\n          className=\"absolute inset-x-0 top-0 h-3/5 rounded-full [background-image:radial-gradient(ellipse_at_top,color-mix(in_oklab,var(--color-primary-foreground)_45%,transparent),transparent_70%)]\"\n          animate={reduce ? undefined : { y: [\"-6%\", \"6%\", \"-6%\"] }}\n          transition={reduce ? undefined : { duration: 2.4, ease: \"easeInOut\", repeat: Infinity }}\n        />\n      </motion.span>\n    </div>\n  )\n}\n\n/* Foam: dolgunun ustunde daha acik token kopuk cizgisi; hafifce titrer (wobble). */\nexport function FoamProgress({ className, size = \"md\", value = 60, label = \"Progress\", ...props }: Props) {\n  const reduce = useReducedMotion()\n  const v = clamp(value)\n  return (\n    <div\n      data-slot=\"styled-progress\"\n      role=\"progressbar\"\n      aria-valuenow={v}\n      aria-valuemin={0}\n      aria-valuemax={100}\n      aria-label={label}\n      className={cn(trackBase, track[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-y-0 left-0 overflow-hidden rounded-full bg-primary\"\n        initial={reduce ? false : { width: 0 }}\n        animate={{ width: `${v}%` }}\n        transition={reduce ? undefined : { duration: 0.8, ease: \"easeOut\" }}\n      >\n        <motion.span\n          aria-hidden=\"true\"\n          className=\"absolute inset-x-0 top-0 h-1/3 rounded-full bg-[color-mix(in_oklab,var(--color-primary-foreground)_55%,transparent)]\"\n          animate={reduce ? undefined : { x: [\"-8%\", \"8%\", \"-8%\"], opacity: [0.7, 1, 0.7] }}\n          transition={reduce ? undefined : { duration: 1.8, ease: \"easeInOut\", repeat: Infinity }}\n        />\n      </motion.span>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/progress-liquid.tsx"
    }
  ],
  "categories": [
    "styled",
    "progress"
  ],
  "type": "registry:component"
}