@starwind-ui/core 1.8.0 → 1.10.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 (151) hide show
  1. package/dist/index.js +50 -23
  2. package/dist/index.js.map +1 -1
  3. package/dist/src/components/accordion/Accordion.astro +8 -2
  4. package/dist/src/components/accordion/AccordionContent.astro +2 -1
  5. package/dist/src/components/accordion/AccordionItem.astro +8 -2
  6. package/dist/src/components/accordion/AccordionTrigger.astro +4 -3
  7. package/dist/src/components/accordion/index.ts +7 -5
  8. package/dist/src/components/alert/Alert.astro +6 -3
  9. package/dist/src/components/alert/AlertDescription.astro +4 -4
  10. package/dist/src/components/alert/AlertTitle.astro +3 -3
  11. package/dist/src/components/alert/index.ts +6 -4
  12. package/dist/src/components/alert-dialog/AlertDialog.astro +273 -0
  13. package/dist/src/components/alert-dialog/AlertDialogAction.astro +44 -0
  14. package/dist/src/components/alert-dialog/AlertDialogCancel.astro +45 -0
  15. package/dist/src/components/alert-dialog/AlertDialogContent.astro +50 -0
  16. package/dist/src/components/alert-dialog/AlertDialogDescription.astro +18 -0
  17. package/dist/src/components/alert-dialog/AlertDialogFooter.astro +16 -0
  18. package/dist/src/components/alert-dialog/AlertDialogHeader.astro +14 -0
  19. package/dist/src/components/alert-dialog/AlertDialogTitle.astro +20 -0
  20. package/dist/src/components/alert-dialog/AlertDialogTrigger.astro +47 -0
  21. package/dist/src/components/alert-dialog/index.ts +46 -0
  22. package/dist/src/components/aspect-ratio/AspectRatio.astro +32 -0
  23. package/dist/src/components/aspect-ratio/index.ts +7 -0
  24. package/dist/src/components/avatar/Avatar.astro +2 -2
  25. package/dist/src/components/avatar/AvatarFallback.astro +2 -2
  26. package/dist/src/components/avatar/AvatarImage.astro +13 -2
  27. package/dist/src/components/avatar/index.ts +6 -4
  28. package/dist/src/components/badge/Badge.astro +15 -12
  29. package/dist/src/components/badge/index.ts +4 -2
  30. package/dist/src/components/breadcrumb/Breadcrumb.astro +1 -1
  31. package/dist/src/components/breadcrumb/BreadcrumbEllipsis.astro +4 -1
  32. package/dist/src/components/breadcrumb/BreadcrumbItem.astro +2 -2
  33. package/dist/src/components/breadcrumb/BreadcrumbLink.astro +2 -2
  34. package/dist/src/components/breadcrumb/BreadcrumbList.astro +2 -2
  35. package/dist/src/components/breadcrumb/BreadcrumbPage.astro +2 -1
  36. package/dist/src/components/breadcrumb/BreadcrumbSeparator.astro +2 -1
  37. package/dist/src/components/breadcrumb/index.ts +16 -6
  38. package/dist/src/components/button/Button.astro +15 -15
  39. package/dist/src/components/button/index.ts +4 -2
  40. package/dist/src/components/card/Card.astro +2 -2
  41. package/dist/src/components/card/CardContent.astro +2 -2
  42. package/dist/src/components/card/CardDescription.astro +2 -2
  43. package/dist/src/components/card/CardFooter.astro +2 -2
  44. package/dist/src/components/card/CardHeader.astro +2 -2
  45. package/dist/src/components/card/CardTitle.astro +2 -2
  46. package/dist/src/components/card/index.ts +16 -7
  47. package/dist/src/components/carousel/Carousel.astro +55 -0
  48. package/dist/src/components/carousel/CarouselContent.astro +26 -0
  49. package/dist/src/components/carousel/CarouselItem.astro +26 -0
  50. package/dist/src/components/carousel/CarouselNext.astro +33 -0
  51. package/dist/src/components/carousel/CarouselPrevious.astro +33 -0
  52. package/dist/src/components/carousel/carousel-script.ts +191 -0
  53. package/dist/src/components/carousel/index.ts +32 -0
  54. package/dist/src/components/checkbox/Checkbox.astro +28 -12
  55. package/dist/src/components/checkbox/index.ts +4 -2
  56. package/dist/src/components/dialog/Dialog.astro +24 -11
  57. package/dist/src/components/dialog/DialogClose.astro +7 -2
  58. package/dist/src/components/dialog/DialogContent.astro +9 -6
  59. package/dist/src/components/dialog/DialogDescription.astro +2 -2
  60. package/dist/src/components/dialog/DialogFooter.astro +2 -2
  61. package/dist/src/components/dialog/DialogHeader.astro +2 -2
  62. package/dist/src/components/dialog/DialogTitle.astro +2 -2
  63. package/dist/src/components/dialog/DialogTrigger.astro +7 -1
  64. package/dist/src/components/dialog/index.ts +20 -5
  65. package/dist/src/components/dropdown/Dropdown.astro +1 -0
  66. package/dist/src/components/dropdown/DropdownContent.astro +2 -1
  67. package/dist/src/components/dropdown/DropdownItem.astro +2 -1
  68. package/dist/src/components/dropdown/DropdownLabel.astro +2 -2
  69. package/dist/src/components/dropdown/DropdownSeparator.astro +3 -2
  70. package/dist/src/components/dropdown/DropdownTrigger.astro +9 -3
  71. package/dist/src/components/dropdown/index.ts +14 -5
  72. package/dist/src/components/dropzone/Dropzone.astro +7 -6
  73. package/dist/src/components/dropzone/DropzoneFilesList.astro +3 -2
  74. package/dist/src/components/dropzone/DropzoneLoadingIndicator.astro +1 -1
  75. package/dist/src/components/dropzone/DropzoneUploadIndicator.astro +1 -1
  76. package/dist/src/components/dropzone/index.ts +14 -3
  77. package/dist/src/components/input/Input.astro +4 -4
  78. package/dist/src/components/input/index.ts +4 -2
  79. package/dist/src/components/item/Item.astro +52 -0
  80. package/dist/src/components/item/ItemActions.astro +16 -0
  81. package/dist/src/components/item/ItemContent.astro +16 -0
  82. package/dist/src/components/item/ItemDescription.astro +19 -0
  83. package/dist/src/components/item/ItemFooter.astro +16 -0
  84. package/dist/src/components/item/ItemGroup.astro +16 -0
  85. package/dist/src/components/item/ItemHeader.astro +16 -0
  86. package/dist/src/components/item/ItemMedia.astro +40 -0
  87. package/dist/src/components/item/ItemSeparator.astro +21 -0
  88. package/dist/src/components/item/ItemTitle.astro +16 -0
  89. package/dist/src/components/item/index.ts +50 -0
  90. package/dist/src/components/label/Label.astro +2 -2
  91. package/dist/src/components/label/index.ts +4 -2
  92. package/dist/src/components/pagination/Pagination.astro +8 -2
  93. package/dist/src/components/pagination/PaginationContent.astro +2 -2
  94. package/dist/src/components/pagination/PaginationEllipsis.astro +7 -2
  95. package/dist/src/components/pagination/PaginationItem.astro +2 -2
  96. package/dist/src/components/pagination/PaginationLink.astro +10 -29
  97. package/dist/src/components/pagination/PaginationNext.astro +2 -1
  98. package/dist/src/components/pagination/PaginationPrevious.astro +2 -1
  99. package/dist/src/components/pagination/index.ts +18 -7
  100. package/dist/src/components/progress/Progress.astro +6 -3
  101. package/dist/src/components/progress/index.ts +7 -2
  102. package/dist/src/components/radio-group/RadioGroup.astro +2 -1
  103. package/dist/src/components/radio-group/RadioGroupItem.astro +17 -15
  104. package/dist/src/components/radio-group/index.ts +16 -3
  105. package/dist/src/components/select/Select.astro +1 -0
  106. package/dist/src/components/select/SelectContent.astro +3 -2
  107. package/dist/src/components/select/SelectGroup.astro +1 -1
  108. package/dist/src/components/select/SelectItem.astro +3 -2
  109. package/dist/src/components/select/SelectLabel.astro +2 -2
  110. package/dist/src/components/select/SelectSeparator.astro +2 -2
  111. package/dist/src/components/select/SelectTrigger.astro +4 -3
  112. package/dist/src/components/select/SelectValue.astro +2 -2
  113. package/dist/src/components/select/index.ts +18 -6
  114. package/dist/src/components/separator/Separator.astro +36 -0
  115. package/dist/src/components/separator/index.ts +7 -0
  116. package/dist/src/components/sheet/Sheet.astro +13 -0
  117. package/dist/src/components/sheet/SheetClose.astro +13 -0
  118. package/dist/src/components/sheet/SheetContent.astro +88 -0
  119. package/dist/src/components/sheet/SheetDescription.astro +16 -0
  120. package/dist/src/components/sheet/SheetFooter.astro +16 -0
  121. package/dist/src/components/sheet/SheetHeader.astro +16 -0
  122. package/dist/src/components/sheet/SheetTitle.astro +16 -0
  123. package/dist/src/components/sheet/SheetTrigger.astro +13 -0
  124. package/dist/src/components/sheet/index.ts +41 -0
  125. package/dist/src/components/skeleton/Skeleton.astro +3 -3
  126. package/dist/src/components/skeleton/index.ts +6 -2
  127. package/dist/src/components/spinner/Spinner.astro +21 -0
  128. package/dist/src/components/spinner/index.ts +7 -0
  129. package/dist/src/components/switch/Switch.astro +16 -13
  130. package/dist/src/components/switch/index.ts +8 -2
  131. package/dist/src/components/table/Table.astro +3 -3
  132. package/dist/src/components/table/TableBody.astro +2 -2
  133. package/dist/src/components/table/TableCaption.astro +2 -2
  134. package/dist/src/components/table/TableCell.astro +2 -2
  135. package/dist/src/components/table/TableFoot.astro +2 -2
  136. package/dist/src/components/table/TableHead.astro +2 -2
  137. package/dist/src/components/table/TableHeader.astro +2 -2
  138. package/dist/src/components/table/TableRow.astro +2 -2
  139. package/dist/src/components/table/index.ts +30 -9
  140. package/dist/src/components/tabs/Tabs.astro +2 -1
  141. package/dist/src/components/tabs/TabsContent.astro +4 -1
  142. package/dist/src/components/tabs/TabsList.astro +9 -3
  143. package/dist/src/components/tabs/TabsTrigger.astro +6 -3
  144. package/dist/src/components/tabs/index.ts +12 -5
  145. package/dist/src/components/textarea/Textarea.astro +4 -4
  146. package/dist/src/components/textarea/index.ts +6 -2
  147. package/dist/src/components/tooltip/Tooltip.astro +2 -1
  148. package/dist/src/components/tooltip/TooltipContent.astro +21 -5
  149. package/dist/src/components/tooltip/TooltipTrigger.astro +1 -1
  150. package/dist/src/components/tooltip/index.ts +8 -3
  151. package/package.json +1 -1
