sh-ui-cli 0.49.0 → 0.51.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 (85) 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/calendar/index.vanilla-extract.tsx +806 -0
  11. package/data/registry/react/components/calendar/styles.css.ts +250 -0
  12. package/data/registry/react/components/carousel/index.vanilla-extract.tsx +430 -0
  13. package/data/registry/react/components/carousel/styles.css.ts +169 -0
  14. package/data/registry/react/components/checkbox/index.vanilla-extract.tsx +96 -0
  15. package/data/registry/react/components/checkbox/styles.css.ts +74 -0
  16. package/data/registry/react/components/code-editor/index.vanilla-extract.tsx +230 -0
  17. package/data/registry/react/components/code-editor/styles.css.ts +97 -0
  18. package/data/registry/react/components/code-panel/index.vanilla-extract.tsx +191 -0
  19. package/data/registry/react/components/code-panel/styles.css.ts +151 -0
  20. package/data/registry/react/components/color-picker/index.vanilla-extract.tsx +467 -0
  21. package/data/registry/react/components/color-picker/styles.css.ts +169 -0
  22. package/data/registry/react/components/combobox/index.vanilla-extract.tsx +165 -0
  23. package/data/registry/react/components/combobox/styles.css.ts +174 -0
  24. package/data/registry/react/components/context-menu/index.vanilla-extract.tsx +251 -0
  25. package/data/registry/react/components/context-menu/styles.css.ts +167 -0
  26. package/data/registry/react/components/date-picker/index.vanilla-extract.tsx +520 -0
  27. package/data/registry/react/components/date-picker/styles.css.ts +111 -0
  28. package/data/registry/react/components/dialog/index.vanilla-extract.tsx +95 -0
  29. package/data/registry/react/components/dialog/styles.css.ts +140 -0
  30. package/data/registry/react/components/dropdown-menu/index.vanilla-extract.tsx +255 -0
  31. package/data/registry/react/components/dropdown-menu/styles.css.ts +175 -0
  32. package/data/registry/react/components/file-upload/index.vanilla-extract.tsx +487 -0
  33. package/data/registry/react/components/file-upload/styles.css.ts +193 -0
  34. package/data/registry/react/components/form/index.vanilla-extract.tsx +61 -0
  35. package/data/registry/react/components/form/styles.css.ts +56 -0
  36. package/data/registry/react/components/header/index.vanilla-extract.tsx +805 -0
  37. package/data/registry/react/components/header/styles.css.ts +413 -0
  38. package/data/registry/react/components/label/index.vanilla-extract.tsx +52 -0
  39. package/data/registry/react/components/label/styles.css.ts +141 -0
  40. package/data/registry/react/components/markdown-editor/index.vanilla-extract.tsx +119 -0
  41. package/data/registry/react/components/markdown-editor/styles.css.ts +231 -0
  42. package/data/registry/react/components/menubar/index.vanilla-extract.tsx +32 -0
  43. package/data/registry/react/components/menubar/styles.css.ts +53 -0
  44. package/data/registry/react/components/numeric-input/index.vanilla-extract.tsx +148 -0
  45. package/data/registry/react/components/numeric-input/styles.css.ts +65 -0
  46. package/data/registry/react/components/page-toc/index.vanilla-extract.tsx +174 -0
  47. package/data/registry/react/components/page-toc/styles.css.ts +97 -0
  48. package/data/registry/react/components/pagination/index.vanilla-extract.tsx +269 -0
  49. package/data/registry/react/components/pagination/styles.css.ts +113 -0
  50. package/data/registry/react/components/popover/index.vanilla-extract.tsx +113 -0
  51. package/data/registry/react/components/popover/styles.css.ts +78 -0
  52. package/data/registry/react/components/progress/index.vanilla-extract.tsx +54 -0
  53. package/data/registry/react/components/progress/styles.css.ts +53 -0
  54. package/data/registry/react/components/radio/index.vanilla-extract.tsx +65 -0
  55. package/data/registry/react/components/radio/styles.css.ts +79 -0
  56. package/data/registry/react/components/rich-text-editor/index.vanilla-extract.tsx +348 -0
  57. package/data/registry/react/components/rich-text-editor/styles.css.ts +243 -0
  58. package/data/registry/react/components/select/index.vanilla-extract.tsx +234 -0
  59. package/data/registry/react/components/select/styles.css.ts +225 -0
  60. package/data/registry/react/components/separator/index.vanilla-extract.tsx +46 -0
  61. package/data/registry/react/components/separator/styles.css.ts +24 -0
  62. package/data/registry/react/components/sidebar/index.vanilla-extract.tsx +1067 -0
  63. package/data/registry/react/components/sidebar/styles.css.ts +578 -0
  64. package/data/registry/react/components/skeleton/index.vanilla-extract.tsx +22 -0
  65. package/data/registry/react/components/skeleton/styles.css.ts +30 -0
  66. package/data/registry/react/components/slider/index.vanilla-extract.tsx +298 -0
  67. package/data/registry/react/components/slider/styles.css.ts +75 -0
  68. package/data/registry/react/components/spinner/index.vanilla-extract.tsx +38 -0
  69. package/data/registry/react/components/spinner/styles.css.ts +60 -0
  70. package/data/registry/react/components/switch/index.vanilla-extract.tsx +39 -0
  71. package/data/registry/react/components/switch/styles.css.ts +87 -0
  72. package/data/registry/react/components/tabs/index.vanilla-extract.tsx +91 -0
  73. package/data/registry/react/components/tabs/styles.css.ts +145 -0
  74. package/data/registry/react/components/textarea/index.vanilla-extract.tsx +23 -0
  75. package/data/registry/react/components/textarea/styles.css.ts +55 -0
  76. package/data/registry/react/components/toast/index.vanilla-extract.tsx +258 -0
  77. package/data/registry/react/components/toast/styles.css.ts +307 -0
  78. package/data/registry/react/components/toggle/index.vanilla-extract.tsx +131 -0
  79. package/data/registry/react/components/toggle/styles.css.ts +109 -0
  80. package/data/registry/react/components/tooltip/index.vanilla-extract.tsx +83 -0
  81. package/data/registry/react/components/tooltip/styles.css.ts +59 -0
  82. package/data/registry/react/registry.json +853 -36
  83. package/package.json +1 -1
  84. package/src/api.d.ts +4 -3
  85. package/src/constants.js +4 -3
