@reopt-ai/opt-ui 1.13.0 → 1.14.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 (37) hide show
  1. package/COMPONENT_CATALOG.md +426 -58
  2. package/README.md +9 -7
  3. package/dist/core/index.cjs +1 -1
  4. package/dist/core/index.d.cts +2 -2
  5. package/dist/core/index.d.ts +2 -2
  6. package/dist/core/index.js +1 -1
  7. package/dist/docs/02-components/01-core.md +225 -26
  8. package/dist/docs/02-components/02-visuals.md +1 -1
  9. package/dist/docs/02-components/03-shells.md +203 -32
  10. package/dist/docs/02-components/04-surfaces.md +1 -1
  11. package/dist/docs/02-components/index.md +4 -4
  12. package/dist/{field-sidebar-Dz7J4ett.d.ts → field-sidebar-CJ4HxP8D.d.cts} +1 -1
  13. package/dist/{field-sidebar-D-rwuN_w.d.cts → field-sidebar-DnhpcT2A.d.ts} +1 -1
  14. package/dist/{field-sidebar-CxxSK4JO.cjs → field-sidebar-ePqFX6MN.cjs} +13 -12
  15. package/dist/{field-sidebar-CRdToHRO.js → field-sidebar-mSVCMAZp.js} +13 -12
  16. package/dist/id-registry.cjs +8 -0
  17. package/dist/id-registry.js +8 -0
  18. package/dist/id-registry.json +17 -0
  19. package/dist/index.cjs +756 -51
  20. package/dist/index.d.cts +196 -10
  21. package/dist/index.d.ts +196 -10
  22. package/dist/index.js +750 -53
  23. package/dist/{key-pad-menu-0KWOnELe.cjs → key-pad-menu-BgtSL3xe.cjs} +9 -6
  24. package/dist/{key-pad-menu-DMmbQ1jF.js → key-pad-menu-CqFI6la9.js} +9 -6
  25. package/dist/{key-pad-menu-BOVu97bj.d.cts → key-pad-menu-D6pYzaj-.d.cts} +12 -3
  26. package/dist/{key-pad-menu-NlZ9zNF8.d.ts → key-pad-menu-Yh7Fpb8m.d.ts} +12 -3
  27. package/dist/meta.cjs +430 -19
  28. package/dist/meta.js +430 -19
  29. package/dist/shells/index.cjs +1 -1
  30. package/dist/shells/index.d.cts +1 -1
  31. package/dist/shells/index.d.ts +1 -1
  32. package/dist/shells/index.js +1 -1
  33. package/dist/{text-truncate-eMzvU_7k.d.cts → text-truncate-Bbul-jMD.d.cts} +1 -30
  34. package/dist/{text-truncate-eMzvU_7k.d.ts → text-truncate-Bbul-jMD.d.ts} +1 -30
  35. package/dist/theme/server.d.cts +2 -2
  36. package/dist/theme/server.d.ts +2 -2
  37. package/package.json +2 -2
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: "Shell Components"
3
- description: "95 Shell layer components — props, examples, keyboard shortcuts."
4
- version: "1.13.0"
3
+ description: "96 Shell layer components — props, examples, keyboard shortcuts."
4
+ version: "1.14.0"
5
5
  generated: true
6
6
  ---
7
7
 
8
- # Shell Components (95)
8
+ # Shell Components (96)
9
9
 
10
10
  ## Navigation & Layout
11
11
 
@@ -498,6 +498,38 @@ import { DataTable } from "@reopt-ai/opt-ui";
498
498
  | `percentageFractionDigits` | `number` | | 1 | percentage 포맷 시 소수점 자리수 |
499
499
  | `loading` | `boolean` | | false | 로딩 시 스켈레톤 표시 |
500
500
 
501
+ **Examples:**
502
+
503
+ _의미가 다른 통계 비교:_
504
+
505
+ ```tsx
506
+ import { SummaryRow } from "@reopt-ai/opt-ui";
507
+ export function Example() {
508
+ return (
509
+ <SummaryRow
510
+ columns={2}
511
+ stats={[
512
+ {
513
+ id: "orders",
514
+ title: "주문",
515
+ value: "120",
516
+ change: "+10%",
517
+ trend: "up",
518
+ },
519
+ {
520
+ id: "errors",
521
+ title: "오류",
522
+ value: "2",
523
+ change: "-50%",
524
+ trend: "down",
525
+ polarity: "negative",
526
+ },
527
+ ]}
528
+ />
529
+ );
530
+ }
531
+ ```
532
+
501
533
  ### CodeSnippetViewer
502
534
 
503
535
  > 코드 스니펫 뷰어. 줄 번호, 복사 버튼, 포커스 가능한 스크롤 영역, syntaxTheme 톤을 지원합니다.
