@starwind-ui/core 1.11.2 → 1.12.1

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 (158) hide show
  1. package/package.json +1 -1
  2. package/dist/index.d.ts +0 -28
  3. package/dist/index.js +0 -74
  4. package/dist/index.js.map +0 -1
  5. package/dist/src/components/accordion/Accordion.astro +0 -247
  6. package/dist/src/components/accordion/AccordionContent.astro +0 -33
  7. package/dist/src/components/accordion/AccordionItem.astro +0 -27
  8. package/dist/src/components/accordion/AccordionTrigger.astro +0 -32
  9. package/dist/src/components/accordion/index.ts +0 -15
  10. package/dist/src/components/alert/Alert.astro +0 -31
  11. package/dist/src/components/alert/AlertDescription.astro +0 -14
  12. package/dist/src/components/alert/AlertTitle.astro +0 -16
  13. package/dist/src/components/alert/index.ts +0 -13
  14. package/dist/src/components/alert-dialog/AlertDialog.astro +0 -273
  15. package/dist/src/components/alert-dialog/AlertDialogAction.astro +0 -44
  16. package/dist/src/components/alert-dialog/AlertDialogCancel.astro +0 -45
  17. package/dist/src/components/alert-dialog/AlertDialogContent.astro +0 -52
  18. package/dist/src/components/alert-dialog/AlertDialogDescription.astro +0 -18
  19. package/dist/src/components/alert-dialog/AlertDialogFooter.astro +0 -16
  20. package/dist/src/components/alert-dialog/AlertDialogHeader.astro +0 -14
  21. package/dist/src/components/alert-dialog/AlertDialogTitle.astro +0 -20
  22. package/dist/src/components/alert-dialog/AlertDialogTrigger.astro +0 -47
  23. package/dist/src/components/alert-dialog/index.ts +0 -46
  24. package/dist/src/components/aspect-ratio/AspectRatio.astro +0 -32
  25. package/dist/src/components/aspect-ratio/index.ts +0 -7
  26. package/dist/src/components/avatar/Avatar.astro +0 -29
  27. package/dist/src/components/avatar/AvatarFallback.astro +0 -18
  28. package/dist/src/components/avatar/AvatarImage.astro +0 -49
  29. package/dist/src/components/avatar/index.ts +0 -13
  30. package/dist/src/components/badge/Badge.astro +0 -51
  31. package/dist/src/components/badge/index.ts +0 -7
  32. package/dist/src/components/breadcrumb/Breadcrumb.astro +0 -11
  33. package/dist/src/components/breadcrumb/BreadcrumbEllipsis.astro +0 -28
  34. package/dist/src/components/breadcrumb/BreadcrumbItem.astro +0 -14
  35. package/dist/src/components/breadcrumb/BreadcrumbLink.astro +0 -22
  36. package/dist/src/components/breadcrumb/BreadcrumbList.astro +0 -16
  37. package/dist/src/components/breadcrumb/BreadcrumbPage.astro +0 -21
  38. package/dist/src/components/breadcrumb/BreadcrumbSeparator.astro +0 -23
  39. package/dist/src/components/breadcrumb/index.ts +0 -37
  40. package/dist/src/components/button/Button.astro +0 -53
  41. package/dist/src/components/button/index.ts +0 -7
  42. package/dist/src/components/card/Card.astro +0 -14
  43. package/dist/src/components/card/CardContent.astro +0 -14
  44. package/dist/src/components/card/CardDescription.astro +0 -14
  45. package/dist/src/components/card/CardFooter.astro +0 -14
  46. package/dist/src/components/card/CardHeader.astro +0 -14
  47. package/dist/src/components/card/CardTitle.astro +0 -14
  48. package/dist/src/components/card/index.ts +0 -26
  49. package/dist/src/components/carousel/Carousel.astro +0 -55
  50. package/dist/src/components/carousel/CarouselContent.astro +0 -26
  51. package/dist/src/components/carousel/CarouselItem.astro +0 -26
  52. package/dist/src/components/carousel/CarouselNext.astro +0 -37
  53. package/dist/src/components/carousel/CarouselPrevious.astro +0 -37
  54. package/dist/src/components/carousel/carousel-script.ts +0 -191
  55. package/dist/src/components/carousel/index.ts +0 -32
  56. package/dist/src/components/checkbox/Checkbox.astro +0 -127
  57. package/dist/src/components/checkbox/index.ts +0 -7
  58. package/dist/src/components/dialog/Dialog.astro +0 -263
  59. package/dist/src/components/dialog/DialogClose.astro +0 -35
  60. package/dist/src/components/dialog/DialogContent.astro +0 -67
  61. package/dist/src/components/dialog/DialogDescription.astro +0 -14
  62. package/dist/src/components/dialog/DialogFooter.astro +0 -14
  63. package/dist/src/components/dialog/DialogHeader.astro +0 -14
  64. package/dist/src/components/dialog/DialogTitle.astro +0 -20
  65. package/dist/src/components/dialog/DialogTrigger.astro +0 -47
  66. package/dist/src/components/dialog/index.ts +0 -45
  67. package/dist/src/components/dropdown/Dropdown.astro +0 -375
  68. package/dist/src/components/dropdown/DropdownContent.astro +0 -81
  69. package/dist/src/components/dropdown/DropdownItem.astro +0 -48
  70. package/dist/src/components/dropdown/DropdownLabel.astro +0 -29
  71. package/dist/src/components/dropdown/DropdownSeparator.astro +0 -21
  72. package/dist/src/components/dropdown/DropdownTrigger.astro +0 -52
  73. package/dist/src/components/dropdown/index.ts +0 -33
  74. package/dist/src/components/dropzone/Dropzone.astro +0 -233
  75. package/dist/src/components/dropzone/DropzoneFilesList.astro +0 -26
  76. package/dist/src/components/dropzone/DropzoneLoadingIndicator.astro +0 -10
  77. package/dist/src/components/dropzone/DropzoneUploadIndicator.astro +0 -10
  78. package/dist/src/components/dropzone/index.ts +0 -24
  79. package/dist/src/components/input/Input.astro +0 -24
  80. package/dist/src/components/input/index.ts +0 -7
  81. package/dist/src/components/item/Item.astro +0 -52
  82. package/dist/src/components/item/ItemActions.astro +0 -16
  83. package/dist/src/components/item/ItemContent.astro +0 -16
  84. package/dist/src/components/item/ItemDescription.astro +0 -19
  85. package/dist/src/components/item/ItemFooter.astro +0 -16
  86. package/dist/src/components/item/ItemGroup.astro +0 -16
  87. package/dist/src/components/item/ItemHeader.astro +0 -16
  88. package/dist/src/components/item/ItemMedia.astro +0 -40
  89. package/dist/src/components/item/ItemSeparator.astro +0 -21
  90. package/dist/src/components/item/ItemTitle.astro +0 -16
  91. package/dist/src/components/item/index.ts +0 -50
  92. package/dist/src/components/kbd/Kbd.astro +0 -21
  93. package/dist/src/components/kbd/KbdGroup.astro +0 -16
  94. package/dist/src/components/kbd/index.ts +0 -11
  95. package/dist/src/components/label/Label.astro +0 -22
  96. package/dist/src/components/label/index.ts +0 -7
  97. package/dist/src/components/pagination/Pagination.astro +0 -20
  98. package/dist/src/components/pagination/PaginationContent.astro +0 -16
  99. package/dist/src/components/pagination/PaginationEllipsis.astro +0 -25
  100. package/dist/src/components/pagination/PaginationItem.astro +0 -16
  101. package/dist/src/components/pagination/PaginationLink.astro +0 -24
  102. package/dist/src/components/pagination/PaginationNext.astro +0 -26
  103. package/dist/src/components/pagination/PaginationPrevious.astro +0 -26
  104. package/dist/src/components/pagination/index.ts +0 -38
  105. package/dist/src/components/progress/Progress.astro +0 -154
  106. package/dist/src/components/progress/index.ts +0 -10
  107. package/dist/src/components/radio-group/RadioGroup.astro +0 -157
  108. package/dist/src/components/radio-group/RadioGroupItem.astro +0 -129
  109. package/dist/src/components/radio-group/RadioGroupTypes.ts +0 -6
  110. package/dist/src/components/radio-group/index.ts +0 -23
  111. package/dist/src/components/select/Select.astro +0 -534
  112. package/dist/src/components/select/SelectContent.astro +0 -83
  113. package/dist/src/components/select/SelectGroup.astro +0 -9
  114. package/dist/src/components/select/SelectItem.astro +0 -49
  115. package/dist/src/components/select/SelectLabel.astro +0 -14
  116. package/dist/src/components/select/SelectSeparator.astro +0 -12
  117. package/dist/src/components/select/SelectTrigger.astro +0 -48
  118. package/dist/src/components/select/SelectTypes.ts +0 -13
  119. package/dist/src/components/select/SelectValue.astro +0 -19
  120. package/dist/src/components/select/index.ts +0 -45
  121. package/dist/src/components/separator/Separator.astro +0 -36
  122. package/dist/src/components/separator/index.ts +0 -7
  123. package/dist/src/components/sheet/Sheet.astro +0 -13
  124. package/dist/src/components/sheet/SheetClose.astro +0 -13
  125. package/dist/src/components/sheet/SheetContent.astro +0 -92
  126. package/dist/src/components/sheet/SheetDescription.astro +0 -16
  127. package/dist/src/components/sheet/SheetFooter.astro +0 -16
  128. package/dist/src/components/sheet/SheetHeader.astro +0 -16
  129. package/dist/src/components/sheet/SheetTitle.astro +0 -16
  130. package/dist/src/components/sheet/SheetTrigger.astro +0 -13
  131. package/dist/src/components/sheet/index.ts +0 -41
  132. package/dist/src/components/skeleton/Skeleton.astro +0 -14
  133. package/dist/src/components/skeleton/index.ts +0 -9
  134. package/dist/src/components/spinner/Spinner.astro +0 -21
  135. package/dist/src/components/spinner/index.ts +0 -7
  136. package/dist/src/components/switch/Switch.astro +0 -191
  137. package/dist/src/components/switch/SwitchTypes.ts +0 -6
  138. package/dist/src/components/switch/index.ts +0 -12
  139. package/dist/src/components/table/Table.astro +0 -18
  140. package/dist/src/components/table/TableBody.astro +0 -16
  141. package/dist/src/components/table/TableCaption.astro +0 -16
  142. package/dist/src/components/table/TableCell.astro +0 -16
  143. package/dist/src/components/table/TableFoot.astro +0 -16
  144. package/dist/src/components/table/TableHead.astro +0 -16
  145. package/dist/src/components/table/TableHeader.astro +0 -16
  146. package/dist/src/components/table/TableRow.astro +0 -16
  147. package/dist/src/components/table/index.ts +0 -42
  148. package/dist/src/components/tabs/Tabs.astro +0 -269
  149. package/dist/src/components/tabs/TabsContent.astro +0 -28
  150. package/dist/src/components/tabs/TabsList.astro +0 -22
  151. package/dist/src/components/tabs/TabsTrigger.astro +0 -34
  152. package/dist/src/components/tabs/index.ts +0 -20
  153. package/dist/src/components/textarea/Textarea.astro +0 -28
  154. package/dist/src/components/textarea/index.ts +0 -9
  155. package/dist/src/components/tooltip/Tooltip.astro +0 -237
  156. package/dist/src/components/tooltip/TooltipContent.astro +0 -114
  157. package/dist/src/components/tooltip/TooltipTrigger.astro +0 -10
  158. package/dist/src/components/tooltip/index.ts +0 -16
