@rimelight/ui 0.0.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.
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/i18n-data.json +186 -0
- package/package.json +49 -0
- package/src/components/FormattedDate.astro +22 -0
- package/src/components/HeaderLink.astro +24 -0
- package/src/components/HttpObservatory.astro +103 -0
- package/src/components/LighthouseScores.astro +204 -0
- package/src/components/MissingTranslationBanner.astro +39 -0
- package/src/components/TableOfContents.astro +106 -0
- package/src/components/ThemeToggle.astro +71 -0
- package/src/components/accordion/Accordion.astro +257 -0
- package/src/components/accordion/AccordionContent.astro +34 -0
- package/src/components/accordion/AccordionItem.astro +29 -0
- package/src/components/accordion/AccordionTrigger.astro +33 -0
- package/src/components/alert/Alert.astro +34 -0
- package/src/components/alert/AlertDescription.astro +15 -0
- package/src/components/alert/AlertTitle.astro +17 -0
- package/src/components/alert-dialog/AlertDialog.astro +275 -0
- package/src/components/alert-dialog/AlertDialogAction.astro +46 -0
- package/src/components/alert-dialog/AlertDialogCancel.astro +46 -0
- package/src/components/alert-dialog/AlertDialogContent.astro +52 -0
- package/src/components/alert-dialog/AlertDialogDescription.astro +18 -0
- package/src/components/alert-dialog/AlertDialogFooter.astro +16 -0
- package/src/components/alert-dialog/AlertDialogHeader.astro +14 -0
- package/src/components/alert-dialog/AlertDialogTitle.astro +20 -0
- package/src/components/alert-dialog/AlertDialogTrigger.astro +47 -0
- package/src/components/aspect-ratio/AspectRatio.astro +32 -0
- package/src/components/avatar/Avatar.astro +29 -0
- package/src/components/avatar/AvatarFallback.astro +18 -0
- package/src/components/avatar/AvatarImage.astro +66 -0
- package/src/components/badge/Badge.astro +57 -0
- package/src/components/breadcrumb/Breadcrumb.astro +12 -0
- package/src/components/breadcrumb/BreadcrumbEllipsis.astro +29 -0
- package/src/components/breadcrumb/BreadcrumbItem.astro +15 -0
- package/src/components/breadcrumb/BreadcrumbLink.astro +24 -0
- package/src/components/breadcrumb/BreadcrumbList.astro +17 -0
- package/src/components/breadcrumb/BreadcrumbPage.astro +22 -0
- package/src/components/breadcrumb/BreadcrumbSeparator.astro +24 -0
- package/src/components/button/Button.astro +58 -0
- package/src/components/button-group/ButtonGroup.astro +64 -0
- package/src/components/button-group/ButtonGroupSeparator.astro +20 -0
- package/src/components/button-group/ButtonGroupText.astro +19 -0
- package/src/components/card/Card.astro +36 -0
- package/src/components/card/CardAction.astro +16 -0
- package/src/components/card/CardContent.astro +16 -0
- package/src/components/card/CardDescription.astro +16 -0
- package/src/components/card/CardFooter.astro +16 -0
- package/src/components/card/CardHeader.astro +19 -0
- package/src/components/card/CardTitle.astro +16 -0
- package/src/components/carousel/Carousel.astro +55 -0
- package/src/components/carousel/CarouselContent.astro +26 -0
- package/src/components/carousel/CarouselItem.astro +26 -0
- package/src/components/carousel/CarouselNext.astro +39 -0
- package/src/components/carousel/CarouselPrevious.astro +41 -0
- package/src/components/carousel/carousel-script.ts +188 -0
- package/src/components/carousel/index.ts +1 -0
- package/src/components/checkbox/Checkbox.astro +133 -0
- package/src/components/collapsible/Collapsible.astro +161 -0
- package/src/components/collapsible/CollapsibleContent.astro +22 -0
- package/src/components/collapsible/CollapsibleTrigger.astro +44 -0
- package/src/components/dialog/Dialog.astro +389 -0
- package/src/components/dialog/DialogClose.astro +35 -0
- package/src/components/dialog/DialogContent.astro +78 -0
- package/src/components/dialog/DialogDescription.astro +14 -0
- package/src/components/dialog/DialogFooter.astro +14 -0
- package/src/components/dialog/DialogHeader.astro +14 -0
- package/src/components/dialog/DialogTitle.astro +18 -0
- package/src/components/dialog/DialogTrigger.astro +47 -0
- package/src/components/dropdown/Dropdown.astro +604 -0
- package/src/components/dropdown/DropdownContent.astro +118 -0
- package/src/components/dropdown/DropdownItem.astro +48 -0
- package/src/components/dropdown/DropdownLabel.astro +29 -0
- package/src/components/dropdown/DropdownSeparator.astro +21 -0
- package/src/components/dropdown/DropdownShortcut.astro +17 -0
- package/src/components/dropdown/DropdownSub.astro +15 -0
- package/src/components/dropdown/DropdownSubContent.astro +39 -0
- package/src/components/dropdown/DropdownSubTrigger.astro +34 -0
- package/src/components/dropdown/DropdownTrigger.astro +52 -0
- package/src/components/dropzone/Dropzone.astro +236 -0
- package/src/components/dropzone/DropzoneFilesList.astro +26 -0
- package/src/components/dropzone/DropzoneLoadingIndicator.astro +10 -0
- package/src/components/dropzone/DropzoneUploadIndicator.astro +10 -0
- package/src/components/embeds/YoutubeEmbed.astro +94 -0
- package/src/components/hero/Hero.astro +166 -0
- package/src/components/icons/Flag.astro +62 -0
- package/src/components/image/ExtendedImage.astro +46 -0
- package/src/components/image/Image.astro +25 -0
- package/src/components/input/Input.astro +27 -0
- package/src/components/input-group/InputGroup.astro +28 -0
- package/src/components/input-group/InputGroupAddon.astro +76 -0
- package/src/components/input-group/InputGroupButton.astro +36 -0
- package/src/components/input-group/InputGroupInput.astro +18 -0
- package/src/components/input-group/InputGroupText.astro +17 -0
- package/src/components/input-group/InputGroupTextarea.astro +22 -0
- package/src/components/input-otp/InputOtp.astro +352 -0
- package/src/components/input-otp/InputOtpGroup.astro +16 -0
- package/src/components/input-otp/InputOtpSeparator.astro +25 -0
- package/src/components/input-otp/InputOtpSlot.astro +50 -0
- package/src/components/input-otp/InputOtpTypes.ts +6 -0
- package/src/components/item/Item.astro +52 -0
- package/src/components/item/ItemActions.astro +16 -0
- package/src/components/item/ItemContent.astro +16 -0
- package/src/components/item/ItemDescription.astro +19 -0
- package/src/components/item/ItemFooter.astro +16 -0
- package/src/components/item/ItemGroup.astro +16 -0
- package/src/components/item/ItemHeader.astro +16 -0
- package/src/components/item/ItemMedia.astro +40 -0
- package/src/components/item/ItemSeparator.astro +23 -0
- package/src/components/item/ItemTitle.astro +16 -0
- package/src/components/kbd/Kbd.astro +21 -0
- package/src/components/kbd/KbdGroup.astro +16 -0
- package/src/components/label/Label.astro +24 -0
- package/src/components/marquee/Marquee.astro +73 -0
- package/src/components/native-select/NativeSelect.astro +68 -0
- package/src/components/native-select/NativeSelectOptGroup.astro +15 -0
- package/src/components/native-select/NativeSelectOption.astro +15 -0
- package/src/components/pagination/Pagination.astro +20 -0
- package/src/components/pagination/PaginationContent.astro +16 -0
- package/src/components/pagination/PaginationEllipsis.astro +37 -0
- package/src/components/pagination/PaginationItem.astro +16 -0
- package/src/components/pagination/PaginationLink.astro +27 -0
- package/src/components/pagination/PaginationNext.astro +33 -0
- package/src/components/pagination/PaginationPrevious.astro +33 -0
- package/src/components/popover/Popover.astro +717 -0
- package/src/components/popover/PopoverContent.astro +102 -0
- package/src/components/popover/PopoverDescription.astro +14 -0
- package/src/components/popover/PopoverHeader.astro +14 -0
- package/src/components/popover/PopoverTitle.astro +14 -0
- package/src/components/popover/PopoverTrigger.astro +51 -0
- package/src/components/progress/Progress.astro +154 -0
- package/src/components/prose/Prose.astro +619 -0
- package/src/components/radio-group/RadioGroup.astro +162 -0
- package/src/components/radio-group/RadioGroupItem.astro +133 -0
- package/src/components/radio-group/RadioGroupTypes.ts +6 -0
- package/src/components/section/Section.astro +167 -0
- package/src/components/select/Select.astro +752 -0
- package/src/components/select/SelectContent.astro +94 -0
- package/src/components/select/SelectGroup.astro +9 -0
- package/src/components/select/SelectItem.astro +51 -0
- package/src/components/select/SelectLabel.astro +14 -0
- package/src/components/select/SelectSearch.astro +49 -0
- package/src/components/select/SelectSeparator.astro +12 -0
- package/src/components/select/SelectTrigger.astro +56 -0
- package/src/components/select/SelectTypes.ts +13 -0
- package/src/components/select/SelectValue.astro +19 -0
- package/src/components/separator/Separator.astro +36 -0
- package/src/components/sheet/Sheet.astro +15 -0
- package/src/components/sheet/SheetClose.astro +15 -0
- package/src/components/sheet/SheetContent.astro +89 -0
- package/src/components/sheet/SheetDescription.astro +16 -0
- package/src/components/sheet/SheetFooter.astro +16 -0
- package/src/components/sheet/SheetHeader.astro +16 -0
- package/src/components/sheet/SheetTitle.astro +16 -0
- package/src/components/sheet/SheetTrigger.astro +15 -0
- package/src/components/sidebar/Sidebar.astro +231 -0
- package/src/components/sidebar/SidebarContent.astro +25 -0
- package/src/components/sidebar/SidebarFooter.astro +22 -0
- package/src/components/sidebar/SidebarGroup.astro +22 -0
- package/src/components/sidebar/SidebarGroupContent.astro +22 -0
- package/src/components/sidebar/SidebarGroupLabel.astro +53 -0
- package/src/components/sidebar/SidebarHeader.astro +22 -0
- package/src/components/sidebar/SidebarInput.astro +24 -0
- package/src/components/sidebar/SidebarInset.astro +22 -0
- package/src/components/sidebar/SidebarMenu.astro +22 -0
- package/src/components/sidebar/SidebarMenuAction.astro +63 -0
- package/src/components/sidebar/SidebarMenuBadge.astro +31 -0
- package/src/components/sidebar/SidebarMenuButton.astro +124 -0
- package/src/components/sidebar/SidebarMenuItem.astro +22 -0
- package/src/components/sidebar/SidebarMenuSkeleton.astro +43 -0
- package/src/components/sidebar/SidebarMenuSub.astro +25 -0
- package/src/components/sidebar/SidebarMenuSubButton.astro +52 -0
- package/src/components/sidebar/SidebarMenuSubItem.astro +17 -0
- package/src/components/sidebar/SidebarProvider.astro +215 -0
- package/src/components/sidebar/SidebarRail.astro +72 -0
- package/src/components/sidebar/SidebarSeparator.astro +25 -0
- package/src/components/sidebar/SidebarTrigger.astro +69 -0
- package/src/components/skeleton/Skeleton.astro +14 -0
- package/src/components/slider/Slider.astro +425 -0
- package/src/components/spinner/Spinner.astro +23 -0
- package/src/components/switch/Switch.astro +192 -0
- package/src/components/switch/SwitchTypes.ts +6 -0
- package/src/components/table/Table.astro +20 -0
- package/src/components/table/TableBody.astro +18 -0
- package/src/components/table/TableCaption.astro +18 -0
- package/src/components/table/TableCell.astro +18 -0
- package/src/components/table/TableFoot.astro +18 -0
- package/src/components/table/TableHead.astro +18 -0
- package/src/components/table/TableHeader.astro +18 -0
- package/src/components/table/TableRow.astro +17 -0
- package/src/components/tabs/Tabs.astro +270 -0
- package/src/components/tabs/TabsContent.astro +28 -0
- package/src/components/tabs/TabsList.astro +23 -0
- package/src/components/tabs/TabsTrigger.astro +34 -0
- package/src/components/textarea/Textarea.astro +31 -0
- package/src/components/toast/ToastDescription.astro +22 -0
- package/src/components/toast/ToastItem.astro +56 -0
- package/src/components/toast/ToastTemplate.astro +27 -0
- package/src/components/toast/ToastTitle.astro +59 -0
- package/src/components/toast/Toaster.astro +981 -0
- package/src/components/toast/index.ts +1 -0
- package/src/components/toast/toast-manager.ts +234 -0
- package/src/components/toggle/Toggle.astro +174 -0
- package/src/components/toggle/ToggleTypes.ts +14 -0
- package/src/components/tooltip/Tooltip.astro +422 -0
- package/src/components/tooltip/TooltipContent.astro +83 -0
- package/src/components/tooltip/TooltipTrigger.astro +13 -0
- package/src/components/video/Video.astro +121 -0
- package/src/config/cookies.ts +5 -0
- package/src/config/index.ts +3 -0
- package/src/config/links.ts +4 -0
- package/src/config/site.config.ts +45 -0
- package/src/domain/cms/index.ts +1 -0
- package/src/domain/cms/types.ts +20 -0
- package/src/domain/i18n/constants.ts +21 -0
- package/src/domain/i18n/cookie-storage.ts +13 -0
- package/src/domain/i18n/country-to-locale-map.ts +67 -0
- package/src/domain/i18n/fallbacks.generated.ts +230 -0
- package/src/domain/i18n/fetcher.ts +268 -0
- package/src/domain/i18n/flags.ts +16 -0
- package/src/domain/i18n/format.ts +90 -0
- package/src/domain/i18n/index.ts +10 -0
- package/src/domain/i18n/middleware/i18n.ts +160 -0
- package/src/domain/i18n/resolve-locale.ts +55 -0
- package/src/domain/i18n/runtime-constants.ts +14 -0
- package/src/domain/i18n/schema.ts +29 -0
- package/src/domain/index.ts +4 -0
- package/src/domain/seo/constants.ts +20 -0
- package/src/domain/seo/index.ts +3 -0
- package/src/domain/seo/services/index.ts +3 -0
- package/src/domain/seo/services/llms.ts +53 -0
- package/src/domain/seo/services/robots.ts +12 -0
- package/src/domain/seo/services/sitemap.ts +56 -0
- package/src/domain/seo/utils.ts +37 -0
- package/src/domain/theme/constants.ts +6 -0
- package/src/domain/theme/index.ts +2 -0
- package/src/domain/theme/schema.ts +10 -0
- package/src/env.d.ts +49 -0
- package/src/i18n.generated.d.ts +202 -0
- package/src/lib/component-preview.ts +73 -0
- package/src/lib/index.ts +6 -0
- package/src/lib/remark/remark-modified-time.ts +13 -0
- package/src/lib/showcase-preview-elements.ts +408 -0
- package/src/lib/showcase-renderer.ts +218 -0
- package/src/lib/showcase-utils.ts +189 -0
- package/src/lib/turnstile.ts +35 -0
- package/src/lib/utils/starwind/positioning.ts +318 -0
- package/src/locales/de/blog.json +9 -0
- package/src/locales/de/common.json +19 -0
- package/src/locales/de/errors.json +6 -0
- package/src/locales/de/home.json +20 -0
- package/src/locales/de/messages.json +8 -0
- package/src/locales/de/nav.json +13 -0
- package/src/locales/de/projects.json +9 -0
- package/src/locales/de/services.json +43 -0
- package/src/locales/en/blog.json +9 -0
- package/src/locales/en/chat.json +29 -0
- package/src/locales/en/common.json +19 -0
- package/src/locales/en/cookie_notice.json +11 -0
- package/src/locales/en/editor.json +24 -0
- package/src/locales/en/errors.json +6 -0
- package/src/locales/en/home.json +20 -0
- package/src/locales/en/messages.json +8 -0
- package/src/locales/en/nav.json +13 -0
- package/src/locales/en/projects.json +9 -0
- package/src/locales/en/services.json +43 -0
- package/src/locales/es/blog.json +9 -0
- package/src/locales/es/common.json +19 -0
- package/src/locales/es/errors.json +6 -0
- package/src/locales/es/home.json +20 -0
- package/src/locales/es/messages.json +8 -0
- package/src/locales/es/nav.json +13 -0
- package/src/locales/es/projects.json +9 -0
- package/src/locales/es/services.json +43 -0
- package/src/locales/ja/blog.json +9 -0
- package/src/locales/ja/common.json +19 -0
- package/src/locales/ja/errors.json +6 -0
- package/src/locales/ja/home.json +20 -0
- package/src/locales/ja/messages.json +8 -0
- package/src/locales/ja/nav.json +13 -0
- package/src/locales/ja/projects.json +9 -0
- package/src/locales/ja/services.json +43 -0
- package/src/locales/pt/blog.json +9 -0
- package/src/locales/pt/chat.json +29 -0
- package/src/locales/pt/common.json +19 -0
- package/src/locales/pt/cookie_notice.json +11 -0
- package/src/locales/pt/editor.json +24 -0
- package/src/locales/pt/errors.json +6 -0
- package/src/locales/pt/home.json +20 -0
- package/src/locales/pt/messages.json +8 -0
- package/src/locales/pt/nav.json +13 -0
- package/src/locales/pt/projects.json +9 -0
- package/src/locales/pt/services.json +43 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/server/cookies.ts +98 -0
- package/src/utils/server/index.ts +1 -0
- package/src/utils/shared/deep-merge.ts +36 -0
- package/src/utils/shared/embed.ts +105 -0
- package/src/utils/shared/index.ts +3 -0
- package/src/utils/shared/parse-boolean.ts +14 -0
- package/worker-configuration.d.ts +14791 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
type VariantProps<T extends (...args: any) => any> = NonNullable<Parameters<T>[0]>;
|
|
6
|
+
|
|
7
|
+
type Props = HTMLAttributes<"caption"> & VariantProps<typeof tableCaption>;
|
|
8
|
+
|
|
9
|
+
export const tableCaption = cv({
|
|
10
|
+
base: "text-muted-foreground mt-2xl text-sm",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<caption class:list={[tableCaption(), className]} {...rest} data-slot="table-caption">
|
|
17
|
+
<slot />
|
|
18
|
+
</caption>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
type VariantProps<T extends (...args: any) => any> = NonNullable<Parameters<T>[0]>;
|
|
6
|
+
|
|
7
|
+
type Props = HTMLAttributes<"td"> & VariantProps<typeof tableCell>;
|
|
8
|
+
|
|
9
|
+
export const tableCell = cv({
|
|
10
|
+
base: "p-5xs align-middle ws-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-6xs",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<td class:list={[tableCell(), className]} {...rest} data-slot="table-cell">
|
|
17
|
+
<slot />
|
|
18
|
+
</td>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
type VariantProps<T extends (...args: any) => any> = NonNullable<Parameters<T>[0]>;
|
|
6
|
+
|
|
7
|
+
type Props = HTMLAttributes<"tfoot"> & VariantProps<typeof tableFoot>;
|
|
8
|
+
|
|
9
|
+
export const tableFoot = cv({
|
|
10
|
+
base: "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<tfoot class:list={[tableFoot(), className]} {...rest} data-slot="table-foot">
|
|
17
|
+
<slot />
|
|
18
|
+
</tfoot>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
type VariantProps<T extends (...args: any) => any> = NonNullable<Parameters<T>[0]>;
|
|
6
|
+
|
|
7
|
+
type Props = HTMLAttributes<"th"> & VariantProps<typeof tableHead>;
|
|
8
|
+
|
|
9
|
+
export const tableHead = cv({
|
|
10
|
+
base: "text-muted-foreground h-2xs px-5xs text-left align-middle font-medium ws-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-6xs",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<th class:list={[tableHead(), className]} {...rest} data-slot="table-head">
|
|
17
|
+
<slot />
|
|
18
|
+
</th>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
type VariantProps<T extends (...args: any) => any> = NonNullable<Parameters<T>[0]>;
|
|
6
|
+
|
|
7
|
+
type Props = HTMLAttributes<"thead"> & VariantProps<typeof tableHeader>;
|
|
8
|
+
|
|
9
|
+
export const tableHeader = cv({
|
|
10
|
+
base: "[&_tr]:border-b",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<thead class:list={[tableHeader(), className]} {...rest} data-slot="table-header">
|
|
17
|
+
<slot />
|
|
18
|
+
</thead>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types"
|
|
3
|
+
import { cv } from "css-variants"
|
|
4
|
+
|
|
5
|
+
type VariantProps<T extends (...args: any) => any> = NonNullable<Parameters<T>[0]>
|
|
6
|
+
type Props = HTMLAttributes<"tr"> & VariantProps<typeof tableRow>
|
|
7
|
+
|
|
8
|
+
export const tableRow = cv({
|
|
9
|
+
base: "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted"
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const { class: className, ...rest } = Astro.props
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<tr role="row" class:list={[tableRow(), className]} {...rest} data-slot="table-row">
|
|
16
|
+
<slot />
|
|
17
|
+
</tr>
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
interface Props extends HTMLAttributes<"div"> {
|
|
6
|
+
defaultValue?: string;
|
|
7
|
+
syncKey?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const tabs = cv({ base: "starwind-tabs" });
|
|
11
|
+
|
|
12
|
+
const { defaultValue, syncKey, class: className, ...rest } = Astro.props;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
class:list={[tabs(), className]}
|
|
17
|
+
data-default-value={defaultValue}
|
|
18
|
+
data-sync-key={syncKey}
|
|
19
|
+
{...rest}
|
|
20
|
+
data-slot="tabs"
|
|
21
|
+
>
|
|
22
|
+
<slot />
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<script>
|
|
26
|
+
type TabValue = string;
|
|
27
|
+
|
|
28
|
+
interface TabsSyncEventDetail {
|
|
29
|
+
value: TabValue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface TabsSyncEvent extends CustomEvent<TabsSyncEventDetail> {
|
|
33
|
+
type: `starwind-tabs-sync:${string}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class TabsHandler {
|
|
37
|
+
private tabs: HTMLElement;
|
|
38
|
+
private triggers: HTMLButtonElement[];
|
|
39
|
+
private contents: HTMLElement[];
|
|
40
|
+
private currentTabIndex: number = 0;
|
|
41
|
+
private tabsId: string;
|
|
42
|
+
private syncKey: string | undefined;
|
|
43
|
+
private storageKey: string;
|
|
44
|
+
private valueToTriggerMap: Map<string, HTMLButtonElement>;
|
|
45
|
+
private valueToContentMap: Map<string, HTMLElement>;
|
|
46
|
+
|
|
47
|
+
constructor(tabs: HTMLElement, idx: number) {
|
|
48
|
+
this.tabs = tabs;
|
|
49
|
+
this.triggers = Array.from(
|
|
50
|
+
tabs.querySelectorAll(":scope > [data-tabs-list] > [data-tabs-trigger]"),
|
|
51
|
+
);
|
|
52
|
+
this.contents = Array.from(tabs.querySelectorAll(":scope > [data-tabs-content]"));
|
|
53
|
+
this.tabsId = `starwind-tabs${idx}`;
|
|
54
|
+
this.syncKey = tabs.dataset.syncKey;
|
|
55
|
+
this.storageKey = this.syncKey
|
|
56
|
+
? `starwind-tabs-${this.syncKey}`
|
|
57
|
+
: `starwind-tabs-${this.tabsId}`;
|
|
58
|
+
|
|
59
|
+
// Create maps for faster lookups
|
|
60
|
+
this.valueToTriggerMap = new Map(
|
|
61
|
+
this.triggers.map((trigger) => [trigger.getAttribute("data-value") ?? "", trigger]),
|
|
62
|
+
);
|
|
63
|
+
this.valueToContentMap = new Map(
|
|
64
|
+
this.contents.map((content) => [content.getAttribute("data-value") ?? "", content]),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
this.setupIds();
|
|
68
|
+
this.initializeTab();
|
|
69
|
+
this.addEventListeners();
|
|
70
|
+
|
|
71
|
+
if (this.syncKey) {
|
|
72
|
+
this.setupSyncListener();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private initializeTab(): void {
|
|
77
|
+
const value = this.syncKey
|
|
78
|
+
? (localStorage.getItem(this.storageKey) ?? this.tabs.dataset.defaultValue)
|
|
79
|
+
: this.tabs.dataset.defaultValue;
|
|
80
|
+
|
|
81
|
+
if (value) {
|
|
82
|
+
this.showTab(value);
|
|
83
|
+
this.currentTabIndex = this.triggers.findIndex(
|
|
84
|
+
(trigger) => trigger.getAttribute("data-value") === value,
|
|
85
|
+
);
|
|
86
|
+
this.setTabIndex();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private setupSyncListener(): void {
|
|
91
|
+
document.addEventListener(`starwind-tabs-sync:${this.syncKey}`, ((e: TabsSyncEvent) => {
|
|
92
|
+
const value = e.detail.value;
|
|
93
|
+
const trigger = this.valueToTriggerMap.get(value);
|
|
94
|
+
const index = trigger ? this.triggers.indexOf(trigger) : -1;
|
|
95
|
+
|
|
96
|
+
if (index !== -1) {
|
|
97
|
+
this.showTab(value);
|
|
98
|
+
this.currentTabIndex = index;
|
|
99
|
+
this.setTabIndex();
|
|
100
|
+
}
|
|
101
|
+
}) as EventListener);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private setupIds(): void {
|
|
105
|
+
this.triggers.forEach((trigger, idx) => {
|
|
106
|
+
const triggerId = `${this.tabsId}-t${idx}`;
|
|
107
|
+
const contentId = `${this.tabsId}-c${idx}`;
|
|
108
|
+
const value = trigger.getAttribute("data-value");
|
|
109
|
+
|
|
110
|
+
trigger.id = triggerId;
|
|
111
|
+
|
|
112
|
+
if (value) {
|
|
113
|
+
trigger.setAttribute("aria-controls", contentId);
|
|
114
|
+
const content = this.valueToContentMap.get(value);
|
|
115
|
+
if (content) {
|
|
116
|
+
content.id = contentId;
|
|
117
|
+
content.setAttribute("aria-labelledby", triggerId);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private setTabIndex(): void {
|
|
124
|
+
this.triggers.forEach((trigger, index) => {
|
|
125
|
+
trigger.setAttribute("tabindex", index === this.currentTabIndex ? "0" : "-1");
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private dispatchSyncEvent(value: TabValue): void {
|
|
130
|
+
if (!this.syncKey) return;
|
|
131
|
+
|
|
132
|
+
document.dispatchEvent(
|
|
133
|
+
new CustomEvent(`starwind-tabs-sync:${this.syncKey}`, { detail: { value } }),
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
localStorage.setItem(this.storageKey, value);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private handleKeyNavigation = (e: KeyboardEvent): void => {
|
|
140
|
+
const key = e.key;
|
|
141
|
+
let newIndex = this.currentTabIndex;
|
|
142
|
+
|
|
143
|
+
switch (key) {
|
|
144
|
+
case "ArrowRight": {
|
|
145
|
+
for (let i = 1; i < this.triggers.length; i++) {
|
|
146
|
+
const index = (this.currentTabIndex + i) % this.triggers.length;
|
|
147
|
+
if (this.triggers[index] && !this.triggers[index]!.disabled) {
|
|
148
|
+
newIndex = index;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case "ArrowLeft": {
|
|
155
|
+
for (let i = 1; i < this.triggers.length; i++) {
|
|
156
|
+
const index = (this.currentTabIndex - i + this.triggers.length) % this.triggers.length;
|
|
157
|
+
if (this.triggers[index] && !this.triggers[index]!.disabled) {
|
|
158
|
+
newIndex = index;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case "Home": {
|
|
165
|
+
for (let i = 0; i < this.triggers.length; i++) {
|
|
166
|
+
if (this.triggers[i] && !this.triggers[i]!.disabled) {
|
|
167
|
+
newIndex = i;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case "End": {
|
|
174
|
+
for (let i = this.triggers.length - 1; i >= 0; i--) {
|
|
175
|
+
if (this.triggers[i] && !this.triggers[i]!.disabled) {
|
|
176
|
+
newIndex = i;
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
default:
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
const newTrigger = this.triggers[newIndex];
|
|
188
|
+
if (!newTrigger) return;
|
|
189
|
+
const value = newTrigger.getAttribute("data-value");
|
|
190
|
+
if (value) {
|
|
191
|
+
this.showTab(value);
|
|
192
|
+
this.currentTabIndex = newIndex;
|
|
193
|
+
this.setTabIndex();
|
|
194
|
+
newTrigger.focus();
|
|
195
|
+
this.dispatchSyncEvent(value);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
private handleClick = (trigger: HTMLElement, index: number): void => {
|
|
200
|
+
const value = trigger.getAttribute("data-value");
|
|
201
|
+
if (value) {
|
|
202
|
+
this.showTab(value);
|
|
203
|
+
this.currentTabIndex = index;
|
|
204
|
+
this.setTabIndex();
|
|
205
|
+
trigger.focus();
|
|
206
|
+
this.dispatchSyncEvent(value);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
private addEventListeners(): void {
|
|
211
|
+
this.triggers.forEach((trigger, index) => {
|
|
212
|
+
trigger.addEventListener("click", () => this.handleClick(trigger, index));
|
|
213
|
+
trigger.addEventListener("keydown", (e) => this.handleKeyNavigation(e));
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private showTab(value: TabValue): void {
|
|
218
|
+
const trigger = this.valueToTriggerMap.get(value);
|
|
219
|
+
const content = this.valueToContentMap.get(value);
|
|
220
|
+
|
|
221
|
+
if (!trigger || !content) return;
|
|
222
|
+
|
|
223
|
+
// Update all triggers and contents
|
|
224
|
+
this.triggers.forEach((t) => {
|
|
225
|
+
const isActive = t === trigger;
|
|
226
|
+
t.setAttribute("data-state", isActive ? "active" : "inactive");
|
|
227
|
+
t.setAttribute("aria-selected", isActive.toString());
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
this.contents.forEach((c) => {
|
|
231
|
+
const isActive = c === content;
|
|
232
|
+
c.setAttribute("data-state", isActive ? "active" : "inactive");
|
|
233
|
+
c.hidden = !isActive;
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Initialize any nested tabs in the active content
|
|
237
|
+
if (content.hasAttribute("data-state") && content.getAttribute("data-state") === "active") {
|
|
238
|
+
const nestedTabs = content.querySelectorAll<HTMLElement>(".starwind-tabs");
|
|
239
|
+
|
|
240
|
+
nestedTabs.forEach((nestedTab, nestedIdx) => {
|
|
241
|
+
// Skip tabs that already have instances
|
|
242
|
+
if (!tabInstances.has(nestedTab)) {
|
|
243
|
+
const uniqueIdx = 1000 + nestedIdx;
|
|
244
|
+
const handler = new TabsHandler(nestedTab, uniqueIdx);
|
|
245
|
+
tabInstances.set(nestedTab, handler);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Store instances in a WeakMap to avoid memory leaks
|
|
253
|
+
const tabInstances = new WeakMap<HTMLElement, TabsHandler>();
|
|
254
|
+
let tabCounter = 0;
|
|
255
|
+
|
|
256
|
+
const setupTabs = () => {
|
|
257
|
+
// First handle top-level tabs
|
|
258
|
+
document.querySelectorAll<HTMLElement>(".starwind-tabs").forEach((tabs) => {
|
|
259
|
+
// Skip tabs that are nested within other tab contents
|
|
260
|
+
const isNested = !!tabs.closest("[data-tabs-content]");
|
|
261
|
+
if (!isNested && !tabInstances.has(tabs)) {
|
|
262
|
+
tabInstances.set(tabs, new TabsHandler(tabs, tabCounter++));
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
setupTabs();
|
|
268
|
+
document.addEventListener("astro:after-swap", setupTabs);
|
|
269
|
+
document.addEventListener("starwind:init", setupTabs);
|
|
270
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
interface Props extends Omit<HTMLAttributes<"div">, "id" | "role" | "tabindex" | "hidden"> {
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const tabsContent = cv({
|
|
10
|
+
base: "mt-3xs focus-visible:outline-2 focus-visible:outline-offset-2",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { value, class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class:list={[tabsContent(), className]}
|
|
18
|
+
data-tabs-content
|
|
19
|
+
data-value={value}
|
|
20
|
+
data-state="inactive"
|
|
21
|
+
role="tabpanel"
|
|
22
|
+
tabindex="0"
|
|
23
|
+
hidden
|
|
24
|
+
{...rest}
|
|
25
|
+
data-slot="tabs-content"
|
|
26
|
+
>
|
|
27
|
+
<slot />
|
|
28
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
type Props = HTMLAttributes<"div">;
|
|
6
|
+
|
|
7
|
+
export const tabsList = cv({
|
|
8
|
+
base: [
|
|
9
|
+
"bg-muted text-muted-foreground inline-flex h-3xl items-center justify-start gap-5xs rounded-lg p-5xs",
|
|
10
|
+
],
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class:list={[tabsList(), className]}
|
|
18
|
+
role="tablist"
|
|
19
|
+
{...rest}
|
|
20
|
+
data-slot="tabs-list"
|
|
21
|
+
>
|
|
22
|
+
<slot />
|
|
23
|
+
</div>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
interface Props extends Omit<HTMLAttributes<"button">, "type" | "id" | "role"> {
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const tabsTrigger = cv({
|
|
10
|
+
base: [
|
|
11
|
+
"inline-flex grow items-center justify-center gap-3xs rounded-sm b border-transparent px-xs py-5xs font-medium ws-nowrap transition-[color,box-shadow]",
|
|
12
|
+
"data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
|
13
|
+
"dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:text-muted-foreground",
|
|
14
|
+
"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
15
|
+
"focus-visible:border-outline focus-visible:ring-outline/50 focus-visible:outline-outline focus-visible:ring-3 focus-visible:outline-1",
|
|
16
|
+
"disabled:pointer-events-none disabled:op-50",
|
|
17
|
+
],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const { value, class: className, ...rest } = Astro.props;
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<button
|
|
24
|
+
class:list={[tabsTrigger(), className]}
|
|
25
|
+
data-tabs-trigger
|
|
26
|
+
data-value={value}
|
|
27
|
+
data-state="inactive"
|
|
28
|
+
role="tab"
|
|
29
|
+
aria-selected="false"
|
|
30
|
+
{...rest}
|
|
31
|
+
data-slot="tabs-trigger"
|
|
32
|
+
>
|
|
33
|
+
<slot />
|
|
34
|
+
</button>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
type VariantProps<T extends (...args: any) => any> = NonNullable<Parameters<T>[0]>;
|
|
6
|
+
|
|
7
|
+
type Props = HTMLAttributes<"textarea"> & VariantProps<typeof textarea>;
|
|
8
|
+
|
|
9
|
+
export const textarea = cv({
|
|
10
|
+
base: [
|
|
11
|
+
"border-input dark:bg-input/30 text-foreground ring-offset-background min-h-3xl w-full rounded-md b bg-transparent shadow-xs",
|
|
12
|
+
"focus-visible:border-outline focus-visible:ring-outline/50 transition-[color,box-shadow] focus-visible:ring-3",
|
|
13
|
+
"file:text-foreground file:border-0 file:bg-transparent file:text-sm file:font-medium",
|
|
14
|
+
"disabled:cursor-not-allowed disabled:op-50",
|
|
15
|
+
"aria-invalid:border-error aria-invalid:focus-visible:ring-error/40",
|
|
16
|
+
"peer placeholder:text-muted-foreground",
|
|
17
|
+
],
|
|
18
|
+
variants: {
|
|
19
|
+
size: {
|
|
20
|
+
sm: "min-h-2xl px-3xs py-6xs text-sm",
|
|
21
|
+
md: "min-h-3xl px-xs py-5xs text-base",
|
|
22
|
+
lg: "min-h-3xl px-2xl py-xs text-lg",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: { size: "md" },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const { size, class: className, ...rest } = Astro.props;
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
<textarea class:list={[textarea({ size }), className]} {...rest} data-slot="textarea"></textarea>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
export const toastDescription = cv({
|
|
6
|
+
base: "starwind-toast-description text-muted-foreground text-sm",
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export interface ToastDescriptionProps extends HTMLAttributes<"div"> {}
|
|
10
|
+
type Props = ToastDescriptionProps;
|
|
11
|
+
|
|
12
|
+
const { class: className, ...rest } = Astro.props;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
class:list={[toastDescription(), className]}
|
|
17
|
+
data-toast-description
|
|
18
|
+
{...rest}
|
|
19
|
+
data-slot="toast-description"
|
|
20
|
+
>
|
|
21
|
+
<slot />
|
|
22
|
+
</div>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
import IconX from "~icons/lucide/x";
|
|
5
|
+
|
|
6
|
+
export const toastItem = cv({
|
|
7
|
+
base: "starwind-toast bg-popover text-popover-foreground pointer-events-auto absolute inset-x-0 bottom-0 flex w-full origin-bottom flex-col gap-5xs overflow-hidden rounded-lg b bg-clip-padding p-md pr-3xl shadow-lg transition-[transform,op] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] data-limited:pointer-events-none data-limited:op-0",
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
default: "border-border",
|
|
11
|
+
success: "border-success/80",
|
|
12
|
+
error: "border-error/80",
|
|
13
|
+
warning: "border-warning/80",
|
|
14
|
+
info: "border-info/80",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
variant: "default",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
type Variant = "default" | "success" | "error" | "warning" | "info";
|
|
23
|
+
|
|
24
|
+
export interface ToastItemProps extends HTMLAttributes<"div"> {
|
|
25
|
+
variant?: Variant;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type Props = ToastItemProps;
|
|
29
|
+
|
|
30
|
+
const { class: className, variant = "default", ...rest } = Astro.props;
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
<div
|
|
34
|
+
class:list={[toastItem({ variant }), className]}
|
|
35
|
+
data-variant={variant}
|
|
36
|
+
data-state="open"
|
|
37
|
+
role="dialog"
|
|
38
|
+
aria-modal="false"
|
|
39
|
+
{...rest}
|
|
40
|
+
data-slot="toast"
|
|
41
|
+
>
|
|
42
|
+
<div
|
|
43
|
+
class="starwind-toast-content grid gap-5xs transition-op duration-200 data-behind:op-0 data-expanded:op-100"
|
|
44
|
+
data-slot="toast-content"
|
|
45
|
+
>
|
|
46
|
+
<slot />
|
|
47
|
+
</div>
|
|
48
|
+
<button
|
|
49
|
+
type="button"
|
|
50
|
+
class="starwind-toast-close text-muted-foreground hover:text-foreground absolute top-3xs right-3xs rounded-md p-5xs op-70 transition-op hover:op-100 focus-visible:ring-2 focus-visible:outline-none"
|
|
51
|
+
data-slot="toast-close"
|
|
52
|
+
aria-label="Close notification"
|
|
53
|
+
>
|
|
54
|
+
<IconX class="size-4" />
|
|
55
|
+
</button>
|
|
56
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
import ToastDescription from "./ToastDescription.astro";
|
|
3
|
+
import ToastItem from "./ToastItem.astro";
|
|
4
|
+
import ToastTitle from "./ToastTitle.astro";
|
|
5
|
+
|
|
6
|
+
type Variant = "default" | "success" | "error" | "warning" | "info" | "loading";
|
|
7
|
+
|
|
8
|
+
export interface ToastTemplateProps {
|
|
9
|
+
variant: Variant;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type Props = ToastTemplateProps;
|
|
13
|
+
|
|
14
|
+
const { variant } = Astro.props;
|
|
15
|
+
|
|
16
|
+
// Loading variant uses default item styling but loading title styling
|
|
17
|
+
const itemVariant = variant === "loading" ? "default" : variant;
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<template data-toast-template={variant}>
|
|
21
|
+
<slot>
|
|
22
|
+
<ToastItem variant={itemVariant}>
|
|
23
|
+
<ToastTitle variant={variant}>Title</ToastTitle>
|
|
24
|
+
<ToastDescription>Description</ToastDescription>
|
|
25
|
+
</ToastItem>
|
|
26
|
+
</slot>
|
|
27
|
+
</template>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from "astro/types";
|
|
3
|
+
import { cv } from "css-variants";
|
|
4
|
+
|
|
5
|
+
import IconCircleCheck from "~icons/lucide/circle-check";
|
|
6
|
+
import IconCircleX from "~icons/lucide/circle-x";
|
|
7
|
+
import IconAlertTriangle from "~icons/lucide/alert-triangle";
|
|
8
|
+
import IconInfo from "~icons/lucide/info";
|
|
9
|
+
import IconLoader2 from "~icons/lucide/loader-2";
|
|
10
|
+
|
|
11
|
+
export const toastTitle = cv({
|
|
12
|
+
base: "starwind-toast-title flex items-center gap-5xs text-sm font-semibold [&_svg]:size-4",
|
|
13
|
+
variants: {
|
|
14
|
+
variant: {
|
|
15
|
+
default: "",
|
|
16
|
+
success: "[&_svg]:text-success",
|
|
17
|
+
error: "[&_svg]:text-error",
|
|
18
|
+
warning: "[&_svg]:text-warning",
|
|
19
|
+
info: "[&_svg]:text-info",
|
|
20
|
+
loading: "[&_svg]:text-muted-foreground",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: "default",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
type Variant = "default" | "success" | "error" | "warning" | "info" | "loading";
|
|
29
|
+
|
|
30
|
+
export interface ToastTitleProps extends HTMLAttributes<"div"> {
|
|
31
|
+
variant?: Variant;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type Props = ToastTitleProps;
|
|
35
|
+
|
|
36
|
+
const { class: className, variant = "default", ...rest } = Astro.props;
|
|
37
|
+
|
|
38
|
+
const icons: Record<string, any> = {
|
|
39
|
+
success: IconCircleCheck,
|
|
40
|
+
error: IconCircleX,
|
|
41
|
+
warning: IconAlertTriangle,
|
|
42
|
+
info: IconInfo,
|
|
43
|
+
loading: IconLoader2,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const Icon = icons[variant];
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
<div
|
|
50
|
+
class:list={[toastTitle({ variant }), className]}
|
|
51
|
+
data-slot="toast-title"
|
|
52
|
+
data-toast-title
|
|
53
|
+
{...rest}
|
|
54
|
+
>
|
|
55
|
+
<slot name="icon">
|
|
56
|
+
{Icon && <Icon class={variant === "loading" ? "animate-spin" : ""} />}
|
|
57
|
+
</slot>
|
|
58
|
+
<span data-toast-title-text><slot /></span>
|
|
59
|
+
</div>
|