@@ -6,16 +6,16 @@ type Props = HTMLAttributes<"div">;
6
6
  const { class: className, ...rest } = Astro.props;
7
7
  ---
8
8
 
9
- <div class:list={["starwind-dialog", className]} {...rest}>
9
+ <div class:list={["starwind-dialog", className]} data-slot="dialog" {...rest}>
10
10
  <slot />
11
11
  </div>
12
12
 
13
13
  <script>
14
14
  class DialogHandler {
15
15
  private triggers: HTMLButtonElement[] = [];
16
- private dialog: HTMLDialogElement;
16
+ private dialog: HTMLDialogElement | null = null;
17
17
  private closeButtons: HTMLButtonElement[] = [];
18
- private backdrop: HTMLElement;
18
+ private backdrop: HTMLElement | null = null;
19
19
  private dialogId: string;
20
20
  /**
21
21
  * The duration of the animation in milliseconds. This is used to calculate the
@@ -24,8 +24,11 @@ const { class: className, ...rest } = Astro.props;
24
24
  private animationDuration: number;
25
25
 
26
26
  constructor(dialogWrapper: HTMLElement, dialogNumber: number) {
27
- this.dialog = dialogWrapper.querySelector("dialog")!;
28
- this.backdrop = dialogWrapper.querySelector(".starwind-dialog-backdrop")!;
27
+ this.dialog = dialogWrapper.querySelector("dialog");
28
+ this.backdrop = dialogWrapper.querySelector(".starwind-dialog-backdrop");
29
+ if (!this.dialog || !this.backdrop) {
30
+ throw new Error("Dialog: dialog or backdrop not found");
31
+ }
29
32
 
30
33
  // if no ID was provided for the wrapper, generate one
31
34
  if (dialogWrapper.id) {
@@ -36,6 +39,7 @@ const { class: className, ...rest } = Astro.props;
36
39
  }
37
40
 
38
41
  // animationDuration is set with inline styles through passed prop to DialogContent
42
+ // if no animationDuration, check data-close-duration
39
43
  const animationDurationString = this.dialog.style.animationDuration;
40
44
  if (animationDurationString.endsWith("ms")) {
41
45
  this.animationDuration = parseFloat(animationDurationString);
@@ -43,7 +47,9 @@ const { class: className, ...rest } = Astro.props;
43
47
  // using something like @playform/compress might optimize to use "s" instead of "ms"
44
48
  this.animationDuration = parseFloat(animationDurationString) * 1000;
45
49
  } else {
46
- this.animationDuration = 200;
50
+ this.animationDuration = this.dialog.dataset.closeDuration
51
+ ? parseFloat(this.dialog.dataset.closeDuration)
52
+ : 200;
47
53
  }
48
54
 
49
55
  // Find internal triggers and handle them
@@ -95,12 +101,12 @@ const { class: className, ...rest } = Astro.props;
95
101
 
96
102
  private setupAccessibility(dialogNumber: number): void {
97
103
  // get the first heading element in the dialog
98
- const firstHeading = this.dialog.querySelector("h1, h2, h3, h4, h5, h6");
104
+ const firstHeading = this.dialog?.querySelector("h1, h2, h3, h4, h5, h6");
99
105
  if (firstHeading) {
100
106
  // create a unique ID for the heading
101
107
  firstHeading.id = `starwind-dialog${dialogNumber}-heading`;
102
108
  // set the aria-labelledby attribute to the first heading element
103
- this.dialog.setAttribute("aria-labelledby", firstHeading.id);
109
+ this.dialog?.setAttribute("aria-labelledby", firstHeading.id);
104
110
  }
105
111
  }
106
112
 
@@ -133,6 +139,7 @@ const { class: className, ...rest } = Astro.props;
133
139
  }
134
140
 
135
141
  private setupEvents(): void {
142
+ if (!this.dialog) return;
136
143
  // Add click listeners to all triggers
137
144
  this.triggers.forEach((trigger) => {
138
145
  trigger.addEventListener("click", () => {
@@ -153,6 +160,7 @@ const { class: className, ...rest } = Astro.props;
153
160
 
154
161
  // Close on click outside
155
162
  this.dialog.addEventListener("click", (e) => {
163
+ if (!this.dialog) return;
156
164
  const dialogDimensions = this.dialog.getBoundingClientRect();
157
165
  const clickedInDialog =
158
166
  e.clientX >= dialogDimensions.left &&
@@ -206,6 +214,7 @@ const { class: className, ...rest } = Astro.props;
206
214
  }
207
215
 
208
216
  private open(): void {
217
+ if (!this.dialog || !this.backdrop) return;
209
218
  this.dialog.showModal();
210
219
  document.body.classList.add("overflow-hidden");
211
220
  this.backdrop.classList.remove("hidden");
@@ -214,14 +223,18 @@ const { class: className, ...rest } = Astro.props;
214
223
  }
215
224
 
216
225
  private close(): void {
217
- document.body.classList.remove("overflow-hidden");
226
+ if (!this.dialog || !this.backdrop) return;
218
227
  this.dialog.dataset.state = "closed";
219
228
  this.backdrop.dataset.state = "closed";
220
229
 
221
230
  // Wait for animation to finish before hiding backdrop
222
231
  setTimeout(() => {
223
- this.backdrop.classList.add("hidden");
224
- this.dialog.close();
232
+ this.backdrop?.classList.add("hidden");
233
+ this.dialog?.close();
234
+ const stillOpen = document.querySelectorAll("dialog[open]").length;
235
+ if (stillOpen === 0) {
236
+ document.body.classList.remove("overflow-hidden");
237
+ }
225
238
  }, this.animationDuration);
226
239
  }
227
240
  }
@@ -19,11 +19,16 @@ if (Astro.slots.has("default")) {
19
19
 
20
20
  {
21
21
  asChild && hasChildren ? (
22
- <div class="starwind-dialog-close" data-as-child>
22
+ <div class="starwind-dialog-close" data-slot="dialog-close" data-as-child>
23
23
  <slot />
24
24
  </div>
25
25
  ) : (
26
- <button type="button" class:list={["starwind-dialog-close", className]} {...rest}>
26
+ <button
27
+ type="button"
28
+ class:list={["starwind-dialog-close", className]}
29
+ data-slot="dialog-close"
30
+ {...rest}
31
+ >
27
32
  <slot>Demo close button</slot>
28
33
  </button>
29
34
  )
@@ -10,7 +10,7 @@ type Props = HTMLAttributes<"dialog"> & {
10
10
  animationDuration?: number;
11
11
  };
12
12
 
13
- const dialogBackdrop = tv({
13
+ export const dialogBackdrop = tv({
14
14
  base: [
15
15
  "starwind-dialog-backdrop fixed inset-0 top-0 left-0 z-50 hidden h-screen w-screen bg-black/80",
16
16
  "data-[state=open]:animate-in fade-in",
@@ -18,7 +18,7 @@ const dialogBackdrop = tv({
18
18
  ],
19
19
  });
20
20
 
21
- const dialogContent = tv({
21
+ export const dialogContent = tv({
22
22
  base: [
23
23
  "fixed top-16 left-[50%] z-50 translate-x-[-50%] sm:top-[50%] sm:translate-y-[-50%]",
24
24
  "bg-background w-full max-w-md border p-8 shadow-lg sm:rounded-lg",
@@ -28,11 +28,11 @@ const dialogContent = tv({
28
28
  ],
29
29
  });
30
30
 
31
- const dialogCloseButton = tv({
31
+ export const dialogCloseButton = tv({
32
32
  base: [
33
33
  "starwind-dialog-close text-muted-foreground",
34
- "absolute top-5.5 right-5.5 rounded-sm opacity-70 transition-opacity hover:opacity-100 disabled:pointer-events-none",
35
- "focus-visible:outline-outline focus-visible:outline-2 focus-visible:outline-offset-2",
34
+ "absolute top-5.5 right-5.5 rounded-sm [&>svg]:opacity-70 hover:[&>svg]:opacity-100",
35
+ "focus-visible:ring-outline/50 transition-[color,box-shadow] outline-none focus-visible:ring-3",
36
36
  ],
37
37
  });
38
38
 
@@ -43,6 +43,7 @@ const { class: className, animationDuration = 200, ...rest } = Astro.props;
43
43
  <div
44
44
  class={dialogBackdrop()}
45
45
  data-state="closed"
46
+ data-slot="dialog-backdrop"
46
47
  style={{ animationDuration: `${animationDuration}ms` }}
47
48
  >
48
49
  </div>
@@ -50,11 +51,13 @@ const { class: className, animationDuration = 200, ...rest } = Astro.props;
50
51
  <dialog
51
52
  class={dialogContent({ class: className })}
52
53
  data-state="closed"
54
+ data-slot="dialog-content"
53
55
  {...rest}
54
56
  style={{ animationDuration: `${animationDuration}ms` }}
55
57
  >
56
58
  <slot />
57
59
  <button type="button" class={dialogCloseButton()} data-dialog-close aria-label="Close dialog">
58
- <X class="size-5" />
60
+ <X class="size-5 transition-opacity" />
61
+ <span class="sr-only">Close</span>
59
62
  </button>
60
63
  </dialog>
@@ -4,11 +4,11 @@ import { tv } from "tailwind-variants";
4
4
 
5
5
  type Props = HTMLAttributes<"p">;
6
6
 
7
- const dialogDescription = tv({ base: "text-muted-foreground" });
7
+ export const dialogDescription = tv({ base: "text-muted-foreground" });
8
8
 
9
9
  const { class: className, ...rest } = Astro.props;
10
10
  ---
11
11
 
12
- <p class={dialogDescription({ class: className })} {...rest}>
12
+ <p class={dialogDescription({ class: className })} data-slot="dialog-description" {...rest}>
13
13
  <slot />
14
14
  </p>
@@ -4,11 +4,11 @@ import { tv } from "tailwind-variants";
4
4
 
5
5
  type Props = HTMLAttributes<"div">;
6
6
 
7
- const dialogFooter = tv({ base: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end" });
7
+ export const dialogFooter = tv({ base: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end" });
8
8
 
9
9
  const { class: className, ...rest } = Astro.props;
10
10
  ---
11
11
 
12
- <div class={dialogFooter({ class: className })} {...rest}>
12
+ <div class={dialogFooter({ class: className })} data-slot="dialog-footer" {...rest}>
13
13
  <slot />
14
14
  </div>
@@ -4,11 +4,11 @@ import { tv } from "tailwind-variants";
4
4
 
5
5
  type Props = HTMLAttributes<"div">;
6
6
 
7
- const dialogHeader = tv({ base: "flex flex-col space-y-2 text-center sm:text-left" });
7
+ export const dialogHeader = tv({ base: "flex flex-col space-y-2 text-center sm:text-left" });
8
8
 
9
9
  const { class: className, ...rest } = Astro.props;
10
10
  ---
11
11
 
12
- <div class={dialogHeader({ class: className })} {...rest}>
12
+ <div class={dialogHeader({ class: className })} data-slot="dialog-header" {...rest}>
13
13
  <slot />
14
14
  </div>
@@ -10,11 +10,11 @@ type Props = Omit<HTMLAttributes<"h2">, "id"> & {
10
10
  children: any;
11
11
  };
12
12
 
13
- const dialogTitle = tv({ base: "text-2xl leading-none font-semibold tracking-tight" });
13
+ export const dialogTitle = tv({ base: "text-xl leading-none font-semibold tracking-tight" });
14
14
 
15
15
  const { class: className, ...rest } = Astro.props;
16
16
  ---
17
17
 
18
- <h2 class={dialogTitle({ class: className })} {...rest}>
18
+ <h2 class={dialogTitle({ class: className })} data-slot="dialog-title" {...rest}>
19
19
  <slot />
20
20
  </h2>
@@ -24,7 +24,12 @@ if (Astro.slots.has("default")) {
24
24
 
25
25
  {
26
26
  asChild && hasChildren ? (
27
- <div class="starwind-dialog-trigger" data-as-child data-dialog-for={dialogFor}>
27
+ <div
28
+ class:list={["starwind-dialog-trigger", className]}
29
+ data-slot="dialog-trigger"
30
+ data-as-child
31
+ data-dialog-for={dialogFor}
32
+ >
28
33
  <slot />
29
34
  </div>
30
35
  ) : (
@@ -32,6 +37,7 @@ if (Astro.slots.has("default")) {
32
37
  type="button"
33
38
  aria-haspopup="dialog"
34
39
  class:list={["starwind-dialog-trigger", className]}
40
+ data-slot="dialog-trigger"
35
41
  data-dialog-for={dialogFor}
36
42
  {...rest}
37
43
  >
@@ -1,12 +1,26 @@
1
1
  import Dialog from "./Dialog.astro";
2
2
  import DialogClose from "./DialogClose.astro";
3
- import DialogContent from "./DialogContent.astro";
4
- import DialogDescription from "./DialogDescription.astro";
5
- import DialogFooter from "./DialogFooter.astro";
6
- import DialogHeader from "./DialogHeader.astro";
7
- import DialogTitle from "./DialogTitle.astro";
3
+ import DialogContent, {
4
+ dialogBackdrop,
5
+ dialogCloseButton,
6
+ dialogContent,
7
+ } from "./DialogContent.astro";
8
+ import DialogDescription, { dialogDescription } from "./DialogDescription.astro";
9
+ import DialogFooter, { dialogFooter } from "./DialogFooter.astro";
10
+ import DialogHeader, { dialogHeader } from "./DialogHeader.astro";
11
+ import DialogTitle, { dialogTitle } from "./DialogTitle.astro";
8
12
  import DialogTrigger from "./DialogTrigger.astro";
9
13
 
14
+ const DialogVariants = {
15
+ dialogBackdrop,
16
+ dialogContent,
17
+ dialogCloseButton,
18
+ dialogDescription,
19
+ dialogFooter,
20
+ dialogHeader,
21
+ dialogTitle,
22
+ };
23
+
10
24
  export {
11
25
  Dialog,
12
26
  DialogClose,
@@ -16,6 +30,7 @@ export {
16
30
  DialogHeader,
17
31
  DialogTitle,
18
32
  DialogTrigger,
33
+ DialogVariants,
19
34
  };
20
35
 
21
36
  export default {
@@ -22,6 +22,7 @@ const { class: className, openOnHover = false, closeDelay = 200, ...rest } = Ast
22
22
  class:list={["starwind-dropdown", "relative", className]}
23
23
  data-open-on-hover={openOnHover ? "true" : undefined}
24
24
  data-close-delay={closeDelay}
25
+ data-slot="dropdown"
25
26
  {...rest}
26
27
  >
27
28
  <slot />
@@ -25,7 +25,7 @@ type Props = HTMLAttributes<"div"> & {
25
25
  animationDuration?: number;
26
26
  };
27
27
 
28
- const dropdownContent = tv({
28
+ export const dropdownContent = tv({
29
29
  base: [
30
30
  "starwind-dropdown-content",
31
31
  "bg-popover text-popover-foreground z-50 min-w-[9rem] overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
@@ -66,6 +66,7 @@ const {
66
66
  data-side={side}
67
67
  data-align={align}
68
68
  data-state="closed"
69
+ data-slot="dropdown-content"
69
70
  tabindex="-1"
70
71
  aria-orientation="vertical"
71
72
  style={{
@@ -13,7 +13,7 @@ type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & {
13
13
  disabled?: boolean;
14
14
  };
15
15
 
16
- const dropdownItem = tv({
16
+ export const dropdownItem = tv({
17
17
  base: [
18
18
  "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 transition-colors outline-none select-none",
19
19
  "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
@@ -41,6 +41,7 @@ const { class: className, inset = false, disabled = false, as: Tag = "div", ...r
41
41
  role="menuitem"
42
42
  tabindex={disabled ? "-1" : "0"}
43
43
  data-disabled={disabled ? "true" : undefined}
44
+ data-slot="dropdown-item"
44
45
  {...rest}
45
46
  >
46
47
  <slot />
@@ -9,7 +9,7 @@ type Props = HTMLAttributes<"div"> & {
9
9
  inset?: boolean;
10
10
  };
11
11
 
12
- const dropdownLabel = tv({
12
+ export const dropdownLabel = tv({
13
13
  base: ["px-2 py-1.5 font-semibold"],
14
14
  variants: {
15
15
  inset: {
@@ -24,6 +24,6 @@ const dropdownLabel = tv({
24
24
  const { class: className, inset = false, ...rest } = Astro.props;
25
25
  ---
26
26
 
27
- <div class={dropdownLabel({ inset, class: className })} {...rest}>
27
+ <div class={dropdownLabel({ inset, class: className })} data-slot="dropdown-label" {...rest}>
28
28
  <slot />
29
29
  </div>
@@ -4,8 +4,8 @@ import { tv } from "tailwind-variants";
4
4
 
5
5
  type Props = HTMLAttributes<"div">;
6
6
 
7
- const dropdownSeparator = tv({
8
- base: "bg-muted -mx-1 my-1 h-px",
7
+ export const dropdownSeparator = tv({
8
+ base: "bg-border -mx-1 my-1 h-px",
9
9
  });
10
10
 
11
11
  const { class: className, ...rest } = Astro.props;
@@ -15,6 +15,7 @@ const { class: className, ...rest } = Astro.props;
15
15
  class={dropdownSeparator({ class: className })}
16
16
  role="separator"
17
17
  aria-orientation="horizontal"
18
+ data-slot="dropdown-separator"
18
19
  {...rest}
19
20
  >
20
21
  </div>
@@ -9,11 +9,12 @@ type Props = Omit<HTMLAttributes<"button">, "role" | "type"> & {
9
9
  asChild?: boolean;
10
10
  };
11
11
 
12
- const dropdownTrigger = tv({
12
+ export const dropdownTrigger = tv({
13
13
  base: [
14
14
  "starwind-dropdown-trigger",
15
15
  "inline-flex items-center justify-center",
16
- "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
16
+ "focus-visible:ring-outline/50 transition-[color,box-shadow] outline-none focus-visible:ring-3",
17
+ "disabled:pointer-events-none",
17
18
  ],
18
19
  });
19
20
 
@@ -28,7 +29,11 @@ if (Astro.slots.has("default")) {
28
29
 
29
30
  {
30
31
  asChild && hasChildren ? (
31
- <div class={`starwind-dropdown-trigger ${className}`} data-as-child>
32
+ <div
33
+ class={`starwind-dropdown-trigger ${className}`}
34
+ data-slot="dropdown-trigger"
35
+ data-as-child
36
+ >
32
37
  <slot />
33
38
  </div>
34
39
  ) : (
@@ -38,6 +43,7 @@ if (Astro.slots.has("default")) {
38
43
  aria-haspopup="true"
39
44
  aria-expanded="false"
40
45
  data-state="closed"
46
+ data-slot="dropdown-trigger"
41
47
  {...rest}
42
48
  >
43
49
  <slot />
@@ -1,9 +1,17 @@
1
1
  import Dropdown from "./Dropdown.astro";
2
- import DropdownContent from "./DropdownContent.astro";
3
- import DropdownItem from "./DropdownItem.astro";
4
- import DropdownLabel from "./DropdownLabel.astro";
5
- import DropdownSeparator from "./DropdownSeparator.astro";
6
- import DropdownTrigger from "./DropdownTrigger.astro";
2
+ import DropdownContent, { dropdownContent } from "./DropdownContent.astro";
3
+ import DropdownItem, { dropdownItem } from "./DropdownItem.astro";
4
+ import DropdownLabel, { dropdownLabel } from "./DropdownLabel.astro";
5
+ import DropdownSeparator, { dropdownSeparator } from "./DropdownSeparator.astro";
6
+ import DropdownTrigger, { dropdownTrigger } from "./DropdownTrigger.astro";
7
+
8
+ const DropdownVariants = {
9
+ dropdownContent,
10
+ dropdownItem,
11
+ dropdownLabel,
12
+ dropdownSeparator,
13
+ dropdownTrigger,
14
+ };
7
15
 
8
16
  export {
9
17
  Dropdown,
@@ -12,6 +20,7 @@ export {
12
20
  DropdownLabel,
13
21
  DropdownSeparator,
14
22
  DropdownTrigger,
23
+ DropdownVariants,
15
24
  };
16
25
 
17
26
  export default {
@@ -16,13 +16,13 @@ type Props = HTMLAttributes<"input"> & {
16
16
  // extract id separately so it can be used in the label. The input will get the same id with "-input" suffix.
17
17
  const { class: className, id, isUploading = false, ...rest } = Astro.props as Props;
18
18
 
19
- const root = tv({
19
+ export const dropzone = tv({
20
20
  base: [
21
21
  "starwind-dropzone",
22
- "relative flex w-full flex-col items-center justify-center gap-1 rounded-lg px-6 py-12",
23
- "bg-background text-muted-foreground border-input cursor-pointer border border-dashed text-center text-sm",
24
- "starwind-transition-colors data-[is-uploading=false]:hover:bg-muted/50 data-[drag-active=true]:bg-muted/50",
25
- "focus-visible:outline-outline focus-visible:ring-0 focus-visible:outline-2 focus-visible:outline-offset-2",
22
+ "relative flex w-full flex-col items-center justify-center gap-1 rounded-lg px-6 py-12 shadow-xs",
23
+ "bg-background dark:bg-input/30 text-muted-foreground border-input cursor-pointer border border-dashed text-center text-sm",
24
+ "data-[is-uploading=false]:hover:bg-muted/50 data-[drag-active=true]:bg-muted/50 transition",
25
+ "focus-visible:border-outline focus-visible:ring-outline/50 outline-none focus-visible:ring-3",
26
26
  ],
27
27
  });
28
28
  ---
@@ -30,7 +30,8 @@ const root = tv({
30
30
  <label
31
31
  id={id}
32
32
  tabindex="0"
33
- class={root({ class: className })}
33
+ class={dropzone({ class: className })}
34
+ data-slot="dropzone"
34
35
  data-drag-active="false"
35
36
  data-has-files="false"
36
37
  data-is-uploading={String(isUploading)}
@@ -6,7 +6,7 @@ type Props = HTMLAttributes<"div">;
6
6
 
7
7
  const { class: className, ...rest } = Astro.props;
8
8
 
9
- const filesList = tv({
9
+ export const dropzoneFilesList = tv({
10
10
  base: [
11
11
  "starwind-files-list",
12
12
  "mt-1 -mb-8 min-h-8",
@@ -17,9 +17,10 @@ const filesList = tv({
17
17
  ---
18
18
 
19
19
  <div
20
- class={filesList({ class: className })}
20
+ class={dropzoneFilesList({ class: className })}
21
21
  aria-live="polite"
22
22
  aria-label="Uploaded files"
23
+ data-slot="dropzone-files-list"
23
24
  {...rest}
24
25
  >
25
26
  </div>
@@ -2,7 +2,7 @@
2
2
  import LoaderIcon from "@tabler/icons/outline/loader-2.svg";
3
3
  ---
4
4
 
5
- <div class="starwind-loading-indicator hidden">
5
+ <div class="starwind-loading-indicator hidden" data-slot="dropzone-loading-indicator">
6
6
  <slot>
7
7
  <LoaderIcon class="mx-auto size-10 animate-spin" aria-hidden="true" />
8
8
  <p class="mt-1 text-sm">Uploading file(s)...</p>
@@ -2,7 +2,7 @@
2
2
  import CloudUploadIcon from "@tabler/icons/outline/cloud-upload.svg";
3
3
  ---
4
4
 
5
- <div class="starwind-upload-indicator">
5
+ <div class="starwind-upload-indicator" data-slot="dropzone-upload-indicator">
6
6
  <slot>
7
7
  <CloudUploadIcon class="mx-auto size-10" aria-hidden="true" />
8
8
  <p class="mt-1 text-sm">Click to upload or drag and drop</p>
@@ -1,9 +1,20 @@
1
- import Dropzone from "./Dropzone.astro";
2
- import DropzoneFilesList from "./DropzoneFilesList.astro";
1
+ import Dropzone, { dropzone } from "./Dropzone.astro";
2
+ import DropzoneFilesList, { dropzoneFilesList } from "./DropzoneFilesList.astro";
3
3
  import DropzoneLoadingIndicator from "./DropzoneLoadingIndicator.astro";
4
4
  import DropzoneUploadIndicator from "./DropzoneUploadIndicator.astro";
5
5
 
6
- export { Dropzone, DropzoneFilesList, DropzoneLoadingIndicator, DropzoneUploadIndicator };
6
+ const DropzoneVariants = {
7
+ dropzone,
8
+ dropzoneFilesList,
9
+ };
10
+
11
+ export {
12
+ Dropzone,
13
+ DropzoneFilesList,
14
+ DropzoneLoadingIndicator,
15
+ DropzoneUploadIndicator,
16
+ DropzoneVariants,
17
+ };
7
18
 
8
19
  export default {
9
20
  Root: Dropzone,
@@ -4,10 +4,10 @@ import { tv, type VariantProps } from "tailwind-variants";
4
4
 
5
5
  type Props = HTMLAttributes<"input"> & VariantProps<typeof input>;
6
6
 
7
- const input = tv({
7
+ export const input = tv({
8
8
  base: [
9
- "border-input bg-background text-foreground w-full rounded-md border",
10
- "focus:outline-outline focus:ring-0 focus:outline-2 focus:outline-offset-2",
9
+ "border-input dark:bg-input/30 text-foreground w-full rounded-md border bg-transparent shadow-xs",
10
+ "focus-visible:border-outline focus-visible:ring-outline/50 transition-[color,box-shadow] focus-visible:ring-3",
11
11
  "file:text-foreground file:my-auto file:mr-4 file:h-full file:border-0 file:bg-transparent file:text-sm file:font-medium",
12
12
  "disabled:cursor-not-allowed disabled:opacity-50",
13
13
  "peer placeholder:text-muted-foreground",
@@ -21,4 +21,4 @@ const input = tv({
21
21
  const { size, class: className, ...rest } = Astro.props;
22
22
  ---
23
23
 
24
- <input class={input({ size, class: className })} {...rest} />
24
+ <input class={input({ size, class: className })} data-slot="input" {...rest} />
@@ -1,5 +1,7 @@
1
- import Input from "./Input.astro";
1
+ import Input, { input } from "./Input.astro";
2
2
 
3
- export { Input };
3
+ const InputVariants = { input };
4
+
5
+ export { Input, InputVariants };
4
6
 
5
7
  export default Input;
@@ -0,0 +1,52 @@
1
+ ---
2
+ import type { HTMLTag, Polymorphic } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & {
6
+ /**
7
+ * Variant of the item
8
+ * @default "default"
9
+ */
10
+ variant?: "default" | "outline" | "muted";
11
+ /**
12
+ * Size of the item
13
+ * @default "default"
14
+ */
15
+ size?: "default" | "sm";
16
+ };
17
+
18
+ export const item = tv({
19
+ base: [
20
+ "group/item flex flex-wrap items-center rounded-md border border-transparent text-sm transition-colors",
21
+ "[a]:hover:bg-accent/50 [a]:transition-colors",
22
+ "focus-visible:border-ring focus-visible:ring-outline/50 outline-none focus-visible:ring-[3px]",
23
+ ],
24
+ variants: {
25
+ variant: {
26
+ default: "bg-transparent",
27
+ outline: "border-border",
28
+ muted: "bg-muted/50",
29
+ },
30
+ size: {
31
+ default: "gap-4 p-4",
32
+ sm: "gap-2.5 px-4 py-3",
33
+ },
34
+ },
35
+ defaultVariants: {
36
+ variant: "default",
37
+ size: "default",
38
+ },
39
+ });
40
+
41
+ const {
42
+ variant = "default",
43
+ size = "default",
44
+ class: className,
45
+ as: Tag = "div",
46
+ ...rest
47
+ } = Astro.props;
48
+ ---
49
+
50
+ <Tag class={item({ variant, size, class: className })} data-slot="item" {...rest}>
51
+ <slot />
52
+ </Tag>
@@ -0,0 +1,16 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { tv } from "tailwind-variants";
4
+
5
+ type Props = HTMLAttributes<"div">;
6
+
7
+ export const itemActions = tv({
8
+ base: "flex items-center gap-2",
9
+ });
10
+
11
+ const { class: className, ...rest } = Astro.props;
12
+ ---
13
+
14
+ <div class={itemActions({ class: className })} data-slot="item-actions" {...rest}>
15
+ <slot />
16
+ </div>