@reopt-ai/opt-ui 1.11.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 +394 -201
  2. package/README.md +43 -5
  3. package/dist/core/index.cjs +2 -2
  4. package/dist/core/index.d.cts +2 -2
  5. package/dist/core/index.d.ts +2 -2
  6. package/dist/core/index.js +2 -2
  7. package/dist/docs/02-components/01-core.md +150 -84
  8. package/dist/docs/02-components/02-visuals.md +1 -1
  9. package/dist/docs/02-components/03-shells.md +258 -117
  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-DAuN4jPV.cjs → field-sidebar-BYgEmdy0.cjs} +1539 -1536
  14. package/dist/{field-sidebar-BXl5RJ3q.js → field-sidebar-BuO37l4c.js} +1540 -1539
  15. package/dist/{field-sidebar-B5SQC35J.d.cts → field-sidebar-CrYlRZew.d.ts} +164 -154
  16. package/dist/{field-sidebar-CBeWE8xX.d.ts → field-sidebar-uXmoyvd7.d.cts} +164 -154
  17. package/dist/id-registry.cjs +78 -6
  18. package/dist/id-registry.d.cts +1 -2
  19. package/dist/id-registry.d.ts +1 -2
  20. package/dist/id-registry.js +78 -8
  21. package/dist/id-registry.json +168 -19
  22. package/dist/index.cjs +1127 -224
  23. package/dist/index.d.cts +567 -58
  24. package/dist/index.d.ts +567 -58
  25. package/dist/index.js +1118 -227
  26. package/dist/{key-pad-menu-BxTy_u0Q.d.cts → key-pad-menu-CwcY_Vps.d.cts} +2 -3
  27. package/dist/{key-pad-menu-wXkWn1I1.js → key-pad-menu-Di2aRGbM.js} +4 -6
  28. package/dist/{key-pad-menu-Cg6rZBie.cjs → key-pad-menu-SItoHPLu.cjs} +1 -1
  29. package/dist/{key-pad-menu-u5GTJl9B.d.ts → key-pad-menu-WBJShCJn.d.ts} +3 -4
  30. package/dist/meta.cjs +678 -19
  31. package/dist/meta.d.cts +12 -36
  32. package/dist/meta.d.ts +12 -36
  33. package/dist/meta.js +678 -21
  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 +1 -1
  38. package/dist/shells/index.d.cts +1 -1
  39. package/dist/shells/index.d.ts +1 -1
  40. package/dist/shells/index.js +1 -1
  41. package/dist/{text-truncate-DW78lg4S.d.cts → text-truncate-CQyfUZvq.d.cts} +31 -3
  42. package/dist/{text-truncate-DW78lg4S.d.ts → text-truncate-CQyfUZvq.d.ts} +31 -3
  43. package/dist/{text-truncate-C17HHCR-.js → text-truncate-DSuZECy0.js} +43 -10
  44. package/dist/{text-truncate-BZdL1k5Z.cjs → text-truncate-I1XLWmRa.cjs} +48 -7
  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-B5SQC35J.d.cts.map +0 -1
  51. package/dist/field-sidebar-BXl5RJ3q.js.map +0 -1
  52. package/dist/field-sidebar-CBeWE8xX.d.ts.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-BxTy_u0Q.d.cts.map +0 -1
  60. package/dist/key-pad-menu-u5GTJl9B.d.ts.map +0 -1
  61. package/dist/key-pad-menu-wXkWn1I1.js.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-C17HHCR-.js.map +0 -1
  69. package/dist/text-truncate-DW78lg4S.d.cts.map +0 -1
  70. package/dist/text-truncate-DW78lg4S.d.ts.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
@@ -2,17 +2,17 @@
2
2
 
3
3
  <!-- DEPRECATED: Prefer dist/docs/02-components/ for per-layer reference. -->
4
4
  <!-- Auto-generated from ComponentMeta. Do not edit. -->
5
- <!-- Version: 1.10.0 -->
5
+ <!-- Version: 1.12.0 -->
6
6
 
7
7
  ## Quick Stats
8
8
 
9
9
  | Layer | Count |
10
10
  | --------- | ------- |
11
- | Core | 70 |
11
+ | Core | 74 |
12
12
  | Visuals | 0 |
13
- | Shells | 83 |
13
+ | Shells | 86 |
14
14
  | Surfaces | 0 |
15
- | **Total** | **153** |
15
+ | **Total** | **160** |
16
16
 
17
17
  ## Component Selection Guide
18
18
 
@@ -95,7 +95,7 @@
95
95
  | 인사이트/이상탐지 | InsightsPanel | Shell |
96
96
  | 프롬프트 템플릿 | PromptTemplate | Shell |
97
97
 
98
- ## Core Components (70)
98
+ ## Core Components (74)
99
99
 
100
100
  ### Input
101
101
 
@@ -175,39 +175,43 @@
175
175
 
176
176
  ### Other
177
177
 
