@reopt-ai/opt-ui 1.10.0 → 1.12.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.
Files changed (73) hide show
  1. package/COMPONENT_CATALOG.md +522 -218
  2. package/README.md +61 -7
  3. package/dist/core/index.cjs +10 -8
  4. package/dist/core/index.d.cts +3 -3
  5. package/dist/core/index.d.ts +3 -3
  6. package/dist/core/index.js +3 -3
  7. package/dist/docs/02-components/01-core.md +213 -96
  8. package/dist/docs/02-components/02-visuals.md +1 -1
  9. package/dist/docs/02-components/03-shells.md +334 -123
  10. package/dist/docs/02-components/04-surfaces.md +1 -1
  11. package/dist/docs/02-components/index.md +5 -5
  12. package/dist/docs/03-recipes/02-dashboards.md +126 -10
  13. package/dist/{field-sidebar-B6Ndr8HE.cjs → field-sidebar-BYgEmdy0.cjs} +2128 -1558
  14. package/dist/{field-sidebar-BXjvV7Cz.js → field-sidebar-BuO37l4c.js} +2111 -1561
  15. package/dist/{field-sidebar-nwcE9LC4.d.cts → field-sidebar-CrYlRZew.d.ts} +375 -154
  16. package/dist/{field-sidebar-DWfJAJlx.d.ts → field-sidebar-uXmoyvd7.d.cts} +375 -154
  17. package/dist/id-registry.cjs +124 -12
  18. package/dist/id-registry.d.cts +1 -2
  19. package/dist/id-registry.d.ts +1 -2
  20. package/dist/id-registry.js +124 -14
  21. package/dist/id-registry.json +265 -31
  22. package/dist/index.cjs +1162 -253
  23. package/dist/index.d.cts +573 -60
  24. package/dist/index.d.ts +573 -60
  25. package/dist/index.js +1134 -242
  26. package/dist/{key-pad-menu-DfZbeXhG.d.cts → key-pad-menu-CwcY_Vps.d.cts} +151 -7
  27. package/dist/{key-pad-menu-BQunU20e.js → key-pad-menu-Di2aRGbM.js} +388 -461
  28. package/dist/{key-pad-menu-D5mQcS5v.cjs → key-pad-menu-SItoHPLu.cjs} +490 -609
  29. package/dist/{key-pad-menu-BsgJMjD4.d.ts → key-pad-menu-WBJShCJn.d.ts} +152 -8
  30. package/dist/meta.cjs +1304 -168
  31. package/dist/meta.d.cts +12 -36
  32. package/dist/meta.d.ts +12 -36
  33. package/dist/meta.js +1304 -170
  34. package/dist/query.d.cts +1 -2
  35. package/dist/query.d.ts +1 -2
  36. package/dist/query.js +0 -2
  37. package/dist/shells/index.cjs +4 -1
  38. package/dist/shells/index.d.cts +2 -2
  39. package/dist/shells/index.d.ts +2 -2
  40. package/dist/shells/index.js +2 -2
  41. package/dist/{text-truncate-BGr7bB_8.d.cts → text-truncate-CQyfUZvq.d.cts} +48 -5
  42. package/dist/{text-truncate-BGr7bB_8.d.ts → text-truncate-CQyfUZvq.d.ts} +48 -5
  43. package/dist/{text-truncate-j6X3z7Pv.js → text-truncate-DSuZECy0.js} +446 -94
  44. package/dist/{text-truncate-CxdzAnhS.cjs → text-truncate-I1XLWmRa.cjs} +522 -90
  45. package/dist/theme/server.d.cts +1 -2
  46. package/dist/theme/server.d.ts +1 -2
  47. package/dist/theme/server.js +0 -2
  48. package/dist/visuals/index.js +0 -1
  49. package/package.json +4 -3
  50. package/dist/field-sidebar-BXjvV7Cz.js.map +0 -1
  51. package/dist/field-sidebar-DWfJAJlx.d.ts.map +0 -1
  52. package/dist/field-sidebar-nwcE9LC4.d.cts.map +0 -1
  53. package/dist/id-registry.d.cts.map +0 -1
  54. package/dist/id-registry.d.ts.map +0 -1
  55. package/dist/id-registry.js.map +0 -1
  56. package/dist/index.d.cts.map +0 -1
  57. package/dist/index.d.ts.map +0 -1
  58. package/dist/index.js.map +0 -1
  59. package/dist/key-pad-menu-BQunU20e.js.map +0 -1
  60. package/dist/key-pad-menu-BsgJMjD4.d.ts.map +0 -1
  61. package/dist/key-pad-menu-DfZbeXhG.d.cts.map +0 -1
  62. package/dist/meta.d.cts.map +0 -1
  63. package/dist/meta.d.ts.map +0 -1
  64. package/dist/meta.js.map +0 -1
  65. package/dist/query.d.cts.map +0 -1
  66. package/dist/query.d.ts.map +0 -1
  67. package/dist/query.js.map +0 -1
  68. package/dist/text-truncate-BGr7bB_8.d.cts.map +0 -1
  69. package/dist/text-truncate-BGr7bB_8.d.ts.map +0 -1
  70. package/dist/text-truncate-j6X3z7Pv.js.map +0 -1
  71. package/dist/theme/server.d.cts.map +0 -1
  72. package/dist/theme/server.d.ts.map +0 -1
  73. package/dist/theme/server.js.map +0 -1
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: "Shell Components"
3
- description: "80 Shell layer components — props, examples, keyboard shortcuts."
4
- version: "1.9.0"
3
+ description: "86 Shell layer components — props, examples, keyboard shortcuts."
4
+ version: "1.12.0"
5
5
  generated: true
6
6
  ---
7
7
 
8
- # Shell Components (80)
8
+ # Shell Components (86)
9
9
 
10
10
  ## Navigation & Layout
11
11
 
@@ -38,6 +38,15 @@ generated: true
38
38
  | ------- | ----------- | -------- | ------- | --------------------------------------------------- |
39
39
  | `menus` | `MenuDef[]` | Yes | | 메뉴 정의 배열. { id, label, items: MenuItemDef[] } |
40
40
 
41
+ **Keyboard Shortcuts:**
42
+
43
+ | Keys | Action |
44
+ | ------------------- | -------------------------- |
45
+ | `← →` | 상위 메뉴 사이 포커스 이동 |
46
+ | `Enter / Space / ↓` | 메뉴 열기 |
47
+ | `↑ ↓` | 열린 메뉴 항목 이동 |
48
+ | `Escape` | 메뉴 닫고 트리거로 복귀 |
49
+
41
50
  ### MegaMenu
42
51
 
43
52
  > 메가 메뉴. Popover + CSS grid 멀티컬럼 + 카테고리 헤딩 + footer 슬롯.
@@ -45,13 +54,22 @@ generated: true
45
54
  **Import:** `import { MegaMenu } from "@reopt-ai/opt-ui"`
46
55
  **Dependencies:** popover (core)
47
56
 
