@cashdoc/cashdoc-cms-design-system 1.0.12

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.
Files changed (121) hide show
  1. package/README.md +125 -0
  2. package/dist/.gitkeep +0 -0
  3. package/dist/components/Button/Button.d.ts +127 -0
  4. package/dist/components/Button/index.d.ts +1 -0
  5. package/dist/components/Checkbox/Checkbox.d.ts +87 -0
  6. package/dist/components/Checkbox/index.d.ts +2 -0
  7. package/dist/components/DatePicker/DatePicker.d.ts +98 -0
  8. package/dist/components/DatePicker/index.d.ts +2 -0
  9. package/dist/components/DateRangePicker/DateRangePicker.d.ts +93 -0
  10. package/dist/components/DateRangePicker/index.d.ts +2 -0
  11. package/dist/components/Dropdown/Combobox.d.ts +86 -0
  12. package/dist/components/Dropdown/Dropdown.d.ts +106 -0
  13. package/dist/components/Dropdown/Select.d.ts +87 -0
  14. package/dist/components/Dropdown/index.d.ts +3 -0
  15. package/dist/components/FileUpload/FileUpload.d.ts +58 -0
  16. package/dist/components/FileUpload/index.d.ts +2 -0
  17. package/dist/components/ImageUpload/ImageUpload.d.ts +154 -0
  18. package/dist/components/ImageUpload/index.d.ts +2 -0
  19. package/dist/components/LoadingCircle/LoadingCircle.d.ts +76 -0
  20. package/dist/components/LoadingCircle/index.d.ts +1 -0
  21. package/dist/components/Modal/ConfirmModal.d.ts +36 -0
  22. package/dist/components/Modal/DeleteModal.d.ts +33 -0
  23. package/dist/components/Modal/ErrorModal.d.ts +32 -0
  24. package/dist/components/Modal/Modal.d.ts +185 -0
  25. package/dist/components/Modal/SuccessModal.d.ts +31 -0
  26. package/dist/components/Modal/WarningModal.d.ts +35 -0
  27. package/dist/components/Modal/index.d.ts +12 -0
  28. package/dist/components/Pagination/Pagination.d.ts +106 -0
  29. package/dist/components/Pagination/index.d.ts +2 -0
  30. package/dist/components/Popover/Popover.d.ts +75 -0
  31. package/dist/components/Popover/PopoverMenuItem.d.ts +36 -0
  32. package/dist/components/Popover/index.d.ts +3 -0
  33. package/dist/components/RadioButton/RadioButton.d.ts +84 -0
  34. package/dist/components/RadioButton/index.d.ts +1 -0
  35. package/dist/components/SideNavigation/SideNavigation.d.ts +98 -0
  36. package/dist/components/SideNavigation/index.d.ts +1 -0
  37. package/dist/components/Switch/Switch.d.ts +71 -0
  38. package/dist/components/Switch/index.d.ts +1 -0
  39. package/dist/components/Table/Table.d.ts +192 -0
  40. package/dist/components/Table/index.d.ts +2 -0
  41. package/dist/components/TagInput/TagInput.d.ts +118 -0
  42. package/dist/components/TagInput/index.d.ts +1 -0
  43. package/dist/components/Text/Text.d.ts +71 -0
  44. package/dist/components/Text/index.d.ts +2 -0
  45. package/dist/components/TextInput/TextInput.d.ts +94 -0
  46. package/dist/components/TextInput/index.d.ts +2 -0
  47. package/dist/components/TimePicker/TimePicker.d.ts +110 -0
  48. package/dist/components/TimePicker/index.d.ts +2 -0
  49. package/dist/components/Toast/Toaster.d.ts +84 -0
  50. package/dist/components/Toast/index.d.ts +4 -0
  51. package/dist/components/ToolTip/ToolTip.d.ts +110 -0
  52. package/dist/components/ToolTip/index.d.ts +2 -0
  53. package/dist/components/icons/index.d.ts +61 -0
  54. package/dist/components/index.d.ts +21 -0
  55. package/dist/index.d.ts +3 -0
  56. package/dist/index.es.js +5233 -0
  57. package/dist/index.es.js.map +1 -0
  58. package/dist/index.umd.js +2 -0
  59. package/dist/index.umd.js.map +1 -0
  60. package/dist/playwright.config.d.ts +6 -0
  61. package/dist/src/components/Button/Button.d.ts +113 -0
  62. package/dist/src/components/Button/index.d.ts +2 -0
  63. package/dist/src/components/Button/variants.d.ts +18 -0
  64. package/dist/src/components/Checkbox/Checkbox.d.ts +90 -0
  65. package/dist/src/components/Checkbox/index.d.ts +2 -0
  66. package/dist/src/components/DatePicker/DatePicker.d.ts +101 -0
  67. package/dist/src/components/DatePicker/index.d.ts +2 -0
  68. package/dist/src/components/DateRangePicker/DateRangePicker.d.ts +96 -0
  69. package/dist/src/components/DateRangePicker/index.d.ts +2 -0
  70. package/dist/src/components/Dropdown/Combobox.d.ts +86 -0
  71. package/dist/src/components/Dropdown/Dropdown.d.ts +107 -0
  72. package/dist/src/components/Dropdown/Select.d.ts +87 -0
  73. package/dist/src/components/Dropdown/index.d.ts +4 -0
  74. package/dist/src/components/Dropdown/variants.d.ts +4 -0
  75. package/dist/src/components/FileUpload/FileUpload.d.ts +61 -0
  76. package/dist/src/components/FileUpload/index.d.ts +2 -0
  77. package/dist/src/components/ImageUpload/ImageUpload.d.ts +157 -0
  78. package/dist/src/components/ImageUpload/index.d.ts +2 -0
  79. package/dist/src/components/LoadingCircle/LoadingCircle.d.ts +79 -0
  80. package/dist/src/components/LoadingCircle/index.d.ts +1 -0
  81. package/dist/src/components/Modal/ConfirmModal.d.ts +36 -0
  82. package/dist/src/components/Modal/DeleteModal.d.ts +33 -0
  83. package/dist/src/components/Modal/ErrorModal.d.ts +32 -0
  84. package/dist/src/components/Modal/Modal.d.ts +188 -0
  85. package/dist/src/components/Modal/SuccessModal.d.ts +31 -0
  86. package/dist/src/components/Modal/WarningModal.d.ts +35 -0
  87. package/dist/src/components/Modal/index.d.ts +12 -0
  88. package/dist/src/components/Pagination/Pagination.d.ts +109 -0
  89. package/dist/src/components/Pagination/index.d.ts +2 -0
  90. package/dist/src/components/Popover/Popover.d.ts +78 -0
  91. package/dist/src/components/Popover/PopoverMenuItem.d.ts +34 -0
  92. package/dist/src/components/Popover/index.d.ts +4 -0
  93. package/dist/src/components/Popover/variants.d.ts +3 -0
  94. package/dist/src/components/RadioButton/RadioButton.d.ts +87 -0
  95. package/dist/src/components/RadioButton/index.d.ts +1 -0
  96. package/dist/src/components/SideNavigation/SideNavigation.d.ts +101 -0
  97. package/dist/src/components/SideNavigation/index.d.ts +1 -0
  98. package/dist/src/components/Switch/Switch.d.ts +74 -0
  99. package/dist/src/components/Switch/index.d.ts +1 -0
  100. package/dist/src/components/Table/Table.d.ts +195 -0
  101. package/dist/src/components/Table/index.d.ts +2 -0
  102. package/dist/src/components/TagInput/TagInput.d.ts +121 -0
  103. package/dist/src/components/TagInput/index.d.ts +1 -0
  104. package/dist/src/components/Text/Text.d.ts +74 -0
  105. package/dist/src/components/Text/index.d.ts +2 -0
  106. package/dist/src/components/TextInput/TextInput.d.ts +97 -0
  107. package/dist/src/components/TextInput/index.d.ts +2 -0
  108. package/dist/src/components/TimePicker/TimePicker.d.ts +113 -0
  109. package/dist/src/components/TimePicker/index.d.ts +2 -0
  110. package/dist/src/components/Toast/Toaster.d.ts +87 -0
  111. package/dist/src/components/Toast/index.d.ts +4 -0
  112. package/dist/src/components/ToolTip/ToolTip.d.ts +112 -0
  113. package/dist/src/components/ToolTip/index.d.ts +2 -0
  114. package/dist/src/components/icons/index.d.ts +61 -0
  115. package/dist/src/components/index.d.ts +21 -0
  116. package/dist/src/index.d.ts +3 -0
  117. package/dist/src/utils/cn.d.ts +3 -0
  118. package/dist/style.css +1 -0
  119. package/dist/utils/cn.d.ts +3 -0
  120. package/dist/vite.config.d.ts +2 -0
  121. package/package.json +99 -0
