@starwind-ui/core 1.15.1 → 1.15.2

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 (216) hide show
  1. package/dist/index.d.ts +28 -0
  2. package/dist/index.js +108 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/src/components/accordion/Accordion.astro +254 -0
  5. package/dist/src/components/accordion/AccordionContent.astro +33 -0
  6. package/dist/src/components/accordion/AccordionItem.astro +27 -0
  7. package/dist/src/components/accordion/AccordionTrigger.astro +32 -0
  8. package/dist/src/components/accordion/index.ts +15 -0
  9. package/dist/src/components/alert/Alert.astro +31 -0
  10. package/dist/src/components/alert/AlertDescription.astro +14 -0
  11. package/dist/src/components/alert/AlertTitle.astro +16 -0
  12. package/dist/src/components/alert/index.ts +13 -0
  13. package/dist/src/components/alert-dialog/AlertDialog.astro +275 -0
  14. package/dist/src/components/alert-dialog/AlertDialogAction.astro +44 -0
  15. package/dist/src/components/alert-dialog/AlertDialogCancel.astro +45 -0
  16. package/dist/src/components/alert-dialog/AlertDialogContent.astro +52 -0
  17. package/dist/src/components/alert-dialog/AlertDialogDescription.astro +18 -0
  18. package/dist/src/components/alert-dialog/AlertDialogFooter.astro +16 -0
  19. package/dist/src/components/alert-dialog/AlertDialogHeader.astro +14 -0
  20. package/dist/src/components/alert-dialog/AlertDialogTitle.astro +20 -0
  21. package/dist/src/components/alert-dialog/AlertDialogTrigger.astro +47 -0
  22. package/dist/src/components/alert-dialog/index.ts +46 -0
  23. package/dist/src/components/aspect-ratio/AspectRatio.astro +32 -0
  24. package/dist/src/components/aspect-ratio/index.ts +7 -0
  25. package/dist/src/components/avatar/Avatar.astro +29 -0
  26. package/dist/src/components/avatar/AvatarFallback.astro +18 -0
  27. package/dist/src/components/avatar/AvatarImage.astro +49 -0
  28. package/dist/src/components/avatar/index.ts +13 -0
  29. package/dist/src/components/badge/Badge.astro +55 -0
  30. package/dist/src/components/badge/index.ts +7 -0
  31. package/dist/src/components/breadcrumb/Breadcrumb.astro +11 -0
  32. package/dist/src/components/breadcrumb/BreadcrumbEllipsis.astro +28 -0
  33. package/dist/src/components/breadcrumb/BreadcrumbItem.astro +14 -0
  34. package/dist/src/components/breadcrumb/BreadcrumbLink.astro +22 -0
  35. package/dist/src/components/breadcrumb/BreadcrumbList.astro +16 -0
  36. package/dist/src/components/breadcrumb/BreadcrumbPage.astro +21 -0
  37. package/dist/src/components/breadcrumb/BreadcrumbSeparator.astro +23 -0
  38. package/dist/src/components/breadcrumb/index.ts +37 -0
  39. package/dist/src/components/button/Button.astro +55 -0
  40. package/dist/src/components/button/index.ts +7 -0
  41. package/dist/src/components/button-group/ButtonGroup.astro +62 -0
  42. package/dist/src/components/button-group/ButtonGroupSeparator.astro +27 -0
  43. package/dist/src/components/button-group/ButtonGroupText.astro +19 -0
  44. package/dist/src/components/button-group/index.ts +17 -0
  45. package/dist/src/components/card/Card.astro +14 -0
  46. package/dist/src/components/card/CardContent.astro +14 -0
  47. package/dist/src/components/card/CardDescription.astro +14 -0
  48. package/dist/src/components/card/CardFooter.astro +14 -0
  49. package/dist/src/components/card/CardHeader.astro +14 -0
  50. package/dist/src/components/card/CardTitle.astro +14 -0
  51. package/dist/src/components/card/index.ts +26 -0
  52. package/dist/src/components/carousel/Carousel.astro +55 -0
  53. package/dist/src/components/carousel/CarouselContent.astro +26 -0
  54. package/dist/src/components/carousel/CarouselItem.astro +26 -0
  55. package/dist/src/components/carousel/CarouselNext.astro +37 -0
  56. package/dist/src/components/carousel/CarouselPrevious.astro +37 -0
  57. package/dist/src/components/carousel/carousel-script.ts +191 -0
  58. package/dist/src/components/carousel/index.ts +32 -0
  59. package/dist/src/components/checkbox/Checkbox.astro +128 -0
  60. package/dist/src/components/checkbox/index.ts +7 -0
  61. package/dist/src/components/collapsible/Collapsible.astro +161 -0
  62. package/dist/src/components/collapsible/CollapsibleContent.astro +22 -0
  63. package/dist/src/components/collapsible/CollapsibleTrigger.astro +44 -0
  64. package/dist/src/components/collapsible/index.ts +13 -0
  65. package/dist/src/components/dialog/Dialog.astro +389 -0
  66. package/dist/src/components/dialog/DialogClose.astro +35 -0
  67. package/dist/src/components/dialog/DialogContent.astro +78 -0
  68. package/dist/src/components/dialog/DialogDescription.astro +14 -0
  69. package/dist/src/components/dialog/DialogFooter.astro +14 -0
  70. package/dist/src/components/dialog/DialogHeader.astro +14 -0
  71. package/dist/src/components/dialog/DialogTitle.astro +22 -0
  72. package/dist/src/components/dialog/DialogTrigger.astro +47 -0
  73. package/dist/src/components/dialog/index.ts +45 -0
  74. package/dist/src/components/dropdown/Dropdown.astro +377 -0
  75. package/dist/src/components/dropdown/DropdownContent.astro +81 -0
  76. package/dist/src/components/dropdown/DropdownItem.astro +48 -0
  77. package/dist/src/components/dropdown/DropdownLabel.astro +29 -0
  78. package/dist/src/components/dropdown/DropdownSeparator.astro +21 -0
  79. package/dist/src/components/dropdown/DropdownTrigger.astro +52 -0
  80. package/dist/src/components/dropdown/index.ts +33 -0
  81. package/dist/src/components/dropzone/Dropzone.astro +236 -0
  82. package/dist/src/components/dropzone/DropzoneFilesList.astro +26 -0
  83. package/dist/src/components/dropzone/DropzoneLoadingIndicator.astro +10 -0
  84. package/dist/src/components/dropzone/DropzoneUploadIndicator.astro +10 -0
  85. package/dist/src/components/dropzone/index.ts +24 -0
  86. package/dist/src/components/image/Image.astro +24 -0
  87. package/dist/src/components/image/index.ts +9 -0
  88. package/dist/src/components/input/Input.astro +25 -0
  89. package/dist/src/components/input/index.ts +7 -0
  90. package/dist/src/components/input-otp/InputOtp.astro +352 -0
  91. package/dist/src/components/input-otp/InputOtpGroup.astro +16 -0
  92. package/dist/src/components/input-otp/InputOtpSeparator.astro +25 -0
  93. package/dist/src/components/input-otp/InputOtpSlot.astro +48 -0
  94. package/dist/src/components/input-otp/InputOtpTypes.ts +6 -0
  95. package/dist/src/components/input-otp/index.ts +33 -0
  96. package/dist/src/components/item/Item.astro +52 -0
  97. package/dist/src/components/item/ItemActions.astro +16 -0
  98. package/dist/src/components/item/ItemContent.astro +16 -0
  99. package/dist/src/components/item/ItemDescription.astro +19 -0
  100. package/dist/src/components/item/ItemFooter.astro +16 -0
  101. package/dist/src/components/item/ItemGroup.astro +16 -0
  102. package/dist/src/components/item/ItemHeader.astro +16 -0
  103. package/dist/src/components/item/ItemMedia.astro +40 -0
  104. package/dist/src/components/item/ItemSeparator.astro +21 -0
  105. package/dist/src/components/item/ItemTitle.astro +16 -0
  106. package/dist/src/components/item/index.ts +50 -0
  107. package/dist/src/components/kbd/Kbd.astro +21 -0
  108. package/dist/src/components/kbd/KbdGroup.astro +16 -0
  109. package/dist/src/components/kbd/index.ts +11 -0
  110. package/dist/src/components/label/Label.astro +22 -0
  111. package/dist/src/components/label/index.ts +7 -0
  112. package/dist/src/components/pagination/Pagination.astro +20 -0
  113. package/dist/src/components/pagination/PaginationContent.astro +16 -0
  114. package/dist/src/components/pagination/PaginationEllipsis.astro +35 -0
  115. package/dist/src/components/pagination/PaginationItem.astro +16 -0
  116. package/dist/src/components/pagination/PaginationLink.astro +24 -0
  117. package/dist/src/components/pagination/PaginationNext.astro +30 -0
  118. package/dist/src/components/pagination/PaginationPrevious.astro +30 -0
  119. package/dist/src/components/pagination/index.ts +38 -0
  120. package/dist/src/components/progress/Progress.astro +155 -0
  121. package/dist/src/components/progress/index.ts +10 -0
  122. package/dist/src/components/prose/Prose.astro +617 -0
  123. package/dist/src/components/prose/index.ts +9 -0
  124. package/dist/src/components/radio-group/RadioGroup.astro +162 -0
  125. package/dist/src/components/radio-group/RadioGroupItem.astro +129 -0
  126. package/dist/src/components/radio-group/RadioGroupTypes.ts +6 -0
  127. package/dist/src/components/radio-group/index.ts +23 -0
  128. package/dist/src/components/select/Select.astro +752 -0
  129. package/dist/src/components/select/SelectContent.astro +94 -0
  130. package/dist/src/components/select/SelectGroup.astro +9 -0
  131. package/dist/src/components/select/SelectItem.astro +51 -0
  132. package/dist/src/components/select/SelectLabel.astro +14 -0
  133. package/dist/src/components/select/SelectSearch.astro +49 -0
  134. package/dist/src/components/select/SelectSeparator.astro +12 -0
  135. package/dist/src/components/select/SelectTrigger.astro +54 -0
  136. package/dist/src/components/select/SelectTypes.ts +13 -0
  137. package/dist/src/components/select/SelectValue.astro +19 -0
  138. package/dist/src/components/select/index.ts +49 -0
  139. package/dist/src/components/separator/Separator.astro +36 -0
  140. package/dist/src/components/separator/index.ts +7 -0
  141. package/dist/src/components/sheet/Sheet.astro +13 -0
  142. package/dist/src/components/sheet/SheetClose.astro +13 -0
  143. package/dist/src/components/sheet/SheetContent.astro +92 -0
  144. package/dist/src/components/sheet/SheetDescription.astro +16 -0
  145. package/dist/src/components/sheet/SheetFooter.astro +16 -0
  146. package/dist/src/components/sheet/SheetHeader.astro +16 -0
  147. package/dist/src/components/sheet/SheetTitle.astro +16 -0
  148. package/dist/src/components/sheet/SheetTrigger.astro +13 -0
  149. package/dist/src/components/sheet/index.ts +41 -0
  150. package/dist/src/components/sidebar/Sidebar.astro +213 -0
  151. package/dist/src/components/sidebar/SidebarContent.astro +24 -0
  152. package/dist/src/components/sidebar/SidebarFooter.astro +21 -0
  153. package/dist/src/components/sidebar/SidebarGroup.astro +21 -0
  154. package/dist/src/components/sidebar/SidebarGroupContent.astro +21 -0
  155. package/dist/src/components/sidebar/SidebarGroupLabel.astro +52 -0
  156. package/dist/src/components/sidebar/SidebarHeader.astro +21 -0
  157. package/dist/src/components/sidebar/SidebarInput.astro +22 -0
  158. package/dist/src/components/sidebar/SidebarInset.astro +21 -0
  159. package/dist/src/components/sidebar/SidebarMenu.astro +21 -0
  160. package/dist/src/components/sidebar/SidebarMenuAction.astro +59 -0
  161. package/dist/src/components/sidebar/SidebarMenuBadge.astro +30 -0
  162. package/dist/src/components/sidebar/SidebarMenuButton.astro +129 -0
  163. package/dist/src/components/sidebar/SidebarMenuItem.astro +21 -0
  164. package/dist/src/components/sidebar/SidebarMenuSkeleton.astro +40 -0
  165. package/dist/src/components/sidebar/SidebarMenuSub.astro +24 -0
  166. package/dist/src/components/sidebar/SidebarMenuSubButton.astro +49 -0
  167. package/dist/src/components/sidebar/SidebarMenuSubItem.astro +16 -0
  168. package/dist/src/components/sidebar/SidebarProvider.astro +213 -0
  169. package/dist/src/components/sidebar/SidebarRail.astro +71 -0
  170. package/dist/src/components/sidebar/SidebarSeparator.astro +22 -0
  171. package/dist/src/components/sidebar/SidebarTrigger.astro +66 -0
  172. package/dist/src/components/sidebar/index.ts +103 -0
  173. package/dist/src/components/skeleton/Skeleton.astro +14 -0
  174. package/dist/src/components/skeleton/index.ts +9 -0
  175. package/dist/src/components/slider/Slider.astro +411 -0
  176. package/dist/src/components/slider/index.ts +9 -0
  177. package/dist/src/components/spinner/Spinner.astro +21 -0
  178. package/dist/src/components/spinner/index.ts +7 -0
  179. package/dist/src/components/switch/Switch.astro +192 -0
  180. package/dist/src/components/switch/SwitchTypes.ts +6 -0
  181. package/dist/src/components/switch/index.ts +12 -0
  182. package/dist/src/components/table/Table.astro +18 -0
  183. package/dist/src/components/table/TableBody.astro +16 -0
  184. package/dist/src/components/table/TableCaption.astro +16 -0
  185. package/dist/src/components/table/TableCell.astro +16 -0
  186. package/dist/src/components/table/TableFoot.astro +16 -0
  187. package/dist/src/components/table/TableHead.astro +16 -0
  188. package/dist/src/components/table/TableHeader.astro +16 -0
  189. package/dist/src/components/table/TableRow.astro +16 -0
  190. package/dist/src/components/table/index.ts +42 -0
  191. package/dist/src/components/tabs/Tabs.astro +271 -0
  192. package/dist/src/components/tabs/TabsContent.astro +28 -0
  193. package/dist/src/components/tabs/TabsList.astro +22 -0
  194. package/dist/src/components/tabs/TabsTrigger.astro +34 -0
  195. package/dist/src/components/tabs/index.ts +20 -0
  196. package/dist/src/components/textarea/Textarea.astro +29 -0
  197. package/dist/src/components/textarea/index.ts +9 -0
  198. package/dist/src/components/theme-toggle/ThemeToggle.astro +208 -0
  199. package/dist/src/components/theme-toggle/index.ts +7 -0
  200. package/dist/src/components/toast/ToastDescription.astro +21 -0
  201. package/dist/src/components/toast/ToastItem.astro +54 -0
  202. package/dist/src/components/toast/ToastTemplate.astro +25 -0
  203. package/dist/src/components/toast/ToastTitle.astro +57 -0
  204. package/dist/src/components/toast/Toaster.astro +982 -0
  205. package/dist/src/components/toast/index.ts +29 -0
  206. package/dist/src/components/toast/toast-manager.ts +216 -0
  207. package/dist/src/components/toggle/Toggle.astro +174 -0
  208. package/dist/src/components/toggle/ToggleTypes.ts +14 -0
  209. package/dist/src/components/toggle/index.ts +8 -0
  210. package/dist/src/components/tooltip/Tooltip.astro +282 -0
  211. package/dist/src/components/tooltip/TooltipContent.astro +89 -0
  212. package/dist/src/components/tooltip/TooltipTrigger.astro +10 -0
  213. package/dist/src/components/tooltip/index.ts +16 -0
  214. package/dist/src/components/video/Video.astro +120 -0
  215. package/dist/src/components/video/index.ts +9 -0
  216. package/package.json +1 -1
