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.
- package/data/changelog/versions.json +25 -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.tailwind.tsx +2 -1
- package/data/registry/react/components/button/index.tsx +3 -4
- 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.tailwind.tsx +8 -10
- package/data/registry/react/components/card/index.tsx +8 -10
- 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.tailwind.tsx +4 -6
- package/data/registry/react/components/input/index.tsx +4 -6
- 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 +159 -43
- package/package.json +1 -1
- package/src/add.mjs +25 -1
- package/src/mcp-init.mjs +13 -5
- package/src/mcp.mjs +20 -15
- package/templates/ui-app-template/sh-ui.config.json +5 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
4
5
|
import { ChevronRightIcon, PanelLeftIcon } from "lucide-react";
|
|
5
6
|
import { Popover, PopoverContent, PopoverTrigger } from "../popover";
|
|
6
7
|
import "./styles.css";
|
|
@@ -205,7 +206,7 @@ export function SidebarProvider({
|
|
|
205
206
|
[state, open, setOpen, isMobile, openMobile, toggleSidebar, activePanel, setActivePanel]
|
|
206
207
|
);
|
|
207
208
|
|
|
208
|
-
const classes =
|
|
209
|
+
const classes = cn("sh-ui-sidebar-wrapper", className);
|
|
209
210
|
|
|
210
211
|
return (
|
|
211
212
|
<SidebarContext.Provider value={value}>
|
|
@@ -288,7 +289,7 @@ export function Sidebar({
|
|
|
288
289
|
);
|
|
289
290
|
|
|
290
291
|
if (collapsible === "none") {
|
|
291
|
-
const classes =
|
|
292
|
+
const classes = cn("sh-ui-sidebar", "sh-ui-sidebar--static", className);
|
|
292
293
|
return wrap(
|
|
293
294
|
<aside className={classes} data-side={side} data-variant={variant} {...props}>
|
|
294
295
|
{children}
|
|
@@ -312,7 +313,7 @@ export function Sidebar({
|
|
|
312
313
|
|
|
313
314
|
return wrap(
|
|
314
315
|
<aside
|
|
315
|
-
className={
|
|
316
|
+
className={cn("sh-ui-sidebar", className)}
|
|
316
317
|
data-state={state}
|
|
317
318
|
data-collapsible={state === "collapsed" ? collapsible : ""}
|
|
318
319
|
data-variant={variant}
|
|
@@ -351,9 +352,7 @@ function MobileSidebar({
|
|
|
351
352
|
)}
|
|
352
353
|
<aside
|
|
353
354
|
ref={asideRef}
|
|
354
|
-
className={
|
|
355
|
-
.filter(Boolean)
|
|
356
|
-
.join(" ")}
|
|
355
|
+
className={cn("sh-ui-sidebar", "sh-ui-sidebar--mobile", className)}
|
|
357
356
|
data-side={side}
|
|
358
357
|
data-state={openMobile ? "open" : "closed"}
|
|
359
358
|
role="dialog"
|
|
@@ -378,7 +377,7 @@ export function SidebarTrigger({ className, onClick, ...props }: SidebarTriggerP
|
|
|
378
377
|
<button
|
|
379
378
|
type="button"
|
|
380
379
|
aria-label="Toggle Sidebar"
|
|
381
|
-
className={
|
|
380
|
+
className={cn("sh-ui-sidebar__trigger", className)}
|
|
382
381
|
onClick={(e) => {
|
|
383
382
|
onClick?.(e);
|
|
384
383
|
toggleSidebar();
|
|
@@ -429,7 +428,7 @@ export function SidebarPanel({ id, className, children, ...props }: SidebarPanel
|
|
|
429
428
|
return (
|
|
430
429
|
<aside
|
|
431
430
|
ref={ref}
|
|
432
|
-
className={
|
|
431
|
+
className={cn("sh-ui-sidebar__panel", className)}
|
|
433
432
|
data-state={open ? "open" : "closed"}
|
|
434
433
|
role={isMobile ? "dialog" : undefined}
|
|
435
434
|
aria-modal={open && isMobile ? "true" : undefined}
|
|
@@ -453,7 +452,7 @@ export function SidebarPanel({ id, className, children, ...props }: SidebarPanel
|
|
|
453
452
|
export function SidebarPanelHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
454
453
|
return (
|
|
455
454
|
<div
|
|
456
|
-
className={
|
|
455
|
+
className={cn("sh-ui-sidebar__panel-header", className)}
|
|
457
456
|
{...props}
|
|
458
457
|
/>
|
|
459
458
|
);
|
|
@@ -463,7 +462,7 @@ export function SidebarPanelHeader({ className, ...props }: React.HTMLAttributes
|
|
|
463
462
|
export function SidebarPanelContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
464
463
|
return (
|
|
465
464
|
<div
|
|
466
|
-
className={
|
|
465
|
+
className={cn("sh-ui-sidebar__panel-content", className)}
|
|
467
466
|
{...props}
|
|
468
467
|
/>
|
|
469
468
|
);
|
|
@@ -475,7 +474,7 @@ export function SidebarPanelContent({ className, ...props }: React.HTMLAttribute
|
|
|
475
474
|
export function SidebarInset({ className, ...props }: React.HTMLAttributes<HTMLElement>) {
|
|
476
475
|
return (
|
|
477
476
|
<main
|
|
478
|
-
className={
|
|
477
|
+
className={cn("sh-ui-sidebar-inset", className)}
|
|
479
478
|
{...props}
|
|
480
479
|
/>
|
|
481
480
|
);
|
|
@@ -487,7 +486,7 @@ export function SidebarInset({ className, ...props }: React.HTMLAttributes<HTMLE
|
|
|
487
486
|
export function SidebarHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
488
487
|
return (
|
|
489
488
|
<div
|
|
490
|
-
className={
|
|
489
|
+
className={cn("sh-ui-sidebar__header", className)}
|
|
491
490
|
{...props}
|
|
492
491
|
/>
|
|
493
492
|
);
|
|
@@ -497,7 +496,7 @@ export function SidebarHeader({ className, ...props }: React.HTMLAttributes<HTML
|
|
|
497
496
|
export function SidebarFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
498
497
|
return (
|
|
499
498
|
<div
|
|
500
|
-
className={
|
|
499
|
+
className={cn("sh-ui-sidebar__footer", className)}
|
|
501
500
|
{...props}
|
|
502
501
|
/>
|
|
503
502
|
);
|
|
@@ -507,7 +506,7 @@ export function SidebarFooter({ className, ...props }: React.HTMLAttributes<HTML
|
|
|
507
506
|
export function SidebarContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
508
507
|
return (
|
|
509
508
|
<div
|
|
510
|
-
className={
|
|
509
|
+
className={cn("sh-ui-sidebar__content", className)}
|
|
511
510
|
{...props}
|
|
512
511
|
/>
|
|
513
512
|
);
|
|
@@ -517,7 +516,7 @@ export function SidebarContent({ className, ...props }: React.HTMLAttributes<HTM
|
|
|
517
516
|
export function SidebarSeparator({ className, ...props }: React.HTMLAttributes<HTMLHRElement>) {
|
|
518
517
|
return (
|
|
519
518
|
<hr
|
|
520
|
-
className={
|
|
519
|
+
className={cn("sh-ui-sidebar__separator", className)}
|
|
521
520
|
{...props}
|
|
522
521
|
/>
|
|
523
522
|
);
|
|
@@ -529,7 +528,7 @@ export function SidebarSeparator({ className, ...props }: React.HTMLAttributes<H
|
|
|
529
528
|
export function SidebarGroup({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
530
529
|
return (
|
|
531
530
|
<div
|
|
532
|
-
className={
|
|
531
|
+
className={cn("sh-ui-sidebar__group", className)}
|
|
533
532
|
{...props}
|
|
534
533
|
/>
|
|
535
534
|
);
|
|
@@ -539,7 +538,7 @@ export function SidebarGroup({ className, ...props }: React.HTMLAttributes<HTMLD
|
|
|
539
538
|
export function SidebarGroupLabel({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
540
539
|
return (
|
|
541
540
|
<div
|
|
542
|
-
className={
|
|
541
|
+
className={cn("sh-ui-sidebar__group-label", className)}
|
|
543
542
|
{...props}
|
|
544
543
|
/>
|
|
545
544
|
);
|
|
@@ -549,7 +548,7 @@ export function SidebarGroupLabel({ className, ...props }: React.HTMLAttributes<
|
|
|
549
548
|
export function SidebarGroupContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
550
549
|
return (
|
|
551
550
|
<div
|
|
552
|
-
className={
|
|
551
|
+
className={cn("sh-ui-sidebar__group-content", className)}
|
|
553
552
|
{...props}
|
|
554
553
|
/>
|
|
555
554
|
);
|
|
@@ -561,7 +560,7 @@ export function SidebarGroupContent({ className, ...props }: React.HTMLAttribute
|
|
|
561
560
|
export function SidebarMenu({ className, ...props }: React.HTMLAttributes<HTMLUListElement>) {
|
|
562
561
|
return (
|
|
563
562
|
<ul
|
|
564
|
-
className={
|
|
563
|
+
className={cn("sh-ui-sidebar__menu", className)}
|
|
565
564
|
{...props}
|
|
566
565
|
/>
|
|
567
566
|
);
|
|
@@ -571,7 +570,7 @@ export function SidebarMenu({ className, ...props }: React.HTMLAttributes<HTMLUL
|
|
|
571
570
|
export function SidebarMenuItem({ className, ...props }: React.HTMLAttributes<HTMLLIElement>) {
|
|
572
571
|
return (
|
|
573
572
|
<li
|
|
574
|
-
className={
|
|
573
|
+
className={cn("sh-ui-sidebar__menu-item", className)}
|
|
575
574
|
{...props}
|
|
576
575
|
/>
|
|
577
576
|
);
|
|
@@ -637,22 +636,16 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
637
636
|
[onClick, panelId, ctx]
|
|
638
637
|
);
|
|
639
638
|
|
|
640
|
-
const cls =
|
|
641
|
-
"sh-ui-sidebar__menu-button",
|
|
639
|
+
const cls = cn("sh-ui-sidebar__menu-button",
|
|
642
640
|
`sh-ui-sidebar__menu-button--${size}`,
|
|
643
|
-
className
|
|
644
|
-
]
|
|
645
|
-
.filter(Boolean)
|
|
646
|
-
.join(" ");
|
|
641
|
+
className);
|
|
647
642
|
|
|
648
643
|
if (asChild && React.isValidElement(children)) {
|
|
649
644
|
const child = children as React.ReactElement<Record<string, unknown>>;
|
|
650
645
|
const merged: Record<string, unknown> = {
|
|
651
646
|
...props,
|
|
652
647
|
onClick: handleClick,
|
|
653
|
-
className:
|
|
654
|
-
.filter(Boolean)
|
|
655
|
-
.join(" "),
|
|
648
|
+
className: cn((child.props.className as string) || "", cls),
|
|
656
649
|
"data-active": resolvedIsActive || undefined,
|
|
657
650
|
};
|
|
658
651
|
return React.cloneElement(child, merged);
|
|
@@ -679,7 +672,7 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
679
672
|
export function SidebarMenuSub({ className, ...props }: React.HTMLAttributes<HTMLUListElement>) {
|
|
680
673
|
return (
|
|
681
674
|
<ul
|
|
682
|
-
className={
|
|
675
|
+
className={cn("sh-ui-sidebar__menu-sub", className)}
|
|
683
676
|
{...props}
|
|
684
677
|
/>
|
|
685
678
|
);
|
|
@@ -689,7 +682,7 @@ export function SidebarMenuSub({ className, ...props }: React.HTMLAttributes<HTM
|
|
|
689
682
|
export function SidebarMenuSubItem({ className, ...props }: React.HTMLAttributes<HTMLLIElement>) {
|
|
690
683
|
return (
|
|
691
684
|
<li
|
|
692
|
-
className={
|
|
685
|
+
className={cn("sh-ui-sidebar__menu-sub-item", className)}
|
|
693
686
|
{...props}
|
|
694
687
|
/>
|
|
695
688
|
);
|
|
@@ -721,21 +714,15 @@ export const SidebarMenuSubButton = React.forwardRef<HTMLAnchorElement, SidebarM
|
|
|
721
714
|
const tocActive = useTOCActiveId();
|
|
722
715
|
const resolvedIsActive =
|
|
723
716
|
isActive ?? (sectionId != null ? tocActive === sectionId : undefined);
|
|
724
|
-
const cls =
|
|
725
|
-
"sh-ui-sidebar__menu-sub-button",
|
|
717
|
+
const cls = cn("sh-ui-sidebar__menu-sub-button",
|
|
726
718
|
`sh-ui-sidebar__menu-sub-button--${size}`,
|
|
727
|
-
className
|
|
728
|
-
]
|
|
729
|
-
.filter(Boolean)
|
|
730
|
-
.join(" ");
|
|
719
|
+
className);
|
|
731
720
|
|
|
732
721
|
if (asChild && React.isValidElement(children)) {
|
|
733
722
|
const child = children as React.ReactElement<Record<string, unknown>>;
|
|
734
723
|
const merged: Record<string, unknown> = {
|
|
735
724
|
...props,
|
|
736
|
-
className:
|
|
737
|
-
.filter(Boolean)
|
|
738
|
-
.join(" "),
|
|
725
|
+
className: cn((child.props.className as string) || "", cls),
|
|
739
726
|
"data-active": resolvedIsActive || undefined,
|
|
740
727
|
};
|
|
741
728
|
return React.cloneElement(child, merged);
|
|
@@ -859,14 +846,10 @@ export function SidebarCollapsibleTrigger({
|
|
|
859
846
|
}: SidebarCollapsibleTriggerProps) {
|
|
860
847
|
const { open, toggle, flyoutMode, flyoutOpen } = useCollapsible();
|
|
861
848
|
|
|
862
|
-
const cls =
|
|
863
|
-
"sh-ui-sidebar__menu-button",
|
|
849
|
+
const cls = cn("sh-ui-sidebar__menu-button",
|
|
864
850
|
`sh-ui-sidebar__menu-button--${size}`,
|
|
865
851
|
"sh-ui-sidebar__collapsible-trigger",
|
|
866
|
-
className
|
|
867
|
-
]
|
|
868
|
-
.filter(Boolean)
|
|
869
|
-
.join(" ");
|
|
852
|
+
className);
|
|
870
853
|
|
|
871
854
|
const isOpen = flyoutMode ? flyoutOpen : open;
|
|
872
855
|
|
|
@@ -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
|
/**
|
|
8
6
|
* 로딩 중 콘텐츠 자리를 채우는 placeholder 박스 (Tailwind utility 변종).
|
|
9
7
|
* `aria-hidden`이 기본 적용되므로 스크린리더에 노출되지 않는다.
|
|
@@ -15,7 +13,7 @@ export const Skeleton = React.forwardRef<
|
|
|
15
13
|
<div
|
|
16
14
|
ref={ref}
|
|
17
15
|
aria-hidden="true"
|
|
18
|
-
className={
|
|
16
|
+
className={cn(
|
|
19
17
|
"block w-full h-4 bg-background-muted rounded-[calc(var(--radius)-2px)] animate-[sh-ui-skeleton-pulse_1.6s_ease-in-out_infinite] motion-reduce:animate-none",
|
|
20
18
|
className,
|
|
21
19
|
)}
|
|
@@ -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
|
/**
|
|
9
7
|
* 로딩 중 콘텐츠 자리를 채우는 placeholder 박스. 폭/높이는 인라인 스타일이나
|
|
10
8
|
* 클래스로 직접 지정한다. `aria-hidden`이 기본 적용되므로 스크린리더에 노출되지
|
|
@@ -17,7 +15,7 @@ export const Skeleton = React.forwardRef<
|
|
|
17
15
|
<div
|
|
18
16
|
ref={ref}
|
|
19
17
|
aria-hidden="true"
|
|
20
|
-
className={
|
|
18
|
+
className={cn("sh-ui-skeleton", className)}
|
|
21
19
|
{...props}
|
|
22
20
|
/>
|
|
23
21
|
));
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
5
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
6
|
-
return args.filter(Boolean).join(" ");
|
|
7
|
-
}
|
|
8
5
|
|
|
6
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
9
7
|
function clamp(n: number, min: number, max: number) {
|
|
10
8
|
return Math.min(max, Math.max(min, n));
|
|
11
9
|
}
|
|
@@ -109,7 +107,7 @@ export const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
|
|
109
107
|
<div
|
|
110
108
|
ref={ref}
|
|
111
109
|
{...rest}
|
|
112
|
-
className={
|
|
110
|
+
className={cn(
|
|
113
111
|
"relative w-full py-[var(--space-2)] select-none",
|
|
114
112
|
disabled && "opacity-[var(--opacity-disabled)] pointer-events-none",
|
|
115
113
|
className,
|
|
@@ -171,7 +169,7 @@ export const SliderTrack = React.forwardRef<HTMLDivElement, React.HTMLAttributes
|
|
|
171
169
|
return (
|
|
172
170
|
<div
|
|
173
171
|
ref={mergedRef}
|
|
174
|
-
className={
|
|
172
|
+
className={cn(
|
|
175
173
|
"relative w-full h-1.5 bg-background-muted rounded-full cursor-pointer touch-none",
|
|
176
174
|
className,
|
|
177
175
|
)}
|
|
@@ -196,7 +194,7 @@ export const SliderRange = React.forwardRef<HTMLDivElement, React.HTMLAttributes
|
|
|
196
194
|
return (
|
|
197
195
|
<div
|
|
198
196
|
ref={ref}
|
|
199
|
-
className={
|
|
197
|
+
className={cn(
|
|
200
198
|
"absolute top-0 left-0 h-full bg-primary rounded-full pointer-events-none",
|
|
201
199
|
className,
|
|
202
200
|
)}
|
|
@@ -243,7 +241,7 @@ export const SliderThumb = React.forwardRef<
|
|
|
243
241
|
aria-valuenow={value}
|
|
244
242
|
aria-disabled={disabled || undefined}
|
|
245
243
|
onKeyDown={onKeyDown}
|
|
246
|
-
className={
|
|
244
|
+
className={cn(
|
|
247
245
|
"absolute top-1/2 w-4 h-4 -ml-2 -translate-y-1/2 bg-background border-2 border-primary rounded-full shadow-[0_1px_2px_rgba(0,0,0,0.1)] cursor-grab transition-transform duration-[80ms] active:cursor-grabbing active:scale-110 active:-translate-y-1/2 focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 [@media(hover:none)_and_(pointer:coarse)]:w-5 [@media(hover:none)_and_(pointer:coarse)]:h-5 [@media(hover:none)_and_(pointer:coarse)]:-ml-2.5",
|
|
248
246
|
className,
|
|
249
247
|
)}
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import "./styles.css";
|
|
5
5
|
|
|
6
|
-
function cx(...args: (string | undefined | false | null)[]) {
|
|
7
|
-
return args.filter(Boolean).join(" ");
|
|
8
|
-
}
|
|
9
6
|
|
|
7
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
10
8
|
function clamp(n: number, min: number, max: number) {
|
|
11
9
|
return Math.min(max, Math.max(min, n));
|
|
12
10
|
}
|
|
@@ -128,7 +126,7 @@ export const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
|
|
128
126
|
<div
|
|
129
127
|
ref={ref}
|
|
130
128
|
{...rest}
|
|
131
|
-
className={
|
|
129
|
+
className={cn(
|
|
132
130
|
"sh-ui-slider",
|
|
133
131
|
disabled && "sh-ui-slider--disabled",
|
|
134
132
|
className,
|
|
@@ -199,7 +197,7 @@ export const SliderTrack = React.forwardRef<
|
|
|
199
197
|
return (
|
|
200
198
|
<div
|
|
201
199
|
ref={mergedRef}
|
|
202
|
-
className={
|
|
200
|
+
className={cn("sh-ui-slider__track", className)}
|
|
203
201
|
onPointerDown={onPointerDown}
|
|
204
202
|
{...props}
|
|
205
203
|
>
|
|
@@ -225,7 +223,7 @@ export const SliderRange = React.forwardRef<
|
|
|
225
223
|
return (
|
|
226
224
|
<div
|
|
227
225
|
ref={ref}
|
|
228
|
-
className={
|
|
226
|
+
className={cn("sh-ui-slider__range", className)}
|
|
229
227
|
style={{ width: percent, ...style }}
|
|
230
228
|
{...props}
|
|
231
229
|
/>
|
|
@@ -291,7 +289,7 @@ export const SliderThumb = React.forwardRef<
|
|
|
291
289
|
aria-valuenow={value}
|
|
292
290
|
aria-disabled={disabled || undefined}
|
|
293
291
|
onKeyDown={onKeyDown}
|
|
294
|
-
className={
|
|
292
|
+
className={cn("sh-ui-slider__thumb", className)}
|
|
295
293
|
style={{ left: percent, ...style }}
|
|
296
294
|
{...props}
|
|
297
295
|
/>
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
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
|
const spinnerVariants = cva(
|
|
9
7
|
"inline-flex items-center justify-center align-middle text-current",
|
|
10
8
|
{
|
|
@@ -39,12 +37,12 @@ export const Spinner = React.forwardRef<HTMLSpanElement, SpinnerProps>(
|
|
|
39
37
|
role="status"
|
|
40
38
|
aria-live="polite"
|
|
41
39
|
aria-label={ariaLabel}
|
|
42
|
-
className={
|
|
40
|
+
className={cn(spinnerVariants({ size }), className)}
|
|
43
41
|
{...props}
|
|
44
42
|
>
|
|
45
43
|
<span
|
|
46
44
|
aria-hidden
|
|
47
|
-
className={
|
|
45
|
+
className={cn(
|
|
48
46
|
"inline-block w-full h-full rounded-full border-current border-t-transparent opacity-80 animate-[sh-ui-spinner-rotate_0.8s_linear_infinite] motion-reduce:[animation-duration:3s]",
|
|
49
47
|
ringBorder,
|
|
50
48
|
)}
|
|
@@ -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 SpinnerSize = "sm" | "md" | "lg";
|
|
9
7
|
|
|
10
8
|
export interface SpinnerProps
|
|
@@ -29,7 +27,7 @@ export const Spinner = React.forwardRef<HTMLSpanElement, SpinnerProps>(
|
|
|
29
27
|
role="status"
|
|
30
28
|
aria-live="polite"
|
|
31
29
|
aria-label={ariaLabel}
|
|
32
|
-
className={
|
|
30
|
+
className={cn("sh-ui-spinner", `sh-ui-spinner--${size}`, className)}
|
|
33
31
|
{...props}
|
|
34
32
|
>
|
|
35
33
|
<span className="sh-ui-spinner__ring" aria-hidden />
|
|
@@ -2,10 +2,8 @@ import * as React from "react";
|
|
|
2
2
|
import { Switch as BaseSwitch } from "@base-ui/react/switch";
|
|
3
3
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
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
|
const switchRoot = cva(
|
|
10
8
|
"inline-flex items-center border-none rounded-full bg-background-muted cursor-pointer shrink-0 p-0.5 transition-colors duration-150 hover:not-data-[disabled]:bg-border-strong focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 data-[checked]:bg-primary data-[checked]:hover:not-data-[disabled]:bg-primary-hover data-[disabled]:opacity-[var(--opacity-disabled)] data-[disabled]:cursor-not-allowed motion-reduce:transition-none",
|
|
11
9
|
{
|
|
@@ -46,11 +44,11 @@ export const Switch = React.forwardRef<HTMLElement, SwitchProps>(
|
|
|
46
44
|
({ className, size = "md", ...props }, ref) => (
|
|
47
45
|
<BaseSwitch.Root
|
|
48
46
|
ref={ref}
|
|
49
|
-
className={
|
|
47
|
+
className={cn(switchRoot({ size }), className)}
|
|
50
48
|
{...props}
|
|
51
49
|
>
|
|
52
50
|
<BaseSwitch.Thumb
|
|
53
|
-
className={
|
|
51
|
+
className={cn(
|
|
54
52
|
switchThumb({ size }),
|
|
55
53
|
size === "sm" && "data-[checked]:translate-x-3.5",
|
|
56
54
|
size === "md" && "data-[checked]:translate-x-[1.125rem]",
|
|
@@ -2,10 +2,8 @@ import * as React from "react";
|
|
|
2
2
|
import { Switch as BaseSwitch } from "@base-ui/react/switch";
|
|
3
3
|
import "./styles.css";
|
|
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
|
/* ───────────── Switch ───────────── */
|
|
10
8
|
|
|
11
9
|
export type SwitchProps = Omit<
|
|
@@ -31,7 +29,7 @@ export const Switch = React.forwardRef<HTMLElement, SwitchProps>(
|
|
|
31
29
|
({ className, size = "md", ...props }, ref) => (
|
|
32
30
|
<BaseSwitch.Root
|
|
33
31
|
ref={ref}
|
|
34
|
-
className={
|
|
32
|
+
className={cn("sh-ui-switch", `sh-ui-switch--${size}`, className)}
|
|
35
33
|
{...props}
|
|
36
34
|
>
|
|
37
35
|
<BaseSwitch.Thumb className="sh-ui-switch__thumb" />
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
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
|
type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
|
|
11
9
|
|
|
12
10
|
export type TabsVariant = "underline" | "pill" | "plain";
|
|
@@ -26,7 +24,7 @@ export const Tabs = React.forwardRef<HTMLDivElement, TabsProps>(
|
|
|
26
24
|
<BaseTabs.Root
|
|
27
25
|
ref={ref}
|
|
28
26
|
data-variant={variant}
|
|
29
|
-
className={
|
|
27
|
+
className={cn("flex flex-col gap-[var(--space-3)] w-full data-[orientation=vertical]:flex-row", className)}
|
|
30
28
|
{...props}
|
|
31
29
|
/>
|
|
32
30
|
</TabsContext.Provider>
|
|
@@ -46,7 +44,7 @@ export const TabsList = React.forwardRef<
|
|
|
46
44
|
<BaseTabs.List
|
|
47
45
|
ref={ref}
|
|
48
46
|
data-variant={variant}
|
|
49
|
-
className={
|
|
47
|
+
className={cn(
|
|
50
48
|
"relative inline-flex items-center gap-[var(--space-1)] w-fit",
|
|
51
49
|
listVariantClasses,
|
|
52
50
|
className,
|
|
@@ -66,7 +64,7 @@ export const TabsTrigger = React.forwardRef<
|
|
|
66
64
|
>(({ className, ...props }, ref) => (
|
|
67
65
|
<BaseTabs.Tab
|
|
68
66
|
ref={ref}
|
|
69
|
-
className={
|
|
67
|
+
className={cn(
|
|
70
68
|
"relative z-[1] inline-flex items-center justify-center gap-1.5 py-[var(--space-2)] px-[var(--space-3)] bg-transparent text-foreground-muted border-0 text-[length:var(--text-sm)] font-medium leading-none cursor-pointer transition-[color,background-color] duration-[var(--duration-fast)] select-none whitespace-nowrap hover:not-disabled:not-data-[selected]:text-foreground focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 data-[selected]:text-foreground disabled:opacity-[var(--opacity-disabled)] disabled:cursor-not-allowed",
|
|
71
69
|
triggerVariantClasses,
|
|
72
70
|
className,
|
|
@@ -85,7 +83,7 @@ export const TabsIndicator = React.forwardRef<
|
|
|
85
83
|
>(({ className, ...props }, ref) => (
|
|
86
84
|
<BaseTabs.Indicator
|
|
87
85
|
ref={ref}
|
|
88
|
-
className={
|
|
86
|
+
className={cn(
|
|
89
87
|
"absolute z-0 pointer-events-none transition-[top,left,width,height] duration-[180ms] data-[activation-direction=none]:transition-none top-[var(--active-tab-top)] left-[var(--active-tab-left)] w-[var(--active-tab-width)] h-[var(--active-tab-height)]",
|
|
90
88
|
indicatorVariantClasses,
|
|
91
89
|
className,
|
|
@@ -101,7 +99,7 @@ export const TabsContent = React.forwardRef<
|
|
|
101
99
|
>(({ className, ...props }, ref) => (
|
|
102
100
|
<BaseTabs.Panel
|
|
103
101
|
ref={ref}
|
|
104
|
-
className={
|
|
102
|
+
className={cn(
|
|
105
103
|
"outline-none focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 focus-visible:rounded-[var(--radius)]",
|
|
106
104
|
className,
|
|
107
105
|
)}
|
|
@@ -4,10 +4,8 @@ import * as React from "react";
|
|
|
4
4
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
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
|
type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
|
|
12
10
|
|
|
13
11
|
export type TabsVariant = "underline" | "pill" | "plain";
|
|
@@ -41,7 +39,7 @@ export const Tabs = React.forwardRef<HTMLDivElement, TabsProps>(
|
|
|
41
39
|
<BaseTabs.Root
|
|
42
40
|
ref={ref}
|
|
43
41
|
data-variant={variant}
|
|
44
|
-
className={
|
|
42
|
+
className={cn("sh-ui-tabs", className)}
|
|
45
43
|
{...props}
|
|
46
44
|
/>
|
|
47
45
|
</TabsContext.Provider>
|
|
@@ -54,7 +52,7 @@ export const TabsList = React.forwardRef<
|
|
|
54
52
|
HTMLDivElement,
|
|
55
53
|
WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseTabs.List>>
|
|
56
54
|
>(({ className, ...props }, ref) => (
|
|
57
|
-
<BaseTabs.List ref={ref} className={
|
|
55
|
+
<BaseTabs.List ref={ref} className={cn("sh-ui-tabs__list", className)} {...props} />
|
|
58
56
|
));
|
|
59
57
|
TabsList.displayName = "TabsList";
|
|
60
58
|
|
|
@@ -63,7 +61,7 @@ export const TabsTrigger = React.forwardRef<
|
|
|
63
61
|
HTMLButtonElement,
|
|
64
62
|
WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseTabs.Tab>>
|
|
65
63
|
>(({ className, ...props }, ref) => (
|
|
66
|
-
<BaseTabs.Tab ref={ref} className={
|
|
64
|
+
<BaseTabs.Tab ref={ref} className={cn("sh-ui-tabs__trigger", className)} {...props} />
|
|
67
65
|
));
|
|
68
66
|
TabsTrigger.displayName = "TabsTrigger";
|
|
69
67
|
|
|
@@ -74,7 +72,7 @@ export const TabsIndicator = React.forwardRef<
|
|
|
74
72
|
>(({ className, ...props }, ref) => (
|
|
75
73
|
<BaseTabs.Indicator
|
|
76
74
|
ref={ref}
|
|
77
|
-
className={
|
|
75
|
+
className={cn("sh-ui-tabs__indicator", className)}
|
|
78
76
|
{...props}
|
|
79
77
|
/>
|
|
80
78
|
));
|
|
@@ -85,7 +83,7 @@ export const TabsContent = React.forwardRef<
|
|
|
85
83
|
HTMLDivElement,
|
|
86
84
|
WithStringClassName<React.ComponentPropsWithoutRef<typeof BaseTabs.Panel>>
|
|
87
85
|
>(({ className, ...props }, ref) => (
|
|
88
|
-
<BaseTabs.Panel ref={ref} className={
|
|
86
|
+
<BaseTabs.Panel ref={ref} className={cn("sh-ui-tabs__content", className)} {...props} />
|
|
89
87
|
));
|
|
90
88
|
TabsContent.displayName = "TabsContent";
|
|
91
89
|
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
3
4
|
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
|
4
5
|
|
|
5
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
6
|
-
return args.filter(Boolean).join(" ");
|
|
7
|
-
}
|
|
8
6
|
|
|
9
7
|
export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
10
8
|
({ className, ...props }, ref) => (
|
|
11
9
|
<textarea
|
|
12
10
|
ref={ref}
|
|
13
|
-
className={
|
|
11
|
+
className={cn(
|
|
14
12
|
"block w-full min-h-20 px-[var(--space-3)] py-[var(--space-2)] bg-background text-foreground border border-border rounded-[var(--radius)] font-[inherit] text-[length:var(--text-sm)] leading-normal resize-y transition-[border-color,box-shadow] duration-[var(--duration-fast)] placeholder:text-foreground-subtle hover:not-disabled:not-focus:border-border-strong focus:outline-none focus:border-foreground focus:shadow-[0_0_0_1px_var(--foreground)] disabled:opacity-[var(--opacity-disabled)] disabled:cursor-not-allowed disabled:bg-background-subtle read-only:bg-background-subtle aria-[invalid=true]:border-danger aria-[invalid=true]:focus:shadow-[0_0_0_1px_var(--danger)] [@media(hover:none)_and_(pointer:coarse)]:text-[length:var(--text-base)]",
|
|
15
13
|
className,
|
|
16
14
|
)}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import "./styles.css";
|
|
3
3
|
|
|
4
|
+
import { cn } from "@SH_UI_UTILS@";
|
|
4
5
|
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
|
5
6
|
|
|
6
|
-
function cx(...args: (string | undefined | false)[]) {
|
|
7
|
-
return args.filter(Boolean).join(" ");
|
|
8
|
-
}
|
|
9
7
|
|
|
10
8
|
/**
|
|
11
9
|
* 여러 줄 텍스트 입력. 네이티브 `<textarea>` 위에 sh-ui 토큰 스타일만 입혔다.
|
|
@@ -16,7 +14,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
|
16
14
|
return (
|
|
17
15
|
<textarea
|
|
18
16
|
ref={ref}
|
|
19
|
-
className={
|
|
17
|
+
className={cn("sh-ui-textarea", className)}
|
|
20
18
|
{...props}
|
|
21
19
|
/>
|
|
22
20
|
);
|