svelora 2.2.0 → 3.0.1
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 +2 -2
- package/dist/CodeBlock/CodeBlock.svelte +83 -0
- package/dist/CodeBlock/CodeBlock.svelte.d.ts +5 -0
- package/dist/CodeBlock/code-block.types.d.ts +15 -0
- package/dist/CodeBlock/code-block.types.js +1 -0
- package/dist/CodeBlock/code-block.variants.d.ts +288 -0
- package/dist/CodeBlock/code-block.variants.js +69 -0
- package/dist/CodeBlock/index.d.ts +2 -0
- package/dist/CodeBlock/index.js +1 -0
- package/dist/Drawer/Drawer.svelte +13 -3
- package/dist/Editor/Editor.svelte +3 -0
- package/dist/Fonts/Fonts.svelte +54 -0
- package/dist/Fonts/Fonts.svelte.d.ts +5 -0
- package/dist/Fonts/fonts.d.ts +12 -0
- package/dist/Fonts/fonts.js +128 -0
- package/dist/Fonts/fonts.types.d.ts +40 -0
- package/dist/Fonts/fonts.types.js +1 -0
- package/dist/Fonts/index.d.ts +3 -0
- package/dist/Fonts/index.js +2 -0
- package/dist/config.d.ts +12 -1
- package/dist/config.js +9 -0
- package/dist/docs/code-block.d.ts +13 -0
- package/dist/docs/code-block.js +214 -0
- package/dist/docs/navigation.d.ts +27 -0
- package/dist/docs/navigation.js +491 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp/cursor.mcp.json +12 -0
- package/dist/mcp/install-template.mjs +55 -0
- package/dist/mcp/server.mjs +338 -0
- package/dist/mcp/svelora-docs.data.json +138 -0
- package/dist/theme.css +20 -1
- package/package.json +30 -9
package/README.md
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
|
-
<a href="https://svelora.vercel.app"><strong>Live Demo</strong></a> ·
|
|
20
|
-
<a href="https://svelora.vercel.app
|
|
19
|
+
<a href="https://svelora-ui.vercel.app/"><strong>Live Demo</strong></a> ·
|
|
20
|
+
<a href="https://svelora-ui.vercel.app//getting-started"><strong>Getting Started</strong></a> ·
|
|
21
21
|
<a href="https://github.com/asphum/svelora/blob/main/CHANGELOG.md"><strong>Changelog</strong></a>
|
|
22
22
|
</p>
|
|
23
23
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { CodeBlockProps } from './code-block.types.js'
|
|
3
|
+
|
|
4
|
+
export type Props = CodeBlockProps
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { getComponentConfig } from '../config.js'
|
|
9
|
+
import { codeBlockDefaults, codeBlockVariants } from './code-block.variants.js'
|
|
10
|
+
|
|
11
|
+
const config = getComponentConfig('codeBlock', codeBlockDefaults)
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
title = 'Code',
|
|
15
|
+
code = '',
|
|
16
|
+
copyText,
|
|
17
|
+
copyable = true,
|
|
18
|
+
html,
|
|
19
|
+
variant = config.defaultVariants.variant,
|
|
20
|
+
size = config.defaultVariants.size,
|
|
21
|
+
class: className,
|
|
22
|
+
ui,
|
|
23
|
+
children
|
|
24
|
+
}: Props = $props()
|
|
25
|
+
|
|
26
|
+
let copyLabel = $state('Copy')
|
|
27
|
+
|
|
28
|
+
const resolvedCopyText = $derived((copyText ?? code).trim())
|
|
29
|
+
const canCopy = $derived(copyable && resolvedCopyText.length > 0)
|
|
30
|
+
|
|
31
|
+
const classes = $derived.by(() => {
|
|
32
|
+
const slots = codeBlockVariants({ variant, size })
|
|
33
|
+
return {
|
|
34
|
+
root: slots.root({ class: [config.slots.root, className, ui?.root] }),
|
|
35
|
+
header: slots.header({ class: [config.slots.header, ui?.header] }),
|
|
36
|
+
title: slots.title({ class: [config.slots.title, ui?.title] }),
|
|
37
|
+
button: slots.button({ class: [config.slots.button, ui?.button] }),
|
|
38
|
+
body: slots.body({ class: [config.slots.body, ui?.body] })
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
function scheduleLabelReset(resetLabel: string): void {
|
|
43
|
+
window.setTimeout(() => {
|
|
44
|
+
copyLabel = resetLabel
|
|
45
|
+
}, 1200)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function handleCopy(): Promise<void> {
|
|
49
|
+
if (!canCopy) return
|
|
50
|
+
if (typeof navigator === 'undefined' || !navigator.clipboard) return
|
|
51
|
+
|
|
52
|
+
const resetLabel = copyLabel
|
|
53
|
+
try {
|
|
54
|
+
await navigator.clipboard.writeText(resolvedCopyText)
|
|
55
|
+
copyLabel = 'Copied'
|
|
56
|
+
} catch {
|
|
57
|
+
copyLabel = 'Failed'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
scheduleLabelReset(resetLabel)
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<div class={classes.root}>
|
|
65
|
+
<div class={classes.header}>
|
|
66
|
+
<p class={classes.title}>{title}</p>
|
|
67
|
+
<button type="button" class={classes.button} disabled={!canCopy} onclick={handleCopy}>
|
|
68
|
+
{copyLabel}
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div class={classes.body}>
|
|
73
|
+
{#if html}
|
|
74
|
+
{@html html}
|
|
75
|
+
{:else if children}
|
|
76
|
+
{@render children()}
|
|
77
|
+
{:else}
|
|
78
|
+
<pre class="shiki">
|
|
79
|
+
<code>{code}</code>
|
|
80
|
+
</pre>
|
|
81
|
+
{/if}
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
3
|
+
import type { CodeBlockVariantProps, CodeBlockSlots } from './code-block.variants.js';
|
|
4
|
+
export type CodeBlockProps = {
|
|
5
|
+
title?: string;
|
|
6
|
+
code?: string;
|
|
7
|
+
copyText?: string;
|
|
8
|
+
copyable?: boolean;
|
|
9
|
+
html?: string;
|
|
10
|
+
variant?: NonNullable<CodeBlockVariantProps['variant']>;
|
|
11
|
+
size?: NonNullable<CodeBlockVariantProps['size']>;
|
|
12
|
+
class?: ClassNameValue;
|
|
13
|
+
ui?: Partial<Record<CodeBlockSlots, ClassNameValue>>;
|
|
14
|
+
children?: Snippet;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
2
|
+
export declare const codeBlockVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
variant: {
|
|
4
|
+
outline: {
|
|
5
|
+
root: string;
|
|
6
|
+
header: string;
|
|
7
|
+
button: string;
|
|
8
|
+
};
|
|
9
|
+
soft: {
|
|
10
|
+
root: string;
|
|
11
|
+
header: string;
|
|
12
|
+
button: string;
|
|
13
|
+
};
|
|
14
|
+
subtle: {
|
|
15
|
+
root: string;
|
|
16
|
+
header: string;
|
|
17
|
+
button: string;
|
|
18
|
+
};
|
|
19
|
+
solid: {
|
|
20
|
+
root: string;
|
|
21
|
+
header: string;
|
|
22
|
+
button: string;
|
|
23
|
+
};
|
|
24
|
+
ghost: {
|
|
25
|
+
root: string;
|
|
26
|
+
header: string;
|
|
27
|
+
button: string;
|
|
28
|
+
};
|
|
29
|
+
none: {
|
|
30
|
+
root: string;
|
|
31
|
+
header: string;
|
|
32
|
+
button: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
size: {
|
|
36
|
+
sm: {
|
|
37
|
+
header: string;
|
|
38
|
+
button: string;
|
|
39
|
+
body: string;
|
|
40
|
+
};
|
|
41
|
+
md: {
|
|
42
|
+
header: string;
|
|
43
|
+
button: string;
|
|
44
|
+
body: string;
|
|
45
|
+
};
|
|
46
|
+
lg: {
|
|
47
|
+
header: string;
|
|
48
|
+
button: string;
|
|
49
|
+
body: string;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
}, {
|
|
53
|
+
root: string;
|
|
54
|
+
header: string;
|
|
55
|
+
title: string;
|
|
56
|
+
button: string;
|
|
57
|
+
body: string;
|
|
58
|
+
}, undefined, {
|
|
59
|
+
variant: {
|
|
60
|
+
outline: {
|
|
61
|
+
root: string;
|
|
62
|
+
header: string;
|
|
63
|
+
button: string;
|
|
64
|
+
};
|
|
65
|
+
soft: {
|
|
66
|
+
root: string;
|
|
67
|
+
header: string;
|
|
68
|
+
button: string;
|
|
69
|
+
};
|
|
70
|
+
subtle: {
|
|
71
|
+
root: string;
|
|
72
|
+
header: string;
|
|
73
|
+
button: string;
|
|
74
|
+
};
|
|
75
|
+
solid: {
|
|
76
|
+
root: string;
|
|
77
|
+
header: string;
|
|
78
|
+
button: string;
|
|
79
|
+
};
|
|
80
|
+
ghost: {
|
|
81
|
+
root: string;
|
|
82
|
+
header: string;
|
|
83
|
+
button: string;
|
|
84
|
+
};
|
|
85
|
+
none: {
|
|
86
|
+
root: string;
|
|
87
|
+
header: string;
|
|
88
|
+
button: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
size: {
|
|
92
|
+
sm: {
|
|
93
|
+
header: string;
|
|
94
|
+
button: string;
|
|
95
|
+
body: string;
|
|
96
|
+
};
|
|
97
|
+
md: {
|
|
98
|
+
header: string;
|
|
99
|
+
button: string;
|
|
100
|
+
body: string;
|
|
101
|
+
};
|
|
102
|
+
lg: {
|
|
103
|
+
header: string;
|
|
104
|
+
button: string;
|
|
105
|
+
body: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
}, {
|
|
109
|
+
root: string;
|
|
110
|
+
header: string;
|
|
111
|
+
title: string;
|
|
112
|
+
button: string;
|
|
113
|
+
body: string;
|
|
114
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
115
|
+
variant: {
|
|
116
|
+
outline: {
|
|
117
|
+
root: string;
|
|
118
|
+
header: string;
|
|
119
|
+
button: string;
|
|
120
|
+
};
|
|
121
|
+
soft: {
|
|
122
|
+
root: string;
|
|
123
|
+
header: string;
|
|
124
|
+
button: string;
|
|
125
|
+
};
|
|
126
|
+
subtle: {
|
|
127
|
+
root: string;
|
|
128
|
+
header: string;
|
|
129
|
+
button: string;
|
|
130
|
+
};
|
|
131
|
+
solid: {
|
|
132
|
+
root: string;
|
|
133
|
+
header: string;
|
|
134
|
+
button: string;
|
|
135
|
+
};
|
|
136
|
+
ghost: {
|
|
137
|
+
root: string;
|
|
138
|
+
header: string;
|
|
139
|
+
button: string;
|
|
140
|
+
};
|
|
141
|
+
none: {
|
|
142
|
+
root: string;
|
|
143
|
+
header: string;
|
|
144
|
+
button: string;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
size: {
|
|
148
|
+
sm: {
|
|
149
|
+
header: string;
|
|
150
|
+
button: string;
|
|
151
|
+
body: string;
|
|
152
|
+
};
|
|
153
|
+
md: {
|
|
154
|
+
header: string;
|
|
155
|
+
button: string;
|
|
156
|
+
body: string;
|
|
157
|
+
};
|
|
158
|
+
lg: {
|
|
159
|
+
header: string;
|
|
160
|
+
button: string;
|
|
161
|
+
body: string;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
}, {
|
|
165
|
+
root: string;
|
|
166
|
+
header: string;
|
|
167
|
+
title: string;
|
|
168
|
+
button: string;
|
|
169
|
+
body: string;
|
|
170
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
171
|
+
export type CodeBlockVariantProps = VariantProps<typeof codeBlockVariants>;
|
|
172
|
+
export type CodeBlockSlots = keyof ReturnType<typeof codeBlockVariants>;
|
|
173
|
+
export declare const codeBlockDefaults: {
|
|
174
|
+
defaultVariants: import("tailwind-variants").TVDefaultVariants<{
|
|
175
|
+
variant: {
|
|
176
|
+
outline: {
|
|
177
|
+
root: string;
|
|
178
|
+
header: string;
|
|
179
|
+
button: string;
|
|
180
|
+
};
|
|
181
|
+
soft: {
|
|
182
|
+
root: string;
|
|
183
|
+
header: string;
|
|
184
|
+
button: string;
|
|
185
|
+
};
|
|
186
|
+
subtle: {
|
|
187
|
+
root: string;
|
|
188
|
+
header: string;
|
|
189
|
+
button: string;
|
|
190
|
+
};
|
|
191
|
+
solid: {
|
|
192
|
+
root: string;
|
|
193
|
+
header: string;
|
|
194
|
+
button: string;
|
|
195
|
+
};
|
|
196
|
+
ghost: {
|
|
197
|
+
root: string;
|
|
198
|
+
header: string;
|
|
199
|
+
button: string;
|
|
200
|
+
};
|
|
201
|
+
none: {
|
|
202
|
+
root: string;
|
|
203
|
+
header: string;
|
|
204
|
+
button: string;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
size: {
|
|
208
|
+
sm: {
|
|
209
|
+
header: string;
|
|
210
|
+
button: string;
|
|
211
|
+
body: string;
|
|
212
|
+
};
|
|
213
|
+
md: {
|
|
214
|
+
header: string;
|
|
215
|
+
button: string;
|
|
216
|
+
body: string;
|
|
217
|
+
};
|
|
218
|
+
lg: {
|
|
219
|
+
header: string;
|
|
220
|
+
button: string;
|
|
221
|
+
body: string;
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
}, {
|
|
225
|
+
root: string;
|
|
226
|
+
header: string;
|
|
227
|
+
title: string;
|
|
228
|
+
button: string;
|
|
229
|
+
body: string;
|
|
230
|
+
}, {
|
|
231
|
+
variant: {
|
|
232
|
+
outline: {
|
|
233
|
+
root: string;
|
|
234
|
+
header: string;
|
|
235
|
+
button: string;
|
|
236
|
+
};
|
|
237
|
+
soft: {
|
|
238
|
+
root: string;
|
|
239
|
+
header: string;
|
|
240
|
+
button: string;
|
|
241
|
+
};
|
|
242
|
+
subtle: {
|
|
243
|
+
root: string;
|
|
244
|
+
header: string;
|
|
245
|
+
button: string;
|
|
246
|
+
};
|
|
247
|
+
solid: {
|
|
248
|
+
root: string;
|
|
249
|
+
header: string;
|
|
250
|
+
button: string;
|
|
251
|
+
};
|
|
252
|
+
ghost: {
|
|
253
|
+
root: string;
|
|
254
|
+
header: string;
|
|
255
|
+
button: string;
|
|
256
|
+
};
|
|
257
|
+
none: {
|
|
258
|
+
root: string;
|
|
259
|
+
header: string;
|
|
260
|
+
button: string;
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
size: {
|
|
264
|
+
sm: {
|
|
265
|
+
header: string;
|
|
266
|
+
button: string;
|
|
267
|
+
body: string;
|
|
268
|
+
};
|
|
269
|
+
md: {
|
|
270
|
+
header: string;
|
|
271
|
+
button: string;
|
|
272
|
+
body: string;
|
|
273
|
+
};
|
|
274
|
+
lg: {
|
|
275
|
+
header: string;
|
|
276
|
+
button: string;
|
|
277
|
+
body: string;
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
}, {
|
|
281
|
+
root: string;
|
|
282
|
+
header: string;
|
|
283
|
+
title: string;
|
|
284
|
+
button: string;
|
|
285
|
+
body: string;
|
|
286
|
+
}>;
|
|
287
|
+
slots: Partial<Record<CodeBlockSlots, string>>;
|
|
288
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const codeBlockVariants = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
root: 'mt-4 overflow-hidden rounded-2xl border border-outline-variant bg-surface-container',
|
|
5
|
+
header: 'flex items-center justify-between border-b border-outline-variant',
|
|
6
|
+
title: 'text-sm font-medium text-on-surface-variant',
|
|
7
|
+
button: 'rounded-md border border-outline-variant text-xs font-medium text-on-surface-variant transition-colors hover:bg-surface-container-highest disabled:cursor-not-allowed disabled:opacity-50',
|
|
8
|
+
body: 'bg-surface-container-highest [&_.shiki]:rounded-none [&_.shiki]:overflow-x-auto [&_.shiki]:m-0'
|
|
9
|
+
},
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
outline: {
|
|
13
|
+
root: 'border border-outline-variant bg-surface-container',
|
|
14
|
+
header: 'border-outline-variant',
|
|
15
|
+
button: 'border-outline-variant'
|
|
16
|
+
},
|
|
17
|
+
soft: {
|
|
18
|
+
root: 'border border-outline-variant/60 bg-surface-container/40',
|
|
19
|
+
header: 'border-outline-variant/60',
|
|
20
|
+
button: 'border-outline-variant/60'
|
|
21
|
+
},
|
|
22
|
+
subtle: {
|
|
23
|
+
root: 'border border-outline-variant/40 bg-surface-container/20',
|
|
24
|
+
header: 'border-outline-variant/40',
|
|
25
|
+
button: 'border-outline-variant/40'
|
|
26
|
+
},
|
|
27
|
+
solid: {
|
|
28
|
+
root: 'border border-outline-variant/60 bg-surface-container-high',
|
|
29
|
+
header: 'border-outline-variant/60',
|
|
30
|
+
button: 'border-outline-variant/60'
|
|
31
|
+
},
|
|
32
|
+
ghost: {
|
|
33
|
+
root: 'border border-transparent bg-transparent',
|
|
34
|
+
header: 'border-outline-variant/30',
|
|
35
|
+
button: 'border-outline-variant/30'
|
|
36
|
+
},
|
|
37
|
+
none: {
|
|
38
|
+
root: 'border-0 bg-transparent rounded-none',
|
|
39
|
+
header: 'border-0 px-0',
|
|
40
|
+
button: 'border-outline-variant/40'
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
size: {
|
|
44
|
+
sm: {
|
|
45
|
+
header: 'px-3 py-2',
|
|
46
|
+
button: 'px-2 py-1',
|
|
47
|
+
body: '[&_.shiki]:p-3 [&_.shiki]:text-xs [&_.shiki]:leading-5'
|
|
48
|
+
},
|
|
49
|
+
md: {
|
|
50
|
+
header: 'px-4 py-3',
|
|
51
|
+
button: 'px-2.5 py-1',
|
|
52
|
+
body: '[&_.shiki]:p-4 [&_.shiki]:text-sm [&_.shiki]:leading-6'
|
|
53
|
+
},
|
|
54
|
+
lg: {
|
|
55
|
+
header: 'px-5 py-4',
|
|
56
|
+
button: 'px-3 py-1.5',
|
|
57
|
+
body: '[&_.shiki]:p-5 [&_.shiki]:text-sm [&_.shiki]:leading-6'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
defaultVariants: {
|
|
62
|
+
variant: 'outline',
|
|
63
|
+
size: 'md'
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
export const codeBlockDefaults = {
|
|
67
|
+
defaultVariants: codeBlockVariants.defaultVariants,
|
|
68
|
+
slots: {}
|
|
69
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CodeBlock } from './CodeBlock.svelte';
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
const rootProps = $derived.by(() => {
|
|
84
|
-
const base = {
|
|
84
|
+
const base: Record<string, unknown> = {
|
|
85
85
|
...rest,
|
|
86
86
|
open,
|
|
87
87
|
onOpenChange: handleOpenChange,
|
|
@@ -99,6 +99,9 @@
|
|
|
99
99
|
onRelease,
|
|
100
100
|
onClose
|
|
101
101
|
}
|
|
102
|
+
if (rest.container) {
|
|
103
|
+
base.container = rest.container
|
|
104
|
+
}
|
|
102
105
|
if (snapPoints && fadeFromIndex !== null) {
|
|
103
106
|
return { ...base, snapPoints, fadeFromIndex }
|
|
104
107
|
}
|
|
@@ -182,9 +185,16 @@
|
|
|
182
185
|
bits-ui v0 internally, which is incompatible with Svelte 5 snippets
|
|
183
186
|
and yields an empty <button> in the DOM. We pass an `onclick` handler
|
|
184
187
|
to the user-supplied trigger snippet so the user's element opens the
|
|
185
|
-
drawer when activated
|
|
188
|
+
drawer when activated, and we manually expose `data-state` so callers
|
|
189
|
+
can style/assert the trigger element.
|
|
186
190
|
-->
|
|
187
|
-
{@render children({
|
|
191
|
+
{@render children({
|
|
192
|
+
props: {
|
|
193
|
+
type: 'button',
|
|
194
|
+
onclick: () => (open = true),
|
|
195
|
+
'data-state': open ? 'open' : 'closed'
|
|
196
|
+
}
|
|
197
|
+
})}
|
|
188
198
|
{/if}
|
|
189
199
|
|
|
190
200
|
{#if portal}
|
|
@@ -467,6 +467,9 @@ export type Props = EditorProps;
|
|
|
467
467
|
try {
|
|
468
468
|
const url = await onImageUpload(file)
|
|
469
469
|
if (!isSafeImageSrc(url)) {
|
|
470
|
+
console.warn(
|
|
471
|
+
`[svelora] Blocked unsafe image src returned by onImageUpload: ${url}`
|
|
472
|
+
)
|
|
470
473
|
return
|
|
471
474
|
}
|
|
472
475
|
editor.chain().focus().setImage({ src: url }).run()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { FontsProps } from './fonts.types.js'
|
|
3
|
+
|
|
4
|
+
export type Props = FontsProps
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { getConfig } from '../config.js'
|
|
9
|
+
import {
|
|
10
|
+
buildFontVariablesCss,
|
|
11
|
+
buildGoogleFontsUrl,
|
|
12
|
+
buildLocalFontFaceCss,
|
|
13
|
+
fontsDefaults,
|
|
14
|
+
resolveFontsOptions
|
|
15
|
+
} from './fonts.js'
|
|
16
|
+
|
|
17
|
+
const globalConfig = getConfig()
|
|
18
|
+
const config = resolveFontsOptions(globalConfig.fonts)
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
fonts,
|
|
22
|
+
families,
|
|
23
|
+
display,
|
|
24
|
+
preconnect
|
|
25
|
+
}: Props = $props()
|
|
26
|
+
|
|
27
|
+
const resolvedFamilies = $derived(families ?? fonts ?? (config === false ? [] : config.families ?? []))
|
|
28
|
+
const resolvedDisplay = $derived(display ?? (config === false ? fontsDefaults.display : config.display))
|
|
29
|
+
const resolvedPreconnect = $derived(
|
|
30
|
+
preconnect ?? (config === false ? fontsDefaults.preconnect : config.preconnect)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
const href = $derived(buildGoogleFontsUrl(resolvedFamilies, resolvedDisplay))
|
|
34
|
+
const localFontFaceCss = $derived(buildLocalFontFaceCss(resolvedFamilies, resolvedDisplay))
|
|
35
|
+
const variableCss = $derived(buildFontVariablesCss(resolvedFamilies))
|
|
36
|
+
const inlineCss = $derived([localFontFaceCss, variableCss].filter((value) => value.length > 0).join('\n\n'))
|
|
37
|
+
const hasFonts = $derived(href.length > 0 || inlineCss.length > 0)
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<svelte:head>
|
|
41
|
+
{#if hasFonts}
|
|
42
|
+
{#if resolvedPreconnect && href}
|
|
43
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
44
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
|
|
45
|
+
{/if}
|
|
46
|
+
{#if href}
|
|
47
|
+
<link rel="stylesheet" href={href} />
|
|
48
|
+
{/if}
|
|
49
|
+
{#if inlineCss}
|
|
50
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
51
|
+
{@html `<style>${inlineCss}</style>`}
|
|
52
|
+
{/if}
|
|
53
|
+
{/if}
|
|
54
|
+
</svelte:head>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FontDefinition, GoogleFontDisplay, FontsConfig, FontsOptions } from './fonts.types.js';
|
|
2
|
+
export declare const defaultFontFamilies: FontDefinition[];
|
|
3
|
+
export declare const fontsDefaults: {
|
|
4
|
+
families: FontDefinition[];
|
|
5
|
+
display: GoogleFontDisplay;
|
|
6
|
+
preconnect: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare function buildGoogleFontsUrl(fonts: FontDefinition[], display?: GoogleFontDisplay): string;
|
|
9
|
+
export declare function buildFontFamily(font: FontDefinition): string;
|
|
10
|
+
export declare function buildLocalFontFaceCss(fonts: FontDefinition[], defaultDisplay?: GoogleFontDisplay): string;
|
|
11
|
+
export declare function buildFontVariablesCss(fonts: FontDefinition[]): string;
|
|
12
|
+
export declare function resolveFontsOptions(config?: FontsConfig): FontsOptions | false;
|