sdocs 0.0.36 → 0.0.38
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/CHANGELOG.md +38 -0
- package/dist/explorer/views/ApiTable.svelte +139 -0
- package/dist/explorer/views/ApiTable.svelte.d.ts +14 -0
- package/dist/explorer/views/ComponentView.svelte +154 -87
- package/dist/explorer/views/CssPropControl.svelte +27 -0
- package/dist/explorer/views/CssPropControl.svelte.d.ts +14 -0
- package/dist/explorer/views/DataTable.svelte +46 -4
- package/dist/explorer/views/PreviewFrame.svelte +11 -1
- package/dist/explorer/views/PreviewFrame.svelte.d.ts +4 -1
- package/dist/explorer/views/PropControl.svelte +69 -0
- package/dist/explorer/views/PropControl.svelte.d.ts +14 -0
- package/dist/explorer/views/format.d.ts +6 -0
- package/dist/explorer/views/format.js +44 -0
- package/dist/server/snippet-compiler.d.ts +3 -2
- package/dist/server/snippet-compiler.js +36 -4
- package/dist/ui/Control/Checkbox.svelte +6 -3
- package/dist/ui/Control/Color.svelte +6 -3
- package/dist/ui/Control/Dimension.svelte +8 -4
- package/dist/ui/Control/Number.svelte +6 -4
- package/dist/ui/Control/Select.svelte +6 -4
- package/dist/ui/Control/Text.svelte +6 -3
- package/dist/ui/Icon/Icon.svelte +10 -0
- package/dist/ui/Icon/icons/database.svg +5 -0
- package/dist/ui/Icon/icons/palette.svg +7 -0
- package/dist/ui/Icon/icons/sliders-horizontal.svg +11 -0
- package/dist/ui/Icon/icons/square-function.svg +5 -0
- package/dist/ui/Icon/icons/zap.svg +3 -0
- package/dist/ui/styles/sdocs.css +49 -0
- package/dist/vite.js +2 -1
- package/package.json +1 -1
- package/dist/explorer/views/ControlsPanel.svelte +0 -186
- package/dist/explorer/views/ControlsPanel.svelte.d.ts +0 -14
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ParsedProp } from '../../types.js';
|
|
3
|
+
import { Text as TextControl, Number as NumberControl, Checkbox as CheckboxControl, Select as SelectControl } from '../../ui/Control/index.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
prop: ParsedProp;
|
|
7
|
+
value: unknown;
|
|
8
|
+
onchange: (value: unknown) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { prop, value, onchange }: Props = $props();
|
|
12
|
+
|
|
13
|
+
/** Parse union type strings like "'sm' | 'md' | 'lg'" or "1 | 2 | 3" into option arrays */
|
|
14
|
+
function parseUnionOptions(type: string | null): string[] | null {
|
|
15
|
+
if (!type || !type.includes('|')) return null;
|
|
16
|
+
const parts = type.split('|').map((s) => s.trim());
|
|
17
|
+
const values: string[] = [];
|
|
18
|
+
let allStrings = true;
|
|
19
|
+
let allNumbers = true;
|
|
20
|
+
for (const part of parts) {
|
|
21
|
+
// Quoted string: 'value' or "value"
|
|
22
|
+
const strMatch = part.match(/^['"](.+)['"]$/);
|
|
23
|
+
if (strMatch) {
|
|
24
|
+
values.push(strMatch[1]);
|
|
25
|
+
allNumbers = false;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
// Bare number: 1, 2, 3
|
|
29
|
+
if (/^\d+(\.\d+)?$/.test(part)) {
|
|
30
|
+
values.push(part);
|
|
31
|
+
allStrings = false;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
// Mixed or unsupported (e.g. 'medium' | number) → null
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (values.length > 0 && (allStrings || allNumbers)) return values;
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const controlType = $derived.by(() => {
|
|
42
|
+
const t = prop.type?.toLowerCase() ?? '';
|
|
43
|
+
if (t === 'string') return 'text';
|
|
44
|
+
if (t === 'number') return 'number';
|
|
45
|
+
if (t === 'boolean') return 'boolean';
|
|
46
|
+
if (parseUnionOptions(prop.type)) return 'select';
|
|
47
|
+
return 'readonly';
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const options = $derived(parseUnionOptions(prop.type) ?? []);
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
{#if controlType === 'text'}
|
|
54
|
+
<TextControl value={String(value ?? prop.default ?? '')} {onchange} />
|
|
55
|
+
{:else if controlType === 'number'}
|
|
56
|
+
<NumberControl value={Number(value ?? prop.default ?? 0)} {onchange} />
|
|
57
|
+
{:else if controlType === 'boolean'}
|
|
58
|
+
<CheckboxControl value={Boolean(value ?? (prop.default === 'true'))} {onchange} />
|
|
59
|
+
{:else if controlType === 'select'}
|
|
60
|
+
<SelectControl value={String(value ?? prop.default ?? options[0] ?? '')} {options} {onchange} />
|
|
61
|
+
{:else}
|
|
62
|
+
<span class="sdocs-control-unsupported">—</span>
|
|
63
|
+
{/if}
|
|
64
|
+
|
|
65
|
+
<style>
|
|
66
|
+
.sdocs-control-unsupported {
|
|
67
|
+
color: var(--color-base-300);
|
|
68
|
+
}
|
|
69
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type PropControlProps = typeof __propDef.props;
|
|
10
|
+
export type PropControlEvents = typeof __propDef.events;
|
|
11
|
+
export type PropControlSlots = typeof __propDef.slots;
|
|
12
|
+
export default class PropControl extends SvelteComponentTyped<PropControlProps, PropControlEvents, PropControlSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Classify a type string for color coding (conventions, not a formal standard) */
|
|
2
|
+
export declare function typeClass(value: unknown): string;
|
|
3
|
+
/** Classify a literal value for color coding (defaults, current state) */
|
|
4
|
+
export declare function valueClass(value: unknown): string;
|
|
5
|
+
/** Split a clean union type into its members; everything else stays whole */
|
|
6
|
+
export declare function typeParts(value: unknown): string[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Classify a type string for color coding (conventions, not a formal standard) */
|
|
2
|
+
export function typeClass(value) {
|
|
3
|
+
const v = String(value).trim();
|
|
4
|
+
if (v === 'string' || /^'[^']*'(\s*\|\s*'[^']*')*$/.test(v))
|
|
5
|
+
return 'string';
|
|
6
|
+
if (v === 'number' || /^\d+(\.\d+)?(\s*\|\s*\d+(\.\d+)?)*$/.test(v))
|
|
7
|
+
return 'number';
|
|
8
|
+
if (v === 'boolean')
|
|
9
|
+
return 'boolean';
|
|
10
|
+
if (v.includes('=>'))
|
|
11
|
+
return 'function';
|
|
12
|
+
if (v.startsWith('Snippet'))
|
|
13
|
+
return 'snippet';
|
|
14
|
+
if (v === 'color')
|
|
15
|
+
return 'color';
|
|
16
|
+
if (v === 'dimension')
|
|
17
|
+
return 'dimension';
|
|
18
|
+
if (v === 'void' || v === 'undefined' || v === 'null')
|
|
19
|
+
return 'void';
|
|
20
|
+
return 'other';
|
|
21
|
+
}
|
|
22
|
+
/** Classify a literal value for color coding (defaults, current state) */
|
|
23
|
+
export function valueClass(value) {
|
|
24
|
+
const v = String(value).trim();
|
|
25
|
+
if (v === 'true' || v === 'false')
|
|
26
|
+
return 'boolean';
|
|
27
|
+
if (/^-?\d+(\.\d+)?$/.test(v))
|
|
28
|
+
return 'number';
|
|
29
|
+
if (/^-?\d+(\.\d+)?(px|rem|em|%|vh|vw|ch|pt)$/.test(v))
|
|
30
|
+
return 'dimension';
|
|
31
|
+
if (/^(#[0-9a-fA-F]{3,8}$|hsla?\(|rgba?\(|oklch\(|oklab\()/.test(v))
|
|
32
|
+
return 'color';
|
|
33
|
+
if (v.startsWith('{') || v.startsWith('['))
|
|
34
|
+
return 'other';
|
|
35
|
+
return 'string';
|
|
36
|
+
}
|
|
37
|
+
/** Split a clean union type into its members; everything else stays whole */
|
|
38
|
+
export function typeParts(value) {
|
|
39
|
+
const v = String(value).trim();
|
|
40
|
+
if (/^'[^']*'(\s*\|\s*'[^']*')+$/.test(v) || /^\d+(\.\d+)?(\s*\|\s*\d+(\.\d+)?)+$/.test(v)) {
|
|
41
|
+
return v.split('|').map((part) => part.trim());
|
|
42
|
+
}
|
|
43
|
+
return [v];
|
|
44
|
+
}
|
|
@@ -9,8 +9,9 @@ export declare function encodeDocPath(filePath: string): string;
|
|
|
9
9
|
/** Resolve relative imports to absolute paths for use in virtual components */
|
|
10
10
|
export declare function resolveImportsToAbsolute(imports: string[], docFilePath: string): string[];
|
|
11
11
|
/** Generate a virtual Svelte iframe wrapper component for a snippet.
|
|
12
|
-
* Includes $state for reactive prop updates via postMessage
|
|
13
|
-
|
|
12
|
+
* Includes $state for reactive prop updates via postMessage, invokes
|
|
13
|
+
* component methods on request, and broadcasts exported state values. */
|
|
14
|
+
export declare function generateIframeComponent(absoluteImports: string[], snippetBody: string, stateNames?: string[]): string;
|
|
14
15
|
/** The JS that boots a preview page: mount the wrapper + parent-frame messaging. */
|
|
15
16
|
export declare function generateMountScript(iframeComponentId: string): string;
|
|
16
17
|
/** Generate the HTML page served inside the iframe (dev / CLI-build inputs) */
|
|
@@ -35,23 +35,55 @@ export function resolveImportsToAbsolute(imports, docFilePath) {
|
|
|
35
35
|
return imp;
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
+
/** Add bind:this to the snippet's root component so the wrapper can reach
|
|
39
|
+
* its exported methods and state. Skipped when the author already binds. */
|
|
40
|
+
function injectRootRef(snippetBody) {
|
|
41
|
+
if (snippetBody.includes('bind:this'))
|
|
42
|
+
return snippetBody;
|
|
43
|
+
const match = snippetBody.match(/<([A-Z][A-Za-z0-9_]*)/);
|
|
44
|
+
if (!match || match.index === undefined)
|
|
45
|
+
return snippetBody;
|
|
46
|
+
const insertAt = match.index + match[0].length;
|
|
47
|
+
return snippetBody.slice(0, insertAt) + ' bind:this={__sdocsRef}' + snippetBody.slice(insertAt);
|
|
48
|
+
}
|
|
38
49
|
/** Generate a virtual Svelte iframe wrapper component for a snippet.
|
|
39
|
-
* Includes $state for reactive prop updates via postMessage
|
|
40
|
-
|
|
50
|
+
* Includes $state for reactive prop updates via postMessage, invokes
|
|
51
|
+
* component methods on request, and broadcasts exported state values. */
|
|
52
|
+
export function generateIframeComponent(absoluteImports, snippetBody, stateNames = []) {
|
|
41
53
|
const importBlock = absoluteImports.length > 0
|
|
42
54
|
? absoluteImports.join('\n') + '\n'
|
|
43
55
|
: '';
|
|
56
|
+
const stateBroadcast = stateNames.length > 0
|
|
57
|
+
? `
|
|
58
|
+
$effect(() => {
|
|
59
|
+
const values: Record<string, unknown> = {};
|
|
60
|
+
for (const name of ${JSON.stringify(stateNames)}) {
|
|
61
|
+
try {
|
|
62
|
+
const v = (__sdocsRef as Record<string, unknown> | undefined)?.[name];
|
|
63
|
+
values[name] = v === undefined ? undefined : JSON.parse(JSON.stringify($state.snapshot(v)));
|
|
64
|
+
} catch {
|
|
65
|
+
values[name] = undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
window.parent.postMessage({ type: 'sdocs:state-values', values }, '*');
|
|
69
|
+
});
|
|
70
|
+
`
|
|
71
|
+
: '';
|
|
44
72
|
// lang="ts" so lifted imports may carry type-only syntax (Svelte 5 erases it natively)
|
|
45
73
|
return `<script lang="ts">
|
|
46
74
|
${importBlock}import { onMount } from 'svelte';
|
|
47
75
|
|
|
48
76
|
let args = $state({});
|
|
49
|
-
|
|
77
|
+
let __sdocsRef = $state();
|
|
78
|
+
${stateBroadcast}
|
|
50
79
|
onMount(() => {
|
|
51
80
|
window.addEventListener('message', (e) => {
|
|
52
81
|
if (e.data?.type === 'sdocs:update-props') {
|
|
53
82
|
args = { ...e.data.props };
|
|
54
83
|
}
|
|
84
|
+
if (e.data?.type === 'sdocs:call-method') {
|
|
85
|
+
(__sdocsRef as Record<string, () => void> | undefined)?.[e.data.name]?.();
|
|
86
|
+
}
|
|
55
87
|
if (e.data?.type === 'sdocs:update-css') {
|
|
56
88
|
const el = document.getElementById('sdocs-preview');
|
|
57
89
|
if (el) {
|
|
@@ -86,7 +118,7 @@ export function generateIframeComponent(absoluteImports, snippetBody) {
|
|
|
86
118
|
|
|
87
119
|
<div id="sdocs-preview">
|
|
88
120
|
{#snippet SdocsPreview(args)}
|
|
89
|
-
${snippetBody}
|
|
121
|
+
${injectRootRef(snippetBody)}
|
|
90
122
|
{/snippet}
|
|
91
123
|
{@render SdocsPreview(args)}
|
|
92
124
|
</div>`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
|
-
label
|
|
3
|
+
/** Optional label; omit when the control sits next to its name (e.g. in a table) */
|
|
4
|
+
label?: string;
|
|
4
5
|
value: boolean;
|
|
5
6
|
onchange: (value: boolean) => void;
|
|
6
7
|
}
|
|
@@ -9,7 +10,9 @@
|
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
<label class="sdocs-control">
|
|
12
|
-
|
|
13
|
+
{#if label}
|
|
14
|
+
<span class="sdocs-control-label">{label}</span>
|
|
15
|
+
{/if}
|
|
13
16
|
<input
|
|
14
17
|
type="checkbox"
|
|
15
18
|
checked={value}
|
|
@@ -28,7 +31,7 @@
|
|
|
28
31
|
.sdocs-control-label {
|
|
29
32
|
min-width: 100px;
|
|
30
33
|
color: var(--color-base-600);
|
|
31
|
-
font-weight:
|
|
34
|
+
font-weight: 600;
|
|
32
35
|
}
|
|
33
36
|
.sdocs-control-checkbox {
|
|
34
37
|
width: 16px;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
|
-
label
|
|
3
|
+
/** Optional label; omit when the control sits next to its name (e.g. in a table) */
|
|
4
|
+
label?: string;
|
|
4
5
|
value: string;
|
|
5
6
|
onchange: (value: string) => void;
|
|
6
7
|
}
|
|
@@ -9,7 +10,9 @@
|
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
<label class="sdocs-control">
|
|
12
|
-
|
|
13
|
+
{#if label}
|
|
14
|
+
<span class="sdocs-control-label">{label}</span>
|
|
15
|
+
{/if}
|
|
13
16
|
<input
|
|
14
17
|
type="color"
|
|
15
18
|
{value}
|
|
@@ -29,7 +32,7 @@
|
|
|
29
32
|
.sdocs-control-label {
|
|
30
33
|
min-width: 100px;
|
|
31
34
|
color: var(--color-base-600);
|
|
32
|
-
font-weight:
|
|
35
|
+
font-weight: 600;
|
|
33
36
|
}
|
|
34
37
|
.sdocs-control-color {
|
|
35
38
|
width: 32px;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
|
-
label
|
|
3
|
+
/** Optional label; omit when the control sits next to its name (e.g. in a table) */
|
|
4
|
+
label?: string;
|
|
4
5
|
value: string;
|
|
5
6
|
onchange: (value: string) => void;
|
|
6
7
|
}
|
|
@@ -10,7 +11,9 @@
|
|
|
10
11
|
</script>
|
|
11
12
|
|
|
12
13
|
<label class="sdocs-control">
|
|
13
|
-
|
|
14
|
+
{#if label}
|
|
15
|
+
<span class="sdocs-control-label">{label}</span>
|
|
16
|
+
{/if}
|
|
14
17
|
<div class="sdocs-control-dimension">
|
|
15
18
|
<input
|
|
16
19
|
type="number"
|
|
@@ -32,7 +35,7 @@
|
|
|
32
35
|
.sdocs-control-label {
|
|
33
36
|
min-width: 100px;
|
|
34
37
|
color: var(--color-base-600);
|
|
35
|
-
font-weight:
|
|
38
|
+
font-weight: 600;
|
|
36
39
|
}
|
|
37
40
|
.sdocs-control-dimension {
|
|
38
41
|
display: flex;
|
|
@@ -40,7 +43,8 @@
|
|
|
40
43
|
gap: 4px;
|
|
41
44
|
}
|
|
42
45
|
.sdocs-control-input {
|
|
43
|
-
|
|
46
|
+
flex: 1;
|
|
47
|
+
min-width: 0;
|
|
44
48
|
padding: 4px 8px;
|
|
45
49
|
border: 1px solid var(--color-base-200);
|
|
46
50
|
border-radius: 4px;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
|
-
label
|
|
3
|
+
/** Optional label; omit when the control sits next to its name (e.g. in a table) */
|
|
4
|
+
label?: string;
|
|
4
5
|
value: number;
|
|
5
6
|
onchange: (value: number) => void;
|
|
6
7
|
}
|
|
@@ -9,7 +10,9 @@
|
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
<label class="sdocs-control">
|
|
12
|
-
|
|
13
|
+
{#if label}
|
|
14
|
+
<span class="sdocs-control-label">{label}</span>
|
|
15
|
+
{/if}
|
|
13
16
|
<input
|
|
14
17
|
type="number"
|
|
15
18
|
{value}
|
|
@@ -28,7 +31,7 @@
|
|
|
28
31
|
.sdocs-control-label {
|
|
29
32
|
min-width: 100px;
|
|
30
33
|
color: var(--color-base-600);
|
|
31
|
-
font-weight:
|
|
34
|
+
font-weight: 600;
|
|
32
35
|
}
|
|
33
36
|
.sdocs-control-input {
|
|
34
37
|
flex: 1;
|
|
@@ -39,6 +42,5 @@
|
|
|
39
42
|
border-radius: 4px;
|
|
40
43
|
font: inherit;
|
|
41
44
|
font-size: 13px;
|
|
42
|
-
max-width: 120px;
|
|
43
45
|
}
|
|
44
46
|
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
|
-
label
|
|
3
|
+
/** Optional label; omit when the control sits next to its name (e.g. in a table) */
|
|
4
|
+
label?: string;
|
|
4
5
|
value: string;
|
|
5
6
|
options: string[];
|
|
6
7
|
onchange: (value: string) => void;
|
|
@@ -10,7 +11,9 @@
|
|
|
10
11
|
</script>
|
|
11
12
|
|
|
12
13
|
<label class="sdocs-control">
|
|
13
|
-
|
|
14
|
+
{#if label}
|
|
15
|
+
<span class="sdocs-control-label">{label}</span>
|
|
16
|
+
{/if}
|
|
14
17
|
<select
|
|
15
18
|
class="sdocs-control-select"
|
|
16
19
|
{value}
|
|
@@ -32,7 +35,7 @@
|
|
|
32
35
|
.sdocs-control-label {
|
|
33
36
|
min-width: 100px;
|
|
34
37
|
color: var(--color-base-600);
|
|
35
|
-
font-weight:
|
|
38
|
+
font-weight: 600;
|
|
36
39
|
}
|
|
37
40
|
.sdocs-control-select {
|
|
38
41
|
flex: 1;
|
|
@@ -43,6 +46,5 @@
|
|
|
43
46
|
font-size: 13px;
|
|
44
47
|
background: var(--color-base-0);
|
|
45
48
|
color: var(--color-base-600);
|
|
46
|
-
max-width: 200px;
|
|
47
49
|
}
|
|
48
50
|
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
interface Props {
|
|
3
|
-
label
|
|
3
|
+
/** Optional label; omit when the control sits next to its name (e.g. in a table) */
|
|
4
|
+
label?: string;
|
|
4
5
|
value: string;
|
|
5
6
|
onchange: (value: string) => void;
|
|
6
7
|
}
|
|
@@ -9,7 +10,9 @@
|
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
<label class="sdocs-control">
|
|
12
|
-
|
|
13
|
+
{#if label}
|
|
14
|
+
<span class="sdocs-control-label">{label}</span>
|
|
15
|
+
{/if}
|
|
13
16
|
<input
|
|
14
17
|
type="text"
|
|
15
18
|
{value}
|
|
@@ -28,7 +31,7 @@
|
|
|
28
31
|
.sdocs-control-label {
|
|
29
32
|
min-width: 100px;
|
|
30
33
|
color: var(--color-base-600);
|
|
31
|
-
font-weight:
|
|
34
|
+
font-weight: 600;
|
|
32
35
|
}
|
|
33
36
|
.sdocs-control-input {
|
|
34
37
|
flex: 1;
|
package/dist/ui/Icon/Icon.svelte
CHANGED
|
@@ -7,13 +7,18 @@
|
|
|
7
7
|
import codeSvg from './icons/code.svg?raw';
|
|
8
8
|
import componentSvg from './icons/component.svg?raw';
|
|
9
9
|
import copySvg from './icons/copy.svg?raw';
|
|
10
|
+
import databaseSvg from './icons/database.svg?raw';
|
|
10
11
|
import diamondSvg from './icons/diamond.svg?raw';
|
|
11
12
|
import fileCodeSvg from './icons/file-code.svg?raw';
|
|
12
13
|
import fileTextSvg from './icons/file-text.svg?raw';
|
|
13
14
|
import folderOpenSvg from './icons/folder-open.svg?raw';
|
|
14
15
|
import folderSvg from './icons/folder.svg?raw';
|
|
16
|
+
import paletteSvg from './icons/palette.svg?raw';
|
|
15
17
|
import panelsTopLeftSvg from './icons/panels-top-left.svg?raw';
|
|
16
18
|
import sdocsSvg from './icons/sdocs.svg?raw';
|
|
19
|
+
import slidersHorizontalSvg from './icons/sliders-horizontal.svg?raw';
|
|
20
|
+
import squareFunctionSvg from './icons/square-function.svg?raw';
|
|
21
|
+
import zapSvg from './icons/zap.svg?raw';
|
|
17
22
|
|
|
18
23
|
const icons: Record<string, string> = {
|
|
19
24
|
'bookmark': bookmarkSvg,
|
|
@@ -24,13 +29,18 @@
|
|
|
24
29
|
'code': codeSvg,
|
|
25
30
|
'component': componentSvg,
|
|
26
31
|
'copy': copySvg,
|
|
32
|
+
'database': databaseSvg,
|
|
27
33
|
'diamond': diamondSvg,
|
|
28
34
|
'file-code': fileCodeSvg,
|
|
29
35
|
'file-text': fileTextSvg,
|
|
30
36
|
'folder-open': folderOpenSvg,
|
|
31
37
|
'folder': folderSvg,
|
|
38
|
+
'palette': paletteSvg,
|
|
32
39
|
'panels-top-left': panelsTopLeftSvg,
|
|
33
40
|
'sdocs': sdocsSvg,
|
|
41
|
+
'sliders-horizontal': slidersHorizontalSvg,
|
|
42
|
+
'square-function': squareFunctionSvg,
|
|
43
|
+
'zap': zapSvg,
|
|
34
44
|
};
|
|
35
45
|
|
|
36
46
|
/**
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<ellipse cx="12" cy="5" rx="9" ry="3"/>
|
|
3
|
+
<path d="M3 5V19A9 3 0 0 0 21 19V5"/>
|
|
4
|
+
<path d="M3 12A9 3 0 0 0 21 12"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/>
|
|
3
|
+
<circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/>
|
|
4
|
+
<circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/>
|
|
5
|
+
<circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/>
|
|
6
|
+
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<line x1="21" x2="14" y1="4" y2="4"/>
|
|
3
|
+
<line x1="10" x2="3" y1="4" y2="4"/>
|
|
4
|
+
<line x1="21" x2="12" y1="12" y2="12"/>
|
|
5
|
+
<line x1="8" x2="3" y1="12" y2="12"/>
|
|
6
|
+
<line x1="21" x2="16" y1="20" y2="20"/>
|
|
7
|
+
<line x1="12" x2="3" y1="20" y2="20"/>
|
|
8
|
+
<line x1="14" x2="14" y1="2" y2="6"/>
|
|
9
|
+
<line x1="8" x2="8" y1="10" y2="14"/>
|
|
10
|
+
<line x1="16" x2="16" y1="18" y2="22"/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<rect width="18" height="18" x="3" y="3" rx="2"/>
|
|
3
|
+
<path d="M9 17c2 0 2.8-1 2.8-2.8V10c0-2 1-3.3 3.2-3"/>
|
|
4
|
+
<path d="M9 11.2h5.7"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>
|
|
3
|
+
</svg>
|
package/dist/ui/styles/sdocs.css
CHANGED
|
@@ -28,6 +28,55 @@
|
|
|
28
28
|
text-decoration: none;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/* Type chips and value literals, color-coded by kind (shared by doc tables) */
|
|
32
|
+
.sdocs-app code[class*='sdocs-type-'] {
|
|
33
|
+
font-family: var(--mono);
|
|
34
|
+
font-size: 12px;
|
|
35
|
+
padding: 1px 4px;
|
|
36
|
+
border-radius: 3px;
|
|
37
|
+
}
|
|
38
|
+
.sdocs-app code.sdocs-type-string { color: var(--color-green-700); background: var(--color-green-100); }
|
|
39
|
+
.sdocs-app code.sdocs-type-number { color: var(--color-amber-700); background: var(--color-amber-100); }
|
|
40
|
+
.sdocs-app code.sdocs-type-boolean { color: var(--color-purple-700); background: var(--color-purple-100); }
|
|
41
|
+
.sdocs-app code.sdocs-type-function { color: var(--color-blue-700); background: var(--color-blue-100); }
|
|
42
|
+
.sdocs-app code.sdocs-type-snippet { color: var(--color-pink-700); background: var(--color-pink-100); }
|
|
43
|
+
.sdocs-app code.sdocs-type-color { color: var(--color-cyan-700); background: var(--color-cyan-100); }
|
|
44
|
+
.sdocs-app code.sdocs-type-dimension { color: var(--color-amber-700); background: var(--color-amber-100); }
|
|
45
|
+
.sdocs-app code.sdocs-type-void { color: var(--color-slate-500); background: var(--color-slate-100); }
|
|
46
|
+
.sdocs-app code.sdocs-type-other { color: var(--color-base-700); background: var(--color-base-100); }
|
|
47
|
+
|
|
48
|
+
.sdocs-app .sdocs-typesep {
|
|
49
|
+
font-family: var(--mono);
|
|
50
|
+
font-size: 12px;
|
|
51
|
+
color: var(--color-base-300);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.sdocs-app .sdocs-value {
|
|
55
|
+
font-family: var(--mono);
|
|
56
|
+
font-size: 12px;
|
|
57
|
+
}
|
|
58
|
+
.sdocs-app .sdocs-value-string { color: var(--color-green-700); }
|
|
59
|
+
.sdocs-app .sdocs-value-number { color: var(--color-amber-700); }
|
|
60
|
+
.sdocs-app .sdocs-value-boolean { color: var(--color-purple-700); }
|
|
61
|
+
.sdocs-app .sdocs-value-dimension { color: var(--color-amber-700); }
|
|
62
|
+
.sdocs-app .sdocs-value-color { color: var(--color-cyan-700); }
|
|
63
|
+
.sdocs-app .sdocs-value-other { color: var(--color-base-600); }
|
|
64
|
+
|
|
65
|
+
/* Raw hue tokens don't invert with the theme; flip shades for dark */
|
|
66
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-string { color: var(--color-green-400); background: var(--color-green-950); }
|
|
67
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-number { color: var(--color-amber-400); background: var(--color-amber-950); }
|
|
68
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-boolean { color: var(--color-purple-400); background: var(--color-purple-950); }
|
|
69
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-function { color: var(--color-blue-400); background: var(--color-blue-950); }
|
|
70
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-snippet { color: var(--color-pink-400); background: var(--color-pink-950); }
|
|
71
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-color { color: var(--color-cyan-400); background: var(--color-cyan-950); }
|
|
72
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-dimension { color: var(--color-amber-400); background: var(--color-amber-950); }
|
|
73
|
+
.sdocs-app[data-sdocs-theme='dark'] code.sdocs-type-void { color: var(--color-slate-400); background: var(--color-slate-950); }
|
|
74
|
+
.sdocs-app[data-sdocs-theme='dark'] .sdocs-value-string { color: var(--color-green-400); }
|
|
75
|
+
.sdocs-app[data-sdocs-theme='dark'] .sdocs-value-number { color: var(--color-amber-400); }
|
|
76
|
+
.sdocs-app[data-sdocs-theme='dark'] .sdocs-value-boolean { color: var(--color-purple-400); }
|
|
77
|
+
.sdocs-app[data-sdocs-theme='dark'] .sdocs-value-dimension { color: var(--color-amber-400); }
|
|
78
|
+
.sdocs-app[data-sdocs-theme='dark'] .sdocs-value-color { color: var(--color-cyan-400); }
|
|
79
|
+
|
|
31
80
|
.sdocs-app[data-sdocs-theme='dark'] {
|
|
32
81
|
/* base — layouts, backgrounds, surfaces, borders, text (inverted) */
|
|
33
82
|
--color-base-0: var(--color-zinc-1000);
|
package/dist/vite.js
CHANGED
|
@@ -216,7 +216,8 @@ export function sdocsPlugin(userConfig) {
|
|
|
216
216
|
if (!snippet)
|
|
217
217
|
return null;
|
|
218
218
|
const absoluteImports = docImportsCache.get(parsed.docFilePath) ?? [];
|
|
219
|
-
|
|
219
|
+
const stateNames = (entry.componentData?.state ?? []).map((s) => s.name);
|
|
220
|
+
return generateIframeComponent(absoluteImports, snippet.body, stateNames);
|
|
220
221
|
}
|
|
221
222
|
// Virtual mount script for an emitted preview page
|
|
222
223
|
if (id.startsWith('\0' + MOUNT_PREFIX)) {
|