sdocs 0.0.35 → 0.0.37

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/explorer/highlighter.d.ts +2 -0
  3. package/dist/explorer/highlighter.js +33 -0
  4. package/dist/explorer/views/ApiTable.svelte +138 -0
  5. package/dist/explorer/views/ApiTable.svelte.d.ts +14 -0
  6. package/dist/explorer/views/ComponentView.svelte +160 -108
  7. package/dist/explorer/views/CssPropControl.svelte +27 -0
  8. package/dist/explorer/views/CssPropControl.svelte.d.ts +14 -0
  9. package/dist/explorer/views/DataTable.svelte +46 -4
  10. package/dist/explorer/views/PreviewFrame.svelte +11 -1
  11. package/dist/explorer/views/PreviewFrame.svelte.d.ts +4 -1
  12. package/dist/explorer/views/PropControl.svelte +69 -0
  13. package/dist/explorer/views/PropControl.svelte.d.ts +14 -0
  14. package/dist/explorer/views/format.d.ts +6 -0
  15. package/dist/explorer/views/format.js +44 -0
  16. package/dist/server/snippet-compiler.d.ts +3 -2
  17. package/dist/server/snippet-compiler.js +36 -4
  18. package/dist/ui/Control/Checkbox.svelte +6 -3
  19. package/dist/ui/Control/Color.svelte +6 -3
  20. package/dist/ui/Control/Dimension.svelte +8 -4
  21. package/dist/ui/Control/Number.svelte +6 -4
  22. package/dist/ui/Control/Select.svelte +6 -4
  23. package/dist/ui/Control/Text.svelte +6 -3
  24. package/dist/ui/Icon/Icon.svelte +10 -0
  25. package/dist/ui/Icon/icons/database.svg +5 -0
  26. package/dist/ui/Icon/icons/palette.svg +7 -0
  27. package/dist/ui/Icon/icons/sliders-horizontal.svg +11 -0
  28. package/dist/ui/Icon/icons/square-function.svg +5 -0
  29. package/dist/ui/Icon/icons/zap.svg +3 -0
  30. package/dist/ui/styles/sdocs.css +49 -0
  31. package/dist/vite.js +2 -20
  32. package/package.json +1 -1
  33. package/dist/explorer/views/ControlsPanel.svelte +0 -186
  34. package/dist/explorer/views/ControlsPanel.svelte.d.ts +0 -14
@@ -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
@@ -72,25 +72,6 @@ export function sdocsPlugin(userConfig) {
72
72
  res.end('Internal error');
73
73
  });
74
74
  });
75
- // API: highlight code on demand
76
- server.middlewares.use((req, res, next) => {
77
- if (req.url !== '/__sdocs/highlight' || req.method !== 'POST')
78
- return next();
79
- let body = '';
80
- req.on('data', (chunk) => { body += chunk; });
81
- req.on('end', async () => {
82
- try {
83
- const { code, lang } = JSON.parse(body);
84
- const html = await highlight(code, lang);
85
- res.setHeader('Content-Type', 'application/json');
86
- res.end(JSON.stringify({ html }));
87
- }
88
- catch {
89
- res.statusCode = 400;
90
- res.end('Invalid request');
91
- }
92
- });
93
- });
94
75
  // Watch for .sdoc file add/unlink/change
