sh-ui-cli 0.14.0 → 0.21.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 (162) hide show
  1. package/bin/sh-ui.mjs +6 -0
  2. package/data/changelog/versions.json +354 -0
  3. package/data/registry/flutter/foundation/sh_ui_tokens.dart +385 -0
  4. package/data/registry/flutter/registry.json +336 -0
  5. package/data/registry/flutter/widgets/sh_ui_accordion.dart +255 -0
  6. package/data/registry/flutter/widgets/sh_ui_app_shell.dart +267 -0
  7. package/data/registry/flutter/widgets/sh_ui_avatar.dart +95 -0
  8. package/data/registry/flutter/widgets/sh_ui_badge.dart +82 -0
  9. package/data/registry/flutter/widgets/sh_ui_breadcrumb.dart +107 -0
  10. package/data/registry/flutter/widgets/sh_ui_button.dart +201 -0
  11. package/data/registry/flutter/widgets/sh_ui_card.dart +159 -0
  12. package/data/registry/flutter/widgets/sh_ui_carousel.dart +204 -0
  13. package/data/registry/flutter/widgets/sh_ui_checkbox.dart +154 -0
  14. package/data/registry/flutter/widgets/sh_ui_color_picker.dart +264 -0
  15. package/data/registry/flutter/widgets/sh_ui_combobox.dart +614 -0
  16. package/data/registry/flutter/widgets/sh_ui_context_menu.dart +71 -0
  17. package/data/registry/flutter/widgets/sh_ui_date_picker.dart +648 -0
  18. package/data/registry/flutter/widgets/sh_ui_dialog.dart +567 -0
  19. package/data/registry/flutter/widgets/sh_ui_dropdown_menu.dart +251 -0
  20. package/data/registry/flutter/widgets/sh_ui_file_upload.dart +200 -0
  21. package/data/registry/flutter/widgets/sh_ui_header.dart +488 -0
  22. package/data/registry/flutter/widgets/sh_ui_input.dart +664 -0
  23. package/data/registry/flutter/widgets/sh_ui_label.dart +145 -0
  24. package/data/registry/flutter/widgets/sh_ui_menubar.dart +98 -0
  25. package/data/registry/flutter/widgets/sh_ui_pagination.dart +276 -0
  26. package/data/registry/flutter/widgets/sh_ui_popover.dart +248 -0
  27. package/data/registry/flutter/widgets/sh_ui_progress.dart +47 -0
  28. package/data/registry/flutter/widgets/sh_ui_radio.dart +108 -0
  29. package/data/registry/flutter/widgets/sh_ui_select.dart +904 -0
  30. package/data/registry/flutter/widgets/sh_ui_separator.dart +42 -0
  31. package/data/registry/flutter/widgets/sh_ui_sidebar.dart +1116 -0
  32. package/data/registry/flutter/widgets/sh_ui_skeleton.dart +129 -0
  33. package/data/registry/flutter/widgets/sh_ui_slider.dart +147 -0
  34. package/data/registry/flutter/widgets/sh_ui_spinner.dart +56 -0
  35. package/data/registry/flutter/widgets/sh_ui_switch.dart +109 -0
  36. package/data/registry/flutter/widgets/sh_ui_tabs.dart +329 -0
  37. package/data/registry/flutter/widgets/sh_ui_textarea.dart +126 -0
  38. package/data/registry/flutter/widgets/sh_ui_toast.dart +362 -0
  39. package/data/registry/flutter/widgets/sh_ui_toggle.dart +229 -0
  40. package/data/registry/flutter/widgets/sh_ui_tooltip.dart +62 -0
  41. package/data/registry/react/components/accordion/index.tsx +85 -0
  42. package/data/registry/react/components/accordion/styles.css +94 -0
  43. package/data/registry/react/components/animations/animations.css +51 -0
  44. package/data/registry/react/components/avatar/index.tsx +75 -0
  45. package/data/registry/react/components/avatar/styles.css +36 -0
  46. package/data/registry/react/components/badge/index.tsx +42 -0
  47. package/data/registry/react/components/badge/styles.css +57 -0
  48. package/data/registry/react/components/base/base.css +102 -0
  49. package/data/registry/react/components/breadcrumb/index.tsx +154 -0
  50. package/data/registry/react/components/breadcrumb/styles.css +82 -0
  51. package/data/registry/react/components/breakpoints/breakpoints.css +17 -0
  52. package/data/registry/react/components/button/index.tsx +47 -0
  53. package/data/registry/react/components/button/styles.css +93 -0
  54. package/data/registry/react/components/card/index.tsx +86 -0
  55. package/data/registry/react/components/card/styles.css +73 -0
  56. package/data/registry/react/components/carousel/index.tsx +432 -0
  57. package/data/registry/react/components/carousel/styles.css +155 -0
  58. package/data/registry/react/components/checkbox/index.tsx +98 -0
  59. package/data/registry/react/components/checkbox/styles.css +75 -0
  60. package/data/registry/react/components/code-panel/copy.tsx +56 -0
  61. package/data/registry/react/components/code-panel/index.tsx +193 -0
  62. package/data/registry/react/components/code-panel/styles.css +124 -0
  63. package/data/registry/react/components/color-picker/index.tsx +466 -0
  64. package/data/registry/react/components/color-picker/styles.css +166 -0
  65. package/data/registry/react/components/combobox/index.tsx +167 -0
  66. package/data/registry/react/components/combobox/styles.css +151 -0
  67. package/data/registry/react/components/context-menu/index.tsx +253 -0
  68. package/data/registry/react/components/context-menu/styles.css +140 -0
  69. package/data/registry/react/components/date-picker/index.tsx +757 -0
  70. package/data/registry/react/components/date-picker/styles.css +279 -0
  71. package/data/registry/react/components/dialog/index.tsx +97 -0
  72. package/data/registry/react/components/dialog/styles.css +127 -0
  73. package/data/registry/react/components/dropdown-menu/index.tsx +257 -0
  74. package/data/registry/react/components/dropdown-menu/styles.css +150 -0
  75. package/data/registry/react/components/file-upload/index.tsx +489 -0
  76. package/data/registry/react/components/file-upload/styles.css +170 -0
  77. package/data/registry/react/components/focus-ring/focus-ring.css +23 -0
  78. package/data/registry/react/components/form/context.ts +92 -0
  79. package/data/registry/react/components/form/field.test.tsx +230 -0
  80. package/data/registry/react/components/form/field.tsx +236 -0
  81. package/data/registry/react/components/form/focus-first-error.ts +54 -0
  82. package/data/registry/react/components/form/form.section.test.tsx +58 -0
  83. package/data/registry/react/components/form/form.test.tsx +146 -0
  84. package/data/registry/react/components/form/form.tsx +180 -0
  85. package/data/registry/react/components/form/index.tsx +61 -0
  86. package/data/registry/react/components/form/steps.test.tsx +106 -0
  87. package/data/registry/react/components/form/steps.tsx +193 -0
  88. package/data/registry/react/components/form/store.test.ts +206 -0
  89. package/data/registry/react/components/form/store.ts +318 -0
  90. package/data/registry/react/components/form/styles.css +47 -0
  91. package/data/registry/react/components/form/types.ts +104 -0
  92. package/data/registry/react/components/form/use-sh-ui-form.ts +15 -0
  93. package/data/registry/react/components/form/utils.test.ts +44 -0
  94. package/data/registry/react/components/form/utils.ts +49 -0
  95. package/data/registry/react/components/form/validation.test.ts +67 -0
  96. package/data/registry/react/components/form/validation.ts +64 -0
  97. package/data/registry/react/components/form-rhf/README.md +27 -0
  98. package/data/registry/react/components/form-rhf/index.tsx +289 -0
  99. package/data/registry/react/components/form-rhf/rhf.test.tsx +42 -0
  100. package/data/registry/react/components/form-tanstack/README.md +27 -0
  101. package/data/registry/react/components/form-tanstack/index.tsx +352 -0
  102. package/data/registry/react/components/form-tanstack/tanstack.test.tsx +45 -0
  103. package/data/registry/react/components/form-yup/README.md +22 -0
  104. package/data/registry/react/components/form-yup/index.tsx +50 -0
  105. package/data/registry/react/components/form-yup/yup.test.ts +27 -0
  106. package/data/registry/react/components/header/index.tsx +257 -0
  107. package/data/registry/react/components/header/styles.css +190 -0
  108. package/data/registry/react/components/input/index.tsx +517 -0
  109. package/data/registry/react/components/input/styles.css +203 -0
  110. package/data/registry/react/components/label/index.tsx +54 -0
  111. package/data/registry/react/components/label/styles.css +90 -0
  112. package/data/registry/react/components/menubar/index.tsx +34 -0
  113. package/data/registry/react/components/menubar/styles.css +45 -0
  114. package/data/registry/react/components/pagination/index.tsx +271 -0
  115. package/data/registry/react/components/pagination/styles.css +105 -0
  116. package/data/registry/react/components/popover/index.tsx +115 -0
  117. package/data/registry/react/components/popover/styles.css +65 -0
  118. package/data/registry/react/components/progress/index.tsx +56 -0
  119. package/data/registry/react/components/progress/styles.css +41 -0
  120. package/data/registry/react/components/radio/index.tsx +67 -0
  121. package/data/registry/react/components/radio/styles.css +80 -0
  122. package/data/registry/react/components/select/index.tsx +236 -0
  123. package/data/registry/react/components/select/styles.css +193 -0
  124. package/data/registry/react/components/separator/index.tsx +48 -0
  125. package/data/registry/react/components/separator/styles.css +15 -0
  126. package/data/registry/react/components/sidebar/index.tsx +1084 -0
  127. package/data/registry/react/components/sidebar/styles.css +502 -0
  128. package/data/registry/react/components/skeleton/index.tsx +24 -0
  129. package/data/registry/react/components/skeleton/styles.css +24 -0
  130. package/data/registry/react/components/slider/index.tsx +300 -0
  131. package/data/registry/react/components/slider/styles.css +64 -0
  132. package/data/registry/react/components/spinner/index.tsx +40 -0
  133. package/data/registry/react/components/spinner/styles.css +37 -0
  134. package/data/registry/react/components/switch/index.tsx +41 -0
  135. package/data/registry/react/components/switch/styles.css +83 -0
  136. package/data/registry/react/components/tabs/index.tsx +93 -0
  137. package/data/registry/react/components/tabs/styles.css +148 -0
  138. package/data/registry/react/components/textarea/index.tsx +25 -0
  139. package/data/registry/react/components/textarea/styles.css +54 -0
  140. package/data/registry/react/components/theme/index.tsx +91 -0
  141. package/data/registry/react/components/toast/index.tsx +257 -0
  142. package/data/registry/react/components/toast/styles.css +290 -0
  143. package/data/registry/react/components/toggle/index.tsx +133 -0
  144. package/data/registry/react/components/toggle/styles.css +85 -0
  145. package/data/registry/react/components/tooltip/index.tsx +85 -0
  146. package/data/registry/react/components/tooltip/styles.css +44 -0
  147. package/data/registry/react/components/z-index/z-index.css +16 -0
  148. package/data/registry/react/hooks/use-active-section.ts +104 -0
  149. package/data/registry/react/hooks/use-media-query.ts +27 -0
  150. package/data/registry/react/lib/cn.ts +39 -0
  151. package/data/registry/react/registry.json +835 -0
  152. package/data/summaries/flutter.json +42 -0
  153. package/data/summaries/react.json +50 -0
  154. package/data/tokens/build.mjs +553 -0
  155. package/data/tokens/src/primitives.json +146 -0
  156. package/data/tokens/src/semantic.json +146 -0
  157. package/package.json +13 -4
  158. package/src/add.mjs +13 -12
  159. package/src/list.mjs +3 -11
  160. package/src/mcp.mjs +308 -0
  161. package/src/paths.mjs +52 -0
  162. package/src/remove.mjs +4 -11