178
- | Component | Description | Key Exports |
179
- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
180
- | FieldToken | 필드 타입을 글리프 하나로 표현하는 토큰. 문자열·숫자·날짜·IP·지오 등 분석 스키마 타입마다 고정된 아이콘과 팔레트 슬롯을 부여해 필드 목록·컬럼 헤더·속성 테이블 전역에서 같은 어휘를 쓴다. | `FieldToken`, `FIELD_TYPE_TOKENS`, `resolveFieldType` |
181
- | Facet | 필드 값 분포를 카운트와 점유율 막대로 보여주고 그 행 자체가 필터가 되는 패싯. 긴 꼬리는 접어 두고 상위 값부터 읽힌다. | `Facet`, `FacetGroup` |
182
- | Expression | 조건을 폼이 아니라 문장으로 쓰고 그 자리에서 편집하는 표현식 절. 알림 규칙·세그먼트 필터처럼 읽어서 검증해야 하는 조건에 쓴다. | `Expression`, `ExpressionGroup` |
183
- | TextTruncate | 실제 폰트로 실제 가용 폭을 측정해 문자열의 식별력이 가장 낮은 부분을 잘라내는 생략. CSS가 못 하는 앞·중간·양끝 생략을 지원하고 전체 문자열은 접근성 트리에 남는다. | `TextTruncate` |
184
- | Highlight | 검색어에 해당하는 구간을 <mark>로 표시. 긴 항목 우선 매칭이라 겹치는 검색어도 조각나지 않는다. | `Highlight` |
185
- | LiveRegion | 라이브 뷰의 변화를 스크린 리더에 읽어 주는 영역. 스로틀로 폭주를 요약하고 두 노드를 번갈아 써서 같은 문구도 다시 읽힌다. | `LiveRegion` |
186
- | ColorPalette | 시각화 색 팔레트를 그 팔레트의 모습 그대로 보여 주고 고르게 하는 컴포넌트. 범주형은 블록, 순차·발산형은 그라디언트로 그려 데이터 종류를 그림이 말한다. | `ColorPaletteDisplay`, `ColorPalettePicker`, `THEME_PALETTES` |
187
- | InlineEdit | 대시보드 제목·지표 이름처럼 읽히는 횟수가 훨씬 많은 값을 그 자리에서 고치는 편집. Enter 확정, Escape 되돌리기, 거절된 저장은 입력을 유지한다. | `InlineEdit` |
188
- | KeyPadMenu | 이름보다 그림으로 알아보기 쉬운 선택지를 타일로 고르는 메뉴. 내부는 실제 radio·checkbox라 키보드와 스크린 리더가 그대로 동작한다. | `KeyPadMenu` |
189
- | Text | 본문, 레이블, 보조 설명, 코드에 일관된 의미 기반 타이포그래피를 적용합니다. | `Text` |
190
- | Heading | 문서의 의미 계층과 시각적 타이포그래피 계층을 독립적으로 제어합니다. | `Heading` |
191
- | Separator | 콘텐츠를 구분하는 가로/세로 디바이더. 라벨을 넣으면 가운데 정렬 구분선이 된다. | `Separator` |
192
- | OtpField | 일회용 코드(OTP)/PIN 입력. 셀 단위 입력, 붙여넣기 분배, 자동 포커스 이동, 백스페이스 네비게이션과 폼 이름/오류 연결을 지원합니다. | `OtpField` |
193
- | Toggle | 눌림(pressed) 두 상태 버튼. 단독 사용하거나 ToggleGroup으로 묶어 단일/다중 선택을 만든다. | `Toggle`, `ToggleGroup` |
194
- | Accordion | 수직으로 쌓인 펼침/접힘 패널. single(한 개)/multiple(여러 개) 모드와 collapsible 지원. | `AccordionRoot`, `AccordionItem`, `AccordionTrigger`, `AccordionContent` |
195
- | Meter | 범위 내 스칼라 측정값 게이지 (디스크 사용량·점수·용량 등). role=meter로 작업 진행률(Progress)과 구분된다. | `Meter` |
196
- | DescriptionList | 한 대상의 라벨 있는 사실들을 시맨틱 <dl>로 표시한다. 상세 패널의 필드 나열을 표준화하고 식별자 복사를 제공한다. | `DescriptionList` |
197
- | Identity | 사람(또는 익명 디바이스)을 목록 셀 한 칸으로 표현한다. 이름→이메일→ID 폴백과 익명 표식을 한 곳에서 처리한다. | `Identity` |
198
- | BlockLayout | Block 루트 레이아웃. 자식 간 section spacing과 선택적 시맨틱 inset을 제공하고 loading prop으로 LoadingOverlay를 자동 래핑합니다. | `BlockLayout` |
199
- | createBlock | Block 팩토리 함수. BlockLayout 래핑을 구조적으로 강제하여 loading/className 처리를 자동화합니다. | `createBlock` |
200
- | StarRating | 1~N점 별점을 선택하는 인터랙티브 레이팅 입력. 읽기 전용 표시도 지원. | `StarRating` |
201
- | ErrorBoundary | React 에러 바운더리. 자식 컴포넌트 렌더 에러를 잡아 fallback UI를 표시합니다. | `ErrorBoundary` |
202
- | Command | cmdk 스타일 명령 anatomy. 자동 필터링 + 키보드 내비게이션. 인라인 또는 CommandDialog로 사용. | `Command`, `CommandDialog`, `CommandInput`, `CommandList`, `CommandEmpty`, `CommandGroup`, `CommandItem`, `CommandSeparator`, `CommandShortcut` |
203
- | ShaderSurface | ogl 기반 애니메이션 WebGL 셰이더 배경. 럭셔리 프리셋(메탈릭/실크/유리 등) + 색·파라미터로 배경·카드 배경을 만든다. 정지 프레임·PNG 캡처·WebGL 폴백 지원. | `ShaderSurface` |
178
+ | Component | Description | Key Exports |
179
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
180
+ | FieldToken | 필드 타입을 글리프 하나로 표현하는 토큰. 문자열·숫자·날짜·IP·지오 등 분석 스키마 타입마다 고정된 아이콘과 팔레트 슬롯을 부여해 필드 목록·컬럼 헤더·속성 테이블 전역에서 같은 어휘를 쓴다. | `FieldToken`, `FIELD_TYPE_TOKENS`, `resolveFieldType` |
181
+ | Facet | 필드 값 분포를 카운트와 점유율 막대로 보여주고 그 행 자체가 필터가 되는 패싯. 긴 꼬리는 접어 두고 상위 값부터 읽힌다. | `Facet`, `FacetGroup` |
182
+ | Expression | 조건을 폼이 아니라 문장으로 쓰고 그 자리에서 편집하는 표현식 절. 알림 규칙·세그먼트 필터처럼 읽어서 검증해야 하는 조건에 쓴다. | `Expression`, `ExpressionGroup` |
183
+ | TextTruncate | 실제 폰트로 실제 가용 폭을 측정해 문자열의 식별력이 가장 낮은 부분을 잘라내는 생략. CSS가 못 하는 앞·중간·양끝 생략을 지원하고 전체 문자열은 접근성 트리에 남는다. | `TextTruncate` |
184
+ | Highlight | 검색어에 해당하는 구간을 <mark>로 표시. 긴 항목 우선 매칭이라 겹치는 검색어도 조각나지 않는다. | `Highlight` |
185
+ | LiveRegion | 라이브 뷰의 변화를 스크린 리더에 읽어 주는 영역. 스로틀로 폭주를 요약하고 두 노드를 번갈아 써서 같은 문구도 다시 읽힌다. | `LiveRegion` |
186
+ | ColorPalette | 시각화 색 팔레트를 그 팔레트의 모습 그대로 보여 주고 고르게 하는 컴포넌트. 범주형은 블록, 순차·발산형은 그라디언트로 그려 데이터 종류를 그림이 말한다. | `ColorPaletteDisplay`, `ColorPalettePicker`, `THEME_PALETTES` |
187
+ | InlineEdit | 대시보드 제목·지표 이름처럼 읽히는 횟수가 훨씬 많은 값을 그 자리에서 고치는 편집. Enter 확정, Escape 되돌리기, 거절된 저장은 입력을 유지한다. | `InlineEdit` |
188
+ | KeyPadMenu | 이름보다 그림으로 알아보기 쉬운 선택지를 타일로 고르는 메뉴. 내부는 실제 radio·checkbox라 키보드와 스크린 리더가 그대로 동작한다. | `KeyPadMenu` |
189
+ | Text | 본문, 레이블, 보조 설명, 코드에 일관된 의미 기반 타이포그래피를 적용합니다. | `Text` |
190
+ | Heading | 문서의 의미 계층과 시각적 타이포그래피 계층을 독립적으로 제어합니다. | `Heading` |
191
+ | Separator | 콘텐츠를 구분하는 가로/세로 디바이더. 라벨을 넣으면 가운데 정렬 구분선이 된다. | `Separator` |
192
+ | OtpField | 일회용 코드(OTP)/PIN 입력. 셀 단위 입력, 붙여넣기 분배, 자동 포커스 이동, 백스페이스 네비게이션과 폼 이름/오류 연결을 지원합니다. | `OtpField` |
193
+ | Toggle | 눌림(pressed) 두 상태 버튼. 단독 사용하거나 ToggleGroup으로 묶어 단일/다중 선택을 만든다. | `Toggle`, `ToggleGroup` |
194
+ | Accordion | 수직으로 쌓인 펼침/접힘 패널. single(한 개)/multiple(여러 개) 모드와 collapsible 지원. | `AccordionRoot`, `AccordionItem`, `AccordionTrigger`, `AccordionContent` |
195
+ | Meter | 범위 내 스칼라 측정값 게이지 (디스크 사용량·점수·용량 등). role=meter로 작업 진행률(Progress)과 구분된다. | `Meter` |
196
+ | DescriptionList | 한 대상의 라벨 있는 사실들을 시맨틱 <dl>로 표시한다. 상세 패널의 필드 나열을 표준화하고 식별자 복사를 제공한다. | `DescriptionList` |
197
+ | Identity | 사람(또는 익명 디바이스)을 목록 셀 한 칸으로 표현한다. 이름→이메일→ID 폴백과 익명 표식을 한 곳에서 처리한다. | `Identity` |
198
+ | BlockLayout | Block 루트 레이아웃. 자식 간 section spacing과 선택적 시맨틱 inset을 제공하고 loading prop으로 LoadingOverlay를 자동 래핑합니다. | `BlockLayout` |
199
+ | createBlock | Block 팩토리 함수. BlockLayout 래핑을 구조적으로 강제하여 loading/className 처리를 자동화합니다. | `createBlock` |
200
+ | StarRating | 1~N점 별점을 선택하는 인터랙티브 레이팅 입력. 읽기 전용 표시도 지원. | `StarRating` |
201
+ | ErrorBoundary | React 에러 바운더리. 자식 컴포넌트 렌더 에러를 잡아 fallback UI를 표시합니다. | `ErrorBoundary` |
202
+ | Command | cmdk 스타일 명령 anatomy. 자동 필터링 + 키보드 내비게이션. 인라인 또는 CommandDialog로 사용. | `Command`, `CommandDialog`, `CommandInput`, `CommandList`, `CommandEmpty`, `CommandGroup`, `CommandItem`, `CommandSeparator`, `CommandShortcut` |
203
+ | ShaderSurface | ogl 기반 애니메이션 WebGL 셰이더 배경. 럭셔리 프리셋(메탈릭/실크/유리 등) + 색·파라미터로 배경·카드 배경을 만든다. 정지 프레임·PNG 캡처·WebGL 폴백 지원. | `ShaderSurface` |
204
+ | Callout | 페이지에 머무는 인페이지 고지. Alert와 달리 dismiss가 없고, 조건이 참인 동안 레이아웃의 일부로 남습니다. | `Callout` |
205
+ | StatusDot | 점 + 텍스트로 상태를 표현합니다. 라벨이 필수라 색만으로 상태를 말할 수 없습니다. | `StatusDot` |
206
+ | CopyButton | 값을 클립보드에 올리고 성공 여부를 알립니다. 클립보드 거부를 삼키지 않습니다. | `CopyButton` |
207
+ | SegmentedControl | 선택지를 모두 보여주는 단일 선택 컨트롤. radio-group 프리미티브 위에 올려 화살표 키가 동작합니다. | `SegmentedControl` |
204
208
 
205
209
  ## Visual Components (0)
206
210
 
207
211
  | Component | Description | Key Exports |
208
212
  | --------- | ----------- | ----------- |
209
213
 
210
- ## Shell Components (83)
214
+ ## Shell Components (86)
211
215
 
212
216
  ### Navigation & Layout
213
217
 
@@ -339,23 +343,26 @@
339
343
 
340
344
  ### Other
341
345
 
