sh-ui-cli 0.45.1 → 0.45.3

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 +25 -0
  2. package/data/registry/react/components/accordion/index.tailwind.tsx +5 -7
  3. package/data/registry/react/components/accordion/index.tsx +5 -7
  4. package/data/registry/react/components/avatar/index.tailwind.tsx +4 -6
  5. package/data/registry/react/components/avatar/index.tsx +4 -6
  6. package/data/registry/react/components/badge/index.tailwind.tsx +2 -4
  7. package/data/registry/react/components/badge/index.tsx +2 -4
  8. package/data/registry/react/components/breadcrumb/index.tailwind.tsx +8 -10
  9. package/data/registry/react/components/breadcrumb/index.tsx +8 -10
  10. package/data/registry/react/components/button/index.tailwind.tsx +2 -1
  11. package/data/registry/react/components/button/index.tsx +3 -4
  12. package/data/registry/react/components/calendar/index.tailwind.tsx +10 -12
  13. package/data/registry/react/components/calendar/index.tsx +9 -11
  14. package/data/registry/react/components/card/index.tailwind.tsx +8 -10
  15. package/data/registry/react/components/card/index.tsx +8 -10
  16. package/data/registry/react/components/carousel/index.tailwind.tsx +7 -9
  17. package/data/registry/react/components/carousel/index.tsx +7 -9
  18. package/data/registry/react/components/checkbox/index.tailwind.tsx +3 -5
  19. package/data/registry/react/components/checkbox/index.tsx +3 -5
  20. package/data/registry/react/components/code-editor/index.tailwind.tsx +2 -4
  21. package/data/registry/react/components/code-editor/index.tsx +2 -4
  22. package/data/registry/react/components/code-panel/index.tailwind.tsx +5 -7
  23. package/data/registry/react/components/code-panel/index.tsx +5 -7
  24. package/data/registry/react/components/color-picker/index.tailwind.tsx +7 -6
  25. package/data/registry/react/components/color-picker/index.tsx +7 -6
  26. package/data/registry/react/components/combobox/index.tailwind.tsx +8 -10
  27. package/data/registry/react/components/combobox/index.tsx +8 -10
  28. package/data/registry/react/components/context-menu/index.tailwind.tsx +10 -12
  29. package/data/registry/react/components/context-menu/index.tsx +10 -12
  30. package/data/registry/react/components/date-picker/index.tailwind.tsx +7 -9
  31. package/data/registry/react/components/date-picker/index.tsx +7 -9
  32. package/data/registry/react/components/dialog/index.tailwind.tsx +6 -8
  33. package/data/registry/react/components/dialog/index.tsx +6 -8
  34. package/data/registry/react/components/dropdown-menu/index.tailwind.tsx +10 -12
  35. package/data/registry/react/components/dropdown-menu/index.tsx +10 -12
  36. package/data/registry/react/components/file-upload/index.tailwind.tsx +6 -8
  37. package/data/registry/react/components/file-upload/index.tsx +6 -8
  38. package/data/registry/react/components/form/field.tailwind.tsx +2 -1
  39. package/data/registry/react/components/form/field.tsx +2 -3
  40. package/data/registry/react/components/header/index.tailwind.tsx +17 -19
  41. package/data/registry/react/components/header/index.tsx +17 -19
  42. package/data/registry/react/components/input/index.tailwind.tsx +4 -6
  43. package/data/registry/react/components/input/index.tsx +4 -6
  44. package/data/registry/react/components/label/index.tailwind.tsx +6 -8
  45. package/data/registry/react/components/label/index.tsx +6 -8
  46. package/data/registry/react/components/markdown-editor/index.tailwind.tsx +2 -4
  47. package/data/registry/react/components/markdown-editor/index.tsx +2 -4
  48. package/data/registry/react/components/menubar/index.tailwind.tsx +2 -4
  49. package/data/registry/react/components/menubar/index.tsx +2 -4
  50. package/data/registry/react/components/numeric-input/index.tailwind.tsx +2 -4
  51. package/data/registry/react/components/numeric-input/index.tsx +2 -4
  52. package/data/registry/react/components/page-toc/index.tailwind.tsx +3 -2
  53. package/data/registry/react/components/page-toc/index.tsx +2 -3
  54. package/data/registry/react/components/pagination/index.tailwind.tsx +8 -10
  55. package/data/registry/react/components/pagination/index.tsx +8 -10
  56. package/data/registry/react/components/popover/index.tailwind.tsx +4 -6
  57. package/data/registry/react/components/popover/index.tsx +4 -6
  58. package/data/registry/react/components/progress/index.tailwind.tsx +3 -5
  59. package/data/registry/react/components/progress/index.tsx +2 -4
  60. package/data/registry/react/components/radio/index.tailwind.tsx +3 -5
  61. package/data/registry/react/components/radio/index.tsx +3 -5
  62. package/data/registry/react/components/rich-text-editor/index.tailwind.tsx +3 -5
  63. package/data/registry/react/components/rich-text-editor/index.tsx +3 -5
  64. package/data/registry/react/components/select/index.tailwind.tsx +8 -10
  65. package/data/registry/react/components/select/index.tsx +8 -10
  66. package/data/registry/react/components/separator/index.tailwind.tsx +2 -4
  67. package/data/registry/react/components/separator/index.tsx +2 -4
  68. package/data/registry/react/components/sidebar/index.tailwind.tsx +32 -43
  69. package/data/registry/react/components/sidebar/index.tsx +29 -46
  70. package/data/registry/react/components/skeleton/index.tailwind.tsx +2 -4
  71. package/data/registry/react/components/skeleton/index.tsx +2 -4
  72. package/data/registry/react/components/slider/index.tailwind.tsx +5 -7
  73. package/data/registry/react/components/slider/index.tsx +5 -7
  74. package/data/registry/react/components/spinner/index.tailwind.tsx +3 -5
  75. package/data/registry/react/components/spinner/index.tsx +2 -4
  76. package/data/registry/react/components/switch/index.tailwind.tsx +3 -5
  77. package/data/registry/react/components/switch/index.tsx +2 -4
  78. package/data/registry/react/components/tabs/index.tailwind.tsx +6 -8
  79. package/data/registry/react/components/tabs/index.tsx +6 -8
  80. package/data/registry/react/components/textarea/index.tailwind.tsx +2 -4
  81. package/data/registry/react/components/textarea/index.tsx +2 -4
  82. package/data/registry/react/components/toggle/index.tailwind.tsx +4 -6
  83. package/data/registry/react/components/toggle/index.tsx +4 -6
  84. package/data/registry/react/components/tooltip/index.tailwind.tsx +2 -4
  85. package/data/registry/react/components/tooltip/index.tsx +2 -4
  86. package/data/registry/react/lib/cn.tailwind.ts +17 -0
  87. package/data/registry/react/peer-versions.json +3 -1
  88. package/data/registry/react/registry.json +159 -43
  89. package/package.json +1 -1
  90. package/src/add.mjs +25 -1
  91. package/src/mcp-init.mjs +13 -5
  92. package/src/mcp.mjs +20 -15
  93. package/templates/ui-app-template/sh-ui.config.json +5 -0
