@bigtablet/design-system 3.16.0 → 3.17.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.ts CHANGED
@@ -35,6 +35,39 @@ type ClassValue = string | number | boolean | undefined | null | ClassValue[] |
35
35
  */
36
36
  declare const cn: (...classes: ClassValue[]) => string;
37
37
 
38
+ /**
39
+ * `as` 로 렌더 요소를 바꾸는 컴포넌트의 props 타입.
40
+ *
41
+ * 왜 필요한가 - `as?: "button" | "a"` 리터럴 유니온으로는 `as={Link}` 처럼 **컴포넌트**를 넘길
42
+ * 수 없다. Next.js 앱에서 DS 버튼을 라우터 링크로 쓰려면 소비자가 DS 를 우회해 자기 버튼을
43
+ * 만들게 되고, 우회가 시작되는 지점이 DS 이탈이 시작되는 지점이다.
44
+ *
45
+ * `as` 에 준 요소의 props 가 그대로 따라온다 - `as="a"` 면 `href`·`target`, `as={Link}` 면
46
+ * `Link` 의 props 가 타입에 들어오고, 컴포넌트 자기 props(`Own`)와 겹치는 이름은 `Own` 이 이긴다.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * interface OwnProps { variant?: "filled" | "text" }
51
+ *
52
+ * const Thing = <T extends React.ElementType = "button">({
53
+ * as,
54
+ * variant = "filled",
55
+ * ...rest
56
+ * }: PolymorphicProps<T, OwnProps>) => {
57
+ * const Tag = as ?? "button";
58
+ * return <Tag {...rest} />;
59
+ * };
60
+ * ```
61
+ */
62
+ type PolymorphicProps<T extends React$1.ElementType, Own> = Own & {
63
+ /** 렌더할 요소나 컴포넌트 */
64
+ as?: T;
65
+ /** 루트 요소 ref (React 19 ref-as-prop) */
66
+ ref?: PolymorphicRef<T>;
67
+ } & Omit<React$1.ComponentPropsWithoutRef<T>, keyof Own | "as" | "ref">;
68
+ /** `as` 에 준 요소의 ref 타입 */
69
+ type PolymorphicRef<T extends React$1.ElementType> = React$1.ComponentPropsWithRef<T>["ref"];
70
+
38
71
  declare function useFocusTrap(containerRef: React$1.RefObject<HTMLElement | null>, isActive: boolean): void;
39
72
 