95
76
  server.watcher.on('add', async (filePath) => {
96
77
  if (isDocFile(filePath)) {
@@ -235,7 +216,8 @@ export function sdocsPlugin(userConfig) {
235
216
  if (!snippet)
236
217
  return null;
237
218
  const absoluteImports = docImportsCache.get(parsed.docFilePath) ?? [];
238
- return generateIframeComponent(absoluteImports, snippet.body);
219
+ const stateNames = (entry.componentData?.state ?? []).map((s) => s.name);
220
+ return generateIframeComponent(absoluteImports, snippet.body, stateNames);
239
221
  }
240
222
  // Virtual mount script for an emitted preview page
241
223
  if (id.startsWith('\0' + MOUNT_PREFIX)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdocs",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "description": "A lightweight documentation tool for Svelte 5 components",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,186 +0,0 @@
1
- <script lang="ts">
2
- import type { ParsedProp, ParsedCssProp } from '../../types.js';
3
- import { Text as TextControl, Number as NumberControl, Checkbox as CheckboxControl, Color as ColorControl, Dimension as DimensionControl, Select as SelectControl } from '../../ui/Control/index.js';
4
-
5
- interface Props {
6
- componentProps: ParsedProp[];
7
- cssProps: ParsedCssProp[];
8
- propValues: Record<string, unknown>;
9
- cssValues: Record<string, string>;
10
- onPropChange: (name: string, value: unknown) => void;
11
- onCssChange: (name: string, value: string) => void;
12
- onReset: () => void;
13
- }
14
-
15
- let { componentProps, cssProps, propValues, cssValues, onPropChange, onCssChange, onReset }: Props = $props();
16
-
17
- // Only show controls for regular props (not events or snippets)
18
- const editableProps = $derived(componentProps.filter((p) => p.category === 'prop'));
19
-
20
- /** Parse union type strings like "'sm' | 'md' | 'lg'" or "1 | 2 | 3" into option arrays */
21
- function parseUnionOptions(type: string | null): string[] | null {
22
- if (!type || !type.includes('|')) return null;
23
- const parts = type.split('|').map((s) => s.trim());
24
- const values: string[] = [];
25
- let allStrings = true;
26
- let allNumbers = true;
27
- for (const part of parts) {
28
- // Quoted string: 'value' or "value"
29
- const strMatch = part.match(/^['"](.+)['"]$/);
30
- if (strMatch) {
31
- values.push(strMatch[1]);
32
- allNumbers = false;
33
- continue;
34
- }
35
- // Bare number: 1, 2, 3
36
- if (/^\d+(\.\d+)?$/.test(part)) {
37
- values.push(part);
38
- allStrings = false;
39
- continue;
40
- }
41
- // Mixed or unsupported (e.g. 'medium' | number) → null
42
- return null;
43
- }
44
- if (values.length > 0 && (allStrings || allNumbers)) return values;
45
- return null;
46
- }
47
-
48
- function getControlType(prop: ParsedProp): 'text' | 'number' | 'boolean' | 'select' | 'readonly' {
49
- const t = prop.type?.toLowerCase() ?? '';
50
- if (t === 'string') return 'text';
51
- if (t === 'number') return 'number';
52
- if (t === 'boolean') return 'boolean';
53
- if (parseUnionOptions(prop.type)) return 'select';
54
- return 'readonly';
55
- }
56
-
57
- function getCssControlType(cssProp: ParsedCssProp): 'color' | 'dimension' | 'text' {
58
- const t = cssProp.type?.toLowerCase() ?? '';
59
- if (t === 'color') return 'color';
60
- if (t === 'dimension') return 'dimension';
61
- return 'text';
62
- }
63
- </script>
64
-
65
- <div class="sdocs-controls">
66
- {#if editableProps.length > 0}
67
- <div class="sdocs-controls-section">
68
- <div class="sdocs-controls-section-title">Props</div>
69
- {#each editableProps as prop (prop.name)}
70
- {@const controlType = getControlType(prop)}
71
- {#if controlType === 'text'}
72
- <TextControl
73
- label={prop.name}
74
- value={String(propValues[prop.name] ?? prop.default ?? '')}
75
- onchange={(v) => onPropChange(prop.name, v)}
76
- />
77
- {:else if controlType === 'number'}
78
- <NumberControl
79
- label={prop.name}
80
- value={Number(propValues[prop.name] ?? prop.default ?? 0)}
81
- onchange={(v) => onPropChange(prop.name, v)}
82
- />
83
- {:else if controlType === 'boolean'}
84
- <CheckboxControl
85
- label={prop.name}
86
- value={Boolean(propValues[prop.name] ?? (prop.default === 'true'))}
87
- onchange={(v) => onPropChange(prop.name, v)}
88
- />
89
- {:else if controlType === 'select'}
90
- {@const options = parseUnionOptions(prop.type) ?? []}
91
- <SelectControl
92
- label={prop.name}
93
- value={String(propValues[prop.name] ?? prop.default ?? options[0] ?? '')}
94
- {options}
95
- onchange={(v) => onPropChange(prop.name, v)}
96
- />
97
- {:else}
98
- <div class="sdocs-control-readonly">
99
- <span class="sdocs-control-label">{prop.name}</span>
100
- <span class="sdocs-control-type">{prop.type ?? 'unknown'}</span>
101
- </div>
102
- {/if}
103
- {/each}
104
- </div>
105
- {/if}
106
-
107
- {#if cssProps.length > 0}
108
- <div class="sdocs-controls-section">
109
- <div class="sdocs-controls-section-title">CSS Custom Properties</div>
110
- {#each cssProps as cssProp (cssProp.name)}
111
- {@const cssType = getCssControlType(cssProp)}
112
- {#if cssType === 'color'}
113
- <ColorControl
114
- label={cssProp.name}
115
- value={cssValues[cssProp.name] ?? cssProp.default ?? '#000000'}
116
- onchange={(v) => onCssChange(cssProp.name, v)}
117
- />
118
- {:else if cssType === 'dimension'}
119
- <DimensionControl
120
- label={cssProp.name}
121
- value={cssValues[cssProp.name] ?? cssProp.default ?? '0px'}
122
- onchange={(v) => onCssChange(cssProp.name, v)}
123
- />
124
- {:else}
125
- <TextControl
126
- label={cssProp.name}
127
- value={cssValues[cssProp.name] ?? cssProp.default ?? ''}
128
- onchange={(v) => onCssChange(cssProp.name, v)}
129
- />
130
- {/if}
131
- {/each}
132
- </div>
133
- {/if}
134
-
135
- <button class="sdocs-reset-btn" onclick={onReset}>Reset</button>
136
- </div>
137
-
138
- <style>
139
- .sdocs-controls {
140
- display: flex;
141
- flex-direction: column;
142
- gap: 12px;
143
- }
144
- .sdocs-controls-section {
145
- display: flex;
146
- flex-direction: column;
147
- gap: 8px;
148
- }
149
- .sdocs-controls-section-title {
150
- font-size: 11px;
151
- font-weight: 600;
152
- color: var(--color-base-400);
153
- text-transform: uppercase;
154
- letter-spacing: 0.05em;
155
- }
156
- .sdocs-control-readonly {
157
- display: flex;
158
- align-items: center;
159
- gap: 8px;
160
- font-size: 13px;
161
- }
162
- .sdocs-control-label {
163
- min-width: 100px;
164
- color: var(--color-base-600);
165
- font-weight: 500;
166
- }
167
- .sdocs-control-type {
168
- color: var(--color-base-400);
169
- font-family: var(--mono);
170
- font-size: 12px;
171
- }
172
- .sdocs-reset-btn {
173
- align-self: flex-start;
174
- padding: 4px 12px;
175
- border: 1px solid var(--color-base-200);
176
- border-radius: 4px;
177
- background: var(--color-base-0);
178
- font: inherit;
179
- font-size: 12px;
180
- color: var(--color-base-600);
181
- cursor: pointer;
182
- }
183
- .sdocs-reset-btn:hover {
184
- background: var(--color-base-100);
185
- }
186
- </style>
@@ -1,14 +0,0 @@
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 ControlsPanelProps = typeof __propDef.props;
10
- export type ControlsPanelEvents = typeof __propDef.events;
11
- export type ControlsPanelSlots = typeof __propDef.slots;
12
- export default class ControlsPanel extends SvelteComponentTyped<ControlsPanelProps, ControlsPanelEvents, ControlsPanelSlots> {
13
- }
14
- export {};