@aphrody/koharu-ui 0.0.0-stage → 0.1.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 (123) hide show
  1. package/README.md +37 -2
  2. package/package.json +70 -4
  3. package/src/assets/NotoSansCJK-VF.otf +0 -0
  4. package/src/assets/OFL.txt +92 -0
  5. package/src/components/ClientOnly.tsx +21 -0
  6. package/src/components/ShenronExportPanel.tsx +213 -0
  7. package/src/components/app/AboutDialog.tsx +64 -0
  8. package/src/components/app/KoharuApp.tsx +58 -0
  9. package/src/components/app/StartupView.tsx +67 -0
  10. package/src/components/app/TitleBar.tsx +322 -0
  11. package/src/components/app/Updater.tsx +143 -0
  12. package/src/components/app/WindowChrome.tsx +137 -0
  13. package/src/components/controls/ColorSampling.tsx +70 -0
  14. package/src/components/controls/ColorWell.tsx +139 -0
  15. package/src/components/controls/CommitTextarea.tsx +63 -0
  16. package/src/components/controls/FontPicker.tsx +543 -0
  17. package/src/components/controls/ModelPicker.tsx +178 -0
  18. package/src/components/controls/OutputPicker.tsx +170 -0
  19. package/src/components/editor/ActivityCenter.tsx +234 -0
  20. package/src/components/editor/AgentPanel.tsx +352 -0
  21. package/src/components/editor/CanvasCommandBar.tsx +38 -0
  22. package/src/components/editor/CanvasOverlay.tsx +194 -0
  23. package/src/components/editor/CanvasWorkspace.tsx +947 -0
  24. package/src/components/editor/Editor.tsx +56 -0
  25. package/src/components/editor/InferenceControl.tsx +457 -0
  26. package/src/components/editor/Inspector.tsx +1073 -0
  27. package/src/components/editor/PageRail.tsx +581 -0
  28. package/src/components/editor/ResourceMonitor.tsx +151 -0
  29. package/src/components/editor/RightSidebar.tsx +50 -0
  30. package/src/components/editor/SelectionControls.tsx +184 -0
  31. package/src/components/editor/StatusBar.tsx +41 -0
  32. package/src/components/editor/ToolBar.tsx +182 -0
  33. package/src/components/editor/useCanvas.ts +194 -0
  34. package/src/components/preferences/GenerationPreferences.tsx +118 -0
  35. package/src/components/preferences/KoharuSettings.tsx +229 -0
  36. package/src/components/preferences/PipelinePreferences.tsx +173 -0
  37. package/src/components/preferences/PreferenceFields.tsx +149 -0
  38. package/src/components/preferences/ProviderPreferences.tsx +173 -0
  39. package/src/components/preferences/SettingsPage.tsx +336 -0
  40. package/src/components/preferences/TranslationPreferences.tsx +187 -0
  41. package/src/components/preferences/TypesettingPreferences.tsx +142 -0
  42. package/src/components/preferences/models.ts +103 -0
  43. package/src/components/start/StartView.tsx +277 -0
  44. package/src/index.ts +59 -0
  45. package/src/internal/components/accordion.tsx +72 -0
  46. package/src/internal/components/alert-dialog.tsx +189 -0
  47. package/src/internal/components/alert.tsx +76 -0
  48. package/src/internal/components/aspect-ratio.tsx +22 -0
  49. package/src/internal/components/attachment.tsx +207 -0
  50. package/src/internal/components/avatar.tsx +109 -0
  51. package/src/internal/components/badge.tsx +52 -0
  52. package/src/internal/components/breadcrumb.tsx +125 -0
  53. package/src/internal/components/bubble.tsx +128 -0
  54. package/src/internal/components/button-group.tsx +87 -0
  55. package/src/internal/components/button.tsx +58 -0
  56. package/src/internal/components/card.tsx +103 -0
  57. package/src/internal/components/checkbox.tsx +29 -0
  58. package/src/internal/components/collapsible.tsx +21 -0
  59. package/src/internal/components/combobox.tsx +298 -0
  60. package/src/internal/components/context-menu.tsx +272 -0
  61. package/src/internal/components/dialog.tsx +162 -0
  62. package/src/internal/components/direction.tsx +6 -0
  63. package/src/internal/components/drawer.tsx +230 -0
  64. package/src/internal/components/dropdown-menu.tsx +278 -0
  65. package/src/internal/components/empty.tsx +104 -0
  66. package/src/internal/components/field.tsx +238 -0
  67. package/src/internal/components/hover-card.tsx +52 -0
  68. package/src/internal/components/input-group.tsx +158 -0
  69. package/src/internal/components/input.tsx +20 -0
  70. package/src/internal/components/item.tsx +201 -0
  71. package/src/internal/components/kbd.tsx +26 -0
  72. package/src/internal/components/label.tsx +20 -0
  73. package/src/internal/components/marker.tsx +71 -0
  74. package/src/internal/components/menubar.tsx +280 -0
  75. package/src/internal/components/message.tsx +92 -0
  76. package/src/internal/components/native-select.tsx +61 -0
  77. package/src/internal/components/navigation-menu.tsx +168 -0
  78. package/src/internal/components/number-field.tsx +68 -0
  79. package/src/internal/components/pagination.tsx +130 -0
  80. package/src/internal/components/popover.tsx +91 -0
  81. package/src/internal/components/progress.tsx +83 -0
  82. package/src/internal/components/radio-group.tsx +38 -0
  83. package/src/internal/components/resizable.tsx +50 -0
  84. package/src/internal/components/scroll-area.tsx +88 -0
  85. package/src/internal/components/select.tsx +191 -0
  86. package/src/internal/components/separator.tsx +25 -0
  87. package/src/internal/components/sheet.tsx +140 -0
  88. package/src/internal/components/sidebar.tsx +723 -0
  89. package/src/internal/components/skeleton.tsx +13 -0
  90. package/src/internal/components/slider.tsx +56 -0
  91. package/src/internal/components/spinner.tsx +10 -0
  92. package/src/internal/components/switch.tsx +32 -0
  93. package/src/internal/components/table.tsx +116 -0
  94. package/src/internal/components/tabs.tsx +82 -0
  95. package/src/internal/components/textarea.tsx +18 -0
  96. package/src/internal/components/toast.tsx +235 -0
  97. package/src/internal/components/toggle-group.tsx +89 -0
  98. package/src/internal/components/toggle.tsx +45 -0
  99. package/src/internal/components/tooltip.tsx +67 -0
  100. package/src/internal/hooks/use-mobile.ts +19 -0
  101. package/src/internal/lib/utils.ts +6 -0
  102. package/src/internal/styles/globals.css +73 -0
  103. package/src/lib/backend.ts +85 -0
  104. package/src/lib/document.ts +46 -0
  105. package/src/lib/geometry.ts +272 -0
  106. package/src/lib/i18n.ts +54 -0
  107. package/src/lib/queries.ts +110 -0
  108. package/src/lib/store.ts +191 -0
  109. package/src/lib/translation.ts +35 -0
  110. package/src/locales/en-US/translation.json +536 -0
  111. package/src/locales/es-ES/translation.json +536 -0
  112. package/src/locales/ja-JP/translation.json +536 -0
  113. package/src/locales/ko-KR/translation.json +536 -0
  114. package/src/locales/pt-BR/translation.json +536 -0
  115. package/src/locales/ru-RU/translation.json +536 -0
  116. package/src/locales/tr-TR/translation.json +536 -0
  117. package/src/locales/zh-CN/translation.json +536 -0
  118. package/src/locales/zh-TW/translation.json +536 -0
  119. package/src/navigation.ts +28 -0
  120. package/src/providers.tsx +132 -0
  121. package/src/shenron-pipeline-env.d.ts +14 -0
  122. package/src/styles.css +246 -0
  123. package/tsconfig.json +21 -0
