@sntlr/registry-shell 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -0
  3. package/dist/adapter/custom.d.ts +47 -0
  4. package/dist/adapter/custom.js +53 -0
  5. package/dist/adapter/custom.js.map +1 -0
  6. package/dist/adapter/default.d.ts +40 -0
  7. package/dist/adapter/default.js +202 -0
  8. package/dist/adapter/default.js.map +1 -0
  9. package/dist/cli/build.d.ts +1 -0
  10. package/dist/cli/build.js +31 -0
  11. package/dist/cli/build.js.map +1 -0
  12. package/dist/cli/dev.d.ts +1 -0
  13. package/dist/cli/dev.js +26 -0
  14. package/dist/cli/dev.js.map +1 -0
  15. package/dist/cli/index.d.ts +12 -0
  16. package/dist/cli/index.js +49 -0
  17. package/dist/cli/index.js.map +1 -0
  18. package/dist/cli/init.d.ts +1 -0
  19. package/dist/cli/init.js +70 -0
  20. package/dist/cli/init.js.map +1 -0
  21. package/dist/cli/shared.d.ts +33 -0
  22. package/dist/cli/shared.js +278 -0
  23. package/dist/cli/shared.js.map +1 -0
  24. package/dist/cli/start.d.ts +1 -0
  25. package/dist/cli/start.js +24 -0
  26. package/dist/cli/start.js.map +1 -0
  27. package/dist/config-loader.d.ts +49 -0
  28. package/dist/config-loader.js +140 -0
  29. package/dist/define-config.d.ts +188 -0
  30. package/dist/define-config.js +21 -0
  31. package/dist/index.d.ts +11 -0
  32. package/dist/index.js +9 -0
  33. package/package.json +124 -0
  34. package/src/adapter/custom.ts +90 -0
  35. package/src/adapter/default.ts +241 -0
  36. package/src/cli/build.ts +38 -0
  37. package/src/cli/dev.ts +38 -0
  38. package/src/cli/index.ts +52 -0
  39. package/src/cli/init.ts +76 -0
  40. package/src/cli/shared.ts +306 -0
  41. package/src/cli/start.ts +28 -0
  42. package/src/config-loader.ts +190 -0
  43. package/src/define-config.ts +206 -0
  44. package/src/index.ts +17 -0
  45. package/src/next-app/app/[...asset]/route.ts +81 -0
  46. package/src/next-app/app/_user-global.css +6 -0
  47. package/src/next-app/app/_user-sources.css +9 -0
  48. package/src/next-app/app/a11y/[name]/route.ts +19 -0
  49. package/src/next-app/app/api/search-index/route.ts +19 -0
  50. package/src/next-app/app/components/[name]/page.tsx +61 -0
  51. package/src/next-app/app/components/layout.tsx +18 -0
  52. package/src/next-app/app/docs/[slug]/page.tsx +53 -0
  53. package/src/next-app/app/docs/layout.tsx +18 -0
  54. package/src/next-app/app/globals.css +329 -0
  55. package/src/next-app/app/layout.tsx +102 -0
  56. package/src/next-app/app/page.tsx +9 -0
  57. package/src/next-app/app/preview-snapshot/[name]/page.tsx +20 -0
  58. package/src/next-app/app/preview-snapshot/layout.tsx +17 -0
  59. package/src/next-app/app/props/[name]/route.ts +19 -0
  60. package/src/next-app/app/r/[name]/route.ts +14 -0
  61. package/src/next-app/app/tests/[name]/route.ts +19 -0
  62. package/src/next-app/components/a11y-info.tsx +287 -0
  63. package/src/next-app/components/a11y-provider.tsx +39 -0
  64. package/src/next-app/components/component-breadcrumb.tsx +55 -0
  65. package/src/next-app/components/component-icon.tsx +140 -0
  66. package/src/next-app/components/component-preview.tsx +13 -0
  67. package/src/next-app/components/component-tabs.tsx +209 -0
  68. package/src/next-app/components/docs-toc.tsx +86 -0
  69. package/src/next-app/components/global-mobile-sidebar.tsx +35 -0
  70. package/src/next-app/components/header.tsx +188 -0
  71. package/src/next-app/components/heading-anchor.tsx +52 -0
  72. package/src/next-app/components/homepage-demo.tsx +180 -0
  73. package/src/next-app/components/locale-toggle.tsx +35 -0
  74. package/src/next-app/components/localized-mdx-client.tsx +14 -0
  75. package/src/next-app/components/localized-mdx.tsx +27 -0
  76. package/src/next-app/components/mobile-sidebar.tsx +22 -0
  77. package/src/next-app/components/nav-data-provider.tsx +37 -0
  78. package/src/next-app/components/navigation-progress.tsx +62 -0
  79. package/src/next-app/components/preview-canvas.tsx +368 -0
  80. package/src/next-app/components/preview-controls.tsx +94 -0
  81. package/src/next-app/components/preview-layout.tsx +218 -0
  82. package/src/next-app/components/props-table.tsx +134 -0
  83. package/src/next-app/components/resizable-preview.tsx +101 -0
  84. package/src/next-app/components/search.tsx +177 -0
  85. package/src/next-app/components/settings-modal.tsx +98 -0
  86. package/src/next-app/components/shell-ui/accordion.tsx +70 -0
  87. package/src/next-app/components/shell-ui/backdrop.tsx +29 -0
  88. package/src/next-app/components/shell-ui/badge.tsx +55 -0
  89. package/src/next-app/components/shell-ui/breadcrumb.tsx +120 -0
  90. package/src/next-app/components/shell-ui/button.tsx +64 -0
  91. package/src/next-app/components/shell-ui/card.tsx +127 -0
  92. package/src/next-app/components/shell-ui/checkbox.tsx +33 -0
  93. package/src/next-app/components/shell-ui/dialog.tsx +171 -0
  94. package/src/next-app/components/shell-ui/empty-state.tsx +66 -0
  95. package/src/next-app/components/shell-ui/input.tsx +27 -0
  96. package/src/next-app/components/shell-ui/kbd.tsx +30 -0
  97. package/src/next-app/components/shell-ui/label.tsx +25 -0
  98. package/src/next-app/components/shell-ui/select.tsx +204 -0
  99. package/src/next-app/components/shell-ui/separator.tsx +32 -0
  100. package/src/next-app/components/shell-ui/skeleton.tsx +18 -0
  101. package/src/next-app/components/shell-ui/table.tsx +124 -0
  102. package/src/next-app/components/shell-ui/tabs.tsx +102 -0
  103. package/src/next-app/components/shell-ui/toggle.tsx +56 -0
  104. package/src/next-app/components/sidebar-layout.tsx +37 -0
  105. package/src/next-app/components/sidebar-provider.tsx +75 -0
  106. package/src/next-app/components/sidebar.tsx +222 -0
  107. package/src/next-app/components/snapshot-preview.tsx +28 -0
  108. package/src/next-app/components/test-info.tsx +155 -0
  109. package/src/next-app/components/theme-provider.tsx +16 -0
  110. package/src/next-app/components/theme-toggle.tsx +21 -0
  111. package/src/next-app/components/translated-text.tsx +8 -0
  112. package/src/next-app/fallback/homepage.tsx +112 -0
  113. package/src/next-app/fallback/previews.ts +17 -0
  114. package/src/next-app/hooks/use-active-section.ts +23 -0
  115. package/src/next-app/hooks/use-controls.ts +72 -0
  116. package/src/next-app/hooks/use-mobile.ts +19 -0
  117. package/src/next-app/lib/branding.ts +52 -0
  118. package/src/next-app/lib/components-nav.ts +8 -0
  119. package/src/next-app/lib/docs.ts +16 -0
  120. package/src/next-app/lib/github.ts +38 -0
  121. package/src/next-app/lib/i18n.tsx +630 -0
  122. package/src/next-app/lib/locales.ts +17 -0
  123. package/src/next-app/lib/preview-loader.ts +7 -0
  124. package/src/next-app/lib/registry-adapter.ts +199 -0
  125. package/src/next-app/lib/utils.ts +6 -0
  126. package/src/next-app/next-env.d.ts +6 -0
  127. package/src/next-app/next.config.ts +101 -0
  128. package/src/next-app/postcss.config.mjs +7 -0
  129. package/src/next-app/public/favicon.ico +0 -0
  130. package/src/next-app/public/favicon_dark.svg +3 -0
  131. package/src/next-app/public/favicon_light.svg +3 -0
  132. package/src/next-app/registry.config.ts +50 -0
  133. package/src/next-app/tsconfig.json +29 -0
  134. package/src/next-app/user-aliases.d.ts +17 -0
@@ -0,0 +1,120 @@
1
+ import * as React from "react"
2
+ import { ChevronRight, MoreHorizontal } from "lucide-react"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "@shell/lib/utils"
6
+
7
+ /** Navigation wrapper that provides an accessible breadcrumb landmark. */
8
+ function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
9
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
10
+ }
11
+
12
+ /** Ordered list that lays out breadcrumb items horizontally with wrapping. */
13
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
14
+ return (
15
+ <ol
16
+ data-slot="breadcrumb-list"
17
+ className={cn(
18
+ "flex flex-wrap items-center gap-1.5 text-sm break-words text-muted-foreground sm:gap-2.5",
19
+ className
20
+ )}
21
+ {...props}
22
+ />
23
+ )
24
+ }
25
+
26
+ /** A single breadcrumb entry that contains a link or the current page indicator. */
27
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
28
+ return (
29
+ <li
30
+ data-slot="breadcrumb-item"
31
+ className={cn("inline-flex items-center gap-1.5", className)}
32
+ {...props}
33
+ />
34
+ )
35
+ }
36
+
37
+ /**
38
+ * A navigational link within a breadcrumb item.
39
+ * @param props.asChild - When true, renders the child element instead of an anchor tag.
40
+ */
41
+ function BreadcrumbLink({
42
+ asChild,
43
+ className,
44
+ ...props
45
+ }: React.ComponentProps<"a"> & {
46
+ /** When true, renders the child element instead of an anchor tag. */
47
+ asChild?: boolean
48
+ }) {
49
+ const Comp = asChild ? Slot.Root : "a"
50
+
51
+ return (
52
+ <Comp
53
+ data-slot="breadcrumb-link"
54
+ className={cn("transition-colors hover:text-foreground", className)}
55
+ {...props}
56
+ />
57
+ )
58
+ }
59
+
60
+ /** Marks the current page in the breadcrumb trail with `aria-current="page"`. */
61
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
62
+ return (
63
+ <span
64
+ data-slot="breadcrumb-page"
65
+ role="link"
66
+ aria-disabled="true"
67
+ aria-current="page"
68
+ className={cn("font-normal text-foreground", className)}
69
+ {...props}
70
+ />
71
+ )
72
+ }
73
+
74
+ /** Visual separator between breadcrumb items, defaulting to a chevron icon. */
75
+ function BreadcrumbSeparator({
76
+ children,
77
+ className,
78
+ ...props
79
+ }: React.ComponentProps<"li">) {
80
+ return (
81
+ <li
82
+ data-slot="breadcrumb-separator"
83
+ role="presentation"
84
+ aria-hidden="true"
85
+ className={cn("[&>svg]:size-3.5", className)}
86
+ {...props}
87
+ >
88
+ {children ?? <ChevronRight />}
89
+ </li>
90
+ )
91
+ }
92
+
93
+ /** Ellipsis indicator used to represent collapsed breadcrumb items. */
94
+ function BreadcrumbEllipsis({
95
+ className,
96
+ ...props
97
+ }: React.ComponentProps<"span">) {
98
+ return (
99
+ <span
100
+ data-slot="breadcrumb-ellipsis"
101
+ role="presentation"
102
+ aria-hidden="true"
103
+ className={cn("flex size-9 items-center justify-center", className)}
104
+ {...props}
105
+ >
106
+ <MoreHorizontal className="size-4" />
107
+ <span className="sr-only">More</span>
108
+ </span>
109
+ )
110
+ }
111
+
112
+ export {
113
+ Breadcrumb,
114
+ BreadcrumbList,
115
+ BreadcrumbItem,
116
+ BreadcrumbLink,
117
+ BreadcrumbPage,
118
+ BreadcrumbSeparator,
119
+ BreadcrumbEllipsis,
120
+ }
@@ -0,0 +1,64 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "@shell/lib/utils"
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap cursor-pointer transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
13
+ destructive:
14
+ "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
15
+ outline:
16
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
17
+ secondary:
18
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
19
+ ghost:
20
+ "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ size: {
24
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
25
+ xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
26
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
27
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
28
+ icon: "size-9",
29
+ "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
30
+ "icon-sm": "size-8",
31
+ "icon-lg": "size-10",
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ variant: "default",
36
+ size: "default",
37
+ },
38
+ }
39
+ )
40
+
41
+ function Button({
42
+ className,
43
+ variant = "default",
44
+ size = "default",
45
+ asChild = false,
46
+ ...props
47
+ }: React.ComponentProps<"button"> &
48
+ VariantProps<typeof buttonVariants> & {
49
+ asChild?: boolean
50
+ }) {
51
+ const Comp = asChild ? Slot.Root : "button"
52
+
53
+ return (
54
+ <Comp
55
+ data-slot="button"
56
+ data-variant={variant}
57
+ data-size={size}
58
+ className={cn(buttonVariants({ variant, size, className }))}
59
+ {...props}
60
+ />
61
+ )
62
+ }
63
+
64
+ export { Button, buttonVariants }
@@ -0,0 +1,127 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@shell/lib/utils"
4
+
5
+ /** A styled container card with rounded corners, border, and shadow. */
6
+ function Card({
7
+ /** Additional CSS classes to apply to the card. */
8
+ className,
9
+ ...props
10
+ }: React.ComponentProps<"div">) {
11
+ return (
12
+ <div
13
+ data-slot="card"
14
+ className={cn(
15
+ "flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ /** Header section of a Card, typically containing a title and description. */
24
+ function CardHeader({
25
+ /** Additional CSS classes to apply to the card header. */
26
+ className,
27
+ ...props
28
+ }: React.ComponentProps<"div">) {
29
+ return (
30
+ <div
31
+ data-slot="card-header"
32
+ className={cn(
33
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
34
+ className
35
+ )}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ /** Title element within a CardHeader. */
42
+ function CardTitle({
43
+ /** Additional CSS classes to apply to the card title. */
44
+ className,
45
+ ...props
46
+ }: React.ComponentProps<"div">) {
47
+ return (
48
+ <div
49
+ data-slot="card-title"
50
+ className={cn("leading-none font-semibold", className)}
51
+ {...props}
52
+ />
53
+ )
54
+ }
55
+
56
+ /** Description text within a CardHeader, rendered in muted style. */
57
+ function CardDescription({
58
+ /** Additional CSS classes to apply to the card description. */
59
+ className,
60
+ ...props
61
+ }: React.ComponentProps<"div">) {
62
+ return (
63
+ <div
64
+ data-slot="card-description"
65
+ className={cn("text-sm text-muted-foreground", className)}
66
+ {...props}
67
+ />
68
+ )
69
+ }
70
+
71
+ /** Action area positioned at the top-right of a CardHeader. */
72
+ function CardAction({
73
+ /** Additional CSS classes to apply to the card action. */
74
+ className,
75
+ ...props
76
+ }: React.ComponentProps<"div">) {
77
+ return (
78
+ <div
79
+ data-slot="card-action"
80
+ className={cn(
81
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
82
+ className
83
+ )}
84
+ {...props}
85
+ />
86
+ )
87
+ }
88
+
89
+ /** Main content area of a Card. */
90
+ function CardContent({
91
+ /** Additional CSS classes to apply to the card content. */
92
+ className,
93
+ ...props
94
+ }: React.ComponentProps<"div">) {
95
+ return (
96
+ <div
97
+ data-slot="card-content"
98
+ className={cn("px-6", className)}
99
+ {...props}
100
+ />
101
+ )
102
+ }
103
+
104
+ /** Footer section of a Card, typically used for actions or metadata. */
105
+ function CardFooter({
106
+ /** Additional CSS classes to apply to the card footer. */
107
+ className,
108
+ ...props
109
+ }: React.ComponentProps<"div">) {
110
+ return (
111
+ <div
112
+ data-slot="card-footer"
113
+ className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
114
+ {...props}
115
+ />
116
+ )
117
+ }
118
+
119
+ export {
120
+ Card,
121
+ CardHeader,
122
+ CardFooter,
123
+ CardTitle,
124
+ CardAction,
125
+ CardDescription,
126
+ CardContent,
127
+ }
@@ -0,0 +1,33 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { CheckIcon } from "lucide-react"
5
+ import { Checkbox as CheckboxPrimitive } from "radix-ui"
6
+
7
+ import { cn } from "@shell/lib/utils"
8
+
9
+ function Checkbox({
10
+ /** Additional CSS class names to apply to the checkbox. */
11
+ className,
12
+ ...props
13
+ }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
14
+ return (
15
+ <CheckboxPrimitive.Root
16
+ data-slot="checkbox"
17
+ className={cn(
18
+ "peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs cursor-pointer transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary",
19
+ className
20
+ )}
21
+ {...props}
22
+ >
23
+ <CheckboxPrimitive.Indicator
24
+ data-slot="checkbox-indicator"
25
+ className="grid place-content-center text-current transition-none"
26
+ >
27
+ <CheckIcon className="size-3.5" />
28
+ </CheckboxPrimitive.Indicator>
29
+ </CheckboxPrimitive.Root>
30
+ )
31
+ }
32
+
33
+ export { Checkbox }
@@ -0,0 +1,171 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { XIcon } from "lucide-react"
5
+ import { Dialog as DialogPrimitive } from "radix-ui"
6
+
7
+ import { cn } from "@shell/lib/utils"
8
+ import { Button } from "@shell/components/shell-ui/button"
9
+
10
+ /** Root dialog component that manages open/closed state. */
11
+ function Dialog({
12
+ ...props
13
+ }: React.ComponentProps<typeof DialogPrimitive.Root>) {
14
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />
15
+ }
16
+
17
+ /** Button that opens the dialog when clicked. */
18
+ function DialogTrigger({
19
+ ...props
20
+ }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
21
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
22
+ }
23
+
24
+ /** Renders dialog content into a React portal outside the DOM hierarchy. */
25
+ function DialogPortal({
26
+ ...props
27
+ }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
28
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
29
+ }
30
+
31
+ /** Button that closes the dialog when clicked. */
32
+ function DialogClose({
33
+ ...props
34
+ }: React.ComponentProps<typeof DialogPrimitive.Close>) {
35
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
36
+ }
37
+
38
+ /** Semi-transparent backdrop rendered behind the dialog content. */
39
+ function DialogOverlay({
40
+ className,
41
+ ...props
42
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
43
+ return (
44
+ <DialogPrimitive.Overlay
45
+ data-slot="dialog-overlay"
46
+ className={cn(
47
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
48
+ className
49
+ )}
50
+ {...props}
51
+ />
52
+ )
53
+ }
54
+
55
+ /**
56
+ * Dialog content container rendered inside a portal with an overlay backdrop.
57
+ * Includes an optional close button in the top-right corner (shown by default).
58
+ */
59
+ function DialogContent({
60
+ className,
61
+ children,
62
+ showCloseButton = true,
63
+ ...props
64
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & {
65
+ showCloseButton?: boolean
66
+ }) {
67
+ return (
68
+ <DialogPortal data-slot="dialog-portal">
69
+ <DialogOverlay />
70
+ <DialogPrimitive.Content
71
+ data-slot="dialog-content"
72
+ className={cn(
73
+ "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
74
+ className
75
+ )}
76
+ {...props}
77
+ >
78
+ {children}
79
+ {showCloseButton && (
80
+ <DialogPrimitive.Close
81
+ data-slot="dialog-close"
82
+ className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background cursor-pointer transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
83
+ >
84
+ <XIcon />
85
+ <span className="sr-only">Close</span>
86
+ </DialogPrimitive.Close>
87
+ )}
88
+ </DialogPrimitive.Content>
89
+ </DialogPortal>
90
+ )
91
+ }
92
+
93
+ /** Layout container for the dialog title and description. */
94
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
95
+ return (
96
+ <div
97
+ data-slot="dialog-header"
98
+ className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
99
+ {...props}
100
+ />
101
+ )
102
+ }
103
+
104
+ /** Layout container for dialog action buttons, with an optional close button. */
105
+ function DialogFooter({
106
+ className,
107
+ showCloseButton = false,
108
+ children,
109
+ ...props
110
+ }: React.ComponentProps<"div"> & {
111
+ showCloseButton?: boolean
112
+ }) {
113
+ return (
114
+ <div
115
+ data-slot="dialog-footer"
116
+ className={cn(
117
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
118
+ className
119
+ )}
120
+ {...props}
121
+ >
122
+ {children}
123
+ {showCloseButton && (
124
+ <DialogPrimitive.Close asChild>
125
+ <Button variant="outline">Close</Button>
126
+ </DialogPrimitive.Close>
127
+ )}
128
+ </div>
129
+ )
130
+ }
131
+
132
+ /** The dialog heading, rendered as an accessible title. */
133
+ function DialogTitle({
134
+ className,
135
+ ...props
136
+ }: React.ComponentProps<typeof DialogPrimitive.Title>) {
137
+ return (
138
+ <DialogPrimitive.Title
139
+ data-slot="dialog-title"
140
+ className={cn("text-lg leading-none font-semibold", className)}
141
+ {...props}
142
+ />
143
+ )
144
+ }
145
+
146
+ /** Secondary descriptive text displayed below the dialog title. */
147
+ function DialogDescription({
148
+ className,
149
+ ...props
150
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
151
+ return (
152
+ <DialogPrimitive.Description
153
+ data-slot="dialog-description"
154
+ className={cn("text-sm text-muted-foreground", className)}
155
+ {...props}
156
+ />
157
+ )
158
+ }
159
+
160
+ export {
161
+ Dialog,
162
+ DialogClose,
163
+ DialogContent,
164
+ DialogDescription,
165
+ DialogFooter,
166
+ DialogHeader,
167
+ DialogOverlay,
168
+ DialogPortal,
169
+ DialogTitle,
170
+ DialogTrigger,
171
+ }
@@ -0,0 +1,66 @@
1
+ import { cn } from "@shell/lib/utils"
2
+
3
+ /** A placeholder shown when a section has no content. Displays an icon, title, and optional description. */
4
+ function EmptyState({
5
+ /** Additional CSS classes. */
6
+ className,
7
+ ...props
8
+ }: React.ComponentProps<"div">) {
9
+ return (
10
+ <div
11
+ data-slot="empty-state"
12
+ className={cn(
13
+ "flex flex-col items-center justify-center rounded-lg border border-dashed border-border py-10 px-6 text-center",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ /** Icon container for the empty state. */
22
+ function EmptyStateIcon({
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<"div">) {
26
+ return (
27
+ <div
28
+ data-slot="empty-state-icon"
29
+ className={cn(
30
+ "mb-3 flex items-center justify-center rounded-full bg-muted p-3 text-muted-foreground [&_svg]:size-6",
31
+ className
32
+ )}
33
+ {...props}
34
+ />
35
+ )
36
+ }
37
+
38
+ /** Title text for the empty state. */
39
+ function EmptyStateTitle({
40
+ className,
41
+ ...props
42
+ }: React.ComponentProps<"h3">) {
43
+ return (
44
+ <h3
45
+ data-slot="empty-state-title"
46
+ className={cn("text-sm font-semibold text-foreground mb-1", className)}
47
+ {...props}
48
+ />
49
+ )
50
+ }
51
+
52
+ /** Description text for the empty state. */
53
+ function EmptyStateDescription({
54
+ className,
55
+ ...props
56
+ }: React.ComponentProps<"p">) {
57
+ return (
58
+ <p
59
+ data-slot="empty-state-description"
60
+ className={cn("text-sm text-muted-foreground max-w-sm", className)}
61
+ {...props}
62
+ />
63
+ )
64
+ }
65
+
66
+ export { EmptyState, EmptyStateIcon, EmptyStateTitle, EmptyStateDescription }
@@ -0,0 +1,27 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@shell/lib/utils"
4
+
5
+ function Input({
6
+ /** Additional CSS class names to apply to the input. */
7
+ className,
8
+ /** The HTML input type attribute (e.g. "text", "password", "email"). */
9
+ type,
10
+ ...props
11
+ }: React.ComponentProps<"input">) {
12
+ return (
13
+ <input
14
+ type={type}
15
+ data-slot="input"
16
+ className={cn(
17
+ "h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30",
18
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
19
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
20
+ className
21
+ )}
22
+ {...props}
23
+ />
24
+ )
25
+ }
26
+
27
+ export { Input }
@@ -0,0 +1,30 @@
1
+ import { cn } from "@shell/lib/utils"
2
+
3
+ /** Displays a keyboard shortcut or key in a styled inline badge. */
4
+ function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
5
+ return (
6
+ <kbd
7
+ data-slot="kbd"
8
+ className={cn(
9
+ "pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none",
10
+ "[&_svg:not([class*='size-'])]:size-3",
11
+ "[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
12
+ className
13
+ )}
14
+ {...props}
15
+ />
16
+ )
17
+ }
18
+
19
+ /** Groups multiple Kbd elements with a separator, representing a key combination. */
20
+ function KbdGroup({ className, ...props }: React.ComponentProps<"div">) {
21
+ return (
22
+ <kbd
23
+ data-slot="kbd-group"
24
+ className={cn("inline-flex items-center gap-1", className)}
25
+ {...props}
26
+ />
27
+ )
28
+ }
29
+
30
+ export { Kbd, KbdGroup }
@@ -0,0 +1,25 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Label as LabelPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@shell/lib/utils"
7
+
8
+ function Label({
9
+ /** Additional CSS class names to apply to the label. */
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
13
+ return (
14
+ <LabelPrimitive.Root
15
+ data-slot="label"
16
+ className={cn(
17
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
18
+ className
19
+ )}
20
+ {...props}
21
+ />
22
+ )
23
+ }
24
+
25
+ export { Label }