@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,61 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "../lib/utils"
4
+ import { ChevronDownIcon } from "lucide-react"
5
+
6
+ type NativeSelectProps = Omit<React.ComponentProps<"select">, "size"> & {
7
+ size?: "sm" | "default"
8
+ }
9
+
10
+ function NativeSelect({
11
+ className,
12
+ size = "default",
13
+ ...props
14
+ }: NativeSelectProps) {
15
+ return (
16
+ <div
17
+ className={cn(
18
+ "group/native-select relative w-fit has-[select:disabled]:opacity-50",
19
+ className
20
+ )}
21
+ data-slot="native-select-wrapper"
22
+ data-size={size}
23
+ >
24
+ <select
25
+ data-slot="native-select"
26
+ data-size={size}
27
+ className="h-8 w-full min-w-0 appearance-none rounded-lg border border-input bg-transparent py-1 pr-8 pl-2.5 text-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-[size=sm]:py-0.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40"
28
+ {...props}
29
+ />
30
+ <ChevronDownIcon className="pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-muted-foreground select-none" aria-hidden="true" data-slot="native-select-icon" />
31
+ </div>
32
+ )
33
+ }
34
+
35
+ function NativeSelectOption({
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<"option">) {
39
+ return (
40
+ <option
41
+ data-slot="native-select-option"
42
+ className={cn("bg-[Canvas] text-[CanvasText]", className)}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+
48
+ function NativeSelectOptGroup({
49
+ className,
50
+ ...props
51
+ }: React.ComponentProps<"optgroup">) {
52
+ return (
53
+ <optgroup
54
+ data-slot="native-select-optgroup"
55
+ className={cn("bg-[Canvas] text-[CanvasText]", className)}
56
+ {...props}
57
+ />
58
+ )
59
+ }
60
+
61
+ export { NativeSelect, NativeSelectOptGroup, NativeSelectOption }
@@ -0,0 +1,168 @@
1
+ import { NavigationMenu as NavigationMenuPrimitive } from "@base-ui/react/navigation-menu"
2
+ import { cva } from "class-variance-authority"
3
+
4
+ import { cn } from "../lib/utils"
5
+ import { ChevronDownIcon } from "lucide-react"
6
+
7
+ function NavigationMenu({
8
+ align = "start",
9
+ className,
10
+ children,
11
+ ...props
12
+ }: NavigationMenuPrimitive.Root.Props &
13
+ Pick<NavigationMenuPrimitive.Positioner.Props, "align">) {
14
+ return (
15
+ <NavigationMenuPrimitive.Root
16
+ data-slot="navigation-menu"
17
+ className={cn(
18
+ "group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
19
+ className
20
+ )}
21
+ {...props}
22
+ >
23
+ {children}
24
+ <NavigationMenuPositioner align={align} />
25
+ </NavigationMenuPrimitive.Root>
26
+ )
27
+ }
28
+
29
+ function NavigationMenuList({
30
+ className,
31
+ ...props
32
+ }: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.List>) {
33
+ return (
34
+ <NavigationMenuPrimitive.List
35
+ data-slot="navigation-menu-list"
36
+ className={cn(
37
+ "group flex flex-1 list-none items-center justify-center gap-0",
38
+ className
39
+ )}
40
+ {...props}
41
+ />
42
+ )
43
+ }
44
+
45
+ function NavigationMenuItem({
46
+ className,
47
+ ...props
48
+ }: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Item>) {
49
+ return (
50
+ <NavigationMenuPrimitive.Item
51
+ data-slot="navigation-menu-item"
52
+ className={cn("relative", className)}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ const navigationMenuTriggerStyle = cva(
59
+ "group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center rounded-lg px-2.5 py-1.5 text-sm font-medium transition-all outline-none hover:bg-muted focus:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-popup-open:bg-muted/50 data-popup-open:hover:bg-muted data-open:bg-muted/50 data-open:hover:bg-muted data-open:focus:bg-muted"
60
+ )
61
+
62
+ function NavigationMenuTrigger({
63
+ className,
64
+ children,
65
+ ...props
66
+ }: NavigationMenuPrimitive.Trigger.Props) {
67
+ return (
68
+ <NavigationMenuPrimitive.Trigger
69
+ data-slot="navigation-menu-trigger"
70
+ className={cn(navigationMenuTriggerStyle(), "group", className)}
71
+ {...props}
72
+ >
73
+ {children}{" "}
74
+ <ChevronDownIcon className="relative top-px ml-1 size-3 transition duration-300 group-data-popup-open/navigation-menu-trigger:rotate-180 group-data-open/navigation-menu-trigger:rotate-180" aria-hidden="true" />
75
+ </NavigationMenuPrimitive.Trigger>
76
+ )
77
+ }
78
+
79
+ function NavigationMenuContent({
80
+ className,
81
+ ...props
82
+ }: NavigationMenuPrimitive.Content.Props) {
83
+ return (
84
+ <NavigationMenuPrimitive.Content
85
+ data-slot="navigation-menu-content"
86
+ className={cn(
87
+ "data-ending-style:data-activation-direction=left:translate-x-[50%] data-ending-style:data-activation-direction=right:translate-x-[-50%] data-starting-style:data-activation-direction=left:translate-x-[-50%] data-starting-style:data-activation-direction=right:translate-x-[50%] h-full w-auto p-1 transition-[opacity,transform,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] group-data-[viewport=false]/navigation-menu:rounded-lg group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:ring-1 group-data-[viewport=false]/navigation-menu:ring-foreground/10 group-data-[viewport=false]/navigation-menu:duration-300 data-ending-style:opacity-0 data-starting-style:opacity-0 data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 data-[motion^=from-]:animate-in data-[motion^=from-]:fade-in data-[motion^=to-]:animate-out data-[motion^=to-]:fade-out **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none group-data-[viewport=false]/navigation-menu:data-open:animate-in group-data-[viewport=false]/navigation-menu:data-open:fade-in-0 group-data-[viewport=false]/navigation-menu:data-open:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-closed:animate-out group-data-[viewport=false]/navigation-menu:data-closed:fade-out-0 group-data-[viewport=false]/navigation-menu:data-closed:zoom-out-95",
88
+ className
89
+ )}
90
+ {...props}
91
+ />
92
+ )
93
+ }
94
+
95
+ function NavigationMenuPositioner({
96
+ className,
97
+ side = "bottom",
98
+ sideOffset = 8,
99
+ align = "start",
100
+ alignOffset = 0,
101
+ ...props
102
+ }: NavigationMenuPrimitive.Positioner.Props) {
103
+ return (
104
+ <NavigationMenuPrimitive.Portal>
105
+ <NavigationMenuPrimitive.Positioner
106
+ side={side}
107
+ sideOffset={sideOffset}
108
+ align={align}
109
+ alignOffset={alignOffset}
110
+ className={cn(
111
+ "isolate z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] data-instant:transition-none data-[side=bottom]:before:top-[-10px] data-[side=bottom]:before:right-0 data-[side=bottom]:before:left-0",
112
+ className
113
+ )}
114
+ {...props}
115
+ >
116
+ <NavigationMenuPrimitive.Popup data-koharu-ui-layer="" className="data-[ending-style]:easing-[ease] xs:w-(--popup-width) relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) rounded-lg bg-popover text-popover-foreground shadow ring-1 ring-foreground/10 transition-[opacity,transform,width,height,scale,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] outline-none data-ending-style:scale-90 data-ending-style:opacity-0 data-ending-style:duration-150 data-starting-style:scale-90 data-starting-style:opacity-0">
117
+ <NavigationMenuPrimitive.Viewport className="relative size-full overflow-hidden" />
118
+ </NavigationMenuPrimitive.Popup>
119
+ </NavigationMenuPrimitive.Positioner>
120
+ </NavigationMenuPrimitive.Portal>
121
+ )
122
+ }
123
+
124
+ function NavigationMenuLink({
125
+ className,
126
+ ...props
127
+ }: NavigationMenuPrimitive.Link.Props) {
128
+ return (
129
+ <NavigationMenuPrimitive.Link
130
+ data-slot="navigation-menu-link"
131
+ className={cn(
132
+ "flex items-center gap-2 rounded-lg p-2 text-sm transition-all outline-none hover:bg-muted focus:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1 in-data-[slot=navigation-menu-content]:rounded-md data-active:bg-muted/50 data-active:hover:bg-muted data-active:focus:bg-muted [&_svg:not([class*='size-'])]:size-4",
133
+ className
134
+ )}
135
+ {...props}
136
+ />
137
+ )
138
+ }
139
+
140
+ function NavigationMenuIndicator({
141
+ className,
142
+ ...props
143
+ }: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Icon>) {
144
+ return (
145
+ <NavigationMenuPrimitive.Icon
146
+ data-slot="navigation-menu-indicator"
147
+ className={cn(
148
+ "top-full z-1 flex h-1.5 items-end justify-center overflow-hidden data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:animate-in data-[state=visible]:fade-in",
149
+ className
150
+ )}
151
+ {...props}
152
+ >
153
+ <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
154
+ </NavigationMenuPrimitive.Icon>
155
+ )
156
+ }
157
+
158
+ export {
159
+ NavigationMenu,
160
+ NavigationMenuContent,
161
+ NavigationMenuIndicator,
162
+ NavigationMenuItem,
163
+ NavigationMenuLink,
164
+ NavigationMenuList,
165
+ NavigationMenuTrigger,
166
+ navigationMenuTriggerStyle,
167
+ NavigationMenuPositioner,
168
+ }
@@ -0,0 +1,68 @@
1
+ 'use client'
2
+
3
+ import { NumberField as NumberFieldPrimitive } from '@base-ui/react/number-field'
4
+ import * as React from 'react'
5
+
6
+ import { cn } from '../lib/utils'
7
+
8
+ const NumberField = NumberFieldPrimitive.Root
9
+
10
+ function NumberFieldGroup({ className, ...props }: NumberFieldPrimitive.Group.Props) {
11
+ return (
12
+ <NumberFieldPrimitive.Group
13
+ data-slot='number-field-group'
14
+ className={cn(
15
+ 'flex h-6 w-full min-w-0 items-center overflow-hidden rounded-md border border-input bg-transparent transition-colors focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/30 dark:bg-input/30 data-disabled:cursor-not-allowed data-disabled:opacity-50',
16
+ className,
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function NumberFieldInput({ className, ...props }: NumberFieldPrimitive.Input.Props) {
24
+ return (
25
+ <NumberFieldPrimitive.Input
26
+ data-slot='number-field-input'
27
+ className={cn(
28
+ 'h-full min-w-0 flex-1 bg-transparent px-1 text-center text-[11px] tabular-nums outline-none selection:bg-primary selection:text-primary-foreground',
29
+ className,
30
+ )}
31
+ {...props}
32
+ />
33
+ )
34
+ }
35
+
36
+ function NumberFieldDecrement({ className, ...props }: NumberFieldPrimitive.Decrement.Props) {
37
+ return (
38
+ <NumberFieldPrimitive.Decrement
39
+ data-slot='number-field-decrement'
40
+ className={cn(
41
+ 'grid size-6 shrink-0 place-items-center border-r border-input text-muted-foreground transition-colors outline-none hover:bg-muted hover:text-foreground focus-visible:bg-muted focus-visible:text-foreground disabled:pointer-events-none disabled:opacity-40 [&_svg:not([class*="size-"])]:size-3',
42
+ className,
43
+ )}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ function NumberFieldIncrement({ className, ...props }: NumberFieldPrimitive.Increment.Props) {
50
+ return (
51
+ <NumberFieldPrimitive.Increment
52
+ data-slot='number-field-increment'
53
+ className={cn(
54
+ 'grid size-6 shrink-0 place-items-center border-l border-input text-muted-foreground transition-colors outline-none hover:bg-muted hover:text-foreground focus-visible:bg-muted focus-visible:text-foreground disabled:pointer-events-none disabled:opacity-40 [&_svg:not([class*="size-"])]:size-3',
55
+ className,
56
+ )}
57
+ {...props}
58
+ />
59
+ )
60
+ }
61
+
62
+ export {
63
+ NumberField,
64
+ NumberFieldDecrement,
65
+ NumberFieldGroup,
66
+ NumberFieldIncrement,
67
+ NumberFieldInput,
68
+ }
@@ -0,0 +1,130 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "../lib/utils"
4
+ import { Button } from "./button"
5
+ import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
6
+
7
+ function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
8
+ return (
9
+ <nav
10
+ role="navigation"
11
+ aria-label="pagination"
12
+ data-slot="pagination"
13
+ className={cn("mx-auto flex w-full justify-center", className)}
14
+ {...props}
15
+ />
16
+ )
17
+ }
18
+
19
+ function PaginationContent({
20
+ className,
21
+ ...props
22
+ }: React.ComponentProps<"ul">) {
23
+ return (
24
+ <ul
25
+ data-slot="pagination-content"
26
+ className={cn("flex items-center gap-0.5", className)}
27
+ {...props}
28
+ />
29
+ )
30
+ }
31
+
32
+ function PaginationItem({ ...props }: React.ComponentProps<"li">) {
33
+ return <li data-slot="pagination-item" {...props} />
34
+ }
35
+
36
+ type PaginationLinkProps = {
37
+ isActive?: boolean
38
+ } & Pick<React.ComponentProps<typeof Button>, "size"> &
39
+ React.ComponentProps<"a">
40
+
41
+ function PaginationLink({
42
+ className,
43
+ isActive,
44
+ size = "icon",
45
+ ...props
46
+ }: PaginationLinkProps) {
47
+ return (
48
+ <Button
49
+ variant={isActive ? "outline" : "ghost"}
50
+ size={size}
51
+ className={cn(className)}
52
+ nativeButton={false}
53
+ render={
54
+ <a
55
+ aria-current={isActive ? "page" : undefined}
56
+ data-slot="pagination-link"
57
+ data-active={isActive}
58
+ {...props}
59
+ />
60
+ }
61
+ />
62
+ )
63
+ }
64
+
65
+ function PaginationPrevious({
66
+ className,
67
+ text = "Previous",
68
+ ...props
69
+ }: React.ComponentProps<typeof PaginationLink> & { text?: string }) {
70
+ return (
71
+ <PaginationLink
72
+ aria-label="Go to previous page"
73
+ size="default"
74
+ className={cn("pl-1.5!", className)}
75
+ {...props}
76
+ >
77
+ <ChevronLeftIcon data-icon="inline-start" />
78
+ <span className="hidden sm:block">{text}</span>
79
+ </PaginationLink>
80
+ )
81
+ }
82
+
83
+ function PaginationNext({
84
+ className,
85
+ text = "Next",
86
+ ...props
87
+ }: React.ComponentProps<typeof PaginationLink> & { text?: string }) {
88
+ return (
89
+ <PaginationLink
90
+ aria-label="Go to next page"
91
+ size="default"
92
+ className={cn("pr-1.5!", className)}
93
+ {...props}
94
+ >
95
+ <span className="hidden sm:block">{text}</span>
96
+ <ChevronRightIcon data-icon="inline-end" />
97
+ </PaginationLink>
98
+ )
99
+ }
100
+
101
+ function PaginationEllipsis({
102
+ className,
103
+ ...props
104
+ }: React.ComponentProps<"span">) {
105
+ return (
106
+ <span
107
+ aria-hidden
108
+ data-slot="pagination-ellipsis"
109
+ className={cn(
110
+ "flex size-8 items-center justify-center [&_svg:not([class*='size-'])]:size-4",
111
+ className
112
+ )}
113
+ {...props}
114
+ >
115
+ <MoreHorizontalIcon
116
+ />
117
+ <span className="sr-only">More pages</span>
118
+ </span>
119
+ )
120
+ }
121
+
122
+ export {
123
+ Pagination,
124
+ PaginationContent,
125
+ PaginationEllipsis,
126
+ PaginationItem,
127
+ PaginationLink,
128
+ PaginationNext,
129
+ PaginationPrevious,
130
+ }
@@ -0,0 +1,91 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Popover as PopoverPrimitive } from "@base-ui/react/popover"
5
+
6
+ import { cn } from "../lib/utils"
7
+
8
+ function Popover({ ...props }: PopoverPrimitive.Root.Props) {
9
+ return <PopoverPrimitive.Root data-slot="popover" {...props} />
10
+ }
11
+
12
+ function PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {
13
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
14
+ }
15
+
16
+ function PopoverContent({
17
+ className,
18
+ align = "center",
19
+ alignOffset = 0,
20
+ side = "bottom",
21
+ sideOffset = 4,
22
+ ...props
23
+ }: PopoverPrimitive.Popup.Props &
24
+ Pick<
25
+ PopoverPrimitive.Positioner.Props,
26
+ "align" | "alignOffset" | "side" | "sideOffset"
27
+ >) {
28
+ return (
29
+ <PopoverPrimitive.Portal>
30
+ <PopoverPrimitive.Positioner
31
+ align={align}
32
+ alignOffset={alignOffset}
33
+ side={side}
34
+ sideOffset={sideOffset}
35
+ className="isolate z-50"
36
+ >
37
+ <PopoverPrimitive.Popup
38
+ data-koharu-ui-layer=""
39
+ data-slot="popover-content"
40
+ className={cn(
41
+ "z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ </PopoverPrimitive.Positioner>
47
+ </PopoverPrimitive.Portal>
48
+ )
49
+ }
50
+
51
+ function PopoverHeader({ className, ...props }: React.ComponentProps<"div">) {
52
+ return (
53
+ <div
54
+ data-slot="popover-header"
55
+ className={cn("flex flex-col gap-0.5 text-sm", className)}
56
+ {...props}
57
+ />
58
+ )
59
+ }
60
+
61
+ function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
62
+ return (
63
+ <PopoverPrimitive.Title
64
+ data-slot="popover-title"
65
+ className={cn("font-medium", className)}
66
+ {...props}
67
+ />
68
+ )
69
+ }
70
+
71
+ function PopoverDescription({
72
+ className,
73
+ ...props
74
+ }: PopoverPrimitive.Description.Props) {
75
+ return (
76
+ <PopoverPrimitive.Description
77
+ data-slot="popover-description"
78
+ className={cn("text-muted-foreground", className)}
79
+ {...props}
80
+ />
81
+ )
82
+ }
83
+
84
+ export {
85
+ Popover,
86
+ PopoverContent,
87
+ PopoverDescription,
88
+ PopoverHeader,
89
+ PopoverTitle,
90
+ PopoverTrigger,
91
+ }
@@ -0,0 +1,83 @@
1
+ "use client"
2
+
3
+ import { Progress as ProgressPrimitive } from "@base-ui/react/progress"
4
+
5
+ import { cn } from "../lib/utils"
6
+
7
+ function Progress({
8
+ className,
9
+ children,
10
+ value,
11
+ ...props
12
+ }: ProgressPrimitive.Root.Props) {
13
+ return (
14
+ <ProgressPrimitive.Root
15
+ value={value}
16
+ data-slot="progress"
17
+ className={cn("flex flex-wrap gap-3", className)}
18
+ {...props}
19
+ >
20
+ {children}
21
+ <ProgressTrack>
22
+ <ProgressIndicator />
23
+ </ProgressTrack>
24
+ </ProgressPrimitive.Root>
25
+ )
26
+ }
27
+
28
+ function ProgressTrack({ className, ...props }: ProgressPrimitive.Track.Props) {
29
+ return (
30
+ <ProgressPrimitive.Track
31
+ className={cn(
32
+ "relative flex h-1 w-full items-center overflow-x-hidden rounded-full bg-muted",
33
+ className
34
+ )}
35
+ data-slot="progress-track"
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function ProgressIndicator({
42
+ className,
43
+ ...props
44
+ }: ProgressPrimitive.Indicator.Props) {
45
+ return (
46
+ <ProgressPrimitive.Indicator
47
+ data-slot="progress-indicator"
48
+ className={cn("h-full bg-primary transition-all", className)}
49
+ {...props}
50
+ />
51
+ )
52
+ }
53
+
54
+ function ProgressLabel({ className, ...props }: ProgressPrimitive.Label.Props) {
55
+ return (
56
+ <ProgressPrimitive.Label
57
+ className={cn("text-sm font-medium", className)}
58
+ data-slot="progress-label"
59
+ {...props}
60
+ />
61
+ )
62
+ }
63
+
64
+ function ProgressValue({ className, ...props }: ProgressPrimitive.Value.Props) {
65
+ return (
66
+ <ProgressPrimitive.Value
67
+ className={cn(
68
+ "ml-auto text-sm text-muted-foreground tabular-nums",
69
+ className
70
+ )}
71
+ data-slot="progress-value"
72
+ {...props}
73
+ />
74
+ )
75
+ }
76
+
77
+ export {
78
+ Progress,
79
+ ProgressTrack,
80
+ ProgressIndicator,
81
+ ProgressLabel,
82
+ ProgressValue,
83
+ }
@@ -0,0 +1,38 @@
1
+ "use client"
2
+
3
+ import { Radio as RadioPrimitive } from "@base-ui/react/radio"
4
+ import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group"
5
+
6
+ import { cn } from "../lib/utils"
7
+
8
+ function RadioGroup({ className, ...props }: RadioGroupPrimitive.Props) {
9
+ return (
10
+ <RadioGroupPrimitive
11
+ data-slot="radio-group"
12
+ className={cn("grid w-full gap-2", className)}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ function RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props) {
19
+ return (
20
+ <RadioPrimitive.Root
21
+ data-slot="radio-group-item"
22
+ className={cn(
23
+ "group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none 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",
24
+ className
25
+ )}
26
+ {...props}
27
+ >
28
+ <RadioPrimitive.Indicator
29
+ data-slot="radio-group-indicator"
30
+ className="flex size-4 items-center justify-center"
31
+ >
32
+ <span className="absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary-foreground" />
33
+ </RadioPrimitive.Indicator>
34
+ </RadioPrimitive.Root>
35
+ )
36
+ }
37
+
38
+ export { RadioGroup, RadioGroupItem }
@@ -0,0 +1,50 @@
1
+ "use client"
2
+
3
+ import * as ResizablePrimitive from "react-resizable-panels"
4
+
5
+ import { cn } from "../lib/utils"
6
+
7
+ function ResizablePanelGroup({
8
+ className,
9
+ ...props
10
+ }: ResizablePrimitive.GroupProps) {
11
+ return (
12
+ <ResizablePrimitive.Group
13
+ data-slot="resizable-panel-group"
14
+ className={cn(
15
+ "flex h-full w-full aria-[orientation=vertical]:flex-col",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function ResizablePanel({ ...props }: ResizablePrimitive.PanelProps) {
24
+ return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
25
+ }
26
+
27
+ function ResizableHandle({
28
+ withHandle,
29
+ className,
30
+ ...props
31
+ }: ResizablePrimitive.SeparatorProps & {
32
+ withHandle?: boolean
33
+ }) {
34
+ return (
35
+ <ResizablePrimitive.Separator
36
+ data-slot="resizable-handle"
37
+ className={cn(
38
+ "relative flex w-px items-center justify-center bg-border ring-offset-background after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-hidden aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90",
39
+ className
40
+ )}
41
+ {...props}
42
+ >
43
+ {withHandle && (
44
+ <div className="z-10 flex h-6 w-1 shrink-0 rounded-lg bg-border" />
45
+ )}
46
+ </ResizablePrimitive.Separator>
47
+ )
48
+ }
49
+
50
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup }