@dogsbay/ui 0.2.0-beta.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 (322) hide show
  1. package/package.json +38 -0
  2. package/src/accordion/Accordion.astro +38 -0
  3. package/src/accordion/AccordionContent.astro +25 -0
  4. package/src/accordion/AccordionItem.astro +26 -0
  5. package/src/accordion/AccordionTrigger.astro +38 -0
  6. package/src/accordion/accordion.ts +189 -0
  7. package/src/accordion/index.ts +4 -0
  8. package/src/alert/Alert.astro +69 -0
  9. package/src/alert/AlertDescription.astro +17 -0
  10. package/src/alert/AlertTitle.astro +21 -0
  11. package/src/alert/CollapsibleAlert.astro +103 -0
  12. package/src/alert/icon.ts +32 -0
  13. package/src/alert/index.ts +4 -0
  14. package/src/alert/variants.ts +29 -0
  15. package/src/alert-dialog/AlertDialog.astro +16 -0
  16. package/src/alert-dialog/AlertDialogAction.astro +23 -0
  17. package/src/alert-dialog/AlertDialogCancel.astro +23 -0
  18. package/src/alert-dialog/AlertDialogContent.astro +37 -0
  19. package/src/alert-dialog/AlertDialogDescription.astro +18 -0
  20. package/src/alert-dialog/AlertDialogFooter.astro +18 -0
  21. package/src/alert-dialog/AlertDialogHeader.astro +18 -0
  22. package/src/alert-dialog/AlertDialogTitle.astro +18 -0
  23. package/src/alert-dialog/AlertDialogTrigger.astro +24 -0
  24. package/src/alert-dialog/alert-dialog.ts +154 -0
  25. package/src/alert-dialog/index.ts +9 -0
  26. package/src/api-doc/ApiDoc.astro +52 -0
  27. package/src/api-doc/index.ts +1 -0
  28. package/src/api-layout/ApiCodePanel.astro +21 -0
  29. package/src/api-layout/ApiLayout.astro +29 -0
  30. package/src/api-layout/ExampleBlock.astro +63 -0
  31. package/src/api-params/ApiParams.astro +96 -0
  32. package/src/api-params/index.ts +1 -0
  33. package/src/api-source/ApiSource.astro +20 -0
  34. package/src/api-source/api-source.css +32 -0
  35. package/src/api-source/index.ts +1 -0
  36. package/src/api-symbol/ApiSymbol.astro +48 -0
  37. package/src/api-symbol/api-symbol.css +89 -0
  38. package/src/api-symbol/index.ts +1 -0
  39. package/src/api-url-bar/ApiUrlBar.astro +63 -0
  40. package/src/avatar/Avatar.astro +57 -0
  41. package/src/avatar/index.ts +1 -0
  42. package/src/badge/Badge.astro +37 -0
  43. package/src/badge/index.ts +1 -0
  44. package/src/breadcrumb/Breadcrumb.astro +32 -0
  45. package/src/breadcrumb/BreadcrumbEllipsis.astro +32 -0
  46. package/src/breadcrumb/BreadcrumbItem.astro +41 -0
  47. package/src/breadcrumb/BreadcrumbSeparator.astro +33 -0
  48. package/src/breadcrumb/index.ts +4 -0
  49. package/src/button/Button.astro +70 -0
  50. package/src/button/index.ts +1 -0
  51. package/src/card/Card.astro +17 -0
  52. package/src/card/CardContent.astro +17 -0
  53. package/src/card/CardDescription.astro +17 -0
  54. package/src/card/CardFooter.astro +17 -0
  55. package/src/card/CardHeader.astro +17 -0
  56. package/src/card/CardTitle.astro +17 -0
  57. package/src/card/index.ts +6 -0
  58. package/src/checkbox/Checkbox.astro +70 -0
  59. package/src/checkbox/index.ts +1 -0
  60. package/src/checkbox-group/CheckboxGroup.astro +38 -0
  61. package/src/checkbox-group/checkbox-group.ts +53 -0
  62. package/src/checkbox-group/index.ts +1 -0
  63. package/src/code-block/CodeBlock.astro +160 -0
  64. package/src/code-rich/CodeRich.astro +267 -0
  65. package/src/code-rich/code-rich.css +68 -0
  66. package/src/code-rich/index.ts +1 -0
  67. package/src/code-samples/CodeSamples.astro +59 -0
  68. package/src/collapsible/Collapsible.astro +35 -0
  69. package/src/collapsible/CollapsibleContent.astro +24 -0
  70. package/src/collapsible/CollapsibleTrigger.astro +23 -0
  71. package/src/collapsible/collapsible.ts +42 -0
  72. package/src/collapsible/index.ts +3 -0
  73. package/src/combobox/Combobox.astro +53 -0
  74. package/src/combobox/ComboboxEmpty.astro +18 -0
  75. package/src/combobox/ComboboxItem.astro +28 -0
  76. package/src/combobox/combobox.ts +179 -0
  77. package/src/combobox/index.ts +3 -0
  78. package/src/command/Command.astro +22 -0
  79. package/src/command/CommandEmpty.astro +18 -0
  80. package/src/command/CommandGroup.astro +24 -0
  81. package/src/command/CommandInput.astro +49 -0
  82. package/src/command/CommandItem.astro +26 -0
  83. package/src/command/CommandList.astro +19 -0
  84. package/src/command/CommandSeparator.astro +16 -0
  85. package/src/command/CommandShortcut.astro +18 -0
  86. package/src/command/command.ts +212 -0
  87. package/src/command/index.ts +8 -0
  88. package/src/content-renderer/ContentRenderer.astro +410 -0
  89. package/src/content-renderer/InlineRenderer.astro +149 -0
  90. package/src/context-menu/ContextMenu.astro +22 -0
  91. package/src/context-menu/ContextMenuContent.astro +24 -0
  92. package/src/context-menu/ContextMenuItem.astro +49 -0
  93. package/src/context-menu/ContextMenuSeparator.astro +14 -0
  94. package/src/context-menu/ContextMenuShortcut.astro +14 -0
  95. package/src/context-menu/ContextMenuTrigger.astro +22 -0
  96. package/src/context-menu/context-menu.ts +238 -0
  97. package/src/context-menu/index.ts +6 -0
  98. package/src/copy-button/CopyButton.astro +88 -0
  99. package/src/copy-button/index.ts +1 -0
  100. package/src/diagram/Diagram.astro +15 -0
  101. package/src/diagram/index.ts +1 -0
  102. package/src/dialog/Dialog.astro +22 -0
  103. package/src/dialog/DialogClose.astro +32 -0
  104. package/src/dialog/DialogContent.astro +37 -0
  105. package/src/dialog/DialogDescription.astro +22 -0
  106. package/src/dialog/DialogFooter.astro +18 -0
  107. package/src/dialog/DialogHeader.astro +18 -0
  108. package/src/dialog/DialogTitle.astro +18 -0
  109. package/src/dialog/DialogTrigger.astro +33 -0
  110. package/src/dialog/dialog.ts +291 -0
  111. package/src/dialog/index.ts +8 -0
  112. package/src/docs-footer/DocsFooter.astro +50 -0
  113. package/src/docs-header/DocsHeader.astro +32 -0
  114. package/src/docs-layout/DocsLayout.astro +187 -0
  115. package/src/docs-layout/index.ts +1 -0
  116. package/src/drawer/Drawer.astro +12 -0
  117. package/src/drawer/DrawerClose.astro +12 -0
  118. package/src/drawer/DrawerContent.astro +46 -0
  119. package/src/drawer/DrawerDescription.astro +10 -0
  120. package/src/drawer/DrawerFooter.astro +10 -0
  121. package/src/drawer/DrawerHandle.astro +16 -0
  122. package/src/drawer/DrawerHeader.astro +10 -0
  123. package/src/drawer/DrawerTitle.astro +10 -0
  124. package/src/drawer/DrawerTrigger.astro +25 -0
  125. package/src/drawer/drawer.ts +262 -0
  126. package/src/drawer/index.ts +9 -0
  127. package/src/dropdown-menu/DropdownMenu.astro +22 -0
  128. package/src/dropdown-menu/DropdownMenuContent.astro +33 -0
  129. package/src/dropdown-menu/DropdownMenuGroup.astro +17 -0
  130. package/src/dropdown-menu/DropdownMenuItem.astro +48 -0
  131. package/src/dropdown-menu/DropdownMenuLabel.astro +28 -0
  132. package/src/dropdown-menu/DropdownMenuSeparator.astro +21 -0
  133. package/src/dropdown-menu/DropdownMenuShortcut.astro +18 -0
  134. package/src/dropdown-menu/DropdownMenuTrigger.astro +34 -0
  135. package/src/dropdown-menu/dropdown-menu.ts +348 -0
  136. package/src/dropdown-menu/index.ts +8 -0
  137. package/src/endpoint-card/EndpointCard.astro +60 -0
  138. package/src/endpoint-card/EndpointCardSection.astro +22 -0
  139. package/src/endpoint-card/EndpointSection.astro +35 -0
  140. package/src/field/Field.astro +31 -0
  141. package/src/field/FieldDescription.astro +22 -0
  142. package/src/field/FieldLabel.astro +24 -0
  143. package/src/field/field.ts +61 -0
  144. package/src/field/index.ts +3 -0
  145. package/src/fieldset/Fieldset.astro +24 -0
  146. package/src/fieldset/FieldsetLegend.astro +18 -0
  147. package/src/fieldset/index.ts +2 -0
  148. package/src/footnote/Footnote.astro +37 -0
  149. package/src/footnote/footnote.ts +79 -0
  150. package/src/footnote/index.ts +1 -0
  151. package/src/form/Form.astro +27 -0
  152. package/src/form/form.ts +160 -0
  153. package/src/form/index.ts +1 -0
  154. package/src/grid/Grid.astro +117 -0
  155. package/src/grid/GridItem.astro +95 -0
  156. package/src/grid/index.ts +2 -0
  157. package/src/image/Image.astro +115 -0
  158. package/src/image/index.ts +1 -0
  159. package/src/input/Input.astro +34 -0
  160. package/src/input/index.ts +1 -0
  161. package/src/kbd/Kbd.astro +17 -0
  162. package/src/kbd/index.ts +1 -0
  163. package/src/label/Label.astro +17 -0
  164. package/src/label/index.ts +1 -0
  165. package/src/link-card/LinkCard.astro +47 -0
  166. package/src/link-card/index.ts +1 -0
  167. package/src/map-view/MapView.astro +88 -0
  168. package/src/map-view/index.ts +1 -0
  169. package/src/map-view/map-view.ts +194 -0
  170. package/src/markdown-example/MarkdownExample.astro +138 -0
  171. package/src/markdown-example/index.ts +1 -0
  172. package/src/math/MathKatex.astro +35 -0
  173. package/src/math/index.ts +1 -0
  174. package/src/menubar/Menubar.astro +25 -0
  175. package/src/menubar/MenubarContent.astro +24 -0
  176. package/src/menubar/MenubarItem.astro +26 -0
  177. package/src/menubar/MenubarMenu.astro +12 -0
  178. package/src/menubar/MenubarSeparator.astro +11 -0
  179. package/src/menubar/MenubarShortcut.astro +11 -0
  180. package/src/menubar/MenubarTrigger.astro +27 -0
  181. package/src/menubar/index.ts +7 -0
  182. package/src/menubar/menubar.ts +258 -0
  183. package/src/meter/Meter.astro +75 -0
  184. package/src/meter/index.ts +1 -0
  185. package/src/method-badge/MethodBadge.astro +32 -0
  186. package/src/navigation-menu/NavigationMenu.astro +24 -0
  187. package/src/navigation-menu/NavigationMenuContent.astro +24 -0
  188. package/src/navigation-menu/NavigationMenuItem.astro +22 -0
  189. package/src/navigation-menu/NavigationMenuLink.astro +26 -0
  190. package/src/navigation-menu/NavigationMenuList.astro +22 -0
  191. package/src/navigation-menu/NavigationMenuTrigger.astro +40 -0
  192. package/src/navigation-menu/index.ts +6 -0
  193. package/src/navigation-menu/navigation-menu.ts +192 -0
  194. package/src/number-field/NumberField.astro +84 -0
  195. package/src/number-field/index.ts +1 -0
  196. package/src/number-field/number-field.ts +68 -0
  197. package/src/pagination/Pagination.astro +59 -0
  198. package/src/pagination/index.ts +1 -0
  199. package/src/parameter-table/ParameterTable.astro +75 -0
  200. package/src/popover/Popover.astro +21 -0
  201. package/src/popover/PopoverContent.astro +31 -0
  202. package/src/popover/PopoverTrigger.astro +31 -0
  203. package/src/popover/index.ts +3 -0
  204. package/src/popover/popover.ts +144 -0
  205. package/src/preview-card/PreviewCard.astro +24 -0
  206. package/src/preview-card/PreviewCardContent.astro +24 -0
  207. package/src/preview-card/PreviewCardTrigger.astro +23 -0
  208. package/src/preview-card/index.ts +3 -0
  209. package/src/preview-card/preview-card.ts +91 -0
  210. package/src/progress/Progress.astro +61 -0
  211. package/src/progress/index.ts +1 -0
  212. package/src/property-item/PropertyItem.astro +183 -0
  213. package/src/property-list/PropertyList.astro +68 -0
  214. package/src/radio-group/RadioGroup.astro +41 -0
  215. package/src/radio-group/RadioGroupItem.astro +36 -0
  216. package/src/radio-group/index.ts +2 -0
  217. package/src/radio-group/radio-group.ts +126 -0
  218. package/src/response-tabs/ResponseTabs.astro +60 -0
  219. package/src/schema-viewer/SchemaViewer.astro +42 -0
  220. package/src/scroll-area/ScrollArea.astro +44 -0
  221. package/src/scroll-area/index.ts +1 -0
  222. package/src/scroll-area/scroll-area.ts +176 -0
  223. package/src/select/Select.astro +34 -0
  224. package/src/select/SelectContent.astro +24 -0
  225. package/src/select/SelectGroup.astro +23 -0
  226. package/src/select/SelectItem.astro +28 -0
  227. package/src/select/SelectLabel.astro +18 -0
  228. package/src/select/SelectSeparator.astro +22 -0
  229. package/src/select/SelectTrigger.astro +28 -0
  230. package/src/select/SelectValue.astro +18 -0
  231. package/src/select/index.ts +8 -0
  232. package/src/select/select.ts +381 -0
  233. package/src/separator/Separator.astro +35 -0
  234. package/src/separator/index.ts +1 -0
  235. package/src/sheet/Sheet.astro +12 -0
  236. package/src/sheet/SheetClose.astro +35 -0
  237. package/src/sheet/SheetContent.astro +52 -0
  238. package/src/sheet/SheetDescription.astro +18 -0
  239. package/src/sheet/SheetFooter.astro +18 -0
  240. package/src/sheet/SheetHeader.astro +18 -0
  241. package/src/sheet/SheetTitle.astro +18 -0
  242. package/src/sheet/SheetTrigger.astro +32 -0
  243. package/src/sheet/index.ts +8 -0
  244. package/src/sheet/sheet.ts +173 -0
  245. package/src/sidebar/Sidebar.astro +113 -0
  246. package/src/sidebar/SidebarContent.astro +18 -0
  247. package/src/sidebar/SidebarFooter.astro +18 -0
  248. package/src/sidebar/SidebarGroup.astro +18 -0
  249. package/src/sidebar/SidebarGroupContent.astro +18 -0
  250. package/src/sidebar/SidebarGroupLabel.astro +18 -0
  251. package/src/sidebar/SidebarHeader.astro +18 -0
  252. package/src/sidebar/SidebarInset.astro +18 -0
  253. package/src/sidebar/SidebarMenu.astro +18 -0
  254. package/src/sidebar/SidebarMenuBadge.astro +18 -0
  255. package/src/sidebar/SidebarMenuButton.astro +71 -0
  256. package/src/sidebar/SidebarMenuItem.astro +18 -0
  257. package/src/sidebar/SidebarMenuSub.astro +18 -0
  258. package/src/sidebar/SidebarMenuSubButton.astro +45 -0
  259. package/src/sidebar/SidebarMenuSubItem.astro +12 -0
  260. package/src/sidebar/SidebarNavTree.astro +106 -0
  261. package/src/sidebar/SidebarProvider.astro +23 -0
  262. package/src/sidebar/SidebarRail.astro +25 -0
  263. package/src/sidebar/SidebarSeparator.astro +21 -0
  264. package/src/sidebar/SidebarTrigger.astro +40 -0
  265. package/src/sidebar/index.ts +19 -0
  266. package/src/sidebar/sidebar.ts +265 -0
  267. package/src/skeleton/Skeleton.astro +16 -0
  268. package/src/skeleton/index.ts +1 -0
  269. package/src/skip-link/SkipLink.astro +24 -0
  270. package/src/slider/Slider.astro +61 -0
  271. package/src/slider/index.ts +1 -0
  272. package/src/slider/slider.ts +111 -0
  273. package/src/spinner/Spinner.astro +54 -0
  274. package/src/spinner/index.ts +1 -0
  275. package/src/steps/Step.astro +16 -0
  276. package/src/steps/Steps.astro +122 -0
  277. package/src/steps/SubSteps.astro +73 -0
  278. package/src/switch/Switch.astro +52 -0
  279. package/src/switch/index.ts +1 -0
  280. package/src/switch/switch.ts +109 -0
  281. package/src/table/Table.astro +24 -0
  282. package/src/table/TableBody.astro +18 -0
  283. package/src/table/TableCaption.astro +18 -0
  284. package/src/table/TableCell.astro +18 -0
  285. package/src/table/TableFooter.astro +18 -0
  286. package/src/table/TableHead.astro +18 -0
  287. package/src/table/TableHeader.astro +18 -0
  288. package/src/table/TableRow.astro +18 -0
  289. package/src/table/index.ts +8 -0
  290. package/src/tabs/Tabs.astro +37 -0
  291. package/src/tabs/TabsContent.astro +32 -0
  292. package/src/tabs/TabsList.astro +23 -0
  293. package/src/tabs/TabsTrigger.astro +29 -0
  294. package/src/tabs/index.ts +4 -0
  295. package/src/tabs/tabs.ts +220 -0
  296. package/src/textarea/Textarea.astro +25 -0
  297. package/src/textarea/index.ts +1 -0
  298. package/src/theme-toggle/ThemeToggle.astro +67 -0
  299. package/src/theme-toggle/index.ts +1 -0
  300. package/src/toast/Toaster.astro +39 -0
  301. package/src/toast/index.ts +3 -0
  302. package/src/toast/toast.ts +104 -0
  303. package/src/toc/TableOfContents.astro +225 -0
  304. package/src/toggle/Toggle.astro +56 -0
  305. package/src/toggle/index.ts +1 -0
  306. package/src/toggle/toggle.ts +38 -0
  307. package/src/toggle-group/ToggleGroup.astro +39 -0
  308. package/src/toggle-group/ToggleGroupItem.astro +56 -0
  309. package/src/toggle-group/index.ts +2 -0
  310. package/src/toggle-group/toggle-group.ts +121 -0
  311. package/src/toolbar/Toolbar.astro +26 -0
  312. package/src/toolbar/ToolbarButton.astro +29 -0
  313. package/src/toolbar/ToolbarSeparator.astro +14 -0
  314. package/src/toolbar/index.ts +3 -0
  315. package/src/toolbar/toolbar.ts +65 -0
  316. package/src/tooltip/Tooltip.astro +21 -0
  317. package/src/tooltip/TooltipContent.astro +25 -0
  318. package/src/tooltip/TooltipTrigger.astro +31 -0
  319. package/src/tooltip/index.ts +3 -0
  320. package/src/tooltip/tooltip.ts +156 -0
  321. package/src/youtube/YouTube.astro +119 -0
  322. package/src/youtube/index.ts +1 -0