342
- | Component | Description | Key Exports |
343
- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------ |
344
- | PageAside | Sticky 페이지 사이드 aside chrome. 고정 너비 + header/body/footer 3-slot. | `PageAside` |
345
- | FailureList | 실패 목록 패널. severity별 색상 강조, 그룹핑, 액션 슬롯을 지원합니다. | `FailureList` |
346
- | KeyValueEditor | 키-값 쌍 편집기. 동적 행 추가/삭제, 비밀값 토글, 유효성 검사를 지원합니다. | `KeyValueEditor` |
347
- | EventTimeline | 이벤트를 순서로 읽히게 하는 타임라인. 인접 이벤트 사이의 경과 시간을 라벨링하고, 속성 페이로드를 제자리에서 펼치며, 세션 단위 그룹핑을 지원한다. | `EventTimeline` |
348
- | ScoreBreakdown | 합성 점수를 축별로 분해해 보여준다. 총점과 함께 각 축의 값·가중치·의미를 노출해 '43'을 판정이 아니라 발견으로 만든다. | `ScoreBreakdown` |
349
- | Flyout | 목록을 화면에 둔 채 레코드를 옆에서 보여주는 상세 패널. 모달이 아니다 — 포커스 트랩·aria-modal·inert 없이 Escape로 닫고 포커스를 되돌린다. | `Flyout` |
350
- | AuditTimeline | 변경 이력 타임라인. 액션별 색상 코딩 + 확장 가능한 diff 뷰. | `AuditTimeline` |
351
- | ChatSidebar | AI 채팅 사이드바. 대화 목록, 검색, 새 대화 버튼. | `ChatSidebar` |
352
- | ChatInput | 채팅 입력 컴포넌트. 자동 리사이즈 textarea, 파일 첨부, 모델/스타일 Select. | `ChatInput` |
353
- | ChatMessageList | 채팅 메시지 목록. 역할별 말풍선, 타이핑 인디케이터, 자동 스크롤. | `ChatMessageList` |
354
- | TimeRangeControl | date math(now-7d, now/d) 기반 시간 범위 컨트롤. quick select, 프리셋/최근 사용, 명시적 Update, 자동 갱신, 창 이동·확대/축소 버튼을 제공합니다. | `TimeRangeControl`, `DEFAULT_TIME_PRESETS` |
355
- | TimeSeriesPanel | 시간 범위 컨트롤과 시계열 차트를 한 단위로 묶은 패널. 드래그 줌과 줌 히스토리(되돌리기), 범례 토글을 포함합니다. | `TimeSeriesPanel` |
356
- | LogTable | 계속 도착하는 로그용 윈도잉 테이블. 컬럼 정의 기반, 상단 삽입 시 스크롤 위치 보존, follow 상태 보고, 셀 값 즉시 필터, 밀도·정렬을 지원합니다. | `LogTable` |
357
- | QueryBar | 검색과 필터를 한 입력으로 합친 쿼리 바. field:value, -부정, (a or b), 비교 연산, 필드·값 자동완성, 절(clause) 칩을 지원합니다. | `QueryBar` |
358
- | FieldSidebar | 데이터에 어떤 필드가 있고 각 필드가 무슨 값을 갖는지 보여주는 사이드바. 값 분포 막대, 컬럼으로 승격, 값 기준 포함/제외 필터를 제공합니다. | `FieldSidebar` |
346
+ | Component | Description | Key Exports |
347
+ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
348
+ | PageAside | Sticky 페이지 사이드 aside chrome. 고정 너비 + header/body/footer 3-slot. | `PageAside` |
349
+ | FailureList | 실패 목록 패널. severity별 색상 강조, 그룹핑, 액션 슬롯을 지원합니다. | `FailureList` |
350
+ | KeyValueEditor | 키-값 쌍 편집기. 동적 행 추가/삭제, 비밀값 토글, 유효성 검사를 지원합니다. | `KeyValueEditor` |
351
+ | EventTimeline | 이벤트를 순서로 읽히게 하는 타임라인. 인접 이벤트 사이의 경과 시간을 라벨링하고, 속성 페이로드를 제자리에서 펼치며, 세션 단위 그룹핑을 지원한다. | `EventTimeline` |
352
+ | ScoreBreakdown | 합성 점수를 축별로 분해해 보여준다. 총점과 함께 각 축의 값·가중치·의미를 노출해 '43'을 판정이 아니라 발견으로 만든다. | `ScoreBreakdown` |
353
+ | Flyout | 목록을 화면에 둔 채 레코드를 옆에서 보여주는 상세 패널. 모달이 아니다 — 포커스 트랩·aria-modal·inert 없이 Escape로 닫고 포커스를 되돌린다. | `Flyout` |
354
+ | AuditTimeline | 변경 이력 타임라인. 액션별 색상 코딩 + 확장 가능한 diff 뷰. | `AuditTimeline` |
355
+ | ChatSidebar | AI 채팅 사이드바. 대화 목록, 검색, 새 대화 버튼. | `ChatSidebar` |
356
+ | ChatInput | 채팅 입력 컴포넌트. 자동 리사이즈 textarea, 파일 첨부, 모델/스타일 Select. | `ChatInput` |
357
+ | ChatMessageList | 채팅 메시지 목록. 역할별 말풍선, 타이핑 인디케이터, 자동 스크롤. | `ChatMessageList` |
358
+ | TimeRangeControl | date math(now-7d, now/d) 기반 시간 범위 컨트롤. quick select, 프리셋/최근 사용, 명시적 Update, 자동 갱신, 창 이동·확대/축소 버튼을 제공합니다. | `TimeRangeControl`, `DEFAULT_TIME_PRESETS` |
359
+ | TimeSeriesPanel | 시간 범위 컨트롤과 시계열 차트를 한 단위로 묶은 패널. 드래그 줌과 줌 히스토리(되돌리기), 범례 토글을 포함합니다. | `TimeSeriesPanel` |
360
+ | LogTable | 계속 도착하는 로그용 윈도잉 테이블. 컬럼 정의 기반, 상단 삽입 시 스크롤 위치 보존, follow 상태 보고, 셀 값 즉시 필터, 밀도·정렬을 지원합니다. | `LogTable` |
361
+ | QueryBar | 검색과 필터를 한 입력으로 합친 쿼리 바. field:value, -부정, (a or b), 비교 연산, 필드·값 자동완성, 절(clause) 칩을 지원합니다. | `QueryBar` |
362
+ | FieldSidebar | 데이터에 어떤 필드가 있고 각 필드가 무슨 값을 갖는지 보여주는 사이드바. 값 분포 막대, 컬럼으로 승격, 값 기준 포함/제외 필터를 제공합니다. | `FieldSidebar` |
363
+ | InspectorLayout | 목록과 인스펙터의 2-pane 레이아웃. 넓으면 밀어내고(push) 좁으면 덮으며(overlay), 닫을 때 포커스를 열었던 자리로 되돌립니다. | `InspectorLayout` |
364
+ | QueryFilterBar | QueryBar와 필터 버튼이 하나의 Query를 공유합니다. 버튼은 상태를 갖지 않고 Query를 읽어 활성 여부를 계산합니다. | `QueryFilterBar`, `hasActiveQuery` |
365
+ | CatalogFrame | 카탈로그 목록의 공통 뼈대. 헤더·통계·고지·필터·인스펙터·페이지네이션·일괄 작업과 빈/에러 상태를 담고, 필터나 페이지가 바뀌면 선택을 비웁니다. | `CatalogFrame`, `CatalogRowActions`, `CatalogCellControls` |
359
366
 
360
367
  ## Surface Components (0)
361
368
 
@@ -560,11 +567,11 @@
560
567
 
561
568
  **Import:** `import { Heading } from "@reopt-ai/opt-ui"`
562
569
 
563
- | Prop | Type | Required | Default | Description |
564
- | ---------- | ------------------------------------------------------------------------ | -------- | ------- | ------------------------ |
565
- | `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | | | 의미 기반 HTML 제목 레벨 |
566
- | `variant` | `"heading-1" "heading-6" \| "display-1" \| "display-2" \| "display-3"` | | | 시각적 제목 역할 |
567
- | `children` | `ReactNode` | | | 제목 콘텐츠 |
570
+ | Prop | Type | Required | Default | Description |
571
+ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------ |
572
+ | `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | | | 의미 기반 HTML 제목 레벨 |
573
+ | `variant` | `"heading-1" \| "heading-2" \| "heading-3" \| "heading-4" \| "heading-5" \| "heading-6" \| "display-1" \| "display-2" \| "display-3"` | | | 시각적 제목 역할 |
574
+ | `children` | `ReactNode` | | | 제목 콘텐츠 |
568
575
 
569
576
  #### Kbd
570
577
 
@@ -1553,15 +1560,16 @@ const store = useFormStore({ defaultValues: { name: "" } });
1553
1560
 
1554
1561
  **Import:** `import { Switch } from "@reopt-ai/opt-ui"`
1555
1562
 
1556
- | Prop | Type | Required | Default | Description |
1557
- | ---------------- | ---------------------------- | -------- | ------- | --------------------------- |
1558
- | `label` | `string` | | | 스위치 레이블 |
1559
- | `description` | `string` | | | 레이블 아래 설명 텍스트 |
1560
- | `checked` | `boolean` | | | 제어 모드: 체크 상태 |
1561
- | `defaultChecked` | `boolean` | | | 비제어 모드: 초기 체크 상태 |
1562
- | `onChange` | `(checked: boolean) => void` | | | 상태 변경 핸들러 |
1563
- | `size` | `"sm" \| "md" \| "lg"` | | "md" | 스위치 크기 |
1564
- | `disabled` | `boolean` | | | 비활성화 상태 |
1563
+ | Prop | Type | Required | Default | Description |
1564
+ | ---------------- | ---------------------------- | -------- | ------- | -------------------------------------------------------------------------- |
1565
+ | `label` | `string` | | | 스위치 레이블 |
1566
+ | `hint` | `string` | | | 레이블 아래 보조 설명 텍스트 |
1567
+ | `description` | `string` | | | 레이블 아래 설명 텍스트 **⚠️ deprecated since 1.9.0 — use `hint` instead** |
1568
+ | `checked` | `boolean` | | | 제어 모드: 체크 상태 |
1569
+ | `defaultChecked` | `boolean` | | | 비제어 모드: 초기 체크 상태 |
1570
+ | `onChange` | `(checked: boolean) => void` | | | 상태 변경 핸들러 |
1571
+ | `size` | `"sm" \| "md" \| "lg"` | | "md" | 스위치 크기 |
1572
+ | `disabled` | `boolean` | | | 비활성화 상태 |
1565
1573
 
1566
1574
  #### Skeleton
1567
1575
 
