@rimelight/ui 0.0.5 → 0.0.7

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 (315) hide show
  1. package/LICENSE +21 -21
  2. package/package.json +22 -14
  3. package/src/components/BlogPost.astro +195 -0
  4. package/src/components/DynamicShowcase.astro +681 -0
  5. package/src/components/ExtendedCarousel.astro +107 -0
  6. package/src/components/FormattedDate.astro +6 -2
  7. package/src/components/Head.astro +153 -0
  8. package/src/components/ProjectPost.astro +197 -0
  9. package/src/components/RLHead.astro +3 -0
  10. package/src/components/ThemeToggle.astro +30 -42
  11. package/src/components/astro/RLAButton.astro +32 -42
  12. package/src/components/astro/RLAHeader.astro +75 -0
  13. package/src/components/nuxt/index.ts +1 -0
  14. package/src/components/vue/RLVButton.vue +50 -37
  15. package/src/components/vue/RLVHeader.vue +78 -0
  16. package/src/composables/index.ts +1 -1
  17. package/src/composables/{useComponentUI.ts → useUi.ts} +3 -3
  18. package/src/config/index.ts +0 -2
  19. package/src/config/site.config.ts +1 -1
  20. package/src/env.d.ts +13 -16
  21. package/src/integrations/ui.ts +106 -81
  22. package/src/integrations/vue-entrypoint.ts +6 -0
  23. package/src/middleware/sri.ts +2 -2
  24. package/src/styles/index.css +2 -0
  25. package/src/themes/button.theme.ts +350 -34
  26. package/src/themes/header.theme.ts +33 -0
  27. package/src/themes/index.ts +3 -1
  28. package/src/utils/index.ts +1 -2
  29. package/i18n-data.json +0 -186
  30. package/src/components/MissingTranslationBanner.astro +0 -39
  31. package/src/components/accordion/Accordion.astro +0 -257
  32. package/src/components/accordion/AccordionContent.astro +0 -34
  33. package/src/components/accordion/AccordionItem.astro +0 -29
  34. package/src/components/accordion/AccordionTrigger.astro +0 -33
  35. package/src/components/alert/Alert.astro +0 -34
  36. package/src/components/alert/AlertDescription.astro +0 -15
  37. package/src/components/alert/AlertTitle.astro +0 -17
  38. package/src/components/alert-dialog/AlertDialog.astro +0 -275
  39. package/src/components/alert-dialog/AlertDialogAction.astro +0 -46
  40. package/src/components/alert-dialog/AlertDialogCancel.astro +0 -46
  41. package/src/components/alert-dialog/AlertDialogContent.astro +0 -52
  42. package/src/components/alert-dialog/AlertDialogDescription.astro +0 -18
  43. package/src/components/alert-dialog/AlertDialogFooter.astro +0 -16
  44. package/src/components/alert-dialog/AlertDialogHeader.astro +0 -14
  45. package/src/components/alert-dialog/AlertDialogTitle.astro +0 -20
  46. package/src/components/alert-dialog/AlertDialogTrigger.astro +0 -47
  47. package/src/components/aspect-ratio/AspectRatio.astro +0 -32
  48. package/src/components/avatar/Avatar.astro +0 -29
  49. package/src/components/avatar/AvatarFallback.astro +0 -18
  50. package/src/components/avatar/AvatarImage.astro +0 -66
  51. package/src/components/badge/Badge.astro +0 -57
  52. package/src/components/breadcrumb/Breadcrumb.astro +0 -12
  53. package/src/components/breadcrumb/BreadcrumbEllipsis.astro +0 -29
  54. package/src/components/breadcrumb/BreadcrumbItem.astro +0 -15
  55. package/src/components/breadcrumb/BreadcrumbLink.astro +0 -24
  56. package/src/components/breadcrumb/BreadcrumbList.astro +0 -17
  57. package/src/components/breadcrumb/BreadcrumbPage.astro +0 -22
  58. package/src/components/breadcrumb/BreadcrumbSeparator.astro +0 -24
  59. package/src/components/button/Button.astro +0 -58
  60. package/src/components/button-group/ButtonGroup.astro +0 -64
  61. package/src/components/button-group/ButtonGroupSeparator.astro +0 -20
  62. package/src/components/button-group/ButtonGroupText.astro +0 -19
  63. package/src/components/card/Card.astro +0 -36
  64. package/src/components/card/CardAction.astro +0 -16
  65. package/src/components/card/CardContent.astro +0 -16
  66. package/src/components/card/CardDescription.astro +0 -16
  67. package/src/components/card/CardFooter.astro +0 -16
  68. package/src/components/card/CardHeader.astro +0 -19
  69. package/src/components/card/CardTitle.astro +0 -16
  70. package/src/components/carousel/Carousel.astro +0 -55
  71. package/src/components/carousel/CarouselContent.astro +0 -26
  72. package/src/components/carousel/CarouselItem.astro +0 -26
  73. package/src/components/carousel/CarouselNext.astro +0 -39
  74. package/src/components/carousel/CarouselPrevious.astro +0 -41
  75. package/src/components/carousel/carousel-script.ts +0 -188
  76. package/src/components/carousel/index.ts +0 -1
  77. package/src/components/checkbox/Checkbox.astro +0 -133
  78. package/src/components/collapsible/Collapsible.astro +0 -161
  79. package/src/components/collapsible/CollapsibleContent.astro +0 -22
  80. package/src/components/collapsible/CollapsibleTrigger.astro +0 -44
  81. package/src/components/dialog/Dialog.astro +0 -389
  82. package/src/components/dialog/DialogClose.astro +0 -35
  83. package/src/components/dialog/DialogContent.astro +0 -78
  84. package/src/components/dialog/DialogDescription.astro +0 -14
  85. package/src/components/dialog/DialogFooter.astro +0 -14
  86. package/src/components/dialog/DialogHeader.astro +0 -14
  87. package/src/components/dialog/DialogTitle.astro +0 -18
  88. package/src/components/dialog/DialogTrigger.astro +0 -47
  89. package/src/components/dropdown/Dropdown.astro +0 -604
  90. package/src/components/dropdown/DropdownContent.astro +0 -118
  91. package/src/components/dropdown/DropdownItem.astro +0 -48
  92. package/src/components/dropdown/DropdownLabel.astro +0 -29
  93. package/src/components/dropdown/DropdownSeparator.astro +0 -21
  94. package/src/components/dropdown/DropdownShortcut.astro +0 -17
  95. package/src/components/dropdown/DropdownSub.astro +0 -15
  96. package/src/components/dropdown/DropdownSubContent.astro +0 -39
  97. package/src/components/dropdown/DropdownSubTrigger.astro +0 -34
  98. package/src/components/dropdown/DropdownTrigger.astro +0 -52
  99. package/src/components/dropzone/Dropzone.astro +0 -236
  100. package/src/components/dropzone/DropzoneFilesList.astro +0 -26
  101. package/src/components/dropzone/DropzoneLoadingIndicator.astro +0 -10
  102. package/src/components/dropzone/DropzoneUploadIndicator.astro +0 -10
  103. package/src/components/embeds/YoutubeEmbed.astro +0 -94
  104. package/src/components/hero/Hero.astro +0 -166
  105. package/src/components/icons/Flag.astro +0 -62
  106. package/src/components/image/ExtendedImage.astro +0 -46
  107. package/src/components/image/Image.astro +0 -25
  108. package/src/components/input/Input.astro +0 -27
  109. package/src/components/input-group/InputGroup.astro +0 -28
  110. package/src/components/input-group/InputGroupAddon.astro +0 -76
  111. package/src/components/input-group/InputGroupButton.astro +0 -36
  112. package/src/components/input-group/InputGroupInput.astro +0 -18
  113. package/src/components/input-group/InputGroupText.astro +0 -17
  114. package/src/components/input-group/InputGroupTextarea.astro +0 -22
  115. package/src/components/input-otp/InputOtp.astro +0 -352
  116. package/src/components/input-otp/InputOtpGroup.astro +0 -16
  117. package/src/components/input-otp/InputOtpSeparator.astro +0 -25
  118. package/src/components/input-otp/InputOtpSlot.astro +0 -50
  119. package/src/components/input-otp/InputOtpTypes.ts +0 -6
  120. package/src/components/item/Item.astro +0 -52
  121. package/src/components/item/ItemActions.astro +0 -16
  122. package/src/components/item/ItemContent.astro +0 -16
  123. package/src/components/item/ItemDescription.astro +0 -19
  124. package/src/components/item/ItemFooter.astro +0 -16
  125. package/src/components/item/ItemGroup.astro +0 -16
  126. package/src/components/item/ItemHeader.astro +0 -16
  127. package/src/components/item/ItemMedia.astro +0 -40
  128. package/src/components/item/ItemSeparator.astro +0 -23
  129. package/src/components/item/ItemTitle.astro +0 -16
  130. package/src/components/kbd/Kbd.astro +0 -21
  131. package/src/components/kbd/KbdGroup.astro +0 -16
  132. package/src/components/label/Label.astro +0 -24
  133. package/src/components/marquee/Marquee.astro +0 -73
  134. package/src/components/native-select/NativeSelect.astro +0 -68
  135. package/src/components/native-select/NativeSelectOptGroup.astro +0 -15
  136. package/src/components/native-select/NativeSelectOption.astro +0 -15
  137. package/src/components/pagination/Pagination.astro +0 -20
  138. package/src/components/pagination/PaginationContent.astro +0 -16
  139. package/src/components/pagination/PaginationEllipsis.astro +0 -37
  140. package/src/components/pagination/PaginationItem.astro +0 -16
  141. package/src/components/pagination/PaginationLink.astro +0 -27
  142. package/src/components/pagination/PaginationNext.astro +0 -33
  143. package/src/components/pagination/PaginationPrevious.astro +0 -33
  144. package/src/components/popover/Popover.astro +0 -717
  145. package/src/components/popover/PopoverContent.astro +0 -102
  146. package/src/components/popover/PopoverDescription.astro +0 -14
  147. package/src/components/popover/PopoverHeader.astro +0 -14
  148. package/src/components/popover/PopoverTitle.astro +0 -14
  149. package/src/components/popover/PopoverTrigger.astro +0 -51
  150. package/src/components/progress/Progress.astro +0 -154
  151. package/src/components/prose/Prose.astro +0 -619
  152. package/src/components/radio-group/RadioGroup.astro +0 -162
  153. package/src/components/radio-group/RadioGroupItem.astro +0 -133
  154. package/src/components/radio-group/RadioGroupTypes.ts +0 -6
  155. package/src/components/section/Section.astro +0 -167
  156. package/src/components/select/Select.astro +0 -752
  157. package/src/components/select/SelectContent.astro +0 -94
  158. package/src/components/select/SelectGroup.astro +0 -9
  159. package/src/components/select/SelectItem.astro +0 -51
  160. package/src/components/select/SelectLabel.astro +0 -14
  161. package/src/components/select/SelectSearch.astro +0 -49
  162. package/src/components/select/SelectSeparator.astro +0 -12
  163. package/src/components/select/SelectTrigger.astro +0 -56
  164. package/src/components/select/SelectTypes.ts +0 -13
  165. package/src/components/select/SelectValue.astro +0 -19
  166. package/src/components/separator/Separator.astro +0 -36
  167. package/src/components/sheet/Sheet.astro +0 -15
  168. package/src/components/sheet/SheetClose.astro +0 -15
  169. package/src/components/sheet/SheetContent.astro +0 -89
  170. package/src/components/sheet/SheetDescription.astro +0 -16
  171. package/src/components/sheet/SheetFooter.astro +0 -16
  172. package/src/components/sheet/SheetHeader.astro +0 -16
  173. package/src/components/sheet/SheetTitle.astro +0 -16
  174. package/src/components/sheet/SheetTrigger.astro +0 -15
  175. package/src/components/sidebar/Sidebar.astro +0 -231
  176. package/src/components/sidebar/SidebarContent.astro +0 -25
  177. package/src/components/sidebar/SidebarFooter.astro +0 -22
  178. package/src/components/sidebar/SidebarGroup.astro +0 -22
  179. package/src/components/sidebar/SidebarGroupContent.astro +0 -22
  180. package/src/components/sidebar/SidebarGroupLabel.astro +0 -53
  181. package/src/components/sidebar/SidebarHeader.astro +0 -22
  182. package/src/components/sidebar/SidebarInput.astro +0 -24
  183. package/src/components/sidebar/SidebarInset.astro +0 -22
  184. package/src/components/sidebar/SidebarMenu.astro +0 -22
  185. package/src/components/sidebar/SidebarMenuAction.astro +0 -63
  186. package/src/components/sidebar/SidebarMenuBadge.astro +0 -31
  187. package/src/components/sidebar/SidebarMenuButton.astro +0 -124
  188. package/src/components/sidebar/SidebarMenuItem.astro +0 -22
  189. package/src/components/sidebar/SidebarMenuSkeleton.astro +0 -43
  190. package/src/components/sidebar/SidebarMenuSub.astro +0 -25
  191. package/src/components/sidebar/SidebarMenuSubButton.astro +0 -52
  192. package/src/components/sidebar/SidebarMenuSubItem.astro +0 -17
  193. package/src/components/sidebar/SidebarProvider.astro +0 -215
  194. package/src/components/sidebar/SidebarRail.astro +0 -72
  195. package/src/components/sidebar/SidebarSeparator.astro +0 -25
  196. package/src/components/sidebar/SidebarTrigger.astro +0 -69
  197. package/src/components/skeleton/Skeleton.astro +0 -14
  198. package/src/components/slider/Slider.astro +0 -425
  199. package/src/components/spinner/Spinner.astro +0 -23
  200. package/src/components/switch/Switch.astro +0 -192
  201. package/src/components/switch/SwitchTypes.ts +0 -6
  202. package/src/components/table/Table.astro +0 -20
  203. package/src/components/table/TableBody.astro +0 -18
  204. package/src/components/table/TableCaption.astro +0 -18
  205. package/src/components/table/TableCell.astro +0 -18
  206. package/src/components/table/TableFoot.astro +0 -18
  207. package/src/components/table/TableHead.astro +0 -18
  208. package/src/components/table/TableHeader.astro +0 -18
  209. package/src/components/table/TableRow.astro +0 -17
  210. package/src/components/tabs/Tabs.astro +0 -270
  211. package/src/components/tabs/TabsContent.astro +0 -28
  212. package/src/components/tabs/TabsList.astro +0 -23
  213. package/src/components/tabs/TabsTrigger.astro +0 -34
  214. package/src/components/textarea/Textarea.astro +0 -31
  215. package/src/components/toast/ToastDescription.astro +0 -22
  216. package/src/components/toast/ToastItem.astro +0 -56
  217. package/src/components/toast/ToastTemplate.astro +0 -27
  218. package/src/components/toast/ToastTitle.astro +0 -59
  219. package/src/components/toast/Toaster.astro +0 -981
  220. package/src/components/toast/index.ts +0 -1
  221. package/src/components/toast/toast-manager.ts +0 -234
  222. package/src/components/toggle/Toggle.astro +0 -174
  223. package/src/components/toggle/ToggleTypes.ts +0 -14
  224. package/src/components/tooltip/Tooltip.astro +0 -422
  225. package/src/components/tooltip/TooltipContent.astro +0 -83
  226. package/src/components/tooltip/TooltipTrigger.astro +0 -13
  227. package/src/components/video/Video.astro +0 -121
  228. package/src/config/cookies.ts +0 -5
  229. package/src/config/links.ts +0 -4
  230. package/src/domain/cms/index.ts +0 -1
  231. package/src/domain/cms/types.ts +0 -20
  232. package/src/domain/i18n/constants.ts +0 -21
  233. package/src/domain/i18n/cookie-storage.ts +0 -13
  234. package/src/domain/i18n/country-to-locale-map.ts +0 -67
  235. package/src/domain/i18n/fallbacks.generated.ts +0 -230
  236. package/src/domain/i18n/fetcher.ts +0 -278
  237. package/src/domain/i18n/flags.ts +0 -16
  238. package/src/domain/i18n/format.ts +0 -90
  239. package/src/domain/i18n/index.ts +0 -10
  240. package/src/domain/i18n/middleware/i18n.ts +0 -161
  241. package/src/domain/i18n/resolve-locale.ts +0 -55
  242. package/src/domain/i18n/runtime-constants.ts +0 -14
  243. package/src/domain/i18n/schema.ts +0 -29
  244. package/src/domain/index.ts +0 -4
  245. package/src/domain/seo/constants.ts +0 -6
  246. package/src/domain/seo/index.ts +0 -3
  247. package/src/domain/seo/services/index.ts +0 -3
  248. package/src/domain/seo/services/llms.ts +0 -56
  249. package/src/domain/seo/services/robots.ts +0 -12
  250. package/src/domain/seo/services/sitemap.ts +0 -56
  251. package/src/domain/seo/utils.ts +0 -36
  252. package/src/domain/theme/constants.ts +0 -6
  253. package/src/domain/theme/index.ts +0 -2
  254. package/src/domain/theme/schema.ts +0 -10
  255. package/src/i18n.generated.d.ts +0 -202
  256. package/src/lib/component-preview.ts +0 -73
  257. package/src/lib/index.ts +0 -6
  258. package/src/lib/remark/remark-modified-time.ts +0 -13
  259. package/src/lib/showcase-preview-elements.ts +0 -408
  260. package/src/lib/showcase-renderer.ts +0 -218
  261. package/src/lib/showcase-utils.ts +0 -189
  262. package/src/lib/turnstile.ts +0 -35
  263. package/src/lib/utils/starwind/positioning.ts +0 -318
  264. package/src/locales/de/blog.json +0 -9
  265. package/src/locales/de/common.json +0 -19
  266. package/src/locales/de/errors.json +0 -6
  267. package/src/locales/de/home.json +0 -20
  268. package/src/locales/de/messages.json +0 -8
  269. package/src/locales/de/nav.json +0 -13
  270. package/src/locales/de/projects.json +0 -9
  271. package/src/locales/de/services.json +0 -43
  272. package/src/locales/en/blog.json +0 -9
  273. package/src/locales/en/chat.json +0 -29
  274. package/src/locales/en/common.json +0 -19
  275. package/src/locales/en/cookie_notice.json +0 -11
  276. package/src/locales/en/editor.json +0 -24
  277. package/src/locales/en/errors.json +0 -6
  278. package/src/locales/en/home.json +0 -20
  279. package/src/locales/en/messages.json +0 -8
  280. package/src/locales/en/nav.json +0 -13
  281. package/src/locales/en/projects.json +0 -9
  282. package/src/locales/en/services.json +0 -43
  283. package/src/locales/es/blog.json +0 -9
  284. package/src/locales/es/common.json +0 -19
  285. package/src/locales/es/errors.json +0 -6
  286. package/src/locales/es/home.json +0 -20
  287. package/src/locales/es/messages.json +0 -8
  288. package/src/locales/es/nav.json +0 -13
  289. package/src/locales/es/projects.json +0 -9
  290. package/src/locales/es/services.json +0 -43
  291. package/src/locales/ja/blog.json +0 -9
  292. package/src/locales/ja/common.json +0 -19
  293. package/src/locales/ja/errors.json +0 -6
  294. package/src/locales/ja/home.json +0 -20
  295. package/src/locales/ja/messages.json +0 -8
  296. package/src/locales/ja/nav.json +0 -13
  297. package/src/locales/ja/projects.json +0 -9
  298. package/src/locales/ja/services.json +0 -43
  299. package/src/locales/pt/blog.json +0 -9
  300. package/src/locales/pt/chat.json +0 -29
  301. package/src/locales/pt/common.json +0 -19
  302. package/src/locales/pt/cookie_notice.json +0 -11
  303. package/src/locales/pt/editor.json +0 -24
  304. package/src/locales/pt/errors.json +0 -6
  305. package/src/locales/pt/home.json +0 -20
  306. package/src/locales/pt/messages.json +0 -8
  307. package/src/locales/pt/nav.json +0 -13
  308. package/src/locales/pt/projects.json +0 -9
  309. package/src/locales/pt/services.json +0 -43
  310. package/src/utils/server/cookies.ts +0 -98
  311. package/src/utils/server/index.ts +0 -1
  312. package/src/utils/shared/deep-merge.ts +0 -36
  313. package/src/utils/shared/index.ts +0 -3
  314. package/src/utils/shared/parse-boolean.ts +0 -14
  315. /package/src/utils/{shared/embed.ts → embed.ts} +0 -0
