@starwind-ui/core 1.6.2 → 1.7.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.
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/src/components/accordion/Accordion.astro +224 -224
- package/dist/src/components/accordion/AccordionContent.astro +13 -13
- package/dist/src/components/accordion/AccordionItem.astro +6 -6
- package/dist/src/components/accordion/AccordionTrigger.astro +13 -13
- package/dist/src/components/accordion/index.ts +4 -4
- package/dist/src/components/alert/Alert.astro +15 -15
- package/dist/src/components/alert/AlertDescription.astro +1 -1
- package/dist/src/components/alert/AlertTitle.astro +2 -2
- package/dist/src/components/alert/index.ts +3 -3
- package/dist/src/components/avatar/Avatar.astro +16 -16
- package/dist/src/components/avatar/AvatarFallback.astro +3 -3
- package/dist/src/components/avatar/AvatarImage.astro +12 -12
- package/dist/src/components/avatar/index.ts +4 -4
- package/dist/src/components/badge/Badge.astro +33 -33
- package/dist/src/components/breadcrumb/Breadcrumb.astro +1 -1
- package/dist/src/components/breadcrumb/BreadcrumbEllipsis.astro +6 -6
- package/dist/src/components/breadcrumb/BreadcrumbItem.astro +1 -1
- package/dist/src/components/breadcrumb/BreadcrumbLink.astro +8 -8
- package/dist/src/components/breadcrumb/BreadcrumbList.astro +2 -2
- package/dist/src/components/breadcrumb/BreadcrumbPage.astro +6 -6
- package/dist/src/components/breadcrumb/BreadcrumbSeparator.astro +7 -7
- package/dist/src/components/breadcrumb/index.ts +14 -14
- package/dist/src/components/button/Button.astro +38 -38
- package/dist/src/components/card/Card.astro +1 -1
- package/dist/src/components/card/CardContent.astro +1 -1
- package/dist/src/components/card/CardDescription.astro +1 -1
- package/dist/src/components/card/CardFooter.astro +1 -1
- package/dist/src/components/card/CardHeader.astro +1 -1
- package/dist/src/components/card/CardTitle.astro +1 -1
- package/dist/src/components/card/index.ts +7 -7
- package/dist/src/components/checkbox/Checkbox.astro +89 -89
- package/dist/src/components/dialog/Dialog.astro +178 -178
- package/dist/src/components/dialog/DialogClose.astro +14 -14
- package/dist/src/components/dialog/DialogContent.astro +32 -32
- package/dist/src/components/dialog/DialogDescription.astro +1 -1
- package/dist/src/components/dialog/DialogFooter.astro +1 -1
- package/dist/src/components/dialog/DialogHeader.astro +1 -1
- package/dist/src/components/dialog/DialogTitle.astro +6 -6
- package/dist/src/components/dialog/DialogTrigger.astro +19 -19
- package/dist/src/components/dialog/index.ts +16 -16
- package/dist/src/components/dropdown/Dropdown.astro +359 -359
- package/dist/src/components/dropdown/DropdownContent.astro +63 -63
- package/dist/src/components/dropdown/DropdownItem.astro +31 -31
- package/dist/src/components/dropdown/DropdownLabel.astro +14 -14
- package/dist/src/components/dropdown/DropdownSeparator.astro +5 -5
- package/dist/src/components/dropdown/DropdownTrigger.astro +26 -26
- package/dist/src/components/dropdown/index.ts +12 -12
- package/dist/src/components/dropzone/Dropzone.astro +232 -0
- package/dist/src/components/dropzone/DropzoneFilesList.astro +25 -0
- package/dist/src/components/dropzone/DropzoneLoadingIndicator.astro +10 -0
- package/dist/src/components/dropzone/DropzoneUploadIndicator.astro +10 -0
- package/dist/src/components/dropzone/index.ts +13 -0
- package/dist/src/components/input/Input.astro +12 -12
- package/dist/src/components/label/Label.astro +8 -8
- package/dist/src/components/pagination/Pagination.astro +1 -1
- package/dist/src/components/pagination/PaginationContent.astro +3 -3
- package/dist/src/components/pagination/PaginationEllipsis.astro +2 -2
- package/dist/src/components/pagination/PaginationItem.astro +3 -3
- package/dist/src/components/pagination/PaginationLink.astro +27 -27
- package/dist/src/components/pagination/PaginationNext.astro +7 -6
- package/dist/src/components/pagination/PaginationPrevious.astro +7 -6
- package/dist/src/components/pagination/index.ts +14 -14
- package/dist/src/components/progress/Progress.astro +151 -0
- package/dist/src/components/progress/index.ts +5 -0
- package/dist/src/components/radio-group/RadioGroup.astro +156 -0
- package/dist/src/components/radio-group/RadioGroupItem.astro +125 -0
- package/dist/src/components/radio-group/RadioGroupTypes.ts +6 -0
- package/dist/src/components/radio-group/index.ts +10 -0
- package/dist/src/components/select/Select.astro +475 -475
- package/dist/src/components/select/SelectContent.astro +62 -62
- package/dist/src/components/select/SelectItem.astro +27 -27
- package/dist/src/components/select/SelectLabel.astro +1 -1
- package/dist/src/components/select/SelectTrigger.astro +28 -28
- package/dist/src/components/select/SelectTypes.ts +5 -5
- package/dist/src/components/select/SelectValue.astro +5 -5
- package/dist/src/components/select/index.ts +16 -16
- package/dist/src/components/skeleton/Skeleton.astro +14 -0
- package/dist/src/components/skeleton/index.ts +5 -0
- package/dist/src/components/switch/Switch.astro +150 -150
- package/dist/src/components/switch/SwitchTypes.ts +4 -4
- package/dist/src/components/table/Table.astro +5 -5
- package/dist/src/components/table/TableBody.astro +3 -3
- package/dist/src/components/table/TableCaption.astro +3 -3
- package/dist/src/components/table/TableCell.astro +3 -3
- package/dist/src/components/table/TableFoot.astro +3 -3
- package/dist/src/components/table/TableHead.astro +3 -3
- package/dist/src/components/table/TableHeader.astro +3 -3
- package/dist/src/components/table/TableRow.astro +3 -3
- package/dist/src/components/table/index.ts +8 -8
- package/dist/src/components/tabs/Tabs.astro +250 -250
- package/dist/src/components/tabs/TabsContent.astro +10 -10
- package/dist/src/components/tabs/TabsList.astro +2 -2
- package/dist/src/components/tabs/TabsTrigger.astro +15 -15
- package/dist/src/components/tabs/index.ts +4 -4
- package/dist/src/components/textarea/Textarea.astro +16 -16
- package/dist/src/components/tooltip/Tooltip.astro +217 -217
- package/dist/src/components/tooltip/TooltipContent.astro +81 -81
- package/dist/src/components/tooltip/index.ts +3 -3
- package/package.json +1 -1
|
@@ -1,67 +1,67 @@
|
|
|
1
1
|
---
|
|
2
2
|
import Check from "@tabler/icons/outline/check.svg";
|
|
3
3
|
import type { HTMLAttributes } from "astro/types";
|
|
4
|
-
import { type VariantProps
|
|
4
|
+
import { tv, type VariantProps } from "tailwind-variants";
|
|
5
5
|
|
|
6
6
|
type Props = Omit<HTMLAttributes<"input">, "type"> &
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
VariantProps<typeof checkbox> & {
|
|
8
|
+
/**
|
|
9
|
+
* Optional label text to display next to the checkbox
|
|
10
|
+
*/
|
|
11
|
+
label?: string;
|
|
12
|
+
};
|
|
13
13
|
|
|
14
14
|
const checkbox = tv({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
15
|
+
slots: {
|
|
16
|
+
base: "starwind-checkbox relative flex items-center space-x-2",
|
|
17
|
+
input: [
|
|
18
|
+
"peer border-input bg-background starwind-transition-colors shrink-0 transform-gpu rounded-sm border",
|
|
19
|
+
"focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:transition-none",
|
|
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:outline-outline",
|
|
39
|
+
icon: "text-background",
|
|
40
|
+
},
|
|
41
|
+
primary: {
|
|
42
|
+
input: "checked:bg-primary focus-visible:outline-primary",
|
|
43
|
+
icon: "text-primary-foreground",
|
|
44
|
+
},
|
|
45
|
+
secondary: {
|
|
46
|
+
input: "checked:bg-secondary focus-visible:outline-secondary",
|
|
47
|
+
icon: "text-secondary-foreground",
|
|
48
|
+
},
|
|
49
|
+
info: { input: "checked:bg-info focus-visible:outline-info", icon: "text-info-foreground" },
|
|
50
|
+
success: {
|
|
51
|
+
input: "checked:bg-success focus-visible:outline-success",
|
|
52
|
+
icon: "text-success-foreground",
|
|
53
|
+
},
|
|
54
|
+
warning: {
|
|
55
|
+
input: "checked:bg-warning focus-visible:outline-warning",
|
|
56
|
+
icon: "text-warning-foreground",
|
|
57
|
+
},
|
|
58
|
+
error: {
|
|
59
|
+
input: "checked:bg-error focus-visible:outline-error",
|
|
60
|
+
icon: "text-error-foreground",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
defaultVariants: { size: "md", variant: "default" },
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
const { id, label, checked, size, variant, class: className, ...rest } = Astro.props;
|
|
@@ -70,42 +70,42 @@ const { base, input, icon, label: labelClass } = checkbox({ size, variant });
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
72
|
<div class={base()}>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
<input type="checkbox" id={id} class={input({ class: className })} {checked} {...rest} />
|
|
74
|
+
<Check class={icon()} />
|
|
75
|
+
{
|
|
76
|
+
label && (
|
|
77
|
+
<label for={id} class={labelClass()}>
|
|
78
|
+
{label}
|
|
79
|
+
</label>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
82
|
</div>
|
|
83
83
|
|
|
84
84
|
<style>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
.starwind-checkbox input[type="checkbox"]:checked {
|
|
86
|
+
background-image: none;
|
|
87
|
+
}
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
/* Check drawing animation */
|
|
90
|
+
.starwind-check-icon {
|
|
91
|
+
stroke-dasharray: 65;
|
|
92
|
+
stroke-dashoffset: 65;
|
|
93
|
+
opacity: 0;
|
|
94
|
+
}
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
.starwind-checkbox input[type="checkbox"]:checked + .starwind-check-icon {
|
|
97
|
+
animation: draw-check 0.3s ease forwards;
|
|
98
|
+
animation-delay: 0.15s;
|
|
99
|
+
}
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
@keyframes draw-check {
|
|
102
|
+
0% {
|
|
103
|
+
stroke-dashoffset: 65;
|
|
104
|
+
opacity: 1;
|
|
105
|
+
}
|
|
106
|
+
100% {
|
|
107
|
+
stroke-dashoffset: 0;
|
|
108
|
+
opacity: 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
111
|
</style>
|
|
@@ -7,185 +7,185 @@ const { class: className, ...rest } = Astro.props;
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
<div class:list={["starwind-dialog", className]} {...rest}>
|
|
10
|
-
|
|
10
|
+
<slot />
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
13
|
<script>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
14
|
+
class DialogHandler {
|
|
15
|
+
private trigger: HTMLButtonElement;
|
|
16
|
+
private dialog: HTMLDialogElement;
|
|
17
|
+
private closeButtons: NodeListOf<HTMLButtonElement>;
|
|
18
|
+
private backdrop: HTMLElement;
|
|
19
|
+
/**
|
|
20
|
+
* The duration of the animation in milliseconds. This is used to calculate the
|
|
21
|
+
* duration of close animation before hiding the dialog and backdrop
|
|
22
|
+
*/
|
|
23
|
+
private animationDuration: number;
|
|
24
|
+
|
|
25
|
+
constructor(dialogWrapper: HTMLElement, dialogNumber: number) {
|
|
26
|
+
this.dialog = dialogWrapper.querySelector("dialog")!;
|
|
27
|
+
this.backdrop = dialogWrapper.querySelector(".starwind-dialog-backdrop")!;
|
|
28
|
+
|
|
29
|
+
// animationDuration is set with inline styles through passed prop to DialogContent
|
|
30
|
+
const animationDurationString = this.dialog.style.animationDuration;
|
|
31
|
+
if (animationDurationString.endsWith("ms")) {
|
|
32
|
+
this.animationDuration = parseFloat(animationDurationString);
|
|
33
|
+
} else if (animationDurationString.endsWith("s")) {
|
|
34
|
+
// using something like @playform/compress might optimize to use "s" instead of "ms"
|
|
35
|
+
this.animationDuration = parseFloat(animationDurationString) * 1000;
|
|
36
|
+
} else {
|
|
37
|
+
this.animationDuration = 200;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// if trigger is set with asChild, use the first child element for trigger button
|
|
41
|
+
const tempTrigger = dialogWrapper.querySelector(".starwind-dialog-trigger") as HTMLElement;
|
|
42
|
+
if (tempTrigger?.hasAttribute("data-as-child")) {
|
|
43
|
+
this.trigger = tempTrigger.firstElementChild as HTMLButtonElement;
|
|
44
|
+
} else {
|
|
45
|
+
this.trigger = tempTrigger as HTMLButtonElement;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// if closeButtons are set with asChild, swap the wrapper with its first child
|
|
49
|
+
const tempCloseButtons = dialogWrapper.querySelectorAll(
|
|
50
|
+
".starwind-dialog-close",
|
|
51
|
+
) as NodeListOf<HTMLElement>;
|
|
52
|
+
tempCloseButtons.forEach((button: HTMLElement) => {
|
|
53
|
+
if (button.hasAttribute("data-as-child")) {
|
|
54
|
+
const childElement = button.firstElementChild;
|
|
55
|
+
if (childElement) {
|
|
56
|
+
childElement.classList.add("starwind-dialog-close");
|
|
57
|
+
button.parentNode?.replaceChild(childElement, button);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return button;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.closeButtons = dialogWrapper.querySelectorAll(
|
|
64
|
+
".starwind-dialog-close",
|
|
65
|
+
) as NodeListOf<HTMLButtonElement>;
|
|
66
|
+
|
|
67
|
+
// if any elements are not there, exit
|
|
68
|
+
if (!this.trigger || !this.dialog || !this.backdrop) return;
|
|
69
|
+
|
|
70
|
+
this.setupAccessibility(dialogNumber);
|
|
71
|
+
this.setupEvents();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private setupAccessibility(dialogNumber: number): void {
|
|
75
|
+
// get the first heading element in the dialog
|
|
76
|
+
const firstHeading = this.dialog.querySelector("h1, h2, h3, h4, h5, h6");
|
|
77
|
+
if (firstHeading) {
|
|
78
|
+
// create a unique ID for the heading
|
|
79
|
+
firstHeading.id = `starwind-dialog${dialogNumber}-heading`;
|
|
80
|
+
// set the aria-labelledby attribute to the first heading element
|
|
81
|
+
this.dialog.setAttribute("aria-labelledby", firstHeading.id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private setupEvents(): void {
|
|
86
|
+
this.trigger?.addEventListener("click", () => {
|
|
87
|
+
this.open();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Add click handlers to all close buttons
|
|
91
|
+
this.closeButtons?.forEach((button) => {
|
|
92
|
+
button.addEventListener("click", () => {
|
|
93
|
+
// Only close if this is the topmost dialog
|
|
94
|
+
const openDialogs = document.querySelectorAll("dialog[open]");
|
|
95
|
+
if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
|
|
96
|
+
this.close();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Close on click outside
|
|
102
|
+
this.dialog.addEventListener("click", (e) => {
|
|
103
|
+
const dialogDimensions = this.dialog.getBoundingClientRect();
|
|
104
|
+
const clickedInDialog =
|
|
105
|
+
e.clientX >= dialogDimensions.left &&
|
|
106
|
+
e.clientX <= dialogDimensions.right &&
|
|
107
|
+
e.clientY >= dialogDimensions.top &&
|
|
108
|
+
e.clientY <= dialogDimensions.bottom;
|
|
109
|
+
|
|
110
|
+
if (!clickedInDialog) {
|
|
111
|
+
// Only close if this is the topmost dialog
|
|
112
|
+
const openDialogs = document.querySelectorAll("dialog[open]");
|
|
113
|
+
if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
|
|
114
|
+
this.close();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Handle escape key
|
|
120
|
+
this.dialog.addEventListener("keydown", (e) => {
|
|
121
|
+
if (e.key === "Escape") {
|
|
122
|
+
// prevent default dialog closing behavior so we can add closing animation
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
// Only close if this is the topmost dialog
|
|
125
|
+
const openDialogs = document.querySelectorAll("dialog[open]");
|
|
126
|
+
if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
|
|
127
|
+
this.close();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Intercept form submissions to handle dialog close
|
|
133
|
+
const forms = this.dialog.querySelectorAll("form");
|
|
134
|
+
forms.forEach((form) => {
|
|
135
|
+
form.addEventListener("submit", (e) => {
|
|
136
|
+
/**
|
|
137
|
+
* Default form.method = "dialog" submissions cause the dialog to close
|
|
138
|
+
* Default form.method = "post" submissions do not close the dialog
|
|
139
|
+
* Here we intercept the form submission and manage the dialog closing if method = "dialog"
|
|
140
|
+
* so we can add closing animation
|
|
141
|
+
* Normal form event listeners for "submit" will still get the form data
|
|
142
|
+
*/
|
|
143
|
+
if (form.method === "dialog") {
|
|
144
|
+
e.preventDefault();
|
|
145
|
+
// Only close if this is the topmost dialog
|
|
146
|
+
const openDialogs = document.querySelectorAll("dialog[open]");
|
|
147
|
+
if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
|
|
148
|
+
this.close();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private open(): void {
|
|
156
|
+
this.dialog.showModal();
|
|
157
|
+
document.body.classList.add("overflow-hidden");
|
|
158
|
+
this.backdrop.classList.remove("hidden");
|
|
159
|
+
this.backdrop.dataset.state = "open";
|
|
160
|
+
this.dialog.dataset.state = "open";
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private close(): void {
|
|
164
|
+
document.body.classList.remove("overflow-hidden");
|
|
165
|
+
this.dialog.dataset.state = "closed";
|
|
166
|
+
this.backdrop.dataset.state = "closed";
|
|
167
|
+
|
|
168
|
+
// Wait for animation to finish before hiding backdrop
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
this.backdrop.classList.add("hidden");
|
|
171
|
+
this.dialog.close();
|
|
172
|
+
}, this.animationDuration);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Store instances in a WeakMap to avoid memory leaks
|
|
177
|
+
const dialogInstances = new WeakMap<HTMLElement, DialogHandler>();
|
|
178
|
+
|
|
179
|
+
// Initialize all dialogs
|
|
180
|
+
const setupDialogs = () => {
|
|
181
|
+
document.querySelectorAll(".starwind-dialog").forEach((dialogWrapper, idx) => {
|
|
182
|
+
const wrapper = dialogWrapper as HTMLElement;
|
|
183
|
+
if (!dialogInstances.has(wrapper)) {
|
|
184
|
+
dialogInstances.set(wrapper, new DialogHandler(wrapper, idx));
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
setupDialogs();
|
|
190
|
+
document.addEventListener("astro:after-swap", setupDialogs);
|
|
191
191
|
</script>
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import type { HTMLAttributes } from "astro/types";
|
|
3
3
|
|
|
4
4
|
type Props = HTMLAttributes<"button"> & {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
/**
|
|
6
|
+
* When true, the component will render its child element instead of a button
|
|
7
|
+
*/
|
|
8
|
+
asChild?: boolean;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
const { class: className, asChild = false, ...rest } = Astro.props;
|
|
@@ -13,18 +13,18 @@ const { class: className, asChild = false, ...rest } = Astro.props;
|
|
|
13
13
|
// Get the first child element if asChild is true
|
|
14
14
|
let hasChildren = false;
|
|
15
15
|
if (Astro.slots.has("default")) {
|
|
16
|
-
|
|
16
|
+
hasChildren = true;
|
|
17
17
|
}
|
|
18
18
|
---
|
|
19
19
|
|
|
20
20
|
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
asChild && hasChildren ? (
|
|
22
|
+
<div class="starwind-dialog-close" data-as-child>
|
|
23
|
+
<slot />
|
|
24
|
+
</div>
|
|
25
|
+
) : (
|
|
26
|
+
<button type="button" class:list={["starwind-dialog-close", className]} {...rest}>
|
|
27
|
+
<slot>Demo close button</slot>
|
|
28
|
+
</button>
|
|
29
|
+
)
|
|
30
30
|
}
|