@reopt-ai/opt-ui 1.14.0 → 1.15.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 (38) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/COMPONENT_CATALOG.md +222 -69
  3. package/README.md +26 -0
  4. package/dist/core/index.cjs +4 -4
  5. package/dist/core/index.d.cts +2 -2
  6. package/dist/core/index.d.ts +2 -2
  7. package/dist/core/index.js +2 -2
  8. package/dist/docs/02-components/01-core.md +37 -33
  9. package/dist/docs/02-components/02-visuals.md +1 -1
  10. package/dist/docs/02-components/03-shells.md +191 -36
  11. package/dist/docs/02-components/04-surfaces.md +1 -1
  12. package/dist/docs/02-components/index.md +4 -4
  13. package/dist/id-registry.cjs +24 -0
  14. package/dist/id-registry.js +24 -0
  15. package/dist/id-registry.json +51 -0
  16. package/dist/index.cjs +445 -381
  17. package/dist/index.d.cts +16 -13
  18. package/dist/index.d.ts +16 -13
  19. package/dist/index.js +303 -245
  20. package/dist/{key-pad-menu-CqFI6la9.js → key-pad-menu-BCOeYvsH.js} +50 -61
  21. package/dist/{key-pad-menu-D6pYzaj-.d.cts → key-pad-menu-CaIsTHB2.d.cts} +12 -8
  22. package/dist/{key-pad-menu-BgtSL3xe.cjs → key-pad-menu-Jaqxhx9P.cjs} +48 -71
  23. package/dist/{key-pad-menu-Yh7Fpb8m.d.ts → key-pad-menu-odAEycIX.d.ts} +12 -8
  24. package/dist/meta.cjs +447 -7
  25. package/dist/meta.js +447 -7
  26. package/dist/{field-sidebar-mSVCMAZp.js → replay-player-layout-BVUNsUS1.js} +891 -191
  27. package/dist/{field-sidebar-ePqFX6MN.cjs → replay-player-layout-Cmzptq89.cjs} +931 -189
  28. package/dist/{field-sidebar-CJ4HxP8D.d.cts → replay-player-layout-DpqdfdQ6.d.ts} +246 -3
  29. package/dist/{field-sidebar-DnhpcT2A.d.ts → replay-player-layout-DuZW-gFF.d.cts} +246 -3
  30. package/dist/shells/index.cjs +58 -52
  31. package/dist/shells/index.d.cts +2 -2
  32. package/dist/shells/index.d.ts +2 -2
  33. package/dist/shells/index.js +2 -2
  34. package/dist/{text-truncate-Bd-0WkSP.js → text-truncate-B-8nJgnu.js} +200 -101
  35. package/dist/{text-truncate-Bbul-jMD.d.cts → text-truncate-DOxUijpB.d.cts} +2 -0
  36. package/dist/{text-truncate-Bbul-jMD.d.ts → text-truncate-DOxUijpB.d.ts} +2 -0
  37. package/dist/{text-truncate-BeYW6XZu.cjs → text-truncate-gQhpMy-Z.cjs} +214 -97
  38. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
1
  "use client";