@@ -3,11 +3,9 @@
3
3
  import * as React from "react";
4
4
  import { Combobox as BaseCombobox } from "@base-ui/react/combobox";
5
5
 
6
+ import { cn } from "@SH_UI_UTILS@";
6
7
  type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
7
8
 
8
- function cx(...args: (string | undefined | false)[]) {
9
- return args.filter(Boolean).join(" ");
10
- }
11
9
 
12
10
  export const Combobox = BaseCombobox.Root;
13
11
  export const ComboboxIcon = BaseCombobox.Icon;
@@ -24,7 +22,7 @@ export const ComboboxInput = React.forwardRef<
24
22
  return (
25
23
  <BaseCombobox.Input
26
24
  ref={ref}
27
- className={cx(
25
+ className={cn(
28
26
  "inline-flex w-full 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 outline-none transition-[border-color] duration-[var(--duration-fast)] placeholder:text-foreground-subtle hover:not-disabled:border-border-strong focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 disabled:opacity-[var(--opacity-disabled)] disabled:pointer-events-none",
29
27
  className,
30
28
  )}
@@ -49,7 +47,7 @@ export const ComboboxContent = React.forwardRef<
49
47
  >
50
48
  <BaseCombobox.Popup
51
49
  ref={ref}
52
- className={cx(
50
+ className={cn(
53
51
  "max-h-[min(20rem,var(--available-height))] overflow-y-auto p-[var(--space-1)] bg-background text-foreground border border-border rounded-[var(--radius)] shadow-[0_8px_24px_rgba(0,0,0,0.08)] outline-none origin-[var(--transform-origin)] transition-[opacity,transform] duration-[140ms] ease-out motion-reduce:transition-none data-[starting-style]:opacity-0 data-[starting-style]:scale-[0.97] data-[ending-style]:opacity-0 data-[ending-style]:scale-[0.97]",
54
52
  className,
55
53
  )}
@@ -71,7 +69,7 @@ export const ComboboxItem = React.forwardRef<
71
69
  return (
72
70
  <BaseCombobox.Item
73
71
  ref={ref}
74
- className={cx(
72
+ className={cn(
75
73
  "flex items-center gap-[var(--space-2)] py-1.5 px-3 text-[length:var(--text-sm)] leading-snug rounded-[calc(var(--radius)-2px)] cursor-pointer select-none outline-none data-[highlighted]:bg-background-muted hover:bg-background-muted data-[selected]:text-foreground data-[selected]:font-medium data-[disabled]:opacity-[var(--opacity-disabled)] data-[disabled]:pointer-events-none",
76
74
  className,
77
75
  )}
@@ -92,7 +90,7 @@ export const ComboboxEmpty = React.forwardRef<
92
90
  return (
93
91
  <BaseCombobox.Empty
94
92
  ref={ref}
95
- className={cx(
93
+ className={cn(
96
94
  "py-[var(--space-3)] px-[var(--space-2)] text-center text-[0.8125rem] text-foreground-muted",
97
95
  className,
98
96
  )}
@@ -108,7 +106,7 @@ export const ComboboxGroupLabel = React.forwardRef<
108
106
  return (
109
107
  <BaseCombobox.GroupLabel
110
108
  ref={ref}
111
- className={cx(
109
+ className={cn(
112
110
  "py-1.5 px-[var(--space-2)] pb-[var(--space-1)] text-[length:var(--text-xs)] font-semibold text-foreground-muted uppercase tracking-[0.04em]",
113
111
  className,
114
112
  )}
@@ -124,7 +122,7 @@ export const ComboboxChip = React.forwardRef<
124
122
  return (
125
123
  <BaseCombobox.Chip
126
124
  ref={ref}
127
- className={cx(
125
+ className={cn(
128
126
  "inline-flex items-center gap-[var(--space-1)] py-0.5 pr-1.5 pl-[var(--space-2)] mr-[var(--space-1)] text-[length:var(--text-xs)] leading-5 bg-background-muted rounded-[calc(var(--radius)-2px)] whitespace-nowrap",
129
127
  className,
130
128
  )}
@@ -140,7 +138,7 @@ export const ComboboxChipRemove = React.forwardRef<
140
138
  return (
141
139
  <BaseCombobox.ChipRemove
142
140
  ref={ref}
143
- className={cx(
141
+ className={cn(
144
142
  "inline-flex items-center justify-center w-4 h-4 p-0 border-0 rounded-full bg-transparent text-foreground-muted text-[length:var(--text-sm)] leading-none cursor-pointer transition-[background-color,color] duration-[var(--duration-fast)] hover:bg-background hover:text-foreground motion-reduce:transition-none",
145
143
  className,
146
144
  )}
@@ -4,11 +4,9 @@ import * as React from "react";
4
4
  import { Combobox as BaseCombobox } from "@base-ui/react/combobox";
5
5
  import "./styles.css";
6
6
 
7
+ import { cn } from "@SH_UI_UTILS@";
7
8
  type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
8
9
 
9
- function cx(...args: (string | undefined | false)[]) {
10
- return args.filter(Boolean).join(" ");
11
- }
12
10
 
13
11
  /**
14
12
  * Select + Input의 결합 — 타이핑으로 목록이 자동 필터링된다.
@@ -40,7 +38,7 @@ export const ComboboxInput = React.forwardRef<
40
38
  return (
41
39
  <BaseCombobox.Input
42
40
  ref={ref}
43
- className={cx("sh-ui-combobox__input", className)}
41
+ className={cn("sh-ui-combobox__input", className)}
44
42
  {...props}
45
43
  />
46
44
  );
@@ -66,7 +64,7 @@ export const ComboboxContent = React.forwardRef<
66
64
  >
67
65
  <BaseCombobox.Popup
68
66
  ref={ref}
69
- className={cx("sh-ui-combobox__content", className)}
67
+ className={cn("sh-ui-combobox__content", className)}
70
68
  {...props}
71
69
  >
72
70
  {children}
@@ -85,7 +83,7 @@ export const ComboboxItem = React.forwardRef<
85
83
  return (
86
84
  <BaseCombobox.Item
87
85
  ref={ref}
88
- className={cx("sh-ui-combobox__item", className)}
86
+ className={cn("sh-ui-combobox__item", className)}
89
87
  {...props}
90
88
  >
91
89
  <BaseCombobox.ItemIndicator className="sh-ui-combobox__item-indicator">
@@ -103,7 +101,7 @@ export const ComboboxEmpty = React.forwardRef<
103
101
  return (
104
102
  <BaseCombobox.Empty
105
103
  ref={ref}
106
- className={cx("sh-ui-combobox__empty", className)}
104
+ className={cn("sh-ui-combobox__empty", className)}
107
105
  {...props}
108
106
  />
109
107
  );
@@ -116,7 +114,7 @@ export const ComboboxGroupLabel = React.forwardRef<
116
114
  return (
117
115
  <BaseCombobox.GroupLabel
118
116
  ref={ref}
119
- className={cx("sh-ui-combobox__group-label", className)}
117
+ className={cn("sh-ui-combobox__group-label", className)}
120
118
  {...props}
121
119
  />
122
120
  );
@@ -130,7 +128,7 @@ export const ComboboxChip = React.forwardRef<
130
128
  return (
131
129
  <BaseCombobox.Chip
132
130
  ref={ref}
133
- className={cx("sh-ui-combobox__chip", className)}
131
+ className={cn("sh-ui-combobox__chip", className)}
134
132
  {...props}
135
133
  />
136
134
  );
@@ -144,7 +142,7 @@ export const ComboboxChipRemove = React.forwardRef<
144
142
  return (
145
143
  <BaseCombobox.ChipRemove
146
144
  ref={ref}
147
- className={cx("sh-ui-combobox__chip-remove", className)}
145
+ className={cn("sh-ui-combobox__chip-remove", className)}
148
146
  {...props}
149
147
  >
150
148
  {children ?? "×"}
@@ -1,11 +1,9 @@
1
1
  import * as React from "react";
2
2
  import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu";
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 | null)[]) {
7
- return args.filter(Boolean).join(" ");
8
- }
9
7
 
10
8
  const itemBase =
11
9
  "relative 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 motion-reduce:transition-none";
@@ -19,7 +17,7 @@ export const ContextMenuTrigger = React.forwardRef<
19
17
  HTMLDivElement,
20
18
  WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.Trigger>>
21
19
  >(function ContextMenuTrigger({ className, ...props }, ref) {
22
- return <BaseContextMenu.Trigger ref={ref} className={cx("contents", className)} {...props} />;
20
+ return <BaseContextMenu.Trigger ref={ref} className={cn("contents", className)} {...props} />;
23
21
  });
24
22
 
25
23
  export interface ContextMenuContentProps
@@ -32,7 +30,7 @@ export const ContextMenuContent = React.forwardRef<HTMLDivElement, ContextMenuCo
32
30
  return (
33
31
  <BaseContextMenu.Portal container={container}>
34
32
  <BaseContextMenu.Positioner className="outline-none z-[var(--z-dropdown)]">
35
- <BaseContextMenu.Popup ref={ref} className={cx(contentClasses, className)} {...props}>
33
+ <BaseContextMenu.Popup ref={ref} className={cn(contentClasses, className)} {...props}>
36
34
  {children}
37
35
  </BaseContextMenu.Popup>
38
36
  </BaseContextMenu.Positioner>
@@ -45,7 +43,7 @@ export const ContextMenuItem = React.forwardRef<
45
43
  HTMLDivElement,
46
44
  WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.Item>>
47
45
  >(function ContextMenuItem({ className, ...props }, ref) {
48
- return <BaseContextMenu.Item ref={ref} className={cx(itemBase, className)} {...props} />;
46
+ return <BaseContextMenu.Item ref={ref} className={cn(itemBase, className)} {...props} />;
49
47
  });
50
48
 
51
49
  export const ContextMenuCheckboxItem = React.forwardRef<
@@ -53,7 +51,7 @@ export const ContextMenuCheckboxItem = React.forwardRef<
53
51
  WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.CheckboxItem>>
54
52
  >(function ContextMenuCheckboxItem({ className, children, ...props }, ref) {
55
53
  return (
56
- <BaseContextMenu.CheckboxItem ref={ref} className={cx(itemBase, itemCheck, className)} {...props}>
54
+ <BaseContextMenu.CheckboxItem ref={ref} className={cn(itemBase, itemCheck, className)} {...props}>
57
55
  <span className="absolute left-2 inline-flex items-center justify-center w-4 h-4 text-foreground" aria-hidden>
58
56
  <BaseContextMenu.CheckboxItemIndicator>
59
57
  <CheckIcon />
@@ -71,7 +69,7 @@ export const ContextMenuRadioItem = React.forwardRef<
71
69
  WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.RadioItem>>
72
70
  >(function ContextMenuRadioItem({ className, children, ...props }, ref) {
73
71
  return (
74
- <BaseContextMenu.RadioItem ref={ref} className={cx(itemBase, itemCheck, className)} {...props}>
72
+ <BaseContextMenu.RadioItem ref={ref} className={cn(itemBase, itemCheck, className)} {...props}>
75
73
  <span className="absolute left-2 inline-flex items-center justify-center w-4 h-4 text-foreground" aria-hidden>
76
74
  <BaseContextMenu.RadioItemIndicator>
77
75
  <DotIcon />
@@ -86,7 +84,7 @@ export const ContextMenuGroup = React.forwardRef<
86
84
  HTMLDivElement,
87
85
  WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseContextMenu.Group>>
88
86
  >(function ContextMenuGroup({ className, ...props }, ref) {
89
- return <BaseContextMenu.Group ref={ref} className={cx("p-0", className)} {...props} />;
87
+ return <BaseContextMenu.Group ref={ref} className={cn("p-0", className)} {...props} />;
90
88
  });
91
89
 
92
90
  export const ContextMenuLabel = React.forwardRef<
@@ -96,7 +94,7 @@ export const ContextMenuLabel = React.forwardRef<
96
94
  return (
97
95
  <BaseContextMenu.GroupLabel
98
96
  ref={ref}
99
- className={cx(
97
+ className={cn(
100
98
  "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]",
101
99
  className,
102
100
  )}
@@ -112,7 +110,7 @@ export const ContextMenuSeparator = React.forwardRef<HTMLDivElement, React.HTMLA
112
110
  ref={ref}
113
111
  role="separator"
114
112
  aria-orientation="horizontal"
115
- className={cx("h-px bg-border my-[var(--space-1)]", className)}
113
+ className={cn("h-px bg-border my-[var(--space-1)]", className)}
116
114
  {...props}
117
115
  />
118
116
  );
@@ -128,7 +126,7 @@ export const ContextMenuSubTrigger = React.forwardRef<
128
126
  return (
129
127
  <BaseContextMenu.SubmenuTrigger
130
128
  ref={ref}
131
- className={cx(itemBase, "data-[popup-open]:bg-background-muted", className)}
129
+ className={cn(itemBase, "data-[popup-open]:bg-background-muted", className)}
132
130
  {...props}
133
131
  >
134
132
  <span className="flex-1 min-w-0 overflow-hidden text-ellipsis whitespace-nowrap">{children}</span>
@@ -2,11 +2,9 @@ import * as React from "react";
2
2
  import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu";
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 | null)[]) {
8
- return args.filter(Boolean).join(" ");
9
- }
10
8
 
11
9
  /* ───────── Root ───────── */
12
10
 
@@ -29,7 +27,7 @@ export const ContextMenuTrigger = React.forwardRef<
29
27
  return (
30
28
  <BaseContextMenu.Trigger
31
29
  ref={ref}
32
- className={cx("sh-ui-cm__trigger", className)}
30
+ className={cn("sh-ui-cm__trigger", className)}
33
31
  {...props}
34
32
  />
35
33
  );
@@ -60,7 +58,7 @@ export const ContextMenuContent = React.forwardRef<
60
58
  <BaseContextMenu.Positioner className="sh-ui-cm__positioner">
61
59
  <BaseContextMenu.Popup
62
60
  ref={ref}
63
- className={cx("sh-ui-cm__content", className)}
61
+ className={cn("sh-ui-cm__content", className)}
64
62
  {...props}
65
63
  >
66
64
  {children}
@@ -80,7 +78,7 @@ export const ContextMenuItem = React.forwardRef<
80
78
  return (
81
79
  <BaseContextMenu.Item
82
80
  ref={ref}
83
- className={cx("sh-ui-cm__item", className)}
81
+ className={cn("sh-ui-cm__item", className)}
84
82
  {...props}
85
83
  />
86
84
  );
@@ -98,7 +96,7 @@ export const ContextMenuCheckboxItem = React.forwardRef<
98
96
  return (
99
97
  <BaseContextMenu.CheckboxItem
100
98
  ref={ref}
101
- className={cx("sh-ui-cm__item", "sh-ui-cm__item--check", className)}
99
+ className={cn("sh-ui-cm__item", "sh-ui-cm__item--check", className)}
102
100
  {...props}
103
101
  >
104
102
  <span className="sh-ui-cm__item-indicator" aria-hidden>
@@ -124,7 +122,7 @@ export const ContextMenuRadioItem = React.forwardRef<
124
122
  return (
125
123
  <BaseContextMenu.RadioItem
126
124
  ref={ref}
127
- className={cx("sh-ui-cm__item", "sh-ui-cm__item--check", className)}
125
+ className={cn("sh-ui-cm__item", "sh-ui-cm__item--check", className)}
128
126
  {...props}
129
127
  >
130
128
  <span className="sh-ui-cm__item-indicator" aria-hidden>
@@ -147,7 +145,7 @@ export const ContextMenuGroup = React.forwardRef<
147
145
  return (
148
146
  <BaseContextMenu.Group
149
147
  ref={ref}
150
- className={cx("sh-ui-cm__group", className)}
148
+ className={cn("sh-ui-cm__group", className)}
151
149
  {...props}
152
150
  />
153
151
  );
@@ -163,7 +161,7 @@ export const ContextMenuLabel = React.forwardRef<
163
161
  return (
164
162
  <BaseContextMenu.GroupLabel
165
163
  ref={ref}
166
- className={cx("sh-ui-cm__label", className)}
164
+ className={cn("sh-ui-cm__label", className)}
167
165
  {...props}
168
166
  />
169
167
  );
@@ -179,7 +177,7 @@ export const ContextMenuSeparator = React.forwardRef<
179
177
  ref={ref}
180
178
  role="separator"
181
179
  aria-orientation="horizontal"
182
- className={cx("sh-ui-cm__separator", className)}
180
+ className={cn("sh-ui-cm__separator", className)}
183
181
  {...props}
184
182
  />
185
183
  );
@@ -200,7 +198,7 @@ export const ContextMenuSubTrigger = React.forwardRef<
200
198
  return (
201
199
  <BaseContextMenu.SubmenuTrigger
202
200
  ref={ref}
203
- className={cx("sh-ui-cm__item", "sh-ui-cm__sub-trigger", className)}
201
+ className={cn("sh-ui-cm__item", "sh-ui-cm__sub-trigger", className)}
204
202
  {...props}
205
203
  >
206
204
  <span className="sh-ui-cm__item-text">{children}</span>
@@ -4,11 +4,9 @@ import * as React from "react";
4
4
  import { Popover as BasePopover } from "@base-ui/react/popover";
5
5
  import { Calendar, type DateRange } from "../calendar";
6
6
 
7
+ import { cn } from "@SH_UI_UTILS@";
7
8
  export type { DateRange };
8
9
 
9
- function cx(...args: (string | undefined | false)[]) {
10
- return args.filter(Boolean).join(" ");
11
- }
12
10
 
13
11
  const formatDefault = (d: Date) =>
14
12
  `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
@@ -121,7 +119,7 @@ export const DatePickerTrigger = React.forwardRef<HTMLButtonElement, DatePickerT
121
119
  if (children !== undefined) return children;
122
120
  return (
123
121
  <>
124
- <span className={cx("overflow-hidden text-ellipsis whitespace-nowrap", !displayText && "text-foreground-subtle")}>
122
+ <span className={cn("overflow-hidden text-ellipsis whitespace-nowrap", !displayText && "text-foreground-subtle")}>
125
123
  {displayText ?? ctx.placeholder}
126
124
  </span>
127
125
  <span className="shrink-0 inline-flex text-foreground-muted ml-[var(--space-2)]" aria-hidden>
@@ -133,7 +131,7 @@ export const DatePickerTrigger = React.forwardRef<HTMLButtonElement, DatePickerT
133
131
  return (
134
132
  <BasePopover.Trigger
135
133
  ref={ref}
136
- className={cx(triggerClasses, className)}
134
+ className={cn(triggerClasses, className)}
137
135
  disabled={ctx.disabled}
138
136
  aria-invalid={ctx.ariaInvalid}
139
137
  aria-haspopup="dialog"
@@ -165,7 +163,7 @@ export const DatePickerContent = React.forwardRef<HTMLDivElement, DatePickerCont
165
163
  return (
166
164
  <BasePopover.Portal container={container}>
167
165
  <BasePopover.Positioner className="z-[var(--z-popover)] outline-none" sideOffset={sideOffset} side={side} align={align}>
168
- <BasePopover.Popup ref={ref} className={cx(popupClasses, className)} {...props}>
166
+ <BasePopover.Popup ref={ref} className={cn(popupClasses, className)} {...props}>
169
167
  {children}
170
168
  </BasePopover.Popup>
171
169
  </BasePopover.Positioner>
@@ -199,7 +197,7 @@ export const DatePickerFooter = React.forwardRef<HTMLDivElement, DatePickerFoote
199
197
  return (
200
198
  <div
201
199
  ref={ref}
202
- className={cx(
200
+ className={cn(
203
201
  "flex items-center justify-end gap-[var(--space-2)] mt-[var(--space-2)] pt-[var(--space-2)] border-t border-border",
204
202
  className,
205
203
  )}
@@ -257,13 +255,13 @@ export const DateRangePicker = React.forwardRef<HTMLButtonElement, DateRangePick
257
255
  <BasePopover.Root open={open} onOpenChange={setOpen}>
258
256
  <BasePopover.Trigger
259
257
  ref={ref}
260
- className={cx(triggerClasses, className)}
258
+ className={cn(triggerClasses, className)}
261
259
  disabled={disabled}
262
260
  aria-invalid={ariaInvalid}
263
261
  aria-haspopup="dialog"
264
262
  onClick={(e) => { if (readOnly) e.preventDefault(); }}
265
263
  >
266
- <span className={cx("overflow-hidden text-ellipsis whitespace-nowrap", !displayText && "text-foreground-subtle")}>
264
+ <span className={cn("overflow-hidden text-ellipsis whitespace-nowrap", !displayText && "text-foreground-subtle")}>
267
265
  {displayText ?? placeholder}
268
266
  </span>
269
267
  <span className="shrink-0 inline-flex text-foreground-muted ml-[var(--space-2)]" aria-hidden>
@@ -5,13 +5,11 @@ import { Popover as BasePopover } from "@base-ui/react/popover";
5
5
  import { Calendar, type DateRange } from "../calendar";
6
6
  import "./styles.css";
7
7
 
8
+ import { cn } from "@SH_UI_UTILS@";
8
9
  export type { DateRange };
9
10
 
10
11
  /* ───────── Helpers ───────── */
11
12
 
12
- function cx(...args: (string | undefined | false)[]) {
13
- return args.filter(Boolean).join(" ");
14
- }
15
13
 
16
14
  const formatDefault = (d: Date) =>
17
15
  `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
@@ -247,7 +245,7 @@ export const DatePickerTrigger = React.forwardRef<HTMLButtonElement, DatePickerT
247
245
  return (
248
246
  <>
249
247
  <span
250
- className={cx(
248
+ className={cn(
251
249
  "sh-ui-date-picker__value",
252
250
  !displayText && "sh-ui-date-picker__placeholder",
253
251
  )}
@@ -264,7 +262,7 @@ export const DatePickerTrigger = React.forwardRef<HTMLButtonElement, DatePickerT
264
262
  return (
265
263
  <BasePopover.Trigger
266
264
  ref={ref}
267
- className={cx("sh-ui-date-picker__trigger", className)}
265
+ className={cn("sh-ui-date-picker__trigger", className)}
268
266
  disabled={ctx.disabled}
269
267
  aria-invalid={ctx.ariaInvalid}
270
268
  aria-haspopup="dialog"
@@ -326,7 +324,7 @@ export const DatePickerContent = React.forwardRef<HTMLDivElement, DatePickerCont
326
324
  >
327
325
  <BasePopover.Popup
328
326
  ref={ref}
329
- className={cx("sh-ui-date-picker__popup", className)}
327
+ className={cn("sh-ui-date-picker__popup", className)}
330
328
  {...props}
331
329
  >
332
330
  {children}
@@ -371,7 +369,7 @@ export const DatePickerFooter = React.forwardRef<HTMLDivElement, DatePickerFoote
371
369
  return (
372
370
  <div
373
371
  ref={ref}
374
- className={cx("sh-ui-date-picker__footer", className)}
372
+ className={cn("sh-ui-date-picker__footer", className)}
375
373
  {...props}
376
374
  />
377
375
  );
@@ -478,7 +476,7 @@ export const DateRangePicker = React.forwardRef<HTMLButtonElement, DateRangePick
478
476
  <BasePopover.Root open={open} onOpenChange={setOpen}>
479
477
  <BasePopover.Trigger
480
478
  ref={ref}
481
- className={cx("sh-ui-date-picker__trigger", className)}
479
+ className={cn("sh-ui-date-picker__trigger", className)}
482
480
  disabled={disabled}
483
481
  aria-invalid={ariaInvalid}
484
482
  aria-haspopup="dialog"
@@ -486,7 +484,7 @@ export const DateRangePicker = React.forwardRef<HTMLButtonElement, DateRangePick
486
484
  if (readOnly) e.preventDefault();
487
485
  }}
488
486
  >
489
- <span className={cx("sh-ui-date-picker__value", !displayText && "sh-ui-date-picker__placeholder")}>
487
+ <span className={cn("sh-ui-date-picker__value", !displayText && "sh-ui-date-picker__placeholder")}>
490
488
  {displayText ?? placeholder}
491
489
  </span>
492
490
  <span className="sh-ui-date-picker__icon" aria-hidden>
@@ -1,11 +1,9 @@
1
1
  import * as React from "react";
2
2
  import { Dialog as BaseDialog } from "@base-ui/react/dialog";
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 Dialog = BaseDialog.Root;
11
9
  export const DialogTrigger = BaseDialog.Trigger;
@@ -14,7 +12,7 @@ export const DialogClose = BaseDialog.Close;
14
12
  export function DialogCloseX({ className, children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
15
13
  return (
16
14
  <BaseDialog.Close
17
- className={cx(
15
+ className={cn(
18
16
  "absolute top-[var(--space-3)] right-[var(--space-3)] inline-flex items-center justify-center w-8 h-8 border-0 rounded-[calc(var(--radius)-2px)] bg-transparent text-foreground-muted text-[length:var(--text-lg)] leading-none cursor-pointer transition-[background-color,color] duration-[var(--duration-fast)] hover:bg-background-muted hover:text-foreground focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 motion-reduce:transition-none",
19
17
  className,
20
18
  )}
@@ -29,7 +27,7 @@ export function DialogCloseX({ className, children, ...props }: React.ButtonHTML
29
27
  export function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
30
28
  return (
31
29
  <div
32
- className={cx(
30
+ className={cn(
33
31
  "flex items-center justify-end gap-[var(--space-2)] pt-[var(--space-4)] border-t border-border mt-auto",
34
32
  className,
35
33
  )}
@@ -50,7 +48,7 @@ export const DialogContent = React.forwardRef<HTMLDivElement, DialogContentProps
50
48
  <BaseDialog.Backdrop className="fixed inset-0 z-[var(--z-overlay)] bg-black/25 backdrop-blur-md transition-opacity duration-[var(--duration-slow)] motion-reduce:transition-none data-[starting-style]:opacity-0 data-[ending-style]:opacity-0" />
51
49
  <BaseDialog.Popup
52
50
  ref={ref}
53
- className={cx(
51
+ className={cn(
54
52
  "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-[var(--z-modal)] flex flex-col w-[calc(100%-2rem)] max-w-md max-h-[calc(100dvh-4rem)] p-[var(--space-6)] bg-background text-foreground border border-border rounded-[var(--radius)] shadow-[var(--shadow-xl)] outline-none overflow-y-auto transition-[opacity,transform] duration-[var(--duration-slow)] motion-reduce:transition-none data-[starting-style]:opacity-0 data-[starting-style]:translate-y-[calc(-50%+0.5rem)] data-[starting-style]:scale-[0.97] data-[ending-style]:opacity-0 data-[ending-style]:translate-y-[calc(-50%+0.25rem)] data-[ending-style]:scale-[0.98] motion-reduce:data-[starting-style]:translate-y-[-50%] motion-reduce:data-[starting-style]:scale-100 motion-reduce:data-[ending-style]:translate-y-[-50%] motion-reduce:data-[ending-style]:scale-100 focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2",
55
53
  className,
56
54
  )}
@@ -70,7 +68,7 @@ export const DialogTitle = React.forwardRef<
70
68
  return (
71
69
  <BaseDialog.Title
72
70
  ref={ref}
73
- className={cx(
71
+ className={cn(
74
72
  "m-0 mb-[var(--space-1)] font-semibold text-[length:var(--text-lg)] leading-snug",
75
73
  className,
76
74
  )}
@@ -86,7 +84,7 @@ export const DialogDescription = React.forwardRef<
86
84
  return (
87
85
  <BaseDialog.Description
88
86
  ref={ref}
89
- className={cx(
87
+ className={cn(
90
88
  "m-0 mb-[var(--space-5)] text-foreground-muted text-[length:var(--text-sm)] leading-normal",
91
89
  className,
92
90
  )}
@@ -2,11 +2,9 @@ import * as React from "react";
2
2
  import { Dialog as BaseDialog } from "@base-ui/react/dialog";
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
  * 모달 다이얼로그 루트. 열림 상태를 가지며 자식으로 Trigger·Content를 둔다.
@@ -24,7 +22,7 @@ export const DialogClose = BaseDialog.Close;
24
22
  export function DialogCloseX({ className, children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
25
23
  return (
26
24
  <BaseDialog.Close
27
- className={cx("sh-ui-dialog__close", className)}
25
+ className={cn("sh-ui-dialog__close", className)}
28
26
  aria-label="닫기"
29
27
  {...props}
30
28
  >
@@ -35,7 +33,7 @@ export function DialogCloseX({ className, children, ...props }: React.ButtonHTML
35
33
 
36
34
  /** Dialog 본문 하단의 액션 버튼 영역. 보통 [취소, 확인] 순서로 배치. */
37
35
  export function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
38
- return <div className={cx("sh-ui-dialog__footer", className)} {...props} />;
36
+ return <div className={cn("sh-ui-dialog__footer", className)} {...props} />;
39
37
  }
40
38
 
41
39
  export interface DialogContentProps
@@ -58,7 +56,7 @@ export const DialogContent = React.forwardRef<HTMLDivElement, DialogContentProps
58
56
  <BaseDialog.Backdrop className="sh-ui-dialog__backdrop" />
59
57
  <BaseDialog.Popup
60
58
  ref={ref}
61
- className={cx("sh-ui-dialog__content", className)}
59
+ className={cn("sh-ui-dialog__content", className)}
62
60
  {...props}
63
61
  >
64
62
  {children}
@@ -76,7 +74,7 @@ export const DialogTitle = React.forwardRef<
76
74
  return (
77
75
  <BaseDialog.Title
78
76
  ref={ref}
79
- className={cx("sh-ui-dialog__title", className)}
77
+ className={cn("sh-ui-dialog__title", className)}
80
78
  {...props}
81
79
  />
82
80
  );
@@ -90,7 +88,7 @@ export const DialogDescription = React.forwardRef<
90
88
  return (
91
89
  <BaseDialog.Description
92
90
  ref={ref}
93
- className={cx("sh-ui-dialog__description", className)}
91
+ className={cn("sh-ui-dialog__description", className)}
94
92
  {...props}
95
93
  />
96
94
  );