{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "segmented-control",
  "title": "Segmented Control",
  "description": "The selected key stretches across toward the new option, then closes up.",
  "dependencies": [
    "@ui-sdk/core@0.1.0-beta.2",
    "@ui-sdk/react@0.1.0-beta.2"
  ],
  "registryDependencies": [
    "@keyframery/motion"
  ],
  "files": [
    {
      "path": "registry/components/keyframery/primitives/segmented-control.tsx",
      "content": "\"use client\"\n\n/* Animated drop-in for `@ui-sdk/react/segmented-control`: same parts, same props. Swap the import and\n   keep your code. This file adds motion only. Colours, radii, shadows and spacing stay yours. */\n\nimport {\n  SegmentedControl as SegmentedControlRoot,\n  SegmentedControlIndicator as SegmentedControlIndicatorPart,\n  SegmentedControlItem as SegmentedControlItemPart,\n} from \"@ui-sdk/react/segmented-control\"\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport * from \"@ui-sdk/react/segmented-control\"\n\n/* UI SDK accepts a class name or a function of state; keep both working. */\nfunction withClass<S>(base: string, className: string | ((state: S) => string | undefined) | undefined) {\n  return typeof className === \"function\" ? (state: S) => cn(base, className(state)) : cn(base, className)\n}\n\nfunction SegmentedControl({ className, ...props }: React.ComponentProps<typeof SegmentedControlRoot>) {\n  return <SegmentedControlRoot className={withClass(\"relative isolate\", className)} {...props} />\n}\n\nfunction SegmentedControlItem({ className, ...props }: React.ComponentProps<typeof SegmentedControlItemPart>) {\n  return (\n    <SegmentedControlItemPart\n      className={withClass(\n        \"transition-[scale] duration-[calc(200ms*var(--kf-speed,1))] ease-pop not-data-disabled:not-data-readonly:active:scale-[0.96] motion-reduce:transition-none!\",\n        className,\n      )}\n      {...props}\n    />\n  )\n}\n\n/* Stretch, the same recipe as the tabs primitive: every edge of the marker is tracked twice,\n   once quickly and once slowly with an 80ms lag, and each edge uses whichever of the two is\n   further out. The edge facing the direction of travel leads, the other follows, so the\n   marker stretches toward the item you pick and closes up there. The registered properties\n   are inherited, so anything inside the indicator can read the same moving edges. */\nconst stretchProperties = [\"la\", \"lb\", \"ra\", \"rb\", \"ta\", \"tb\", \"ba\", \"bb\"]\n  .map((n) => `@property --kf-${n}{syntax:\"<length>\";inherits:true;initial-value:0px}`)\n  .join(\"\")\n\nfunction SegmentedControlIndicator({\n  className,\n  ...props\n}: React.ComponentProps<typeof SegmentedControlIndicatorPart>) {\n  /* Hold the transitions until UI SDK has measured the checked item, so the marker is\n     simply there on load instead of sliding in from the corner. */\n  const [ready, setReady] = React.useState(false)\n  React.useEffect(() => {\n    const timer = setTimeout(() => setReady(true), 150)\n    return () => clearTimeout(timer)\n  }, [])\n\n  return (\n    <>\n      <style href=\"kf-stretch\" precedence=\"default\">\n        {stretchProperties}\n      </style>\n      <SegmentedControlIndicatorPart\n        data-ready={ready || undefined}\n        className={withClass(\n          cn(\n            \"pointer-events-none absolute\",\n            /* No box while nothing is checked. */\n            \"[[data-slot=segmented-control]:not(:has([data-checked]))>&]:invisible\",\n            \"[--kf-la:var(--segmented-control-indicator-left,0px)] [--kf-lb:var(--segmented-control-indicator-left,0px)]\",\n            \"[--kf-ra:var(--segmented-control-indicator-right,0px)] [--kf-rb:var(--segmented-control-indicator-right,0px)]\",\n            \"[--kf-ta:var(--segmented-control-indicator-top,0px)] [--kf-tb:var(--segmented-control-indicator-top,0px)]\",\n            \"[--kf-ba:var(--segmented-control-indicator-bottom,0px)] [--kf-bb:var(--segmented-control-indicator-bottom,0px)]\",\n            \"top-[min(var(--kf-ta),var(--kf-tb))] right-[min(var(--kf-ra),var(--kf-rb))] bottom-[min(var(--kf-ba),var(--kf-bb))] left-[min(var(--kf-la),var(--kf-lb))]\",\n            \"motion-reduce:transition-none! data-ready:[transition:--kf-la_calc(260ms*var(--kf-speed,1))_var(--ease-house),--kf-ra_calc(260ms*var(--kf-speed,1))_var(--ease-house),--kf-ta_calc(260ms*var(--kf-speed,1))_var(--ease-house),--kf-ba_calc(260ms*var(--kf-speed,1))_var(--ease-house),--kf-lb_calc(380ms*var(--kf-speed,1))_var(--ease-house)_calc(80ms*var(--kf-speed,1)),--kf-rb_calc(380ms*var(--kf-speed,1))_var(--ease-house)_calc(80ms*var(--kf-speed,1)),--kf-tb_calc(380ms*var(--kf-speed,1))_var(--ease-house)_calc(80ms*var(--kf-speed,1)),--kf-bb_calc(380ms*var(--kf-speed,1))_var(--ease-house)_calc(80ms*var(--kf-speed,1))]\",\n            \"motion-reduce:[transition:none]!\",\n          ),\n          className,\n        )}\n        {...props}\n      />\n    </>\n  )\n}\n\nexport { SegmentedControl, SegmentedControlIndicator, SegmentedControlItem }\n",
      "type": "registry:component",
      "target": "components/keyframery/primitives/segmented-control.tsx"
    },
    {
      "path": "registry/components/keyframery/segmented-control.tsx",
      "content": "\"use client\"\n\n/* Styled segmented control: the animated primitive plus the Keyframery look. */\n\nimport * as React from \"react\"\n\nimport {\n  SegmentedControl as SegmentedControlRoot,\n  SegmentedControlIndicator as SegmentedControlIndicatorPrimitive,\n  SegmentedControlItem as SegmentedControlItemPrimitive,\n} from \"@/components/keyframery/primitives/segmented-control\"\nimport { cn } from \"@/lib/utils\"\n\n/* One box shared by the real item and its copy inside the key, so both lay out identically. */\nconst itemBox =\n  \"inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-[9px] px-3 text-[13px] leading-none font-medium whitespace-nowrap [&_svg]:size-3.5 [&_svg]:shrink-0\"\n\nconst rowLayout = \"flex items-stretch gap-0.5 p-1 data-[orientation=vertical]:flex-col\"\n\n/* The control renders its own key (the indicator), like the tabs list does, so don't add a\n   SegmentedControlIndicator inside it. */\nfunction SegmentedControl({\n  className,\n  children,\n  orientation,\n  ...props\n}: Omit<React.ComponentProps<typeof SegmentedControlRoot>, \"children\"> & {\n  children?: React.ReactNode\n}) {\n  return (\n    <SegmentedControlRoot\n      orientation={orientation}\n      className={cn(\n        rowLayout,\n        \"inline-flex w-fit rounded-[12px] bg-muted outline-none\",\n        \"shadow-[inset_0_1px_2px_rgb(0_0_0/0.07),inset_0_0_0_1px_rgb(0_0_0/0.035)]\",\n        \"dark:shadow-[inset_0_1px_2px_rgb(0_0_0/0.5),inset_0_0_0_1px_rgb(255_255_255/0.04)]\",\n        \"data-disabled:opacity-60\",\n        className as string,\n      )}\n      {...props}\n    >\n      {children}\n      {/* The key: a raised surface that stretches toward the item you pick. */}\n      <SegmentedControlIndicator>\n        {/* A copy of the labels in the selected colour, clipped to the key. It is offset by the\n            key's own moving edges, so it stays still while the key passes over it. */}\n        <span className=\"absolute inset-0 overflow-hidden rounded-[inherit]\">\n          <span\n            data-orientation={orientation ?? \"horizontal\"}\n            className={cn(\n              rowLayout,\n              \"absolute text-foreground\",\n              \"top-[calc(min(var(--kf-ta),var(--kf-tb))*-1)] left-[calc(min(var(--kf-la),var(--kf-lb))*-1)]\",\n              \"h-[calc(var(--segmented-control-indicator-top,0px)+var(--segmented-control-indicator-height,0px)+var(--segmented-control-indicator-bottom,0px))]\",\n              \"w-[calc(var(--segmented-control-indicator-left,0px)+var(--segmented-control-indicator-width,0px)+var(--segmented-control-indicator-right,0px))]\",\n            )}\n          >\n            {React.Children.map(children, (child) =>\n              React.isValidElement<{ children?: React.ReactNode }>(child) ? (\n                <span className={itemBox}>{child.props.children}</span>\n              ) : null,\n            )}\n          </span>\n        </span>\n      </SegmentedControlIndicator>\n    </SegmentedControlRoot>\n  )\n}\n\nfunction SegmentedControlIndicator({\n  className,\n  ...props\n}: React.ComponentProps<typeof SegmentedControlIndicatorPrimitive>) {\n  return (\n    <SegmentedControlIndicatorPrimitive\n      aria-hidden\n      className={cn(\n        \"z-10 rounded-[9px] bg-background\",\n        \"shadow-[0_0_0_1px_rgb(0_0_0/0.06),0_1px_1px_rgb(0_0_0/0.05),0_3px_6px_-2px_rgb(0_0_0/0.1)]\",\n        \"dark:bg-accent dark:shadow-[0_0_0_1px_rgb(255_255_255/0.07),inset_0_1px_0_rgb(255_255_255/0.08),0_2px_6px_-1px_rgb(0_0_0/0.6)]\",\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction SegmentedControlItem({\n  className,\n  ...props\n}: React.ComponentProps<typeof SegmentedControlItemPrimitive>) {\n  return (\n    <SegmentedControlItemPrimitive\n      className={cn(\n        itemBox,\n        \"relative cursor-pointer text-muted-foreground outline-none select-none\",\n        \"transition-[color,background-color,scale] motion-reduce:transition-none! hover:bg-foreground/[0.045] hover:text-foreground\",\n        \"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-muted\",\n        \"data-disabled:pointer-events-none data-disabled:opacity-40 data-readonly:cursor-default\",\n        className as string,\n      )}\n      {...props}\n    />\n  )\n}\n\nexport { SegmentedControl, SegmentedControlIndicator, SegmentedControlItem }\n",
      "type": "registry:component",
      "target": "components/keyframery/segmented-control.tsx"
    }
  ],
  "type": "registry:component"
}