@refrakt-md/lumina 0.4.0 → 0.5.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/base.css +18 -0
- package/contracts/structures.json +1360 -3
- package/dist/config.d.ts +2 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -229
- package/dist/config.js.map +1 -1
- package/dist/icons.d.ts +3 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +86 -0
- package/dist/icons.js.map +1 -0
- package/dist/transform.d.ts +2 -0
- package/dist/transform.d.ts.map +1 -1
- package/dist/transform.js +2 -0
- package/dist/transform.js.map +1 -1
- package/index.css +12 -0
- package/package.json +18 -11
- package/styles/elements/blockquote.css +8 -4
- package/styles/elements/code.css +40 -0
- package/styles/global.css +0 -7
- package/styles/layouts/blog.css +267 -0
- package/styles/layouts/default.css +26 -6
- package/styles/layouts/docs.css +84 -18
- package/styles/layouts/mobile.css +84 -0
- package/styles/runes/bento.css +2 -0
- package/styles/runes/codegroup.css +7 -2
- package/styles/runes/design-context.css +25 -0
- package/styles/runes/feature.css +30 -14
- package/styles/runes/form.css +1 -2
- package/styles/runes/grid.css +25 -7
- package/styles/runes/hero.css +15 -0
- package/styles/runes/map.css +113 -0
- package/styles/runes/palette.css +91 -0
- package/styles/runes/preview.css +188 -0
- package/styles/runes/sandbox.css +23 -0
- package/styles/runes/spacing.css +110 -0
- package/styles/runes/steps.css +21 -3
- package/styles/runes/swatch.css +28 -0
- package/styles/runes/symbol.css +164 -0
- package/styles/runes/tabs.css +6 -0
- package/styles/runes/testimonial.css +2 -3
- package/styles/runes/timeline.css +43 -24
- package/styles/runes/typography.css +104 -0
- package/svelte/elements.ts +1 -0
- package/{sveltekit → svelte}/index.ts +0 -8
- package/svelte/layouts/BlogLayout.svelte +173 -0
- package/svelte/layouts/DefaultLayout.svelte +67 -0
- package/svelte/layouts/DocsLayout.svelte +155 -0
- package/{sveltekit → svelte}/manifest.json +1 -1
- package/svelte/registry.ts +2 -0
- package/svelte/tokens.css +6 -0
- package/dist/lib/engine.d.ts +0 -13
- package/dist/lib/engine.d.ts.map +0 -1
- package/dist/lib/engine.js +0 -218
- package/dist/lib/engine.js.map +0 -1
- package/dist/lib/helpers.d.ts +0 -14
- package/dist/lib/helpers.d.ts.map +0 -1
- package/dist/lib/helpers.js +0 -26
- package/dist/lib/helpers.js.map +0 -1
- package/dist/lib/types.d.ts +0 -74
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/types.js +0 -2
- package/dist/lib/types.js.map +0 -1
- package/sveltekit/components/Accordion.svelte +0 -26
- package/sveltekit/components/Bento.svelte +0 -50
- package/sveltekit/components/Chart.svelte +0 -121
- package/sveltekit/components/CodeGroup.svelte +0 -88
- package/sveltekit/components/Comparison.svelte +0 -209
- package/sveltekit/components/DataTable.svelte +0 -154
- package/sveltekit/components/Details.svelte +0 -23
- package/sveltekit/components/Diagram.svelte +0 -45
- package/sveltekit/components/Embed.svelte +0 -36
- package/sveltekit/components/Form.svelte +0 -194
- package/sveltekit/components/Grid.svelte +0 -42
- package/sveltekit/components/Nav.svelte +0 -62
- package/sveltekit/components/Pricing.svelte +0 -20
- package/sveltekit/components/Reveal.svelte +0 -62
- package/sveltekit/components/Storyboard.svelte +0 -41
- package/sveltekit/components/Tabs.svelte +0 -75
- package/sveltekit/components/Testimonial.svelte +0 -26
- package/sveltekit/elements/Blockquote.svelte +0 -37
- package/sveltekit/elements/Pre.svelte +0 -77
- package/sveltekit/elements/Table.svelte +0 -40
- package/sveltekit/elements.ts +0 -11
- package/sveltekit/layouts/BlogLayout.svelte +0 -382
- package/sveltekit/layouts/DefaultLayout.svelte +0 -70
- package/sveltekit/layouts/DocsLayout.svelte +0 -133
- package/sveltekit/registry.ts +0 -59
- package/sveltekit/tokens.css +0 -71
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from 'svelte';
|
|
3
|
-
import type { Snippet } from 'svelte';
|
|
4
|
-
import type { SerializedTag } from '@refrakt-md/svelte';
|
|
5
|
-
|
|
6
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
7
|
-
|
|
8
|
-
const language = tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'language')?.attributes?.content || 'mermaid';
|
|
9
|
-
const title = tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'title')?.attributes?.content || '';
|
|
10
|
-
const source = tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.['data-name'] === 'source')?.attributes?.content || '';
|
|
11
|
-
|
|
12
|
-
let container: HTMLDivElement;
|
|
13
|
-
let rendered = $state(false);
|
|
14
|
-
|
|
15
|
-
onMount(async () => {
|
|
16
|
-
if (language === 'mermaid' && source) {
|
|
17
|
-
try {
|
|
18
|
-
const cdn = 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
19
|
-
const mermaid = (await import(/* @vite-ignore */ cdn)).default;
|
|
20
|
-
mermaid.initialize({ startOnLoad: false, theme: 'default' });
|
|
21
|
-
const { svg } = await mermaid.render('mermaid-' + Math.random().toString(36).slice(2), source);
|
|
22
|
-
container.innerHTML = svg;
|
|
23
|
-
rendered = true;
|
|
24
|
-
} catch (e) {
|
|
25
|
-
container.textContent = source;
|
|
26
|
-
}
|
|
27
|
-
} else if (language === 'ascii' && source) {
|
|
28
|
-
container.textContent = source;
|
|
29
|
-
container.style.fontFamily = 'var(--rf-font-mono)';
|
|
30
|
-
container.style.whiteSpace = 'pre';
|
|
31
|
-
rendered = true;
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
<figure class="rf-diagram" typeof="Diagram">
|
|
37
|
-
{#if title}
|
|
38
|
-
<figcaption class="rf-diagram__title">{title}</figcaption>
|
|
39
|
-
{/if}
|
|
40
|
-
<div class="rf-diagram__container" bind:this={container}>
|
|
41
|
-
{#if !rendered}
|
|
42
|
-
<pre class="rf-diagram__source"><code>{source}</code></pre>
|
|
43
|
-
{/if}
|
|
44
|
-
</div>
|
|
45
|
-
</figure>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { SerializedTag } from '@refrakt-md/svelte';
|
|
3
|
-
import type { Snippet } from 'svelte';
|
|
4
|
-
|
|
5
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
6
|
-
|
|
7
|
-
const getMeta = (prop: string) => tag.children
|
|
8
|
-
.find((c: any) => c?.name === 'meta' && c?.attributes?.property === prop)
|
|
9
|
-
?.attributes?.content;
|
|
10
|
-
|
|
11
|
-
const embedUrl = getMeta('embedUrl') || getMeta('url') || '';
|
|
12
|
-
const title = getMeta('title') || 'Embedded content';
|
|
13
|
-
const aspect = getMeta('aspect') || '16:9';
|
|
14
|
-
const provider = getMeta('provider') || '';
|
|
15
|
-
|
|
16
|
-
const [w, h] = aspect.split(':').map(Number);
|
|
17
|
-
const paddingPercent = h && w ? (h / w) * 100 : 56.25;
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<figure class="rf-embed" data-provider={provider || undefined}>
|
|
21
|
-
{#if embedUrl}
|
|
22
|
-
<div class="rf-embed__wrapper" style="padding-bottom: {paddingPercent}%">
|
|
23
|
-
<iframe
|
|
24
|
-
src={embedUrl}
|
|
25
|
-
{title}
|
|
26
|
-
frameborder="0"
|
|
27
|
-
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
28
|
-
allowfullscreen
|
|
29
|
-
loading="lazy"
|
|
30
|
-
></iframe>
|
|
31
|
-
</div>
|
|
32
|
-
{/if}
|
|
33
|
-
<div class="rf-embed__fallback">
|
|
34
|
-
{@render children()}
|
|
35
|
-
</div>
|
|
36
|
-
</figure>
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import type { SerializedTag } from '@refrakt-md/svelte';
|
|
4
|
-
|
|
5
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
6
|
-
|
|
7
|
-
const isForm = tag.attributes.typeof === 'Form';
|
|
8
|
-
|
|
9
|
-
// Form-level properties
|
|
10
|
-
const action = isForm
|
|
11
|
-
? tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'action')?.attributes?.content || ''
|
|
12
|
-
: '';
|
|
13
|
-
const method = isForm
|
|
14
|
-
? tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'method')?.attributes?.content || 'POST'
|
|
15
|
-
: 'POST';
|
|
16
|
-
const success = isForm
|
|
17
|
-
? tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'success')?.attributes?.content || ''
|
|
18
|
-
: '';
|
|
19
|
-
const errorMsg = isForm
|
|
20
|
-
? tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'error')?.attributes?.content || ''
|
|
21
|
-
: '';
|
|
22
|
-
const formStyle = isForm
|
|
23
|
-
? tag.attributes['data-style'] || 'stacked'
|
|
24
|
-
: 'stacked';
|
|
25
|
-
const honeypot = isForm
|
|
26
|
-
? tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'honeypot')?.attributes?.content !== 'false'
|
|
27
|
-
: true;
|
|
28
|
-
|
|
29
|
-
// FormField properties
|
|
30
|
-
const fieldName = !isForm
|
|
31
|
-
? tag.children.find((c: any) => c?.name === 'span' && c?.attributes?.property === 'name')?.children?.[0] || ''
|
|
32
|
-
: '';
|
|
33
|
-
const fieldType = !isForm
|
|
34
|
-
? tag.attributes['data-field-type'] || 'text'
|
|
35
|
-
: '';
|
|
36
|
-
const required = !isForm
|
|
37
|
-
? tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'required')?.attributes?.content === 'true'
|
|
38
|
-
: false;
|
|
39
|
-
const placeholder = !isForm
|
|
40
|
-
? tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'placeholder')?.attributes?.content || ''
|
|
41
|
-
: '';
|
|
42
|
-
const options = !isForm
|
|
43
|
-
? (tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'options')?.attributes?.content || '')
|
|
44
|
-
.split(',')
|
|
45
|
-
.map((o: string) => o.trim())
|
|
46
|
-
.filter(Boolean)
|
|
47
|
-
: [];
|
|
48
|
-
|
|
49
|
-
const fieldId = !isForm ? `field-${fieldName.toLowerCase().replace(/\s+/g, '-')}` : '';
|
|
50
|
-
|
|
51
|
-
// Form submission state
|
|
52
|
-
let status = $state<'idle' | 'submitting' | 'success' | 'error'>('idle');
|
|
53
|
-
let statusMessage = $state('');
|
|
54
|
-
|
|
55
|
-
async function handleSubmit(e: SubmitEvent) {
|
|
56
|
-
e.preventDefault();
|
|
57
|
-
if (!action) return;
|
|
58
|
-
|
|
59
|
-
status = 'submitting';
|
|
60
|
-
const formData = new FormData(e.target as HTMLFormElement);
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
const response = await fetch(action, {
|
|
64
|
-
method: method,
|
|
65
|
-
body: formData,
|
|
66
|
-
headers: { 'Accept': 'application/json' },
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
if (response.ok) {
|
|
70
|
-
status = 'success';
|
|
71
|
-
statusMessage = success || 'Form submitted successfully.';
|
|
72
|
-
(e.target as HTMLFormElement).reset();
|
|
73
|
-
} else {
|
|
74
|
-
status = 'error';
|
|
75
|
-
statusMessage = errorMsg || 'Something went wrong. Please try again.';
|
|
76
|
-
}
|
|
77
|
-
} catch {
|
|
78
|
-
status = 'error';
|
|
79
|
-
statusMessage = errorMsg || 'Something went wrong. Please try again.';
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
</script>
|
|
83
|
-
|
|
84
|
-
{#if isForm}
|
|
85
|
-
<form
|
|
86
|
-
class="rf-form {formStyle !== 'stacked' ? `rf-form--${formStyle}` : ''}"
|
|
87
|
-
action={action}
|
|
88
|
-
method={method}
|
|
89
|
-
onsubmit={handleSubmit}
|
|
90
|
-
>
|
|
91
|
-
{#if honeypot}
|
|
92
|
-
<div class="rf-form__hp" aria-hidden="true">
|
|
93
|
-
<input type="text" name="_gotcha" autocomplete="off" tabindex={-1} />
|
|
94
|
-
</div>
|
|
95
|
-
{/if}
|
|
96
|
-
{@render children()}
|
|
97
|
-
{#if status === 'submitting'}
|
|
98
|
-
<div class="rf-form__status rf-form__status--submitting" role="status">Submitting...</div>
|
|
99
|
-
{:else if status === 'success'}
|
|
100
|
-
<div class="rf-form__status rf-form__status--success" role="alert">{statusMessage}</div>
|
|
101
|
-
{:else if status === 'error'}
|
|
102
|
-
<div class="rf-form__status rf-form__status--error" role="alert">{statusMessage}</div>
|
|
103
|
-
{/if}
|
|
104
|
-
</form>
|
|
105
|
-
{:else if fieldType === 'group'}
|
|
106
|
-
<fieldset class="rf-form-fieldset">
|
|
107
|
-
<legend>{fieldName}</legend>
|
|
108
|
-
{@render children()}
|
|
109
|
-
</fieldset>
|
|
110
|
-
{:else if fieldType === 'submit'}
|
|
111
|
-
<button type="submit" class="rf-form__submit">{fieldName}</button>
|
|
112
|
-
{:else if fieldType === 'separator'}
|
|
113
|
-
<hr class="rf-form__separator" />
|
|
114
|
-
{:else if fieldType === 'help'}
|
|
115
|
-
<p class="rf-form__help">{fieldName}</p>
|
|
116
|
-
{:else if fieldType === 'description'}
|
|
117
|
-
<p class="rf-form__text">{fieldName}</p>
|
|
118
|
-
{:else if fieldType === 'textarea'}
|
|
119
|
-
<div class="rf-form-field">
|
|
120
|
-
<label for={fieldId}>
|
|
121
|
-
{fieldName}
|
|
122
|
-
{#if required}<span class="rf-form-field__required" aria-hidden="true">*</span>{/if}
|
|
123
|
-
</label>
|
|
124
|
-
<textarea
|
|
125
|
-
id={fieldId}
|
|
126
|
-
name={fieldId}
|
|
127
|
-
placeholder={placeholder}
|
|
128
|
-
required={required}
|
|
129
|
-
rows={4}
|
|
130
|
-
></textarea>
|
|
131
|
-
</div>
|
|
132
|
-
{:else if fieldType === 'select'}
|
|
133
|
-
<div class="rf-form-field">
|
|
134
|
-
<label for={fieldId}>
|
|
135
|
-
{fieldName}
|
|
136
|
-
{#if required}<span class="rf-form-field__required" aria-hidden="true">*</span>{/if}
|
|
137
|
-
</label>
|
|
138
|
-
<select id={fieldId} name={fieldId} required={required}>
|
|
139
|
-
<option value="" disabled selected>Select an option</option>
|
|
140
|
-
{#each options as option}
|
|
141
|
-
<option value={option}>{option}</option>
|
|
142
|
-
{/each}
|
|
143
|
-
</select>
|
|
144
|
-
</div>
|
|
145
|
-
{:else if fieldType === 'radio'}
|
|
146
|
-
<fieldset class="rf-form-field rf-form-choice-group">
|
|
147
|
-
<legend>
|
|
148
|
-
{fieldName}
|
|
149
|
-
{#if required}<span class="rf-form-field__required" aria-hidden="true">*</span>{/if}
|
|
150
|
-
</legend>
|
|
151
|
-
{#each options as option, i}
|
|
152
|
-
<label class="rf-form-choice">
|
|
153
|
-
<input
|
|
154
|
-
type="radio"
|
|
155
|
-
name={fieldId}
|
|
156
|
-
value={option}
|
|
157
|
-
required={required && i === 0}
|
|
158
|
-
/>
|
|
159
|
-
<span>{option}</span>
|
|
160
|
-
</label>
|
|
161
|
-
{/each}
|
|
162
|
-
</fieldset>
|
|
163
|
-
{:else if fieldType === 'checkbox'}
|
|
164
|
-
<fieldset class="rf-form-field rf-form-choice-group">
|
|
165
|
-
<legend>
|
|
166
|
-
{fieldName}
|
|
167
|
-
{#if required}<span class="rf-form-field__required" aria-hidden="true">*</span>{/if}
|
|
168
|
-
</legend>
|
|
169
|
-
{#each options as option}
|
|
170
|
-
<label class="rf-form-choice">
|
|
171
|
-
<input
|
|
172
|
-
type="checkbox"
|
|
173
|
-
name={fieldId}
|
|
174
|
-
value={option}
|
|
175
|
-
/>
|
|
176
|
-
<span>{option}</span>
|
|
177
|
-
</label>
|
|
178
|
-
{/each}
|
|
179
|
-
</fieldset>
|
|
180
|
-
{:else}
|
|
181
|
-
<div class="rf-form-field">
|
|
182
|
-
<label for={fieldId}>
|
|
183
|
-
{fieldName}
|
|
184
|
-
{#if required}<span class="rf-form-field__required" aria-hidden="true">*</span>{/if}
|
|
185
|
-
</label>
|
|
186
|
-
<input
|
|
187
|
-
type={fieldType}
|
|
188
|
-
id={fieldId}
|
|
189
|
-
name={fieldId}
|
|
190
|
-
placeholder={placeholder}
|
|
191
|
-
required={required}
|
|
192
|
-
/>
|
|
193
|
-
</div>
|
|
194
|
-
{/if}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { SerializedTag, RendererNode } from '@refrakt-md/svelte';
|
|
3
|
-
import { Renderer } from '@refrakt-md/svelte';
|
|
4
|
-
import type { Snippet } from 'svelte';
|
|
5
|
-
|
|
6
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
7
|
-
|
|
8
|
-
function isTag(n: RendererNode): n is SerializedTag {
|
|
9
|
-
return n !== null && typeof n === 'object' && !Array.isArray(n) && (n as any).$$mdtype === 'Tag';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const layoutDiv = $derived(tag.children.find(
|
|
13
|
-
(c): c is SerializedTag => isTag(c) && c.attributes?.['data-layout'] === 'grid'
|
|
14
|
-
));
|
|
15
|
-
const columns = $derived(layoutDiv?.attributes?.['data-columns']);
|
|
16
|
-
const flow = $derived(layoutDiv?.attributes?.['data-flow']);
|
|
17
|
-
const gridItems = $derived(layoutDiv?.children?.filter((c): c is SerializedTag => isTag(c)) ?? []);
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
{#if gridItems.length > 0}
|
|
21
|
-
<div
|
|
22
|
-
class="rf-grid"
|
|
23
|
-
style:grid-template-columns={columns ? `repeat(${columns}, 1fr)` : undefined}
|
|
24
|
-
style:grid-auto-flow={flow || undefined}
|
|
25
|
-
>
|
|
26
|
-
{#each gridItems as item}
|
|
27
|
-
{@const colspan = Number(item.attributes?.['data-colspan']) || 1}
|
|
28
|
-
{@const rowspan = Number(item.attributes?.['data-rowspan']) || 1}
|
|
29
|
-
<div
|
|
30
|
-
class="rf-grid__item"
|
|
31
|
-
style:grid-column={colspan > 1 ? `span ${colspan}` : undefined}
|
|
32
|
-
style:grid-row={rowspan > 1 ? `span ${rowspan}` : undefined}
|
|
33
|
-
>
|
|
34
|
-
<Renderer node={item.children} />
|
|
35
|
-
</div>
|
|
36
|
-
{/each}
|
|
37
|
-
</div>
|
|
38
|
-
{:else}
|
|
39
|
-
<div class="rf-grid">
|
|
40
|
-
{@render children()}
|
|
41
|
-
</div>
|
|
42
|
-
{/if}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { SerializedTag, RendererNode } from '@refrakt-md/svelte';
|
|
3
|
-
import type { Snippet } from 'svelte';
|
|
4
|
-
import { getContext } from 'svelte';
|
|
5
|
-
import { page } from '$app/state';
|
|
6
|
-
|
|
7
|
-
interface PageEntry {
|
|
8
|
-
url: string;
|
|
9
|
-
title: string;
|
|
10
|
-
draft: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
14
|
-
const typeName = $derived(tag.attributes.typeof);
|
|
15
|
-
const pages = getContext<PageEntry[]>('pages');
|
|
16
|
-
|
|
17
|
-
function getSlug(tag: SerializedTag): string | null {
|
|
18
|
-
for (const child of tag.children) {
|
|
19
|
-
if (isTag(child) && child.name === 'span' && child.attributes.property === 'slug') {
|
|
20
|
-
return getTextContent(child);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function isTag(node: RendererNode): node is SerializedTag {
|
|
27
|
-
return node !== null && typeof node === 'object' && !Array.isArray(node) && (node as any).$$mdtype === 'Tag';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function getTextContent(node: RendererNode): string {
|
|
31
|
-
if (typeof node === 'string') return node;
|
|
32
|
-
if (typeof node === 'number') return String(node);
|
|
33
|
-
if (isTag(node)) return node.children.map(getTextContent).join('');
|
|
34
|
-
if (Array.isArray(node)) return node.map(getTextContent).join('');
|
|
35
|
-
return '';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function resolvePage(slug: string): PageEntry | undefined {
|
|
39
|
-
return pages?.find(p => p.url.endsWith('/' + slug) || p.url === '/' + slug);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const slug = $derived(typeName === 'NavItem' ? getSlug(tag) : null);
|
|
43
|
-
const linkedPage = $derived(slug ? resolvePage(slug) : null);
|
|
44
|
-
</script>
|
|
45
|
-
|
|
46
|
-
{#if typeName === 'Nav'}
|
|
47
|
-
<nav class="rf-nav">
|
|
48
|
-
{@render children()}
|
|
49
|
-
</nav>
|
|
50
|
-
{:else if typeName === 'NavGroup'}
|
|
51
|
-
<div class="rf-nav-group">
|
|
52
|
-
{@render children()}
|
|
53
|
-
</div>
|
|
54
|
-
{:else if typeName === 'NavItem' && linkedPage}
|
|
55
|
-
<a href={linkedPage.url} class="rf-nav-item__link" class:rf-nav-item__link--active={page.url.pathname === linkedPage.url}>
|
|
56
|
-
{linkedPage.title}
|
|
57
|
-
</a>
|
|
58
|
-
{:else}
|
|
59
|
-
<div class="rf-nav-item">
|
|
60
|
-
{@render children()}
|
|
61
|
-
</div>
|
|
62
|
-
{/if}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { SerializedTag } from '@refrakt-md/svelte';
|
|
3
|
-
import type { Snippet } from 'svelte';
|
|
4
|
-
|
|
5
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
6
|
-
|
|
7
|
-
const typeName = tag.attributes.typeof;
|
|
8
|
-
const isTier = typeName === 'Tier' || typeName === 'FeaturedTier';
|
|
9
|
-
const isFeatured = typeName === 'FeaturedTier';
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
{#if typeName === 'Pricing'}
|
|
13
|
-
<section class="rf-pricing">
|
|
14
|
-
{@render children()}
|
|
15
|
-
</section>
|
|
16
|
-
{:else if isTier}
|
|
17
|
-
<li class="rf-tier {isFeatured ? 'rf-tier--featured' : ''}">
|
|
18
|
-
{@render children()}
|
|
19
|
-
</li>
|
|
20
|
-
{/if}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import type { SerializedTag } from '@refrakt-md/svelte';
|
|
4
|
-
import { Renderer } from '@refrakt-md/svelte';
|
|
5
|
-
|
|
6
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
7
|
-
|
|
8
|
-
const isGroup = tag.attributes.typeof === 'Reveal';
|
|
9
|
-
|
|
10
|
-
const stepName = !isGroup
|
|
11
|
-
? tag.children.find((c: any) => c?.name === 'span' && c?.attributes?.property === 'name')?.children?.[0] || ''
|
|
12
|
-
: '';
|
|
13
|
-
|
|
14
|
-
const mode = isGroup
|
|
15
|
-
? tag.children.find((c: any) => c?.name === 'meta')?.attributes?.content || 'click'
|
|
16
|
-
: 'click';
|
|
17
|
-
|
|
18
|
-
const stepsDiv = isGroup
|
|
19
|
-
? tag.children.find((c: any) => c?.name === 'div' && c?.attributes?.['data-name'] === 'steps')
|
|
20
|
-
: null;
|
|
21
|
-
|
|
22
|
-
const totalSteps = isGroup && stepsDiv
|
|
23
|
-
? (stepsDiv as any).children?.filter((c: any) => c?.attributes?.typeof === 'RevealStep')?.length ?? 0
|
|
24
|
-
: 0;
|
|
25
|
-
|
|
26
|
-
let visibleCount = $state(1);
|
|
27
|
-
</script>
|
|
28
|
-
|
|
29
|
-
{#if isGroup}
|
|
30
|
-
<section class="rf-reveal">
|
|
31
|
-
{#if stepsDiv}
|
|
32
|
-
<div class="rf-reveal__steps">
|
|
33
|
-
{#each (stepsDiv as any).children?.filter((c: any) => c?.attributes?.typeof === 'RevealStep') ?? [] as step, i}
|
|
34
|
-
<div class="rf-reveal-step {i < visibleCount ? 'rf-reveal-step--visible' : 'rf-reveal-step--hidden'}">
|
|
35
|
-
<Renderer node={step} />
|
|
36
|
-
</div>
|
|
37
|
-
{/each}
|
|
38
|
-
</div>
|
|
39
|
-
{:else}
|
|
40
|
-
{@render children()}
|
|
41
|
-
{/if}
|
|
42
|
-
{#if mode === 'click' && visibleCount < totalSteps}
|
|
43
|
-
<button class="rf-reveal__next" onclick={() => visibleCount++}>
|
|
44
|
-
Continue
|
|
45
|
-
</button>
|
|
46
|
-
{/if}
|
|
47
|
-
{#if mode === 'click' && visibleCount >= totalSteps && totalSteps > 1}
|
|
48
|
-
<button class="rf-reveal__reset" onclick={() => visibleCount = 1}>
|
|
49
|
-
Start over
|
|
50
|
-
</button>
|
|
51
|
-
{/if}
|
|
52
|
-
</section>
|
|
53
|
-
{:else}
|
|
54
|
-
<div class="rf-reveal-step__content">
|
|
55
|
-
{#if stepName}
|
|
56
|
-
<h3 class="rf-reveal-step__title">{stepName}</h3>
|
|
57
|
-
{/if}
|
|
58
|
-
<div class="rf-reveal-step__body">
|
|
59
|
-
{@render children()}
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
{/if}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import type { SerializedTag, RendererNode } from '@refrakt-md/svelte';
|
|
4
|
-
import { Renderer } from '@refrakt-md/svelte';
|
|
5
|
-
|
|
6
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
7
|
-
|
|
8
|
-
function isTag(n: RendererNode): n is SerializedTag {
|
|
9
|
-
return n !== null && typeof n === 'object' && !Array.isArray(n) && (n as any).$$mdtype === 'Tag';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const isGroup = $derived(tag.attributes.typeof === 'Storyboard');
|
|
13
|
-
|
|
14
|
-
// Style modifier is consumed by engine; read from data attribute
|
|
15
|
-
const styleName = $derived(isGroup
|
|
16
|
-
? tag.attributes['data-style'] || 'clean'
|
|
17
|
-
: 'clean');
|
|
18
|
-
const columns = $derived(isGroup
|
|
19
|
-
? parseInt(tag.children.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'columns')?.attributes?.content || '3', 10)
|
|
20
|
-
: 3);
|
|
21
|
-
|
|
22
|
-
const panelsEl = $derived(isGroup
|
|
23
|
-
? tag.children.find((c): c is SerializedTag => isTag(c) && c.attributes?.['data-name'] === 'panels')
|
|
24
|
-
: undefined);
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
{#if isGroup}
|
|
28
|
-
<div class="rf-storyboard rf-storyboard--{styleName}" style="--sb-columns: {columns};">
|
|
29
|
-
<div class="rf-storyboard__panels">
|
|
30
|
-
{#if panelsEl}
|
|
31
|
-
<Renderer node={panelsEl.children} />
|
|
32
|
-
{/if}
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
{:else}
|
|
36
|
-
<div class="rf-storyboard-panel">
|
|
37
|
-
<div class="rf-storyboard-panel__body">
|
|
38
|
-
{@render children()}
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
{/if}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { SerializedTag, RendererNode } from '@refrakt-md/svelte';
|
|
3
|
-
import { Renderer } from '@refrakt-md/svelte';
|
|
4
|
-
import type { Snippet } from 'svelte';
|
|
5
|
-
|
|
6
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
7
|
-
|
|
8
|
-
const typeName = $derived(tag.attributes.typeof);
|
|
9
|
-
|
|
10
|
-
function isTag(n: RendererNode): n is SerializedTag {
|
|
11
|
-
return n !== null && typeof n === 'object' && !Array.isArray(n) && (n as any).$$mdtype === 'Tag';
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function getTextContent(node: RendererNode): string {
|
|
15
|
-
if (typeof node === 'string') return node;
|
|
16
|
-
if (typeof node === 'number') return String(node);
|
|
17
|
-
if (isTag(node)) return node.children.map(getTextContent).join('');
|
|
18
|
-
if (Array.isArray(node)) return node.map(getTextContent).join('');
|
|
19
|
-
return '';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// For TabGroup: parse the ul/li structure from the transform
|
|
23
|
-
const { tabs, panels } = $derived.by(() => {
|
|
24
|
-
const tabs: { name: string }[] = [];
|
|
25
|
-
const panels: { children: RendererNode[] }[] = [];
|
|
26
|
-
if (typeName === 'TabGroup') {
|
|
27
|
-
for (const child of tag.children) {
|
|
28
|
-
if (!isTag(child) || child.name !== 'ul') continue;
|
|
29
|
-
for (const item of child.children) {
|
|
30
|
-
if (!isTag(item)) continue;
|
|
31
|
-
if (item.attributes?.typeof === 'Tab') {
|
|
32
|
-
const nameNode = item.children.find(
|
|
33
|
-
(c): c is SerializedTag => isTag(c) && c.attributes?.property === 'name'
|
|
34
|
-
);
|
|
35
|
-
const name = nameNode ? getTextContent(nameNode) : getTextContent(item);
|
|
36
|
-
tabs.push({ name: name.trim() });
|
|
37
|
-
} else if (item.attributes?.typeof === 'TabPanel') {
|
|
38
|
-
panels.push({ children: item.children });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return { tabs, panels };
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
let activeIndex = $state(0);
|
|
47
|
-
</script>
|
|
48
|
-
|
|
49
|
-
{#if typeName === 'TabGroup' && tabs.length > 0}
|
|
50
|
-
<div class="rf-tabs">
|
|
51
|
-
<div class="rf-tabs__bar" role="tablist">
|
|
52
|
-
{#each tabs as tab, i}
|
|
53
|
-
<button
|
|
54
|
-
class="rf-tabs__button {i === activeIndex ? 'rf-tabs__button--active' : ''}"
|
|
55
|
-
role="tab"
|
|
56
|
-
aria-selected={i === activeIndex}
|
|
57
|
-
onclick={() => activeIndex = i}
|
|
58
|
-
>
|
|
59
|
-
{tab.name}
|
|
60
|
-
</button>
|
|
61
|
-
{/each}
|
|
62
|
-
</div>
|
|
63
|
-
<div class="rf-tabs__panels">
|
|
64
|
-
{#each panels as panel, i}
|
|
65
|
-
{#if i === activeIndex}
|
|
66
|
-
<div class="rf-tabs__panel" role="tabpanel">
|
|
67
|
-
<Renderer node={panel.children} />
|
|
68
|
-
</div>
|
|
69
|
-
{/if}
|
|
70
|
-
{/each}
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
{:else}
|
|
74
|
-
{@render children()}
|
|
75
|
-
{/if}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { SerializedTag } from '@refrakt-md/svelte';
|
|
3
|
-
import type { Snippet } from 'svelte';
|
|
4
|
-
|
|
5
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
6
|
-
|
|
7
|
-
const rating = $derived(tag.children
|
|
8
|
-
.find((c: any) => c?.name === 'meta' && c?.attributes?.property === 'rating')
|
|
9
|
-
?.attributes?.content);
|
|
10
|
-
|
|
11
|
-
const hasRating = $derived(rating !== undefined && rating !== null);
|
|
12
|
-
const stars = $derived(hasRating ? Math.min(5, Math.max(0, Number(rating))) : 0);
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<article class="rf-testimonial">
|
|
16
|
-
{#if hasRating}
|
|
17
|
-
<div class="rf-testimonial__rating" aria-label="{stars} out of 5 stars">
|
|
18
|
-
{#each Array(5) as _, i}
|
|
19
|
-
<span class="rf-testimonial__star {i < stars ? 'rf-testimonial__star--filled' : ''}">★</span>
|
|
20
|
-
{/each}
|
|
21
|
-
</div>
|
|
22
|
-
{/if}
|
|
23
|
-
<div class="rf-testimonial__content">
|
|
24
|
-
{@render children()}
|
|
25
|
-
</div>
|
|
26
|
-
</article>
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { SerializedTag } from '@refrakt-md/svelte';
|
|
3
|
-
import type { Snippet } from 'svelte';
|
|
4
|
-
|
|
5
|
-
let { tag, children }: { tag: SerializedTag; children: Snippet } = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<blockquote class="themed-blockquote">
|
|
9
|
-
<svg class="quote-mark" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
10
|
-
<path d="M10 8C10 5.79 8.21 4 6 4C3.79 4 2 5.79 2 8C2 10.21 3.79 12 6 12C6.67 12 7.31 11.83 7.88 11.54C7.63 14.08 5.55 16.09 3 16.34V18.36C6.68 18.09 9.64 15.13 9.93 11.45C9.98 10.99 10 10.5 10 10V8ZM22 8C22 5.79 20.21 4 18 4C15.79 4 14 5.79 14 8C14 10.21 15.79 12 18 12C18.67 12 19.31 11.83 19.88 11.54C19.63 14.08 17.55 16.09 15 16.34V18.36C18.68 18.09 21.64 15.13 21.93 11.45C21.98 10.99 22 10.5 22 10V8Z" fill="currentColor"/>
|
|
11
|
-
</svg>
|
|
12
|
-
{@render children()}
|
|
13
|
-
</blockquote>
|
|
14
|
-
|
|
15
|
-
<style>
|
|
16
|
-
.themed-blockquote {
|
|
17
|
-
position: relative;
|
|
18
|
-
border-left: 3px solid var(--color-primary);
|
|
19
|
-
margin: 1.5rem 0;
|
|
20
|
-
padding: 1rem 1.25rem 1rem 2.75rem;
|
|
21
|
-
color: var(--color-muted);
|
|
22
|
-
background: var(--color-surface);
|
|
23
|
-
border-radius: 0 var(--radius-md) var(--radius-md) 0;
|
|
24
|
-
}
|
|
25
|
-
.quote-mark {
|
|
26
|
-
position: absolute;
|
|
27
|
-
left: 0.75rem;
|
|
28
|
-
top: 1rem;
|
|
29
|
-
width: 18px;
|
|
30
|
-
height: 18px;
|
|
31
|
-
color: var(--color-primary);
|
|
32
|
-
opacity: 0.4;
|
|
33
|
-
}
|
|
34
|
-
.themed-blockquote :global(p:last-child) {
|
|
35
|
-
margin-bottom: 0;
|
|
36
|
-
}
|
|
37
|
-
</style>
|