{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"motion-toggle-group","type":"registry:component","title":"Toggle Group (Motion)","description":"ToggleGroup with motion: with type=\"single\" one background springs between the toggles; with \"multiple\" each pops in and out.","dependencies":["motion","radix-ui"],"registryDependencies":["https://dashral.com/r/utils.json","https://dashral.com/r/motion-reduced.json","https://dashral.com/r/motion-tokens.json","https://dashral.com/r/toggle.json","https://dashral.com/r/toggle-group.json"],"files":[{"path":"registry/dashral/motion/toggle-group.tsx","type":"registry:file","target":"components/dashral/motion/toggle-group.tsx","content":"\"use client\"\n\nimport * as React from \"react\"\nimport { ToggleGroup as ToggleGroupPrimitive } from \"radix-ui\"\nimport { AnimatePresence, LayoutGroup, motion } from \"motion/react\"\nimport { toggleOnFill, toggleVariants } from \"../toggle\"\nimport type { ToggleGroupProps } from \"../toggle-group\"\nimport { cn } from \"../lib/utils\"\n\nimport { useReducedMotion } from \"../lib/motion-reduced\"\nimport { duration, ease, spring } from \"../lib/motion-tokens\"\n\nexport type { ToggleGroupProps, ToggleGroupItem } from \"../toggle-group\"\n\n/**\n * The kit's ToggleGroup with motion: the same items, types, variants and props. With type=\"single\" the pressed one's\n * background is one element springing from toggle to toggle; with \"multiple\" each pops in from the middle and shrinks\n * away on its own. Toggles press in while held. With reduced motion the backgrounds only fade.\n */\nexport function ToggleGroup(allProps: ToggleGroupProps) {\n  const { items, variant = \"ghost\", size, color = \"neutral\", attached = false, className, classNames, type, value, defaultValue, onValueChange, ...props } = allProps\n  const reduced = useReducedMotion()\n  const group = React.useId()\n  const [own, setOwn] = React.useState<string | string[]>(defaultValue ?? (type === \"multiple\" ? [] : \"\"))\n  const current = value ?? own\n  const isOn = (item: string) => (Array.isArray(current) ? current.includes(item) : current === item)\n  const change = (next: string | string[]) => {\n    if (value === undefined) setOwn(next)\n    ;(onValueChange as ((v: string | string[]) => void) | undefined)?.(next)\n  }\n\n  const root = {\n    \"data-slot\": \"toggle-group\",\n    className: cn(\n      \"isolate inline-flex w-fit items-center\",\n      attached ? (variant === \"outline\" ? \"rounded-md border border-input shadow-xs\" : \"rounded-md\") : \"gap-1\",\n      className\n    ),\n    ...props,\n  }\n\n  const children = items.map((item) => {\n    const on = isOn(item.value)\n    return (\n      <ToggleGroupPrimitive.Item key={item.value} value={item.value} disabled={item.disabled} aria-label={item[\"aria-label\"]} data-slot=\"toggle-group-item\" asChild>\n        <motion.button\n          whileTap={reduced || item.disabled ? undefined : { scale: 0.92 }}\n          transition={spring.press}\n          className={toggleVariants({\n            variant: attached ? \"ghost\" : variant,\n            size,\n            color,\n            className: cn(\n              \"relative data-[state=on]:bg-transparent data-[state=on]:hover:bg-transparent\",\n              attached && \"rounded-none first:rounded-s-md last:rounded-e-md\",\n              attached && variant === \"outline\" && \"border-s border-input first:border-s-0\",\n              classNames?.item\n            ),\n          })}\n        >\n          {type === \"single\" ? (\n            on && (\n              <motion.span\n                layoutId=\"pressed\"\n                aria-hidden\n                className={cn(\"absolute inset-0 -z-10 rounded-[inherit]\", toggleOnFill[color])}\n                transition={reduced ? { duration: 0 } : spring.move}\n              />\n            )\n          ) : (\n            <AnimatePresence initial={false}>\n              {on && (\n                <motion.span\n                  key=\"on\"\n                  aria-hidden\n                  className={cn(\"absolute inset-0 -z-10 rounded-[inherit]\", toggleOnFill[color])}\n                  initial={reduced ? { opacity: 0 } : { opacity: 0, scale: 0.6 }}\n                  animate={{ opacity: 1, scale: 1 }}\n                  exit={reduced ? { opacity: 0 } : { opacity: 0, scale: 0.6, transition: { duration: duration.fast, ease: ease.exit } }}\n                  transition={reduced ? { duration: duration.fast } : { ...spring.pop, opacity: { duration: duration.fast } }}\n                />\n              )}\n            </AnimatePresence>\n          )}\n          {item.icon}\n          {item.label}\n        </motion.button>\n      </ToggleGroupPrimitive.Item>\n    )\n  })\n\n  return (\n    <LayoutGroup id={group}>\n      {type === \"single\" ? (\n        <ToggleGroupPrimitive.Root type=\"single\" value={current as string} onValueChange={change} {...root}>\n          {children}\n        </ToggleGroupPrimitive.Root>\n      ) : (\n        <ToggleGroupPrimitive.Root type=\"multiple\" value={current as string[]} onValueChange={change} {...root}>\n          {children}\n        </ToggleGroupPrimitive.Root>\n      )}\n    </LayoutGroup>\n  )\n}\n"}]}