@bestow-ui/react 1.7.0 → 2.0.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.
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _bestow_ui_tokens from '@bestow-ui/tokens';
2
2
  import { space } from '@bestow-ui/tokens';
3
3
  import * as react from 'react';
4
- import { ReactNode, HTMLAttributes, ElementType, CSSProperties, ComponentPropsWithoutRef, InputHTMLAttributes, ButtonHTMLAttributes, AnchorHTMLAttributes, ReactElement, FocusEvent, SelectHTMLAttributes, OlHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes, ChangeEvent, TextareaHTMLAttributes } from 'react';
4
+ import { ReactNode, HTMLAttributes, ElementType, ComponentPropsWithRef, ReactElement, RefAttributes, CSSProperties, ComponentPropsWithoutRef, InputHTMLAttributes, ButtonHTMLAttributes, AnchorHTMLAttributes, FocusEvent, SelectHTMLAttributes, OlHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes, ChangeEvent, TextareaHTMLAttributes } from 'react';
5
5
  export { ResidentNumberInfo, composeExtraAddress, formatBusinessNumber, formatKoreanAmount, formatKoreanDate, formatPhoneNumber, formatResidentNumber, isValidBusinessNumber, isValidResidentNumber, maskCardNumber, maskDigits, maskName, maskPhoneNumber, maskResidentNumber, parseResidentNumber } from '@bestow-ui/korean-utils';
6
6
  import * as RadixAccordion from '@radix-ui/react-accordion';
7
7
  import * as Dialog from '@radix-ui/react-dialog';
@@ -69,6 +69,9 @@ declare const lightTokens: {
69
69
  readonly normal: "200ms";
70
70
  readonly slow: "320ms";
71
71
  };
