@vllnt/ui 0.1.3 → 0.1.6

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 (217) 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 +65 -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 +235 -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 +123 -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 +109 -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 +171 -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 +141 -0
  77. package/dist/components/hover-card/hover-card.js +26 -0
  78. package/dist/components/hover-card/index.js +6 -0
  79. package/dist/components/index.js +633 -0
  80. package/dist/components/inline-input/index.js +4 -0
  81. package/dist/components/inline-input/inline-input.js +42 -0
  82. package/dist/components/input/index.js +4 -0
  83. package/dist/components/input/input.js +23 -0
  84. package/dist/components/input-otp/index.js +12 -0
  85. package/dist/components/input-otp/input-otp.js +54 -0
  86. package/dist/components/key-concept/index.js +8 -0
  87. package/dist/components/key-concept/key-concept.js +79 -0
  88. package/dist/components/keyboard-shortcuts-help/index.js +6 -0
  89. package/dist/components/keyboard-shortcuts-help/keyboard-shortcuts-help.js +121 -0
  90. package/dist/components/label/index.js +4 -0
  91. package/dist/components/label/label.js +21 -0
  92. package/dist/components/lang-provider/index.js +4 -0
  93. package/dist/components/lang-provider/lang-provider.js +18 -0
  94. package/dist/components/learning-objectives/index.js +10 -0
  95. package/dist/components/learning-objectives/learning-objectives.js +76 -0
  96. package/dist/components/mdx-content/index.js +4 -0
  97. package/dist/components/mdx-content/mdx-content.js +140 -0
  98. package/dist/components/menubar/index.js +36 -0
  99. package/dist/components/menubar/menubar.js +183 -0
  100. package/dist/components/model-selector/index.js +6 -0
  101. package/dist/components/model-selector/model-selector.js +374 -0
  102. package/dist/components/navbar-saas/index.js +6 -0
  103. package/dist/components/navbar-saas/navbar-saas.js +68 -0
  104. package/dist/components/navbar-saas/use-mobile.js +19 -0
  105. package/dist/components/navigation-menu/index.js +22 -0
  106. package/dist/components/navigation-menu/navigation-menu.js +108 -0
  107. package/dist/components/pagination/index.js +4 -0
  108. package/dist/components/pagination/pagination.js +44 -0
  109. package/dist/components/popover/index.js +12 -0
  110. package/dist/components/popover/popover.js +28 -0
  111. package/dist/components/pro-tip/index.js +8 -0
  112. package/dist/components/pro-tip/pro-tip.js +139 -0
  113. package/dist/components/profile-section/index.js +4 -0
  114. package/dist/components/profile-section/profile-section.js +45 -0
  115. package/dist/components/progress-bar/index.js +4 -0
  116. package/dist/components/progress-bar/progress-bar.js +56 -0
  117. package/dist/components/progress-card/index.js +6 -0
  118. package/dist/components/progress-card/progress-card.js +68 -0
  119. package/dist/components/quiz/index.js +4 -0
  120. package/dist/components/quiz/quiz.js +210 -0
  121. package/dist/components/radio-group/index.js +5 -0
  122. package/dist/components/radio-group/radio-group.js +36 -0
  123. package/dist/components/resizable/index.js +10 -0
  124. package/dist/components/resizable/resizable.js +39 -0
  125. package/dist/components/scroll-area/index.js +5 -0
  126. package/dist/components/scroll-area/scroll-area.js +39 -0
  127. package/dist/components/search-bar/index.js +4 -0
  128. package/dist/components/search-bar/search-bar.js +120 -0
  129. package/dist/components/search-dialog/index.js +4 -0
  130. package/dist/components/search-dialog/search-dialog.js +102 -0
  131. package/dist/components/select/index.js +24 -0
  132. package/dist/components/select/select.js +125 -0
  133. package/dist/components/separator/index.js +4 -0
  134. package/dist/components/separator/separator.js +25 -0
  135. package/dist/components/share-dialog/index.js +6 -0
  136. package/dist/components/share-dialog/share-dialog.js +121 -0
  137. package/dist/components/share-section/index.js +6 -0
  138. package/dist/components/share-section/share-section.js +57 -0
  139. package/dist/components/sheet/index.js +24 -0
  140. package/dist/components/sheet/sheet.js +116 -0
  141. package/dist/components/sidebar/index.js +4 -0
  142. package/dist/components/sidebar/sidebar.js +188 -0
  143. package/dist/components/sidebar-provider/index.js +5 -0
  144. package/dist/components/sidebar-provider/sidebar-provider.js +25 -0
  145. package/dist/components/sidebar-toggle/index.js +4 -0
  146. package/dist/components/sidebar-toggle/sidebar-toggle.js +36 -0
  147. package/dist/components/skeleton/index.js +4 -0
  148. package/dist/components/skeleton/skeleton.js +17 -0
  149. package/dist/components/slider/index.js +4 -0
  150. package/dist/components/slider/slider.js +24 -0
  151. package/dist/components/slideshow/index.js +6 -0
  152. package/dist/components/slideshow/slideshow.js +442 -0
  153. package/dist/components/social-fab/index.js +6 -0
  154. package/dist/components/social-fab/social-fab.js +211 -0
  155. package/dist/components/social-fab/use-social-fab.js +111 -0
  156. package/dist/components/spinner/index.js +4 -0
  157. package/dist/components/spinner/spinner.js +23 -0
  158. package/dist/components/step-by-step/index.js +8 -0
  159. package/dist/components/step-by-step/step-by-step.js +194 -0
  160. package/dist/components/step-navigation/index.js +4 -0
  161. package/dist/components/step-navigation/step-navigation.js +119 -0
  162. package/dist/components/switch/index.js +4 -0
  163. package/dist/components/switch/switch.js +28 -0
  164. package/dist/components/table/index.js +20 -0
  165. package/dist/components/table/table.js +87 -0
  166. package/dist/components/table-of-contents/index.js +4 -0
  167. package/dist/components/table-of-contents/table-of-contents.js +71 -0
  168. package/dist/components/table-of-contents-panel/index.js +6 -0
  169. package/dist/components/table-of-contents-panel/table-of-contents-panel.js +202 -0
  170. package/dist/components/tabs/index.js +12 -0
  171. package/dist/components/tabs/tabs.js +84 -0
  172. package/dist/components/terminal/index.js +8 -0
  173. package/dist/components/terminal/terminal.js +119 -0
  174. package/dist/components/textarea/index.js +4 -0
  175. package/dist/components/textarea/textarea.js +22 -0
  176. package/dist/components/theme-provider/index.js +4 -0
  177. package/dist/components/theme-provider/theme-provider.js +11 -0
  178. package/dist/components/theme-toggle/index.js +4 -0
  179. package/dist/components/theme-toggle/theme-toggle.js +172 -0
  180. package/dist/components/thinking-block/index.js +4 -0
  181. package/dist/components/thinking-block/thinking-block.js +52 -0
  182. package/dist/components/tldr-section/index.js +4 -0
  183. package/dist/components/tldr-section/tldr-section.js +92 -0
  184. package/dist/components/toast/index.js +18 -0
  185. package/dist/components/toast/toast.js +84 -0
  186. package/dist/components/toast/toaster.js +38 -0
  187. package/dist/components/toggle/index.js +5 -0
  188. package/dist/components/toggle/toggle.js +39 -0
  189. package/dist/components/toggle-group/index.js +5 -0
  190. package/dist/components/toggle-group/toggle-group.js +46 -0
  191. package/dist/components/tooltip/index.js +12 -0
  192. package/dist/components/tooltip/tooltip.js +27 -0
  193. package/dist/components/truncated-text/index.js +4 -0
  194. package/dist/components/truncated-text/truncated-text.js +25 -0
  195. package/dist/components/tutorial-card/index.js +6 -0
  196. package/dist/components/tutorial-card/tutorial-card.js +75 -0
  197. package/dist/components/tutorial-complete/index.js +6 -0
  198. package/dist/components/tutorial-complete/tutorial-complete.js +134 -0
  199. package/dist/components/tutorial-filters/index.js +6 -0
  200. package/dist/components/tutorial-filters/tutorial-filters.js +205 -0
  201. package/dist/components/tutorial-intro-content/index.js +6 -0
  202. package/dist/components/tutorial-intro-content/tutorial-intro-content.js +141 -0
  203. package/dist/components/tutorial-mdx/index.js +8 -0
  204. package/dist/components/tutorial-mdx/tutorial-mdx.js +219 -0
  205. package/dist/components/video-embed/index.js +4 -0
  206. package/dist/components/video-embed/video-embed.js +77 -0
  207. package/dist/index.js +12 -8557
  208. package/dist/lib/types.js +11 -0
  209. package/dist/lib/use-debounce.js +17 -0
  210. package/dist/lib/utils.js +8 -0
  211. package/dist/tailwind-preset.d.ts +5 -0
  212. package/dist/tailwind-preset.js +9 -10
  213. package/dist/types/content.js +0 -0
  214. package/dist/types/index.js +0 -0
  215. package/package.json +1 -1
  216. package/dist/chunk-XRV5RSYH.js +0 -569
  217. package/dist/flow-diagram-N3EHM6VB.js +0 -2