@@ -0,0 +1,125 @@
1
+ import * as React from "react"
2
+ import { mergeProps } from "@base-ui/react/merge-props"
3
+ import { useRender } from "@base-ui/react/use-render"
4
+
5
+ import { cn } from "../lib/utils"
6
+ import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
7
+
8
+ function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
9
+ return (
10
+ <nav
11
+ aria-label="breadcrumb"
12
+ data-slot="breadcrumb"
13
+ className={cn(className)}
14
+ {...props}
15
+ />
16
+ )
17
+ }
18
+
19
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
20
+ return (
21
+ <ol
22
+ data-slot="breadcrumb-list"
23
+ className={cn(
24
+ "flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground",
25
+ className
26
+ )}
27
+ {...props}
28
+ />
29
+ )
30
+ }
31
+
32
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
33
+ return (
34
+ <li
35
+ data-slot="breadcrumb-item"
36
+ className={cn("inline-flex items-center gap-1", className)}
37
+ {...props}
38
+ />
39
+ )
40
+ }
41
+
42
+ function BreadcrumbLink({
43
+ className,
44
+ render,
45
+ ...props
46
+ }: useRender.ComponentProps<"a">) {
47
+ return useRender({
48
+ defaultTagName: "a",
49
+ props: mergeProps<"a">(
50
+ {
51
+ className: cn("transition-colors hover:text-foreground", className),
52
+ },
53
+ props
54
+ ),
55
+ render,
56
+ state: {
57
+ slot: "breadcrumb-link",
58
+ },
59
+ })
60
+ }
61
+
62
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
63
+ return (
64
+ <span
65
+ data-slot="breadcrumb-page"
66
+ role="link"
67
+ aria-disabled="true"
68
+ aria-current="page"
69
+ className={cn("font-normal text-foreground", className)}
70
+ {...props}
71
+ />
72
+ )
73
+ }
74
+
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 ?? (
89
+ <ChevronRightIcon />
90
+ )}
91
+ </li>
92
+ )
93
+ }
94
+
95
+ function BreadcrumbEllipsis({
96
+ className,
97
+ ...props
98
+ }: React.ComponentProps<"span">) {
99
+ return (
100
+ <span
101
+ data-slot="breadcrumb-ellipsis"
102
+ role="presentation"
103
+ aria-hidden="true"
104
+ className={cn(
105
+ "flex size-5 items-center justify-center [&>svg]:size-4",
106
+ className
107
+ )}
108
+ {...props}
109
+ >
110
+ <MoreHorizontalIcon
111
+ />
112
+ <span className="sr-only">More</span>
113
+ </span>
114
+ )
115
+ }
116
+
117
+ export {
118
+ Breadcrumb,
119
+ BreadcrumbList,
120
+ BreadcrumbItem,
121
+ BreadcrumbLink,
122
+ BreadcrumbPage,
123
+ BreadcrumbSeparator,
124
+ BreadcrumbEllipsis,
125
+ }
@@ -0,0 +1,128 @@
1
+ import * as React from "react"
2
+ import { mergeProps } from "@base-ui/react/merge-props"
3
+ import { useRender } from "@base-ui/react/use-render"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+
6
+ import { cn } from "../lib/utils"
7
+
8
+ function BubbleGroup({ className, ...props }: React.ComponentProps<"div">) {
9
+ return (
10
+ <div
11
+ data-slot="bubble-group"
12
+ className={cn("flex min-w-0 flex-col gap-2", className)}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ const bubbleVariants = cva(
19
+ "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
20
+ {
21
+ variants: {
22
+ variant: {
23
+ default:
24
+ "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
25
+ secondary:
26
+ "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
27
+ muted:
28
+ "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
29
+ tinted:
30
+ "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
31
+ outline:
32
+ "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
33
+ ghost:
34
+ "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
35
+ destructive:
36
+ "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30",
37
+ },
38
+ },
39
+ defaultVariants: {
40
+ variant: "default",
41
+ },
42
+ }
43
+ )
44
+
45
+ function Bubble({
46
+ variant = "default",
47
+ align = "start",
48
+ className,
49
+ ...props
50
+ }: React.ComponentProps<"div"> &
51
+ VariantProps<typeof bubbleVariants> & {
52
+ align?: "start" | "end"
53
+ }) {
54
+ return (
55
+ <div
56
+ data-slot="bubble"
57
+ data-variant={variant}
58
+ data-align={align}
59
+ className={cn(bubbleVariants({ variant }), className)}
60
+ {...props}
61
+ />
62
+ )
63
+ }
64
+
65
+ function BubbleContent({
66
+ className,
67
+ render,
68
+ ...props
69
+ }: useRender.ComponentProps<"div">) {
70
+ return useRender({
71
+ defaultTagName: "div",
72
+ props: mergeProps<"div">(
73
+ {
74
+ className: cn(
75
+ "w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
76
+ className
77
+ ),
78
+ },
79
+ props
80
+ ),
81
+ render,
82
+ state: {
83
+ slot: "bubble-content",
84
+ },
85
+ })
86
+ }
87
+
88
+ const bubbleReactionsVariants = cva(
89
+ "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
90
+ {
91
+ variants: {
92
+ side: {
93
+ top: "top-0 -translate-y-3/4",
94
+ bottom: "bottom-0 translate-y-3/4",
95
+ },
96
+ align: {
97
+ start: "left-3",
98
+ end: "right-3",
99
+ },
100
+ },
101
+ defaultVariants: {
102
+ side: "bottom",
103
+ align: "end",
104
+ },
105
+ }
106
+ )
107
+
108
+ function BubbleReactions({
109
+ side = "bottom",
110
+ align = "end",
111
+ className,
112
+ ...props
113
+ }: React.ComponentProps<"div"> & {
114
+ align?: "start" | "end"
115
+ side?: "top" | "bottom"
116
+ }) {
117
+ return (
118
+ <div
119
+ data-slot="bubble-reactions"
120
+ data-align={align}
121
+ data-side={side}
122
+ className={cn(bubbleReactionsVariants({ side, align }), className)}
123
+ {...props}
124
+ />
125
+ )
126
+ }
127
+
128
+ export { BubbleGroup, Bubble, BubbleContent, BubbleReactions }
@@ -0,0 +1,87 @@
1
+ import { mergeProps } from "@base-ui/react/merge-props"
2
+ import { useRender } from "@base-ui/react/use-render"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "../lib/utils"
6
+ import { Separator } from "./separator"
7
+
8
+ const buttonGroupVariants = cva(
9
+ "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
10
+ {
11
+ variants: {
12
+ orientation: {
13
+ horizontal:
14
+ "*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-lg! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
15
+ vertical:
16
+ "flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-lg! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0",
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ orientation: "horizontal",
21
+ },
22
+ }
23
+ )
24
+
25
+ function ButtonGroup({
26
+ className,
27
+ orientation,
28
+ ...props
29
+ }: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
30
+ return (
31
+ <div
32
+ role="group"
33
+ data-slot="button-group"
34
+ data-orientation={orientation}
35
+ className={cn(buttonGroupVariants({ orientation }), className)}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function ButtonGroupText({
42
+ className,
43
+ render,
44
+ ...props
45
+ }: useRender.ComponentProps<"div">) {
46
+ return useRender({
47
+ defaultTagName: "div",
48
+ props: mergeProps<"div">(
49
+ {
50
+ className: cn(
51
+ "flex items-center gap-2 rounded-lg border bg-muted px-2.5 text-sm font-medium [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
52
+ className
53
+ ),
54
+ },
55
+ props
56
+ ),
57
+ render,
58
+ state: {
59
+ slot: "button-group-text",
60
+ },
61
+ })
62
+ }
63
+
64
+ function ButtonGroupSeparator({
65
+ className,
66
+ orientation = "vertical",
67
+ ...props
68
+ }: React.ComponentProps<typeof Separator>) {
69
+ return (
70
+ <Separator
71
+ data-slot="button-group-separator"
72
+ orientation={orientation}
73
+ className={cn(
74
+ "relative self-stretch bg-input data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto",
75
+ className
76
+ )}
77
+ {...props}
78
+ />
79
+ )
80
+ }
81
+
82
+ export {
83
+ ButtonGroup,
84
+ ButtonGroupSeparator,
85
+ ButtonGroupText,
86
+ buttonGroupVariants,
87
+ }
@@ -0,0 +1,58 @@
1
+ import { Button as ButtonPrimitive } from "@base-ui/react/button"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "../lib/utils"
5
+
6
+ const buttonVariants = cva(
7
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
12
+ outline:
13
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
14
+ secondary:
15
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
16
+ ghost:
17
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
18
+ destructive:
19
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ size: {
23
+ default:
24
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
25
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
26
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
27
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
28
+ icon: "size-8",
29
+ "icon-xs":
30
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
31
+ "icon-sm":
32
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
33
+ "icon-lg": "size-9",
34
+ },
35
+ },
36
+ defaultVariants: {
37
+ variant: "default",
38
+ size: "default",
39
+ },
40
+ }
41
+ )
42
+
43
+ function Button({
44
+ className,
45
+ variant = "default",
46
+ size = "default",
47
+ ...props
48
+ }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
49
+ return (
50
+ <ButtonPrimitive
51
+ data-slot="button"
52
+ className={cn(buttonVariants({ variant, size, className }))}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ export { Button, buttonVariants }
@@ -0,0 +1,103 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "../lib/utils"
4
+
5
+ function Card({
6
+ className,
7
+ size = "default",
8
+ ...props
9
+ }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
10
+ return (
11
+ <div
12
+ data-slot="card"
13
+ data-size={size}
14
+ className={cn(
15
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
24
+ return (
25
+ <div
26
+ data-slot="card-header"
27
+ className={cn(
28
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
29
+ className
30
+ )}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
37
+ return (
38
+ <div
39
+ data-slot="card-title"
40
+ className={cn(
41
+ "text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
50
+ return (
51
+ <div
52
+ data-slot="card-description"
53
+ className={cn("text-sm text-muted-foreground", className)}
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
60
+ return (
61
+ <div
62
+ data-slot="card-action"
63
+ className={cn(
64
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
65
+ className
66
+ )}
67
+ {...props}
68
+ />
69
+ )
70
+ }
71
+
72
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
73
+ return (
74
+ <div
75
+ data-slot="card-content"
76
+ className={cn("px-(--card-spacing)", className)}
77
+ {...props}
78
+ />
79
+ )
80
+ }
81
+
82
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
83
+ return (
84
+ <div
85
+ data-slot="card-footer"
86
+ className={cn(
87
+ "flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
88
+ className
89
+ )}
90
+ {...props}
91
+ />
92
+ )
93
+ }
94
+
95
+ export {
96
+ Card,
97
+ CardHeader,
98
+ CardFooter,
99
+ CardTitle,
100
+ CardAction,
101
+ CardDescription,
102
+ CardContent,
103
+ }
@@ -0,0 +1,29 @@
1
+ "use client"
2
+
3
+ import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
4
+
5
+ import { cn } from "../lib/utils"
6
+ import { CheckIcon } from "lucide-react"
7
+
8
+ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
9
+ return (
10
+ <CheckboxPrimitive.Root
11
+ data-slot="checkbox"
12
+ className={cn(
13
+ "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary",
14
+ className
15
+ )}
16
+ {...props}
17
+ >
18
+ <CheckboxPrimitive.Indicator
19
+ data-slot="checkbox-indicator"
20
+ className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
21
+ >
22
+ <CheckIcon
23
+ />
24
+ </CheckboxPrimitive.Indicator>
25
+ </CheckboxPrimitive.Root>
26
+ )
27
+ }
28
+
29
+ export { Checkbox }
@@ -0,0 +1,21 @@
1
+ "use client"
2
+
3
+ import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
4
+
5
+ function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
6
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
7
+ }
8
+
9
+ function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
10
+ return (
11
+ <CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
12
+ )
13
+ }
14
+
15
+ function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
16
+ return (
17
+ <CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
18
+ )
19
+ }
20
+
21
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }