@starwind-ui/core 1.14.0 → 1.15.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 (179) hide show
  1. package/package.json +1 -1
  2. package/dist/index.d.ts +0 -28
  3. package/dist/index.js +0 -85
  4. package/dist/index.js.map +0 -1
  5. package/dist/src/components/accordion/Accordion.astro +0 -254
  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 -275
  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 -49
  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 -54
  41. package/dist/src/components/button/index.ts +0 -7
  42. package/dist/src/components/button-group/ButtonGroup.astro +0 -62
  43. package/dist/src/components/button-group/ButtonGroupSeparator.astro +0 -27
  44. package/dist/src/components/button-group/ButtonGroupText.astro +0 -19
  45. package/dist/src/components/button-group/index.ts +0 -17
  46. package/dist/src/components/card/Card.astro +0 -14
  47. package/dist/src/components/card/CardContent.astro +0 -14
  48. package/dist/src/components/card/CardDescription.astro +0 -14
  49. package/dist/src/components/card/CardFooter.astro +0 -14
  50. package/dist/src/components/card/CardHeader.astro +0 -14
  51. package/dist/src/components/card/CardTitle.astro +0 -14
  52. package/dist/src/components/card/index.ts +0 -26
  53. package/dist/src/components/carousel/Carousel.astro +0 -55
  54. package/dist/src/components/carousel/CarouselContent.astro +0 -26
  55. package/dist/src/components/carousel/CarouselItem.astro +0 -26
  56. package/dist/src/components/carousel/CarouselNext.astro +0 -37
  57. package/dist/src/components/carousel/CarouselPrevious.astro +0 -37
  58. package/dist/src/components/carousel/carousel-script.ts +0 -191
  59. package/dist/src/components/carousel/index.ts +0 -32
  60. package/dist/src/components/checkbox/Checkbox.astro +0 -128
  61. package/dist/src/components/checkbox/index.ts +0 -7
  62. package/dist/src/components/dialog/Dialog.astro +0 -355
  63. package/dist/src/components/dialog/DialogClose.astro +0 -35
  64. package/dist/src/components/dialog/DialogContent.astro +0 -78
  65. package/dist/src/components/dialog/DialogDescription.astro +0 -14
  66. package/dist/src/components/dialog/DialogFooter.astro +0 -14
  67. package/dist/src/components/dialog/DialogHeader.astro +0 -14
  68. package/dist/src/components/dialog/DialogTitle.astro +0 -22
  69. package/dist/src/components/dialog/DialogTrigger.astro +0 -47
  70. package/dist/src/components/dialog/index.ts +0 -45
  71. package/dist/src/components/dropdown/Dropdown.astro +0 -377
  72. package/dist/src/components/dropdown/DropdownContent.astro +0 -81
  73. package/dist/src/components/dropdown/DropdownItem.astro +0 -48
  74. package/dist/src/components/dropdown/DropdownLabel.astro +0 -29
  75. package/dist/src/components/dropdown/DropdownSeparator.astro +0 -21
  76. package/dist/src/components/dropdown/DropdownTrigger.astro +0 -52
  77. package/dist/src/components/dropdown/index.ts +0 -33
  78. package/dist/src/components/dropzone/Dropzone.astro +0 -236
  79. package/dist/src/components/dropzone/DropzoneFilesList.astro +0 -26
  80. package/dist/src/components/dropzone/DropzoneLoadingIndicator.astro +0 -10
  81. package/dist/src/components/dropzone/DropzoneUploadIndicator.astro +0 -10
  82. package/dist/src/components/dropzone/index.ts +0 -24
  83. package/dist/src/components/image/Image.astro +0 -24
  84. package/dist/src/components/image/index.ts +0 -9
  85. package/dist/src/components/input/Input.astro +0 -25
  86. package/dist/src/components/input/index.ts +0 -7
  87. package/dist/src/components/item/Item.astro +0 -52
  88. package/dist/src/components/item/ItemActions.astro +0 -16
  89. package/dist/src/components/item/ItemContent.astro +0 -16
  90. package/dist/src/components/item/ItemDescription.astro +0 -19
  91. package/dist/src/components/item/ItemFooter.astro +0 -16
  92. package/dist/src/components/item/ItemGroup.astro +0 -16
  93. package/dist/src/components/item/ItemHeader.astro +0 -16
  94. package/dist/src/components/item/ItemMedia.astro +0 -40
  95. package/dist/src/components/item/ItemSeparator.astro +0 -21
  96. package/dist/src/components/item/ItemTitle.astro +0 -16
  97. package/dist/src/components/item/index.ts +0 -50
  98. package/dist/src/components/kbd/Kbd.astro +0 -21
  99. package/dist/src/components/kbd/KbdGroup.astro +0 -16
  100. package/dist/src/components/kbd/index.ts +0 -11
  101. package/dist/src/components/label/Label.astro +0 -22
  102. package/dist/src/components/label/index.ts +0 -7
  103. package/dist/src/components/pagination/Pagination.astro +0 -20
  104. package/dist/src/components/pagination/PaginationContent.astro +0 -16
  105. package/dist/src/components/pagination/PaginationEllipsis.astro +0 -35
  106. package/dist/src/components/pagination/PaginationItem.astro +0 -16
  107. package/dist/src/components/pagination/PaginationLink.astro +0 -24
  108. package/dist/src/components/pagination/PaginationNext.astro +0 -30
  109. package/dist/src/components/pagination/PaginationPrevious.astro +0 -30
  110. package/dist/src/components/pagination/index.ts +0 -38
  111. package/dist/src/components/progress/Progress.astro +0 -155
  112. package/dist/src/components/progress/index.ts +0 -10
  113. package/dist/src/components/radio-group/RadioGroup.astro +0 -162
  114. package/dist/src/components/radio-group/RadioGroupItem.astro +0 -129
  115. package/dist/src/components/radio-group/RadioGroupTypes.ts +0 -6
  116. package/dist/src/components/radio-group/index.ts +0 -23
  117. package/dist/src/components/select/Select.astro +0 -751
  118. package/dist/src/components/select/SelectContent.astro +0 -94
  119. package/dist/src/components/select/SelectGroup.astro +0 -9
  120. package/dist/src/components/select/SelectItem.astro +0 -51
  121. package/dist/src/components/select/SelectLabel.astro +0 -14
  122. package/dist/src/components/select/SelectSearch.astro +0 -49
  123. package/dist/src/components/select/SelectSeparator.astro +0 -12
  124. package/dist/src/components/select/SelectTrigger.astro +0 -54
  125. package/dist/src/components/select/SelectTypes.ts +0 -13
  126. package/dist/src/components/select/SelectValue.astro +0 -19
  127. package/dist/src/components/select/index.ts +0 -49
  128. package/dist/src/components/separator/Separator.astro +0 -36
  129. package/dist/src/components/separator/index.ts +0 -7
  130. package/dist/src/components/sheet/Sheet.astro +0 -13
  131. package/dist/src/components/sheet/SheetClose.astro +0 -13
  132. package/dist/src/components/sheet/SheetContent.astro +0 -92
  133. package/dist/src/components/sheet/SheetDescription.astro +0 -16
  134. package/dist/src/components/sheet/SheetFooter.astro +0 -16
  135. package/dist/src/components/sheet/SheetHeader.astro +0 -16
  136. package/dist/src/components/sheet/SheetTitle.astro +0 -16
  137. package/dist/src/components/sheet/SheetTrigger.astro +0 -13
  138. package/dist/src/components/sheet/index.ts +0 -41
  139. package/dist/src/components/skeleton/Skeleton.astro +0 -14
  140. package/dist/src/components/skeleton/index.ts +0 -9
  141. package/dist/src/components/slider/Slider.astro +0 -411
  142. package/dist/src/components/slider/index.ts +0 -9
  143. package/dist/src/components/spinner/Spinner.astro +0 -21
  144. package/dist/src/components/spinner/index.ts +0 -7
  145. package/dist/src/components/switch/Switch.astro +0 -192
  146. package/dist/src/components/switch/SwitchTypes.ts +0 -6
  147. package/dist/src/components/switch/index.ts +0 -12
  148. package/dist/src/components/table/Table.astro +0 -18
  149. package/dist/src/components/table/TableBody.astro +0 -16
  150. package/dist/src/components/table/TableCaption.astro +0 -16
  151. package/dist/src/components/table/TableCell.astro +0 -16
  152. package/dist/src/components/table/TableFoot.astro +0 -16
  153. package/dist/src/components/table/TableHead.astro +0 -16
  154. package/dist/src/components/table/TableHeader.astro +0 -16
  155. package/dist/src/components/table/TableRow.astro +0 -16
  156. package/dist/src/components/table/index.ts +0 -42
  157. package/dist/src/components/tabs/Tabs.astro +0 -271
  158. package/dist/src/components/tabs/TabsContent.astro +0 -28
  159. package/dist/src/components/tabs/TabsList.astro +0 -22
  160. package/dist/src/components/tabs/TabsTrigger.astro +0 -34
  161. package/dist/src/components/tabs/index.ts +0 -20
  162. package/dist/src/components/textarea/Textarea.astro +0 -29
  163. package/dist/src/components/textarea/index.ts +0 -9
  164. package/dist/src/components/toast/ToastDescription.astro +0 -21
  165. package/dist/src/components/toast/ToastItem.astro +0 -54
  166. package/dist/src/components/toast/ToastTemplate.astro +0 -25
  167. package/dist/src/components/toast/ToastTitle.astro +0 -57
  168. package/dist/src/components/toast/Toaster.astro +0 -982
  169. package/dist/src/components/toast/index.ts +0 -29
  170. package/dist/src/components/toast/toast-manager.ts +0 -216
  171. package/dist/src/components/toggle/Toggle.astro +0 -174
  172. package/dist/src/components/toggle/ToggleTypes.ts +0 -14
  173. package/dist/src/components/toggle/index.ts +0 -8
  174. package/dist/src/components/tooltip/Tooltip.astro +0 -239
  175. package/dist/src/components/tooltip/TooltipContent.astro +0 -114
  176. package/dist/src/components/tooltip/TooltipTrigger.astro +0 -10
  177. package/dist/src/components/tooltip/index.ts +0 -16
  178. package/dist/src/components/video/Video.astro +0 -120
  179. package/dist/src/components/video/index.ts +0 -9