@@ -882,6 +914,27 @@ const filters = [
882
914
  | `presets` | `TimePresetDef[]` | | | 빠른 프리셋 목록 (Today, Last 7d 등) |
883
915
  | `labels` | `TimeRangeSelectorLabels` | | | i18n용 라벨 오버라이드 |
884
916
 
917
+ **Examples:**
918
+
919
+ _제어되는 조회 기간:_
920
+
921
+ ```tsx
922
+ "use client";
923
+ import { useState } from "react";
924
+ import { TimeRangeSelector, type DateRange } from "@reopt-ai/opt-ui";
925
+ export function Example() {
926
+ const [range, setRange] = useState<DateRange>({ start: null, end: null });
927
+ return (
928
+ <TimeRangeSelector
929
+ value={range}
930
+ onChange={setRange}
931
+ labels={{ title: "조회 기간", placeholder: "기간 선택" }}
932
+ presets={[{ label: "최근 7일", days: 7 }]}
933
+ />
934
+ );
935
+ }
936
+ ```
937
+
885
938
  ### ComparisonSelector
886
939
 
887
940
  > 비교 선택기. 고유 레이블이 연결된 Select × 2 + Swap 버튼 조합. CohortComparison, FunnelAnalysis 등에서 사용합니다.
@@ -1378,6 +1431,24 @@ const fields = [
1378
1431
  | `toast` | `ToastMessage` | Yes | | 토스트 메시지 객체 |
1379
1432
  | `onDismiss` | `() => void` | Yes | | 닫기 핸들러 |
1380
1433
 
1434
+ **Examples:**
1435
+
1436
+ _사용자 동작의 결과 알림:_
1437
+
1438
+ ```tsx
1439
+ "use client";
1440
+ import { Button, ToastProvider, toast } from "@reopt-ai/opt-ui";
1441
+ export function Example() {
1442
+ return (
1443
+ <ToastProvider>
1444
+ <Button onClick={() => toast.success("알림 동작을 확인했습니다")}>
1445
+ 알림 테스트
1446
+ </Button>
1447
+ </ToastProvider>
1448
+ );
1449
+ }
1450
+ ```
1451
+
1381
1452
  ## Development
1382
1453
 
1383
1454
  | Component | Description | Key Exports |
@@ -1423,35 +1494,36 @@ const fields = [
1423
1494
 
1424
1495
  ## Other
1425
1496
 
1426
- | Component | Description | Key Exports |
1427
- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
1428
- | PageAside | Sticky 페이지 사이드 aside chrome. 고정 너비 + header/body/footer 3-slot. | `PageAside` |
1429
- | FailureList | 실패 목록 패널. severity별 색상 강조, 그룹핑, 액션 슬롯을 지원합니다. | `FailureList` |
1430
- | KeyValueEditor | 키-값 쌍 편집기. 동적 행 추가/삭제, 비밀값 토글, 유효성 검사를 지원합니다. | `KeyValueEditor` |
1431
- | EventTimeline | 이벤트를 순서로 읽히게 하는 타임라인. 인접 이벤트 사이의 경과 시간을 라벨링하고, 속성 페이로드를 제자리에서 펼치며, 세션 단위 그룹핑을 지원한다. | `EventTimeline` |
1432
- | ScoreBreakdown | 합성 점수를 축별로 분해해 보여준다. 총점과 함께 축의 값·가중치·의미를 노출해 '43'을 판정이 아니라 발견으로 만든다. | `ScoreBreakdown` |
1433
- | Flyout | 목록을 화면에 레코드를 옆에서 보여주는 상세 패널. 모달이 아니다 포커스 트랩·aria-modal·inert 없이 Escape로 닫고 포커스를 되돌린다. | `Flyout` |
1434
- | AuditTimeline | 변경 이력 타임라인. 액션별 색상 코딩 + 확장 가능한 diff 뷰. | `AuditTimeline` |
1435
- | ChatSidebar | AI 채팅 사이드바. 대화 목록, 검색, 대화 버튼. | `ChatSidebar` |
1436
- | ChatInput | 채팅 입력 컴포넌트. 자동 리사이즈 textarea, 파일 첨부, 모델/스타일 Select. | `ChatInput` |
1437
- | ChatMessageList | 채팅 메시지 목록. 역할별 말풍선, 타이핑 인디케이터, 자동 스크롤. | `ChatMessageList` |
1438
- | TimeRangeControl | date math(now-7d, now/d) 기반 시간 범위 컨트롤. quick select, 프리셋/최근 사용, 명시적 Update, 자동 갱신, 창 이동·확대/축소 버튼을 제공합니다. | `TimeRangeControl`, `DEFAULT_TIME_PRESETS` |
1439
- | TimeSeriesPanel | 시간 범위 컨트롤과 시계열 차트를 단위로 묶은 패널. 드래그 줌과 히스토리(되돌리기), 범례 토글을 포함합니다. | `TimeSeriesPanel` |
1440
- | LogTable | 계속 도착하는 로그용 윈도잉 테이블. 컬럼 정의 기반, 상단 삽입 스크롤 위치 보존, follow 상태 보고, 셀 값 즉시 필터, 밀도·정렬을 지원합니다. | `LogTable` |
1441
- | QueryBar | 검색과 필터를 입력으로 합친 쿼리 바. field:value, -부정, (a or b), 비교 연산, 필드·값 자동완성, 절(clause) 칩을 지원합니다. | `QueryBar` |
1442
- | FieldSidebar | 데이터에 어떤 필드가 있고 필드가 무슨 값을 갖는지 보여주는 사이드바. 분포 막대, 컬럼으로 승격, 기준 포함/제외 필터를 제공합니다. | `FieldSidebar` |
1443
- | InspectorLayout | 목록과 인스펙터의 2-pane 레이아웃. 넓으면 밀어내고(push) 좁으면 덮으며(overlay), 닫을 포커스를 열었던 자리로 되돌립니다. | `InspectorLayout` |
1444
- | QueryFilterBar | QueryBar와 필터 버튼이 하나의 Query를 공유합니다. 버튼은 상태를 갖지 않고 Query를 읽어 활성 여부를 계산합니다. | `QueryFilterBar`, `hasActiveQuery` |
1445
- | CatalogFrame | 카탈로그 목록의 공통 뼈대. 헤더·통계·고지·필터·인스펙터·페이지네이션·일괄 작업과 빈/에러 상태를 담고, 필터나 페이지가 바뀌면 선택을 비웁니다. | `CatalogFrame`, `CatalogRowActions`, `CatalogCellControls` |
1446
- | SchemaTree | 쿼리할 있는 테이블과 컬럼을 타입 글리프와 함께 보여주는 트리. 테이블·컬럼을 함께 검색하고, 이름을 커서에 삽입하거나 테이블을 미리보기합니다. | `SchemaTree` |
1447
- | QueryToolbar | 실행 버튼 하나가 상태를 말하는 쿼리 툴바. 변경됨/현재/실행 중을 색과 문구로 구분하고, 실행 중이면 취소로 바뀌며, 선택 영역·전체 실행은 분할 버튼 뒤에 둡니다. | `QueryToolbar` |
1448
- | QueryOutputPane | 쿼리 결과가 놓이는 출력 패널. 대기·실행 중·오류·취소·완료 상태를 그리고, 완료는 표·차트·좌우 분할로 전환하며, 상태바에 수·경과·읽은 바이트·절단 여부를 남깁니다. | `QueryOutputPane` |
1449
- | QueryResultChart | 결과 행을 차트로 그리는 빌더. 문자·날짜 컬럼을 축으로, 숫자 컬럼을 값으로 고르고, 숫자면 숫자로 보여줍니다. 설정은 호출자가 들고 있어 저장 쿼리와 함께 보관됩니다. | `QueryResultChart` |
1450
- | QueryFiltersMenu | 기간과 속성 조건을 데이터로 들고 {filters} 플레이스홀더로 SQL에 전달하는 메뉴. 플레이스홀더가 없으면 조건이 적용되지 않는다고 경고하고 삽입 버튼을 제공합니다. | `QueryFiltersMenu` |
1451
- | QueryVariablesMenu | 실행마다 바뀌는 값을 이름 붙여 두는 변수 메뉴. SQL은 {variables.name}으로 참조하고 치환은 호출자가 합니다. | `QueryVariablesMenu` |
1452
- | QueryHistoryList | 실행 이력 목록. 실행의 성공/실패, 시각, 수, 경과를 보여주고 편집기로 되돌리거나 다시 실행합니다. | `QueryHistoryList` |
1453
- | SaveQueryDialog | 쿼리에 이름·설명·공개 여부를 붙여 저장하는 다이얼로그. 편집기에 문장이 여럿이면 어느 문장을 저장할지 넘겨 보며 고릅니다. | `SaveQueryDialog` |
1454
- | QueryWorkspace | 스키마·편집기·출력의 3-pane 쿼리 워크스페이스. 패널은 리사이즈되고 사이드바는 접히며, storageKey로 레이아웃을 기억합니다. 툴바·편집기·출력은 슬롯입니다. | `QueryWorkspace` |
1497
+ | Component | Description | Key Exports |
1498
+ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1499
+ | PageAside | Sticky 페이지 사이드 aside chrome. 고정 너비 + header/body/footer 3-slot. | `PageAside` |
1500
+ | FailureList | 실패 목록 패널. severity별 색상 강조, 그룹핑, 액션 슬롯을 지원합니다. | `FailureList` |
1501
+ | KeyValueEditor | 키-값 쌍 편집기. 동적 행 추가/삭제, 비밀값 토글, 유효성 검사를 지원합니다. | `KeyValueEditor` |
1502
+ | CriteriaBuilder | 도메인 무관 2단계 조건 트리 편집기. 그룹 AND/OR, 순서·복제·부정·오류를 셸이 맡고 조건 문장은 소비자가 Expression 칩으로 렌더링합니다. | `CriteriaBuilder`, `criteriaBuilderMove`, `criteriaBuilderDuplicate`, `criteriaBuilderRemove`, `criteriaBuilderInsert`, `criteriaBuilderRemoveGroup`, `criteriaBuilderDuplicateGroup`, `criteriaGroupLetter` |
1503
+ | EventTimeline | 이벤트를 순서로 읽히게 하는 타임라인. 인접 이벤트 사이의 경과 시간을 라벨링하고, 속성 페이로드를 제자리에서 펼치며, 세션 단위 그룹핑을 지원한다. | `EventTimeline` |
1504
+ | ScoreBreakdown | 합성 점수를 축별로 분해해 보여준다. 총점과 함께 축의 값·가중치·의미를 노출해 '43'을 판정이 아니라 발견으로 만든다. | `ScoreBreakdown` |
1505
+ | Flyout | 목록을 화면에 레코드를 옆에서 보여주는 상세 패널. 모달이 아니다 — 포커스 트랩·aria-modal·inert 없이 Escape로 닫고 포커스를 되돌린다. | `Flyout` |
1506
+ | AuditTimeline | 변경 이력 타임라인. 액션별 색상 코딩 + 확장 가능한 diff 뷰. | `AuditTimeline` |
1507
+ | ChatSidebar | AI 채팅 사이드바. 대화 목록, 검색, 대화 버튼. | `ChatSidebar` |
1508
+ | ChatInput | 채팅 입력 컴포넌트. 자동 리사이즈 textarea, 파일 첨부, 모델/스타일 Select. | `ChatInput` |
1509
+ | ChatMessageList | 채팅 메시지 목록. 역할별 말풍선, 타이핑 인디케이터, 자동 스크롤. | `ChatMessageList` |
1510
+ | TimeRangeControl | date math(now-7d, now/d) 기반 시간 범위 컨트롤. quick select, 프리셋/최근 사용, 명시적 Update, 자동 갱신, 이동·확대/축소 버튼을 제공합니다. | `TimeRangeControl`, `DEFAULT_TIME_PRESETS` |
1511
+ | TimeSeriesPanel | 시간 범위 컨트롤과 시계열 차트를 단위로 묶은 패널. 드래그 줌과 히스토리(되돌리기), 범례 토글을 포함합니다. | `TimeSeriesPanel` |
1512
+ | LogTable | 계속 도착하는 로그용 윈도잉 테이블. 컬럼 정의 기반, 상단 삽입 스크롤 위치 보존, follow 상태 보고, 값 즉시 필터, 밀도·정렬을 지원합니다. | `LogTable` |
1513
+ | QueryBar | 검색과 필터를 입력으로 합친 쿼리 바. field:value, -부정, (a or b), 비교 연산, 필드·값 자동완성, 절(clause) 칩을 지원합니다. | `QueryBar` |
1514
+ | FieldSidebar | 데이터에 어떤 필드가 있고 필드가 무슨 값을 갖는지 보여주는 사이드바. 분포 막대, 컬럼으로 승격, 값 기준 포함/제외 필터를 제공합니다. | `FieldSidebar` |
1515
+ | InspectorLayout | 목록과 인스펙터의 2-pane 레이아웃. 넓으면 밀어내고(push) 좁으면 덮으며(overlay), 닫을 포커스를 열었던 자리로 되돌립니다. | `InspectorLayout` |
1516
+ | QueryFilterBar | QueryBar와 필터 버튼이 하나의 Query를 공유합니다. 버튼은 상태를 갖지 않고 Query를 읽어 활성 여부를 계산합니다. | `QueryFilterBar`, `hasActiveQuery` |
1517
+ | CatalogFrame | 카탈로그 목록의 공통 뼈대. 헤더·통계·고지·필터·인스펙터·페이지네이션·일괄 작업과 빈/에러 상태를 담고, 필터나 페이지가 바뀌면 선택을 비웁니다. | `CatalogFrame`, `CatalogRowActions`, `CatalogCellControls` |
1518
+ | SchemaTree | 쿼리할 있는 테이블과 컬럼을 타입 글리프와 함께 보여주는 트리. 테이블·컬럼을 함께 검색하고, 이름을 커서에 삽입하거나 테이블을 미리보기합니다. | `SchemaTree` |
1519
+ | QueryToolbar | 실행 버튼 하나가 상태를 말하는 쿼리 툴바. 변경됨/현재/실행 중을 색과 문구로 구분하고, 실행 중이면 취소로 바뀌며, 선택 영역·전체 실행은 분할 버튼 뒤에 둡니다. | `QueryToolbar` |
1520
+ | QueryOutputPane | 쿼리 결과가 놓이는 출력 패널. 대기·실행 중·오류·취소·완료 상태를 그리고, 완료는 표·차트·좌우 분할로 전환하며, 상태바에수·경과·읽은 바이트·절단 여부를 남깁니다. | `QueryOutputPane` |
1521
+ | QueryResultChart | 결과 행을 차트로 그리는 빌더. 문자·날짜 컬럼을 축으로, 숫자 컬럼을 값으로 고르고, 숫자면 숫자로 보여줍니다. 설정은 호출자가 들고 있어 저장 쿼리와 함께 보관됩니다. | `QueryResultChart` |
1522
+ | QueryFiltersMenu | 기간과 속성 조건을 데이터로 들고 {filters} 플레이스홀더로 SQL에 전달하는 메뉴. 플레이스홀더가 없으면 조건이 적용되지 않는다고 경고하고 삽입 버튼을 제공합니다. | `QueryFiltersMenu` |
1523
+ | QueryVariablesMenu | 실행마다 바뀌는 값을 이름 붙여 두는 변수 메뉴. SQL은 {variables.name}으로 참조하고 치환은 호출자가 합니다. | `QueryVariablesMenu` |
1524
+ | QueryHistoryList | 실행 이력 목록. 실행의 성공/실패, 시각, 수, 경과를 보여주고 편집기로 되돌리거나 다시 실행합니다. | `QueryHistoryList` |
1525
+ | SaveQueryDialog | 쿼리에 이름·설명·공개 여부를 붙여 저장하는 다이얼로그. 편집기에 문장이 여럿이면 어느 문장을 저장할지 넘겨 보며 고릅니다. | `SaveQueryDialog` |
1526
+ | QueryWorkspace | 스키마·편집기·출력의 3-pane 쿼리 워크스페이스. 패널은 리사이즈되고 사이드바는 접히며, storageKey로 레이아웃을 기억합니다. 툴바·편집기·출력은 슬롯입니다. | `QueryWorkspace` |
1455
1527
 
1456
1528
  ### PageAside
1457
1529
 
@@ -1515,6 +1587,105 @@ const fields = [
1515
1587
  | ----- | ------------------ |
1516
1588
  | `Tab` | 키/값 필드 간 이동 |
1517
1589
 
1590
+ ### CriteriaBuilder
1591
+
1592
+ > 도메인 무관 2단계 조건 트리 편집기. 그룹 AND/OR, 순서·복제·부정·오류를 셸이 맡고 조건 문장은 소비자가 Expression 칩으로 렌더링합니다.
1593
+
1594
+ **Import:** `import { CriteriaBuilder } from "@reopt-ai/opt-ui"`
1595
+ **Dependencies:** segmented-control (core), dropdown-menu (core), button (core), callout (core), empty-state (core), kbd (core)
1596
+
1597
+ | Prop | Type | Required | Default | Description |
1598
+ | --------------------- | -------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------ |
1599
+ | `value` | `CriteriaBuilderValue<TCriterion>` | Yes | | 조건 트리. { logic, groups: [{ id, logic, criteria }] } |
1600
+ | `onChange` | `(next: CriteriaBuilderValue<TCriterion>) => void` | Yes | | 트리 변경 핸들러 |
1601
+ | `kinds` | `CriteriaBuilderKindOption[]` | Yes | | 조건 추가 메뉴 항목. group으로 섹션을 나누고 negatedLabel이 있으면 부정 항목을 따로 냅니다 |
1602
+ | `createCriterion` | `(kind: string, negate: boolean) => TCriterion` | Yes | | 메뉴 선택으로 만들 초기 조건. 고유 id를 돌려줘야 합니다 |
1603
+ | `renderCriterion` | `(criterion: TCriterion, api: CriteriaRenderApi<TCriterion>) => React.ReactNode` | Yes | | 조건 한 줄의 편집 가능한 문장 렌더러 |
1604
+ | `cloneCriterion` | `(criterion: TCriterion) => TCriterion` | | | 복제 시 만들 사본. 기본은 새 id를 붙인 얕은 복사 |
1605
+ | `createGroupId` | `() => string` | | | 셸이 만드는 그룹의 id. 기본 group-N |
1606
+ | `errors` | `Record<string, string>` | | | 조건 id 또는 그룹 id별 오류 메시지 |
1607
+ | `maxGroups` | `number` | | 10 | 그룹 최대 수 |
1608
+ | `maxCriteriaPerGroup` | `number` | | 20 | 그룹당 조건 최대 수 |
1609
+ | `allowNegation` | `boolean` | | true | 조건별 부정 토글 표시 |
1610
+ | `disabled` | `boolean` | | false | 전체 비활성화 |
1611
+ | `aside` | `React.ReactNode` | | | 넓은 화면에서 트리 옆, 좁은 화면에서 아래에 놓이는 미리보기 슬롯 |
1612
+ | `labels` | `CriteriaBuilderLabels` | | | i18n용 라벨 오버라이드 (기본 한국어) |
1613
+ | `className` | `string` | | | 루트 CSS 클래스 |
1614
+ | `aria-label` | `string` | | | 빌더 접근성 이름 |
1615
+
1616
+ **Keyboard Shortcuts:**
1617
+
1618
+ | Keys | Action |
1619
+ | ---- | ----------------------------------- |
1620
+ | `A` | 포커스된 그룹에 조건 추가 메뉴 열기 |
1621
+ | `G` | 그룹 추가 |
1622
+
1623
+ **Examples:**
1624
+
1625
+ _이벤트 조건 세그먼트:_
1626
+
1627
+ ```tsx
1628
+ "use client";
1629
+ import { useState } from "react";
1630
+ import {
1631
+ CriteriaBuilder,
1632
+ Expression,
1633
+ ExpressionGroup,
1634
+ type CriteriaBuilderValue,
1635
+ } from "@reopt-ai/opt-ui";
1636
+
1637
+ interface Criterion {
1638
+ id: string;
1639
+ kind: string;
1640
+ negate?: boolean;
1641
+ event: string;
1642
+ }
1643
+
1644
+ let seq = 0;
1645
+
1646
+ export function Example() {
1647
+ const [value, setValue] = useState<CriteriaBuilderValue<Criterion>>({
1648
+ logic: "and",
1649
+ groups: [
1650
+ {
1651
+ id: "g1",
1652
+ logic: "and",
1653
+ criteria: [{ id: "c1", kind: "performed", event: "purchase" }],
1654
+ },
1655
+ ],
1656
+ });
1657
+ return (
1658
+ <CriteriaBuilder
1659
+ value={value}
1660
+ onChange={setValue}
1661
+ kinds={[
1662
+ {
1663
+ kind: "performed",
1664
+ label: "이벤트를 수행함",
1665
+ negatedLabel: "이벤트를 수행하지 않음",
1666
+ },
1667
+ ]}
1668
+ createCriterion={(kind, negate) => ({
1669
+ id: `c${++seq}`,
1670
+ kind,
1671
+ negate,
1672
+ event: "",
1673
+ })}
1674
+ renderCriterion={(criterion, api) => (
1675
+ <ExpressionGroup>
1676
+ <Expression
1677
+ description={criterion.negate ? "수행하지 않음" : "수행함"}
1678
+ value={criterion.event || "이벤트 선택"}
1679
+ invalid={api.invalid || criterion.event === ""}
1680
+ onClick={() => api.update({ event: "purchase" })}
1681
+ />
1682
+ </ExpressionGroup>
1683
+ )}
1684
+ />
1685
+ );
1686
+ }
1687
+ ```
1688
+
1518
1689
  ### EventTimeline
1519
1690
 
1520
1691
  > 이벤트를 순서로 읽히게 하는 타임라인. 인접 이벤트 사이의 경과 시간을 라벨링하고, 속성 페이로드를 제자리에서 펼치며, 세션 단위 그룹핑을 지원한다.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Surface Components"
3
3
  description: "0 Surface layer components — props, examples, keyboard shortcuts."
4
- version: "1.13.0"
4
+ version: "1.14.0"
5
5
  generated: true
6
6
  ---
7
7
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Component Reference"
3
- description: "Complete reference for 169 @reopt-ai/opt-ui components across 4 layers."
4
- version: "1.13.0"
3
+ description: "Complete reference for 170 @reopt-ai/opt-ui components across 4 layers."
4
+ version: "1.14.0"
5
5
  generated: true
6
6
  ---
7
7
 
@@ -13,9 +13,9 @@ generated: true
13
13
  | --------- | ------- |
14
14
  | Core | 74 |
15
15
  | Visuals | 0 |
16
- | Shells | 95 |
16
+ | Shells | 96 |
17
17
  | Surfaces | 0 |
18
- | **Total** | **169** |
18
+ | **Total** | **170** |
19
19
 
20
20
  ## Component Selection Guide
21
21
 
@@ -1,5 +1,5 @@
1
1
 
2
- import { A as DomainDef, B as MenuDef, F as FailureItem, I as FaqItem, J as TabDef, K as SelectOption, O as CommandDef, U as NavItemDef, W as ProjectDef, _ as DateRangePreset, a as FieldDataType, et as ToolbarButtonDef, j as EnvGroupDef, k as DeploymentStep, m as DateRange, q as StatCard, r as TruncationSide, y as BranchDef, z as FormFieldDef } from "./text-truncate-eMzvU_7k.js";
2
+ import { B as ProjectDef, D as EnvGroupDef, E as DomainDef, F as FormFieldDef, H as SelectOption, I as MenuDef, M as FaqItem, T as DeploymentStep, U as StatCard, W as TabDef, X as ToolbarButtonDef, _ as DateRangePreset, a as FieldDataType, j as FailureItem, m as DateRange, r as TruncationSide, w as CommandDef, y as BranchDef, z as NavItemDef } from "./text-truncate-Bbul-jMD.cjs";
3
3
  import * as React from "react";
4
4
  import { ReactNode, Ref } from "react";
5
5
  import { TimeGranularity, TimeRange, TimeRange as TimeRange$1, TimeSeriesAnnotation, TimeSeriesChartProps, TimeSeriesDef, TimeSeriesPoint } from "@reopt-ai/opt-charts";
@@ -1,5 +1,5 @@
1
1
 
2
- import { A as DomainDef, B as MenuDef, F as FailureItem, I as FaqItem, J as TabDef, K as SelectOption, O as CommandDef, U as NavItemDef, W as ProjectDef, _ as DateRangePreset, a as FieldDataType, et as ToolbarButtonDef, j as EnvGroupDef, k as DeploymentStep, m as DateRange, q as StatCard, r as TruncationSide, y as BranchDef, z as FormFieldDef } from "./text-truncate-eMzvU_7k.cjs";
2
+ import { B as ProjectDef, D as EnvGroupDef, E as DomainDef, F as FormFieldDef, H as SelectOption, I as MenuDef, M as FaqItem, T as DeploymentStep, U as StatCard, W as TabDef, X as ToolbarButtonDef, _ as DateRangePreset, a as FieldDataType, j as FailureItem, m as DateRange, r as TruncationSide, w as CommandDef, y as BranchDef, z as NavItemDef } from "./text-truncate-Bbul-jMD.js";
3
3
  import * as React from "react";
4
4
  import { ReactNode, Ref } from "react";
5
5
  import { TimeGranularity, TimeRange, TimeRange as TimeRange$1, TimeSeriesAnnotation, TimeSeriesChartProps, TimeSeriesDef, TimeSeriesPoint } from "@reopt-ai/opt-charts";
@@ -4621,18 +4621,6 @@ function QueryHistoryList({ items, loading = false, onLoad, onRerun, onClear, he
4621
4621
  "data-opt-slug": "query-history-list.QueryHistoryList",
4622
4622
  children: [
4623
4623
  header,
4624
- onClear && items.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4625
- className: "flex flex-none justify-end px-2 pt-1",
4626
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.Button, {
4627
- variant: "ghost",
4628
- size: "sm",
4629
- onClick: onClear,
4630
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Trash2, {
4631
- className: "size-3.5",
4632
- "aria-hidden": true
4633
- }), labels.clear]
4634
- })
4635
- }),
4636
4624
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4637
4625
  className: "min-h-0 flex-1 overflow-y-auto",
4638
4626
  children: loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -4695,6 +4683,19 @@ function QueryHistoryList({ items, loading = false, onLoad, onRerun, onClear, he
4695
4683
  }, item.id);
4696
4684
  })