@@ -0,0 +1,40 @@
1
+ ---
2
+ import type { ComponentProps, HTMLAttributes } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ import { Skeleton } from "@/components/starwind/skeleton";
6
+
7
+ const sidebarMenuSkeleton = tv({
8
+ base: "flex h-8 items-center gap-2 rounded-md px-2",
9
+ });
10
+
11
+ type Props = HTMLAttributes<"div"> & {
12
+ /**
13
+ * Whether to show the icon skeleton
14
+ * @default false
15
+ */
16
+ showIcon?: boolean;
17
+ /**
18
+ * Width of the text skeleton (random 50-90% if not specified)
19
+ */
20
+ width?: string;
21
+ };
22
+
23
+ const { showIcon = false, width, class: className, ...rest } = Astro.props;
24
+
25
+ const skeletonWidth = width || `${Math.floor(Math.random() * 40) + 50}%`;
26
+ ---
27
+
28
+ <div
29
+ class={sidebarMenuSkeleton({ class: className })}
30
+ data-slot="sidebar-menu-skeleton"
31
+ data-sidebar="menu-skeleton"
32
+ {...rest}
33
+ >
34
+ {showIcon && <Skeleton class="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />}
35
+ <Skeleton
36
+ class="h-4 max-w-(--skeleton-width) flex-1"
37
+ style={`--skeleton-width: ${skeletonWidth}`}
38
+ data-sidebar="menu-skeleton-text"
39
+ />
40
+ </div>
@@ -0,0 +1,24 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ type Props = HTMLAttributes<"ul">;
6
+
7
+ export const sidebarMenuSub = tv({
8
+ base: [
9
+ "border-sidebar-border mx-4.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5",
10
+ "group-data-[collapsible=icon]:hidden",
11
+ ],
12
+ });
13
+
14
+ const { class: className, ...rest } = Astro.props;
15
+ ---
16
+
17
+ <ul
18
+ class={sidebarMenuSub({ class: className })}
19
+ data-slot="sidebar-menu-sub"
20
+ data-sidebar="menu-sub"
21
+ {...rest}
22
+ >
23
+ <slot />
24
+ </ul>
@@ -0,0 +1,49 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { tv, type VariantProps } from "tailwind-variants";
4
+
5
+ type Props = HTMLAttributes<"a"> &
6
+ VariantProps<typeof sidebarMenuSubButton> & {
7
+ /**
8
+ * Whether the menu sub item is currently active
9
+ */
10
+ isActive?: boolean;
11
+ };
12
+
13
+ export const sidebarMenuSubButton = tv({
14
+ base: [
15
+ "text-sidebar-foreground ring-sidebar-outline",
16
+ "flex h-8 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2.5",
17
+ "outline-hidden",
18
+ "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
19
+ "focus-visible:ring-2",
20
+ "active:bg-sidebar-accent active:text-sidebar-accent-foreground",
21
+ "disabled:pointer-events-none disabled:opacity-50",
22
+ "aria-disabled:pointer-events-none aria-disabled:opacity-50",
23
+ "[&>svg]:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
24
+ "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
25
+ ],
26
+ variants: {
27
+ size: {
28
+ sm: "text-sm",
29
+ md: "text-base",
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ size: "md",
34
+ },
35
+ });
36
+
37
+ const { size, isActive = false, class: className, ...rest } = Astro.props;
38
+ ---
39
+
40
+ <a
41
+ class={sidebarMenuSubButton({ size, class: className })}
42
+ data-slot="sidebar-menu-sub-button"
43
+ data-sidebar="menu-sub-button"
44
+ data-size={size || "md"}
45
+ data-active={isActive}
46
+ {...rest}
47
+ >
48
+ <slot />
49
+ </a>
@@ -0,0 +1,16 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+
4
+ type Props = HTMLAttributes<"li">;
5
+
6
+ const { class: className, ...rest } = Astro.props;
7
+ ---
8
+
9
+ <li
10
+ class:list={["group/menu-sub-item relative", className]}
11
+ data-slot="sidebar-menu-sub-item"
12
+ data-sidebar="menu-sub-item"
13
+ {...rest}
14
+ >
15
+ <slot />
16
+ </li>
@@ -0,0 +1,213 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ type Props = HTMLAttributes<"div"> & {
6
+ /**
7
+ * Default open state of the sidebar
8
+ * @default true
9
+ */
10
+ defaultOpen?: boolean;
11
+ /**
12
+ * Keyboard shortcut to toggle the sidebar
13
+ * @default "b"
14
+ */
15
+ keyboardShortcut?: string;
16
+ };
17
+
18
+ export const sidebarProvider = tv({
19
+ base: [
20
+ "starwind-sidebar-provider",
21
+ "group/sidebar-wrapper flex min-h-svh w-full",
22
+ "has-data-[variant=inset]:bg-sidebar",
23
+ ],
24
+ });
25
+
26
+ const {
27
+ defaultOpen = true,
28
+ keyboardShortcut = "b",
29
+ class: className,
30
+ style,
31
+ ...rest
32
+ } = Astro.props;
33
+
34
+ const SIDEBAR_WIDTH = "18rem";
35
+ const SIDEBAR_WIDTH_ICON = "3.5rem";
36
+
37
+ // Parse style prop to extract CSS variable overrides
38
+ const styleObj = typeof style === "string" ? {} : ((style as Record<string, string>) ?? {});
39
+ const mergedStyle = {
40
+ "--sidebar-width": styleObj["--sidebar-width"] ?? SIDEBAR_WIDTH,
41
+ "--sidebar-width-icon": styleObj["--sidebar-width-icon"] ?? SIDEBAR_WIDTH_ICON,
42
+ ...styleObj,
43
+ };
44
+ ---
45
+
46
+ <div
47
+ class={sidebarProvider({ class: className })}
48
+ data-slot="sidebar-provider"
49
+ data-state={defaultOpen ? "expanded" : "collapsed"}
50
+ data-mobile-open="false"
51
+ data-keyboard-shortcut={keyboardShortcut}
52
+ style={mergedStyle}
53
+ {...rest}
54
+ >
55
+ <slot />
56
+ </div>
57
+
58
+ <script>
59
+ class SidebarController {
60
+ private provider: HTMLElement;
61
+ private boundKeyHandler: (e: KeyboardEvent) => void;
62
+ private boundResizeHandler: () => void;
63
+ private wasMobile: boolean = false;
64
+
65
+ constructor(provider: HTMLElement) {
66
+ this.provider = provider;
67
+ this.boundKeyHandler = this.handleKeydown.bind(this);
68
+ this.boundResizeHandler = this.handleResize.bind(this);
69
+ this.wasMobile = this.isMobile();
70
+ this.setupKeyboardShortcut();
71
+ this.setupCustomEvents();
72
+ this.setupResizeListener();
73
+ }
74
+
75
+ private handleKeydown(e: KeyboardEvent) {
76
+ // Skip if focus is in an editable element
77
+ const target = e.target as HTMLElement | null;
78
+ if (target) {
79
+ const tagName = target.tagName.toLowerCase();
80
+ if (
81
+ tagName === "input" ||
82
+ tagName === "textarea" ||
83
+ tagName === "select" ||
84
+ target.isContentEditable ||
85
+ target.closest("[contenteditable='true']")
86
+ ) {
87
+ return;
88
+ }
89
+ }
90
+
91
+ const shortcut = this.provider.getAttribute("data-keyboard-shortcut") || "b";
92
+ if (e.key === shortcut && (e.metaKey || e.ctrlKey)) {
93
+ e.preventDefault();
94
+ this.toggle();
95
+ }
96
+ }
97
+
98
+ private setupKeyboardShortcut() {
99
+ document.removeEventListener("keydown", this.boundKeyHandler);
100
+ document.addEventListener("keydown", this.boundKeyHandler);
101
+ }
102
+
103
+ private setupCustomEvents() {
104
+ this.provider.addEventListener("sidebar:toggle", () => this.toggle());
105
+ this.provider.addEventListener("sidebar:open", () => this.setOpen(true));
106
+ this.provider.addEventListener("sidebar:close", () => this.setOpen(false));
107
+ this.provider.addEventListener("sidebar:toggle-mobile", () => this.toggleMobile());
108
+ this.provider.addEventListener("sidebar:open-mobile", () => this.setMobileOpen(true));
109
+ this.provider.addEventListener("sidebar:close-mobile", () => this.setMobileOpen(false));
110
+ }
111
+
112
+ private handleResize() {
113
+ const isMobileNow = this.isMobile();
114
+ // Close mobile sheet when transitioning from mobile to desktop
115
+ if (this.wasMobile && !isMobileNow) {
116
+ this.setMobileOpen(false);
117
+ }
118
+ this.wasMobile = isMobileNow;
119
+ }
120
+
121
+ private setupResizeListener() {
122
+ window.removeEventListener("resize", this.boundResizeHandler);
123
+ window.addEventListener("resize", this.boundResizeHandler);
124
+ }
125
+
126
+ isMobile(): boolean {
127
+ // Check if desktop sidebar is hidden (has display: none from hidden class)
128
+ const desktopSidebar = this.provider.querySelector<HTMLElement>('[data-slot="sidebar"]');
129
+ if (!desktopSidebar) return false;
130
+ return getComputedStyle(desktopSidebar).display === "none";
131
+ }
132
+
133
+ getState(): "expanded" | "collapsed" {
134
+ return this.provider.getAttribute("data-state") as "expanded" | "collapsed";
135
+ }
136
+
137
+ isOpen(): boolean {
138
+ return this.getState() === "expanded";
139
+ }
140
+
141
+ isMobileOpen(): boolean {
142
+ return this.provider.getAttribute("data-mobile-open") === "true";
143
+ }
144
+
145
+ toggle() {
146
+ if (this.isMobile()) {
147
+ this.toggleMobile();
148
+ } else {
149
+ this.setOpen(!this.isOpen());
150
+ }
151
+ }
152
+
153
+ setOpen(open: boolean) {
154
+ const state = open ? "expanded" : "collapsed";
155
+ this.provider.setAttribute("data-state", state);
156
+ this.provider.dispatchEvent(new CustomEvent("sidebar:change", { detail: { open, state } }));
157
+ }
158
+
159
+ toggleMobile() {
160
+ // Check the actual dialog state instead of our tracked state
161
+ const mobileSheet = this.provider.querySelector<HTMLElement>(".starwind-sheet");
162
+ const dialogContent = mobileSheet?.querySelector<HTMLElement>(".starwind-dialog-content");
163
+ const isCurrentlyOpen = dialogContent?.dataset.state === "open";
164
+
165
+ this.setMobileOpen(!isCurrentlyOpen);
166
+ }
167
+
168
+ setMobileOpen(open: boolean) {
169
+ this.provider.setAttribute("data-mobile-open", String(open));
170
+
171
+ // Find the mobile sidebar Sheet and use Dialog's programmatic API
172
+ const mobileSheet = this.provider.querySelector<HTMLElement>(".starwind-sheet");
173
+ if (mobileSheet) {
174
+ const eventName = open ? "dialog:open" : "dialog:close";
175
+ mobileSheet.dispatchEvent(new CustomEvent(eventName));
176
+ }
177
+
178
+ this.provider.dispatchEvent(new CustomEvent("sidebar:mobile-change", { detail: { open } }));
179
+ }
180
+
181
+ destroy() {
182
+ document.removeEventListener("keydown", this.boundKeyHandler);
183
+ window.removeEventListener("resize", this.boundResizeHandler);
184
+ }
185
+ }
186
+
187
+ const sidebarInstances = new WeakMap<HTMLElement, SidebarController>();
188
+ const trackedProviders = new Set<HTMLElement>();
189
+
190
+ const cleanupSidebars = () => {
191
+ // Destroy controllers for providers no longer in DOM
192
+ for (const provider of trackedProviders) {
193
+ if (!document.contains(provider)) {
194
+ sidebarInstances.get(provider)?.destroy();
195
+ trackedProviders.delete(provider);
196
+ }
197
+ }
198
+ };
199
+
200
+ const setupSidebars = () => {
201
+ document.querySelectorAll<HTMLElement>(".starwind-sidebar-provider").forEach((provider) => {
202
+ if (!sidebarInstances.has(provider)) {
203
+ sidebarInstances.set(provider, new SidebarController(provider));
204
+ trackedProviders.add(provider);
205
+ }
206
+ });
207
+ };
208
+
209
+ setupSidebars();
210
+ document.addEventListener("astro:before-swap", cleanupSidebars);
211
+ document.addEventListener("astro:after-swap", setupSidebars);
212
+ document.addEventListener("starwind:init", setupSidebars);
213
+ </script>
@@ -0,0 +1,71 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ type Props = HTMLAttributes<"button">;
6
+
7
+ export const sidebarRail = tv({
8
+ base: [
9
+ "starwind-sidebar-rail",
10
+ "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear sm:flex",
11
+ "group-data-[side=left]:-right-4 group-data-[side=right]:left-0",
12
+ "after:absolute after:inset-y-0 after:left-1/2 after:w-[2px]",
13
+ "hover:after:bg-sidebar-border",
14
+ "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
15
+ "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize",
16
+ "[[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
17
+ "hover:group-data-[collapsible=offcanvas]:bg-sidebar",
18
+ "group-data-[collapsible=offcanvas]:translate-x-0",
19
+ "group-data-[collapsible=offcanvas]:after:left-full",
20
+ "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
21
+ "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
22
+ ],
23
+ });
24
+
25
+ const { class: className, ...rest } = Astro.props;
26
+ ---
27
+
28
+ <button
29
+ type="button"
30
+ class={sidebarRail({ class: className })}
31
+ data-slot="sidebar-rail"
32
+ data-sidebar="rail"
33
+ aria-label="Toggle Sidebar"
34
+ tabindex="-1"
35
+ {...rest}></button>
36
+
37
+ <script>
38
+ class SidebarRailHandler {
39
+ private rail: HTMLElement;
40
+ private provider: HTMLElement | null;
41
+
42
+ constructor(rail: HTMLElement) {
43
+ this.rail = rail;
44
+ this.provider = rail.closest<HTMLElement>('[data-slot="sidebar-provider"]');
45
+ this.init();
46
+ }
47
+
48
+ private init() {
49
+ this.rail.addEventListener("click", this.handleClick.bind(this));
50
+ }
51
+
52
+ private handleClick() {
53
+ if (this.provider) {
54
+ this.provider.dispatchEvent(new CustomEvent("sidebar:toggle"));
55
+ }
56
+ }
57
+ }
58
+
59
+ const railInstances = new WeakMap<HTMLElement, SidebarRailHandler>();
60
+
61
+ const setupSidebarRails = () => {
62
+ document.querySelectorAll<HTMLElement>(".starwind-sidebar-rail").forEach((rail) => {
63
+ if (railInstances.has(rail)) return;
64
+ railInstances.set(rail, new SidebarRailHandler(rail));
65
+ });
66
+ };
67
+
68
+ setupSidebarRails();
69
+ document.addEventListener("astro:after-swap", setupSidebarRails);
70
+ document.addEventListener("starwind:init", setupSidebarRails);
71
+ </script>
@@ -0,0 +1,22 @@
1
+ ---
2
+ import type { ComponentProps } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ import { Separator } from "@/components/starwind/separator";
6
+
7
+ const sidebarSeparator = tv({
8
+ base: "bg-sidebar-border mx-2 w-auto",
9
+ });
10
+
11
+ type Props = ComponentProps<typeof Separator>;
12
+
13
+ const { orientation = "horizontal", class: className, ...rest } = Astro.props;
14
+ ---
15
+
16
+ <Separator
17
+ orientation={orientation}
18
+ class={sidebarSeparator({ class: className })}
19
+ data-slot="sidebar-separator"
20
+ data-sidebar="separator"
21
+ {...rest}
22
+ />
@@ -0,0 +1,66 @@
1
+ ---
2
+ import PanelLeft from "@tabler/icons/outline/layout-sidebar.svg";
3
+ import type { ComponentProps } from "astro/types";
4
+ import { tv } from "tailwind-variants";
5
+
6
+ const sidebarTrigger = tv({
7
+ base: "starwind-sidebar-trigger",
8
+ });
9
+
10
+ import { Button } from "@/components/starwind/button";
11
+
12
+ type Props = ComponentProps<typeof Button>;
13
+
14
+ const { class: className, size = "icon-sm", variant = "ghost", ...rest } = Astro.props;
15
+ ---
16
+
17
+ <Button
18
+ variant={variant}
19
+ size={size}
20
+ class={sidebarTrigger({ class: className })}
21
+ data-slot="sidebar-trigger"
22
+ data-sidebar="trigger"
23
+ aria-label="Toggle Sidebar"
24
+ {...rest}
25
+ >
26
+ <slot name="icon">
27
+ <PanelLeft />
28
+ </slot>
29
+ <span class="sr-only">Toggle Sidebar</span>
30
+ </Button>
31
+
32
+ <script>
33
+ class SidebarTriggerHandler {
34
+ private trigger: HTMLElement;
35
+ private provider: HTMLElement | null;
36
+
37
+ constructor(trigger: HTMLElement) {
38
+ this.trigger = trigger;
39
+ this.provider = trigger.closest<HTMLElement>('[data-slot="sidebar-provider"]');
40
+ this.init();
41
+ }
42
+
43
+ private init() {
44
+ this.trigger.addEventListener("click", this.handleClick.bind(this));
45
+ }
46
+
47
+ private handleClick() {
48
+ if (this.provider) {
49
+ this.provider.dispatchEvent(new CustomEvent("sidebar:toggle"));
50
+ }
51
+ }
52
+ }
53
+
54
+ const triggerInstances = new WeakMap<HTMLElement, SidebarTriggerHandler>();
55
+
56
+ const setupSidebarTriggers = () => {
57
+ document.querySelectorAll<HTMLElement>(".starwind-sidebar-trigger").forEach((trigger) => {
58
+ if (triggerInstances.has(trigger)) return;
59
+ triggerInstances.set(trigger, new SidebarTriggerHandler(trigger));
60
+ });
61
+ };
62
+
63
+ setupSidebarTriggers();
64
+ document.addEventListener("astro:after-swap", setupSidebarTriggers);
65
+ document.addEventListener("starwind:init", setupSidebarTriggers);
66
+ </script>
@@ -0,0 +1,103 @@
1
+ import Sidebar, {
2
+ sidebar,
3
+ sidebarContainer,
4
+ sidebarGap,
5
+ sidebarInner,
6
+ sidebarMobileContent,
7
+ } from "./Sidebar.astro";
8
+ import SidebarContent, { sidebarContent } from "./SidebarContent.astro";
9
+ import SidebarFooter, { sidebarFooter } from "./SidebarFooter.astro";
10
+ import SidebarGroup, { sidebarGroup } from "./SidebarGroup.astro";
11
+ import SidebarGroupContent, { sidebarGroupContent } from "./SidebarGroupContent.astro";
12
+ import SidebarGroupLabel, { sidebarGroupLabel } from "./SidebarGroupLabel.astro";
13
+ import SidebarHeader, { sidebarHeader } from "./SidebarHeader.astro";
14
+ import SidebarInput from "./SidebarInput.astro";
15
+ import SidebarInset, { sidebarInset } from "./SidebarInset.astro";
16
+ import SidebarMenu, { sidebarMenu } from "./SidebarMenu.astro";
17
+ import SidebarMenuAction, { sidebarMenuAction } from "./SidebarMenuAction.astro";
18
+ import SidebarMenuBadge, { sidebarMenuBadge } from "./SidebarMenuBadge.astro";
19
+ import SidebarMenuButton, { sidebarMenuButton } from "./SidebarMenuButton.astro";
20
+ import SidebarMenuItem, { sidebarMenuItem } from "./SidebarMenuItem.astro";
21
+ import SidebarMenuSkeleton from "./SidebarMenuSkeleton.astro";
22
+ import SidebarMenuSub, { sidebarMenuSub } from "./SidebarMenuSub.astro";
23
+ import SidebarMenuSubButton, { sidebarMenuSubButton } from "./SidebarMenuSubButton.astro";
24
+ import SidebarMenuSubItem from "./SidebarMenuSubItem.astro";
25
+ import SidebarProvider, { sidebarProvider } from "./SidebarProvider.astro";
26
+ import SidebarRail, { sidebarRail } from "./SidebarRail.astro";
27
+ import SidebarSeparator from "./SidebarSeparator.astro";
28
+ import SidebarTrigger from "./SidebarTrigger.astro";
29
+
30
+ const SidebarVariants = {
31
+ sidebar,
32
+ sidebarGap,
33
+ sidebarContainer,
34
+ sidebarInner,
35
+ sidebarMobileContent,
36
+ sidebarContent,
37
+ sidebarFooter,
38
+ sidebarGroup,
39
+ sidebarGroupContent,
40
+ sidebarGroupLabel,
41
+ sidebarHeader,
42
+ sidebarInset,
43
+ sidebarMenu,
44
+ sidebarMenuAction,
45
+ sidebarMenuBadge,
46
+ sidebarMenuButton,
47
+ sidebarMenuItem,
48
+ sidebarMenuSub,
49
+ sidebarMenuSubButton,
50
+ sidebarProvider,
51
+ sidebarRail,
52
+ };
53
+
54
+ export {
55
+ Sidebar,
56
+ SidebarContent,
57
+ SidebarFooter,
58
+ SidebarGroup,
59
+ SidebarGroupContent,
60
+ SidebarGroupLabel,
61
+ SidebarHeader,
62
+ SidebarInput,
63
+ SidebarInset,
64
+ SidebarMenu,
65
+ SidebarMenuAction,
66
+ SidebarMenuBadge,
67
+ SidebarMenuButton,
68
+ SidebarMenuItem,
69
+ SidebarMenuSkeleton,
70
+ SidebarMenuSub,
71
+ SidebarMenuSubButton,
72
+ SidebarMenuSubItem,
73
+ SidebarProvider,
74
+ SidebarRail,
75
+ SidebarSeparator,
76
+ SidebarTrigger,
77
+ SidebarVariants,
78
+ };
79
+
80
+ export default {
81
+ Root: SidebarProvider,
82
+ Sidebar,
83
+ Content: SidebarContent,
84
+ Footer: SidebarFooter,
85
+ Group: SidebarGroup,
86
+ GroupContent: SidebarGroupContent,
87
+ GroupLabel: SidebarGroupLabel,
88
+ Header: SidebarHeader,
89
+ Input: SidebarInput,
90
+ Inset: SidebarInset,
91
+ Menu: SidebarMenu,
92
+ MenuAction: SidebarMenuAction,
93
+ MenuBadge: SidebarMenuBadge,
94
+ MenuButton: SidebarMenuButton,
95
+ MenuItem: SidebarMenuItem,
96
+ MenuSkeleton: SidebarMenuSkeleton,
97
+ MenuSub: SidebarMenuSub,
98
+ MenuSubButton: SidebarMenuSubButton,
99
+ MenuSubItem: SidebarMenuSubItem,
100
+ Rail: SidebarRail,
101
+ Separator: SidebarSeparator,
102
+ Trigger: SidebarTrigger,
103
+ };
@@ -0,0 +1,14 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ type Props = HTMLAttributes<"div">;
6
+
7
+ const { class: className, ...rest } = Astro.props;
8
+
9
+ export const skeleton = tv({
10
+ base: "bg-muted animate-pulse rounded-md",
11
+ });
12
+ ---
13
+
14
+ <div class={skeleton({ class: className })} data-slot="skeleton" {...rest}></div>
@@ -0,0 +1,9 @@
1
+ import Skeleton, { skeleton } from "./Skeleton.astro";
2
+
3
+ const SkeletonVariants = {
4
+ skeleton,
5
+ };
6
+
7
+ export { Skeleton, SkeletonVariants };
8
+
9
+ export default Skeleton;