2
- import { $ as useFormContext, $t as CompositeItem, A as FormGroup, An as SkeletonText, At as AlertDialogPanel, B as FormRemove, Bt as SelectItem, C as FormCheckbox, Ct as ComboboxEmpty, D as FormDescription, Dn as SkeletonAvatar, Dt as ComboboxItem, En as Skeleton, Et as ComboboxInput, Ft as DialogFooter, G as FormSelectPopover, Gt as Tab, H as FormRoot, Ht as SelectPopover, I as FormProvider, It as DialogHeader, J as FormSubmit, Jt as TabsRoot, Kt as TabList, L as FormPush, Lt as DialogHeading, Mt as DialogDescription, N as FormInput, Nt as DialogDisclosure, O as FormError, On as SkeletonCard, Ot as ComboboxPopover, P as FormLabel, Pt as DialogDismiss, Qt as Composite, R as FormRadio, Rt as DialogPanel, St as MenubarRoot, T as FormControl, Tn as StatCard, Tt as ComboboxGroupLabel, U as FormSelect, Ut as SelectRoot, V as FormReset, Vt as SelectLabel, W as FormSelectItem, Wt as SelectTrigger, Xt as DisclosureRoot, Y as FormSwitch, Yt as DisclosureContent, Z as FormTextarea, Zt as DisclosureTrigger, _ as DropdownTrigger, _n as Spinner, _t as MenuPopover, bn as EmptyState, bt as MenuTrigger, c as ResizableHandle, ct as PopoverContent, d as Checkbox, dn as ToolbarRoot, dt as Slider, en as CompositeProvider, et as useFormStore, f as CheckboxGroup, fn as ToolbarSeparator, ft as NumberInput, g as DropdownSeparator, gn as Alert, gr as Kbd, gt as MenuItemRadio, h as DropdownMenu, hn as TooltipProvider, ht as MenuItemCheckbox, i as FieldToken, in as Textarea, it as IconPicker, j as FormGroupLabel, jt as DialogBody, k as FormField, kn as SkeletonTable, kt as ComboboxRoot, l as ResizablePanel, ln as ToolbarButton, lt as PopoverRoot, m as DropdownItem, mn as TooltipAnchor, mt as MenuItem, n as Highlight, nn as CompositeZone, nt as DateRangePicker, o as resolveFieldType, on as Switch, ot as ColorPicker, p as DropdownContent, pn as Tooltip, pt as MenuButtonArrow, qt as TabPanel, r as FIELD_TYPE_TOKENS, rn as Meter, rt as TagInput, s as Pagination, sn as Input, st as PopoverClose, t as TextTruncate, tn as CompositeRow, tt as DEFAULT_PRESETS, u as ResizablePanelGroup, un as ToolbarContainer, ut as PopoverTrigger, vn as Badge, vt as MenuRoot, wt as ComboboxGroup, xn as Button, xt as MenubarContainer, yn as DescriptionList, yt as MenuSeparator, z as FormRadioGroup, zt as DialogRoot } from "../text-truncate-Bd-0WkSP.js";
3
- import { $ as OtpField, B as CardFooter, C as Logo, D as PageHeader, E as ScrollArea, F as CircularProgress, G as AvatarGroup, H as CardTitle, I as Progress, J as AccordionItem, K as Breadcrumb, L as Card, M as RadioGroup, N as ConditionBuilder, O as createBlock, P as StepBuilder, Q as ToggleGroup, R as CardContent, S as DrawerRoot, T as Container, U as Identity, V as CardHeader, W as Avatar, X as AccordionTrigger, Y as AccordionRoot, Z as Toggle, _ as getShaderFragment, a as THEME_PALETTES, b as DrawerClose, c as ExpressionGroup, d as ShaderSurface, et as Separator, f as SHADER_OVERLAY_PARAM_KEYS, g as SHADER_PRESET_IDS, h as SHADER_PRESETS, i as ColorPalettePicker, j as Radio, k as BlockLayout, l as Facet, m as SHADER_PARAM_KEYS, n as InlineEdit, nt as Text, o as LiveRegion, p as SHADER_PARAM_FALLBACK, q as AccordionContent, r as ColorPaletteDisplay, s as Expression, t as KeyPadMenu, tt as Heading, u as FacetGroup, v as getShaderPreset, w as Section, x as DrawerPanel, y as VirtualList, z as CardDescription } from "../key-pad-menu-CqFI6la9.js";
2
+ import { $ as useFormContext, $t as Composite, A as FormGroup, An as SkeletonTable, At as ComboboxRoot, B as FormRemove, Bt as DialogRoot, C as FormCheckbox, Ct as MenubarRoot, D as FormDescription, Dn as Skeleton, Dt as ComboboxInput, En as StatCard, Et as ComboboxGroupLabel, Ft as DialogDismiss, G as FormSelectPopover, Gt as SelectTrigger, H as FormRoot, Ht as SelectLabel, I as FormProvider, It as DialogFooter, J as FormSubmit, Jt as TabPanel, Kt as Tab, L as FormPush, Lt as DialogHeader, Mn as Toggle, Mt as DialogBody, N as FormInput, Nn as ToggleGroup, Nt as DialogDescription, O as FormError, On as SkeletonAvatar, Ot as ComboboxItem, P as FormLabel, Pt as DialogDisclosure, Qt as DisclosureTrigger, R as FormRadio, Rt as DialogHeading, Sn as Button, St as MenubarContainer, T as FormControl, Tt as ComboboxGroup, U as FormSelect, Ut as SelectPopover, V as FormReset, Vt as SelectItem, W as FormSelectItem, Wt as SelectRoot, Xt as DisclosureContent, Y as FormSwitch, Yt as TabsRoot, Z as FormTextarea, Zt as DisclosureRoot, _ as DropdownTrigger, _n as Alert, _t as MenuItemRadio, an as Textarea, at as IconPicker, bn as DescriptionList, bt as MenuSeparator, c as ResizableHandle, cn as Input, ct as PopoverClose, d as Checkbox, dn as ToolbarContainer, dt as PopoverTrigger, en as CompositeItem, et as useFormStore, f as CheckboxGroup, fn as ToolbarRoot, ft as Slider, g as DropdownSeparator, gn as TooltipProvider, gt as MenuItemCheckbox, h as DropdownMenu, hn as TooltipAnchor, ht as MenuItem, i as FieldToken, in as Meter, j as FormGroupLabel, jn as SkeletonText, jt as AlertDialogPanel, k as FormField, kn as SkeletonCard, kt as ComboboxPopover, l as ResizablePanel, lt as PopoverContent, m as DropdownItem, mn as Tooltip, mt as MenuButtonArrow, n as Highlight, nn as CompositeRow, nt as DateRangePicker, o as resolveFieldType, p as DropdownContent, pn as ToolbarSeparator, pt as NumberInput, qt as TabList, r as FIELD_TYPE_TOKENS, rn as CompositeZone, rt as TagInput, s as Pagination, sn as Switch, st as ColorPicker, t as TextTruncate, tn as CompositeProvider, tt as DEFAULT_PRESETS, u as ResizablePanelGroup, un as ToolbarButton, ut as PopoverRoot, vn as Spinner, vt as MenuPopover, wt as ComboboxEmpty, xn as EmptyState, xt as MenuTrigger, yn as Badge, yr as Kbd, yt as MenuRoot, z as FormRadioGroup, zt as DialogPanel } from "../text-truncate-B-8nJgnu.js";
3
+ import { $ as Heading, B as CardFooter, C as Logo, D as PageHeader, E as ScrollArea, F as CircularProgress, G as AvatarGroup, H as CardTitle, I as Progress, J as AccordionItem, K as Breadcrumb, L as Card, M as RadioGroup, N as ConditionBuilder, O as createBlock, P as StepBuilder, Q as Separator, R as CardContent, S as DrawerRoot, T as Container, U as Identity, V as CardHeader, W as Avatar, X as AccordionTrigger, Y as AccordionRoot, Z as OtpField, _ as getShaderFragment, a as THEME_PALETTES, b as DrawerClose, c as ExpressionGroup, d as ShaderSurface, et as Text, f as SHADER_OVERLAY_PARAM_KEYS, g as SHADER_PRESET_IDS, h as SHADER_PRESETS, i as ColorPalettePicker, j as Radio, k as BlockLayout, l as Facet, m as SHADER_PARAM_KEYS, n as InlineEdit, o as LiveRegion, p as SHADER_PARAM_FALLBACK, q as AccordionContent, r as ColorPaletteDisplay, s as Expression, t as KeyPadMenu, u as FacetGroup, v as getShaderPreset, w as Section, x as DrawerPanel, y as VirtualList, z as CardDescription } from "../key-pad-menu-BCOeYvsH.js";
4
4
  export { AccordionContent, AccordionItem, AccordionRoot, AccordionTrigger, Alert, AlertDialogPanel, Avatar, AvatarGroup, Badge, BlockLayout, BlockLayout as SurfaceLayout, Breadcrumb, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CheckboxGroup, CircularProgress, ColorPaletteDisplay, ColorPalettePicker, ColorPicker, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxPopover, ComboboxRoot, Composite, CompositeItem, CompositeProvider, CompositeRow, CompositeZone, ConditionBuilder, Container, DEFAULT_PRESETS, DateRangePicker, DescriptionList, DialogBody, DialogDescription, DialogDisclosure, DialogDismiss, DialogFooter, DialogHeader, DialogHeading, DialogPanel, DialogRoot, DisclosureContent, DisclosureRoot, DisclosureTrigger, DrawerClose, DrawerPanel, DrawerRoot, DropdownContent, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, Expression, ExpressionGroup, FIELD_TYPE_TOKENS, Facet, FacetGroup, FieldToken, FormCheckbox, FormControl, FormDescription, FormError, FormField, FormGroup, FormGroupLabel, FormInput, FormLabel, FormProvider, FormPush, FormRadio, FormRadioGroup, FormRemove, FormReset, FormRoot, FormSelect, FormSelectItem, FormSelectPopover, FormSubmit, FormSwitch, FormTextarea, Heading, Highlight, IconPicker, Identity, InlineEdit, Input, Kbd, KeyPadMenu, LiveRegion, Logo, MenuButtonArrow, MenuItem, MenuItemCheckbox, MenuItemRadio, MenuPopover, MenuRoot, MenuSeparator, MenuTrigger, MenubarContainer, MenubarRoot, Meter, NumberInput, OtpField, PageHeader, Pagination, PopoverClose, PopoverContent, PopoverRoot, PopoverTrigger, Progress, Radio, RadioGroup, ResizableHandle, ResizablePanel, ResizablePanelGroup, SHADER_OVERLAY_PARAM_KEYS, SHADER_PARAM_FALLBACK, SHADER_PARAM_KEYS, SHADER_PRESETS, SHADER_PRESET_IDS, ScrollArea, Section, SelectItem, SelectLabel, SelectPopover, SelectRoot, SelectTrigger, Separator, ShaderSurface, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTable, SkeletonText, Slider, Spinner, StatCard, StepBuilder, Switch, THEME_PALETTES, Tab, TabList, TabPanel, TabsRoot, TagInput, Text, TextTruncate, Textarea, Toggle, ToggleGroup, ToolbarButton, ToolbarContainer, ToolbarRoot, ToolbarSeparator, Tooltip, TooltipAnchor, TooltipProvider, VirtualList, createBlock, createBlock as createSurface, getShaderFragment, getShaderPreset, resolveFieldType, useFormContext, useFormStore };
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Core Components"
3
3
  description: "74 Core layer components — props, examples, keyboard shortcuts."
