sh-ui-cli 0.48.0 → 0.50.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/data/changelog/versions.json +27 -0
- package/data/registry/react/components/accordion/index.vanilla-extract.tsx +97 -0
- package/data/registry/react/components/accordion/styles.css.ts +131 -0
- package/data/registry/react/components/avatar/index.vanilla-extract.tsx +73 -0
- package/data/registry/react/components/avatar/styles.css.ts +68 -0
- package/data/registry/react/components/badge/index.vanilla-extract.tsx +40 -0
- package/data/registry/react/components/badge/styles.css.ts +71 -0
- package/data/registry/react/components/breadcrumb/index.vanilla-extract.tsx +152 -0
- package/data/registry/react/components/breadcrumb/styles.css.ts +95 -0
- package/data/registry/react/components/button/index.vanilla-extract.tsx +45 -0
- package/data/registry/react/components/button/styles.css.ts +120 -0
- package/data/registry/react/components/calendar/index.vanilla-extract.tsx +806 -0
- package/data/registry/react/components/calendar/styles.css.ts +250 -0
- package/data/registry/react/components/card/index.vanilla-extract.tsx +63 -0
- package/data/registry/react/components/card/styles.css.ts +88 -0
- package/data/registry/react/components/carousel/index.vanilla-extract.tsx +430 -0
- package/data/registry/react/components/carousel/styles.css.ts +169 -0
- package/data/registry/react/components/checkbox/index.vanilla-extract.tsx +96 -0
- package/data/registry/react/components/checkbox/styles.css.ts +74 -0
- package/data/registry/react/components/code-editor/index.vanilla-extract.tsx +230 -0
- package/data/registry/react/components/code-editor/styles.css.ts +97 -0
- package/data/registry/react/components/code-panel/index.vanilla-extract.tsx +191 -0
- package/data/registry/react/components/code-panel/styles.css.ts +151 -0
- package/data/registry/react/components/color-picker/index.vanilla-extract.tsx +467 -0
- package/data/registry/react/components/color-picker/styles.css.ts +169 -0
- package/data/registry/react/components/combobox/index.vanilla-extract.tsx +165 -0
- package/data/registry/react/components/combobox/styles.css.ts +174 -0
- package/data/registry/react/components/context-menu/index.vanilla-extract.tsx +251 -0
- package/data/registry/react/components/context-menu/styles.css.ts +167 -0
- package/data/registry/react/components/date-picker/index.vanilla-extract.tsx +520 -0
- package/data/registry/react/components/date-picker/styles.css.ts +111 -0
- package/data/registry/react/components/dialog/index.vanilla-extract.tsx +95 -0
- package/data/registry/react/components/dialog/styles.css.ts +140 -0
- package/data/registry/react/components/dropdown-menu/index.vanilla-extract.tsx +255 -0
- package/data/registry/react/components/dropdown-menu/styles.css.ts +175 -0
- package/data/registry/react/components/file-upload/index.vanilla-extract.tsx +487 -0
- package/data/registry/react/components/file-upload/styles.css.ts +193 -0
- package/data/registry/react/components/form/index.vanilla-extract.tsx +61 -0
- package/data/registry/react/components/form/styles.css.ts +56 -0
- package/data/registry/react/components/header/index.vanilla-extract.tsx +805 -0
- package/data/registry/react/components/header/styles.css.ts +413 -0
- package/data/registry/react/components/input/index.vanilla-extract.tsx +425 -0
- package/data/registry/react/components/input/styles.css.ts +202 -0
- package/data/registry/react/components/label/index.vanilla-extract.tsx +52 -0
- package/data/registry/react/components/label/styles.css.ts +141 -0
- package/data/registry/react/components/markdown-editor/index.vanilla-extract.tsx +119 -0
- package/data/registry/react/components/markdown-editor/styles.css.ts +231 -0
- package/data/registry/react/components/menubar/index.vanilla-extract.tsx +32 -0
- package/data/registry/react/components/menubar/styles.css.ts +53 -0
- package/data/registry/react/components/numeric-input/index.vanilla-extract.tsx +148 -0
- package/data/registry/react/components/numeric-input/styles.css.ts +65 -0
- package/data/registry/react/components/page-toc/index.vanilla-extract.tsx +174 -0
- package/data/registry/react/components/page-toc/styles.css.ts +97 -0
- package/data/registry/react/components/pagination/index.vanilla-extract.tsx +269 -0
- package/data/registry/react/components/pagination/styles.css.ts +113 -0
- package/data/registry/react/components/popover/index.vanilla-extract.tsx +113 -0
- package/data/registry/react/components/popover/styles.css.ts +78 -0
- package/data/registry/react/components/progress/index.vanilla-extract.tsx +54 -0
- package/data/registry/react/components/progress/styles.css.ts +53 -0
- package/data/registry/react/components/radio/index.vanilla-extract.tsx +65 -0
- package/data/registry/react/components/radio/styles.css.ts +79 -0
- package/data/registry/react/components/rich-text-editor/index.vanilla-extract.tsx +348 -0
- package/data/registry/react/components/rich-text-editor/styles.css.ts +243 -0
- package/data/registry/react/components/select/index.vanilla-extract.tsx +234 -0
- package/data/registry/react/components/select/styles.css.ts +225 -0
- package/data/registry/react/components/separator/index.vanilla-extract.tsx +46 -0
- package/data/registry/react/components/separator/styles.css.ts +24 -0
- package/data/registry/react/components/sidebar/index.vanilla-extract.tsx +1067 -0
- package/data/registry/react/components/sidebar/styles.css.ts +578 -0
- package/data/registry/react/components/skeleton/index.vanilla-extract.tsx +22 -0
- package/data/registry/react/components/skeleton/styles.css.ts +30 -0
- package/data/registry/react/components/slider/index.vanilla-extract.tsx +298 -0
- package/data/registry/react/components/slider/styles.css.ts +75 -0
- package/data/registry/react/components/spinner/index.vanilla-extract.tsx +38 -0
- package/data/registry/react/components/spinner/styles.css.ts +60 -0
- package/data/registry/react/components/switch/index.vanilla-extract.tsx +39 -0
- package/data/registry/react/components/switch/styles.css.ts +87 -0
- package/data/registry/react/components/tabs/index.vanilla-extract.tsx +91 -0
- package/data/registry/react/components/tabs/styles.css.ts +145 -0
- package/data/registry/react/components/textarea/index.vanilla-extract.tsx +23 -0
- package/data/registry/react/components/textarea/styles.css.ts +55 -0
- package/data/registry/react/components/toast/index.vanilla-extract.tsx +258 -0
- package/data/registry/react/components/toast/styles.css.ts +307 -0
- package/data/registry/react/components/toggle/index.vanilla-extract.tsx +131 -0
- package/data/registry/react/components/toggle/styles.css.ts +109 -0
- package/data/registry/react/components/tooltip/index.vanilla-extract.tsx +83 -0
- package/data/registry/react/components/tooltip/styles.css.ts +59 -0
- package/data/registry/react/peer-versions.json +1 -0
- package/data/registry/react/registry.json +922 -42
- package/data/tokens/build.mjs +3 -0
- package/package.json +1 -1
- package/src/api.d.ts +4 -3
- package/src/constants.js +4 -3
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu";
|
|
3
|
+
import { byKey, cm__trigger, cm__positioner, cm__content, cm__item, cmItemText, cmItemCheck, cmItemIndicator, cm__group, cm__label, cm__separator, cmSubArrow, cmSubTrigger } from "./styles.css";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
6
|
+
type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/* ───────── Root ───────── */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 우클릭(또는 long-press)으로 열리는 컨텍스트 메뉴 루트. 자식으로 Trigger와 Content를 둔다.
|
|
13
|
+
* 사용 가능 액션이 명시적으로 보이는 게 유리한 경우엔 일반 버튼 + DropdownMenu를 권장.
|
|
14
|
+
*/
|
|
15
|
+
export const ContextMenu = BaseContextMenu.Root;
|
|
16
|
+
|
|
17
|
+
/* ───────── Trigger ─────────
|
|
18
|
+
* 우클릭(또는 long-press)을 감지하는 wrapper. 기본은 투명, 사용자는
|
|
19
|
+
* 자신의 영역(Card, 이미지 등)에 적용하여 감싼다.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** 우클릭/long-press를 감지할 영역. Card나 이미지 등 임의 영역을 자식으로 감싼다. */
|
|
23
|
+
export const ContextMenuTrigger = React.forwardRef<
|
|
24
|
+
HTMLDivElement,
|
|
25
|
+
WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.Trigger>>
|
|
26
|
+
>(function ContextMenuTrigger({ className, ...props }, ref) {
|
|
27
|
+
return (
|
|
28
|
+
<BaseContextMenu.Trigger
|
|
29
|
+
ref={ref}
|
|
30
|
+
className={cn(cm__trigger, className)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
/* ───────── Content ───────── */
|
|
37
|
+
|
|
38
|
+
export interface ContextMenuContentProps
|
|
39
|
+
extends WithStringClassName<
|
|
40
|
+
React.ComponentPropsWithoutRef<typeof BaseContextMenu.Popup>
|
|
41
|
+
> {
|
|
42
|
+
/**
|
|
43
|
+
* Portal이 마운트될 DOM 노드.
|
|
44
|
+
* @default document.body
|
|
45
|
+
*/
|
|
46
|
+
container?: React.ComponentPropsWithoutRef<
|
|
47
|
+
typeof BaseContextMenu.Portal
|
|
48
|
+
>["container"];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** 메뉴의 실제 콘텐츠. portal로 마운트되며 클릭 위치 기준으로 자동 배치된다. */
|
|
52
|
+
export const ContextMenuContent = React.forwardRef<
|
|
53
|
+
HTMLDivElement,
|
|
54
|
+
ContextMenuContentProps
|
|
55
|
+
>(function ContextMenuContent({ className, children, container, ...props }, ref) {
|
|
56
|
+
return (
|
|
57
|
+
<BaseContextMenu.Portal container={container}>
|
|
58
|
+
<BaseContextMenu.Positioner className={cm__positioner}>
|
|
59
|
+
<BaseContextMenu.Popup
|
|
60
|
+
ref={ref}
|
|
61
|
+
className={cn(cm__content, className)}
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
{children}
|
|
65
|
+
</BaseContextMenu.Popup>
|
|
66
|
+
</BaseContextMenu.Positioner>
|
|
67
|
+
</BaseContextMenu.Portal>
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
/* ───────── Item ───────── */
|
|
72
|
+
|
|
73
|
+
/** 일반 메뉴 항목. 클릭 시 메뉴가 닫히고 onClick이 발생한다. */
|
|
74
|
+
export const ContextMenuItem = React.forwardRef<
|
|
75
|
+
HTMLDivElement,
|
|
76
|
+
WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.Item>>
|
|
77
|
+
>(function ContextMenuItem({ className, ...props }, ref) {
|
|
78
|
+
return (
|
|
79
|
+
<BaseContextMenu.Item
|
|
80
|
+
ref={ref}
|
|
81
|
+
className={cn(cm__item, className)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/* ───────── CheckboxItem / RadioItem ───────── */
|
|
88
|
+
|
|
89
|
+
/** 체크 표시를 토글하는 메뉴 항목. 메뉴는 닫지 않고 상태만 바꾸는 옵션 ON/OFF 용도. */
|
|
90
|
+
export const ContextMenuCheckboxItem = React.forwardRef<
|
|
91
|
+
HTMLDivElement,
|
|
92
|
+
WithStringClassName<
|
|
93
|
+
React.ComponentPropsWithoutRef<typeof BaseContextMenu.CheckboxItem>
|
|
94
|
+
>
|
|
95
|
+
>(function ContextMenuCheckboxItem({ className, children, ...props }, ref) {
|
|
96
|
+
return (
|
|
97
|
+
<BaseContextMenu.CheckboxItem
|
|
98
|
+
ref={ref}
|
|
99
|
+
className={cn(cm__item, cmItemCheck, className)}
|
|
100
|
+
{...props}
|
|
101
|
+
>
|
|
102
|
+
<span className={cmItemIndicator} aria-hidden>
|
|
103
|
+
<BaseContextMenu.CheckboxItemIndicator>
|
|
104
|
+
<CheckIcon />
|
|
105
|
+
</BaseContextMenu.CheckboxItemIndicator>
|
|
106
|
+
</span>
|
|
107
|
+
<span className={cmItemText}>{children}</span>
|
|
108
|
+
</BaseContextMenu.CheckboxItem>
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/** RadioItem들을 단일 선택 그룹으로 묶는 컨테이너. `value`로 선택값을 제어. */
|
|
113
|
+
export const ContextMenuRadioGroup = BaseContextMenu.RadioGroup;
|
|
114
|
+
|
|
115
|
+
/** ContextMenuRadioGroup 내부의 단일 선택 항목. */
|
|
116
|
+
export const ContextMenuRadioItem = React.forwardRef<
|
|
117
|
+
HTMLDivElement,
|
|
118
|
+
WithStringClassName<
|
|
119
|
+
React.ComponentPropsWithoutRef<typeof BaseContextMenu.RadioItem>
|
|
120
|
+
>
|
|
121
|
+
>(function ContextMenuRadioItem({ className, children, ...props }, ref) {
|
|
122
|
+
return (
|
|
123
|
+
<BaseContextMenu.RadioItem
|
|
124
|
+
ref={ref}
|
|
125
|
+
className={cn(cm__item, cmItemCheck, className)}
|
|
126
|
+
{...props}
|
|
127
|
+
>
|
|
128
|
+
<span className={cmItemIndicator} aria-hidden>
|
|
129
|
+
<BaseContextMenu.RadioItemIndicator>
|
|
130
|
+
<DotIcon />
|
|
131
|
+
</BaseContextMenu.RadioItemIndicator>
|
|
132
|
+
</span>
|
|
133
|
+
<span className={cmItemText}>{children}</span>
|
|
134
|
+
</BaseContextMenu.RadioItem>
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
/* ───────── Group / Label / Separator ───────── */
|
|
139
|
+
|
|
140
|
+
/** 의미적으로 묶이는 항목 그룹. ContextMenuLabel과 함께 사용해 카테고리 헤더를 붙인다. */
|
|
141
|
+
export const ContextMenuGroup = React.forwardRef<
|
|
142
|
+
HTMLDivElement,
|
|
143
|
+
WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.Group>>
|
|
144
|
+
>(function ContextMenuGroup({ className, ...props }, ref) {
|
|
145
|
+
return (
|
|
146
|
+
<BaseContextMenu.Group
|
|
147
|
+
ref={ref}
|
|
148
|
+
className={cn(cm__group, className)}
|
|
149
|
+
{...props}
|
|
150
|
+
/>
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
/** 그룹의 카테고리 헤더 라벨. 클릭 불가, 시각·접근성 컨텍스트 제공용. */
|
|
155
|
+
export const ContextMenuLabel = React.forwardRef<
|
|
156
|
+
HTMLDivElement,
|
|
157
|
+
WithStringClassName<
|
|
158
|
+
React.ComponentPropsWithoutRef<typeof BaseContextMenu.GroupLabel>
|
|
159
|
+
>
|
|
160
|
+
>(function ContextMenuLabel({ className, ...props }, ref) {
|
|
161
|
+
return (
|
|
162
|
+
<BaseContextMenu.GroupLabel
|
|
163
|
+
ref={ref}
|
|
164
|
+
className={cn(cm__label, className)}
|
|
165
|
+
{...props}
|
|
166
|
+
/>
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
/** 항목 사이의 시각적 구분선. */
|
|
171
|
+
export const ContextMenuSeparator = React.forwardRef<
|
|
172
|
+
HTMLDivElement,
|
|
173
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
174
|
+
>(function ContextMenuSeparator({ className, ...props }, ref) {
|
|
175
|
+
return (
|
|
176
|
+
<div
|
|
177
|
+
ref={ref}
|
|
178
|
+
role="separator"
|
|
179
|
+
aria-orientation="horizontal"
|
|
180
|
+
className={cn(cm__separator, className)}
|
|
181
|
+
{...props}
|
|
182
|
+
/>
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
/* ───────── Submenu ───────── */
|
|
187
|
+
|
|
188
|
+
/** 서브메뉴 루트. 호버/포커스 시 우측으로 자식 메뉴를 펼친다. */
|
|
189
|
+
export const ContextMenuSub = BaseContextMenu.SubmenuRoot;
|
|
190
|
+
|
|
191
|
+
/** 서브메뉴를 여는 항목. 우측 화살표 아이콘이 자동 부착된다. */
|
|
192
|
+
export const ContextMenuSubTrigger = React.forwardRef<
|
|
193
|
+
HTMLDivElement,
|
|
194
|
+
WithStringClassName<
|
|
195
|
+
React.ComponentPropsWithoutRef<typeof BaseContextMenu.SubmenuTrigger>
|
|
196
|
+
>
|
|
197
|
+
>(function ContextMenuSubTrigger({ className, children, ...props }, ref) {
|
|
198
|
+
return (
|
|
199
|
+
<BaseContextMenu.SubmenuTrigger
|
|
200
|
+
ref={ref}
|
|
201
|
+
className={cn(cm__item, cmSubTrigger, className)}
|
|
202
|
+
{...props}
|
|
203
|
+
>
|
|
204
|
+
<span className={cmItemText}>{children}</span>
|
|
205
|
+
<span className={cmSubArrow} aria-hidden>
|
|
206
|
+
<ChevronRightIcon />
|
|
207
|
+
</span>
|
|
208
|
+
</BaseContextMenu.SubmenuTrigger>
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
/** 서브메뉴의 콘텐츠. ContextMenuContent의 별칭이다. */
|
|
213
|
+
export const ContextMenuSubContent = ContextMenuContent;
|
|
214
|
+
|
|
215
|
+
/* ───────── 기본 아이콘 ───────── */
|
|
216
|
+
|
|
217
|
+
function CheckIcon() {
|
|
218
|
+
return (
|
|
219
|
+
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden>
|
|
220
|
+
<path
|
|
221
|
+
d="M3.5 8.5l3 3 6-7"
|
|
222
|
+
stroke="currentColor"
|
|
223
|
+
strokeWidth="1.75"
|
|
224
|
+
strokeLinecap="round"
|
|
225
|
+
strokeLinejoin="round"
|
|
226
|
+
/>
|
|
227
|
+
</svg>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function DotIcon() {
|
|
232
|
+
return (
|
|
233
|
+
<svg width="8" height="8" viewBox="0 0 8 8" fill="currentColor" aria-hidden>
|
|
234
|
+
<circle cx="4" cy="4" r="3" />
|
|
235
|
+
</svg>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function ChevronRightIcon() {
|
|
240
|
+
return (
|
|
241
|
+
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden>
|
|
242
|
+
<path
|
|
243
|
+
d="M6 4l4 4-4 4"
|
|
244
|
+
stroke="currentColor"
|
|
245
|
+
strokeWidth="1.5"
|
|
246
|
+
strokeLinecap="round"
|
|
247
|
+
strokeLinejoin="round"
|
|
248
|
+
/>
|
|
249
|
+
</svg>
|
|
250
|
+
);
|
|
251
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { style, keyframes } from "@vanilla-extract/css";
|
|
2
|
+
|
|
3
|
+
export const shUiCmIn = keyframes({
|
|
4
|
+
"from": {
|
|
5
|
+
opacity: 0,
|
|
6
|
+
transform: "scale(0.96)",
|
|
7
|
+
},
|
|
8
|
+
"to": {
|
|
9
|
+
opacity: 1,
|
|
10
|
+
transform: "scale(1)",
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const shUiCmOut = keyframes({
|
|
15
|
+
"from": {
|
|
16
|
+
opacity: 1,
|
|
17
|
+
transform: "scale(1)",
|
|
18
|
+
},
|
|
19
|
+
"to": {
|
|
20
|
+
opacity: 0,
|
|
21
|
+
transform: "scale(0.96)",
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const cm__trigger = style({
|
|
26
|
+
display: "contents",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const cm__positioner = style({
|
|
30
|
+
outline: "none",
|
|
31
|
+
zIndex: "var(--z-dropdown)",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const cm__content = style({
|
|
35
|
+
minWidth: "10rem",
|
|
36
|
+
maxHeight: "min(24rem, var(--available-height, 24rem))",
|
|
37
|
+
overflowY: "auto",
|
|
38
|
+
padding: "var(--space-1)",
|
|
39
|
+
background: "var(--background)",
|
|
40
|
+
color: "var(--foreground)",
|
|
41
|
+
border: "1px solid var(--border)",
|
|
42
|
+
borderRadius: "var(--radius)",
|
|
43
|
+
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.08),\n 0 2px 4px -2px rgba(0, 0, 0, 0.05)",
|
|
44
|
+
fontSize: "var(--text-sm)",
|
|
45
|
+
transformOrigin: "var(--transform-origin)",
|
|
46
|
+
animation: "sh-ui-cm-in 140ms ease-out",
|
|
47
|
+
outline: "none",
|
|
48
|
+
selectors: {
|
|
49
|
+
"&[data-ending-style]": {
|
|
50
|
+
animation: "sh-ui-cm-out 100ms ease-in forwards",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
"@media": {
|
|
54
|
+
"(prefers-reduced-motion: reduce)": {
|
|
55
|
+
animation: "none",
|
|
56
|
+
selectors: {
|
|
57
|
+
"&[data-ending-style]": {
|
|
58
|
+
animation: "none",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export const cm__item = style({
|
|
66
|
+
position: "relative",
|
|
67
|
+
display: "flex",
|
|
68
|
+
alignItems: "center",
|
|
69
|
+
gap: "var(--space-2)",
|
|
70
|
+
padding: "0.5rem 0.75rem",
|
|
71
|
+
borderRadius: "calc(var(--radius) - 2px)",
|
|
72
|
+
cursor: "pointer",
|
|
73
|
+
outline: "none",
|
|
74
|
+
userSelect: "none",
|
|
75
|
+
transition: "background-color 80ms",
|
|
76
|
+
selectors: {
|
|
77
|
+
"&[data-highlighted]": {
|
|
78
|
+
background: "var(--background-muted)",
|
|
79
|
+
},
|
|
80
|
+
"&:hover": {
|
|
81
|
+
background: "var(--background-muted)",
|
|
82
|
+
},
|
|
83
|
+
"&[data-disabled]": {
|
|
84
|
+
opacity: "var(--opacity-disabled)",
|
|
85
|
+
pointerEvents: "none",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
"@media": {
|
|
89
|
+
"(prefers-reduced-motion: reduce)": {
|
|
90
|
+
transition: "none",
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export const cmItemText = style({
|
|
96
|
+
flex: 1,
|
|
97
|
+
minWidth: 0,
|
|
98
|
+
overflow: "hidden",
|
|
99
|
+
textOverflow: "ellipsis",
|
|
100
|
+
whiteSpace: "nowrap",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export const cmItemCheck = style({
|
|
104
|
+
paddingLeft: "1.75rem",
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
export const cmItemIndicator = style({
|
|
108
|
+
position: "absolute",
|
|
109
|
+
left: "0.5rem",
|
|
110
|
+
display: "inline-flex",
|
|
111
|
+
alignItems: "center",
|
|
112
|
+
justifyContent: "center",
|
|
113
|
+
width: "1rem",
|
|
114
|
+
height: "1rem",
|
|
115
|
+
color: "var(--foreground)",
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export const cm__group = style({
|
|
119
|
+
padding: 0,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export const cm__label = style({
|
|
123
|
+
padding: "var(--space-2) var(--space-2) var(--space-1)",
|
|
124
|
+
fontSize: "var(--text-xs)",
|
|
125
|
+
fontWeight: "var(--weight-semibold)",
|
|
126
|
+
color: "var(--foreground-muted)",
|
|
127
|
+
textTransform: "uppercase",
|
|
128
|
+
letterSpacing: "0.04em",
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
export const cm__separator = style({
|
|
132
|
+
height: "1px",
|
|
133
|
+
background: "var(--border)",
|
|
134
|
+
margin: "var(--space-1) 0",
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
export const cmSubArrow = style({
|
|
138
|
+
display: "inline-flex",
|
|
139
|
+
alignItems: "center",
|
|
140
|
+
justifyContent: "center",
|
|
141
|
+
marginLeft: "auto",
|
|
142
|
+
color: "var(--foreground-muted)",
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
export const cmSubTrigger = style({
|
|
146
|
+
selectors: {
|
|
147
|
+
"&[data-popup-open]": {
|
|
148
|
+
background: "var(--background-muted)",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/** 동적 키로 클래스 참조용 — `byKey[\`badge--${variant}\`]` 같은 패턴 지원. */
|
|
154
|
+
export const byKey: Record<string, string> = {
|
|
155
|
+
"cm__trigger": cm__trigger,
|
|
156
|
+
"cm__positioner": cm__positioner,
|
|
157
|
+
"cm__content": cm__content,
|
|
158
|
+
"cm__item": cm__item,
|
|
159
|
+
"cm__item-text": cmItemText,
|
|
160
|
+
"cm__item--check": cmItemCheck,
|
|
161
|
+
"cm__item-indicator": cmItemIndicator,
|
|
162
|
+
"cm__group": cm__group,
|
|
163
|
+
"cm__label": cm__label,
|
|
164
|
+
"cm__separator": cm__separator,
|
|
165
|
+
"cm__sub-arrow": cmSubArrow,
|
|
166
|
+
"cm__sub-trigger": cmSubTrigger,
|
|
167
|
+
};
|