@poodle-kit/ui 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Button.tsx"],"sourcesContent":["import type { ButtonHTMLAttributes, ReactNode } from \"react\";\n\ntype Variant = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\ntype Size = \"sm\" | \"md\" | \"lg\";\n\nexport type ButtonProps = {\n label?: string;\n children?: ReactNode;\n variant?: Variant;\n size?: Size;\n fullWidth?: boolean;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\nconst base =\n \"inline-flex items-center justify-center rounded-lg font-semibold \" +\n \"transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 \" +\n \"disabled:opacity-50 disabled:cursor-not-allowed\";\n\nconst sizes: Record<Size, string> = {\n sm: \"h-8 px-3 text-sm\",\n md: \"h-10 px-4 text-sm\",\n lg: \"h-12 px-5 text-base\",\n};\n\nconst variants: Record<Variant, string> = {\n primary:\n \"bg-blue-600 text-white hover:bg-blue-700 focus-visible:ring-blue-600 shadow-sm\",\n secondary:\n \"bg-gray-100 text-gray-900 hover:bg-gray-200 focus-visible:ring-gray-400 border border-gray-200\",\n ghost:\n \"bg-transparent text-gray-900 hover:bg-gray-100 focus-visible:ring-gray-400\",\n danger:\n \"bg-red-600 text-white hover:bg-red-700 focus-visible:ring-red-600 shadow-sm\",\n};\n\n// className 합치기(외부 라이브러리 없이)\nfunction cx(...classes: Array<string | undefined | false>) {\n return classes.filter(Boolean).join(\" \");\n}\n\nexport function Button({\n label,\n children,\n variant = \"primary\",\n size = \"md\",\n fullWidth = false,\n className,\n ...rest\n}: ButtonProps) {\n return (\n <button\n type=\"button\"\n className={cx(\n base,\n sizes[size],\n variants[variant],\n fullWidth && \"w-full\",\n className\n )}\n {...rest}\n >\n {children || label}\n </button>\n );\n}\n"],"mappings":";AAkDI;AArCJ,IAAM,OACJ;AAIF,IAAM,QAA8B;AAAA,EAClC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEA,IAAM,WAAoC;AAAA,EACxC,SACE;AAAA,EACF,WACE;AAAA,EACF,OACE;AAAA,EACF,QACE;AACJ;AAGA,SAAS,MAAM,SAA4C;AACzD,SAAO,QAAQ,OAAO,OAAO,EAAE,KAAK,GAAG;AACzC;AAEO,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,YAAY;AAAA,EACZ;AAAA,EACA,GAAG;AACL,GAAgB;AACd,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA,MAAM,IAAI;AAAA,QACV,SAAS,OAAO;AAAA,QAChB,aAAa;AAAA,QACb;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH,sBAAY;AAAA;AAAA,EACf;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/components/button/button.tsx","../src/lib/cn.ts","../src/components/input/input.tsx","../src/components/input/input-message.tsx","../src/components/image-uploader/image-uploader.tsx","../src/icons/index.tsx","../src/components/image-uploader/use-image-uploader.ts","../src/theme/provider.tsx","../src/theme/theme-to-css-vars.ts","../src/theme/use-theme.ts","../src/theme/types.ts","../src/theme/defaults/default.ts"],"sourcesContent":["import { type ButtonHTMLAttributes, forwardRef } from 'react';\r\nimport { Slot } from '@radix-ui/react-slot';\r\nimport { cva, type VariantProps } from 'class-variance-authority';\r\nimport { cn } from '../../lib/cn';\r\n\r\nconst buttonVariants = cva(\r\n 'inline-flex items-center justify-center rounded-[var(--radius-md)] font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\r\n {\r\n variants: {\r\n variant: {\r\n default:\r\n 'bg-primary text-primary-foreground hover:bg-primary/90',\r\n secondary:\r\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\r\n info: 'bg-info text-info-foreground hover:bg-info/90',\r\n danger: 'bg-danger text-danger-foreground hover:bg-danger/90',\r\n warning:\r\n 'bg-warning text-warning-foreground hover:bg-warning/90',\r\n success:\r\n 'bg-success text-success-foreground hover:bg-success/90',\r\n ghost: 'hover:bg-accent hover:text-accent-foreground',\r\n outline:\r\n 'border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground',\r\n link: 'text-primary underline-offset-4 hover:underline',\r\n },\r\n size: {\r\n default: 'h-10 px-4 py-2',\r\n sm: 'h-9 rounded-[var(--radius-md)] px-3',\r\n lg: 'h-11 rounded-[var(--radius-md)] px-8',\r\n icon: 'h-10 w-10',\r\n },\r\n },\r\n defaultVariants: {\r\n variant: 'default',\r\n size: 'default',\r\n },\r\n },\r\n);\r\n\r\nexport interface ButtonProps\r\n extends\r\n ButtonHTMLAttributes<HTMLButtonElement>,\r\n VariantProps<typeof buttonVariants> {\r\n asChild?: boolean;\r\n}\r\n\r\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\r\n ({ className, variant, size, asChild = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'button';\r\n return (\r\n <Comp\r\n className={cn(buttonVariants({ variant, size, className }))}\r\n ref={ref}\r\n type=\"button\"\r\n {...props}\r\n />\r\n );\r\n },\r\n);\r\n\r\nButton.displayName = 'Button';\r\n\r\nexport { Button, buttonVariants };\r\n","import { type ClassValue, clsx } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","import {\r\n type InputHTMLAttributes,\r\n forwardRef,\r\n type ReactNode,\r\n} from 'react';\r\nimport { cva } from 'class-variance-authority';\r\nimport { cn } from '../../lib/cn';\r\n\r\n/**\r\n * 상태(state)와 크기(size)에 따른 input 스타일 변형\r\n *\r\n * state:\r\n * - default: 기본 포커스 링\r\n * - error: 빨간 테두리 + 포커스 링\r\n * - success: 초록 테두리 + 포커스 링\r\n */\r\nconst inputVariants = cva(\r\n 'flex w-full rounded-[var(--radius-md)] border border-input bg-background text-sm placeholder:text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',\r\n {\r\n variants: {\r\n size: {\r\n default: 'h-10 px-3 py-2',\r\n sm: 'h-9 px-2 text-xs',\r\n lg: 'h-11 px-4',\r\n },\r\n state: {\r\n default: 'focus-visible:ring-ring',\r\n error: 'border-danger focus-visible:ring-danger',\r\n success: 'border-success focus-visible:ring-success',\r\n },\r\n },\r\n defaultVariants: {\r\n size: 'default',\r\n state: 'default',\r\n },\r\n },\r\n);\r\n\r\nexport interface InputProps extends Omit<\r\n InputHTMLAttributes<HTMLInputElement>,\r\n 'size'\r\n> {\r\n /** input 크기 */\r\n size?: 'default' | 'sm' | 'lg';\r\n /** 라벨 텍스트 */\r\n label?: string;\r\n /** 에러 상태 — 빨간 테두리, aria-invalid 자동 설정 */\r\n error?: boolean;\r\n /** 성공 상태 — 초록 테두리 */\r\n success?: boolean;\r\n /** 좌측 아이콘 (ReactNode) */\r\n leftIcon?: ReactNode;\r\n /** 우측 아이콘 (ReactNode) */\r\n rightIcon?: ReactNode;\r\n /** 좌측 아이콘 클릭 핸들러 — 없으면 아이콘이 클릭 불가 */\r\n onLeftIconClick?: () => void;\r\n /** 우측 아이콘 클릭 핸들러 — 없으면 아이콘이 클릭 불가 */\r\n onRightIconClick?: () => void;\r\n /** wrapper div에 적용할 className */\r\n className?: string;\r\n /** input 요소에만 적용할 className */\r\n inputClassName?: string;\r\n}\r\n\r\nconst Input = forwardRef<HTMLInputElement, InputProps>(\r\n (\r\n {\r\n className,\r\n inputClassName,\r\n size,\r\n error,\r\n success,\r\n label,\r\n id,\r\n leftIcon,\r\n rightIcon,\r\n onLeftIconClick,\r\n onRightIconClick,\r\n required,\r\n disabled,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n // error > success > default 우선순위로 state 결정\r\n const state = error ? 'error' : success ? 'success' : 'default';\r\n\r\n return (\r\n <div className={cn('flex flex-col gap-1', className)}>\r\n {/* 라벨 — required이면 * 표시 */}\r\n {label && (\r\n <label\r\n htmlFor={id}\r\n className={cn(\r\n 'text-sm font-medium',\r\n disabled && 'opacity-50',\r\n )}\r\n >\r\n {label}\r\n {required && (\r\n <span className=\"ml-1 text-danger\" aria-label=\"필수\">\r\n *\r\n </span>\r\n )}\r\n </label>\r\n )}\r\n\r\n {/* input + 아이콘을 감싸는 relative 컨테이너 */}\r\n <div className=\"relative\">\r\n {/* 좌측 아이콘 — onLeftIconClick 없으면 pointer-events-none */}\r\n {leftIcon && (\r\n <button\r\n type=\"button\"\r\n disabled={!onLeftIconClick}\r\n aria-label=\"left icon\"\r\n className={cn(\r\n 'absolute left-3 top-1/2 z-10 -translate-y-1/2',\r\n onLeftIconClick\r\n ? 'cursor-pointer'\r\n : 'pointer-events-none cursor-default',\r\n disabled && 'opacity-50',\r\n )}\r\n onClick={onLeftIconClick}\r\n >\r\n {leftIcon}\r\n </button>\r\n )}\r\n\r\n <input\r\n id={id}\r\n ref={ref}\r\n required={required}\r\n disabled={disabled}\r\n // error 상태일 때 스크린리더가 invalid 필드로 인식\r\n aria-invalid={error || undefined}\r\n className={cn(\r\n inputVariants({ size, state }),\r\n // 아이콘이 있을 때 텍스트가 아이콘에 가리지 않도록 패딩 추가\r\n leftIcon && 'pl-9',\r\n rightIcon && 'pr-9',\r\n inputClassName,\r\n )}\r\n {...props}\r\n />\r\n\r\n {/* 우측 아이콘 — onRightIconClick 없으면 pointer-events-none */}\r\n {rightIcon && (\r\n <button\r\n type=\"button\"\r\n disabled={!onRightIconClick}\r\n aria-label=\"right icon\"\r\n className={cn(\r\n 'absolute right-3 top-1/2 z-10 -translate-y-1/2',\r\n onRightIconClick\r\n ? 'cursor-pointer'\r\n : 'pointer-events-none cursor-default',\r\n disabled && 'opacity-50',\r\n )}\r\n onClick={onRightIconClick}\r\n >\r\n {rightIcon}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nInput.displayName = 'Input';\r\n\r\nexport { Input, inputVariants };\r\n","import type { ReactNode } from 'react';\r\nimport { cn } from '../../lib/cn';\r\n\r\nexport interface InputMessageProps {\r\n /** 표시할 메시지 텍스트 */\r\n children: ReactNode;\r\n /** true이면 빨간색(에러), false/undefined이면 회색(도움말) */\r\n error?: boolean;\r\n className?: string;\r\n}\r\n\r\n/**\r\n * InputMessage — Input 하단에 표시되는 에러/헬프 메시지 컴포넌트\r\n *\r\n * Input과 분리된 별도 컴포넌트로, 애니메이션이 필요하면\r\n * 이 컴포넌트를 motion.div로 감싸서 사용한다.\r\n *\r\n * @example\r\n * // 기본 사용\r\n * <InputMessage error>올바른 이메일을 입력해주세요.</InputMessage>\r\n * <InputMessage>8자 이상 입력해주세요.</InputMessage>\r\n *\r\n * // 애니메이션 적용\r\n * <AnimatePresence>\r\n * {error && (\r\n * <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>\r\n * <InputMessage error>{error}</InputMessage>\r\n * </motion.div>\r\n * )}\r\n * </AnimatePresence>\r\n */\r\nexport function InputMessage({\r\n children,\r\n error,\r\n className,\r\n}: InputMessageProps) {\r\n return (\r\n <p\r\n className={cn(\r\n 'text-xs',\r\n error ? 'text-danger' : 'text-muted-foreground',\r\n className,\r\n )}\r\n >\r\n {children}\r\n </p>\r\n );\r\n}\r\n","'use client';\r\n\r\nimport { forwardRef, useId } from 'react';\r\nimport type { ReactNode } from 'react';\r\nimport { cva, type VariantProps } from 'class-variance-authority';\r\nimport { cn } from '../../lib/cn';\r\nimport { PlusIcon, XIcon } from '../../icons';\r\nimport {\r\n useImageUploader,\r\n type ExistingImage,\r\n type NewImageFile,\r\n type UseImageUploaderOptions,\r\n} from './use-image-uploader';\r\n\r\n// ─── CVA Variants ─────────────────────────────────────────────────────────────\r\n\r\nconst imageUploaderVariants = cva('flex gap-2', {\r\n variants: {\r\n layout: {\r\n /** 가로 스크롤 행 (기본값) */\r\n row: 'flex-row flex-nowrap overflow-x-auto',\r\n /** 자동 줄바꿈 격자 */\r\n grid: 'flex-wrap',\r\n },\r\n },\r\n defaultVariants: { layout: 'row' },\r\n});\r\n\r\n// ─── Props ────────────────────────────────────────────────────────────────────\r\n\r\nexport interface ImageUploaderProps\r\n extends\r\n UseImageUploaderOptions,\r\n VariantProps<typeof imageUploaderVariants> {\r\n className?: string;\r\n /** true이면 모든 인터랙션을 비활성화해요 */\r\n disabled?: boolean;\r\n /**\r\n * 이미지 추가 버튼의 내용을 교체할 수 있어요.\r\n * 기본값은 + 아이콘과 현재/최대 개수를 표시해요.\r\n */\r\n placeholder?: ReactNode;\r\n}\r\n\r\n// ─── Private Sub-components ──────────────────────────────────────────────────\r\n\r\ninterface AddButtonProps {\r\n onClick: () => void;\r\n disabled?: boolean;\r\n current: number;\r\n max: number;\r\n children?: ReactNode;\r\n}\r\n\r\nfunction AddButton({\r\n onClick,\r\n disabled,\r\n current,\r\n max,\r\n children,\r\n}: AddButtonProps) {\r\n return (\r\n <button\r\n type=\"button\"\r\n onClick={onClick}\r\n disabled={disabled}\r\n aria-label={`이미지 추가 (${current}/${max})`}\r\n className={cn(\r\n 'shrink-0 w-20 h-20',\r\n 'flex flex-col items-center justify-center gap-1',\r\n 'rounded-lg',\r\n 'border-2 border-dashed border-border',\r\n 'bg-muted text-muted-foreground',\r\n 'cursor-pointer select-none',\r\n 'transition-colors duration-150',\r\n 'hover:bg-accent hover:text-accent-foreground hover:border-border',\r\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\r\n 'disabled:pointer-events-none disabled:opacity-50',\r\n )}\r\n >\r\n {children ?? (\r\n <>\r\n <PlusIcon className=\"w-5 h-5\" />\r\n <span className=\"text-[10px] font-medium leading-none tabular-nums\">\r\n {current}/{max}\r\n </span>\r\n </>\r\n )}\r\n </button>\r\n );\r\n}\r\n\r\ninterface ImageItemProps {\r\n src: string;\r\n alt: string;\r\n onRemove: () => void;\r\n disabled?: boolean;\r\n}\r\n\r\nfunction ImageItem({ src, alt, onRemove, disabled }: ImageItemProps) {\r\n return (\r\n <div className=\"relative shrink-0 w-20 h-20 group/item\">\r\n <img\r\n src={src}\r\n alt={alt}\r\n draggable={false}\r\n className=\"w-full h-full object-cover rounded-lg\"\r\n />\r\n {!disabled && (\r\n <button\r\n type=\"button\"\r\n onClick={onRemove}\r\n aria-label={`${alt} 삭제`}\r\n className={cn(\r\n 'absolute -top-1.5 -right-1.5',\r\n 'w-5 h-5 rounded-full',\r\n 'flex items-center justify-center',\r\n 'bg-foreground text-background',\r\n 'transition-all duration-150',\r\n 'opacity-0 scale-75',\r\n 'group-hover/item:opacity-100 group-hover/item:scale-100',\r\n 'group-focus-within/item:opacity-100 group-focus-within/item:scale-100',\r\n 'hover:scale-110 active:scale-90',\r\n 'focus-visible:opacity-100 focus-visible:scale-100',\r\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',\r\n )}\r\n >\r\n <XIcon strokeWidth=\"2.5\" />\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// ─── Main Component ───────────────────────────────────────────────────────────\r\n\r\nexport const ImageUploader = forwardRef<\r\n HTMLDivElement,\r\n ImageUploaderProps\r\n>(\r\n (\r\n {\r\n className,\r\n layout,\r\n disabled,\r\n placeholder,\r\n initialImages,\r\n maxImages = 4,\r\n maxSizeMb,\r\n accept,\r\n onFileSelect,\r\n onDeleteExisting,\r\n onError,\r\n },\r\n ref,\r\n ) => {\r\n const uid = useId();\r\n\r\n const {\r\n existingImages,\r\n newImages,\r\n totalCount,\r\n isDragActive,\r\n inputRef,\r\n openFilePicker,\r\n removeExisting,\r\n removeNew,\r\n dragHandlers,\r\n inputProps,\r\n } = useImageUploader({\r\n initialImages,\r\n maxImages,\r\n maxSizeMb,\r\n accept,\r\n onFileSelect,\r\n onDeleteExisting,\r\n onError,\r\n });\r\n\r\n const canAdd = !disabled && totalCount < maxImages;\r\n\r\n return (\r\n <div ref={ref} className={cn('flex flex-col gap-2', className)}>\r\n {/* Screen reader live region — count 변경 시 자동 공지 */}\r\n <div\r\n role=\"status\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"true\"\r\n className=\"sr-only\"\r\n >\r\n {totalCount > 0\r\n ? `이미지 ${totalCount}개 선택됨. 최대 ${maxImages}개까지 추가할 수 있어요.`\r\n : `이미지를 추가해주세요. 최대 ${maxImages}개까지 추가할 수 있어요.`}\r\n </div>\r\n\r\n {/* Drag 활성 시 screen reader 긴급 공지 */}\r\n {isDragActive && (\r\n <span role=\"alert\" className=\"sr-only\">\r\n 파일을 여기에 놓아주세요\r\n </span>\r\n )}\r\n\r\n {/* 숨겨진 파일 input (탭 순서에서 제외, 버튼이 대신 처리) */}\r\n <input\r\n ref={inputRef}\r\n id={`${uid}-input`}\r\n type=\"file\"\r\n tabIndex={-1}\r\n aria-hidden=\"true\"\r\n className=\"sr-only\"\r\n disabled={disabled}\r\n {...inputProps}\r\n />\r\n\r\n {/* Drop zone + 이미지 목록 */}\r\n <div\r\n role=\"group\"\r\n aria-label={`이미지 업로더, ${totalCount}/${maxImages}개 선택됨`}\r\n className={cn(\r\n imageUploaderVariants({ layout }),\r\n 'rounded-lg p-1 -ml-1',\r\n 'transition-all duration-200',\r\n isDragActive &&\r\n 'ring-2 ring-primary ring-offset-2 bg-primary/5',\r\n )}\r\n {...(canAdd ? dragHandlers : {})}\r\n >\r\n {/* 이미지 추가 버튼 */}\r\n {canAdd && (\r\n <AddButton\r\n onClick={openFilePicker}\r\n disabled={disabled}\r\n current={totalCount}\r\n max={maxImages}\r\n >\r\n {placeholder}\r\n </AddButton>\r\n )}\r\n\r\n {/* 기존 이미지 (sequence 순 정렬) */}\r\n {sortBySequence(existingImages).map((img, index) => (\r\n <ImageItem\r\n key={`existing-${img.id}`}\r\n src={img.url}\r\n alt={`이미지 ${index + 1}`}\r\n onRemove={() => removeExisting(img.id)}\r\n disabled={disabled}\r\n />\r\n ))}\r\n\r\n {/* 새로 선택한 이미지 */}\r\n {newImages.map((item, index) => (\r\n <ImageItem\r\n key={`new-${item.id}`}\r\n src={item.preview}\r\n alt={`새 이미지 ${existingImages.length + index + 1}`}\r\n onRemove={() => removeNew(item.id)}\r\n disabled={disabled}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n },\r\n);\r\n\r\nImageUploader.displayName = 'ImageUploader';\r\n\r\n// ─── Helpers ──────────────────────────────────────────────────────────────────\r\n\r\nfunction sortBySequence(images: ExistingImage[]): ExistingImage[] {\r\n return [...images].sort(\r\n (a, b) => (a.sequence ?? 0) - (b.sequence ?? 0),\r\n );\r\n}\r\n\r\n// ─── Exports ──────────────────────────────────────────────────────────────────\r\n\r\nexport { imageUploaderVariants };\r\nexport type { ExistingImage, NewImageFile };\r\n","import type { SVGProps } from 'react';\r\n\r\n// ─── Base ─────────────────────────────────────────────────────────────────────\r\n\r\ntype IconProps = SVGProps<SVGSVGElement>;\r\n\r\nfunction createIcon(paths: React.ReactNode, defaultSize = 24) {\r\n return function Icon({\r\n width = defaultSize,\r\n height = defaultSize,\r\n ...props\r\n }: IconProps) {\r\n return (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width={width}\r\n height={height}\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n {...props}\r\n >\r\n {paths}\r\n </svg>\r\n );\r\n };\r\n}\r\n\r\n// ─── Icons ────────────────────────────────────────────────────────────────────\r\n\r\nexport const PlusIcon = createIcon(\r\n <>\r\n <path d=\"M5 12h14\" />\r\n <path d=\"M12 5v14\" />\r\n </>,\r\n);\r\n\r\nexport const XIcon = createIcon(\r\n <>\r\n <path d=\"M18 6 6 18\" />\r\n <path d=\"m6 6 12 12\" />\r\n </>,\r\n 12,\r\n);\r\n","'use client';\r\n\r\nimport {\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from 'react';\r\nimport type React from 'react';\r\n\r\n// ─── Public Types ────────────────────────────────────────────────────────────\r\n\r\n/** 서버에서 받은 기존 이미지 */\r\nexport interface ExistingImage {\r\n id: number | string;\r\n url: string;\r\n /** 이미지 순서 (정렬에 사용) */\r\n sequence?: number;\r\n}\r\n\r\n/** 새로 선택한 파일 (미리보기 포함) */\r\nexport interface NewImageFile {\r\n file: File;\r\n /** `URL.createObjectURL()` 로 생성된 미리보기 URL */\r\n preview: string;\r\n /** React key / 삭제 식별자 */\r\n id: string;\r\n}\r\n\r\n/** 유효성 검사 에러 Union 타입 */\r\nexport type ImageUploaderError =\r\n | { type: 'MAX_IMAGES'; message: string; maxImages: number }\r\n | {\r\n type: 'MAX_SIZE';\r\n message: string;\r\n maxSizeMb: number;\r\n file: File;\r\n }\r\n | {\r\n type: 'INVALID_TYPE';\r\n message: string;\r\n file: File;\r\n accept: string;\r\n };\r\n\r\nexport interface UseImageUploaderOptions {\r\n /** 수정 모드에서 서버 이미지를 전달해요 */\r\n initialImages?: ExistingImage[];\r\n /** 최대 업로드 가능 이미지 수 (기본값: 4) */\r\n maxImages?: number;\r\n /** 파일 1개의 최대 크기 (MB). 미설정 시 제한 없음 */\r\n maxSizeMb?: number;\r\n /** 허용할 파일 형식 (기본값: 'image/*') */\r\n accept?: string;\r\n /** 현재 선택된 전체 File[] 배열이 변경될 때 호출돼요 */\r\n onFileSelect?: (files: File[]) => void;\r\n /** 기존 이미지가 삭제될 때 삭제된 id 배열을 전달해요 */\r\n onDeleteExisting?: (deletedIds: Array<number | string>) => void;\r\n /** 유효성 검사 실패 시 호출돼요 (toast 등 직접 처리) */\r\n onError?: (error: ImageUploaderError) => void;\r\n}\r\n\r\nexport interface UseImageUploaderReturn {\r\n /** 삭제되지 않은 기존 이미지 */\r\n existingImages: ExistingImage[];\r\n /** 새로 선택한 이미지 (미리보기 포함) */\r\n newImages: NewImageFile[];\r\n /** 기존 + 새 이미지 합산 개수 */\r\n totalCount: number;\r\n /** 드래그 활성 여부 */\r\n isDragActive: boolean;\r\n /** 파일 input 요소의 ref */\r\n inputRef: React.RefObject<HTMLInputElement>;\r\n /** 파일 선택 다이얼로그 열기 */\r\n openFilePicker: () => void;\r\n /** 기존 이미지 삭제 */\r\n removeExisting: (id: number | string) => void;\r\n /** 새로 선택한 이미지 삭제 */\r\n removeNew: (id: string) => void;\r\n /** drop zone에 spread할 drag 이벤트 핸들러 */\r\n dragHandlers: {\r\n onDragOver: React.DragEventHandler;\r\n onDragLeave: React.DragEventHandler;\r\n onDrop: React.DragEventHandler;\r\n };\r\n /** file input에 spread할 props */\r\n inputProps: {\r\n onChange: React.ChangeEventHandler<HTMLInputElement>;\r\n accept: string;\r\n multiple: boolean;\r\n };\r\n}\r\n\r\n// ─── Helpers ─────────────────────────────────────────────────────────────────\r\n\r\nfunction matchesAccept(file: File, accept: string): boolean {\r\n return accept\r\n .split(',')\r\n .map((s) => s.trim().toLowerCase())\r\n .some((pattern) => {\r\n if (pattern === '*' || pattern === '*/*') return true;\r\n if (pattern.startsWith('.'))\r\n return file.name.toLowerCase().endsWith(pattern);\r\n if (pattern.endsWith('/*'))\r\n return file.type.startsWith(pattern.slice(0, -2));\r\n return file.type === pattern;\r\n });\r\n}\r\n\r\n// ─── Hook ────────────────────────────────────────────────────────────────────\r\n\r\nexport function useImageUploader({\r\n initialImages,\r\n maxImages = 4,\r\n maxSizeMb,\r\n accept = 'image/*',\r\n onFileSelect,\r\n onDeleteExisting,\r\n onError,\r\n}: UseImageUploaderOptions): UseImageUploaderReturn {\r\n const [newImages, setNewImages] = useState<NewImageFile[]>([]);\r\n const [deletedIds, setDeletedIds] = useState<\r\n Array<number | string>\r\n >([]);\r\n const [isDragActive, setIsDragActive] = useState(false);\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n\r\n // 콜백 refs — 매 렌더 후 갱신해 stale closure 없이 최신 값 참조\r\n const onFileSelectRef = useRef(onFileSelect);\r\n const onDeleteExistingRef = useRef(onDeleteExisting);\r\n const onErrorRef = useRef(onError);\r\n useEffect(() => {\r\n onFileSelectRef.current = onFileSelect;\r\n onDeleteExistingRef.current = onDeleteExisting;\r\n onErrorRef.current = onError;\r\n });\r\n\r\n // 상태 refs — 콜백 내에서 최신 상태를 직접 읽기 위해 사용\r\n const newImagesRef = useRef<NewImageFile[]>([]);\r\n const deletedIdsRef = useRef<Array<number | string>>([]);\r\n const existingCountRef = useRef(0);\r\n\r\n const existingImages = useMemo(\r\n () =>\r\n (initialImages ?? []).filter(\r\n (img) => !deletedIds.includes(img.id),\r\n ),\r\n [initialImages, deletedIds],\r\n );\r\n\r\n // 렌더 후 refs 동기화\r\n useEffect(() => {\r\n newImagesRef.current = newImages;\r\n }, [newImages]);\r\n useEffect(() => {\r\n deletedIdsRef.current = deletedIds;\r\n }, [deletedIds]);\r\n useEffect(() => {\r\n existingCountRef.current = existingImages.length;\r\n }, [existingImages.length]);\r\n\r\n // 언마운트 시 모든 preview URL 해제\r\n useEffect(() => {\r\n return () => {\r\n newImagesRef.current.forEach((item) =>\r\n URL.revokeObjectURL(item.preview),\r\n );\r\n };\r\n }, []);\r\n\r\n const processFiles = useCallback(\r\n (files: File[]) => {\r\n const currentTotal =\r\n existingCountRef.current + newImagesRef.current.length;\r\n const onErr = onErrorRef.current;\r\n const onSelect = onFileSelectRef.current;\r\n\r\n if (currentTotal >= maxImages) {\r\n onErr?.({\r\n type: 'MAX_IMAGES',\r\n message: `이미지는 최대 ${maxImages}장까지 추가할 수 있어요.`,\r\n maxImages,\r\n });\r\n return;\r\n }\r\n\r\n const remainingSlots = maxImages - currentTotal;\r\n\r\n if (files.length > remainingSlots) {\r\n onErr?.({\r\n type: 'MAX_IMAGES',\r\n message: `이미지는 최대 ${maxImages}장까지 추가할 수 있어요.`,\r\n maxImages,\r\n });\r\n }\r\n\r\n const validFiles: NewImageFile[] = [];\r\n\r\n for (const file of files.slice(0, remainingSlots)) {\r\n if (!matchesAccept(file, accept)) {\r\n onErr?.({\r\n type: 'INVALID_TYPE',\r\n message: `지원하지 않는 파일 형식이에요.`,\r\n file,\r\n accept,\r\n });\r\n continue;\r\n }\r\n\r\n if (\r\n maxSizeMb !== undefined &&\r\n file.size > maxSizeMb * 1024 * 1024\r\n ) {\r\n onErr?.({\r\n type: 'MAX_SIZE',\r\n message: `${file.name}의 크기가 ${maxSizeMb}MB를 초과해요.`,\r\n maxSizeMb,\r\n file,\r\n });\r\n continue;\r\n }\r\n\r\n validFiles.push({\r\n file,\r\n preview: URL.createObjectURL(file),\r\n id: crypto.randomUUID(),\r\n });\r\n }\r\n\r\n if (validFiles.length === 0) return;\r\n\r\n const next = [...newImagesRef.current, ...validFiles];\r\n newImagesRef.current = next;\r\n setNewImages(next);\r\n onSelect?.(next.map((item) => item.file));\r\n },\r\n [maxImages, accept, maxSizeMb],\r\n );\r\n\r\n const removeExisting = useCallback((id: number | string) => {\r\n const next = [...deletedIdsRef.current, id];\r\n deletedIdsRef.current = next;\r\n setDeletedIds(next);\r\n onDeleteExistingRef.current?.(next);\r\n }, []);\r\n\r\n const removeNew = useCallback((id: string) => {\r\n const current = newImagesRef.current;\r\n const toRemove = current.find((item) => item.id === id);\r\n if (toRemove) URL.revokeObjectURL(toRemove.preview);\r\n const next = current.filter((item) => item.id !== id);\r\n newImagesRef.current = next;\r\n setNewImages(next);\r\n onFileSelectRef.current?.(next.map((item) => item.file));\r\n }, []);\r\n\r\n const handleChange = useCallback(\r\n (e: React.ChangeEvent<HTMLInputElement>) => {\r\n if (!e.target.files) return;\r\n processFiles(Array.from(e.target.files));\r\n e.target.value = '';\r\n },\r\n [processFiles],\r\n );\r\n\r\n const handleDragOver = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDragActive(true);\r\n }, []);\r\n\r\n const handleDragLeave = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // 자식 요소로 이동하는 경우는 무시\r\n if (e.currentTarget.contains(e.relatedTarget as Node)) return;\r\n setIsDragActive(false);\r\n }, []);\r\n\r\n const handleDrop = useCallback(\r\n (e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setIsDragActive(false);\r\n processFiles(Array.from(e.dataTransfer.files));\r\n },\r\n [processFiles],\r\n );\r\n\r\n return {\r\n existingImages,\r\n newImages,\r\n totalCount: existingImages.length + newImages.length,\r\n isDragActive,\r\n inputRef,\r\n openFilePicker: () => inputRef.current?.click(),\r\n removeExisting,\r\n removeNew,\r\n dragHandlers: {\r\n onDragOver: handleDragOver,\r\n onDragLeave: handleDragLeave,\r\n onDrop: handleDrop,\r\n },\r\n inputProps: {\r\n onChange: handleChange,\r\n accept,\r\n multiple: true,\r\n },\r\n };\r\n}\r\n","import React, {\r\n createContext,\r\n useEffect,\r\n useState,\r\n useMemo,\r\n} from 'react';\r\nimport type {\r\n Theme,\r\n ThemeProviderProps,\r\n ThemeProviderState,\r\n} from './types';\r\nimport { themeToCssVars, applyCssVars } from './theme-to-css-vars';\r\n\r\nexport const ThemeContext = createContext<\r\n ThemeProviderState | undefined\r\n>(undefined);\r\n\r\nexport function ThemeProvider({\r\n children,\r\n defaultTheme = 'system',\r\n storageKey = 'poodle-ui-theme',\r\n config,\r\n darkConfig,\r\n customThemes = {},\r\n enableColorSchemeSync = true,\r\n}: ThemeProviderProps) {\r\n const [theme, setTheme] = useState<Theme>(() => {\r\n if (typeof window === 'undefined') {\r\n return defaultTheme;\r\n }\r\n try {\r\n return (\r\n (localStorage.getItem(storageKey) as Theme) || defaultTheme\r\n );\r\n } catch {\r\n return defaultTheme;\r\n }\r\n });\r\n\r\n // Convert theme configs to CSS variables (memoized)\r\n const lightCssVars = useMemo(\r\n () => (config ? themeToCssVars(config) : null),\r\n [config],\r\n );\r\n\r\n const darkCssVars = useMemo(\r\n () => (darkConfig ? themeToCssVars(darkConfig) : null),\r\n [darkConfig],\r\n );\r\n\r\n useEffect(() => {\r\n const root = window.document.documentElement;\r\n\r\n root.classList.remove(\r\n 'light',\r\n 'dark',\r\n ...Object.keys(customThemes),\r\n );\r\n\r\n let actualTheme: string;\r\n\r\n if (theme === 'system') {\r\n actualTheme = window.matchMedia('(prefers-color-scheme: dark)')\r\n .matches\r\n ? 'dark'\r\n : 'light';\r\n } else {\r\n actualTheme = theme;\r\n }\r\n\r\n root.classList.add(actualTheme);\r\n\r\n if (enableColorSchemeSync) {\r\n const isDark =\r\n actualTheme === 'dark' || customThemes[actualTheme]?.dark;\r\n root.style.colorScheme = isDark ? 'dark' : 'light';\r\n }\r\n\r\n // Apply custom theme config (priority: config > customThemes)\r\n if (actualTheme === 'light' && lightCssVars) {\r\n applyCssVars(root, lightCssVars);\r\n } else if (actualTheme === 'dark' && darkCssVars) {\r\n applyCssVars(root, darkCssVars);\r\n } else if (customThemes[actualTheme]?.cssVars) {\r\n // Legacy support for customThemes\r\n Object.entries(customThemes[actualTheme].cssVars!).forEach(\r\n ([key, value]) => {\r\n root.style.setProperty(key, value);\r\n },\r\n );\r\n }\r\n }, [\r\n theme,\r\n lightCssVars,\r\n darkCssVars,\r\n customThemes,\r\n enableColorSchemeSync,\r\n ]);\r\n\r\n useEffect(() => {\r\n if (theme !== 'system') return;\r\n\r\n const mediaQuery = window.matchMedia(\r\n '(prefers-color-scheme: dark)',\r\n );\r\n const handler = () => {\r\n setTheme('system');\r\n };\r\n\r\n mediaQuery.addEventListener('change', handler);\r\n return () => mediaQuery.removeEventListener('change', handler);\r\n }, [theme]);\r\n\r\n const handleSetTheme = (newTheme: Theme) => {\r\n try {\r\n localStorage.setItem(storageKey, newTheme);\r\n } catch {\r\n // localStorage not available\r\n }\r\n setTheme(newTheme);\r\n };\r\n\r\n const value: ThemeProviderState = {\r\n theme,\r\n setTheme: handleSetTheme,\r\n };\r\n\r\n return (\r\n <ThemeContext.Provider value={value}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n}\r\n","import type { ThemeConfig } from './types';\r\n\r\n/**\r\n * Convert ThemeConfig to CSS variables object\r\n */\r\nexport function themeToCssVars(\r\n theme: ThemeConfig,\r\n): Record<string, string> {\r\n const cssVars: Record<string, string> = {};\r\n\r\n // Colors\r\n if (theme.colors) {\r\n Object.entries(theme.colors).forEach(([key, value]) => {\r\n if (typeof value === 'string') {\r\n cssVars[`--color-${key}`] = value;\r\n } else if (typeof value === 'object' && value !== null) {\r\n if ('DEFAULT' in value) {\r\n cssVars[`--color-${key}`] = value.DEFAULT;\r\n }\r\n if ('foreground' in value) {\r\n cssVars[`--color-${key}-foreground`] = value.foreground;\r\n }\r\n }\r\n });\r\n }\r\n\r\n // Radius\r\n if (theme.radius) {\r\n Object.entries(theme.radius).forEach(([key, value]) => {\r\n cssVars[`--radius-${key}`] = value;\r\n });\r\n }\r\n\r\n // Font sizes\r\n if (theme.fontSize) {\r\n Object.entries(theme.fontSize).forEach(([key, value]) => {\r\n if (Array.isArray(value)) {\r\n const [size, config] = value;\r\n cssVars[`--text-${key}`] = size;\r\n if (config.lineHeight) {\r\n cssVars[`--leading-${key}`] = config.lineHeight;\r\n }\r\n } else {\r\n cssVars[`--text-${key}`] = value;\r\n }\r\n });\r\n }\r\n\r\n // Font families\r\n if (theme.fontFamily) {\r\n Object.entries(theme.fontFamily).forEach(([key, value]) => {\r\n cssVars[`--font-${key}`] = value.join(', ');\r\n });\r\n }\r\n\r\n // Font weights\r\n if (theme.fontWeight) {\r\n Object.entries(theme.fontWeight).forEach(([key, value]) => {\r\n cssVars[`--font-weight-${key}`] = value;\r\n });\r\n }\r\n\r\n // Shadows\r\n if (theme.shadows) {\r\n Object.entries(theme.shadows).forEach(([key, value]) => {\r\n cssVars[`--shadow-${key}`] = value;\r\n });\r\n }\r\n\r\n // Z-index\r\n if (theme.zIndex) {\r\n Object.entries(theme.zIndex).forEach(([key, value]) => {\r\n cssVars[`--z-${key}`] = value.toString();\r\n });\r\n }\r\n\r\n // Animation\r\n if (theme.animation) {\r\n if (theme.animation.duration) {\r\n Object.entries(theme.animation.duration).forEach(\r\n ([key, value]) => {\r\n cssVars[`--duration-${key}`] = value;\r\n },\r\n );\r\n }\r\n if (theme.animation.ease) {\r\n Object.entries(theme.animation.ease).forEach(([key, value]) => {\r\n cssVars[`--ease-${key}`] = value;\r\n });\r\n }\r\n }\r\n\r\n // Spacing (Tailwind v4 compatible)\r\n if (theme.spacing) {\r\n Object.entries(theme.spacing).forEach(([key, value]) => {\r\n cssVars[`--spacing-${key}`] = value;\r\n });\r\n }\r\n\r\n return cssVars;\r\n}\r\n\r\n/**\r\n * Apply CSS variables to an element\r\n */\r\nexport function applyCssVars(\r\n element: HTMLElement,\r\n cssVars: Record<string, string>,\r\n): void {\r\n Object.entries(cssVars).forEach(([key, value]) => {\r\n element.style.setProperty(key, value);\r\n });\r\n}\r\n\r\n/**\r\n * Remove CSS variables from an element\r\n */\r\nexport function removeCssVars(\r\n element: HTMLElement,\r\n keys: string[],\r\n): void {\r\n keys.forEach((key) => {\r\n element.style.removeProperty(key);\r\n });\r\n}\r\n\r\n/**\r\n * Format CSS variables object to CSS string\r\n * Useful for build-time CSS generation\r\n *\r\n * @example\r\n * ```ts\r\n * const cssVars = themeToCssVars(myTheme);\r\n * const cssString = formatCssVars(cssVars);\r\n * console.log(cssString);\r\n * // Output:\r\n * // --color-primary: oklch(0.5 0.2 250);\r\n * // --color-primary-foreground: oklch(1 0 0);\r\n * ```\r\n */\r\nexport function formatCssVars(\r\n cssVars: Record<string, string>,\r\n): string {\r\n return Object.entries(cssVars)\r\n .map(([key, value]) => ` ${key}: ${value};`)\r\n .join('\\n');\r\n}\r\n\r\n/**\r\n * Generate CSS variables string from theme config\r\n * Combines themeToCssVars + formatCssVars for convenience\r\n *\r\n * @example\r\n * ```ts\r\n * import { defineTheme, generateThemeCss } from '@poodle-kit/ui/theme';\r\n *\r\n * const myTheme = defineTheme({ colors: { ... } });\r\n * const cssString = generateThemeCss(myTheme);\r\n * console.log(cssString);\r\n * // Output:\r\n * // --color-primary: oklch(0.5 0.2 250);\r\n * // --color-primary-foreground: oklch(1 0 0);\r\n * ```\r\n */\r\nexport function generateThemeCss(theme: ThemeConfig): string {\r\n const cssVars = themeToCssVars(theme);\r\n return formatCssVars(cssVars);\r\n}\r\n","import { useContext } from 'react';\r\nimport { ThemeContext } from './provider';\r\nimport type { ThemeProviderState } from './types';\r\n\r\nexport function useTheme(): ThemeProviderState {\r\n const context = useContext(ThemeContext);\r\n\r\n if (context === undefined) {\r\n throw new Error('useTheme must be used within a ThemeProvider');\r\n }\r\n\r\n return context;\r\n}\r\n","export type Theme = 'light' | 'dark' | 'system' | string;\r\n\r\nexport type ColorValue =\r\n | string\r\n | {\r\n DEFAULT: string;\r\n foreground: string;\r\n };\r\n\r\nexport interface ThemeColors {\r\n // Page & Container colors\r\n background?: ColorValue;\r\n foreground?: ColorValue;\r\n muted?: ColorValue;\r\n accent?: ColorValue;\r\n card?: ColorValue;\r\n popover?: ColorValue;\r\n\r\n // Brand & Action colors\r\n primary?: ColorValue;\r\n secondary?: ColorValue;\r\n\r\n // Semantic colors\r\n info?: ColorValue;\r\n danger?: ColorValue;\r\n warning?: ColorValue;\r\n success?: ColorValue;\r\n destructive?: ColorValue;\r\n\r\n // Border & Input colors\r\n border?: ColorValue;\r\n input?: ColorValue;\r\n ring?: ColorValue;\r\n\r\n // Custom colors\r\n [key: string]: ColorValue | undefined;\r\n}\r\n\r\nexport interface ThemeConfig {\r\n colors: ThemeColors;\r\n spacing?: Record<string, string>;\r\n radius?: Record<string, string>;\r\n fontSize?: Record<\r\n string,\r\n string | [string, { lineHeight: string; letterSpacing?: string }]\r\n >;\r\n fontFamily?: Record<string, string[]>;\r\n fontWeight?: Record<string, string>;\r\n shadows?: Record<string, string>;\r\n zIndex?: Record<string, string>;\r\n animation?: {\r\n duration?: Record<string, string>;\r\n ease?: Record<string, string>;\r\n };\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface CustomThemeDefinition {\r\n dark?: boolean;\r\n cssVars?: Record<string, string>;\r\n}\r\n\r\nexport interface ThemeProviderProps {\r\n children: React.ReactNode;\r\n defaultTheme?: Theme;\r\n storageKey?: string;\r\n /** Custom theme configuration for light mode */\r\n config?: ThemeConfig;\r\n /** Custom theme configuration for dark mode */\r\n darkConfig?: ThemeConfig;\r\n /** Legacy: Custom theme definitions (deprecated, use config instead) */\r\n customThemes?: Record<string, CustomThemeDefinition>;\r\n enableColorSchemeSync?: boolean;\r\n}\r\n\r\nexport interface ThemeProviderState {\r\n theme: Theme;\r\n setTheme: (theme: Theme) => void;\r\n}\r\n\r\nexport function defineTheme<T extends ThemeConfig>(config: T): T {\r\n return config;\r\n}\r\n","/**\r\n * Default Theme Tokens\r\n *\r\n * This is a reference implementation showing how to define themes.\r\n * Copy this pattern to your project and customize the values.\r\n *\r\n * @example\r\n * ```tsx\r\n * // your-app/src/theme/my-theme.ts\r\n * import { defineTheme } from '@poodle-kit/ui/theme';\r\n *\r\n * export const myLightTheme = defineTheme({\r\n * colors: {\r\n * primary: { DEFAULT: 'oklch(0.5 0.2 250)', foreground: 'oklch(1 0 0)' },\r\n * // ... your custom colors\r\n * },\r\n * radius: { md: '0.5rem' },\r\n * });\r\n *\r\n * export const myDarkTheme = defineTheme({\r\n * colors: {\r\n * primary: { DEFAULT: 'oklch(0.7 0.2 250)', foreground: 'oklch(0.09 0 0)' },\r\n * // ... your custom colors\r\n * },\r\n * radius: { md: '0.5rem' },\r\n * });\r\n * ```\r\n *\r\n * Then use in your app:\r\n * ```tsx\r\n * import { ThemeProvider } from '@poodle-kit/ui';\r\n * import { myLightTheme, myDarkTheme } from './theme/my-theme';\r\n *\r\n * <ThemeProvider config={myLightTheme} darkConfig={myDarkTheme}>\r\n * <App />\r\n * </ThemeProvider>\r\n * ```\r\n */\r\n\r\nimport { defineTheme } from '../types';\r\n\r\n/**\r\n * Default Light Theme\r\n * Clean neutral design with semantic color tokens\r\n */\r\nexport const defaultLightTheme = defineTheme({\r\n colors: {\r\n // Page & Container colors\r\n background: {\r\n DEFAULT: 'oklch(1 0 0)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n muted: {\r\n DEFAULT: 'oklch(0.96 0 0)',\r\n foreground: 'oklch(0.45 0 0)',\r\n },\r\n\r\n accent: {\r\n DEFAULT: 'oklch(0.96 0 0)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n card: {\r\n DEFAULT: 'oklch(1 0 0)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n popover: {\r\n DEFAULT: 'oklch(1 0 0)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n // Brand & Action colors\r\n primary: {\r\n DEFAULT: 'oklch(0.09 0 0)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n secondary: {\r\n DEFAULT: 'oklch(0.45 0 0)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n // Semantic colors\r\n info: {\r\n DEFAULT: 'oklch(0.55 0.15 250)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n danger: {\r\n DEFAULT: 'oklch(0.576 0.204 27.325)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n warning: {\r\n DEFAULT: 'oklch(0.75 0.15 75)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n success: {\r\n DEFAULT: 'oklch(0.60 0.15 145)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n // Border & Input colors\r\n border: 'oklch(0.90 0 0)',\r\n input: 'oklch(0.90 0 0)',\r\n ring: 'oklch(0.09 0 0)',\r\n },\r\n\r\n radius: {\r\n none: '0',\r\n sm: '0.125rem',\r\n base: '0.25rem',\r\n md: '0.375rem',\r\n lg: '0.5rem',\r\n xl: '0.75rem',\r\n '2xl': '1rem',\r\n '3xl': '1.5rem',\r\n full: '9999px',\r\n },\r\n});\r\n\r\n/**\r\n * Default Dark Theme\r\n * Clean neutral design with semantic color tokens\r\n */\r\nexport const defaultDarkTheme = defineTheme({\r\n colors: {\r\n // Page & Container colors\r\n background: {\r\n DEFAULT: 'oklch(0.09 0 0)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n muted: {\r\n DEFAULT: 'oklch(0.17 0 0)',\r\n foreground: 'oklch(0.65 0 0)',\r\n },\r\n\r\n accent: {\r\n DEFAULT: 'oklch(0.17 0 0)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n card: {\r\n DEFAULT: 'oklch(0.09 0 0)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n popover: {\r\n DEFAULT: 'oklch(0.09 0 0)',\r\n foreground: 'oklch(0.98 0 0)',\r\n },\r\n\r\n // Brand & Action colors\r\n primary: {\r\n DEFAULT: 'oklch(0.98 0 0)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n secondary: {\r\n DEFAULT: 'oklch(0.65 0 0)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n // Semantic colors\r\n info: {\r\n DEFAULT: 'oklch(0.65 0.15 250)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n danger: {\r\n DEFAULT: 'oklch(0.701 0.191 29.234)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n warning: {\r\n DEFAULT: 'oklch(0.80 0.15 75)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n success: {\r\n DEFAULT: 'oklch(0.70 0.15 145)',\r\n foreground: 'oklch(0.09 0 0)',\r\n },\r\n\r\n // Border & Input colors\r\n border: 'oklch(0.27 0 0)',\r\n input: 'oklch(0.27 0 0)',\r\n ring: 'oklch(0.98 0 0)',\r\n },\r\n\r\n radius: {\r\n none: '0',\r\n sm: '0.125rem',\r\n base: '0.25rem',\r\n md: '0.375rem',\r\n lg: '0.5rem',\r\n xl: '0.75rem',\r\n '2xl': '1rem',\r\n '3xl': '1.5rem',\r\n full: '9999px',\r\n },\r\n});\r\n"],"mappings":"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","names":["forwardRef","cva","jsx","cva","forwardRef","jsx","forwardRef","cva","jsx","jsxs","Fragment","jsx","jsxs","cva","forwardRef","useEffect","useState","useMemo","jsx","useState","useMemo","useEffect","value"]}
@@ -0,0 +1,5 @@
1
+ import { ClassValue } from 'clsx';
2
+
3
+ declare function cn(...inputs: ClassValue[]): string;
4
+
5
+ export { cn };
@@ -0,0 +1,5 @@
1
+ import { ClassValue } from 'clsx';
2
+
3
+ declare function cn(...inputs: ClassValue[]): string;
4
+
5
+ export { cn };
package/dist/lib/cn.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lib/cn.ts
21
+ var cn_exports = {};
22
+ __export(cn_exports, {
23
+ cn: () => cn
24
+ });
25
+ module.exports = __toCommonJS(cn_exports);
26
+ var import_clsx = require("clsx");
27
+ var import_tailwind_merge = require("tailwind-merge");
28
+ function cn(...inputs) {
29
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
30
+ }
31
+ // Annotate the CommonJS export names for ESM import in node:
32
+ 0 && (module.exports = {
33
+ cn
34
+ });
35
+ //# sourceMappingURL=cn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsC;AACtC,4BAAwB;AAEjB,SAAS,MAAM,QAAsB;AAC1C,aAAO,mCAAQ,kBAAK,MAAM,CAAC;AAC7B;","names":[]}
@@ -0,0 +1,10 @@
1
+ // src/lib/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+ export {
8
+ cn
9
+ };
10
+ //# sourceMappingURL=cn.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n"],"mappings":";AAAA,SAA0B,YAAY;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;","names":[]}
@@ -0,0 +1,287 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type Theme = 'light' | 'dark' | 'system' | string;
4
+ type ColorValue = string | {
5
+ DEFAULT: string;
6
+ foreground: string;
7
+ };
8
+ interface ThemeColors {
9
+ background?: ColorValue;
10
+ foreground?: ColorValue;
11
+ muted?: ColorValue;
12
+ accent?: ColorValue;
13
+ card?: ColorValue;
14
+ popover?: ColorValue;
15
+ primary?: ColorValue;
16
+ secondary?: ColorValue;
17
+ info?: ColorValue;
18
+ danger?: ColorValue;
19
+ warning?: ColorValue;
20
+ success?: ColorValue;
21
+ destructive?: ColorValue;
22
+ border?: ColorValue;
23
+ input?: ColorValue;
24
+ ring?: ColorValue;
25
+ [key: string]: ColorValue | undefined;
26
+ }
27
+ interface ThemeConfig {
28
+ colors: ThemeColors;
29
+ spacing?: Record<string, string>;
30
+ radius?: Record<string, string>;
31
+ fontSize?: Record<string, string | [string, {
32
+ lineHeight: string;
33
+ letterSpacing?: string;
34
+ }]>;
35
+ fontFamily?: Record<string, string[]>;
36
+ fontWeight?: Record<string, string>;
37
+ shadows?: Record<string, string>;
38
+ zIndex?: Record<string, string>;
39
+ animation?: {
40
+ duration?: Record<string, string>;
41
+ ease?: Record<string, string>;
42
+ };
43
+ [key: string]: unknown;
44
+ }
45
+ interface CustomThemeDefinition {
46
+ dark?: boolean;
47
+ cssVars?: Record<string, string>;
48
+ }
49
+ interface ThemeProviderProps {
50
+ children: React.ReactNode;
51
+ defaultTheme?: Theme;
52
+ storageKey?: string;
53
+ /** Custom theme configuration for light mode */
54
+ config?: ThemeConfig;
55
+ /** Custom theme configuration for dark mode */
56
+ darkConfig?: ThemeConfig;
57
+ /** Legacy: Custom theme definitions (deprecated, use config instead) */
58
+ customThemes?: Record<string, CustomThemeDefinition>;
59
+ enableColorSchemeSync?: boolean;
60
+ }
61
+ interface ThemeProviderState {
62
+ theme: Theme;
63
+ setTheme: (theme: Theme) => void;
64
+ }
65
+ declare function defineTheme<T extends ThemeConfig>(config: T): T;
66
+
67
+ declare function ThemeProvider({ children, defaultTheme, storageKey, config, darkConfig, customThemes, enableColorSchemeSync, }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
68
+
69
+ declare function useTheme(): ThemeProviderState;
70
+
71
+ /**
72
+ * Convert ThemeConfig to CSS variables object
73
+ */
74
+ declare function themeToCssVars(theme: ThemeConfig): Record<string, string>;
75
+ /**
76
+ * Apply CSS variables to an element
77
+ */
78
+ declare function applyCssVars(element: HTMLElement, cssVars: Record<string, string>): void;
79
+ /**
80
+ * Remove CSS variables from an element
81
+ */
82
+ declare function removeCssVars(element: HTMLElement, keys: string[]): void;
83
+ /**
84
+ * Format CSS variables object to CSS string
85
+ * Useful for build-time CSS generation
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const cssVars = themeToCssVars(myTheme);
90
+ * const cssString = formatCssVars(cssVars);
91
+ * console.log(cssString);
92
+ * // Output:
93
+ * // --color-primary: oklch(0.5 0.2 250);
94
+ * // --color-primary-foreground: oklch(1 0 0);
95
+ * ```
96
+ */
97
+ declare function formatCssVars(cssVars: Record<string, string>): string;
98
+ /**
99
+ * Generate CSS variables string from theme config
100
+ * Combines themeToCssVars + formatCssVars for convenience
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * import { defineTheme, generateThemeCss } from '@poodle-kit/ui/theme';
105
+ *
106
+ * const myTheme = defineTheme({ colors: { ... } });
107
+ * const cssString = generateThemeCss(myTheme);
108
+ * console.log(cssString);
109
+ * // Output:
110
+ * // --color-primary: oklch(0.5 0.2 250);
111
+ * // --color-primary-foreground: oklch(1 0 0);
112
+ * ```
113
+ */
114
+ declare function generateThemeCss(theme: ThemeConfig): string;
115
+
116
+ /**
117
+ * Default Theme Tokens
118
+ *
119
+ * This is a reference implementation showing how to define themes.
120
+ * Copy this pattern to your project and customize the values.
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * // your-app/src/theme/my-theme.ts
125
+ * import { defineTheme } from '@poodle-kit/ui/theme';
126
+ *
127
+ * export const myLightTheme = defineTheme({
128
+ * colors: {
129
+ * primary: { DEFAULT: 'oklch(0.5 0.2 250)', foreground: 'oklch(1 0 0)' },
130
+ * // ... your custom colors
131
+ * },
132
+ * radius: { md: '0.5rem' },
133
+ * });
134
+ *
135
+ * export const myDarkTheme = defineTheme({
136
+ * colors: {
137
+ * primary: { DEFAULT: 'oklch(0.7 0.2 250)', foreground: 'oklch(0.09 0 0)' },
138
+ * // ... your custom colors
139
+ * },
140
+ * radius: { md: '0.5rem' },
141
+ * });
142
+ * ```
143
+ *
144
+ * Then use in your app:
145
+ * ```tsx
146
+ * import { ThemeProvider } from '@poodle-kit/ui';
147
+ * import { myLightTheme, myDarkTheme } from './theme/my-theme';
148
+ *
149
+ * <ThemeProvider config={myLightTheme} darkConfig={myDarkTheme}>
150
+ * <App />
151
+ * </ThemeProvider>
152
+ * ```
153
+ */
154
+ /**
155
+ * Default Light Theme
156
+ * Clean neutral design with semantic color tokens
157
+ */
158
+ declare const defaultLightTheme: {
159
+ colors: {
160
+ background: {
161
+ DEFAULT: string;
162
+ foreground: string;
163
+ };
164
+ muted: {
165
+ DEFAULT: string;
166
+ foreground: string;
167
+ };
168
+ accent: {
169
+ DEFAULT: string;
170
+ foreground: string;
171
+ };
172
+ card: {
173
+ DEFAULT: string;
174
+ foreground: string;
175
+ };
176
+ popover: {
177
+ DEFAULT: string;
178
+ foreground: string;
179
+ };
180
+ primary: {
181
+ DEFAULT: string;
182
+ foreground: string;
183
+ };
184
+ secondary: {
185
+ DEFAULT: string;
186
+ foreground: string;
187
+ };
188
+ info: {
189
+ DEFAULT: string;
190
+ foreground: string;
191
+ };
192
+ danger: {
193
+ DEFAULT: string;
194
+ foreground: string;
195
+ };
196
+ warning: {
197
+ DEFAULT: string;
198
+ foreground: string;
199
+ };
200
+ success: {
201
+ DEFAULT: string;
202
+ foreground: string;
203
+ };
204
+ border: string;
205
+ input: string;
206
+ ring: string;
207
+ };
208
+ radius: {
209
+ none: string;
210
+ sm: string;
211
+ base: string;
212
+ md: string;
213
+ lg: string;
214
+ xl: string;
215
+ '2xl': string;
216
+ '3xl': string;
217
+ full: string;
218
+ };
219
+ };
220
+ /**
221
+ * Default Dark Theme
222
+ * Clean neutral design with semantic color tokens
223
+ */
224
+ declare const defaultDarkTheme: {
225
+ colors: {
226
+ background: {
227
+ DEFAULT: string;
228
+ foreground: string;
229
+ };
230
+ muted: {
231
+ DEFAULT: string;
232
+ foreground: string;
233
+ };
234
+ accent: {
235
+ DEFAULT: string;
236
+ foreground: string;
237
+ };
238
+ card: {
239
+ DEFAULT: string;
240
+ foreground: string;
241
+ };
242
+ popover: {
243
+ DEFAULT: string;
244
+ foreground: string;
245
+ };
246
+ primary: {
247
+ DEFAULT: string;
248
+ foreground: string;
249
+ };
250
+ secondary: {
251
+ DEFAULT: string;
252
+ foreground: string;
253
+ };
254
+ info: {
255
+ DEFAULT: string;
256
+ foreground: string;
257
+ };
258
+ danger: {
259
+ DEFAULT: string;
260
+ foreground: string;
261
+ };
262
+ warning: {
263
+ DEFAULT: string;
264
+ foreground: string;
265
+ };
266
+ success: {
267
+ DEFAULT: string;
268
+ foreground: string;
269
+ };
270
+ border: string;
271
+ input: string;
272
+ ring: string;
273
+ };
274
+ radius: {
275
+ none: string;
276
+ sm: string;
277
+ base: string;
278
+ md: string;
279
+ lg: string;
280
+ xl: string;
281
+ '2xl': string;
282
+ '3xl': string;
283
+ full: string;
284
+ };
285
+ };
286
+
287
+ export { type CustomThemeDefinition, type Theme, type ThemeColors, type ThemeConfig, ThemeProvider, type ThemeProviderProps, type ThemeProviderState, applyCssVars, defaultDarkTheme, defaultLightTheme, defineTheme, formatCssVars, generateThemeCss, removeCssVars, themeToCssVars, useTheme };