@dogsbay/ui 0.2.0-beta.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/package.json +38 -0
- package/src/accordion/Accordion.astro +38 -0
- package/src/accordion/AccordionContent.astro +25 -0
- package/src/accordion/AccordionItem.astro +26 -0
- package/src/accordion/AccordionTrigger.astro +38 -0
- package/src/accordion/accordion.ts +189 -0
- package/src/accordion/index.ts +4 -0
- package/src/alert/Alert.astro +69 -0
- package/src/alert/AlertDescription.astro +17 -0
- package/src/alert/AlertTitle.astro +21 -0
- package/src/alert/CollapsibleAlert.astro +103 -0
- package/src/alert/icon.ts +32 -0
- package/src/alert/index.ts +4 -0
- package/src/alert/variants.ts +29 -0
- package/src/alert-dialog/AlertDialog.astro +16 -0
- package/src/alert-dialog/AlertDialogAction.astro +23 -0
- package/src/alert-dialog/AlertDialogCancel.astro +23 -0
- package/src/alert-dialog/AlertDialogContent.astro +37 -0
- package/src/alert-dialog/AlertDialogDescription.astro +18 -0
- package/src/alert-dialog/AlertDialogFooter.astro +18 -0
- package/src/alert-dialog/AlertDialogHeader.astro +18 -0
- package/src/alert-dialog/AlertDialogTitle.astro +18 -0
- package/src/alert-dialog/AlertDialogTrigger.astro +24 -0
- package/src/alert-dialog/alert-dialog.ts +154 -0
- package/src/alert-dialog/index.ts +9 -0
- package/src/api-doc/ApiDoc.astro +52 -0
- package/src/api-doc/index.ts +1 -0
- package/src/api-layout/ApiCodePanel.astro +21 -0
- package/src/api-layout/ApiLayout.astro +29 -0
- package/src/api-layout/ExampleBlock.astro +63 -0
- package/src/api-params/ApiParams.astro +96 -0
- package/src/api-params/index.ts +1 -0
- package/src/api-source/ApiSource.astro +20 -0
- package/src/api-source/api-source.css +32 -0
- package/src/api-source/index.ts +1 -0
- package/src/api-symbol/ApiSymbol.astro +48 -0
- package/src/api-symbol/api-symbol.css +89 -0
- package/src/api-symbol/index.ts +1 -0
- package/src/api-url-bar/ApiUrlBar.astro +63 -0
- package/src/avatar/Avatar.astro +57 -0
- package/src/avatar/index.ts +1 -0
- package/src/badge/Badge.astro +37 -0
- package/src/badge/index.ts +1 -0
- package/src/breadcrumb/Breadcrumb.astro +32 -0
- package/src/breadcrumb/BreadcrumbEllipsis.astro +32 -0
- package/src/breadcrumb/BreadcrumbItem.astro +41 -0
- package/src/breadcrumb/BreadcrumbSeparator.astro +33 -0
- package/src/breadcrumb/index.ts +4 -0
- package/src/button/Button.astro +70 -0
- package/src/button/index.ts +1 -0
- package/src/card/Card.astro +17 -0
- package/src/card/CardContent.astro +17 -0
- package/src/card/CardDescription.astro +17 -0
- package/src/card/CardFooter.astro +17 -0
- package/src/card/CardHeader.astro +17 -0
- package/src/card/CardTitle.astro +17 -0
- package/src/card/index.ts +6 -0
- package/src/checkbox/Checkbox.astro +70 -0
- package/src/checkbox/index.ts +1 -0
- package/src/checkbox-group/CheckboxGroup.astro +38 -0
- package/src/checkbox-group/checkbox-group.ts +53 -0
- package/src/checkbox-group/index.ts +1 -0
- package/src/code-block/CodeBlock.astro +160 -0
- package/src/code-rich/CodeRich.astro +267 -0
- package/src/code-rich/code-rich.css +68 -0
- package/src/code-rich/index.ts +1 -0
- package/src/code-samples/CodeSamples.astro +59 -0
- package/src/collapsible/Collapsible.astro +35 -0
- package/src/collapsible/CollapsibleContent.astro +24 -0
- package/src/collapsible/CollapsibleTrigger.astro +23 -0
- package/src/collapsible/collapsible.ts +42 -0
- package/src/collapsible/index.ts +3 -0
- package/src/combobox/Combobox.astro +53 -0
- package/src/combobox/ComboboxEmpty.astro +18 -0
- package/src/combobox/ComboboxItem.astro +28 -0
- package/src/combobox/combobox.ts +179 -0
- package/src/combobox/index.ts +3 -0
- package/src/command/Command.astro +22 -0
- package/src/command/CommandEmpty.astro +18 -0
- package/src/command/CommandGroup.astro +24 -0
- package/src/command/CommandInput.astro +49 -0
- package/src/command/CommandItem.astro +26 -0
- package/src/command/CommandList.astro +19 -0
- package/src/command/CommandSeparator.astro +16 -0
- package/src/command/CommandShortcut.astro +18 -0
- package/src/command/command.ts +212 -0
- package/src/command/index.ts +8 -0
- package/src/content-renderer/ContentRenderer.astro +410 -0
- package/src/content-renderer/InlineRenderer.astro +149 -0
- package/src/context-menu/ContextMenu.astro +22 -0
- package/src/context-menu/ContextMenuContent.astro +24 -0
- package/src/context-menu/ContextMenuItem.astro +49 -0
- package/src/context-menu/ContextMenuSeparator.astro +14 -0
- package/src/context-menu/ContextMenuShortcut.astro +14 -0
- package/src/context-menu/ContextMenuTrigger.astro +22 -0
- package/src/context-menu/context-menu.ts +238 -0
- package/src/context-menu/index.ts +6 -0
- package/src/copy-button/CopyButton.astro +88 -0
- package/src/copy-button/index.ts +1 -0
- package/src/diagram/Diagram.astro +15 -0
- package/src/diagram/index.ts +1 -0
- package/src/dialog/Dialog.astro +22 -0
- package/src/dialog/DialogClose.astro +32 -0
- package/src/dialog/DialogContent.astro +37 -0
- package/src/dialog/DialogDescription.astro +22 -0
- package/src/dialog/DialogFooter.astro +18 -0
- package/src/dialog/DialogHeader.astro +18 -0
- package/src/dialog/DialogTitle.astro +18 -0
- package/src/dialog/DialogTrigger.astro +33 -0
- package/src/dialog/dialog.ts +291 -0
- package/src/dialog/index.ts +8 -0
- package/src/docs-footer/DocsFooter.astro +50 -0
- package/src/docs-header/DocsHeader.astro +32 -0
- package/src/docs-layout/DocsLayout.astro +187 -0
- package/src/docs-layout/index.ts +1 -0
- package/src/drawer/Drawer.astro +12 -0
- package/src/drawer/DrawerClose.astro +12 -0
- package/src/drawer/DrawerContent.astro +46 -0
- package/src/drawer/DrawerDescription.astro +10 -0
- package/src/drawer/DrawerFooter.astro +10 -0
- package/src/drawer/DrawerHandle.astro +16 -0
- package/src/drawer/DrawerHeader.astro +10 -0
- package/src/drawer/DrawerTitle.astro +10 -0
- package/src/drawer/DrawerTrigger.astro +25 -0
- package/src/drawer/drawer.ts +262 -0
- package/src/drawer/index.ts +9 -0
- package/src/dropdown-menu/DropdownMenu.astro +22 -0
- package/src/dropdown-menu/DropdownMenuContent.astro +33 -0
- package/src/dropdown-menu/DropdownMenuGroup.astro +17 -0
- package/src/dropdown-menu/DropdownMenuItem.astro +48 -0
- package/src/dropdown-menu/DropdownMenuLabel.astro +28 -0
- package/src/dropdown-menu/DropdownMenuSeparator.astro +21 -0
- package/src/dropdown-menu/DropdownMenuShortcut.astro +18 -0
- package/src/dropdown-menu/DropdownMenuTrigger.astro +34 -0
- package/src/dropdown-menu/dropdown-menu.ts +348 -0
- package/src/dropdown-menu/index.ts +8 -0
- package/src/endpoint-card/EndpointCard.astro +60 -0
- package/src/endpoint-card/EndpointCardSection.astro +22 -0
- package/src/endpoint-card/EndpointSection.astro +35 -0
- package/src/field/Field.astro +31 -0
- package/src/field/FieldDescription.astro +22 -0
- package/src/field/FieldLabel.astro +24 -0
- package/src/field/field.ts +61 -0
- package/src/field/index.ts +3 -0
- package/src/fieldset/Fieldset.astro +24 -0
- package/src/fieldset/FieldsetLegend.astro +18 -0
- package/src/fieldset/index.ts +2 -0
- package/src/footnote/Footnote.astro +37 -0
- package/src/footnote/footnote.ts +79 -0
- package/src/footnote/index.ts +1 -0
- package/src/form/Form.astro +27 -0
- package/src/form/form.ts +160 -0
- package/src/form/index.ts +1 -0
- package/src/grid/Grid.astro +117 -0
- package/src/grid/GridItem.astro +95 -0
- package/src/grid/index.ts +2 -0
- package/src/image/Image.astro +115 -0
- package/src/image/index.ts +1 -0
- package/src/input/Input.astro +34 -0
- package/src/input/index.ts +1 -0
- package/src/kbd/Kbd.astro +17 -0
- package/src/kbd/index.ts +1 -0
- package/src/label/Label.astro +17 -0
- package/src/label/index.ts +1 -0
- package/src/link-card/LinkCard.astro +47 -0
- package/src/link-card/index.ts +1 -0
- package/src/map-view/MapView.astro +88 -0
- package/src/map-view/index.ts +1 -0
- package/src/map-view/map-view.ts +194 -0
- package/src/markdown-example/MarkdownExample.astro +138 -0
- package/src/markdown-example/index.ts +1 -0
- package/src/math/MathKatex.astro +35 -0
- package/src/math/index.ts +1 -0
- package/src/menubar/Menubar.astro +25 -0
- package/src/menubar/MenubarContent.astro +24 -0
- package/src/menubar/MenubarItem.astro +26 -0
- package/src/menubar/MenubarMenu.astro +12 -0
- package/src/menubar/MenubarSeparator.astro +11 -0
- package/src/menubar/MenubarShortcut.astro +11 -0
- package/src/menubar/MenubarTrigger.astro +27 -0
- package/src/menubar/index.ts +7 -0
- package/src/menubar/menubar.ts +258 -0
- package/src/meter/Meter.astro +75 -0
- package/src/meter/index.ts +1 -0
- package/src/method-badge/MethodBadge.astro +32 -0
- package/src/navigation-menu/NavigationMenu.astro +24 -0
- package/src/navigation-menu/NavigationMenuContent.astro +24 -0
- package/src/navigation-menu/NavigationMenuItem.astro +22 -0
- package/src/navigation-menu/NavigationMenuLink.astro +26 -0
- package/src/navigation-menu/NavigationMenuList.astro +22 -0
- package/src/navigation-menu/NavigationMenuTrigger.astro +40 -0
- package/src/navigation-menu/index.ts +6 -0
- package/src/navigation-menu/navigation-menu.ts +192 -0
- package/src/number-field/NumberField.astro +84 -0
- package/src/number-field/index.ts +1 -0
- package/src/number-field/number-field.ts +68 -0
- package/src/pagination/Pagination.astro +59 -0
- package/src/pagination/index.ts +1 -0
- package/src/parameter-table/ParameterTable.astro +75 -0
- package/src/popover/Popover.astro +21 -0
- package/src/popover/PopoverContent.astro +31 -0
- package/src/popover/PopoverTrigger.astro +31 -0
- package/src/popover/index.ts +3 -0
- package/src/popover/popover.ts +144 -0
- package/src/preview-card/PreviewCard.astro +24 -0
- package/src/preview-card/PreviewCardContent.astro +24 -0
- package/src/preview-card/PreviewCardTrigger.astro +23 -0
- package/src/preview-card/index.ts +3 -0
- package/src/preview-card/preview-card.ts +91 -0
- package/src/progress/Progress.astro +61 -0
- package/src/progress/index.ts +1 -0
- package/src/property-item/PropertyItem.astro +183 -0
- package/src/property-list/PropertyList.astro +68 -0
- package/src/radio-group/RadioGroup.astro +41 -0
- package/src/radio-group/RadioGroupItem.astro +36 -0
- package/src/radio-group/index.ts +2 -0
- package/src/radio-group/radio-group.ts +126 -0
- package/src/response-tabs/ResponseTabs.astro +60 -0
- package/src/schema-viewer/SchemaViewer.astro +42 -0
- package/src/scroll-area/ScrollArea.astro +44 -0
- package/src/scroll-area/index.ts +1 -0
- package/src/scroll-area/scroll-area.ts +176 -0
- package/src/select/Select.astro +34 -0
- package/src/select/SelectContent.astro +24 -0
- package/src/select/SelectGroup.astro +23 -0
- package/src/select/SelectItem.astro +28 -0
- package/src/select/SelectLabel.astro +18 -0
- package/src/select/SelectSeparator.astro +22 -0
- package/src/select/SelectTrigger.astro +28 -0
- package/src/select/SelectValue.astro +18 -0
- package/src/select/index.ts +8 -0
- package/src/select/select.ts +381 -0
- package/src/separator/Separator.astro +35 -0
- package/src/separator/index.ts +1 -0
- package/src/sheet/Sheet.astro +12 -0
- package/src/sheet/SheetClose.astro +35 -0
- package/src/sheet/SheetContent.astro +52 -0
- package/src/sheet/SheetDescription.astro +18 -0
- package/src/sheet/SheetFooter.astro +18 -0
- package/src/sheet/SheetHeader.astro +18 -0
- package/src/sheet/SheetTitle.astro +18 -0
- package/src/sheet/SheetTrigger.astro +32 -0
- package/src/sheet/index.ts +8 -0
- package/src/sheet/sheet.ts +173 -0
- package/src/sidebar/Sidebar.astro +113 -0
- package/src/sidebar/SidebarContent.astro +18 -0
- package/src/sidebar/SidebarFooter.astro +18 -0
- package/src/sidebar/SidebarGroup.astro +18 -0
- package/src/sidebar/SidebarGroupContent.astro +18 -0
- package/src/sidebar/SidebarGroupLabel.astro +18 -0
- package/src/sidebar/SidebarHeader.astro +18 -0
- package/src/sidebar/SidebarInset.astro +18 -0
- package/src/sidebar/SidebarMenu.astro +18 -0
- package/src/sidebar/SidebarMenuBadge.astro +18 -0
- package/src/sidebar/SidebarMenuButton.astro +71 -0
- package/src/sidebar/SidebarMenuItem.astro +18 -0
- package/src/sidebar/SidebarMenuSub.astro +18 -0
- package/src/sidebar/SidebarMenuSubButton.astro +45 -0
- package/src/sidebar/SidebarMenuSubItem.astro +12 -0
- package/src/sidebar/SidebarNavTree.astro +106 -0
- package/src/sidebar/SidebarProvider.astro +23 -0
- package/src/sidebar/SidebarRail.astro +25 -0
- package/src/sidebar/SidebarSeparator.astro +21 -0
- package/src/sidebar/SidebarTrigger.astro +40 -0
- package/src/sidebar/index.ts +19 -0
- package/src/sidebar/sidebar.ts +265 -0
- package/src/skeleton/Skeleton.astro +16 -0
- package/src/skeleton/index.ts +1 -0
- package/src/skip-link/SkipLink.astro +24 -0
- package/src/slider/Slider.astro +61 -0
- package/src/slider/index.ts +1 -0
- package/src/slider/slider.ts +111 -0
- package/src/spinner/Spinner.astro +54 -0
- package/src/spinner/index.ts +1 -0
- package/src/steps/Step.astro +16 -0
- package/src/steps/Steps.astro +122 -0
- package/src/steps/SubSteps.astro +73 -0
- package/src/switch/Switch.astro +52 -0
- package/src/switch/index.ts +1 -0
- package/src/switch/switch.ts +109 -0
- package/src/table/Table.astro +24 -0
- package/src/table/TableBody.astro +18 -0
- package/src/table/TableCaption.astro +18 -0
- package/src/table/TableCell.astro +18 -0
- package/src/table/TableFooter.astro +18 -0
- package/src/table/TableHead.astro +18 -0
- package/src/table/TableHeader.astro +18 -0
- package/src/table/TableRow.astro +18 -0
- package/src/table/index.ts +8 -0
- package/src/tabs/Tabs.astro +37 -0
- package/src/tabs/TabsContent.astro +32 -0
- package/src/tabs/TabsList.astro +23 -0
- package/src/tabs/TabsTrigger.astro +29 -0
- package/src/tabs/index.ts +4 -0
- package/src/tabs/tabs.ts +220 -0
- package/src/textarea/Textarea.astro +25 -0
- package/src/textarea/index.ts +1 -0
- package/src/theme-toggle/ThemeToggle.astro +67 -0
- package/src/theme-toggle/index.ts +1 -0
- package/src/toast/Toaster.astro +39 -0
- package/src/toast/index.ts +3 -0
- package/src/toast/toast.ts +104 -0
- package/src/toc/TableOfContents.astro +225 -0
- package/src/toggle/Toggle.astro +56 -0
- package/src/toggle/index.ts +1 -0
- package/src/toggle/toggle.ts +38 -0
- package/src/toggle-group/ToggleGroup.astro +39 -0
- package/src/toggle-group/ToggleGroupItem.astro +56 -0
- package/src/toggle-group/index.ts +2 -0
- package/src/toggle-group/toggle-group.ts +121 -0
- package/src/toolbar/Toolbar.astro +26 -0
- package/src/toolbar/ToolbarButton.astro +29 -0
- package/src/toolbar/ToolbarSeparator.astro +14 -0
- package/src/toolbar/index.ts +3 -0
- package/src/toolbar/toolbar.ts +65 -0
- package/src/tooltip/Tooltip.astro +21 -0
- package/src/tooltip/TooltipContent.astro +25 -0
- package/src/tooltip/TooltipTrigger.astro +31 -0
- package/src/tooltip/index.ts +3 -0
- package/src/tooltip/tooltip.ts +156 -0
- package/src/youtube/YouTube.astro +119 -0
- package/src/youtube/index.ts +1 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const tableRow = tv({
|
|
5
|
+
base: "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
class?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<tr class={tableRow({ class: className })} {...rest}>
|
|
17
|
+
<slot />
|
|
18
|
+
</tr>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { default as Table } from "./Table.astro";
|
|
2
|
+
export { default as TableHeader } from "./TableHeader.astro";
|
|
3
|
+
export { default as TableBody } from "./TableBody.astro";
|
|
4
|
+
export { default as TableFooter } from "./TableFooter.astro";
|
|
5
|
+
export { default as TableRow } from "./TableRow.astro";
|
|
6
|
+
export { default as TableHead } from "./TableHead.astro";
|
|
7
|
+
export { default as TableCell } from "./TableCell.astro";
|
|
8
|
+
export { default as TableCaption } from "./TableCaption.astro";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const tabs = tv({
|
|
5
|
+
base: "w-full my-4 border border-border rounded-lg overflow-hidden",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
defaultValue?: string;
|
|
10
|
+
orientation?: "horizontal" | "vertical";
|
|
11
|
+
syncKey?: string;
|
|
12
|
+
class?: string;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
defaultValue,
|
|
18
|
+
orientation = "horizontal",
|
|
19
|
+
syncKey,
|
|
20
|
+
class: className,
|
|
21
|
+
...rest
|
|
22
|
+
} = Astro.props;
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<db-tabs
|
|
26
|
+
class={tabs({ class: className })}
|
|
27
|
+
default-value={defaultValue}
|
|
28
|
+
orientation={orientation}
|
|
29
|
+
sync-key={syncKey}
|
|
30
|
+
{...rest}
|
|
31
|
+
>
|
|
32
|
+
<slot />
|
|
33
|
+
</db-tabs>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
import "@dogsbay/elements/db-tabs";
|
|
37
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const tabsContent = tv({
|
|
5
|
+
base: "px-4 py-3 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 [&>:first-child]:mt-0 [&>:last-child]:mb-0",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
value: string;
|
|
10
|
+
default?: boolean;
|
|
11
|
+
class?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
value,
|
|
17
|
+
default: isDefault = false,
|
|
18
|
+
class: className,
|
|
19
|
+
...rest
|
|
20
|
+
} = Astro.props;
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<div
|
|
24
|
+
class={tabsContent({ class: className })}
|
|
25
|
+
data-part="content"
|
|
26
|
+
data-value={value}
|
|
27
|
+
role="tabpanel"
|
|
28
|
+
hidden={!isDefault}
|
|
29
|
+
{...rest}
|
|
30
|
+
>
|
|
31
|
+
<slot />
|
|
32
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const tabsList = tv({
|
|
5
|
+
base: "flex items-center bg-muted p-1 text-muted-foreground border-b border-border",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
class?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class={tabsList({ class: className })}
|
|
18
|
+
data-part="list"
|
|
19
|
+
role="tablist"
|
|
20
|
+
{...rest}
|
|
21
|
+
>
|
|
22
|
+
<slot />
|
|
23
|
+
</div>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const tabsTrigger = tv({
|
|
5
|
+
base: "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-selected:bg-background aria-selected:text-foreground aria-selected:shadow-sm",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
value: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
class?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { value, disabled = false, class: className, ...rest } = Astro.props;
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<button
|
|
19
|
+
class={tabsTrigger({ class: className })}
|
|
20
|
+
data-part="trigger"
|
|
21
|
+
data-value={value}
|
|
22
|
+
role="tab"
|
|
23
|
+
type="button"
|
|
24
|
+
disabled={disabled || undefined}
|
|
25
|
+
aria-disabled={disabled ? "true" : undefined}
|
|
26
|
+
{...rest}
|
|
27
|
+
>
|
|
28
|
+
<slot />
|
|
29
|
+
</button>
|
package/src/tabs/tabs.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { CompositeNavigation } from "@dogsbay/primitives/composite";
|
|
2
|
+
import type { Orientation } from "@dogsbay/primitives/composite";
|
|
3
|
+
|
|
4
|
+
interface TabsInstance {
|
|
5
|
+
root: HTMLElement;
|
|
6
|
+
list: HTMLElement;
|
|
7
|
+
triggers: HTMLElement[];
|
|
8
|
+
panels: HTMLElement[];
|
|
9
|
+
nav: CompositeNavigation;
|
|
10
|
+
value: string;
|
|
11
|
+
syncKey: string | null;
|
|
12
|
+
orientation: Orientation;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const instances = new WeakMap<HTMLElement, TabsInstance>();
|
|
16
|
+
|
|
17
|
+
let idCounter = 0;
|
|
18
|
+
function uniqueId(prefix: string) {
|
|
19
|
+
return `${prefix}-${++idCounter}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function initTabs(root: HTMLElement) {
|
|
23
|
+
if (instances.has(root)) return;
|
|
24
|
+
|
|
25
|
+
const list = root.querySelector("[data-part='list']") as HTMLElement | null;
|
|
26
|
+
if (!list) return;
|
|
27
|
+
|
|
28
|
+
const triggers = Array.from(
|
|
29
|
+
list.querySelectorAll("[data-part='trigger']"),
|
|
30
|
+
) as HTMLElement[];
|
|
31
|
+
const panels = Array.from(
|
|
32
|
+
root.querySelectorAll("[data-part='content']"),
|
|
33
|
+
) as HTMLElement[];
|
|
34
|
+
|
|
35
|
+
const orientation = (root.dataset.orientation as Orientation) || "horizontal";
|
|
36
|
+
const defaultValue =
|
|
37
|
+
root.dataset.defaultValue || triggers[0]?.dataset.value || "";
|
|
38
|
+
const syncKey = root.dataset.syncKey || null;
|
|
39
|
+
|
|
40
|
+
// Set orientation on tablist
|
|
41
|
+
list.setAttribute("aria-orientation", orientation);
|
|
42
|
+
|
|
43
|
+
// Generate IDs and link triggers ↔ panels
|
|
44
|
+
triggers.forEach((trigger) => {
|
|
45
|
+
const value = trigger.dataset.value!;
|
|
46
|
+
const triggerId = trigger.id || uniqueId("base-tab");
|
|
47
|
+
trigger.id = triggerId;
|
|
48
|
+
|
|
49
|
+
const panel = panels.find((p) => p.dataset.value === value);
|
|
50
|
+
if (panel) {
|
|
51
|
+
const panelId = panel.id || uniqueId("base-tabpanel");
|
|
52
|
+
panel.id = panelId;
|
|
53
|
+
trigger.setAttribute("aria-controls", panelId);
|
|
54
|
+
panel.setAttribute("aria-labelledby", triggerId);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Set up composite navigation
|
|
59
|
+
const nav = new CompositeNavigation(list, "[data-part='trigger']", {
|
|
60
|
+
orientation,
|
|
61
|
+
loop: true,
|
|
62
|
+
homeEnd: true,
|
|
63
|
+
onHighlightedIndexChange: () => {
|
|
64
|
+
// Selection follows focus — activate the focused tab
|
|
65
|
+
const focused = document.activeElement as HTMLElement;
|
|
66
|
+
const value = focused?.dataset?.value;
|
|
67
|
+
if (value) selectTab(root, value);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const instance: TabsInstance = {
|
|
72
|
+
root,
|
|
73
|
+
list,
|
|
74
|
+
triggers,
|
|
75
|
+
panels,
|
|
76
|
+
nav,
|
|
77
|
+
value: "",
|
|
78
|
+
syncKey,
|
|
79
|
+
orientation,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
instances.set(root, instance);
|
|
83
|
+
|
|
84
|
+
// Click handler — also handles non-keyboard activation
|
|
85
|
+
list.addEventListener("click", (e) => {
|
|
86
|
+
const trigger = (e.target as HTMLElement).closest(
|
|
87
|
+
"[data-part='trigger']",
|
|
88
|
+
) as HTMLElement | null;
|
|
89
|
+
if (!trigger || trigger.hasAttribute("disabled")) return;
|
|
90
|
+
const value = trigger.dataset.value;
|
|
91
|
+
if (value) selectTab(root, value);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Activate navigation
|
|
95
|
+
nav.activate();
|
|
96
|
+
|
|
97
|
+
// Sync: read initial value from localStorage or hash
|
|
98
|
+
let initialValue = defaultValue;
|
|
99
|
+
if (syncKey) {
|
|
100
|
+
const stored = localStorage.getItem(`base-tabs-sync:${syncKey}`);
|
|
101
|
+
if (stored && triggers.some((t) => t.dataset.value === stored)) {
|
|
102
|
+
initialValue = stored;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Deep link: check URL hash
|
|
107
|
+
const hash = window.location.hash.slice(1);
|
|
108
|
+
if (hash && triggers.some((t) => t.dataset.value === hash)) {
|
|
109
|
+
initialValue = hash;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Set initial selection
|
|
113
|
+
selectTab(root, initialValue);
|
|
114
|
+
|
|
115
|
+
// Listen for sync events from other tabs instances with same syncKey
|
|
116
|
+
if (syncKey) {
|
|
117
|
+
window.addEventListener("storage", (e) => {
|
|
118
|
+
if (e.key !== `base-tabs-sync:${syncKey}`) return;
|
|
119
|
+
const newValue = e.newValue;
|
|
120
|
+
if (newValue && instance.value !== newValue) {
|
|
121
|
+
selectTab(root, newValue);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Listen for same-page sync (custom event)
|
|
126
|
+
document.addEventListener(`base-tabs-sync:${syncKey}`, ((
|
|
127
|
+
e: CustomEvent,
|
|
128
|
+
) => {
|
|
129
|
+
const newValue = e.detail.value;
|
|
130
|
+
if (newValue && instance.value !== newValue) {
|
|
131
|
+
selectTab(root, newValue);
|
|
132
|
+
}
|
|
133
|
+
}) as EventListener);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function selectTab(root: HTMLElement, value: string) {
|
|
138
|
+
const instance = instances.get(root);
|
|
139
|
+
if (!instance) return;
|
|
140
|
+
if (instance.value === value) return;
|
|
141
|
+
|
|
142
|
+
instance.value = value;
|
|
143
|
+
|
|
144
|
+
// Update triggers
|
|
145
|
+
instance.triggers.forEach((trigger) => {
|
|
146
|
+
const isSelected = trigger.dataset.value === value;
|
|
147
|
+
trigger.setAttribute("aria-selected", String(isSelected));
|
|
148
|
+
trigger.setAttribute("tabindex", isSelected ? "0" : "-1");
|
|
149
|
+
if (isSelected) {
|
|
150
|
+
trigger.setAttribute("data-state", "active");
|
|
151
|
+
} else {
|
|
152
|
+
trigger.removeAttribute("data-state");
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Update panels
|
|
157
|
+
instance.panels.forEach((panel) => {
|
|
158
|
+
const isActive = panel.dataset.value === value;
|
|
159
|
+
panel.hidden = !isActive;
|
|
160
|
+
if (isActive) {
|
|
161
|
+
panel.setAttribute("data-state", "active");
|
|
162
|
+
// Ensure panel is focusable for keyboard users
|
|
163
|
+
if (!panel.hasAttribute("tabindex")) {
|
|
164
|
+
panel.setAttribute("tabindex", "0");
|
|
165
|
+
}
|
|
166
|
+
// Lazy init: initialize any nested tabs that haven't been set up yet
|
|
167
|
+
panel.querySelectorAll("[data-component='tabs']").forEach((nestedEl) => {
|
|
168
|
+
if (!instances.has(nestedEl as HTMLElement)) {
|
|
169
|
+
initTabs(nestedEl as HTMLElement);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
} else {
|
|
173
|
+
panel.removeAttribute("data-state");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Update hash
|
|
178
|
+
if (window.location.hash.slice(1) !== value) {
|
|
179
|
+
// Only update hash if the user interacted (not on initial load)
|
|
180
|
+
// We skip this to avoid scroll jumps on page load
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Sync to localStorage and other instances
|
|
184
|
+
if (instance.syncKey) {
|
|
185
|
+
localStorage.setItem(`base-tabs-sync:${instance.syncKey}`, value);
|
|
186
|
+
document.dispatchEvent(
|
|
187
|
+
new CustomEvent(`base-tabs-sync:${instance.syncKey}`, {
|
|
188
|
+
detail: { value, source: root },
|
|
189
|
+
}),
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Dispatch change event
|
|
194
|
+
root.dispatchEvent(
|
|
195
|
+
new CustomEvent("base-tabs:change", {
|
|
196
|
+
detail: { value },
|
|
197
|
+
bubbles: true,
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Auto-initialize — skip tabs inside hidden panels (they'll be lazy-inited)
|
|
203
|
+
function init() {
|
|
204
|
+
document.querySelectorAll("[data-component='tabs']").forEach((el) => {
|
|
205
|
+
const tabsEl = el as HTMLElement;
|
|
206
|
+
// Skip if inside a hidden tabpanel (will be lazy-inited when panel activates)
|
|
207
|
+
const parentPanel = tabsEl.closest("[data-part='content'][hidden]");
|
|
208
|
+
if (parentPanel) return;
|
|
209
|
+
initTabs(tabsEl);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (document.readyState === "loading") {
|
|
214
|
+
document.addEventListener("DOMContentLoaded", init);
|
|
215
|
+
} else {
|
|
216
|
+
init();
|
|
217
|
+
}
|
|
218
|
+
document.addEventListener("astro:page-load", init);
|
|
219
|
+
|
|
220
|
+
export { initTabs, selectTab };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const textarea = tv({
|
|
5
|
+
base: "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
6
|
+
variants: {
|
|
7
|
+
invalid: {
|
|
8
|
+
true: "border-destructive focus-visible:ring-destructive",
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
invalid?: boolean;
|
|
15
|
+
class?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
const { invalid = false, class: className, ...rest } = Astro.props;
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<textarea
|
|
22
|
+
class={textarea({ invalid: invalid || undefined, class: className })}
|
|
23
|
+
aria-invalid={invalid ? "true" : undefined}
|
|
24
|
+
data-invalid={invalid || undefined}
|
|
25
|
+
{...rest}></textarea>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Textarea } from "./Textarea.astro";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const themeToggle = tv({
|
|
5
|
+
base: "inline-flex h-9 w-9 items-center justify-center rounded-md border border-border bg-background text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
class?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<button
|
|
17
|
+
class={themeToggle({ class: className })}
|
|
18
|
+
data-component="theme-toggle"
|
|
19
|
+
type="button"
|
|
20
|
+
aria-label="Toggle dark mode"
|
|
21
|
+
{...rest}
|
|
22
|
+
>
|
|
23
|
+
<svg
|
|
24
|
+
class="dark:hidden h-4 w-4"
|
|
25
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
26
|
+
fill="none"
|
|
27
|
+
viewBox="0 0 24 24"
|
|
28
|
+
stroke-width="2"
|
|
29
|
+
stroke="currentColor"
|
|
30
|
+
aria-hidden="true"
|
|
31
|
+
>
|
|
32
|
+
<path
|
|
33
|
+
stroke-linecap="round"
|
|
34
|
+
stroke-linejoin="round"
|
|
35
|
+
d="M21.752 15.002A9.72 9.72 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z"
|
|
36
|
+
></path>
|
|
37
|
+
</svg>
|
|
38
|
+
<svg
|
|
39
|
+
class="hidden dark:block h-4 w-4"
|
|
40
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
41
|
+
fill="none"
|
|
42
|
+
viewBox="0 0 24 24"
|
|
43
|
+
stroke-width="2"
|
|
44
|
+
stroke="currentColor"
|
|
45
|
+
aria-hidden="true"
|
|
46
|
+
>
|
|
47
|
+
<path
|
|
48
|
+
stroke-linecap="round"
|
|
49
|
+
stroke-linejoin="round"
|
|
50
|
+
d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z"
|
|
51
|
+
></path>
|
|
52
|
+
</svg>
|
|
53
|
+
</button>
|
|
54
|
+
|
|
55
|
+
<script>
|
|
56
|
+
function setupThemeToggles() {
|
|
57
|
+
document.querySelectorAll("[data-component='theme-toggle']").forEach((btn) => {
|
|
58
|
+
btn.addEventListener("click", () => {
|
|
59
|
+
const isDark = document.documentElement.classList.toggle("dark");
|
|
60
|
+
localStorage.setItem("theme", isDark ? "dark" : "light");
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setupThemeToggles();
|
|
66
|
+
document.addEventListener("astro:after-swap", setupThemeToggles);
|
|
67
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as ThemeToggle } from "./ThemeToggle.astro";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const toaster = tv({
|
|
5
|
+
base: "fixed z-[100] flex max-h-screen w-full flex-col-reverse gap-2 p-4 sm:flex-col",
|
|
6
|
+
variants: {
|
|
7
|
+
position: {
|
|
8
|
+
"top-right": "top-0 right-0 sm:max-w-[420px]",
|
|
9
|
+
"top-left": "top-0 left-0 sm:max-w-[420px]",
|
|
10
|
+
"bottom-right": "bottom-0 right-0 sm:max-w-[420px]",
|
|
11
|
+
"bottom-left": "bottom-0 left-0 sm:max-w-[420px]",
|
|
12
|
+
"top-center": "top-0 left-1/2 -translate-x-1/2 sm:max-w-[420px]",
|
|
13
|
+
"bottom-center": "bottom-0 left-1/2 -translate-x-1/2 sm:max-w-[420px]",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
position: "bottom-right",
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
interface Props {
|
|
22
|
+
position?: "top-right" | "top-left" | "bottom-right" | "bottom-left" | "top-center" | "bottom-center";
|
|
23
|
+
class?: string;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const { position = "bottom-right", class: className, ...rest } = Astro.props;
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<div
|
|
31
|
+
class={toaster({ position, class: className })}
|
|
32
|
+
data-component="toaster"
|
|
33
|
+
data-position={position}
|
|
34
|
+
role="region"
|
|
35
|
+
aria-label="Notifications"
|
|
36
|
+
aria-live="polite"
|
|
37
|
+
{...rest}
|
|
38
|
+
>
|
|
39
|
+
</div>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export interface ToastOptions {
|
|
2
|
+
title: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
variant?: "default" | "destructive";
|
|
5
|
+
duration?: number;
|
|
6
|
+
action?: { label: string; onClick: () => void };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let toastId = 0;
|
|
10
|
+
|
|
11
|
+
const variantClasses = {
|
|
12
|
+
default:
|
|
13
|
+
"border bg-background text-foreground",
|
|
14
|
+
destructive:
|
|
15
|
+
"border-destructive bg-destructive text-destructive-foreground",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function getToaster(): HTMLElement | null {
|
|
19
|
+
return document.querySelector("[data-component='toaster']");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function createToastElement(options: ToastOptions): HTMLElement {
|
|
23
|
+
const id = `toast-${++toastId}`;
|
|
24
|
+
const variant = options.variant ?? "default";
|
|
25
|
+
|
|
26
|
+
const el = document.createElement("div");
|
|
27
|
+
el.id = id;
|
|
28
|
+
el.setAttribute("role", "status");
|
|
29
|
+
el.setAttribute("aria-live", "polite");
|
|
30
|
+
el.setAttribute("aria-atomic", "true");
|
|
31
|
+
el.setAttribute("data-part", "toast");
|
|
32
|
+
el.setAttribute("data-state", "open");
|
|
33
|
+
el.setAttribute("data-variant", variant);
|
|
34
|
+
el.className = `group pointer-events-auto relative flex w-full items-center justify-between gap-4 overflow-hidden rounded-md p-4 shadow-lg transition-all data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-full data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-right-full ${variantClasses[variant]}`;
|
|
35
|
+
|
|
36
|
+
const content = document.createElement("div");
|
|
37
|
+
content.className = "grid gap-1";
|
|
38
|
+
|
|
39
|
+
const title = document.createElement("div");
|
|
40
|
+
title.className = "text-sm font-semibold";
|
|
41
|
+
title.textContent = options.title;
|
|
42
|
+
content.appendChild(title);
|
|
43
|
+
|
|
44
|
+
if (options.description) {
|
|
45
|
+
const desc = document.createElement("div");
|
|
46
|
+
desc.className = "text-sm opacity-90";
|
|
47
|
+
desc.textContent = options.description;
|
|
48
|
+
content.appendChild(desc);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
el.appendChild(content);
|
|
52
|
+
|
|
53
|
+
// Action button
|
|
54
|
+
if (options.action) {
|
|
55
|
+
const actionBtn = document.createElement("button");
|
|
56
|
+
actionBtn.className =
|
|
57
|
+
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2";
|
|
58
|
+
actionBtn.textContent = options.action.label;
|
|
59
|
+
actionBtn.addEventListener("click", () => {
|
|
60
|
+
options.action!.onClick();
|
|
61
|
+
dismiss(el);
|
|
62
|
+
});
|
|
63
|
+
el.appendChild(actionBtn);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Close button
|
|
67
|
+
const closeBtn = document.createElement("button");
|
|
68
|
+
closeBtn.className =
|
|
69
|
+
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100";
|
|
70
|
+
closeBtn.setAttribute("aria-label", "Close");
|
|
71
|
+
closeBtn.innerHTML =
|
|
72
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>';
|
|
73
|
+
closeBtn.addEventListener("click", () => dismiss(el));
|
|
74
|
+
el.appendChild(closeBtn);
|
|
75
|
+
|
|
76
|
+
return el;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function dismiss(el: HTMLElement) {
|
|
80
|
+
el.setAttribute("data-state", "closed");
|
|
81
|
+
setTimeout(() => el.remove(), 200);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function toast(options: ToastOptions) {
|
|
85
|
+
const toaster = getToaster();
|
|
86
|
+
if (!toaster) {
|
|
87
|
+
console.warn("No <Toaster> found in the DOM.");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const el = createToastElement(options);
|
|
92
|
+
toaster.appendChild(el);
|
|
93
|
+
|
|
94
|
+
// Auto-dismiss
|
|
95
|
+
const duration = options.duration ?? 5000;
|
|
96
|
+
if (duration > 0) {
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
if (el.parentElement) dismiss(el);
|
|
99
|
+
}, duration);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Expose globally for demo page scripts
|
|
104
|
+
(window as unknown as Record<string, unknown>).__toast = toast;
|