@bestow-ui/react 0.0.0-stage → 0.2.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.
@@ -0,0 +1,361 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, ElementType, ReactElement } from 'react';
3
+ import * as Dialog from '@radix-ui/react-dialog';
4
+ import { space } from '@bestow-ui/tokens';
5
+
6
+ /** 컴포넌트 스타일은 반드시 vars 를 통해 토큰을 참조한다. */
7
+ declare const vars: {
8
+ color: {
9
+ bg: {
10
+ default: `var(--${string})`;
11
+ subtle: `var(--${string})`;
12
+ muted: `var(--${string})`;
13
+ inverse: `var(--${string})`;
14
+ overlay: `var(--${string})`;
15
+ };
16
+ fg: {
17
+ default: `var(--${string})`;
18
+ muted: `var(--${string})`;
19
+ subtle: `var(--${string})`;
20
+ inverse: `var(--${string})`;
21
+ };
22
+ border: {
23
+ default: `var(--${string})`;
24
+ strong: `var(--${string})`;
25
+ focus: `var(--${string})`;
26
+ };
27
+ primary: {
28
+ solid: `var(--${string})`;
29
+ solidHover: `var(--${string})`;
30
+ contrast: `var(--${string})`;
31
+ subtle: `var(--${string})`;
32
+ subtleHover: `var(--${string})`;
33
+ text: `var(--${string})`;
34
+ };
35
+ neutral: {
36
+ solid: `var(--${string})`;
37
+ solidHover: `var(--${string})`;
38
+ contrast: `var(--${string})`;
39
+ subtle: `var(--${string})`;
40
+ subtleHover: `var(--${string})`;
41
+ text: `var(--${string})`;
42
+ };
43
+ danger: {
44
+ solid: `var(--${string})`;
45
+ solidHover: `var(--${string})`;
46
+ contrast: `var(--${string})`;
47
+ subtle: `var(--${string})`;
48
+ subtleHover: `var(--${string})`;
49
+ text: `var(--${string})`;
50
+ };
51
+ success: {
52
+ solid: `var(--${string})`;
53
+ solidHover: `var(--${string})`;
54
+ contrast: `var(--${string})`;
55
+ subtle: `var(--${string})`;
56
+ subtleHover: `var(--${string})`;
57
+ text: `var(--${string})`;
58
+ };
59
+ };
60
+ space: {
61
+ readonly 0: `var(--${string})`;
62
+ readonly 1: `var(--${string})`;
63
+ readonly 2: `var(--${string})`;
64
+ readonly 3: `var(--${string})`;
65
+ readonly 4: `var(--${string})`;
66
+ readonly 5: `var(--${string})`;
67
+ readonly 6: `var(--${string})`;
68
+ readonly 8: `var(--${string})`;
69
+ readonly 10: `var(--${string})`;
70
+ readonly 12: `var(--${string})`;
71
+ readonly 16: `var(--${string})`;
72
+ };
73
+ radius: {
74
+ readonly none: `var(--${string})`;
75
+ readonly sm: `var(--${string})`;
76
+ readonly md: `var(--${string})`;
77
+ readonly lg: `var(--${string})`;
78
+ readonly xl: `var(--${string})`;
79
+ readonly full: `var(--${string})`;
80
+ };
81
+ font: {
82
+ family: {
83
+ readonly sans: `var(--${string})`;
84
+ readonly mono: `var(--${string})`;
85
+ };
86
+ size: {
87
+ readonly xs: `var(--${string})`;
88
+ readonly sm: `var(--${string})`;
89
+ readonly md: `var(--${string})`;
90
+ readonly lg: `var(--${string})`;
91
+ readonly xl: `var(--${string})`;
92
+ readonly '2xl': `var(--${string})`;
93
+ readonly '3xl': `var(--${string})`;
94
+ readonly '4xl': `var(--${string})`;
95
+ };
96
+ weight: {
97
+ readonly regular: `var(--${string})`;
98
+ readonly medium: `var(--${string})`;
99
+ readonly semibold: `var(--${string})`;
100
+ readonly bold: `var(--${string})`;
101
+ };
102
+ lineHeight: {
103
+ readonly tight: `var(--${string})`;
104
+ readonly normal: `var(--${string})`;
105
+ readonly relaxed: `var(--${string})`;
106
+ };
107
+ };
108
+ shadow: {
109
+ readonly sm: `var(--${string})`;
110
+ readonly md: `var(--${string})`;
111
+ readonly lg: `var(--${string})`;
112
+ };
113
+ duration: {
114
+ readonly fast: `var(--${string})`;
115
+ readonly normal: `var(--${string})`;
116
+ readonly slow: `var(--${string})`;
117
+ };
118
+ zIndex: {
119
+ readonly dropdown: `var(--${string})`;
120
+ readonly overlay: `var(--${string})`;
121
+ readonly modal: `var(--${string})`;
122
+ readonly toast: `var(--${string})`;
123
+ readonly tooltip: `var(--${string})`;
124
+ };
125
+ };
126
+ declare const themeClass: {
127
+ light: string;
128
+ dark: string;
129
+ };
130
+ type ThemeName = keyof typeof themeClass;
131
+
132
+ interface ThemeProviderProps extends HTMLAttributes<HTMLDivElement> {
133
+ /** 적용할 테마. 중첩해서 일부 영역만 다른 테마를 적용할 수도 있다. */
134
+ theme?: ThemeName;
135
+ }
136
+ declare const ThemeProvider: react.ForwardRefExoticComponent<ThemeProviderProps & react.RefAttributes<HTMLDivElement>>;
137
+ /** 현재 적용 중인 테마 이름을 반환한다. */
138
+ declare function useTheme(): ThemeName;
139
+ /**
140
+ * Portal 로 ThemeProvider 바깥(body)에 렌더링되는 요소에 붙일 className.
141
+ * 현재 테마의 CSS 변수와 기본 글꼴을 다시 적용한다.
142
+ */
143
+ declare function usePortalClassName(): string;
144
+
145
+ interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color'> {
146
+ /** 시각적 스타일 */
147
+ variant?: 'solid' | 'soft' | 'outline' | 'ghost';
148
+ /** 의미 색상 */
149
+ color?: 'primary' | 'neutral' | 'danger';
150
+ /** 크기 */
151
+ size?: 'sm' | 'md' | 'lg';
152
+ /** 부모 너비를 꽉 채운다 */
153
+ fullWidth?: boolean;
154
+ /** 레이블 앞에 표시할 아이콘 */
155
+ startIcon?: ReactNode;
156
+ /** 레이블 뒤에 표시할 아이콘 */
157
+ endIcon?: ReactNode;
158
+ }
159
+ declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
160
+
161
+ interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {
162
+ /** 체크박스 옆에 표시할 레이블 */
163
+ label?: ReactNode;
164
+ /** 크기 */
165
+ size?: 'sm' | 'md';
166
+ /** 일부 선택 상태 (전체 선택 체크박스 등) */
167
+ indeterminate?: boolean;
168
+ /** 에러 상태 */
169
+ invalid?: boolean;
170
+ }
171
+ declare const Checkbox: react.ForwardRefExoticComponent<CheckboxProps & react.RefAttributes<HTMLInputElement>>;
172
+
173
+ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
174
+ /** 크기 */
175
+ size?: 'sm' | 'md' | 'lg';
176
+ /** 에러 상태 표시 (aria-invalid 도 함께 설정된다) */
177
+ invalid?: boolean;
178
+ /** 부모 너비를 꽉 채운다 */
179
+ fullWidth?: boolean;
180
+ /** 입력창 앞에 표시할 요소 (아이콘, 단위 등) */
181
+ startAdornment?: ReactNode;
182
+ /** 입력창 뒤에 표시할 요소 */
183
+ endAdornment?: ReactNode;
184
+ /** 바깥 래퍼에 적용할 className. className 은 input 요소에 적용된다 */
185
+ rootClassName?: string;
186
+ }
187
+ declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
188
+
189
+ interface TextFieldProps extends Omit<InputProps, 'invalid'> {
190
+ /** 입력창 위에 표시할 레이블 */
191
+ label?: ReactNode;
192
+ /** 입력창 아래에 표시할 도움말. error 일 때는 에러 메시지로 표시된다 */
193
+ helperText?: ReactNode;
194
+ /** 에러 상태 */
195
+ error?: boolean;
196
+ }
197
+ declare const TextField: react.ForwardRefExoticComponent<TextFieldProps & react.RefAttributes<HTMLInputElement>>;
198
+
199
+ interface ModalProps {
200
+ /** 열림 상태 (제어 모드) */
201
+ open?: boolean;
202
+ /** 처음 열림 상태 (비제어 모드) */
203
+ defaultOpen?: boolean;
204
+ /** 열림 상태가 바뀔 때 호출된다 */
205
+ onOpenChange?: (open: boolean) => void;
206
+ /** 클릭하면 모달을 여는 요소. 버튼 등 포커스 가능한 요소 하나여야 한다 */
207
+ trigger?: ReactNode;
208
+ /** 제목 (스크린리더가 모달 이름으로 읽는다) */
209
+ title: ReactNode;
210
+ /** 제목 아래 설명 */
211
+ description?: ReactNode;
212
+ /** 본문 */
213
+ children?: ReactNode;
214
+ /** 하단 버튼 영역. 닫기 버튼은 ModalClose 로 감싼다 */
215
+ footer?: ReactNode;
216
+ /** 너비 */
217
+ size?: 'sm' | 'md' | 'lg';
218
+ /** 오른쪽 위 닫기(X) 버튼 숨기기 */
219
+ hideCloseButton?: boolean;
220
+ /** 바깥 영역 클릭으로 닫기 (기본 true) */
221
+ closeOnOverlayClick?: boolean;
222
+ /** 내용 영역 className */
223
+ className?: string;
224
+ }
225
+ declare function Modal({ open, defaultOpen, onOpenChange, trigger, title, description, children, footer, size, hideCloseButton, closeOnOverlayClick, className, }: ModalProps): react.JSX.Element;
226
+ /**
227
+ * 감싼 요소를 클릭하면 모달이 닫힌다.
228
+ * @example <ModalClose asChild><Button>취소</Button></ModalClose>
229
+ */
230
+ declare const ModalClose: react.ForwardRefExoticComponent<Dialog.DialogCloseProps & react.RefAttributes<HTMLButtonElement>>;
231
+
232
+ interface SelectOption {
233
+ value: string;
234
+ label: ReactNode;
235
+ disabled?: boolean;
236
+ }
237
+ interface SelectProps {
238
+ /** 선택지 목록 */
239
+ options: SelectOption[];
240
+ /** 선택된 값 (제어 모드) */
241
+ value?: string;
242
+ /** 처음 선택된 값 (비제어 모드) */
243
+ defaultValue?: string;
244
+ /** 값이 바뀔 때 호출된다 */
245
+ onValueChange?: (value: string) => void;
246
+ /** 선택 전 표시할 문구 */
247
+ placeholder?: ReactNode;
248
+ /** 위에 표시할 레이블 */
249
+ label?: ReactNode;
250
+ /** 아래에 표시할 도움말. error 일 때는 에러 메시지로 표시된다 */
251
+ helperText?: ReactNode;
252
+ /** 에러 상태 */
253
+ error?: boolean;
254
+ /** 크기 */
255
+ size?: 'sm' | 'md' | 'lg';
256
+ /** 부모 너비를 꽉 채운다 */
257
+ fullWidth?: boolean;
258
+ disabled?: boolean;
259
+ required?: boolean;
260
+ /** form 제출 시 사용할 이름 */
261
+ name?: string;
262
+ id?: string;
263
+ /** label 이 없을 때 스크린리더용 이름 */
264
+ 'aria-label'?: string;
265
+ /** 트리거 className */
266
+ className?: string;
267
+ }
268
+ declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLButtonElement>>;
269
+
270
+ interface StackProps extends HTMLAttributes<HTMLElement> {
271
+ /** 렌더링할 요소 */
272
+ as?: ElementType;
273
+ /** 배치 방향 */
274
+ direction?: 'row' | 'column' | 'row-reverse' | 'column-reverse';
275
+ /** 자식 사이 간격 (space 토큰 키) */
276
+ gap?: keyof typeof space;
277
+ /** 교차축 정렬 (align-items) */
278
+ align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline';
279
+ /** 주축 정렬 (justify-content) */
280
+ justify?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
281
+ /** 줄바꿈 허용 */
282
+ wrap?: boolean;
283
+ }
284
+ declare const Stack: react.ForwardRefExoticComponent<StackProps & react.RefAttributes<HTMLElement>>;
285
+
286
+ interface ToastOptions {
287
+ /** 제목 */
288
+ title: ReactNode;
289
+ /** 설명 */
290
+ description?: ReactNode;
291
+ /** 의미 색상 */
292
+ variant?: 'default' | 'success' | 'danger';
293
+ /** 자동으로 닫히기까지 시간(ms). Infinity 면 자동으로 닫히지 않는다 */
294
+ duration?: number;
295
+ /** 실행 버튼 */
296
+ action?: {
297
+ label: string;
298
+ onClick: () => void;
299
+ /** 스크린리더용 대체 설명 (예: "실행 취소하려면 Ctrl+Z") */
300
+ altText?: string;
301
+ };
302
+ }
303
+ interface ToastContextValue {
304
+ /** 토스트를 띄우고 id 를 반환한다 */
305
+ toast: (options: ToastOptions) => number;
306
+ /** id 의 토스트를 닫는다. id 가 없으면 모두 닫는다 */
307
+ dismiss: (id?: number) => void;
308
+ }
309
+ interface ToastProviderProps {
310
+ children: ReactNode;
311
+ /** 기본 표시 시간(ms) */
312
+ duration?: number;
313
+ /** 스크린리더가 토스트 영역을 읽을 때 쓰는 이름 */
314
+ label?: string;
315
+ }
316
+ /** 앱 최상단(ThemeProvider 안쪽)에 한 번 감싸고, 하위에서 useToast() 로 토스트를 띄운다. */
317
+ declare function ToastProvider({ children, duration, label }: ToastProviderProps): react.JSX.Element;
318
+ declare function useToast(): ToastContextValue;
319
+
320
+ interface TooltipProps {
321
+ /** 툴팁 내용 */
322
+ content: ReactNode;
323
+ /** 툴팁을 띄울 요소. ref 를 받을 수 있는 요소 하나여야 한다 */
324
+ children: ReactElement;
325
+ /** 표시 방향 */
326
+ side?: 'top' | 'right' | 'bottom' | 'left';
327
+ /** 정렬 */
328
+ align?: 'start' | 'center' | 'end';
329
+ /** 마우스를 올린 뒤 표시까지 지연 시간(ms) */
330
+ delay?: number;
331
+ /** 열림 상태 (제어 모드) */
332
+ open?: boolean;
333
+ /** 처음 열림 상태 (비제어 모드) */
334
+ defaultOpen?: boolean;
335
+ /** 열림 상태가 바뀔 때 호출된다 */
336
+ onOpenChange?: (open: boolean) => void;
337
+ /** true 이면 툴팁을 띄우지 않고 children 만 렌더링한다 */
338
+ disabled?: boolean;
339
+ /** 툴팁 className */
340
+ className?: string;
341
+ }
342
+ declare function Tooltip({ content, children, side, align, delay, open, defaultOpen, onOpenChange, disabled, className, }: TooltipProps): react.JSX.Element;
343
+
344
+ type TypographyVariant = 'display' | 'h1' | 'h2' | 'h3' | 'h4' | 'body-lg' | 'body' | 'body-sm' | 'caption';
345
+ interface TypographyProps extends Omit<HTMLAttributes<HTMLElement>, 'color'> {
346
+ /** 텍스트 스타일 */
347
+ variant?: TypographyVariant;
348
+ /** 렌더링할 요소. 기본값은 variant 에 따라 결정된다 (h1, p, span 등) */
349
+ as?: ElementType;
350
+ /** 글자 색상 */
351
+ color?: 'default' | 'muted' | 'subtle' | 'primary' | 'danger' | 'success' | 'inherit';
352
+ /** variant 의 기본 굵기를 덮어쓴다 */
353
+ weight?: 'regular' | 'medium' | 'semibold' | 'bold';
354
+ /** 정렬 */
355
+ align?: 'start' | 'center' | 'end';
356
+ /** 한 줄로 자르고 말줄임표를 표시한다 */
357
+ truncate?: boolean;
358
+ }
359
+ declare const Typography: react.ForwardRefExoticComponent<TypographyProps & react.RefAttributes<HTMLElement>>;
360
+
361
+ export { Button, type ButtonProps, Checkbox, type CheckboxProps, Input, type InputProps, Modal, ModalClose, type ModalProps, Select, type SelectOption, type SelectProps, Stack, type StackProps, TextField, type TextFieldProps, type ThemeName, ThemeProvider, type ThemeProviderProps, type ToastOptions, ToastProvider, type ToastProviderProps, Tooltip, type TooltipProps, Typography, type TypographyProps, type TypographyVariant, themeClass, usePortalClassName, useTheme, useToast, vars };