{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button-group",
  "title": "ButtonGroup",
  "description": "버튼 무리 — 방향(가로/세로) 변형, 자식 버튼 모서리 연접·테두리 중복 제거를 cloneElement 주입으로 재현. 구분선·텍스트 포함.",
  "dependencies": [
    "@unikit-bridge/ui",
    "class-variance-authority",
    "clsx",
    "tailwind-merge",
    "tailwindcss"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/button-group.tsx",
      "content": "// ButtonGroup — shadcn/ui new-york-v4 button-group을 UniKit UI 유니버설로 이식.\n//\n// 포팅 판단（자식 셀렉터 제거）:\n// - 원본의 붙임（attach） 처리는 자식 셀렉터（［&>*:not（:first-child）］:\n//   rounded-l-none 등）로 동작한다. 네이티브에 자식 셀렉터가 없으므로\n//   ButtonGroup이 Children.map으로 각 자식 요소에 위치 클래스（첫/끝 모서리\n//   정리·테두리 중복 제거·포커스 z-순서）를 cloneElement로 주입한다 —\n//   CSS 셀렉터 없이 양쪽에서 동일하게 동작한다（Button 등 기존 컴포넌트의\n//   className 병합 규칙（twMerge）과 맞물려 나중 값이 이긴다）.\n// - data-slot 기반 중첩 그룹 간격 토큰（gap-2）과 select-trigger\n//   관련 토큰은 data-slot 없이 표현 불가 → 제거.\n// - ButtonGroupText의 asChild（radix Slot） 제거 — View+Text 구조 고정\n//   （이중 지정: 전경색은 내부 Text에）.\n// - ButtonGroupSeparator가 감싸던 Separator는 인라인 View（bg-border）로 대리\n//   （신규 파일 6종 제한 — separator.tsx 생성 불가）.\nimport {\n  Children,\n  cloneElement,\n  forwardRef,\n  isValidElement,\n  type ReactElement,\n  type ReactNode,\n} from \"react\";\nimport {\n  Text,\n  View,\n  type BridgeViewRef,\n  type ViewProps,\n} from \"@unikit-bridge/ui/primitives\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\n// 그룹 뼈대 — 원본의 방향 변형. 모서리 붙임 토큰은 아래 주입 로직으로 이동.\n// w-fit은 uniwind 미지원 — self-start 치환으로 양쪽 플랫폼 내용 폭을 맞춘다（M-2）.\nconst buttonGroupVariants = cva(\"flex self-start items-stretch\", {\n  variants: {\n    orientation: {\n      horizontal: \"flex-row\",\n      vertical: \"flex-col\",\n    },\n  },\n  defaultVariants: {\n    orientation: \"horizontal\",\n  },\n});\n\ntype ButtonGroupOrientation = \"horizontal\" | \"vertical\";\n\n// 위치별 붙임 클래스 — 원본 자식 셀렉터의 치환.\n// 첫 자식은 시작 모서리를, 끝 자식은 끝 모서리를 유지하고 나머지 모서리를\n// 없애 붙은 모양을 만든다. 이웃 테두리 중복（border-l-0/border-t-0）도 정리.\nfunction buttonGroupAttachClasses(\n  index: number,\n  total: number,\n  orientation: ButtonGroupOrientation,\n): string {\n  const isFirst = index === 0;\n  const isLast = index === total - 1;\n  const horizontal = orientation === \"horizontal\";\n  return cn(\n    // 포커스 받은 자식이 위로 — 원본 ［&>*］:focus-visible:relative/z-10 치환\n    \"web:focus-visible:relative web:focus-visible:z-10\",\n    !isFirst &&\n      (horizontal ? \"rounded-l-none border-l-0\" : \"rounded-t-none border-t-0\"),\n    !isLast && (horizontal ? \"rounded-r-none\" : \"rounded-b-none\"),\n  );\n}\n\n// ---------------------------------------------------------------------------\n// ButtonGroup — 버튼 무리 컨테이너. 자식에 붙임 클래스를 주입한다.\n// ---------------------------------------------------------------------------\nexport type ButtonGroupProps = ViewProps &\n  VariantProps<typeof buttonGroupVariants> & {\n    children?: ReactNode;\n  };\n\nconst ButtonGroup = forwardRef<BridgeViewRef, ButtonGroupProps>(\n  ({ className, orientation, children, ...props }, ref) => {\n    const resolvedOrientation: ButtonGroupOrientation =\n      orientation ?? \"horizontal\";\n    const items = Children.toArray(children);\n    const attached = items.map((child, index) => {\n      // 문자열 등 비（非）요소 자식은 그대로 둔다（Children.toArray가 null·\n      // boolean은 이미 걷어냈다）. React 19 타입은 unknown props로 좁히므로\n      // className을 받는 요소로 단언해 cloneElement한다.\n      if (!isValidElement(child)) {\n        return child;\n      }\n      const typedChild = child as ReactElement<{ className?: string }>;\n      return cloneElement(typedChild, {\n        className: cn(\n          typedChild.props.className,\n          buttonGroupAttachClasses(index, items.length, resolvedOrientation),\n        ),\n      });\n    });\n    return (\n      <View\n        ref={ref}\n        className={cn(buttonGroupVariants({ orientation }), className)}\n        {...props}\n      >\n        {attached}\n      </View>\n    );\n  },\n);\nButtonGroup.displayName = \"ButtonGroup\";\n\n// ---------------------------------------------------------------------------\n// ButtonGroupText — 그룹 안 텍스트 조각（예: 승수 \"×2\"）. View+Text 구조.\n// ---------------------------------------------------------------------------\nexport type ButtonGroupTextProps = ViewProps & {\n  children?: ReactNode;\n};\n\nconst ButtonGroupText = forwardRef<BridgeViewRef, ButtonGroupTextProps>(\n  ({ className, children, ...props }, ref) => (\n    <View\n      ref={ref}\n      className={cn(\n        // 원본 flex items-center gap-2 — 브리지 flex-col 기본이라 flex-row 명시.\n        \"flex flex-row items-center gap-2 rounded-md border border-border bg-muted px-4\",\n        className,\n      )}\n      {...props}\n    >\n      {/* 이중 지정 원칙: 배경·테두리는 View, 전경색은 내부 Text에 */}\n      <Text className=\"font-sans text-sm font-medium text-foreground\">\n        {children}\n      </Text>\n    </View>\n  ),\n);\nButtonGroupText.displayName = \"ButtonGroupText\";\n\n// ---------------------------------------------------------------------------\n// ButtonGroupSeparator — 그룹 안 구분선. 기본 vertical（가로 무리의 세로 줄）.\n// ---------------------------------------------------------------------------\nexport type ButtonGroupSeparatorProps = ViewProps & {\n  /** 구분선 방향 — 원본 기본값 vertical 유지（self-stretch로 교차축 채움） */\n  orientation?: \"horizontal\" | \"vertical\";\n};\n\nconst ButtonGroupSeparator = forwardRef<\n  BridgeViewRef,\n  ButtonGroupSeparatorProps\n>(({ className, orientation = \"vertical\", ...props }, ref) => (\n  <View\n    ref={ref}\n    className={cn(\n      // 원본 구분선 색은 bg-input.\n      \"self-stretch bg-input\",\n      orientation === \"vertical\" ? \"w-px\" : \"h-px w-full\",\n      className,\n    )}\n    {...props}\n  />\n));\nButtonGroupSeparator.displayName = \"ButtonGroupSeparator\";\n\nexport {\n  ButtonGroup,\n  ButtonGroupSeparator,\n  ButtonGroupText,\n  buttonGroupVariants,\n};\n",
      "type": "registry:ui",
      "target": "components/unikit/button-group.tsx"
    }
  ],
  "type": "registry:ui"
}
