@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,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* DocsLayout — canonical documentation layout with sidebar navigation.
|
|
4
|
+
*
|
|
5
|
+
* Handles all the boilerplate that every docs site needs:
|
|
6
|
+
* - ClientRouter for view transitions (sidebar state preserved)
|
|
7
|
+
* - Dark mode with localStorage persistence
|
|
8
|
+
* - SidebarProvider + Sidebar + SidebarInset wiring
|
|
9
|
+
* - Sticky header with SidebarTrigger + ThemeToggle
|
|
10
|
+
* - Active nav highlighting + ancestor expansion
|
|
11
|
+
* - Dark mode preservation across view transitions
|
|
12
|
+
*
|
|
13
|
+
* Install: npx dogsbay add docs-layout
|
|
14
|
+
*
|
|
15
|
+
* Prerequisites:
|
|
16
|
+
* - Run `npx dogsbay init` first (creates theme.css + global.css)
|
|
17
|
+
* - Import global.css in your pages or a wrapper layout:
|
|
18
|
+
* `import "@/styles/global.css";`
|
|
19
|
+
* - DocsLayout does NOT import your styles — that's your app's responsibility,
|
|
20
|
+
* same as shadcn's globals.css pattern.
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* ---
|
|
24
|
+
* import "@/styles/global.css";
|
|
25
|
+
* import DocsLayout from "@ui/docs-layout/DocsLayout.astro";
|
|
26
|
+
* const nav = [{ label: "Guide", items: [{ label: "Quick Start", href: "/quick-start" }] }];
|
|
27
|
+
* ---
|
|
28
|
+
* <DocsLayout title="Quick Start" siteTitle="My Docs" nav={nav}>
|
|
29
|
+
* <p>Page content here</p>
|
|
30
|
+
* </DocsLayout>
|
|
31
|
+
*/
|
|
32
|
+
import { ClientRouter } from "astro:transitions";
|
|
33
|
+
import SidebarProvider from "../sidebar/SidebarProvider.astro";
|
|
34
|
+
import Sidebar from "../sidebar/Sidebar.astro";
|
|
35
|
+
import SidebarHeader from "../sidebar/SidebarHeader.astro";
|
|
36
|
+
import SidebarContent from "../sidebar/SidebarContent.astro";
|
|
37
|
+
import SidebarTrigger from "../sidebar/SidebarTrigger.astro";
|
|
38
|
+
import SidebarInset from "../sidebar/SidebarInset.astro";
|
|
39
|
+
import SidebarRail from "../sidebar/SidebarRail.astro";
|
|
40
|
+
import SidebarGroup from "../sidebar/SidebarGroup.astro";
|
|
41
|
+
import SidebarGroupLabel from "../sidebar/SidebarGroupLabel.astro";
|
|
42
|
+
import SidebarGroupContent from "../sidebar/SidebarGroupContent.astro";
|
|
43
|
+
import SidebarMenu from "../sidebar/SidebarMenu.astro";
|
|
44
|
+
import SidebarMenuItem from "../sidebar/SidebarMenuItem.astro";
|
|
45
|
+
import SidebarMenuButton from "../sidebar/SidebarMenuButton.astro";
|
|
46
|
+
import SidebarSeparator from "../sidebar/SidebarSeparator.astro";
|
|
47
|
+
import SidebarNavTree from "../sidebar/SidebarNavTree.astro";
|
|
48
|
+
import Separator from "../separator/Separator.astro";
|
|
49
|
+
import ThemeToggle from "../theme-toggle/ThemeToggle.astro";
|
|
50
|
+
|
|
51
|
+
interface NavItem {
|
|
52
|
+
label: string;
|
|
53
|
+
href?: string;
|
|
54
|
+
icon?: string;
|
|
55
|
+
children?: NavItem[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface NavSection {
|
|
59
|
+
label: string;
|
|
60
|
+
items: NavItem[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface Props {
|
|
64
|
+
/** Page title — shown in header and <title> tag */
|
|
65
|
+
title: string;
|
|
66
|
+
/** Site title — shown in sidebar header */
|
|
67
|
+
siteTitle?: string;
|
|
68
|
+
/** Meta description */
|
|
69
|
+
description?: string;
|
|
70
|
+
/** Navigation sections for the sidebar */
|
|
71
|
+
nav?: NavSection[];
|
|
72
|
+
/** Sidebar collapsible mode */
|
|
73
|
+
collapsible?: "offcanvas" | "icon" | "none";
|
|
74
|
+
/** Max width for content area */
|
|
75
|
+
maxWidth?: string;
|
|
76
|
+
/** Language attribute */
|
|
77
|
+
lang?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const {
|
|
81
|
+
title,
|
|
82
|
+
siteTitle = "Docs",
|
|
83
|
+
description = "",
|
|
84
|
+
nav = [],
|
|
85
|
+
collapsible = "icon",
|
|
86
|
+
maxWidth = "max-w-3xl",
|
|
87
|
+
lang = "en",
|
|
88
|
+
} = Astro.props;
|
|
89
|
+
|
|
90
|
+
const currentPath = Astro.url.pathname.replace(/\/$/, "") || "/";
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
<!doctype html>
|
|
94
|
+
<html lang={lang}>
|
|
95
|
+
<head>
|
|
96
|
+
<meta charset="UTF-8" />
|
|
97
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
98
|
+
{description && <meta name="description" content={description} />}
|
|
99
|
+
<title>{title} — {siteTitle}</title>
|
|
100
|
+
<ClientRouter />
|
|
101
|
+
<script is:inline>
|
|
102
|
+
if (localStorage.getItem("theme") === "dark") {
|
|
103
|
+
document.documentElement.classList.add("dark");
|
|
104
|
+
}
|
|
105
|
+
</script>
|
|
106
|
+
<slot name="head" />
|
|
107
|
+
</head>
|
|
108
|
+
<body class="min-h-screen bg-background text-foreground antialiased">
|
|
109
|
+
<SidebarProvider>
|
|
110
|
+
<Sidebar collapsible={collapsible}>
|
|
111
|
+
<SidebarHeader>
|
|
112
|
+
<SidebarMenu>
|
|
113
|
+
<SidebarMenuItem>
|
|
114
|
+
<SidebarMenuButton href="/" size="lg">
|
|
115
|
+
<span class="font-semibold">{siteTitle}</span>
|
|
116
|
+
</SidebarMenuButton>
|
|
117
|
+
</SidebarMenuItem>
|
|
118
|
+
</SidebarMenu>
|
|
119
|
+
</SidebarHeader>
|
|
120
|
+
<SidebarSeparator />
|
|
121
|
+
<SidebarContent>
|
|
122
|
+
{nav.map((section) => (
|
|
123
|
+
<SidebarGroup>
|
|
124
|
+
<SidebarGroupLabel>{section.label}</SidebarGroupLabel>
|
|
125
|
+
<SidebarGroupContent>
|
|
126
|
+
<SidebarNavTree items={section.items} currentPath={currentPath} />
|
|
127
|
+
</SidebarGroupContent>
|
|
128
|
+
</SidebarGroup>
|
|
129
|
+
))}
|
|
130
|
+
</SidebarContent>
|
|
131
|
+
<SidebarRail />
|
|
132
|
+
</Sidebar>
|
|
133
|
+
<SidebarInset>
|
|
134
|
+
<header class="sticky top-0 z-40 flex items-center gap-3 border-b border-border bg-background/95 px-4 py-3 backdrop-blur-sm">
|
|
135
|
+
<SidebarTrigger />
|
|
136
|
+
<Separator orientation="vertical" class="h-5" />
|
|
137
|
+
<span class="text-sm font-medium" data-page-title>{title}</span>
|
|
138
|
+
<div class="ml-auto">
|
|
139
|
+
<slot name="header-actions">
|
|
140
|
+
<ThemeToggle />
|
|
141
|
+
</slot>
|
|
142
|
+
</div>
|
|
143
|
+
</header>
|
|
144
|
+
<main class="flex-1 px-6 py-8" transition:animate="fade">
|
|
145
|
+
<div class:list={["mx-auto", maxWidth]}>
|
|
146
|
+
<slot />
|
|
147
|
+
</div>
|
|
148
|
+
</main>
|
|
149
|
+
<slot name="footer" />
|
|
150
|
+
</SidebarInset>
|
|
151
|
+
</SidebarProvider>
|
|
152
|
+
|
|
153
|
+
<script>
|
|
154
|
+
import "../sidebar/sidebar.ts";
|
|
155
|
+
|
|
156
|
+
function updateActiveNav() {
|
|
157
|
+
const path = window.location.pathname.replace(/\/$/, "") || "/";
|
|
158
|
+
document.querySelectorAll("[data-nav-href]").forEach((el) => {
|
|
159
|
+
const href = el.getAttribute("data-nav-href")?.replace(/\/$/, "") || "";
|
|
160
|
+
if (href === path) {
|
|
161
|
+
el.setAttribute("data-active", "true");
|
|
162
|
+
let parent = el.parentElement;
|
|
163
|
+
while (parent) {
|
|
164
|
+
if (parent.tagName === "DETAILS") {
|
|
165
|
+
parent.setAttribute("open", "");
|
|
166
|
+
}
|
|
167
|
+
parent = parent.parentElement;
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
el.removeAttribute("data-active");
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
updateActiveNav();
|
|
176
|
+
|
|
177
|
+
document.addEventListener("astro:before-swap", (e: any) => {
|
|
178
|
+
const dark = document.documentElement.classList.contains("dark");
|
|
179
|
+
e.newDocument.documentElement.classList.toggle("dark", dark);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
document.addEventListener("astro:after-swap", () => {
|
|
183
|
+
updateActiveNav();
|
|
184
|
+
});
|
|
185
|
+
</script>
|
|
186
|
+
</body>
|
|
187
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DocsLayout } from "./DocsLayout.astro";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerClose = tv({
|
|
5
|
+
base: "inline-flex items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props { class?: string; [key: string]: unknown; }
|
|
9
|
+
const { class: className, ...rest } = Astro.props;
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<button class={drawerClose({ class: className })} data-part="close" type="button" {...rest}><slot /></button>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv, type VariantProps } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerBackdrop = tv({
|
|
5
|
+
base: "fixed inset-0 z-50 bg-black/80 transition-opacity",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const drawerContent = tv({
|
|
9
|
+
base: "fixed z-[51] flex flex-col bg-background transition-transform",
|
|
10
|
+
variants: {
|
|
11
|
+
direction: {
|
|
12
|
+
down: "inset-x-0 bottom-0 mt-24 rounded-t-[10px] border-t",
|
|
13
|
+
up: "inset-x-0 top-0 mb-24 rounded-b-[10px] border-b",
|
|
14
|
+
left: "inset-y-0 left-0 mr-24 w-3/4 rounded-r-[10px] border-r sm:max-w-sm",
|
|
15
|
+
right: "inset-y-0 right-0 ml-24 w-3/4 rounded-l-[10px] border-l sm:max-w-sm",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
defaultVariants: {
|
|
19
|
+
direction: "down",
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
type ContentVariants = VariantProps<typeof drawerContent>;
|
|
24
|
+
|
|
25
|
+
interface Props {
|
|
26
|
+
direction?: ContentVariants["direction"];
|
|
27
|
+
class?: string;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { direction = "down", class: className, ...rest } = Astro.props;
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
<div class={drawerBackdrop()} data-part="backdrop" data-state="closed" hidden></div>
|
|
35
|
+
<div
|
|
36
|
+
class={drawerContent({ direction, class: className })}
|
|
37
|
+
data-part="content"
|
|
38
|
+
data-direction={direction}
|
|
39
|
+
role="dialog"
|
|
40
|
+
aria-modal="true"
|
|
41
|
+
data-state="closed"
|
|
42
|
+
hidden
|
|
43
|
+
{...rest}
|
|
44
|
+
>
|
|
45
|
+
<slot />
|
|
46
|
+
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerDescription = tv({ base: "text-sm text-muted-foreground" });
|
|
5
|
+
|
|
6
|
+
interface Props { class?: string; [key: string]: unknown; }
|
|
7
|
+
const { class: className, ...rest } = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<p class={drawerDescription({ class: className })} data-part="description" {...rest}><slot /></p>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerFooter = tv({ base: "mt-auto flex flex-col gap-2 p-4" });
|
|
5
|
+
|
|
6
|
+
interface Props { class?: string; [key: string]: unknown; }
|
|
7
|
+
const { class: className, ...rest } = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<div class={drawerFooter({ class: className })} {...rest}><slot /></div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerHandle = tv({
|
|
5
|
+
base: "mx-auto mt-4 h-2 w-[100px] rounded-full 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
|
+
<div class={drawerHandle({ class: className })} data-part="handle" aria-hidden="true" {...rest}></div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerHeader = tv({ base: "grid gap-1.5 p-4 text-center sm:text-left" });
|
|
5
|
+
|
|
6
|
+
interface Props { class?: string; [key: string]: unknown; }
|
|
7
|
+
const { class: className, ...rest } = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<div class={drawerHeader({ class: className })} {...rest}><slot /></div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerTitle = tv({ base: "text-lg font-semibold leading-none tracking-tight" });
|
|
5
|
+
|
|
6
|
+
interface Props { class?: string; [key: string]: unknown; }
|
|
7
|
+
const { class: className, ...rest } = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<h2 class={drawerTitle({ class: className })} data-part="title" {...rest}><slot /></h2>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const drawerTrigger = tv({
|
|
5
|
+
base: "inline-flex items-center justify-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
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={drawerTrigger({ class: className })}
|
|
18
|
+
data-part="trigger"
|
|
19
|
+
type="button"
|
|
20
|
+
aria-haspopup="dialog"
|
|
21
|
+
aria-expanded="false"
|
|
22
|
+
{...rest}
|
|
23
|
+
>
|
|
24
|
+
<slot />
|
|
25
|
+
</button>
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { FocusTrap } from "@dogsbay/primitives/focus-trap";
|
|
2
|
+
import { ScrollLock } from "@dogsbay/primitives/scroll-lock";
|
|
3
|
+
import { markOthersInert } from "@dogsbay/primitives/inert";
|
|
4
|
+
import { createPortal } from "@dogsbay/primitives/portal";
|
|
5
|
+
|
|
6
|
+
// Swipe constants (matching Base UI)
|
|
7
|
+
const SWIPE_CLOSE_RATIO = 0.5;
|
|
8
|
+
const VELOCITY_THRESHOLD = 0.4;
|
|
9
|
+
const DAMPING_FACTOR = 0.5;
|
|
10
|
+
|
|
11
|
+
interface DrawerInstance {
|
|
12
|
+
root: HTMLElement;
|
|
13
|
+
trigger: HTMLElement | null;
|
|
14
|
+
content: HTMLElement;
|
|
15
|
+
backdrop: HTMLElement;
|
|
16
|
+
handle: HTMLElement | null;
|
|
17
|
+
focusTrap: FocusTrap;
|
|
18
|
+
cleanupPortal: (() => void) | null;
|
|
19
|
+
cleanupInert: (() => void) | null;
|
|
20
|
+
open: boolean;
|
|
21
|
+
direction: "down" | "up" | "left" | "right";
|
|
22
|
+
// Swipe state
|
|
23
|
+
swiping: boolean;
|
|
24
|
+
swipeStart: { x: number; y: number; time: number };
|
|
25
|
+
currentDisplacement: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const instances = new WeakMap<HTMLElement, DrawerInstance>();
|
|
29
|
+
|
|
30
|
+
let idCounter = 0;
|
|
31
|
+
function uniqueId(prefix: string) {
|
|
32
|
+
return `${prefix}-${++idCounter}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function init(root: HTMLElement) {
|
|
36
|
+
if (root.hasAttribute("data-initialized")) return;
|
|
37
|
+
root.setAttribute("data-initialized", "");
|
|
38
|
+
|
|
39
|
+
const ownPart = (selector: string) => {
|
|
40
|
+
const all = root.querySelectorAll(selector);
|
|
41
|
+
for (let i = 0; i < all.length; i++) {
|
|
42
|
+
const el = all[i] as HTMLElement;
|
|
43
|
+
if (el.closest("[data-component='drawer']") === root) return el;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const content = ownPart("[data-part='content']");
|
|
49
|
+
const backdrop = ownPart("[data-part='backdrop']");
|
|
50
|
+
const trigger = ownPart("[data-part='trigger']");
|
|
51
|
+
const handle = ownPart("[data-part='handle']");
|
|
52
|
+
if (!content || !backdrop) return;
|
|
53
|
+
|
|
54
|
+
const direction = (content.getAttribute("data-direction") || "down") as DrawerInstance["direction"];
|
|
55
|
+
const dialogId = content.id || uniqueId("base-drawer");
|
|
56
|
+
content.id = dialogId;
|
|
57
|
+
|
|
58
|
+
if (trigger) {
|
|
59
|
+
trigger.setAttribute("aria-controls", dialogId);
|
|
60
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const title = content.querySelector("[data-part='title']") as HTMLElement | null;
|
|
64
|
+
const description = content.querySelector("[data-part='description']") as HTMLElement | null;
|
|
65
|
+
if (title) {
|
|
66
|
+
const titleId = title.id || uniqueId("base-drawer-title");
|
|
67
|
+
title.id = titleId;
|
|
68
|
+
content.setAttribute("aria-labelledby", titleId);
|
|
69
|
+
}
|
|
70
|
+
if (description) {
|
|
71
|
+
const descId = description.id || uniqueId("base-drawer-desc");
|
|
72
|
+
description.id = descId;
|
|
73
|
+
content.setAttribute("aria-describedby", descId);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const instance: DrawerInstance = {
|
|
77
|
+
root,
|
|
78
|
+
trigger,
|
|
79
|
+
content,
|
|
80
|
+
backdrop,
|
|
81
|
+
handle,
|
|
82
|
+
focusTrap: new FocusTrap(content),
|
|
83
|
+
cleanupPortal: null,
|
|
84
|
+
cleanupInert: null,
|
|
85
|
+
open: false,
|
|
86
|
+
direction,
|
|
87
|
+
swiping: false,
|
|
88
|
+
swipeStart: { x: 0, y: 0, time: 0 },
|
|
89
|
+
currentDisplacement: 0,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
instances.set(root, instance);
|
|
93
|
+
|
|
94
|
+
// Trigger click
|
|
95
|
+
trigger?.addEventListener("click", () => openDrawer(instance));
|
|
96
|
+
|
|
97
|
+
// Close button
|
|
98
|
+
content.addEventListener("click", (e) => {
|
|
99
|
+
if ((e.target as HTMLElement).closest("[data-part='close']")) {
|
|
100
|
+
closeDrawer(instance);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Backdrop click closes
|
|
105
|
+
backdrop.addEventListener("click", () => closeDrawer(instance));
|
|
106
|
+
|
|
107
|
+
// Escape closes
|
|
108
|
+
content.addEventListener("keydown", (e) => {
|
|
109
|
+
if (e.key === "Escape") {
|
|
110
|
+
e.preventDefault();
|
|
111
|
+
closeDrawer(instance);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Swipe-to-dismiss on handle and content
|
|
116
|
+
setupSwipe(instance);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function setupSwipe(instance: DrawerInstance) {
|
|
120
|
+
const { content, handle, direction } = instance;
|
|
121
|
+
const swipeTarget = handle || content;
|
|
122
|
+
|
|
123
|
+
swipeTarget.addEventListener("pointerdown", (e) => {
|
|
124
|
+
if (!instance.open) return;
|
|
125
|
+
instance.swiping = true;
|
|
126
|
+
instance.swipeStart = { x: e.clientX, y: e.clientY, time: Date.now() };
|
|
127
|
+
instance.currentDisplacement = 0;
|
|
128
|
+
content.style.transition = "none";
|
|
129
|
+
swipeTarget.setPointerCapture(e.pointerId);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
swipeTarget.addEventListener("pointermove", (e) => {
|
|
133
|
+
if (!instance.swiping) return;
|
|
134
|
+
|
|
135
|
+
const dx = e.clientX - instance.swipeStart.x;
|
|
136
|
+
const dy = e.clientY - instance.swipeStart.y;
|
|
137
|
+
|
|
138
|
+
// Get displacement in the swipe direction
|
|
139
|
+
let displacement: number;
|
|
140
|
+
switch (direction) {
|
|
141
|
+
case "down": displacement = Math.max(0, dy); break;
|
|
142
|
+
case "up": displacement = Math.max(0, -dy); break;
|
|
143
|
+
case "left": displacement = Math.max(0, -dx); break;
|
|
144
|
+
case "right": displacement = Math.max(0, dx); break;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
instance.currentDisplacement = displacement;
|
|
148
|
+
|
|
149
|
+
// Apply transform with damping for over-drag
|
|
150
|
+
const size = getContentSize(instance);
|
|
151
|
+
const damped = displacement > size
|
|
152
|
+
? size + (displacement - size) * DAMPING_FACTOR
|
|
153
|
+
: displacement;
|
|
154
|
+
|
|
155
|
+
applySwipeTransform(instance, damped);
|
|
156
|
+
|
|
157
|
+
// Update backdrop opacity
|
|
158
|
+
const progress = Math.max(0, 1 - damped / size);
|
|
159
|
+
instance.backdrop.style.opacity = String(progress);
|
|
160
|
+
|
|
161
|
+
content.setAttribute("data-swiping", "");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
swipeTarget.addEventListener("pointerup", (e) => {
|
|
165
|
+
if (!instance.swiping) return;
|
|
166
|
+
instance.swiping = false;
|
|
167
|
+
content.removeAttribute("data-swiping");
|
|
168
|
+
content.style.transition = "";
|
|
169
|
+
|
|
170
|
+
const displacement = instance.currentDisplacement;
|
|
171
|
+
const size = getContentSize(instance);
|
|
172
|
+
const elapsed = Date.now() - instance.swipeStart.time;
|
|
173
|
+
const velocity = displacement / Math.max(elapsed, 1);
|
|
174
|
+
|
|
175
|
+
// Close if past threshold or velocity is high enough
|
|
176
|
+
if (displacement / size > SWIPE_CLOSE_RATIO || velocity > VELOCITY_THRESHOLD) {
|
|
177
|
+
// Animate to closed position then close
|
|
178
|
+
applySwipeTransform(instance, size);
|
|
179
|
+
instance.backdrop.style.opacity = "0";
|
|
180
|
+
setTimeout(() => closeDrawer(instance), 200);
|
|
181
|
+
} else {
|
|
182
|
+
// Snap back
|
|
183
|
+
applySwipeTransform(instance, 0);
|
|
184
|
+
instance.backdrop.style.opacity = "";
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function getContentSize(instance: DrawerInstance): number {
|
|
190
|
+
const { content, direction } = instance;
|
|
191
|
+
return direction === "down" || direction === "up"
|
|
192
|
+
? content.offsetHeight
|
|
193
|
+
: content.offsetWidth;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function applySwipeTransform(instance: DrawerInstance, displacement: number) {
|
|
197
|
+
const { content, direction } = instance;
|
|
198
|
+
switch (direction) {
|
|
199
|
+
case "down": content.style.transform = `translateY(${displacement}px)`; break;
|
|
200
|
+
case "up": content.style.transform = `translateY(${-displacement}px)`; break;
|
|
201
|
+
case "left": content.style.transform = `translateX(${-displacement}px)`; break;
|
|
202
|
+
case "right": content.style.transform = `translateX(${displacement}px)`; break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function openDrawer(instance: DrawerInstance) {
|
|
207
|
+
if (instance.open) return;
|
|
208
|
+
instance.open = true;
|
|
209
|
+
|
|
210
|
+
const contentPortal = createPortal(instance.content, instance.content.id);
|
|
211
|
+
const backdropPortal = createPortal(instance.backdrop, `${instance.content.id}-backdrop`);
|
|
212
|
+
instance.cleanupPortal = () => { contentPortal(); backdropPortal(); };
|
|
213
|
+
|
|
214
|
+
instance.content.hidden = false;
|
|
215
|
+
instance.backdrop.hidden = false;
|
|
216
|
+
instance.content.setAttribute("data-state", "open");
|
|
217
|
+
instance.backdrop.setAttribute("data-state", "open");
|
|
218
|
+
instance.content.style.transform = "";
|
|
219
|
+
instance.backdrop.style.opacity = "";
|
|
220
|
+
instance.trigger?.setAttribute("aria-expanded", "true");
|
|
221
|
+
|
|
222
|
+
ScrollLock.activate();
|
|
223
|
+
instance.cleanupInert = markOthersInert(instance.content);
|
|
224
|
+
instance.focusTrap.activate();
|
|
225
|
+
|
|
226
|
+
instance.root.dispatchEvent(new CustomEvent("base-drawer:open", { bubbles: true }));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function closeDrawer(instance: DrawerInstance) {
|
|
230
|
+
if (!instance.open) return;
|
|
231
|
+
instance.open = false;
|
|
232
|
+
|
|
233
|
+
instance.focusTrap.deactivate();
|
|
234
|
+
instance.cleanupInert?.();
|
|
235
|
+
instance.cleanupInert = null;
|
|
236
|
+
ScrollLock.deactivate();
|
|
237
|
+
|
|
238
|
+
instance.content.setAttribute("data-state", "closed");
|
|
239
|
+
instance.backdrop.setAttribute("data-state", "closed");
|
|
240
|
+
instance.content.style.transform = "";
|
|
241
|
+
instance.backdrop.style.opacity = "";
|
|
242
|
+
instance.trigger?.setAttribute("aria-expanded", "false");
|
|
243
|
+
|
|
244
|
+
instance.content.hidden = true;
|
|
245
|
+
instance.backdrop.hidden = true;
|
|
246
|
+
instance.cleanupPortal?.();
|
|
247
|
+
instance.cleanupPortal = null;
|
|
248
|
+
|
|
249
|
+
instance.trigger?.focus();
|
|
250
|
+
instance.root.dispatchEvent(new CustomEvent("base-drawer:close", { bubbles: true }));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function initAll() {
|
|
254
|
+
document.querySelectorAll<HTMLElement>("[data-component='drawer']").forEach(init);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (document.readyState === "loading") {
|
|
258
|
+
document.addEventListener("DOMContentLoaded", initAll);
|
|
259
|
+
} else {
|
|
260
|
+
initAll();
|
|
261
|
+
}
|
|
262
|
+
document.addEventListener("astro:page-load", initAll);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as Drawer } from "./Drawer.astro";
|
|
2
|
+
export { default as DrawerTrigger } from "./DrawerTrigger.astro";
|
|
3
|
+
export { default as DrawerContent } from "./DrawerContent.astro";
|
|
4
|
+
export { default as DrawerHandle } from "./DrawerHandle.astro";
|
|
5
|
+
export { default as DrawerHeader } from "./DrawerHeader.astro";
|
|
6
|
+
export { default as DrawerTitle } from "./DrawerTitle.astro";
|
|
7
|
+
export { default as DrawerDescription } from "./DrawerDescription.astro";
|
|
8
|
+
export { default as DrawerFooter } from "./DrawerFooter.astro";
|
|
9
|
+
export { default as DrawerClose } from "./DrawerClose.astro";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const dropdownMenu = tv({
|
|
5
|
+
base: "relative inline-block",
|
|
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={dropdownMenu({ class: className })}
|
|
18
|
+
data-component="dropdown-menu"
|
|
19
|
+
{...rest}
|
|
20
|
+
>
|
|
21
|
+
<slot />
|
|
22
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
const dropdownMenuContent = tv({
|
|
5
|
+
base: "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
side?: "top" | "bottom" | "left" | "right";
|
|
10
|
+
align?: "start" | "center" | "end";
|
|
11
|
+
class?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
side = "bottom",
|
|
17
|
+
align = "start",
|
|
18
|
+
class: className,
|
|
19
|
+
...rest
|
|
20
|
+
} = Astro.props;
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<div
|
|
24
|
+
class={dropdownMenuContent({ class: className })}
|
|
25
|
+
data-part="content"
|
|
26
|
+
data-side={side}
|
|
27
|
+
data-align={align}
|
|
28
|
+
role="menu"
|
|
29
|
+
hidden
|
|
30
|
+
{...rest}
|
|
31
|
+
>
|
|
32
|
+
<slot />
|
|
33
|
+
</div>
|