svelte-docsmith 0.2.0 → 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 -25
- package/dist/clipboard.svelte.d.ts +1 -1
- package/dist/clipboard.svelte.js +15 -8
- package/dist/config.d.ts +36 -6
- package/dist/config.js +33 -7
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -0
- package/dist/markdown-layout.svelte +14 -1
- package/dist/markdown-layout.svelte.d.ts +2 -0
- package/dist/preprocess.d.ts +4 -5
- package/dist/preprocess.js +15 -7
- package/dist/search/context.svelte.d.ts +7 -0
- package/dist/search/context.svelte.js +20 -0
- package/dist/search/create-search.d.ts +14 -0
- package/dist/search/create-search.js +56 -0
- package/dist/search/snippet.d.ts +7 -0
- package/dist/search/snippet.js +43 -0
- package/dist/search.d.ts +10 -0
- package/dist/search.js +4 -0
- package/dist/theme.css +25 -0
- package/dist/types.d.ts +0 -6
- package/dist/ui/badge.svelte +10 -1
- package/dist/ui/badge.svelte.d.ts +2 -0
- package/dist/ui/callout.svelte +9 -9
- package/dist/ui/callout.svelte.d.ts +3 -3
- package/dist/ui/layouts/docs-header.svelte +5 -11
- package/dist/ui/layouts/docs-header.svelte.d.ts +0 -6
- package/dist/ui/layouts/docs-mobile-header.svelte +40 -8
- package/dist/ui/layouts/docs-mobile-header.svelte.d.ts +5 -4
- package/dist/ui/layouts/docs-shell.svelte +49 -5
- package/dist/ui/layouts/docs-shell.svelte.d.ts +16 -1
- package/dist/ui/layouts/error-page.svelte +82 -0
- package/dist/ui/layouts/error-page.svelte.d.ts +25 -0
- package/dist/ui/layouts/seo-head.svelte +65 -0
- package/dist/ui/layouts/seo-head.svelte.d.ts +11 -0
- package/dist/ui/markdown/h2.svelte +7 -3
- package/dist/ui/markdown/h3.svelte +7 -3
- package/dist/ui/markdown/pre.svelte +79 -29
- package/dist/ui/prop.svelte +71 -36
- package/dist/ui/prop.svelte.d.ts +1 -1
- package/dist/ui/props-table.svelte +10 -62
- package/dist/ui/search-trigger.svelte +31 -0
- package/dist/ui/search-trigger.svelte.d.ts +6 -0
- package/dist/ui/search.svelte +167 -0
- package/dist/ui/search.svelte.d.ts +13 -0
- package/dist/ui/shadcn/accordion/accordion.svelte.d.ts +1 -1
- package/dist/ui/shadcn/command/command-dialog.svelte +42 -0
- package/dist/ui/shadcn/command/command-dialog.svelte.d.ts +14 -0
- package/dist/ui/shadcn/command/command-empty.svelte +17 -0
- package/dist/ui/shadcn/command/command-empty.svelte.d.ts +4 -0
- package/dist/ui/shadcn/command/command-group.svelte +33 -0
- package/dist/ui/shadcn/command/command-group.svelte.d.ts +7 -0
- package/dist/ui/shadcn/command/command-input.svelte +36 -0
- package/dist/ui/shadcn/command/command-input.svelte.d.ts +4 -0
- package/dist/ui/shadcn/command/command-item.svelte +27 -0
- package/dist/ui/shadcn/command/command-item.svelte.d.ts +4 -0
- package/dist/ui/shadcn/command/command-link-item.svelte +20 -0
- package/dist/ui/shadcn/command/command-link-item.svelte.d.ts +4 -0
- package/dist/ui/shadcn/command/command-list.svelte +20 -0
- package/dist/ui/shadcn/command/command-list.svelte.d.ts +4 -0
- package/dist/ui/shadcn/command/command-loading.svelte +7 -0
- package/dist/ui/shadcn/command/command-loading.svelte.d.ts +4 -0
- package/dist/ui/shadcn/command/command-separator.svelte +17 -0
- package/dist/ui/shadcn/command/command-separator.svelte.d.ts +4 -0
- package/dist/ui/shadcn/command/command-shortcut.svelte +23 -0
- package/dist/ui/shadcn/command/command-shortcut.svelte.d.ts +5 -0
- package/dist/ui/shadcn/command/command.svelte +28 -0
- package/dist/ui/shadcn/command/command.svelte.d.ts +8 -0
- package/dist/ui/shadcn/command/index.d.ts +12 -0
- package/dist/ui/shadcn/command/index.js +14 -0
- package/dist/ui/shadcn/dialog/dialog-close.svelte +11 -0
- package/dist/ui/shadcn/dialog/dialog-close.svelte.d.ts +4 -0
- package/dist/ui/shadcn/dialog/dialog-content.svelte +48 -0
- package/dist/ui/shadcn/dialog/dialog-content.svelte.d.ts +13 -0
- package/dist/ui/shadcn/dialog/dialog-description.svelte +20 -0
- package/dist/ui/shadcn/dialog/dialog-description.svelte.d.ts +4 -0
- package/dist/ui/shadcn/dialog/dialog-footer.svelte +32 -0
- package/dist/ui/shadcn/dialog/dialog-footer.svelte.d.ts +8 -0
- package/dist/ui/shadcn/dialog/dialog-header.svelte +20 -0
- package/dist/ui/shadcn/dialog/dialog-header.svelte.d.ts +5 -0
- package/dist/ui/shadcn/dialog/dialog-overlay.svelte +20 -0
- package/dist/ui/shadcn/dialog/dialog-overlay.svelte.d.ts +4 -0
- package/dist/ui/shadcn/dialog/dialog-portal.svelte +7 -0
- package/dist/ui/shadcn/dialog/dialog-portal.svelte.d.ts +3 -0
- package/dist/ui/shadcn/dialog/dialog-title.svelte +17 -0
- package/dist/ui/shadcn/dialog/dialog-title.svelte.d.ts +4 -0
- package/dist/ui/shadcn/dialog/dialog-trigger.svelte +11 -0
- package/dist/ui/shadcn/dialog/dialog-trigger.svelte.d.ts +4 -0
- package/dist/ui/shadcn/dialog/dialog.svelte +7 -0
- package/dist/ui/shadcn/dialog/dialog.svelte.d.ts +3 -0
- package/dist/ui/shadcn/dialog/index.d.ts +11 -0
- package/dist/ui/shadcn/dialog/index.js +13 -0
- package/dist/ui/shadcn/input/index.d.ts +2 -0
- package/dist/ui/shadcn/input/index.js +4 -0
- package/dist/ui/shadcn/input/input.svelte +48 -0
- package/dist/ui/shadcn/input/input.svelte.d.ts +13 -0
- package/dist/ui/shadcn/input-group/index.d.ts +7 -0
- package/dist/ui/shadcn/input-group/index.js +9 -0
- package/dist/ui/shadcn/input-group/input-group-addon.svelte +53 -0
- package/dist/ui/shadcn/input-group/input-group-addon.svelte.d.ts +32 -0
- package/dist/ui/shadcn/input-group/input-group-button.svelte +49 -0
- package/dist/ui/shadcn/input-group/input-group-button.svelte.d.ts +32 -0
- package/dist/ui/shadcn/input-group/input-group-input.svelte +23 -0
- package/dist/ui/shadcn/input-group/input-group-input.svelte.d.ts +11 -0
- package/dist/ui/shadcn/input-group/input-group-text.svelte +22 -0
- package/dist/ui/shadcn/input-group/input-group-text.svelte.d.ts +5 -0
- package/dist/ui/shadcn/input-group/input-group-textarea.svelte +23 -0
- package/dist/ui/shadcn/input-group/input-group-textarea.svelte.d.ts +3 -0
- package/dist/ui/shadcn/input-group/input-group.svelte +24 -0
- package/dist/ui/shadcn/input-group/input-group.svelte.d.ts +5 -0
- package/dist/ui/shadcn/tabs/tabs.svelte.d.ts +1 -1
- package/dist/ui/shadcn/textarea/index.d.ts +2 -0
- package/dist/ui/shadcn/textarea/index.js +4 -0
- package/dist/ui/shadcn/textarea/textarea.svelte +23 -0
- package/dist/ui/shadcn/textarea/textarea.svelte.d.ts +5 -0
- package/dist/ui/tab-item.svelte +35 -9
- package/dist/ui/tab-item.svelte.d.ts +9 -4
- package/dist/ui/tabs-phase.svelte +19 -0
- package/dist/ui/tabs-phase.svelte.d.ts +9 -0
- package/dist/ui/tabs.svelte +47 -24
- package/dist/ui/tabs.svelte.d.ts +16 -6
- package/dist/vite.d.ts +8 -6
- package/dist/vite.js +140 -47
- package/package.json +8 -2
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
const { children, ...attrs }: HeadingProps = $props();
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
|
-
<h3 {...attrs} class="flex
|
|
8
|
+
<h3 {...attrs} class="group flex items-center gap-2">
|
|
9
9
|
{@render children()}
|
|
10
|
-
<a
|
|
11
|
-
|
|
10
|
+
<a
|
|
11
|
+
href="#{attrs.id}"
|
|
12
|
+
aria-label="Link to this section"
|
|
13
|
+
class="opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
|
|
14
|
+
>
|
|
15
|
+
<Link class="text-primary size-5" />
|
|
12
16
|
</a>
|
|
13
17
|
</h3>
|
|
@@ -20,24 +20,6 @@
|
|
|
20
20
|
<pre class="not-prose shiki max-h-[32rem] flex shrink" use:clipboard.readText>
|
|
21
21
|
{@render children()}
|
|
22
22
|
</pre>
|
|
23
|
-
|
|
24
|
-
<!-- Scroll indicators with increased fade intensity -->
|
|
25
|
-
<div
|
|
26
|
-
class="absolute bottom-0 left-0 right-0 h-4 bg-gradient-to-t from-muted via-muted/70 to-transparent pointer-events-none"
|
|
27
|
-
aria-hidden="true"
|
|
28
|
-
></div>
|
|
29
|
-
<div
|
|
30
|
-
class="absolute top-0 left-0 right-0 h-4 bg-gradient-to-b from-muted via-muted/70 to-transparent pointer-events-none"
|
|
31
|
-
aria-hidden="true"
|
|
32
|
-
></div>
|
|
33
|
-
<div
|
|
34
|
-
class="absolute top-0 bottom-0 right-0 w-4 bg-gradient-to-l from-muted via-muted/70 to-transparent pointer-events-none"
|
|
35
|
-
aria-hidden="true"
|
|
36
|
-
></div>
|
|
37
|
-
<div
|
|
38
|
-
class="absolute top-0 bottom-0 left-0 w-4 bg-gradient-to-r from-muted via-muted/70 to-transparent pointer-events-none"
|
|
39
|
-
aria-hidden="true"
|
|
40
|
-
></div>
|
|
41
23
|
</ScrollArea>
|
|
42
24
|
</div>
|
|
43
25
|
|
|
@@ -46,7 +28,7 @@
|
|
|
46
28
|
* Plain CSS (not @apply): these style Shiki's output and ship inside the
|
|
47
29
|
* published package, where the consumer's Tailwind theme context isn't
|
|
48
30
|
* available to resolve @apply (Tailwind v4 compiles scoped styles in
|
|
49
|
-
* isolation).
|
|
31
|
+
* isolation).
|
|
50
32
|
*/
|
|
51
33
|
:global(pre code) {
|
|
52
34
|
display: block;
|
|
@@ -62,27 +44,95 @@
|
|
|
62
44
|
padding-inline: 1rem;
|
|
63
45
|
}
|
|
64
46
|
|
|
47
|
+
/* Two tiers of annotation. EMPHASIS (highlight, word) tints with the theme's
|
|
48
|
+
--primary, so it reads as the brand pointing at a line and recolors with
|
|
49
|
+
the active theme. SEMANTIC (diff, error, warning) uses fixed OKLCH hues so
|
|
50
|
+
green/red/amber stay legible on any theme. All are translucent washes over
|
|
51
|
+
the code background via color-mix. */
|
|
52
|
+
|
|
53
|
+
/* --- Line highlight (// [!code highlight] and {1,3} meta) --- */
|
|
65
54
|
:global(pre span.line.highlighted) {
|
|
66
|
-
background
|
|
55
|
+
background: color-mix(in oklch, var(--primary) 12%, transparent);
|
|
67
56
|
}
|
|
68
|
-
|
|
69
57
|
:global(.dark pre span.line.highlighted) {
|
|
70
|
-
background
|
|
58
|
+
background: color-mix(in oklch, var(--primary) 20%, transparent);
|
|
71
59
|
}
|
|
72
60
|
|
|
61
|
+
/* --- Diff (// [!code ++] / [!code --]) with +/- gutter glyphs --- */
|
|
62
|
+
:global(pre span.line.diff) {
|
|
63
|
+
position: relative;
|
|
64
|
+
}
|
|
73
65
|
:global(pre span.line.diff.add) {
|
|
74
|
-
background
|
|
66
|
+
background: color-mix(in oklch, oklch(0.7 0.16 150) 15%, transparent);
|
|
75
67
|
}
|
|
76
|
-
|
|
77
68
|
:global(pre span.line.diff.remove) {
|
|
78
|
-
background
|
|
69
|
+
background: color-mix(in oklch, oklch(0.62 0.2 25) 14%, transparent);
|
|
79
70
|
}
|
|
80
|
-
|
|
81
71
|
:global(.dark pre span.line.diff.add) {
|
|
82
|
-
background
|
|
72
|
+
background: color-mix(in oklch, oklch(0.7 0.16 150) 22%, transparent);
|
|
83
73
|
}
|
|
84
|
-
|
|
85
74
|
:global(.dark pre span.line.diff.remove) {
|
|
86
|
-
background
|
|
75
|
+
background: color-mix(in oklch, oklch(0.62 0.2 25) 22%, transparent);
|
|
76
|
+
}
|
|
77
|
+
:global(pre span.line.diff::before) {
|
|
78
|
+
position: absolute;
|
|
79
|
+
left: 0.45rem;
|
|
80
|
+
font-weight: 600;
|
|
81
|
+
}
|
|
82
|
+
:global(pre span.line.diff.add::before) {
|
|
83
|
+
content: '+';
|
|
84
|
+
color: oklch(0.6 0.15 150);
|
|
85
|
+
}
|
|
86
|
+
:global(pre span.line.diff.remove::before) {
|
|
87
|
+
content: '−';
|
|
88
|
+
color: oklch(0.58 0.19 25);
|
|
89
|
+
}
|
|
90
|
+
:global(.dark pre span.line.diff.add::before) {
|
|
91
|
+
color: oklch(0.78 0.17 150);
|
|
92
|
+
}
|
|
93
|
+
:global(.dark pre span.line.diff.remove::before) {
|
|
94
|
+
color: oklch(0.72 0.18 25);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* --- Error / warning severity (// [!code error] / [!code warning]).
|
|
98
|
+
No gutter glyph, so they stay distinct from the +/- diff lines. --- */
|
|
99
|
+
:global(pre span.line.highlighted.error) {
|
|
100
|
+
background: color-mix(in oklch, oklch(0.62 0.2 25) 18%, transparent);
|
|
101
|
+
}
|
|
102
|
+
:global(pre span.line.highlighted.warning) {
|
|
103
|
+
background: color-mix(in oklch, oklch(0.8 0.13 85) 22%, transparent);
|
|
104
|
+
}
|
|
105
|
+
:global(.dark pre span.line.highlighted.error) {
|
|
106
|
+
background: color-mix(in oklch, oklch(0.62 0.2 25) 26%, transparent);
|
|
107
|
+
}
|
|
108
|
+
:global(.dark pre span.line.highlighted.warning) {
|
|
109
|
+
background: color-mix(in oklch, oklch(0.8 0.13 85) 20%, transparent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* --- Focus (// [!code focus]): dim the other lines and restore on hover.
|
|
113
|
+
A clean opacity fade reads calmer than a muddy blur. `:has` recreates
|
|
114
|
+
Shiki's stripped container flag from the line classes alone. --- */
|
|
115
|
+
:global(pre code:has(span.line.focused) span.line:not(.focused)) {
|
|
116
|
+
opacity: 0.42;
|
|
117
|
+
transition: opacity 0.25s ease;
|
|
118
|
+
}
|
|
119
|
+
:global(pre:hover code:has(span.line.focused) span.line:not(.focused)) {
|
|
120
|
+
opacity: 1;
|
|
121
|
+
}
|
|
122
|
+
@media (prefers-reduced-motion: reduce) {
|
|
123
|
+
:global(pre code:has(span.line.focused) span.line:not(.focused)) {
|
|
124
|
+
transition: none;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* --- Word highlight (// [!code word:name]): a primary-tinted inline pill --- */
|
|
129
|
+
:global(pre .highlighted-word) {
|
|
130
|
+
border-radius: 0.3rem;
|
|
131
|
+
padding: 0.1rem 0.3rem;
|
|
132
|
+
background: color-mix(in oklch, var(--primary) 16%, transparent);
|
|
133
|
+
box-shadow: 0 0 0 1px color-mix(in oklch, var(--primary) 35%, transparent);
|
|
134
|
+
}
|
|
135
|
+
:global(.dark pre .highlighted-word) {
|
|
136
|
+
background: color-mix(in oklch, var(--primary) 24%, transparent);
|
|
87
137
|
}
|
|
88
138
|
</style>
|
package/dist/ui/prop.svelte
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
type?: string;
|
|
15
15
|
/** Mark the property as required. */
|
|
16
16
|
required?: boolean;
|
|
17
|
-
/** Default value, shown
|
|
17
|
+
/** Default value, shown alongside the type. */
|
|
18
18
|
default?: string;
|
|
19
19
|
/** Description. */
|
|
20
20
|
children?: Snippet;
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
|
|
23
23
|
// Split a union into per-value chips so long ones wrap as a tidy pill group
|
|
24
24
|
// instead of ugly broken text. Skip splitting when the type is a generic
|
|
25
|
-
// (`Array<A | B>`) where a top-level `|` split
|
|
25
|
+
// (`Array<A | B>`) or a signature (`() => …`) where a top-level `|` split
|
|
26
|
+
// would be wrong — those render as one chip that wraps on its own.
|
|
26
27
|
const typeParts = $derived.by(() => {
|
|
27
28
|
if (!type) return [];
|
|
28
29
|
if (/[<(]/.test(type)) return [type];
|
|
@@ -31,46 +32,64 @@
|
|
|
31
32
|
.map((s) => s.trim())
|
|
32
33
|
.filter(Boolean);
|
|
33
34
|
});
|
|
35
|
+
const solo = $derived(typeParts.length === 1);
|
|
34
36
|
</script>
|
|
35
37
|
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
<code>{name}</code>
|
|
38
|
+
<div class="prop-row">
|
|
39
|
+
<div class="prop-head">
|
|
40
|
+
<code class="prop-name">{name}</code>
|
|
39
41
|
{#if required}<span class="prop-required">required</span>{/if}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
|
|
43
|
+
{#if type}
|
|
44
|
+
<span class="prop-types">
|
|
45
|
+
{#each typeParts as part (part)}
|
|
46
|
+
<code class="type-chip" class:type-chip-solo={solo}>{part}</code>
|
|
47
|
+
{/each}
|
|
48
|
+
</span>
|
|
49
|
+
{/if}
|
|
50
|
+
|
|
47
51
|
{#if defaultValue !== undefined}
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
<span class="prop-default">
|
|
53
|
+
<span class="prop-default-label">default</span>
|
|
54
|
+
<code>{defaultValue}</code>
|
|
55
|
+
</span>
|
|
51
56
|
{/if}
|
|
52
|
-
</
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
{#if children}
|
|
60
|
+
<div class="prop-desc">{@render children()}</div>
|
|
61
|
+
{/if}
|
|
62
|
+
</div>
|
|
57
63
|
|
|
58
64
|
<style>
|
|
65
|
+
.prop-row {
|
|
66
|
+
padding: 0.95rem 1rem;
|
|
67
|
+
border-top: 1px solid var(--border);
|
|
68
|
+
}
|
|
69
|
+
.prop-row:first-child {
|
|
70
|
+
border-top: none;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Name + required + type + default flow on one wrapping line. */
|
|
74
|
+
.prop-head {
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-wrap: wrap;
|
|
77
|
+
align-items: center;
|
|
78
|
+
gap: 0.4rem 0.6rem;
|
|
79
|
+
min-width: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
59
82
|
/* Name is the anchor you scan for: mono, ink, medium weight. */
|
|
60
83
|
.prop-name {
|
|
61
|
-
white-space: nowrap;
|
|
62
|
-
}
|
|
63
|
-
.prop-name code {
|
|
64
84
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
65
85
|
font-size: 0.8125rem;
|
|
66
86
|
font-weight: 600;
|
|
67
87
|
color: var(--foreground);
|
|
68
88
|
}
|
|
89
|
+
|
|
69
90
|
/* Solid brand pill — the sanctioned primary-foreground-on-primary pairing,
|
|
70
91
|
so it stays legible in both themes (terracotta-on-tint fails AA in light). */
|
|
71
92
|
.prop-required {
|
|
72
|
-
display: inline-block;
|
|
73
|
-
margin-left: 0.45rem;
|
|
74
93
|
padding: 0.05rem 0.4rem;
|
|
75
94
|
border-radius: 9999px;
|
|
76
95
|
background: var(--primary);
|
|
@@ -78,17 +97,18 @@
|
|
|
78
97
|
font-size: 0.625rem;
|
|
79
98
|
font-weight: 600;
|
|
80
99
|
letter-spacing: 0.02em;
|
|
81
|
-
|
|
100
|
+
text-transform: uppercase;
|
|
82
101
|
}
|
|
83
102
|
|
|
84
103
|
/* Type values as chips: a union wraps as a neat pill group, each token
|
|
85
|
-
unbroken.
|
|
86
|
-
.prop-
|
|
87
|
-
|
|
104
|
+
unbroken. A lone signature/generic wraps within itself on narrow screens. */
|
|
105
|
+
.prop-types {
|
|
106
|
+
display: inline-flex;
|
|
107
|
+
flex-wrap: wrap;
|
|
108
|
+
gap: 0.3rem;
|
|
109
|
+
min-width: 0;
|
|
88
110
|
}
|
|
89
111
|
.type-chip {
|
|
90
|
-
display: inline-block;
|
|
91
|
-
margin: 0.1rem 0.3rem 0.1rem 0;
|
|
92
112
|
padding: 0.05rem 0.4rem;
|
|
93
113
|
border-radius: 0.4rem;
|
|
94
114
|
border: 1px solid var(--border);
|
|
@@ -98,22 +118,36 @@
|
|
|
98
118
|
color: var(--foreground);
|
|
99
119
|
white-space: nowrap;
|
|
100
120
|
}
|
|
121
|
+
.type-chip-solo {
|
|
122
|
+
white-space: normal;
|
|
123
|
+
overflow-wrap: anywhere;
|
|
124
|
+
max-width: 100%;
|
|
125
|
+
}
|
|
101
126
|
|
|
127
|
+
/* Default sits at the end of the line, pushed right when there's room. */
|
|
102
128
|
.prop-default {
|
|
129
|
+
display: inline-flex;
|
|
130
|
+
align-items: baseline;
|
|
131
|
+
gap: 0.35rem;
|
|
132
|
+
margin-left: auto;
|
|
103
133
|
white-space: nowrap;
|
|
104
134
|
}
|
|
135
|
+
.prop-default-label {
|
|
136
|
+
font-size: 0.7rem;
|
|
137
|
+
color: var(--muted-foreground);
|
|
138
|
+
}
|
|
105
139
|
.prop-default code {
|
|
106
140
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
107
|
-
font-size: 0.
|
|
141
|
+
font-size: 0.78rem;
|
|
108
142
|
color: var(--foreground);
|
|
109
143
|
}
|
|
110
|
-
.prop-none {
|
|
111
|
-
color: var(--muted-foreground);
|
|
112
|
-
}
|
|
113
144
|
|
|
114
145
|
.prop-desc {
|
|
115
|
-
|
|
146
|
+
margin-top: 0.5rem;
|
|
147
|
+
color: var(--muted-foreground);
|
|
148
|
+
font-size: 0.875rem;
|
|
116
149
|
line-height: 1.55;
|
|
150
|
+
max-width: 68ch;
|
|
117
151
|
}
|
|
118
152
|
.prop-desc :global(code) {
|
|
119
153
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
@@ -121,6 +155,7 @@
|
|
|
121
155
|
padding: 0.05em 0.3em;
|
|
122
156
|
border-radius: 0.3rem;
|
|
123
157
|
background: color-mix(in oklch, var(--muted) 60%, transparent);
|
|
158
|
+
color: var(--foreground);
|
|
124
159
|
}
|
|
125
160
|
.prop-desc :global(a) {
|
|
126
161
|
color: var(--primary);
|
package/dist/ui/prop.svelte.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ type $$ComponentProps = {
|
|
|
6
6
|
type?: string;
|
|
7
7
|
/** Mark the property as required. */
|
|
8
8
|
required?: boolean;
|
|
9
|
-
/** Default value, shown
|
|
9
|
+
/** Default value, shown alongside the type. */
|
|
10
10
|
default?: string;
|
|
11
11
|
/** Description. */
|
|
12
12
|
children?: Snippet;
|
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
<Prop name="variant" type="'a' | 'b'" default="'a'">Visual intent.</Prop>
|
|
19
19
|
<Prop name="href" type="string" required>Turns it into a link.</Prop>
|
|
20
20
|
</PropsTable>
|
|
21
|
+
|
|
22
|
+
Rows stack (name/type/default on one line, description below) so long type
|
|
23
|
+
signatures never force a horizontal scroll or crush the description.
|
|
21
24
|
-->
|
|
22
25
|
<div class="props-table not-prose">
|
|
23
26
|
{#if title}
|
|
@@ -26,20 +29,8 @@
|
|
|
26
29
|
<span class="props-table-caption-name">{title}</span>
|
|
27
30
|
</div>
|
|
28
31
|
{/if}
|
|
29
|
-
<div class="props-
|
|
30
|
-
|
|
31
|
-
<thead>
|
|
32
|
-
<tr>
|
|
33
|
-
<th class="col-prop">Prop</th>
|
|
34
|
-
<th class="col-type">Type</th>
|
|
35
|
-
<th class="col-default">Default</th>
|
|
36
|
-
<th class="col-desc">Description</th>
|
|
37
|
-
</tr>
|
|
38
|
-
</thead>
|
|
39
|
-
<tbody>
|
|
40
|
-
{@render children()}
|
|
41
|
-
</tbody>
|
|
42
|
-
</table>
|
|
32
|
+
<div class="props-list">
|
|
33
|
+
{@render children()}
|
|
43
34
|
</div>
|
|
44
35
|
</div>
|
|
45
36
|
|
|
@@ -49,12 +40,11 @@
|
|
|
49
40
|
border: 1px solid var(--border);
|
|
50
41
|
border-radius: var(--radius);
|
|
51
42
|
background: var(--card);
|
|
52
|
-
/* Clip the scroll region to the rounded corners. */
|
|
53
43
|
overflow: hidden;
|
|
54
44
|
}
|
|
55
45
|
|
|
56
|
-
/* Caption = which component. Mono + ink weight, distinct from the
|
|
57
|
-
|
|
46
|
+
/* Caption = which component. Mono + ink weight, distinct from the rows below
|
|
47
|
+
it so the header never reads as one grey slab. */
|
|
58
48
|
.props-table-caption {
|
|
59
49
|
display: flex;
|
|
60
50
|
align-items: center;
|
|
@@ -78,50 +68,8 @@
|
|
|
78
68
|
color: var(--foreground);
|
|
79
69
|
}
|
|
80
70
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.props-table table {
|
|
85
|
-
width: 100%;
|
|
86
|
-
border-collapse: collapse;
|
|
87
|
-
font-size: 0.875rem;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/* Column headers: quiet labels, no fill — the caption owns the emphasis. */
|
|
91
|
-
.props-table :global(thead th) {
|
|
92
|
-
text-align: left;
|
|
93
|
-
font-size: 0.75rem;
|
|
94
|
-
font-weight: 500;
|
|
95
|
-
color: var(--muted-foreground);
|
|
96
|
-
padding: 0.55rem 1rem;
|
|
97
|
-
border-bottom: 1px solid var(--border);
|
|
98
|
-
white-space: nowrap;
|
|
99
|
-
}
|
|
100
|
-
/* Prop / Default shrink to their content; Type flexes; Description holds width. */
|
|
101
|
-
.props-table :global(.col-prop),
|
|
102
|
-
.props-table :global(.col-default) {
|
|
103
|
-
width: 1%;
|
|
104
|
-
}
|
|
105
|
-
.props-table :global(.col-desc) {
|
|
106
|
-
width: 40%;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.props-table :global(tbody td) {
|
|
110
|
-
padding: 0.7rem 1rem;
|
|
111
|
-
vertical-align: baseline;
|
|
112
|
-
border-top: 1px solid var(--border);
|
|
113
|
-
transition: background-color 120ms ease;
|
|
114
|
-
}
|
|
115
|
-
.props-table :global(tbody tr:first-child td) {
|
|
116
|
-
border-top: none;
|
|
117
|
-
}
|
|
118
|
-
.props-table :global(tbody tr:hover td) {
|
|
119
|
-
background: color-mix(in oklch, var(--muted) 45%, transparent);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
@media (prefers-reduced-motion: reduce) {
|
|
123
|
-
.props-table :global(tbody td) {
|
|
124
|
-
transition: none;
|
|
125
|
-
}
|
|
71
|
+
/* Each child <Prop> is a `.prop-row` with its own border-top. */
|
|
72
|
+
.props-list {
|
|
73
|
+
min-width: 0;
|
|
126
74
|
}
|
|
127
75
|
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import SearchIcon from '@lucide/svelte/icons/search';
|
|
3
|
+
import { useSearch } from '../search/context.svelte.js';
|
|
4
|
+
|
|
5
|
+
const { class: className = '' }: { class?: string } = $props();
|
|
6
|
+
|
|
7
|
+
const search = useSearch();
|
|
8
|
+
|
|
9
|
+
// Resolve the modifier label client-side so SSR stays platform-neutral.
|
|
10
|
+
let isMac = $state(false);
|
|
11
|
+
$effect(() => {
|
|
12
|
+
isMac = navigator.platform.toLowerCase().includes('mac');
|
|
13
|
+
});
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
{#if search}
|
|
17
|
+
<button
|
|
18
|
+
type="button"
|
|
19
|
+
onclick={() => (search.open = true)}
|
|
20
|
+
class="text-muted-foreground hover:text-foreground border-border/50 bg-muted/40 hover:bg-muted focus-visible:ring-ring inline-flex h-8 items-center gap-2 rounded-md border px-2.5 text-sm transition-colors focus-visible:ring-2 focus-visible:outline-none {className}"
|
|
21
|
+
>
|
|
22
|
+
<SearchIcon class="size-4 shrink-0" />
|
|
23
|
+
<span class="hidden sm:inline">Search</span>
|
|
24
|
+
<kbd
|
|
25
|
+
class="border-border/60 bg-background text-muted-foreground pointer-events-none ml-2 hidden h-5 items-center gap-0.5 rounded border px-1.5 font-mono text-[10px] font-medium sm:inline-flex"
|
|
26
|
+
>
|
|
27
|
+
{isMac ? '⌘' : 'Ctrl'}K
|
|
28
|
+
</kbd>
|
|
29
|
+
<span class="sr-only">Search documentation</span>
|
|
30
|
+
</button>
|
|
31
|
+
{/if}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { goto } from '$app/navigation';
|
|
3
|
+
import * as Command from './shadcn/command/index.js';
|
|
4
|
+
import { useSearch } from '../search/context.svelte.js';
|
|
5
|
+
import type { SearchDoc } from '../config.js';
|
|
6
|
+
import type { SearchEngine } from '../search/create-search.js';
|
|
7
|
+
import CornerDownLeft from '@lucide/svelte/icons/corner-down-left';
|
|
8
|
+
import FileText from '@lucide/svelte/icons/file-text';
|
|
9
|
+
import LoaderCircle from '@lucide/svelte/icons/loader-circle';
|
|
10
|
+
import SearchIcon from '@lucide/svelte/icons/search';
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
load,
|
|
14
|
+
placeholder = 'Search documentation...'
|
|
15
|
+
}: {
|
|
16
|
+
/**
|
|
17
|
+
* Lazily provide the generated search records. Wired by the consumer so the
|
|
18
|
+
* index is code-split and only fetched when the palette first opens, e.g.
|
|
19
|
+
* `() => import('svelte-docsmith/search').then((m) => m.docs)`.
|
|
20
|
+
*/
|
|
21
|
+
load: () => Promise<SearchDoc[]>;
|
|
22
|
+
placeholder?: string;
|
|
23
|
+
} = $props();
|
|
24
|
+
|
|
25
|
+
const search = useSearch();
|
|
26
|
+
|
|
27
|
+
let query = $state('');
|
|
28
|
+
let engine = $state<SearchEngine | null>(null);
|
|
29
|
+
let status = $state<'idle' | 'loading' | 'error'>('idle');
|
|
30
|
+
|
|
31
|
+
const trimmed = $derived(query.trim());
|
|
32
|
+
const results = $derived(engine && trimmed ? engine.search(query) : []);
|
|
33
|
+
|
|
34
|
+
// Build the index the first time the palette opens; keep it for later opens.
|
|
35
|
+
async function ensureEngine() {
|
|
36
|
+
if (engine || status === 'loading') return;
|
|
37
|
+
status = 'loading';
|
|
38
|
+
try {
|
|
39
|
+
const [{ createSearchEngine }, docs] = await Promise.all([
|
|
40
|
+
import('../search/create-search.js'),
|
|
41
|
+
load()
|
|
42
|
+
]);
|
|
43
|
+
engine = createSearchEngine(docs);
|
|
44
|
+
status = 'idle';
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('[svelte-docsmith] failed to load the search index', error);
|
|
47
|
+
status = 'error';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
$effect(() => {
|
|
52
|
+
if (search?.open) ensureEngine();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
function onWindowKeydown(event: KeyboardEvent) {
|
|
56
|
+
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') {
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
if (search) search.open = !search.open;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function select(path: string) {
|
|
63
|
+
if (search) search.open = false;
|
|
64
|
+
query = '';
|
|
65
|
+
goto(path);
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<svelte:window onkeydown={onWindowKeydown} />
|
|
70
|
+
|
|
71
|
+
{#if search}
|
|
72
|
+
<Command.Dialog
|
|
73
|
+
bind:open={search.open}
|
|
74
|
+
shouldFilter={false}
|
|
75
|
+
title="Search"
|
|
76
|
+
description="Search the documentation"
|
|
77
|
+
class="ring-border/70 shadow-2xl ring-1 sm:max-w-xl"
|
|
78
|
+
>
|
|
79
|
+
<Command.Input bind:value={query} {placeholder} />
|
|
80
|
+
|
|
81
|
+
<div class="bg-border/50 -mx-1 mt-1 h-px"></div>
|
|
82
|
+
|
|
83
|
+
<Command.List class="scrollbar-slim max-h-[min(24rem,60vh)] px-2 py-2">
|
|
84
|
+
{#if status === 'loading'}
|
|
85
|
+
<div class="text-muted-foreground flex items-center justify-center gap-2 py-10 text-sm">
|
|
86
|
+
<LoaderCircle class="size-4 animate-spin" />
|
|
87
|
+
Loading search…
|
|
88
|
+
</div>
|
|
89
|
+
{:else if status === 'error'}
|
|
90
|
+
<div class="text-muted-foreground px-4 py-10 text-center text-sm">
|
|
91
|
+
Search is unavailable right now.
|
|
92
|
+
</div>
|
|
93
|
+
{:else if !trimmed}
|
|
94
|
+
<div
|
|
95
|
+
class="text-muted-foreground flex flex-col items-center gap-3 px-4 py-10 text-center text-sm"
|
|
96
|
+
>
|
|
97
|
+
<span
|
|
98
|
+
class="bg-muted/60 text-muted-foreground flex size-11 items-center justify-center rounded-full"
|
|
99
|
+
>
|
|
100
|
+
<SearchIcon class="size-5" />
|
|
101
|
+
</span>
|
|
102
|
+
<span>Search across every page of the documentation.</span>
|
|
103
|
+
</div>
|
|
104
|
+
{:else if results.length === 0}
|
|
105
|
+
<div class="text-muted-foreground px-4 py-10 text-center text-sm">
|
|
106
|
+
No results for <span class="text-foreground font-medium">“{trimmed}”</span>.
|
|
107
|
+
</div>
|
|
108
|
+
{:else}
|
|
109
|
+
{#each results as result (result.path)}
|
|
110
|
+
<Command.LinkItem
|
|
111
|
+
href={result.path}
|
|
112
|
+
onSelect={() => select(result.path)}
|
|
113
|
+
class="group/result mb-0.5 flex items-center gap-3 rounded-lg px-2.5 py-2 aria-selected:bg-accent aria-selected:text-accent-foreground"
|
|
114
|
+
>
|
|
115
|
+
<span
|
|
116
|
+
class="border-border/60 bg-muted/40 text-muted-foreground group-aria-selected/result:border-accent-foreground/20 group-aria-selected/result:text-accent-foreground flex size-8 shrink-0 items-center justify-center rounded-md border"
|
|
117
|
+
>
|
|
118
|
+
<FileText class="size-4" />
|
|
119
|
+
</span>
|
|
120
|
+
|
|
121
|
+
<span class="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
122
|
+
<span class="flex items-center gap-2">
|
|
123
|
+
<span class="truncate font-medium">{result.title}</span>
|
|
124
|
+
{#if result.section}
|
|
125
|
+
<span
|
|
126
|
+
class="border-border/60 text-muted-foreground group-aria-selected/result:border-accent-foreground/20 group-aria-selected/result:text-accent-foreground/80 ml-auto shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-medium tracking-wide uppercase"
|
|
127
|
+
>
|
|
128
|
+
{result.section}
|
|
129
|
+
</span>
|
|
130
|
+
{/if}
|
|
131
|
+
</span>
|
|
132
|
+
{#if result.snippet}
|
|
133
|
+
<span
|
|
134
|
+
class="text-muted-foreground group-aria-selected/result:text-accent-foreground/80 line-clamp-1 text-xs"
|
|
135
|
+
>
|
|
136
|
+
{result.snippet}
|
|
137
|
+
</span>
|
|
138
|
+
{/if}
|
|
139
|
+
</span>
|
|
140
|
+
|
|
141
|
+
<CornerDownLeft
|
|
142
|
+
class="text-muted-foreground group-aria-selected/result:text-accent-foreground size-4 shrink-0 opacity-0 group-aria-selected/result:opacity-100"
|
|
143
|
+
/>
|
|
144
|
+
</Command.LinkItem>
|
|
145
|
+
{/each}
|
|
146
|
+
{/if}
|
|
147
|
+
</Command.List>
|
|
148
|
+
|
|
149
|
+
<div
|
|
150
|
+
class="border-border/50 text-muted-foreground -mx-1 flex items-center gap-4 border-t px-4 py-2 text-[11px]"
|
|
151
|
+
>
|
|
152
|
+
<span class="flex items-center gap-1.5">
|
|
153
|
+
<kbd class="border-border/60 bg-muted/40 rounded border px-1.5 py-0.5 font-sans">↑</kbd>
|
|
154
|
+
<kbd class="border-border/60 bg-muted/40 rounded border px-1.5 py-0.5 font-sans">↓</kbd>
|
|
155
|
+
to navigate
|
|
156
|
+
</span>
|
|
157
|
+
<span class="flex items-center gap-1.5">
|
|
158
|
+
<kbd class="border-border/60 bg-muted/40 rounded border px-1.5 py-0.5 font-sans">↵</kbd>
|
|
159
|
+
to open
|
|
160
|
+
</span>
|
|
161
|
+
<span class="ml-auto flex items-center gap-1.5">
|
|
162
|
+
<kbd class="border-border/60 bg-muted/40 rounded border px-1.5 py-0.5 font-sans">esc</kbd>
|
|
163
|
+
to close
|
|
164
|
+
</span>
|
|
165
|
+
</div>
|
|
166
|
+
</Command.Dialog>
|
|
167
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SearchDoc } from '../config.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Lazily provide the generated search records. Wired by the consumer so the
|
|
5
|
+
* index is code-split and only fetched when the palette first opens, e.g.
|
|
6
|
+
* `() => import('svelte-docsmith/search').then((m) => m.docs)`.
|
|
7
|
+
*/
|
|
8
|
+
load: () => Promise<SearchDoc[]>;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
};
|
|
11
|
+
declare const Search: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type Search = ReturnType<typeof Search>;
|
|
13
|
+
export default Search;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Accordion as AccordionPrimitive } from 'bits-ui';
|
|
2
|
-
declare const Accordion: import("svelte").Component<AccordionPrimitive.RootProps, {}, "
|
|
2
|
+
declare const Accordion: import("svelte").Component<AccordionPrimitive.RootProps, {}, "value" | "ref">;
|
|
3
3
|
type Accordion = ReturnType<typeof Accordion>;
|
|
4
4
|
export default Accordion;
|