@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,212 @@
|
|
|
1
|
+
interface CommandInstance {
|
|
2
|
+
root: HTMLElement;
|
|
3
|
+
input: HTMLInputElement;
|
|
4
|
+
list: HTMLElement;
|
|
5
|
+
empty: HTMLElement | null;
|
|
6
|
+
items: HTMLElement[];
|
|
7
|
+
groups: HTMLElement[];
|
|
8
|
+
selectedIndex: number;
|
|
9
|
+
filter: (item: HTMLElement, query: string) => boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const instances = new WeakMap<HTMLElement, CommandInstance>();
|
|
13
|
+
|
|
14
|
+
function defaultFilter(item: HTMLElement, query: string): boolean {
|
|
15
|
+
const text = item.textContent?.toLowerCase() || "";
|
|
16
|
+
const keywords = item.dataset.keywords?.toLowerCase() || "";
|
|
17
|
+
const q = query.toLowerCase();
|
|
18
|
+
return text.includes(q) || keywords.includes(q);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function initCommand(root: HTMLElement) {
|
|
22
|
+
if (instances.has(root)) return;
|
|
23
|
+
|
|
24
|
+
const input = root.querySelector(
|
|
25
|
+
"[data-part='input']",
|
|
26
|
+
) as HTMLInputElement | null;
|
|
27
|
+
const list = root.querySelector(
|
|
28
|
+
"[data-part='list']",
|
|
29
|
+
) as HTMLElement | null;
|
|
30
|
+
const empty = root.querySelector(
|
|
31
|
+
"[data-part='empty']",
|
|
32
|
+
) as HTMLElement | null;
|
|
33
|
+
|
|
34
|
+
if (!input || !list) return;
|
|
35
|
+
|
|
36
|
+
// ARIA linkage: combobox → listbox
|
|
37
|
+
if (!list.id) list.id = `command-list-${Math.random().toString(36).slice(2, 8)}`;
|
|
38
|
+
input.setAttribute("aria-controls", list.id);
|
|
39
|
+
|
|
40
|
+
const items = Array.from(
|
|
41
|
+
list.querySelectorAll("[data-part='item']"),
|
|
42
|
+
) as HTMLElement[];
|
|
43
|
+
const groups = Array.from(
|
|
44
|
+
list.querySelectorAll("[data-part='group']"),
|
|
45
|
+
) as HTMLElement[];
|
|
46
|
+
|
|
47
|
+
const instance: CommandInstance = {
|
|
48
|
+
root,
|
|
49
|
+
input,
|
|
50
|
+
list,
|
|
51
|
+
empty,
|
|
52
|
+
items,
|
|
53
|
+
groups,
|
|
54
|
+
selectedIndex: -1,
|
|
55
|
+
filter: defaultFilter,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
instances.set(root, instance);
|
|
59
|
+
|
|
60
|
+
// Input filtering
|
|
61
|
+
input.addEventListener("input", () => {
|
|
62
|
+
filterItems(root);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Keyboard navigation
|
|
66
|
+
input.addEventListener("keydown", (e) => {
|
|
67
|
+
const visibleItems = getVisibleItems(instance);
|
|
68
|
+
if (visibleItems.length === 0) return;
|
|
69
|
+
|
|
70
|
+
if (e.key === "ArrowDown") {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
const currentVisible = instance.selectedIndex >= 0
|
|
73
|
+
? visibleItems.indexOf(instance.items[instance.selectedIndex])
|
|
74
|
+
: -1;
|
|
75
|
+
const nextIdx = currentVisible < visibleItems.length - 1
|
|
76
|
+
? currentVisible + 1
|
|
77
|
+
: 0;
|
|
78
|
+
selectItem(root, instance.items.indexOf(visibleItems[nextIdx]));
|
|
79
|
+
} else if (e.key === "ArrowUp") {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
const currentVisible = instance.selectedIndex >= 0
|
|
82
|
+
? visibleItems.indexOf(instance.items[instance.selectedIndex])
|
|
83
|
+
: -1;
|
|
84
|
+
const prevIdx = currentVisible > 0
|
|
85
|
+
? currentVisible - 1
|
|
86
|
+
: visibleItems.length - 1;
|
|
87
|
+
selectItem(root, instance.items.indexOf(visibleItems[prevIdx]));
|
|
88
|
+
} else if (e.key === "Home") {
|
|
89
|
+
e.preventDefault();
|
|
90
|
+
selectItem(root, instance.items.indexOf(visibleItems[0]));
|
|
91
|
+
} else if (e.key === "End") {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
selectItem(
|
|
94
|
+
root,
|
|
95
|
+
instance.items.indexOf(visibleItems[visibleItems.length - 1]),
|
|
96
|
+
);
|
|
97
|
+
} else if (e.key === "Enter") {
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
if (instance.selectedIndex >= 0) {
|
|
100
|
+
const item = instance.items[instance.selectedIndex];
|
|
101
|
+
if (!item.hidden && item.dataset.disabled !== "true") {
|
|
102
|
+
item.click();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Item hover
|
|
109
|
+
items.forEach((item) => {
|
|
110
|
+
item.addEventListener("pointerenter", () => {
|
|
111
|
+
if (item.hidden || item.dataset.disabled === "true") return;
|
|
112
|
+
selectItem(root, instance.items.indexOf(item));
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Initial filter (empty query shows all)
|
|
117
|
+
filterItems(root);
|
|
118
|
+
|
|
119
|
+
// Select first visible item
|
|
120
|
+
const visibleItems = getVisibleItems(instance);
|
|
121
|
+
if (visibleItems.length > 0) {
|
|
122
|
+
selectItem(root, instance.items.indexOf(visibleItems[0]));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function getVisibleItems(instance: CommandInstance): HTMLElement[] {
|
|
127
|
+
return instance.items.filter(
|
|
128
|
+
(item) => !item.hidden && item.dataset.disabled !== "true",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function filterItems(root: HTMLElement) {
|
|
133
|
+
const instance = instances.get(root);
|
|
134
|
+
if (!instance) return;
|
|
135
|
+
|
|
136
|
+
const query = instance.input.value.trim();
|
|
137
|
+
|
|
138
|
+
// Filter items
|
|
139
|
+
let anyVisible = false;
|
|
140
|
+
instance.items.forEach((item) => {
|
|
141
|
+
const matches = query === "" || instance.filter(item, query);
|
|
142
|
+
item.hidden = !matches;
|
|
143
|
+
if (matches) anyVisible = true;
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Hide empty groups (groups where all items are hidden)
|
|
147
|
+
instance.groups.forEach((group) => {
|
|
148
|
+
const groupItems = Array.from(
|
|
149
|
+
group.querySelectorAll("[data-part='item']"),
|
|
150
|
+
) as HTMLElement[];
|
|
151
|
+
const hasVisible = groupItems.some((item) => !item.hidden);
|
|
152
|
+
group.hidden = !hasVisible;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Show/hide empty message
|
|
156
|
+
if (instance.empty) {
|
|
157
|
+
instance.empty.hidden = anyVisible || query === "";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Select first visible item
|
|
161
|
+
const visibleItems = getVisibleItems(instance);
|
|
162
|
+
if (visibleItems.length > 0) {
|
|
163
|
+
selectItem(root, instance.items.indexOf(visibleItems[0]));
|
|
164
|
+
} else {
|
|
165
|
+
clearSelection(root);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function selectItem(root: HTMLElement, index: number) {
|
|
170
|
+
const instance = instances.get(root);
|
|
171
|
+
if (!instance) return;
|
|
172
|
+
if (index < 0 || index >= instance.items.length) return;
|
|
173
|
+
|
|
174
|
+
// Clear previous
|
|
175
|
+
if (instance.selectedIndex >= 0) {
|
|
176
|
+
instance.items[instance.selectedIndex].removeAttribute("data-selected");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
instance.selectedIndex = index;
|
|
180
|
+
const item = instance.items[index];
|
|
181
|
+
item.setAttribute("data-selected", "true");
|
|
182
|
+
item.scrollIntoView({ block: "nearest" });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function clearSelection(root: HTMLElement) {
|
|
186
|
+
const instance = instances.get(root);
|
|
187
|
+
if (!instance) return;
|
|
188
|
+
|
|
189
|
+
if (instance.selectedIndex >= 0) {
|
|
190
|
+
instance.items[instance.selectedIndex].removeAttribute("data-selected");
|
|
191
|
+
}
|
|
192
|
+
instance.selectedIndex = -1;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Auto-initialize
|
|
196
|
+
function init() {
|
|
197
|
+
document
|
|
198
|
+
.querySelectorAll("[data-component='command']")
|
|
199
|
+
.forEach((el) => {
|
|
200
|
+
initCommand(el as HTMLElement);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (document.readyState === "loading") {
|
|
205
|
+
document.addEventListener("DOMContentLoaded", init);
|
|
206
|
+
} else {
|
|
207
|
+
init();
|
|
208
|
+
}
|
|
209
|
+
document.addEventListener("astro:page-load", init);
|
|
210
|
+
document.addEventListener("astro:after-swap", init);
|
|
211
|
+
|
|
212
|
+
export { initCommand, filterItems };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { default as Command } from "./Command.astro";
|
|
2
|
+
export { default as CommandInput } from "./CommandInput.astro";
|
|
3
|
+
export { default as CommandList } from "./CommandList.astro";
|
|
4
|
+
export { default as CommandEmpty } from "./CommandEmpty.astro";
|
|
5
|
+
export { default as CommandGroup } from "./CommandGroup.astro";
|
|
6
|
+
export { default as CommandItem } from "./CommandItem.astro";
|
|
7
|
+
export { default as CommandSeparator } from "./CommandSeparator.astro";
|
|
8
|
+
export { default as CommandShortcut } from "./CommandShortcut.astro";
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* ContentRenderer — recursive TreeNode[] renderer (DEPRECATED).
|
|
4
|
+
*
|
|
5
|
+
* STATUS: deprecated. Frozen for new TreeNode types. Scheduled for removal.
|
|
6
|
+
*
|
|
7
|
+
* The canonical TreeNode → Astro path is `@dogsbay/format-astro` (the
|
|
8
|
+
* `treeToAstro()` serializer + `exportAstroProject()` project generator).
|
|
9
|
+
* That path emits editable `.astro` source files with explicit component
|
|
10
|
+
* imports — same shipping model as the rest of Dogsbay (you own the source).
|
|
11
|
+
*
|
|
12
|
+
* This component existed as a stop-gap before format-astro shipped — a
|
|
13
|
+
* runtime renderer that walks a TreeNode and emits markup at Astro build
|
|
14
|
+
* time. The four format exporters (format-astro, format-mkdocs,
|
|
15
|
+
* format-obsidian, format-dogsbay-md) all follow the "compile to source"
|
|
16
|
+
* model and bypass this renderer.
|
|
17
|
+
*
|
|
18
|
+
* What still uses ContentRenderer (kept working until removal):
|
|
19
|
+
* - apps/demo/src/pages/{docs,material,mkdocs,mkdocs-material}/[...slug].astro
|
|
20
|
+
* - apps/material-docs/src/pages/docs/[...slug].astro
|
|
21
|
+
* - apps/ui-docs/src/pages/handbook/styling.astro
|
|
22
|
+
* - the legacy `--dynamic` flag on `dogsbay import-mkdocs`
|
|
23
|
+
*
|
|
24
|
+
* DO NOT add new TreeNode-type cases here. Add them to format-astro
|
|
25
|
+
* instead. When the listed consumers are migrated, this file can be
|
|
26
|
+
* deleted.
|
|
27
|
+
*
|
|
28
|
+
* Imports: alert, code-block, code-rich, tabs, table, steps, diagram,
|
|
29
|
+
* api-params, api-symbol, api-doc, api-source, youtube, image, grid
|
|
30
|
+
*/
|
|
31
|
+
import Alert from "../alert/Alert.astro";
|
|
32
|
+
import AlertTitle from "../alert/AlertTitle.astro";
|
|
33
|
+
import AlertDescription from "../alert/AlertDescription.astro";
|
|
34
|
+
import CollapsibleAlert from "../alert/CollapsibleAlert.astro";
|
|
35
|
+
import Steps from "../steps/Steps.astro";
|
|
36
|
+
import Step from "../steps/Step.astro";
|
|
37
|
+
import SubSteps from "../steps/SubSteps.astro";
|
|
38
|
+
import CodeBlock from "../code-block/CodeBlock.astro";
|
|
39
|
+
import CodeRich from "../code-rich/CodeRich.astro";
|
|
40
|
+
import "../code-rich/code-rich.css";
|
|
41
|
+
import Diagram from "../diagram/Diagram.astro";
|
|
42
|
+
import ApiParams from "../api-params/ApiParams.astro";
|
|
43
|
+
import ApiSymbol from "../api-symbol/ApiSymbol.astro";
|
|
44
|
+
import ApiDoc from "../api-doc/ApiDoc.astro";
|
|
45
|
+
import ApiSource from "../api-source/ApiSource.astro";
|
|
46
|
+
import Grid from "../grid/Grid.astro";
|
|
47
|
+
import YouTube from "../youtube/YouTube.astro";
|
|
48
|
+
import BlockImage from "../image/Image.astro";
|
|
49
|
+
import Tabs from "../tabs/Tabs.astro";
|
|
50
|
+
import TabsList from "../tabs/TabsList.astro";
|
|
51
|
+
import TabsTrigger from "../tabs/TabsTrigger.astro";
|
|
52
|
+
import TabsContent from "../tabs/TabsContent.astro";
|
|
53
|
+
import Table from "../table/Table.astro";
|
|
54
|
+
import TableHeader from "../table/TableHeader.astro";
|
|
55
|
+
import TableBody from "../table/TableBody.astro";
|
|
56
|
+
import TableRow from "../table/TableRow.astro";
|
|
57
|
+
import TableHead from "../table/TableHead.astro";
|
|
58
|
+
import TableCell from "../table/TableCell.astro";
|
|
59
|
+
import InlineRenderer from "./InlineRenderer.astro";
|
|
60
|
+
import MathKatex from "../math/MathKatex.astro";
|
|
61
|
+
|
|
62
|
+
interface InlineNode {
|
|
63
|
+
type: string;
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface TreeNode {
|
|
68
|
+
type: string;
|
|
69
|
+
props?: Record<string, unknown>;
|
|
70
|
+
html?: string;
|
|
71
|
+
inline?: InlineNode[];
|
|
72
|
+
children?: TreeNode[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
interface Props {
|
|
76
|
+
node: TreeNode;
|
|
77
|
+
images?: Record<string, ImageMetadata>;
|
|
78
|
+
icons?: any;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { node, images = {}, icons } = Astro.props;
|
|
82
|
+
const children = node.children || [];
|
|
83
|
+
|
|
84
|
+
// Determine if code block needs CodeRich (annotations/line numbers)
|
|
85
|
+
const isRichCode = node.type === "code" && (
|
|
86
|
+
node.props?.lineNumbers ||
|
|
87
|
+
node.props?.highlights ||
|
|
88
|
+
((node.props?.code as string) || "").includes("[!code")
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// html-container helpers
|
|
92
|
+
const containerAttrs = node.type === "html-container"
|
|
93
|
+
? (node.props?.attrs as Record<string, string>) || {}
|
|
94
|
+
: {};
|
|
95
|
+
const containerClass = containerAttrs.class || "";
|
|
96
|
+
const isColumns = node.type === "html-container" && containerClass.includes("mdx-columns");
|
|
97
|
+
const isGridCards = node.type === "html-container" && containerClass.includes("grid") && containerClass.includes("cards");
|
|
98
|
+
|
|
99
|
+
// Block image detection: paragraph with sole image (or link-wrapped image) inline child
|
|
100
|
+
const blockImage = (() => {
|
|
101
|
+
if (node.type !== "paragraph" || !node.children?.length) return null;
|
|
102
|
+
const prose = node.children[0];
|
|
103
|
+
if (prose?.type !== "prose" || !prose.inline) return null;
|
|
104
|
+
const meaningful = prose.inline.filter((n: InlineNode) => !(n.type === "text" && (n.text as string || "").trim() === ""));
|
|
105
|
+
if (meaningful.length !== 1) return null;
|
|
106
|
+
const sole = meaningful[0];
|
|
107
|
+
if (sole.type === "image") return sole;
|
|
108
|
+
if (sole.type === "link") {
|
|
109
|
+
const linkChildren = (sole.children as InlineNode[]) || [];
|
|
110
|
+
if (linkChildren.length === 1 && linkChildren[0].type === "image") return linkChildren[0];
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
})();
|
|
114
|
+
|
|
115
|
+
/** Convert InlineNode[] to HTML string (for headings rendered via set:html). */
|
|
116
|
+
function inlineToHtml(nodes: InlineNode[]): string {
|
|
117
|
+
return nodes.map(n => {
|
|
118
|
+
switch (n.type) {
|
|
119
|
+
case "text": {
|
|
120
|
+
let s = String(n.text || "");
|
|
121
|
+
if (n.bold) s = `<strong>${s}</strong>`;
|
|
122
|
+
if (n.italic) s = `<em>${s}</em>`;
|
|
123
|
+
if (n.strikethrough) s = `<s>${s}</s>`;
|
|
124
|
+
return s;
|
|
125
|
+
}
|
|
126
|
+
case "code": return `<code>${n.text || ""}</code>`;
|
|
127
|
+
case "highlight": return `<mark>${inlineToHtml((n.children || []) as InlineNode[])}</mark>`;
|
|
128
|
+
case "link": return `<a href="${n.href || ""}">${inlineToHtml((n.children || []) as InlineNode[])}</a>`;
|
|
129
|
+
case "image": return `<img src="${n.src || ""}" alt="${n.alt || ""}">`;
|
|
130
|
+
case "kbd": return (n.keys as string[] || []).map((k: string) => `<kbd>${k}</kbd>`).join("+");
|
|
131
|
+
case "html-inline": return String(n.html || "");
|
|
132
|
+
case "break": return "<br>";
|
|
133
|
+
default: return "";
|
|
134
|
+
}
|
|
135
|
+
}).join("");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Resolve an image src path to ImageMetadata from the images map. */
|
|
139
|
+
function resolveImage(src: string): ImageMetadata | undefined {
|
|
140
|
+
if (!src || src.startsWith("http")) return undefined;
|
|
141
|
+
const normalized = "/" + src.replace(/^(?:\.\.\/)+/, "").replace(/^\/+/, "");
|
|
142
|
+
const clean = normalized.replace(/#.*$/, "");
|
|
143
|
+
return images[clean];
|
|
144
|
+
}
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
{/* ── Prose ──────────────────────────────────────────────── */}
|
|
148
|
+
{node.type === "prose" && node.inline && (
|
|
149
|
+
<Fragment>
|
|
150
|
+
{node.inline.map(span => <InlineRenderer node={span} icons={icons} images={images} />)}
|
|
151
|
+
</Fragment>
|
|
152
|
+
)}
|
|
153
|
+
{node.type === "prose" && !node.inline && <Fragment set:html={node.html} />}
|
|
154
|
+
|
|
155
|
+
{/* ── Heading with anchor ────────────────────────────────── */}
|
|
156
|
+
{node.type === "heading" && (
|
|
157
|
+
<Fragment set:html={
|
|
158
|
+
`<h${node.props!.level} id="${node.props!.slug || ''}" class="group scroll-mt-20">` +
|
|
159
|
+
`${node.inline ? inlineToHtml(node.inline) : (node.html?.replace(/<h\d[^>]*>|<\/h\d>/g, '') || node.props!.text || '')}` +
|
|
160
|
+
`<a href="#${node.props!.slug || ''}" class="no-underline ml-2 opacity-0 group-hover:opacity-50 transition-opacity text-muted-foreground" aria-label="Link to this heading">¶</a>` +
|
|
161
|
+
`</h${node.props!.level}>`
|
|
162
|
+
} />
|
|
163
|
+
)}
|
|
164
|
+
|
|
165
|
+
{/* ── Paragraph — block image gets <figure>, normal gets <p> */}
|
|
166
|
+
{node.type === "paragraph" && blockImage && (
|
|
167
|
+
<BlockImage
|
|
168
|
+
src={blockImage.src as string}
|
|
169
|
+
alt={blockImage.alt as string || ""}
|
|
170
|
+
title={blockImage.title as string}
|
|
171
|
+
width={blockImage.width as number}
|
|
172
|
+
height={blockImage.height as number}
|
|
173
|
+
imageData={resolveImage(blockImage.src as string)}
|
|
174
|
+
block
|
|
175
|
+
/>
|
|
176
|
+
)}
|
|
177
|
+
{node.type === "paragraph" && !blockImage && (
|
|
178
|
+
<p>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</p>
|
|
179
|
+
)}
|
|
180
|
+
|
|
181
|
+
{/* ── Code block — smart routing to CodeBlock or CodeRich ── */}
|
|
182
|
+
{node.type === "code" && !isRichCode && (
|
|
183
|
+
<CodeBlock
|
|
184
|
+
code={(node.props?.code as string) || ""}
|
|
185
|
+
lang={(node.props?.lang as string) || "plaintext"}
|
|
186
|
+
title={node.props?.title as string}
|
|
187
|
+
/>
|
|
188
|
+
)}
|
|
189
|
+
{node.type === "code" && isRichCode && (
|
|
190
|
+
<CodeRich
|
|
191
|
+
code={(node.props?.code as string) || ""}
|
|
192
|
+
lang={(node.props?.lang as string) || "plaintext"}
|
|
193
|
+
title={node.props?.title as string}
|
|
194
|
+
lineNumbers={!!node.props?.lineNumbers}
|
|
195
|
+
highlights={node.props?.highlights as string}
|
|
196
|
+
/>
|
|
197
|
+
)}
|
|
198
|
+
|
|
199
|
+
{/* ── Callout / Admonition ───────────────────────────────── */}
|
|
200
|
+
{node.type === "callout" && (
|
|
201
|
+
<Alert variant={(node.props?.variant as any) || "note"} class="my-4">
|
|
202
|
+
{node.props?.title && <AlertTitle>{node.props.title}</AlertTitle>}
|
|
203
|
+
<AlertDescription>
|
|
204
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
205
|
+
</AlertDescription>
|
|
206
|
+
</Alert>
|
|
207
|
+
)}
|
|
208
|
+
|
|
209
|
+
{/* ── Details / Collapsible admonition ───────────────────── */}
|
|
210
|
+
{node.type === "details" && (
|
|
211
|
+
<CollapsibleAlert
|
|
212
|
+
variant={(node.props?.variant as any) || "note"}
|
|
213
|
+
title={(node.props?.title || node.props?.variant || "Details") as string}
|
|
214
|
+
open={node.props?.open as boolean}
|
|
215
|
+
class="my-4"
|
|
216
|
+
>
|
|
217
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
218
|
+
</CollapsibleAlert>
|
|
219
|
+
)}
|
|
220
|
+
|
|
221
|
+
{/* ── Steps ──────────────────────────────────────────────── */}
|
|
222
|
+
{node.type === "steps" && (
|
|
223
|
+
<Steps>
|
|
224
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
225
|
+
</Steps>
|
|
226
|
+
)}
|
|
227
|
+
{node.type === "step" && (
|
|
228
|
+
<Step>
|
|
229
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
230
|
+
</Step>
|
|
231
|
+
)}
|
|
232
|
+
{node.type === "substeps" && (
|
|
233
|
+
<SubSteps>
|
|
234
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
235
|
+
</SubSteps>
|
|
236
|
+
)}
|
|
237
|
+
|
|
238
|
+
{/* ── Tabs ────────────────────────────────────────────────── */}
|
|
239
|
+
{node.type === "tabs" && (
|
|
240
|
+
<Tabs defaultValue={(children[0]?.props?.value || children[0]?.props?.label || "tab-0") as string} syncKey={node.props?.syncKey as string | undefined} class="my-4">
|
|
241
|
+
<TabsList>
|
|
242
|
+
{children.map((tab, i) => (
|
|
243
|
+
<TabsTrigger value={(tab.props?.value || tab.props?.label || `tab-${i}`) as string}>
|
|
244
|
+
{tab.inline
|
|
245
|
+
? tab.inline.map((span: any) => <InlineRenderer node={span} icons={icons} images={images} />)
|
|
246
|
+
: (tab.props?.label || tab.props?.title) as string
|
|
247
|
+
}
|
|
248
|
+
</TabsTrigger>
|
|
249
|
+
))}
|
|
250
|
+
</TabsList>
|
|
251
|
+
{children.map((tab, i) => (
|
|
252
|
+
<TabsContent value={(tab.props?.value || tab.props?.label || `tab-${i}`) as string}>
|
|
253
|
+
{(tab.children || []).map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
254
|
+
</TabsContent>
|
|
255
|
+
))}
|
|
256
|
+
</Tabs>
|
|
257
|
+
)}
|
|
258
|
+
{node.type === "tab" && (
|
|
259
|
+
<div>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</div>
|
|
260
|
+
)}
|
|
261
|
+
|
|
262
|
+
{/* ── Definition list ────────────────────────────────────── */}
|
|
263
|
+
{node.type === "deflist" && (
|
|
264
|
+
<dl class="my-4 space-y-2">
|
|
265
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
266
|
+
</dl>
|
|
267
|
+
)}
|
|
268
|
+
{node.type === "dt" && (
|
|
269
|
+
<dt class="font-semibold">{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</dt>
|
|
270
|
+
)}
|
|
271
|
+
{node.type === "dd" && (
|
|
272
|
+
<dd class="ml-6 text-muted-foreground">{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</dd>
|
|
273
|
+
)}
|
|
274
|
+
|
|
275
|
+
{/* ── Table ──────────────────────────────────────────────── */}
|
|
276
|
+
{node.type === "table" && (
|
|
277
|
+
<Table class="my-4">
|
|
278
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
279
|
+
</Table>
|
|
280
|
+
)}
|
|
281
|
+
{node.type === "thead" && <TableHeader>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</TableHeader>}
|
|
282
|
+
{node.type === "tbody" && <TableBody>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</TableBody>}
|
|
283
|
+
{node.type === "tr" && <TableRow>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</TableRow>}
|
|
284
|
+
{node.type === "th" && <TableHead>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</TableHead>}
|
|
285
|
+
{node.type === "td" && <TableCell>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</TableCell>}
|
|
286
|
+
|
|
287
|
+
{/* ── Standard block elements ────────────────────────────── */}
|
|
288
|
+
{node.type === "ordered-list" && <ol>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</ol>}
|
|
289
|
+
{node.type === "unordered-list" && <ul>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</ul>}
|
|
290
|
+
{node.type === "list-item" && <li>{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}</li>}
|
|
291
|
+
{node.type === "blockquote" && (
|
|
292
|
+
<blockquote class="border-l-4 border-border pl-4 italic text-muted-foreground">
|
|
293
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
294
|
+
</blockquote>
|
|
295
|
+
)}
|
|
296
|
+
{node.type === "hr" && <hr class="my-8 border-border" />}
|
|
297
|
+
{node.type === "html" && (() => {
|
|
298
|
+
let html = node.html || "";
|
|
299
|
+
if (html.includes("<img") && Object.keys(images).length > 0) {
|
|
300
|
+
html = html.replace(/src="([^"]+)"/g, (_match: string, src: string) => {
|
|
301
|
+
const resolved = resolveImage(src);
|
|
302
|
+
if (resolved) return `src="${resolved.src}" width="${resolved.width}" height="${resolved.height}"`;
|
|
303
|
+
return _match;
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return <Fragment set:html={html} />;
|
|
307
|
+
})()}
|
|
308
|
+
|
|
309
|
+
{/* ── API Documentation ──────────────────────────────────── */}
|
|
310
|
+
{(node.type === "api-class" || node.type === "api-member") && (
|
|
311
|
+
<ApiSymbol
|
|
312
|
+
name={(node.props?.name as string) || ""}
|
|
313
|
+
kind={(node.props?.kind as any) || "func"}
|
|
314
|
+
signature={node.props?.signature as string}
|
|
315
|
+
bases={(node.props?.bases as string[]) || []}
|
|
316
|
+
type={node.props?.type as string}
|
|
317
|
+
level={node.type === "api-class" ? 2 : 3}
|
|
318
|
+
>
|
|
319
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
320
|
+
</ApiSymbol>
|
|
321
|
+
)}
|
|
322
|
+
{node.type === "api-doc" && (
|
|
323
|
+
<ApiDoc html={(node.props?.html as string) || ""} />
|
|
324
|
+
)}
|
|
325
|
+
{node.type === "api-params" && (
|
|
326
|
+
<ApiParams params={(node.props?.params as any[]) || []} />
|
|
327
|
+
)}
|
|
328
|
+
{node.type === "api-source" && (
|
|
329
|
+
<ApiSource
|
|
330
|
+
code={(node.props?.code as string) || ""}
|
|
331
|
+
file={node.props?.file as string}
|
|
332
|
+
line={node.props?.line as number}
|
|
333
|
+
/>
|
|
334
|
+
)}
|
|
335
|
+
|
|
336
|
+
{/* ── Diagram — pre-rendered SVG ─────────────────────────── */}
|
|
337
|
+
{node.type === "diagram" && (
|
|
338
|
+
<Diagram
|
|
339
|
+
lang={(node.props?.lang as string) || "mermaid"}
|
|
340
|
+
code={(node.props?.code as string) || ""}
|
|
341
|
+
svg={(node.props?.svg as string) || ""}
|
|
342
|
+
title={node.props?.title as string}
|
|
343
|
+
/>
|
|
344
|
+
)}
|
|
345
|
+
|
|
346
|
+
{/* ── Footnotes ──────────────────────────────────────────── */}
|
|
347
|
+
{node.type === "footnote-list" && (
|
|
348
|
+
<ol class="list-decimal pl-6 space-y-1" data-footnote-list>
|
|
349
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
350
|
+
</ol>
|
|
351
|
+
)}
|
|
352
|
+
{node.type === "footnote-def" && (
|
|
353
|
+
<li id={(node.props?.id as string) || ""} class="text-sm text-muted-foreground">
|
|
354
|
+
{node.inline
|
|
355
|
+
? <span>{node.inline.map(span => <InlineRenderer node={span} icons={icons} images={images} />)}</span>
|
|
356
|
+
: <Fragment set:html={node.html} />
|
|
357
|
+
}
|
|
358
|
+
{" "}<a href={`#${node.props?.backrefId || ""}`} class="text-primary hover:underline" aria-label={`Back to reference ${node.props?.label}`}>↩</a>
|
|
359
|
+
</li>
|
|
360
|
+
)}
|
|
361
|
+
|
|
362
|
+
{/* ── Math block ─────────────────────────────────────────── */}
|
|
363
|
+
{node.type === "math-block" && (
|
|
364
|
+
<MathKatex latex={(node.props?.latex as string) || ""} display />
|
|
365
|
+
)}
|
|
366
|
+
|
|
367
|
+
{/* ── YouTube embed ──────────────────────────────────────── */}
|
|
368
|
+
{node.type === "youtube" && (
|
|
369
|
+
<YouTube
|
|
370
|
+
id={(node.props?.id as string) || ""}
|
|
371
|
+
title={(node.props?.title as string) || "YouTube video"}
|
|
372
|
+
class="my-4"
|
|
373
|
+
/>
|
|
374
|
+
)}
|
|
375
|
+
|
|
376
|
+
{/* ── Annotation list ────────────────────────────────────── */}
|
|
377
|
+
{node.type === "annotation-list" && (
|
|
378
|
+
<div class="my-2 rounded-md border-l-4 border-info/50 bg-info/5 p-4">
|
|
379
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
380
|
+
</div>
|
|
381
|
+
)}
|
|
382
|
+
|
|
383
|
+
{/* ── HTML containers: columns, grid cards, generic ──────── */}
|
|
384
|
+
{node.type === "html-container" && isColumns && (
|
|
385
|
+
<div class="columns-1 sm:columns-2 gap-4 [&_ul]:m-0">
|
|
386
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
387
|
+
</div>
|
|
388
|
+
)}
|
|
389
|
+
{node.type === "html-container" && isGridCards && (
|
|
390
|
+
<Grid cols={[1, 2]} gap={4}>
|
|
391
|
+
{children
|
|
392
|
+
.filter(c => c.type === "unordered-list")
|
|
393
|
+
.flatMap(ul => ul.children || [])
|
|
394
|
+
.map(item => (
|
|
395
|
+
<div class="rounded-lg border bg-card p-4 text-card-foreground shadow-sm [&_hr]:my-3 [&_hr]:border-border">
|
|
396
|
+
{(item.children || []).map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
397
|
+
</div>
|
|
398
|
+
))
|
|
399
|
+
}
|
|
400
|
+
</Grid>
|
|
401
|
+
)}
|
|
402
|
+
{node.type === "html-container" && !isColumns && !isGridCards && (
|
|
403
|
+
<Fragment>
|
|
404
|
+
{children.map(child => <Astro.self node={child} images={images} icons={icons} />)}
|
|
405
|
+
</Fragment>
|
|
406
|
+
)}
|
|
407
|
+
|
|
408
|
+
<script>
|
|
409
|
+
import "@dogsbay/elements/db-tabs";
|
|
410
|
+
</script>
|