@@ -1802,16 +1810,17 @@ import {
1802
1810
 
1803
1811
  **Checkbox:**
1804
1812
 
1805
- | Prop | Type | Required | Default | Description |
1806
- | ---------------- | ---------------------------- | -------- | ------- | ---------------------------------- |
1807
- | `label` | `string` | | | 체크박스 레이블 |
1808
- | `description` | `string` | | | 레이블 아래 설명 텍스트 |
1809
- | `checked` | `boolean` | | | 제어 모드: 체크 상태 |
1810
- | `defaultChecked` | `boolean` | | | 비제어 모드: 초기 체크 상태 |
1811
- | `onChange` | `(checked: boolean) => void` | | | 상태 변경 핸들러 |
1812
- | `size` | `"sm" \| "md" \| "lg"` | | "md" | 체크박스 크기 |
1813
- | `value` | `string` | | | CheckboxGroup 내에서 사용할 값 |
1814
- | `indeterminate` | `boolean` | | false | 불확정 상태 표시 (마이너스 아이콘) |
1813
+ | Prop | Type | Required | Default | Description |
1814
+ | ---------------- | ---------------------------- | -------- | ------- | -------------------------------------------------------------------------- |
1815
+ | `label` | `string` | | | 체크박스 레이블 |
1816
+ | `hint` | `string` | | | 레이블 아래 보조 설명 텍스트 |
1817
+ | `description` | `string` | | | 레이블 아래 설명 텍스트 **⚠️ deprecated since 1.9.0 — use `hint` instead** |
1818
+ | `checked` | `boolean` | | | 제어 모드: 체크 상태 |
1819
+ | `defaultChecked` | `boolean` | | | 비제어 모드: 초기 체크 상태 |
1820
+ | `onChange` | `(checked: boolean) => void` | | | 상태 변경 핸들러 |
1821
+ | `size` | `"sm" \| "md" \| "lg"` | | "md" | 체크박스 크기 |
1822
+ | `value` | `string` | | | CheckboxGroup 내에서 사용할 |
1823
+ | `indeterminate` | `boolean` | | false | 불확정 상태 표시 (마이너스 아이콘) |
1815
1824
 
1816
1825
  **CheckboxGroup:**
1817
1826
 
@@ -1840,12 +1849,13 @@ import {
1840
1849
 
1841
1850
  **Radio:**
1842
1851
 
1843
- | Prop | Type | Required | Default | Description |
1844
- | ------------- | ---------------------- | -------- | ------- | ---------------------------------------------------------- |
1845
- | `value` | `string` | | | 라디오 값 (RadioGroup 안에서는 부모가 관리하므로 optional) |
1846
- | `label` | `string` | | | 라디오 레이블 |
1847
- | `description` | `string` | | | 레이블 아래 설명 텍스트 |
1848
- | `size` | `"sm" \| "md" \| "lg"` | | "md" | 라디오 크기 |
1852
+ | Prop | Type | Required | Default | Description |
1853
+ | ------------- | ---------------------- | -------- | ------- | -------------------------------------------------------------------------- |
1854
+ | `value` | `string` | | | 라디오 값 (RadioGroup 안에서는 부모가 관리하므로 optional) |
1855
+ | `label` | `string` | | | 라디오 레이블 |
1856
+ | `hint` | `string` | | | 레이블 아래 보조 설명 텍스트 |
1857
+ | `description` | `string` | | | 레이블 아래 설명 텍스트 **⚠️ deprecated since 1.9.0 — use `hint` instead** |
1858
+ | `size` | `"sm" \| "md" \| "lg"` | | "md" | 라디오 크기 |
1849
1859
 
1850
1860
  **Keyboard Shortcuts:**
1851
1861
 
@@ -1859,21 +1869,21 @@ import {
1859
1869
 
1860
1870
  **Import:** `import { DateRangePicker } from "@reopt-ai/opt-ui"`
1861
1871
 
1862
- | Prop | Type | Required | Default | Description |
1863
- | --------------------- | ----------------------------------------------------- | -------- | ------------------- | ------------------------------------------------------ |
1864
- | `value` | `DateRange` | | | 제어 모드: { start: Date \| null, end: Date \| null } |
1865
- | `onChange` | `(range: DateRange) => void` | | | 범위 변경 핸들러 |
1866
- | `presets` | `DateRangePreset[]` | | | 빠른 선택 프리셋 배열 (기본: Today, Last 7/30/90 days) |
1867
- | `placeholder` | `string` | | "Select date range" | 미선택 시 표시 텍스트 |
1868
- | `label` | `string` | | | 입력 필드 레이블 |
1869
- | `disabled` | `boolean` | | false | 비활성화 상태 |
1870
- | `format` | `(date: Date) => string` | | | 날짜 포맷 함수 |
1871
- | `comparison` | `boolean` | | false | 비교 모드 활성화 |
1872
- | `comparisonMode` | `"previous" \| "year-over-year"` | | "previous" | 비교 기준 (이전 기간 / 전년 동기) |
1873
- | `onComparisonChange` | `(comparison: boolean, mode: ComparisonMode) => void` | | | 비교 모드 변경 콜백 |
1874
- | `showGranularity` | `boolean` | | false | 시간 단위 선택기 표시 |
1875
- | `granularity` | `"hour" \| "day" \| "week" \| "month"` | | "day" | 시간 단위 |
1876
- | `onGranularityChange` | `(granularity: DateGranularity) => void` | | | 시간 단위 변경 콜백 |
1872
+ | Prop | Type | Required | Default | Description |
1873
+ | --------------------- | ---------------------------------------- | -------- | ------------------- | ------------------------------------------------------ |
1874
+ | `value` | `DateRange` | | | 제어 모드: { start: Date \| null, end: Date \| null } |
1875
+ | `onChange` | `(range: DateRange) => void` | | | 범위 변경 핸들러 |
1876
+ | `presets` | `DateRangePreset[]` | | | 빠른 선택 프리셋 배열 (기본: Today, Last 7/30/90 days) |
1877
+ | `placeholder` | `string` | | "Select date range" | 미선택 시 표시 텍스트 |
1878
+ | `label` | `string` | | | 입력 필드 레이블 |
1879
+ | `disabled` | `boolean` | | false | 비활성화 상태 |
1880
+ | `format` | `(date: Date) => string` | | | 날짜 포맷 함수 |
1881
+ | `comparison` | `boolean` | | false | 비교 모드 활성화 |
1882
+ | `comparisonMode` | `"previous" \| "year-over-year"` | | "previous" | 비교 기준 (이전 기간 / 전년 동기) |
1883
+ | `onComparisonChange` | `(mode: ComparisonMode \| null) => void` | | | 비교 모드 변경 콜백 |
1884
+ | `showGranularity` | `boolean` | | false | 시간 단위 선택기 표시 |
1885
+ | `granularity` | `"hour" \| "day" \| "week" \| "month"` | | "day" | 시간 단위 |
1886
+ | `onGranularityChange` | `(granularity: DateGranularity) => void` | | | 시간 단위 변경 콜백 |
1877
1887
 
1878
1888
  #### TagInput
1879
1889
 
@@ -2090,16 +2100,16 @@ import {
2090
2100
 
2091
2101
  **ResizablePanelGroup:**
2092
2102
 
2093
- | Prop | Type | Required | Default | Description |
2094
- | ----------------- | ------------------------------------------ | -------- | ------- | --------------------------------------------------- |
2095
- | `direction` | `"horizontal" \| "vertical"` | Yes | | 패널 분할 방향 |
2096
- | `children` | `ReactNode` | Yes | | ResizablePanel + ResizableHandle 조합 |
2097
- | `id` | `string` | | | 그룹과 defaultLayout의 패널 크기를 식별하는 고유 ID |
2098
- | `defaultLayout` | `Record<string, number>` | | | 패널 ID별 초기 비율(0-100) |
2099
- | `onLayoutChanged` | `(layout: Record<string, number>) => void` | | | 드래그가 끝난 뒤 확정된 레이아웃 콜백 |
2100
- | `groupRef` | `Ref<ResizablePanelGroupHandle>` | | | 레이아웃 조회·설정을 위한 명령형 그룹 ref |
2101
- | `autoSaveId` | `string` | | | id의 deprecated 별칭 |
2102
- | `className` | `string` | | | 커스텀 CSS 클래스 |
2103
+ | Prop | Type | Required | Default | Description |
2104
+ | ----------------- | ------------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |
2105
+ | `direction` | `"horizontal" \| "vertical"` | Yes | | 패널 분할 방향 |
2106
+ | `children` | `ReactNode` | Yes | | ResizablePanel + ResizableHandle 조합 |
2107
+ | `id` | `string` | | | 그룹과 defaultLayout의 패널 크기를 식별하는 고유 ID |
2108
+ | `defaultLayout` | `Record<string, number>` | | | 패널 ID별 초기 비율(0-100) |
2109
+ | `onLayoutChanged` | `(layout: Record<string, number>) => void` | | | 드래그가 끝난 뒤 확정된 레이아웃 콜백 |
2110
+ | `groupRef` | `Ref<ResizablePanelGroupHandle>` | | | 레이아웃 조회·설정을 위한 명령형 그룹 ref |
2111
+ | `autoSaveId` | `string` | | | id의 deprecated 별칭 **⚠️ deprecated since 1.6.0 — use `id` instead — id + defaultLayout + onLayoutChanged 조합으로 대체되었습니다.** |
2112
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
2103
2113
 
2104
2114
  **ResizablePanel:**
2105
2115
 
@@ -2356,6 +2366,57 @@ const MyDashboard = createBlock<MyDashboardProps>(
2356
2366
  | `paused` | `boolean` | | | true면 단일 프레임만 렌더 (카드 배경 등) |
2357
2367
  | `dpr` | `number` | | | device pixel ratio 상한 (기본 min(dpr, 2)) |
2358
2368
 
2369
+ #### Callout
2370
+
2371
+ **Import:** `import { Callout } from "@reopt-ai/opt-ui"`
2372
+
2373
+ | Prop | Type | Required | Default | Description |
2374
+ | ---------- | ----------------------------------------------------------- | -------- | ------- | ------------------------------------------- |
2375
+ | `tone` | `"info" \| "success" \| "warning" \| "danger" \| "neutral"` | | "info" | 고지의 성격 |
2376
+ | `title` | `ReactNode` | | | 한 줄 제목 |
2377
+ | `icon` | `ReactNode` | | | tone 기본 글리프 대체. null이면 글리프 없음 |
2378
+ | `action` | `ReactNode` | | | 다음 한 걸음. 둘 이상이면 고지가 아니라 폼 |
2379
+ | `size` | `"sm" \| "md"` | | "md" | 밀도 |
2380
+ | `children` | `ReactNode` | | | 본문 |
2381
+
2382
+ #### StatusDot
2383
+
2384
+ **Import:** `import { StatusDot } from "@reopt-ai/opt-ui"`
2385
+
2386
+ | Prop | Type | Required | Default | Description |
2387
+ | ---------- | ---------------------------------------------------------------------- | -------- | --------- | -------------------------------------- |
2388
+ | `tone` | `"neutral" \| "muted" \| "info" \| "success" \| "warning" \| "danger"` | | "neutral" | 점 색상 |
2389
+ | `size` | `"sm" \| "md"` | | "md" | 점과 글자 크기 |
2390
+ | `children` | `ReactNode` | Yes | | 상태 라벨. 필수 — 색은 상태가 아닙니다 |
2391
+ | `hint` | `string` | | | 판정 기준 툴팁 |
2392
+
2393
+ #### CopyButton
2394
+
2395
+ **Import:** `import { CopyButton } from "@reopt-ai/opt-ui"`
2396
+
2397
+ | Prop | Type | Required | Default | Description |
2398
+ | ------------------ | ----------------------- | -------- | ------- | ------------------------------------------------------- |
2399
+ | `value` | `string` | Yes | | 복사할 텍스트 |
2400
+ | `variant` | `"icon" \| "text"` | | "icon" | 글리프만 / 글리프 + 라벨 |
2401
+ | `size` | `"sm" \| "md"` | | "md" | 버튼 크기 |
2402
+ | `feedbackDuration` | `number` | | 1500 | 확인 상태 유지 시간 (ms) |
2403
+ | `onCopy` | `(ok: boolean) => void` | | | 실제로 복사됐는지 — 비보안 컨텍스트·권한 거부에서 false |
2404
+ | `labels` | `CopyButtonLabels` | | | copy / copied / failed 문구 |
2405
+
2406
+ #### SegmentedControl
2407
+
2408
+ **Import:** `import { SegmentedControl } from "@reopt-ai/opt-ui"`
2409
+
2410
+ | Prop | Type | Required | Default | Description |
2411
+ | ------------ | ----------------------------- | -------- | ------- | ------------------------------------------------------- |
2412
+ | `options` | `SegmentedControlOption<T>[]` | Yes | | 세그먼트 목록 (value / label / icon / badge / disabled) |
2413
+ | `value` | `T` | Yes | | 선택된 값 |
2414
+ | `onChange` | `(value: T) => void` | Yes | | 선택 변경 |
2415
+ | `size` | `"sm" \| "md"` | | "md" | 컨트롤 크기 |
2416
+ | `fullWidth` | `boolean` | | false | 컨테이너를 균등 분할 |
2417
+ | `disabled` | `boolean` | | false | 전체 비활성 |
2418
+ | `aria-label` | `string` | Yes | | radiogroup 이름. 필수 |
2419
+
2359
2420
  ### Visual Layer
2360
2421
 
2361
2422
  ### Shell Layer
@@ -2369,6 +2430,13 @@ const MyDashboard = createBlock<MyDashboardProps>(
2369
2430
  | ------- | ----------- | -------- | ------- | --------------------------------------- |
2370
2431
  | `items` | `FaqItem[]` | Yes | | FAQ 항목 배열. { id, question, answer } |
2371
2432
 
2433
+ **Keyboard Shortcuts:**
2434
+
2435
+ | Keys | Action |
2436
+ | --------------- | --------------------- |
2437
+ | `↑ ↓` | 질문 사이 포커스 이동 |
2438
+ | `Enter / Space` | 답변 펼치기 또는 접기 |
2439
+
2372
2440
  #### PageAside
2373
2441
 
2374
2442
  **Import:** `import { PageAside } from "@reopt-ai/opt-ui"`
@@ -2505,33 +2573,42 @@ const fields = [
2505
2573
  | ------- | ----------- | -------- | ------- | --------------------------------------------------- |
2506
2574
  | `menus` | `MenuDef[]` | Yes | | 메뉴 정의 배열. { id, label, items: MenuItemDef[] } |
2507
2575
 
2576
+ **Keyboard Shortcuts:**
2577
+
2578
+ | Keys | Action |
2579
+ | ------------------- | -------------------------- |
2580
+ | `← →` | 상위 메뉴 사이 포커스 이동 |
2581
+ | `Enter / Space / ↓` | 메뉴 열기 |
2582
+ | `↑ ↓` | 열린 메뉴 항목 이동 |
2583
+ | `Escape` | 메뉴 닫고 트리거로 복귀 |
2584
+
2508
2585
  #### CommandPalette
2509
2586
 
2510
2587
  **Import:** `import { CommandPalette } from "@reopt-ai/opt-ui"`
2511
2588
  **Dependencies:** dialog (core), combobox (core), kbd (core)
2512
2589
 
2513
- | Prop | Type | Required | Default | Description |
2514
- | --------------- | -------------------------------------------- | -------- | ------- | ----------------------------------------------------- |
2515
- | `commands` | `Omit<Command, "action">[]` | Yes | | 커맨드 목록. { id, label, group, shortcut? } |
2516
- | `open` | `boolean` | Yes | | 열림 상태 |
2517
- | `onOpenChange` | `(open: boolean) => void` | Yes | | 상태 변경 핸들러 |
2518
- | `onSelect` | `(command: Omit<Command, 'action'>) => void` | | | 커맨드 선택 핸들러 |
2519
- | `inline` | `boolean` | | false | true일 때 풀스크린 Dialog 대신 인라인 팝업으로 렌더링 |
2520
- | `labels` | `CommandPaletteLabels` | | | title/description/input/list/empty/escape 문구 |
2521
- | `footer` | `ReactNode` | | | 명령 목록 아래에 표시할 footer slot |
2522
- | `empty` | `ReactNode` | | | 결과가 없을 때 표시할 empty slot |
2523
- | `inputTrailing` | `ReactNode` | | | 검색 입력 우측 보조 콘텐츠 |
2590
+ | Prop | Type | Required | Default | Description |
2591
+ | --------------- | ----------------------------------------------- | -------- | ------- | ----------------------------------------------------- |
2592
+ | `commands` | `Omit<CommandDef, "action">[]` | Yes | | 커맨드 목록. { id, label, group, shortcut? } |
2593
+ | `open` | `boolean` | Yes | | 열림 상태 |
2594
+ | `onOpenChange` | `(open: boolean) => void` | Yes | | 상태 변경 핸들러 |
2595
+ | `onSelect` | `(command: Omit<CommandDef, "action">) => void` | | | 커맨드 선택 핸들러 |
2596
+ | `inline` | `boolean` | | false | true일 때 풀스크린 Dialog 대신 인라인 팝업으로 렌더링 |
2597
+ | `labels` | `CommandPaletteLabels` | | | title/description/input/list/empty/escape 문구 |
2598
+ | `footer` | `ReactNode` | | | 명령 목록 아래에 표시할 footer slot |
2599
+ | `empty` | `ReactNode` | | | 결과가 없을 때 표시할 empty slot |
2600
+ | `inputTrailing` | `ReactNode` | | | 검색 입력 우측 보조 콘텐츠 |
2524
2601
 
2525
2602
  #### CommandPaletteTrigger
2526
2603
 
2527
2604
  **Import:** `import { CommandPaletteTrigger } from "@reopt-ai/opt-ui"`
2528
2605
  **Dependencies:** command-palette (shells)
2529
2606
 
2530
- | Prop | Type | Required | Default | Description |
2531
- | ---------- | -------------------------------------------- | -------- | ------- | -------------------------------------------------- |
2532
- | `commands` | `Omit<Command, "action">[]` | Yes | | 커맨드 목록 |
2533
- | `onSelect` | `(command: Omit<Command, 'action'>) => void` | | | 커맨드 선택 핸들러 |
2534
- | `labels` | `CommandPaletteTriggerLabels` | | | 내부 CommandPalette에 전달할 title/input/list 문구 |
2607
+ | Prop | Type | Required | Default | Description |
2608
+ | ---------- | ----------------------------------------------- | -------- | ------- | -------------------------------------------------- |
2609
+ | `commands` | `Omit<CommandDef, "action">[]` | Yes | | 커맨드 목록 |
2610
+ | `onSelect` | `(command: Omit<CommandDef, "action">) => void` | | | 커맨드 선택 핸들러 |
2611
+ | `labels` | `CommandPaletteTriggerLabels` | | | 내부 CommandPalette에 전달할 title/input/list 문구 |
2535
2612
 
2536
2613
  #### DeploymentTimeline
2537
2614
 
@@ -2741,11 +2818,11 @@ import { DataTable } from "@reopt-ai/opt-ui";
2741
2818
  **Import:** `import { FilterBar } from "@reopt-ai/opt-ui"`
2742
2819
  **Dependencies:** select (core), input (core), button (core), switch (core), checkbox (core), date-range-picker (core)
2743
2820
 
2744
- | Prop | Type | Required | Default | Description |
2745
- | ---------------- | ------------------------------------------------------- | -------- | ------- | ----------------------------------------------------- |
2746
- | `filters` | `FilterGroupDef[]` | Yes | | 필터 그룹 배열. { id, label, type, options?, value? } |
2747
- | `onFilterChange` | `(filterId: string, value: string \| string[]) => void` | | | 필터 변경 핸들러 |
2748
- | `onClearAll` | `() => void` | | | 모든 필터 초기화 핸들러 |
2821
+ | Prop | Type | Required | Default | Description |
2822
+ | ---------------- | ------------------------------------------------------------------ | -------- | ------- | ----------------------------------------------------- |
2823
+ | `filters` | `FilterGroupDef[]` | Yes | | 필터 그룹 배열. { id, label, type, options?, value? } |
2824
+ | `onFilterChange` | `(filterId: string, value: string \| string[] \| boolean) => void` | | | 필터 변경 핸들러 |
2825
+ | `onClearAll` | `() => void` | | | 모든 필터 초기화 핸들러 |
2749
2826
 
2750
2827
  **Examples:**
2751
2828
 
@@ -2811,15 +2888,15 @@ const filters = [
2811
2888
  **Import:** `import { AuthForm } from "@reopt-ai/opt-ui"`
2812
2889
  **Dependencies:** form (core)
2813
2890
 
2814
- | Prop | Type | Required | Default | Description |
2815
- | ------------------- | ---------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------- |
2816
- | `defaultMode` | `"login" \| "signup"` | | "login" | 초기 모드 (비제어) |
2817
- | `mode` | `"login" \| "signup"` | | | 제어 모드: 현재 모드 |
2818
- | `onModeChange` | `(mode: "login" \| "signup") => void` | | | 모드 변경 핸들러 |
2819
- | `showRememberMe` | `boolean` | | true | 로그인 모드에서 '로그인 상태 유지' 표시 여부 |
2820
- | `minPasswordLength` | `number` | | 8 | 비밀번호 최소 길이 |
2821
- | `onSubmit` | `(values: { email, password, confirmPassword?, rememberMe?, mode }) => void` | | | 제출 핸들러 |
2822
- | `labels` | `AuthFormLabels` | | | i18n용 라벨 오버라이드 |
2891
+ | Prop | Type | Required | Default | Description |
2892
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------- |
2893
+ | `defaultMode` | `"login" \| "signup"` | | "login" | 초기 모드 (비제어) |
2894
+ | `mode` | `"login" \| "signup"` | | | 제어 모드: 현재 모드 |
2895
+ | `onModeChange` | `(mode: "login" \| "signup") => void` | | | 모드 변경 핸들러 |
2896
+ | `showRememberMe` | `boolean` | | true | 로그인 모드에서 '로그인 상태 유지' 표시 여부 |
2897
+ | `minPasswordLength` | `number` | | 8 | 비밀번호 최소 길이 |
2898
+ | `onSubmit` | `(values: { email: string; password: string; confirmPassword?: string; rememberMe?: boolean; mode: "login" \| "signup" }) => void` | | | 제출 핸들러 |
2899
+ | `labels` | `AuthFormLabels` | | | i18n용 라벨 오버라이드 |
2823
2900
 
2824
2901
  #### WizardForm
2825
2902
 
@@ -2855,17 +2932,17 @@ const filters = [
2855
2932
  **Import:** `import { FileUploadForm } from "@reopt-ai/opt-ui"`
2856
2933
  **Dependencies:** form (core)
2857
2934
 
2858
- | Prop | Type | Required | Default | Description |
2859
- | ----------------- | ------------------------------------------------ | -------- | ------------------------- | ----------------------------------------- |
2860
- | `accept` | `string` | | "image/*,.pdf,.doc,.docx" | 허용 파일 타입 |
2861
- | `showPreview` | `boolean` | | true | 이미지 미리보기 표시 |
2862
- | `showFileInfo` | `boolean` | | true | 파일 정보 표시 |
2863
- | `showDescription` | `boolean` | | true | 설명 텍스트영역 표시 |
2864
- | `maxFileSize` | `number` | | | 최대 파일 크기 (bytes) |
2865
- | `onSubmit` | `(values: { title, description, file }) => void` | | | 제출 핸들러 |
2866
- | `labels` | `FileUploadFormLabels` | | | i18n용 라벨 오버라이드 |
2867
- | `onPreview` | `(file: File) => void` | | | 파일 선택 후 프리뷰 콜백 |
2868
- | `columnMapping` | `ReactNode` | | | CSV 컬럼 매핑 UI 슬롯 (파일 선택 후 표시) |
2935
+ | Prop | Type | Required | Default | Description |
2936
+ | ----------------- | ------------------------------------------------------------------------------ | -------- | ------------------------- | ----------------------------------------- |
2937
+ | `accept` | `string` | | "image/*,.pdf,.doc,.docx" | 허용 파일 타입 |
2938
+ | `showPreview` | `boolean` | | true | 이미지 미리보기 표시 |
2939
+ | `showFileInfo` | `boolean` | | true | 파일 정보 표시 |
2940
+ | `showDescription` | `boolean` | | true | 설명 텍스트영역 표시 |
2941
+ | `maxFileSize` | `number` | | | 최대 파일 크기 (bytes) |
2942
+ | `onSubmit` | `(values: { title: string; description: string; file: File \| null }) => void` | | | 제출 핸들러 |
2943
+ | `labels` | `FileUploadFormLabels` | | | i18n용 라벨 오버라이드 |
2944
+ | `onPreview` | `(file: File) => void` | | | 파일 선택 후 프리뷰 콜백 |
2945
+ | `columnMapping` | `ReactNode` | | | CSV 컬럼 매핑 UI 슬롯 (파일 선택 후 표시) |
2869
2946
 
2870
2947
  #### EventIcon
2871
2948
 
@@ -3020,16 +3097,16 @@ const filters = [
3020
3097
  **Import:** `import { ReportBuilder } from "@reopt-ai/opt-ui"`
3021
3098
  **Dependencies:** button (core), input (core)
3022
3099
 
3023
- | Prop | Type | Required | Default | Description |
3024
- | ------------- | ------------------------------------------------------------------ | -------- | ------- | ----------------------------------- |
3025
- | `chartTypes` | `ChartTypeDef[]` | | | 차트 타입 그리드 (기본 9종 제공) |
3026
- | `dataSources` | `DataSourceDef[]` | | | 데이터 소스 드롭다운 옵션 |
3027
- | `configForm` | `ReactNode` | | | 차트별 데이터 설정 폼 슬롯 (step 2) |
3028
- | `styleForm` | `ReactNode` | | | 차트별 스타일 설정 폼 슬롯 (step 3) |
3029
- | `preview` | `ReactNode` | | | 차트 미리보기 슬롯 (step 4) |
3030
- | `onSave` | `(report: { name, description, chartType, dataSourceId }) => void` | | | 저장 콜백 |
3031
- | `onCancel` | `() => void` | | | 취소 콜백 |
3032
- | `labels` | `ReportBuilderLabels` | | | UI 텍스트 커스터마이징 |
3100
+ | Prop | Type | Required | Default | Description |
3101
+ | ------------- | ------------------------------------------------------------------------------------------------------------------ | -------- | ------- | ----------------------------------- |
3102
+ | `chartTypes` | `ChartTypeDef[]` | | | 차트 타입 그리드 (기본 9종 제공) |
3103
+ | `dataSources` | `DataSourceDef[]` | | | 데이터 소스 드롭다운 옵션 |
3104
+ | `configForm` | `ReactNode` | | | 차트별 데이터 설정 폼 슬롯 (step 2) |
3105
+ | `styleForm` | `ReactNode` | | | 차트별 스타일 설정 폼 슬롯 (step 3) |
3106
+ | `preview` | `ReactNode` | | | 차트 미리보기 슬롯 (step 4) |
3107
+ | `onSave` | `(report: { name: string; description: string; chartType: ReportBuilderChartType; dataSourceId: string }) => void` | | | 저장 콜백 |
3108
+ | `onCancel` | `() => void` | | | 취소 콜백 |
3109
+ | `labels` | `ReportBuilderLabels` | | | UI 텍스트 커스터마이징 |
3033
3110
 
3034
3111
  #### InsightsPanel
3035
3112
 
@@ -3275,15 +3352,15 @@ import { AppShell } from "@reopt-ai/opt-ui";
3275
3352
  **Import:** `import { AsyncCombobox } from "@reopt-ai/opt-ui"`
3276
3353
  **Dependencies:** combobox (core), spinner (core)
3277
3354
 
3278
- | Prop | Type | Required | Default | Description |
3279
- | ------------- | ---------------------------------- | -------- | --------- | ---------------------------------------- |
3280
- | `onSearch` | `(q: string) => Promise<string[]>` | Yes | | 검색 콜백 |
3281
- | `debounceMs` | `number` | | 300 | 디바운스 ms |
3282
- | `minChars` | `number` | | 1 | 최소 검색 글자 수 |
3283
- | `placeholder` | `string` | | "Search…" | 플레이스홀더 |
3284
- | `onSelect` | `(value: string) => void` | | | 선택 콜백 |
3285
- | `labels` | `AsyncComboboxLabels` | | | input/loading/noResults/placeholder 문구 |
3286
- | `loadingText` | `string` | | | 로딩 문구. labels.loading 사용 권장 |
3355
+ | Prop | Type | Required | Default | Description |
3356
+ | ------------- | -------------------------------------- | -------- | --------- | ----------------------------------------------------------------------------- |
3357
+ | `onSearch` | `(query: string) => Promise<string[]>` | Yes | | 검색 콜백 |
3358
+ | `debounceMs` | `number` | | 300 | 디바운스 ms |
3359
+ | `minChars` | `number` | | 1 | 최소 검색 글자 수 |
3360
+ | `placeholder` | `string` | | "Search…" | 플레이스홀더 **⚠️ deprecated since 1.9.0 — use `labels.placeholder` instead** |
3361
+ | `onSelect` | `(value: string) => void` | | | 선택 콜백 |
3362
+ | `labels` | `AsyncComboboxLabels` | | | input/loading/noResults/placeholder 문구 |
3363
+ | `loadingText` | `string` | | | 로딩 문구 **⚠️ deprecated since 1.9.0 — use `labels.loading` instead** |
3287
3364
 
3288
3365
  #### VerticalTabs
3289
3366
 
@@ -3296,6 +3373,13 @@ import { AppShell } from "@reopt-ai/opt-ui";
3296
3373
  | `defaultTabId` | `string` | | | 기본 선택 탭 ID |
3297
3374
  | `className` | `string` | | | 커스텀 CSS 클래스 |
3298
3375
 
3376
+ **Keyboard Shortcuts:**
3377
+
3378
+ | Keys | Action |
3379
+ | ------------ | ------------------------------- |
3380
+ | `↑ ↓` | 세로 탭 사이 이동 및 선택 |
3381
+ | `Home / End` | 첫 번째 또는 마지막 탭으로 이동 |
3382
+
3299
3383
  #### ColumnToggler
3300
3384
 
3301
3385
  **Import:** `import { ColumnToggler } from "@reopt-ai/opt-ui"`
@@ -3312,13 +3396,22 @@ import { AppShell } from "@reopt-ai/opt-ui";
3312
3396
  **Import:** `import { TreeTable } from "@reopt-ai/opt-ui"`
3313
3397
  **Dependencies:** data-table (shells)
3314
3398
 
3315
- | Prop | Type | Required | Default | Description |
3316
- | ----------------- | -------------------- | -------- | ------- | ------------------ |
3317
- | `data` | `TreeNode<T>[]` | Yes | | 트리 노드 배열 |
3318
- | `columns` | `TreeColumnDef<T>[]` | Yes | | 컬럼 정의 |
3319
- | `defaultExpanded` | `string[]` | | [] | 기본 펼침 노드 ID |
3320
- | `indentSize` | `number` | | 24 | 들여쓰기 크기 (px) |
3321
- | `className` | `string` | | | 커스텀 CSS 클래스 |
3399
+ | Prop | Type | Required | Default | Description |
3400
+ | ----------------- | ------------------------------- | -------- | ------- | ----------------------------------------------- |
3401
+ | `data` | `TreeNode<T>[]` | Yes | | 트리 노드 배열 |
3402
+ | `columns` | `TreeColumnDef<T>[]` | Yes | | 컬럼 정의 |
3403
+ | `defaultExpanded` | `string[]` | | [] | 기본 펼침 노드 ID |
3404
+ | `indentSize` | `number` | | 24 | 들여쓰기 크기 (px) |
3405
+ | `getRowLabel` | `(node: TreeNode<T>) => string` | | | 행별 펼침/접기 컨트롤의 접근 가능한 이름 생성기 |
3406
+ | `aria-label` | `string` | | | 표의 접근 가능한 이름 |
3407
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
3408
+
3409
+ **Keyboard Shortcuts:**
3410
+
3411
+ | Keys | Action |
3412
+ | --------------- | -------------------------- |
3413
+ | `Tab` | 펼침/접기 컨트롤 사이 이동 |
3414
+ | `Enter / Space` | 하위 행 펼치기 또는 접기 |
3322
3415
 
3323
3416
  #### InlineEditTable
3324
3417
 
@@ -3338,13 +3431,13 @@ import { AppShell } from "@reopt-ai/opt-ui";
3338
3431
  **Import:** `import { KanbanBoard } from "@reopt-ai/opt-ui"`
3339
3432
  **Dependencies:** scroll-area (core)
3340
3433
 
3341
- | Prop | Type | Required | Default | Description |
3342
- | -------------- | ------------------------------------------- | -------- | ------- | -------------------------------- |
3343
- | `columns` | `KanbanColumn<T>[]` | Yes | | 컬럼 목록 (각 컬럼에 items 배열) |
3344
- | `onDragEnd` | `(itemId, fromCol, toCol, toIndex) => void` | Yes | | 드래그 완료 콜백 |
3345
- | `renderCard` | `(item: T) => ReactNode` | Yes | | 카드 렌더링 함수 |
3346
- | `keyExtractor` | `(item: T) => string` | Yes | | 항목 키 추출기 |
3347
- | `className` | `string` | | | 커스텀 CSS 클래스 |
3434
+ | Prop | Type | Required | Default | Description |
3435
+ | -------------- | ------------------------------------------------------------------------------------- | -------- | ------- | -------------------------------- |
3436
+ | `columns` | `KanbanColumn<T>[]` | Yes | | 컬럼 목록 (각 컬럼에 items 배열) |
3437
+ | `onDragEnd` | `(itemId: string, fromColumnId: string, toColumnId: string, toIndex: number) => void` | Yes | | 드래그 완료 콜백 |
3438
+ | `renderCard` | `(item: T) => ReactNode` | Yes | | 카드 렌더링 함수 |
3439
+ | `keyExtractor` | `(item: T) => string` | Yes | | 항목 키 추출기 |
3440
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
3348
3441
 
3349
3442
  #### RichTextEditor
3350
3443
 
@@ -3402,25 +3495,34 @@ import { AppShell } from "@reopt-ai/opt-ui";
3402
3495
  **Import:** `import { DataImportWizard } from "@reopt-ai/opt-ui"`
3403
3496
  **Dependencies:** button (core)
3404
3497
 
3405
- | Prop | Type | Required | Default | Description |
3406
- | ----------------- | ------------------------- | -------- | ------- | ------------------- |
3407
- | `fields` | `ImportFieldDef[]` | Yes | | 매핑 대상 필드 목록 |
3408
- | `onImport` | `(mapping, data) => void` | Yes | | 임포트 확정 콜백 |
3409
- | `acceptedFormats` | `string` | | ".csv" | 허용 파일 형식 |
3410
- | `className` | `string` | | | 커스텀 CSS 클래스 |
3498
+ | Prop | Type | Required | Default | Description |
3499
+ | ----------------- | ------------------------------------------------------------- | -------- | ------- | ------------------- |
3500
+ | `fields` | `ImportFieldDef[]` | Yes | | 매핑 대상 필드 목록 |
3501
+ | `onImport` | `(mapping: Record<string, string>, data: string[][]) => void` | Yes | | 임포트 확정 콜백 |
3502
+ | `acceptedFormats` | `string` | | ".csv" | 허용 파일 형식 |
3503
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
3411
3504
 
3412
3505
  #### MegaMenu
3413
3506
 
3414
3507
  **Import:** `import { MegaMenu } from "@reopt-ai/opt-ui"`
3415
3508
  **Dependencies:** popover (core)
3416
3509
 
3417
- | Prop | Type | Required | Default | Description |
3418
- | -------------- | ------------------- | -------- | ------- | ------------------ |
3419
- | `menus` | `MegaMenuSection[]` | Yes | | 메뉴 섹션 배열 |
3420
- | `columns` | `number` | | 3 | 그리드 컬럼 수 |
3421
- | `footer` | `ReactNode` | | | 하단 footer 슬롯 |
3422
- | `triggerLabel` | `string` | | "Menu" | 트리거 버튼 텍스트 |
3423
- | `className` | `string` | | | 커스텀 CSS 클래스 |
3510
+ | Prop | Type | Required | Default | Description |
3511
+ | -------------- | ------------------- | -------- | ------- | ------------------------------------------- |
3512
+ | `menus` | `MegaMenuSection[]` | Yes | | 메뉴 섹션 배열 |
3513
+ | `columns` | `number` | | 3 | 그리드 컬럼 수 |
3514
+ | `footer` | `ReactNode` | | | 하단 footer 슬롯 |
3515
+ | `triggerLabel` | `string` | | "Menu" | 트리거 버튼 텍스트 |
3516
+ | `aria-label` | `string` | | | 열린 메가 메뉴 탐색 영역의 접근 가능한 이름 |
3517
+ | `className` | `string` | | | 커스텀 CSS 클래스 |
3518
+
3519
+ **Keyboard Shortcuts:**
3520
+
3521
+ | Keys | Action |
3522
+ | --------------- | -------------------------- |
3523
+ | `Enter / Space` | 메가 메뉴 열기 |
3524
+ | `Tab` | 메뉴 링크와 액션 사이 이동 |
3525
+ | `Escape` | 메가 메뉴 닫기 |
3424
3526
 
3425
3527
  #### BulkActions
3426
3528
 
@@ -3610,16 +3712,19 @@ const messages = [
3610
3712
 
3611
3713
  **Import:** `import { TimeSeriesPanel } from "@reopt-ai/opt-ui"`
3612
3714
 
3613
- | Prop | Type | Required | Default | Description |
3614
- | ------------------ | ---------------------------- | -------- | ------- | --------------------------------------------- |
3615
- | `data` | `TimeSeriesPoint[]` | Yes | | 시계열 데이터 |
3616
- | `series` | `TimeSeriesDef[]` | Yes | | 시리즈 정의 |
3617
- | `range` | `TimeRange` | Yes | | 조회 구간 — 차트 축도 여기에 고정됩니다 |
3618
- | `onRangeChange` | `(range: TimeRange) => void` | Yes | | 드래그 줌·컨트롤 변경으로 구간이 바뀔 때 호출 |
3619
- | `showRangeControl` | `boolean` | | true | 헤더에 TimeRangeControl 렌더 |
3620
- | `toggleableLegend` | `boolean` | | false | 범례 클릭으로 시리즈 숨김 |
3621
- | `annotations` | `TimeSeriesAnnotation[]` | | | 시간축 마커/구간 |
3622
- | `height` | `number` | | 280 | 차트 높이 |
3715
+ | Prop | Type | Required | Default | Description |
3716
+ | ------------------ | ---------------------------- | -------- | ------- | --------------------------------------------------------- |
3717
+ | `title` | `ReactNode` | | | 패널 제목. aria-label이 없으면 region 이름으로 연결됩니다 |
3718
+ | `description` | `ReactNode` | | | 패널 보조 설명 |
3719
+ | `data` | `TimeSeriesPoint[]` | Yes | | 시계열 데이터 |
3720
+ | `series` | `TimeSeriesDef[]` | Yes | | 시리즈 정의 |
3721
+ | `range` | `TimeRange` | Yes | | 조회 구간 — 차트 축도 여기에 고정됩니다 |
3722
+ | `onRangeChange` | `(range: TimeRange) => void` | Yes | | 드래그 줌·컨트롤 변경으로 구간이 바뀔 때 호출 |
3723
+ | `showRangeControl` | `boolean` | | true | 헤더에 TimeRangeControl 렌더 |
3724
+ | `toggleableLegend` | `boolean` | | false | 범례 클릭으로 시리즈 숨김 |
3725
+ | `annotations` | `TimeSeriesAnnotation[]` | | | 시간축 마커/구간 |
3726
+ | `height` | `number` | | 280 | 차트 높이 |
3727
+ | `aria-label` | `string` | | | 제목 대신 사용할 패널 region의 접근 가능한 이름 |
3623
3728
 
3624
3729
  #### LogTable
3625
3730
 
@@ -3669,4 +3774,92 @@ const messages = [
3669
3774
  | `onToggleColumn` | `(field: string, next: boolean) => void` | | | 컬럼 추가/제거 |
3670
3775
  | `onFilter` | `(field: string, value: string, intent: "include" \| "exclude") => void` | | | 값 기준 필터 |
3671
3776
 
3777
+ #### InspectorLayout
3778
+
3779
+ **Import:** `import { InspectorLayout } from "@reopt-ai/opt-ui"`
3780
+
3781
+ | Prop | Type | Required | Default | Description |
3782
+ | ------------- | ----------------------- | -------- | ------- | ---------------------------------------------- |
3783
+ | `children` | `ReactNode` | Yes | | 목록. 인스펙터가 열려도 마운트와 스크롤을 유지 |
3784
+ | `inspector` | `ReactNode` | | | 인스펙터 내용. 닫혀 있으면 렌더하지 않음 |
3785
+ | `open` | `boolean` | Yes | | 열림 |
3786
+ | `onClose` | `() => void` | Yes | | 닫기 |
3787
+ | `title` | `ReactNode` | | | 인스펙터 제목 |
3788
+ | `description` | `ReactNode` | | | 제목 아래 한 줄 |
3789
+ | `actions` | `ReactNode` | | | 닫기 버튼 옆 컨트롤 |
3790
+ | `footer` | `ReactNode` | | | 인스펙터 하단 |
3791
+ | `breakpoint` | `"lg" \| "xl" \| "2xl"` | | "xl" | 이 폭 이상이면 push |
3792
+ | `width` | `"sm" \| "md" \| "lg"` | | "md" | push 레이아웃에서의 인스펙터 폭 |
3793
+
3794
+ #### QueryFilterBar
3795
+
3796
+ **Import:** `import { QueryFilterBar } from "@reopt-ai/opt-ui"`
3797
+
3798
+ | Prop | Type | Required | Default | Description |
3799
+ | ---------------- | ------------------------ | -------- | ------- | -------------------------------------------------------------------------- |
3800
+ | `value` | `Query` | Yes | | 필터 상태 전부 |
3801
+ | `onChange` | `(query: Query) => void` | Yes | | Query 변경 |
3802
+ | `filters` | `QueryFilterDef[]` | Yes | | 필터 컨트롤 정의 (is / field_value_selection / field_value_toggle) |
3803
+ | `fields` | `QueryField[]` | | | 텍스트 입력 자동완성 |
3804
+ | `actions` | `ReactNode` | | | 필터 행 끝 슬롯 |
3805
+ | `showClauses` | `boolean` | | true | 절을 제거 가능한 칩으로 표시 |
3806
+ | `live` | `boolean` | | false | 매 입력마다 커밋 |
3807
+ | `disabled` | `boolean` | | false | 전체 비활성 |
3808
+ | `queryBarLabels` | `QueryBarLabels` | | | QueryBar로 통과되는 나머지 문구. placeholder/ariaLabel은 labels가 이깁니다 |
3809
+
3810
+ #### CatalogFrame
3811
+
3812
+ **Import:** `import { CatalogFrame } from "@reopt-ai/opt-ui"`
3813
+
3814
+ **CatalogFrame:**
3815
+
3816
+ | Prop | Type | Required | Default | Description |
3817
+ | ---------------------- | ------------------------------ | -------- | ------- | ----------------------------------------------------------------- |
3818
+ | `children` | `ReactNode` | Yes | | 테이블. 빈/에러 상태에서는 대체됨 |
3819
+ | `isEmpty` | `boolean` | Yes | | 테이블이 0행인지 |
3820
+ | `query` | `Query` | Yes | | 필터 상태 |
3821
+ | `onQueryChange` | `(query: Query) => void` | Yes | | Query 변경 |
3822
+ | `filters` | `QueryFilterDef[]` | | | 필터 정의 |
3823
+ | `stats` | `StatCardType[]` | | | 통계 카드 |
3824
+ | `onStatClick` | `(stat: StatCardType) => void` | | | 카드 클릭 = 필터 |
3825
+ | `notice` | `ReactNode` | | | 목록 위 고지 |
3826
+ | `emptyActions` | `ReactNode` | | | 필터 없는 빈 상태의 다음 행동 (필터된 빈 상태는 필터 지우기 유지) |
3827
+ | `header` | `ReactNode` | | | 헤더 슬롯 |
3828
+ | `actions` | `ReactNode` | | | 액션 슬롯 |
3829
+ | `toolbar` | `ReactNode` | | | 통계와 필터 사이 컨트롤 (스코프 세그먼트 등) |
3830
+ | `inspector` | `ReactNode` | | | 인스펙터 내용 |
3831
+ | `inspectorOpen` | `boolean` | Yes | | 인스펙터 열림 |
3832
+ | `onInspectorClose` | `() => void` | Yes | | 인스펙터 닫기 |
3833
+ | `inspectorTitle` | `ReactNode` | | | 인스펙터 제목 |
3834
+ | `inspectorDescription` | `ReactNode` | | | 인스펙터 설명 |
3835
+ | `inspectorActions` | `ReactNode` | | | 인스펙터 헤더 컨트롤 |
3836
+ | `inspectorFooter` | `ReactNode` | | | 인스펙터 하단 |
3837
+ | `inspectorWidth` | `"sm" \| "md" \| "lg"` | | | push 레이아웃 폭 |
3838
+ | `page` | `number` | | 1 | 현재 페이지 |
3839
+ | `pageSize` | `number` | | 50 | 페이지 크기 |
3840
+ | `totalCount` | `number` | | | 필터 반영 총 개수 |
3841
+ | `onPageChange` | `(page: number) => void` | | | 페이지 변경 |
3842
+ | `selectedKeys` | `string[]` | | | 선택된 행 |
3843
+ | `onSelectionChange` | `(keys: string[]) => void` | | | 선택 변경. 필터·페이지가 바뀌면 프레임이 비웁니다 |
3844
+ | `bulkActions` | `FloatingAction[]` | | | 일괄 작업 |
3845
+ | `onBulkAction` | `(actionId: string) => void` | | | 일괄 작업 실행 |
3846
+ | `error` | `ReactNode` | | | 읽기 실패. 빈 목록과 다른 답 |
3847
+ | `onRetry` | `() => void` | | | 재시도 |
3848
+ | `labels` | `CatalogFrameLabels` | | | 빈/필터된 빈/에러 문구 |
3849
+
3850
+ **CatalogRowActions:**
3851
+
3852
+ | Prop | Type | Required | Default | Description |
3853
+ | -------------- | ------------------------- | -------- | ------- | ------------------------------------------------------- |
3854
+ | `item` | `T` | Yes | | 이 행의 항목 |
3855
+ | `actions` | `CatalogRowAction<T>[]` | Yes | | 행 액션 |
3856
+ | `visibleCount` | `number` | | 2 | 오버플로 전에 노출할 개수. available 필터링 후에 적용됨 |
3857
+ | `labels` | `CatalogRowActionsLabels` | | | 그룹·오버플로 라벨 |
3858
+
3859
+ **CatalogCellControls:**
3860
+
3861
+ | Prop | Type | Required | Default | Description |
3862
+ | ---------- | ----------- | -------- | ------- | ---------------------------------- |
3863
+ | `children` | `ReactNode` | Yes | | 행 클릭으로 새면 안 되는 셀 컨트롤 |
3864
+
3672
3865
  ### Surface Layer