@@ -1,29 +0,0 @@
1
- import type { PromiseOptions, PromiseStateOption, ToastOptions, Variant } from "./toast-manager";
2
- import { toast } from "./toast-manager";
3
- import ToastDescription from "./ToastDescription.astro";
4
- import Toaster from "./Toaster.astro";
5
- import ToastItem from "./ToastItem.astro";
6
- import ToastTemplate from "./ToastTemplate.astro";
7
- import ToastTitle from "./ToastTitle.astro";
8
-
9
- export {
10
- type PromiseOptions,
11
- type PromiseStateOption,
12
- toast,
13
- ToastDescription,
14
- Toaster,
15
- ToastItem,
16
- type ToastOptions,
17
- ToastTemplate,
18
- ToastTitle,
19
- type Variant,
20
- };
21
-
22
- export default {
23
- Manager: toast,
24
- Viewport: Toaster,
25
- Item: ToastItem,
26
- Title: ToastTitle,
27
- Description: ToastDescription,
28
- Template: ToastTemplate,
29
- };
@@ -1,216 +0,0 @@
1
- /**
2
- * Starwind Toast API
3
- *
4
- * A simple, framework-agnostic toast notification system.
5
- *
6
- * @example
7
- * ```ts
8
- * import { toast } from "@/components/starwind/toast";
9
- *
10
- * // Simple usage
11
- * toast("Hello world");
12
- * toast({ title: "Success", description: "Item saved" });
13
- *
14
- * // Variant shortcuts
15
- * toast.success("Saved successfully");
16
- * toast.error("Something went wrong");
17
- * toast.warning("Please check your input");
18
- * toast.info("New update available");
19
- * toast.loading("Processing...");
20
- *
21
- * // Promise handling
22
- * toast.promise(saveData(), {
23
- * loading: "Saving...",
24
- * success: "Saved!",
25
- * error: "Failed to save",
26
- * });
27
- *
28
- * // Management
29
- * const id = toast("Processing...");
30
- * toast.update(id, { title: "Almost done..." });
31
- * toast.dismiss(id);
32
- * toast.dismiss(); // dismiss all
33
- * ```
34
- */
35
-
36
- export type Variant = "default" | "success" | "error" | "warning" | "info" | "loading";
37
-
38
- export interface ToastOptions {
39
- id?: string;
40
- title?: string;
41
- description?: string;
42
- variant?: Variant;
43
- /** Duration in ms. Set to 0 for infinite (no auto-dismiss). */
44
- duration?: number;
45
- /** Callback when toast close animation starts */
46
- onClose?: () => void;
47
- /** Callback when toast is removed from DOM */
48
- onRemove?: () => void;
49
- action?: {
50
- label: string;
51
- onClick: () => void;
52
- };
53
- }
54
-
55
- export interface PromiseStateOption {
56
- title?: string;
57
- description?: string;
58
- duration?: number;
59
- }
60
-
61
- export type PromiseStateValue<T> =
62
- | string
63
- | PromiseStateOption
64
- | ((data: T) => string | PromiseStateOption);
65
-
66
- export interface PromiseOptions<T, E = Error> {
67
- loading: string | PromiseStateOption;
68
- success: PromiseStateValue<T>;
69
- error: PromiseStateValue<E>;
70
- }
71
-
72
- interface ToastManager {
73
- add(options: ToastOptions): string;
74
- update(id: string, options: Partial<ToastOptions>): void;
75
- close(id: string): void;
76
- closeAll(): void;
77
- }
78
-
79
- /**
80
- * Get the toast manager instance from the window
81
- */
82
- function getManager(): ToastManager | null {
83
- if (typeof window === "undefined") return null;
84
- return (window as any).__starwind__.toast as ToastManager | null;
85
- }
86
-
87
- /**
88
- * Normalize a string or options object to ToastOptions
89
- */
90
- function normalizeOption<T>(
91
- value: string | PromiseStateOption | ((data: T) => string | PromiseStateOption),
92
- data?: T,
93
- ): Omit<ToastOptions, "variant"> {
94
- const resolved = typeof value === "function" ? value(data as T) : value;
95
- if (typeof resolved === "string") {
96
- return { title: resolved };
97
- }
98
- return resolved;
99
- }
100
-
101
- /**
102
- * Create a toast notification
103
- */
104
- function createToast(
105
- messageOrOptions: string | ToastOptions,
106
- extraOptions?: Omit<ToastOptions, "title">,
107
- ): string {
108
- let options: ToastOptions;
109
- if (typeof messageOrOptions === "string") {
110
- options = { title: messageOrOptions, ...extraOptions };
111
- } else {
112
- options = messageOrOptions;
113
- }
114
-
115
- const manager = getManager();
116
- if (manager) {
117
- return manager.add(options);
118
- }
119
-
120
- console.warn("Toast: No Toaster found. Add <Toaster /> to your layout.");
121
- return "";
122
- }
123
-
124
- /**
125
- * Create a toast with a specific variant
126
- */
127
- function createVariantToast(
128
- variant: Variant,
129
- message: string,
130
- options?: Omit<ToastOptions, "variant">,
131
- ): string {
132
- return createToast({ ...options, title: message, variant });
133
- }
134
-
135
- /**
136
- * Toast API interface
137
- */
138
- interface ToastAPI {
139
- (message: string, options?: Omit<ToastOptions, "title">): string;
140
- (options: ToastOptions): string;
141
- success(message: string, options?: Omit<ToastOptions, "variant">): string;
142
- error(message: string, options?: Omit<ToastOptions, "variant">): string;
143
- warning(message: string, options?: Omit<ToastOptions, "variant">): string;
144
- info(message: string, options?: Omit<ToastOptions, "variant">): string;
145
- loading(message: string, options?: Omit<ToastOptions, "variant">): string;
146
- promise<T, E = Error>(promise: Promise<T>, options: PromiseOptions<T, E>): Promise<T>;
147
- update(id: string, options: Partial<ToastOptions>): void;
148
- dismiss(id?: string): void;
149
- }
150
-
151
- /**
152
- * Main toast function with variant methods attached
153
- */
154
- const toast = createToast as ToastAPI;
155
-
156
- toast.success = (message: string, options?: Omit<ToastOptions, "variant">) =>
157
- createVariantToast("success", message, options);
158
-
159
- toast.error = (message: string, options?: Omit<ToastOptions, "variant">) =>
160
- createVariantToast("error", message, options);
161
-
162
- toast.warning = (message: string, options?: Omit<ToastOptions, "variant">) =>
163
- createVariantToast("warning", message, options);
164
-
165
- toast.info = (message: string, options?: Omit<ToastOptions, "variant">) =>
166
- createVariantToast("info", message, options);
167
-
168
- toast.loading = (message: string, options?: Omit<ToastOptions, "variant">) =>
169
- createVariantToast("loading", message, { ...options, duration: 0 });
170
-
171
- toast.promise = async <T, E = Error>(
172
- promise: Promise<T>,
173
- options: PromiseOptions<T, E>,
174
- ): Promise<T> => {
175
- const loadingOpts = normalizeOption(options.loading);
176
- const id = createToast({
177
- ...loadingOpts,
178
- variant: "loading",
179
- duration: 0, // Don't auto-dismiss while loading
180
- });
181
-
182
- try {
183
- const data = await promise;
184
- const successOpts = normalizeOption(options.success, data);
185
- toast.update(id, { ...successOpts, variant: "success" });
186
- return data;
187
- } catch (error) {
188
- const errorOpts = normalizeOption(options.error, error as E);
189
- toast.update(id, { ...errorOpts, variant: "error" });
190
- throw error;
191
- }
192
- };
193
-
194
- toast.update = (id: string, options: Partial<ToastOptions>): void => {
195
- const manager = getManager();
196
- if (manager) {
197
- manager.update(id, options);
198
- } else {
199
- console.warn("Toast: No Toaster found. Add <Toaster /> to your layout.");
200
- }
201
- };
202
-
203
- toast.dismiss = (id?: string): void => {
204
- const manager = getManager();
205
- if (!manager) {
206
- // Can't dismiss if manager isn't ready
207
- return;
208
- }
209
- if (id) {
210
- manager.close(id);
211
- } else {
212
- manager.closeAll();
213
- }
214
- };
215
-
216
- export { toast };
@@ -1,174 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { tv, type VariantProps } from "tailwind-variants";
4
-
5
- export const toggle = tv({
6
- base: [
7
- "inline-flex items-center justify-center gap-2 rounded-md font-medium whitespace-nowrap",
8
- "disabled:pointer-events-none disabled:opacity-50",
9
- "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
10
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
11
- "focus-visible:border-outline focus-visible:ring-outline/50 focus-visible:ring-3",
12
- "transition-colors outline-none",
13
- "aria-invalid:ring-error/20 dark:aria-invalid:ring-error/40 aria-invalid:border-error",
14
- ],
15
- variants: {
16
- variant: {
17
- default: "hover:bg-muted hover:text-muted-foreground bg-transparent",
18
- outline:
19
- "border-input hover:bg-accent hover:text-accent-foreground border bg-transparent shadow-xs",
20
- },
21
- size: {
22
- sm: "h-9 min-w-9 px-2 text-sm",
23
- md: "h-11 min-w-11 px-2.5 text-base",
24
- lg: "h-12 min-w-12 px-3 text-lg",
25
- },
26
- },
27
- defaultVariants: {
28
- variant: "default",
29
- size: "md",
30
- },
31
- });
32
-
33
- type Props = VariantProps<typeof toggle> &
34
- HTMLAttributes<"button"> & {
35
- /**
36
- * The pressed state of the toggle when initially rendered
37
- */
38
- defaultPressed?: boolean;
39
- /**
40
- * Optional sync group name. When set, all toggles with the same sync group will mirror each other's state
41
- */
42
- syncGroup?: string;
43
- };
44
-
45
- const { class: className, defaultPressed = false, syncGroup, variant, size, ...rest } = Astro.props;
46
-
47
- const dataState = defaultPressed ? "on" : "off";
48
- ---
49
-
50
- <button
51
- type="button"
52
- class={toggle({ variant, size, class: `starwind-toggle ${className || ""}` })}
53
- data-slot="toggle"
54
- data-state={dataState}
55
- data-sync-group={syncGroup}
56
- aria-pressed={defaultPressed}
57
- {...rest}
58
- >
59
- <slot />
60
- </button>
61
-
62
- <script>
63
- import type { ToggleChangeEvent, ToggleSyncEvent } from "./ToggleTypes";
64
-
65
- class ToggleHandler {
66
- private toggle: HTMLButtonElement;
67
- private syncGroup?: string;
68
-
69
- constructor(toggle: HTMLButtonElement, idx: number) {
70
- this.toggle = toggle;
71
- this.syncGroup = toggle.dataset.syncGroup;
72
-
73
- if (!this.toggle.id) {
74
- this.toggle.id = `starwind-toggle${idx}`;
75
- }
76
-
77
- this.setupEventListeners();
78
-
79
- if (this.syncGroup) {
80
- this.setupSyncListener();
81
- }
82
- }
83
-
84
- private setupEventListeners(): void {
85
- this.toggle.addEventListener("click", () => this.handleToggle());
86
- this.toggle.addEventListener("keydown", (event) => this.handleKeyDown(event));
87
- }
88
-
89
- private setupSyncListener(): void {
90
- if (!this.syncGroup) return;
91
-
92
- document.addEventListener(`starwind-toggle-sync:${this.syncGroup}`, ((e: ToggleSyncEvent) => {
93
- // Don't sync if this toggle triggered the event
94
- if (e.detail.sourceId === this.toggle.id) return;
95
-
96
- const newPressed = e.detail.pressed;
97
- this.updateState(newPressed, false); // false = don't dispatch sync event
98
- }) as EventListener);
99
- }
100
-
101
- private handleToggle(): void {
102
- if (this.isDisabled()) return;
103
-
104
- const isPressed = this.toggle.getAttribute("aria-pressed") === "true";
105
- const newPressed = !isPressed;
106
-
107
- this.updateState(newPressed, true);
108
- }
109
-
110
- private handleKeyDown(event: KeyboardEvent): void {
111
- if (this.isDisabled()) return;
112
-
113
- if (event.key === " " || event.key === "Enter") {
114
- event.preventDefault();
115
- this.handleToggle();
116
- }
117
- }
118
-
119
- private isDisabled(): boolean {
120
- return this.toggle.disabled;
121
- }
122
-
123
- private updateState(pressed: boolean, dispatchSync: boolean): void {
124
- const newState = pressed ? "on" : "off";
125
-
126
- this.toggle.setAttribute("aria-pressed", pressed.toString());
127
- this.toggle.setAttribute("data-state", newState);
128
-
129
- // Dispatch change event (always fired for user to listen to)
130
- const changeEvent = new CustomEvent<ToggleChangeEvent["detail"]>("starwind-toggle:change", {
131
- detail: {
132
- pressed,
133
- toggleId: this.toggle.id,
134
- syncGroup: this.syncGroup,
135
- },
136
- bubbles: true,
137
- cancelable: true,
138
- });
139
-
140
- this.toggle.dispatchEvent(changeEvent);
141
-
142
- // Dispatch sync event if in a sync group and requested
143
- if (this.syncGroup && dispatchSync) {
144
- const syncEvent = new CustomEvent<ToggleSyncEvent["detail"]>(
145
- `starwind-toggle-sync:${this.syncGroup}`,
146
- {
147
- detail: {
148
- pressed,
149
- sourceId: this.toggle.id,
150
- },
151
- },
152
- );
153
-
154
- document.dispatchEvent(syncEvent);
155
- }
156
- }
157
- }
158
-
159
- // Store instances in a WeakMap to avoid memory leaks
160
- const toggleInstances = new WeakMap<HTMLElement, ToggleHandler>();
161
- let toggleCounter = 0;
162
-
163
- const setupToggles = () => {
164
- document.querySelectorAll<HTMLButtonElement>(".starwind-toggle").forEach((toggle) => {
165
- if (!toggleInstances.has(toggle)) {
166
- toggleInstances.set(toggle, new ToggleHandler(toggle, toggleCounter++));
167
- }
168
- });
169
- };
170
-
171
- setupToggles();
172
- document.addEventListener("astro:after-swap", setupToggles);
173
- document.addEventListener("starwind:init", setupToggles);
174
- </script>
@@ -1,14 +0,0 @@
1
- export interface ToggleChangeEvent extends CustomEvent {
2
- detail: {
3
- pressed: boolean;
4
- toggleId: string;
5
- syncGroup?: string;
6
- };
7
- }
8
-
9
- export interface ToggleSyncEvent extends CustomEvent {
10
- detail: {
11
- pressed: boolean;
12
- sourceId: string;
13
- };
14
- }
@@ -1,8 +0,0 @@
1
- import Toggle, { toggle } from "./Toggle.astro";
2
- import type { ToggleChangeEvent, ToggleSyncEvent } from "./ToggleTypes";
3
-
4
- const ToggleVariants = { toggle };
5
-
6
- export { Toggle, type ToggleChangeEvent, type ToggleSyncEvent, ToggleVariants };
7
-
8
- export default Toggle;
@@ -1,239 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { tv } from "tailwind-variants";
4
-
5
- type Props = HTMLAttributes<"div"> & {
6
- /**
7
- * Time in milliseconds to wait before showing the tooltip
8
- */
9
- openDelay?: number;
10
- /**
11
- * Time in milliseconds to wait before hiding the tooltip
12
- */
13
- closeDelay?: number;
14
- /**
15
- * When true, prevents the tooltip from staying open when hovering over its content
16
- */
17
- disableHoverableContent?: boolean;
18
- };
19
-
20
- export const tooltip = tv({ base: "starwind-tooltip relative inline-block" });
21
-
22
- const {
23
- openDelay = 200,
24
- closeDelay = 200,
25
- disableHoverableContent = false,
26
- class: className,
27
- } = Astro.props;
28
- ---
29
-
30
- <div
31
- class={tooltip({ class: className })}
32
- data-slot="tooltip"
33
- data-state="closed"
34
- data-open-delay={openDelay}
35
- data-close-delay={closeDelay}
36
- {...!disableHoverableContent && { "data-content-hoverable": "" }}
37
- >
38
- <slot />
39
- </div>
40
-
41
- <script>
42
- class TooltipHandler {
43
- private tooltip: HTMLElement;
44
- private trigger: HTMLElement | null;
45
- private content: HTMLElement | null;
46
- private openTimerRef: number | null = null;
47
- private closeTimerRef: number | null = null;
48
- private contentId: string;
49
- private animationDuration = 150;
50
-
51
- constructor(tooltip: HTMLElement, idx: number) {
52
- this.contentId = `starwind-tooltip${idx}`;
53
- this.tooltip = tooltip;
54
- this.content = tooltip.querySelector(".starwind-tooltip-content");
55
-
56
- // if tooltip.firstElementChild is this.content, then get the next element
57
- this.trigger = tooltip.firstElementChild as HTMLElement;
58
- if (this.trigger === this.content) {
59
- this.trigger = this.trigger.nextElementSibling as HTMLElement;
60
- }
61
-
62
- this.trigger.classList.add("starwind-tooltip-trigger");
63
-
64
- if (!this.trigger || !this.content) return;
65
-
66
- // animationDuration is set with inline styles through passed prop to TooltipContent
67
- const animationDurationString = this.content.style.animationDuration;
68
- if (animationDurationString.endsWith("ms")) {
69
- this.animationDuration = parseFloat(animationDurationString);
70
- } else if (animationDurationString.endsWith("s")) {
71
- // using something like @playform/compress might optimize to use "s" instead of "ms"
72
- this.animationDuration = parseFloat(animationDurationString) * 1000;
73
- }
74
- this.init();
75
- }
76
-
77
- private init() {
78
- this.setupAccessibility();
79
- this.setupEvents();
80
- }
81
-
82
- private setupAccessibility() {
83
- if (!this.trigger || !this.content) return;
84
- this.trigger.setAttribute("aria-describedby", this.contentId);
85
- this.content.id = this.contentId;
86
- }
87
-
88
- private setupEvents() {
89
- if (!this.trigger || !this.content) return;
90
-
91
- // Trigger events
92
- this.trigger.addEventListener("mouseenter", () => this.show());
93
- this.trigger.addEventListener("mouseleave", () => this.hide());
94
- this.trigger.addEventListener("focus", () => this.show(true));
95
- this.trigger.addEventListener("blur", () => this.hide(true));
96
-
97
- // Content events
98
- if (this.tooltip.hasAttribute("data-content-hoverable")) {
99
- this.content.addEventListener("mouseenter", () => this.show());
100
- this.content.addEventListener("mouseleave", () => this.hide());
101
- }
102
-
103
- // if data-avoid-collisions exists, add resize listener to reset any translations
104
- if (this.content.hasAttribute("data-avoid-collisions")) {
105
- window.addEventListener(
106
- "resize",
107
- () => {
108
- if (!this.content) return;
109
- this.content.style.transform = "";
110
- },
111
- { passive: true },
112
- );
113
- }
114
-
115
- // Document events
116
- document.addEventListener("keydown", (e) => {
117
- if (e.key === "Escape" && this.tooltip.getAttribute("data-state") === "open") {
118
- this.hide(true);
119
- }
120
- });
121
-
122
- document.addEventListener("click", (e) => {
123
- if (
124
- !this.tooltip.contains(e.target as Node) &&
125
- this.tooltip.getAttribute("data-state") === "open"
126
- ) {
127
- this.hide(true);
128
- }
129
- });
130
- }
131
-
132
- private show(immediate: boolean = false) {
133
- if (!this.content || !this.trigger) return;
134
- if (immediate) {
135
- this.tooltip.setAttribute("data-state", "open");
136
- this.content.setAttribute("data-state", "open");
137
- this.content.style.display = "block";
138
- this.checkBoundary(this.content);
139
- this.clearOpenTimer();
140
- return;
141
- }
142
-
143
- this.clearCloseTimer();
144
-
145
- const delay = parseInt(this.tooltip.getAttribute("data-open-delay") || "700");
146
- this.openTimerRef = window.setTimeout(() => {
147
- if (!this.content || !this.trigger) return;
148
- this.tooltip.setAttribute("data-state", "open");
149
- this.content.setAttribute("data-state", "open");
150
- this.content.style.display = "block";
151
- this.checkBoundary(this.content);
152
- this.openTimerRef = null;
153
- }, delay);
154
- }
155
-
156
- private hide(immediate: boolean = false) {
157
- if (!this.content || !this.trigger) return;
158
- this.clearOpenTimer();
159
-
160
- if (immediate) {
161
- this.clearCloseTimer();
162
- this.tooltip.setAttribute("data-state", "closed");
163
- setTimeout(() => {
164
- if (!this.content) return;
165
- this.content.style.display = "none";
166
- }, this.animationDuration);
167
- this.content.setAttribute("data-state", "closed");
168
- return;
169
- }
170
-
171
- this.closeTimerRef = window.setTimeout(
172
- () => {
173
- this.tooltip.setAttribute("data-state", "closed");
174
- setTimeout(() => {
175
- if (!this.content) return;
176
- this.content.style.display = "none";
177
- }, this.animationDuration);
178
- if (!this.content) return;
179
- this.content.setAttribute("data-state", "closed");
180
- this.closeTimerRef = null;
181
- },
182
- parseInt(this.tooltip.getAttribute("data-close-delay") || "300"),
183
- );
184
- }
185
-
186
- private checkBoundary(tooltipElement: HTMLElement) {
187
- if (!tooltipElement) return;
188
-
189
- // if data-avoid-collisions does not exist, return
190
- if (!tooltipElement.hasAttribute("data-avoid-collisions")) return;
191
-
192
- const viewportWidth = window.innerWidth;
193
- const tooltipRect = tooltipElement.getBoundingClientRect();
194
- const padding = 16; // Add some padding from viewport edges
195
-
196
- // Check if tooltip extends beyond right edge of viewport
197
- if (tooltipRect.right > viewportWidth - padding) {
198
- const overflow = tooltipRect.right - (viewportWidth - padding);
199
- tooltipElement.style.transform = `translateX(-${overflow + padding}px)`;
200
- }
201
-
202
- // Check if tooltip extends beyond left edge of viewport
203
- if (tooltipRect.left < padding) {
204
- const overflow = padding - tooltipRect.left;
205
- tooltipElement.style.transform = `translateX(${overflow + padding}px)`;
206
- }
207
- }
208
-
209
- private clearOpenTimer() {
210
- if (this.openTimerRef) {
211
- window.clearTimeout(this.openTimerRef);
212
- this.openTimerRef = null;
213
- }
214
- }
215
-
216
- private clearCloseTimer() {
217
- if (this.closeTimerRef) {
218
- window.clearTimeout(this.closeTimerRef);
219
- this.closeTimerRef = null;
220
- }
221
- }
222
- }
223
-
224
- // Store instances in a WeakMap to avoid memory leaks
225
- const tooltipInstances = new WeakMap<HTMLElement, TooltipHandler>();
226
- let tooltipCounter = 0;
227
-
228
- const setupTooltips = () => {
229
- document.querySelectorAll<HTMLElement>(".starwind-tooltip").forEach((tooltip) => {
230
- if (!tooltipInstances.has(tooltip)) {
231
- tooltipInstances.set(tooltip, new TooltipHandler(tooltip, tooltipCounter++));
232
- }
233
- });
234
- };
235
-
236
- setupTooltips();
237
- document.addEventListener("astro:after-swap", setupTooltips);
238
- document.addEventListener("starwind:init", setupTooltips);
239
- </script>