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.
Files changed (93) hide show
  1. package/data/changelog/versions.json +27 -0
  2. package/data/registry/react/components/accordion/index.vanilla-extract.tsx +97 -0
  3. package/data/registry/react/components/accordion/styles.css.ts +131 -0
  4. package/data/registry/react/components/avatar/index.vanilla-extract.tsx +73 -0
  5. package/data/registry/react/components/avatar/styles.css.ts +68 -0
  6. package/data/registry/react/components/badge/index.vanilla-extract.tsx +40 -0
  7. package/data/registry/react/components/badge/styles.css.ts +71 -0
  8. package/data/registry/react/components/breadcrumb/index.vanilla-extract.tsx +152 -0
  9. package/data/registry/react/components/breadcrumb/styles.css.ts +95 -0
  10. package/data/registry/react/components/button/index.vanilla-extract.tsx +45 -0
  11. package/data/registry/react/components/button/styles.css.ts +120 -0
  12. package/data/registry/react/components/calendar/index.vanilla-extract.tsx +806 -0
  13. package/data/registry/react/components/calendar/styles.css.ts +250 -0
  14. package/data/registry/react/components/card/index.vanilla-extract.tsx +63 -0
  15. package/data/registry/react/components/card/styles.css.ts +88 -0
  16. package/data/registry/react/components/carousel/index.vanilla-extract.tsx +430 -0
  17. package/data/registry/react/components/carousel/styles.css.ts +169 -0
  18. package/data/registry/react/components/checkbox/index.vanilla-extract.tsx +96 -0
  19. package/data/registry/react/components/checkbox/styles.css.ts +74 -0
  20. package/data/registry/react/components/code-editor/index.vanilla-extract.tsx +230 -0
  21. package/data/registry/react/components/code-editor/styles.css.ts +97 -0
  22. package/data/registry/react/components/code-panel/index.vanilla-extract.tsx +191 -0
  23. package/data/registry/react/components/code-panel/styles.css.ts +151 -0
  24. package/data/registry/react/components/color-picker/index.vanilla-extract.tsx +467 -0
  25. package/data/registry/react/components/color-picker/styles.css.ts +169 -0
  26. package/data/registry/react/components/combobox/index.vanilla-extract.tsx +165 -0
  27. package/data/registry/react/components/combobox/styles.css.ts +174 -0
  28. package/data/registry/react/components/context-menu/index.vanilla-extract.tsx +251 -0
  29. package/data/registry/react/components/context-menu/styles.css.ts +167 -0
  30. package/data/registry/react/components/date-picker/index.vanilla-extract.tsx +520 -0
  31. package/data/registry/react/components/date-picker/styles.css.ts +111 -0
  32. package/data/registry/react/components/dialog/index.vanilla-extract.tsx +95 -0
  33. package/data/registry/react/components/dialog/styles.css.ts +140 -0
  34. package/data/registry/react/components/dropdown-menu/index.vanilla-extract.tsx +255 -0
  35. package/data/registry/react/components/dropdown-menu/styles.css.ts +175 -0
  36. package/data/registry/react/components/file-upload/index.vanilla-extract.tsx +487 -0
  37. package/data/registry/react/components/file-upload/styles.css.ts +193 -0
  38. package/data/registry/react/components/form/index.vanilla-extract.tsx +61 -0
  39. package/data/registry/react/components/form/styles.css.ts +56 -0
  40. package/data/registry/react/components/header/index.vanilla-extract.tsx +805 -0
  41. package/data/registry/react/components/header/styles.css.ts +413 -0
  42. package/data/registry/react/components/input/index.vanilla-extract.tsx +425 -0
  43. package/data/registry/react/components/input/styles.css.ts +202 -0
  44. package/data/registry/react/components/label/index.vanilla-extract.tsx +52 -0
  45. package/data/registry/react/components/label/styles.css.ts +141 -0
  46. package/data/registry/react/components/markdown-editor/index.vanilla-extract.tsx +119 -0
  47. package/data/registry/react/components/markdown-editor/styles.css.ts +231 -0
  48. package/data/registry/react/components/menubar/index.vanilla-extract.tsx +32 -0
  49. package/data/registry/react/components/menubar/styles.css.ts +53 -0
  50. package/data/registry/react/components/numeric-input/index.vanilla-extract.tsx +148 -0
  51. package/data/registry/react/components/numeric-input/styles.css.ts +65 -0
  52. package/data/registry/react/components/page-toc/index.vanilla-extract.tsx +174 -0
  53. package/data/registry/react/components/page-toc/styles.css.ts +97 -0
  54. package/data/registry/react/components/pagination/index.vanilla-extract.tsx +269 -0
  55. package/data/registry/react/components/pagination/styles.css.ts +113 -0
  56. package/data/registry/react/components/popover/index.vanilla-extract.tsx +113 -0
  57. package/data/registry/react/components/popover/styles.css.ts +78 -0
  58. package/data/registry/react/components/progress/index.vanilla-extract.tsx +54 -0
  59. package/data/registry/react/components/progress/styles.css.ts +53 -0
  60. package/data/registry/react/components/radio/index.vanilla-extract.tsx +65 -0
  61. package/data/registry/react/components/radio/styles.css.ts +79 -0
  62. package/data/registry/react/components/rich-text-editor/index.vanilla-extract.tsx +348 -0
  63. package/data/registry/react/components/rich-text-editor/styles.css.ts +243 -0
  64. package/data/registry/react/components/select/index.vanilla-extract.tsx +234 -0
  65. package/data/registry/react/components/select/styles.css.ts +225 -0
  66. package/data/registry/react/components/separator/index.vanilla-extract.tsx +46 -0
  67. package/data/registry/react/components/separator/styles.css.ts +24 -0
  68. package/data/registry/react/components/sidebar/index.vanilla-extract.tsx +1067 -0
  69. package/data/registry/react/components/sidebar/styles.css.ts +578 -0
  70. package/data/registry/react/components/skeleton/index.vanilla-extract.tsx +22 -0
  71. package/data/registry/react/components/skeleton/styles.css.ts +30 -0
  72. package/data/registry/react/components/slider/index.vanilla-extract.tsx +298 -0
  73. package/data/registry/react/components/slider/styles.css.ts +75 -0
  74. package/data/registry/react/components/spinner/index.vanilla-extract.tsx +38 -0
  75. package/data/registry/react/components/spinner/styles.css.ts +60 -0
  76. package/data/registry/react/components/switch/index.vanilla-extract.tsx +39 -0
  77. package/data/registry/react/components/switch/styles.css.ts +87 -0
  78. package/data/registry/react/components/tabs/index.vanilla-extract.tsx +91 -0
  79. package/data/registry/react/components/tabs/styles.css.ts +145 -0
  80. package/data/registry/react/components/textarea/index.vanilla-extract.tsx +23 -0
  81. package/data/registry/react/components/textarea/styles.css.ts +55 -0
  82. package/data/registry/react/components/toast/index.vanilla-extract.tsx +258 -0
  83. package/data/registry/react/components/toast/styles.css.ts +307 -0
  84. package/data/registry/react/components/toggle/index.vanilla-extract.tsx +131 -0
  85. package/data/registry/react/components/toggle/styles.css.ts +109 -0
  86. package/data/registry/react/components/tooltip/index.vanilla-extract.tsx +83 -0
  87. package/data/registry/react/components/tooltip/styles.css.ts +59 -0
  88. package/data/registry/react/peer-versions.json +1 -0
  89. package/data/registry/react/registry.json +922 -42
  90. package/data/tokens/build.mjs +3 -0
  91. package/package.json +1 -1
  92. package/src/api.d.ts +4 -3
  93. 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
+ };