4
- version: "1.14.0"
4
+ version: "1.15.0"
5
5
  generated: true
6
6
  ---
7
7
 
@@ -492,19 +492,20 @@ import {
492
492
 
493
493
  **Import:** `import { Slider } from "@reopt-ai/opt-ui"`
494
494
 
495
- | Prop | Type | Required | Default | Description |
496
- | -------------- | --------------------------- | -------- | ------- | ------------------ |
497
- | `value` | `number` | | | 제어 모드 값 |
498
- | `defaultValue` | `number` | | 0 | 비제어 모드 초기값 |
499
- | `onChange` | `(value: number) => void` | | | 값 변경 핸들러 |
500
- | `min` | `number` | | 0 | 최솟값 |
501
- | `max` | `number` | | 100 | 최댓값 |
502
- | `step` | `number` | | 1 | 증감 단위 |
503
- | `label` | `string` | | | 레이블 텍스트 |
504
- | `showValue` | `boolean` | | false | 현재 값 표시 여부 |
505
- | `formatValue` | `(value: number) => string` | | | 값 포맷 함수 |
506
- | `disabled` | `boolean` | | | 비활성화 |
507
- | `className` | `string` | | | 최외곽 CSS 클래스 |
495
+ | Prop | Type | Required | Default | Description |
496
+ | --------------- | --------------------------- | -------- | ------- | ----------------------------------------------------------------- |
497
+ | `value` | `number` | | | 제어 모드 값 |
498
+ | `defaultValue` | `number` | | 0 | 비제어 모드 초기값 |
499
+ | `onChange` | `(value: number) => void` | | | 값 변경 핸들러 |
500
+ | `onValueCommit` | `(value: number) => void` | | | 포인터·키보드 편집 완료 시 한 번 호출. 취소와 외부 값 갱신은 제외 |
501
+ | `min` | `number` | | 0 | 최솟값 |
502
+ | `max` | `number` | | 100 | 최댓값 |
503
+ | `step` | `number` | | 1 | 증감 단위 |
504
+ | `label` | `string` | | | 레이블 텍스트 |
505
+ | `showValue` | `boolean` | | false | 현재 표시 여부 |
506
+ | `formatValue` | `(value: number) => string` | | | 값 포맷 함수 |
507
+ | `disabled` | `boolean` | | | 비활성화 |
508
+ | `className` | `string` | | | 최외곽 CSS 클래스 |
508
509
 
509
510
  ## Form Integration
510
511
 
@@ -547,12 +548,15 @@ import {
547
548
 
548
549
  **FormSelect:**
549
550
 
550
- | Prop | Type | Required | Default | Description |
551
- | ------------- | ----------- | -------- | ------- | ------------------------------ |
552
- | `name` | `string` | Yes | | 필드 이름 |
553
- | `children` | `ReactNode` | Yes | | FormSelectPopover 자식 요소 |
554
- | `placeholder` | `string` | | | 미선택 표시 텍스트 |
555
- | `className` | `string` | | | 추가 CSS 클래스 |
551
+ | Prop | Type | Required | Default | Description |
552
+ | ------------------ | ----------- | -------- | ------- | ------------------------------------------ |
553
+ | `id` | `string` | | | 트리거 ID. 외부 FormLabel의 htmlFor와 연결 |
554
+ | `aria-label` | `string` | | | 입력의 접근 가능한 이름 |
555
+ | `aria-describedby` | `string` | | | 설명·오류 요소의 ID 목록 |
556
+ | `name` | `string` | Yes | | 필드 이름 |
557
+ | `children` | `ReactNode` | Yes | | FormSelectPopover 등 자식 요소 |
558
+ | `placeholder` | `string` | | | 미선택 시 표시 텍스트 |
559
+ | `className` | `string` | | | 추가 CSS 클래스 |
556
560
 
557
561
  **FormSelectPopover:**
558
562
 
@@ -2078,19 +2082,19 @@ import {
2078
2082
 
2079
2083
  **Import:** `import { InlineEdit } from "@reopt-ai/opt-ui"`
2080
2084
 
2081
- | Prop | Type | Required | Default | Description |
2082
- | ------------- | --------------------------------------------------------------- | -------- | ---------- | ------------------------------------------- |
2083
- | `value` | `string` | Yes | | 현재 값 |
2084
- | `onSave` | `(next: string) => boolean \| void \| Promise<boolean \| void>` | Yes | | 저장. false 반환하면 거절하고 편집을 유지 |
2085
- | `as` | `"span" \| "h1" \| "h2" \| "h3" \| "h4"` | | "span" | 읽기 모드 요소 |
2086
- | `size` | `"sm" \| "md" \| "lg" \| "xl"` | | "md" | 타이포 크기 |
2087
- | `placeholder` | `string` | | | 입력 자리표시자 |
2088
- | `emptyText` | `string` | | "Untitled" | 빈 값 표시 |
2089
- | `disabled` | `boolean` | | false | 편집 불가 |
2090
- | `maxLength` | `number` | | | 최대 길이 |
2091
- | `suffix` | `ReactNode` | | | 읽기 모드 텍스트 뒤 요소 |
2092
- | `labels` | `InlineEditLabels` | | | 지역화 문자열 |
2093
- | `className` | `string` | | | 추가 CSS 클래스 |
2085
+ | Prop | Type | Required | Default | Description |
2086
+ | ------------- | --------------------------------------------------------------- | -------- | ---------- | ----------------------------------------------------------------- |
2087
+ | `value` | `string` | Yes | | 현재 값 |
2088
+ | `onSave` | `(next: string) => boolean \| void \| Promise<boolean \| void>` | Yes | | 저장. false 반환 또는 Promise 실패 시 입력을 유지하고 오류를 알림 |
2089
+ | `as` | `"span" \| "h1" \| "h2" \| "h3" \| "h4"` | | "span" | 읽기 모드 요소 |
2090
+ | `size` | `"sm" \| "md" \| "lg" \| "xl"` | | "md" | 타이포 크기 |
2091
+ | `placeholder` | `string` | | | 입력 자리표시자 |
2092
+ | `emptyText` | `string` | | "Untitled" | 빈 값 표시 |
2093
+ | `disabled` | `boolean` | | false | 편집 불가 |
2094
+ | `maxLength` | `number` | | | 최대 길이 |
2095
+ | `suffix` | `ReactNode` | | | 읽기 모드 텍스트 뒤 요소 |
2096
+ | `labels` | `InlineEditLabels` | | | 입력 이름(input), 편집·저장·취소·오류 안내 문자열 |
2097
+ | `className` | `string` | | | 추가 CSS 클래스 |
2094
2098
 
2095
2099
  ### KeyPadMenu
2096
2100
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Visual Components"
3
3
  description: "0 Visual layer components — props, examples, keyboard shortcuts."
4
- version: "1.14.0"
4
+ version: "1.15.0"
5
5
  generated: true
6
6
  ---
7
7
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: "Shell Components"
3
- description: "96 Shell layer components — props, examples, keyboard shortcuts."
4
- version: "1.14.0"
3
+ description: "99 Shell layer components — props, examples, keyboard shortcuts."
4
+ version: "1.15.0"
5
5
  generated: true
6
6
  ---
7
7
 
8
- # Shell Components (96)
8
+ # Shell Components (99)
9
9
 
10
10
  ## Navigation & Layout
11
11
 
@@ -998,10 +998,10 @@ export function Example() {
998
998
  **Import:** `import { SettingsForm } from "@reopt-ai/opt-ui"`
999
999
  **Dependencies:** form (core), checkbox (core), radio-group (core), switch (core)
1000
1000
 
1001
- | Prop | Type | Required | Default | Description |
1002
- | ---------- | ------------------------------------------- | -------- | ------- | ----------------- |
1003
- | `fields` | `FormFieldDef[]` | Yes | | 폼 필드 정의 배열 |
1004
- | `onSubmit` | `(values: Record<string, unknown>) => void` | | | 제출 핸들러 |
1001
+ | Prop | Type | Required | Default | Description |
1002
+ | ---------- | ------------------------------------------------------------ | -------- | ------- | ----------------- |
1003
+ | `fields` | `FormFieldDef[]` | Yes | | 폼 필드 정의 배열 |
1004
+ | `onSubmit` | `(values: Record<string, unknown>) => void \| Promise<void>` | | | 제출 핸들러 |
1005
1005
 
1006
1006
  **Examples:**
1007
1007
 
@@ -1026,15 +1026,15 @@ const fields = [
1026
1026
  **Import:** `import { AuthForm } from "@reopt-ai/opt-ui"`
1027
1027
  **Dependencies:** form (core)
1028
1028
 
1029
- | Prop | Type | Required | Default | Description |
1030
- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------- |
1031
- | `defaultMode` | `"login" \| "signup"` | | "login" | 초기 모드 (비제어) |
1032
- | `mode` | `"login" \| "signup"` | | | 제어 모드: 현재 모드 |
1033
- | `onModeChange` | `(mode: "login" \| "signup") => void` | | | 모드 변경 핸들러 |
1034
- | `showRememberMe` | `boolean` | | true | 로그인 모드에서 '로그인 상태 유지' 표시 여부 |
1035
- | `minPasswordLength` | `number` | | 8 | 비밀번호 최소 길이 |
1036
- | `onSubmit` | `(values: { email: string; password: string; confirmPassword?: string; rememberMe?: boolean; mode: "login" \| "signup" }) => void` | | | 제출 핸들러 |
1037
- | `labels` | `AuthFormLabels` | | | i18n용 라벨 오버라이드 |
1029
+ | Prop | Type | Required | Default | Description |
1030
+ | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------------------------------------------- |
1031
+ | `defaultMode` | `"login" \| "signup"` | | "login" | 초기 모드 (비제어) |
1032
+ | `mode` | `"login" \| "signup"` | | | 제어 모드: 현재 모드 |
1033
+ | `onModeChange` | `(mode: "login" \| "signup") => void` | | | 모드 변경 핸들러 |
1034
+ | `showRememberMe` | `boolean` | | true | 로그인 모드에서 '로그인 상태 유지' 표시 여부 |
1035
+ | `minPasswordLength` | `number` | | 8 | 비밀번호 최소 길이 |
1036
+ | `onSubmit` | `(values: { email: string; password: string; confirmPassword?: string; rememberMe?: boolean; mode: "login" \| "signup" }) => void \| Promise<void>` | | | 제출 핸들러 |
1037
+ | `labels` | `AuthFormLabels` | | | i18n용 라벨 오버라이드 |
1038
1038
 
1039
1039
  ### DynamicFieldForm
1040
1040
 
@@ -1050,7 +1050,7 @@ const fields = [
1050
1050
  | `maxFields` | `number` | | | 최대 필드 수 |
1051
1051
  | `fieldType` | `"text" \| "email" \| "url" \| "number"` | | "text" | 필드 입력 타입 |
1052
1052
  | `validateField` | `(value: string, index: number) => string \| undefined` | | | 커스텀 필드 검증 함수 |
1053
- | `onSubmit` | `(values: string[]) => void` | | | 제출 핸들러 |
1053
+ | `onSubmit` | `(values: string[]) => void \| Promise<void>` | | | 제출 핸들러 |
1054
1054
  | `labels` | `DynamicFieldFormLabels` | | | i18n용 라벨 오버라이드 |
1055
1055
 
1056
1056
  ### FileUploadForm
@@ -1060,17 +1060,17 @@ const fields = [
1060
1060
  **Import:** `import { FileUploadForm } from "@reopt-ai/opt-ui"`
1061
1061
  **Dependencies:** form (core)
1062
1062
 
1063
- | Prop | Type | Required | Default | Description |
1064
- | ----------------- | ------------------------------------------------------------------------------ | -------- | ------------------------- | ----------------------------------------- |
1065
- | `accept` | `string` | | "image/*,.pdf,.doc,.docx" | 허용 파일 타입 |
1066
- | `showPreview` | `boolean` | | true | 이미지 미리보기 표시 |
1067
- | `showFileInfo` | `boolean` | | true | 파일 정보 표시 |
1068
- | `showDescription` | `boolean` | | true | 설명 텍스트영역 표시 |
1069
- | `maxFileSize` | `number` | | | 최대 파일 크기 (bytes) |
1070
- | `onSubmit` | `(values: { title: string; description: string; file: File \| null }) => void` | | | 제출 핸들러 |
1071
- | `labels` | `FileUploadFormLabels` | | | i18n용 라벨 오버라이드 |
1072
- | `onPreview` | `(file: File) => void` | | | 파일 선택 후 프리뷰 콜백 |
1073
- | `columnMapping` | `ReactNode` | | | CSV 컬럼 매핑 UI 슬롯 (파일 선택 후 표시) |
1063
+ | Prop | Type | Required | Default | Description |
1064
+ | ----------------- | ----------------------------------------------------------------------------------------------- | -------- | ------------------------- | ----------------------------------------- |
1065
+ | `accept` | `string` | | "image/*,.pdf,.doc,.docx" | 허용 파일 타입 |
1066
+ | `showPreview` | `boolean` | | true | 이미지 미리보기 표시 |
1067
+ | `showFileInfo` | `boolean` | | true | 파일 정보 표시 |
1068
+ | `showDescription` | `boolean` | | true | 설명 텍스트영역 표시 |
1069
+ | `maxFileSize` | `number` | | | 최대 파일 크기 (bytes) |
1070
+ | `onSubmit` | `(values: { title: string; description: string; file: File \| null }) => void \| Promise<void>` | | | 제출 핸들러 |
1071
+ | `labels` | `FileUploadFormLabels` | | | i18n용 라벨 오버라이드 |
1072
+ | `onPreview` | `(file: File) => void` | | | 파일 선택 후 프리뷰 콜백 |
1073
+ | `columnMapping` | `ReactNode` | | | CSV 컬럼 매핑 UI 슬롯 (파일 선택 후 표시) |
1074
1074
 
1075
1075
  ### WizardForm
1076
1076
 
@@ -1079,14 +1079,14 @@ const fields = [
1079
1079
  **Import:** `import { WizardForm } from "@reopt-ai/opt-ui"`
1080
1080
  **Dependencies:** form (core), checkbox (core), radio-group (core)
1081
1081
 
1082
- | Prop | Type | Required | Default | Description |
1083
- | -------------- | ------------------------------------------- | -------- | ------- | ------------------------------------------ |
1084
- | `fields` | `FormFieldDef[]` | Yes | | 폼 필드 정의 배열 |
1085
- | `steps` | `WizardStepDef[]` | Yes | | 단계 정의. { id, label, fields: string[] } |
1086
- | `showReview` | `boolean` | | true | 마지막 리뷰 단계 표시 여부 |
1087
- | `onSubmit` | `(values: Record<string, unknown>) => void` | | | 제출 핸들러 |
1088
- | `onStepChange` | `(stepIndex: number) => void` | | | 단계 변경 핸들러 |
1089
- | `labels` | `WizardFormLabels` | | | i18n용 라벨 오버라이드 |
1082
+ | Prop | Type | Required | Default | Description |
1083
+ | -------------- | ------------------------------------------------------------ | -------- | ------- | ------------------------------------------ |
1084
+ | `fields` | `FormFieldDef[]` | Yes | | 폼 필드 정의 배열 |
1085
+ | `steps` | `WizardStepDef[]` | Yes | | 단계 정의. { id, label, fields: string[] } |
1086
+ | `showReview` | `boolean` | | true | 마지막 리뷰 단계 표시 여부 |
1087
+ | `onSubmit` | `(values: Record<string, unknown>) => void \| Promise<void>` | | | 제출 핸들러 |
1088
+ | `onStepChange` | `(stepIndex: number) => void` | | | 단계 변경 핸들러 |
1089
+ | `labels` | `WizardFormLabels` | | | i18n용 라벨 오버라이드 |
1090
1090
 
1091
1091
  ### ConfirmDialog
1092
1092
 
@@ -1524,6 +1524,9 @@ export function Example() {
1524
1524
  | QueryHistoryList | 실행 이력 목록. 각 실행의 성공/실패, 시각, 행 수, 경과를 보여주고 편집기로 되돌리거나 다시 실행합니다. | `QueryHistoryList` |
1525
1525
  | SaveQueryDialog | 쿼리에 이름·설명·공개 여부를 붙여 저장하는 다이얼로그. 편집기에 문장이 여럿이면 어느 문장을 저장할지 넘겨 보며 고릅니다. | `SaveQueryDialog` |
1526
1526
  | QueryWorkspace | 스키마·편집기·출력의 3-pane 쿼리 워크스페이스. 패널은 리사이즈되고 사이드바는 접히며, storageKey로 레이아웃을 기억합니다. 툴바·편집기·출력은 슬롯입니다. | `QueryWorkspace` |
1527
+ | ReplayScrubber | 세션 리플레이의 탐색 트랙. 활동/비활성/미로딩 구간, 활동 밀도, 이벤트 마커를 한 플레이헤드 아래에 겹쳐 그리고, 드래그·키보드 탐색이 끝났을 때만 seek을 커밋한다. | `ReplayScrubber`, `groupReplayMarkers` |
1528
+ | ReplayTransport | 세션 리플레이 재생 컨트롤. 재생/일시정지, 앞뒤 점프, 배속 메뉴, 비활성 건너뛰기 토글, 전체화면, 경과/시계 타임코드 전환을 제공하며 재생 상태는 호스트가 소유한다. | `ReplayTransport`, `formatReplayElapsed` |
1529
+ | ReplayPlayerLayout | 세션 리플레이 플레이어의 프레임. 스테이지·메타 바·컨트롤·리사이즈 가능한 인스펙터를 배치하고, 플레이어 전체의 전체화면과 입력 필드를 피하는 키보드 단축키 범위를 소유한다. | `ReplayPlayerLayout`, `replayShortcutKey` |
1527
1530
 
1528
1531
  ### PageAside
1529
1532
 
@@ -2229,3 +2232,155 @@ const messages = [
2229
2232
  | `defaultSidebarSize` | `number` | | 22 | 사이드바 폭(%) |
2230
2233
  | `defaultEditorSize` | `number` | | 40 | 편집기 높이(%) |
2231
2234
  | `labels` | `QueryWorkspaceLabels` | | | 문구 오버라이드 |
2235
+
2236
+ ### ReplayScrubber
2237
+
2238
+ > 세션 리플레이의 탐색 트랙. 활동/비활성/미로딩 구간, 활동 밀도, 이벤트 마커를 한 플레이헤드 아래에 겹쳐 그리고, 드래그·키보드 탐색이 끝났을 때만 seek을 커밋한다.
2239
+
2240
+ **Import:** `import { ReplayScrubber } from "@reopt-ai/opt-ui"`
2241
+
2242
+ | Prop | Type | Required | Default | Description |
2243
+ | ---------------- | ---------------------------------------- | -------- | ------- | ----------------------------------------------------------- |
2244
+ | `start` | `number` | Yes | | 재생 가능한 첫 시각(절대값, 보통 epoch ms) |
2245
+ | `end` | `number` | Yes | | 재생 가능한 마지막 시각 |
2246
+ | `position` | `number` | Yes | | 현재 플레이헤드. [start, end]로 클램프 |
2247
+ | `segments` | `ReplayScrubberSegment[]` | | | 활동 분류 구간. active/inactive/gap/buffer |
2248
+ | `buffered` | `Array<{ start: number; end: number }>` | | | 이미 로드된 범위 |
2249
+ | `activity` | `number[]` | | | 0..1로 정규화한 활동 밀도 버킷. 로그 스케일 영역으로 그린다 |
2250
+ | `markers` | `ReplayScrubberMarker[]` | | | 트랙 위 관심 지점. 가까운 마커는 하나로 합쳐진다 |
2251
+ | `onSeek` | `(time: number) => void` | Yes | | 포인터·키보드 조작이 끝났을 때 한 번 호출 |
2252
+ | `onPreview` | `(time: number \| null) => void` | | | 드래그·호버 중 미리보기 시각. 비싼 seek에 쓰지 않는다 |
2253
+ | `onMarkerSelect` | `(marker: ReplayScrubberMarker) => void` | | | 마커 선택. 생략하면 해당 시각으로 seek |
2254
+ | `formatTime` | `(time: number) => string` | | | 배지와 aria-valuetext 포맷. 기본 start 기준 m:ss |
2255
+ | `stepMs` | `number` | | 5000 | 화살표 키 이동량 |
2256
+ | `largeStepMs` | `number` | | 30000 | PageUp/PageDown·Shift+화살표 이동량 |
2257
+ | `disabled` | `boolean` | | false | 모든 조작을 비활성화 |
2258
+ | `labels` | `ReplayScrubberLabels` | | | 접근성 문구 오버라이드 |
2259
+ | `className` | `string` | | | 추가 클래스 |
2260
+
2261
+ **Examples:**
2262
+
2263
+ _구간·마커가 있는 탐색 트랙:_
2264
+
2265
+ ```tsx
2266
+ import { ReplayScrubber } from "@reopt-ai/opt-ui";
2267
+
2268
+ <ReplayScrubber
2269
+ start={recording.start}
2270
+ end={recording.end}
2271
+ position={playhead}
2272
+ segments={[
2273
+ { start: recording.start, end: recording.start + 60_000, kind: "active" },
2274
+ { start: recording.start + 60_000, end: recording.end, kind: "inactive" },
2275
+ ]}
2276
+ markers={[{ id: "err", time: errorAt, label: "TypeError", tone: "danger" }]}
2277
+ onSeek={(time) => player.seek(time)}
2278
+ labels={{ track: "녹화 탐색" }}
2279
+ />;
2280
+ ```
2281
+
2282
+ ### ReplayTransport
2283
+
2284
+ > 세션 리플레이 재생 컨트롤. 재생/일시정지, 앞뒤 점프, 배속 메뉴, 비활성 건너뛰기 토글, 전체화면, 경과/시계 타임코드 전환을 제공하며 재생 상태는 호스트가 소유한다.
2285
+
2286
+ **Import:** `import { ReplayTransport } from "@reopt-ai/opt-ui"`
2287
+
2288
+ | Prop | Type | Required | Default | Description |
2289
+ | ---------------------- | -------------------------------------- | -------- | ----------------------------- | ---------------------------------------------- |
2290
+ | `playing` | `boolean` | Yes | | 재생 중 여부 |
2291
+ | `ended` | `boolean` | | false | 끝에 도달. 재생 버튼이 다시 시작을 제안 |
2292
+ | `position` | `number` | Yes | | 절대 플레이헤드 시각 |
2293
+ | `start` | `number` | Yes | | 녹화 시작 시각(절대값) |
2294
+ | `end` | `number` | Yes | | 녹화 종료 시각(절대값) |
2295
+ | `onTogglePlay` | `() => void` | Yes | | 재생/일시정지 토글. ended면 처음부터 다시 시작 |
2296
+ | `onSkip` | `(deltaMs: number) => void` | Yes | | 부호 있는 시간만큼 이동 |
2297
+ | `onSkipToStart` | `() => void` | | | 처음으로. 생략하면 버튼 숨김 |
2298
+ | `jumpMs` | `number` | | 10000 | 앞뒤 점프 버튼 이동량(ms) |
2299
+ | `speed` | `number` | Yes | | 현재 배속 |
2300
+ | `speeds` | `readonly number[]` | | [0.5, 1, 1.5, 2, 3, 4, 8, 16] | 선택 가능한 배속 목록 |
2301
+ | `onSpeedChange` | `(speed: number) => void` | Yes | | 배속 변경 콜백 |
2302
+ | `skipInactive` | `boolean` | Yes | | 비활성 구간 건너뛰기 여부 |
2303
+ | `onSkipInactiveChange` | `(skip: boolean) => void` | Yes | | 건너뛰기 토글 콜백 |
2304
+ | `fullscreen` | `boolean` | | | 전체화면 상태(호스트 소유) |
2305
+ | `onFullscreenChange` | `(fullscreen: boolean) => void` | | | 있으면 전체화면 버튼 표시 |
2306
+ | `timecode` | `"elapsed" \| "clock"` | | "elapsed" | 경과 시간 또는 실제 시각 표시 모드 |
2307
+ | `onTimecodeChange` | `(mode: "elapsed" \| "clock") => void` | | | 있으면 타임코드를 클릭해 전환 |
2308
+ | `formatClock` | `(time: number) => string` | | | clock 모드 포맷 |
2309
+ | `disabled` | `boolean` | | false | 모든 조작을 비활성화 |
2310
+ | `children` | `ReactNode` | | | 오른쪽에 추가 컨트롤 |
2311
+ | `labels` | `ReplayTransportLabels` | | | 문구 오버라이드 |
2312
+ | `shortcuts` | `ReplayTransportShortcuts` | | | 툴팁에 표시할 단축키 |
2313
+ | `className` | `string` | | | 추가 클래스 |
2314
+
2315
+ **Examples:**
2316
+
2317
+ _호스트가 재생 상태를 소유하는 트랜스포트:_
2318
+
2319
+ ```tsx
2320
+ import { ReplayTransport } from "@reopt-ai/opt-ui";
2321
+
2322
+ <ReplayTransport
2323
+ playing={playing}
2324
+ position={playhead}
2325
+ start={recording.start}
2326
+ end={recording.end}
2327
+ onTogglePlay={() => (playing ? player.pause() : player.play())}
2328
+ onSkip={(delta) => player.seek(playhead + delta)}
2329
+ speed={speed}
2330
+ onSpeedChange={setSpeed}
2331
+ skipInactive={skipInactive}
2332
+ onSkipInactiveChange={setSkipInactive}
2333
+ labels={{ play: "재생", pause: "일시정지" }}
2334
+ />;
2335
+ ```
2336
+
2337
+ ### ReplayPlayerLayout
2338
+
2339
+ > 세션 리플레이 플레이어의 프레임. 스테이지·메타 바·컨트롤·리사이즈 가능한 인스펙터를 배치하고, 플레이어 전체의 전체화면과 입력 필드를 피하는 키보드 단축키 범위를 소유한다.
2340
+
2341
+ **Import:** `import { ReplayPlayerLayout } from "@reopt-ai/opt-ui"`
2342
+
2343
+ | Prop | Type | Required | Default | Description |
2344
+ | ----------------------- | ------------------------------- | -------- | ------- | -------------------------------------------------------------------- |
2345
+ | `stage` | `ReactNode` | Yes | | 녹화가 렌더되는 영역(iframe 호스트) |
2346
+ | `meta` | `ReactNode` | | | 스테이지 위 얇은 바: URL, 창, 기기 |
2347
+ | `controls` | `ReactNode` | | | 스테이지 아래 트랜스포트와 스크러버 |
2348
+ | `inspector` | `ReactNode` | | | 측면 패널. 생략하면 패널 없음 |
2349
+ | `inspectorOpen` | `boolean` | | true | 인스펙터 표시 여부(제어됨) |
2350
+ | `onInspectorOpenChange` | `(open: boolean) => void` | | | 있으면 토글 버튼 표시 |
2351
+ | `inspectorSize` | `number` | | 34 | 인스펙터 초기 폭(%) |
2352
+ | `layoutId` | `string` | | | 리사이즈 레이아웃 영속 id |
2353
+ | `fullscreen` | `boolean` | | false | 전체화면 상태(호스트 소유) |
2354
+ | `onFullscreenChange` | `(fullscreen: boolean) => void` | | | 전체화면 변경 콜백. 브라우저가 스스로 나가도 호출된다 |
2355
+ | `shortcuts` | `ReplayShortcutMap` | | | 포커스가 안에 있고 입력 필드가 아닐 때만 동작. false를 반환하면 전파 |
2356
+ | `overlay` | `ReactNode` | | | 스테이지 위 오버레이: 로딩, 오류, 건너뛰는 중 |
2357
+ | `labels` | `ReplayPlayerLayoutLabels` | | | 문구 오버라이드 |
2358
+ | `className` | `string` | | | 추가 클래스 |
2359
+
2360
+ **Examples:**
2361
+
2362
+ _스테이지·컨트롤·인스펙터 배치와 단축키:_
2363
+
2364
+ ```tsx
2365
+ import { ReplayPlayerLayout } from "@reopt-ai/opt-ui";
2366
+
2367
+ <ReplayPlayerLayout
2368
+ layoutId="replay-player"
2369
+ meta={<span>{currentPath}</span>}
2370
+ stage={<div ref={stageRef} />}
2371
+ controls={
2372
+ <>
2373
+ {scrubber}
2374
+ {transport}
2375
+ </>
2376
+ }
2377
+ inspector={<EventList onSelect={(e) => player.seek(e.time)} />}
2378
+ inspectorOpen={inspectorOpen}
2379
+ onInspectorOpenChange={setInspectorOpen}
2380
+ shortcuts={{
2381
+ space: togglePlay,
2382
+ arrowleft: () => skip(-10_000),
2383
+ arrowright: () => skip(10_000),
2384
+ }}
2385
+ />;
2386
+ ```
@@ -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.14.0"
4
+ version: "1.15.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 170 @reopt-ai/opt-ui components across 4 layers."
4
- version: "1.14.0"
3
+ description: "Complete reference for 173 @reopt-ai/opt-ui components across 4 layers."
4
+ version: "1.15.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 | 96 |
16
+ | Shells | 99 |
17
17
  | Surfaces | 0 |
18
- | **Total** | **170** |
18
+ | **Total** | **173** |
19
19
 
20
20
  ## Component Selection Guide
21
21
 
@@ -1248,6 +1248,24 @@ const ID_REGISTRY = Object.freeze({
1248
1248
  layer: "core",
1249
1249
  metaName: "RadioGroup"
1250
1250
  },
1251
+ A3VYS: {
1252
+ slug: "replay-player-layout",
1253
+ exportName: "ReplayPlayerLayout",
1254
+ layer: "shells",
1255
+ metaName: "ReplayPlayerLayout"
1256
+ },
1257
+ B98JP: {
1258
+ slug: "replay-scrubber",
1259
+ exportName: "ReplayScrubber",
1260
+ layer: "shells",
1261
+ metaName: "ReplayScrubber"
1262
+ },
1263
+ RW9FW: {
1264
+ slug: "replay-transport",
1265
+ exportName: "ReplayTransport",
1266
+ layer: "shells",
1267
+ metaName: "ReplayTransport"
1268
+ },
1251
1269
  K9STD: {
1252
1270
  slug: "report-builder",
1253
1271
  exportName: "ReportBuilder",
@@ -1875,6 +1893,9 @@ const SLUG_TO_ID = Object.freeze({
1875
1893
  "quick-actions.QuickActions": "CEM9F",
1876
1894
  "radio-group.Radio": "HY7YG",
1877
1895
  "radio-group.RadioGroup": "2F20H",
1896
+ "replay-player-layout.ReplayPlayerLayout": "A3VYS",
1897
+ "replay-scrubber.ReplayScrubber": "B98JP",
1898
+ "replay-transport.ReplayTransport": "RW9FW",
1878
1899
  "report-builder.ReportBuilder": "K9STD",
1879
1900
  "resizable.ResizableHandle": "6Z22W",
1880
1901
  "resizable.ResizablePanel": "88X4V",
@@ -2154,6 +2175,9 @@ const ALL_SLUGS = Object.freeze([
2154
2175
  "quick-actions.QuickActions",
2155
2176
  "radio-group.Radio",
2156
2177
  "radio-group.RadioGroup",
2178
+ "replay-player-layout.ReplayPlayerLayout",
2179
+ "replay-scrubber.ReplayScrubber",
2180
+ "replay-transport.ReplayTransport",
2157
2181
  "report-builder.ReportBuilder",
2158
2182
  "resizable.ResizableHandle",
2159
2183
  "resizable.ResizablePanel",
@@ -1247,6 +1247,24 @@ const ID_REGISTRY = Object.freeze({
1247
1247
  layer: "core",
1248
1248
  metaName: "RadioGroup"
1249
1249
  },
1250
+ A3VYS: {
1251
+ slug: "replay-player-layout",
1252
+ exportName: "ReplayPlayerLayout",
1253
+ layer: "shells",
1254
+ metaName: "ReplayPlayerLayout"
1255
+ },
1256
+ B98JP: {
1257
+ slug: "replay-scrubber",
1258
+ exportName: "ReplayScrubber",
1259
+ layer: "shells",
1260
+ metaName: "ReplayScrubber"
1261
+ },
1262
+ RW9FW: {
1263
+ slug: "replay-transport",
1264
+ exportName: "ReplayTransport",
1265
+ layer: "shells",
1266
+ metaName: "ReplayTransport"
1267
+ },
1250
1268
  K9STD: {
1251
1269
  slug: "report-builder",
1252
1270
  exportName: "ReportBuilder",
@@ -1874,6 +1892,9 @@ const SLUG_TO_ID = Object.freeze({
1874
1892
  "quick-actions.QuickActions": "CEM9F",
1875
1893
  "radio-group.Radio": "HY7YG",
1876
1894
  "radio-group.RadioGroup": "2F20H",
1895
+ "replay-player-layout.ReplayPlayerLayout": "A3VYS",
1896
+ "replay-scrubber.ReplayScrubber": "B98JP",
1897
+ "replay-transport.ReplayTransport": "RW9FW",
1877
1898
  "report-builder.ReportBuilder": "K9STD",
1878
1899
  "resizable.ResizableHandle": "6Z22W",
1879
1900
  "resizable.ResizablePanel": "88X4V",
@@ -2153,6 +2174,9 @@ const ALL_SLUGS = Object.freeze([
2153
2174
  "quick-actions.QuickActions",
2154
2175
  "radio-group.Radio",
2155
2176
  "radio-group.RadioGroup",
2177
+ "replay-player-layout.ReplayPlayerLayout",
2178
+ "replay-scrubber.ReplayScrubber",
2179
+ "replay-transport.ReplayTransport",
2156
2180
  "report-builder.ReportBuilder",
2157
2181
  "resizable.ResizableHandle",
2158
2182
  "resizable.ResizablePanel",