@vllnt/ui 0.1.4 → 0.1.7-canary.2c4792f

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 (225) hide show
  1. package/dist/components/accordion/accordion.js +172 -0
  2. package/dist/components/accordion/index.js +12 -0
  3. package/dist/components/alert/alert.js +53 -0
  4. package/dist/components/alert/index.js +7 -0
  5. package/dist/components/alert-dialog/alert-dialog.js +117 -0
  6. package/dist/components/alert-dialog/index.js +26 -0
  7. package/dist/components/aspect-ratio/aspect-ratio.js +6 -0
  8. package/dist/components/aspect-ratio/index.js +4 -0
  9. package/dist/components/avatar/avatar.js +43 -0
  10. package/dist/components/avatar/index.js +6 -0
  11. package/dist/components/badge/badge.js +26 -0
  12. package/dist/components/badge/index.js +5 -0
  13. package/dist/components/blog-card/blog-card.js +50 -0
  14. package/dist/components/blog-card/index.js +5 -0
  15. package/dist/components/breadcrumb/breadcrumb.js +61 -0
  16. package/dist/components/breadcrumb/index.js +4 -0
  17. package/dist/components/button/button.js +48 -0
  18. package/dist/components/button/index.js +5 -0
  19. package/dist/components/calendar/calendar.js +71 -0
  20. package/dist/components/calendar/index.js +4 -0
  21. package/dist/components/callout/callout.js +59 -0
  22. package/dist/components/callout/index.js +4 -0
  23. package/dist/components/card/card.js +64 -0
  24. package/dist/components/card/index.js +16 -0
  25. package/dist/components/carousel/carousel.js +239 -0
  26. package/dist/components/carousel/index.js +14 -0
  27. package/dist/components/category-filter/category-filter.js +34 -0
  28. package/dist/components/category-filter/index.js +4 -0
  29. package/dist/components/chart/area-chart.js +99 -0
  30. package/dist/components/chart/bar-chart.js +80 -0
  31. package/dist/components/chart/index.js +3 -0
  32. package/dist/components/chart/line-chart.js +97 -0
  33. package/dist/components/checkbox/checkbox.js +28 -0
  34. package/dist/components/checkbox/index.js +4 -0
  35. package/dist/components/checklist/checklist.js +181 -0
  36. package/dist/components/checklist/index.js +6 -0
  37. package/dist/components/code-block/code-block.js +126 -0
  38. package/dist/components/code-block/index.js +4 -0
  39. package/dist/components/code-playground/code-playground.js +86 -0
  40. package/dist/components/code-playground/index.js +8 -0
  41. package/dist/components/collapsible/collapsible.js +10 -0
  42. package/dist/components/collapsible/index.js +10 -0
  43. package/dist/components/command/command.js +123 -0
  44. package/dist/components/command/index.js +22 -0
  45. package/dist/components/comparison/comparison.js +121 -0
  46. package/dist/components/comparison/index.js +8 -0
  47. package/dist/components/completion-dialog/completion-dialog.js +173 -0
  48. package/dist/components/completion-dialog/index.js +6 -0
  49. package/dist/components/content-intro/content-intro.js +144 -0
  50. package/dist/components/content-intro/index.js +6 -0
  51. package/dist/components/context-menu/context-menu.js +154 -0
  52. package/dist/components/context-menu/index.js +34 -0
  53. package/dist/components/cookie-consent/cookie-consent.js +175 -0
  54. package/dist/components/cookie-consent/index.js +8 -0
  55. package/dist/components/dialog/dialog.js +105 -0
  56. package/dist/components/dialog/index.js +24 -0
  57. package/dist/components/drawer/drawer.js +102 -0
  58. package/dist/components/drawer/index.js +24 -0
  59. package/dist/components/dropdown-menu/dropdown-menu.js +151 -0
  60. package/dist/components/dropdown-menu/index.js +34 -0
  61. package/dist/components/exercise/exercise.js +112 -0
  62. package/dist/components/exercise/index.js +4 -0
  63. package/dist/components/faq/faq.js +56 -0
  64. package/dist/components/faq/index.js +5 -0
  65. package/dist/components/filter-bar/filter-bar.js +244 -0
  66. package/dist/components/filter-bar/index.js +6 -0
  67. package/dist/components/floating-action-button/floating-action-button.js +35 -0
  68. package/dist/components/floating-action-button/index.js +6 -0
  69. package/dist/components/flow-diagram/flow-canvas.js +109 -0
  70. package/dist/components/flow-diagram/flow-controls.js +140 -0
  71. package/dist/components/flow-diagram/flow-diagram.js +114 -0
  72. package/dist/components/flow-diagram/flow-error-boundary.js +63 -0
  73. package/dist/components/flow-diagram/flow-fullscreen.js +58 -0
  74. package/dist/components/flow-diagram/index.js +12 -0
  75. package/dist/components/flow-diagram/types.js +0 -0
  76. package/dist/components/flow-diagram/use-flow-diagram.js +146 -0
  77. package/dist/components/horizontal-scroll-row/horizontal-scroll-row.js +66 -0
  78. package/dist/components/horizontal-scroll-row/index.js +6 -0
  79. package/dist/components/hover-card/hover-card.js +26 -0
  80. package/dist/components/hover-card/index.js +6 -0
  81. package/dist/components/index.js +641 -0
  82. package/dist/components/inline-input/index.js +4 -0
  83. package/dist/components/inline-input/inline-input.js +42 -0
  84. package/dist/components/input/index.js +4 -0
  85. package/dist/components/input/input.js +23 -0
  86. package/dist/components/input-otp/index.js +12 -0
  87. package/dist/components/input-otp/input-otp.js +54 -0
  88. package/dist/components/key-concept/index.js +8 -0
  89. package/dist/components/key-concept/key-concept.js +79 -0
  90. package/dist/components/keyboard-shortcuts-help/index.js +6 -0
  91. package/dist/components/keyboard-shortcuts-help/keyboard-shortcuts-help.js +121 -0
  92. package/dist/components/label/index.js +4 -0
  93. package/dist/components/label/label.js +21 -0
  94. package/dist/components/lang-provider/index.js +4 -0
  95. package/dist/components/lang-provider/lang-provider.js +18 -0
  96. package/dist/components/learning-objectives/index.js +10 -0
  97. package/dist/components/learning-objectives/learning-objectives.js +76 -0
  98. package/dist/components/mdx-content/index.js +4 -0
  99. package/dist/components/mdx-content/mdx-content.js +151 -0
  100. package/dist/components/menubar/index.js +36 -0
  101. package/dist/components/menubar/menubar.js +183 -0
  102. package/dist/components/model-selector/index.js +6 -0
  103. package/dist/components/model-selector/model-selector.js +374 -0
  104. package/dist/components/navbar-saas/index.js +6 -0
  105. package/dist/components/navbar-saas/navbar-saas.js +68 -0
  106. package/dist/components/navbar-saas/use-mobile.js +19 -0
  107. package/dist/components/navigation-menu/index.js +22 -0
  108. package/dist/components/navigation-menu/navigation-menu.js +108 -0
  109. package/dist/components/pagination/index.js +4 -0
  110. package/dist/components/pagination/pagination.js +44 -0
  111. package/dist/components/popover/index.js +12 -0
  112. package/dist/components/popover/popover.js +28 -0
  113. package/dist/components/pro-tip/index.js +8 -0
  114. package/dist/components/pro-tip/pro-tip.js +139 -0
  115. package/dist/components/profile-section/index.js +4 -0
  116. package/dist/components/profile-section/profile-section.js +45 -0
  117. package/dist/components/progress-bar/index.js +4 -0
  118. package/dist/components/progress-bar/progress-bar.js +56 -0
  119. package/dist/components/progress-card/index.js +6 -0
  120. package/dist/components/progress-card/progress-card.js +71 -0
  121. package/dist/components/quiz/index.js +4 -0
  122. package/dist/components/quiz/quiz.js +210 -0
  123. package/dist/components/radio-group/index.js +5 -0
  124. package/dist/components/radio-group/radio-group.js +36 -0
  125. package/dist/components/resizable/index.js +10 -0
  126. package/dist/components/resizable/resizable.js +39 -0
  127. package/dist/components/scroll-area/index.js +5 -0
  128. package/dist/components/scroll-area/scroll-area.js +39 -0
  129. package/dist/components/search-bar/index.js +4 -0
  130. package/dist/components/search-bar/search-bar.js +122 -0
  131. package/dist/components/search-dialog/index.js +4 -0
  132. package/dist/components/search-dialog/search-dialog.js +102 -0
  133. package/dist/components/select/index.js +24 -0
  134. package/dist/components/select/select.js +125 -0
  135. package/dist/components/separator/index.js +4 -0
  136. package/dist/components/separator/separator.js +25 -0
  137. package/dist/components/share-dialog/index.js +6 -0
  138. package/dist/components/share-dialog/share-dialog.js +121 -0
  139. package/dist/components/share-section/index.js +6 -0
  140. package/dist/components/share-section/share-section.js +57 -0
  141. package/dist/components/sheet/index.js +24 -0
  142. package/dist/components/sheet/sheet.js +116 -0
  143. package/dist/components/sidebar/index.js +4 -0
  144. package/dist/components/sidebar/sidebar.js +188 -0
  145. package/dist/components/sidebar-provider/index.js +5 -0
  146. package/dist/components/sidebar-provider/sidebar-provider.js +25 -0
  147. package/dist/components/sidebar-toggle/index.js +4 -0
  148. package/dist/components/sidebar-toggle/sidebar-toggle.js +36 -0
  149. package/dist/components/skeleton/index.js +4 -0
  150. package/dist/components/skeleton/skeleton.js +17 -0
  151. package/dist/components/slider/index.js +4 -0
  152. package/dist/components/slider/slider.js +24 -0
  153. package/dist/components/slideshow/index.js +6 -0
  154. package/dist/components/slideshow/slideshow.js +440 -0
  155. package/dist/components/social-fab/index.js +6 -0
  156. package/dist/components/social-fab/social-fab.js +211 -0
  157. package/dist/components/social-fab/use-social-fab.js +111 -0
  158. package/dist/components/spinner/index.js +4 -0
  159. package/dist/components/spinner/spinner.js +23 -0
  160. package/dist/components/step-by-step/index.js +8 -0
  161. package/dist/components/step-by-step/step-by-step.js +194 -0
  162. package/dist/components/step-navigation/index.js +4 -0
  163. package/dist/components/step-navigation/step-navigation.js +119 -0
  164. package/dist/components/switch/index.js +4 -0
  165. package/dist/components/switch/switch.js +28 -0
  166. package/dist/components/table/index.js +20 -0
  167. package/dist/components/table/table.js +87 -0
  168. package/dist/components/table-of-contents/index.js +4 -0
  169. package/dist/components/table-of-contents/table-of-contents.js +71 -0
  170. package/dist/components/table-of-contents-panel/index.js +6 -0
  171. package/dist/components/table-of-contents-panel/table-of-contents-panel.js +202 -0
  172. package/dist/components/tabs/index.js +12 -0
  173. package/dist/components/tabs/tabs.js +84 -0
  174. package/dist/components/terminal/index.js +8 -0
  175. package/dist/components/terminal/terminal.js +119 -0
  176. package/dist/components/textarea/index.js +4 -0
  177. package/dist/components/textarea/textarea.js +22 -0
  178. package/dist/components/theme-provider/index.js +4 -0
  179. package/dist/components/theme-provider/theme-provider.js +11 -0
  180. package/dist/components/theme-toggle/index.js +4 -0
  181. package/dist/components/theme-toggle/theme-toggle.js +170 -0
  182. package/dist/components/thinking-block/index.js +4 -0
  183. package/dist/components/thinking-block/thinking-block.js +56 -0
  184. package/dist/components/tldr-section/index.js +4 -0
  185. package/dist/components/tldr-section/tldr-section.js +101 -0
  186. package/dist/components/toast/index.js +18 -0
  187. package/dist/components/toast/toast.js +84 -0
  188. package/dist/components/toast/toaster.js +38 -0
  189. package/dist/components/toggle/index.js +5 -0
  190. package/dist/components/toggle/toggle.js +39 -0
  191. package/dist/components/toggle-group/index.js +5 -0
  192. package/dist/components/toggle-group/toggle-group.js +46 -0
  193. package/dist/components/tooltip/index.js +12 -0
  194. package/dist/components/tooltip/tooltip.js +27 -0
  195. package/dist/components/truncated-text/index.js +4 -0
  196. package/dist/components/truncated-text/truncated-text.js +25 -0
  197. package/dist/components/tutorial-card/index.js +6 -0
  198. package/dist/components/tutorial-card/tutorial-card.js +78 -0
  199. package/dist/components/tutorial-complete/index.js +6 -0
  200. package/dist/components/tutorial-complete/tutorial-complete.js +134 -0
  201. package/dist/components/tutorial-filters/index.js +6 -0
  202. package/dist/components/tutorial-filters/tutorial-filters.js +205 -0
  203. package/dist/components/tutorial-intro-content/index.js +6 -0
  204. package/dist/components/tutorial-intro-content/tutorial-intro-content.js +141 -0
  205. package/dist/components/tutorial-mdx/index.js +8 -0
  206. package/dist/components/tutorial-mdx/tutorial-mdx.js +219 -0
  207. package/dist/components/video-embed/index.js +4 -0
  208. package/dist/components/video-embed/video-embed.js +77 -0
  209. package/dist/components/view-switcher/index.js +6 -0
  210. package/dist/components/view-switcher/view-switcher.js +92 -0
  211. package/dist/index.d.ts +44 -2
  212. package/dist/index.js +14 -8556
  213. package/dist/lib/types.js +11 -0
  214. package/dist/lib/use-debounce.js +17 -0
  215. package/dist/lib/use-horizontal-scroll.js +60 -0
  216. package/dist/lib/use-mounted.js +17 -0
  217. package/dist/lib/utils.js +8 -0
  218. package/dist/tailwind-preset.d.ts +5 -0
  219. package/dist/tailwind-preset.js +9 -10
  220. package/dist/types/content.js +0 -0
  221. package/dist/types/index.js +0 -0
  222. package/package.json +42 -23
  223. package/LICENSE +0 -21
  224. package/dist/chunk-XRV5RSYH.js +0 -569
  225. package/dist/flow-diagram-N3EHM6VB.js +0 -2
