sh-ui-cli 0.45.2 → 0.46.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 +26 -0
- package/data/registry/react/components/accordion/index.tailwind.tsx +5 -7
- package/data/registry/react/components/accordion/index.tsx +5 -7
- package/data/registry/react/components/avatar/index.tailwind.tsx +4 -6
- package/data/registry/react/components/avatar/index.tsx +4 -6
- package/data/registry/react/components/badge/index.tailwind.tsx +2 -4
- package/data/registry/react/components/badge/index.tsx +2 -4
- package/data/registry/react/components/breadcrumb/index.tailwind.tsx +8 -10
- package/data/registry/react/components/breadcrumb/index.tsx +8 -10
- package/data/registry/react/components/button/index.module.tsx +45 -0
- package/data/registry/react/components/button/index.tailwind.tsx +2 -1
- package/data/registry/react/components/button/index.tsx +3 -4
- package/data/registry/react/components/button/styles.module.css +92 -0
- package/data/registry/react/components/calendar/index.tailwind.tsx +10 -12
- package/data/registry/react/components/calendar/index.tsx +9 -11
- package/data/registry/react/components/card/index.module.tsx +63 -0
- package/data/registry/react/components/card/index.tailwind.tsx +8 -10
- package/data/registry/react/components/card/index.tsx +8 -10
- package/data/registry/react/components/card/styles.module.css +73 -0
- package/data/registry/react/components/carousel/index.tailwind.tsx +7 -9
- package/data/registry/react/components/carousel/index.tsx +7 -9
- package/data/registry/react/components/checkbox/index.tailwind.tsx +3 -5
- package/data/registry/react/components/checkbox/index.tsx +3 -5
- package/data/registry/react/components/code-editor/index.tailwind.tsx +2 -4
- package/data/registry/react/components/code-editor/index.tsx +2 -4
- package/data/registry/react/components/code-panel/index.tailwind.tsx +5 -7
- package/data/registry/react/components/code-panel/index.tsx +5 -7
- package/data/registry/react/components/color-picker/index.tailwind.tsx +7 -6
- package/data/registry/react/components/color-picker/index.tsx +7 -6
- package/data/registry/react/components/combobox/index.tailwind.tsx +8 -10
- package/data/registry/react/components/combobox/index.tsx +8 -10
- package/data/registry/react/components/context-menu/index.tailwind.tsx +10 -12
- package/data/registry/react/components/context-menu/index.tsx +10 -12
- package/data/registry/react/components/date-picker/index.tailwind.tsx +7 -9
- package/data/registry/react/components/date-picker/index.tsx +7 -9
- package/data/registry/react/components/dialog/index.tailwind.tsx +6 -8
- package/data/registry/react/components/dialog/index.tsx +6 -8
- package/data/registry/react/components/dropdown-menu/index.tailwind.tsx +10 -12
- package/data/registry/react/components/dropdown-menu/index.tsx +10 -12
- package/data/registry/react/components/file-upload/index.tailwind.tsx +6 -8
- package/data/registry/react/components/file-upload/index.tsx +6 -8
- package/data/registry/react/components/form/field.tailwind.tsx +2 -1
- package/data/registry/react/components/form/field.tsx +2 -3
- package/data/registry/react/components/header/index.tailwind.tsx +17 -19
- package/data/registry/react/components/header/index.tsx +17 -19
- package/data/registry/react/components/input/index.module.tsx +486 -0
- package/data/registry/react/components/input/index.tailwind.tsx +4 -6
- package/data/registry/react/components/input/index.tsx +4 -6
- package/data/registry/react/components/input/styles.module.css +200 -0
- package/data/registry/react/components/label/index.tailwind.tsx +6 -8
- package/data/registry/react/components/label/index.tsx +6 -8
- package/data/registry/react/components/markdown-editor/index.tailwind.tsx +2 -4
- package/data/registry/react/components/markdown-editor/index.tsx +2 -4
- package/data/registry/react/components/menubar/index.tailwind.tsx +2 -4
- package/data/registry/react/components/menubar/index.tsx +2 -4
- package/data/registry/react/components/numeric-input/index.tailwind.tsx +2 -4
- package/data/registry/react/components/numeric-input/index.tsx +2 -4
- package/data/registry/react/components/page-toc/index.tailwind.tsx +3 -2
- package/data/registry/react/components/page-toc/index.tsx +2 -3
- package/data/registry/react/components/pagination/index.tailwind.tsx +8 -10
- package/data/registry/react/components/pagination/index.tsx +8 -10
- package/data/registry/react/components/popover/index.tailwind.tsx +4 -6
- package/data/registry/react/components/popover/index.tsx +4 -6
- package/data/registry/react/components/progress/index.tailwind.tsx +3 -5
- package/data/registry/react/components/progress/index.tsx +2 -4
- package/data/registry/react/components/radio/index.tailwind.tsx +3 -5
- package/data/registry/react/components/radio/index.tsx +3 -5
- package/data/registry/react/components/rich-text-editor/index.tailwind.tsx +3 -5
- package/data/registry/react/components/rich-text-editor/index.tsx +3 -5
- package/data/registry/react/components/select/index.tailwind.tsx +8 -10
- package/data/registry/react/components/select/index.tsx +8 -10
- package/data/registry/react/components/separator/index.tailwind.tsx +2 -4
- package/data/registry/react/components/separator/index.tsx +2 -4
- package/data/registry/react/components/sidebar/index.tailwind.tsx +32 -43
- package/data/registry/react/components/sidebar/index.tsx +29 -46
- package/data/registry/react/components/skeleton/index.tailwind.tsx +2 -4
- package/data/registry/react/components/skeleton/index.tsx +2 -4
- package/data/registry/react/components/slider/index.tailwind.tsx +5 -7
- package/data/registry/react/components/slider/index.tsx +5 -7
- package/data/registry/react/components/spinner/index.tailwind.tsx +3 -5
- package/data/registry/react/components/spinner/index.tsx +2 -4
- package/data/registry/react/components/switch/index.tailwind.tsx +3 -5
- package/data/registry/react/components/switch/index.tsx +2 -4
- package/data/registry/react/components/tabs/index.tailwind.tsx +6 -8
- package/data/registry/react/components/tabs/index.tsx +6 -8
- package/data/registry/react/components/textarea/index.tailwind.tsx +2 -4
- package/data/registry/react/components/textarea/index.tsx +2 -4
- package/data/registry/react/components/toggle/index.tailwind.tsx +4 -6
- package/data/registry/react/components/toggle/index.tsx +4 -6
- package/data/registry/react/components/tooltip/index.tailwind.tsx +2 -4
- package/data/registry/react/components/tooltip/index.tsx +2 -4
- package/data/registry/react/lib/cn.tailwind.ts +17 -0
- package/data/registry/react/peer-versions.json +3 -1
- package/data/registry/react/registry.json +202 -43
- package/data/tokens/build.mjs +4 -0
- package/package.json +1 -1
- package/src/add.mjs +37 -13
- package/templates/ui-app-template/sh-ui.config.json +5 -0
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import "./styles.css";
|
|
3
3
|
|
|
4
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
5
|
-
return args.filter(Boolean).join(" ");
|
|
6
|
-
}
|
|
7
4
|
|
|
5
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
8
6
|
/* ───────── Pagination (nav) ─────────
|
|
9
7
|
* 시맨틱: <nav aria-label="Pagination"><ul>...</ul></nav>.
|
|
10
8
|
* 현재 페이지 링크에 aria-current="page"를 부여해 스크린리더가 위치를 읽게 한다.
|
|
@@ -22,7 +20,7 @@ export const Pagination = React.forwardRef<
|
|
|
22
20
|
<nav
|
|
23
21
|
ref={ref}
|
|
24
22
|
aria-label="Pagination"
|
|
25
|
-
className={
|
|
23
|
+
className={cn("sh-ui-pagination", className)}
|
|
26
24
|
{...props}
|
|
27
25
|
/>
|
|
28
26
|
);
|
|
@@ -38,7 +36,7 @@ export const PaginationContent = React.forwardRef<
|
|
|
38
36
|
return (
|
|
39
37
|
<ul
|
|
40
38
|
ref={ref}
|
|
41
|
-
className={
|
|
39
|
+
className={cn("sh-ui-pagination__content", className)}
|
|
42
40
|
{...props}
|
|
43
41
|
/>
|
|
44
42
|
);
|
|
@@ -54,7 +52,7 @@ export const PaginationItem = React.forwardRef<
|
|
|
54
52
|
return (
|
|
55
53
|
<li
|
|
56
54
|
ref={ref}
|
|
57
|
-
className={
|
|
55
|
+
className={cn("sh-ui-pagination__item", className)}
|
|
58
56
|
{...props}
|
|
59
57
|
/>
|
|
60
58
|
);
|
|
@@ -98,7 +96,7 @@ export const PaginationLink = React.forwardRef<
|
|
|
98
96
|
aria-current={isActive ? "page" : undefined}
|
|
99
97
|
data-active={isActive ? "" : undefined}
|
|
100
98
|
data-size={size}
|
|
101
|
-
className={
|
|
99
|
+
className={cn("sh-ui-pagination__link", className)}
|
|
102
100
|
{...props}
|
|
103
101
|
/>
|
|
104
102
|
);
|
|
@@ -117,7 +115,7 @@ export const PaginationPrevious = React.forwardRef<
|
|
|
117
115
|
<PaginationLink
|
|
118
116
|
ref={ref}
|
|
119
117
|
aria-label="이전 페이지"
|
|
120
|
-
className={
|
|
118
|
+
className={cn("sh-ui-pagination__nav", className)}
|
|
121
119
|
{...props}
|
|
122
120
|
>
|
|
123
121
|
<ChevronLeftIcon />
|
|
@@ -135,7 +133,7 @@ export const PaginationNext = React.forwardRef<
|
|
|
135
133
|
<PaginationLink
|
|
136
134
|
ref={ref}
|
|
137
135
|
aria-label="다음 페이지"
|
|
138
|
-
className={
|
|
136
|
+
className={cn("sh-ui-pagination__nav", className)}
|
|
139
137
|
{...props}
|
|
140
138
|
>
|
|
141
139
|
{children ?? <span>다음</span>}
|
|
@@ -156,7 +154,7 @@ export const PaginationEllipsis = React.forwardRef<
|
|
|
156
154
|
ref={ref}
|
|
157
155
|
role="presentation"
|
|
158
156
|
aria-hidden="true"
|
|
159
|
-
className={
|
|
157
|
+
className={cn("sh-ui-pagination__ellipsis", className)}
|
|
160
158
|
{...props}
|
|
161
159
|
>
|
|
162
160
|
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden>
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
3
3
|
|
|
4
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
4
5
|
type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
|
|
5
6
|
|
|
6
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
7
|
-
return args.filter(Boolean).join(" ");
|
|
8
|
-
}
|
|
9
7
|
|
|
10
8
|
export const Popover = BasePopover.Root;
|
|
11
9
|
export const PopoverTrigger = BasePopover.Trigger;
|
|
@@ -35,7 +33,7 @@ export const PopoverContent = React.forwardRef<HTMLDivElement, PopoverContentPro
|
|
|
35
33
|
>
|
|
36
34
|
<BasePopover.Popup
|
|
37
35
|
ref={ref}
|
|
38
|
-
className={
|
|
36
|
+
className={cn(
|
|
39
37
|
"min-w-48 p-[var(--space-2)] bg-background text-foreground border border-border rounded-[var(--radius)] shadow-[0_8px_24px_rgba(0,0,0,0.12)] outline-none text-[length:var(--text-sm)] leading-snug origin-[var(--transform-origin)] transition-[opacity,transform] duration-[140ms] ease-out motion-reduce:transition-none data-[starting-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:scale-95 motion-reduce:data-[starting-style]:scale-100 motion-reduce:data-[ending-style]:scale-100 focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2",
|
|
40
38
|
className,
|
|
41
39
|
)}
|
|
@@ -57,7 +55,7 @@ export const PopoverTitle = React.forwardRef<
|
|
|
57
55
|
return (
|
|
58
56
|
<BasePopover.Title
|
|
59
57
|
ref={ref}
|
|
60
|
-
className={
|
|
58
|
+
className={cn("m-0 mb-[var(--space-1)] font-semibold text-[0.9375rem]", className)}
|
|
61
59
|
{...props}
|
|
62
60
|
/>
|
|
63
61
|
);
|
|
@@ -70,7 +68,7 @@ export const PopoverDescription = React.forwardRef<
|
|
|
70
68
|
return (
|
|
71
69
|
<BasePopover.Description
|
|
72
70
|
ref={ref}
|
|
73
|
-
className={
|
|
71
|
+
className={cn("m-0 text-foreground-muted text-[0.8125rem]", className)}
|
|
74
72
|
{...props}
|
|
75
73
|
/>
|
|
76
74
|
);
|
|
@@ -2,11 +2,9 @@ import * as React from "react";
|
|
|
2
2
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
3
3
|
import "./styles.css";
|
|
4
4
|
|
|
5
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
5
6
|
type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
|
|
6
7
|
|
|
7
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
8
|
-
return args.filter(Boolean).join(" ");
|
|
9
|
-
}
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* 트리거 요소에 떠다니는 가벼운 패널을 띄우는 비모달 컨테이너. 포커스를 가두지 않으므로
|
|
@@ -72,7 +70,7 @@ export const PopoverContent = React.forwardRef<HTMLDivElement, PopoverContentPro
|
|
|
72
70
|
>
|
|
73
71
|
<BasePopover.Popup
|
|
74
72
|
ref={ref}
|
|
75
|
-
className={
|
|
73
|
+
className={cn("sh-ui-popover__content", className)}
|
|
76
74
|
{...props}
|
|
77
75
|
>
|
|
78
76
|
{showArrow && (
|
|
@@ -94,7 +92,7 @@ export const PopoverTitle = React.forwardRef<
|
|
|
94
92
|
return (
|
|
95
93
|
<BasePopover.Title
|
|
96
94
|
ref={ref}
|
|
97
|
-
className={
|
|
95
|
+
className={cn("sh-ui-popover__title", className)}
|
|
98
96
|
{...props}
|
|
99
97
|
/>
|
|
100
98
|
);
|
|
@@ -108,7 +106,7 @@ export const PopoverDescription = React.forwardRef<
|
|
|
108
106
|
return (
|
|
109
107
|
<BasePopover.Description
|
|
110
108
|
ref={ref}
|
|
111
|
-
className={
|
|
109
|
+
className={cn("sh-ui-popover__description", className)}
|
|
112
110
|
{...props}
|
|
113
111
|
/>
|
|
114
112
|
);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
4
|
-
return args.filter(Boolean).join(" ");
|
|
5
|
-
}
|
|
6
3
|
|
|
4
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
7
5
|
function clamp(n: number, min: number, max: number) {
|
|
8
6
|
return Math.min(max, Math.max(min, n));
|
|
9
7
|
}
|
|
@@ -32,14 +30,14 @@ export const Progress = React.forwardRef<HTMLDivElement, ProgressProps>(
|
|
|
32
30
|
aria-valuemax={isDeterminate ? max : undefined}
|
|
33
31
|
aria-valuenow={isDeterminate ? value : undefined}
|
|
34
32
|
data-state={isDeterminate ? "determinate" : "indeterminate"}
|
|
35
|
-
className={
|
|
33
|
+
className={cn(
|
|
36
34
|
"relative w-full h-2 overflow-hidden bg-background-muted rounded-full",
|
|
37
35
|
className,
|
|
38
36
|
)}
|
|
39
37
|
{...props}
|
|
40
38
|
>
|
|
41
39
|
<div
|
|
42
|
-
className={
|
|
40
|
+
className={cn(
|
|
43
41
|
"h-full bg-primary rounded-full transition-[width] duration-[var(--duration-base)] ease-out motion-reduce:transition-none",
|
|
44
42
|
!isDeterminate &&
|
|
45
43
|
"w-2/5 animate-[sh-ui-progress-slide_1.2s_ease-in-out_infinite] motion-reduce:animate-none motion-reduce:translate-x-3/4",
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import "./styles.css";
|
|
3
3
|
|
|
4
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
5
|
-
return args.filter(Boolean).join(" ");
|
|
6
|
-
}
|
|
7
4
|
|
|
5
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
8
6
|
function clamp(n: number, min: number, max: number) {
|
|
9
7
|
return Math.min(max, Math.max(min, n));
|
|
10
8
|
}
|
|
@@ -42,7 +40,7 @@ export const Progress = React.forwardRef<HTMLDivElement, ProgressProps>(
|
|
|
42
40
|
aria-valuemax={isDeterminate ? max : undefined}
|
|
43
41
|
aria-valuenow={isDeterminate ? value : undefined}
|
|
44
42
|
data-state={isDeterminate ? "determinate" : "indeterminate"}
|
|
45
|
-
className={
|
|
43
|
+
className={cn("sh-ui-progress", className)}
|
|
46
44
|
{...props}
|
|
47
45
|
>
|
|
48
46
|
<div
|
|
@@ -2,10 +2,8 @@ import * as React from "react";
|
|
|
2
2
|
import { Radio as BaseRadio } from "@base-ui/react/radio";
|
|
3
3
|
import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
|
|
4
4
|
|
|
5
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
6
|
-
return args.filter(Boolean).join(" ");
|
|
7
|
-
}
|
|
8
5
|
|
|
6
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
9
7
|
export type RadioProps = Omit<
|
|
10
8
|
React.ComponentPropsWithoutRef<typeof BaseRadio.Root>,
|
|
11
9
|
"className"
|
|
@@ -17,7 +15,7 @@ export const Radio = React.forwardRef<HTMLElement, RadioProps>(
|
|
|
17
15
|
({ className, ...props }, ref) => (
|
|
18
16
|
<BaseRadio.Root
|
|
19
17
|
ref={ref}
|
|
20
|
-
className={
|
|
18
|
+
className={cn(
|
|
21
19
|
"inline-flex items-center justify-center w-[1.125rem] h-[1.125rem] border border-border-strong rounded-full bg-background cursor-pointer shrink-0 transition-[border-color] duration-[var(--duration-fast)] hover:not-data-[disabled]:border-foreground focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 data-[checked]:border-primary data-[disabled]:opacity-[var(--opacity-disabled)] data-[disabled]:cursor-not-allowed motion-reduce:transition-none [@media(hover:none)_and_(pointer:coarse)]:w-5 [@media(hover:none)_and_(pointer:coarse)]:h-5",
|
|
22
20
|
className,
|
|
23
21
|
)}
|
|
@@ -41,7 +39,7 @@ export const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(
|
|
|
41
39
|
({ className, orientation = "vertical", ...props }, ref) => (
|
|
42
40
|
<BaseRadioGroup
|
|
43
41
|
ref={ref}
|
|
44
|
-
className={
|
|
42
|
+
className={cn(
|
|
45
43
|
"flex gap-2.5",
|
|
46
44
|
orientation === "vertical" ? "flex-col" : "flex-row flex-wrap",
|
|
47
45
|
className,
|
|
@@ -3,10 +3,8 @@ import { Radio as BaseRadio } from "@base-ui/react/radio";
|
|
|
3
3
|
import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
|
|
4
4
|
import "./styles.css";
|
|
5
5
|
|
|
6
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
7
|
-
return args.filter(Boolean).join(" ");
|
|
8
|
-
}
|
|
9
6
|
|
|
7
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
10
8
|
/* ───────────── Radio ───────────── */
|
|
11
9
|
|
|
12
10
|
export type RadioProps = Omit<
|
|
@@ -24,7 +22,7 @@ export const Radio = React.forwardRef<HTMLElement, RadioProps>(
|
|
|
24
22
|
({ className, ...props }, ref) => (
|
|
25
23
|
<BaseRadio.Root
|
|
26
24
|
ref={ref}
|
|
27
|
-
className={
|
|
25
|
+
className={cn("sh-ui-radio", className)}
|
|
28
26
|
{...props}
|
|
29
27
|
>
|
|
30
28
|
<BaseRadio.Indicator className="sh-ui-radio__indicator" />
|
|
@@ -58,7 +56,7 @@ export const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(
|
|
|
58
56
|
({ className, orientation = "vertical", ...props }, ref) => (
|
|
59
57
|
<BaseRadioGroup
|
|
60
58
|
ref={ref}
|
|
61
|
-
className={
|
|
59
|
+
className={cn("sh-ui-radio-group", className)}
|
|
62
60
|
data-orientation={orientation}
|
|
63
61
|
{...props}
|
|
64
62
|
/>
|
|
@@ -5,6 +5,7 @@ import { useEditor, EditorContent, type Editor } from "@tiptap/react";
|
|
|
5
5
|
import StarterKit from "@tiptap/starter-kit";
|
|
6
6
|
import Placeholder from "@tiptap/extension-placeholder";
|
|
7
7
|
import Link from "@tiptap/extension-link";
|
|
8
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
8
9
|
import {
|
|
9
10
|
BoldIcon, ItalicIcon, StrikethroughIcon,
|
|
10
11
|
Heading1Icon, Heading2Icon, Heading3Icon,
|
|
@@ -26,9 +27,6 @@ export interface RichTextEditorProps {
|
|
|
26
27
|
"aria-label"?: string;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
30
|
-
return args.filter(Boolean).join(" ");
|
|
31
|
-
}
|
|
32
30
|
|
|
33
31
|
export function RichTextEditor({
|
|
34
32
|
value: valueProp, defaultValue, onChange, placeholder, readOnly = false, hideToolbar = false,
|
|
@@ -68,7 +66,7 @@ export function RichTextEditor({
|
|
|
68
66
|
|
|
69
67
|
return (
|
|
70
68
|
<div
|
|
71
|
-
className={
|
|
69
|
+
className={cn(
|
|
72
70
|
"sh-ui-rte flex flex-col border border-border rounded-[var(--radius)] bg-background overflow-hidden transition-[border-color] duration-[var(--duration-fast)] focus-within:border-foreground focus-within:outline-[length:var(--border-width-strong)] focus-within:outline-foreground focus-within:outline-offset-2 data-[readonly]:bg-background-subtle motion-reduce:transition-none",
|
|
73
71
|
className,
|
|
74
72
|
)}
|
|
@@ -158,7 +156,7 @@ function ToolbarButton({ editor, label, icon, isActive, canRun, run, disabled }:
|
|
|
158
156
|
return (
|
|
159
157
|
<button
|
|
160
158
|
type="button"
|
|
161
|
-
className={
|
|
159
|
+
className={cn(
|
|
162
160
|
"inline-flex items-center justify-center w-7 h-7 p-0 bg-transparent text-foreground-muted border border-transparent rounded-[calc(var(--radius)-2px)] cursor-pointer transition-[color,background-color,border-color] duration-[var(--duration-fast)] hover:not-disabled:text-foreground hover:not-disabled:bg-background hover:not-disabled:border-border focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-1 disabled:opacity-50 disabled:cursor-not-allowed motion-reduce:transition-none",
|
|
163
161
|
isActive && "text-foreground bg-background border-border-strong",
|
|
164
162
|
)}
|
|
@@ -5,6 +5,7 @@ import { useEditor, EditorContent, type Editor } from "@tiptap/react";
|
|
|
5
5
|
import StarterKit from "@tiptap/starter-kit";
|
|
6
6
|
import Placeholder from "@tiptap/extension-placeholder";
|
|
7
7
|
import Link from "@tiptap/extension-link";
|
|
8
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
8
9
|
import {
|
|
9
10
|
BoldIcon,
|
|
10
11
|
ItalicIcon,
|
|
@@ -51,9 +52,6 @@ export interface RichTextEditorProps {
|
|
|
51
52
|
"aria-label"?: string;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
55
|
-
return args.filter(Boolean).join(" ");
|
|
56
|
-
}
|
|
57
55
|
|
|
58
56
|
/**
|
|
59
57
|
* Tiptap 기반 리치 텍스트 에디터.
|
|
@@ -117,7 +115,7 @@ export function RichTextEditor({
|
|
|
117
115
|
|
|
118
116
|
return (
|
|
119
117
|
<div
|
|
120
|
-
className={
|
|
118
|
+
className={cn("sh-ui-rte", className)}
|
|
121
119
|
data-readonly={readOnly || undefined}
|
|
122
120
|
style={
|
|
123
121
|
{
|
|
@@ -330,7 +328,7 @@ function ToolbarButton({
|
|
|
330
328
|
return (
|
|
331
329
|
<button
|
|
332
330
|
type="button"
|
|
333
|
-
className={
|
|
331
|
+
className={cn("sh-ui-rte__btn", isActive && "is-active")}
|
|
334
332
|
aria-label={label}
|
|
335
333
|
aria-pressed={isActive || undefined}
|
|
336
334
|
title={label}
|
|
@@ -3,17 +3,15 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Select as BaseSelect } from "@base-ui/react/select";
|
|
5
5
|
|
|
6
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
7
|
-
return args.filter(Boolean).join(" ");
|
|
8
|
-
}
|
|
9
6
|
|
|
7
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
10
8
|
export const Select = BaseSelect.Root;
|
|
11
9
|
|
|
12
10
|
export function SelectValue({ placeholder, className, ...props }: { placeholder?: string; className?: string } & Omit<
|
|
13
11
|
React.ComponentPropsWithoutRef<typeof BaseSelect.Value>, "children"
|
|
14
12
|
>) {
|
|
15
13
|
return (
|
|
16
|
-
<BaseSelect.Value className={
|
|
14
|
+
<BaseSelect.Value className={cn("flex-1 text-left overflow-hidden text-ellipsis whitespace-nowrap", className)} {...props}>
|
|
17
15
|
{(value) =>
|
|
18
16
|
value !== null && value !== undefined && value !== "" ? (
|
|
19
17
|
(value as React.ReactNode)
|
|
@@ -31,7 +29,7 @@ export const SelectTrigger = React.forwardRef<
|
|
|
31
29
|
>(({ className, children, ...props }, ref) => (
|
|
32
30
|
<BaseSelect.Trigger
|
|
33
31
|
ref={ref}
|
|
34
|
-
className={
|
|
32
|
+
className={cn(
|
|
35
33
|
"inline-flex items-center justify-between gap-[var(--space-2)] min-w-40 h-[var(--control-md)] px-[var(--space-3)] bg-background text-foreground border border-border rounded-[var(--radius)] text-[length:var(--text-sm)] leading-none cursor-pointer transition-[border-color,background-color] duration-[var(--duration-fast)] select-none hover:not-disabled:border-border-strong focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 data-[popup-open]:border-border-strong disabled:opacity-[var(--opacity-disabled)] disabled:pointer-events-none",
|
|
36
34
|
className,
|
|
37
35
|
)}
|
|
@@ -61,7 +59,7 @@ export const SelectContent = React.forwardRef<
|
|
|
61
59
|
<BaseSelect.Positioner className="outline-none z-[var(--z-dropdown)]" sideOffset={4} align="start">
|
|
62
60
|
<BaseSelect.Popup
|
|
63
61
|
ref={ref}
|
|
64
|
-
className={
|
|
62
|
+
className={cn(
|
|
65
63
|
"min-w-[var(--anchor-width,10rem)] max-h-[min(24rem,var(--available-height,24rem))] overflow-y-auto p-[var(--space-1)] bg-background text-foreground border border-border rounded-[var(--radius)] shadow-[0_4px_6px_-1px_rgba(0,0,0,0.08),0_2px_4px_-2px_rgba(0,0,0,0.05)] text-[length:var(--text-sm)] origin-[var(--transform-origin)] animate-[sh-ui-select-in_140ms_ease-out] data-[ending-style]:animate-[sh-ui-select-out_100ms_ease-in_forwards] motion-reduce:animate-none motion-reduce:data-[ending-style]:animate-none",
|
|
66
64
|
className,
|
|
67
65
|
)}
|
|
@@ -82,7 +80,7 @@ export const SelectLabel = React.forwardRef<
|
|
|
82
80
|
>(({ className, ...props }, ref) => (
|
|
83
81
|
<BaseSelect.GroupLabel
|
|
84
82
|
ref={ref}
|
|
85
|
-
className={
|
|
83
|
+
className={cn(
|
|
86
84
|
"py-[var(--space-2)] px-[var(--space-2)] pb-[var(--space-1)] text-[length:var(--text-xs)] font-semibold text-foreground-muted uppercase tracking-[0.04em]",
|
|
87
85
|
className,
|
|
88
86
|
)}
|
|
@@ -97,7 +95,7 @@ export const SelectItem = React.forwardRef<
|
|
|
97
95
|
>(({ className, children, ...props }, ref) => (
|
|
98
96
|
<BaseSelect.Item
|
|
99
97
|
ref={ref}
|
|
100
|
-
className={
|
|
98
|
+
className={cn(
|
|
101
99
|
"flex items-center gap-[var(--space-2)] py-2 px-3 rounded-[calc(var(--radius)-2px)] cursor-pointer outline-none select-none transition-colors duration-[80ms] data-[highlighted]:bg-background-muted hover:bg-background-muted data-[disabled]:opacity-[var(--opacity-disabled)] data-[disabled]:pointer-events-none",
|
|
102
100
|
className,
|
|
103
101
|
)}
|
|
@@ -122,7 +120,7 @@ export const SelectSeparator = React.forwardRef<
|
|
|
122
120
|
>(({ className, ...props }, ref) => (
|
|
123
121
|
<BaseSelect.Separator
|
|
124
122
|
ref={ref}
|
|
125
|
-
className={
|
|
123
|
+
className={cn("h-px bg-border my-[var(--space-1)]", className)}
|
|
126
124
|
{...props}
|
|
127
125
|
/>
|
|
128
126
|
));
|
|
@@ -178,7 +176,7 @@ export function MultiSelectValue({
|
|
|
178
176
|
} & Omit<React.ComponentPropsWithoutRef<typeof BaseSelect.Value>, "children" | "render">) {
|
|
179
177
|
const { remove, clear } = useMultiSelect();
|
|
180
178
|
return (
|
|
181
|
-
<BaseSelect.Value className={
|
|
179
|
+
<BaseSelect.Value className={cn("flex-1 text-left overflow-hidden text-ellipsis whitespace-nowrap", className)} {...props}>
|
|
182
180
|
{(value) => {
|
|
183
181
|
const arr = Array.isArray(value) ? (value as string[]) : [];
|
|
184
182
|
if (arr.length === 0) return <span className="text-foreground-subtle">{placeholder}</span>;
|
|
@@ -4,10 +4,8 @@ import * as React from "react";
|
|
|
4
4
|
import { Select as BaseSelect } from "@base-ui/react/select";
|
|
5
5
|
import "./styles.css";
|
|
6
6
|
|
|
7
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
8
|
-
return args.filter(Boolean).join(" ");
|
|
9
|
-
}
|
|
10
7
|
|
|
8
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
11
9
|
export const Select = BaseSelect.Root;
|
|
12
10
|
|
|
13
11
|
/** shadcn 호환: <SelectValue placeholder="..." /> */
|
|
@@ -20,7 +18,7 @@ export function SelectValue({
|
|
|
20
18
|
"children"
|
|
21
19
|
>) {
|
|
22
20
|
return (
|
|
23
|
-
<BaseSelect.Value className={
|
|
21
|
+
<BaseSelect.Value className={cn("sh-ui-select__value", className)} {...props}>
|
|
24
22
|
{(value) =>
|
|
25
23
|
value !== null && value !== undefined && value !== "" ? (
|
|
26
24
|
(value as React.ReactNode)
|
|
@@ -38,7 +36,7 @@ export const SelectTrigger = React.forwardRef<
|
|
|
38
36
|
>(({ className, children, ...props }, ref) => (
|
|
39
37
|
<BaseSelect.Trigger
|
|
40
38
|
ref={ref}
|
|
41
|
-
className={
|
|
39
|
+
className={cn("sh-ui-select__trigger", className)}
|
|
42
40
|
{...props}
|
|
43
41
|
>
|
|
44
42
|
{children}
|
|
@@ -74,7 +72,7 @@ export const SelectContent = React.forwardRef<
|
|
|
74
72
|
>
|
|
75
73
|
<BaseSelect.Popup
|
|
76
74
|
ref={ref}
|
|
77
|
-
className={
|
|
75
|
+
className={cn("sh-ui-select__content", className)}
|
|
78
76
|
{...props}
|
|
79
77
|
>
|
|
80
78
|
{children}
|
|
@@ -92,7 +90,7 @@ export const SelectLabel = React.forwardRef<
|
|
|
92
90
|
>(({ className, ...props }, ref) => (
|
|
93
91
|
<BaseSelect.GroupLabel
|
|
94
92
|
ref={ref}
|
|
95
|
-
className={
|
|
93
|
+
className={cn("sh-ui-select__label", className)}
|
|
96
94
|
{...props}
|
|
97
95
|
/>
|
|
98
96
|
));
|
|
@@ -104,7 +102,7 @@ export const SelectItem = React.forwardRef<
|
|
|
104
102
|
>(({ className, children, ...props }, ref) => (
|
|
105
103
|
<BaseSelect.Item
|
|
106
104
|
ref={ref}
|
|
107
|
-
className={
|
|
105
|
+
className={cn("sh-ui-select__item", className)}
|
|
108
106
|
{...props}
|
|
109
107
|
>
|
|
110
108
|
<BaseSelect.ItemIndicator className="sh-ui-select__indicator" aria-hidden>
|
|
@@ -131,7 +129,7 @@ export const SelectSeparator = React.forwardRef<
|
|
|
131
129
|
>(({ className, ...props }, ref) => (
|
|
132
130
|
<BaseSelect.Separator
|
|
133
131
|
ref={ref}
|
|
134
|
-
className={
|
|
132
|
+
className={cn("sh-ui-select__separator", className)}
|
|
135
133
|
{...props}
|
|
136
134
|
/>
|
|
137
135
|
));
|
|
@@ -223,7 +221,7 @@ export function MultiSelectValue({
|
|
|
223
221
|
>) {
|
|
224
222
|
const { remove, clear } = useMultiSelect();
|
|
225
223
|
return (
|
|
226
|
-
<BaseSelect.Value className={
|
|
224
|
+
<BaseSelect.Value className={cn("sh-ui-select__value", className)} {...props}>
|
|
227
225
|
{(value) => {
|
|
228
226
|
const arr = Array.isArray(value) ? (value as string[]) : [];
|
|
229
227
|
if (arr.length === 0) {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
4
|
-
return args.filter(Boolean).join(" ");
|
|
5
|
-
}
|
|
6
3
|
|
|
4
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
7
5
|
export type SeparatorOrientation = "horizontal" | "vertical";
|
|
8
6
|
|
|
9
7
|
export interface SeparatorProps
|
|
@@ -33,7 +31,7 @@ export const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(
|
|
|
33
31
|
aria-orientation={decorative ? undefined : orientation}
|
|
34
32
|
aria-hidden={decorative || undefined}
|
|
35
33
|
data-orientation={orientation}
|
|
36
|
-
className={
|
|
34
|
+
className={cn("bg-border shrink-0", sizing, className)}
|
|
37
35
|
{...props}
|
|
38
36
|
/>
|
|
39
37
|
);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import "./styles.css";
|
|
3
3
|
|
|
4
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
5
|
-
return args.filter(Boolean).join(" ");
|
|
6
|
-
}
|
|
7
4
|
|
|
5
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
8
6
|
export type SeparatorOrientation = "horizontal" | "vertical";
|
|
9
7
|
|
|
10
8
|
export interface SeparatorProps
|
|
@@ -35,7 +33,7 @@ export const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(
|
|
|
35
33
|
aria-orientation={decorative ? undefined : orientation}
|
|
36
34
|
aria-hidden={decorative || undefined}
|
|
37
35
|
data-orientation={orientation}
|
|
38
|
-
className={
|
|
36
|
+
className={cn(
|
|
39
37
|
"sh-ui-separator",
|
|
40
38
|
`sh-ui-separator--${orientation}`,
|
|
41
39
|
className,
|