4697
4685
  })
4686
+ }),
4687
+ onClear && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4688
+ className: "border-border-subtle flex flex-none justify-end border-t px-2 py-1",
4689
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_text_truncate.Button, {
4690
+ variant: "ghost",
4691
+ size: "sm",
4692
+ onClick: onClear,
4693
+ disabled: items.length === 0,
4694
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Trash2, {
4695
+ className: "size-3.5",
4696
+ "aria-hidden": true
4697
+ }), labels.clear]
4698
+ })
4698
4699
  })
4699
4700
  ]
4700
4701
  });
@@ -4620,18 +4620,6 @@ function QueryHistoryList({ items, loading = false, onLoad, onRerun, onClear, he
4620
4620
  "data-opt-slug": "query-history-list.QueryHistoryList",
4621
4621
  children: [
4622
4622
  header,
4623
- onClear && items.length > 0 && /* @__PURE__ */ jsx("div", {
4624
- className: "flex flex-none justify-end px-2 pt-1",
4625
- children: /* @__PURE__ */ jsxs(Button, {
4626
- variant: "ghost",
4627
- size: "sm",
4628
- onClick: onClear,
4629
- children: [/* @__PURE__ */ jsx(Trash2, {
4630
- className: "size-3.5",
4631
- "aria-hidden": true
4632
- }), labels.clear]
4633
- })
4634
- }),
4635
4623
  /* @__PURE__ */ jsx("div", {
4636
4624
  className: "min-h-0 flex-1 overflow-y-auto",
4637
4625
  children: loading ? /* @__PURE__ */ jsx("p", {
@@ -4694,6 +4682,19 @@ function QueryHistoryList({ items, loading = false, onLoad, onRerun, onClear, he
4694
4682
  }, item.id);
4695
4683
  })
4696
4684
  })
4685
+ }),
4686
+ onClear && /* @__PURE__ */ jsx("div", {
4687
+ className: "border-border-subtle flex flex-none justify-end border-t px-2 py-1",
4688
+ children: /* @__PURE__ */ jsxs(Button, {
4689
+ variant: "ghost",
4690
+ size: "sm",
4691
+ onClick: onClear,
4692
+ disabled: items.length === 0,
4693
+ children: [/* @__PURE__ */ jsx(Trash2, {
4694
+ className: "size-3.5",
4695
+ "aria-hidden": true
4696
+ }), labels.clear]
4697
+ })
4697
4698
  })
4698
4699
  ]
