@reopt-ai/opt-ui 1.12.5 → 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.
- package/CHANGELOG.md +236 -0
- package/COMPONENT_CATALOG.md +670 -123
- package/README.md +9 -7
- package/dist/core/index.cjs +13 -13
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/docs/02-components/01-core.md +260 -61
- package/dist/docs/02-components/02-visuals.md +1 -1
- package/dist/docs/02-components/03-shells.md +431 -63
- package/dist/docs/02-components/04-surfaces.md +1 -1
- package/dist/docs/02-components/index.md +4 -4
- package/dist/{field-sidebar-YaWHfLLW.d.ts → field-sidebar-CJ4HxP8D.d.cts} +824 -2
- package/dist/{field-sidebar-Ct8c9L4V.d.cts → field-sidebar-DnhpcT2A.d.ts} +824 -2
- package/dist/{field-sidebar-DwtrYSSt.cjs → field-sidebar-ePqFX6MN.cjs} +4339 -244
- package/dist/{field-sidebar-Ben7MQD4.js → field-sidebar-mSVCMAZp.js} +3976 -235
- package/dist/id-registry.cjs +80 -0
- package/dist/id-registry.js +80 -0
- package/dist/id-registry.json +170 -0
- package/dist/index.cjs +1096 -1476
- package/dist/index.d.cts +243 -92
- package/dist/index.d.ts +243 -92
- package/dist/index.js +1004 -1415
- package/dist/{key-pad-menu-BpQebDyw.cjs → key-pad-menu-BgtSL3xe.cjs} +60 -487
- package/dist/{key-pad-menu-CYYtS_Tl.js → key-pad-menu-CqFI6la9.js} +61 -422
- package/dist/{key-pad-menu-CwcY_Vps.d.cts → key-pad-menu-D6pYzaj-.d.cts} +14 -56
- package/dist/{key-pad-menu-WBJShCJn.d.ts → key-pad-menu-Yh7Fpb8m.d.ts} +14 -56
- package/dist/meta.cjs +1312 -12
- package/dist/meta.js +1312 -12
- package/dist/shells/index.cjs +20 -1
- package/dist/shells/index.d.cts +2 -2
- package/dist/shells/index.d.ts +2 -2
- package/dist/shells/index.js +2 -2
- package/dist/{text-truncate-CQyfUZvq.d.cts → text-truncate-Bbul-jMD.d.cts} +52 -30
- package/dist/{text-truncate-CQyfUZvq.d.ts → text-truncate-Bbul-jMD.d.ts} +52 -30
- package/dist/{text-truncate-Dlm7JwDf.js → text-truncate-Bd-0WkSP.js} +461 -97
- package/dist/{text-truncate-CqdiQuj8.cjs → text-truncate-BeYW6XZu.cjs} +523 -99
- package/dist/theme/server.cjs +2 -2
- package/dist/theme/server.d.cts +2 -2
- package/dist/theme/server.d.ts +2 -2
- package/dist/theme/server.js +2 -2
- package/package.json +6 -2
package/dist/meta.cjs
CHANGED
|
@@ -1221,6 +1221,10 @@ const coreMetas = [
|
|
|
1221
1221
|
},
|
|
1222
1222
|
{
|
|
1223
1223
|
name: "setOpen",
|
|
1224
|
+
deprecated: {
|
|
1225
|
+
since: "1.13.0",
|
|
1226
|
+
replacement: "onOpenChange"
|
|
1227
|
+
},
|
|
1224
1228
|
type: "(open: boolean) => void",
|
|
1225
1229
|
description: "제어 모드: 상태 변경 핸들러"
|
|
1226
1230
|
},
|
|
@@ -1255,6 +1259,26 @@ const coreMetas = [
|
|
|
1255
1259
|
testDescribe: "Disclosure"
|
|
1256
1260
|
},
|
|
1257
1261
|
{
|
|
1262
|
+
usage: {
|
|
1263
|
+
anatomy: ["TabsRoot 안에 TabList와 TabPanel을 두고 Tab.id와 TabPanel.tabId를 맞춥니다."],
|
|
1264
|
+
bestPractices: ["TabList에 접근 가능한 이름을 지정하고, 제어 모드는 selectedId와 onSelectedIdChange를 함께 연결합니다."],
|
|
1265
|
+
avoid: ["다른 URL로 이동하는 주 내비게이션을 탭 패널로 구현하지 않습니다."]
|
|
1266
|
+
},
|
|
1267
|
+
examples: [{
|
|
1268
|
+
validation: "typechecked",
|
|
1269
|
+
title: "이름 있는 두 패널",
|
|
1270
|
+
code: `import { TabsRoot, TabList, Tab, TabPanel } from "@reopt-ai/opt-ui";
|
|
1271
|
+
|
|
1272
|
+
export function Example() {
|
|
1273
|
+
return <TabsRoot defaultSelectedId="overview">
|
|
1274
|
+
<TabList aria-label="프로젝트 정보">
|
|
1275
|
+
<Tab id="overview">개요</Tab><Tab id="activity">활동</Tab>
|
|
1276
|
+
</TabList>
|
|
1277
|
+
<TabPanel tabId="overview">프로젝트 요약</TabPanel>
|
|
1278
|
+
<TabPanel tabId="activity">최근 활동</TabPanel>
|
|
1279
|
+
</TabsRoot>;
|
|
1280
|
+
}`
|
|
1281
|
+
}],
|
|
1258
1282
|
name: "Tabs",
|
|
1259
1283
|
category: "core",
|
|
1260
1284
|
description: "탭 패널 시스템. 4-part anatomy: Root, TabList, Tab, TabPanel.",
|
|
@@ -1298,6 +1322,10 @@ const coreMetas = [
|
|
|
1298
1322
|
},
|
|
1299
1323
|
{
|
|
1300
1324
|
name: "setSelectedId",
|
|
1325
|
+
deprecated: {
|
|
1326
|
+
since: "1.13.0",
|
|
1327
|
+
replacement: "onSelectedIdChange"
|
|
1328
|
+
},
|
|
1301
1329
|
type: "(id: string | null) => void",
|
|
1302
1330
|
description: "제어 모드: 탭 변경 핸들러"
|
|
1303
1331
|
}
|
|
@@ -1378,6 +1406,11 @@ const coreMetas = [
|
|
|
1378
1406
|
testDescribe: "Tabs"
|
|
1379
1407
|
},
|
|
1380
1408
|
{
|
|
1409
|
+
usage: {
|
|
1410
|
+
anatomy: ["SelectRoot 안에 Label, Trigger, Popover, Item을 조합합니다."],
|
|
1411
|
+
bestPractices: ["옵션 value는 표시 문구와 분리된 안정적인 키로 유지합니다. multiple 모드에서는 배열 값을 사용합니다."],
|
|
1412
|
+
avoid: ["선택 목록에 명령 실행 버튼을 섞지 않습니다. 명령은 DropdownMenu로 분리합니다."]
|
|
1413
|
+
},
|
|
1381
1414
|
name: "Select",
|
|
1382
1415
|
category: "core",
|
|
1383
1416
|
description: "드롭다운 선택 컴포넌트. 5-part anatomy: Root, Label, Trigger, Popover, Item.",
|
|
@@ -1466,6 +1499,10 @@ const coreMetas = [
|
|
|
1466
1499
|
},
|
|
1467
1500
|
{
|
|
1468
1501
|
name: "gutter",
|
|
1502
|
+
deprecated: {
|
|
1503
|
+
since: "1.13.0",
|
|
1504
|
+
replacement: "sideOffset"
|
|
1505
|
+
},
|
|
1469
1506
|
type: "number",
|
|
1470
1507
|
default: "4",
|
|
1471
1508
|
description: "트리거와의 간격 (px)"
|
|
@@ -1514,6 +1551,11 @@ const coreMetas = [
|
|
|
1514
1551
|
}]
|
|
1515
1552
|
},
|
|
1516
1553
|
{
|
|
1554
|
+
usage: {
|
|
1555
|
+
anatomy: ["DialogRoot에서 Disclosure와 Panel을 연결하고 Panel 안에 Heading과 Description을 둡니다."],
|
|
1556
|
+
bestPractices: ["열림을 제어할 때 open과 onOpenChange를 함께 제공합니다. 닫기 동작은 DialogDismiss로 노출합니다."],
|
|
1557
|
+
avoid: ["제목 없는 모달이나 종료 방법 없는 모달을 만들지 않습니다. 파괴적 확인은 AlertDialogPanel의 계약을 사용합니다."]
|
|
1558
|
+
},
|
|
1517
1559
|
name: "Dialog",
|
|
1518
1560
|
category: "core",
|
|
1519
1561
|
description: "모달 다이얼로그. 9-part anatomy: Root, Disclosure, Panel, Heading, Description, Dismiss, Header, Body, Footer.",
|
|
@@ -1544,6 +1586,10 @@ const coreMetas = [
|
|
|
1544
1586
|
description: "제어 모드: 열림 상태"
|
|
1545
1587
|
}, {
|
|
1546
1588
|
name: "setOpen",
|
|
1589
|
+
deprecated: {
|
|
1590
|
+
since: "1.13.0",
|
|
1591
|
+
replacement: "onOpenChange"
|
|
1592
|
+
},
|
|
1547
1593
|
type: "(open: boolean) => void",
|
|
1548
1594
|
description: "제어 모드: 상태 변경 핸들러"
|
|
1549
1595
|
}],
|
|
@@ -1667,6 +1713,10 @@ const coreMetas = [
|
|
|
1667
1713
|
props: {
|
|
1668
1714
|
ComboboxRoot: [{
|
|
1669
1715
|
name: "setValue",
|
|
1716
|
+
deprecated: {
|
|
1717
|
+
since: "1.13.0",
|
|
1718
|
+
replacement: "onValueChange"
|
|
1719
|
+
},
|
|
1670
1720
|
type: "(value: string) => void",
|
|
1671
1721
|
description: "입력값 변경 핸들러"
|
|
1672
1722
|
}, {
|
|
@@ -1708,6 +1758,10 @@ const coreMetas = [
|
|
|
1708
1758
|
},
|
|
1709
1759
|
{
|
|
1710
1760
|
name: "gutter",
|
|
1761
|
+
deprecated: {
|
|
1762
|
+
since: "1.13.0",
|
|
1763
|
+
replacement: "sideOffset"
|
|
1764
|
+
},
|
|
1711
1765
|
type: "number",
|
|
1712
1766
|
default: "4",
|
|
1713
1767
|
description: "입력과의 간격 (px)"
|
|
@@ -1839,6 +1893,10 @@ const coreMetas = [
|
|
|
1839
1893
|
},
|
|
1840
1894
|
{
|
|
1841
1895
|
name: "gutter",
|
|
1896
|
+
deprecated: {
|
|
1897
|
+
since: "1.13.0",
|
|
1898
|
+
replacement: "sideOffset"
|
|
1899
|
+
},
|
|
1842
1900
|
type: "number",
|
|
1843
1901
|
default: "8",
|
|
1844
1902
|
description: "트리거와의 간격 (px)"
|
|
@@ -2192,6 +2250,10 @@ const coreMetas = [
|
|
|
2192
2250
|
},
|
|
2193
2251
|
{
|
|
2194
2252
|
name: "gutter",
|
|
2253
|
+
deprecated: {
|
|
2254
|
+
since: "1.13.0",
|
|
2255
|
+
replacement: "sideOffset"
|
|
2256
|
+
},
|
|
2195
2257
|
type: "number",
|
|
2196
2258
|
default: "4",
|
|
2197
2259
|
description: "트리거와의 간격 (px)"
|
|
@@ -2514,6 +2576,10 @@ const store = useFormStore({
|
|
|
2514
2576
|
]
|
|
2515
2577
|
},
|
|
2516
2578
|
{
|
|
2579
|
+
usage: {
|
|
2580
|
+
bestPractices: ["주요 실행에는 primary, 파괴적 실행에는 danger를 사용하고 동작을 설명하는 텍스트를 유지합니다.", "폼 제출은 type=submit을 명시합니다. loading은 버튼을 비활성화하고 aria-busy를 설정합니다."],
|
|
2581
|
+
avoid: ["페이지 이동을 버튼 클릭으로만 구현하지 않습니다. 아이콘만 표시할 때 접근 가능한 이름을 생략하지 않습니다."]
|
|
2582
|
+
},
|
|
2517
2583
|
name: "Button",
|
|
2518
2584
|
category: "core",
|
|
2519
2585
|
description: "접근성 버튼 컴포넌트. 4가지 변형(primary, secondary, ghost, danger), 3가지 크기, 로딩/아이콘과 aria-busy 상태를 지원합니다.",
|
|
@@ -2568,6 +2634,16 @@ const store = useFormStore({
|
|
|
2568
2634
|
}]
|
|
2569
2635
|
},
|
|
2570
2636
|
{
|
|
2637
|
+
usage: {
|
|
2638
|
+
bestPractices: ["variant 색상과 함께 상태를 설명하는 텍스트를 표시합니다. progress를 지정하면 dot 대신 진행률 링이 표시됩니다."],
|
|
2639
|
+
avoid: ["Badge를 클릭 가능한 버튼처럼 사용하거나 색상만으로 성공·실패를 구분하지 않습니다."]
|
|
2640
|
+
},
|
|
2641
|
+
examples: [{
|
|
2642
|
+
validation: "typechecked",
|
|
2643
|
+
title: "텍스트가 있는 상태",
|
|
2644
|
+
code: `import { Badge } from "@reopt-ai/opt-ui";
|
|
2645
|
+
export function Example() { return <Badge variant="success" dot>동기화 완료</Badge>; }`
|
|
2646
|
+
}],
|
|
2571
2647
|
name: "Badge",
|
|
2572
2648
|
category: "core",
|
|
2573
2649
|
description: "인라인 상태 뱃지. 5가지 색상 변형, 상태 점(dot) 옵션 지원.",
|
|
@@ -2607,6 +2683,16 @@ const store = useFormStore({
|
|
|
2607
2683
|
testDescribe: "Badge"
|
|
2608
2684
|
},
|
|
2609
2685
|
{
|
|
2686
|
+
usage: {
|
|
2687
|
+
bestPractices: ["단독 로딩 표시는 aria-label로 작업을 설명합니다. 주변 status가 이미 상태를 읽으면 aria-hidden으로 중복 낭독을 막습니다."],
|
|
2688
|
+
avoid: ["Spinner 자체가 요청 진행 상태나 오류 처리를 관리한다고 가정하지 않습니다."]
|
|
2689
|
+
},
|
|
2690
|
+
examples: [{
|
|
2691
|
+
validation: "typechecked",
|
|
2692
|
+
title: "이름 있는 로딩 표시",
|
|
2693
|
+
code: `import { Spinner } from "@reopt-ai/opt-ui";
|
|
2694
|
+
export function Example() { return <Spinner size="sm" aria-label="검색 결과 불러오는 중" />; }`
|
|
2695
|
+
}],
|
|
2610
2696
|
name: "Spinner",
|
|
2611
2697
|
category: "core",
|
|
2612
2698
|
description: "로딩 상태 표시 스피너. 3가지 크기와 장식용 aria-hidden 모드를 지원합니다.",
|
|
@@ -2622,6 +2708,16 @@ const store = useFormStore({
|
|
|
2622
2708
|
testDescribe: "Spinner"
|
|
2623
2709
|
},
|
|
2624
2710
|
{
|
|
2711
|
+
usage: {
|
|
2712
|
+
bestPractices: ["title에는 문제 요약을, 본문에는 사용자가 할 수 있는 다음 행동을 적습니다. 닫을 수 있다면 onDismiss로 상태를 갱신합니다."],
|
|
2713
|
+
avoid: ["일반 설명 문구를 모두 긴급 알림으로 노출하거나 오류 원인을 색상으로만 전달하지 않습니다."]
|
|
2714
|
+
},
|
|
2715
|
+
examples: [{
|
|
2716
|
+
validation: "typechecked",
|
|
2717
|
+
title: "재시도 가능한 오류 안내",
|
|
2718
|
+
code: `import { Alert } from "@reopt-ai/opt-ui";
|
|
2719
|
+
export function Example() { return <Alert variant="error" title="저장하지 못했습니다">연결 상태를 확인한 뒤 다시 저장하세요.</Alert>; }`
|
|
2720
|
+
}],
|
|
2625
2721
|
name: "Alert",
|
|
2626
2722
|
category: "core",
|
|
2627
2723
|
description: "알림 메시지 컴포넌트. 4가지 변형(info, success, warning, error), 제목/본문/닫기 버튼 지원.",
|
|
@@ -2660,6 +2756,10 @@ const store = useFormStore({
|
|
|
2660
2756
|
testDescribe: "Alert"
|
|
2661
2757
|
},
|
|
2662
2758
|
{
|
|
2759
|
+
usage: {
|
|
2760
|
+
bestPractices: ["label로 입력 목적을, hint로 형식을 안내합니다. error는 오류 문자열이며 표시될 때 hint보다 우선합니다.", "제어 값은 문자열로 유지하고 onChange의 event.target.value를 저장합니다. FormControl 조합에서는 레이블을 중복하지 않습니다."],
|
|
2761
|
+
avoid: ["placeholder를 유일한 레이블로 사용하거나 제어/비제어 상태를 렌더 중 전환하지 않습니다."]
|
|
2762
|
+
},
|
|
2663
2763
|
name: "Input",
|
|
2664
2764
|
category: "core",
|
|
2665
2765
|
description: "독립적인 텍스트 입력 컴포넌트. 레이블, 에러, 힌트, 아이콘 지원.",
|
|
@@ -2726,6 +2826,21 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
2726
2826
|
}]
|
|
2727
2827
|
},
|
|
2728
2828
|
{
|
|
2829
|
+
usage: {
|
|
2830
|
+
bestPractices: ["즉시 적용되는 켜짐/꺼짐 설정에 사용합니다. onChange는 DOM 이벤트가 아니라 boolean을 전달합니다."],
|
|
2831
|
+
avoid: ["제출 시 한꺼번에 적용되는 동의 목록을 즉시 적용 스위치로 표현하지 않습니다. label을 상태마다 바꾸지 않습니다."]
|
|
2832
|
+
},
|
|
2833
|
+
examples: [{
|
|
2834
|
+
validation: "typechecked",
|
|
2835
|
+
title: "제어되는 알림 설정",
|
|
2836
|
+
code: `"use client";
|
|
2837
|
+
import { useState } from "react";
|
|
2838
|
+
import { Switch } from "@reopt-ai/opt-ui";
|
|
2839
|
+
export function Example() {
|
|
2840
|
+
const [enabled, setEnabled] = useState(false);
|
|
2841
|
+
return <Switch label="이메일 알림" hint="새 댓글을 이메일로 받습니다" checked={enabled} onChange={setEnabled} />;
|
|
2842
|
+
}`
|
|
2843
|
+
}],
|
|
2729
2844
|
name: "Switch",
|
|
2730
2845
|
category: "core",
|
|
2731
2846
|
description: "토글 스위치 컴포넌트. 3가지 크기와 레이블/설명의 명시적 접근성 연결을 지원합니다.",
|
|
@@ -2782,6 +2897,16 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
2782
2897
|
testDescribe: "Switch"
|
|
2783
2898
|
},
|
|
2784
2899
|
{
|
|
2900
|
+
usage: {
|
|
2901
|
+
bestPractices: ["로드될 콘텐츠와 비슷한 크기·행 수를 사용해 레이아웃 이동을 줄입니다. 컨테이너에서 로딩 상태를 설명합니다."],
|
|
2902
|
+
avoid: ["빈 결과나 요청 오류를 끝나지 않는 스켈레톤으로 대신하지 않습니다."]
|
|
2903
|
+
},
|
|
2904
|
+
examples: [{
|
|
2905
|
+
validation: "typechecked",
|
|
2906
|
+
title: "목록 로딩 자리 확보",
|
|
2907
|
+
code: `import { SkeletonTable } from "@reopt-ai/opt-ui";
|
|
2908
|
+
export function Example() { return <section aria-label="목록 불러오는 중" aria-busy="true"><SkeletonTable rows={3} columns={4} /></section>; }`
|
|
2909
|
+
}],
|
|
2785
2910
|
name: "Skeleton",
|
|
2786
2911
|
category: "core",
|
|
2787
2912
|
description: "로딩 플레이스홀더. text/circular/rectangular 변형. 프리셋 컴포넌트 포함.",
|
|
@@ -2852,6 +2977,16 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
2852
2977
|
testDescribe: "Skeleton"
|
|
2853
2978
|
},
|
|
2854
2979
|
{
|
|
2980
|
+
usage: {
|
|
2981
|
+
bestPractices: ["여러 줄의 자유 입력에 사용하고 label과 hint로 목적·분량을 안내합니다. rows로 초기 높이를 정합니다."],
|
|
2982
|
+
avoid: ["짧은 단일 값 입력에 과도한 편집 영역을 쓰거나 사용자의 세로 크기 조절을 불필요하게 막지 않습니다."]
|
|
2983
|
+
},
|
|
2984
|
+
examples: [{
|
|
2985
|
+
validation: "typechecked",
|
|
2986
|
+
title: "설명 입력",
|
|
2987
|
+
code: `import { Textarea } from "@reopt-ai/opt-ui";
|
|
2988
|
+
export function Example() { return <Textarea label="변경 이유" name="reason" hint="검토자가 알아야 할 내용을 적어주세요" rows={4} resize="vertical" />; }`
|
|
2989
|
+
}],
|
|
2855
2990
|
name: "Textarea",
|
|
2856
2991
|
category: "core",
|
|
2857
2992
|
description: "멀티라인 텍스트 입력. Input과 동일한 API (label, error, hint).",
|
|
@@ -2896,6 +3031,16 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
2896
3031
|
testDescribe: "Textarea"
|
|
2897
3032
|
},
|
|
2898
3033
|
{
|
|
3034
|
+
usage: {
|
|
3035
|
+
bestPractices: ["name으로 이미지 실패 시 이니셜을 제공하고, alt는 이미지의 실제 의미를 설명합니다. AvatarGroup의 max로 표시 개수를 제한합니다."],
|
|
3036
|
+
avoid: ["이미지나 온라인 상태 점만으로 사용자 신원·상태를 전달하지 않습니다."]
|
|
3037
|
+
},
|
|
3038
|
+
examples: [{
|
|
3039
|
+
validation: "typechecked",
|
|
3040
|
+
title: "이미지 없이 사용자 표시",
|
|
3041
|
+
code: `import { Avatar, AvatarGroup } from "@reopt-ai/opt-ui";
|
|
3042
|
+
export function Example() { return <AvatarGroup max={3}><Avatar name="김민수" /><Avatar name="이지수" /></AvatarGroup>; }`
|
|
3043
|
+
}],
|
|
2899
3044
|
name: "Avatar",
|
|
2900
3045
|
category: "core",
|
|
2901
3046
|
description: "사용자 아바타. 이미지, 이니셜 자동 생성, 스크린 리더에 노출되는 상태 인디케이터, 그룹을 지원합니다.",
|
|
@@ -2959,6 +3104,16 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
2959
3104
|
testDescribe: "Avatar"
|
|
2960
3105
|
},
|
|
2961
3106
|
{
|
|
3107
|
+
usage: {
|
|
3108
|
+
bestPractices: ["완료량을 알면 value와 max를 같은 단위로 제공합니다. 진행률에 작업을 설명하는 접근 가능한 이름을 붙입니다."],
|
|
3109
|
+
avoid: ["측정할 수 없는 진행률을 임의 숫자로 표시하지 않습니다. 완료·실패 후에도 진행 중 표시를 남기지 않습니다."]
|
|
3110
|
+
},
|
|
3111
|
+
examples: [{
|
|
3112
|
+
validation: "typechecked",
|
|
3113
|
+
title: "업로드 진행률",
|
|
3114
|
+
code: `import { Progress } from "@reopt-ai/opt-ui";
|
|
3115
|
+
export function Example() { return <Progress value={35} max={100} aria-label="파일 업로드" />; }`
|
|
3116
|
+
}],
|
|
2962
3117
|
name: "Progress",
|
|
2963
3118
|
category: "core",
|
|
2964
3119
|
description: "진행률 표시. Linear/Circular, determinate/indeterminate 변형과 안전하게 보정된 ARIA 값을 지원합니다.",
|
|
@@ -3411,6 +3566,16 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
3411
3566
|
testDescribe: "Card"
|
|
3412
3567
|
},
|
|
3413
3568
|
{
|
|
3569
|
+
usage: {
|
|
3570
|
+
bestPractices: ["CheckboxGroup에는 각 Checkbox의 고유 value를 제공합니다. 단일 onChange는 boolean, 그룹 onChange는 문자열 배열을 전달합니다.", "일부 항목만 선택한 전체 선택 컨트롤에는 indeterminate를 사용합니다."],
|
|
3571
|
+
avoid: ["서로 배타적인 선택지를 체크박스로 구성하거나 label 없이 체크 상태만 노출하지 않습니다."]
|
|
3572
|
+
},
|
|
3573
|
+
examples: [{
|
|
3574
|
+
validation: "typechecked",
|
|
3575
|
+
title: "복수 선택 그룹",
|
|
3576
|
+
code: `import { Checkbox, CheckboxGroup } from "@reopt-ai/opt-ui";
|
|
3577
|
+
export function Example() { return <CheckboxGroup label="알림 채널" defaultValue={["email"]}><Checkbox value="email" label="이메일" /><Checkbox value="push" label="푸시" /></CheckboxGroup>; }`
|
|
3578
|
+
}],
|
|
3414
3579
|
name: "Checkbox",
|
|
3415
3580
|
category: "core",
|
|
3416
3581
|
description: "독립적인 체크박스 컴포넌트. 레이블, 설명, 그룹과 DOM property까지 동기화되는 indeterminate 상태를 지원합니다.",
|
|
@@ -3920,6 +4085,11 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
3920
4085
|
type: "number",
|
|
3921
4086
|
description: "매치 카운트 표시 (toLocaleString 포맷)"
|
|
3922
4087
|
},
|
|
4088
|
+
{
|
|
4089
|
+
name: "labels",
|
|
4090
|
+
type: "ConditionBuilderLabels",
|
|
4091
|
+
description: "미리보기 문구 오버라이드 (previewSuffix, formatPreview). 기본은 영어 \"matches\""
|
|
4092
|
+
},
|
|
3923
4093
|
{
|
|
3924
4094
|
name: "addNestedGroupLabel",
|
|
3925
4095
|
type: "string",
|
|
@@ -3930,6 +4100,17 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
3930
4100
|
testDescribe: "ConditionBuilder"
|
|
3931
4101
|
},
|
|
3932
4102
|
{
|
|
4103
|
+
usage: {
|
|
4104
|
+
anatomy: ["PopoverRoot 안에 Trigger와 Content를 두고 Content 안에 Close를 제공할 수 있습니다."],
|
|
4105
|
+
bestPractices: ["트리거와 관련된 짧은 보조 작업을 배치합니다. 위치는 PopoverRoot의 placement로 지정합니다."],
|
|
4106
|
+
avoid: ["복잡한 필수 입력 작업을 작은 팝오버에 가두거나 트리거의 접근 가능한 이름을 생략하지 않습니다."]
|
|
4107
|
+
},
|
|
4108
|
+
examples: [{
|
|
4109
|
+
validation: "typechecked",
|
|
4110
|
+
title: "보조 설명 열고 닫기",
|
|
4111
|
+
code: `import { PopoverRoot, PopoverTrigger, PopoverContent, PopoverClose } from "@reopt-ai/opt-ui";
|
|
4112
|
+
export function Example() { return <PopoverRoot><PopoverTrigger>공유 안내</PopoverTrigger><PopoverContent><p>초대받은 사용자만 문서를 볼 수 있습니다.</p><PopoverClose>닫기</PopoverClose></PopoverContent></PopoverRoot>; }`
|
|
4113
|
+
}],
|
|
3933
4114
|
name: "Popover",
|
|
3934
4115
|
category: "core",
|
|
3935
4116
|
description: "Popover 프리미티브 래퍼. 트리거 요소에 연결된 플로팅 콘텐츠를 표시합니다.",
|
|
@@ -3948,11 +4129,6 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
3948
4129
|
action: "트리거 활성화"
|
|
3949
4130
|
}],
|
|
3950
4131
|
props: { PopoverContent: [{
|
|
3951
|
-
name: "gutter",
|
|
3952
|
-
type: "number",
|
|
3953
|
-
default: "8",
|
|
3954
|
-
description: "트리거와의 간격 (px)"
|
|
3955
|
-
}, {
|
|
3956
4132
|
name: "className",
|
|
3957
4133
|
type: "string",
|
|
3958
4134
|
description: "커스텀 CSS 클래스"
|
|
@@ -3989,6 +4165,10 @@ const store = useFormStore({ defaultValues: { name: "" } });
|
|
|
3989
4165
|
props: {
|
|
3990
4166
|
DropdownContent: [{
|
|
3991
4167
|
name: "gutter",
|
|
4168
|
+
deprecated: {
|
|
4169
|
+
since: "1.13.0",
|
|
4170
|
+
replacement: "sideOffset"
|
|
4171
|
+
},
|
|
3992
4172
|
type: "number",
|
|
3993
4173
|
default: "4",
|
|
3994
4174
|
description: "트리거와의 간격 (px)"
|
|
@@ -4737,6 +4917,16 @@ const MyDashboard = createBlock<MyDashboardProps>(
|
|
|
4737
4917
|
testDescribe: "VirtualList"
|
|
4738
4918
|
},
|
|
4739
4919
|
{
|
|
4920
|
+
usage: {
|
|
4921
|
+
bestPractices: ["기존 콘텐츠를 유지한 채 갱신할 때 loading을 연결하고 label로 진행 중인 작업을 설명합니다."],
|
|
4922
|
+
avoid: ["오버레이가 키보드 접근까지 차단한다고 가정하지 않습니다. 중복 실행 방지가 필요하면 내부 컨트롤도 비활성화합니다."]
|
|
4923
|
+
},
|
|
4924
|
+
examples: [{
|
|
4925
|
+
validation: "typechecked",
|
|
4926
|
+
title: "기존 결과를 유지하는 갱신 표시",
|
|
4927
|
+
code: `import { LoadingOverlay } from "@reopt-ai/opt-ui";
|
|
4928
|
+
export function Example() { return <LoadingOverlay loading label="목록 새로고침 중"><p>이전 조회 결과</p></LoadingOverlay>; }`
|
|
4929
|
+
}],
|
|
4740
4930
|
name: "LoadingOverlay",
|
|
4741
4931
|
category: "core",
|
|
4742
4932
|
description: "로딩 오버레이. 중복 status 없이 하나의 aria-busy 라이브 영역으로 콘텐츠 위 로딩 상태를 표시합니다.",
|
|
@@ -4999,6 +5189,7 @@ const MyDashboard = createBlock<MyDashboardProps>(
|
|
|
4999
5189
|
description: "페이지에 머무는 인페이지 고지. Alert와 달리 dismiss가 없고, 조건이 참인 동안 레이아웃의 일부로 남습니다.",
|
|
5000
5190
|
slug: "callout",
|
|
5001
5191
|
exports: ["Callout"],
|
|
5192
|
+
ariaRole: "status",
|
|
5002
5193
|
props: { Callout: [
|
|
5003
5194
|
{
|
|
5004
5195
|
name: "tone",
|
|
@@ -5781,6 +5972,10 @@ const fields = [
|
|
|
5781
5972
|
testDescribe: "DomainTable"
|
|
5782
5973
|
},
|
|
5783
5974
|
{
|
|
5975
|
+
usage: {
|
|
5976
|
+
bestPractices: ["keyExtractor에는 정렬·필터 후에도 유지되는 행 ID를 사용합니다. 보이는 title이 없으면 ariaLabel로 grid 이름을 지정합니다.", "컬럼 accessor는 행 타입에 맞춰 선언하고, 서버 조회·편집·대규모 가상화가 필요하면 opt-datagrid의 계약을 검토합니다."],
|
|
5977
|
+
avoid: ["배열 인덱스를 행 식별자로 사용하거나 비어 있는 헤더로 액션 컬럼을 익명화하지 않습니다. headerHidden을 사용합니다."]
|
|
5978
|
+
},
|
|
5784
5979
|
name: "DataTable",
|
|
5785
5980
|
category: "shell",
|
|
5786
5981
|
description: "제네릭 데이터 테이블. 제목은 opt-in이고 ariaLabel로 grid를 이름 붙이며, 동적 컬럼·안전 정렬·키보드 리사이즈·Composite 탐색을 지원합니다.",
|
|
@@ -5927,6 +6122,17 @@ const data = [
|
|
|
5927
6122
|
}]
|
|
5928
6123
|
},
|
|
5929
6124
|
{
|
|
6125
|
+
usage: {
|
|
6126
|
+
bestPractices: ["앱 경계에 ToastProvider를 한 번 마운트한 뒤 이벤트 핸들러에서 toast를 호출합니다. message는 결과를, action은 다음 행동을 설명합니다."],
|
|
6127
|
+
avoid: ["렌더 함수에서 toast를 호출하거나 반드시 읽어야 하는 오류·동의를 자동으로 사라지는 토스트에만 표시하지 않습니다."]
|
|
6128
|
+
},
|
|
6129
|
+
examples: [{
|
|
6130
|
+
validation: "typechecked",
|
|
6131
|
+
title: "사용자 동작의 결과 알림",
|
|
6132
|
+
code: `"use client";
|
|
6133
|
+
import { Button, ToastProvider, toast } from "@reopt-ai/opt-ui";
|
|
6134
|
+
export function Example() { return <ToastProvider><Button onClick={() => toast.success("알림 동작을 확인했습니다")}>알림 테스트</Button></ToastProvider>; }`
|
|
6135
|
+
}],
|
|
5930
6136
|
name: "NotificationToast",
|
|
5931
6137
|
category: "shell",
|
|
5932
6138
|
description: "토스트 알림 시스템. 포인터/키보드 상호작용 중 자동 닫힘을 일시 정지하고, 중요도별 live region으로 전역 알림을 관리합니다.",
|
|
@@ -6121,6 +6327,10 @@ const data = [
|
|
|
6121
6327
|
testDescribe: "ActivityFeed"
|
|
6122
6328
|
},
|
|
6123
6329
|
{
|
|
6330
|
+
usage: {
|
|
6331
|
+
bestPractices: ["filters의 id를 안정적으로 유지하고 onFilterChange에서 해당 필터의 value를 갱신합니다. onClearAll에서는 적용된 값과 조회 조건을 함께 초기화합니다."],
|
|
6332
|
+
avoid: ["필터 UI 변경만으로 서버 데이터까지 자동 조회된다고 가정하지 않습니다. 비동기 조회와 오류 처리는 호출자가 연결합니다."]
|
|
6333
|
+
},
|
|
6124
6334
|
name: "FilterBar",
|
|
6125
6335
|
category: "shell",
|
|
6126
6336
|
description: "필터링 바 컴포넌트. 검색, 선택, 다중 선택 필터 지원.",
|
|
@@ -6940,15 +7150,26 @@ const filters = [
|
|
|
6940
7150
|
{
|
|
6941
7151
|
name: "QueryResultsTable",
|
|
6942
7152
|
category: "shell",
|
|
6943
|
-
|
|
7153
|
+
functionalCategory: "data-display",
|
|
7154
|
+
maturity: "stable",
|
|
7155
|
+
keywords: [
|
|
7156
|
+
"sql",
|
|
7157
|
+
"query",
|
|
7158
|
+
"results",
|
|
7159
|
+
"grid",
|
|
7160
|
+
"table",
|
|
7161
|
+
"virtualized"
|
|
7162
|
+
],
|
|
7163
|
+
description: "쿼리 결과 테이블. 타입이 표시되는 헤더, 로컬 정렬, 컬럼 리사이즈, 행 상세 패널을 갖추고 행을 윈도잉해 만 행도 스크롤로 다룹니다. NULL·불리언·객체를 빈칸 대신 글자로 씁니다.",
|
|
6944
7164
|
slug: "query-results-table",
|
|
6945
7165
|
exports: ["QueryResultsTable"],
|
|
7166
|
+
domlessExports: ["formatQueryCell"],
|
|
6946
7167
|
props: { QueryResultsTable: [
|
|
6947
7168
|
{
|
|
6948
7169
|
name: "columns",
|
|
6949
|
-
type: "string
|
|
7170
|
+
type: "Array<string | QueryResultColumn>",
|
|
6950
7171
|
required: true,
|
|
6951
|
-
description: "컬럼
|
|
7172
|
+
description: "컬럼 이름, 또는 타입을 포함한 컬럼 정의"
|
|
6952
7173
|
},
|
|
6953
7174
|
{
|
|
6954
7175
|
name: "rows",
|
|
@@ -6956,6 +7177,12 @@ const filters = [
|
|
|
6956
7177
|
required: true,
|
|
6957
7178
|
description: "결과 행"
|
|
6958
7179
|
},
|
|
7180
|
+
{
|
|
7181
|
+
name: "maxHeight",
|
|
7182
|
+
type: "number | \"fill\"",
|
|
7183
|
+
default: "400",
|
|
7184
|
+
description: "스크롤 높이(px). fill이면 부모 높이를 채움"
|
|
7185
|
+
},
|
|
6959
7186
|
{
|
|
6960
7187
|
name: "loading",
|
|
6961
7188
|
type: "boolean",
|
|
@@ -6966,12 +7193,59 @@ const filters = [
|
|
|
6966
7193
|
type: "string",
|
|
6967
7194
|
description: "assertive 오류 상태"
|
|
6968
7195
|
},
|
|
7196
|
+
{
|
|
7197
|
+
name: "sortable",
|
|
7198
|
+
type: "boolean",
|
|
7199
|
+
default: "true",
|
|
7200
|
+
description: "헤더 클릭 정렬"
|
|
7201
|
+
},
|
|
7202
|
+
{
|
|
7203
|
+
name: "sort",
|
|
7204
|
+
type: "QueryResultSort | null",
|
|
7205
|
+
description: "제어형 정렬 상태"
|
|
7206
|
+
},
|
|
7207
|
+
{
|
|
7208
|
+
name: "onSortChange",
|
|
7209
|
+
type: "(sort: QueryResultSort | null) => void",
|
|
7210
|
+
description: "정렬 변경"
|
|
7211
|
+
},
|
|
7212
|
+
{
|
|
7213
|
+
name: "rowHeight",
|
|
7214
|
+
type: "number",
|
|
7215
|
+
default: "32",
|
|
7216
|
+
description: "행 높이(px). 윈도잉의 기준"
|
|
7217
|
+
},
|
|
7218
|
+
{
|
|
7219
|
+
name: "rowDetails",
|
|
7220
|
+
type: "boolean",
|
|
7221
|
+
default: "true",
|
|
7222
|
+
description: "행을 상세 패널로 열기"
|
|
7223
|
+
},
|
|
7224
|
+
{
|
|
7225
|
+
name: "footer",
|
|
7226
|
+
type: "ReactNode",
|
|
7227
|
+
description: "행 수 뒤에 붙는 푸터 내용 — 경과 시간, 읽은 바이트"
|
|
7228
|
+
},
|
|
6969
7229
|
{
|
|
6970
7230
|
name: "labels",
|
|
6971
7231
|
type: "QueryResultsTableLabels",
|
|
6972
|
-
description: "로딩/빈 상태/행
|
|
7232
|
+
description: "로딩/빈 상태/행 수/정렬/상세 문구"
|
|
6973
7233
|
}
|
|
6974
7234
|
] },
|
|
7235
|
+
dependencies: [
|
|
7236
|
+
{
|
|
7237
|
+
slug: "field-token",
|
|
7238
|
+
category: "core"
|
|
7239
|
+
},
|
|
7240
|
+
{
|
|
7241
|
+
slug: "flyout",
|
|
7242
|
+
category: "shell"
|
|
7243
|
+
},
|
|
7244
|
+
{
|
|
7245
|
+
slug: "description-list",
|
|
7246
|
+
category: "core"
|
|
7247
|
+
}
|
|
7248
|
+
],
|
|
6975
7249
|
testDescribe: "QueryResultsTable"
|
|
6976
7250
|
},
|
|
6977
7251
|
{
|
|
@@ -7011,12 +7285,12 @@ const filters = [
|
|
|
7011
7285
|
},
|
|
7012
7286
|
{
|
|
7013
7287
|
name: "onRun",
|
|
7014
|
-
type: "(sql: string) => void",
|
|
7015
|
-
description: "Mod+Enter 실행
|
|
7288
|
+
type: "(sql: string, context: SqlEditorRunContext) => void",
|
|
7289
|
+
description: "Mod+Enter 실행 핸들러. 두 번째 인자로 선택 영역과 커서 위치"
|
|
7016
7290
|
},
|
|
7017
7291
|
{
|
|
7018
7292
|
name: "onRunAndAdvance",
|
|
7019
|
-
type: "(sql: string) => void",
|
|
7293
|
+
type: "(sql: string, context: SqlEditorRunContext) => void",
|
|
7020
7294
|
description: "Shift+Enter — 실행 후 다음 셀/탭으로 이동"
|
|
7021
7295
|
},
|
|
7022
7296
|
{
|
|
@@ -7069,6 +7343,18 @@ const filters = [
|
|
|
7069
7343
|
type: "boolean",
|
|
7070
7344
|
description: "실행 힌트/버튼 표시. 기본값은 onRun이 있을 때 표시"
|
|
7071
7345
|
},
|
|
7346
|
+
{
|
|
7347
|
+
name: "lineNumbers",
|
|
7348
|
+
type: "boolean",
|
|
7349
|
+
default: "true",
|
|
7350
|
+
description: "줄 번호 거터"
|
|
7351
|
+
},
|
|
7352
|
+
{
|
|
7353
|
+
name: "theme",
|
|
7354
|
+
type: "SqlEditorTheme",
|
|
7355
|
+
default: "\"auto\"",
|
|
7356
|
+
description: "편집기 색상. auto는 OptThemeProvider의 resolved mode를 따름"
|
|
7357
|
+
},
|
|
7072
7358
|
{
|
|
7073
7359
|
name: "labels",
|
|
7074
7360
|
type: "SqlEditorLabels",
|
|
@@ -7259,6 +7545,221 @@ const filters = [
|
|
|
7259
7545
|
}],
|
|
7260
7546
|
testDescribe: "SegmentBuilder"
|
|
7261
7547
|
},
|
|
7548
|
+
{
|
|
7549
|
+
name: "CriteriaBuilder",
|
|
7550
|
+
category: "shell",
|
|
7551
|
+
description: "도메인 무관 2단계 조건 트리 편집기. 그룹 AND/OR, 순서·복제·부정·오류를 셸이 맡고 조건 문장은 소비자가 Expression 칩으로 렌더링합니다.",
|
|
7552
|
+
slug: "criteria-builder",
|
|
7553
|
+
exports: [
|
|
7554
|
+
"CriteriaBuilder",
|
|
7555
|
+
"criteriaBuilderMove",
|
|
7556
|
+
"criteriaBuilderDuplicate",
|
|
7557
|
+
"criteriaBuilderRemove",
|
|
7558
|
+
"criteriaBuilderInsert",
|
|
7559
|
+
"criteriaBuilderRemoveGroup",
|
|
7560
|
+
"criteriaBuilderDuplicateGroup",
|
|
7561
|
+
"criteriaGroupLetter"
|
|
7562
|
+
],
|
|
7563
|
+
props: { CriteriaBuilder: [
|
|
7564
|
+
{
|
|
7565
|
+
name: "value",
|
|
7566
|
+
type: "CriteriaBuilderValue<TCriterion>",
|
|
7567
|
+
required: true,
|
|
7568
|
+
description: "조건 트리. { logic, groups: [{ id, logic, criteria }] }"
|
|
7569
|
+
},
|
|
7570
|
+
{
|
|
7571
|
+
name: "onChange",
|
|
7572
|
+
type: "(next: CriteriaBuilderValue<TCriterion>) => void",
|
|
7573
|
+
required: true,
|
|
7574
|
+
description: "트리 변경 핸들러"
|
|
7575
|
+
},
|
|
7576
|
+
{
|
|
7577
|
+
name: "kinds",
|
|
7578
|
+
type: "CriteriaBuilderKindOption[]",
|
|
7579
|
+
required: true,
|
|
7580
|
+
description: "조건 추가 메뉴 항목. group으로 섹션을 나누고 negatedLabel이 있으면 부정 항목을 따로 냅니다"
|
|
7581
|
+
},
|
|
7582
|
+
{
|
|
7583
|
+
name: "createCriterion",
|
|
7584
|
+
type: "(kind: string, negate: boolean) => TCriterion",
|
|
7585
|
+
required: true,
|
|
7586
|
+
description: "메뉴 선택으로 만들 초기 조건. 고유 id를 돌려줘야 합니다"
|
|
7587
|
+
},
|
|
7588
|
+
{
|
|
7589
|
+
name: "renderCriterion",
|
|
7590
|
+
type: "(criterion: TCriterion, api: CriteriaRenderApi<TCriterion>) => React.ReactNode",
|
|
7591
|
+
required: true,
|
|
7592
|
+
description: "조건 한 줄의 편집 가능한 문장 렌더러"
|
|
7593
|
+
},
|
|
7594
|
+
{
|
|
7595
|
+
name: "cloneCriterion",
|
|
7596
|
+
type: "(criterion: TCriterion) => TCriterion",
|
|
7597
|
+
description: "복제 시 만들 사본. 기본은 새 id를 붙인 얕은 복사"
|
|
7598
|
+
},
|
|
7599
|
+
{
|
|
7600
|
+
name: "createGroupId",
|
|
7601
|
+
type: "() => string",
|
|
7602
|
+
description: "셸이 만드는 그룹의 id. 기본 group-N"
|
|
7603
|
+
},
|
|
7604
|
+
{
|
|
7605
|
+
name: "errors",
|
|
7606
|
+
type: "Record<string, string>",
|
|
7607
|
+
description: "조건 id 또는 그룹 id별 오류 메시지"
|
|
7608
|
+
},
|
|
7609
|
+
{
|
|
7610
|
+
name: "maxGroups",
|
|
7611
|
+
type: "number",
|
|
7612
|
+
default: "10",
|
|
7613
|
+
description: "그룹 최대 수"
|
|
7614
|
+
},
|
|
7615
|
+
{
|
|
7616
|
+
name: "maxCriteriaPerGroup",
|
|
7617
|
+
type: "number",
|
|
7618
|
+
default: "20",
|
|
7619
|
+
description: "그룹당 조건 최대 수"
|
|
7620
|
+
},
|
|
7621
|
+
{
|
|
7622
|
+
name: "allowNegation",
|
|
7623
|
+
type: "boolean",
|
|
7624
|
+
default: "true",
|
|
7625
|
+
description: "조건별 부정 토글 표시"
|
|
7626
|
+
},
|
|
7627
|
+
{
|
|
7628
|
+
name: "disabled",
|
|
7629
|
+
type: "boolean",
|
|
7630
|
+
default: "false",
|
|
7631
|
+
description: "전체 비활성화"
|
|
7632
|
+
},
|
|
7633
|
+
{
|
|
7634
|
+
name: "aside",
|
|
7635
|
+
type: "React.ReactNode",
|
|
7636
|
+
description: "넓은 화면에서 트리 옆, 좁은 화면에서 아래에 놓이는 미리보기 슬롯"
|
|
7637
|
+
},
|
|
7638
|
+
{
|
|
7639
|
+
name: "labels",
|
|
7640
|
+
type: "CriteriaBuilderLabels",
|
|
7641
|
+
description: "i18n용 라벨 오버라이드 (기본 한국어)"
|
|
7642
|
+
},
|
|
7643
|
+
{
|
|
7644
|
+
name: "className",
|
|
7645
|
+
type: "string",
|
|
7646
|
+
description: "루트 CSS 클래스"
|
|
7647
|
+
},
|
|
7648
|
+
{
|
|
7649
|
+
name: "aria-label",
|
|
7650
|
+
type: "string",
|
|
7651
|
+
description: "빌더 접근성 이름"
|
|
7652
|
+
}
|
|
7653
|
+
] },
|
|
7654
|
+
ariaRole: "group",
|
|
7655
|
+
keyboardShortcuts: [{
|
|
7656
|
+
keys: "A",
|
|
7657
|
+
action: "포커스된 그룹에 조건 추가 메뉴 열기"
|
|
7658
|
+
}, {
|
|
7659
|
+
keys: "G",
|
|
7660
|
+
action: "그룹 추가"
|
|
7661
|
+
}],
|
|
7662
|
+
dependencies: [
|
|
7663
|
+
{
|
|
7664
|
+
slug: "segmented-control",
|
|
7665
|
+
category: "core"
|
|
7666
|
+
},
|
|
7667
|
+
{
|
|
7668
|
+
slug: "dropdown-menu",
|
|
7669
|
+
category: "core"
|
|
7670
|
+
},
|
|
7671
|
+
{
|
|
7672
|
+
slug: "button",
|
|
7673
|
+
category: "core"
|
|
7674
|
+
},
|
|
7675
|
+
{
|
|
7676
|
+
slug: "callout",
|
|
7677
|
+
category: "core"
|
|
7678
|
+
},
|
|
7679
|
+
{
|
|
7680
|
+
slug: "empty-state",
|
|
7681
|
+
category: "core"
|
|
7682
|
+
},
|
|
7683
|
+
{
|
|
7684
|
+
slug: "kbd",
|
|
7685
|
+
category: "core"
|
|
7686
|
+
}
|
|
7687
|
+
],
|
|
7688
|
+
testDescribe: "CriteriaBuilder",
|
|
7689
|
+
usage: {
|
|
7690
|
+
bestPractices: [
|
|
7691
|
+
"조건 데이터 타입과 각 조건의 문장은 소비자가 소유합니다. renderCriterion에서 Expression 칩을 조합하고, 값 편집은 Popover로 여세요.",
|
|
7692
|
+
"createCriterion은 kind와 negate만 받아 초기 조건을 만듭니다. id는 여기서 고유하게 발급하세요.",
|
|
7693
|
+
"errors는 조건 id·그룹 id로 키를 잡습니다. 검증은 소비자가 하고 셸은 표시와 aria 연결만 맡습니다.",
|
|
7694
|
+
"aside에 라이브 카운트(StatCard)를 두면 넓은 화면에서 트리 옆에, 좁은 화면에서 아래에 놓입니다."
|
|
7695
|
+
],
|
|
7696
|
+
anatomy: ["루트 AND/OR 세그먼트 컨트롤 → 그룹 패널(레터마크 + 그룹 AND/OR + 복제/제거) → 조건 행(부정 토글 + 문장 + 이동/복제/제거) → 조건 추가 메뉴 → 그룹 추가 버튼"],
|
|
7697
|
+
avoid: ["kinds에 없는 kind를 다른 kind의 필드로 대체 렌더링하지 마세요. 셸은 이를 경고 행으로 보여 주고 바꾸기/제거만 허용합니다.", "SegmentBuilder처럼 고정 select 조합이 충분하다면 이 셸은 과합니다. 문장형 편집과 그룹 논리가 필요할 때 쓰세요."]
|
|
7698
|
+
},
|
|
7699
|
+
examples: [{
|
|
7700
|
+
validation: "typechecked",
|
|
7701
|
+
title: "이벤트 조건 세그먼트",
|
|
7702
|
+
code: `"use client";
|
|
7703
|
+
import { useState } from "react";
|
|
7704
|
+
import {
|
|
7705
|
+
CriteriaBuilder,
|
|
7706
|
+
Expression,
|
|
7707
|
+
ExpressionGroup,
|
|
7708
|
+
type CriteriaBuilderValue,
|
|
7709
|
+
} from "@reopt-ai/opt-ui";
|
|
7710
|
+
|
|
7711
|
+
interface Criterion {
|
|
7712
|
+
id: string;
|
|
7713
|
+
kind: string;
|
|
7714
|
+
negate?: boolean;
|
|
7715
|
+
event: string;
|
|
7716
|
+
}
|
|
7717
|
+
|
|
7718
|
+
let seq = 0;
|
|
7719
|
+
|
|
7720
|
+
export function Example() {
|
|
7721
|
+
const [value, setValue] = useState<CriteriaBuilderValue<Criterion>>({
|
|
7722
|
+
logic: "and",
|
|
7723
|
+
groups: [
|
|
7724
|
+
{
|
|
7725
|
+
id: "g1",
|
|
7726
|
+
logic: "and",
|
|
7727
|
+
criteria: [{ id: "c1", kind: "performed", event: "purchase" }],
|
|
7728
|
+
},
|
|
7729
|
+
],
|
|
7730
|
+
});
|
|
7731
|
+
return (
|
|
7732
|
+
<CriteriaBuilder
|
|
7733
|
+
value={value}
|
|
7734
|
+
onChange={setValue}
|
|
7735
|
+
kinds={[
|
|
7736
|
+
{
|
|
7737
|
+
kind: "performed",
|
|
7738
|
+
label: "이벤트를 수행함",
|
|
7739
|
+
negatedLabel: "이벤트를 수행하지 않음",
|
|
7740
|
+
},
|
|
7741
|
+
]}
|
|
7742
|
+
createCriterion={(kind, negate) => ({
|
|
7743
|
+
id: \`c\${++seq}\`,
|
|
7744
|
+
kind,
|
|
7745
|
+
negate,
|
|
7746
|
+
event: "",
|
|
7747
|
+
})}
|
|
7748
|
+
renderCriterion={(criterion, api) => (
|
|
7749
|
+
<ExpressionGroup>
|
|
7750
|
+
<Expression
|
|
7751
|
+
description={criterion.negate ? "수행하지 않음" : "수행함"}
|
|
7752
|
+
value={criterion.event || "이벤트 선택"}
|
|
7753
|
+
invalid={api.invalid || criterion.event === ""}
|
|
7754
|
+
onClick={() => api.update({ event: "purchase" })}
|
|
7755
|
+
/>
|
|
7756
|
+
</ExpressionGroup>
|
|
7757
|
+
)}
|
|
7758
|
+
/>
|
|
7759
|
+
);
|
|
7760
|
+
}`
|
|
7761
|
+
}]
|
|
7762
|
+
},
|
|
7262
7763
|
{
|
|
7263
7764
|
name: "InsightsPanel",
|
|
7264
7765
|
category: "shell",
|
|
@@ -7315,6 +7816,21 @@ const filters = [
|
|
|
7315
7816
|
testDescribe: "InsightsPanel"
|
|
7316
7817
|
},
|
|
7317
7818
|
{
|
|
7819
|
+
usage: {
|
|
7820
|
+
bestPractices: ["제어 모드에서는 value와 onChange를 함께 연결합니다. labels와 presets의 label은 제품 언어로 제공합니다.", "프리셋은 로컬 날짜의 자정을 기준으로 계산하므로 API의 시간대·종료일 포함 여부를 조회 계층에서 명시적으로 변환합니다."],
|
|
7821
|
+
avoid: ["날짜 선택만으로 서버 집계가 갱신된다고 가정하거나 null 날짜를 유효한 조회 범위로 전송하지 않습니다."]
|
|
7822
|
+
},
|
|
7823
|
+
examples: [{
|
|
7824
|
+
validation: "typechecked",
|
|
7825
|
+
title: "제어되는 조회 기간",
|
|
7826
|
+
code: `"use client";
|
|
7827
|
+
import { useState } from "react";
|
|
7828
|
+
import { TimeRangeSelector, type DateRange } from "@reopt-ai/opt-ui";
|
|
7829
|
+
export function Example() {
|
|
7830
|
+
const [range, setRange] = useState<DateRange>({ start: null, end: null });
|
|
7831
|
+
return <TimeRangeSelector value={range} onChange={setRange} labels={{ title: "조회 기간", placeholder: "기간 선택" }} presets={[{ label: "최근 7일", days: 7 }]} />;
|
|
7832
|
+
}`
|
|
7833
|
+
}],
|
|
7318
7834
|
name: "TimeRangeSelector",
|
|
7319
7835
|
category: "shell",
|
|
7320
7836
|
description: "시간 범위 선택기. Popover + DateRangePicker + 프리셋 버튼 조합. 12개 시계열 Surface에서 사용.",
|
|
@@ -7404,6 +7920,19 @@ const filters = [
|
|
|
7404
7920
|
testDescribe: "ExportButton"
|
|
7405
7921
|
},
|
|
7406
7922
|
{
|
|
7923
|
+
usage: {
|
|
7924
|
+
bestPractices: ["stats에는 안정적인 id와 표시 value를 제공합니다. 감소가 좋은 지표는 polarity=negative로 비교 의미를 명시합니다.", "선택 가능한 카드에서는 onStatClick과 selectedStatId를 같은 조회 상태에 연결합니다. 빈 목록 문구는 labels로 제공합니다."],
|
|
7925
|
+
avoid: ["loading 중 빈 결과를 확정적으로 표시하거나 모든 상승 추세를 좋은 결과로 해석하지 않습니다."]
|
|
7926
|
+
},
|
|
7927
|
+
examples: [{
|
|
7928
|
+
validation: "typechecked",
|
|
7929
|
+
title: "의미가 다른 통계 비교",
|
|
7930
|
+
code: `import { SummaryRow } from "@reopt-ai/opt-ui";
|
|
7931
|
+
export function Example() { return <SummaryRow columns={2} stats={[
|
|
7932
|
+
{ id: "orders", title: "주문", value: "120", change: "+10%", trend: "up" },
|
|
7933
|
+
{ id: "errors", title: "오류", value: "2", change: "-50%", trend: "down", polarity: "negative" },
|
|
7934
|
+
]} />; }`
|
|
7935
|
+
}],
|
|
7407
7936
|
name: "SummaryRow",
|
|
7408
7937
|
category: "shell",
|
|
7409
7938
|
description: "통계 요약 행. StatCard 그리드 레이아웃을 표준화합니다. loading 시 SkeletonCard 표시.",
|
|
@@ -9881,6 +10410,777 @@ const messages = [
|
|
|
9881
10410
|
avoid: ["선택 초기화를 호출자에게 맡기지 않습니다 — 보이지 않는 행에 일괄 작업이 적용됩니다."]
|
|
9882
10411
|
},
|
|
9883
10412
|
testDescribe: "CatalogFrame"
|
|
10413
|
+
},
|
|
10414
|
+
{
|
|
10415
|
+
name: "SchemaTree",
|
|
10416
|
+
category: "shell",
|
|
10417
|
+
functionalCategory: "navigation",
|
|
10418
|
+
maturity: "stable",
|
|
10419
|
+
keywords: [
|
|
10420
|
+
"sql",
|
|
10421
|
+
"schema",
|
|
10422
|
+
"tables",
|
|
10423
|
+
"columns",
|
|
10424
|
+
"tree",
|
|
10425
|
+
"autocomplete"
|
|
10426
|
+
],
|
|
10427
|
+
description: "쿼리할 수 있는 테이블과 컬럼을 타입 글리프와 함께 보여주는 트리. 테이블·컬럼을 함께 검색하고, 이름을 커서에 삽입하거나 테이블을 미리보기합니다.",
|
|
10428
|
+
slug: "schema-tree",
|
|
10429
|
+
exports: ["SchemaTree"],
|
|
10430
|
+
props: { SchemaTree: [
|
|
10431
|
+
{
|
|
10432
|
+
name: "tables",
|
|
10433
|
+
type: "SchemaTreeTable[]",
|
|
10434
|
+
required: true,
|
|
10435
|
+
description: "테이블과 컬럼"
|
|
10436
|
+
},
|
|
10437
|
+
{
|
|
10438
|
+
name: "loading",
|
|
10439
|
+
type: "boolean",
|
|
10440
|
+
description: "스키마 조회 중"
|
|
10441
|
+
},
|
|
10442
|
+
{
|
|
10443
|
+
name: "defaultExpanded",
|
|
10444
|
+
type: "string[]",
|
|
10445
|
+
description: "처음에 펼칠 테이블. 생략 시 첫 테이블"
|
|
10446
|
+
},
|
|
10447
|
+
{
|
|
10448
|
+
name: "onInsert",
|
|
10449
|
+
type: "(name: string, kind: \"table\" | \"column\", table: string) => void",
|
|
10450
|
+
description: "이름을 편집기 커서에 삽입"
|
|
10451
|
+
},
|
|
10452
|
+
{
|
|
10453
|
+
name: "onPreview",
|
|
10454
|
+
type: "(table: string) => void",
|
|
10455
|
+
description: "테이블 미리보기 실행. SQL은 호출자가 작성"
|
|
10456
|
+
},
|
|
10457
|
+
{
|
|
10458
|
+
name: "header",
|
|
10459
|
+
type: "ReactNode",
|
|
10460
|
+
description: "검색창 위 내용"
|
|
10461
|
+
},
|
|
10462
|
+
{
|
|
10463
|
+
name: "labels",
|
|
10464
|
+
type: "SchemaTreeLabels",
|
|
10465
|
+
description: "문구 오버라이드"
|
|
10466
|
+
}
|
|
10467
|
+
] },
|
|
10468
|
+
dependencies: [{
|
|
10469
|
+
slug: "field-token",
|
|
10470
|
+
category: "core"
|
|
10471
|
+
}, {
|
|
10472
|
+
slug: "highlight",
|
|
10473
|
+
category: "core"
|
|
10474
|
+
}],
|
|
10475
|
+
ariaRole: "complementary",
|
|
10476
|
+
testDescribe: "SchemaTree"
|
|
10477
|
+
},
|
|
10478
|
+
{
|
|
10479
|
+
name: "QueryToolbar",
|
|
10480
|
+
category: "shell",
|
|
10481
|
+
functionalCategory: "action",
|
|
10482
|
+
maturity: "stable",
|
|
10483
|
+
keywords: [
|
|
10484
|
+
"sql",
|
|
10485
|
+
"run",
|
|
10486
|
+
"cancel",
|
|
10487
|
+
"toolbar",
|
|
10488
|
+
"shortcut"
|
|
10489
|
+
],
|
|
10490
|
+
description: "실행 버튼 하나가 상태를 말하는 쿼리 툴바. 변경됨/현재/실행 중을 색과 문구로 구분하고, 실행 중이면 취소로 바뀌며, 선택 영역·전체 실행은 분할 버튼 뒤에 둡니다.",
|
|
10491
|
+
slug: "query-toolbar",
|
|
10492
|
+
exports: ["QueryToolbar"],
|
|
10493
|
+
props: { QueryToolbar: [
|
|
10494
|
+
{
|
|
10495
|
+
name: "onRun",
|
|
10496
|
+
type: "() => void",
|
|
10497
|
+
required: true,
|
|
10498
|
+
description: "커서 위치의 문장 실행"
|
|
10499
|
+
},
|
|
10500
|
+
{
|
|
10501
|
+
name: "onCancel",
|
|
10502
|
+
type: "() => void",
|
|
10503
|
+
description: "실행 중 취소. 있으면 버튼이 Cancel로 전환"
|
|
10504
|
+
},
|
|
10505
|
+
{
|
|
10506
|
+
name: "running",
|
|
10507
|
+
type: "boolean",
|
|
10508
|
+
description: "실행 중"
|
|
10509
|
+
},
|
|
10510
|
+
{
|
|
10511
|
+
name: "runState",
|
|
10512
|
+
type: "QueryRunState",
|
|
10513
|
+
default: "\"idle\"",
|
|
10514
|
+
description: "마지막 실행 대비 변경 여부"
|
|
10515
|
+
},
|
|
10516
|
+
{
|
|
10517
|
+
name: "runDisabledReason",
|
|
10518
|
+
type: "string",
|
|
10519
|
+
description: "실행 불가 사유. 툴팁으로 표시"
|
|
10520
|
+
},
|
|
10521
|
+
{
|
|
10522
|
+
name: "onRunSelection",
|
|
10523
|
+
type: "() => void",
|
|
10524
|
+
description: "선택 영역만 실행"
|
|
10525
|
+
},
|
|
10526
|
+
{
|
|
10527
|
+
name: "hasSelection",
|
|
10528
|
+
type: "boolean",
|
|
10529
|
+
description: "선택 영역이 있는지. 없으면 항목 비활성"
|
|
10530
|
+
},
|
|
10531
|
+
{
|
|
10532
|
+
name: "onRunAll",
|
|
10533
|
+
type: "() => void",
|
|
10534
|
+
description: "전체 문장 실행"
|
|
10535
|
+
},
|
|
10536
|
+
{
|
|
10537
|
+
name: "multiStatement",
|
|
10538
|
+
type: "boolean",
|
|
10539
|
+
description: "문장이 둘 이상인지. 아니면 전체 실행을 숨김"
|
|
10540
|
+
},
|
|
10541
|
+
{
|
|
10542
|
+
name: "onSave",
|
|
10543
|
+
type: "() => void",
|
|
10544
|
+
description: "저장 다이얼로그 열기"
|
|
10545
|
+
},
|
|
10546
|
+
{
|
|
10547
|
+
name: "saveDisabled",
|
|
10548
|
+
type: "boolean",
|
|
10549
|
+
description: "저장 비활성"
|
|
10550
|
+
},
|
|
10551
|
+
{
|
|
10552
|
+
name: "children",
|
|
10553
|
+
type: "ReactNode",
|
|
10554
|
+
description: "실행 그룹 뒤의 컨트롤 — 필터, 변수"
|
|
10555
|
+
},
|
|
10556
|
+
{
|
|
10557
|
+
name: "trailing",
|
|
10558
|
+
type: "ReactNode",
|
|
10559
|
+
description: "끝쪽 컨트롤"
|
|
10560
|
+
},
|
|
10561
|
+
{
|
|
10562
|
+
name: "modifierKey",
|
|
10563
|
+
type: "string",
|
|
10564
|
+
description: "단축키 힌트의 수정자 글리프. 기본은 플랫폼 감지"
|
|
10565
|
+
},
|
|
10566
|
+
{
|
|
10567
|
+
name: "labels",
|
|
10568
|
+
type: "QueryToolbarLabels",
|
|
10569
|
+
description: "문구 오버라이드"
|
|
10570
|
+
}
|
|
10571
|
+
] },
|
|
10572
|
+
dependencies: [
|
|
10573
|
+
{
|
|
10574
|
+
slug: "button",
|
|
10575
|
+
category: "core"
|
|
10576
|
+
},
|
|
10577
|
+
{
|
|
10578
|
+
slug: "kbd",
|
|
10579
|
+
category: "core"
|
|
10580
|
+
},
|
|
10581
|
+
{
|
|
10582
|
+
slug: "dropdown-menu",
|
|
10583
|
+
category: "core"
|
|
10584
|
+
}
|
|
10585
|
+
],
|
|
10586
|
+
ariaRole: "toolbar",
|
|
10587
|
+
testDescribe: "QueryToolbar"
|
|
10588
|
+
},
|
|
10589
|
+
{
|
|
10590
|
+
name: "QueryOutputPane",
|
|
10591
|
+
category: "shell",
|
|
10592
|
+
functionalCategory: "data-display",
|
|
10593
|
+
maturity: "stable",
|
|
10594
|
+
keywords: [
|
|
10595
|
+
"sql",
|
|
10596
|
+
"results",
|
|
10597
|
+
"chart",
|
|
10598
|
+
"split",
|
|
10599
|
+
"status bar"
|
|
10600
|
+
],
|
|
10601
|
+
description: "쿼리 결과가 놓이는 출력 패널. 대기·실행 중·오류·취소·완료 상태를 그리고, 완료는 표·차트·좌우 분할로 전환하며, 상태바에 행 수·경과·읽은 바이트·절단 여부를 남깁니다.",
|
|
10602
|
+
slug: "query-output-pane",
|
|
10603
|
+
exports: ["QueryOutputPane"],
|
|
10604
|
+
props: { QueryOutputPane: [
|
|
10605
|
+
{
|
|
10606
|
+
name: "view",
|
|
10607
|
+
type: "QueryOutputView",
|
|
10608
|
+
required: true,
|
|
10609
|
+
description: "표 / 차트 / 분할"
|
|
10610
|
+
},
|
|
10611
|
+
{
|
|
10612
|
+
name: "onViewChange",
|
|
10613
|
+
type: "(view: QueryOutputView) => void",
|
|
10614
|
+
required: true,
|
|
10615
|
+
description: "뷰 전환"
|
|
10616
|
+
},
|
|
10617
|
+
{
|
|
10618
|
+
name: "results",
|
|
10619
|
+
type: "ReactNode",
|
|
10620
|
+
required: true,
|
|
10621
|
+
description: "결과 테이블"
|
|
10622
|
+
},
|
|
10623
|
+
{
|
|
10624
|
+
name: "chart",
|
|
10625
|
+
type: "ReactNode",
|
|
10626
|
+
description: "차트 빌더. 없으면 차트 뷰를 숨김"
|
|
10627
|
+
},
|
|
10628
|
+
{
|
|
10629
|
+
name: "status",
|
|
10630
|
+
type: "\"idle\" | \"running\" | \"success\" | \"error\" | \"cancelled\"",
|
|
10631
|
+
required: true,
|
|
10632
|
+
description: "실행 수명주기"
|
|
10633
|
+
},
|
|
10634
|
+
{
|
|
10635
|
+
name: "error",
|
|
10636
|
+
type: "string",
|
|
10637
|
+
description: "백엔드 오류 원문"
|
|
10638
|
+
},
|
|
10639
|
+
{
|
|
10640
|
+
name: "runningSeconds",
|
|
10641
|
+
type: "number",
|
|
10642
|
+
description: "실행 경과 초. 로딩 상태에 표시"
|
|
10643
|
+
},
|
|
10644
|
+
{
|
|
10645
|
+
name: "onCancel",
|
|
10646
|
+
type: "() => void",
|
|
10647
|
+
description: "실행 취소"
|
|
10648
|
+
},
|
|
10649
|
+
{
|
|
10650
|
+
name: "stats",
|
|
10651
|
+
type: "QueryRunStats",
|
|
10652
|
+
description: "행 수, 경과, 읽은 바이트, 절단 여부"
|
|
10653
|
+
},
|
|
10654
|
+
{
|
|
10655
|
+
name: "actions",
|
|
10656
|
+
type: "ReactNode",
|
|
10657
|
+
description: "뷰 전환 오른쪽 컨트롤"
|
|
10658
|
+
},
|
|
10659
|
+
{
|
|
10660
|
+
name: "statusExtra",
|
|
10661
|
+
type: "ReactNode",
|
|
10662
|
+
description: "상태바 추가 내용"
|
|
10663
|
+
},
|
|
10664
|
+
{
|
|
10665
|
+
name: "banner",
|
|
10666
|
+
type: "ReactNode",
|
|
10667
|
+
description: "출력 위 알림"
|
|
10668
|
+
},
|
|
10669
|
+
{
|
|
10670
|
+
name: "onRetry",
|
|
10671
|
+
type: "() => void",
|
|
10672
|
+
description: "오류 상태 닫기"
|
|
10673
|
+
},
|
|
10674
|
+
{
|
|
10675
|
+
name: "labels",
|
|
10676
|
+
type: "QueryOutputPaneLabels",
|
|
10677
|
+
description: "문구 오버라이드"
|
|
10678
|
+
}
|
|
10679
|
+
] },
|
|
10680
|
+
dependencies: [
|
|
10681
|
+
{
|
|
10682
|
+
slug: "segmented-control",
|
|
10683
|
+
category: "core"
|
|
10684
|
+
},
|
|
10685
|
+
{
|
|
10686
|
+
slug: "empty-state",
|
|
10687
|
+
category: "core"
|
|
10688
|
+
},
|
|
10689
|
+
{
|
|
10690
|
+
slug: "resizable",
|
|
10691
|
+
category: "core"
|
|
10692
|
+
}
|
|
10693
|
+
],
|
|
10694
|
+
ariaRole: "region",
|
|
10695
|
+
testDescribe: "QueryOutputPane"
|
|
10696
|
+
},
|
|
10697
|
+
{
|
|
10698
|
+
name: "QueryResultChart",
|
|
10699
|
+
category: "shell",
|
|
10700
|
+
functionalCategory: "data-display",
|
|
10701
|
+
maturity: "stable",
|
|
10702
|
+
keywords: [
|
|
10703
|
+
"sql",
|
|
10704
|
+
"chart",
|
|
10705
|
+
"visualization",
|
|
10706
|
+
"line",
|
|
10707
|
+
"bar",
|
|
10708
|
+
"pie",
|
|
10709
|
+
"number"
|
|
10710
|
+
],
|
|
10711
|
+
description: "결과 행을 차트로 그리는 빌더. 첫 문자·날짜 컬럼을 축으로, 숫자 컬럼을 값으로 고르고, 한 행 한 숫자면 큰 숫자로 보여줍니다. 설정은 호출자가 들고 있어 저장 쿼리와 함께 보관됩니다.",
|
|
10712
|
+
slug: "query-result-chart",
|
|
10713
|
+
exports: ["QueryResultChart"],
|
|
10714
|
+
domlessExports: ["defaultQueryChartConfig", "numericResultColumns"],
|
|
10715
|
+
props: { QueryResultChart: [
|
|
10716
|
+
{
|
|
10717
|
+
name: "columns",
|
|
10718
|
+
type: "QueryResultColumn[]",
|
|
10719
|
+
required: true,
|
|
10720
|
+
description: "결과 컬럼"
|
|
10721
|
+
},
|
|
10722
|
+
{
|
|
10723
|
+
name: "rows",
|
|
10724
|
+
type: "Array<Record<string, unknown>>",
|
|
10725
|
+
required: true,
|
|
10726
|
+
description: "결과 행"
|
|
10727
|
+
},
|
|
10728
|
+
{
|
|
10729
|
+
name: "config",
|
|
10730
|
+
type: "QueryChartConfig",
|
|
10731
|
+
required: true,
|
|
10732
|
+
description: "차트 종류, 축, 값 컬럼"
|
|
10733
|
+
},
|
|
10734
|
+
{
|
|
10735
|
+
name: "onConfigChange",
|
|
10736
|
+
type: "(config: QueryChartConfig) => void",
|
|
10737
|
+
required: true,
|
|
10738
|
+
description: "설정 변경"
|
|
10739
|
+
},
|
|
10740
|
+
{
|
|
10741
|
+
name: "showControls",
|
|
10742
|
+
type: "boolean",
|
|
10743
|
+
default: "true",
|
|
10744
|
+
description: "컨트롤 표시. 임베드 카드에서는 끔"
|
|
10745
|
+
},
|
|
10746
|
+
{
|
|
10747
|
+
name: "height",
|
|
10748
|
+
type: "number",
|
|
10749
|
+
description: "차트 높이(px). 기본은 부모 채움"
|
|
10750
|
+
},
|
|
10751
|
+
{
|
|
10752
|
+
name: "maxPoints",
|
|
10753
|
+
type: "number",
|
|
10754
|
+
default: "1000",
|
|
10755
|
+
description: "차트에 그릴 최대 행 수"
|
|
10756
|
+
},
|
|
10757
|
+
{
|
|
10758
|
+
name: "labels",
|
|
10759
|
+
type: "QueryResultChartLabels",
|
|
10760
|
+
description: "문구 오버라이드"
|
|
10761
|
+
}
|
|
10762
|
+
] },
|
|
10763
|
+
dependencies: [
|
|
10764
|
+
{
|
|
10765
|
+
slug: "line-chart",
|
|
10766
|
+
category: "visuals"
|
|
10767
|
+
},
|
|
10768
|
+
{
|
|
10769
|
+
slug: "bar-chart",
|
|
10770
|
+
category: "visuals"
|
|
10771
|
+
},
|
|
10772
|
+
{
|
|
10773
|
+
slug: "area-chart",
|
|
10774
|
+
category: "visuals"
|
|
10775
|
+
},
|
|
10776
|
+
{
|
|
10777
|
+
slug: "pie-chart",
|
|
10778
|
+
category: "visuals"
|
|
10779
|
+
},
|
|
10780
|
+
{
|
|
10781
|
+
slug: "segmented-control",
|
|
10782
|
+
category: "core"
|
|
10783
|
+
},
|
|
10784
|
+
{
|
|
10785
|
+
slug: "select",
|
|
10786
|
+
category: "core"
|
|
10787
|
+
}
|
|
10788
|
+
],
|
|
10789
|
+
testDescribe: "QueryResultChart"
|
|
10790
|
+
},
|
|
10791
|
+
{
|
|
10792
|
+
name: "QueryFiltersMenu",
|
|
10793
|
+
category: "shell",
|
|
10794
|
+
functionalCategory: "input",
|
|
10795
|
+
maturity: "stable",
|
|
10796
|
+
keywords: [
|
|
10797
|
+
"sql",
|
|
10798
|
+
"filters",
|
|
10799
|
+
"date range",
|
|
10800
|
+
"placeholder",
|
|
10801
|
+
"where"
|
|
10802
|
+
],
|
|
10803
|
+
description: "기간과 속성 조건을 데이터로 들고 {filters} 플레이스홀더로 SQL에 전달하는 메뉴. 플레이스홀더가 없으면 조건이 적용되지 않는다고 경고하고 삽입 버튼을 제공합니다.",
|
|
10804
|
+
slug: "query-filters-menu",
|
|
10805
|
+
exports: ["QueryFiltersMenu"],
|
|
10806
|
+
domlessExports: [
|
|
10807
|
+
"EMPTY_QUERY_FILTERS",
|
|
10808
|
+
"VALUELESS_OPERATORS",
|
|
10809
|
+
"hasActiveQueryFilters",
|
|
10810
|
+
"countActiveQueryFilters"
|
|
10811
|
+
],
|
|
10812
|
+
props: { QueryFiltersMenu: [
|
|
10813
|
+
{
|
|
10814
|
+
name: "value",
|
|
10815
|
+
type: "QueryFilters",
|
|
10816
|
+
required: true,
|
|
10817
|
+
description: "기간과 속성 필터"
|
|
10818
|
+
},
|
|
10819
|
+
{
|
|
10820
|
+
name: "onChange",
|
|
10821
|
+
type: "(filters: QueryFilters) => void",
|
|
10822
|
+
required: true,
|
|
10823
|
+
description: "필터 변경"
|
|
10824
|
+
},
|
|
10825
|
+
{
|
|
10826
|
+
name: "fields",
|
|
10827
|
+
type: "QueryFilterField[]",
|
|
10828
|
+
required: true,
|
|
10829
|
+
description: "필드 선택지"
|
|
10830
|
+
},
|
|
10831
|
+
{
|
|
10832
|
+
name: "placeholderPresent",
|
|
10833
|
+
type: "boolean",
|
|
10834
|
+
description: "SQL에 {filters}가 있는지"
|
|
10835
|
+
},
|
|
10836
|
+
{
|
|
10837
|
+
name: "onInsertPlaceholder",
|
|
10838
|
+
type: "() => void",
|
|
10839
|
+
description: "{filters}를 커서에 삽입"
|
|
10840
|
+
},
|
|
10841
|
+
{
|
|
10842
|
+
name: "onLoadValues",
|
|
10843
|
+
type: "(field: string) => Promise<string[]>",
|
|
10844
|
+
description: "필드의 알려진 값. 값 입력란의 제안으로 쓰이며 자유 입력도 허용"
|
|
10845
|
+
},
|
|
10846
|
+
{
|
|
10847
|
+
name: "presets",
|
|
10848
|
+
type: "DateRangePreset[]",
|
|
10849
|
+
description: "기간 프리셋"
|
|
10850
|
+
},
|
|
10851
|
+
{
|
|
10852
|
+
name: "disabled",
|
|
10853
|
+
type: "boolean",
|
|
10854
|
+
description: "비활성"
|
|
10855
|
+
},
|
|
10856
|
+
{
|
|
10857
|
+
name: "labels",
|
|
10858
|
+
type: "QueryFiltersMenuLabels",
|
|
10859
|
+
description: "문구 오버라이드"
|
|
10860
|
+
}
|
|
10861
|
+
] },
|
|
10862
|
+
dependencies: [
|
|
10863
|
+
{
|
|
10864
|
+
slug: "popover",
|
|
10865
|
+
category: "core"
|
|
10866
|
+
},
|
|
10867
|
+
{
|
|
10868
|
+
slug: "date-range-picker",
|
|
10869
|
+
category: "core"
|
|
10870
|
+
},
|
|
10871
|
+
{
|
|
10872
|
+
slug: "select",
|
|
10873
|
+
category: "core"
|
|
10874
|
+
},
|
|
10875
|
+
{
|
|
10876
|
+
slug: "combobox",
|
|
10877
|
+
category: "core"
|
|
10878
|
+
},
|
|
10879
|
+
{
|
|
10880
|
+
slug: "callout",
|
|
10881
|
+
category: "core"
|
|
10882
|
+
}
|
|
10883
|
+
],
|
|
10884
|
+
testDescribe: "QueryFiltersMenu"
|
|
10885
|
+
},
|
|
10886
|
+
{
|
|
10887
|
+
name: "QueryVariablesMenu",
|
|
10888
|
+
category: "shell",
|
|
10889
|
+
functionalCategory: "input",
|
|
10890
|
+
maturity: "stable",
|
|
10891
|
+
keywords: [
|
|
10892
|
+
"sql",
|
|
10893
|
+
"variables",
|
|
10894
|
+
"parameters",
|
|
10895
|
+
"placeholder"
|
|
10896
|
+
],
|
|
10897
|
+
description: "실행마다 바뀌는 값을 이름 붙여 두는 변수 메뉴. SQL은 {variables.name}으로 참조하고 치환은 호출자가 합니다.",
|
|
10898
|
+
slug: "query-variables-menu",
|
|
10899
|
+
exports: ["QueryVariablesMenu"],
|
|
10900
|
+
domlessExports: ["isValidQueryVariableName"],
|
|
10901
|
+
props: { QueryVariablesMenu: [
|
|
10902
|
+
{
|
|
10903
|
+
name: "value",
|
|
10904
|
+
type: "QueryVariable[]",
|
|
10905
|
+
required: true,
|
|
10906
|
+
description: "변수 목록"
|
|
10907
|
+
},
|
|
10908
|
+
{
|
|
10909
|
+
name: "onChange",
|
|
10910
|
+
type: "(variables: QueryVariable[]) => void",
|
|
10911
|
+
required: true,
|
|
10912
|
+
description: "변수 변경"
|
|
10913
|
+
},
|
|
10914
|
+
{
|
|
10915
|
+
name: "onInsert",
|
|
10916
|
+
type: "(name: string) => void",
|
|
10917
|
+
description: "{variables.name}을 커서에 삽입"
|
|
10918
|
+
},
|
|
10919
|
+
{
|
|
10920
|
+
name: "disabled",
|
|
10921
|
+
type: "boolean",
|
|
10922
|
+
description: "비활성"
|
|
10923
|
+
},
|
|
10924
|
+
{
|
|
10925
|
+
name: "disabledReason",
|
|
10926
|
+
type: "string",
|
|
10927
|
+
description: "비활성 사유. 툴팁으로 표시"
|
|
10928
|
+
},
|
|
10929
|
+
{
|
|
10930
|
+
name: "labels",
|
|
10931
|
+
type: "QueryVariablesMenuLabels",
|
|
10932
|
+
description: "문구 오버라이드"
|
|
10933
|
+
}
|
|
10934
|
+
] },
|
|
10935
|
+
dependencies: [{
|
|
10936
|
+
slug: "popover",
|
|
10937
|
+
category: "core"
|
|
10938
|
+
}, {
|
|
10939
|
+
slug: "input",
|
|
10940
|
+
category: "core"
|
|
10941
|
+
}],
|
|
10942
|
+
testDescribe: "QueryVariablesMenu"
|
|
10943
|
+
},
|
|
10944
|
+
{
|
|
10945
|
+
name: "QueryHistoryList",
|
|
10946
|
+
category: "shell",
|
|
10947
|
+
functionalCategory: "data-display",
|
|
10948
|
+
maturity: "stable",
|
|
10949
|
+
keywords: [
|
|
10950
|
+
"sql",
|
|
10951
|
+
"history",
|
|
10952
|
+
"recent",
|
|
10953
|
+
"rerun"
|
|
10954
|
+
],
|
|
10955
|
+
description: "실행 이력 목록. 각 실행의 성공/실패, 시각, 행 수, 경과를 보여주고 편집기로 되돌리거나 다시 실행합니다.",
|
|
10956
|
+
slug: "query-history-list",
|
|
10957
|
+
exports: ["QueryHistoryList"],
|
|
10958
|
+
props: { QueryHistoryList: [
|
|
10959
|
+
{
|
|
10960
|
+
name: "items",
|
|
10961
|
+
type: "QueryHistoryItem[]",
|
|
10962
|
+
required: true,
|
|
10963
|
+
description: "최근 실행부터"
|
|
10964
|
+
},
|
|
10965
|
+
{
|
|
10966
|
+
name: "loading",
|
|
10967
|
+
type: "boolean",
|
|
10968
|
+
description: "이력 조회 중"
|
|
10969
|
+
},
|
|
10970
|
+
{
|
|
10971
|
+
name: "onLoad",
|
|
10972
|
+
type: "(item: QueryHistoryItem) => void",
|
|
10973
|
+
description: "쿼리를 편집기로"
|
|
10974
|
+
},
|
|
10975
|
+
{
|
|
10976
|
+
name: "onRerun",
|
|
10977
|
+
type: "(item: QueryHistoryItem) => void",
|
|
10978
|
+
description: "그대로 다시 실행"
|
|
10979
|
+
},
|
|
10980
|
+
{
|
|
10981
|
+
name: "onClear",
|
|
10982
|
+
type: "() => void",
|
|
10983
|
+
description: "이력 비우기"
|
|
10984
|
+
},
|
|
10985
|
+
{
|
|
10986
|
+
name: "header",
|
|
10987
|
+
type: "ReactNode",
|
|
10988
|
+
description: "목록 위 내용"
|
|
10989
|
+
},
|
|
10990
|
+
{
|
|
10991
|
+
name: "labels",
|
|
10992
|
+
type: "QueryHistoryListLabels",
|
|
10993
|
+
description: "문구 오버라이드"
|
|
10994
|
+
}
|
|
10995
|
+
] },
|
|
10996
|
+
dependencies: [{
|
|
10997
|
+
slug: "button",
|
|
10998
|
+
category: "core"
|
|
10999
|
+
}],
|
|
11000
|
+
ariaRole: "region",
|
|
11001
|
+
testDescribe: "QueryHistoryList"
|
|
11002
|
+
},
|
|
11003
|
+
{
|
|
11004
|
+
name: "SaveQueryDialog",
|
|
11005
|
+
category: "shell",
|
|
11006
|
+
functionalCategory: "overlay",
|
|
11007
|
+
maturity: "stable",
|
|
11008
|
+
keywords: [
|
|
11009
|
+
"sql",
|
|
11010
|
+
"save",
|
|
11011
|
+
"dialog",
|
|
11012
|
+
"saved query"
|
|
11013
|
+
],
|
|
11014
|
+
description: "쿼리에 이름·설명·공개 여부를 붙여 저장하는 다이얼로그. 편집기에 문장이 여럿이면 어느 문장을 저장할지 넘겨 보며 고릅니다.",
|
|
11015
|
+
slug: "save-query-dialog",
|
|
11016
|
+
exports: ["SaveQueryDialog"],
|
|
11017
|
+
props: { SaveQueryDialog: [
|
|
11018
|
+
{
|
|
11019
|
+
name: "open",
|
|
11020
|
+
type: "boolean",
|
|
11021
|
+
required: true,
|
|
11022
|
+
description: "열림"
|
|
11023
|
+
},
|
|
11024
|
+
{
|
|
11025
|
+
name: "onOpenChange",
|
|
11026
|
+
type: "(open: boolean) => void",
|
|
11027
|
+
required: true,
|
|
11028
|
+
description: "열림 상태 변경"
|
|
11029
|
+
},
|
|
11030
|
+
{
|
|
11031
|
+
name: "onSubmit",
|
|
11032
|
+
type: "(values: SaveQueryValues) => void | Promise<void>",
|
|
11033
|
+
required: true,
|
|
11034
|
+
description: "저장"
|
|
11035
|
+
},
|
|
11036
|
+
{
|
|
11037
|
+
name: "candidates",
|
|
11038
|
+
type: "string[]",
|
|
11039
|
+
required: true,
|
|
11040
|
+
description: "저장할 SQL 후보. 문장이 여럿이면 여러 개"
|
|
11041
|
+
},
|
|
11042
|
+
{
|
|
11043
|
+
name: "initialCandidate",
|
|
11044
|
+
type: "number",
|
|
11045
|
+
default: "0",
|
|
11046
|
+
description: "처음 보여줄 후보"
|
|
11047
|
+
},
|
|
11048
|
+
{
|
|
11049
|
+
name: "candidateIsSelection",
|
|
11050
|
+
type: "boolean",
|
|
11051
|
+
description: "후보가 선택 영역인지"
|
|
11052
|
+
},
|
|
11053
|
+
{
|
|
11054
|
+
name: "initialValues",
|
|
11055
|
+
type: "Partial<Omit<SaveQueryValues, \"sql\">>",
|
|
11056
|
+
description: "기존 저장 쿼리를 수정할 때의 초기값"
|
|
11057
|
+
},
|
|
11058
|
+
{
|
|
11059
|
+
name: "mode",
|
|
11060
|
+
type: "\"create\" | \"update\"",
|
|
11061
|
+
default: "\"create\"",
|
|
11062
|
+
description: "새로 저장 / 수정"
|
|
11063
|
+
},
|
|
11064
|
+
{
|
|
11065
|
+
name: "saving",
|
|
11066
|
+
type: "boolean",
|
|
11067
|
+
description: "저장 중"
|
|
11068
|
+
},
|
|
11069
|
+
{
|
|
11070
|
+
name: "error",
|
|
11071
|
+
type: "string",
|
|
11072
|
+
description: "저장 실패 메시지"
|
|
11073
|
+
},
|
|
11074
|
+
{
|
|
11075
|
+
name: "labels",
|
|
11076
|
+
type: "SaveQueryDialogLabels",
|
|
11077
|
+
description: "문구 오버라이드"
|
|
11078
|
+
}
|
|
11079
|
+
] },
|
|
11080
|
+
dependencies: [
|
|
11081
|
+
{
|
|
11082
|
+
slug: "dialog",
|
|
11083
|
+
category: "core"
|
|
11084
|
+
},
|
|
11085
|
+
{
|
|
11086
|
+
slug: "input",
|
|
11087
|
+
category: "core"
|
|
11088
|
+
},
|
|
11089
|
+
{
|
|
11090
|
+
slug: "textarea",
|
|
11091
|
+
category: "core"
|
|
11092
|
+
},
|
|
11093
|
+
{
|
|
11094
|
+
slug: "switch",
|
|
11095
|
+
category: "core"
|
|
11096
|
+
}
|
|
11097
|
+
],
|
|
11098
|
+
testDescribe: "SaveQueryDialog"
|
|
11099
|
+
},
|
|
11100
|
+
{
|
|
11101
|
+
name: "QueryWorkspace",
|
|
11102
|
+
category: "shell",
|
|
11103
|
+
functionalCategory: "layout",
|
|
11104
|
+
maturity: "stable",
|
|
11105
|
+
keywords: [
|
|
11106
|
+
"sql",
|
|
11107
|
+
"workspace",
|
|
11108
|
+
"layout",
|
|
11109
|
+
"resizable",
|
|
11110
|
+
"sidebar"
|
|
11111
|
+
],
|
|
11112
|
+
description: "스키마·편집기·출력의 3-pane 쿼리 워크스페이스. 패널은 리사이즈되고 사이드바는 접히며, storageKey로 레이아웃을 기억합니다. 툴바·편집기·출력은 슬롯입니다.",
|
|
11113
|
+
slug: "query-workspace",
|
|
11114
|
+
exports: ["QueryWorkspace"],
|
|
11115
|
+
props: { QueryWorkspace: [
|
|
11116
|
+
{
|
|
11117
|
+
name: "sidebar",
|
|
11118
|
+
type: "ReactNode",
|
|
11119
|
+
description: "왼쪽 패널 내용"
|
|
11120
|
+
},
|
|
11121
|
+
{
|
|
11122
|
+
name: "sidebarOpen",
|
|
11123
|
+
type: "boolean",
|
|
11124
|
+
description: "제어형 사이드바 열림"
|
|
11125
|
+
},
|
|
11126
|
+
{
|
|
11127
|
+
name: "onSidebarOpenChange",
|
|
11128
|
+
type: "(open: boolean) => void",
|
|
11129
|
+
description: "사이드바 열림 변경"
|
|
11130
|
+
},
|
|
11131
|
+
{
|
|
11132
|
+
name: "header",
|
|
11133
|
+
type: "ReactNode",
|
|
11134
|
+
description: "툴바 위 — 탭이나 페이지 헤더"
|
|
11135
|
+
},
|
|
11136
|
+
{
|
|
11137
|
+
name: "toolbar",
|
|
11138
|
+
type: "ReactNode",
|
|
11139
|
+
description: "툴바"
|
|
11140
|
+
},
|
|
11141
|
+
{
|
|
11142
|
+
name: "editor",
|
|
11143
|
+
type: "ReactNode",
|
|
11144
|
+
required: true,
|
|
11145
|
+
description: "편집기"
|
|
11146
|
+
},
|
|
11147
|
+
{
|
|
11148
|
+
name: "output",
|
|
11149
|
+
type: "ReactNode",
|
|
11150
|
+
required: true,
|
|
11151
|
+
description: "출력"
|
|
11152
|
+
},
|
|
11153
|
+
{
|
|
11154
|
+
name: "storageKey",
|
|
11155
|
+
type: "string",
|
|
11156
|
+
description: "패널 크기를 localStorage에 기억할 키"
|
|
11157
|
+
},
|
|
11158
|
+
{
|
|
11159
|
+
name: "defaultSidebarSize",
|
|
11160
|
+
type: "number",
|
|
11161
|
+
default: "22",
|
|
11162
|
+
description: "사이드바 폭(%)"
|
|
11163
|
+
},
|
|
11164
|
+
{
|
|
11165
|
+
name: "defaultEditorSize",
|
|
11166
|
+
type: "number",
|
|
11167
|
+
default: "40",
|
|
11168
|
+
description: "편집기 높이(%)"
|
|
11169
|
+
},
|
|
11170
|
+
{
|
|
11171
|
+
name: "labels",
|
|
11172
|
+
type: "QueryWorkspaceLabels",
|
|
11173
|
+
description: "문구 오버라이드"
|
|
11174
|
+
}
|
|
11175
|
+
] },
|
|
11176
|
+
dependencies: [{
|
|
11177
|
+
slug: "resizable",
|
|
11178
|
+
category: "core"
|
|
11179
|
+
}, {
|
|
11180
|
+
slug: "button",
|
|
11181
|
+
category: "core"
|
|
11182
|
+
}],
|
|
11183
|
+
testDescribe: "QueryWorkspace"
|
|
9884
11184
|
}
|
|
9885
11185
|
];
|
|
9886
11186
|
//#endregion
|