48
- | Prop | Type | Required | Default | Description |
49
- | -------------- | ------------------- | -------- | ------- | ------------------ |
50
- | `menus` | `MegaMenuSection[]` | Yes | | 메뉴 섹션 배열 |
51
- | `columns` | `number` | | 3 | 그리드 컬럼 수 |
52
- | `footer` | `ReactNode` | | | 하단 footer 슬롯 |
53
- | `triggerLabel` | `string` | | "Menu" | 트리거 버튼 텍스트 |
54
- | `className` | `string` | | | 커스텀 CSS 클래스 |
57
+ | Prop | Type | Required | Default | Description |
58
+ | -------------- | ------------------- | -------- | ------- | ------------------------------------------- |
59
+ | `menus` | `MegaMenuSection[]` | Yes | | 메뉴 섹션 배열 |
60
+ | `columns` | `number` | | 3 | 그리드 컬럼 수 |
61
+ | `footer` | `ReactNode` | | | 하단 footer 슬롯 |
62
+ | `triggerLabel` | `string` | | "Menu" | 트리거 버튼 텍스트 |
63
+ | `aria-label` | `string` | | | 열린 메가 메뉴 탐색 영역의 접근 가능한 이름 |
64
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
65
+
66
+ **Keyboard Shortcuts:**
67
+
68
+ | Keys | Action |
69
+ | --------------- | -------------------------- |
70
+ | `Enter / Space` | 메가 메뉴 열기 |
71
+ | `Tab` | 메뉴 링크와 액션 사이 이동 |
72
+ | `Escape` | 메가 메뉴 닫기 |
55
73
 
56
74
  ### SidebarNav
57
75
 
@@ -165,6 +183,13 @@ import { AppShell } from "@reopt-ai/opt-ui";
165
183
  | `defaultTabId` | `string` | | | 기본 선택 탭 ID |
166
184
  | `className` | `string` | | | 커스텀 CSS 클래스 |
167
185
 
186
+ **Keyboard Shortcuts:**
187
+
188
+ | Keys | Action |
189
+ | ------------ | ------------------------------- |
190
+ | `↑ ↓` | 세로 탭 사이 이동 및 선택 |
191
+ | `Home / End` | 첫 번째 또는 마지막 탭으로 이동 |
192
+
168
193
  ### FaqAccordion
169
194
 
170
195
  > FAQ 질문/답변 아코디언. Composite + Disclosure 조합.
@@ -176,6 +201,13 @@ import { AppShell } from "@reopt-ai/opt-ui";
176
201
  | ------- | ----------- | -------- | ------- | --------------------------------------- |
177
202
  | `items` | `FaqItem[]` | Yes | | FAQ 항목 배열. { id, question, answer } |
178
203
 
204
+ **Keyboard Shortcuts:**
205
+
206
+ | Keys | Action |
207
+ | --------------- | --------------------- |
208
+ | `↑ ↓` | 질문 사이 포커스 이동 |
209
+ | `Enter / Space` | 답변 펼치기 또는 접기 |
210
+
179
211
  ### CommandPalette
180
212
 
181
213
  > Cmd+K 스타일 커맨드 팔레트. Dialog + Combobox + match-sorter 퍼지 검색.
@@ -183,17 +215,17 @@ import { AppShell } from "@reopt-ai/opt-ui";
183
215
  **Import:** `import { CommandPalette } from "@reopt-ai/opt-ui"`
184
216
  **Dependencies:** dialog (core), combobox (core), kbd (core)
185
217
 
186
- | Prop | Type | Required | Default | Description |
187
- | --------------- | -------------------------------------------- | -------- | ------- | ----------------------------------------------------- |
188
- | `commands` | `Omit<Command, "action">[]` | Yes | | 커맨드 목록. { id, label, group, shortcut? } |
189
- | `open` | `boolean` | Yes | | 열림 상태 |
190
- | `onOpenChange` | `(open: boolean) => void` | Yes | | 상태 변경 핸들러 |
191
- | `onSelect` | `(command: Omit<Command, 'action'>) => void` | | | 커맨드 선택 핸들러 |
192
- | `inline` | `boolean` | | false | true일 때 풀스크린 Dialog 대신 인라인 팝업으로 렌더링 |
193
- | `labels` | `CommandPaletteLabels` | | | title/description/input/list/empty/escape 문구 |
194
- | `footer` | `ReactNode` | | | 명령 목록 아래에 표시할 footer slot |
195
- | `empty` | `ReactNode` | | | 결과가 없을 때 표시할 empty slot |
196
- | `inputTrailing` | `ReactNode` | | | 검색 입력 우측 보조 콘텐츠 |
218
+ | Prop | Type | Required | Default | Description |
219
+ | --------------- | ----------------------------------------------- | -------- | ------- | ----------------------------------------------------- |
220
+ | `commands` | `Omit<CommandDef, "action">[]` | Yes | | 커맨드 목록. { id, label, group, shortcut? } |
221
+ | `open` | `boolean` | Yes | | 열림 상태 |
222
+ | `onOpenChange` | `(open: boolean) => void` | Yes | | 상태 변경 핸들러 |
223
+ | `onSelect` | `(command: Omit<CommandDef, "action">) => void` | | | 커맨드 선택 핸들러 |
224
+ | `inline` | `boolean` | | false | true일 때 풀스크린 Dialog 대신 인라인 팝업으로 렌더링 |
225
+ | `labels` | `CommandPaletteLabels` | | | title/description/input/list/empty/escape 문구 |
226
+ | `footer` | `ReactNode` | | | 명령 목록 아래에 표시할 footer slot |
227
+ | `empty` | `ReactNode` | | | 결과가 없을 때 표시할 empty slot |
228
+ | `inputTrailing` | `ReactNode` | | | 검색 입력 우측 보조 콘텐츠 |
197
229
 
198
230
  ### CommandPaletteTrigger
199
231
 
@@ -202,11 +234,11 @@ import { AppShell } from "@reopt-ai/opt-ui";
202
234
  **Import:** `import { CommandPaletteTrigger } from "@reopt-ai/opt-ui"`
203
235
  **Dependencies:** command-palette (shells)
204
236
 
205
- | Prop | Type | Required | Default | Description |
206
- | ---------- | -------------------------------------------- | -------- | ------- | -------------------------------------------------- |
207
- | `commands` | `Omit<Command, "action">[]` | Yes | | 커맨드 목록 |
208
- | `onSelect` | `(command: Omit<Command, 'action'>) => void` | | | 커맨드 선택 핸들러 |
209
- | `labels` | `CommandPaletteTriggerLabels` | | | 내부 CommandPalette에 전달할 title/input/list 문구 |
237
+ | Prop | Type | Required | Default | Description |
238
+ | ---------- | ----------------------------------------------- | -------- | ------- | -------------------------------------------------- |
239
+ | `commands` | `Omit<CommandDef, "action">[]` | Yes | | 커맨드 목록 |
240
+ | `onSelect` | `(command: Omit<CommandDef, "action">) => void` | | | 커맨드 선택 핸들러 |
241
+ | `labels` | `CommandPaletteTriggerLabels` | | | 내부 CommandPalette에 전달할 title/input/list 문구 |
210
242
 