@@ -0,0 +1,111 @@
1
+ function init(root: HTMLElement) {
2
+ if (root.hasAttribute("data-initialized")) return;
3
+ root.setAttribute("data-initialized", "");
4
+
5
+ const track = root.querySelector<HTMLElement>("[data-part='track']");
6
+ const range = root.querySelector<HTMLElement>("[data-part='range']");
7
+ const thumb = root.querySelector<HTMLElement>("[data-part='thumb']");
8
+ const hiddenInput = root.querySelector<HTMLInputElement>("[data-part='hidden-input']");
9
+ if (!track || !range || !thumb) return;
10
+
11
+ const min = Number(root.getAttribute("data-min") || "0");
12
+ const max = Number(root.getAttribute("data-max") || "100");
13
+ const step = Number(root.getAttribute("data-step") || "1");
14
+
15
+ let value = Number(thumb.getAttribute("aria-valuenow") || "50");
16
+
17
+ function setValue(n: number) {
18
+ // Snap to step
19
+ const snapped = Math.round((n - min) / step) * step + min;
20
+ value = Math.min(max, Math.max(min, snapped));
21
+ const pct = ((value - min) / (max - min)) * 100;
22
+
23
+ thumb.setAttribute("aria-valuenow", String(value));
24
+ thumb.style.left = `calc(${pct}% - 10px)`;
25
+ range.style.width = `${pct}%`;
26
+
27
+ if (hiddenInput) hiddenInput.value = String(value);
28
+
29
+ root.dispatchEvent(new CustomEvent("change", { detail: { value }, bubbles: true }));
30
+ }
31
+
32
+ // Pointer drag
33
+ let isDragging = false;
34
+
35
+ function valueFromPointer(e: PointerEvent) {
36
+ const rect = track.getBoundingClientRect();
37
+ const pct = Math.min(1, Math.max(0, (e.clientX - rect.left) / rect.width));
38
+ return min + pct * (max - min);
39
+ }
40
+
41
+ thumb.addEventListener("pointerdown", (e) => {
42
+ if (root.hasAttribute("data-disabled")) return;
43
+ isDragging = true;
44
+ thumb.setPointerCapture(e.pointerId);
45
+ e.preventDefault();
46
+ });
47
+
48
+ thumb.addEventListener("pointermove", (e) => {
49
+ if (!isDragging) return;
50
+ setValue(valueFromPointer(e));
51
+ });
52
+
53
+ thumb.addEventListener("pointerup", () => {
54
+ isDragging = false;
55
+ });
56
+
57
+ // Click on track
58
+ track.addEventListener("pointerdown", (e) => {
59
+ if (root.hasAttribute("data-disabled")) return;
60
+ if (e.target === thumb) return;
61
+ setValue(valueFromPointer(e));
62
+ // Start dragging from new position
63
+ isDragging = true;
64
+ thumb.setPointerCapture(e.pointerId);
65
+ });
66
+
67
+ // Keyboard
68
+ thumb.addEventListener("keydown", (e) => {
69
+ if (root.hasAttribute("data-disabled")) return;
70
+
71
+ switch (e.key) {
72
+ case "ArrowRight":
73
+ case "ArrowUp":
74
+ e.preventDefault();
75
+ setValue(value + step);
76
+ break;
77
+ case "ArrowLeft":
78
+ case "ArrowDown":
79
+ e.preventDefault();
80
+ setValue(value - step);
81
+ break;
82
+ case "Home":
83
+ e.preventDefault();
84
+ setValue(min);
85
+ break;
86
+ case "End":
87
+ e.preventDefault();
88
+ setValue(max);
89
+ break;
90
+ case "PageUp":
91
+ e.preventDefault();
92
+ setValue(value + step * 10);
93
+ break;
94
+ case "PageDown":
95
+ e.preventDefault();
96
+ setValue(value - step * 10);
97
+ break;
98
+ }
99
+ });
100
+ }
101
+
102
+ function initAll() {
103
+ document.querySelectorAll<HTMLElement>("[data-component='slider']").forEach(init);
104
+ }
105
+
106
+ if (document.readyState === "loading") {
107
+ document.addEventListener("DOMContentLoaded", initAll);
108
+ } else {
109
+ initAll();
110
+ }
111
+ document.addEventListener("astro:page-load", initAll);
@@ -0,0 +1,54 @@
1
+ ---
2
+ import { tv, type VariantProps } from "tailwind-variants";
3
+
4
+ const spinner = tv({
5
+ base: "animate-spin text-foreground",
6
+ variants: {
7
+ size: {
8
+ sm: "h-4 w-4",
9
+ default: "h-6 w-6",
10
+ lg: "h-10 w-10",
11
+ },
12
+ },
13
+ defaultVariants: {
14
+ size: "default",
15
+ },
16
+ });
17
+
18
+ type SpinnerVariants = VariantProps<typeof spinner>;
19
+
20
+ interface Props {
21
+ size?: SpinnerVariants["size"];
22
+ class?: string;
23
+ [key: string]: unknown;
24
+ }
25
+ const { size = "default", class: className, ...rest } = Astro.props;
26
+ ---
27
+
28
+ <div
29
+ class={spinner({ size, class: className })}
30
+ role="status"
31
+ aria-label="Loading"
32
+ {...rest}
33
+ >
34
+ <svg
35
+ viewBox="0 0 24 24"
36
+ fill="none"
37
+ xmlns="http://www.w3.org/2000/svg"
38
+ aria-hidden="true"
39
+ class="h-full w-full"
40
+ >
41
+ <circle
42
+ cx="12"
43
+ cy="12"
44
+ r="10"
45
+ stroke="currentColor"
46
+ stroke-width="3"
47
+ opacity="0.25"></circle>
48
+ <path
49
+ d="M12 2a10 10 0 0 1 10 10"
50
+ stroke="currentColor"
51
+ stroke-width="3"
52
+ stroke-linecap="round"></path>
53
+ </svg>
54
+ </div>
@@ -0,0 +1 @@
1
+ export { default as Spinner } from "./Spinner.astro";
@@ -0,0 +1,16 @@
1
+ ---
2
+ /**
3
+ * Single step item. Used inside <Steps> or <SubSteps>.
4
+ * Renders as <li> with step styling applied by the parent's CSS.
5
+ */
6
+ interface Props {
7
+ class?: string;
8
+ [key: string]: unknown;
9
+ }
10
+
11
+ const { class: className, ...rest } = Astro.props;
12
+ ---
13
+
14
+ <li class={className} {...rest}>
15
+ <slot />
16
+ </li>
@@ -0,0 +1,122 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const steps = tv({
5
+ base: "steps-list",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <ol
17
+ class={steps({ class: className })}
18
+ role="list"
19
+ {...rest}
20
+ >
21
+ <slot />
22
+ </ol>
23
+
24
+ <style>
25
+ .steps-list {
26
+ position: relative;
27
+ padding-left: 1.75rem;
28
+ counter-reset: step;
29
+ list-style: none;
30
+ margin: 0;
31
+ }
32
+
33
+ .steps-list > :global(li) {
34
+ position: relative;
35
+ padding-bottom: 1.5rem;
36
+ counter-increment: step;
37
+ }
38
+
39
+ .steps-list > :global(li:last-child) {
40
+ padding-bottom: 0;
41
+ }
42
+
43
+ /* Numbered circle */
44
+ .steps-list > :global(li::before) {
45
+ content: counter(step);
46
+ position: absolute;
47
+ left: -1.75rem;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ width: 1.5rem;
52
+ height: 1.5rem;
53
+ border-radius: 9999px;
54
+ border: 2px solid var(--color-border);
55
+ background: var(--color-background);
56
+ color: var(--color-foreground);
57
+ font-size: 0.75rem;
58
+ font-weight: 600;
59
+ line-height: 1;
60
+ }
61
+
62
+ /* Connector line */
63
+ .steps-list > :global(li:not(:last-child)::after) {
64
+ content: "";
65
+ position: absolute;
66
+ left: calc(-1.75rem + 0.6875rem);
67
+ top: 1.75rem;
68
+ bottom: 0;
69
+ width: 1px;
70
+ background: var(--color-border);
71
+ }
72
+
73
+ /* Sub-steps: nested ol inside li */
74
+ .steps-list > :global(li) :global(ol) {
75
+ position: relative;
76
+ padding-left: 1.5rem;
77
+ counter-reset: substep;
78
+ list-style: none;
79
+ margin: 0.75rem 0 0 0;
80
+ }
81
+
82
+ .steps-list > :global(li) :global(ol > li) {
83
+ position: relative;
84
+ padding-bottom: 1rem;
85
+ counter-increment: substep;
86
+ }
87
+
88
+ .steps-list > :global(li) :global(ol > li:last-child) {
89
+ padding-bottom: 0;
90
+ }
91
+
92
+ /* Lettered circle (a, b, c) */
93
+ .steps-list > :global(li) :global(ol > li::before) {
94
+ content: counter(substep, lower-alpha);
95
+ position: absolute;
96
+ left: -1.5rem;
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ width: 1.25rem;
101
+ height: 1.25rem;
102
+ border-radius: 9999px;
103
+ border: 1.5px solid var(--color-border);
104
+ background: var(--color-background);
105
+ color: var(--color-muted-foreground, #737373);
106
+ font-size: 0.625rem;
107
+ font-weight: 600;
108
+ line-height: 1;
109
+ }
110
+
111
+ /* Sub-step connector line */
112
+ .steps-list > :global(li) :global(ol > li:not(:last-child)::after) {
113
+ content: "";
114
+ position: absolute;
115
+ left: calc(-1.5rem + 0.5625rem);
116
+ top: 1.5rem;
117
+ bottom: 0;
118
+ width: 1px;
119
+ background: var(--color-border);
120
+ opacity: 0.6;
121
+ }
122
+ </style>
@@ -0,0 +1,73 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const subSteps = tv({
5
+ base: "sub-steps-list",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <ol
17
+ class={subSteps({ class: className })}
18
+ role="list"
19
+ {...rest}
20
+ >
21
+ <slot />
22
+ </ol>
23
+
24
+ <style>
25
+ .sub-steps-list {
26
+ position: relative;
27
+ padding-left: 1.5rem;
28
+ counter-reset: substep;
29
+ list-style: none;
30
+ margin: 0.75rem 0 0 0;
31
+ }
32
+
33
+ .sub-steps-list > :global(li) {
34
+ position: relative;
35
+ padding-bottom: 1rem;
36
+ counter-increment: substep;
37
+ }
38
+
39
+ .sub-steps-list > :global(li:last-child) {
40
+ padding-bottom: 0;
41
+ }
42
+
43
+ /* Lettered circle (a, b, c) */
44
+ .sub-steps-list > :global(li::before) {
45
+ content: counter(substep, lower-alpha);
46
+ position: absolute;
47
+ left: -1.5rem;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ width: 1.25rem;
52
+ height: 1.25rem;
53
+ border-radius: 9999px;
54
+ border: 1.5px solid var(--color-border);
55
+ background: var(--color-background);
56
+ color: var(--color-muted-foreground, #737373);
57
+ font-size: 0.625rem;
58
+ font-weight: 600;
59
+ line-height: 1;
60
+ }
61
+
62
+ /* Connector line (thinner) */
63
+ .sub-steps-list > :global(li:not(:last-child)::after) {
64
+ content: "";
65
+ position: absolute;
66
+ left: calc(-1.5rem + 0.5625rem);
67
+ top: 1.5rem;
68
+ bottom: 0;
69
+ width: 1px;
70
+ background: var(--color-border);
71
+ opacity: 0.6;
72
+ }
73
+ </style>
@@ -0,0 +1,52 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const switchRoot = tv({
5
+ base: "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
6
+ });
7
+
8
+ const switchThumb = tv({
9
+ base: "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
10
+ });
11
+
12
+ interface Props {
13
+ name?: string;
14
+ defaultChecked?: boolean;
15
+ disabled?: boolean;
16
+ required?: boolean;
17
+ value?: string;
18
+ class?: string;
19
+ [key: string]: unknown;
20
+ }
21
+
22
+ const {
23
+ name,
24
+ defaultChecked = false,
25
+ disabled = false,
26
+ required = false,
27
+ value = "on",
28
+ class: className,
29
+ ...rest
30
+ } = Astro.props;
31
+ ---
32
+
33
+ <button
34
+ class={switchRoot({ class: className })}
35
+ data-component="switch"
36
+ data-name={name}
37
+ data-value={value}
38
+ data-default-checked={defaultChecked || undefined}
39
+ type="button"
40
+ role="switch"
41
+ aria-checked={String(defaultChecked)}
42
+ disabled={disabled || undefined}
43
+ aria-disabled={disabled ? "true" : undefined}
44
+ aria-required={required ? "true" : undefined}
45
+ data-state={defaultChecked ? "checked" : "unchecked"}
46
+ {...rest}
47
+ >
48
+ <span
49
+ class={switchThumb()}
50
+ data-part="thumb"
51
+ data-state={defaultChecked ? "checked" : "unchecked"}></span>
52
+ </button>
@@ -0,0 +1 @@
1
+ export { default as Switch } from "./Switch.astro";
@@ -0,0 +1,109 @@
1
+ interface SwitchInstance {
2
+ root: HTMLElement;
3
+ thumb: HTMLElement;
4
+ hiddenInput: HTMLInputElement | null;
5
+ checked: boolean;
6
+ }
7
+
8
+ const instances = new WeakMap<HTMLElement, SwitchInstance>();
9
+
10
+ function initSwitch(root: HTMLElement) {
11
+ if (instances.has(root)) return;
12
+
13
+ const thumb = root.querySelector("[data-part='thumb']") as HTMLElement | null;
14
+ if (!thumb) return;
15
+
16
+ const name = root.dataset.name;
17
+ const value = root.dataset.value || "on";
18
+ const defaultChecked = root.hasAttribute("data-default-checked");
19
+ const required = root.getAttribute("aria-required") === "true";
20
+
21
+ // Create hidden input for form submission
22
+ let hiddenInput: HTMLInputElement | null = null;
23
+ if (name) {
24
+ hiddenInput = document.createElement("input");
25
+ hiddenInput.type = "hidden";
26
+ hiddenInput.name = name;
27
+ hiddenInput.value = defaultChecked ? value : "";
28
+ if (required) hiddenInput.required = true;
29
+ // Insert after the switch button
30
+ root.parentElement?.insertBefore(hiddenInput, root.nextSibling);
31
+ }
32
+
33
+ const instance: SwitchInstance = {
34
+ root,
35
+ thumb,
36
+ hiddenInput,
37
+ checked: defaultChecked,
38
+ };
39
+
40
+ instances.set(root, instance);
41
+
42
+ // Click handler
43
+ root.addEventListener("click", () => {
44
+ if (
45
+ root.hasAttribute("disabled") ||
46
+ root.getAttribute("aria-disabled") === "true"
47
+ ) {
48
+ return;
49
+ }
50
+ setChecked(root, !instance.checked);
51
+ });
52
+
53
+ // Keyboard — Space and Enter toggle (button role handles Enter natively,
54
+ // but switch role needs explicit Space handling)
55
+ root.addEventListener("keydown", (e) => {
56
+ if (
57
+ root.hasAttribute("disabled") ||
58
+ root.getAttribute("aria-disabled") === "true"
59
+ ) {
60
+ return;
61
+ }
62
+ if (e.key === " ") {
63
+ e.preventDefault();
64
+ setChecked(root, !instance.checked);
65
+ }
66
+ });
67
+ }
68
+
69
+ function setChecked(root: HTMLElement, checked: boolean) {
70
+ const instance = instances.get(root);
71
+ if (!instance) return;
72
+
73
+ instance.checked = checked;
74
+ const state = checked ? "checked" : "unchecked";
75
+
76
+ root.setAttribute("aria-checked", String(checked));
77
+ root.setAttribute("data-state", state);
78
+ instance.thumb.setAttribute("data-state", state);
79
+
80
+ // Update hidden input
81
+ if (instance.hiddenInput) {
82
+ const value = root.dataset.value || "on";
83
+ instance.hiddenInput.value = checked ? value : "";
84
+ }
85
+
86
+ // Dispatch change event
87
+ root.dispatchEvent(
88
+ new CustomEvent("base-switch:change", {
89
+ detail: { checked },
90
+ bubbles: true,
91
+ }),
92
+ );
93
+ }
94
+
95
+ // Auto-initialize
96
+ function init() {
97
+ document.querySelectorAll("[data-component='switch']").forEach((el) => {
98
+ initSwitch(el as HTMLElement);
99
+ });
100
+ }
101
+
102
+ if (document.readyState === "loading") {
103
+ document.addEventListener("DOMContentLoaded", init);
104
+ } else {
105
+ init();
106
+ }
107
+ document.addEventListener("astro:page-load", init);
108
+
109
+ export { initSwitch, setChecked };
@@ -0,0 +1,24 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const tableContainer = tv({
5
+ base: "relative w-full overflow-x-auto",
6
+ });
7
+
8
+ const table = tv({
9
+ base: "w-full caption-bottom text-sm",
10
+ });
11
+
12
+ interface Props {
13
+ class?: string;
14
+ [key: string]: unknown;
15
+ }
16
+
17
+ const { class: className, ...rest } = Astro.props;
18
+ ---
19
+
20
+ <div class={tableContainer()}>
21
+ <table class={table({ class: className })} {...rest}>
22
+ <slot />
23
+ </table>
24
+ </div>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const tableBody = tv({
5
+ base: "[&_tr:last-child]:border-0",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <tbody class={tableBody({ class: className })} {...rest}>
17
+ <slot />
18
+ </tbody>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const tableCaption = tv({
5
+ base: "mt-4 text-sm text-muted-foreground",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <caption class={tableCaption({ class: className })} {...rest}>
17
+ <slot />
18
+ </caption>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const tableCell = tv({
5
+ base: "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <td class={tableCell({ class: className })} {...rest}>
17
+ <slot />
18
+ </td>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const tableFooter = tv({
5
+ base: "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <tfoot class={tableFooter({ class: className })} {...rest}>
17
+ <slot />
18
+ </tfoot>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const tableHead = tv({
5
+ base: "h-10 px-2 text-left align-middle font-semibold text-muted-foreground whitespace-nowrap [&:has([role=checkbox])]:pr-0",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <th class={tableHead({ class: className })} {...rest}>
17
+ <slot />
18
+ </th>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { tv } from "tailwind-variants";
3
+
4
+ const tableHeader = tv({
5
+ base: "[&_tr]:border-b",
6
+ });
7
+
8
+ interface Props {
9
+ class?: string;
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ const { class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <thead class={tableHeader({ class: className })} {...rest}>
17
+ <slot />
18
+ </thead>