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,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
|
|
|
@@ -116,14 +117,12 @@ export function SidebarProvider({
|
|
|
116
117
|
return (
|
|
117
118
|
<SidebarContext.Provider value={value}>
|
|
118
119
|
<div
|
|
119
|
-
className={[
|
|
120
|
-
"[--sidebar-width:16rem] [--sidebar-width-icon:3rem] [--sidebar-width-mobile:18rem]",
|
|
120
|
+
className={cn("[--sidebar-width:16rem] [--sidebar-width-icon:3rem] [--sidebar-width-mobile:18rem]",
|
|
121
121
|
"[--sidebar-bg:var(--background-subtle)] [--sidebar-fg:var(--foreground)] [--sidebar-border:var(--border)]",
|
|
122
122
|
"[--sidebar-accent:var(--background-muted)] [--sidebar-accent-fg:var(--foreground)]",
|
|
123
123
|
"flex w-full",
|
|
124
124
|
embedded ? "min-h-0 h-full" : "min-h-[100svh]",
|
|
125
|
-
className
|
|
126
|
-
].filter(Boolean).join(" ")}
|
|
125
|
+
className)}
|
|
127
126
|
style={style}
|
|
128
127
|
data-embedded={embedded || undefined}
|
|
129
128
|
data-panel-open={activePanel ? "true" : undefined}
|
|
@@ -160,7 +159,7 @@ export function Sidebar({ side = "left", variant = "sidebar", collapsible = "off
|
|
|
160
159
|
if (collapsible === "none") {
|
|
161
160
|
return wrap(
|
|
162
161
|
<aside
|
|
163
|
-
className={
|
|
162
|
+
className={cn(sidebarRoot, "h-[100svh] sticky top-0", className)}
|
|
164
163
|
data-side={side}
|
|
165
164
|
data-variant={variant}
|
|
166
165
|
{...props}
|
|
@@ -180,7 +179,7 @@ export function Sidebar({ side = "left", variant = "sidebar", collapsible = "off
|
|
|
180
179
|
|
|
181
180
|
return wrap(
|
|
182
181
|
<aside
|
|
183
|
-
className={
|
|
182
|
+
className={cn(sidebarRoot, className)}
|
|
184
183
|
data-state={state}
|
|
185
184
|
data-collapsible={state === "collapsed" ? collapsible : ""}
|
|
186
185
|
data-variant={variant}
|
|
@@ -208,13 +207,11 @@ function MobileSidebar({ side, className, openMobile, setOpenMobile, children, .
|
|
|
208
207
|
)}
|
|
209
208
|
<aside
|
|
210
209
|
ref={asideRef}
|
|
211
|
-
className={[
|
|
212
|
-
"fixed top-0 bottom-0 w-[var(--sidebar-width-mobile)] z-[var(--z-overlay)] transition-transform duration-[var(--duration-slow)] flex flex-col bg-[var(--sidebar-bg)] text-[var(--sidebar-fg)] motion-reduce:transition-none",
|
|
210
|
+
className={cn("fixed top-0 bottom-0 w-[var(--sidebar-width-mobile)] z-[var(--z-overlay)] transition-transform duration-[var(--duration-slow)] flex flex-col bg-[var(--sidebar-bg)] text-[var(--sidebar-fg)] motion-reduce:transition-none",
|
|
213
211
|
side === "left"
|
|
214
212
|
? "left-0 border-r border-[var(--sidebar-border)] data-[state=open]:translate-x-0 data-[state=closed]:-translate-x-full"
|
|
215
213
|
: "right-0 border-l border-[var(--sidebar-border)] data-[state=open]:translate-x-0 data-[state=closed]:translate-x-full",
|
|
216
|
-
className
|
|
217
|
-
].filter(Boolean).join(" ")}
|
|
214
|
+
className)}
|
|
218
215
|
data-side={side}
|
|
219
216
|
data-state={openMobile ? "open" : "closed"}
|
|
220
217
|
role="dialog"
|
|
@@ -236,10 +233,8 @@ export function SidebarTrigger({ className, onClick, ...props }: SidebarTriggerP
|
|
|
236
233
|
<button
|
|
237
234
|
type="button"
|
|
238
235
|
aria-label="Toggle Sidebar"
|
|
239
|
-
className={[
|
|
240
|
-
|
|
241
|
-
className,
|
|
242
|
-
].filter(Boolean).join(" ")}
|
|
236
|
+
className={cn("inline-flex items-center justify-center w-8 h-8 border border-transparent bg-transparent text-foreground-muted rounded-[calc(var(--radius)-2px)] cursor-pointer transition-[background-color,color,border-color] duration-[var(--duration-fast)] hover:bg-[var(--sidebar-accent)] hover:text-foreground focus-visible:outline-[length:var(--border-width-strong)] focus-visible:outline-foreground focus-visible:outline-offset-2 motion-reduce:transition-none",
|
|
237
|
+
className)}
|
|
243
238
|
onClick={(e) => { onClick?.(e); toggleSidebar(); }}
|
|
244
239
|
{...props}
|
|
245
240
|
>
|
|
@@ -267,10 +262,8 @@ export function SidebarPanel({ id, className, children, ...props }: SidebarPanel
|
|
|
267
262
|
return (
|
|
268
263
|
<aside
|
|
269
264
|
ref={ref}
|
|
270
|
-
className={[
|
|
271
|
-
|
|
272
|
-
className,
|
|
273
|
-
].filter(Boolean).join(" ")}
|
|
265
|
+
className={cn("[--sidebar-panel-width:20rem] flex flex-col w-[var(--sidebar-panel-width)] shrink-0 bg-background border-r border-[var(--sidebar-border)] relative z-[4] overflow-hidden animate-[sh-ui-sidebar-panel-in_180ms_ease-out] data-[state=closed]:hidden max-md:fixed max-md:top-0 max-md:bottom-0 max-md:left-0 max-md:w-[min(var(--sidebar-panel-width),90vw)] max-md:z-[var(--z-modal)] max-md:shadow-[0_10px_30px_rgba(0,0,0,0.15)] motion-reduce:animate-none",
|
|
266
|
+
className)}
|
|
274
267
|
data-state={open ? "open" : "closed"}
|
|
275
268
|
role={isMobile ? "dialog" : undefined}
|
|
276
269
|
aria-modal={open && isMobile ? "true" : undefined}
|
|
@@ -293,7 +286,7 @@ export function SidebarPanel({ id, className, children, ...props }: SidebarPanel
|
|
|
293
286
|
export function SidebarPanelHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
294
287
|
return (
|
|
295
288
|
<div
|
|
296
|
-
className={
|
|
289
|
+
className={cn("flex items-center gap-[var(--space-2)] py-3.5 px-[var(--space-4)] border-b border-[var(--sidebar-border)] font-semibold text-[0.9375rem]", className)}
|
|
297
290
|
{...props}
|
|
298
291
|
/>
|
|
299
292
|
);
|
|
@@ -302,58 +295,56 @@ export function SidebarPanelHeader({ className, ...props }: React.HTMLAttributes
|
|
|
302
295
|
export function SidebarPanelContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
303
296
|
return (
|
|
304
297
|
<div
|
|
305
|
-
className={
|
|
298
|
+
className={cn("flex-1 min-h-0 overflow-y-auto py-[var(--space-3)] px-[var(--space-4)] pb-[var(--space-4)]", className)}
|
|
306
299
|
{...props}
|
|
307
300
|
/>
|
|
308
301
|
);
|
|
309
302
|
}
|
|
310
303
|
|
|
311
304
|
export function SidebarInset({ className, ...props }: React.HTMLAttributes<HTMLElement>) {
|
|
312
|
-
return <main className={
|
|
305
|
+
return <main className={cn("flex-1 min-w-0 bg-background flex flex-col", className)} {...props} />;
|
|
313
306
|
}
|
|
314
307
|
|
|
315
308
|
export function SidebarHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
316
|
-
return <div className={
|
|
309
|
+
return <div className={cn("flex flex-col gap-[var(--space-2)] p-[var(--space-2)] overflow-hidden", className)} {...props} />;
|
|
317
310
|
}
|
|
318
311
|
|
|
319
312
|
export function SidebarFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
320
|
-
return <div className={
|
|
313
|
+
return <div className={cn("flex flex-col gap-[var(--space-2)] p-[var(--space-2)] overflow-hidden", className)} {...props} />;
|
|
321
314
|
}
|
|
322
315
|
|
|
323
316
|
export function SidebarContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
324
|
-
return <div className={
|
|
317
|
+
return <div className={cn("flex flex-col flex-1 min-h-0 overflow-y-auto gap-0", className)} {...props} />;
|
|
325
318
|
}
|
|
326
319
|
|
|
327
320
|
export function SidebarSeparator({ className, ...props }: React.HTMLAttributes<HTMLHRElement>) {
|
|
328
|
-
return <hr className={
|
|
321
|
+
return <hr className={cn("my-[var(--space-1)] mx-[var(--space-2)] border-0 border-t border-[var(--sidebar-border)] w-auto", className)} {...props} />;
|
|
329
322
|
}
|
|
330
323
|
|
|
331
324
|
export function SidebarGroup({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
332
|
-
return <div className={
|
|
325
|
+
return <div className={cn("flex flex-col p-[var(--space-2)] min-w-0", className)} {...props} />;
|
|
333
326
|
}
|
|
334
327
|
|
|
335
328
|
export function SidebarGroupLabel({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
336
329
|
return (
|
|
337
330
|
<div
|
|
338
|
-
className={[
|
|
339
|
-
|
|
340
|
-
className,
|
|
341
|
-
].filter(Boolean).join(" ")}
|
|
331
|
+
className={cn("flex items-center h-8 px-[var(--space-2)] text-[length:var(--text-xs)] font-medium text-foreground-muted rounded-[calc(var(--radius)-2px)] [[data-state=collapsed][data-collapsible=icon]_&]:hidden",
|
|
332
|
+
className)}
|
|
342
333
|
{...props}
|
|
343
334
|
/>
|
|
344
335
|
);
|
|
345
336
|
}
|
|
346
337
|
|
|
347
338
|
export function SidebarGroupContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
348
|
-
return <div className={
|
|
339
|
+
return <div className={cn("w-full text-[length:var(--text-sm)]", className)} {...props} />;
|
|
349
340
|
}
|
|
350
341
|
|
|
351
342
|
export function SidebarMenu({ className, ...props }: React.HTMLAttributes<HTMLUListElement>) {
|
|
352
|
-
return <ul className={
|
|
343
|
+
return <ul className={cn("list-none m-0 p-0 flex flex-col min-w-0 gap-0", className)} {...props} />;
|
|
353
344
|
}
|
|
354
345
|
|
|
355
346
|
export function SidebarMenuItem({ className, ...props }: React.HTMLAttributes<HTMLLIElement>) {
|
|
356
|
-
return <li className={
|
|
347
|
+
return <li className={cn("relative m-0", className)} {...props} />;
|
|
357
348
|
}
|
|
358
349
|
|
|
359
350
|
export interface SidebarMenuButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
@@ -385,14 +376,14 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
385
376
|
if (!e.defaultPrevented && panelId != null && ctx) ctx.setActivePanel(panelId);
|
|
386
377
|
}, [onClick, panelId, ctx]);
|
|
387
378
|
|
|
388
|
-
const cls =
|
|
379
|
+
const cls = cn(menuButtonBase, menuButtonSize[size], className);
|
|
389
380
|
|
|
390
381
|
if (asChild && React.isValidElement(children)) {
|
|
391
382
|
const child = children as React.ReactElement<Record<string, unknown>>;
|
|
392
383
|
const merged: Record<string, unknown> = {
|
|
393
384
|
...props,
|
|
394
385
|
onClick: handleClick,
|
|
395
|
-
className:
|
|
386
|
+
className: cn((child.props.className as string) || "", cls),
|
|
396
387
|
"data-active": resolvedIsActive || undefined,
|
|
397
388
|
};
|
|
398
389
|
return React.cloneElement(child, merged);
|
|
@@ -409,17 +400,15 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
409
400
|
export function SidebarMenuSub({ className, ...props }: React.HTMLAttributes<HTMLUListElement>) {
|
|
410
401
|
return (
|
|
411
402
|
<ul
|
|
412
|
-
className={[
|
|
413
|
-
|
|
414
|
-
className,
|
|
415
|
-
].filter(Boolean).join(" ")}
|
|
403
|
+
className={cn("list-none mt-0.5 ml-3.5 pt-0.5 pr-0 pb-0.5 pl-2.5 border-l border-[var(--sidebar-border)] flex flex-col gap-0.5 min-w-0 [[data-state=collapsed][data-collapsible=icon]_&]:hidden",
|
|
404
|
+
className)}
|
|
416
405
|
{...props}
|
|
417
406
|
/>
|
|
418
407
|
);
|
|
419
408
|
}
|
|
420
409
|
|
|
421
410
|
export function SidebarMenuSubItem({ className, ...props }: React.HTMLAttributes<HTMLLIElement>) {
|
|
422
|
-
return <li className={
|
|
411
|
+
return <li className={cn("relative", className)} {...props} />;
|
|
423
412
|
}
|
|
424
413
|
|
|
425
414
|
export interface SidebarMenuSubButtonProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
@@ -436,13 +425,13 @@ export const SidebarMenuSubButton = React.forwardRef<HTMLAnchorElement, SidebarM
|
|
|
436
425
|
function SidebarMenuSubButton({ className, isActive, size = "md", asChild, sectionId, children, ...props }, ref) {
|
|
437
426
|
const tocActive = useTOCActiveId();
|
|
438
427
|
const resolvedIsActive = isActive ?? (sectionId != null ? tocActive === sectionId : undefined);
|
|
439
|
-
const cls =
|
|
428
|
+
const cls = cn(menuSubButtonBase, size === "sm" && "text-[length:var(--text-xs)]", className);
|
|
440
429
|
|
|
441
430
|
if (asChild && React.isValidElement(children)) {
|
|
442
431
|
const child = children as React.ReactElement<Record<string, unknown>>;
|
|
443
432
|
const merged: Record<string, unknown> = {
|
|
444
433
|
...props,
|
|
445
|
-
className:
|
|
434
|
+
className: cn((child.props.className as string) || "", cls),
|
|
446
435
|
"data-active": resolvedIsActive || undefined,
|
|
447
436
|
};
|
|
448
437
|
return React.cloneElement(child, merged);
|
|
@@ -503,7 +492,7 @@ export interface SidebarCollapsibleTriggerProps extends React.ButtonHTMLAttribut
|
|
|
503
492
|
|
|
504
493
|
export function SidebarCollapsibleTrigger({ className, size = "md", children, onClick, ...props }: SidebarCollapsibleTriggerProps) {
|
|
505
494
|
const { open, toggle, flyoutMode, flyoutOpen } = useCollapsible();
|
|
506
|
-
const cls =
|
|
495
|
+
const cls = cn(menuButtonBase, menuButtonSize[size], className);
|
|
507
496
|
const isOpen = flyoutMode ? flyoutOpen : open;
|
|
508
497
|
|
|
509
498
|
const content = (
|
|
@@ -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 />
|