211
243
  ### ProjectSwitcher
212
244
 
@@ -375,13 +407,22 @@ import { DataTable } from "@reopt-ai/opt-ui";
375
407
  **Import:** `import { TreeTable } from "@reopt-ai/opt-ui"`
376
408
  **Dependencies:** data-table (shells)
377
409
 
378
- | Prop | Type | Required | Default | Description |
379
- | ----------------- | -------------------- | -------- | ------- | ------------------ |
380
- | `data` | `TreeNode<T>[]` | Yes | | 트리 노드 배열 |
381
- | `columns` | `TreeColumnDef<T>[]` | Yes | | 컬럼 정의 |
382
- | `defaultExpanded` | `string[]` | | [] | 기본 펼침 노드 ID |
383
- | `indentSize` | `number` | | 24 | 들여쓰기 크기 (px) |
384
- | `className` | `string` | | | 커스텀 CSS 클래스 |
410
+ | Prop | Type | Required | Default | Description |
411
+ | ----------------- | ------------------------------- | -------- | ------- | ----------------------------------------------- |
412
+ | `data` | `TreeNode<T>[]` | Yes | | 트리 노드 배열 |
413
+ | `columns` | `TreeColumnDef<T>[]` | Yes | | 컬럼 정의 |
414
+ | `defaultExpanded` | `string[]` | | [] | 기본 펼침 노드 ID |
415
+ | `indentSize` | `number` | | 24 | 들여쓰기 크기 (px) |
416
+ | `getRowLabel` | `(node: TreeNode<T>) => string` | | | 행별 펼침/접기 컨트롤의 접근 가능한 이름 생성기 |
417
+ | `aria-label` | `string` | | | 표의 접근 가능한 이름 |
418
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
419
+
420
+ **Keyboard Shortcuts:**
421
+
422
+ | Keys | Action |
423
+ | --------------- | -------------------------- |
424
+ | `Tab` | 펼침/접기 컨트롤 사이 이동 |
425
+ | `Enter / Space` | 하위 행 펼치기 또는 접기 |
385
426
 
386
427
  ### DomainTable
387
428
 
@@ -434,15 +475,17 @@ import { DataTable } from "@reopt-ai/opt-ui";
434
475
  **Import:** `import { SummaryRow } from "@reopt-ai/opt-ui"`
435
476
  **Dependencies:** stat-card (core), skeleton (core)
436
477
 
437
- | Prop | Type | Required | Default | Description |
438
- | -------------------------- | -------------------------------- | -------- | ------- | -------------------------------- |
439
- | `stats` | `StatCardType[]` | Yes | | 통계 카드 배열 |
440
- | `columns` | `2 \| 3 \| 4` | | 4 | 컬럼 수 |
441
- | `onStatClick` | `(stat: StatCardType) => void` | | | 카드 클릭 핸들러 |
442
- | `formatValue` | `(stat: StatCardType) => string` | | | 표시 커스텀 포맷 함수 |
443
- | `durationFractionDigits` | `number` | | 1 | duration 포맷 소수점 자리수 |
444
- | `percentageFractionDigits` | `number` | | 1 | percentage 포맷 소수점 자리수 |
445
- | `loading` | `boolean` | | false | 로딩스켈레톤 표시 |
478
+ | Prop | Type | Required | Default | Description |
479
+ | -------------------------- | -------------------------------- | -------- | ------- | ------------------------------------------------------- |
480
+ | `stats` | `StatCardType[]` | Yes | | 통계 카드 배열 |
481
+ | `columns` | `2 \| 3 \| 4 \| 5 \| 6` | | 4 | 컬럼 수 |
482
+ | `onStatClick` | `(stat: StatCardType) => void` | | | 카드 클릭 핸들러. 지정 시 카드 자체가 버튼으로 렌더된다 |
483
+ | `selectedStatId` | `string` | | | 선택 가능한 행에서 현재 뷰를 이끄는 카드 id |
484
+ | `size` | `"sm" \| "md"` | | "md" | 카드 밀도. 헤더 스트립에는 sm |
485
+ | `formatValue` | `(stat: StatCardType) => string` | | | 표시 커스텀 포맷 함수 |
486
+ | `durationFractionDigits` | `number` | | 1 | duration 포맷 소수점 자리수 |
487
+ | `percentageFractionDigits` | `number` | | 1 | percentage 포맷 시 소수점 자리수 |
488
+ | `loading` | `boolean` | | false | 로딩 시 스켈레톤 표시 |
446
489
 
447
490
  ### CodeSnippetViewer
448
491
 
@@ -590,13 +633,13 @@ import { DataTable } from "@reopt-ai/opt-ui";
590
633
  **Import:** `import { KanbanBoard } from "@reopt-ai/opt-ui"`
591
634
  **Dependencies:** scroll-area (core)
592
635
 
593
- | Prop | Type | Required | Default | Description |
594
- | -------------- | ------------------------------------------- | -------- | ------- | -------------------------------- |
595
- | `columns` | `KanbanColumn<T>[]` | Yes | | 컬럼 목록 (각 컬럼에 items 배열) |
596
- | `onDragEnd` | `(itemId, fromCol, toCol, toIndex) => void` | Yes | | 드래그 완료 콜백 |
597
- | `renderCard` | `(item: T) => ReactNode` | Yes | | 카드 렌더링 함수 |
598
- | `keyExtractor` | `(item: T) => string` | Yes | | 항목 키 추출기 |
599
- | `className` | `string` | | | 커스텀 CSS 클래스 |
636
+ | Prop | Type | Required | Default | Description |
637
+ | -------------- | ------------------------------------------------------------------------------------- | -------- | ------- | -------------------------------- |
638
+ | `columns` | `KanbanColumn<T>[]` | Yes | | 컬럼 목록 (각 컬럼에 items 배열) |
639
+ | `onDragEnd` | `(itemId: string, fromColumnId: string, toColumnId: string, toIndex: number) => void` | Yes | | 드래그 완료 콜백 |
640
+ | `renderCard` | `(item: T) => ReactNode` | Yes | | 카드 렌더링 함수 |
641
+ | `keyExtractor` | `(item: T) => string` | Yes | | 항목 키 추출기 |
642
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
600
643
 
601
644
  ### AuditLog
602
645
 
@@ -682,15 +725,15 @@ import { SearchCombobox } from "@reopt-ai/opt-ui";
682
725
  **Import:** `import { AsyncCombobox } from "@reopt-ai/opt-ui"`
683
726
  **Dependencies:** combobox (core), spinner (core)
684
727
 