@@ -1,37 +0,0 @@
1
- ---
2
- import ArrowLeft from "@tabler/icons/outline/arrow-left.svg";
3
- import type { ComponentProps } from "astro/types";
4
- import { tv } from "tailwind-variants";
5
-
6
- import { Button } from "@/components/starwind/button";
7
-
8
- export const carouselPrevious = tv({
9
- base: [
10
- "starwind-carousel-previous absolute size-8 rounded-full",
11
- // Horizontal positioning
12
- "group-data-[axis=x]/carousel:top-1/2 group-data-[axis=x]/carousel:-left-12 group-data-[axis=x]/carousel:-translate-y-1/2",
13
- // Vertical positioning
14
- "group-data-[axis=y]/carousel:-top-12 group-data-[axis=y]/carousel:left-1/2 group-data-[axis=y]/carousel:-translate-x-1/2 group-data-[axis=y]/carousel:rotate-90",
15
- ],
16
- });
17
-
18
- type Props = ComponentProps<typeof Button>;
19
-
20
- const { class: className = "", variant = "outline", size = "icon", ...rest } = Astro.props;
21
- ---
22
-
23
- <Button
24
- data-slot="carousel-previous"
25
- variant={variant}
26
- size={size}
27
- class={carouselPrevious({ class: className })}
28
- aria-label="Previous slide"
29
- {...rest}
30
- >
31
- <slot name="icon">
32
- <ArrowLeft />
33
- </slot>
34
- <slot>
35
- <span class="sr-only">Previous slide</span>
36
- </slot>
37
- </Button>
@@ -1,191 +0,0 @@
1
- import EmblaCarousel, {
2
- type EmblaCarouselType,
3
- type EmblaEventType,
4
- type EmblaOptionsType,
5
- type EmblaPluginType,
6
- } from "embla-carousel";
7
-
8
- export type CarouselApi = EmblaCarouselType;
9
-
10
- export interface CarouselOptions {
11
- opts?: EmblaOptionsType;
12
- plugins?: EmblaPluginType[];
13
- setApi?: (api: CarouselApi) => void;
14
- }
15
-
16
- export interface CarouselManager {
17
- api: CarouselApi;
18
- scrollPrev: () => void;
19
- scrollNext: () => void;
20
- canScrollPrev: () => boolean;
21
- canScrollNext: () => boolean;
22
- destroy: () => void;
23
- }
24
-
25
- export function initCarousel(
26
- carouselElement: HTMLElement,
27
- options: CarouselOptions = {},
28
- ): CarouselManager | null {
29
- // don't re-initialize if already initialized
30
- if (carouselElement.dataset.initialized === "true") return null;
31
- carouselElement.dataset.initialized = "true";
32
-
33
- if (!carouselElement) {
34
- console.warn("Carousel element not found");
35
- return null;
36
- }
37
-
38
- // Find content element - Embla expects the viewport element, not the container
39
- const viewportElement = carouselElement.querySelector(
40
- '[data-slot="carousel-content"]',
41
- ) as HTMLElement;
42
- if (!viewportElement) {
43
- console.warn("Carousel content element not found");
44
- return null;
45
- }
46
-
47
- // Get configuration from data attributes
48
- const axisData = carouselElement.dataset.axis;
49
- const axis: EmblaOptionsType["axis"] = axisData === "y" ? "y" : "x";
50
-
51
- // Safely parse data options
52
- let dataOpts = {};
53
- try {
54
- const optsString = carouselElement.dataset.opts;
55
- if (optsString && optsString !== "undefined" && optsString !== "null") {
56
- dataOpts = JSON.parse(optsString);
57
- }
58
- } catch (e) {
59
- console.warn("Failed to parse carousel opts:", e);
60
- dataOpts = {};
61
- }
62
-
63
- // Ensure dataOpts is a valid object
64
- if (!dataOpts || typeof dataOpts !== "object") {
65
- dataOpts = {};
66
- }
67
-
68
- // Merge options - ensure we always have a valid object
69
- const emblaOptions: EmblaOptionsType = {
70
- axis,
71
- ...dataOpts,
72
- ...(options.opts || {}),
73
- };
74
-
75
- // Handle plugins - EmblaCarousel expects undefined when no plugins, not empty array
76
- const plugins = options.plugins && options.plugins.length > 0 ? options.plugins : undefined;
77
-
78
- // console.log("ID:", carouselElement.id);
79
- // console.log("Plugins:", plugins);
80
- // console.log("Options:", emblaOptions);
81
-
82
- // Find navigation buttons
83
- const prevButton = carouselElement.querySelector(
84
- '[data-slot="carousel-previous"]',
85
- ) as HTMLButtonElement;
86
- const nextButton = carouselElement.querySelector(
87
- '[data-slot="carousel-next"]',
88
- ) as HTMLButtonElement;
89
-
90
- // Initialize Embla
91
- let emblaApi: EmblaCarouselType;
92
- if (plugins) {
93
- emblaApi = EmblaCarousel(viewportElement, emblaOptions, plugins);
94
- } else {
95
- emblaApi = EmblaCarousel(viewportElement, emblaOptions);
96
- }
97
-
98
- // Update button states
99
- const updateButtons = () => {
100
- const canScrollPrev = emblaApi.canScrollPrev();
101
- const canScrollNext = emblaApi.canScrollNext();
102
-
103
- if (prevButton) {
104
- prevButton.disabled = !canScrollPrev;
105
- prevButton.setAttribute("aria-disabled", (!canScrollPrev).toString());
106
- }
107
-
108
- if (nextButton) {
109
- nextButton.disabled = !canScrollNext;
110
- nextButton.setAttribute("aria-disabled", (!canScrollNext).toString());
111
- }
112
- };
113
-
114
- // Event handlers for cleanup
115
- const prevClickHandler = () => emblaApi.scrollPrev();
116
- const nextClickHandler = () => emblaApi.scrollNext();
117
- const keydownHandler = (event: KeyboardEvent) => {
118
- if (axis === "y") {
119
- // Vertical axis: ArrowUp = previous, ArrowDown = next
120
- if (event.key === "ArrowUp") {
121
- event.preventDefault();
122
- emblaApi.scrollPrev();
123
- } else if (event.key === "ArrowDown") {
124
- event.preventDefault();
125
- emblaApi.scrollNext();
126
- }
127
- } else {
128
- // Horizontal axis (default): ArrowLeft = previous, ArrowRight = next
129
- if (event.key === "ArrowLeft") {
130
- event.preventDefault();
131
- emblaApi.scrollPrev();
132
- } else if (event.key === "ArrowRight") {
133
- event.preventDefault();
134
- emblaApi.scrollNext();
135
- }
136
- }
137
- };
138
-
139
- // Setup event listeners
140
- const setupEventListeners = () => {
141
- // Navigation button listeners
142
- prevButton?.addEventListener("click", prevClickHandler);
143
- nextButton?.addEventListener("click", nextClickHandler);
144
-
145
- // Keyboard navigation
146
- carouselElement.addEventListener("keydown", keydownHandler);
147
- };
148
-
149
- // Setup user API callback
150
- const setupUserCallbacks = () => {
151
- if (options.setApi) {
152
- options.setApi(emblaApi);
153
- }
154
- };
155
-
156
- // Initialize everything
157
- updateButtons();
158
- setupEventListeners();
159
- setupUserCallbacks();
160
-
161
- // Setup internal event listeners
162
- emblaApi.on("select", updateButtons);
163
- emblaApi.on("init", () => {
164
- updateButtons();
165
- });
166
- emblaApi.on("reInit", () => {
167
- updateButtons();
168
- });
169
-
170
- // Return manager interface
171
- return {
172
- api: emblaApi,
173
- scrollPrev: () => emblaApi.scrollPrev(),
174
- scrollNext: () => emblaApi.scrollNext(),
175
- canScrollPrev: () => emblaApi.canScrollPrev(),
176
- canScrollNext: () => emblaApi.canScrollNext(),
177
- destroy: () => {
178
- // Remove event listeners to prevent memory leaks
179
- if (prevButton) {
180
- prevButton.removeEventListener("click", prevClickHandler);
181
- }
182
- if (nextButton) {
183
- nextButton.removeEventListener("click", nextClickHandler);
184
- }
185
- carouselElement.removeEventListener("keydown", keydownHandler);
186
-
187
- // Destroy the Embla instance
188
- emblaApi.destroy();
189
- },
190
- };
191
- }
@@ -1,32 +0,0 @@
1
- import Carousel from "./Carousel.astro";
2
- import {
3
- type CarouselApi,
4
- type CarouselManager,
5
- type CarouselOptions,
6
- initCarousel,
7
- } from "./carousel-script";
8
- import CarouselContent from "./CarouselContent.astro";
9
- import CarouselItem from "./CarouselItem.astro";
10
- import CarouselNext from "./CarouselNext.astro";
11
- import CarouselPrevious from "./CarouselPrevious.astro";
12
-
13
- export {
14
- Carousel,
15
- type CarouselApi,
16
- CarouselContent,
17
- CarouselItem,
18
- type CarouselManager,
19
- CarouselNext,
20
- type CarouselOptions,
21
- CarouselPrevious,
22
- initCarousel,
23
- };
24
-
25
- export default {
26
- Root: Carousel,
27
- Content: CarouselContent,
28
- Item: CarouselItem,
29
- Next: CarouselNext,
30
- Previous: CarouselPrevious,
31
- init: initCarousel,
32
- };
@@ -1,127 +0,0 @@
1
- ---
2
- import Check from "@tabler/icons/outline/check.svg";
3
- import type { HTMLAttributes } from "astro/types";
4
- import { tv, type VariantProps } from "tailwind-variants";
5
-
6
- type Props = Omit<HTMLAttributes<"input">, "type"> &
7
- VariantProps<typeof checkbox> & {
8
- /**
9
- * Optional label text to display next to the checkbox
10
- */
11
- label?: string;
12
- };
13
-
14
- export const checkbox = tv({
15
- slots: {
16
- base: "starwind-checkbox relative flex items-center space-x-2",
17
- input: [
18
- "peer border-input bg-background dark:bg-input/30 shrink-0 transform-gpu rounded-sm border",
19
- "transition-all focus-visible:ring-3",
20
- "outline-0 focus:ring-0 focus:ring-offset-0",
21
- "not-disabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-50",
22
- ],
23
- icon: [
24
- "pointer-events-none absolute stroke-3 p-0.5 opacity-0 transition-opacity peer-checked:opacity-100",
25
- "starwind-check-icon",
26
- ],
27
- label:
28
- "font-medium peer-not-disabled:cursor-pointer peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
29
- },
30
- variants: {
31
- size: {
32
- sm: { input: "size-4", icon: "size-4", label: "text-sm" },
33
- md: { input: "size-5", icon: "size-5", label: "text-base" },
34
- lg: { input: "size-6", icon: "size-6", label: "text-lg" },
35
- },
36
- variant: {
37
- default: {
38
- input: "checked:bg-foreground focus-visible:ring-outline/50 focus-visible:border-outline",
39
- icon: "text-background",
40
- },
41
- primary: {
42
- input:
43
- "checked:bg-primary checked:border-primary focus-visible:ring-primary/50 focus-visible:border-primary",
44
- icon: "text-primary-foreground",
45
- },
46
- secondary: {
47
- input:
48
- "checked:bg-secondary checked:border-secondary focus-visible:ring-secondary/50 focus-visible:border-secondary",
49
- icon: "text-secondary-foreground",
50
- },
51
- info: {
52
- input:
53
- "checked:bg-info checked:border-info focus-visible:ring-info/50 focus-visible:border-info",
54
- icon: "text-info-foreground",
55
- },
56
- success: {
57
- input:
58
- "checked:bg-success checked:border-success focus-visible:ring-success/50 focus-visible:border-success",
59
- icon: "text-success-foreground",
60
- },
61
- warning: {
62
- input:
63
- "checked:bg-warning checked:border-warning focus-visible:ring-warning/50 focus-visible:border-warning",
64
- icon: "text-warning-foreground",
65
- },
66
- error: {
67
- input:
68
- "checked:bg-error checked:border-error focus-visible:ring-error/50 focus-visible:border-error",
69
- icon: "text-error-foreground",
70
- },
71
- },
72
- },
73
- defaultVariants: { size: "md", variant: "default" },
74
- });
75
-
76
- const { id, label, checked, size, variant, class: className, ...rest } = Astro.props;
77
-
78
- const { base, input, icon, label: labelClass } = checkbox({ size, variant });
79
- ---
80
-
81
- <div class={base()}>
82
- <input
83
- type="checkbox"
84
- id={id}
85
- class={input({ class: className })}
86
- data-slot="checkbox-input"
87
- {checked}
88
- {...rest}
89
- />
90
- <Check class={icon()} />
91
- {
92
- label && (
93
- <label for={id} class={labelClass()} data-slot="checkbox-label">
94
- {label}
95
- </label>
96
- )
97
- }
98
- </div>
99
-
100
- <style>
101
- .starwind-checkbox input[type="checkbox"]:checked {
102
- background-image: none;
103
- }
104
-
105
- /* Check drawing animation */
106
- .starwind-check-icon {
107
- stroke-dasharray: 65;
108
- stroke-dashoffset: 65;
109
- opacity: 0;
110
- }
111
-
112
- .starwind-checkbox input[type="checkbox"]:checked + .starwind-check-icon {
113
- animation: draw-check 0.3s ease forwards;
114
- animation-delay: 0.15s;
115
- }
116
-
117
- @keyframes draw-check {
118
- 0% {
119
- stroke-dashoffset: 65;
120
- opacity: 1;
121
- }
122
- 100% {
123
- stroke-dashoffset: 0;
124
- opacity: 1;
125
- }
126
- }
127
- </style>
@@ -1,7 +0,0 @@
1
- import Checkbox, { checkbox } from "./Checkbox.astro";
2
-
3
- const CheckboxVariants = { checkbox };
4
-
5
- export { Checkbox, CheckboxVariants };
6
-
7
- export default Checkbox;
@@ -1,263 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
-
4
- type Props = HTMLAttributes<"div">;
5
-
6
- const { class: className, ...rest } = Astro.props;
7
- ---
8
-
9
- <div class:list={["starwind-dialog", className]} data-slot="dialog" {...rest}>
10
- <slot />
11
- </div>
12
-
13
- <script>
14
- class DialogHandler {
15
- private triggers: HTMLButtonElement[] = [];
16
- private dialog: HTMLDialogElement | null = null;
17
- private closeButtons: HTMLButtonElement[] = [];
18
- private backdrop: HTMLElement | null = null;
19
- private dialogId: string;
20
- /**
21
- * The duration of the animation in milliseconds. This is used to calculate the
22
- * duration of close animation before hiding the dialog and backdrop
23
- */
24
- private animationDuration: number;
25
-
26
- constructor(dialogWrapper: HTMLElement, dialogNumber: number) {
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
- }
32
-
33
- // if no ID was provided for the wrapper, generate one
34
- if (dialogWrapper.id) {
35
- this.dialogId = dialogWrapper.id;
36
- } else {
37
- this.dialogId = `starwind-dialog${dialogNumber}`;
38
- dialogWrapper.id = this.dialogId;
39
- }
40
-
41
- // animationDuration is set with inline styles through passed prop to DialogContent
42
- // if no animationDuration, check data-close-duration
43
- const animationDurationString = this.dialog.style.animationDuration;
44
- if (animationDurationString.endsWith("ms")) {
45
- this.animationDuration = parseFloat(animationDurationString);
46
- } else if (animationDurationString.endsWith("s")) {
47
- // using something like @playform/compress might optimize to use "s" instead of "ms"
48
- this.animationDuration = parseFloat(animationDurationString) * 1000;
49
- } else {
50
- this.animationDuration = this.dialog.dataset.closeDuration
51
- ? parseFloat(this.dialog.dataset.closeDuration)
52
- : 200;
53
- }
54
-
55
- // Find internal triggers and handle them
56
- const internalTriggers = dialogWrapper.querySelectorAll(".starwind-dialog-trigger");
57
- internalTriggers.forEach((triggerElement) => {
58
- const tempTrigger = triggerElement as HTMLElement;
59
- let trigger: HTMLButtonElement;
60
-
61
- if (tempTrigger?.hasAttribute("data-as-child")) {
62
- trigger = tempTrigger.firstElementChild as HTMLButtonElement;
63
- } else {
64
- trigger = tempTrigger as HTMLButtonElement;
65
- }
66
-
67
- if (trigger) {
68
- this.triggers.push(trigger);
69
- }
70
- });
71
-
72
- // Find external triggers that target this dialog
73
- this.findExternalTriggers();
74
-
75
- // if closeButtons are set with asChild, swap the wrapper with its first child
76
- const tempCloseButtons = dialogWrapper.querySelectorAll(
77
- ".starwind-dialog-close",
78
- ) as NodeListOf<HTMLElement>;
79
- tempCloseButtons.forEach((button: HTMLElement) => {
80
- if (button.hasAttribute("data-as-child")) {
81
- const childElement = button.firstElementChild;
82
- if (childElement) {
83
- childElement.classList.add("starwind-dialog-close");
84
- button.parentNode?.replaceChild(childElement, button);
85
- }
86
- }
87
- return button;
88
- });
89
-
90
- // Convert NodeList to Array for consistency with triggers
91
- this.closeButtons = Array.from(
92
- dialogWrapper.querySelectorAll(".starwind-dialog-close"),
93
- ) as HTMLButtonElement[];
94
-
95
- // if essential elements are not there, exit
96
- if (!this.dialog || !this.backdrop) return;
97
-
98
- this.setupAccessibility(dialogNumber);
99
- this.setupEvents();
100
- }
101
-
102
- private setupAccessibility(dialogNumber: number): void {
103
- // get the first heading element in the dialog
104
- const firstHeading = this.dialog?.querySelector("h1, h2, h3, h4, h5, h6");
105
- if (firstHeading) {
106
- // create a unique ID for the heading
107
- firstHeading.id = `starwind-dialog${dialogNumber}-heading`;
108
- // set the aria-labelledby attribute to the first heading element
109
- this.dialog?.setAttribute("aria-labelledby", firstHeading.id);
110
- }
111
- }
112
-
113
- /**
114
- * Find all external triggers that target this dialog
115
- */
116
- private findExternalTriggers(): void {
117
- const externalTriggers = document.querySelectorAll(
118
- `.starwind-dialog-trigger[data-dialog-for="${this.dialogId}"]`,
119
- );
120
-
121
- externalTriggers.forEach((triggerElement) => {
122
- // Skip if this is an internal trigger we already processed
123
- const dialogWrapper = triggerElement.closest(".starwind-dialog");
124
- if (dialogWrapper && dialogWrapper.id === this.dialogId) {
125
- return;
126
- }
127
-
128
- let trigger: HTMLButtonElement;
129
- if (triggerElement.hasAttribute("data-as-child")) {
130
- trigger = triggerElement.firstElementChild as HTMLButtonElement;
131
- } else {
132
- trigger = triggerElement as HTMLButtonElement;
133
- }
134
-
135
- if (trigger && !this.triggers.includes(trigger)) {
136
- this.triggers.push(trigger);
137
- }
138
- });
139
- }
140
-
141
- private setupEvents(): void {
142
- if (!this.dialog) return;
143
- // Add click listeners to all triggers
144
- this.triggers.forEach((trigger) => {
145
- trigger.addEventListener("click", () => {
146
- this.open();
147
- });
148
- });
149
-
150
- // Add click handlers to all close buttons
151
- this.closeButtons?.forEach((button) => {
152
- button.addEventListener("click", () => {
153
- // Only close if this is the topmost dialog
154
- const openDialogs = document.querySelectorAll("dialog[open]");
155
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
156
- this.close();
157
- }
158
- });
159
- });
160
-
161
- // Close on click outside
162
- this.dialog.addEventListener("click", (e) => {
163
- if (!this.dialog) return;
164
- const dialogDimensions = this.dialog.getBoundingClientRect();
165
- const clickedInDialog =
166
- e.clientX >= dialogDimensions.left &&
167
- e.clientX <= dialogDimensions.right &&
168
- e.clientY >= dialogDimensions.top &&
169
- e.clientY <= dialogDimensions.bottom;
170
-
171
- if (!clickedInDialog) {
172
- // Only close if this is the topmost dialog
173
- const openDialogs = document.querySelectorAll("dialog[open]");
174
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
175
- this.close();
176
- }
177
- }
178
- });
179
-
180
- // Handle escape key
181
- this.dialog.addEventListener("keydown", (e) => {
182
- if (e.key === "Escape") {
183
- // prevent default dialog closing behavior so we can add closing animation
184
- e.preventDefault();
185
- // Only close if this is the topmost dialog
186
- const openDialogs = document.querySelectorAll("dialog[open]");
187
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
188
- this.close();
189
- }
190
- }
191
- });
192
-
193
- // Intercept form submissions to handle dialog close
194
- const forms = this.dialog.querySelectorAll("form");
195
- forms.forEach((form) => {
196
- form.addEventListener("submit", (e) => {
197
- /**
198
- * Default form.method = "dialog" submissions cause the dialog to close
199
- * Default form.method = "post" submissions do not close the dialog
200
- * Here we intercept the form submission and manage the dialog closing if method = "dialog"
201
- * so we can add closing animation
202
- * Normal form event listeners for "submit" will still get the form data
203
- */
204
- if (form.method === "dialog") {
205
- e.preventDefault();
206
- // Only close if this is the topmost dialog
207
- const openDialogs = document.querySelectorAll("dialog[open]");
208
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
209
- this.close();
210
- }
211
- }
212
- });
213
- });
214
- }
215
-
216
- private open(): void {
217
- if (!this.dialog || !this.backdrop) return;
218
- this.dialog.showModal();
219
- document.body.classList.add("overflow-hidden");
220
- this.backdrop.classList.remove("hidden");
221
- this.backdrop.dataset.state = "open";
222
- this.dialog.dataset.state = "open";
223
- }
224
-
225
- private close(): void {
226
- if (!this.dialog || !this.backdrop) return;
227
- this.dialog.dataset.state = "closed";
228
- this.backdrop.dataset.state = "closed";
229
-
230
- // Wait for animation to finish before hiding backdrop
231
- setTimeout(() => {
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
- }
238
- }, this.animationDuration);
239
- }
240
- }
241
-
242
- // Store instances in a WeakMap to avoid memory leaks
243
- const dialogInstances = new WeakMap<HTMLElement, DialogHandler>();
244
-
245
- // Initialize all dialogs
246
- const setupDialogs = () => {
247
- document.querySelectorAll(".starwind-dialog").forEach((dialogWrapper, idx) => {
248
- const wrapper = dialogWrapper as HTMLElement;
249
- if (!dialogInstances.has(wrapper)) {
250
- dialogInstances.set(wrapper, new DialogHandler(wrapper, idx));
251
- }
252
- });
253
- };
254
-
255
- setupDialogs();
256
- document.addEventListener("astro:after-swap", setupDialogs);
257
- </script>
258
-
259
- <style>
260
- .overflow-hidden {
261
- overflow: hidden;
262
- }
263
- </style>
@@ -1,35 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
-
4
- type Props = HTMLAttributes<"button"> & {
5
- /**
6
- * When true, the component will render its child element instead of a button
7
- */
8
- asChild?: boolean;
9
- };
10
-
11
- const { class: className, asChild = false, ...rest } = Astro.props;
12
-
13
- // Get the first child element if asChild is true
14
- let hasChildren = false;
15
- if (Astro.slots.has("default")) {
16
- hasChildren = true;
17
- }
18
- ---
19
-
20
- {
21
- asChild && hasChildren ? (
22
- <div class="starwind-dialog-close" data-slot="dialog-close" data-as-child>
23
- <slot />
24
- </div>
25
- ) : (
26
- <button
27
- type="button"
28
- class:list={["starwind-dialog-close", className]}
29
- data-slot="dialog-close"
30
- {...rest}
31
- >
32
- <slot>Demo close button</slot>
33
- </button>
34
- )
35
- }