@@ -0,0 +1,183 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { forwardRef } from "react";
4
+ import * as MenubarPrimitive from "@radix-ui/react-menubar";
5
+ import { Check, ChevronRight, Circle } from "lucide-react";
6
+ import { cn } from "../../lib/utils";
7
+ const MenubarMenu = MenubarPrimitive.Menu;
8
+ const MenubarGroup = MenubarPrimitive.Group;
9
+ const MenubarPortal = MenubarPrimitive.Portal;
10
+ const MenubarSub = MenubarPrimitive.Sub;
11
+ const MenubarRadioGroup = MenubarPrimitive.RadioGroup;
12
+ const Menubar = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
13
+ MenubarPrimitive.Root,
14
+ {
15
+ className: cn(
16
+ "flex h-10 items-center space-x-1 rounded-md border bg-background p-1",
17
+ className
18
+ ),
19
+ ref,
20
+ ...props
21
+ }
22
+ ));
23
+ Menubar.displayName = MenubarPrimitive.Root.displayName;
24
+ const MenubarTrigger = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
25
+ MenubarPrimitive.Trigger,
26
+ {
27
+ className: cn(
28
+ "flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
29
+ className
30
+ ),
31
+ ref,
32
+ ...props
33
+ }
34
+ ));
35
+ MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
36
+ const MenubarSubTrigger = forwardRef(({ children, className, inset, ...props }, ref) => /* @__PURE__ */ jsxs(
37
+ MenubarPrimitive.SubTrigger,
38
+ {
39
+ className: cn(
40
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
41
+ inset && "pl-8",
42
+ className
43
+ ),
44
+ ref,
45
+ ...props,
46
+ children: [
47
+ children,
48
+ /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto h-4 w-4" })
49
+ ]
50
+ }
51
+ ));
52
+ MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
53
+ const MenubarSubContent = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
54
+ MenubarPrimitive.SubContent,
55
+ {
56
+ className: cn(
57
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-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",
58
+ className
59
+ ),
60
+ ref,
61
+ ...props
62
+ }
63
+ ));
64
+ MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
65
+ const MenubarContent = forwardRef(
66
+ ({ align = "start", alignOffset = -4, className, sideOffset = 8, ...props }, ref) => /* @__PURE__ */ jsx(MenubarPrimitive.Portal, { children: /* @__PURE__ */ jsx(
67
+ MenubarPrimitive.Content,
68
+ {
69
+ align,
70
+ alignOffset,
71
+ className: cn(
72
+ "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-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",
73
+ className
74
+ ),
75
+ ref,
76
+ sideOffset,
77
+ ...props
78
+ }
79
+ ) })
80
+ );
81
+ MenubarContent.displayName = MenubarPrimitive.Content.displayName;
82
+ const MenubarItem = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
83
+ MenubarPrimitive.Item,
84
+ {
85
+ className: cn(
86
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
87
+ inset && "pl-8",
88
+ className
89
+ ),
90
+ ref,
91
+ ...props
92
+ }
93
+ ));
94
+ MenubarItem.displayName = MenubarPrimitive.Item.displayName;
95
+ const MenubarCheckboxItem = forwardRef(({ checked, children, className, ...props }, ref) => /* @__PURE__ */ jsxs(
96
+ MenubarPrimitive.CheckboxItem,
97
+ {
98
+ checked,
99
+ className: cn(
100
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
101
+ className
102
+ ),
103
+ ref,
104
+ ...props,
105
+ children: [
106
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(MenubarPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }) }),
107
+ children
108
+ ]
109
+ }
110
+ ));
111
+ MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
112
+ const MenubarRadioItem = forwardRef(({ children, className, ...props }, ref) => /* @__PURE__ */ jsxs(
113
+ MenubarPrimitive.RadioItem,
114
+ {
115
+ className: cn(
116
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
117
+ className
118
+ ),
119
+ ref,
120
+ ...props,
121
+ children: [
122
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(MenubarPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Circle, { className: "h-2 w-2 fill-current" }) }) }),
123
+ children
124
+ ]
125
+ }
126
+ ));
127
+ MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
128
+ const MenubarLabel = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
129
+ MenubarPrimitive.Label,
130
+ {
131
+ className: cn(
132
+ "px-2 py-1.5 text-sm font-semibold",
133
+ inset && "pl-8",
134
+ className
135
+ ),
136
+ ref,
137
+ ...props
138
+ }
139
+ ));
140
+ MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
141
+ const MenubarSeparator = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
142
+ MenubarPrimitive.Separator,
143
+ {
144
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
145
+ ref,
146
+ ...props
147
+ }
148
+ ));
149
+ MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
150
+ const MenubarShortcut = ({
151
+ className,
152
+ ...props
153
+ }) => {
154
+ return /* @__PURE__ */ jsx(
155
+ "span",
156
+ {
157
+ className: cn(
158
+ "ml-auto text-xs tracking-widest text-muted-foreground",
159
+ className
160
+ ),
161
+ ...props
162
+ }
163
+ );
164
+ };
165
+ MenubarShortcut.displayName = "MenubarShortcut";
166
+ export {
167
+ Menubar,
168
+ MenubarCheckboxItem,
169
+ MenubarContent,
170
+ MenubarGroup,
171
+ MenubarItem,
172
+ MenubarLabel,
173
+ MenubarMenu,
174
+ MenubarPortal,
175
+ MenubarRadioGroup,
176
+ MenubarRadioItem,
177
+ MenubarSeparator,
178
+ MenubarShortcut,
179
+ MenubarSub,
180
+ MenubarSubContent,
181
+ MenubarSubTrigger,
182
+ MenubarTrigger
183
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ ModelSelector
3
+ } from "./model-selector";
4
+ export {
5
+ ModelSelector
6
+ };
@@ -0,0 +1,374 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useMemo, useRef, useState } from "react";
4
+ import { ArrowUpDown, Filter } from "lucide-react";
5
+ import { cn } from "../../lib/utils";
6
+ import { Badge } from "../badge";
7
+ import { Button } from "../button";
8
+ import {
9
+ Command,
10
+ CommandEmpty,
11
+ CommandGroup,
12
+ CommandItem,
13
+ CommandList
14
+ } from "../command";
15
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../dialog";
16
+ import {
17
+ DropdownMenu,
18
+ DropdownMenuContent,
19
+ DropdownMenuLabel,
20
+ DropdownMenuRadioGroup,
21
+ DropdownMenuRadioItem,
22
+ DropdownMenuSeparator,
23
+ DropdownMenuTrigger
24
+ } from "../dropdown-menu";
25
+ import { Input } from "../input";
26
+ function getProvider(modelId) {
27
+ const parts = modelId.split("/");
28
+ return parts[0] || "unknown";
29
+ }
30
+ function getAveragePrice(model) {
31
+ if (!model.pricing) return Number.POSITIVE_INFINITY;
32
+ const inputPrice = model.pricing.input ?? 0;
33
+ const outputPrice = model.pricing.output ?? inputPrice;
34
+ return (inputPrice + outputPrice) / 2;
35
+ }
36
+ function formatPrice(price) {
37
+ if (!price) return "N/A";
38
+ return `$${price.toFixed(2)}/1M`;
39
+ }
40
+ function getProviders(models) {
41
+ const { providers } = models.reduce(
42
+ (accumulator, model) => {
43
+ const provider = getProvider(model.id);
44
+ if (!accumulator.seen.has(provider)) {
45
+ accumulator.seen.add(provider);
46
+ accumulator.providers.push(provider);
47
+ }
48
+ return accumulator;
49
+ },
50
+ { providers: [], seen: /* @__PURE__ */ new Set() }
51
+ );
52
+ return providers.sort();
53
+ }
54
+ function applyProviderFilter(models, providerFilter) {
55
+ if (providerFilter === "all") return models;
56
+ return models.filter((model) => getProvider(model.id) === providerFilter);
57
+ }
58
+ function applySearchFilter(models, modelSearchQuery) {
59
+ if (!modelSearchQuery.trim()) return models;
60
+ const query = modelSearchQuery.toLowerCase();
61
+ return models.filter(
62
+ (model) => model.name.toLowerCase().includes(query) || model.id.toLowerCase().includes(query) || model.description?.toLowerCase().includes(query) || getProvider(model.id).toLowerCase().includes(query)
63
+ );
64
+ }
65
+ function sortModelsBy(models, sortBy) {
66
+ const sorted = [...models];
67
+ return sorted.sort((a, b) => {
68
+ switch (sortBy) {
69
+ case "name":
70
+ return a.name.localeCompare(b.name);
71
+ case "price-low":
72
+ return getAveragePrice(a) - getAveragePrice(b);
73
+ case "price-high":
74
+ return getAveragePrice(b) - getAveragePrice(a);
75
+ case "provider": {
76
+ const providerA = getProvider(a.id);
77
+ const providerB = getProvider(b.id);
78
+ if (providerA !== providerB) return providerA.localeCompare(providerB);
79
+ return a.name.localeCompare(b.name);
80
+ }
81
+ default:
82
+ return 0;
83
+ }
84
+ });
85
+ }
86
+ function promoteSelected(models, selectedModelId) {
87
+ const sorted = [...models];
88
+ const selectedIndex = sorted.findIndex(
89
+ (model) => model.id === selectedModelId
90
+ );
91
+ if (selectedIndex > 0) {
92
+ const [selected] = sorted.splice(selectedIndex, 1);
93
+ if (selected) sorted.unshift(selected);
94
+ }
95
+ return sorted;
96
+ }
97
+ function resetFilters(setModelSearchQuery, setProviderFilter, setSortBy) {
98
+ setModelSearchQuery("");
99
+ setProviderFilter("all");
100
+ setSortBy("name");
101
+ }
102
+ function handleModelSelect({
103
+ handleClose,
104
+ id,
105
+ onSelectModel,
106
+ selectionGuardReference
107
+ }) {
108
+ if (selectionGuardReference.current === id) return;
109
+ selectionGuardReference.current = id;
110
+ onSelectModel(id);
111
+ setTimeout(() => {
112
+ if (selectionGuardReference.current === id)
113
+ selectionGuardReference.current = null;
114
+ }, 0);
115
+ handleClose(false);
116
+ }
117
+ function filterAndSortModels({
118
+ models,
119
+ modelSearchQuery,
120
+ providerFilter,
121
+ selectedModelId,
122
+ sortBy
123
+ }) {
124
+ const filtered = applySearchFilter(
125
+ applyProviderFilter(models, providerFilter),
126
+ modelSearchQuery
127
+ );
128
+ return promoteSelected(sortModelsBy(filtered, sortBy), selectedModelId);
129
+ }
130
+ function useFilteredModels(options) {
131
+ const { models, modelSearchQuery, providerFilter, selectedModelId, sortBy } = options;
132
+ return useMemo(
133
+ () => filterAndSortModels({
134
+ models,
135
+ modelSearchQuery,
136
+ providerFilter,
137
+ selectedModelId,
138
+ sortBy
139
+ }),
140
+ [models, modelSearchQuery, sortBy, providerFilter, selectedModelId]
141
+ );
142
+ }
143
+ function useModelSelectorState({
144
+ models,
145
+ onOpenChange,
146
+ onSelectModel,
147
+ selectedModelId
148
+ }) {
149
+ const [modelSearchQuery, setModelSearchQuery] = useState("");
150
+ const [sortBy, setSortBy] = useState("name");
151
+ const [providerFilter, setProviderFilter] = useState("all");
152
+ const selectionGuardReference = useRef(null);
153
+ const providers = useMemo(() => getProviders(models), [models]);
154
+ const filteredAndSortedModels = useFilteredModels({
155
+ models,
156
+ modelSearchQuery,
157
+ providerFilter,
158
+ selectedModelId,
159
+ sortBy
160
+ });
161
+ const handleClose = (nextOpen) => {
162
+ onOpenChange(nextOpen);
163
+ if (!nextOpen) {
164
+ resetFilters(setModelSearchQuery, setProviderFilter, setSortBy);
165
+ }
166
+ };
167
+ const handleSelect = (id) => {
168
+ handleModelSelect({
169
+ handleClose,
170
+ id,
171
+ onSelectModel,
172
+ selectionGuardReference
173
+ });
174
+ };
175
+ return {
176
+ filteredAndSortedModels,
177
+ handleClose,
178
+ handleSelect,
179
+ modelSearchQuery,
180
+ providerFilter,
181
+ providers,
182
+ setModelSearchQuery,
183
+ setProviderFilter,
184
+ setSortBy,
185
+ sortBy
186
+ };
187
+ }
188
+ function ProviderFilterMenu({
189
+ onChange,
190
+ providerFilter,
191
+ providers
192
+ }) {
193
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
194
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { className: "h-9 gap-2", size: "sm", variant: "outline", children: [
195
+ /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4" }),
196
+ providerFilter === "all" ? "All Providers" : providerFilter
197
+ ] }) }),
198
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-48", children: [
199
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Filter by Provider" }),
200
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
201
+ /* @__PURE__ */ jsxs(DropdownMenuRadioGroup, { onValueChange: onChange, value: providerFilter, children: [
202
+ /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "all", children: "All Providers" }),
203
+ providers.map((provider) => /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: provider, children: provider }, provider))
204
+ ] })
205
+ ] })
206
+ ] });
207
+ }
208
+ function SortMenu({ onChange, sortBy }) {
209
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
210
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { className: "h-9 gap-2", size: "sm", variant: "outline", children: [
211
+ /* @__PURE__ */ jsx(ArrowUpDown, { className: "h-4 w-4" }),
212
+ "Sort"
213
+ ] }) }),
214
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-48", children: [
215
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Sort by" }),
216
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
217
+ /* @__PURE__ */ jsxs(
218
+ DropdownMenuRadioGroup,
219
+ {
220
+ onValueChange: (value) => {
221
+ onChange(value);
222
+ },
223
+ value: sortBy,
224
+ children: [
225
+ /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "name", children: "Name" }),
226
+ /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "provider", children: "Provider" }),
227
+ /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "price-low", children: "Price: Low to High" }),
228
+ /* @__PURE__ */ jsx(DropdownMenuRadioItem, { value: "price-high", children: "Price: High to Low" })
229
+ ]
230
+ }
231
+ )
232
+ ] })
233
+ ] });
234
+ }
235
+ function ModelSelectorFilters({
236
+ modelSearchQuery,
237
+ onProviderChange,
238
+ onSearchChange,
239
+ onSortChange,
240
+ providerFilter,
241
+ providers,
242
+ sortBy
243
+ }) {
244
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-1 pb-2 border-b", children: [
245
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
246
+ Input,
247
+ {
248
+ className: "h-9",
249
+ onChange: (event) => {
250
+ onSearchChange(event.target.value);
251
+ },
252
+ placeholder: "Search models or providers...",
253
+ value: modelSearchQuery
254
+ }
255
+ ) }),
256
+ /* @__PURE__ */ jsx(
257
+ ProviderFilterMenu,
258
+ {
259
+ onChange: onProviderChange,
260
+ providerFilter,
261
+ providers
262
+ }
263
+ ),
264
+ /* @__PURE__ */ jsx(SortMenu, { onChange: onSortChange, sortBy })
265
+ ] });
266
+ }
267
+ function ModelList({ models, onSelect, selectedModelId }) {
268
+ return /* @__PURE__ */ jsx(Command, { className: "flex-1", shouldFilter: false, children: /* @__PURE__ */ jsxs(CommandList, { className: "max-h-[60vh]", children: [
269
+ /* @__PURE__ */ jsx(CommandEmpty, { children: "No models found." }),
270
+ /* @__PURE__ */ jsx(CommandGroup, { children: models.map((model) => /* @__PURE__ */ jsx(
271
+ ModelListItem,
272
+ {
273
+ model,
274
+ onSelect,
275
+ selectedModelId
276
+ },
277
+ model.id
278
+ )) })
279
+ ] }) });
280
+ }
281
+ function ModelPricing({ pricing }) {
282
+ if (!pricing) return null;
283
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-xs text-muted-foreground pointer-events-none", children: [
284
+ pricing.input ? /* @__PURE__ */ jsxs("span", { children: [
285
+ "In: ",
286
+ formatPrice(pricing.input)
287
+ ] }) : null,
288
+ pricing.output ? /* @__PURE__ */ jsxs("span", { children: [
289
+ "Out: ",
290
+ formatPrice(pricing.output)
291
+ ] }) : null
292
+ ] });
293
+ }
294
+ function ModelListItem({
295
+ model,
296
+ onSelect,
297
+ selectedModelId
298
+ }) {
299
+ const isSelected = selectedModelId === model.id;
300
+ const provider = getProvider(model.id);
301
+ return /* @__PURE__ */ jsxs(
302
+ CommandItem,
303
+ {
304
+ className: cn(
305
+ "flex flex-col items-start py-3",
306
+ isSelected && "bg-accent"
307
+ ),
308
+ disabled: isSelected,
309
+ onSelect: () => {
310
+ onSelect(model.id);
311
+ },
312
+ value: model.id,
313
+ children: [
314
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between w-full pointer-events-none", children: [
315
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
316
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: model.name }),
317
+ isSelected ? /* @__PURE__ */ jsx(Badge, { className: "text-xs pointer-events-none", variant: "secondary", children: "Selected" }) : null,
318
+ /* @__PURE__ */ jsx(
319
+ Badge,
320
+ {
321
+ className: "text-xs font-mono pointer-events-none",
322
+ variant: "outline",
323
+ children: provider
324
+ }
325
+ )
326
+ ] }),
327
+ /* @__PURE__ */ jsx(ModelPricing, { pricing: model.pricing })
328
+ ] }),
329
+ model.description ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mt-1 pointer-events-none", children: model.description }) : null,
330
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mt-1 font-mono pointer-events-none", children: model.id })
331
+ ]
332
+ }
333
+ );
334
+ }
335
+ function ModelSelector(props) {
336
+ const {
337
+ filteredAndSortedModels,
338
+ handleClose,
339
+ handleSelect,
340
+ modelSearchQuery,
341
+ providerFilter,
342
+ providers,
343
+ setModelSearchQuery,
344
+ setProviderFilter,
345
+ setSortBy,
346
+ sortBy
347
+ } = useModelSelectorState(props);
348
+ return /* @__PURE__ */ jsx(Dialog, { onOpenChange: handleClose, open: props.open, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-2xl max-h-[80vh] flex flex-col", children: [
349
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "Select Model" }) }),
350
+ /* @__PURE__ */ jsx(
351
+ ModelSelectorFilters,
352
+ {
353
+ modelSearchQuery,
354
+ onProviderChange: setProviderFilter,
355
+ onSearchChange: setModelSearchQuery,
356
+ onSortChange: setSortBy,
357
+ providerFilter,
358
+ providers,
359
+ sortBy
360
+ }
361
+ ),
362
+ /* @__PURE__ */ jsx(
363
+ ModelList,
364
+ {
365
+ models: filteredAndSortedModels,
366
+ onSelect: handleSelect,
367
+ selectedModelId: props.selectedModelId
368
+ }
369
+ )
370
+ ] }) });
371
+ }
372
+ export {
373
+ ModelSelector
374
+ };
@@ -0,0 +1,6 @@
1
+ import { NavbarSaas } from "./navbar-saas";
2
+ import { useMobile } from "./use-mobile";
3
+ export {
4
+ NavbarSaas,
5
+ useMobile
6
+ };
@@ -0,0 +1,68 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Menu, X } from "lucide-react";
4
+ import Link from "next/link";
5
+ import { usePathname } from "next/navigation";
6
+ import { cn } from "../../lib/utils";
7
+ import { Button } from "../button";
8
+ import { useSidebar } from "../sidebar-provider";
9
+ import { ThemeToggle } from "../theme-toggle";
10
+ import { useMobile } from "./use-mobile";
11
+ function NavbarSaas({
12
+ brand,
13
+ navItems = [],
14
+ rightSlot,
15
+ showMobileMenu = true
16
+ }) {
17
+ const pathname = usePathname();
18
+ const { open, setOpen } = useSidebar();
19
+ const isMobile = useMobile();
20
+ return /* @__PURE__ */ jsx("header", { className: "sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-full", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex h-16 items-center justify-between px-4", children: [
21
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
22
+ showMobileMenu && isMobile ? /* @__PURE__ */ jsx(
23
+ Button,
24
+ {
25
+ className: "lg:hidden",
26
+ onClick: () => {
27
+ setOpen(!open);
28
+ },
29
+ size: "icon",
30
+ variant: "ghost",
31
+ children: open ? /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Menu, { className: "h-4 w-4" })
32
+ }
33
+ ) : null,
34
+ brand ? typeof brand === "string" ? /* @__PURE__ */ jsx(Link, { className: "text-xl font-bold truncate", href: "/", children: brand }) : brand : null,
35
+ navItems.length > 0 ? /* @__PURE__ */ jsx("nav", { className: "hidden md:flex gap-6", children: navItems.map((item) => /* @__PURE__ */ jsx(
36
+ Link,
37
+ {
38
+ className: cn(
39
+ "text-sm font-medium transition-colors hover:text-foreground/80",
40
+ pathname === item.href ? "text-foreground" : "text-foreground/60"
41
+ ),
42
+ href: item.href,
43
+ children: item.title
44
+ },
45
+ item.href
46
+ )) }) : null
47
+ ] }),
48
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
49
+ rightSlot,
50
+ /* @__PURE__ */ jsx(
51
+ ThemeToggle,
52
+ {
53
+ dict: {
54
+ theme: {
55
+ dark: "Dark",
56
+ light: "Light",
57
+ system: "System",
58
+ toggle_theme: "Toggle theme"
59
+ }
60
+ }
61
+ }
62
+ )
63
+ ] })
64
+ ] }) }) });
65
+ }
66
+ export {
67
+ NavbarSaas
68
+ };
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { useEffect, useState } from "react";
3
+ function useMobile() {
4
+ const [isMobile, setIsMobile] = useState(false);
5
+ useEffect(() => {
6
+ const checkMobile = () => {
7
+ setIsMobile(window.innerWidth < 1024);
8
+ };
9
+ checkMobile();
10
+ window.addEventListener("resize", checkMobile);
11
+ return () => {
12
+ window.removeEventListener("resize", checkMobile);
13
+ };
14
+ }, []);
15
+ return isMobile;
16
+ }
17
+ export {
18
+ useMobile
19
+ };
@@ -0,0 +1,22 @@
1
+ import {
2
+ NavigationMenu,
3
+ NavigationMenuContent,
4
+ NavigationMenuIndicator,
5
+ NavigationMenuItem,
6
+ NavigationMenuLink,
7
+ NavigationMenuList,
8
+ NavigationMenuTrigger,
9
+ navigationMenuTriggerStyle,
10
+ NavigationMenuViewport
11
+ } from "./navigation-menu";
12
+ export {
13
+ NavigationMenu,
14
+ NavigationMenuContent,
15
+ NavigationMenuIndicator,
16
+ NavigationMenuItem,
17
+ NavigationMenuLink,
18
+ NavigationMenuList,
19
+ NavigationMenuTrigger,
20
+ NavigationMenuViewport,
21
+ navigationMenuTriggerStyle
22
+ };