@aureuma/svelta 0.1.1 → 0.4.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/README.md +66 -1
- package/package.json +21 -8
- package/packages/core/dist/appearance/AppearanceSwitcher.svelte +58 -0
- package/packages/core/dist/appearance/AppearanceSwitcher.svelte.d.ts +21 -0
- package/packages/core/dist/appearance/index.d.ts +3 -0
- package/packages/core/dist/appearance/index.js +3 -0
- package/packages/core/dist/appearance/palettes.d.ts +10 -0
- package/packages/core/dist/appearance/palettes.js +36 -0
- package/packages/core/dist/appearance/store.d.ts +20 -0
- package/packages/core/dist/appearance/store.js +87 -0
- package/packages/core/dist/components/blog/BackLink.svelte +7 -4
- package/packages/core/dist/components/blog/BlogCard.svelte +23 -10
- package/packages/core/dist/components/blog/BlogHeroCard.svelte +31 -15
- package/packages/core/dist/components/blog/Container.svelte +3 -2
- package/packages/core/dist/components/blog/Container.svelte.d.ts +1 -1
- package/packages/core/dist/components/blog/MorePosts.svelte +1 -1
- package/packages/core/dist/components/blog/ShareButtons.svelte +81 -47
- package/packages/core/dist/components/blog/ShareButtons.svelte.d.ts +2 -0
- package/packages/core/dist/components/blog/TagTabs.svelte +71 -18
- package/packages/core/dist/components/blog/TagTabs.svelte.d.ts +4 -2
- package/packages/core/dist/components/docs/DocsPager.svelte +28 -0
- package/packages/core/dist/{theme/ThemeSwitcher.svelte.d.ts → components/docs/DocsPager.svelte.d.ts} +6 -5
- package/packages/core/dist/components/docs/DocsSectionGrid.svelte +26 -0
- package/packages/core/dist/components/docs/DocsSectionGrid.svelte.d.ts +21 -0
- package/packages/core/dist/components/docs/DocsShell.svelte +19 -0
- package/packages/core/dist/components/docs/DocsShell.svelte.d.ts +31 -0
- package/packages/core/dist/components/docs/DocsSidebar.svelte +31 -0
- package/packages/core/dist/components/docs/DocsSidebar.svelte.d.ts +22 -0
- package/packages/core/dist/experience/index.d.ts +9 -0
- package/packages/core/dist/experience/index.js +45 -0
- package/packages/core/dist/experience/patterns.d.ts +26 -0
- package/packages/core/dist/experience/patterns.js +98 -0
- package/packages/core/dist/index.d.ts +10 -1
- package/packages/core/dist/index.js +6 -0
- package/packages/core/dist/server/blog.d.ts +14 -1
- package/packages/core/dist/server/blog.js +144 -14
- package/packages/core/dist/server/docs.d.ts +64 -0
- package/packages/core/dist/server/docs.js +309 -0
- package/packages/core/dist/server/index.d.ts +1 -0
- package/packages/core/dist/server/index.js +1 -0
- package/packages/core/dist/types/blog.d.ts +14 -0
- package/packages/core/dist/types/docs.d.ts +28 -0
- package/packages/core/dist/types/docs.js +1 -0
- package/packages/core/dist/types/experience.d.ts +63 -0
- package/packages/core/dist/types/experience.js +1 -0
- package/packages/core/dist/theme/ThemeSwitcher.svelte +0 -34
- package/packages/core/dist/theme/index.d.ts +0 -2
- package/packages/core/dist/theme/index.js +0 -2
- package/packages/core/dist/theme/store.d.ts +0 -12
- package/packages/core/dist/theme/store.js +0 -50
|
@@ -1,18 +1,53 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { BROWSER } from 'esm-env';
|
|
3
|
+
import type { SharePlatform } from '../../types/blog';
|
|
4
|
+
|
|
5
|
+
type ShareLinkPlatform = Exclude<SharePlatform, 'copy'>;
|
|
3
6
|
|
|
4
7
|
export let title: string;
|
|
5
8
|
export let url: string;
|
|
6
9
|
export let label: string = 'Share this article';
|
|
7
10
|
export let testId: string | undefined = undefined;
|
|
11
|
+
export let platforms: SharePlatform[] = ['x', 'linkedin', 'facebook'];
|
|
8
12
|
|
|
9
13
|
let copied = false;
|
|
10
14
|
|
|
15
|
+
const shareBuilders: Record<ShareLinkPlatform, (pageUrl: string, pageTitle: string) => string> = {
|
|
16
|
+
x: (pageUrl, pageTitle) =>
|
|
17
|
+
`https://twitter.com/intent/tweet?text=${encodeURIComponent(pageTitle)}&url=${encodeURIComponent(pageUrl)}`,
|
|
18
|
+
linkedin: (pageUrl) =>
|
|
19
|
+
`https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(pageUrl)}`,
|
|
20
|
+
facebook: (pageUrl) =>
|
|
21
|
+
`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(pageUrl)}`,
|
|
22
|
+
reddit: (pageUrl, pageTitle) =>
|
|
23
|
+
`https://www.reddit.com/submit?url=${encodeURIComponent(pageUrl)}&title=${encodeURIComponent(pageTitle)}`,
|
|
24
|
+
hackernews: (pageUrl, pageTitle) =>
|
|
25
|
+
`https://news.ycombinator.com/submitlink?u=${encodeURIComponent(pageUrl)}&t=${encodeURIComponent(pageTitle)}`
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const shareLabels: Record<ShareLinkPlatform, string> = {
|
|
29
|
+
x: 'Share on X',
|
|
30
|
+
linkedin: 'Share on LinkedIn',
|
|
31
|
+
facebook: 'Share on Facebook',
|
|
32
|
+
reddit: 'Share on Reddit',
|
|
33
|
+
hackernews: 'Share on Hacker News'
|
|
34
|
+
};
|
|
35
|
+
|
|
11
36
|
function openShare(href: string) {
|
|
12
37
|
if (!BROWSER) return;
|
|
13
38
|
window.open(href, '_blank', 'noopener,noreferrer');
|
|
14
39
|
}
|
|
15
40
|
|
|
41
|
+
function isShareLinkPlatform(platform: SharePlatform): platform is ShareLinkPlatform {
|
|
42
|
+
return platform in shareBuilders;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function uniquePlatforms(input: SharePlatform[]): SharePlatform[] {
|
|
46
|
+
const deduped = new Set<SharePlatform>();
|
|
47
|
+
for (const platform of input) deduped.add(platform);
|
|
48
|
+
return Array.from(deduped);
|
|
49
|
+
}
|
|
50
|
+
|
|
16
51
|
async function copyLink() {
|
|
17
52
|
if (!BROWSER) return;
|
|
18
53
|
try {
|
|
@@ -20,7 +55,6 @@
|
|
|
20
55
|
copied = true;
|
|
21
56
|
window.setTimeout(() => (copied = false), 1200);
|
|
22
57
|
} catch {
|
|
23
|
-
// Fallback for older browsers.
|
|
24
58
|
const ta = document.createElement('textarea');
|
|
25
59
|
ta.value = url;
|
|
26
60
|
ta.style.position = 'fixed';
|
|
@@ -34,60 +68,59 @@
|
|
|
34
68
|
}
|
|
35
69
|
}
|
|
36
70
|
|
|
37
|
-
$:
|
|
38
|
-
$:
|
|
71
|
+
$: normalizedPlatforms = uniquePlatforms(platforms);
|
|
72
|
+
$: linkPlatforms = normalizedPlatforms.filter(isShareLinkPlatform);
|
|
39
73
|
</script>
|
|
40
74
|
|
|
41
75
|
<div data-testid={testId}>
|
|
42
76
|
<p class="text-xs font-mono uppercase tracking-[0.6px] text-text-muted">{label}</p>
|
|
43
77
|
<div class="mt-3 flex flex-wrap gap-2">
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
openShare(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
</button>
|
|
78
|
+
{#each linkPlatforms as platform (platform)}
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
81
|
+
class="inline-flex size-8 items-center justify-center rounded-full border border-border-soft/10 bg-background-soft/45 text-text-sub/65 transition-all duration-200 hover:bg-background-main/75 hover:text-text-main"
|
|
82
|
+
on:click={() => openShare(shareBuilders[platform](url, title))}
|
|
83
|
+
aria-label={shareLabels[platform]}
|
|
84
|
+
>
|
|
85
|
+
{#if platform === 'x'}
|
|
86
|
+
<svg viewBox="0 0 24 24" class="size-4" aria-hidden="true">
|
|
87
|
+
<path
|
|
88
|
+
fill="currentColor"
|
|
89
|
+
d="M18.9 2H22l-6.8 7.8L23 22h-6.8l-5.3-6.9L4.9 22H2l7.4-8.6L1.5 2h7l4.8 6.2L18.9 2Zm-1.2 18h1.7L7.8 3.9H6.1L17.7 20Z"
|
|
90
|
+
/>
|
|
91
|
+
</svg>
|
|
92
|
+
{:else if platform === 'linkedin'}
|
|
93
|
+
<svg viewBox="0 0 24 24" class="size-4" aria-hidden="true">
|
|
94
|
+
<path
|
|
95
|
+
fill="currentColor"
|
|
96
|
+
d="M4.98 3.5C4.98 4.88 3.87 6 2.5 6S0 4.88 0 3.5 1.12 1 2.5 1s2.48 1.12 2.48 2.5ZM0.5 23.5h4V7.98h-4V23.5ZM8 7.98h3.84v2.12h.05c.53-1 1.83-2.12 3.77-2.12 4.03 0 4.78 2.65 4.78 6.1v9.42h-4v-8.36c0-1.99-.03-4.55-2.77-4.55-2.77 0-3.2 2.16-3.2 4.4v8.5H8V7.98Z"
|
|
97
|
+
/>
|
|
98
|
+
</svg>
|
|
99
|
+
{:else if platform === 'facebook'}
|
|
100
|
+
<svg viewBox="0 0 24 24" class="size-4" aria-hidden="true">
|
|
101
|
+
<path
|
|
102
|
+
fill="currentColor"
|
|
103
|
+
d="M13.5 22v-8h2.7l.4-3H13.5V9.1c0-.9.3-1.6 1.7-1.6h1.6V4.8c-.3 0-1.4-.1-2.7-.1-2.7 0-4.5 1.6-4.5 4.6V11H7v3h2.6v8h3.9Z"
|
|
104
|
+
/>
|
|
105
|
+
</svg>
|
|
106
|
+
{:else if platform === 'reddit'}
|
|
107
|
+
<svg viewBox="0 0 24 24" class="size-4" aria-hidden="true">
|
|
108
|
+
<path
|
|
109
|
+
fill="currentColor"
|
|
110
|
+
d="M14.8 14.4a1.2 1.2 0 1 0 1.2 1.2 1.2 1.2 0 0 0-1.2-1.2Zm-5.6 0a1.2 1.2 0 1 0 1.2 1.2 1.2 1.2 0 0 0-1.2-1.2ZM12 21c3.9 0 7-2.2 7-4.9a3 3 0 0 0-.9-2.1 2 2 0 1 0-3.2-2.2 10.6 10.6 0 0 0-5.8 0 2 2 0 1 0-3.2 2.2A3 3 0 0 0 5 16.1C5 18.8 8.1 21 12 21Zm0-1.6c-3 0-5.4-1.5-5.4-3.3s2.4-3.3 5.4-3.3 5.4 1.5 5.4 3.3-2.4 3.3-5.4 3.3Zm2.6-2.3a.8.8 0 1 1 0 1.6h-5.2a.8.8 0 1 1 0-1.6h5.2Z"
|
|
111
|
+
/>
|
|
112
|
+
</svg>
|
|
113
|
+
{:else if platform === 'hackernews'}
|
|
114
|
+
<svg viewBox="0 0 24 24" class="size-4" aria-hidden="true">
|
|
115
|
+
<path fill="currentColor" d="M3 3h18v18H3V3Zm6.8 4.2 2.2 4 2.2-4h2l-3.1 5.4V17h-2v-4.4L7.8 7.2h2Z" />
|
|
116
|
+
</svg>
|
|
117
|
+
{/if}
|
|
118
|
+
</button>
|
|
119
|
+
{/each}
|
|
87
120
|
|
|
88
121
|
<button
|
|
89
122
|
type="button"
|
|
90
|
-
class="inline-flex size-8 items-center justify-center rounded-full border border-border-soft/10 bg-background-soft text-text-sub transition hover:bg-background-main/
|
|
123
|
+
class="inline-flex size-8 items-center justify-center rounded-full border border-border-soft/10 bg-background-soft/45 text-text-sub/65 transition-all duration-200 hover:bg-background-main/75 hover:text-text-main"
|
|
91
124
|
on:click={copyLink}
|
|
92
125
|
aria-label="Copy link"
|
|
93
126
|
>
|
|
@@ -111,3 +144,4 @@
|
|
|
111
144
|
<p class="mt-2 text-xs font-mono uppercase tracking-[0.6px] text-brand">Copied</p>
|
|
112
145
|
{/if}
|
|
113
146
|
</div>
|
|
147
|
+
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SharePlatform } from '../../types/blog';
|
|
1
2
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
3
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
4
|
$$bindings?: Bindings;
|
|
@@ -16,6 +17,7 @@ declare const ShareButtons: $$__sveltets_2_IsomorphicComponent<{
|
|
|
16
17
|
url: string;
|
|
17
18
|
label?: string;
|
|
18
19
|
testId?: string | undefined;
|
|
20
|
+
platforms?: SharePlatform[];
|
|
19
21
|
}, {
|
|
20
22
|
[evt: string]: CustomEvent<any>;
|
|
21
23
|
}, {}, {}, string>;
|
|
@@ -1,32 +1,85 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import
|
|
2
|
+
import { onMount, tick } from 'svelte';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
type TagTab = { label: string; slug: string };
|
|
5
|
+
export let categories: TagTab[];
|
|
5
6
|
export let selected: string; // "" means all
|
|
6
7
|
export let onSelect: (slug: string) => void;
|
|
7
8
|
$: items = [{ label: 'All articles', slug: '' }, ...categories];
|
|
9
|
+
|
|
10
|
+
let railEl: HTMLDivElement | null = null;
|
|
11
|
+
let buttonEls: HTMLButtonElement[] = [];
|
|
12
|
+
let indicatorLeft = 0;
|
|
13
|
+
let indicatorWidth = 0;
|
|
14
|
+
let indicatorReady = false;
|
|
15
|
+
|
|
16
|
+
async function syncIndicator(scroll = false) {
|
|
17
|
+
await tick();
|
|
18
|
+
const index = Math.max(
|
|
19
|
+
0,
|
|
20
|
+
items.findIndex((item) => item.slug === selected)
|
|
21
|
+
);
|
|
22
|
+
const button = buttonEls[index];
|
|
23
|
+
if (!button) {
|
|
24
|
+
indicatorReady = false;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
indicatorLeft = button.offsetLeft;
|
|
29
|
+
indicatorWidth = button.offsetWidth;
|
|
30
|
+
indicatorReady = true;
|
|
31
|
+
|
|
32
|
+
if (scroll) {
|
|
33
|
+
button.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
$: {
|
|
38
|
+
void selected;
|
|
39
|
+
void items;
|
|
40
|
+
syncIndicator(true);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
onMount(() => {
|
|
44
|
+
syncIndicator(false);
|
|
45
|
+
const ro = new ResizeObserver(() => syncIndicator(false));
|
|
46
|
+
if (railEl) ro.observe(railEl);
|
|
47
|
+
return () => ro.disconnect();
|
|
48
|
+
});
|
|
8
49
|
</script>
|
|
9
50
|
|
|
10
51
|
<div class="relative" data-testid="blog-tags">
|
|
11
52
|
<div
|
|
12
|
-
class="fade-mask-x no-scrollbar
|
|
53
|
+
class="fade-mask-x no-scrollbar overflow-x-auto py-2"
|
|
13
54
|
role="tablist"
|
|
14
55
|
aria-label="Blog categories"
|
|
15
56
|
>
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
57
|
+
<div bind:this={railEl} class="relative inline-flex min-w-max items-center gap-1 whitespace-nowrap pr-3">
|
|
58
|
+
{#if indicatorReady}
|
|
59
|
+
<span
|
|
60
|
+
class="pointer-events-none absolute bottom-[2px] top-[2px] z-[0] rounded-full border border-border-soft/15 bg-background-soft/90 shadow-[0_10px_20px_-14px_rgba(8,14,24,0.75)] transition-[left,width] duration-500 ease-[cubic-bezier(0.2,0.9,0.2,1)]"
|
|
61
|
+
style={`left:${indicatorLeft}px;width:${indicatorWidth}px;`}
|
|
62
|
+
></span>
|
|
63
|
+
<span
|
|
64
|
+
class="pointer-events-none absolute bottom-[3px] top-[3px] z-[0] rounded-full bg-background-main/60 blur-[7px] transition-[left,width] duration-500 ease-[cubic-bezier(0.2,0.9,0.2,1)]"
|
|
65
|
+
style={`left:${indicatorLeft}px;width:${indicatorWidth}px;`}
|
|
66
|
+
></span>
|
|
67
|
+
{/if}
|
|
68
|
+
|
|
69
|
+
{#each items as item, index (item.slug)}
|
|
70
|
+
<button
|
|
71
|
+
bind:this={buttonEls[index]}
|
|
72
|
+
type="button"
|
|
73
|
+
role="tab"
|
|
74
|
+
aria-selected={selected === item.slug}
|
|
75
|
+
class="relative z-[2] h-[30px] whitespace-nowrap px-3 text-xs font-mono uppercase tracking-[0.7px] transition-colors duration-200
|
|
76
|
+
hover:text-text-main
|
|
77
|
+
{selected === item.slug ? 'text-text-main' : 'text-text-sub'}"
|
|
78
|
+
on:click={() => onSelect(item.slug)}
|
|
79
|
+
>
|
|
80
|
+
{item.label}
|
|
81
|
+
</button>
|
|
82
|
+
{/each}
|
|
83
|
+
</div>
|
|
31
84
|
</div>
|
|
32
85
|
</div>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { BlogCategory } from '../../types/blog';
|
|
2
1
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
2
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
3
|
$$bindings?: Bindings;
|
|
@@ -13,7 +12,10 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
13
12
|
z_$$bindings?: Bindings;
|
|
14
13
|
}
|
|
15
14
|
declare const TagTabs: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
-
categories:
|
|
15
|
+
categories: {
|
|
16
|
+
label: string;
|
|
17
|
+
slug: string;
|
|
18
|
+
}[];
|
|
17
19
|
selected: string;
|
|
18
20
|
onSelect: (slug: string) => void;
|
|
19
21
|
}, {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DocsPage } from '../../types/docs';
|
|
3
|
+
|
|
4
|
+
export let previous: DocsPage | null = null;
|
|
5
|
+
export let next: DocsPage | null = null;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="mt-12 grid grid-cols-1 gap-3 border-t border-border-soft/10 pt-6 md:grid-cols-2" data-testid="docs-pager">
|
|
9
|
+
<a
|
|
10
|
+
href={previous ? `/docs/${previous.slug}` : '#'}
|
|
11
|
+
class="rounded-2xl border border-border-soft/10 bg-background-soft p-4 transition hover:bg-background-main/60 {previous
|
|
12
|
+
? ''
|
|
13
|
+
: 'pointer-events-none opacity-45'}"
|
|
14
|
+
>
|
|
15
|
+
<p class="text-[11px] font-mono uppercase tracking-[0.6px] text-text-muted">Previous</p>
|
|
16
|
+
<p class="mt-1 text-sm font-medium text-text-main">{previous?.navTitle || 'None'}</p>
|
|
17
|
+
</a>
|
|
18
|
+
|
|
19
|
+
<a
|
|
20
|
+
href={next ? `/docs/${next.slug}` : '#'}
|
|
21
|
+
class="rounded-2xl border border-border-soft/10 bg-background-soft p-4 text-left transition hover:bg-background-main/60 {next
|
|
22
|
+
? ''
|
|
23
|
+
: 'pointer-events-none opacity-45'}"
|
|
24
|
+
>
|
|
25
|
+
<p class="text-[11px] font-mono uppercase tracking-[0.6px] text-text-muted">Next</p>
|
|
26
|
+
<p class="mt-1 text-sm font-medium text-text-main">{next?.navTitle || 'None'}</p>
|
|
27
|
+
</a>
|
|
28
|
+
</div>
|
package/packages/core/dist/{theme/ThemeSwitcher.svelte.d.ts → components/docs/DocsPager.svelte.d.ts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DocsPage } from '../../types/docs';
|
|
2
2
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
3
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
4
|
$$bindings?: Bindings;
|
|
@@ -12,10 +12,11 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
12
12
|
};
|
|
13
13
|
z_$$bindings?: Bindings;
|
|
14
14
|
}
|
|
15
|
-
declare const
|
|
16
|
-
|
|
15
|
+
declare const DocsPager: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
previous?: DocsPage | null;
|
|
17
|
+
next?: DocsPage | null;
|
|
17
18
|
}, {
|
|
18
19
|
[evt: string]: CustomEvent<any>;
|
|
19
20
|
}, {}, {}, string>;
|
|
20
|
-
type
|
|
21
|
-
export default
|
|
21
|
+
type DocsPager = InstanceType<typeof DocsPager>;
|
|
22
|
+
export default DocsPager;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DocsSidebarSection } from '../../types/docs';
|
|
3
|
+
|
|
4
|
+
export let sections: DocsSidebarSection[] = [];
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="grid grid-cols-1 gap-6 md:grid-cols-2" data-testid="docs-section-grid">
|
|
8
|
+
{#each sections as section (section.id)}
|
|
9
|
+
<section class="rounded-3xl border border-border-soft/10 bg-background-soft p-6">
|
|
10
|
+
<p class="text-xs font-mono uppercase tracking-[0.6px] text-text-muted">{section.label}</p>
|
|
11
|
+
<ul class="mt-4 space-y-2">
|
|
12
|
+
{#each section.pages as page (page.slug)}
|
|
13
|
+
<li>
|
|
14
|
+
<a
|
|
15
|
+
href={`/docs/${page.slug}`}
|
|
16
|
+
class="inline-flex items-center gap-2 text-sm text-text-sub transition hover:text-text-main"
|
|
17
|
+
>
|
|
18
|
+
<span class="inline-block size-1.5 rounded-full bg-brand"></span>
|
|
19
|
+
{page.navTitle}
|
|
20
|
+
</a>
|
|
21
|
+
</li>
|
|
22
|
+
{/each}
|
|
23
|
+
</ul>
|
|
24
|
+
</section>
|
|
25
|
+
{/each}
|
|
26
|
+
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DocsSidebarSection } from '../../types/docs';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const DocsSectionGrid: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
sections?: DocsSidebarSection[];
|
|
17
|
+
}, {
|
|
18
|
+
[evt: string]: CustomEvent<any>;
|
|
19
|
+
}, {}, {}, string>;
|
|
20
|
+
type DocsSectionGrid = InstanceType<typeof DocsSectionGrid>;
|
|
21
|
+
export default DocsSectionGrid;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DocsSidebarSection } from '../../types/docs';
|
|
3
|
+
import Container from '../blog/Container.svelte';
|
|
4
|
+
import DocsSidebar from './DocsSidebar.svelte';
|
|
5
|
+
|
|
6
|
+
export let sections: DocsSidebarSection[] = [];
|
|
7
|
+
export let currentSlug = '';
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<Container>
|
|
11
|
+
<div class="grid grid-cols-1 gap-10 pb-24 pt-12 lg:grid-cols-[260px_minmax(0,1fr)] lg:gap-14">
|
|
12
|
+
<aside class="lg:sticky lg:top-20 lg:self-start">
|
|
13
|
+
<DocsSidebar {sections} {currentSlug} />
|
|
14
|
+
</aside>
|
|
15
|
+
<div class="min-w-0">
|
|
16
|
+
<slot />
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</Container>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { DocsSidebarSection } from '../../types/docs';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
16
|
+
default: any;
|
|
17
|
+
} ? Props extends Record<string, never> ? any : {
|
|
18
|
+
children?: any;
|
|
19
|
+
} : {});
|
|
20
|
+
declare const DocsShell: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
21
|
+
sections?: DocsSidebarSection[];
|
|
22
|
+
currentSlug?: string;
|
|
23
|
+
}, {
|
|
24
|
+
default: {};
|
|
25
|
+
}>, {
|
|
26
|
+
[evt: string]: CustomEvent<any>;
|
|
27
|
+
}, {
|
|
28
|
+
default: {};
|
|
29
|
+
}, {}, string>;
|
|
30
|
+
type DocsShell = InstanceType<typeof DocsShell>;
|
|
31
|
+
export default DocsShell;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DocsSidebarSection } from '../../types/docs';
|
|
3
|
+
|
|
4
|
+
export let sections: DocsSidebarSection[] = [];
|
|
5
|
+
export let currentSlug = '';
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<nav aria-label="Documentation" class="space-y-8" data-testid="docs-sidebar">
|
|
9
|
+
{#each sections as section (section.id)}
|
|
10
|
+
<section>
|
|
11
|
+
<h2 class="text-[11px] font-mono uppercase tracking-[0.6px] text-text-muted">
|
|
12
|
+
{section.label}
|
|
13
|
+
</h2>
|
|
14
|
+
<ul class="mt-3 space-y-1">
|
|
15
|
+
{#each section.pages as page (page.slug)}
|
|
16
|
+
<li>
|
|
17
|
+
<a
|
|
18
|
+
href={`/docs/${page.slug}`}
|
|
19
|
+
class="block rounded-lg px-3 py-2 text-sm transition hover:bg-background-soft hover:text-text-main
|
|
20
|
+
{currentSlug === page.slug
|
|
21
|
+
? 'bg-background-soft text-text-main'
|
|
22
|
+
: 'text-text-sub'}"
|
|
23
|
+
>
|
|
24
|
+
{page.navTitle}
|
|
25
|
+
</a>
|
|
26
|
+
</li>
|
|
27
|
+
{/each}
|
|
28
|
+
</ul>
|
|
29
|
+
</section>
|
|
30
|
+
{/each}
|
|
31
|
+
</nav>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DocsSidebarSection } from '../../types/docs';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const DocsSidebar: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
sections?: DocsSidebarSection[];
|
|
17
|
+
currentSlug?: string;
|
|
18
|
+
}, {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
}, {}, {}, string>;
|
|
21
|
+
type DocsSidebar = InstanceType<typeof DocsSidebar>;
|
|
22
|
+
export default DocsSidebar;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ExperienceCatalog, ExperienceDefinition, ExperienceKind } from '../types/experience';
|
|
2
|
+
import { createBlogPatternConfig, createDocsPatternConfig, createSveltaPatternConfig, DEFAULT_BLOG_PATTERN_CONFIG, DEFAULT_DOCS_PATTERN_CONFIG, resolveDocsEditUrl } from './patterns';
|
|
3
|
+
export type { ExperienceCatalog, ExperienceDefinition, ExperienceKind, SveltaBlogPatternConfig, SveltaDocsPatternConfig, SveltaNavItem, SveltaPatternConfig } from '../types/experience';
|
|
4
|
+
export { createBlogPatternConfig, createDocsPatternConfig, createSveltaPatternConfig, DEFAULT_BLOG_PATTERN_CONFIG, DEFAULT_DOCS_PATTERN_CONFIG, resolveDocsEditUrl };
|
|
5
|
+
export declare function parseExperienceKind(input: string | null | undefined, fallback?: ExperienceKind): ExperienceKind;
|
|
6
|
+
export declare function createExperienceCatalog(opts?: {
|
|
7
|
+
defaultKind?: ExperienceKind;
|
|
8
|
+
overrides?: Partial<Record<ExperienceKind, Partial<ExperienceDefinition>>>;
|
|
9
|
+
}): ExperienceCatalog;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createBlogPatternConfig, createDocsPatternConfig, createSveltaPatternConfig, DEFAULT_BLOG_PATTERN_CONFIG, DEFAULT_DOCS_PATTERN_CONFIG, resolveDocsEditUrl } from './patterns';
|
|
2
|
+
export { createBlogPatternConfig, createDocsPatternConfig, createSveltaPatternConfig, DEFAULT_BLOG_PATTERN_CONFIG, DEFAULT_DOCS_PATTERN_CONFIG, resolveDocsEditUrl };
|
|
3
|
+
const DEFAULTS = {
|
|
4
|
+
docs: {
|
|
5
|
+
kind: 'docs',
|
|
6
|
+
label: 'Documentation',
|
|
7
|
+
description: 'Structured guides with sections, side navigation, and next/previous links.',
|
|
8
|
+
href: '/docs'
|
|
9
|
+
},
|
|
10
|
+
blog: {
|
|
11
|
+
kind: 'blog',
|
|
12
|
+
label: 'Blog',
|
|
13
|
+
description: 'Editorial posts with categories, summaries, and RSS distribution.',
|
|
14
|
+
href: '/blog'
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export function parseExperienceKind(input, fallback = 'docs') {
|
|
18
|
+
if (input === 'docs' || input === 'blog')
|
|
19
|
+
return input;
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
export function createExperienceCatalog(opts) {
|
|
23
|
+
const defaultKind = opts?.defaultKind ?? 'docs';
|
|
24
|
+
const docs = {
|
|
25
|
+
...DEFAULTS.docs,
|
|
26
|
+
...(opts?.overrides?.docs ?? {}),
|
|
27
|
+
kind: 'docs'
|
|
28
|
+
};
|
|
29
|
+
const blog = {
|
|
30
|
+
...DEFAULTS.blog,
|
|
31
|
+
...(opts?.overrides?.blog ?? {}),
|
|
32
|
+
kind: 'blog'
|
|
33
|
+
};
|
|
34
|
+
const byKind = { docs, blog };
|
|
35
|
+
const items = [docs, blog];
|
|
36
|
+
return {
|
|
37
|
+
defaultKind,
|
|
38
|
+
items,
|
|
39
|
+
byKind,
|
|
40
|
+
resolve(kind) {
|
|
41
|
+
const parsed = parseExperienceKind(kind, defaultKind);
|
|
42
|
+
return byKind[parsed];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SveltaBlogPatternConfig, SveltaDocsPatternConfig, SveltaPatternConfig } from '../types/experience';
|
|
2
|
+
type DocsPatternOverrides = Partial<Omit<SveltaDocsPatternConfig, 'kind' | 'navigation' | 'search' | 'toc' | 'feedback'>> & {
|
|
3
|
+
navigation?: Partial<SveltaDocsPatternConfig['navigation']> & {
|
|
4
|
+
header?: SveltaDocsPatternConfig['navigation']['header'];
|
|
5
|
+
footer?: SveltaDocsPatternConfig['navigation']['footer'];
|
|
6
|
+
};
|
|
7
|
+
search?: Partial<SveltaDocsPatternConfig['search']>;
|
|
8
|
+
toc?: Partial<SveltaDocsPatternConfig['toc']>;
|
|
9
|
+
feedback?: Partial<SveltaDocsPatternConfig['feedback']>;
|
|
10
|
+
};
|
|
11
|
+
type BlogPatternOverrides = Partial<Omit<SveltaBlogPatternConfig, 'kind' | 'navigation'>> & {
|
|
12
|
+
navigation?: Partial<SveltaBlogPatternConfig['navigation']> & {
|
|
13
|
+
header?: SveltaBlogPatternConfig['navigation']['header'];
|
|
14
|
+
footer?: SveltaBlogPatternConfig['navigation']['footer'];
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export declare const DEFAULT_DOCS_PATTERN_CONFIG: SveltaDocsPatternConfig;
|
|
18
|
+
export declare const DEFAULT_BLOG_PATTERN_CONFIG: SveltaBlogPatternConfig;
|
|
19
|
+
export declare function createDocsPatternConfig(overrides?: DocsPatternOverrides): SveltaDocsPatternConfig;
|
|
20
|
+
export declare function createBlogPatternConfig(overrides?: BlogPatternOverrides): SveltaBlogPatternConfig;
|
|
21
|
+
export declare function createSveltaPatternConfig(overrides?: {
|
|
22
|
+
docs?: DocsPatternOverrides;
|
|
23
|
+
blog?: BlogPatternOverrides;
|
|
24
|
+
}): SveltaPatternConfig;
|
|
25
|
+
export declare function resolveDocsEditUrl(config: SveltaDocsPatternConfig, slug: string): string;
|
|
26
|
+
export {};
|