685
- | Prop | Type | Required | Default | Description |
686
- | ------------- | ---------------------------------- | -------- | --------- | ---------------------------------------- |
687
- | `onSearch` | `(q: string) => Promise<string[]>` | Yes | | 검색 콜백 |
688
- | `debounceMs` | `number` | | 300 | 디바운스 ms |
689
- | `minChars` | `number` | | 1 | 최소 검색 글자 수 |
690
- | `placeholder` | `string` | | "Search…" | 플레이스홀더 |
691
- | `onSelect` | `(value: string) => void` | | | 선택 콜백 |
692
- | `labels` | `AsyncComboboxLabels` | | | input/loading/noResults/placeholder 문구 |
693
- | `loadingText` | `string` | | | 로딩 문구. labels.loading 사용 권장 |
728
+ | Prop | Type | Required | Default | Description |
729
+ | ------------- | -------------------------------------- | -------- | --------- | ----------------------------------------------------------------------------- |
730
+ | `onSearch` | `(query: string) => Promise<string[]>` | Yes | | 검색 콜백 |
731
+ | `debounceMs` | `number` | | 300 | 디바운스 ms |
732
+ | `minChars` | `number` | | 1 | 최소 검색 글자 수 |
733
+ | `placeholder` | `string` | | "Search…" | 플레이스홀더 **⚠️ deprecated since 1.9.0 — use `labels.placeholder` instead** |
734
+ | `onSelect` | `(value: string) => void` | | | 선택 콜백 |
735
+ | `labels` | `AsyncComboboxLabels` | | | input/loading/noResults/placeholder 문구 |
736
+ | `loadingText` | `string` | | | 로딩 문구 **⚠️ deprecated since 1.9.0 — use `labels.loading` instead** |
694
737
 
695
738
  ### StatusSelect
696
739
 
@@ -727,11 +770,11 @@ import { SearchCombobox } from "@reopt-ai/opt-ui";
727
770
  **Import:** `import { FilterBar } from "@reopt-ai/opt-ui"`
728
771
  **Dependencies:** select (core), input (core), button (core), switch (core), checkbox (core), date-range-picker (core)
729
772
 
730
- | Prop | Type | Required | Default | Description |
731
- | ---------------- | ------------------------------------------------------- | -------- | ------- | ----------------------------------------------------- |
732
- | `filters` | `FilterGroupDef[]` | Yes | | 필터 그룹 배열. { id, label, type, options?, value? } |
733
- | `onFilterChange` | `(filterId: string, value: string \| string[]) => void` | | | 필터 변경 핸들러 |
734
- | `onClearAll` | `() => void` | | | 모든 필터 초기화 핸들러 |
773
+ | Prop | Type | Required | Default | Description |
774
+ | ---------------- | ------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------- |
775
+ | `filters` | `FilterGroupDef[]` | Yes | | 필터 그룹 배열. { id, label, type, options?, value? } |
776
+ | `onFilterChange` | `(filterId: string, value: string \| string[] \| boolean) => void` | | | 필터 변경 핸들러 |
777
+ | `onClearAll` | `() => void` | | | 모든 필터 초기화 핸들러 |
735
778
 
736
779
  **Examples:**
737
780
 
