svelte-docsmith 0.1.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/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/clipboard.svelte.d.ts +6 -0
- package/dist/clipboard.svelte.js +27 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +55 -0
- package/dist/content.d.ts +10 -0
- package/dist/content.js +4 -0
- package/dist/highlight.d.ts +17 -0
- package/dist/highlight.js +34 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +26 -0
- package/dist/markdown-layout.svelte +21 -0
- package/dist/markdown-layout.svelte.d.ts +18 -0
- package/dist/preprocess.d.ts +33 -0
- package/dist/preprocess.js +65 -0
- package/dist/shadcn.d.ts +12 -0
- package/dist/shadcn.js +5 -0
- package/dist/theme.css +201 -0
- package/dist/themes/amethyst.css +76 -0
- package/dist/themes/bubblegum.css +79 -0
- package/dist/themes/claude.css +79 -0
- package/dist/themes/evergreen.css +76 -0
- package/dist/themes/graphite.css +79 -0
- package/dist/themes/mono.css +79 -0
- package/dist/themes/nord.css +79 -0
- package/dist/themes/ocean.css +76 -0
- package/dist/themes/rose.css +78 -0
- package/dist/themes/tangerine.css +81 -0
- package/dist/toc/from-content.d.ts +11 -0
- package/dist/toc/from-content.js +18 -0
- package/dist/toc/index.d.ts +3 -0
- package/dist/toc/index.js +3 -0
- package/dist/toc/toc.svelte.d.ts +26 -0
- package/dist/toc/toc.svelte.js +74 -0
- package/dist/toc/types.d.ts +11 -0
- package/dist/toc/types.js +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.js +1 -0
- package/dist/ui/accordion-item.svelte +24 -0
- package/dist/ui/accordion-item.svelte.d.ts +9 -0
- package/dist/ui/accordion.svelte +45 -0
- package/dist/ui/accordion.svelte.d.ts +15 -0
- package/dist/ui/background-pattern.svelte +17 -0
- package/dist/ui/background-pattern.svelte.d.ts +26 -0
- package/dist/ui/badge.svelte +54 -0
- package/dist/ui/badge.svelte.d.ts +12 -0
- package/dist/ui/callout.svelte +125 -0
- package/dist/ui/callout.svelte.d.ts +13 -0
- package/dist/ui/card-grid.svelte +10 -0
- package/dist/ui/card-grid.svelte.d.ts +7 -0
- package/dist/ui/card.svelte +52 -0
- package/dist/ui/card.svelte.d.ts +14 -0
- package/dist/ui/copy-button.svelte +30 -0
- package/dist/ui/copy-button.svelte.d.ts +9 -0
- package/dist/ui/file-tree-item.svelte +70 -0
- package/dist/ui/file-tree-item.svelte.d.ts +14 -0
- package/dist/ui/file-tree.svelte +34 -0
- package/dist/ui/file-tree.svelte.d.ts +7 -0
- package/dist/ui/icons/github.svelte +14 -0
- package/dist/ui/icons/github.svelte.d.ts +6 -0
- package/dist/ui/kbd.svelte +11 -0
- package/dist/ui/kbd.svelte.d.ts +7 -0
- package/dist/ui/layouts/breadcrumbs.svelte +37 -0
- package/dist/ui/layouts/breadcrumbs.svelte.d.ts +10 -0
- package/dist/ui/layouts/docs-footer.svelte +40 -0
- package/dist/ui/layouts/docs-footer.svelte.d.ts +7 -0
- package/dist/ui/layouts/docs-header.svelte +109 -0
- package/dist/ui/layouts/docs-header.svelte.d.ts +18 -0
- package/dist/ui/layouts/docs-mobile-header.svelte +106 -0
- package/dist/ui/layouts/docs-mobile-header.svelte.d.ts +18 -0
- package/dist/ui/layouts/docs-shell.svelte +133 -0
- package/dist/ui/layouts/docs-shell.svelte.d.ts +25 -0
- package/dist/ui/layouts/docs-sidebar.svelte +36 -0
- package/dist/ui/layouts/docs-sidebar.svelte.d.ts +8 -0
- package/dist/ui/layouts/prev-next-nav.svelte +32 -0
- package/dist/ui/layouts/prev-next-nav.svelte.d.ts +8 -0
- package/dist/ui/live-example.svelte +67 -0
- package/dist/ui/live-example.svelte.d.ts +10 -0
- package/dist/ui/markdown/code.svelte +11 -0
- package/dist/ui/markdown/code.svelte.d.ts +7 -0
- package/dist/ui/markdown/h2.svelte +13 -0
- package/dist/ui/markdown/h2.svelte.d.ts +4 -0
- package/dist/ui/markdown/h3.svelte +13 -0
- package/dist/ui/markdown/h3.svelte.d.ts +4 -0
- package/dist/ui/markdown/index.d.ts +5 -0
- package/dist/ui/markdown/index.js +5 -0
- package/dist/ui/markdown/pre.svelte +88 -0
- package/dist/ui/markdown/pre.svelte.d.ts +7 -0
- package/dist/ui/markdown/table.svelte +80 -0
- package/dist/ui/markdown/table.svelte.d.ts +7 -0
- package/dist/ui/markdown/types.d.ts +3 -0
- package/dist/ui/markdown/types.js +1 -0
- package/dist/ui/prop.svelte +130 -0
- package/dist/ui/prop.svelte.d.ts +16 -0
- package/dist/ui/props-table.svelte +127 -0
- package/dist/ui/props-table.svelte.d.ts +9 -0
- package/dist/ui/shadcn/accordion/accordion-content.svelte +27 -0
- package/dist/ui/shadcn/accordion/accordion-content.svelte.d.ts +4 -0
- package/dist/ui/shadcn/accordion/accordion-item.svelte +17 -0
- package/dist/ui/shadcn/accordion/accordion-item.svelte.d.ts +4 -0
- package/dist/ui/shadcn/accordion/accordion-trigger.svelte +38 -0
- package/dist/ui/shadcn/accordion/accordion-trigger.svelte.d.ts +8 -0
- package/dist/ui/shadcn/accordion/accordion.svelte +19 -0
- package/dist/ui/shadcn/accordion/accordion.svelte.d.ts +4 -0
- package/dist/ui/shadcn/accordion/index.d.ts +5 -0
- package/dist/ui/shadcn/accordion/index.js +7 -0
- package/dist/ui/shadcn/badge/badge.svelte +50 -0
- package/dist/ui/shadcn/badge/badge.svelte.d.ts +38 -0
- package/dist/ui/shadcn/badge/index.d.ts +2 -0
- package/dist/ui/shadcn/badge/index.js +2 -0
- package/dist/ui/shadcn/button/button.svelte +89 -0
- package/dist/ui/shadcn/button/button.svelte.d.ts +70 -0
- package/dist/ui/shadcn/button/index.d.ts +2 -0
- package/dist/ui/shadcn/button/index.js +4 -0
- package/dist/ui/shadcn/popover/index.d.ts +9 -0
- package/dist/ui/shadcn/popover/index.js +11 -0
- package/dist/ui/shadcn/popover/popover-close.svelte +7 -0
- package/dist/ui/shadcn/popover/popover-close.svelte.d.ts +4 -0
- package/dist/ui/shadcn/popover/popover-content.svelte +31 -0
- package/dist/ui/shadcn/popover/popover-content.svelte.d.ts +10 -0
- package/dist/ui/shadcn/popover/popover-description.svelte +20 -0
- package/dist/ui/shadcn/popover/popover-description.svelte.d.ts +5 -0
- package/dist/ui/shadcn/popover/popover-header.svelte +20 -0
- package/dist/ui/shadcn/popover/popover-header.svelte.d.ts +5 -0
- package/dist/ui/shadcn/popover/popover-portal.svelte +7 -0
- package/dist/ui/shadcn/popover/popover-portal.svelte.d.ts +3 -0
- package/dist/ui/shadcn/popover/popover-title.svelte +15 -0
- package/dist/ui/shadcn/popover/popover-title.svelte.d.ts +5 -0
- package/dist/ui/shadcn/popover/popover-trigger.svelte +17 -0
- package/dist/ui/shadcn/popover/popover-trigger.svelte.d.ts +4 -0
- package/dist/ui/shadcn/popover/popover.svelte +7 -0
- package/dist/ui/shadcn/popover/popover.svelte.d.ts +3 -0
- package/dist/ui/shadcn/scroll-area/index.d.ts +3 -0
- package/dist/ui/shadcn/scroll-area/index.js +5 -0
- package/dist/ui/shadcn/scroll-area/scroll-area-scrollbar.svelte +30 -0
- package/dist/ui/shadcn/scroll-area/scroll-area-scrollbar.svelte.d.ts +4 -0
- package/dist/ui/shadcn/scroll-area/scroll-area.svelte +43 -0
- package/dist/ui/shadcn/scroll-area/scroll-area.svelte.d.ts +11 -0
- package/dist/ui/shadcn/separator/index.d.ts +2 -0
- package/dist/ui/shadcn/separator/index.js +4 -0
- package/dist/ui/shadcn/separator/separator.svelte +23 -0
- package/dist/ui/shadcn/separator/separator.svelte.d.ts +4 -0
- package/dist/ui/shadcn/sheet/index.d.ts +11 -0
- package/dist/ui/shadcn/sheet/index.js +13 -0
- package/dist/ui/shadcn/sheet/sheet-close.svelte +7 -0
- package/dist/ui/shadcn/sheet/sheet-close.svelte.d.ts +4 -0
- package/dist/ui/shadcn/sheet/sheet-content.svelte +55 -0
- package/dist/ui/shadcn/sheet/sheet-content.svelte.d.ts +15 -0
- package/dist/ui/shadcn/sheet/sheet-description.svelte +17 -0
- package/dist/ui/shadcn/sheet/sheet-description.svelte.d.ts +4 -0
- package/dist/ui/shadcn/sheet/sheet-footer.svelte +20 -0
- package/dist/ui/shadcn/sheet/sheet-footer.svelte.d.ts +5 -0
- package/dist/ui/shadcn/sheet/sheet-header.svelte +20 -0
- package/dist/ui/shadcn/sheet/sheet-header.svelte.d.ts +5 -0
- package/dist/ui/shadcn/sheet/sheet-overlay.svelte +17 -0
- package/dist/ui/shadcn/sheet/sheet-overlay.svelte.d.ts +4 -0
- package/dist/ui/shadcn/sheet/sheet-portal.svelte +7 -0
- package/dist/ui/shadcn/sheet/sheet-portal.svelte.d.ts +3 -0
- package/dist/ui/shadcn/sheet/sheet-title.svelte +17 -0
- package/dist/ui/shadcn/sheet/sheet-title.svelte.d.ts +4 -0
- package/dist/ui/shadcn/sheet/sheet-trigger.svelte +7 -0
- package/dist/ui/shadcn/sheet/sheet-trigger.svelte.d.ts +4 -0
- package/dist/ui/shadcn/sheet/sheet.svelte +7 -0
- package/dist/ui/shadcn/sheet/sheet.svelte.d.ts +3 -0
- package/dist/ui/shadcn/tabs/index.d.ts +5 -0
- package/dist/ui/shadcn/tabs/index.js +7 -0
- package/dist/ui/shadcn/tabs/tabs-content.svelte +17 -0
- package/dist/ui/shadcn/tabs/tabs-content.svelte.d.ts +4 -0
- package/dist/ui/shadcn/tabs/tabs-list.svelte +40 -0
- package/dist/ui/shadcn/tabs/tabs-list.svelte.d.ts +25 -0
- package/dist/ui/shadcn/tabs/tabs-trigger.svelte +23 -0
- package/dist/ui/shadcn/tabs/tabs-trigger.svelte.d.ts +4 -0
- package/dist/ui/shadcn/tabs/tabs.svelte +19 -0
- package/dist/ui/shadcn/tabs/tabs.svelte.d.ts +4 -0
- package/dist/ui/step.svelte +82 -0
- package/dist/ui/step.svelte.d.ts +9 -0
- package/dist/ui/steps.svelte +71 -0
- package/dist/ui/steps.svelte.d.ts +7 -0
- package/dist/ui/tab-item.svelte +14 -0
- package/dist/ui/tab-item.svelte.d.ts +6 -0
- package/dist/ui/table-of-contents.svelte +114 -0
- package/dist/ui/table-of-contents.svelte.d.ts +9 -0
- package/dist/ui/tabs.svelte +29 -0
- package/dist/ui/tabs.svelte.d.ts +8 -0
- package/dist/ui/theme-provider.svelte +23 -0
- package/dist/ui/theme-provider.svelte.d.ts +10 -0
- package/dist/ui/theme-toggle.svelte +22 -0
- package/dist/ui/theme-toggle.svelte.d.ts +6 -0
- package/dist/vite.d.ts +32 -0
- package/dist/vite.js +216 -0
- package/package.json +115 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Badge } from '../shadcn/badge/index.js';
|
|
3
|
+
import { Button } from '../shadcn/button/index.js';
|
|
4
|
+
import { Separator } from '../shadcn/separator/index.js';
|
|
5
|
+
import GithubIcon from '../icons/github.svelte';
|
|
6
|
+
import ThemeToggle from '../theme-toggle.svelte';
|
|
7
|
+
import type { DocsmithConfig } from '../../config.js';
|
|
8
|
+
import BookOpenText from '@lucide/svelte/icons/book-open-text';
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
config,
|
|
13
|
+
logo,
|
|
14
|
+
actions,
|
|
15
|
+
standalone = false
|
|
16
|
+
}: {
|
|
17
|
+
config: DocsmithConfig;
|
|
18
|
+
/** Custom logo mark; defaults to a book icon in a primary-tinted chip. */
|
|
19
|
+
logo?: Snippet;
|
|
20
|
+
/** Extra header controls, rendered before the theme toggle. */
|
|
21
|
+
actions?: Snippet;
|
|
22
|
+
/**
|
|
23
|
+
* Show at every breakpoint (for pages without the docs mobile header, e.g.
|
|
24
|
+
* a landing page). Default: desktop-only, since the docs shell pairs this
|
|
25
|
+
* with a separate mobile header.
|
|
26
|
+
*/
|
|
27
|
+
standalone?: boolean;
|
|
28
|
+
} = $props();
|
|
29
|
+
|
|
30
|
+
let isScrolled = $state(false);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<svelte:window onscroll={() => (isScrolled = window.scrollY > 50)} />
|
|
34
|
+
|
|
35
|
+
<header
|
|
36
|
+
class="sticky top-0 z-40 w-full transition-all duration-200 {standalone
|
|
37
|
+
? 'block'
|
|
38
|
+
: 'hidden lg:block'} {isScrolled
|
|
39
|
+
? 'bg-background/60 supports-backdrop-filter:bg-background/60 border-border/40 border-b backdrop-blur-xl'
|
|
40
|
+
: 'border-transparent bg-transparent'}"
|
|
41
|
+
>
|
|
42
|
+
<div class="mx-auto flex h-14 max-w-7xl items-center justify-between gap-2 px-4 md:px-6 lg:px-8">
|
|
43
|
+
<a href="/" class="group flex items-center gap-2.5">
|
|
44
|
+
<div
|
|
45
|
+
class="bg-primary/10 text-primary group-hover:bg-primary/20 flex size-8 items-center justify-center rounded-lg transition-all duration-200"
|
|
46
|
+
>
|
|
47
|
+
{#if logo}
|
|
48
|
+
{@render logo()}
|
|
49
|
+
{:else if config.logo}
|
|
50
|
+
<img src={config.logo} alt="" class="size-5 object-contain" />
|
|
51
|
+
{:else}
|
|
52
|
+
<BookOpenText class="size-5" />
|
|
53
|
+
{/if}
|
|
54
|
+
</div>
|
|
55
|
+
<span class="text-base font-semibold tracking-tight md:text-lg">{config.title}</span>
|
|
56
|
+
</a>
|
|
57
|
+
|
|
58
|
+
<div class="ml-auto flex items-center gap-2">
|
|
59
|
+
{#if config.nav?.length}
|
|
60
|
+
<nav class="mr-1 flex items-center gap-1">
|
|
61
|
+
{#each config.nav as link (link.href)}
|
|
62
|
+
<a
|
|
63
|
+
href={link.href}
|
|
64
|
+
target={link.external ? '_blank' : undefined}
|
|
65
|
+
rel={link.external ? 'noopener noreferrer' : undefined}
|
|
66
|
+
class="text-muted-foreground hover:text-foreground rounded-md px-3 py-1.5 text-sm font-medium transition-colors"
|
|
67
|
+
>
|
|
68
|
+
{link.label}
|
|
69
|
+
</a>
|
|
70
|
+
{/each}
|
|
71
|
+
</nav>
|
|
72
|
+
{/if}
|
|
73
|
+
|
|
74
|
+
{#if config.version}
|
|
75
|
+
<div class="px-2">
|
|
76
|
+
<Badge
|
|
77
|
+
variant="outline"
|
|
78
|
+
class="bg-muted/50 border-border/50 font-mono text-xs font-normal"
|
|
79
|
+
>
|
|
80
|
+
v{config.version}
|
|
81
|
+
</Badge>
|
|
82
|
+
</div>
|
|
83
|
+
{/if}
|
|
84
|
+
|
|
85
|
+
<Separator orientation="vertical" class="bg-border/40 mx-1 min-h-0 h-6" />
|
|
86
|
+
|
|
87
|
+
<div class="flex items-center gap-0.5">
|
|
88
|
+
{#if actions}
|
|
89
|
+
{@render actions()}
|
|
90
|
+
{/if}
|
|
91
|
+
|
|
92
|
+
{#if config.github}
|
|
93
|
+
<Button
|
|
94
|
+
size="icon"
|
|
95
|
+
variant="ghost"
|
|
96
|
+
target="_blank"
|
|
97
|
+
href={config.github}
|
|
98
|
+
class="text-muted-foreground hover:text-foreground size-8"
|
|
99
|
+
>
|
|
100
|
+
<GithubIcon class="size-4" />
|
|
101
|
+
<span class="sr-only">GitHub</span>
|
|
102
|
+
</Button>
|
|
103
|
+
{/if}
|
|
104
|
+
|
|
105
|
+
<ThemeToggle />
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</header>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DocsmithConfig } from '../../config.js';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
config: DocsmithConfig;
|
|
5
|
+
/** Custom logo mark; defaults to a book icon in a primary-tinted chip. */
|
|
6
|
+
logo?: Snippet;
|
|
7
|
+
/** Extra header controls, rendered before the theme toggle. */
|
|
8
|
+
actions?: Snippet;
|
|
9
|
+
/**
|
|
10
|
+
* Show at every breakpoint (for pages without the docs mobile header, e.g.
|
|
11
|
+
* a landing page). Default: desktop-only, since the docs shell pairs this
|
|
12
|
+
* with a separate mobile header.
|
|
13
|
+
*/
|
|
14
|
+
standalone?: boolean;
|
|
15
|
+
};
|
|
16
|
+
declare const DocsHeader: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
17
|
+
type DocsHeader = ReturnType<typeof DocsHeader>;
|
|
18
|
+
export default DocsHeader;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { page } from '$app/state';
|
|
3
|
+
import type { DocsmithConfig, NavGroup } from '../../config.js';
|
|
4
|
+
import type { TocItem } from '../../toc/index.js';
|
|
5
|
+
import DocsSidebar from './docs-sidebar.svelte';
|
|
6
|
+
import TableOfContents from '../table-of-contents.svelte';
|
|
7
|
+
import ThemeToggle from '../theme-toggle.svelte';
|
|
8
|
+
import { Button } from '../shadcn/button/index.js';
|
|
9
|
+
import * as Popover from '../shadcn/popover/index.js';
|
|
10
|
+
import { ScrollArea } from '../shadcn/scroll-area/index.js';
|
|
11
|
+
import * as Sheet from '../shadcn/sheet/index.js';
|
|
12
|
+
import BookOpenText from '@lucide/svelte/icons/book-open-text';
|
|
13
|
+
import Menu from '@lucide/svelte/icons/menu';
|
|
14
|
+
import PanelRight from '@lucide/svelte/icons/panel-right';
|
|
15
|
+
import type { Snippet } from 'svelte';
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
config,
|
|
19
|
+
nav,
|
|
20
|
+
title,
|
|
21
|
+
tocItems,
|
|
22
|
+
tocActiveId = null,
|
|
23
|
+
logo,
|
|
24
|
+
actions
|
|
25
|
+
}: {
|
|
26
|
+
config: DocsmithConfig;
|
|
27
|
+
nav: NavGroup[];
|
|
28
|
+
/** Title of the current page, shown between the menu and controls. */
|
|
29
|
+
title: string;
|
|
30
|
+
/** In-page TOC entries; the TOC popover is hidden when empty. */
|
|
31
|
+
tocItems: TocItem[];
|
|
32
|
+
/** Id of the heading currently in view. */
|
|
33
|
+
tocActiveId?: string | null;
|
|
34
|
+
logo?: Snippet;
|
|
35
|
+
actions?: Snippet;
|
|
36
|
+
} = $props();
|
|
37
|
+
|
|
38
|
+
let isMenuOpen = $state(false);
|
|
39
|
+
let isTocOpen = $state(false);
|
|
40
|
+
|
|
41
|
+
$effect(() => {
|
|
42
|
+
// Close the overlays on navigation.
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- read to make the route a reactive dependency
|
|
44
|
+
page.url.pathname;
|
|
45
|
+
isMenuOpen = false;
|
|
46
|
+
isTocOpen = false;
|
|
47
|
+
});
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<header
|
|
51
|
+
class="bg-background/95 supports-backdrop-filter:bg-background/60 sticky top-0 z-40 w-full border-b backdrop-blur lg:hidden"
|
|
52
|
+
>
|
|
53
|
+
<div class="flex h-14 items-center gap-2 px-4">
|
|
54
|
+
<Sheet.Root bind:open={isMenuOpen}>
|
|
55
|
+
<Sheet.Trigger>
|
|
56
|
+
{#snippet child({ props })}
|
|
57
|
+
<Button variant="ghost" size="icon" class="-ml-2" {...props}>
|
|
58
|
+
<Menu class="size-5" />
|
|
59
|
+
<span class="sr-only">Toggle menu</span>
|
|
60
|
+
</Button>
|
|
61
|
+
{/snippet}
|
|
62
|
+
</Sheet.Trigger>
|
|
63
|
+
<Sheet.Content side="left" class="pr-0">
|
|
64
|
+
<div class="px-7 pt-4 pb-4">
|
|
65
|
+
<a href="/" class="flex items-center gap-2 font-bold">
|
|
66
|
+
{#if logo}
|
|
67
|
+
{@render logo()}
|
|
68
|
+
{:else}
|
|
69
|
+
<BookOpenText class="text-primary size-5" />
|
|
70
|
+
{/if}
|
|
71
|
+
<span class="inline-block">{config.title}</span>
|
|
72
|
+
</a>
|
|
73
|
+
</div>
|
|
74
|
+
<ScrollArea class="my-4 h-[calc(100vh-8rem)] pb-10 pl-2">
|
|
75
|
+
<DocsSidebar {nav} class="static block h-auto w-full" />
|
|
76
|
+
</ScrollArea>
|
|
77
|
+
</Sheet.Content>
|
|
78
|
+
</Sheet.Root>
|
|
79
|
+
|
|
80
|
+
<div class="flex-1 truncate font-bold">{title}</div>
|
|
81
|
+
|
|
82
|
+
<div class="flex items-center gap-1">
|
|
83
|
+
{#if actions}
|
|
84
|
+
{@render actions()}
|
|
85
|
+
{/if}
|
|
86
|
+
|
|
87
|
+
<ThemeToggle />
|
|
88
|
+
|
|
89
|
+
{#if tocItems.length > 0}
|
|
90
|
+
<Popover.Root bind:open={isTocOpen}>
|
|
91
|
+
<Popover.Trigger>
|
|
92
|
+
{#snippet child({ props })}
|
|
93
|
+
<Button variant="ghost" size="icon" class="size-8" {...props}>
|
|
94
|
+
<PanelRight class="size-4" />
|
|
95
|
+
<span class="sr-only">Table of contents</span>
|
|
96
|
+
</Button>
|
|
97
|
+
{/snippet}
|
|
98
|
+
</Popover.Trigger>
|
|
99
|
+
<Popover.Content class="max-h-[60vh] w-64 overflow-y-auto p-4" align="end">
|
|
100
|
+
<TableOfContents items={tocItems} activeId={tocActiveId} class="static block w-full" />
|
|
101
|
+
</Popover.Content>
|
|
102
|
+
</Popover.Root>
|
|
103
|
+
{/if}
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</header>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DocsmithConfig, NavGroup } from '../../config.js';
|
|
2
|
+
import type { TocItem } from '../../toc/index.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
type $$ComponentProps = {
|
|
5
|
+
config: DocsmithConfig;
|
|
6
|
+
nav: NavGroup[];
|
|
7
|
+
/** Title of the current page, shown between the menu and controls. */
|
|
8
|
+
title: string;
|
|
9
|
+
/** In-page TOC entries; the TOC popover is hidden when empty. */
|
|
10
|
+
tocItems: TocItem[];
|
|
11
|
+
/** Id of the heading currently in view. */
|
|
12
|
+
tocActiveId?: string | null;
|
|
13
|
+
logo?: Snippet;
|
|
14
|
+
actions?: Snippet;
|
|
15
|
+
};
|
|
16
|
+
declare const DocsMobileHeader: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
17
|
+
type DocsMobileHeader = ReturnType<typeof DocsMobileHeader>;
|
|
18
|
+
export default DocsMobileHeader;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { page } from '$app/state';
|
|
3
|
+
import { afterNavigate } from '$app/navigation';
|
|
4
|
+
import { navFromContent, type DocsContentItem, type DocsmithConfig } from '../../config.js';
|
|
5
|
+
import { createToc } from '../../toc/index.js';
|
|
6
|
+
import BackgroundPattern from '../background-pattern.svelte';
|
|
7
|
+
import ThemeProvider from '../theme-provider.svelte';
|
|
8
|
+
import DocsHeader from './docs-header.svelte';
|
|
9
|
+
import DocsFooter from './docs-footer.svelte';
|
|
10
|
+
import DocsMobileHeader from './docs-mobile-header.svelte';
|
|
11
|
+
import DocsSidebar from './docs-sidebar.svelte';
|
|
12
|
+
import PrevNextNav from './prev-next-nav.svelte';
|
|
13
|
+
import Breadcrumbs, { type Crumb } from './breadcrumbs.svelte';
|
|
14
|
+
import TableOfContents from '../table-of-contents.svelte';
|
|
15
|
+
import type { Snippet } from 'svelte';
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
config,
|
|
19
|
+
content = [],
|
|
20
|
+
children,
|
|
21
|
+
logo,
|
|
22
|
+
actions,
|
|
23
|
+
footer,
|
|
24
|
+
pattern = false,
|
|
25
|
+
layout = 'docs'
|
|
26
|
+
}: {
|
|
27
|
+
config: DocsmithConfig;
|
|
28
|
+
content?: DocsContentItem[];
|
|
29
|
+
children: Snippet;
|
|
30
|
+
/** Custom logo mark for the header and mobile menu. */
|
|
31
|
+
logo?: Snippet;
|
|
32
|
+
/** Extra header controls (desktop and mobile), before the theme toggle. */
|
|
33
|
+
actions?: Snippet;
|
|
34
|
+
/** Rendered below the content column (copyright, credits, …). */
|
|
35
|
+
footer?: Snippet;
|
|
36
|
+
/** Render the decorative grid-and-glow page background. */
|
|
37
|
+
pattern?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* `docs` (default): the three-column shell — sidebar, content, in-page TOC.
|
|
40
|
+
* `page`: full-bleed content with the same header/footer/background but no
|
|
41
|
+
* sidebar or TOC — for a landing or any non-doc page, so the whole site
|
|
42
|
+
* shares one chrome.
|
|
43
|
+
*/
|
|
44
|
+
layout?: 'docs' | 'page';
|
|
45
|
+
} = $props();
|
|
46
|
+
|
|
47
|
+
const nav = $derived(navFromContent(content));
|
|
48
|
+
|
|
49
|
+
// Ordered flat page list drives the prev/next links.
|
|
50
|
+
const flatNav = $derived(nav.flatMap((group) => group.items));
|
|
51
|
+
const pageIndex = $derived(flatNav.findIndex((item) => item.url === page.url.pathname));
|
|
52
|
+
const prev = $derived(pageIndex > 0 ? flatNav[pageIndex - 1] : undefined);
|
|
53
|
+
const next = $derived(
|
|
54
|
+
pageIndex >= 0 && pageIndex < flatNav.length - 1 ? flatNav[pageIndex + 1] : undefined
|
|
55
|
+
);
|
|
56
|
+
const currentTitle = $derived(pageIndex >= 0 ? flatNav[pageIndex].title : config.title);
|
|
57
|
+
|
|
58
|
+
// Breadcrumb trail: the current page's sidebar group, then the page itself.
|
|
59
|
+
const currentGroup = $derived(
|
|
60
|
+
nav.find((group) => group.items.some((item) => item.url === page.url.pathname))
|
|
61
|
+
);
|
|
62
|
+
const breadcrumbs = $derived.by(() => {
|
|
63
|
+
const crumbs: Crumb[] = [];
|
|
64
|
+
if (currentGroup) crumbs.push({ title: currentGroup.title });
|
|
65
|
+
if (pageIndex >= 0) crumbs.push({ title: currentTitle });
|
|
66
|
+
return crumbs;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// In-page TOC, scanned from the rendered content and re-scanned after every
|
|
70
|
+
// navigation (client-side included) so it never goes stale.
|
|
71
|
+
let contentEl = $state<HTMLElement | null>(null);
|
|
72
|
+
const toc = createToc(() => contentEl);
|
|
73
|
+
afterNavigate(() => {
|
|
74
|
+
toc.refresh();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Server-rendered TOC (headings extracted at build time into the content
|
|
78
|
+
// index) so the list is present on first paint. Once the client engine has
|
|
79
|
+
// scanned the DOM, its items take over (scroll-spy + edge-case accuracy).
|
|
80
|
+
const pageToc = $derived(content.find((item) => item.path === page.url.pathname)?.toc ?? []);
|
|
81
|
+
const tocItems = $derived(toc.items.length ? toc.items : pageToc);
|
|
82
|
+
</script>
|
|
83
|
+
|
|
84
|
+
<div class="relative isolate flex min-h-screen flex-col">
|
|
85
|
+
<!-- Owns light/dark for the whole app — consumers never wire mode-watcher. -->
|
|
86
|
+
<ThemeProvider />
|
|
87
|
+
|
|
88
|
+
{#if pattern}
|
|
89
|
+
<BackgroundPattern />
|
|
90
|
+
{/if}
|
|
91
|
+
|
|
92
|
+
{#if layout === 'page'}
|
|
93
|
+
<DocsHeader {config} {logo} {actions} standalone />
|
|
94
|
+
|
|
95
|
+
<main class="flex-1">
|
|
96
|
+
{@render children()}
|
|
97
|
+
</main>
|
|
98
|
+
{:else}
|
|
99
|
+
<DocsHeader {config} {logo} {actions} />
|
|
100
|
+
|
|
101
|
+
<DocsMobileHeader
|
|
102
|
+
{config}
|
|
103
|
+
{nav}
|
|
104
|
+
title={currentTitle}
|
|
105
|
+
tocItems={toc.items}
|
|
106
|
+
tocActiveId={toc.activeId}
|
|
107
|
+
{logo}
|
|
108
|
+
{actions}
|
|
109
|
+
/>
|
|
110
|
+
|
|
111
|
+
<div class="mx-auto flex w-full max-w-7xl flex-1 gap-12 px-4 md:px-6 lg:px-8 lg:pt-10">
|
|
112
|
+
<DocsSidebar {nav} />
|
|
113
|
+
|
|
114
|
+
<main bind:this={contentEl} class="min-w-0 flex-1 py-6 lg:py-0">
|
|
115
|
+
<Breadcrumbs items={breadcrumbs} />
|
|
116
|
+
{@render children()}
|
|
117
|
+
<PrevNextNav {prev} {next} />
|
|
118
|
+
</main>
|
|
119
|
+
|
|
120
|
+
<!-- Reserve the TOC column so its content filling in after hydration
|
|
121
|
+
never shifts the page. -->
|
|
122
|
+
<div class="hidden w-56 shrink-0 lg:block">
|
|
123
|
+
<TableOfContents items={tocItems} activeId={toc.activeId} />
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
{/if}
|
|
127
|
+
|
|
128
|
+
{#if footer}
|
|
129
|
+
{@render footer()}
|
|
130
|
+
{:else if config.footer}
|
|
131
|
+
<DocsFooter {config} />
|
|
132
|
+
{/if}
|
|
133
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type DocsContentItem, type DocsmithConfig } from '../../config.js';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
config: DocsmithConfig;
|
|
5
|
+
content?: DocsContentItem[];
|
|
6
|
+
children: Snippet;
|
|
7
|
+
/** Custom logo mark for the header and mobile menu. */
|
|
8
|
+
logo?: Snippet;
|
|
9
|
+
/** Extra header controls (desktop and mobile), before the theme toggle. */
|
|
10
|
+
actions?: Snippet;
|
|
11
|
+
/** Rendered below the content column (copyright, credits, …). */
|
|
12
|
+
footer?: Snippet;
|
|
13
|
+
/** Render the decorative grid-and-glow page background. */
|
|
14
|
+
pattern?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* `docs` (default): the three-column shell — sidebar, content, in-page TOC.
|
|
17
|
+
* `page`: full-bleed content with the same header/footer/background but no
|
|
18
|
+
* sidebar or TOC — for a landing or any non-doc page, so the whole site
|
|
19
|
+
* shares one chrome.
|
|
20
|
+
*/
|
|
21
|
+
layout?: 'docs' | 'page';
|
|
22
|
+
};
|
|
23
|
+
declare const DocsShell: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
24
|
+
type DocsShell = ReturnType<typeof DocsShell>;
|
|
25
|
+
export default DocsShell;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { page } from '$app/state';
|
|
3
|
+
import { cn } from '../../shadcn.js';
|
|
4
|
+
import type { NavGroup } from '../../config.js';
|
|
5
|
+
|
|
6
|
+
const { nav, class: className = '' }: { nav: NavGroup[]; class?: string } = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<aside class={cn('sticky top-24 hidden h-screen w-56 shrink-0 bg-transparent lg:block', className)}>
|
|
10
|
+
<div class="max-h-[calc(100vh-10rem)] overflow-y-auto px-4">
|
|
11
|
+
<nav class="space-y-6">
|
|
12
|
+
{#each nav as group (group.title)}
|
|
13
|
+
<div class="space-y-3">
|
|
14
|
+
<h4 class="text-foreground px-2 text-sm font-semibold">{group.title}</h4>
|
|
15
|
+
<ul class="space-y-1">
|
|
16
|
+
{#each group.items as item (item.url)}
|
|
17
|
+
<li>
|
|
18
|
+
<a
|
|
19
|
+
href={item.url}
|
|
20
|
+
class={cn(
|
|
21
|
+
'hover:text-primary hover:bg-primary/20 block rounded-md px-2 py-1.5 text-sm transition-colors',
|
|
22
|
+
page.url.pathname === item.url
|
|
23
|
+
? 'text-primary bg-primary/20 font-medium'
|
|
24
|
+
: 'text-muted-foreground'
|
|
25
|
+
)}
|
|
26
|
+
>
|
|
27
|
+
{item.title}
|
|
28
|
+
</a>
|
|
29
|
+
</li>
|
|
30
|
+
{/each}
|
|
31
|
+
</ul>
|
|
32
|
+
</div>
|
|
33
|
+
{/each}
|
|
34
|
+
</nav>
|
|
35
|
+
</div>
|
|
36
|
+
</aside>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NavGroup } from '../../config.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
nav: NavGroup[];
|
|
4
|
+
class?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const DocsSidebar: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type DocsSidebar = ReturnType<typeof DocsSidebar>;
|
|
8
|
+
export default DocsSidebar;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { NavItem } from '../../config.js';
|
|
3
|
+
|
|
4
|
+
const { prev, next }: { prev?: NavItem; next?: NavItem } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
{#if prev || next}
|
|
8
|
+
<nav class="border-border mt-8 flex justify-between gap-4 border-t pt-8">
|
|
9
|
+
{#if prev}
|
|
10
|
+
<a
|
|
11
|
+
href={prev.url}
|
|
12
|
+
class="border-border hover:border-primary flex min-w-0 flex-1 flex-col gap-1 rounded-lg border p-4 transition-colors"
|
|
13
|
+
>
|
|
14
|
+
<span class="text-muted-foreground text-xs">Previous</span>
|
|
15
|
+
<span class="text-foreground truncate font-medium">{prev.title}</span>
|
|
16
|
+
</a>
|
|
17
|
+
{:else}
|
|
18
|
+
<div class="flex-1"></div>
|
|
19
|
+
{/if}
|
|
20
|
+
{#if next}
|
|
21
|
+
<a
|
|
22
|
+
href={next.url}
|
|
23
|
+
class="border-border hover:border-primary ml-auto flex min-w-0 flex-1 flex-col gap-1 rounded-lg border p-4 text-right transition-colors"
|
|
24
|
+
>
|
|
25
|
+
<span class="text-muted-foreground text-xs">Next</span>
|
|
26
|
+
<span class="text-foreground truncate font-medium">{next.title}</span>
|
|
27
|
+
</a>
|
|
28
|
+
{:else}
|
|
29
|
+
<div class="flex-1"></div>
|
|
30
|
+
{/if}
|
|
31
|
+
</nav>
|
|
32
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NavItem } from '../../config.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
prev?: NavItem;
|
|
4
|
+
next?: NavItem;
|
|
5
|
+
};
|
|
6
|
+
declare const PrevNextNav: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type PrevNextNav = ReturnType<typeof PrevNextNav>;
|
|
8
|
+
export default PrevNextNav;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useClipboard } from '../clipboard.svelte.js';
|
|
3
|
+
import { Button } from './shadcn/button/index.js';
|
|
4
|
+
import CopyButton from './copy-button.svelte';
|
|
5
|
+
import Code from '@lucide/svelte/icons/code';
|
|
6
|
+
import type { Snippet } from 'svelte';
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
source,
|
|
10
|
+
children
|
|
11
|
+
}: {
|
|
12
|
+
/** Pre-highlighted source HTML (Shiki output), rendered as the source panel. */
|
|
13
|
+
source?: string;
|
|
14
|
+
/** The live, rendered example. */
|
|
15
|
+
children: Snippet;
|
|
16
|
+
} = $props();
|
|
17
|
+
|
|
18
|
+
let showSource = $state(false);
|
|
19
|
+
const clipboard = useClipboard();
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<div class="not-prose my-6 overflow-hidden rounded-lg border border-border">
|
|
23
|
+
<div class="flex justify-center bg-muted/30 p-8">
|
|
24
|
+
{@render children()}
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
{#if source}
|
|
28
|
+
<div class="flex items-center border-t border-border bg-muted/50 px-2 py-1">
|
|
29
|
+
<Button variant="ghost" size="sm" onclick={() => (showSource = !showSource)}>
|
|
30
|
+
<Code class="size-4" />
|
|
31
|
+
{showSource ? 'Hide' : 'Show'} source
|
|
32
|
+
</Button>
|
|
33
|
+
{#if showSource}
|
|
34
|
+
<CopyButton copied={clipboard.copied} onclick={() => clipboard.copy()} class="ml-auto" />
|
|
35
|
+
{/if}
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
{#if showSource}
|
|
39
|
+
<div class="source bg-muted border-t border-border text-sm" use:clipboard.readText>
|
|
40
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -- trusted Shiki-highlighted source generated at build time -->
|
|
41
|
+
{@html source}
|
|
42
|
+
</div>
|
|
43
|
+
{/if}
|
|
44
|
+
{/if}
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<style>
|
|
48
|
+
/* Match the markdown code-block treatment: the source sits on `bg-muted`
|
|
49
|
+
(Shiki's own background is stripped by the `?source` transform) with the
|
|
50
|
+
same per-line padding. */
|
|
51
|
+
.source :global(pre) {
|
|
52
|
+
margin: 0;
|
|
53
|
+
border-radius: 0;
|
|
54
|
+
max-height: 32rem;
|
|
55
|
+
overflow: auto;
|
|
56
|
+
background: transparent;
|
|
57
|
+
}
|
|
58
|
+
.source :global(pre code) {
|
|
59
|
+
display: block;
|
|
60
|
+
padding-block: 1rem;
|
|
61
|
+
}
|
|
62
|
+
.source :global(pre span.line) {
|
|
63
|
+
display: inline-block;
|
|
64
|
+
width: 100%;
|
|
65
|
+
padding-inline: 1rem;
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
/** Pre-highlighted source HTML (Shiki output), rendered as the source panel. */
|
|
4
|
+
source?: string;
|
|
5
|
+
/** The live, rendered example. */
|
|
6
|
+
children: Snippet;
|
|
7
|
+
};
|
|
8
|
+
declare const LiveExample: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type LiveExample = ReturnType<typeof LiveExample>;
|
|
10
|
+
export default LiveExample;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
const { children }: { children: Snippet } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<code
|
|
8
|
+
class="not-prose bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold"
|
|
9
|
+
>
|
|
10
|
+
{@render children()}
|
|
11
|
+
</code>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Link from '@lucide/svelte/icons/link';
|
|
3
|
+
import type { HeadingProps } from './types.js';
|
|
4
|
+
|
|
5
|
+
const { children, ...attrs }: HeadingProps = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<h2 {...attrs} class="flex gap-2 items-center group">
|
|
9
|
+
{@render children()}
|
|
10
|
+
<a href="#{attrs.id}" class="opacity-0 group-hover:opacity-100 transition-opacity">
|
|
11
|
+
<Link class="size-5 text-primary" />
|
|
12
|
+
</a>
|
|
13
|
+
</h2>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Link from '@lucide/svelte/icons/link';
|
|
3
|
+
import type { HeadingProps } from './types.js';
|
|
4
|
+
|
|
5
|
+
const { children, ...attrs }: HeadingProps = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<h3 {...attrs} class="flex gap-2 items-center group">
|
|
9
|
+
{@render children()}
|
|
10
|
+
<a href="#{attrs.id}" class="opacity-0 group-hover:opacity-100 transition-opacity">
|
|
11
|
+
<Link class="size-5 text-primary" />
|
|
12
|
+
</a>
|
|
13
|
+
</h3>
|