40
73
  /**
@@ -100,6 +133,64 @@ declare function useSpringPresence({ visible, from, onExitComplete, }: {
100
133
  transform: _react_spring_web.SpringValue<string>;
101
134
  };
102
135
 
136
+ /** 팝업 목록의 한 항목이 최소한 갖춰야 하는 모양. 라벨·값 등 나머지는 소비자 몫이다. */
137
+ interface ListboxItem {
138
+ /** 비활성 항목은 키보드 이동에서 건너뛰고 선택되지 않는다 */
139
+ disabled?: boolean;
140
+ }
141
+ interface UseListboxPopupArgs<T extends ListboxItem> {
142
+ /** 현재 목록에 보이는 항목 (검색 필터가 적용된 뒤의 배열) */
143
+ items: T[];
144
+ /** 항목이 확정될 때 호출 - Enter 또는 클릭 */
145
+ onCommit: (item: T) => void;
146
+ /** 트리거가 비활성이면 키보드 처리를 하지 않는다 */
147
+ disabled?: boolean;
148
+ /**
149
+ * 패널을 닫을 때 트리거로 포커스를 되돌릴지. 포커스가 패널 안(검색 입력)에 있는
150
+ * 형태에서 필요하다 - 안 되돌리면 닫는 순간 포커스가 body 로 유실된다.
151
+ */
152
+ returnFocusOnClose?: boolean;
153
+ /** 열릴 때 활성으로 둘 항목의 인덱스. 보통 선택된 항목 */
154
+ initialActiveIndex?: (items: T[]) => number;
155
+ }
156
+ interface UseListboxPopupResult {
157
+ isOpen: boolean;
158
+ setIsOpen: React$1.Dispatch<React$1.SetStateAction<boolean>>;
159
+ /** 위로 열릴지 - 아래 공간이 모자랄 때만 true */
160
+ dropUp: boolean;
161
+ activeIndex: number;
162
+ setActiveIndex: React$1.Dispatch<React$1.SetStateAction<number>>;
163
+ /** 바깥 클릭 감지 기준. 트리거와 패널을 함께 감싸는 요소에 붙인다 */
164
+ wrapperRef: React$1.RefObject<HTMLDivElement | null>;
165
+ /** 트리거 요소. 닫을 때 포커스를 되돌릴 대상 */
166
+ triggerRef: React$1.RefObject<HTMLButtonElement | null>;
167
+ /**
168
+ * 스크롤되는 목록 요소(`role="listbox"`). 붙이면 방향키로 옮긴 활성 항목을 따라 스크롤한다.
169
+ * 안 붙여도 나머지 동작은 그대로다 - 목록이 짧아 스크롤이 없는 경우.
170
+ */
171
+ listRef: React$1.RefObject<HTMLDivElement | null>;
172
+ /** 닫고 필요하면 트리거로 포커스를 되돌린다 */
173
+ close: () => void;
174
+ /** 방향키 이동 - 비활성 항목을 건너뛰고 양끝에서 순환한다 */
175
+ moveActive: (dir: 1 | -1) => void;
176
+ /** 현재 활성 항목을 확정한다 */
177
+ commitActive: () => void;
178
+ /** 트리거(button)용 키보드 핸들러 */
179
+ onTriggerKeyDown: (event: React$1.KeyboardEvent<HTMLElement>) => void;
180
+ /** 패널 안 입력(검색·콤보박스)용 키보드 핸들러 */
181
+ onInputKeyDown: (event: React$1.KeyboardEvent<HTMLElement>) => void;
182
+ }
183
+ /**
184
+ * 트리거 + 팝업 목록의 개폐·활성 항목·키보드·바깥 클릭·열림 방향을 담당한다.
185
+ *
186
+ * `Dropdown` 이 이 로직을 인라인으로 갖고 있었다. `Combobox` 가 같은 동작(APG Combobox 키보드
187
+ * 규약, 비활성 건너뛰기, dropUp)을 필요로 하는데, 복사하면 두 벌이 갈린다 - 이 저장소에서
188
+ * "형제 구현 한쪽만 고침" 이 이미 네 번 났다.
189
+ *
190
+ * 목록의 **내용**(검색·다중 선택·비동기)은 소비자가 갖는다. 이 훅은 팝업의 **거동**만 안다.
191
+ */
192
+ declare function useListboxPopup<T extends ListboxItem>({ items, onCommit, disabled, returnFocusOnClose, initialActiveIndex, }: UseListboxPopupArgs<T>): UseListboxPopupResult;
193
+
103
194
  interface AccordionItem {
104
195
  key: string;
105
196
  title: React$1.ReactNode;
@@ -196,6 +287,98 @@ interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
196
287
  */
197
288
  declare const Badge: ({ variant, shape, size, appearance, count, max, className, children, ...props }: BadgeProps) => React$1.JSX.Element;
198
289
 
290
+ interface DescriptionListItem {
291
+ /** 항목 이름 */
292
+ label: React$1.ReactNode;
293
+ /** 항목 값 */
294
+ value: React$1.ReactNode;
295
+ /** 이 항목만 값을 한 줄 전체로 (긴 주소·메모) */
296
+ full?: boolean;
297
+ }
298
+ type DescriptionListLayout = "row" | "stack";
299
+ interface DescriptionListProps extends React$1.HTMLAttributes<HTMLDListElement> {
300
+ /** 이름·값 쌍 */
301
+ items: DescriptionListItem[];
302
+ /**
303
+ * 배치 (기본값: "row").
304
+ * - `row`: 이름 왼쪽, 값 오른쪽. 좁은 화면에서는 자동으로 쌓인다
305
+ * - `stack`: 항상 이름 위, 값 아래
306
+ */
307
+ layout?: DescriptionListLayout;
308
+ /** 항목 사이 구분선 (기본값: false) */
309
+ divided?: boolean;
310
+ /** 루트 요소 ref (React 19 ref-as-prop) */
311
+ ref?: React$1.Ref<HTMLDListElement>;
312
+ }
313
+ /**
314
+ * 이름·값 쌍의 목록. 상세 보기 화면의 기본 골격이다.
315
+ *
316
+ * `<dl>` · `<dt>` · `<dd>` 로 렌더한다 - 손으로 만들면 거의 항상 `<div>` 두 개가 되고, 그러면
317
+ * 스크린리더에 이름과 값의 관계가 남지 않는다. 이름만 읽고 값을 따로 읽어 주는 목록이 된다.
318
+ *
319
+ * `row` 는 좁은 화면에서 스스로 쌓인다 - 이름과 값을 한 줄에 억지로 붙이면 값이 잘린다.
320
+ *
321
+ * @example
322
+ * ```tsx
323
+ * <DescriptionList
324
+ * divided
325
+ * items={[
326
+ * { label: "주문번호", value: "#1024" },
327
+ * { label: "결제수단", value: "신용카드" },
328
+ * { label: "배송지", value: "서울시 …", full: true },
329
+ * ]}
330
+ * />
331
+ * ```
332
+ */
333
+ declare const DescriptionList: ({ items, layout, divided, className, ref, ...props }: DescriptionListProps) => React$1.JSX.Element;
334
+
335
+ /** 변화량의 색. 방향(↑↓)과 좋음/나쁨은 다르다 - "재고 부족 +2" 는 오르지만 나쁘다 */
336
+ type StatDeltaTone = "positive" | "negative" | "neutral";
337
+ interface StatProps extends React$1.HTMLAttributes<HTMLDivElement> {
338
+ /** 지표 이름 */
339
+ label: React$1.ReactNode;
340
+ /** 지표 값. 숫자는 `tabular-nums` 로 폭이 고정된다 */
341
+ value: React$1.ReactNode;
342
+ /** 값 아래 변화량 (예: `+12%`) */
343
+ delta?: React$1.ReactNode;
344
+ /**
345
+ * 변화량의 색 (기본값: "neutral").
346
+ * 방향이 아니라 **좋음/나쁨**을 고른다 - 재고 부족이 늘어난 것은 `negative` 다.
347
+ */
348
+ deltaTone?: StatDeltaTone;
349
+ /** 라벨 왼쪽 장식 아이콘 */
350
+ icon?: React$1.ReactNode;
351
+ /** 루트 요소 ref (React 19 ref-as-prop) */
352
+ ref?: React$1.Ref<HTMLDivElement>;
353
+ }
354
+ declare const Stat: ({ label, value, delta, deltaTone, icon, className, ref, ...props }: StatProps) => React$1.JSX.Element;
355
+
356
+ /** 항목의 진행 상태. 색과 연결선의 진하기를 정한다 */
357
+ type TimelineStatus = "done" | "active" | "pending";
358
+ interface TimelineItem {
359
+ /** 목록 키 */
360
+ id: string | number;
361
+ /** 항목 제목 */
362
+ title: React$1.ReactNode;
363
+ /** 제목 오른쪽의 시각 */
364
+ time?: React$1.ReactNode;
365
+ /** 제목 아래 설명 */
366
+ description?: React$1.ReactNode;
367
+ /** 진행 상태 (기본값: "pending") */
368
+ status?: TimelineStatus;
369
+ /** 인디케이터 안에 넣을 아이콘. 없으면 점 */
370
+ icon?: React$1.ReactNode;
371
+ /** 항목 아래에 붙일 임의 내용 (첨부, 액션 버튼 등) */
372
+ children?: React$1.ReactNode;
373
+ }
374
+ interface TimelineProps extends React$1.HTMLAttributes<HTMLOListElement> {
375
+ /** 위에서 아래로 흐르는 순서대로 */
376
+ items: TimelineItem[];
377
+ /** 루트 요소 ref (React 19 ref-as-prop) */
378
+ ref?: React$1.Ref<HTMLOListElement>;
379
+ }
380
+ declare const Timeline: ({ items, className, ref, ...props }: TimelineProps) => React$1.JSX.Element;
381
+
199
382
  interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title"> {
200
383
  /**
201
384
  * 일러스트 영역 (아이콘/이미지 등). **장식 전용** - `aria-hidden="true"` 래퍼로 접근성 트리에서
@@ -273,7 +456,7 @@ interface ErrorStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "
273
456
  * <ErrorState variant="widget" title="불러오기 실패" action={<Button size="sm" onClick={retry}>재시도</Button>} />
274
457
  * ```
275
458
  */
276
- declare const ErrorState: ({ title, description, icon, action, variant, className, ...props }: ErrorStateProps) => React$1.JSX.Element;
459
+ declare const ErrorState: ({ title: titleProp, description, icon, action, variant, className, ...props }: ErrorStateProps) => React$1.JSX.Element;
277
460
 
278
461
  interface BottomNavProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "onChange"> {
279
462
  /** 스크린 리더 레이블 (기본 "주요 메뉴") */
@@ -298,7 +481,7 @@ interface BottomNavProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "onCh
298
481
  * <BottomNavSpacer />
299
482
  * ```
300
483
  */
301
- declare const BottomNav: ({ ariaLabel, className, children, ...props }: BottomNavProps) => React$1.JSX.Element;
484
+ declare const BottomNav: ({ ariaLabel: ariaLabelProp, className, children, ...props }: BottomNavProps) => React$1.JSX.Element;
302
485
  interface BottomNavItemCommon {
303
486
  /** 아이콘 (필수) */
304
487
  icon: React$1.ReactNode;
@@ -309,22 +492,27 @@ interface BottomNavItemCommon {
309
492
  /** 아이콘 우상단 dot/카운트 (Badge 등) */
310
493
  badge?: React$1.ReactNode;
311
494
  }
312
- type BottomNavItemButton = BottomNavItemCommon & {
313
- as?: "button";
314
- href?: never;
315
- } & Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, "children">;
316
- type BottomNavItemAnchor = BottomNavItemCommon & {
317
- as: "a";
318
- href: string;
319
- /** anchor native `disabled` 없음 - `aria-disabled` + `preventDefault` 로 처리. */
495
+ /**
496
+ * BottomNavItem props. `as` 로 렌더 요소를 바꾼다 - `"a"`, `Link`(Next.js) 등 무엇이든.
497
+ *
498
+ * `disabled` 는 여기 남는다 - anchor·커스텀 컴포넌트에는 native `disabled` 가 없어
499
+ * `aria-disabled` + `tabIndex={-1}` + 클릭 차단으로 처리해야 하기 때문이다.
500
+ *
501
+ * `as="a"` 면 `href` 는 **필수**다 - 판별 유니온 시절 계약이고, `href` 없는 `<a>` 는 링크
502
+ * 시맨틱이 없다(`AnchorHTMLAttributes.href` 옵션이라 그대로 두면 느슨해진다).
503
+ */
504
+ type BottomNavItemProps<T extends React$1.ElementType = "button"> = PolymorphicProps<T, BottomNavItemCommon & {
320
505
  disabled?: boolean;
321
- } & Omit<React$1.AnchorHTMLAttributes<HTMLAnchorElement>, "children" | "type">;
322
- type BottomNavItemProps = BottomNavItemButton | BottomNavItemAnchor;
506
+ }> & ("button" extends T ? {
507
+ href?: string;
508
+ } : Record<never, never>) & ("a" extends T ? {
509
+ href: string;
510
+ } : Record<never, never>);
323
511
  /**
324
512
  * `BottomNav` 의 항목. icon + label 수직 스택.
325
513
  * active 시 `aria-current="page"` 자동 부여.
326
514
  */
327
- declare const BottomNavItem: (props: BottomNavItemProps) => React$1.JSX.Element;
515
+ declare const BottomNavItem: <T extends React$1.ElementType = "button">(props: BottomNavItemProps<T>) => React$1.JSX.Element;
328
516
  /**
329
517
  * 페이지 본문 끝에 두면 `BottomNav` 가 콘텐츠를 가리지 않게 빈 공간 확보.
330
518
  * `--bt-bottom-nav-height` (+ safe-area) 만큼 height.
@@ -359,7 +547,7 @@ interface BreadcrumbProps extends React$1.HTMLAttributes<HTMLElement> {
359
547
  * ]} />
360
548
  * ```
361
549
  */
362
- declare const Breadcrumb: ({ items, separator, navLabel, className, ...props }: BreadcrumbProps) => React$1.JSX.Element;
550
+ declare const Breadcrumb: ({ items, separator, navLabel: navLabelProp, className, ...props }: BreadcrumbProps) => React$1.JSX.Element;
363
551
 
364
552
  interface MenuItem {
365
553
  key: string;
@@ -516,8 +704,14 @@ interface SidebarProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "onChan
516
704
  * </Sidebar>
517
705
  * ```
518
706
  */
519
- declare const Sidebar: ({ header, headerCollapsed, footer, collapsed: collapsedProp, defaultCollapsed, onCollapsedChange, collapsible, toggleLabel, width, collapsedWidth, mode, className, children, style, ...props }: SidebarProps) => React$1.JSX.Element;
707
+ declare const Sidebar: ({ header, headerCollapsed, footer, collapsed: collapsedProp, defaultCollapsed, onCollapsedChange, collapsible, toggleLabel: toggleLabelProp, width, collapsedWidth, mode, className, children, style, ...props }: SidebarProps) => React$1.JSX.Element;
520
708
  interface SidebarItemCommon {
709
+ /**
710
+ * 비활성. `<button>` 은 native `disabled`, 그 밖의 요소(anchor·`Link` 등)는
711
+ * `aria-disabled` + `tabIndex={-1}` + 클릭 차단으로 처리한다 - native `disabled` 가 없는
712
+ * 요소에 그냥 넘기면 조용히 무시되고 비활성 항목이 눌린다.
713
+ */
714
+ disabled?: boolean;
521
715
  /** 왼쪽 아이콘 */
522
716
  icon?: React$1.ReactNode;
523
717
  /** 현재 활성 상태 */
@@ -525,16 +719,21 @@ interface SidebarItemCommon {
525
719
  /** 오른쪽 trailing (Badge 등) */
526
720
  trailing?: React$1.ReactNode;
527
721
  }
528
- type SidebarItemButton = SidebarItemCommon & {
529
- as?: "button";
530
- href?: never;
531
- } & React$1.ButtonHTMLAttributes<HTMLButtonElement>;
532
- type SidebarItemAnchor = SidebarItemCommon & {
533
- as: "a";
722
+ /**
723
+ * SidebarItem props. `as` 로 렌더 요소를 바꾼다 - `"a"`, `Link`(Next.js) 등 무엇이든.
724
+ *
725
+ * 리터럴 유니온(`"button" | "a"`)이었을 때는 Next 앱에서 사이드바 항목을 라우터 링크로 만들
726
+ * 방법이 없어, 소비자가 DS 를 우회해 자기 항목을 만들었다.
727
+ *
728
+ * `as="a"` 면 `href` 는 **필수**다 - 판별 유니온 시절 계약이고, `href` 없는 `<a>` 는 링크
729
+ * 시맨틱이 없다(`AnchorHTMLAttributes.href` 가 옵션이라 그대로 두면 느슨해진다).
730
+ */
731
+ type SidebarItemProps<T extends React$1.ElementType = "button"> = PolymorphicProps<T, SidebarItemCommon> & ("button" extends T ? {
732
+ href?: string;
733
+ } : Record<never, never>) & ("a" extends T ? {
534
734
  href: string;
535
- } & Omit<React$1.AnchorHTMLAttributes<HTMLAnchorElement>, "type">;
536
- type SidebarItemProps = SidebarItemButton | SidebarItemAnchor;
537
- declare const SidebarItem: (props: SidebarItemProps) => React$1.JSX.Element;
735
+ } : Record<never, never>);
736
+ declare const SidebarItem: <T extends React$1.ElementType = "button">(props: SidebarItemProps<T>) => React$1.JSX.Element;
538
737
  interface SidebarSectionProps extends React$1.HTMLAttributes<HTMLDivElement> {
539
738
  /** 섹션 라벨 (collapsed 상태에선 hidden) */
540
739
  label?: string;
@@ -1212,6 +1411,196 @@ interface ChipProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "onClic
1212
1411
  }
1213
1412
  declare const Chip: ({ type, size, tone, label, selected, removable, disabled, open, leadingIcon, onClick, onRemove, removeLabel, className, ...props }: ChipProps) => React$1.JSX.Element;
1214
1413
 
1414
+ type TableSize = "sm" | "md" | "lg";
1415
+ type TableSortDirection = "asc" | "desc";
1416
+ interface TableSort {
1417
+ /** 정렬 중인 컬럼의 `TableColumn.key` */
1418
+ key: string;
1419
+ /** 정렬 방향 */
1420
+ direction: TableSortDirection;
1421
+ }
1422
+ interface TableColumn<T extends object> {
1423
+ /** 컬럼 식별자 - `data[key]` 자동 렌더링에도 쓰임 */
1424
+ key: string;
1425
+ /** thead에 표시할 헤더 텍스트 */
1426
+ header: React$1.ReactNode;
1427
+ /** 셀 렌더 함수. 없으면 `item[key]` 자동 렌더 */
1428
+ render?: (item: T, index: number) => React$1.ReactNode;
1429
+ /** CSS width 값 (예: "120px", "20%") */
1430
+ width?: string;
1431
+ /** 정렬 */
1432
+ align?: "left" | "center" | "right";
1433
+ /** 정렬 가능한 컬럼 여부 (기본값: false). 클릭 시 `onSortChange` 발화 - 실제 정렬은 소비자가 수행 */
1434
+ sortable?: boolean;
1435
+ }
1436
+ /** `selectable` 시 `rowKey` 를 요구하기 위한 판별 유니온 */
1437
+ type TableSelectionProps<T extends object> = {
1438
+ /** 행 선택(체크박스 컬럼) 활성화 여부 */
1439
+ selectable: true;
1440
+ /** 행 고유 key 추출 함수 - `selectable` 사용 시 필수 */
1441
+ rowKey: (row: T) => string;
1442
+ /** 선택된 행 key 배열 (제어형) */
1443
+ selectedKeys?: string[];
1444
+ /** 선택 변경 콜백 */
1445
+ onSelectionChange?: (keys: string[]) => void;
1446
+ } | {
1447
+ selectable?: false;
1448
+ rowKey?: (row: T) => string;
1449
+ selectedKeys?: string[];
1450
+ onSelectionChange?: (keys: string[]) => void;
1451
+ };
1452
+ type TableProps<T extends object> = {
1453
+ /** 컬럼 정의 */
1454
+ columns: TableColumn<T>[];
1455
+ /** 표시할 데이터 배열 */
1456
+ data: T[];
1457
+ /** 행의 고유 key 추출 함수 */
1458
+ keyExtractor: (item: T, index: number) => string | number;
1459
+ /** 데이터 없을 때 표시 */
1460
+ emptyMessage?: React$1.ReactNode;
1461
+ /** 로딩 상태 - 헤더 유지, 바디만 스켈레톤 */
1462
+ isLoading?: boolean;
1463
+ /** 로딩 시 스켈레톤 행 개수 (기본값: 5) */
1464
+ skeletonRows?: number;
1465
+ /** 테이블 크기 */
1466
+ size?: TableSize;
1467
+ /** 행 hover 강조 (기본값: true) */
1468
+ hoverable?: boolean;
1469
+ /** thead sticky 고정 (기본값: false) */
1470
+ stickyHeader?: boolean;
1471
+ /** 스크린 리더용 테이블 레이블 */
1472
+ ariaLabel?: string;
1473
+ /** 루트 wrapper에 추가할 className */
1474
+ className?: string;
1475
+ /** 행 클릭 콜백 */
1476
+ onRowClick?: (item: T, index: number) => void;
1477
+ /**
1478
+ * clickable 행(onRowClick)의 동작 설명. 각 clickable 행에 `aria-describedby` 로 연결된다 (기본값: "클릭 가능한 행").
1479
+ * 행마다 셀 데이터가 이미 행을 식별하므로 여기엔 동작만 담으면 된다 (예: "선택하면 상세 항목으로 이동").
1480
+ * `""`(빈 문자열)로 두면 힌트를 붙이지 않는다.
1481
+ * `aria-label` 대신 `aria-describedby` 를 쓰는 이유: `<tr>` 의 `aria-label`/`role="button"` 은 행/셀의
1482
+ * accessible name 을 덮거나 셀을 presentational 로 만들어 스크린리더가 셀 데이터를 못 읽는다.
1483
+ */
1484
+ rowClickHint?: string;
1485
+ /** 현재 정렬 상태 (제어형). `undefined` 는 정렬 없음 */
1486
+ sort?: TableSort;
1487
+ /** 정렬 가능한 헤더 클릭 시 발화 (none→asc→desc→none 순환). DS는 데이터를 직접 정렬하지 않음 - 정렬된 `data` 를 다시 전달해야 함 */
1488
+ onSortChange?: (sort: TableSort | undefined) => void;
1489
+ /** 전체 선택 체크박스 aria-label */
1490
+ selectAllAriaLabel?: string;
1491
+ /** 개별 행 선택 체크박스 aria-label (기본값: (i) => `${i+1}번째 행 선택`) */
1492
+ selectRowAriaLabel?: (index: number) => string;
1493
+ } & TableSelectionProps<T>;
1494
+ /**
1495
+ * 데이터 테이블을 렌더링한다. 로딩 중에는 헤더 유지, 바디에 스켈레톤 행을 표시한다.
1496
+ * @param props 테이블 속성
1497
+ * @returns 테이블 컴포넌트
1498
+ */
1499
+ declare const Table: <T extends object>({ columns, data, keyExtractor, emptyMessage: emptyMessageProp, isLoading, skeletonRows, size, hoverable, stickyHeader, ariaLabel, className, onRowClick, rowClickHint: rowClickHintProp, sort, onSortChange, selectAllAriaLabel: selectAllAriaLabelProp, selectRowAriaLabel: selectRowAriaLabelProp, selectable, rowKey, selectedKeys, onSelectionChange, }: TableProps<T>) => React$1.JSX.Element;
1500
+
1501
+ /**
1502
+ * 목록 화면이 데이터를 받는 모양.
1503
+ *
1504
+ * TanStack Query 등의 결과를 그대로 넣을 수 있게 필드 이름을 맞췄지만, 어떤 라이브러리도
1505
+ * import 하지 않는다 - DS 가 특정 데이터 계층에 묶이면 안 된다.
1506
+ */
1507
+ interface DataViewQuery<T> {
1508
+ /** 현재 페이지에 표시할 행 */
1509
+ data: T[] | undefined;
1510
+ /** 첫 로딩 여부. true 면 Table 의 스켈레톤이 나온다 */
1511
+ isLoading?: boolean;
1512
+ /** 실패. 지정하면 표 대신 ErrorState 가 나온다 */
1513
+ error?: unknown;
1514
+ /** 재시도. 지정하면 ErrorState 에 버튼이 붙는다 */
1515
+ refetch?: () => void;
1516
+ }
1517
+ interface DataViewToolbar {
1518
+ /** 검색 입력 표시 여부 */
1519
+ search?: boolean;
1520
+ /** 검색어 (제어형) */
1521
+ searchValue?: string;
1522
+ /** 검색어 변경 콜백 */
1523
+ onSearchChange?: (value: string) => void;
1524
+ /** 검색 입력 placeholder */
1525
+ searchPlaceholder?: string;
1526
+ /** 검색 왼쪽에 놓을 필터 컨트롤 (`Dropdown` 등) */
1527
+ filters?: React$1.ReactNode;
1528
+ }
1529
+ interface DataViewSelectionAction {
1530
+ /** 버튼 라벨 */
1531
+ label: string;
1532
+ /** 선택된 key 를 받아 실행 */
1533
+ onRun: (keys: string[]) => void;
1534
+ /** 위험한 액션(삭제 등) - 빨간 강조 */
1535
+ danger?: boolean;
1536
+ }
1537
+ interface DataViewPagination {
1538
+ /** 현재 페이지 (1-based) */
1539
+ page: number;
1540
+ /** 전체 페이지 수 */
1541
+ totalPages: number;
1542
+ /** 페이지 변경 콜백 */
1543
+ onPageChange: (page: number) => void;
1544
+ }
1545
+ interface DataViewProps<T extends object> extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "children"> {
1546
+ /** 데이터와 그 상태 */
1547
+ query: DataViewQuery<T>;
1548
+ /** 표 컬럼 정의 */
1549
+ columns: TableColumn<T>[];
1550
+ /** 행 고유 key */
1551
+ rowKey: (row: T) => string;
1552
+ /** 상단 검색·필터 줄 */
1553
+ toolbar?: DataViewToolbar;
1554
+ /**
1555
+ * 행을 선택했을 때 나타나는 액션. 지정하면 표에 체크박스 컬럼이 붙는다.
1556
+ * 선택 상태는 `DataView` 가 들고 있다.
1557
+ */
1558
+ selectionActions?: DataViewSelectionAction[];
1559
+ /** 하단 페이지네이션 */
1560
+ pagination?: DataViewPagination;
1561
+ /** 데이터가 비었을 때. 미지정 시 기본 `EmptyState` */
1562
+ empty?: React$1.ReactNode;
1563
+ /** 정렬 상태 (제어형) */
1564
+ sort?: TableSort;
1565
+ /** 정렬 변경 콜백 */
1566
+ onSortChange?: (sort: TableSort | undefined) => void;
1567
+ /** 행 클릭 */
1568
+ onRowClick?: (row: T, index: number) => void;
1569
+ /** 표의 접근성 이름 */
1570
+ ariaLabel?: string;
1571
+ /** 선택 액션 줄의 안내 문구 (기본값: (n) => `${n}개 선택됨`) */
1572
+ selectionSummary?: (count: number) => string;
1573
+ /** 선택 해제 버튼 라벨 */
1574
+ clearSelectionLabel?: string;
1575
+ /** 실패 상태 제목 */
1576
+ errorTitle?: string;
1577
+ /** 재시도 버튼 라벨 */
1578
+ retryLabel?: string;
1579
+ }
1580
+ /**
1581
+ * 목록 화면 한 벌 - 검색·필터, 표, 선택 액션, 페이지네이션, 그리고 **네 상태 분기**.
1582
+ *
1583
+ * `Table` 은 정렬·선택·스켈레톤을 정직하게 처리하지만 목록 "화면" 은 그 위아래가 더 있다.
1584
+ * 그 조합이 없어서 화면마다 다시 만들어졌고, 특히 **에러 상태를 빠뜨린 화면**이 생겼다.
1585
+ * 여기서는 loading / error / empty / data 가 한 곳에서 갈린다.
1586
+ *
1587
+ * 새로 그리는 것은 거의 없다 - `Table`·`Pagination`·`EmptyState`·`ErrorState`·`TextField`·
1588
+ * `Button` 을 그대로 쓴다.
1589
+ *
1590
+ * @example
1591
+ * ```tsx
1592
+ * <DataView
1593
+ * query={usersQuery}
1594
+ * columns={columns}
1595
+ * rowKey={(u) => u.id}
1596
+ * toolbar={{ search: true, searchValue: q, onSearchChange: setQ }}
1597
+ * selectionActions={[{ label: "삭제", danger: true, onRun: removeRows }]}
1598
+ * pagination={{ page, totalPages, onPageChange: setPage }}
1599
+ * />
1600
+ * ```
1601
+ */
1602
+ declare const DataView: <T extends object>({ query, columns, rowKey, toolbar, selectionActions, pagination, empty, sort, onSortChange, onRowClick, ariaLabel, selectionSummary: selectionSummaryProp, clearSelectionLabel: clearSelectionLabelProp, errorTitle: errorTitleProp, retryLabel: retryLabelProp, className, ...props }: DataViewProps<T>) => React$1.JSX.Element;
1603
+
1215
1604
  interface DividerProps extends React$1.HTMLAttributes<HTMLHRElement> {
1216
1605
  /** 구분선 두께 (기본값: "standard") */
1217
1606
  weight?: "standard" | "heavy";
@@ -1392,105 +1781,18 @@ declare const Prose: {
1392
1781
  displayName: string;
1393
1782
  };
1394
1783
 
1395
- type TableSize = "sm" | "md" | "lg";
1396
- type TableSortDirection = "asc" | "desc";
1397
- interface TableSort {
1398
- /** 정렬 중인 컬럼의 `TableColumn.key` */
1399
- key: string;
1400
- /** 정렬 방향 */
1401
- direction: TableSortDirection;
1402
- }
1403
- interface TableColumn<T extends object> {
1404
- /** 컬럼 식별자 - `data[key]` 자동 렌더링에도 쓰임 */
1405
- key: string;
1406
- /** thead에 표시할 헤더 텍스트 */
1407
- header: React$1.ReactNode;
1408
- /** 셀 렌더 함수. 없으면 `item[key]` 자동 렌더 */
1409
- render?: (item: T, index: number) => React$1.ReactNode;
1410
- /** CSS width 값 (예: "120px", "20%") */
1411
- width?: string;
1412
- /** 정렬 (기본값: "left") */
1413
- align?: "left" | "center" | "right";
1414
- /** 정렬 가능한 컬럼 여부 (기본값: false). 클릭 시 `onSortChange` 발화 - 실제 정렬은 소비자가 수행 */
1415
- sortable?: boolean;
1416
- }
1417
- /** `selectable` 시 `rowKey` 를 요구하기 위한 판별 유니온 */
1418
- type TableSelectionProps<T extends object> = {
1419
- /** 행 선택(체크박스 컬럼) 활성화 여부 */
1420
- selectable: true;
1421
- /** 행 고유 key 추출 함수 - `selectable` 사용 시 필수 */
1422
- rowKey: (row: T) => string;
1423
- /** 선택된 행 key 배열 (제어형) */
1424
- selectedKeys?: string[];
1425
- /** 선택 변경 콜백 */
1426
- onSelectionChange?: (keys: string[]) => void;
1427
- } | {
1428
- selectable?: false;
1429
- rowKey?: (row: T) => string;
1430
- selectedKeys?: string[];
1431
- onSelectionChange?: (keys: string[]) => void;
1432
- };
1433
- type TableProps<T extends object> = {
1434
- /** 컬럼 정의 */
1435
- columns: TableColumn<T>[];
1436
- /** 표시할 데이터 배열 */
1437
- data: T[];
1438
- /** 행의 고유 key 추출 함수 */
1439
- keyExtractor: (item: T, index: number) => string | number;
1440
- /** 데이터 없을 때 표시 (기본값: "데이터가 없습니다") */
1441
- emptyMessage?: React$1.ReactNode;
1442
- /** 로딩 상태 - 헤더 유지, 바디만 스켈레톤 */
1443
- isLoading?: boolean;
1444
- /** 로딩 시 스켈레톤 행 개수 (기본값: 5) */
1445
- skeletonRows?: number;
1446
- /** 테이블 크기 (기본값: "md") */
1447
- size?: TableSize;
1448
- /** 행 hover 강조 (기본값: true) */
1449
- hoverable?: boolean;
1450
- /** thead sticky 고정 (기본값: false) */
1451
- stickyHeader?: boolean;
1452
- /** 스크린 리더용 테이블 레이블 */
1453
- ariaLabel?: string;
1454
- /** 루트 wrapper에 추가할 className */
1455
- className?: string;
1456
- /** 행 클릭 콜백 */
1457
- onRowClick?: (item: T, index: number) => void;
1458
- /**
1459
- * clickable 행(onRowClick)의 동작 설명. 각 clickable 행에 `aria-describedby` 로 연결된다 (기본값: "클릭 가능한 행").
1460
- * 행마다 셀 데이터가 이미 행을 식별하므로 여기엔 동작만 담으면 된다 (예: "선택하면 상세 항목으로 이동").
1461
- * `""`(빈 문자열)로 두면 힌트를 붙이지 않는다.
1462
- * `aria-label` 대신 `aria-describedby` 를 쓰는 이유: `<tr>` 의 `aria-label`/`role="button"` 은 행/셀의
1463
- * accessible name 을 덮거나 셀을 presentational 로 만들어 스크린리더가 셀 데이터를 못 읽는다.
1464
- */
1465
- rowClickHint?: string;
1466
- /** 현재 정렬 상태 (제어형). `undefined` 는 정렬 없음 */
1467
- sort?: TableSort;
1468
- /** 정렬 가능한 헤더 클릭 시 발화 (none→asc→desc→none 순환). DS는 데이터를 직접 정렬하지 않음 - 정렬된 `data` 를 다시 전달해야 함 */
1469
- onSortChange?: (sort: TableSort | undefined) => void;
1470
- /** 전체 선택 체크박스 aria-label (기본값: "전체 선택") */
1471
- selectAllAriaLabel?: string;
1472
- /** 개별 행 선택 체크박스 aria-label (기본값: (i) => `${i+1}번째 행 선택`) */
1473
- selectRowAriaLabel?: (index: number) => string;
1474
- } & TableSelectionProps<T>;
1475
- /**
1476
- * 데이터 테이블을 렌더링한다. 로딩 중에는 헤더 유지, 바디에 스켈레톤 행을 표시한다.
1477
- * @param props 테이블 속성
1478
- * @returns 테이블 컴포넌트
1479
- */
1480
- declare const Table: <T extends object>({ columns, data, keyExtractor, emptyMessage, isLoading, skeletonRows, size, hoverable, stickyHeader, ariaLabel, className, onRowClick, rowClickHint, sort, onSortChange, selectAllAriaLabel, selectRowAriaLabel, selectable, rowKey, selectedKeys, onSelectionChange, }: TableProps<T>) => React$1.JSX.Element;
1481
-
1482
1784
  type AlertVariant = "info" | "success" | "warning" | "error";
1483
1785
  type AlertActionsAlign = "left" | "center" | "right";
1484
1786
  interface AlertOptions {
1485
- /** 알림 스타일 변형 (기본값: "info") */
1787
+ /** 알림 스타일 변형 */
1486
1788
  variant?: AlertVariant;
1487
1789
  /** 알림 제목 */
1488
1790
  title?: React$1.ReactNode;
1489
1791
  /** 알림 본문 메시지 */
1490
1792
  message?: React$1.ReactNode;
1491
- /** 확인 버튼 텍스트 (기본값: "확인") */
1793
+ /** 확인 버튼 텍스트 */
1492
1794
  confirmText?: string;
1493
- /** 취소 버튼 텍스트 (기본값: "취소") */
1795
+ /** 취소 버튼 텍스트 */
1494
1796
  cancelText?: string;
1495
1797
  /** 취소 버튼 표시 여부 (기본값: false) */
1496
1798
  showCancel?: boolean;
@@ -1501,7 +1803,7 @@ interface AlertOptions {
1501
1803
  * @default false
1502
1804
  */
1503
1805
  destructive?: boolean;
1504
- /** 액션 버튼 정렬 (기본값: "right") */
1806
+ /** 액션 버튼 정렬 */
1505
1807
  actionsAlign?: AlertActionsAlign;
1506
1808
  /** 변형 아이콘 표시 여부 (기본값: false). 원하면 명시적으로 켜기 */
1507
1809
  showIcon?: boolean;
@@ -1560,7 +1862,7 @@ declare const Skeleton: ({ variant, width, height, radius, className, style, ...
1560
1862
  interface SpinnerProps {
1561
1863
  /** 스피너 크기(px) (기본값: 24) */
1562
1864
  size?: number;
1563
- /** 스피너 접근성 레이블 (기본값: "로딩 중") */
1865
+ /** 스피너 접근성 레이블 */
1564
1866
  ariaLabel?: string;
1565
1867
  }
1566
1868
  /**
@@ -1569,7 +1871,7 @@ interface SpinnerProps {
1569
1871
  * @param props 스피너 속성
1570
1872
  * @returns 렌더링된 스피너 요소
1571
1873
  */
1572
- declare const Spinner: ({ size, ariaLabel }: SpinnerProps) => React$1.JSX.Element;
1874
+ declare const Spinner: ({ size, ariaLabel: ariaLabelProp }: SpinnerProps) => React$1.JSX.Element;
1573
1875
 
1574
1876
  type ToastVariant = "success" | "error" | "warning" | "info" | "default";
1575
1877
  interface ToastProviderProps {
@@ -1577,7 +1879,7 @@ interface ToastProviderProps {
1577
1879
  children: React$1.ReactNode;
1578
1880
  /** 최대 동시 표시 토스트 수 (기본값: 5) */
1579
1881
  maxCount?: number;
1580
- /** 토스트 닫기 버튼의 aria-label (기본값: "닫기") */
1882
+ /** 토스트 닫기 버튼의 aria-label */
1581
1883
  closeAriaLabel?: string;
1582
1884
  /** 토스트 리전(`role="region"`)의 접근성 이름 (기본값: "알림"). 스크린리더의 리전 목록에 뜬다 */
1583
1885
  regionLabel?: string;
@@ -1588,7 +1890,7 @@ interface ToastProviderProps {
1588
1890
  * @param props Provider 속성
1589
1891
  * @returns 렌더링된 Provider와 토스트 컨테이너
1590
1892
  */
1591
- declare const ToastProvider: ({ children, maxCount, closeAriaLabel, regionLabel, }: ToastProviderProps) => React$1.JSX.Element;
1893
+ declare const ToastProvider: ({ children, maxCount, closeAriaLabel: closeAriaLabelProp, regionLabel: regionLabelProp, }: ToastProviderProps) => React$1.JSX.Element;
1592
1894
 
1593
1895
  /**
1594
1896
  * 토스트 메시지를 표시하는 훅.
@@ -1617,7 +1919,7 @@ interface TopLoadingProps {
1617
1919
  height?: number;
1618
1920
  /** 표시 여부 */
1619
1921
  isLoading?: boolean;
1620
- /** 프로그레스 바의 접근성 레이블 (기본값: "페이지 로딩 중") */
1922
+ /** 프로그레스 바의 접근성 레이블 */
1621
1923
  ariaLabel?: string;
1622
1924
  }
1623
1925
  /**
@@ -1626,7 +1928,7 @@ interface TopLoadingProps {
1626
1928
  * @param props 로딩바 속성
1627
1929
  * @returns 렌더링된 로딩바 요소 또는 null
1628
1930
  */
1629
- declare const TopLoading: ({ progress, color, height, isLoading, ariaLabel, }: TopLoadingProps) => React$1.JSX.Element | null;
1931
+ declare const TopLoading: ({ progress, color, height, isLoading, ariaLabel: ariaLabelProp, }: TopLoadingProps) => React$1.JSX.Element | null;
1630
1932
 
1631
1933
  interface CheckboxProps extends Omit<React$1.InputHTMLAttributes<HTMLInputElement>, "size"> {
1632
1934
  /** 체크박스 옆에 표시할 라벨 */
@@ -1649,6 +1951,71 @@ declare const Checkbox: {
1649
1951
  displayName: string;
1650
1952
  };
1651
1953
 
1954
+ interface ComboboxOption {
1955
+ /** 선택 시 돌려줄 값 */
1956
+ value: string;
1957
+ /** 목록과 트리거에 표시할 텍스트 */
1958
+ label: string;
1959
+ /** 비활성 - 키보드 이동에서 건너뛰고 선택되지 않는다 */
1960
+ disabled?: boolean;
1961
+ }
1962
+ type ComboboxSize = "sm" | "md" | "lg";
1963
+ interface ComboboxProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
1964
+ /** 선택된 값 (제어형) */
1965
+ value?: ComboboxOption | null;
1966
+ /** 선택 변경 콜백 */
1967
+ onValueChange?: (option: ComboboxOption | null) => void;
1968
+ /**
1969
+ * 검색어가 바뀔 때 호출. 서버에서 후보를 가져오는 자리다.
1970
+ * `debounceMs` 만큼 기다린 뒤 호출되고, 늦게 도착한 응답은 버려진다.
1971
+ */
1972
+ onSearch: (query: string) => Promise<ComboboxOption[]>;
1973
+ /** 검색어 입력 전에 보여줄 초기 후보 */
1974
+ defaultOptions?: ComboboxOption[];
1975
+ /** 검색 호출 간격 (기본값: 250ms) */
1976
+ debounceMs?: number;
1977
+ /** 입력 placeholder */
1978
+ placeholder?: string;
1979
+ /** 결과 없음 문구 */
1980
+ emptyMessage?: string;
1981
+ /** 검색 전 안내 문구 */
1982
+ idleMessage?: string;
1983
+ /** 크기 */
1984
+ size?: ComboboxSize;
1985
+ /** 비활성 여부 */
1986
+ disabled?: boolean;
1987
+ /** 전체 너비 차지 */
1988
+ fullWidth?: boolean;
1989
+ /** 목록 항목 렌더 커스터마이즈. 미지정 시 `label` */
1990
+ renderOption?: (option: ComboboxOption) => React$1.ReactNode;
1991
+ /** 접근성 이름 - `Field` 로 감싸면 그쪽 라벨이 우선한다 */
1992
+ ariaLabel?: string;
1993
+ /** 로딩 안내 */
1994
+ loadingLabel?: string;
1995
+ }
1996
+ /**
1997
+ * 후보를 서버에서 가져오는 선택 입력 (APG Combobox).
1998
+ *
1999
+ * `Dropdown` 도 `searchable` 로 타이핑 검색을 지원하지만 **이미 받아 둔 옵션 배열 안에서만**
2000
+ * 거른다. 담당자·회사·상품처럼 후보가 수백 개인 필드는 그 목록을 통째로 내려받을 수 없어
2001
+ * 소비자가 DS 를 우회해 직접 만들게 된다 - 우회가 시작되는 지점이 DS 이탈이 시작되는 지점이다.
2002
+ *
2003
+ * 팝업의 거동(개폐·활성 항목·키보드·바깥 클릭)은 `useListboxPopup` 을 `Dropdown` 과 공유한다.
2004
+ * 여기 있는 것은 **비동기 네 가지**뿐이다 - 디바운스, 로딩 표시, 응답 경합 차단,
2005
+ * "아직 검색 안 함" 과 "결과 없음" 의 구분.
2006
+ *
2007
+ * @example
2008
+ * ```tsx
2009
+ * <Combobox
2010
+ * value={owner}
2011
+ * onValueChange={setOwner}
2012
+ * onSearch={(q) => api.searchUsers(q)}
2013
+ * emptyMessage="일치하는 담당자가 없습니다"
2014
+ * />
2015
+ * ```
2016
+ */
2017
+ declare const Combobox: ({ value, onValueChange, onSearch, defaultOptions, debounceMs, placeholder: placeholderProp, emptyMessage: emptyMessageProp, idleMessage: idleMessageProp, size, disabled, fullWidth, renderOption, ariaLabel, loadingLabel: loadingLabelProp, className, ...props }: ComboboxProps) => React$1.JSX.Element;
2018
+
1652
2019
  type DatePickerMode = "year-month" | "year-month-day";
1653
2020
  type SelectableRange = "all" | "until-today";
1654
2021
  interface DatePickerBaseProps {
@@ -1656,7 +2023,7 @@ interface DatePickerBaseProps {
1656
2023
  label?: string;
1657
2024
  /** 제어형 날짜 값 ("YYYY-MM" 또는 "YYYY-MM-DD" 형식) */
1658
2025
  value?: string;
1659
- /** 선택 모드 (기본값: "year-month-day") */
2026
+ /** 선택 모드 */
1660
2027
  mode?: DatePickerMode;
1661
2028
  /** 연도 선택 범위 시작 (기본값: 1950) */
1662
2029
  startYear?: number;
@@ -1675,11 +2042,11 @@ interface DatePickerBaseProps {
1675
2042
  * @deprecated `fullWidth` 사용 또는 CSS로 처리
1676
2043
  */
1677
2044
  width?: number | string;
1678
- /** 연도 select의 라벨/플레이스홀더 (기본값: "년") */
2045
+ /** 연도 select의 라벨/플레이스홀더 */
1679
2046
  yearLabel?: string;
1680
- /** 월 select의 라벨/플레이스홀더 (기본값: "월") */
2047
+ /** 월 select의 라벨/플레이스홀더 */
1681
2048
  monthLabel?: string;
1682
- /** 일 select의 라벨/플레이스홀더 (기본값: "일") */
2049
+ /** 일 select의 라벨/플레이스홀더 */
1683
2050
  dayLabel?: string;
1684
2051
  /**
1685
2052
  * minDate 설정 시 스크린리더에 전달할 안내 문구 포맷.
@@ -1704,7 +2071,54 @@ type DatePickerProps = DatePickerBaseProps & DatePickerCallbacks;
1704
2071
  * 연/월/일 선택형 데이트 피커를 렌더링한다.
1705
2072
  * 내부적으로 DS Dropdown 3개를 조합해 드롭다운 UX 일관성을 유지한다.
1706
2073
  */
1707
- declare const DatePicker: ({ label, value, onValueChange, onChange, mode, startYear, endYear: endYearProp, minDate, selectableRange, disabled, fullWidth, width, yearLabel, monthLabel, dayLabel, minDateSrFormat, selectableRangeUntilTodaySrText, }: DatePickerProps) => React$1.JSX.Element;
2074
+ declare const DatePicker: ({ label, value, onValueChange, onChange, mode, startYear, endYear: endYearProp, minDate, selectableRange, disabled, fullWidth, width, yearLabel: yearLabelProp, monthLabel: monthLabelProp, dayLabel: dayLabelProp, minDateSrFormat: minDateSrFormatProp, selectableRangeUntilTodaySrText: selectableRangeUntilTodaySrTextProp, }: DatePickerProps) => React$1.JSX.Element;
2075
+
2076
+ interface DateRange {
2077
+ /** 시작일 (`"YYYY-MM-DD"`). 아직 고르지 않았으면 undefined */
2078
+ start?: string;
2079
+ /** 종료일 (`"YYYY-MM-DD"`). 아직 고르지 않았으면 undefined */
2080
+ end?: string;
2081
+ }
2082
+ interface DateRangePickerProps {
2083
+ /** 제어형 값 */
2084
+ value?: DateRange;
2085
+ /** 범위 변경. 시작일이 종료일을 넘어서면 종료일이 비워진 값이 온다 */
2086
+ onValueChange: (value: DateRange) => void;
2087
+ /** 시작일 select 묶음의 라벨 */
2088
+ startLabel?: string;
2089
+ /** 종료일 select 묶음의 라벨 */
2090
+ endLabel?: string;
2091
+ /** 연도 선택 범위 시작 (기본값: 1950) */
2092
+ startYear?: number;
2093
+ /** 연도 선택 범위 끝. 미지정 시 현재 연도 + 10 */
2094
+ endYear?: number;
2095
+ /** 선택 가능한 가장 이른 날짜 (`"YYYY-MM-DD"`) */
2096
+ minDate?: string;
2097
+ /** `"until-today"` 면 오늘 이후를 고를 수 없다 (기본값: "all") */
2098
+ selectableRange?: "all" | "until-today";
2099
+ /** 비활성 여부 */
2100
+ disabled?: boolean;
2101
+ /** 전체 너비 차지 (기본값: true) */
2102
+ fullWidth?: boolean;
2103
+ }
2104
+ /**
2105
+ * 시작일·종료일 한 쌍. `DatePicker` 둘을 묶는다.
2106
+ *
2107
+ * **거꾸로 된 범위를 만들 수 없다.** 종료일의 최소값이 시작일이라 애초에 이전 날짜가 목록에
2108
+ * 없고, 시작일을 종료일보다 뒤로 옮기면 종료일이 비워진다. 손으로 두 개를 나란히 두면 이
2109
+ * 검증을 화면마다 다시 쓰고, 대개 "조회" 버튼을 누른 뒤 서버 오류로 알게 된다.
2110
+ *
2111
+ * 종료일을 조용히 시작일로 맞추지 않고 **비운다** - 사용자가 고르지 않은 날짜를 고른 것처럼
2112
+ * 만들면 그대로 조회·저장된다.
2113
+ *
2114
+ * @example
2115
+ * ```tsx
2116
+ * <Field name="period" label="조회 기간">
2117
+ * <DateRangePicker value={period} onValueChange={setPeriod} selectableRange="until-today" />
2118
+ * </Field>
2119
+ * ```
2120
+ */
2121
+ declare const DateRangePicker: ({ value, onValueChange, startLabel: startLabelProp, endLabel: endLabelProp, startYear, endYear, minDate, selectableRange, disabled, fullWidth, }: DateRangePickerProps) => React$1.JSX.Element;
1708
2122
 
1709
2123
  type DropdownSize = "sm" | "md" | "lg";
1710
2124
  /**
@@ -1732,13 +2146,13 @@ interface DropdownCommonProps {
1732
2146
  id?: string;
1733
2147
  /** 드롭다운 위에 표시할 플로팅 라벨 텍스트 */
1734
2148
  label?: string;
1735
- /** 선택 전 표시할 플레이스홀더 (기본값: "선택…") */
2149
+ /** 선택 전 표시할 플레이스홀더 */
1736
2150
  placeholder?: string;
1737
2151
  /** 표시할 옵션 목록 */
1738
2152
  options: DropdownOption[];
1739
2153
  /** 비활성화 여부 */
1740
2154
  disabled?: boolean;
1741
- /** 드롭다운 크기 (기본값: "md") */
2155
+ /** 드롭다운 크기 */
1742
2156
  size?: DropdownSize;
1743
2157
  /**
1744
2158
  * @deprecated Dropdown 은 이제 항상 부모 너비를 채웁니다. 인라인 사용 시 부모를 `inline-block + width` 로 감싸세요.
@@ -1746,7 +2160,7 @@ interface DropdownCommonProps {
1746
2160
  fullWidth?: boolean;
1747
2161
  /** 루트 요소에 추가할 className */
1748
2162
  className?: string;
1749
- /** 컨트롤 시각 변형 (기본값: "outline") */
2163
+ /** 컨트롤 시각 변형 */
1750
2164
  variant?: DropdownVariant;
1751
2165
  /**
1752
2166
  * @deprecated textAlign은 더 이상 지원되지 않습니다.
@@ -1757,11 +2171,11 @@ interface DropdownCommonProps {
1757
2171
  * (기본값: false)
1758
2172
  */
1759
2173
  searchable?: boolean;
1760
- /** 검색 입력의 placeholder (기본값: "검색…") */
2174
+ /** 검색 입력의 placeholder */
1761
2175
  searchPlaceholder?: string;
1762
- /** 필터 결과가 0개일 때 표시할 텍스트 (기본값: "결과 없음") */
2176
+ /** 필터 결과가 0개일 때 표시할 텍스트 */
1763
2177
  emptyText?: string;
1764
- /** 멀티 선택 요약 텍스트 (기본값: "N개 선택") */
2178
+ /** 멀티 선택 요약 텍스트 */
1765
2179
  selectedSummary?: (count: number) => string;
1766
2180
  /**
1767
2181
  * 네이티브 폼 제출 참여용 name. 지정 시 선택 값이 hidden input 으로 렌더되어
@@ -1805,9 +2219,78 @@ type DropdownProps = DropdownSingleProps | DropdownMultipleProps;
1805
2219
  */
1806
2220
  declare const Dropdown: (props: DropdownProps) => React$1.JSX.Element;
1807
2221
 
2222
+ /**
2223
+ * `Field` 가 자식 입력에게 내리는 값.
2224
+ *
2225
+ * 입력이 직접 읽지 않고 {@link useFieldControl} 을 거친다 - `Field` 밖에서는 `undefined` 라,
2226
+ * 입력은 지금까지처럼 자기 id 와 자기 `supportingText` 로 동작한다.
2227
+ */
2228
+ interface FieldControl {
2229
+ /** 입력에 붙일 id. `Field` 의 `<label htmlFor>` 이 이 값을 가리킨다 */
2230
+ inputId: string;
2231
+ /**
2232
+ * 라벨 요소의 id. `role="group"` 컨테이너(DatePicker·OtpInput·RadioGroup)는 `htmlFor` 로
2233
+ * 연결되지 않으므로 이 값을 `aria-labelledby` 에 쓴다. 라벨이 없으면 undefined.
2234
+ */
2235
+ labelId: string | undefined;
2236
+ /** help·error 를 함께 가리키는 `aria-describedby` 값. 둘 다 없으면 undefined */
2237
+ describedBy: string | undefined;
2238
+ /** 에러 상태 - 입력은 `aria-invalid` 에 반영한다 */
2239
+ invalid: boolean;
2240
+ /** 필수 여부 - 입력은 `aria-required` 에 반영한다 */
2241
+ required: boolean;
2242
+ }
2243
+ /**
2244
+ * 입력 컴포넌트가 감싸는 `Field` 를 인식하는 훅.
2245
+ *
2246
+ * `Field` 밖에서는 `undefined` 를 돌려주므로, 입력은 아래처럼 **자기 값을 기본으로 두고**
2247
+ * 필드가 있을 때만 양보하면 된다. 기존 동작이 바뀌지 않는다.
2248
+ *
2249
+ * ```tsx
2250
+ * const generatedId = useId();
2251
+ * const field = useFieldControl();
2252
+ * const inputId = id ?? field?.inputId ?? generatedId;
2253
+ * ```
2254
+ */
2255
+ declare function useFieldControl(): FieldControl | undefined;
2256
+ interface FieldProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "children"> {
2257
+ /** 필드 이름. `Form` 의 `errors[name]` 을 찾는 키이자 입력 id 의 접두사 */
2258
+ name: string;
2259
+ /** 라벨 텍스트. `Field` 가 소유하므로 자식 입력에는 `label` 을 주지 않는다 */
2260
+ label?: string;
2261
+ /** 필수 표시(*). 자식 입력에 `aria-required` 로도 전달된다 */
2262
+ required?: boolean;
2263
+ /** 입력 아래 도움말. 에러가 있으면 에러가 대신 보인다 */
2264
+ help?: React$1.ReactNode;
2265
+ /**
2266
+ * 에러 메시지. 지정하면 `Form` 의 `errors[name]` 보다 우선한다.
2267
+ * 문자열이 아니어도 되지만 스크린리더가 읽으므로 텍스트를 권장한다.
2268
+ */
2269
+ error?: React$1.ReactNode;
2270
+ /** 입력 하나 (`<TextField />`, `<Dropdown />` 등) */
2271
+ children: React$1.ReactNode;
2272
+ }
2273
+ /**
2274
+ * 라벨·필수 표시·도움말·에러와 그 접근성 연결을 소유하는 폼 필드 래퍼.
2275
+ *
2276
+ * 입력 11종은 label/supportingText/error 를 **서로 다르게** 갖고 있다 - 9종만 label 이 있고
2277
+ * error 는 5종뿐이라, 폼 화면은 입력 밖에 문구를 직접 그려 왔다. `Field` 가 그 자리를 가져가면
2278
+ * 어떤 입력을 넣어도 라벨 위치·간격·에러 문구·`aria-describedby` 가 같아진다.
2279
+ *
2280
+ * 입력의 기존 prop 은 그대로 살아 있다. `Field` 없이 쓰면 지금과 동일하게 동작한다.
2281
+ *
2282
+ * @example
2283
+ * ```tsx
2284
+ * <Field name="email" label="이메일" required help="로그인 ID 로 사용됩니다">
2285
+ * <TextField />
2286
+ * </Field>
2287
+ * ```
2288
+ */
2289
+ declare const Field: ({ name, label, required, help, error: errorProp, children, className, ...props }: FieldProps) => React$1.JSX.Element;
2290
+
1808
2291
  type FileInputVariant = "button" | "preview";
1809
2292
  interface FileInputProps extends React$1.InputHTMLAttributes<HTMLInputElement> {
1810
- /** 파일 선택 버튼 라벨 / preview variant 빈 상태 텍스트 (기본값: "파일 선택") */
2293
+ /** 파일 선택 버튼 라벨 / preview variant 빈 상태 텍스트 */
1811
2294
  label?: string;
1812
2295
  /** 파일 선택 시 호출되는 콜백 */
1813
2296
  onFiles?: (files: FileList | null) => void;
@@ -1830,7 +2313,48 @@ interface FileInputProps extends React$1.InputHTMLAttributes<HTMLInputElement> {
1830
2313
  * @param props 파일 입력 속성
1831
2314
  * @returns 렌더링된 파일 입력 UI
1832
2315
  */
1833
- declare const FileInput: ({ label, onFiles, supportingText, preview, variant, previewSize, className, disabled, accept, onChange, ...props }: FileInputProps) => React$1.JSX.Element;
2316
+ declare const FileInput: ({ label: labelProp, onFiles, supportingText, preview, variant, previewSize, className, disabled, accept, onChange, ...props }: FileInputProps) => React$1.JSX.Element;
2317
+
2318
+ interface FormProps extends Omit<React$1.FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
2319
+ /**
2320
+ * 필드 이름 → 에러 메시지. 해당 `Field` 가 자기 이름으로 찾아 표시한다.
2321
+ * 서버 검증 실패(422) 응답을 필드에 꽂는 표준 경로다.
2322
+ */
2323
+ errors?: Record<string, React$1.ReactNode>;
2324
+ /** 제출 콜백. `event.preventDefault()` 는 `Form` 이 이미 호출한 뒤 부른다 */
2325
+ onSubmit?: (event: React$1.FormEvent<HTMLFormElement>) => void;
2326
+ children: React$1.ReactNode;
2327
+ }
2328
+ /**
2329
+ * `Field` 들을 묶어 세로 간격과 **서버 에러 배분**을 소유하는 폼 컨테이너.
2330
+ *
2331
+ * 폼 라이브러리에 의존하지 않는다 - `errors` 맵과 `onSubmit` 만 받으므로 react-hook-form 이든
2332
+ * 수동 상태든 어댑터 한 겹으로 붙는다.
2333
+ *
2334
+ * @example
2335
+ * ```tsx
2336
+ * <Form onSubmit={save} errors={serverErrors}>
2337
+ * <Field name="email" label="이메일" required>
2338
+ * <TextField />
2339
+ * </Field>
2340
+ * <Form.Actions>
2341
+ * <Button type="submit">저장</Button>
2342
+ * </Form.Actions>
2343
+ * </Form>
2344
+ * ```
2345
+ */
2346
+ declare const Form: {
2347
+ ({ errors, onSubmit, children, className, ...props }: FormProps): React$1.JSX.Element;
2348
+ Actions: {
2349
+ ({ align, children, className, ...props }: FormActionsProps): React$1.JSX.Element;
2350
+ displayName: string;
2351
+ };
2352
+ };
2353
+ interface FormActionsProps extends React$1.HTMLAttributes<HTMLDivElement> {
2354
+ /** 버튼 정렬 (기본값: "end") */
2355
+ align?: "start" | "center" | "end" | "between";
2356
+ children: React$1.ReactNode;
2357
+ }
1834
2358
 
1835
2359
  /**
1836
2360
  * 정사각 이미지 크롭의 좌표 계산. 화면 조작(드래그 이동량 + 확대 배율)을 원본 픽셀 기준
@@ -1917,7 +2441,7 @@ interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivElement>, "onErro
1917
2441
  * 원격 URL 을 넘기면 `canvas.drawImage` 가 서버의 CORS(`Access-Control-Allow-Origin`)에
1918
2442
  * 의존한다 — 확실히 자르려면 로컬 `File`/`Blob` 을 권장한다.
1919
2443
  */
1920
- declare function ImageCropper({ ref, src, outputSize, outputType, quality, circular, viewportSize, minZoom, maxZoom, onReady, onError, className, label, hint, zoomOutLabel, zoomLabel, zoomInLabel, noPanHint, ...rest }: ImageCropperProps): React$1.JSX.Element;
2444
+ declare function ImageCropper({ ref, src, outputSize, outputType, quality, circular, viewportSize, minZoom, maxZoom, onReady, onError, className, label: labelProp, hint: hintProp, zoomOutLabel: zoomOutLabelProp, zoomLabel: zoomLabelProp, zoomInLabel: zoomInLabelProp, noPanHint: noPanHintProp, ...rest }: ImageCropperProps): React$1.JSX.Element;
1921
2445
 
1922
2446
  interface OtpInputProps {
1923
2447
  /** OTP 자릿수 (기본값: 6) */
@@ -1948,7 +2472,7 @@ interface OtpInputProps {
1948
2472
  * @returns 렌더링된 OTP 입력 요소
1949
2473
  */
1950
2474
  declare const OtpInput: {
1951
- ({ length, value, onValueChange, onChange, error, disabled, supportingText, autoFocus, ariaLabel, className, }: OtpInputProps): React$1.JSX.Element;
2475
+ ({ length, value, onValueChange, onChange, error, disabled, supportingText, autoFocus, ariaLabel: ariaLabelProp, className, }: OtpInputProps): React$1.JSX.Element;
1952
2476
  displayName: string;
1953
2477
  };
1954
2478
 
@@ -2036,6 +2560,47 @@ declare const RadioGroup: {
2036
2560
  displayName: string;
2037
2561
  };
2038
2562
 
2563
+ type TagInputSize = "sm" | "md" | "lg";
2564
+ interface TagInputProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
2565
+ /** 태그 목록 (제어형). 주지 않으면 내부 상태로 동작한다 */
2566
+ value?: string[];
2567
+ /** 비제어형 초기 태그 */
2568
+ defaultValue?: string[];
2569
+ /** 태그가 추가·제거될 때 */
2570
+ onValueChange?: (tags: string[]) => void;
2571
+ /** 입력 placeholder */
2572
+ placeholder?: string;
2573
+ /** 최대 개수. 도달하면 더 추가되지 않는다 */
2574
+ maxTags?: number;
2575
+ /** 같은 값을 여러 번 넣도록 허용 (기본값: false) */
2576
+ allowDuplicates?: boolean;
2577
+ /** 크기 */
2578
+ size?: TagInputSize;
2579
+ /** 비활성 여부 */
2580
+ disabled?: boolean;
2581
+ /** 전체 너비 차지 */
2582
+ fullWidth?: boolean;
2583
+ /** 접근성 이름 - `Field` 로 감싸면 그쪽 라벨이 우선한다 */
2584
+ ariaLabel?: string;
2585
+ }
2586
+ /**
2587
+ * 후보 목록에 없는 값을 사용자가 직접 만들어 넣는 다중 입력.
2588
+ *
2589
+ * 후보가 정해져 있으면 `Dropdown` 의 `multiple` 을, 후보를 서버에서 가져와야 하면 `Combobox` 를
2590
+ * 쓴다. `TagInput` 이 맡는 것은 **목록 자체가 없는** 경우다 - 자유 키워드, 사내 라벨, 검색 필터처럼
2591
+ * 사용자가 만들어 내는 값.
2592
+ *
2593
+ * 태그 칩은 `Chip` 의 `static` + `removable` 을 그대로 쓴다.
2594
+ *
2595
+ * @example
2596
+ * ```tsx
2597
+ * <Field name="keywords" label="키워드">
2598
+ * <TagInput value={tags} onValueChange={setTags} maxTags={10} />
2599
+ * </Field>
2600
+ * ```
2601
+ */
2602
+ declare const TagInput: ({ value, defaultValue, onValueChange, placeholder: placeholderProp, maxTags, allowDuplicates, size, disabled, fullWidth, ariaLabel, className, ...props }: TagInputProps) => React$1.JSX.Element;
2603
+
2039
2604
  type TextFieldSize = "sm" | "md" | "lg";
2040
2605
  /**
2041
2606
  * 입력 필드 시각 변형.
@@ -2050,9 +2615,9 @@ type TextFieldVariant = "outline" | "filled";
2050
2615
  */
2051
2616
  type ImeStrategy = "delayed" | "immediate";
2052
2617
  interface TextFieldProps extends Omit<React$1.InputHTMLAttributes<HTMLInputElement>, "size" | "onChange" | "value" | "defaultValue"> {
2053
- /** 입력 필드 크기 (기본값: "md") */
2618
+ /** 입력 필드 크기 */
2054
2619
  size?: TextFieldSize;
2055
- /** 입력 필드 시각 변형 (기본값: "outline") */
2620
+ /** 입력 필드 시각 변형 */
2056
2621
  variant?: TextFieldVariant;
2057
2622
  /** 입력 필드 위에 표시할 라벨 텍스트 */
2058
2623
  label?: string;
@@ -2101,7 +2666,7 @@ interface TextFieldProps extends Omit<React$1.InputHTMLAttributes<HTMLInputEleme
2101
2666
  };
2102
2667
  /** 값이 있을 때 오른쪽에 지우기(X) 버튼 표시 여부 */
2103
2668
  clearable?: boolean;
2104
- /** 지우기(X) 버튼의 `aria-label` (기본값: "지우기") */
2669
+ /** 지우기(X) 버튼의 `aria-label` */
2105
2670
  clearLabel?: string;
2106
2671
  /** 컨테이너 전체 너비 차지 여부 */
2107
2672
  fullWidth?: boolean;
@@ -2131,7 +2696,7 @@ interface TextFieldProps extends Omit<React$1.InputHTMLAttributes<HTMLInputEleme
2131
2696
  * @returns 렌더링된 텍스트 필드 UI
2132
2697
  */
2133
2698
  declare const TextField: {
2134
- ({ id, label, showLabel, supportingText, error, success, identifier, leadingIcon, trailingIcon, leadingAction, trailingAction, showPasswordToggle, passwordToggleLabels, clearable, clearLabel, type, fullWidth, size, variant, className, onValueChange, onChangeAction, imeStrategy, value, defaultValue, transformValue, ref, ...props }: TextFieldProps): React$1.JSX.Element;
2699
+ ({ id, label, showLabel, supportingText, error, success, identifier, leadingIcon, trailingIcon, leadingAction, trailingAction, showPasswordToggle, passwordToggleLabels, clearable, clearLabel: clearLabelProp, type, fullWidth, size, variant, className, onValueChange, onChangeAction, imeStrategy, value, defaultValue, transformValue, ref, ...props }: TextFieldProps): React$1.JSX.Element;
2135
2700
  displayName: string;
2136
2701
  };
2137
2702
 
@@ -2202,6 +2767,49 @@ declare const Textarea: {
2202
2767
  displayName: string;
2203
2768
  };
2204
2769
 
2770
+ interface TimePickerProps {
2771
+ /** 위에 표시할 라벨 */
2772
+ label?: string;
2773
+ /** 제어형 값 (`"HH:mm"`) */
2774
+ value?: string;
2775
+ /** 선택 변경 */
2776
+ onValueChange: (value: string) => void;
2777
+ /** 분 간격 (기본값: 5). 5·10·15·30 처럼 60 의 약수를 준다 */
2778
+ minuteStep?: number;
2779
+ /** 선택 가능한 가장 이른 시각 (`"HH:mm"`) */
2780
+ minTime?: string;
2781
+ /** 선택 가능한 가장 늦은 시각 (`"HH:mm"`) */
2782
+ maxTime?: string;
2783
+ /** 비활성 여부 */
2784
+ disabled?: boolean;
2785
+ /** 전체 너비 차지 (기본값: true) */
2786
+ fullWidth?: boolean;
2787
+ /** 시 select 의 라벨/placeholder */
2788
+ hourLabel?: string;
2789
+ /** 분 select 의 라벨/placeholder */
2790
+ minuteLabel?: string;
2791
+ }
2792
+ /**
2793
+ * 시·분 선택. `DatePicker` 와 같은 방식으로 DS `Dropdown` 두 개를 조합한다.
2794
+ *
2795
+ * 손으로 만들면 갈리는 것들을 여기서 소유한다.
2796
+ *
2797
+ * - **분 간격** — 예약·근무 시간은 5분·30분 단위인데 60개 옵션을 다 그리면 고르기 어렵다
2798
+ * - **영업시간 밖 차단** — `minTime`/`maxTime` 이 시 목록까지 좁힌다. 분만 걸러 두면 09:00 이
2799
+ * 최소인데 08시를 고를 수 있고, 그때 분 목록이 비어 막힌 화면이 된다
2800
+ * - **경계에서의 분 목록** — 최소가 09:30 이면 09시의 분은 30분부터 시작한다
2801
+ *
2802
+ * 값은 24시간 `"HH:mm"` 이다 - 12시간 표기는 화면 표시의 문제라 소비자가 포맷한다.
2803
+ *
2804
+ * @example
2805
+ * ```tsx
2806
+ * <Field name="pickupAt" label="픽업 시각">
2807
+ * <TimePicker value={time} onValueChange={setTime} minuteStep={30} minTime="09:00" maxTime="21:00" />
2808
+ * </Field>
2809
+ * ```
2810
+ */
2811
+ declare const TimePicker: ({ label, value, onValueChange, minuteStep, minTime, maxTime, disabled, fullWidth, hourLabel: hourLabelProp, minuteLabel: minuteLabelProp, }: TimePickerProps) => React$1.JSX.Element;
2812
+
2205
2813
  interface ToggleProps extends Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, "onChange"> {
2206
2814
  /** 제어형 토글 상태 */
2207
2815
  checked?: boolean;
@@ -2258,37 +2866,46 @@ interface ButtonBaseProps {
2258
2866
  */
2259
2867
  disabled?: boolean;
2260
2868
  }
2261
- /** `<button>` 으로 렌더링 (기본) */
2262
- interface ButtonAsButton extends ButtonBaseProps, Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, keyof ButtonBaseProps> {
2263
- /** 렌더링할 요소 (기본값: "button") */
2264
- as?: "button";
2265
- /** button 렌더 시엔 href 허용하지 않음 (href 주면 anchor 분기되도록) */
2266
- href?: never;
2267
- /** 루트 button 요소 ref (React 19 ref-as-prop) */
2268
- ref?: React$1.Ref<HTMLButtonElement>;
2269
- }
2270
- /** `<a>` 렌더링 - 링크 시맨틱(우클릭 탭·미들클릭·SR 링크 안내) */
2271
- interface ButtonAsAnchor extends ButtonBaseProps, Omit<React$1.AnchorHTMLAttributes<HTMLAnchorElement>, keyof ButtonBaseProps> {
2272
- /** anchor 렌더링 - 생략 가능(href 줘도 anchor 분기) */
2273
- as?: "a";
2274
- /** 링크 대상 (anchor 필수) */
2869
+ /**
2870
+ * Button props. `as` 로 렌더 요소를 바꾼다 - `"a"`, `Link`(Next.js) 무엇이든.
2871
+ *
2872
+ * `as` 를 주지 않으면 `<button>` 이고, `href` 만 주면 `<a>` 로 간다(예전부터 지원한 경로다).
2873
+ * 경로를 유니온으로 만들면 `ref={(el) => …}` 파라미터 추론이 깨진다 - 기본 케이스에만
2874
+ * `href` 를 더하는 조건부 교차로 두면 타입이 하나로 남아 추론이 유지된다.
2875
+ *
2876
+ * `as="a"` 면 `href` 는 **필수**다 - 판별 유니온 시절 `ButtonAsAnchor` 의 계약이고, `href` 없는
2877
+ * `<a>` 는 링크 시맨틱(클릭·포커스)이 없어 접근성 트리에서 링크로 잡히지도 않는다. `React` 의
2878
+ * `AnchorHTMLAttributes` `href?` 그대로 두면 옵션으로 느슨해진다.
2879
+ */
2880
+ type ButtonProps<T extends React$1.ElementType = "button"> = PolymorphicProps<T, ButtonBaseProps> & ("button" extends T ? {
2881
+ href?: string;
2882
+ } : Record<never, never>) & ("a" extends T ? {
2275
2883
  href: string;
2276
- /** 루트 anchor 요소 ref (React 19 ref-as-prop) */
2277
- ref?: React$1.Ref<HTMLAnchorElement>;
2278
- }
2884
+ } : Record<never, never>);
2279
2885
  /**
2280
- * Button props - `as`/`href` 에 따라 button 또는 anchor 렌더링되는 discriminated union.
2281
- * `as` 미지정 시 기본 `<button>` (기존 동작과 100% 호환).
2886
+ * @deprecated `ButtonProps<"button">` 쓰세요. 리터럴 유니온 시절의 이름입니다.
2282
2887
  */
2283
- type ButtonProps = ButtonAsButton | ButtonAsAnchor;
2888
+ type ButtonAsButton = ButtonProps<"button">;
2889
+ /**
2890
+ * @deprecated `ButtonProps<"a">` 을 쓰세요. 리터럴 유니온 시절의 이름입니다.
2891
+ */
2892
+ type ButtonAsAnchor = ButtonProps<"a">;
2284
2893
  /**
2285
2894
  * 버튼을 렌더링한다.
2286
2895
  * Figma DS 기준 4가지 variant(filled/tonal/outline/text)와 4가지 size(sm/md/lg/xl)를 지원한다.
2287
- * `as="a"` (또는 `href` 지정) 시 동일 스타일의 anchor 로 렌더링한다.
2288
- * @param props 버튼 속성
2289
- * @returns 렌더링된 button 또는 anchor 요소
2896
+ *
2897
+ * `as` 렌더 요소를 바꾼다 - `as="a"`(또는 `href` 만 지정)는 anchor, `as={Link}` 는 라우터 링크.
2898
+ *
2899
+ * **native `disabled` 는 `<button>` 에만 준다.** 그 밖의 요소에는 `aria-disabled` +
2900
+ * `tabIndex={-1}` + 클릭 차단으로 처리한다 - anchor 와 커스텀 컴포넌트에는 native disabled 가
2901
+ * 없어서 그냥 넘기면 조용히 무시되고 비활성 버튼이 눌린다.
2902
+ *
2903
+ * @example
2904
+ * ```tsx
2905
+ * <Button as={Link} href="/orders">주문 보기</Button>
2906
+ * ```
2290
2907
  */
2291
- declare const Button: (props: ButtonProps) => React$1.JSX.Element;
2908
+ declare const Button: <T extends React$1.ElementType = "button">(props: ButtonProps<T>) => React$1.JSX.Element;
2292
2909
 
2293
2910
  type IconButtonVariant = "standard" | "filled" | "tonal" | "outlined";
2294
2911
  type IconButtonSize = "sm" | "md";
@@ -2347,9 +2964,9 @@ interface PaginationBaseProps {
2347
2964
  page: number;
2348
2965
  /** 전체 페이지 수 */
2349
2966
  totalPages: number;
2350
- /** 이전 페이지 버튼 aria-label (기본값: "이전 페이지") */
2967
+ /** 이전 페이지 버튼 aria-label */
2351
2968
  prevLabel?: string;
2352
- /** 다음 페이지 버튼 aria-label (기본값: "다음 페이지") */
2969
+ /** 다음 페이지 버튼 aria-label */
2353
2970
  nextLabel?: string;
2354
2971
  /** `<nav>` 랜드마크 이름 (기본값: "페이지 이동"). 스크린리더의 리전 목록에 그대로 뜬다 */
2355
2972
  navLabel?: string;
@@ -2368,7 +2985,7 @@ type PaginationProps = PaginationBaseProps & PaginationCallbacks;
2368
2985
  * @param props 페이지네이션 속성
2369
2986
  * @returns 렌더링된 페이지네이션 UI
2370
2987
  */
2371
- declare const Pagination: ({ page, totalPages, onPageChange, onChange, prevLabel, nextLabel, navLabel, }: PaginationProps) => React$1.JSX.Element;
2988
+ declare const Pagination: ({ page, totalPages, onPageChange, onChange, prevLabel: prevLabelProp, nextLabel: nextLabelProp, navLabel: navLabelProp, }: PaginationProps) => React$1.JSX.Element;
2372
2989
 
2373
2990
  /** Drawer 가 미끄러져 들어오는 방향 (top 은 범위 외) */
2374
2991
  type DrawerPlacement = "left" | "right" | "bottom";
@@ -2377,7 +2994,7 @@ interface DrawerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "titl
2377
2994
  open: boolean;
2378
2995
  /** 드로어 닫기 콜백 */
2379
2996
  onClose?: () => void;
2380
- /** 슬라이드 방향 (기본값: "right") */
2997
+ /** 슬라이드 방향 */
2381
2998
  placement?: DrawerPlacement;
2382
2999
  /** 패널 크기 - left/right 는 너비, bottom 은 높이 (기본값: 360). number ⇒ px */
2383
3000
  size?: number | string;
@@ -2397,7 +3014,7 @@ interface DrawerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "titl
2397
3014
  dismissible?: boolean;
2398
3015
  /** 우상단 X 닫기 아이콘 표시 여부 (기본값: true) */
2399
3016
  showCloseIcon?: boolean;
2400
- /** X 닫기 버튼 접근성 레이블 (기본값: "닫기") */
3017
+ /** X 닫기 버튼 접근성 레이블 */
2401
3018
  closeLabel?: string;
2402
3019
  /**
2403
3020
  * 드로어 접근성 레이블. `title` 이 없을 때 이 값이 접근성 이름이 된다.
@@ -2418,7 +3035,7 @@ interface DrawerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "titl
2418
3035
  * @returns 열림 상태일 때 렌더링된 드로어, 닫힘 상태면 null
2419
3036
  */
2420
3037
  declare const Drawer: {
2421
- ({ open, onClose, placement, size, title, footer, closeOnOverlay, dismissible, showCloseIcon, closeLabel, ariaLabel, onExited, children, className, ...props }: DrawerProps): React$1.ReactPortal | null;
3038
+ ({ open, onClose, placement, size, title, footer, closeOnOverlay, dismissible, showCloseIcon, closeLabel: closeLabelProp, ariaLabel, onExited, children, className, ...props }: DrawerProps): React$1.ReactPortal | null;
2422
3039
  displayName: string;
2423
3040
  };
2424
3041
 
@@ -2450,7 +3067,7 @@ interface ModalProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title
2450
3067
  footerAlign?: ModalFooterAlign;
2451
3068
  /** 우상단 X 닫기 아이콘 표시 여부 (기본값: true) */
2452
3069
  showCloseIcon?: boolean;
2453
- /** X 닫기 버튼 접근성 레이블 (기본값: "닫기") */
3070
+ /** X 닫기 버튼 접근성 레이블 */
2454
3071
  closeLabel?: string;
2455
3072
  /**
2456
3073
  * 모달 접근성 레이블. `title` 이 없으면 이 값이 유일한 접근성 이름이다 - 폴백이 없으므로
@@ -2469,7 +3086,128 @@ interface ModalProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title
2469
3086
  * @param props 모달 속성
2470
3087
  * @returns 열림 상태일 때 렌더링된 모달, 닫힘 상태면 null
2471
3088
  */
2472
- declare const Modal: ({ open, onClose, closeOnOverlay, dismissible, width, title, description, footer, footerAlign, showCloseIcon, closeLabel, children, className, ariaLabel, onExited, ...props }: ModalProps) => React$1.ReactPortal | null;
3089
+ declare const Modal: ({ open, onClose, closeOnOverlay, dismissible, width, title, description, footer, footerAlign, showCloseIcon, closeLabel: closeLabelProp, children, className, ariaLabel, onExited, ...props }: ModalProps) => React$1.ReactPortal | null;
3090
+
3091
+ /**
3092
+ * DS 가 스스로 렌더하는 모든 사용자 노출 문구. 컴포넌트 안에 흩어져 있던 기본값을 한곳에 모은다.
3093
+ *
3094
+ * 왜 한곳이어야 하나 - 소비자가 영어 화면을 만들려면 지금은 컴포넌트 **인스턴스마다** prop 을
3095
+ * 넘겨야 한다. `Modal` 을 40번 쓰는 앱이면 `closeLabel` 을 40번 적는다. 하나라도 빠지면 그
3096
+ * 화면만 한국어로 남는다.
3097
+ *
3098
+ * `{name}` 은 자리표시자다. 값은 `t(key, { name: … })` 로 채운다.
3099
+ */
3100
+ interface LocaleMessages {
3101
+ "chip.remove": string;
3102
+ "dataView.clearSelection": string;
3103
+ "dataView.empty": string;
3104
+ "dataView.errorTitle": string;
3105
+ "dataView.retry": string;
3106
+ "dataView.search": string;
3107
+ "dataView.selectionSummary": string;
3108
+ "table.empty": string;
3109
+ "table.rowClickHint": string;
3110
+ "table.selectAll": string;
3111
+ "table.selectRow": string;
3112
+ "alert.cancel": string;
3113
+ "alert.confirm": string;
3114
+ "errorState.title": string;
3115
+ "spinner.label": string;
3116
+ "toast.close": string;
3117
+ "toast.region": string;
3118
+ "topLoading.label": string;
3119
+ "combobox.empty": string;
3120
+ "combobox.idle": string;
3121
+ "combobox.loading": string;
3122
+ "combobox.placeholder": string;
3123
+ "datePicker.day": string;
3124
+ "datePicker.minDateSr": string;
3125
+ "datePicker.month": string;
3126
+ "datePicker.rangeUntilTodaySr": string;
3127
+ "datePicker.year": string;
3128
+ "dateRange.end": string;
3129
+ "dateRange.start": string;
3130
+ "dropdown.empty": string;
3131
+ "dropdown.placeholder": string;
3132
+ "dropdown.searchPlaceholder": string;
3133
+ "dropdown.selectedSummary": string;
3134
+ "fileInput.label": string;
3135
+ "fileInput.removeImage": string;
3136
+ "imageCropper.hint": string;
3137
+ "imageCropper.label": string;
3138
+ "imageCropper.noPanHint": string;
3139
+ "imageCropper.zoom": string;
3140
+ "imageCropper.zoomIn": string;
3141
+ "imageCropper.zoomOut": string;
3142
+ "otpInput.digit": string;
3143
+ "otpInput.label": string;
3144
+ "tagInput.added": string;
3145
+ "tagInput.addedWithNotes": string;
3146
+ "tagInput.atCap": string;
3147
+ "tagInput.duplicate": string;
3148
+ "tagInput.placeholder": string;
3149
+ "tagInput.removed": string;
3150
+ "textField.clear": string;
3151
+ "textField.passwordHide": string;
3152
+ "textField.passwordShow": string;
3153
+ "timePicker.hour": string;
3154
+ "timePicker.minute": string;
3155
+ "timePicker.rangeSr": string;
3156
+ "bottomNav.label": string;
3157
+ "breadcrumb.label": string;
3158
+ "pagination.label": string;
3159
+ "pagination.next": string;
3160
+ "pagination.prev": string;
3161
+ "sidebar.toggle": string;
3162
+ "drawer.close": string;
3163
+ "modal.close": string;
3164
+ }
3165
+ type LocaleKey = keyof LocaleMessages;
3166
+ /** 기본 카탈로그. 이 값이 각 컴포넌트의 기본 문구다 */
3167
+ declare const ko: LocaleMessages;
3168
+ /** 영어 카탈로그. `<LocaleProvider locale="en">` 로 고른다 */
3169
+ declare const en: LocaleMessages;
3170
+ declare const catalogs: {
3171
+ readonly ko: LocaleMessages;
3172
+ readonly en: LocaleMessages;
3173
+ };
3174
+ type LocaleName = keyof typeof catalogs;
3175
+
3176
+ /** `t(key, vars)` - 카탈로그에서 문구를 꺼내고 `{name}` 자리표시자를 채운다 */
3177
+ type LocaleText = (key: LocaleKey, vars?: Record<string, string | number>) => string;
3178
+ interface LocaleProviderProps {
3179
+ /** 기준 카탈로그 (기본값: "ko") */
3180
+ locale?: LocaleName;
3181
+ /** 기준 위에 덮어쓸 문구. 한 줄만 바꿀 때 쓴다 */
3182
+ messages?: Partial<LocaleMessages>;
3183
+ children?: React$1.ReactNode;
3184
+ }
3185
+ /**
3186
+ * DS 가 스스로 렌더하는 문구를 한곳에서 정한다.
3187
+ *
3188
+ * Provider 가 없으면 한국어 카탈로그가 그대로 쓰인다 - 기존 소비자의 화면은 바뀌지 않는다.
3189
+ *
3190
+ * @example 영어 화면
3191
+ * ```tsx
3192
+ * <LocaleProvider locale="en">
3193
+ * <App />
3194
+ * </LocaleProvider>
3195
+ * ```
3196
+ *
3197
+ * @example 한 줄만 바꾸기
3198
+ * ```tsx
3199
+ * <LocaleProvider messages={{ "table.empty": "주문이 없습니다" }}>
3200
+ * ```
3201
+ */
3202
+ declare const LocaleProvider: ({ locale, messages, children }: LocaleProviderProps) => React$1.JSX.Element;
3203
+ /**
3204
+ * 컴포넌트가 자기 기본 문구를 꺼내는 통로. Provider 밖에서는 한국어 카탈로그를 돌려준다.
3205
+ *
3206
+ * prop 으로 받은 값이 항상 우선이다 - `closeLabel ?? t("modal.close")`.
3207
+ */
3208
+ declare function useLocaleText(): LocaleText;
3209
+ /** 현재 로케일 이름. 날짜·숫자 포맷을 소비자가 맞출 때 쓴다 */
3210
+ declare function useLocaleName(): LocaleName;
2473
3211
 
2474
3212
  type ThemeMode = "light" | "dark" | "system";
2475
3213
  type ResolvedTheme = "light" | "dark";
@@ -2508,8 +3246,47 @@ interface ThemeProviderProps {
2508
3246
  */
2509
3247
  declare const ThemeProvider: React$1.FC<ThemeProviderProps>;
2510
3248
 
3249
+ interface AppShellProps extends React$1.HTMLAttributes<HTMLDivElement> {
3250
+ /** 좌측 네비게이션. 보통 `Sidebar` */
3251
+ sidebar?: React$1.ReactNode;
3252
+ /** 콘텐츠 열 위에 고정되는 헤더. 보통 `NavBar` */
3253
+ header?: React$1.ReactNode;
3254
+ /** 본문 여백 (기본값: true). 자체 여백을 가진 화면은 false */
3255
+ padded?: boolean;
3256
+ /** 루트 요소 ref (React 19 ref-as-prop) */
3257
+ ref?: React$1.Ref<HTMLDivElement>;
3258
+ }
3259
+ /**
3260
+ * 관리자·대시보드 화면의 껍데기. 사이드바 열 + 고정 헤더 + 본문을 한 곳에서 잡는다.
3261
+ *
3262
+ * 화면마다 `<div style={{ display: "flex", minHeight: "100vh" }}>` 로 다시 만들던 층이고,
3263
+ * 그때마다 조용히 빠지던 것들을 여기서 소유한다.
3264
+ *
3265
+ * - **문서가 스크롤한다.** 본문을 `overflow-y: auto` 로 만들면 `Modal`·`Drawer` 의 스크롤
3266
+ * 잠금(`body { overflow: hidden }`)이 본문에 닿지 않아 모달 뒤 배경이 계속 스크롤된다.
3267
+ * 사이드바와 헤더는 `sticky` 로 붙인다.
3268
+ * - **콘텐츠 열은 `minmax(0, 1fr)`.** 없으면 자기 넘침을 스스로 처리하지 않는 자식(줄바꿈 없는
3269
+ * 긴 문자열, 폭이 고정된 블록)이 열 자체를 자기 폭까지 늘린다. 실측 - 1800px 자식을 넣으면
3270
+ * 열이 1024px → 1869px 로 늘어나 고정 헤더와 모든 행이 화면보다 넓어진다. 이 값이 있으면
3271
+ * 열은 뷰포트 폭에 머물고 넘침은 그 자식 안에 남는다.
3272
+ * - **하단 크롬 여백.** `Sidebar` 는 600px 아래에서 fixed BottomBar 로 변신해 문서 흐름에서
3273
+ * 빠지고, `BottomNav` 도 fixed 다. 본문 끝이 그 아래로 가려지지 않게 `--bt-bottom-inset`
3274
+ * 만큼 띄운다.
3275
+ *
3276
+ * 헤더를 사이드바 위까지 꽉 채우려면 `AppShell` 밖에 두면 된다.
3277
+ *
3278
+ * @example
3279
+ * ```tsx
3280
+ * <AppShell sidebar={<Sidebar … />} header={<NavBar layout="fluid" sticky … />}>
3281
+ * <PageHeader title="대시보드" actions={<Button>추가</Button>} />
3282
+ * <DataView … />
3283
+ * </AppShell>
3284
+ * ```
3285
+ */
3286
+ declare const AppShell: ({ sidebar, header, padded, className, children, ref, ...props }: AppShellProps) => React$1.JSX.Element;
3287
+
2511
3288
  type ContainerSize = "sm" | "md" | "lg" | "xl" | "full";
2512
- interface ContainerProps extends React$1.HTMLAttributes<HTMLDivElement> {
3289
+ interface ContainerOwnProps {
2513
3290
  /**
2514
3291
  * max-width 크기
2515
3292
  * - sm: 640px | md: 768px | lg: 1024px | xl: 1200px | full: 100%
@@ -2518,11 +3295,15 @@ interface ContainerProps extends React$1.HTMLAttributes<HTMLDivElement> {
2518
3295
  size?: ContainerSize;
2519
3296
  /** 가운데 정렬 (기본 true) */
2520
3297
  center?: boolean;
2521
- /** 렌더링할 HTML 요소 */
2522
- as?: React$1.ElementType;
2523
- /** 루트 요소 ref (React 19 ref-as-prop) */
2524
- ref?: React$1.Ref<HTMLElement>;
2525
3298
  }
3299
+ /**
3300
+ * Container props. `as` 로 렌더 요소를 바꾼다 - `"main"`·`"ul"` 같은 태그든 `Link` 같은
3301
+ * 컴포넌트든, 그 요소의 props 가 타입에 그대로 따라온다.
3302
+ *
3303
+ * 예전에는 `as?: React.ElementType` 이라 요소만 갈리고 props 는 `div` 기준으로 고정돼,
3304
+ * `as="a"` 로 바꿔도 `href` 가 타입에 없었다.
3305
+ */
3306
+ type ContainerProps<T extends React$1.ElementType = "div"> = PolymorphicProps<T, ContainerOwnProps>;
2526
3307
  /**
2527
3308
  * max-width 제한 + 반응형 수평 패딩을 가진 컨테이너.
2528
3309
  * 모든 마케팅/서비스 페이지의 기본 wrapper.
@@ -2535,11 +3316,11 @@ interface ContainerProps extends React$1.HTMLAttributes<HTMLDivElement> {
2535
3316
  * </Container>
2536
3317
  * ```
2537
3318
  */
2538
- declare const Container: ({ size, center, as: Tag, ref, className, children, ...props }: ContainerProps) => React$1.JSX.Element;
3319
+ declare const Container: <T extends React$1.ElementType = "div">({ size, center, as, ref, className, children, ...props }: ContainerProps<T>) => React$1.JSX.Element;
2539
3320
 
2540
3321
  type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | "auto";
2541
3322
  type GridGap = 0 | 4 | 8 | 12 | 16 | 20 | 24 | 32 | 40 | 48;
2542
- interface GridProps extends React$1.HTMLAttributes<HTMLDivElement> {
3323
+ interface GridOwnProps {
2543
3324
  /**
2544
3325
  * 열 수. "auto" = auto-fill (minColWidth 사용)
2545
3326
  * @default 3
@@ -2561,11 +3342,15 @@ interface GridProps extends React$1.HTMLAttributes<HTMLDivElement> {
2561
3342
  colGap?: GridGap;
2562
3343
  /** 반응형 - compact(< 600px)에서 강제 1열 (기본 true) */
2563
3344
  singleColOnMobile?: boolean;
2564
- /** 렌더링할 HTML 요소 */
2565
- as?: React$1.ElementType;
2566
- /** 루트 요소 ref (React 19 ref-as-prop) */
2567
- ref?: React$1.Ref<HTMLElement>;
2568
3345
  }
3346
+ /**
3347
+ * Grid props. `as` 로 렌더 요소를 바꾼다 - `"main"`·`"ul"` 같은 태그든 `Link` 같은
3348
+ * 컴포넌트든, 그 요소의 props 가 타입에 그대로 따라온다.
3349
+ *
3350
+ * 예전에는 `as?: React.ElementType` 이라 요소만 갈리고 props 는 `div` 기준으로 고정돼,
3351
+ * `as="a"` 로 바꿔도 `href` 가 타입에 없었다.
3352
+ */
3353
+ type GridProps<T extends React$1.ElementType = "div"> = PolymorphicProps<T, GridOwnProps>;
2569
3354
  /**
2570
3355
  * CSS Grid 기반 2D 레이아웃 컨테이너.
2571
3356
  * 고정 열 수 또는 auto-fill 반응형 그리드.
@@ -2583,11 +3368,49 @@ interface GridProps extends React$1.HTMLAttributes<HTMLDivElement> {
2583
3368
  * </Grid>
2584
3369
  * ```
2585
3370
  */
2586
- declare const Grid: ({ cols, minColWidth, gap, rowGap, colGap, singleColOnMobile, as: Tag, ref, className, children, style, ...props }: GridProps) => React$1.JSX.Element;
3371
+ declare const Grid: <T extends React$1.ElementType = "div">({ cols, minColWidth, gap, rowGap, colGap, singleColOnMobile, as, ref, className, children, style, ...props }: GridProps<T>) => React$1.JSX.Element;
3372
+
3373
+ interface PageHeaderProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title"> {
3374
+ /** 화면 제목. `h1` 로 렌더된다 */
3375
+ title: React$1.ReactNode;
3376
+ /** 제목 아래 한 줄 설명 */
3377
+ description?: React$1.ReactNode;
3378
+ /** 제목 위 경로. 보통 `Breadcrumb` */
3379
+ breadcrumb?: React$1.ReactNode;
3380
+ /** 우측 액션. 보통 `Button` 하나 또는 둘 */
3381
+ actions?: React$1.ReactNode;
3382
+ /** 제목 줄 아래에 붙는 영역. 보통 `TabList` */
3383
+ tabs?: React$1.ReactNode;
3384
+ /** 루트 요소 ref (React 19 ref-as-prop) */
3385
+ ref?: React$1.Ref<HTMLDivElement>;
3386
+ }
3387
+ /**
3388
+ * 화면 제목 줄. 경로 · 제목 · 설명 · 액션 · 탭을 한 규약으로 묶는다.
3389
+ *
3390
+ * 화면마다 `<h1 style={{ fontSize: 20, fontWeight: 600 }}>` 로 다시 만들던 층이다.
3391
+ * 제목 크기와 설명 색을 화면마다 정하면 같은 제품 안에서 제목이 서로 다른 크기로 보인다.
3392
+ *
3393
+ * 제목은 `h1` 이다 - 화면의 제목이므로 문서에 하나만 있어야 한다.
3394
+ *
3395
+ * 겉은 `<header>` 가 아니라 `<div>` 다. `<header>` 는 `<main>` 안에 있어도 banner landmark 로
3396
+ * 계산되므로(`main` 은 sectioning content 가 아니다), `NavBar` 의 `<header>` 와 banner 가 둘이
3397
+ * 되어 landmark 목록이 망가진다.
3398
+ *
3399
+ * @example
3400
+ * ```tsx
3401
+ * <PageHeader
3402
+ * breadcrumb={<Breadcrumb items={…} />}
3403
+ * title="주문 관리"
3404
+ * description="최근 30일 주문을 봅니다"
3405
+ * actions={<Button>주문 추가</Button>}
3406
+ * />
3407
+ * ```
3408
+ */
3409
+ declare const PageHeader: ({ title, description, breadcrumb, actions, tabs, className, ref, ...props }: PageHeaderProps) => React$1.JSX.Element;
2587
3410
 
2588
3411
  type SectionSpacing = "xs" | "sm" | "md" | "lg" | "xl";
2589
3412
  type SectionBg = "default" | "dim" | "accent" | "inverted" | "transparent";
2590
- interface SectionProps extends React$1.HTMLAttributes<HTMLElement> {
3413
+ interface SectionOwnProps {
2591
3414
  /**
2592
3415
  * 수직 패딩 크기
2593
3416
  * - xs: 32px | sm: 48px | md: 64px | lg: 96px | xl: 128px
@@ -2600,11 +3423,15 @@ interface SectionProps extends React$1.HTMLAttributes<HTMLElement> {
2600
3423
  * @default "default"
2601
3424
  */
2602
3425
  bg?: SectionBg;
2603
- /** 렌더링할 HTML 요소 */
2604
- as?: React$1.ElementType;
2605
- /** 루트 요소 ref (React 19 ref-as-prop) */
2606
- ref?: React$1.Ref<HTMLElement>;
2607
3426
  }
3427
+ /**
3428
+ * Section props. `as` 로 렌더 요소를 바꾼다 - `"main"`·`"ul"` 같은 태그든 `Link` 같은
3429
+ * 컴포넌트든, 그 요소의 props 가 타입에 그대로 따라온다.
3430
+ *
3431
+ * 예전에는 `as?: React.ElementType` 이라 요소만 갈리고 props 는 `div` 기준으로 고정돼,
3432
+ * `as="a"` 로 바꿔도 `href` 가 타입에 없었다.
3433
+ */
3434
+ type SectionProps<T extends React$1.ElementType = "section"> = PolymorphicProps<T, SectionOwnProps>;
2608
3435
  /**
2609
3436
  * 마케팅 페이지의 섹션 단위. 수직 여백 + 배경색 variants.
2610
3437
  *
@@ -2618,14 +3445,14 @@ interface SectionProps extends React$1.HTMLAttributes<HTMLElement> {
2618
3445
  * </Section>
2619
3446
  * ```
2620
3447
  */
2621
- declare const Section: ({ spacing, bg, as: Tag, ref, className, children, ...props }: SectionProps) => React$1.JSX.Element;
3448
+ declare const Section: <T extends React$1.ElementType = "section">({ spacing, bg, as, ref, className, children, ...props }: SectionProps<T>) => React$1.JSX.Element;
2622
3449
 
2623
3450
  type StackDirection = "vertical" | "horizontal";
2624
3451
  type StackAlign = "start" | "center" | "end" | "stretch";
2625
3452
  type StackJustify = "start" | "center" | "end" | "between" | "around" | "evenly";
2626
3453
  type StackGap = 0 | 2 | 4 | 8 | 12 | 16 | 20 | 24 | 32 | 40 | 48;
2627
3454
  type StackWrap = "nowrap" | "wrap" | "wrap-reverse";
2628
- interface StackProps extends React$1.HTMLAttributes<HTMLDivElement> {
3455
+ interface StackOwnProps {
2629
3456
  /**
2630
3457
  * flex 방향
2631
3458
  * @default "vertical"
@@ -2642,11 +3469,15 @@ interface StackProps extends React$1.HTMLAttributes<HTMLDivElement> {
2642
3469
  justify?: StackJustify;
2643
3470
  /** flex-wrap */
2644
3471
  wrap?: StackWrap;
2645
- /** 렌더링할 HTML 요소 */
2646
- as?: React$1.ElementType;
2647
- /** 루트 요소 ref (React 19 ref-as-prop) */
2648
- ref?: React$1.Ref<HTMLElement>;
2649
3472
  }
3473
+ /**
3474
+ * Stack props. `as` 로 렌더 요소를 바꾼다 - `"main"`·`"ul"` 같은 태그든 `Link` 같은
3475
+ * 컴포넌트든, 그 요소의 props 가 타입에 그대로 따라온다.
3476
+ *
3477
+ * 예전에는 `as?: React.ElementType` 이라 요소만 갈리고 props 는 `div` 기준으로 고정돼,
3478
+ * `as="a"` 로 바꿔도 `href` 가 타입에 없었다.
3479
+ */
3480
+ type StackProps<T extends React$1.ElementType = "div"> = PolymorphicProps<T, StackOwnProps>;
2650
3481
  /**
2651
3482
  * Flex 기반 1D 레이아웃 컨테이너.
2652
3483
  * 수직(column) / 수평(row) 스택 + 간격/정렬 제어.
@@ -2664,6 +3495,6 @@ interface StackProps extends React$1.HTMLAttributes<HTMLDivElement> {
2664
3495
  * </Stack>
2665
3496
  * ```
2666
3497
  */
2667
- declare const Stack: ({ direction, gap, align, justify, wrap, as: Tag, ref, className, children, style, ...props }: StackProps) => React$1.JSX.Element;
3498
+ declare const Stack: <T extends React$1.ElementType = "div">({ direction, gap, align, justify, wrap, as, ref, className, children, style, ...props }: StackProps<T>) => React$1.JSX.Element;
2668
3499
 
2669
- export { Accordion, type AccordionItem, type AccordionProps, type AlertActionsAlign, type AlertOptions, AlertProvider, type AlertVariant, Avatar, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeAppearance, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeVariant, BottomNav, BottomNavItem, type BottomNavItemProps, type BottomNavProps, BottomNavSpacer, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonAsAnchor, type ButtonAsButton, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardFooterAlign, type CardProps, type CardVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipSize, type ChipTone, type ChipType, Container, type ContainerProps, type ContainerSize, type CropImageSize, type CropOffset, type CropRect, DatePicker, type DatePickerProps, Divider, type DividerProps, Drawer, type DrawerPlacement, type DrawerProps, Dropdown, type DropdownMultipleProps, type DropdownOption, type DropdownProps, type DropdownSingleProps, type DropdownSize, type DropdownVariant, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, type ErrorStateVariant, FileInput, type FileInputProps, type FileInputVariant, Grid, type GridCols, type GridGap, type GridProps, Hero, type HeroAction, type HeroAlign, type HeroHeight, type HeroOverlay, type HeroProps, Icon, IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant, type IconProps, ImageCropper, type ImageCropperHandle, type ImageCropperProps, type ImeStrategy, LinearProgress, type LinearProgressProps, ListItem, type ListItemProps, MediaCard, type MediaCardImage, type MediaCardImagePosition, type MediaCardProps, type MediaCardShadow, Menu, type MenuItem, type MenuProps, Modal, type ModalFooterAlign, type ModalProps, NavBar, type NavBarLayout, type NavBarLocaleConfig, type NavBarLocaleOption, type NavBarProps, type NavBarVariant, NavLink, type NavLinkProps, OtpInput, type OtpInputProps, Pagination, type PaginationProps, Popover, type PopoverPlacement, type PopoverProps, Prose, type ProseProps, type ProseSize, Radio, RadioGroup, type RadioGroupContextValue, type RadioGroupOrientation, type RadioGroupProps, type RadioGroupSize, type RadioProps, type ResolvedTheme, Section, type SectionBg, type SectionProps, type SectionSpacing, Sidebar, SidebarItem, type SidebarItemProps, type SidebarMode, type SidebarProps, SidebarSection, type SidebarSectionProps, Skeleton, type SkeletonProps, type SkeletonVariant, Spinner, type SpinnerProps, Stack, type StackAlign, type StackDirection, type StackGap, type StackJustify, type StackProps, type StackWrap, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, type TableColumn, type TableProps, type TableSize, type TableSort, type TableSortDirection, Tabs, type TabsProps, type TabsSize, type TabsVariant, TextField, type TextFieldProps, type TextFieldSize, type TextFieldVariant, Textarea, type TextareaProps, type TextareaResize, type TextareaSize, type ThemeMode, ThemeProvider, type ThemeProviderProps, ToastProvider, type ToastProviderProps, type ToastVariant, Toggle, type ToggleProps, Tooltip, type TooltipPlacement, type TooltipProps, TopLoading, type TopLoadingProps, a11y, baseBorderWidth, baseColors, baseTypography, borderWidth, breakpoints, cn, colors, elevation, iconSize, motion, opacity, radius, skeleton, spacing, typography, useAlert, useFocusTrap, useRadioGroupContext, useReducedMotion, useSpringHover, useSpringPresence, useTheme, useToast, zIndex };
3500
+ export { Accordion, type AccordionItem, type AccordionProps, type AlertActionsAlign, type AlertOptions, AlertProvider, type AlertVariant, AppShell, type AppShellProps, Avatar, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeAppearance, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeVariant, BottomNav, BottomNavItem, type BottomNavItemProps, type BottomNavProps, BottomNavSpacer, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonAsAnchor, type ButtonAsButton, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardFooterAlign, type CardProps, type CardVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipSize, type ChipTone, type ChipType, Combobox, type ComboboxOption, type ComboboxProps, type ComboboxSize, Container, type ContainerProps, type ContainerSize, type CropImageSize, type CropOffset, type CropRect, DataView, type DataViewPagination, type DataViewProps, type DataViewQuery, type DataViewSelectionAction, type DataViewToolbar, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, DescriptionList, type DescriptionListItem, type DescriptionListLayout, type DescriptionListProps, Divider, type DividerProps, Drawer, type DrawerPlacement, type DrawerProps, Dropdown, type DropdownMultipleProps, type DropdownOption, type DropdownProps, type DropdownSingleProps, type DropdownSize, type DropdownVariant, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, type ErrorStateVariant, Field, type FieldControl, type FieldProps, FileInput, type FileInputProps, type FileInputVariant, Form, type FormActionsProps, type FormProps, Grid, type GridCols, type GridGap, type GridProps, Hero, type HeroAction, type HeroAlign, type HeroHeight, type HeroOverlay, type HeroProps, Icon, IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant, type IconProps, ImageCropper, type ImageCropperHandle, type ImageCropperProps, type ImeStrategy, LinearProgress, type LinearProgressProps, ListItem, type ListItemProps, type ListboxItem, type LocaleKey, type LocaleMessages, type LocaleName, LocaleProvider, type LocaleProviderProps, type LocaleText, MediaCard, type MediaCardImage, type MediaCardImagePosition, type MediaCardProps, type MediaCardShadow, Menu, type MenuItem, type MenuProps, Modal, type ModalFooterAlign, type ModalProps, NavBar, type NavBarLayout, type NavBarLocaleConfig, type NavBarLocaleOption, type NavBarProps, type NavBarVariant, NavLink, type NavLinkProps, OtpInput, type OtpInputProps, PageHeader, type PageHeaderProps, Pagination, type PaginationProps, type PolymorphicProps, type PolymorphicRef, Popover, type PopoverPlacement, type PopoverProps, Prose, type ProseProps, type ProseSize, Radio, RadioGroup, type RadioGroupContextValue, type RadioGroupOrientation, type RadioGroupProps, type RadioGroupSize, type RadioProps, type ResolvedTheme, Section, type SectionBg, type SectionProps, type SectionSpacing, Sidebar, SidebarItem, type SidebarItemProps, type SidebarMode, type SidebarProps, SidebarSection, type SidebarSectionProps, Skeleton, type SkeletonProps, type SkeletonVariant, Spinner, type SpinnerProps, Stack, type StackAlign, type StackDirection, type StackGap, type StackJustify, type StackProps, type StackWrap, Stat, type StatDeltaTone, type StatProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, type TableColumn, type TableProps, type TableSize, type TableSort, type TableSortDirection, Tabs, type TabsProps, type TabsSize, type TabsVariant, TagInput, type TagInputProps, type TagInputSize, TextField, type TextFieldProps, type TextFieldSize, type TextFieldVariant, Textarea, type TextareaProps, type TextareaResize, type TextareaSize, type ThemeMode, ThemeProvider, type ThemeProviderProps, TimePicker, type TimePickerProps, Timeline, type TimelineItem, type TimelineProps, type TimelineStatus, ToastProvider, type ToastProviderProps, type ToastVariant, Toggle, type ToggleProps, Tooltip, type TooltipPlacement, type TooltipProps, TopLoading, type TopLoadingProps, type UseListboxPopupArgs, type UseListboxPopupResult, a11y, baseBorderWidth, baseColors, baseTypography, borderWidth, breakpoints, catalogs, cn, colors, elevation, en, iconSize, ko, motion, opacity, radius, skeleton, spacing, typography, useAlert, useFieldControl, useFocusTrap, useListboxPopup, useLocaleName, useLocaleText, useRadioGroupContext, useReducedMotion, useSpringHover, useSpringPresence, useTheme, useToast, zIndex };