@@ -0,0 +1,191 @@
1
+ import { codeToHtml } from "shiki";
2
+ import { CodePanelCopyButton } from "./copy";
3
+ import { byKey, code, code__header, code__filename, codeCopyFloating, code__copy, codeCopyLabel, code__body, dark } from "./styles.css";
4
+
5
+
6
+ import { cn } from "@SH_UI_UTILS@";
7
+ export interface CodePanelProps
8
+ extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
9
+ /** 하이라이팅할 코드 문자열. children을 제공하지 않을 때 필수. */
10
+ code?: string;
11
+ /**
12
+ * shiki가 지원하는 언어 ID (예: `"tsx"`, `"typescript"`, `"bash"`, `"json"`).
13
+ * 미지원 언어면 plain text로 폴백.
14
+ *
15
+ * @default "text"
16
+ */
17
+ language?: string;
18
+ /**
19
+ * 상단 헤더에 표시할 파일명. 지정하면 헤더가 그려지고 그 안에 복사 버튼이 들어가며,
20
+ * 미지정 시 우상단에 floating 복사 버튼만 표시된다.
21
+ */
22
+ filename?: string;
23
+ /**
24
+ * 좌측 줄 번호 표시 여부.
25
+ * @default true
26
+ */
27
+ showLineNumbers?: boolean;
28
+ /**
29
+ * 복사 버튼 숨기기. 코드 발췌가 클립보드 복사용이 아닐 때 사용.
30
+ * @default false
31
+ */
32
+ hideCopy?: boolean;
33
+ /**
34
+ * compound 모드. 직접 `CodePanelHeader`/`CodePanelFilename`/`CodePanelCopy`/`CodePanelBody`를
35
+ * 조합해 헤더 액션 추가나 복사 버튼 위치 변경 등을 한다. 지정 시 `code`/`language` 등은 무시.
36
+ */
37
+ children?: React.ReactNode;
38
+ }
39
+
40
+ /**
41
+ * 코드 블록 + 복사 버튼 패널. shiki로 SSR에서 하이라이팅.
42
+ *
43
+ * 기본 사용(자식 생략) — `code` prop만 넘기면 기본 레이아웃을 렌더한다.
44
+ * 커스텀 구성 — `CodePanelHeader`, `CodePanelFilename`, `CodePanelCopy`,
45
+ * `CodePanelBody`를 직접 조합하여 헤더 액션 추가·복사 버튼 위치 변경 등이 가능하다.
46
+ */
47
+ export async function CodePanel({
48
+ code,
49
+ language = "text",
50
+ filename,
51
+ showLineNumbers = true,
52
+ hideCopy,
53
+ className,
54
+ children,
55
+ ...rest
56
+ }: CodePanelProps) {
57
+ const classes = cn(code, className);
58
+
59
+ if (children !== undefined) {
60
+ return (
61
+ <div className={classes} {...rest}>
62
+ {children}
63
+ </div>
64
+ );
65
+ }
66
+
67
+ if (code === undefined) {
68
+ throw new Error("CodePanel: `code` prop 또는 children 중 하나가 필요합니다.");
69
+ }
70
+
71
+ const trimmed = code.replace(/\n$/, "");
72
+
73
+ return (
74
+ <div className={classes} {...rest}>
75
+ {filename ? (
76
+ <CodePanelHeader>
77
+ <CodePanelFilename>{filename}</CodePanelFilename>
78
+ {!hideCopy && <CodePanelCopy code={trimmed} />}
79
+ </CodePanelHeader>
80
+ ) : (
81
+ !hideCopy && (
82
+ <div className={codeCopyFloating}>
83
+ <CodePanelCopy code={trimmed} />
84
+ </div>
85
+ )
86
+ )}
87
+ <CodePanelBody
88
+ code={trimmed}
89
+ language={language}
90
+ showLineNumbers={showLineNumbers}
91
+ />
92
+ </div>
93
+ );
94
+ }
95
+
96
+ /* ───────── CodePanelHeader ───────── */
97
+
98
+ /** 파일명·복사 버튼 등을 담는 코드 블록 상단 바. CodePanel 자식으로 사용. */
99
+ export function CodePanelHeader({
100
+ className,
101
+ children,
102
+ ...props
103
+ }: React.HTMLAttributes<HTMLDivElement>) {
104
+ return (
105
+ <div className={cn(code__header, className)} {...props}>
106
+ {children}
107
+ </div>
108
+ );
109
+ }
110
+
111
+ /* ───────── CodePanelFilename ───────── */
112
+
113
+ /** CodePanelHeader 안에 표시되는 파일명 라벨. */
114
+ export function CodePanelFilename({
115
+ className,
116
+ children,
117
+ ...props
118
+ }: React.HTMLAttributes<HTMLSpanElement>) {
119
+ return (
120
+ <span className={cn(code__filename, className)} {...props}>
121
+ {children}
122
+ </span>
123
+ );
124
+ }
125
+
126
+ /* ───────── CodePanelCopy ─────────
127
+ * 클립보드 복사 버튼. 내부적으로 client 컴포넌트를 사용한다.
128
+ */
129
+
130
+ export interface CodePanelCopyProps {
131
+ /** 클립보드에 복사할 코드 문자열. 부모(주로 CodePanel)가 명시적으로 전달한다. */
132
+ code: string;
133
+ }
134
+
135
+ /** 클립보드 복사 버튼. 부모가 복사할 코드 문자열을 명시적으로 전달한다. */
136
+ export function CodePanelCopy({ code }: CodePanelCopyProps) {
137
+ return <CodePanelCopyButton code={code} />;
138
+ }
139
+
140
+ /* ───────── CodePanelBody ─────────
141
+ * shiki로 코드를 하이라이팅하여 렌더하는 async 컴포넌트.
142
+ */
143
+
144
+ export interface CodePanelBodyProps
145
+ extends Omit<
146
+ React.HTMLAttributes<HTMLDivElement>,
147
+ "children" | "dangerouslySetInnerHTML"
148
+ > {
149
+ /** 하이라이팅할 코드 문자열. */
150
+ code: string;
151
+ /**
152
+ * shiki 언어 ID.
153
+ * @default "text"
154
+ */
155
+ language?: string;
156
+ /**
157
+ * 좌측 줄 번호 표시 여부.
158
+ * @default true
159
+ */
160
+ showLineNumbers?: boolean;
161
+ }
162
+
163
+ /**
164
+ * shiki로 코드를 SSR 하이라이팅하여 렌더하는 async 컴포넌트.
165
+ * 라이트/다크 테마는 `github-light`/`github-dark`를 사용하며, 부모 테마 클래스에 따라 자동 전환된다.
166
+ */
167
+ export async function CodePanelBody({
168
+ code,
169
+ language = "text",
170
+ showLineNumbers = true,
171
+ className,
172
+ ...rest
173
+ }: CodePanelBodyProps) {
174
+ const trimmed = code.replace(/\n$/, "");
175
+ const html = await codeToHtml(trimmed, {
176
+ lang: language,
177
+ themes: { light: "github-light", dark: "github-dark" },
178
+ defaultColor: false,
179
+ });
180
+
181
+ return (
182
+ <div
183
+ className={cn(code__body, className)}
184
+ data-line-numbers={showLineNumbers || undefined}
185
+ dangerouslySetInnerHTML={{ __html: html }}
186
+ {...rest}
187
+ />
188
+ );
189
+ }
190
+
191
+ export { CodePanelCopyButton };
@@ -0,0 +1,151 @@
1
+ import { style } from "@vanilla-extract/css";
2
+
3
+ export const code = style({
4
+ position: "relative",
5
+ border: "1px solid var(--border)",
6
+ borderRadius: "var(--radius)",
7
+ background: "var(--background-subtle)",
8
+ overflow: "hidden",
9
+ fontSize: "0.8125rem",
10
+ lineHeight: 1.6,
11
+ margin: "var(--space-4) 0",
12
+ selectors: {
13
+ [`&:hover ${codeCopyFloating}`]: {
14
+ opacity: 1,
15
+ },
16
+ [`&:focus-within ${codeCopyFloating}`]: {
17
+ opacity: 1,
18
+ },
19
+ },
20
+ "@media": {
21
+ "(max-width: 640px)": {
22
+ fontSize: "var(--text-xs)",
23
+ },
24
+ },
25
+ });
26
+
27
+ export const code__header = style({
28
+ display: "flex",
29
+ alignItems: "center",
30
+ justifyContent: "space-between",
31
+ gap: "var(--space-2)",
32
+ padding: "var(--space-2) var(--space-3) var(--space-2) var(--space-4)",
33
+ borderBottom: "1px solid var(--border)",
34
+ background: "var(--background-muted)",
35
+ fontSize: "var(--text-xs)",
36
+ color: "var(--foreground-muted)",
37
+ });
38
+
39
+ export const code__filename = style({
40
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
41
+ color: "var(--foreground)",
42
+ });
43
+
44
+ export const codeCopyFloating = style({
45
+ position: "absolute",
46
+ top: "var(--space-2)",
47
+ right: "var(--space-2)",
48
+ zIndex: 1,
49
+ opacity: 0,
50
+ transition: "opacity var(--duration-fast)",
51
+ });
52
+
53
+ export const code__copy = style({
54
+ display: "inline-flex",
55
+ alignItems: "center",
56
+ gap: "0.375rem",
57
+ padding: "var(--space-1) var(--space-2)",
58
+ background: "var(--background)",
59
+ color: "var(--foreground-muted)",
60
+ border: "1px solid var(--border)",
61
+ borderRadius: "calc(var(--radius) - 2px)",
62
+ fontSize: "var(--text-xs)",
63
+ lineHeight: 1,
64
+ cursor: "pointer",
65
+ transition: "color var(--duration-fast), border-color var(--duration-fast), background-color var(--duration-fast)",
66
+ WebkitTapHighlightColor: "transparent",
67
+ selectors: {
68
+ "&:hover": {
69
+ color: "var(--foreground)",
70
+ borderColor: "var(--border-strong)",
71
+ },
72
+ "&:focus-visible": {
73
+ outline: "var(--border-width-strong) solid var(--foreground)",
74
+ outlineOffset: "2px",
75
+ },
76
+ },
77
+ });
78
+
79
+ export const codeCopyLabel = style({
80
+ fontSize: "var(--text-xs)",
81
+ });
82
+
83
+ export const code__body = style({
84
+ overflowX: "auto",
85
+ selectors: {
86
+ "& pre": {
87
+ margin: 0,
88
+ padding: "var(--space-3) var(--space-4)",
89
+ background: "transparent !important",
90
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
91
+ fontSize: "inherit",
92
+ lineHeight: "inherit",
93
+ border: "none",
94
+ borderRadius: 0,
95
+ },
96
+ "& code": {
97
+ background: "transparent",
98
+ padding: 0,
99
+ fontSize: "inherit",
100
+ display: "block",
101
+ },
102
+ "& .shiki": {
103
+ color: "var(--shiki-light) !important",
104
+ backgroundColor: "transparent !important",
105
+ },
106
+ "& .shiki span": {
107
+ color: "var(--shiki-light) !important",
108
+ backgroundColor: "transparent !important",
109
+ },
110
+ "&[data-line-numbers] pre code": {
111
+ counterReset: "step",
112
+ counterIncrement: "step 0",
113
+ },
114
+ "&[data-line-numbers] pre code .line::before": {
115
+ content: "counter(step)",
116
+ counterIncrement: "step",
117
+ display: "inline-block",
118
+ width: "1.75rem",
119
+ marginRight: "var(--space-4)",
120
+ textAlign: "right",
121
+ color: "var(--foreground-muted)",
122
+ opacity: 0.7,
123
+ userSelect: "none",
124
+ },
125
+ },
126
+ });
127
+
128
+ export const dark = style({
129
+ selectors: {
130
+ [`& ${code__body} .shiki`]: {
131
+ color: "var(--shiki-dark) !important",
132
+ backgroundColor: "transparent !important",
133
+ },
134
+ [`& ${code__body} .shiki span`]: {
135
+ color: "var(--shiki-dark) !important",
136
+ backgroundColor: "transparent !important",
137
+ },
138
+ },
139
+ });
140
+
141
+ /** 동적 키로 클래스 참조용 — `byKey[\`badge--${variant}\`]` 같은 패턴 지원. */
142
+ export const byKey: Record<string, string> = {
143
+ "code": code,
144
+ "code__header": code__header,
145
+ "code__filename": code__filename,
146
+ "code__copy-floating": codeCopyFloating,
147
+ "code__copy": code__copy,
148
+ "code__copy-label": codeCopyLabel,
149
+ "code__body": code__body,
150
+ "dark": dark,
151
+ };