@@ -0,0 +1,106 @@
1
+ import { VariantProps } from 'class-variance-authority';
2
+
3
+ export declare const dropdownTriggerVariants: (props?: ({
4
+ variant?: "default" | "outline" | "ghost" | null | undefined;
5
+ size?: "default" | "sm" | "lg" | null | undefined;
6
+ } & import('class-variance-authority/types').ClassProp) | undefined) => string;
7
+ export interface DropdownOption {
8
+ value: string;
9
+ label: string;
10
+ disabled?: boolean;
11
+ }
12
+ export interface DropdownProps extends VariantProps<typeof dropdownTriggerVariants> {
13
+ options: DropdownOption[];
14
+ value?: string;
15
+ placeholder?: string;
16
+ onValueChange?: (value: string) => void;
17
+ disabled?: boolean;
18
+ className?: string;
19
+ dropdownClassName?: string;
20
+ searchable?: boolean;
21
+ clearable?: boolean;
22
+ multiple?: boolean;
23
+ maxHeight?: number;
24
+ }
25
+ /**
26
+ * 사용자가 목록에서 하나 또는 여러 개의 옵션을 선택할 수 있게 하는 컴포넌트입니다.
27
+ *
28
+ * {@link Dropdown}은 공간이 제한적인 UI에서 다양한 선택지를 효율적으로 제공합니다.
29
+ * 검색 기능, 다중 선택(Multiple), 선택 해제(Clearable) 등 복잡한 선택 시나리오를 지원합니다.
30
+ *
31
+ * ## When (언제 사용해야 하는가)
32
+ *
33
+ * **사용해야 하는 경우:**
34
+ * - **단일/다중 선택**: 5개 이상의 옵션 중 하나 또는 여러 개를 선택해야 할 때
35
+ * - **공간 절약**: 라디오 버튼이나 체크박스 그룹을 표시하기엔 화면 공간이 부족할 때
36
+ * - **동적 필터링**: 옵션이 너무 많아 검색을 통해 원하는 항목을 찾아야 할 때
37
+ *
38
+ * **사용하지 말아야 하는 경우:**
39
+ * - **옵션이 적은 경우(2-4개)**: 사용자가 모든 옵션을 한눈에 볼 수 있는 `RadioButton`이나 `Checkbox`가 더 좋습니다.
40
+ * - **설정 토글**: 단순히 On/Off를 전환하는 것이라면 `Switch`를 사용하세요.
41
+ * - **단순 내비게이션**: 클릭 시 다른 페이지로 이동만 하는 기능이라면 `Button`이나 `SideNavigation` 아이템이 더 적절합니다.
42
+ *
43
+ * ## Layout behavior
44
+ *
45
+ * - **Popover Menu**: 클릭 시 버튼 아래(또는 위)에 옵션 목록이 나타나며, 다른 요소들 위에 오버레이됩니다.
46
+ * - **Flexible Width**: 부모 컨테이너의 너비에 맞춰지거나, `className`을 통해 고정 너비를 가질 수 있습니다.
47
+ * - **Scrolling**: 옵션이 많아지면 `maxHeight` 설정에 따라 목록 내부에 스크롤이 발생합니다.
48
+ *
49
+ * ## Usage guidelines
50
+ *
51
+ * ### ✅ Do (권장 사항)
52
+ *
53
+ * - **논리적 정렬**: 옵션 목록은 가나다순, 사용 빈도순 등 사용자가 예측 가능한 순서로 정렬하세요.
54
+ * - **검색 기능 활용**: 옵션이 10개 이상인 경우 `searchable` 속성을 활성화하여 편의성을 높이세요.
55
+ * - **상태 표시**: `placeholder`를 통해 무엇을 선택해야 하는지 안내하고, 선택 후에는 선택된 항목을 명확히 표시하세요.
56
+ *
57
+ * ### 🚫 Don't (주의/금지 사항)
58
+ *
59
+ * - **너무 많은 텍스트**: 각 옵션의 레이블은 가급적 한 줄에 들어오도록 짧게 작성하세요.
60
+ * - **중첩 드롭다운 지양**: 드롭다운 안에서 또 다른 드롭다운이 열리는 복잡한 계층 구조는 피하는 것이 좋습니다.
61
+ *
62
+ * ## Accessibility
63
+ *
64
+ * - **Keyboard Interaction**: `Enter`나 `Space`로 열고, 화살표 키로 이동하며, `Esc`로 닫을 수 있습니다.
65
+ * - **Screen Reader**: `aria-expanded`, `aria-haspopup` 등의 속성을 통해 드롭다운의 상태와 역할을 스크린 리더에 전달합니다.
66
+ * - **Focus Management**: 드롭다운이 열리면 검색창이나 첫 번째 옵션으로 포커스가 이동합니다.
67
+ *
68
+ * ## Example
69
+ *
70
+ * {@tool snippet}
71
+ * 기본적인 단일 선택 드롭다운:
72
+ *
73
+ * ```tsx
74
+ * <Dropdown
75
+ * options={[
76
+ * { value: 'ko', label: '한국어' },
77
+ * { value: 'en', label: '영어' },
78
+ * { value: 'ja', label: '일본어' },
79
+ * ]}
80
+ * placeholder="언어를 선택하세요"
81
+ * onValueChange={(val) => console.log(val)}
82
+ * />
83
+ * ```
84
+ * {@end-tool}
85
+ *
86
+ * {@tool snippet}
87
+ * 검색과 다중 선택이 가능한 드롭다운:
88
+ *
89
+ * ```tsx
90
+ * <Dropdown
91
+ * options={largeOptionList}
92
+ * multiple={true}
93
+ * searchable={true}
94
+ * clearable={true}
95
+ * placeholder="태그 선택"
96
+ * />
97
+ * ```
98
+ * {@end-tool}
99
+ *
100
+ * See also:
101
+ *
102
+ * - {@link Select}, 기본적인 HTML select 스타일의 컴포넌트
103
+ * - {@link Combobox}, 입력과 선택이 결합된 컴포넌트
104
+ * - {@link Popover}, 더 자유로운 형태의 팝오버가 필요한 경우
105
+ */
106
+ export declare const Dropdown: import('react').ForwardRefExoticComponent<DropdownProps & import('react').RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,87 @@
1
+ import { DropdownProps } from './Dropdown';
2
+
3
+ export interface SelectProps extends Omit<DropdownProps, "multiple" | "searchable" | "clearable"> {
4
+ label?: string;
5
+ helperText?: string;
6
+ error?: string;
7
+ required?: boolean;
8
+ }
9
+ /**
10
+ * 사용자에게 레이블, 도움말, 에러 메시지와 함께 단일 선택 드롭다운을 제공하는 컴포넌트입니다.
11
+ *
12
+ * {@link Select}는 {@link Dropdown}을 기반으로 하며, 폼(Form) 구성에 필요한
13
+ * 추가적인 UI 요소(레이블, 필수 표시, 유효성 검사 메시지 등)를 포함하고 있습니다.
14
+ * 주로 입력 폼 내에서 하나의 값을 선택받아야 할 때 사용됩니다.
15
+ *
16
+ * ## When (언제 사용해야 하는가)
17
+ *
18
+ * **사용해야 하는 경우:**
19
+ * - **표준 폼 입력**: 이름, 이메일 등과 함께 성별, 지역, 카테고리 등을 선택받을 때
20
+ * - **유효성 검사가 필요한 경우**: 선택하지 않았을 때 에러 메시지를 표시해야 하는 상황
21
+ * - **상세 설명 필요**: 입력 항목에 대한 추가적인 도움말(helperText)이 필요한 경우
22
+ *
23
+ * **사용하지 말아야 하는 경우:**
24
+ * - **단순 필터/정렬**: 레이블 없이 목록 위에 놓이는 필터 등은 `Dropdown`을 직접 사용하세요.
25
+ * - **다중 선택/검색**: 다중 선택이나 검색 기능이 필요하다면 `Dropdown` 또는 `Combobox`를 사용하세요.
26
+ *
27
+ * ## Layout behavior
28
+ *
29
+ * - **Vertical Stack**: 레이블 - 드롭다운 버튼 - 도움말/에러 메시지가 수직으로 배치됩니다.
30
+ * - **Consistency**: 다른 입력 컴포넌트(TextInput 등)와 동일한 간격과 스타일을 유지하여 일관된 폼 레이아웃을 구성합니다.
31
+ *
32
+ * ## Usage guidelines
33
+ *
34
+ * ### ✅ Do (권장 사항)
35
+ *
36
+ * - **명확한 레이블**: 사용자가 무엇을 선택해야 하는지 알 수 있도록 구체적인 레이블을 제공하세요.
37
+ * - **필수 여부 표시**: `required` 속성을 사용하여 필수 입력 항목임을 시각적으로 나타내세요.
38
+ * - **에러 메시지 활용**: 유효성 검사 실패 시 `error` prop을 통해 구체적인 오류 원인을 안내하세요.
39
+ *
40
+ * ### 🚫 Don't (주의/금지 사항)
41
+ *
42
+ * - **레이블 생략 지양**: 폼 내에서는 접근성과 사용자 경험을 위해 가급적 레이블을 생략하지 마세요.
43
+ * - **과도한 도움말**: 도움말이 너무 길어지면 폼 전체의 가독성이 떨어집니다. 가급적 한 줄 이내로 작성하세요.
44
+ *
45
+ * ## Accessibility
46
+ *
47
+ * - **Label Association**: 레이블은 드롭다운 버튼과 논리적으로 연결되어 스크린 리더에서 함께 읽어줍니다.
48
+ * - **Error States**: 에러 상태가 되면 `aria-invalid` 등의 속성을 통해 시각 장애 사용자에게도 오류 상태를 전달합니다.
49
+ *
50
+ * ## Example
51
+ *
52
+ * {@tool snippet}
53
+ * 레이블과 필수 표시가 포함된 선택 창:
54
+ *
55
+ * ```tsx
56
+ * <Select
57
+ * label="사용자 등급"
58
+ * required={true}
59
+ * options={[
60
+ * { value: 'admin', label: '관리자' },
61
+ * { value: 'editor', label: '편집자' },
62
+ * { value: 'viewer', label: '뷰어' },
63
+ * ]}
64
+ * placeholder="등급을 선택해 주세요"
65
+ * />
66
+ * ```
67
+ * {@end-tool}
68
+ *
69
+ * {@tool snippet}
70
+ * 에러 메시지가 표시된 상태:
71
+ *
72
+ * ```tsx
73
+ * <Select
74
+ * label="국가 선택"
75
+ * options={countryOptions}
76
+ * error="국가를 선택하는 것은 필수입니다"
77
+ * />
78
+ * ```
79
+ * {@end-tool}
80
+ *
81
+ * See also:
82
+ *
83
+ * - {@link Dropdown}, 레이블 없이 단순한 선택 기능만 필요한 경우
84
+ * - {@link TextInput}, 텍스트 직접 입력이 필요한 경우
85
+ * - {@link RadioButton}, 옵션이 적고 한눈에 보여야 하는 경우
86
+ */
87
+ export declare const Select: import('react').ForwardRefExoticComponent<SelectProps & import('react').RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,3 @@
1
+ export { Dropdown, dropdownTriggerVariants, type DropdownProps, type DropdownOption, } from './Dropdown';
2
+ export { Select, type SelectProps } from './Select';
3
+ export { Combobox, type ComboboxProps } from './Combobox';
@@ -0,0 +1,58 @@
1
+ import { Accept } from 'react-dropzone';
2
+
3
+ export interface FileUploadProps {
4
+ value?: File[];
5
+ onChange?: (files: File[]) => void;
6
+ maxFiles?: number;
7
+ maxSize?: number;
8
+ accept?: Accept;
9
+ disabled?: boolean;
10
+ className?: string;
11
+ onError?: (error: string) => void;
12
+ }
13
+ /**
14
+ * 드래그 앤 드롭 및 클릭을 통해 파일을 업로드할 수 있는 컴포넌트입니다.
15
+ *
16
+ * {@link FileUpload}는 사용자가 다양한 형식의 파일을 선택하고 업로드할 수 있게 합니다.
17
+ * 드래그 앤 드롭, 클릭하여 선택, 파일 목록 표시 등의 기능을 제공합니다.
18
+ *
19
+ * ## When (언제 사용해야 하는가)
20
+ *
21
+ * **사용해야 하는 경우:**
22
+ * - **문서 첨부**: PDF, Word, Excel 등의 문서 파일을 업로드할 때
23
+ * - **다양한 파일 형식**: 이미지뿐만 아니라 여러 종류의 파일을 업로드할 때
24
+ * - **파일 목록 관리**: 업로드된 파일의 이름과 크기를 확인해야 할 때
25
+ *
26
+ * **사용하지 말아야 하는 경우:**
27
+ * - **이미지 전용**: 이미지만 업로드하고 미리보기가 필요한 경우는 {@link ImageUpload} 사용
28
+ *
29
+ * ## Example
30
+ *
31
+ * {@tool snippet}
32
+ * 기본 파일 업로드:
33
+ *
34
+ * ```tsx
35
+ * <FileUpload
36
+ * onChange={(files) => console.log(files)}
37
+ * maxFiles={1}
38
+ * maxSize={10 * 1024 * 1024} // 10MB
39
+ * />
40
+ * ```
41
+ * {@end-tool}
42
+ *
43
+ * {@tool snippet}
44
+ * 다중 파일 업로드 (PDF만):
45
+ *
46
+ * ```tsx
47
+ * <FileUpload
48
+ * onChange={(files) => console.log(files)}
49
+ * maxFiles={5}
50
+ * accept={{ "application/pdf": [".pdf"] }}
51
+ * />
52
+ * ```
53
+ * {@end-tool}
54
+ */
55
+ export declare const FileUpload: {
56
+ ({ value, onChange, maxFiles, maxSize, accept, disabled, className, onError, }: FileUploadProps): import("react/jsx-runtime").JSX.Element;
57
+ displayName: string;
58
+ };
@@ -0,0 +1,2 @@
1
+ export { FileUpload } from './FileUpload';
2
+ export type { FileUploadProps } from './FileUpload';
@@ -0,0 +1,154 @@
1
+ import { Accept } from 'react-dropzone';
2
+
3
+ export interface ImageMetadata {
4
+ width: number;
5
+ height: number;
6
+ aspectRatio: number;
7
+ size: number;
8
+ }
9
+ export interface ImageUploadProps {
10
+ value?: File[];
11
+ onChange?: (files: File[]) => void;
12
+ maxFiles?: number;
13
+ maxSize?: number;
14
+ accept?: Accept;
15
+ disabled?: boolean;
16
+ className?: string;
17
+ showPreview?: boolean;
18
+ error?: boolean;
19
+ onError?: (error: string) => void;
20
+ validateImage?: (file: File, metadata: ImageMetadata) => string | null | Promise<string | null>;
21
+ placeholder?: string;
22
+ placeholderActive?: string;
23
+ }
24
+ /**
25
+ * 드래그 앤 드롭 및 클릭을 통해 이미지를 업로드할 수 있는 컴포넌트입니다.
26
+ *
27
+ * {@link ImageUpload}는 사용자가 이미지 파일을 선택하고 업로드할 수 있게 합니다.
28
+ * 드래그 앤 드롭, 클릭하여 선택, 미리보기 등의 기능을 제공합니다.
29
+ *
30
+ * ## When (언제 사용해야 하는가)
31
+ *
32
+ * **사용해야 하는 경우:**
33
+ * - **프로필 이미지 업로드**: 사용자 프로필 사진 등록 시
34
+ * - **상품 이미지 등록**: 여러 상품 이미지를 한 번에 업로드해야 할 때
35
+ * - **문서 첨부**: 이미지 형태의 문서나 스크린샷을 첨부할 때
36
+ *
37
+ * **사용하지 말아야 하는 경우:**
38
+ * - **일반 파일 업로드**: 이미지가 아닌 다양한 형식의 파일을 업로드할 때는 일반 FileUpload 컴포넌트 사용
39
+ * - **대용량 파일**: 매우 큰 파일의 경우 진행률 표시가 있는 별도 업로드 컴포넌트 고려
40
+ *
41
+ * ## Example
42
+ *
43
+ * {@tool snippet}
44
+ * 기본 이미지 업로드:
45
+ *
46
+ * ```tsx
47
+ * <ImageUpload
48
+ * onChange={(files) => console.log(files)}
49
+ * maxFiles={1}
50
+ * maxSize={5 * 1024 * 1024} // 5MB
51
+ * />
52
+ * ```
53
+ * {@end-tool}
54
+ *
55
+ * {@tool snippet}
56
+ * 다중 이미지 업로드:
57
+ *
58
+ * ```tsx
59
+ * <ImageUpload
60
+ * onChange={(files) => console.log(files)}
61
+ * maxFiles={5}
62
+ * showPreview={true}
63
+ * />
64
+ * ```
65
+ * {@end-tool}
66
+ *
67
+ * {@tool snippet}
68
+ * 최소 이미지 크기 검증:
69
+ *
70
+ * ```tsx
71
+ * <ImageUpload
72
+ * validateImage={(file, metadata) => {
73
+ * if (metadata.width < 800 || metadata.height < 600) {
74
+ * return "이미지는 최소 800x600 이상이어야 합니다.";
75
+ * }
76
+ * return null;
77
+ * }}
78
+ * onError={(error) => alert(error)}
79
+ * />
80
+ * ```
81
+ * {@end-tool}
82
+ *
83
+ * {@tool snippet}
84
+ * 정확한 이미지 크기 검증:
85
+ *
86
+ * ```tsx
87
+ * <ImageUpload
88
+ * validateImage={(file, metadata) => {
89
+ * if (metadata.width !== 1920 || metadata.height !== 1080) {
90
+ * return `이미지는 정확히 1920x1080이어야 합니다. (현재: ${metadata.width}x${metadata.height})`;
91
+ * }
92
+ * return null;
93
+ * }}
94
+ * onError={(error) => alert(error)}
95
+ * />
96
+ * ```
97
+ * {@end-tool}
98
+ *
99
+ * {@tool snippet}
100
+ * 이미지 비율 검증:
101
+ *
102
+ * ```tsx
103
+ * <ImageUpload
104
+ * validateImage={(file, metadata) => {
105
+ * const targetRatio = 16 / 9;
106
+ * const tolerance = 0.1;
107
+ * if (Math.abs(metadata.aspectRatio - targetRatio) > tolerance) {
108
+ * return "이미지 비율은 16:9여야 합니다.";
109
+ * }
110
+ * return null;
111
+ * }}
112
+ * onError={(error) => alert(error)}
113
+ * />
114
+ * ```
115
+ * {@end-tool}
116
+ *
117
+ * {@tool snippet}
118
+ * 복합 검증:
119
+ *
120
+ * ```tsx
121
+ * <ImageUpload
122
+ * validateImage={(file, metadata) => {
123
+ * if (metadata.width > 4000) {
124
+ * return "이미지 너비는 4000px를 초과할 수 없습니다.";
125
+ * }
126
+ * if (metadata.aspectRatio < 1) {
127
+ * return "세로 이미지는 업로드할 수 없습니다.";
128
+ * }
129
+ * if (metadata.size > 2 * 1024 * 1024) {
130
+ * return "파일 크기는 2MB를 초과할 수 없습니다.";
131
+ * }
132
+ * return null;
133
+ * }}
134
+ * onError={(error) => alert(error)}
135
+ * />
136
+ * ```
137
+ * {@end-tool}
138
+ *
139
+ * {@tool snippet}
140
+ * 커스텀 안내 문구:
141
+ *
142
+ * ```tsx
143
+ * <ImageUpload
144
+ * placeholder="상품 이미지를 업로드하세요"
145
+ * placeholderActive="이미지를 드롭하세요"
146
+ * onChange={(files) => console.log(files)}
147
+ * />
148
+ * ```
149
+ * {@end-tool}
150
+ */
151
+ export declare const ImageUpload: {
152
+ ({ value, onChange, maxFiles, maxSize, accept, disabled, className, showPreview, error, onError, validateImage, placeholder, placeholderActive, }: ImageUploadProps): import("react/jsx-runtime").JSX.Element;
153
+ displayName: string;
154
+ };
@@ -0,0 +1,2 @@
1
+ export { ImageUpload } from './ImageUpload';
2
+ export type { ImageUploadProps } from './ImageUpload';
@@ -0,0 +1,76 @@
1
+ interface LoadingCircleProps {
2
+ size?: "sm" | "md" | "lg";
3
+ className?: string;
4
+ }
5
+ /**
6
+ * 시스템이 데이터를 처리 중이거나 다음 화면을 준비 중임을 시각적으로 나타내는 인디케이터입니다.
7
+ *
8
+ * {@link LoadingCircle}은 회전하는 원형 애니메이션을 통해 작업이 진행 중임을 알려
9
+ * 사용자가 시스템이 멈춘 것으로 오해하지 않도록 돕습니다.
10
+ *
11
+ * ## When (언제 사용해야 하는가)
12
+ *
13
+ * **사용해야 하는 경우:**
14
+ * - **데이터 로딩**: 페이지 진입 시 API로부터 데이터를 불러올 때
15
+ * - **작업 처리 중**: 버튼 클릭 후 서버 응답을 기다릴 때
16
+ * - **업로드/다운로드**: 파일 전송 상태를 표시할 때
17
+ * - **점진적 로딩**: 무한 스크롤 등 하단에 추가 데이터를 불러올 때
18
+ *
19
+ * **사용하지 말아야 하는 경우:**
20
+ * - **짧은 대기 시간**: 0.3초 미만의 아주 짧은 대기 시간에는 오히려 화면을 깜빡거리게 할 수 있으므로 생략하는 것이 좋습니다.
21
+ * - **진행률 표시**: 전체 작업 중 어느 정도 진행되었는지 정확한 수치가 중요한 경우 Progress Bar를 고려하세요.
22
+ *
23
+ * ## Layout behavior
24
+ *
25
+ * - **Centered**: 기본적으로 컨테이너의 중앙에 배치되도록 설정되어 있습니다.
26
+ * - **Fixed vs Inline**: 페이지 전체 로딩 시에는 고정된 위치(Overlay)에, 버튼 내부 등에는 인라인으로 배치할 수 있습니다.
27
+ *
28
+ * ## Usage guidelines
29
+ *
30
+ * ### ✅ Do (권장 사항)
31
+ *
32
+ * - **적절한 크기 선택**: 로딩이 일어나는 맥락(페이지 전체, 카드 내부, 버튼 내부 등)에 맞는 `size`를 선택하세요.
33
+ * - **텍스트와 병행**: 필요한 경우 '불러오는 중...'과 같은 텍스트를 함께 표시하여 의미를 더 명확히 하세요.
34
+ *
35
+ * ### 🚫 Don't (주의/금지 사항)
36
+ *
37
+ * - **남용 지양**: 한 화면에 너무 많은 로딩 서클이 동시에 나타나면 사용자에게 피로감을 줄 수 있습니다.
38
+ * - **무한 로딩**: 작업이 실패한 경우 로딩을 멈추고 적절한 에러 메시지를 표시해야 합니다.
39
+ *
40
+ * ## Accessibility
41
+ *
42
+ * - **Role**: `role="status"` 또는 `role="progressbar"`를 사용하여 현재 상태를 스크린 리더에 알립니다.
43
+ * - **Aria Label**: 시각적으로 확인이 어려운 사용자를 위해 `aria-label="로딩 중"`과 같은 정보를 제공하는 것이 좋습니다.
44
+ *
45
+ * ## Example
46
+ *
47
+ * {@tool snippet}
48
+ * 기본적인 로딩 서클 사용 예시:
49
+ *
50
+ * ```tsx
51
+ * {isLoading ? (
52
+ * <LoadingCircle size="md" />
53
+ * ) : (
54
+ * <DataContent />
55
+ * )}
56
+ * ```
57
+ * {@end-tool}
58
+ *
59
+ * {@tool snippet}
60
+ * 버튼 내부의 로딩 상태:
61
+ *
62
+ * ```tsx
63
+ * <Button disabled={isSubmitting}>
64
+ * {isSubmitting && <LoadingCircle size="sm" className="mr-2" />}
65
+ * 제출하기
66
+ * </Button>
67
+ * ```
68
+ * {@end-tool}
69
+ *
70
+ * See also:
71
+ *
72
+ * - {@link Button}, 버튼 자체의 로딩 상태를 지원함
73
+ * - {@link Modal}, 로딩 상태를 포함할 수 있는 오버레이
74
+ */
75
+ export declare function LoadingCircle({ size, className }: LoadingCircleProps): import("react/jsx-runtime").JSX.Element;
76
+ export {};
@@ -0,0 +1 @@
1
+ export { LoadingCircle } from './LoadingCircle';
@@ -0,0 +1,36 @@
1
+ import { default as React } from 'react';
2
+
3
+ export interface ConfirmModalProps {
4
+ open: boolean;
5
+ onOpenChange: (open: boolean) => void;
6
+ title?: string;
7
+ message: React.ReactNode;
8
+ confirmText?: string;
9
+ onConfirm?: () => void;
10
+ className?: string;
11
+ }
12
+ /**
13
+ * 사용자에게 특정 작업에 대한 최종 확인을 받기 위한 단순화된 모달 컴포넌트입니다.
14
+ *
15
+ * {@link ConfirmModal}은 {@link Modal}을 기반으로 구성되었으며, 상징적인 체크 아이콘과
16
+ * 하나의 '확인' 버튼만을 제공하여 사용자의 빠른 의사결정을 돕습니다.
17
+ * 주로 성공적인 처리 알림이나 단순한 동의가 필요할 때 사용됩니다.
18
+ *
19
+ * ## When (언제 사용해야 하는가)
20
+ *
21
+ * **사용해야 하는 경우:**
22
+ * - **결과 확인**: 설정 변경, 데이터 저장 등 작업이 정상적으로 완료되었음을 알릴 때
23
+ * - **단순 안내**: 사용자에게 중요한 안내 사항을 전달하고 확인을 받아야 할 때
24
+ *
25
+ * **사용하지 말아야 하는 경우:**
26
+ * - **중요한 결정/취소 필요**: '예/아니오'와 같이 선택지가 필요한 경우 일반 `Modal`이나 `DeleteModal`을 사용하세요.
27
+ * - **데이터 입력**: 폼 입력이 필요한 경우 일반 `Modal`을 사용하세요.
28
+ *
29
+ * ## Usage guidelines
30
+ *
31
+ * ### ✅ Do (권장 사항)
32
+ *
33
+ * - **간결한 메시지**: 메시지는 가급적 2-3줄 이내로 짧고 명확하게 작성하세요.
34
+ * - **적절한 타이틀**: "저장 완료", "안내" 등 문맥에 맞는 타이틀을 사용하세요.
35
+ */
36
+ export declare const ConfirmModal: React.ForwardRefExoticComponent<ConfirmModalProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,33 @@
1
+ import { default as React } from 'react';
2
+
3
+ export interface DeleteModalProps {
4
+ open: boolean;
5
+ onOpenChange: (open: boolean) => void;
6
+ title?: string;
7
+ message?: React.ReactNode;
8
+ confirmText?: string;
9
+ cancelText?: string;
10
+ onConfirm: () => void;
11
+ onCancel?: () => void;
12
+ className?: string;
13
+ }
14
+ /**
15
+ * 데이터를 삭제하거나 영구적인 작업을 수행하기 전, 사용자의 최종 승인을 받기 위한 경고 모달입니다.
16
+ *
17
+ * {@link DeleteModal}은 파괴적인(Destructive) 액션을 강조하기 위해 빨간색 경고 아이콘과
18
+ * 눈에 띄는 삭제 버튼을 제공합니다. 사용자가 실수로 데이터를 삭제하는 것을 방지하는 안전장치 역할을 합니다.
19
+ *
20
+ * ## When (언제 사용해야 하는가)
21
+ *
22
+ * **사용해야 하는 경우:**
23
+ * - **영구적 데이터 삭제**: 게시글, 사용자 계정, 설정값 등을 삭제할 때
24
+ * - **되돌릴 수 없는 작업**: 초기화, 데이터 덮어쓰기 등 주의가 필요한 작업을 수행할 때
25
+ *
26
+ * ## Usage guidelines
27
+ *
28
+ * ### ✅ Do (권장 사항)
29
+ *
30
+ * - **구체적인 정보 포함**: 단순히 "삭제하시겠습니까?" 보다는 "사용자 '홍길동'의 정보를 삭제하시겠습니까?"와 같이 구체적인 대상을 명시하는 것이 좋습니다.
31
+ * - **위험성 강조**: 해당 작업이 되돌릴 수 없음을 메시지에 포함하세요.
32
+ */
33
+ export declare const DeleteModal: React.ForwardRefExoticComponent<DeleteModalProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,32 @@
1
+ import { default as React } from 'react';
2
+
3
+ export interface ErrorModalProps {
4
+ open: boolean;
5
+ onOpenChange: (open: boolean) => void;
6
+ title?: string;
7
+ message: React.ReactNode;
8
+ confirmText?: string;
9
+ onConfirm?: () => void;
10
+ className?: string;
11
+ }
12
+ /**
13
+ * 시스템 오류나 사용자의 잘못된 조작으로 인해 작업이 실패했음을 알리는 모달입니다.
14
+ *
15
+ * {@link ErrorModal}은 빨간색 X 아이콘을 통해 부정적인 결과임을 즉각적으로 전달하며,
16
+ * 사용자가 문제를 인지하고 다음 행동을 취할 수 있도록 돕습니다.
17
+ *
18
+ * ## When (언제 사용해야 하는가)
19
+ *
20
+ * **사용해야 하는 경우:**
21
+ * - **API 통신 실패**: 서버 오류나 네트워크 문제로 요청을 처리할 수 없을 때
22
+ * - **유효성 검사 실패**: 입력한 정보에 중대한 결함이 있어 처리가 중단되었을 때
23
+ * - **권한 부족**: 특정 기능을 사용할 권한이 없음을 알릴 때
24
+ *
25
+ * ## Usage guidelines
26
+ *
27
+ * ### ✅ Do (권장 사항)
28
+ *
29
+ * - **구체적인 원인 안내**: 단순히 "오류가 발생했습니다" 보다는 "이미 존재하는 이메일입니다"와 같이 해결 가능한 정보를 제공하세요.
30
+ * - **해결 방법 제시**: 가능하다면 "나중에 다시 시도해 주세요" 또는 "고객센터로 문의해 주세요"와 같은 가이드를 포함하세요.
31
+ */
32
+ export declare const ErrorModal: React.ForwardRefExoticComponent<ErrorModalProps & React.RefAttributes<HTMLDivElement>>;