72
+ opacity: {
73
+ readonly disabled: "0.5";
74
+ };
72
75
  zIndex: {
73
76
  readonly overlay: "1300";
74
77
  readonly modal: "1310";
@@ -81,33 +84,9 @@ declare const lightTokens: {
81
84
  type Widen<T> = {
82
85
  [K in keyof T]: T[K] extends string ? string : Widen<T[K]>;
83
86
  };
84
- /**
85
- * 기본값이 없는 선택 토큰 — CSS 변수를 정의하지 않고, 쓰는 곳에서 `fallbackVar` 로 기존 토큰을 따른다.
86
- * 그래서 넣지 않으면 화면이 그대로이고, 기존 토큰(border.default 등)을 덮어쓴 사용자 설정도 계속 따른다(하위 영역의 CSS 덮어쓰기 포함).
87
- * - `color.border.input`·`inputHover` (1.x 추가): 입력 칸(Input·Select·Combobox·Textarea·인증번호 칸 등) 테두리. 기본은 border.default·border.strong.
88
- * 흰 배경과 1.3:1 인 기본 테두리를 3:1 이상으로 올리려면 `strongInputBorders` 를 쓴다(2.0 에서 기본값이 될 예정).
89
- * - `color.border.control` (1.x 추가): Checkbox·Radio 테두리, 꺼진 Switch 트랙, Stepper 의 예정 단계. 기본은 border.strong(라이트 2.07:1).
90
- */
91
- declare const optionalTokens: {
92
- color: {
93
- border: {
94
- input: string;
95
- inputHover: string;
96
- control: string;
97
- };
98
- };
99
- };
100
- type ThemeTokens = Widen<typeof lightTokens> & Widen<typeof optionalTokens>;
87
+ type ThemeTokens = Widen<typeof lightTokens>;
101
88
  declare const vars: {
102
89
  color: {
103
- border: {
104
- input: `var(--${string})`;
105
- inputHover: `var(--${string})`;
106
- control: `var(--${string})`;
107
- default: `var(--${string})`;
108
- strong: `var(--${string})`;
109
- focus: `var(--${string})`;
110
- };
111
90
  bg: {
112
91
  default: `var(--${string})`;
113
92
  subtle: `var(--${string})`;
@@ -121,6 +100,14 @@ declare const vars: {
121
100
  subtle: `var(--${string})`;
122
101
  inverse: `var(--${string})`;
123
102
  };
103
+ border: {
104
+ default: `var(--${string})`;
105
+ strong: `var(--${string})`;
106
+ focus: `var(--${string})`;
107
+ input: `var(--${string})`;
108
+ inputHover: `var(--${string})`;
109
+ control: `var(--${string})`;
110
+ };
124
111
  primary: {
125
112
  solid: `var(--${string})`;
126
113
  solidHover: `var(--${string})`;
@@ -228,6 +215,9 @@ declare const vars: {
228
215
  readonly normal: `var(--${string})`;
229
216
  readonly slow: `var(--${string})`;
230
217
  };
218
+ opacity: {
219
+ readonly disabled: `var(--${string})`;
220
+ };
231
221
  zIndex: {
232
222
  readonly overlay: `var(--${string})`;
233
223
  readonly modal: `var(--${string})`;
@@ -286,13 +276,11 @@ type IntentName = 'primary' | 'neutral' | 'danger' | 'success' | 'warning' | 'in
286
276
  declare function createIntentColors(intent: IntentName, color: string): ThemeInput;
287
277
 
288
278
  /**
289
- * 입력 칸·체크 컨트롤 테두리를 배경과 3:1 이상으로 올리는 테마 입력 (WCAG 1.4.11 비텍스트 대비) — 2.0 에서 기본값이 될 예정.
290
- * - 입력 칸(border.input): 기본 border.default 는 흰 배경과 1.3:1. hover 는 테두리보다 더 진하게(다크는 더 밝게).
291
- * - Checkbox·Radio 테두리, 꺼진 Switch, Stepper 예정 단계(border.control): 기본 border.strong 은 라이트 흰 배경과 2.07:1.
279
+ * 입력 칸·체크 컨트롤 테두리를 배경과 3:1 이상으로 올리는 테마 입력 (WCAG 1.4.11 비텍스트 대비).
280
+ * 1.x 에서 2.0 기본값을 미리 켜던 묶음이다 — 2.0 부터 기본 테두리(border.input·inputHover·control)가 이 값과 같다.
292
281
  *
293
- * @example
294
- * <ThemeProvider overrides={createTheme(strongInputBorders)}>…</ThemeProvider>
295
- * createTheme(createIntentColors('primary', '#7c3aed'), strongInputBorders) // 브랜드 테마와 함께
282
+ * @deprecated 2.0 부터 기본값과 같아 넣지 않아도 된다. 3.0 에서 제거한다(docs/MIGRATION-2.0.md).
283
+ * 객체 값이라 개발 모드 경고(warnOnce)는 내지 않는다 — 읽을 때 경고하려면 getter 가 필요해 tree-shaking 이 깨진다.
296
284
  */
297
285
  declare const strongInputBorders: ThemeInput;
298
286
 
@@ -335,6 +323,7 @@ interface BestowMessages {
335
323
  /** Stepper — 목록 이름 "진행 단계", 완료한 단계에 붙는 "완료" (1.0 이후 추가, 선택 키) */
336
324
  steps?: string;
337
325
  stepCompleted?: string;
326
+ stepInProgress?: string;
338
327
  /**
339
328
  * FileUpload (1.0 이후 추가, 선택 키) — "파일 선택", "또는 여기로 끌어다 놓으세요", "선택한 파일", "○○ 삭제",
340
329
  * "파일 2개 선택됨", "○○ 삭제됨", 크기·형식·개수 초과 안내
@@ -513,6 +502,25 @@ interface BadgeProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'color'> {
513
502
  }
514
503
  declare const Badge: react.ForwardRefExoticComponent<BadgeProps & react.RefAttributes<HTMLSpanElement>>;
515
504
 
505
+ /**
506
+ * `as` 로 다른 요소·컴포넌트를 그리는 컴포넌트(Stack·Card·Grid·Typography·Container·VisuallyHidden)의 타입.
507
+ * - `as` 가 있으면 그 요소·컴포넌트의 props 와 ref 를 따른다 — `as="time"` 의 `dateTime`, `as="a"` 의 `href`, `as={Link}` 의 `href`.
508
+ * - 맞지 않으면 1.x 와 같은 타입(`Props` + `Ref<RefElement>`)으로 한 번 더 확인한다. 그래서 1.x 에서 통과하던 코드
509
+ * (`useRef<HTMLElement>` 를 `as="ul"` 에 넘기기, 필수 props 를 빠뜨린 `as={Link}` 등)는 계속 통과한다.
510
+ * 마지막 시그니처가 1.x 타입이라 `ComponentProps<typeof Stack>`·`ComponentRef<typeof Stack>` 도 1.x 와 같다
511
+ * (TypeScript 는 겹친 시그니처 중 마지막 것으로 추론한다).
512
+ *
513
+ * `Base` 는 `Props` 가 물려받은 HTML 속성 타입 — 이것을 뺀 나머지가 컴포넌트 고유 props 이고, `as` 의 props 보다 우선한다
514
+ * (Typography 의 `color` 처럼 HTML 속성과 이름이 겹치는 고유 prop 이 있으면 Base 에서 그 이름을 뺀다).
515
+ */
516
+ interface PolymorphicComponent<Props, RefElement, Base = HTMLAttributes<HTMLElement>> {
517
+ <C extends ElementType>(props: {
518
+ as: C;
519
+ } & Omit<Props, keyof Base | 'as'> & Omit<ComponentPropsWithRef<C>, Exclude<keyof Props, keyof Base>>): ReactElement | null;
520
+ (props: Props & RefAttributes<RefElement>): ReactElement | null;
521
+ displayName?: string;
522
+ }
523
+
516
524
  interface CardProps extends HTMLAttributes<HTMLElement> {
517
525
  /** 시각적 스타일. outline 은 테두리, elevated 는 그림자(다크 모드는 가장자리 ring 포함), soft 는 옅은 배경 */
518
526
  variant?: 'outline' | 'elevated' | 'soft';
@@ -522,7 +530,7 @@ interface CardProps extends HTMLAttributes<HTMLElement> {
522
530
  as?: ElementType;
523
531
  }
524
532
  /** 배경·테두리·radius·padding 을 가진 컨테이너. 자식 사이 간격은 16px. */
525
- declare const Card: react.ForwardRefExoticComponent<CardProps & react.RefAttributes<HTMLElement>>;
533
+ declare const Card: PolymorphicComponent<CardProps, HTMLElement>;
526
534
  type CardSectionProps = HTMLAttributes<HTMLDivElement>;
527
535
  /** 제목·설명 영역. Typography 와 함께 쓴다. */
528
536
  declare const CardHeader: react.ForwardRefExoticComponent<CardSectionProps & react.RefAttributes<HTMLDivElement>>;
@@ -540,7 +548,7 @@ interface ContainerProps extends HTMLAttributes<HTMLElement> {
540
548
  flush?: boolean;
541
549
  }
542
550
  /** 내용을 가운데에 두고 최대 폭과 좌우 여백을 정하는 페이지 틀 */
543
- declare const Container: react.ForwardRefExoticComponent<ContainerProps & react.RefAttributes<HTMLElement>>;
551
+ declare const Container: PolymorphicComponent<ContainerProps, HTMLElement>;
544
552
 
545
553
  interface DescriptionListItem {
546
554
  /** 이름 (dt) */
@@ -650,7 +658,7 @@ interface GridProps extends HTMLAttributes<HTMLElement> {
650
658
  /** 칸 사이 간격 (space 토큰 키). 구간별 값도 받는다 */
651
659
  gap?: Responsive<keyof typeof space>;
652
660
  }
653
- declare const Grid: react.ForwardRefExoticComponent<GridProps & react.RefAttributes<HTMLElement>>;
661
+ declare const Grid: PolymorphicComponent<GridProps, HTMLElement>;
654
662
 
655
663
  interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'> {
656
664
  /** 현재 값 (0 ~ max). 생략하거나 null 이면 진행률을 모르는 상태(indeterminate)로 움직이는 막대를 보여 준다 */
@@ -706,7 +714,7 @@ interface StackProps extends HTMLAttributes<HTMLElement> {
706
714
  /** 줄바꿈 허용 */
707
715
  wrap?: boolean;
708
716
  }
709
- declare const Stack: react.ForwardRefExoticComponent<StackProps & react.RefAttributes<HTMLElement>>;
717
+ declare const Stack: PolymorphicComponent<StackProps, HTMLElement>;
710
718
 
711
719
  type TypographyVariant = 'display' | 'h1' | 'h2' | 'h3' | 'h4' | 'body-lg' | 'body' | 'body-sm' | 'caption';
712
720
  interface TypographyProps extends Omit<HTMLAttributes<HTMLElement>, 'color'> {
@@ -723,7 +731,7 @@ interface TypographyProps extends Omit<HTMLAttributes<HTMLElement>, 'color'> {
723
731
  /** 한 줄로 자르고 말줄임표를 표시한다 */
724
732
  truncate?: boolean;
725
733
  }
726
- declare const Typography: react.ForwardRefExoticComponent<TypographyProps & react.RefAttributes<HTMLElement>>;
734
+ declare const Typography: PolymorphicComponent<TypographyProps, HTMLElement, Omit<HTMLAttributes<HTMLElement>, "color">>;
727
735
 
728
736
  interface VisuallyHiddenProps extends HTMLAttributes<HTMLElement> {
729
737
  /** 렌더링할 요소 (기본 span) */
@@ -733,7 +741,7 @@ interface VisuallyHiddenProps extends HTMLAttributes<HTMLElement> {
733
741
  * 화면에는 보이지 않고 스크린리더만 읽는 글자. 아이콘만 있는 열 머리글("작업"), 보이는 글자에 붙는 보충 설명 등에 쓴다.
734
742
  * `display: none`·`hidden` 과 달리 보조기술이 읽는다. hook 이 없어 서버 컴포넌트로도 렌더링된다.
735
743
  */
736
- declare const VisuallyHidden: react.ForwardRefExoticComponent<VisuallyHiddenProps & react.RefAttributes<HTMLElement>>;
744
+ declare const VisuallyHidden: PolymorphicComponent<VisuallyHiddenProps, HTMLElement>;
737
745
 
738
746
  /**
739
747
  * 폼 칸으로 포커스를 옮긴다(오류 요약의 링크, 제출 실패 뒤 등). `target` 은 칸의 id 나 요소.
@@ -1061,6 +1069,13 @@ interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'col
1061
1069
  * `disabled` 와 달리 포커스는 유지된다.
1062
1070
  */
1063
1071
  loading?: boolean;
1072
+ /**
1073
+ * 자식 요소(라우터 링크 등)에 버튼 모양과 속성을 입혀 그대로 렌더링한다. 서버 컴포넌트에서도 쓸 수 있다.
1074
+ * 페이지를 이동하는 주요 동작에 쓰고, 자식은 요소 하나여야 한다.
1075
+ * `disabled` 면 `aria-disabled` 를 붙이고 Tab 순서에서 빼며 클릭을 막는다. 휠 클릭은 막지 못하니 링크는 되도록 비활성으로 두지 않는다.
1076
+ * @example <Button asChild><NextLink href="/signup">시작하기</NextLink></Button>
1077
+ */
1078
+ asChild?: boolean;
1064
1079
  }
1065
1080
  declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
1066
1081
 
@@ -1475,6 +1490,8 @@ interface IconButtonProps extends Omit<ButtonProps, 'startIcon' | 'endIcon' | 'f
1475
1490
  loading?: boolean;
1476
1491
  /** 버튼이 하는 일을 설명하는 이름 (예: "삭제"). 아이콘만으로는 스크린리더가 알 수 없어 필수다 */
1477
1492
  'aria-label': string;
1493
+ /** 자식 요소(라우터 링크 등)에 모양과 속성을 입혀 그대로 렌더링한다. 아이콘은 그 요소 안에 넣는다 */
1494
+ asChild?: boolean;
1478
1495
  /** 아이콘. 크기는 버튼 size 에 맞춰 자동으로 조절된다 (sm 16px · md 20px · lg 24px) */
1479
1496
  children: ReactNode;
1480
1497
  }
@@ -1958,6 +1975,11 @@ interface StepperProps extends Omit<OlHTMLAttributes<HTMLOListElement>, 'childre
1958
1975
  current: number;
1959
1976
  /** horizontal(기본): 가로로 나란히, 이름은 원 아래. vertical: 세로로, 이름은 원 오른쪽(설명이 길 때) */
1960
1977
  orientation?: 'horizontal' | 'vertical';
1978
+ /**
1979
+ * 현재 단계가 진행 중이다(AI 응답·업로드 처리 등). 원 안에 스피너를 보여 주고 이름에 "(진행 중)" 을 함께 읽는다.
1980
+ * 단계가 바뀌는 순간을 스크린리더에 알리려면 `role="status"` 영역을 따로 둔다.
1981
+ */
1982
+ loading?: boolean;
1961
1983
  /** 목록 이름 (기본 "진행 단계") */
1962
1984
  'aria-label'?: string;
1963
1985
  }
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _bestow_ui_tokens from '@bestow-ui/tokens';
2
2
  import { space } from '@bestow-ui/tokens';
3
3
  import * as react from 'react';
4
- import { ReactNode, HTMLAttributes, ElementType, CSSProperties, ComponentPropsWithoutRef, InputHTMLAttributes, ButtonHTMLAttributes, AnchorHTMLAttributes, ReactElement, FocusEvent, SelectHTMLAttributes, OlHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes, ChangeEvent, TextareaHTMLAttributes } from 'react';
4
+ import { ReactNode, HTMLAttributes, ElementType, ComponentPropsWithRef, ReactElement, RefAttributes, CSSProperties, ComponentPropsWithoutRef, InputHTMLAttributes, ButtonHTMLAttributes, AnchorHTMLAttributes, FocusEvent, SelectHTMLAttributes, OlHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes, ChangeEvent, TextareaHTMLAttributes } from 'react';
5
5
  export { ResidentNumberInfo, composeExtraAddress, formatBusinessNumber, formatKoreanAmount, formatKoreanDate, formatPhoneNumber, formatResidentNumber, isValidBusinessNumber, isValidResidentNumber, maskCardNumber, maskDigits, maskName, maskPhoneNumber, maskResidentNumber, parseResidentNumber } from '@bestow-ui/korean-utils';
6
6
  import * as RadixAccordion from '@radix-ui/react-accordion';
7
7
  import * as Dialog from '@radix-ui/react-dialog';
@@ -69,6 +69,9 @@ declare const lightTokens: {
69
69
  readonly normal: "200ms";
70
70
  readonly slow: "320ms";
71
71
  };
72
+ opacity: {
73
+ readonly disabled: "0.5";
74
+ };
72
75
  zIndex: {
73
76
  readonly overlay: "1300";
74
77
  readonly modal: "1310";
@@ -81,33 +84,9 @@ declare const lightTokens: {
81
84
  type Widen<T> = {
82
85
  [K in keyof T]: T[K] extends string ? string : Widen<T[K]>;
83
86
  };
84
- /**
85
- * 기본값이 없는 선택 토큰 — CSS 변수를 정의하지 않고, 쓰는 곳에서 `fallbackVar` 로 기존 토큰을 따른다.
86
- * 그래서 넣지 않으면 화면이 그대로이고, 기존 토큰(border.default 등)을 덮어쓴 사용자 설정도 계속 따른다(하위 영역의 CSS 덮어쓰기 포함).
87
- * - `color.border.input`·`inputHover` (1.x 추가): 입력 칸(Input·Select·Combobox·Textarea·인증번호 칸 등) 테두리. 기본은 border.default·border.strong.
88
- * 흰 배경과 1.3:1 인 기본 테두리를 3:1 이상으로 올리려면 `strongInputBorders` 를 쓴다(2.0 에서 기본값이 될 예정).
89
- * - `color.border.control` (1.x 추가): Checkbox·Radio 테두리, 꺼진 Switch 트랙, Stepper 의 예정 단계. 기본은 border.strong(라이트 2.07:1).
90
- */
91
- declare const optionalTokens: {
92
- color: {
93
- border: {
94
- input: string;
95
- inputHover: string;
96
- control: string;
97
- };
98
- };
99
- };
100
- type ThemeTokens = Widen<typeof lightTokens> & Widen<typeof optionalTokens>;
87
+ type ThemeTokens = Widen<typeof lightTokens>;
101
88
  declare const vars: {
102
89
  color: {
103
- border: {
104
- input: `var(--${string})`;
105
- inputHover: `var(--${string})`;
106
- control: `var(--${string})`;
107
- default: `var(--${string})`;
108
- strong: `var(--${string})`;
109
- focus: `var(--${string})`;
110
- };
111
90
  bg: {
112
91
  default: `var(--${string})`;
113
92
  subtle: `var(--${string})`;
@@ -121,6 +100,14 @@ declare const vars: {
121
100
  subtle: `var(--${string})`;
122
101
  inverse: `var(--${string})`;
123
102
  };
103
+ border: {
104
+ default: `var(--${string})`;
105
+ strong: `var(--${string})`;
106
+ focus: `var(--${string})`;
107
+ input: `var(--${string})`;
108
+ inputHover: `var(--${string})`;
109
+ control: `var(--${string})`;
110
+ };
124
111
  primary: {
125
112
  solid: `var(--${string})`;
126
113
  solidHover: `var(--${string})`;
@@ -228,6 +215,9 @@ declare const vars: {
228
215
  readonly normal: `var(--${string})`;
229
216
  readonly slow: `var(--${string})`;
230
217
  };
218
+ opacity: {
219
+ readonly disabled: `var(--${string})`;
220
+ };
231
221
  zIndex: {
232
222
  readonly overlay: `var(--${string})`;
233
223
  readonly modal: `var(--${string})`;
@@ -286,13 +276,11 @@ type IntentName = 'primary' | 'neutral' | 'danger' | 'success' | 'warning' | 'in
286
276
  declare function createIntentColors(intent: IntentName, color: string): ThemeInput;
287
277
 
288
278
  /**
289
- * 입력 칸·체크 컨트롤 테두리를 배경과 3:1 이상으로 올리는 테마 입력 (WCAG 1.4.11 비텍스트 대비) — 2.0 에서 기본값이 될 예정.
290
- * - 입력 칸(border.input): 기본 border.default 는 흰 배경과 1.3:1. hover 는 테두리보다 더 진하게(다크는 더 밝게).
291
- * - Checkbox·Radio 테두리, 꺼진 Switch, Stepper 예정 단계(border.control): 기본 border.strong 은 라이트 흰 배경과 2.07:1.
279
+ * 입력 칸·체크 컨트롤 테두리를 배경과 3:1 이상으로 올리는 테마 입력 (WCAG 1.4.11 비텍스트 대비).
280
+ * 1.x 에서 2.0 기본값을 미리 켜던 묶음이다 — 2.0 부터 기본 테두리(border.input·inputHover·control)가 이 값과 같다.
292
281
  *
293
- * @example
294
- * <ThemeProvider overrides={createTheme(strongInputBorders)}>…</ThemeProvider>
295
- * createTheme(createIntentColors('primary', '#7c3aed'), strongInputBorders) // 브랜드 테마와 함께
282
+ * @deprecated 2.0 부터 기본값과 같아 넣지 않아도 된다. 3.0 에서 제거한다(docs/MIGRATION-2.0.md).
283
+ * 객체 값이라 개발 모드 경고(warnOnce)는 내지 않는다 — 읽을 때 경고하려면 getter 가 필요해 tree-shaking 이 깨진다.
296
284
  */
297
285
  declare const strongInputBorders: ThemeInput;
298
286
 
@@ -335,6 +323,7 @@ interface BestowMessages {
335
323
  /** Stepper — 목록 이름 "진행 단계", 완료한 단계에 붙는 "완료" (1.0 이후 추가, 선택 키) */
336
324
  steps?: string;
337
325
  stepCompleted?: string;
326
+ stepInProgress?: string;
338
327
  /**
339
328
  * FileUpload (1.0 이후 추가, 선택 키) — "파일 선택", "또는 여기로 끌어다 놓으세요", "선택한 파일", "○○ 삭제",
340
329
  * "파일 2개 선택됨", "○○ 삭제됨", 크기·형식·개수 초과 안내
@@ -513,6 +502,25 @@ interface BadgeProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'color'> {
513
502
  }
514
503
  declare const Badge: react.ForwardRefExoticComponent<BadgeProps & react.RefAttributes<HTMLSpanElement>>;
515
504
 
505
+ /**
506
+ * `as` 로 다른 요소·컴포넌트를 그리는 컴포넌트(Stack·Card·Grid·Typography·Container·VisuallyHidden)의 타입.
507
+ * - `as` 가 있으면 그 요소·컴포넌트의 props 와 ref 를 따른다 — `as="time"` 의 `dateTime`, `as="a"` 의 `href`, `as={Link}` 의 `href`.
508
+ * - 맞지 않으면 1.x 와 같은 타입(`Props` + `Ref<RefElement>`)으로 한 번 더 확인한다. 그래서 1.x 에서 통과하던 코드
509
+ * (`useRef<HTMLElement>` 를 `as="ul"` 에 넘기기, 필수 props 를 빠뜨린 `as={Link}` 등)는 계속 통과한다.
510
+ * 마지막 시그니처가 1.x 타입이라 `ComponentProps<typeof Stack>`·`ComponentRef<typeof Stack>` 도 1.x 와 같다
511
+ * (TypeScript 는 겹친 시그니처 중 마지막 것으로 추론한다).
512
+ *
513
+ * `Base` 는 `Props` 가 물려받은 HTML 속성 타입 — 이것을 뺀 나머지가 컴포넌트 고유 props 이고, `as` 의 props 보다 우선한다
514
+ * (Typography 의 `color` 처럼 HTML 속성과 이름이 겹치는 고유 prop 이 있으면 Base 에서 그 이름을 뺀다).
515
+ */
516
+ interface PolymorphicComponent<Props, RefElement, Base = HTMLAttributes<HTMLElement>> {
517
+ <C extends ElementType>(props: {
518
+ as: C;
519
+ } & Omit<Props, keyof Base | 'as'> & Omit<ComponentPropsWithRef<C>, Exclude<keyof Props, keyof Base>>): ReactElement | null;
520
+ (props: Props & RefAttributes<RefElement>): ReactElement | null;
521
+ displayName?: string;
522
+ }
523
+
516
524
  interface CardProps extends HTMLAttributes<HTMLElement> {
517
525
  /** 시각적 스타일. outline 은 테두리, elevated 는 그림자(다크 모드는 가장자리 ring 포함), soft 는 옅은 배경 */
518
526
  variant?: 'outline' | 'elevated' | 'soft';
@@ -522,7 +530,7 @@ interface CardProps extends HTMLAttributes<HTMLElement> {
522
530
  as?: ElementType;
523
531
  }
524
532
  /** 배경·테두리·radius·padding 을 가진 컨테이너. 자식 사이 간격은 16px. */
525
- declare const Card: react.ForwardRefExoticComponent<CardProps & react.RefAttributes<HTMLElement>>;
533
+ declare const Card: PolymorphicComponent<CardProps, HTMLElement>;
526
534
  type CardSectionProps = HTMLAttributes<HTMLDivElement>;
527
535
  /** 제목·설명 영역. Typography 와 함께 쓴다. */
528
536
  declare const CardHeader: react.ForwardRefExoticComponent<CardSectionProps & react.RefAttributes<HTMLDivElement>>;
@@ -540,7 +548,7 @@ interface ContainerProps extends HTMLAttributes<HTMLElement> {
540
548
  flush?: boolean;
541
549
  }
542
550
  /** 내용을 가운데에 두고 최대 폭과 좌우 여백을 정하는 페이지 틀 */
543
- declare const Container: react.ForwardRefExoticComponent<ContainerProps & react.RefAttributes<HTMLElement>>;
551
+ declare const Container: PolymorphicComponent<ContainerProps, HTMLElement>;
544
552
 
545
553
  interface DescriptionListItem {
546
554
  /** 이름 (dt) */
@@ -650,7 +658,7 @@ interface GridProps extends HTMLAttributes<HTMLElement> {
650
658
  /** 칸 사이 간격 (space 토큰 키). 구간별 값도 받는다 */
651
659
  gap?: Responsive<keyof typeof space>;
652
660
  }
653
- declare const Grid: react.ForwardRefExoticComponent<GridProps & react.RefAttributes<HTMLElement>>;
661
+ declare const Grid: PolymorphicComponent<GridProps, HTMLElement>;
654
662
 
655
663
  interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'color'> {
656
664
  /** 현재 값 (0 ~ max). 생략하거나 null 이면 진행률을 모르는 상태(indeterminate)로 움직이는 막대를 보여 준다 */
@@ -706,7 +714,7 @@ interface StackProps extends HTMLAttributes<HTMLElement> {
706
714
  /** 줄바꿈 허용 */
707
715
  wrap?: boolean;
708
716
  }
709
- declare const Stack: react.ForwardRefExoticComponent<StackProps & react.RefAttributes<HTMLElement>>;
717
+ declare const Stack: PolymorphicComponent<StackProps, HTMLElement>;
710
718
 
711
719
  type TypographyVariant = 'display' | 'h1' | 'h2' | 'h3' | 'h4' | 'body-lg' | 'body' | 'body-sm' | 'caption';
712
720
  interface TypographyProps extends Omit<HTMLAttributes<HTMLElement>, 'color'> {
@@ -723,7 +731,7 @@ interface TypographyProps extends Omit<HTMLAttributes<HTMLElement>, 'color'> {
723
731
  /** 한 줄로 자르고 말줄임표를 표시한다 */
724
732
  truncate?: boolean;
725
733
  }
726
- declare const Typography: react.ForwardRefExoticComponent<TypographyProps & react.RefAttributes<HTMLElement>>;
734
+ declare const Typography: PolymorphicComponent<TypographyProps, HTMLElement, Omit<HTMLAttributes<HTMLElement>, "color">>;
727
735
 
728
736
  interface VisuallyHiddenProps extends HTMLAttributes<HTMLElement> {
729
737
  /** 렌더링할 요소 (기본 span) */
@@ -733,7 +741,7 @@ interface VisuallyHiddenProps extends HTMLAttributes<HTMLElement> {
733
741
  * 화면에는 보이지 않고 스크린리더만 읽는 글자. 아이콘만 있는 열 머리글("작업"), 보이는 글자에 붙는 보충 설명 등에 쓴다.
734
742
  * `display: none`·`hidden` 과 달리 보조기술이 읽는다. hook 이 없어 서버 컴포넌트로도 렌더링된다.
735
743
  */
736
- declare const VisuallyHidden: react.ForwardRefExoticComponent<VisuallyHiddenProps & react.RefAttributes<HTMLElement>>;
744
+ declare const VisuallyHidden: PolymorphicComponent<VisuallyHiddenProps, HTMLElement>;
737
745
 
738
746
  /**
739
747
  * 폼 칸으로 포커스를 옮긴다(오류 요약의 링크, 제출 실패 뒤 등). `target` 은 칸의 id 나 요소.
@@ -1061,6 +1069,13 @@ interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'col
1061
1069
  * `disabled` 와 달리 포커스는 유지된다.
1062
1070
  */
1063
1071
  loading?: boolean;
1072
+ /**
1073
+ * 자식 요소(라우터 링크 등)에 버튼 모양과 속성을 입혀 그대로 렌더링한다. 서버 컴포넌트에서도 쓸 수 있다.
1074
+ * 페이지를 이동하는 주요 동작에 쓰고, 자식은 요소 하나여야 한다.
1075
+ * `disabled` 면 `aria-disabled` 를 붙이고 Tab 순서에서 빼며 클릭을 막는다. 휠 클릭은 막지 못하니 링크는 되도록 비활성으로 두지 않는다.
1076
+ * @example <Button asChild><NextLink href="/signup">시작하기</NextLink></Button>
1077
+ */
1078
+ asChild?: boolean;
1064
1079
  }
1065
1080
  declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
1066
1081
 
@@ -1475,6 +1490,8 @@ interface IconButtonProps extends Omit<ButtonProps, 'startIcon' | 'endIcon' | 'f
1475
1490
  loading?: boolean;
1476
1491
  /** 버튼이 하는 일을 설명하는 이름 (예: "삭제"). 아이콘만으로는 스크린리더가 알 수 없어 필수다 */
1477
1492
  'aria-label': string;
1493
+ /** 자식 요소(라우터 링크 등)에 모양과 속성을 입혀 그대로 렌더링한다. 아이콘은 그 요소 안에 넣는다 */
1494
+ asChild?: boolean;
1478
1495
  /** 아이콘. 크기는 버튼 size 에 맞춰 자동으로 조절된다 (sm 16px · md 20px · lg 24px) */
1479
1496
  children: ReactNode;
1480
1497
  }
@@ -1958,6 +1975,11 @@ interface StepperProps extends Omit<OlHTMLAttributes<HTMLOListElement>, 'childre
1958
1975
  current: number;
1959
1976
  /** horizontal(기본): 가로로 나란히, 이름은 원 아래. vertical: 세로로, 이름은 원 오른쪽(설명이 길 때) */
1960
1977
  orientation?: 'horizontal' | 'vertical';
1978
+ /**
1979
+ * 현재 단계가 진행 중이다(AI 응답·업로드 처리 등). 원 안에 스피너를 보여 주고 이름에 "(진행 중)" 을 함께 읽는다.
1980
+ * 단계가 바뀌는 순간을 스크린리더에 알리려면 `role="status"` 영역을 따로 둔다.
1981
+ */
1982
+ loading?: boolean;
1961
1983
  /** 목록 이름 (기본 "진행 단계") */
1962
1984
  'aria-label'?: string;
1963
1985
  }
package/dist/shared.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  toISODate,
18
18
  vars,
19
19
  visuallyHidden
20
- } from "./chunk-YYLDXZWR.js";
20
+ } from "./chunk-BDQ5IJIS.js";
21
21
 
22
22
  // src/theme/color.ts
23
23
  import { darkColors, lightColors, palette } from "@bestow-ui/tokens";
@@ -200,6 +200,7 @@ var en = {
200
200
  increment: "Increase",
201
201
  steps: "Progress",
202
202
  stepCompleted: "completed",
203
+ stepInProgress: "in progress",
203
204
  fileSelect: "Choose files",
204
205
  fileDropHint: "or drag and drop here",
205
206
  fileList: "Selected files",