@@ -1,44 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { cv } from "css-variants";
4
-
5
- type Props = HTMLAttributes<"button"> & {
6
- /**
7
- * When true, renders as a wrapper div instead of a button,
8
- * allowing a custom trigger element as a child
9
- */
10
- asChild?: boolean;
11
- };
12
-
13
- export const collapsibleTrigger = cv({
14
- base: "starwind-collapsible-trigger",
15
- });
16
-
17
- const { class: className, asChild = false, ...rest } = Astro.props;
18
-
19
- let hasChildren = false;
20
- if (Astro.slots.has("default")) {
21
- hasChildren = true;
22
- }
23
- ---
24
-
25
- {
26
- asChild && hasChildren ? (
27
- <div
28
- class:list={[collapsibleTrigger(), className]}
29
- data-slot="collapsible-trigger"
30
- data-as-child
31
- >
32
- <slot />
33
- </div>
34
- ) : (
35
- <button
36
- type="button"
37
- class:list={[collapsibleTrigger(), className]}
38
- {...rest}
39
- data-slot="collapsible-trigger"
40
- >
41
- <slot />
42
- </button>
43
- )
44
- }
@@ -1,389 +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]} {...rest} data-slot="dialog">
10
- <slot />
11
- </div>
12
-
13
- <script>
14
- // Store instances in a WeakMap to avoid memory leaks
15
- const dialogInstances = new WeakMap<HTMLElement, DialogHandler>();
16
- let dialogCounter = 0;
17
-
18
- class DialogHandler {
19
- private triggers: HTMLButtonElement[] = [];
20
- private dialog: HTMLDialogElement | null = null;
21
- private closeButtons: HTMLButtonElement[] = [];
22
- private backdrop: HTMLElement | null = null;
23
- private dialogWrapper: HTMLElement;
24
- private dialogId: string;
25
- /**
26
- * The duration of the animation in milliseconds. This is used to calculate the
27
- * duration of close animation before hiding the dialog and backdrop
28
- */
29
- private animationDuration: number;
30
- private parentDialog: DialogHandler | null = null;
31
- private nestedOpenCount: number = 0;
32
- private isNested: boolean = false;
33
- private _closeTimeout: number | null = null;
34
- private _isClosing: boolean = false;
35
-
36
- constructor(dialogWrapper: HTMLElement, dialogNumber: number) {
37
- this.dialogWrapper = dialogWrapper;
38
- this.dialog = dialogWrapper.querySelector("dialog");
39
- this.backdrop = dialogWrapper.querySelector(".starwind-dialog-backdrop");
40
- if (!this.dialog || !this.backdrop) {
41
- throw new Error("Dialog: dialog or backdrop not found");
42
- }
43
-
44
- // if no ID was provided for the wrapper, generate one
45
- if (dialogWrapper.id) {
46
- this.dialogId = dialogWrapper.id;
47
- } else {
48
- this.dialogId = `starwind-dialog${dialogNumber}`;
49
- dialogWrapper.id = this.dialogId;
50
- }
51
-
52
- // animationDuration is set with inline styles through passed prop to DialogContent
53
- // if no animationDuration, check data-close-duration
54
- const animationDurationString = this.dialog.style.animationDuration;
55
- if (animationDurationString.endsWith("ms")) {
56
- this.animationDuration = parseFloat(animationDurationString);
57
- } else if (animationDurationString.endsWith("s")) {
58
- // using something like @playform/compress might optimize to use "s" instead of "ms"
59
- this.animationDuration = parseFloat(animationDurationString) * 1000;
60
- } else {
61
- this.animationDuration = this.dialog.dataset.closeDuration
62
- ? parseFloat(this.dialog.dataset.closeDuration)
63
- : 200;
64
- }
65
-
66
- // Find internal triggers and handle them
67
- const internalTriggers = dialogWrapper.querySelectorAll(".starwind-dialog-trigger");
68
- internalTriggers.forEach((triggerElement) => {
69
- const tempTrigger = triggerElement as HTMLElement;
70
- let trigger: HTMLButtonElement;
71
-
72
- if (tempTrigger?.hasAttribute("data-as-child")) {
73
- trigger = tempTrigger.firstElementChild as HTMLButtonElement;
74
- } else {
75
- trigger = tempTrigger as HTMLButtonElement;
76
- }
77
-
78
- if (trigger) {
79
- this.triggers.push(trigger);
80
- }
81
- });
82
-
83
- // Find external triggers that target this dialog
84
- this.findExternalTriggers();
85
-
86
- // if closeButtons are set with asChild, swap the wrapper with its first child
87
- const tempCloseButtons = dialogWrapper.querySelectorAll(
88
- ".starwind-dialog-close",
89
- ) as NodeListOf<HTMLElement>;
90
- tempCloseButtons.forEach((button: HTMLElement) => {
91
- if (button.hasAttribute("data-as-child")) {
92
- const childElement = button.firstElementChild;
93
- if (childElement) {
94
- childElement.classList.add("starwind-dialog-close");
95
- button.parentNode?.replaceChild(childElement, button);
96
- }
97
- }
98
- return button;
99
- });
100
-
101
- // Convert NodeList to Array for consistency with triggers
102
- this.closeButtons = Array.from(
103
- dialogWrapper.querySelectorAll(".starwind-dialog-close"),
104
- ) as HTMLButtonElement[];
105
-
106
- // if essential elements are not there, exit
107
- if (!this.dialog || !this.backdrop) return;
108
-
109
- this.setupAccessibility(dialogNumber);
110
- this.setupEvents();
111
- }
112
-
113
- private setupAccessibility(dialogNumber: number): void {
114
- // get the first heading element in the dialog
115
- const firstHeading = this.dialog?.querySelector("h1, h2, h3, h4, h5, h6");
116
- if (firstHeading) {
117
- // create a unique ID for the heading
118
- firstHeading.id = `starwind-dialog${dialogNumber}-heading`;
119
- // set the aria-labelledby attribute to the first heading element
120
- this.dialog?.setAttribute("aria-labelledby", firstHeading.id);
121
- }
122
- }
123
-
124
- /**
125
- * Find all external triggers that target this dialog
126
- */
127
- private findExternalTriggers(): void {
128
- const externalTriggers = document.querySelectorAll(
129
- `.starwind-dialog-trigger[data-dialog-for="${this.dialogId}"]`,
130
- );
131
-
132
- externalTriggers.forEach((triggerElement) => {
133
- // Skip if this is an internal trigger we already processed
134
- const dialogWrapper = triggerElement.closest(".starwind-dialog");
135
- if (dialogWrapper && dialogWrapper.id === this.dialogId) {
136
- return;
137
- }
138
-
139
- let trigger: HTMLButtonElement;
140
- if (triggerElement.hasAttribute("data-as-child")) {
141
- trigger = triggerElement.firstElementChild as HTMLButtonElement;
142
- } else {
143
- trigger = triggerElement as HTMLButtonElement;
144
- }
145
-
146
- if (trigger && !this.triggers.includes(trigger)) {
147
- this.triggers.push(trigger);
148
- }
149
- });
150
- }
151
-
152
- private setupEvents(): void {
153
- if (!this.dialog) return;
154
-
155
- // Add programmatic open/close via custom events on the wrapper
156
- this.dialogWrapper.addEventListener("dialog:open", () => this.open());
157
- this.dialogWrapper.addEventListener("dialog:close", () => this.close());
158
- this.dialogWrapper.addEventListener("dialog:toggle", () => {
159
- if (this.dialog?.open) {
160
- this.close();
161
- } else {
162
- this.open();
163
- }
164
- });
165
-
166
- // Add click listeners to all triggers
167
- this.triggers.forEach((trigger) => {
168
- trigger.addEventListener("click", () => {
169
- this.open();
170
- });
171
- });
172
-
173
- // Add click handlers to all close buttons
174
- this.closeButtons?.forEach((button) => {
175
- button.addEventListener("click", () => {
176
- // Only close if this is the topmost dialog
177
- const openDialogs = document.querySelectorAll("dialog[open]");
178
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
179
- this.close();
180
- }
181
- });
182
- });
183
-
184
- // Close on click outside
185
- this.dialog.addEventListener("click", (e) => {
186
- if (!this.dialog) return;
187
- const dialogDimensions = this.dialog.getBoundingClientRect();
188
- const clickedInDialog =
189
- e.clientX >= dialogDimensions.left &&
190
- e.clientX <= dialogDimensions.right &&
191
- e.clientY >= dialogDimensions.top &&
192
- e.clientY <= dialogDimensions.bottom;
193
-
194
- if (!clickedInDialog) {
195
- // Only close if this is the topmost dialog
196
- const openDialogs = document.querySelectorAll("dialog[open]");
197
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
198
- this.close();
199
- }
200
- }
201
- });
202
-
203
- // Handle escape key
204
- this.dialog.addEventListener("keydown", (e) => {
205
- if (e.key === "Escape") {
206
- // prevent default dialog closing behavior so we can add closing animation
207
- e.preventDefault();
208
- // Only close if this is the topmost dialog
209
- const openDialogs = document.querySelectorAll("dialog[open]");
210
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
211
- this.close();
212
- }
213
- }
214
- });
215
-
216
- // Intercept form submissions to handle dialog close
217
- const forms = this.dialog.querySelectorAll("form");
218
- forms.forEach((form) => {
219
- form.addEventListener("submit", (e) => {
220
- /**
221
- * Default form.method = "dialog" submissions cause the dialog to close
222
- * Default form.method = "post" submissions do not close the dialog
223
- * Here we intercept the form submission and manage the dialog closing if method = "dialog"
224
- * so we can add closing animation
225
- * Normal form event listeners for "submit" will still get the form data
226
- */
227
- if (form.method === "dialog") {
228
- e.preventDefault();
229
- // Only close if this is the topmost dialog
230
- const openDialogs = document.querySelectorAll("dialog[open]");
231
- if (openDialogs.length > 0 && openDialogs[openDialogs.length - 1] === this.dialog) {
232
- this.close();
233
- }
234
- }
235
- });
236
- });
237
- }
238
-
239
- private open(): void {
240
- if (!this.dialog || !this.backdrop) return;
241
- // Return early if already open
242
- if (this.dialog.open && !this._isClosing) return;
243
-
244
- // Cancel any pending close
245
- if (this._closeTimeout !== null) {
246
- clearTimeout(this._closeTimeout);
247
- this._closeTimeout = null;
248
- }
249
- this._isClosing = false;
250
-
251
- // Reset nested count when opening (in case it wasn't properly reset)
252
- this.nestedOpenCount = 0;
253
- this.updateNestedState();
254
-
255
- this.dialog.showModal();
256
- document.body.classList.add("overflow-hidden");
257
-
258
- // For nested dialogs, hide the backdrop and notify parent
259
- if (this.isNested && this.parentDialog) {
260
- this.backdrop.classList.add("hidden");
261
- this.parentDialog.onNestedDialogOpen();
262
- } else {
263
- this.backdrop.classList.remove("hidden");
264
- this.backdrop.dataset.state = "open";
265
- }
266
-
267
- this.dialog.dataset.state = "open";
268
- }
269
-
270
- private close(): void {
271
- if (!this.dialog || !this.backdrop) return;
272
- // Return early if already closed or closing
273
- if (!this.dialog.open || this._isClosing) return;
274
-
275
- // Clear any existing close timeout
276
- if (this._closeTimeout !== null) {
277
- clearTimeout(this._closeTimeout);
278
- this._closeTimeout = null;
279
- }
280
-
281
- this._isClosing = true;
282
- this.dialog.dataset.state = "closed";
283
-
284
- // Notify parent dialog that nested dialog is closing
285
- if (this.isNested && this.parentDialog) {
286
- this.parentDialog.onNestedDialogClose();
287
- } else {
288
- this.backdrop.dataset.state = "closed";
289
- }
290
-
291
- // Wait for animation to finish before hiding backdrop
292
- this._closeTimeout = window.setTimeout(() => {
293
- if (!this.isNested) {
294
- this.backdrop?.classList.add("hidden");
295
- }
296
- this.dialog?.close();
297
- this._isClosing = false;
298
- this._closeTimeout = null;
299
- const stillOpen = document.querySelectorAll("dialog[open]").length;
300
- if (stillOpen === 0) {
301
- document.body.classList.remove("overflow-hidden");
302
- }
303
- }, this.animationDuration);
304
- }
305
-
306
- /**
307
- * Called by child dialogs when they open
308
- */
309
- public onNestedDialogOpen(): void {
310
- this.nestedOpenCount++;
311
- this.updateNestedState();
312
- // Propagate up the chain to grandparent dialogs
313
- if (this.parentDialog) {
314
- this.parentDialog.onNestedDialogOpen();
315
- }
316
- }
317
-
318
- /**
319
- * Called by child dialogs when they close
320
- */
321
- public onNestedDialogClose(): void {
322
- this.nestedOpenCount = Math.max(0, this.nestedOpenCount - 1);
323
- this.updateNestedState();
324
- // Propagate up the chain to grandparent dialogs
325
- if (this.parentDialog) {
326
- this.parentDialog.onNestedDialogClose();
327
- }
328
- }
329
-
330
- /**
331
- * Updates the nested dialog state attributes
332
- */
333
- private updateNestedState(): void {
334
- if (!this.dialog) return;
335
-
336
- if (this.nestedOpenCount > 0) {
337
- this.dialog.setAttribute("data-nested-dialog-open", "");
338
- this.dialog.style.setProperty("--nested-dialogs", String(this.nestedOpenCount));
339
- } else {
340
- this.dialog.removeAttribute("data-nested-dialog-open");
341
- this.dialog.style.removeProperty("--nested-dialogs");
342
- }
343
- }
344
-
345
- /**
346
- * Links this dialog to its parent dialog (called after all dialogs are initialized)
347
- */
348
- public linkParentDialog(): void {
349
- const parentDialogWrapper = this.dialogWrapper.parentElement?.closest(".starwind-dialog");
350
- if (parentDialogWrapper) {
351
- this.isNested = true;
352
- const parentInstance = dialogInstances.get(parentDialogWrapper as HTMLElement);
353
- if (parentInstance) {
354
- this.parentDialog = parentInstance;
355
- }
356
- }
357
- }
358
- }
359
-
360
- // Initialize all dialogs
361
- const setupDialogs = () => {
362
- // First pass: create all dialog instances
363
- document.querySelectorAll(".starwind-dialog").forEach((dialogWrapper) => {
364
- const wrapper = dialogWrapper as HTMLElement;
365
- if (!dialogInstances.has(wrapper)) {
366
- dialogInstances.set(wrapper, new DialogHandler(wrapper, dialogCounter++));
367
- }
368
- });
369
-
370
- // Second pass: link parent dialogs (now that all instances exist)
371
- document.querySelectorAll(".starwind-dialog").forEach((dialogWrapper) => {
372
- const wrapper = dialogWrapper as HTMLElement;
373
- const instance = dialogInstances.get(wrapper);
374
- if (instance) {
375
- instance.linkParentDialog();
376
- }
377
- });
378
- };
379
-
380
- setupDialogs();
381
- document.addEventListener("astro:after-swap", setupDialogs);
382
- document.addEventListener("starwind:init", setupDialogs);
383
- </script>
384
-
385
- <style>
386
- .overflow-hidden {
387
- overflow: hidden;
388
- }
389
- </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
- {...rest}
30
- data-slot="dialog-close"
31
- >
32
- <slot>Demo close button</slot>
33
- </button>
34
- )
35
- }
@@ -1,78 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { cv } from "css-variants";
4
- import IconX from "~icons/lucide/x";
5
-
6
- type Props = HTMLAttributes<"dialog"> & {
7
- /**
8
- * Open and close animation duration in milliseconds
9
- */
10
- animationDuration?: number;
11
- };
12
-
13
- export const dialogBackdrop = cv({
14
- base: [
15
- "starwind-dialog-backdrop fixed inset-0 top-0 left-0 z-50 hidden h-screen w-screen bg-black/80",
16
- "data-[state=open]:animate-in fade-in",
17
- "data-[state=closed]:animate-out data-[state=closed]:fill-mode-forwards fade-out",
18
- ],
19
- });
20
-
21
- export const dialogContent = cv({
22
- base: [
23
- "starwind-dialog-content",
24
- "fixed top-2xl left-[50%] z-50 translate-x-[-50%] sm:top-[50%] sm:translate-y-[-50%]",
25
- "bg-background w-full max-w-md rounded-lg b p-8 shadow-lg",
26
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fill-mode-forwards transition-[translate,scale,opacity]",
27
- "fade-in zoom-in-95 slide-in-from-bottom-2",
28
- "fade-out zoom-out-95 slide-out-to-bottom-2",
29
- "data-[state=open]:data-[nested-dialog-open]:-translate-y-[calc(50%-var(--nested-offset)*var(--nested-dialogs,1))]",
30
- "data-[state=open]:data-[nested-dialog-open]:scale-[calc(1-var(--nested-scale)*var(--nested-dialogs,1))]",
31
- "max-sm:data-[state=open]:data-[nested-dialog-open]:translate-y-[calc(var(--nested-offset)*var(--nested-dialogs,1))]",
32
- ],
33
- });
34
-
35
- export const dialogCloseButton = cv({
36
- base: [
37
- "starwind-dialog-close text-muted-foreground",
38
- "absolute top-5.5 right-5.5 rounded-sm [&>svg]:op-70 hover:[&>svg]:op-100",
39
- "focus-visible:ring-outline/50 transition-[color,box-shadow] outline-none focus-visible:ring-3",
40
- ],
41
- });
42
-
43
- const { class: className, animationDuration = 200, ...rest } = Astro.props;
44
- ---
45
-
46
- <!-- dialog overlay -->
47
- <slot name="backdrop">
48
- <div
49
- class={dialogBackdrop()}
50
- data-state="closed"
51
- data-slot="dialog-backdrop"
52
- style={{ animationDuration: `${animationDuration}ms` }}
53
- >
54
- </div>
55
- </slot>
56
-
57
- <dialog
58
- class:list={[dialogContent(), className]}
59
- data-state="closed"
60
- style={{ animationDuration: `${animationDuration}ms` }}
61
- {...rest}
62
- data-slot="dialog-content"
63
- >
64
- <slot />
65
- <button type="button" class={dialogCloseButton()} data-dialog-close aria-label="Close dialog">
66
- <slot name="icon">
67
- <IconX class="size-5 transition-opacity" />
68
- </slot>
69
- <span class="sr-only">Close</span>
70
- </button>
71
- </dialog>
72
-
73
- <style>
74
- .starwind-dialog-content {
75
- --nested-offset: var(--spacing-md);
76
- --nested-scale: 0.05;
77
- }
78
- </style>
@@ -1,14 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { cv } from "css-variants";
4
-
5
- type Props = HTMLAttributes<"p">;
6
-
7
- export const dialogDescription = cv({ base: "text-muted-foreground text-sm" });
8
-
9
- const { class: className, ...rest } = Astro.props;
10
- ---
11
-
12
- <p class:list={[dialogDescription(), className]} {...rest} data-slot="dialog-description">
13
- <slot />
14
- </p>
@@ -1,14 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { cv } from "css-variants";
4
-
5
- type Props = HTMLAttributes<"div">;
6
-
7
- export const dialogFooter = cv({ base: "flex flex-col-reverse gap-3xs sm:flex-row sm:justify-end" });
8
-
9
- const { class: className, ...rest } = Astro.props;
10
- ---
11
-
12
- <div class:list={[dialogFooter(), className]} {...rest} data-slot="dialog-footer">
13
- <slot />
14
- </div>
@@ -1,14 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { cv } from "css-variants";
4
-
5
- type Props = HTMLAttributes<"div">;
6
-
7
- export const dialogHeader = cv({ base: "flex flex-col space-y-2 text-center sm:text-left" });
8
-
9
- const { class: className, ...rest } = Astro.props;
10
- ---
11
-
12
- <div class:list={[dialogHeader(), className]} {...rest} data-slot="dialog-header">
13
- <slot />
14
- </div>
@@ -1,18 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import { cv } from "css-variants";
4
-
5
- type Props = Omit<HTMLAttributes<"h2">, "id"> & {
6
- id?: string;
7
- };
8
-
9
- export const dialogTitle = cv({
10
- base: "text-lg font-semibold leading-none tracking-tight",
11
- });
12
-
13
- const { class: className, id, ...rest } = Astro.props;
14
- ---
15
-
16
- <h2 class:list={[dialogTitle(), className]} id={id} {...rest} data-slot="dialog-title">
17
- <slot />
18
- </h2>
@@ -1,47 +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 with a simple wrapper instead of a button component
7
- */
8
- asChild?: boolean;
9
- /**
10
- * Optional ID of the dialog to trigger. If not provided and the trigger is inside a Dialog component,
11
- * it will automatically target that dialog. Required when used outside a Dialog component.
12
- */
13
- for?: string;
14
- };
15
-
16
- const { class: className, asChild = false, for: dialogFor, ...rest } = Astro.props;
17
-
18
- // Get the first child element if asChild is true
19
- let hasChildren = false;
20
- if (Astro.slots.has("default")) {
21
- hasChildren = true;
22
- }
23
- ---
24
-
25
- {
26
- asChild && hasChildren ? (
27
- <div
28
- class:list={["starwind-dialog-trigger", className]}
29
- data-slot="dialog-trigger"
30
- data-as-child
31
- data-dialog-for={dialogFor}
32
- >
33
- <slot />
34
- </div>
35
- ) : (
36
- <button
37
- type="button"
38
- aria-haspopup="dialog"
39
- class:list={["starwind-dialog-trigger", className]}
40
- data-dialog-for={dialogFor}
41
- {...rest}
42
- data-slot="dialog-trigger"
43
- >
44
- <slot />
45
- </button>
46
- )
47
- }