4699
4700
  });
@@ -408,6 +408,12 @@ const ID_REGISTRY = Object.freeze({
408
408
  layer: "core",
409
409
  metaName: "CopyButton"
410
410
  },
411
+ "6F4JG": {
412
+ slug: "criteria-builder",
413
+ exportName: "CriteriaBuilder",
414
+ layer: "shells",
415
+ metaName: "CriteriaBuilder"
416
+ },
411
417
  BM7NA: {
412
418
  slug: "dashboard-grid",
413
419
  exportName: "DashboardGrid",
@@ -1729,6 +1735,7 @@ const SLUG_TO_ID = Object.freeze({
1729
1735
  "container.Container": "H3G96",
1730
1736
  "content-tabs.ContentTabs": "9W97K",
1731
1737
  "copy-button.CopyButton": "E0C8T",
1738
+ "criteria-builder.CriteriaBuilder": "6F4JG",
1732
1739
  "dashboard-grid.DashboardGrid": "BM7NA",
1733
1740
  "data-import-wizard.DataImportWizard": "QD9XR",
1734
1741
  "data-table.DataTable": "J1KN4",
@@ -2007,6 +2014,7 @@ const ALL_SLUGS = Object.freeze([
2007
2014
  "container.Container",
2008
2015
  "content-tabs.ContentTabs",
2009
2016
  "copy-button.CopyButton",
2017
+ "criteria-builder.CriteriaBuilder",
2010
2018
  "dashboard-grid.DashboardGrid",
2011
2019
  "data-import-wizard.DataImportWizard",
2012
2020
  "data-table.DataTable",
@@ -407,6 +407,12 @@ const ID_REGISTRY = Object.freeze({
407
407
  layer: "core",
408
408
  metaName: "CopyButton"
409
409
  },
410
+ "6F4JG": {
411
+ slug: "criteria-builder",
412
+ exportName: "CriteriaBuilder",
413
+ layer: "shells",
414
+ metaName: "CriteriaBuilder"
415
+ },
410
416
  BM7NA: {
411
417
  slug: "dashboard-grid",
412
418
  exportName: "DashboardGrid",
@@ -1728,6 +1734,7 @@ const SLUG_TO_ID = Object.freeze({
1728
1734
  "container.Container": "H3G96",
1729
1735
  "content-tabs.ContentTabs": "9W97K",
1730
1736
  "copy-button.CopyButton": "E0C8T",
1737
+ "criteria-builder.CriteriaBuilder": "6F4JG",
1731
1738
  "dashboard-grid.DashboardGrid": "BM7NA",
1732
1739
  "data-import-wizard.DataImportWizard": "QD9XR",
1733
1740
  "data-table.DataTable": "J1KN4",
@@ -2006,6 +2013,7 @@ const ALL_SLUGS = Object.freeze([
2006
2013
  "container.Container",
2007
2014
  "content-tabs.ContentTabs",
2008
2015
  "copy-button.CopyButton",
2016
+ "criteria-builder.CriteriaBuilder",
2009
2017
  "dashboard-grid.DashboardGrid",
2010
2018
  "data-import-wizard.DataImportWizard",
2011
2019
  "data-table.DataTable",
@@ -605,6 +605,15 @@
605
605
  "metaName": "CopyButton",
606
606
  "sourcePath": "src/core/copy-button.tsx"
607
607
  },
608
+ "6F4JG": {
609
+ "id": "6F4JG",
610
+ "slug": "criteria-builder",
611
+ "fullSlug": "criteria-builder.CriteriaBuilder",
612
+ "exportName": "CriteriaBuilder",
613
+ "layer": "shells",
614
+ "metaName": "CriteriaBuilder",
615
+ "sourcePath": "src/shells/criteria-builder.tsx"
616
+ },
608
617
  "BM7NA": {
609
618
  "id": "BM7NA",
610
619
  "slug": "dashboard-grid",
@@ -2546,6 +2555,7 @@
2546
2555
  "container.Container": "H3G96",
2547
2556
  "content-tabs.ContentTabs": "9W97K",
2548
2557
  "copy-button.CopyButton": "E0C8T",
2558
+ "criteria-builder.CriteriaBuilder": "6F4JG",
2549
2559
  "dashboard-grid.DashboardGrid": "BM7NA",
2550
2560
  "data-import-wizard.DataImportWizard": "QD9XR",
2551
2561
  "data-table.DataTable": "J1KN4",
@@ -3171,6 +3181,13 @@
3171
3181
  "slug": "copy-button.CopyButton"
3172
3182
  }
3173
3183
  ],
3184
+ "src/shells/criteria-builder.tsx": [
3185
+ {
3186
+ "exportName": "CriteriaBuilder",
3187
+ "id": "6F4JG",
3188
+ "slug": "criteria-builder.CriteriaBuilder"
3189
+ }
3190
+ ],
3174
3191
  "src/shells/dashboard-grid.tsx": [
3175
3192
  {
3176
3193
  "exportName": "DashboardGrid",