@@ -0,0 +1,151 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
+ import { cn } from "../../lib/utils";
6
+ const DropdownMenu = DropdownMenuPrimitive.Root;
7
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
8
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group;
9
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
10
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
11
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
12
+ const DropdownMenuSubTrigger = React.forwardRef(({ children, className, inset, ...props }, reference) => /* @__PURE__ */ jsxs(
13
+ DropdownMenuPrimitive.SubTrigger,
14
+ {
15
+ className: cn(
16
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
17
+ inset && "pl-8",
18
+ className
19
+ ),
20
+ ref: reference,
21
+ ...props,
22
+ children: [
23
+ children,
24
+ /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs", children: "\u203A" })
25
+ ]
26
+ }
27
+ ));
28
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
29
+ const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, reference) => /* @__PURE__ */ jsx(
30
+ DropdownMenuPrimitive.SubContent,
31
+ {
32
+ className: cn(
33
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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",
34
+ className
35
+ ),
36
+ ref: reference,
37
+ ...props
38
+ }
39
+ ));
40
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
41
+ const DropdownMenuContent = React.forwardRef(({ className, sideOffset = 4, ...props }, reference) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
42
+ DropdownMenuPrimitive.Content,
43
+ {
44
+ className: cn(
45
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md 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",
46
+ className
47
+ ),
48
+ ref: reference,
49
+ sideOffset,
50
+ ...props
51
+ }
52
+ ) }));
53
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
54
+ const DropdownMenuItem = React.forwardRef(({ className, inset, ...props }, reference) => /* @__PURE__ */ jsx(
55
+ DropdownMenuPrimitive.Item,
56
+ {
57
+ className: cn(
58
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
59
+ inset && "pl-8",
60
+ className
61
+ ),
62
+ ref: reference,
63
+ ...props
64
+ }
65
+ ));
66
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
67
+ const DropdownMenuCheckboxItem = React.forwardRef(({ checked, children, className, ...props }, reference) => /* @__PURE__ */ jsxs(
68
+ DropdownMenuPrimitive.CheckboxItem,
69
+ {
70
+ checked,
71
+ className: cn(
72
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
73
+ className
74
+ ),
75
+ ref: reference,
76
+ ...props,
77
+ children: [
78
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx("span", { className: "text-xs", children: "\u2713" }) }) }),
79
+ children
80
+ ]
81
+ }
82
+ ));
83
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
84
+ const DropdownMenuRadioItem = React.forwardRef(({ children, className, ...props }, reference) => /* @__PURE__ */ jsxs(
85
+ DropdownMenuPrimitive.RadioItem,
86
+ {
87
+ className: cn(
88
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
89
+ className
90
+ ),
91
+ ref: reference,
92
+ ...props,
93
+ children: [
94
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx("span", { className: "text-xs", children: "\u25CB" }) }) }),
95
+ children
96
+ ]
97
+ }
98
+ ));
99
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
100
+ const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, reference) => /* @__PURE__ */ jsx(
101
+ DropdownMenuPrimitive.Label,
102
+ {
103
+ className: cn(
104
+ "px-2 py-1.5 text-sm font-semibold",
105
+ inset && "pl-8",
106
+ className
107
+ ),
108
+ ref: reference,
109
+ ...props
110
+ }
111
+ ));
112
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
113
+ const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, reference) => /* @__PURE__ */ jsx(
114
+ DropdownMenuPrimitive.Separator,
115
+ {
116
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
117
+ ref: reference,
118
+ ...props
119
+ }
120
+ ));
121
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
122
+ const DropdownMenuShortcut = ({
123
+ className,
124
+ ...props
125
+ }) => {
126
+ return /* @__PURE__ */ jsx(
127
+ "span",
128
+ {
129
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className),
130
+ ...props
131
+ }
132
+ );
133
+ };
134
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
135
+ export {
136
+ DropdownMenu,
137
+ DropdownMenuCheckboxItem,
138
+ DropdownMenuContent,
139
+ DropdownMenuGroup,
140
+ DropdownMenuItem,
141
+ DropdownMenuLabel,
142
+ DropdownMenuPortal,
143
+ DropdownMenuRadioGroup,
144
+ DropdownMenuRadioItem,
145
+ DropdownMenuSeparator,
146
+ DropdownMenuShortcut,
147
+ DropdownMenuSub,
148
+ DropdownMenuSubContent,
149
+ DropdownMenuSubTrigger,
150
+ DropdownMenuTrigger
151
+ };
@@ -0,0 +1,34 @@
1
+ import {
2
+ DropdownMenu,
3
+ DropdownMenuCheckboxItem,
4
+ DropdownMenuContent,
5
+ DropdownMenuGroup,
6
+ DropdownMenuItem,
7
+ DropdownMenuLabel,
8
+ DropdownMenuPortal,
9
+ DropdownMenuRadioGroup,
10
+ DropdownMenuRadioItem,
11
+ DropdownMenuSeparator,
12
+ DropdownMenuShortcut,
13
+ DropdownMenuSub,
14
+ DropdownMenuSubContent,
15
+ DropdownMenuSubTrigger,
16
+ DropdownMenuTrigger
17
+ } from "./dropdown-menu";
18
+ export {
19
+ DropdownMenu,
20
+ DropdownMenuCheckboxItem,
21
+ DropdownMenuContent,
22
+ DropdownMenuGroup,
23
+ DropdownMenuItem,
24
+ DropdownMenuLabel,
25
+ DropdownMenuPortal,
26
+ DropdownMenuRadioGroup,
27
+ DropdownMenuRadioItem,
28
+ DropdownMenuSeparator,
29
+ DropdownMenuShortcut,
30
+ DropdownMenuSub,
31
+ DropdownMenuSubContent,
32
+ DropdownMenuSubTrigger,
33
+ DropdownMenuTrigger
34
+ };
@@ -0,0 +1,112 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Check, Dumbbell, Eye, EyeOff } from "lucide-react";
5
+ import { cn } from "../../lib/utils";
6
+ import { Button } from "../button";
7
+ const difficultyConfig = {
8
+ easy: { className: "text-green-600 dark:text-green-400", label: "Easy" },
9
+ hard: { className: "text-red-600 dark:text-red-400", label: "Hard" },
10
+ medium: { className: "text-amber-600 dark:text-amber-400", label: "Medium" }
11
+ };
12
+ function ExerciseHeader({ completed, config, onToggle, title }) {
13
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 mb-4", children: [
14
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
15
+ /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx(Dumbbell, { className: "h-5 w-5 text-primary" }) }),
16
+ /* @__PURE__ */ jsxs("div", { children: [
17
+ /* @__PURE__ */ jsx("h4", { className: "font-semibold text-foreground", children: title }),
18
+ /* @__PURE__ */ jsx("span", { className: cn("text-xs font-medium", config.className), children: config.label })
19
+ ] })
20
+ ] }),
21
+ /* @__PURE__ */ jsx(
22
+ Button,
23
+ {
24
+ className: cn(completed && "bg-green-500 hover:bg-green-600"),
25
+ onClick: onToggle,
26
+ size: "sm",
27
+ variant: completed ? "default" : "outline",
28
+ children: completed ? /* @__PURE__ */ jsxs(Fragment, { children: [
29
+ /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 mr-1" }),
30
+ "Done"
31
+ ] }) : "Mark Complete"
32
+ }
33
+ )
34
+ ] });
35
+ }
36
+ function ExerciseHint({ hint, onShow, showHint }) {
37
+ return /* @__PURE__ */ jsx("div", { className: "mb-4", children: showHint ? /* @__PURE__ */ jsxs("div", { className: "p-3 rounded bg-muted/50 text-sm", children: [
38
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-xs uppercase tracking-wider text-muted-foreground mb-1", children: "Hint" }),
39
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground italic", children: hint })
40
+ ] }) : /* @__PURE__ */ jsx(
41
+ "button",
42
+ {
43
+ className: "text-sm text-primary hover:underline",
44
+ onClick: onShow,
45
+ type: "button",
46
+ children: "Need a hint?"
47
+ }
48
+ ) });
49
+ }
50
+ function ExerciseSolution({ onToggle, showSolution, solution }) {
51
+ return /* @__PURE__ */ jsxs("div", { children: [
52
+ /* @__PURE__ */ jsx(Button, { className: "mb-3", onClick: onToggle, size: "sm", variant: "outline", children: showSolution ? /* @__PURE__ */ jsxs(Fragment, { children: [
53
+ /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4 mr-1" }),
54
+ "Hide Solution"
55
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
56
+ /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4 mr-1" }),
57
+ "Show Solution"
58
+ ] }) }),
59
+ showSolution ? /* @__PURE__ */ jsxs("div", { className: "p-4 rounded-lg bg-card border text-sm [&>pre]:my-0", children: [
60
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-xs uppercase tracking-wider text-muted-foreground mb-2", children: "Solution" }),
61
+ solution
62
+ ] }) : null
63
+ ] });
64
+ }
65
+ function Exercise({
66
+ children,
67
+ difficulty = "medium",
68
+ hint,
69
+ solution,
70
+ title
71
+ }) {
72
+ const [showSolution, setShowSolution] = useState(false);
73
+ const [showHint, setShowHint] = useState(false);
74
+ const [completed, setCompleted] = useState(false);
75
+ return /* @__PURE__ */ jsxs("div", { className: "my-6 rounded-lg border-2 border-dashed border-primary/30 bg-primary/5 p-6", children: [
76
+ /* @__PURE__ */ jsx(
77
+ ExerciseHeader,
78
+ {
79
+ completed,
80
+ config: difficultyConfig[difficulty],
81
+ onToggle: () => {
82
+ setCompleted(!completed);
83
+ },
84
+ title
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground mb-4 [&>p]:mb-2 [&>ul]:mb-2", children }),
88
+ hint ? /* @__PURE__ */ jsx(
89
+ ExerciseHint,
90
+ {
91
+ hint,
92
+ onShow: () => {
93
+ setShowHint(true);
94
+ },
95
+ showHint
96
+ }
97
+ ) : null,
98
+ solution ? /* @__PURE__ */ jsx(
99
+ ExerciseSolution,
100
+ {
101
+ onToggle: () => {
102
+ setShowSolution(!showSolution);
103
+ },
104
+ showSolution,
105
+ solution
106
+ }
107
+ ) : null
108
+ ] });
109
+ }
110
+ export {
111
+ Exercise
112
+ };
@@ -0,0 +1,4 @@
1
+ import { Exercise } from "./exercise";
2
+ export {
3
+ Exercise
4
+ };
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { ChevronDown, HelpCircle } from "lucide-react";
5
+ import { cn } from "../../lib/utils";
6
+ function FAQItem({ children, defaultOpen = false, question }) {
7
+ const [isOpen, setIsOpen] = useState(defaultOpen);
8
+ return /* @__PURE__ */ jsxs("div", { className: "border-b border-border last:border-b-0", children: [
9
+ /* @__PURE__ */ jsxs(
10
+ "button",
11
+ {
12
+ className: "w-full flex items-center justify-between py-4 text-left hover:text-primary transition-colors",
13
+ onClick: () => {
14
+ setIsOpen(!isOpen);
15
+ },
16
+ type: "button",
17
+ children: [
18
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm pr-4", children: question }),
19
+ /* @__PURE__ */ jsx(
20
+ ChevronDown,
21
+ {
22
+ className: cn(
23
+ "h-4 w-4 flex-shrink-0 transition-transform duration-200",
24
+ isOpen && "rotate-180"
25
+ )
26
+ }
27
+ )
28
+ ]
29
+ }
30
+ ),
31
+ /* @__PURE__ */ jsx(
32
+ "div",
33
+ {
34
+ className: cn(
35
+ "overflow-hidden transition-all duration-200",
36
+ isOpen ? "max-h-96 pb-4" : "max-h-0"
37
+ ),
38
+ children: /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground [&>p]:mb-2 [&>p:last-child]:mb-0", children })
39
+ }
40
+ )
41
+ ] });
42
+ }
43
+ function FAQ({ children, title = "Frequently Asked Questions" }) {
44
+ return /* @__PURE__ */ jsxs("div", { className: "my-6 rounded-lg border bg-card", children: [
45
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-4 border-b border-border", children: [
46
+ /* @__PURE__ */ jsx(HelpCircle, { className: "h-5 w-5 text-primary" }),
47
+ /* @__PURE__ */ jsx("h4", { className: "font-semibold", children: title })
48
+ ] }),
49
+ /* @__PURE__ */ jsx("div", { className: "px-4", children })
50
+ ] });
51
+ }
52
+ FAQ.Item = FAQItem;
53
+ export {
54
+ FAQ,
55
+ FAQItem
56
+ };
@@ -0,0 +1,5 @@
1
+ import { FAQ, FAQItem } from "./faq";
2
+ export {
3
+ FAQ,
4
+ FAQItem
5
+ };
@@ -0,0 +1,244 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { memo, useCallback, useState } from "react";
4
+ import { cn } from "../../lib/utils";
5
+ import { Badge } from "../badge";
6
+ function SearchInput({
7
+ disabled,
8
+ label,
9
+ onChange,
10
+ placeholder,
11
+ value
12
+ }) {
13
+ return /* @__PURE__ */ jsxs("div", { children: [
14
+ /* @__PURE__ */ jsx("label", { className: "sr-only", htmlFor: "filter-search", children: label }),
15
+ /* @__PURE__ */ jsx(
16
+ "input",
17
+ {
18
+ className: cn(
19
+ "w-full px-4 py-2 border border-border rounded-lg",
20
+ "bg-background text-foreground placeholder:text-muted-foreground",
21
+ "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
22
+ ),
23
+ defaultValue: value,
24
+ disabled,
25
+ id: "filter-search",
26
+ onChange: (event) => {
27
+ onChange(event.target.value);
28
+ },
29
+ placeholder,
30
+ type: "text"
31
+ }
32
+ )
33
+ ] });
34
+ }
35
+ function DifficultyFilter({
36
+ activeDifficulty,
37
+ disabled,
38
+ label,
39
+ onChange,
40
+ options
41
+ }) {
42
+ return /* @__PURE__ */ jsxs("div", { children: [
43
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 mb-2", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: label }) }),
44
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: options.map((option) => {
45
+ const isActive = option.value === activeDifficulty;
46
+ return /* @__PURE__ */ jsx(
47
+ "button",
48
+ {
49
+ className: cn(
50
+ "px-3 py-1 text-sm rounded-lg border transition-colors",
51
+ isActive ? "bg-primary text-primary-foreground border-transparent" : "bg-background text-foreground border-border hover:bg-muted"
52
+ ),
53
+ disabled,
54
+ onClick: () => {
55
+ onChange(option.value);
56
+ },
57
+ type: "button",
58
+ children: option.label
59
+ },
60
+ option.value
61
+ );
62
+ }) })
63
+ ] });
64
+ }
65
+ function TagFilter({
66
+ clearLabel,
67
+ currentTags,
68
+ label,
69
+ onClearTags,
70
+ onTagToggle,
71
+ tags
72
+ }) {
73
+ if (tags.length === 0) return null;
74
+ return /* @__PURE__ */ jsxs("div", { children: [
75
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
76
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: label }),
77
+ currentTags.length > 0 ? /* @__PURE__ */ jsx(
78
+ "button",
79
+ {
80
+ className: "text-xs text-muted-foreground hover:text-foreground transition-colors",
81
+ onClick: onClearTags,
82
+ type: "button",
83
+ children: clearLabel
84
+ }
85
+ ) : null
86
+ ] }),
87
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: tags.map((tag) => {
88
+ const isActive = currentTags.includes(tag);
89
+ return /* @__PURE__ */ jsx(
90
+ Badge,
91
+ {
92
+ className: cn(
93
+ "cursor-pointer transition-all",
94
+ isActive ? "bg-primary text-primary-foreground border-transparent" : "hover:bg-muted"
95
+ ),
96
+ onClick: () => {
97
+ onTagToggle(tag);
98
+ },
99
+ variant: isActive ? "default" : "outline",
100
+ children: tag
101
+ },
102
+ tag
103
+ );
104
+ }) })
105
+ ] });
106
+ }
107
+ function ActiveFiltersSummary({
108
+ clearAllLabel,
109
+ currentDifficulty,
110
+ currentTags,
111
+ difficultyOptions,
112
+ label,
113
+ onClearAll,
114
+ searchLabel,
115
+ searchQuery
116
+ }) {
117
+ if (!currentDifficulty && currentTags.length === 0 && !searchQuery)
118
+ return null;
119
+ const difficultyLabel = difficultyOptions.find(
120
+ (o) => o.value === currentDifficulty
121
+ )?.label;
122
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
123
+ /* @__PURE__ */ jsx("span", { children: label }),
124
+ difficultyLabel ? /* @__PURE__ */ jsx(Badge, { className: "capitalize", variant: "secondary", children: difficultyLabel }) : null,
125
+ currentTags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: tag }, tag)),
126
+ searchQuery ? /* @__PURE__ */ jsxs(Badge, { variant: "secondary", children: [
127
+ searchLabel,
128
+ ' "',
129
+ searchQuery,
130
+ '"'
131
+ ] }) : null,
132
+ /* @__PURE__ */ jsx(
133
+ "button",
134
+ {
135
+ className: "text-xs hover:underline",
136
+ onClick: onClearAll,
137
+ type: "button",
138
+ children: clearAllLabel
139
+ }
140
+ )
141
+ ] });
142
+ }
143
+ const DEFAULT_LABELS = {
144
+ activeFilters: "Active filters:",
145
+ clearAll: "Clear all",
146
+ clearTags: "Clear",
147
+ difficultyLabel: "Difficulty:",
148
+ searchLabel: "Search",
149
+ searchPlaceholder: "Search...",
150
+ tagsLabel: "Tags:"
151
+ };
152
+ function FilterBarImpl({
153
+ className,
154
+ currentDifficulty,
155
+ currentTags,
156
+ difficultyOptions,
157
+ labels = {},
158
+ onFiltersChange,
159
+ searchQuery,
160
+ tags
161
+ }) {
162
+ const [isPending, setIsPending] = useState(false);
163
+ const mergedLabels = { ...DEFAULT_LABELS, ...labels };
164
+ const handleDifficultyChange = useCallback(
165
+ (difficulty) => {
166
+ setIsPending(true);
167
+ onFiltersChange({ difficulty });
168
+ setIsPending(false);
169
+ },
170
+ [onFiltersChange]
171
+ );
172
+ const handleSearchChange = useCallback(
173
+ (search) => {
174
+ onFiltersChange({ search });
175
+ },
176
+ [onFiltersChange]
177
+ );
178
+ const handleTagToggle = useCallback(
179
+ (tag) => {
180
+ const newTags = currentTags.includes(tag) ? currentTags.filter((t) => t !== tag) : [...currentTags, tag];
181
+ onFiltersChange({ tags: newTags });
182
+ },
183
+ [currentTags, onFiltersChange]
184
+ );
185
+ const handleClearAll = useCallback(() => {
186
+ onFiltersChange({ difficulty: "all", search: "", tags: [] });
187
+ const input = document.querySelector("#filter-search");
188
+ if (input) input.value = "";
189
+ }, [onFiltersChange]);
190
+ const activeDifficulty = currentDifficulty || "all";
191
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4 mb-8", className), children: [
192
+ /* @__PURE__ */ jsx(
193
+ SearchInput,
194
+ {
195
+ disabled: isPending,
196
+ label: mergedLabels.searchLabel,
197
+ onChange: handleSearchChange,
198
+ placeholder: mergedLabels.searchPlaceholder,
199
+ value: searchQuery
200
+ }
201
+ ),
202
+ /* @__PURE__ */ jsx(
203
+ DifficultyFilter,
204
+ {
205
+ activeDifficulty,
206
+ disabled: isPending,
207
+ label: mergedLabels.difficultyLabel,
208
+ onChange: handleDifficultyChange,
209
+ options: difficultyOptions
210
+ }
211
+ ),
212
+ /* @__PURE__ */ jsx(
213
+ TagFilter,
214
+ {
215
+ clearLabel: mergedLabels.clearTags,
216
+ currentTags,
217
+ label: mergedLabels.tagsLabel,
218
+ onClearTags: () => {
219
+ onFiltersChange({ tags: [] });
220
+ },
221
+ onTagToggle: handleTagToggle,
222
+ tags
223
+ }
224
+ ),
225
+ /* @__PURE__ */ jsx(
226
+ ActiveFiltersSummary,
227
+ {
228
+ clearAllLabel: mergedLabels.clearAll,
229
+ currentDifficulty,
230
+ currentTags,
231
+ difficultyOptions,
232
+ label: mergedLabels.activeFilters,
233
+ onClearAll: handleClearAll,
234
+ searchLabel: mergedLabels.searchLabel,
235
+ searchQuery
236
+ }
237
+ )
238
+ ] });
239
+ }
240
+ const FilterBar = memo(FilterBarImpl);
241
+ FilterBar.displayName = "FilterBar";
242
+ export {
243
+ FilterBar
244
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ FilterBar
3
+ } from "./filter-bar";
4
+ export {
5
+ FilterBar
6
+ };
@@ -0,0 +1,35 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { memo } from "react";
4
+ import { cn } from "../../lib/utils";
5
+ function FloatingActionButtonImpl({
6
+ "aria-label": ariaLabel,
7
+ children,
8
+ className,
9
+ onClick,
10
+ position = "bottom-right"
11
+ }) {
12
+ return /* @__PURE__ */ jsx(
13
+ "button",
14
+ {
15
+ "aria-label": ariaLabel,
16
+ className: cn(
17
+ "fixed z-40 flex h-12 w-12 items-center justify-center rounded-full",
18
+ "bg-primary text-primary-foreground shadow-lg",
19
+ "transition-transform hover:scale-110",
20
+ "focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
21
+ position === "bottom-right" && "bottom-20 right-4 sm:bottom-4",
22
+ position === "bottom-left" && "bottom-20 left-4 sm:bottom-4",
23
+ className
24
+ ),
25
+ onClick,
26
+ type: "button",
27
+ children
28
+ }
29
+ );
30
+ }
31
+ const FloatingActionButton = memo(FloatingActionButtonImpl);
32
+ FloatingActionButton.displayName = "FloatingActionButton";
33
+ export {
34
+ FloatingActionButton
35
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ FloatingActionButton
3
+ } from "./floating-action-button";
4
+ export {
5
+ FloatingActionButton
6
+ };