@@ -0,0 +1,257 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Menu as BaseMenu } from "@base-ui-components/react/menu";
5
+ import "./styles.css";
6
+
7
+ type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
8
+
9
+ function cx(...args: (string | undefined | false | null)[]) {
10
+ return args.filter(Boolean).join(" ");
11
+ }
12
+
13
+ /* ───────── Root ───────── */
14
+
15
+ export const DropdownMenu = BaseMenu.Root;
16
+
17
+ /* ───────── Trigger ───────── */
18
+
19
+ export const DropdownMenuTrigger = React.forwardRef<
20
+ HTMLButtonElement,
21
+ WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseMenu.Trigger>>
22
+ >(function DropdownMenuTrigger({ className, ...props }, ref) {
23
+ return (
24
+ <BaseMenu.Trigger
25
+ ref={ref}
26
+ className={cx("sh-ui-dm__trigger", className)}
27
+ {...props}
28
+ />
29
+ );
30
+ });
31
+
32
+ /* ───────── Content ─────────
33
+ * Portal + Positioner + Popup을 한 컴포넌트로 묶는다. Popover와 동일한 관용.
34
+ */
35
+
36
+ export interface DropdownMenuContentProps
37
+ extends WithStringClassName<
38
+ React.ComponentPropsWithoutRef<typeof BaseMenu.Popup>
39
+ > {
40
+ side?: "top" | "right" | "bottom" | "left";
41
+ align?: "start" | "center" | "end";
42
+ /** Trigger-Popup 간격(px). 기본 6. */
43
+ sideOffset?: number;
44
+ container?: React.ComponentPropsWithoutRef<
45
+ typeof BaseMenu.Portal
46
+ >["container"];
47
+ }
48
+
49
+ export const DropdownMenuContent = React.forwardRef<
50
+ HTMLDivElement,
51
+ DropdownMenuContentProps
52
+ >(function DropdownMenuContent(
53
+ { className, children, side, align, sideOffset = 6, container, ...props },
54
+ ref,
55
+ ) {
56
+ return (
57
+ <BaseMenu.Portal container={container}>
58
+ <BaseMenu.Positioner
59
+ className="sh-ui-dm__positioner"
60
+ side={side}
61
+ align={align}
62
+ sideOffset={sideOffset}
63
+ >
64
+ <BaseMenu.Popup
65
+ ref={ref}
66
+ className={cx("sh-ui-dm__content", className)}
67
+ {...props}
68
+ >
69
+ {children}
70
+ </BaseMenu.Popup>
71
+ </BaseMenu.Positioner>
72
+ </BaseMenu.Portal>
73
+ );
74
+ });
75
+
76
+ /* ───────── Item ───────── */
77
+
78
+ export const DropdownMenuItem = React.forwardRef<
79
+ HTMLDivElement,
80
+ WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseMenu.Item>>
81
+ >(function DropdownMenuItem({ className, ...props }, ref) {
82
+ return (
83
+ <BaseMenu.Item
84
+ ref={ref}
85
+ className={cx("sh-ui-dm__item", className)}
86
+ {...props}
87
+ />
88
+ );
89
+ });
90
+
91
+ /* ───────── CheckboxItem ───────── */
92
+
93
+ export interface DropdownMenuCheckboxItemProps
94
+ extends WithStringClassName<
95
+ React.ComponentPropsWithoutRef<typeof BaseMenu.CheckboxItem>
96
+ > {}
97
+
98
+ export const DropdownMenuCheckboxItem = React.forwardRef<
99
+ HTMLDivElement,
100
+ DropdownMenuCheckboxItemProps
101
+ >(function DropdownMenuCheckboxItem({ className, children, ...props }, ref) {
102
+ return (
103
+ <BaseMenu.CheckboxItem
104
+ ref={ref}
105
+ className={cx("sh-ui-dm__item", "sh-ui-dm__item--check", className)}
106
+ {...props}
107
+ >
108
+ <span className="sh-ui-dm__item-indicator" aria-hidden>
109
+ <BaseMenu.CheckboxItemIndicator>
110
+ <CheckIcon />
111
+ </BaseMenu.CheckboxItemIndicator>
112
+ </span>
113
+ <span className="sh-ui-dm__item-text">{children}</span>
114
+ </BaseMenu.CheckboxItem>
115
+ );
116
+ });
117
+
118
+ /* ───────── RadioGroup / RadioItem ───────── */
119
+
120
+ export const DropdownMenuRadioGroup = BaseMenu.RadioGroup;
121
+
122
+ export interface DropdownMenuRadioItemProps
123
+ extends WithStringClassName<
124
+ React.ComponentPropsWithoutRef<typeof BaseMenu.RadioItem>
125
+ > {}
126
+
127
+ export const DropdownMenuRadioItem = React.forwardRef<
128
+ HTMLDivElement,
129
+ DropdownMenuRadioItemProps
130
+ >(function DropdownMenuRadioItem({ className, children, ...props }, ref) {
131
+ return (
132
+ <BaseMenu.RadioItem
133
+ ref={ref}
134
+ className={cx("sh-ui-dm__item", "sh-ui-dm__item--check", className)}
135
+ {...props}
136
+ >
137
+ <span className="sh-ui-dm__item-indicator" aria-hidden>
138
+ <BaseMenu.RadioItemIndicator>
139
+ <DotIcon />
140
+ </BaseMenu.RadioItemIndicator>
141
+ </span>
142
+ <span className="sh-ui-dm__item-text">{children}</span>
143
+ </BaseMenu.RadioItem>
144
+ );
145
+ });
146
+
147
+ /* ───────── Group / Label ───────── */
148
+
149
+ export const DropdownMenuGroup = React.forwardRef<
150
+ HTMLDivElement,
151
+ WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseMenu.Group>>
152
+ >(function DropdownMenuGroup({ className, ...props }, ref) {
153
+ return (
154
+ <BaseMenu.Group
155
+ ref={ref}
156
+ className={cx("sh-ui-dm__group", className)}
157
+ {...props}
158
+ />
159
+ );
160
+ });
161
+
162
+ export const DropdownMenuLabel = React.forwardRef<
163
+ HTMLDivElement,
164
+ WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseMenu.GroupLabel>>
165
+ >(function DropdownMenuLabel({ className, ...props }, ref) {
166
+ return (
167
+ <BaseMenu.GroupLabel
168
+ ref={ref}
169
+ className={cx("sh-ui-dm__label", className)}
170
+ {...props}
171
+ />
172
+ );
173
+ });
174
+
175
+ /* ───────── Separator ─────────
176
+ * Base UI Menu에 전용 Separator가 없어 role="separator" div로 대체.
177
+ */
178
+
179
+ export const DropdownMenuSeparator = React.forwardRef<
180
+ HTMLDivElement,
181
+ React.HTMLAttributes<HTMLDivElement>
182
+ >(function DropdownMenuSeparator({ className, ...props }, ref) {
183
+ return (
184
+ <div
185
+ ref={ref}
186
+ role="separator"
187
+ aria-orientation="horizontal"
188
+ className={cx("sh-ui-dm__separator", className)}
189
+ {...props}
190
+ />
191
+ );
192
+ });
193
+
194
+ /* ───────── Submenu ───────── */
195
+
196
+ export const DropdownMenuSub = BaseMenu.SubmenuRoot;
197
+
198
+ export const DropdownMenuSubTrigger = React.forwardRef<
199
+ HTMLDivElement,
200
+ WithStringClassName<
201
+ React.ComponentPropsWithoutRef<typeof BaseMenu.SubmenuTrigger>
202
+ >
203
+ >(function DropdownMenuSubTrigger({ className, children, ...props }, ref) {
204
+ return (
205
+ <BaseMenu.SubmenuTrigger
206
+ ref={ref}
207
+ className={cx("sh-ui-dm__item", "sh-ui-dm__sub-trigger", className)}
208
+ {...props}
209
+ >
210
+ <span className="sh-ui-dm__item-text">{children}</span>
211
+ <span className="sh-ui-dm__sub-arrow" aria-hidden>
212
+ <ChevronRightIcon />
213
+ </span>
214
+ </BaseMenu.SubmenuTrigger>
215
+ );
216
+ });
217
+
218
+ /** Submenu 내용물 — 최상위 Content와 동일한 포털 구조. */
219
+ export const DropdownMenuSubContent = DropdownMenuContent;
220
+
221
+ /* ───────── 기본 아이콘 ───────── */
222
+
223
+ function CheckIcon() {
224
+ return (
225
+ <svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden>
226
+ <path
227
+ d="M3.5 8.5l3 3 6-7"
228
+ stroke="currentColor"
229
+ strokeWidth="1.75"
230
+ strokeLinecap="round"
231
+ strokeLinejoin="round"
232
+ />
233
+ </svg>
234
+ );
235
+ }
236
+
237
+ function DotIcon() {
238
+ return (
239
+ <svg width="8" height="8" viewBox="0 0 8 8" fill="currentColor" aria-hidden>
240
+ <circle cx="4" cy="4" r="3" />
241
+ </svg>
242
+ );
243
+ }
244
+
245
+ function ChevronRightIcon() {
246
+ return (
247
+ <svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden>
248
+ <path
249
+ d="M6 4l4 4-4 4"
250
+ stroke="currentColor"
251
+ strokeWidth="1.5"
252
+ strokeLinecap="round"
253
+ strokeLinejoin="round"
254
+ />
255
+ </svg>
256
+ );
257
+ }
@@ -0,0 +1,150 @@
1
+ /* ───────── Trigger ─────────
2
+ * 기본 스타일을 최소화하여 사용자가 Button/아이콘 버튼 등 어떤 트리거든
3
+ * 덮어쓸 수 있게 한다. 포커스 링만 담당.
4
+ */
5
+ .sh-ui-dm__trigger {
6
+ font: inherit;
7
+ cursor: pointer;
8
+ -webkit-tap-highlight-color: transparent;
9
+ }
10
+
11
+ .sh-ui-dm__trigger:focus-visible {
12
+ outline: var(--border-width-strong) solid var(--foreground);
13
+ outline-offset: 2px;
14
+ }
15
+
16
+ /* ───────── Positioner / Content ───────── */
17
+
18
+ .sh-ui-dm__positioner {
19
+ outline: none;
20
+ z-index: var(--z-dropdown);
21
+ }
22
+
23
+ .sh-ui-dm__content {
24
+ min-width: 10rem;
25
+ max-height: min(24rem, var(--available-height, 24rem));
26
+ overflow-y: auto;
27
+ padding: var(--space-1);
28
+ background: var(--background);
29
+ color: var(--foreground);
30
+ border: 1px solid var(--border);
31
+ border-radius: var(--radius);
32
+ box-shadow:
33
+ 0 4px 6px -1px rgba(0, 0, 0, 0.08),
34
+ 0 2px 4px -2px rgba(0, 0, 0, 0.05);
35
+ font-size: var(--text-sm);
36
+ transform-origin: var(--transform-origin);
37
+ animation: sh-ui-dm-in 140ms ease-out;
38
+ outline: none;
39
+ }
40
+
41
+ .sh-ui-dm__content[data-ending-style] {
42
+ animation: sh-ui-dm-out 100ms ease-in forwards;
43
+ }
44
+
45
+ @keyframes sh-ui-dm-in {
46
+ from { opacity: 0; transform: scale(0.96); }
47
+ to { opacity: 1; transform: scale(1); }
48
+ }
49
+ @keyframes sh-ui-dm-out {
50
+ from { opacity: 1; transform: scale(1); }
51
+ to { opacity: 0; transform: scale(0.96); }
52
+ }
53
+
54
+ /* ───────── Item ───────── */
55
+
56
+ .sh-ui-dm__item {
57
+ position: relative;
58
+ display: flex;
59
+ align-items: center;
60
+ gap: var(--space-2);
61
+ padding: 0.5rem 0.75rem;
62
+ border-radius: calc(var(--radius) - 2px);
63
+ cursor: pointer;
64
+ outline: none;
65
+ user-select: none;
66
+ transition: background-color 80ms;
67
+ }
68
+
69
+ .sh-ui-dm__item[data-highlighted],
70
+ .sh-ui-dm__item:hover {
71
+ background: var(--background-muted);
72
+ }
73
+
74
+ .sh-ui-dm__item[data-disabled] {
75
+ opacity: var(--opacity-disabled);
76
+ pointer-events: none;
77
+ }
78
+
79
+ .sh-ui-dm__item-text {
80
+ flex: 1;
81
+ min-width: 0;
82
+ overflow: hidden;
83
+ text-overflow: ellipsis;
84
+ white-space: nowrap;
85
+ }
86
+
87
+ /* checkbox/radio item — 왼쪽 인디케이터 공간 확보 */
88
+ .sh-ui-dm__item--check {
89
+ padding-left: 1.75rem;
90
+ }
91
+
92
+ .sh-ui-dm__item-indicator {
93
+ position: absolute;
94
+ left: 0.5rem;
95
+ display: inline-flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ width: 1rem;
99
+ height: 1rem;
100
+ color: var(--foreground);
101
+ }
102
+
103
+ /* ───────── Group / Label ───────── */
104
+
105
+ .sh-ui-dm__group {
106
+ padding: 0;
107
+ }
108
+
109
+ .sh-ui-dm__label {
110
+ padding: var(--space-2) var(--space-2) var(--space-1);
111
+ font-size: var(--text-xs);
112
+ font-weight: var(--weight-semibold);
113
+ color: var(--foreground-muted);
114
+ text-transform: uppercase;
115
+ letter-spacing: 0.04em;
116
+ }
117
+
118
+ /* ───────── Separator ───────── */
119
+
120
+ .sh-ui-dm__separator {
121
+ height: 1px;
122
+ background: var(--border);
123
+ margin: var(--space-1) 0;
124
+ }
125
+
126
+ /* ───────── Submenu trigger ───────── */
127
+
128
+ .sh-ui-dm__sub-arrow {
129
+ display: inline-flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ margin-left: auto;
133
+ color: var(--foreground-muted);
134
+ }
135
+
136
+ .sh-ui-dm__sub-trigger[data-popup-open] {
137
+ background: var(--background-muted);
138
+ }
139
+
140
+ /* ───────── Reduced motion ───────── */
141
+
142
+ @media (prefers-reduced-motion: reduce) {
143
+ .sh-ui-dm__content,
144
+ .sh-ui-dm__content[data-ending-style] {
145
+ animation: none;
146
+ }
147
+ .sh-ui-dm__item {
148
+ transition: none;
149
+ }
150
+ }