{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pagination",
  "title": "Pagination",
  "description": "페이지 매김 — 7종 구성, ‹ › 글리프, isActive 페이지 스타일. Button 변형(buttonVariants) 재사용.",
  "dependencies": [
    "@unikit-bridge/ui",
    "class-variance-authority",
    "clsx",
    "tailwind-merge",
    "tailwindcss"
  ],
  "registryDependencies": [
    "utils",
    "button"
  ],
  "files": [
    {
      "path": "registry/ui/pagination.tsx",
      "content": "// Pagination — shadcn/ui new-york-v4 pagination 포팅（shadcn-ref/ui/pagination.tsx）.\n// 7종 export. lucide 아이콘 제거.\n// 포팅 판단:\n// - 원본은 <a>에 buttonVariants를 얹는다 — 포팅은 Pressable role=\"link\"에\n//   ./button의 buttonVariants（컨테이너） + buttonTextVariants（내부 Text 전경색,\n//   이중 지정）를 함께 얹는다. import 경로 \"./button\"은 양 트리（src·registry）에서\n//   동일하다.\n// - 원본의 data-active·aria-current=\"page\" → isActive?: boolean prop 조건부\n//   클래스（ghost↔outline 변형 전환）로 재현하고, aria-current=\"page\"는 사이클 40\n//   브리지 확장（§2.1）으로 소급 지정한다（웹 전용 — RN 계약 없음, 시각 강조가 담당）.\n// - 아이콘: ChevronLeftIcon·ChevronRightIcon·MoreHorizontalIcon — 브리지 SVG\n//   아이콘 프리미티브（lucide — primitives 경유）. Previous/Next 라벨은 원본의\n//   sm 미만 숨김（hidden sm:block）을 web:hidden web:sm:inline으로 재현 —\n//   네이티브에서는 항상 표시된다（터치 가독성）.\n// - PaginationLink의 children이 문자열（숫자 포함）이면 이중 지정 원칙대로 내부\n//   Text로 감싸고, ReactNode면 그대로 렌더한다（Previous/Next는 아이콘+라벨\n//   두 Text를 flex 간격으로 배치하기 위해 노드를 직접 넘긴다）.\n// - 원본 <nav>의 role=\"navigation\"은 BridgeRole에 없어 미지원 — 라벨만 유지.\n//   sr-only 보조 텍스트는 웹 전용 클래스라 생략（Ellipsis는 어차피 aria-hidden）.\n// - 터치 타깃 44px 보정은 button.tsx와 같은 hitSlop 기준（§3.1）.\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n  ChevronLeftIcon,\n  ChevronRightIcon,\n  MoreHorizontalIcon,\n  Pressable,\n  Text,\n  View,\n  type BridgePressableRef,\n  type BridgeViewRef,\n  type PressableProps,\n  type ViewProps,\n} from \"@unikit-bridge/ui/primitives\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants, buttonTextVariants } from \"./button\";\n\nconst paginationVariants = cva(\"mx-auto w-full flex-row justify-center\");\nconst paginationContentVariants = cva(\"flex-row items-center gap-1\");\n\n// 방향 아이콘 전경색 cva — export API 호환용（이름 유지; 본문 ChevronIcon은\n// 브리지 lucide 아이콘 프리미티브로 대체되어 있다）.\nconst paginationGlyphVariants = cva(\"text-base leading-none text-foreground\");\n// Previous/Next 라벨 — 웹에서는 sm 미만 숨김（원본 hidden sm:block 재현）.\nconst paginationLabelVariants = cva(\n  \"font-sans text-sm font-medium text-foreground web:whitespace-nowrap web:hidden web:sm:inline\",\n);\nconst paginationEllipsisVariants = cva(\n  \"h-9 w-9 flex-row items-center justify-center\",\n);\nconst paginationEllipsisTextVariants = cva(\n  \"text-base leading-none text-foreground\",\n);\n\n// 터치 타깃 보정 — button.tsx의 HIT_SLOP과 같은 기준（44px − 시각높이）/2.\n// button 사이즈 정비（사이클 71）에 맞춰 h-9 기준으로 갱신.\nconst HIT_SLOP = {\n  xs: 10,\n  sm: 6,\n  default: 4,\n  lg: 2,\n  icon: 4,\n  \"icon-xs\": 10,\n  \"icon-sm\": 6,\n  \"icon-lg\": 2,\n} as const;\n\nexport type PaginationProps = ViewProps;\nexport type PaginationContentProps = ViewProps;\nexport type PaginationItemProps = ViewProps;\nexport type PaginationEllipsisProps = ViewProps;\n\nexport type PaginationLinkProps = PressableProps &\n  Pick<VariantProps<typeof buttonVariants>, \"size\"> & {\n    /** 현재 페이지 — 원본 data-active 대체（outline 변형으로 강조） */\n    isActive?: boolean;\n    children?: ReactNode;\n  };\nexport type PaginationPreviousProps = PaginationLinkProps & {\n  /** 이전 라벨 텍스트（기본 \"Previous\" — 현지화 시 지정, G4） */\n  label?: string;\n};\nexport type PaginationNextProps = PaginationLinkProps & {\n  /** 다음 라벨 텍스트（기본 \"Next\" — 현지화 시 지정, G4） */\n  label?: string;\n};\n\nconst Pagination = forwardRef<BridgeViewRef, PaginationProps>(\n  ({ className, ...props }, ref) => (\n    <View\n      ref={ref}\n      accessibilityLabel=\"pagination\"\n      className={cn(paginationVariants(), className)}\n      {...props}\n    />\n  ),\n);\nPagination.displayName = \"Pagination\";\n\nconst PaginationContent = forwardRef<BridgeViewRef, PaginationContentProps>(\n  ({ className, ...props }, ref) => (\n    <View\n      ref={ref}\n      className={cn(paginationContentVariants(), className)}\n      {...props}\n    />\n  ),\n);\nPaginationContent.displayName = \"PaginationContent\";\n\n// 원본 <li>처럼 기본 클래스 없이 props를 그대로 통과시킨다.\nconst PaginationItem = forwardRef<BridgeViewRef, PaginationItemProps>(\n  ({ ...props }, ref) => <View ref={ref} {...props} />,\n);\nPaginationItem.displayName = \"PaginationItem\";\n\nconst PaginationLink = forwardRef<BridgePressableRef, PaginationLinkProps>(\n  (\n    { className, isActive, size = \"icon\", children, hitSlop, ...props },\n    ref,\n  ) => {\n    const variant = isActive ? \"outline\" : \"ghost\";\n    const resolvedSize = size ?? \"icon\";\n    return (\n      <Pressable\n        ref={ref}\n        accessibilityRole=\"link\"\n        aria-current={isActive ? \"page\" : undefined}\n        hitSlop={hitSlop ?? HIT_SLOP[resolvedSize]}\n        className={cn(\n          buttonVariants({ variant, size }),\n          // 활성 페이지 강조 테두리 — outline 변형의 border-input은 1.27:1로\n          // 현재 페이지 표시가 배경에 묻힌다. foreground/50（≥3:1, G4）로 조정.\n          isActive && \"border-foreground/50\",\n          className,\n        )}\n        {...props}\n      >\n        {typeof children === \"string\" || typeof children === \"number\" ? (\n          <Text className={cn(buttonTextVariants({ variant }))}>\n            {children}\n          </Text>\n        ) : (\n          children\n        )}\n      </Pressable>\n    );\n  },\n);\nPaginationLink.displayName = \"PaginationLink\";\n\nconst PaginationPrevious = forwardRef<\n  BridgePressableRef,\n  PaginationPreviousProps\n>(({ className, label = \"Previous\", ...props }, ref) => (\n  <PaginationLink\n    ref={ref}\n    accessibilityLabel=\"Go to previous page\"\n    size=\"default\"\n    className={cn(\"gap-1 px-2.5 web:sm:pl-2.5\", className)}\n    {...props}\n  >\n    <ChevronLeftIcon className=\"size-4\" />\n    <Text className={cn(paginationLabelVariants())}>{label}</Text>\n  </PaginationLink>\n));\nPaginationPrevious.displayName = \"PaginationPrevious\";\n\nconst PaginationNext = forwardRef<BridgePressableRef, PaginationNextProps>(\n  ({ className, label = \"Next\", ...props }, ref) => (\n    <PaginationLink\n      ref={ref}\n      accessibilityLabel=\"Go to next page\"\n      size=\"default\"\n      className={cn(\"gap-1 px-2.5 web:sm:pr-2.5\", className)}\n      {...props}\n    >\n      <Text className={cn(paginationLabelVariants())}>{label}</Text>\n      <ChevronRightIcon className=\"size-4\" />\n    </PaginationLink>\n  ),\n);\nPaginationNext.displayName = \"PaginationNext\";\n\n// 페이지 생략 아이콘 — MoreHorizontalIcon.\nconst PaginationEllipsis = forwardRef<BridgeViewRef, PaginationEllipsisProps>(\n  ({ className, ...props }, ref) => (\n    <View\n      ref={ref}\n      aria-hidden\n      className={cn(paginationEllipsisVariants(), className)}\n      {...props}\n    >\n      <MoreHorizontalIcon className=\"size-4 text-muted-foreground\" />\n    </View>\n  ),\n);\nPaginationEllipsis.displayName = \"PaginationEllipsis\";\n\nexport {\n  Pagination,\n  PaginationContent,\n  PaginationLink,\n  PaginationItem,\n  PaginationPrevious,\n  PaginationNext,\n  PaginationEllipsis,\n  paginationVariants,\n  paginationContentVariants,\n  paginationGlyphVariants,\n  paginationLabelVariants,\n  paginationEllipsisVariants,\n  paginationEllipsisTextVariants,\n};\n",
      "type": "registry:ui",
      "target": "components/unikit/pagination.tsx"
    }
  ],
  "type": "registry:ui"
}