@@ -919,15 +962,15 @@ const fields = [
919
962
  **Import:** `import { AuthForm } from "@reopt-ai/opt-ui"`
920
963
  **Dependencies:** form (core)
921
964
 
922
- | Prop | Type | Required | Default | Description |
923
- | ------------------- | ---------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------- |
924
- | `defaultMode` | `"login" \| "signup"` | | "login" | 초기 모드 (비제어) |
925
- | `mode` | `"login" \| "signup"` | | | 제어 모드: 현재 모드 |
926
- | `onModeChange` | `(mode: "login" \| "signup") => void` | | | 모드 변경 핸들러 |
927
- | `showRememberMe` | `boolean` | | true | 로그인 모드에서 '로그인 상태 유지' 표시 여부 |
928
- | `minPasswordLength` | `number` | | 8 | 비밀번호 최소 길이 |
929
- | `onSubmit` | `(values: { email, password, confirmPassword?, rememberMe?, mode }) => void` | | | 제출 핸들러 |
930
- | `labels` | `AuthFormLabels` | | | i18n용 라벨 오버라이드 |
965
+ | Prop | Type | Required | Default | Description |
966
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------- |
967
+ | `defaultMode` | `"login" \| "signup"` | | "login" | 초기 모드 (비제어) |
968
+ | `mode` | `"login" \| "signup"` | | | 제어 모드: 현재 모드 |
969
+ | `onModeChange` | `(mode: "login" \| "signup") => void` | | | 모드 변경 핸들러 |
970
+ | `showRememberMe` | `boolean` | | true | 로그인 모드에서 '로그인 상태 유지' 표시 여부 |
971
+ | `minPasswordLength` | `number` | | 8 | 비밀번호 최소 길이 |
972
+ | `onSubmit` | `(values: { email: string; password: string; confirmPassword?: string; rememberMe?: boolean; mode: "login" \| "signup" }) => void` | | | 제출 핸들러 |
973
+ | `labels` | `AuthFormLabels` | | | i18n용 라벨 오버라이드 |
931
974
 
932
975
  ### DynamicFieldForm
933
976
 
@@ -953,17 +996,17 @@ const fields = [
953
996
  **Import:** `import { FileUploadForm } from "@reopt-ai/opt-ui"`
954
997
  **Dependencies:** form (core)
955
998
 
956
- | Prop | Type | Required | Default | Description |
957
- | ----------------- | ------------------------------------------------ | -------- | ------------------------- | ----------------------------------------- |
958
- | `accept` | `string` | | "image/*,.pdf,.doc,.docx" | 허용 파일 타입 |
959
- | `showPreview` | `boolean` | | true | 이미지 미리보기 표시 |
960
- | `showFileInfo` | `boolean` | | true | 파일 정보 표시 |
961
- | `showDescription` | `boolean` | | true | 설명 텍스트영역 표시 |
962
- | `maxFileSize` | `number` | | | 최대 파일 크기 (bytes) |
963
- | `onSubmit` | `(values: { title, description, file }) => void` | | | 제출 핸들러 |
964
- | `labels` | `FileUploadFormLabels` | | | i18n용 라벨 오버라이드 |
965
- | `onPreview` | `(file: File) => void` | | | 파일 선택 후 프리뷰 콜백 |
966
- | `columnMapping` | `ReactNode` | | | CSV 컬럼 매핑 UI 슬롯 (파일 선택 후 표시) |
999
+ | Prop | Type | Required | Default | Description |
1000
+ | ----------------- | ------------------------------------------------------------------------------ | -------- | ------------------------- | ----------------------------------------- |
1001
+ | `accept` | `string` | | "image/*,.pdf,.doc,.docx" | 허용 파일 타입 |
1002
+ | `showPreview` | `boolean` | | true | 이미지 미리보기 표시 |
1003
+ | `showFileInfo` | `boolean` | | true | 파일 정보 표시 |
1004
+ | `showDescription` | `boolean` | | true | 설명 텍스트영역 표시 |
1005
+ | `maxFileSize` | `number` | | | 최대 파일 크기 (bytes) |
1006
+ | `onSubmit` | `(values: { title: string; description: string; file: File \| null }) => void` | | | 제출 핸들러 |
1007
+ | `labels` | `FileUploadFormLabels` | | | i18n용 라벨 오버라이드 |
1008
+ | `onPreview` | `(file: File) => void` | | | 파일 선택 후 프리뷰 콜백 |
1009
+ | `columnMapping` | `ReactNode` | | | CSV 컬럼 매핑 UI 슬롯 (파일 선택 후 표시) |
967
1010
 
968
1011
  ### WizardForm
969
1012
 
@@ -1083,12 +1126,12 @@ const fields = [
1083
1126
  **Import:** `import { DataImportWizard } from "@reopt-ai/opt-ui"`
1084
1127
  **Dependencies:** button (core)
1085
1128
 
1086
- | Prop | Type | Required | Default | Description |
1087
- | ----------------- | ------------------------- | -------- | ------- | ------------------- |
1088
- | `fields` | `ImportFieldDef[]` | Yes | | 매핑 대상 필드 목록 |
1089
- | `onImport` | `(mapping, data) => void` | Yes | | 임포트 확정 콜백 |
1090
- | `acceptedFormats` | `string` | | ".csv" | 허용 파일 형식 |
1091
- | `className` | `string` | | | 커스텀 CSS 클래스 |
1129
+ | Prop | Type | Required | Default | Description |
1130
+ | ----------------- | ------------------------------------------------------------- | -------- | ------- | ------------------- |
1131
+ | `fields` | `ImportFieldDef[]` | Yes | | 매핑 대상 필드 목록 |
1132
+ | `onImport` | `(mapping: Record<string, string>, data: string[][]) => void` | Yes | | 임포트 확정 콜백 |
1133
+ | `acceptedFormats` | `string` | | ".csv" | 허용 파일 형식 |
1134
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
1092
1135
 
1093
1136
  ## Analytics
1094
1137
 
@@ -1215,16 +1258,16 @@ const fields = [
1215
1258
  **Import:** `import { ReportBuilder } from "@reopt-ai/opt-ui"`
1216
1259
  **Dependencies:** button (core), input (core)
1217
1260
 
1218
- | Prop | Type | Required | Default | Description |
1219
- | ------------- | ------------------------------------------------------------------ | -------- | ------- | ----------------------------------- |
1220
- | `chartTypes` | `ChartTypeDef[]` | | | 차트 타입 그리드 (기본 9종 제공) |
1221
- | `dataSources` | `DataSourceDef[]` | | | 데이터 소스 드롭다운 옵션 |
1222
- | `configForm` | `ReactNode` | | | 차트별 데이터 설정 폼 슬롯 (step 2) |
1223
- | `styleForm` | `ReactNode` | | | 차트별 스타일 설정 폼 슬롯 (step 3) |
1224
- | `preview` | `ReactNode` | | | 차트 미리보기 슬롯 (step 4) |
1225
- | `onSave` | `(report: { name, description, chartType, dataSourceId }) => void` | | | 저장 콜백 |
1226
- | `onCancel` | `() => void` | | | 취소 콜백 |
1227
- | `labels` | `ReportBuilderLabels` | | | UI 텍스트 커스터마이징 |
1261
+ | Prop | Type | Required | Default | Description |
1262
+ | ------------- | ------------------------------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------- |
1263
+ | `chartTypes` | `ChartTypeDef[]` | | | 차트 타입 그리드 (기본 9종 제공) |
1264
+ | `dataSources` | `DataSourceDef[]` | | | 데이터 소스 드롭다운 옵션 |
1265
+ | `configForm` | `ReactNode` | | | 차트별 데이터 설정 폼 슬롯 (step 2) |
1266
+ | `styleForm` | `ReactNode` | | | 차트별 스타일 설정 폼 슬롯 (step 3) |
1267
+ | `preview` | `ReactNode` | | | 차트 미리보기 슬롯 (step 4) |
1268
+ | `onSave` | `(report: { name: string; description: string; chartType: ReportBuilderChartType; dataSourceId: string }) => void` | | | 저장 콜백 |
1269
+ | `onCancel` | `() => void` | | | 취소 콜백 |
1270
+ | `labels` | `ReportBuilderLabels` | | | UI 텍스트 커스터마이징 |
1228
1271
 
1229
1272
  ## Widgets & Reports
1230
1273
 
@@ -1323,20 +1366,26 @@ const fields = [
1323
1366
 
1324
1367
  ## Other
1325
1368
 
1326
- | Component | Description | Key Exports |
1327
- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
1328
- | PageAside | Sticky 페이지 사이드 aside chrome. 고정 너비 + header/body/footer 3-slot. | `PageAside` |
1329
- | FailureList | 실패 목록 패널. severity별 색상 강조, 그룹핑, 액션 슬롯을 지원합니다. | `FailureList` |
1330
- | KeyValueEditor | 키-값 쌍 편집기. 동적 행 추가/삭제, 비밀값 토글, 유효성 검사를 지원합니다. | `KeyValueEditor` |
1331
- | AuditTimeline | 변경 이력 타임라인. 액션별 색상 코딩 + 확장 가능한 diff 뷰. | `AuditTimeline` |
1332
- | ChatSidebar | AI 채팅 사이드바. 대화 목록, 검색, 대화 버튼. | `ChatSidebar` |
1333
- | ChatInput | 채팅 입력 컴포넌트. 자동 리사이즈 textarea, 파일 첨부, 모델/스타일 Select. | `ChatInput` |
1334
- | ChatMessageList | 채팅 메시지 목록. 역할별 말풍선, 타이핑 인디케이터, 자동 스크롤. | `ChatMessageList` |
1335
- | TimeRangeControl | date math(now-7d, now/d) 기반 시간 범위 컨트롤. quick select, 프리셋/최근 사용, 명시적 Update, 자동 갱신, 창 이동·확대/축소 버튼을 제공합니다. | `TimeRangeControl`, `DEFAULT_TIME_PRESETS` |
1336
- | TimeSeriesPanel | 시간 범위 컨트롤과 시계열 차트를 단위로 묶은 패널. 드래그 줌과 줌 히스토리(되돌리기), 범례 토글을 포함합니다. | `TimeSeriesPanel` |
1337
- | LogTable | 계속 도착하는 로그용 윈도잉 테이블. 컬럼 정의 기반, 상단 삽입 시 스크롤 위치 보존, follow 상태 보고, 셀 값 즉시 필터, 밀도·정렬을 지원합니다. | `LogTable` |
1338
- | QueryBar | 검색과 필터를 입력으로 합친 쿼리 바. field:value, -부정, (a or b), 비교 연산, 필드·값 자동완성, 절(clause) 칩을 지원합니다. | `QueryBar` |
1339
- | FieldSidebar | 데이터에 어떤 필드가 있고 필드가 무슨 값을 갖는지 보여주는 사이드바. 분포 막대, 컬럼으로 승격, 값 기준 포함/제외 필터를 제공합니다. | `FieldSidebar` |
1369
+ | Component | Description | Key Exports |
1370
+ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
1371
+ | PageAside | Sticky 페이지 사이드 aside chrome. 고정 너비 + header/body/footer 3-slot. | `PageAside` |
1372
+ | FailureList | 실패 목록 패널. severity별 색상 강조, 그룹핑, 액션 슬롯을 지원합니다. | `FailureList` |
1373
+ | KeyValueEditor | 키-값 쌍 편집기. 동적 행 추가/삭제, 비밀값 토글, 유효성 검사를 지원합니다. | `KeyValueEditor` |
1374
+ | EventTimeline | 이벤트를 순서로 읽히게 하는 타임라인. 인접 이벤트 사이의 경과 시간을 라벨링하고, 속성 페이로드를 제자리에서 펼치며, 세션 단위 그룹핑을 지원한다. | `EventTimeline` |
1375
+ | ScoreBreakdown | 합성 점수를 축별로 분해해 보여준다. 총점과 함께 축의 값·가중치·의미를 노출해 '43'을 판정이 아니라 발견으로 만든다. | `ScoreBreakdown` |
1376
+ | Flyout | 목록을 화면에 레코드를 옆에서 보여주는 상세 패널. 모달이 아니다 — 포커스 트랩·aria-modal·inert 없이 Escape로 닫고 포커스를 되돌린다. | `Flyout` |
1377
+ | AuditTimeline | 변경 이력 타임라인. 액션별 색상 코딩 + 확장 가능한 diff 뷰. | `AuditTimeline` |
1378
+ | ChatSidebar | AI 채팅 사이드바. 대화 목록, 검색, 대화 버튼. | `ChatSidebar` |
1379
+ | ChatInput | 채팅 입력 컴포넌트. 자동 리사이즈 textarea, 파일 첨부, 모델/스타일 Select. | `ChatInput` |
1380
+ | ChatMessageList | 채팅 메시지 목록. 역할별 말풍선, 타이핑 인디케이터, 자동 스크롤. | `ChatMessageList` |
1381
+ | TimeRangeControl | date math(now-7d, now/d) 기반 시간 범위 컨트롤. quick select, 프리셋/최근 사용, 명시적 Update, 자동 갱신, 이동·확대/축소 버튼을 제공합니다. | `TimeRangeControl`, `DEFAULT_TIME_PRESETS` |
1382
+ | TimeSeriesPanel | 시간 범위 컨트롤과 시계열 차트를 단위로 묶은 패널. 드래그 줌과 히스토리(되돌리기), 범례 토글을 포함합니다. | `TimeSeriesPanel` |
1383
+ | LogTable | 계속 도착하는 로그용 윈도잉 테이블. 컬럼 정의 기반, 상단 삽입 시 스크롤 위치 보존, follow 상태 보고, 셀 값 즉시 필터, 밀도·정렬을 지원합니다. | `LogTable` |
1384
+ | QueryBar | 검색과 필터를 한 입력으로 합친 쿼리 바. field:value, -부정, (a or b), 비교 연산, 필드·값 자동완성, 절(clause) 칩을 지원합니다. | `QueryBar` |
1385
+ | FieldSidebar | 데이터에 어떤 필드가 있고 각 필드가 무슨 값을 갖는지 보여주는 사이드바. 값 분포 막대, 컬럼으로 승격, 값 기준 포함/제외 필터를 제공합니다. | `FieldSidebar` |
1386
+ | InspectorLayout | 목록과 인스펙터의 2-pane 레이아웃. 넓으면 밀어내고(push) 좁으면 덮으며(overlay), 닫을 때 포커스를 열었던 자리로 되돌립니다. | `InspectorLayout` |
1387
+ | QueryFilterBar | QueryBar와 필터 버튼이 하나의 Query를 공유합니다. 버튼은 상태를 갖지 않고 Query를 읽어 활성 여부를 계산합니다. | `QueryFilterBar`, `hasActiveQuery` |
1388
+ | CatalogFrame | 카탈로그 목록의 공통 뼈대. 헤더·통계·고지·필터·인스펙터·페이지네이션·일괄 작업과 빈/에러 상태를 담고, 필터나 페이지가 바뀌면 선택을 비웁니다. | `CatalogFrame`, `CatalogRowActions`, `CatalogCellControls` |
1340
1389
 
1341
1390
  ### PageAside
1342
1391
 
@@ -1400,6 +1449,71 @@ const fields = [
1400
1449
  | ----- | ------------------ |
1401
1450
  | `Tab` | 키/값 필드 간 이동 |
1402
1451
 
1452
+ ### EventTimeline
1453
+
1454
+ > 이벤트를 순서로 읽히게 하는 타임라인. 인접 이벤트 사이의 경과 시간을 라벨링하고, 속성 페이로드를 제자리에서 펼치며, 세션 단위 그룹핑을 지원한다.
1455
+
1456
+ **Import:** `import { EventTimeline } from "@reopt-ai/opt-ui"`
1457
+
1458
+ | Prop | Type | Required | Default | Description |
1459
+ | -------------- | ----------------------------------- | -------- | ------- | ----------------------------------------------------------------------------- |
1460
+ | `items` | `EventTimelineItem[]` | | | 평면 목록. groups가 있으면 무시된다 |
1461
+ | `groups` | `EventTimelineGroup[]` | | | 그룹(주로 세션) 단위 목록. 접기/펼치기와 그룹 요약을 제공 |
1462
+ | `showGaps` | `boolean` | | true | 인접 이벤트 사이 경과 시간 표시. 체크아웃 직전 4분 정지 같은 것이 발견이 된다 |
1463
+ | `order` | `"desc" \| "asc"` | | "desc" | 전달된 items의 정렬 방향. 경과 시간 계산 기준 |
1464
+ | `minGapMs` | `number` | | 1000 | 이 값 미만의 간격은 라벨을 생략 |
1465
+ | `loading` | `boolean` | | false | 스켈레톤 표시 |
1466
+ | `hasMore` | `boolean` | | false | 더 불러올 항목 존재 |
1467
+ | `onLoadMore` | `() => void` | | | 더 보기 핸들러 |
1468
+ | `onItemSelect` | `(item: EventTimelineItem) => void` | | | 이벤트 헤드라인 클릭 핸들러 |
1469
+ | `locale` | `string` | | | 경과 시간 포맷 로케일 |
1470
+ | `labels` | `EventTimelineLabels` | | | 문구 오버라이드 |
1471
+
1472
+ ### ScoreBreakdown
1473
+
1474
+ > 합성 점수를 축별로 분해해 보여준다. 총점과 함께 각 축의 값·가중치·의미를 노출해 '43'을 판정이 아니라 발견으로 만든다.
1475
+
1476
+ **Import:** `import { ScoreBreakdown } from "@reopt-ai/opt-ui"`
1477
+
1478
+ | Prop | Type | Required | Default | Description |
1479
+ | --------- | ---------------------- | -------- | ------- | -------------------------------------------------- |
1480
+ | `score` | `number` | Yes | | 총점 |
1481
+ | `max` | `number` | | 100 | 총점 상한 |
1482
+ | `axes` | `ScoreAxis[]` | Yes | | 기여 축 배열. { id, label, value, hint?, weight? } |
1483
+ | `bands` | `ScoreBand[]` | | | 점수 구간 이름과 색. { min, label, tone? } |
1484
+ | `formula` | `ReactNode` | | | 총점 산출식 설명 한 줄 |
1485
+ | `loading` | `boolean` | | false | 스켈레톤 표시 |
1486
+ | `labels` | `ScoreBreakdownLabels` | | | 문구 오버라이드 |
1487
+
1488
+ ### Flyout
1489
+
1490
+ > 목록을 화면에 둔 채 레코드를 옆에서 보여주는 상세 패널. 모달이 아니다 — 포커스 트랩·aria-modal·inert 없이 Escape로 닫고 포커스를 되돌린다.
1491
+
1492
+ **Import:** `import { Flyout } from "@reopt-ai/opt-ui"`
1493
+
1494
+ | Prop | Type | Required | Default | Description |
1495
+ | --------------------- | ----------------------- | -------- | --------- | ----------------------------------------------------------------------------------- |
1496
+ | `open` | `boolean` | Yes | | 열림 상태 |
1497
+ | `onClose` | `() => void` | Yes | | 닫기 핸들러 |
1498
+ | `title` | `ReactNode` | | | 패널 제목 |
1499
+ | `description` | `ReactNode` | | | 제목 아래 한 줄 설명 |
1500
+ | `type` | `"overlay" \| "inline"` | | "overlay" | overlay는 페이지 위에 띄우고, inline은 aside로 렌더해 배치를 부모 레이아웃에 맡긴다 |
1501
+ | `side` | `"right" \| "left"` | | "right" | overlay일 때 붙는 방향 |
1502
+ | `size` | `"sm" \| "md" \| "lg"` | | "md" | 패널 너비 |
1503
+ | `actions` | `ReactNode` | | | 닫기 버튼 앞 컨트롤 |
1504
+ | `footer` | `ReactNode` | | | 하단 고정 영역 |
1505
+ | `scrim` | `boolean` | | false | 뒤 페이지를 어둡게. 기본 off — 목록이 계속 읽혀야 한다 |
1506
+ | `closeOnOutsideClick` | `boolean` | | true | 바깥 클릭 시 닫기 (overlay 전용) |
1507
+ | `hideCloseButton` | `boolean` | | false | 닫기 버튼 숨김 |
1508
+ | `labels` | `FlyoutLabels` | | | 문구 오버라이드 |
1509
+ | `children` | `ReactNode` | Yes | | 패널 본문 |
1510
+
1511
+ **Keyboard Shortcuts:**
1512
+
1513
+ | Keys | Action |
1514
+ | -------- | ----------------------------------- |
1515
+ | `Escape` | 패널 닫고 여는 컨트롤로 포커스 복귀 |
1516
+
1403
1517
  ### AuditTimeline
1404
1518
 
1405
1519
  > 변경 이력 타임라인. 액션별 색상 코딩 + 확장 가능한 diff 뷰.
@@ -1524,16 +1638,19 @@ const messages = [
1524
1638
 
1525
1639
  **Import:** `import { TimeSeriesPanel } from "@reopt-ai/opt-ui"`
1526
1640
 
1527
- | Prop | Type | Required | Default | Description |
1528
- | ------------------ | ---------------------------- | -------- | ------- | --------------------------------------------- |
1529
- | `data` | `TimeSeriesPoint[]` | Yes | | 시계열 데이터 |
1530
- | `series` | `TimeSeriesDef[]` | Yes | | 시리즈 정의 |
1531
- | `range` | `TimeRange` | Yes | | 조회 구간 — 차트 축도 여기에 고정됩니다 |
1532
- | `onRangeChange` | `(range: TimeRange) => void` | Yes | | 드래그 줌·컨트롤 변경으로 구간이 바뀔 때 호출 |
1533
- | `showRangeControl` | `boolean` | | true | 헤더에 TimeRangeControl 렌더 |
1534
- | `toggleableLegend` | `boolean` | | false | 범례 클릭으로 시리즈 숨김 |
1535
- | `annotations` | `TimeSeriesAnnotation[]` | | | 시간축 마커/구간 |
1536
- | `height` | `number` | | 280 | 차트 높이 |
1641
+ | Prop | Type | Required | Default | Description |
1642
+ | ------------------ | ---------------------------- | -------- | ------- | --------------------------------------------------------- |
1643
+ | `title` | `ReactNode` | | | 패널 제목. aria-label이 없으면 region 이름으로 연결됩니다 |
1644
+ | `description` | `ReactNode` | | | 패널 보조 설명 |
1645
+ | `data` | `TimeSeriesPoint[]` | Yes | | 시계열 데이터 |
1646
+ | `series` | `TimeSeriesDef[]` | Yes | | 시리즈 정의 |
1647
+ | `range` | `TimeRange` | Yes | | 조회 구간 — 차트 축도 여기에 고정됩니다 |
1648
+ | `onRangeChange` | `(range: TimeRange) => void` | Yes | | 드래그 줌·컨트롤 변경으로 구간이 바뀔 때 호출 |
1649
+ | `showRangeControl` | `boolean` | | true | 헤더에 TimeRangeControl 렌더 |
1650
+ | `toggleableLegend` | `boolean` | | false | 범례 클릭으로 시리즈 숨김 |
1651
+ | `annotations` | `TimeSeriesAnnotation[]` | | | 시간축 마커/구간 |
1652
+ | `height` | `number` | | 280 | 차트 높이 |
1653
+ | `aria-label` | `string` | | | 제목 대신 사용할 패널 region의 접근 가능한 이름 |
1537
1654
 
1538
1655
  ### LogTable
1539
1656
 
@@ -1588,3 +1705,97 @@ const messages = [
1588
1705
  | `sampledRows` | `number` | | | 집계 대상 행 수 (분모) |
1589
1706
  | `onToggleColumn` | `(field: string, next: boolean) => void` | | | 컬럼 추가/제거 |
1590
1707
  | `onFilter` | `(field: string, value: string, intent: "include" \| "exclude") => void` | | | 값 기준 필터 |
1708
+
1709
+ ### InspectorLayout
1710
+
1711
+ > 목록과 인스펙터의 2-pane 레이아웃. 넓으면 밀어내고(push) 좁으면 덮으며(overlay), 닫을 때 포커스를 열었던 자리로 되돌립니다.
1712
+
1713
+ **Import:** `import { InspectorLayout } from "@reopt-ai/opt-ui"`
1714
+
1715
+ | Prop | Type | Required | Default | Description |
1716
+ | ------------- | ----------------------- | -------- | ------- | ---------------------------------------------- |
1717
+ | `children` | `ReactNode` | Yes | | 목록. 인스펙터가 열려도 마운트와 스크롤을 유지 |
1718
+ | `inspector` | `ReactNode` | | | 인스펙터 내용. 닫혀 있으면 렌더하지 않음 |
1719
+ | `open` | `boolean` | Yes | | 열림 |
1720
+ | `onClose` | `() => void` | Yes | | 닫기 |
1721
+ | `title` | `ReactNode` | | | 인스펙터 제목 |
1722
+ | `description` | `ReactNode` | | | 제목 아래 한 줄 |
1723
+ | `actions` | `ReactNode` | | | 닫기 버튼 옆 컨트롤 |
1724
+ | `footer` | `ReactNode` | | | 인스펙터 하단 |
1725
+ | `breakpoint` | `"lg" \| "xl" \| "2xl"` | | "xl" | 이 폭 이상이면 push |
1726
+ | `width` | `"sm" \| "md" \| "lg"` | | "md" | push 레이아웃에서의 인스펙터 폭 |
1727
+
1728
+ ### QueryFilterBar
1729
+
1730
+ > QueryBar와 필터 버튼이 하나의 Query를 공유합니다. 버튼은 상태를 갖지 않고 Query를 읽어 활성 여부를 계산합니다.
1731
+
1732
+ **Import:** `import { QueryFilterBar } from "@reopt-ai/opt-ui"`
1733
+
1734
+ | Prop | Type | Required | Default | Description |
1735
+ | ---------------- | ------------------------ | -------- | ------- | -------------------------------------------------------------------------- |
1736
+ | `value` | `Query` | Yes | | 필터 상태 전부 |
1737
+ | `onChange` | `(query: Query) => void` | Yes | | Query 변경 |
1738
+ | `filters` | `QueryFilterDef[]` | Yes | | 필터 컨트롤 정의 (is / field_value_selection / field_value_toggle) |
1739
+ | `fields` | `QueryField[]` | | | 텍스트 입력 자동완성 |
1740
+ | `actions` | `ReactNode` | | | 필터 행 끝 슬롯 |
1741
+ | `showClauses` | `boolean` | | true | 절을 제거 가능한 칩으로 표시 |
1742
+ | `live` | `boolean` | | false | 매 입력마다 커밋 |
1743
+ | `disabled` | `boolean` | | false | 전체 비활성 |
1744
+ | `queryBarLabels` | `QueryBarLabels` | | | QueryBar로 통과되는 나머지 문구. placeholder/ariaLabel은 labels가 이깁니다 |
1745
+
1746
+ ### CatalogFrame
1747
+
1748
+ > 카탈로그 목록의 공통 뼈대. 헤더·통계·고지·필터·인스펙터·페이지네이션·일괄 작업과 빈/에러 상태를 담고, 필터나 페이지가 바뀌면 선택을 비웁니다.
1749
+
1750
+ **Import:** `import { CatalogFrame } from "@reopt-ai/opt-ui"`
1751
+
1752
+ **CatalogFrame:**
1753
+
1754
+ | Prop | Type | Required | Default | Description |
1755
+ | ---------------------- | ------------------------------ | -------- | ------- | ----------------------------------------------------------------- |
1756
+ | `children` | `ReactNode` | Yes | | 테이블. 빈/에러 상태에서는 대체됨 |
1757
+ | `isEmpty` | `boolean` | Yes | | 테이블이 0행인지 |
1758
+ | `query` | `Query` | Yes | | 필터 상태 |
1759
+ | `onQueryChange` | `(query: Query) => void` | Yes | | Query 변경 |
1760
+ | `filters` | `QueryFilterDef[]` | | | 필터 정의 |
1761
+ | `stats` | `StatCardType[]` | | | 통계 카드 |
1762
+ | `onStatClick` | `(stat: StatCardType) => void` | | | 카드 클릭 = 필터 |
1763
+ | `notice` | `ReactNode` | | | 목록 위 고지 |
1764
+ | `emptyActions` | `ReactNode` | | | 필터 없는 빈 상태의 다음 행동 (필터된 빈 상태는 필터 지우기 유지) |
1765
+ | `header` | `ReactNode` | | | 헤더 슬롯 |
1766
+ | `actions` | `ReactNode` | | | 액션 슬롯 |
1767
+ | `toolbar` | `ReactNode` | | | 통계와 필터 사이 컨트롤 (스코프 세그먼트 등) |
1768
+ | `inspector` | `ReactNode` | | | 인스펙터 내용 |
1769
+ | `inspectorOpen` | `boolean` | Yes | | 인스펙터 열림 |
1770
+ | `onInspectorClose` | `() => void` | Yes | | 인스펙터 닫기 |
1771
+ | `inspectorTitle` | `ReactNode` | | | 인스펙터 제목 |
1772
+ | `inspectorDescription` | `ReactNode` | | | 인스펙터 설명 |
1773
+ | `inspectorActions` | `ReactNode` | | | 인스펙터 헤더 컨트롤 |
1774
+ | `inspectorFooter` | `ReactNode` | | | 인스펙터 하단 |
1775
+ | `inspectorWidth` | `"sm" \| "md" \| "lg"` | | | push 레이아웃 폭 |
1776
+ | `page` | `number` | | 1 | 현재 페이지 |
1777
+ | `pageSize` | `number` | | 50 | 페이지 크기 |
1778
+ | `totalCount` | `number` | | | 필터 반영 총 개수 |
1779
+ | `onPageChange` | `(page: number) => void` | | | 페이지 변경 |
1780
+ | `selectedKeys` | `string[]` | | | 선택된 행 |
1781
+ | `onSelectionChange` | `(keys: string[]) => void` | | | 선택 변경. 필터·페이지가 바뀌면 프레임이 비웁니다 |
1782
+ | `bulkActions` | `FloatingAction[]` | | | 일괄 작업 |
1783
+ | `onBulkAction` | `(actionId: string) => void` | | | 일괄 작업 실행 |
1784
+ | `error` | `ReactNode` | | | 읽기 실패. 빈 목록과 다른 답 |
1785
+ | `onRetry` | `() => void` | | | 재시도 |
1786
+ | `labels` | `CatalogFrameLabels` | | | 빈/필터된 빈/에러 문구 |
1787
+
1788
+ **CatalogRowActions:**
1789
+
1790
+ | Prop | Type | Required | Default | Description |
1791
+ | -------------- | ------------------------- | -------- | ------- | ------------------------------------------------------- |
1792
+ | `item` | `T` | Yes | | 이 행의 항목 |
1793
+ | `actions` | `CatalogRowAction<T>[]` | Yes | | 행 액션 |
1794
+ | `visibleCount` | `number` | | 2 | 오버플로 전에 노출할 개수. available 필터링 후에 적용됨 |
1795
+ | `labels` | `CatalogRowActionsLabels` | | | 그룹·오버플로 라벨 |
1796
+
1797
+ **CatalogCellControls:**
1798
+
1799
+ | Prop | Type | Required | Default | Description |
1800
+ | ---------- | ----------- | -------- | ------- | ---------------------------------- |
1801
+ | `children` | `ReactNode` | Yes | | 행 클릭으로 새면 안 되는 셀 컨트롤 |