sdocs 0.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.
Files changed (129) hide show
  1. package/README.md +43 -0
  2. package/bin/sdocs.js +2 -0
  3. package/dist/Sdocs.svelte +1210 -0
  4. package/dist/Sdocs.svelte.d.ts +5 -0
  5. package/dist/cli/app-plugin.d.ts +7 -0
  6. package/dist/cli/app-plugin.js +69 -0
  7. package/dist/cli/config.d.ts +12 -0
  8. package/dist/cli/config.js +34 -0
  9. package/dist/cli/index.d.ts +1 -0
  10. package/dist/cli/index.js +72 -0
  11. package/dist/cli/server.d.ts +2 -0
  12. package/dist/cli/server.js +62 -0
  13. package/dist/docgen.d.ts +47 -0
  14. package/dist/docgen.js +463 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +4 -0
  17. package/dist/internal/ComponentPreview.svelte +58 -0
  18. package/dist/internal/ComponentPreview.svelte.d.ts +17 -0
  19. package/dist/internal/CssPropsTable.svelte +239 -0
  20. package/dist/internal/CssPropsTable.svelte.d.ts +11 -0
  21. package/dist/internal/Home.svelte +92 -0
  22. package/dist/internal/Home.svelte.d.ts +9 -0
  23. package/dist/internal/MethodsTable.svelte +72 -0
  24. package/dist/internal/MethodsTable.svelte.d.ts +7 -0
  25. package/dist/internal/PropsTable.svelte +342 -0
  26. package/dist/internal/PropsTable.svelte.d.ts +12 -0
  27. package/dist/internal/Showcase.svelte +130 -0
  28. package/dist/internal/Showcase.svelte.d.ts +21 -0
  29. package/dist/types.d.ts +162 -0
  30. package/dist/types.js +1 -0
  31. package/dist/ui/Badge/Badge.docs.svelte +46 -0
  32. package/dist/ui/Badge/Badge.docs.svelte.d.ts +26 -0
  33. package/dist/ui/Badge/Badge.svelte +59 -0
  34. package/dist/ui/Badge/Badge.svelte.d.ts +17 -0
  35. package/dist/ui/Badge/index.d.ts +1 -0
  36. package/dist/ui/Badge/index.js +1 -0
  37. package/dist/ui/Checkbox/Checkbox.docs.svelte +51 -0
  38. package/dist/ui/Checkbox/Checkbox.docs.svelte.d.ts +27 -0
  39. package/dist/ui/Checkbox/Checkbox.svelte +169 -0
  40. package/dist/ui/Checkbox/Checkbox.svelte.d.ts +18 -0
  41. package/dist/ui/Checkbox/index.d.ts +1 -0
  42. package/dist/ui/Checkbox/index.js +1 -0
  43. package/dist/ui/CodeBlock/CodeBlock.docs.svelte +28 -0
  44. package/dist/ui/CodeBlock/CodeBlock.docs.svelte.d.ts +24 -0
  45. package/dist/ui/CodeBlock/CodeBlock.svelte +101 -0
  46. package/dist/ui/CodeBlock/CodeBlock.svelte.d.ts +7 -0
  47. package/dist/ui/CodeBlock/index.d.ts +1 -0
  48. package/dist/ui/CodeBlock/index.js +1 -0
  49. package/dist/ui/Frame/Frame.docs.svelte +140 -0
  50. package/dist/ui/Frame/Frame.docs.svelte.d.ts +26 -0
  51. package/dist/ui/Frame/Frame.svelte +88 -0
  52. package/dist/ui/Frame/Frame.svelte.d.ts +15 -0
  53. package/dist/ui/Frame/index.d.ts +1 -0
  54. package/dist/ui/Frame/index.js +1 -0
  55. package/dist/ui/InputNumber/InputNumber.docs.svelte +50 -0
  56. package/dist/ui/InputNumber/InputNumber.docs.svelte.d.ts +26 -0
  57. package/dist/ui/InputNumber/InputNumber.svelte +275 -0
  58. package/dist/ui/InputNumber/InputNumber.svelte.d.ts +26 -0
  59. package/dist/ui/InputNumber/index.d.ts +1 -0
  60. package/dist/ui/InputNumber/index.js +1 -0
  61. package/dist/ui/InputText/InputText.docs.svelte +43 -0
  62. package/dist/ui/InputText/InputText.docs.svelte.d.ts +26 -0
  63. package/dist/ui/InputText/InputText.svelte +116 -0
  64. package/dist/ui/InputText/InputText.svelte.d.ts +22 -0
  65. package/dist/ui/InputText/index.d.ts +1 -0
  66. package/dist/ui/InputText/index.js +1 -0
  67. package/dist/ui/Panel/CollapsiblePanel.docs.svelte +45 -0
  68. package/dist/ui/Panel/CollapsiblePanel.docs.svelte.d.ts +25 -0
  69. package/dist/ui/Panel/CollapsiblePanel.svelte +93 -0
  70. package/dist/ui/Panel/CollapsiblePanel.svelte.d.ts +14 -0
  71. package/dist/ui/Panel/index.d.ts +1 -0
  72. package/dist/ui/Panel/index.js +1 -0
  73. package/dist/ui/Placeholder/Placeholder.docs.svelte +49 -0
  74. package/dist/ui/Placeholder/Placeholder.docs.svelte.d.ts +26 -0
  75. package/dist/ui/Placeholder/Placeholder.svelte +99 -0
  76. package/dist/ui/Placeholder/Placeholder.svelte.d.ts +21 -0
  77. package/dist/ui/Placeholder/index.d.ts +1 -0
  78. package/dist/ui/Placeholder/index.js +1 -0
  79. package/dist/ui/Radio/Radio.docs.svelte +67 -0
  80. package/dist/ui/Radio/Radio.docs.svelte.d.ts +27 -0
  81. package/dist/ui/Radio/Radio.svelte +165 -0
  82. package/dist/ui/Radio/Radio.svelte.d.ts +22 -0
  83. package/dist/ui/Radio/RadioGroup.docs.svelte +70 -0
  84. package/dist/ui/Radio/RadioGroup.docs.svelte.d.ts +27 -0
  85. package/dist/ui/Radio/RadioGroup.svelte +98 -0
  86. package/dist/ui/Radio/RadioGroup.svelte.d.ts +27 -0
  87. package/dist/ui/Radio/index.d.ts +2 -0
  88. package/dist/ui/Radio/index.js +2 -0
  89. package/dist/ui/SegmentControl/SegmentControl.docs.svelte +54 -0
  90. package/dist/ui/SegmentControl/SegmentControl.docs.svelte.d.ts +25 -0
  91. package/dist/ui/SegmentControl/SegmentControl.svelte +120 -0
  92. package/dist/ui/SegmentControl/SegmentControl.svelte.d.ts +18 -0
  93. package/dist/ui/SegmentControl/index.d.ts +1 -0
  94. package/dist/ui/SegmentControl/index.js +1 -0
  95. package/dist/ui/Stack/Stack.docs.svelte +63 -0
  96. package/dist/ui/Stack/Stack.docs.svelte.d.ts +26 -0
  97. package/dist/ui/Stack/Stack.svelte +45 -0
  98. package/dist/ui/Stack/Stack.svelte.d.ts +19 -0
  99. package/dist/ui/Stack/index.d.ts +1 -0
  100. package/dist/ui/Stack/index.js +1 -0
  101. package/dist/ui/Table/Body.svelte +17 -0
  102. package/dist/ui/Table/Body.svelte.d.ts +11 -0
  103. package/dist/ui/Table/Caption.svelte +17 -0
  104. package/dist/ui/Table/Caption.svelte.d.ts +11 -0
  105. package/dist/ui/Table/Cell.svelte +24 -0
  106. package/dist/ui/Table/Cell.svelte.d.ts +15 -0
  107. package/dist/ui/Table/Foot.svelte +17 -0
  108. package/dist/ui/Table/Foot.svelte.d.ts +11 -0
  109. package/dist/ui/Table/Head.svelte +17 -0
  110. package/dist/ui/Table/Head.svelte.d.ts +11 -0
  111. package/dist/ui/Table/Header.svelte +27 -0
  112. package/dist/ui/Table/Header.svelte.d.ts +17 -0
  113. package/dist/ui/Table/Row.svelte +19 -0
  114. package/dist/ui/Table/Row.svelte.d.ts +13 -0
  115. package/dist/ui/Table/Table.docs.svelte +197 -0
  116. package/dist/ui/Table/Table.docs.svelte.d.ts +28 -0
  117. package/dist/ui/Table/Table.svelte +140 -0
  118. package/dist/ui/Table/Table.svelte.d.ts +27 -0
  119. package/dist/ui/Table/index.js +10 -0
  120. package/dist/ui/css/colors.css +377 -0
  121. package/dist/ui/css/global.css +10 -0
  122. package/dist/ui/index.d.ts +12 -0
  123. package/dist/ui/index.js +12 -0
  124. package/dist/virtual-sdocs.d.ts +20 -0
  125. package/dist/vite-plugin.d.ts +18 -0
  126. package/dist/vite-plugin.js +206 -0
  127. package/dist/vite.d.ts +2 -0
  128. package/dist/vite.js +2 -0
  129. package/package.json +76 -0
@@ -0,0 +1,342 @@
1
+ <script lang="ts">
2
+ import type { ArgType, ArgTypes } from '../types.js';
3
+ import { Checkbox, SegmentControl, InputText, InputNumber, Placeholder, Table } from '../ui/index.js';
4
+ import type { default as PlaceholderType } from '../ui/Placeholder/Placeholder.svelte';
5
+
6
+ interface Props {
7
+ argTypes: ArgTypes;
8
+ args: Record<string, unknown>;
9
+ /** Callback when args change (enables interactive controls) */
10
+ onchange?: (args: Record<string, unknown>) => void;
11
+ }
12
+
13
+ let { argTypes, args, onchange }: Props = $props();
14
+
15
+ let isInteractive = $derived(!!onchange);
16
+
17
+ let bangRefs: Record<string, PlaceholderType> = {};
18
+
19
+ // Get sorted prop names
20
+ let propNames = $derived(Object.keys(argTypes).sort());
21
+
22
+ function getTypeName(argType: ArgTypes[string]): string {
23
+ if (argType.type) {
24
+ if (typeof argType.type === 'string') return argType.type;
25
+ if (argType.type.name) return argType.type.name;
26
+ }
27
+ if (argType.control) {
28
+ if (typeof argType.control === 'string') return argType.control;
29
+ if (argType.control.type) return argType.control.type;
30
+ }
31
+ return '-';
32
+ }
33
+
34
+ function getDefaultValue(name: string, argType: ArgTypes[string]): string {
35
+ if (argType.defaultValue !== undefined) {
36
+ return formatValue(argType.defaultValue);
37
+ }
38
+ if (args[name] !== undefined) {
39
+ return formatValue(args[name]);
40
+ }
41
+ return '-';
42
+ }
43
+
44
+ function formatValue(value: unknown): string {
45
+ if (value === null) return 'null';
46
+ if (value === undefined) return 'undefined';
47
+ if (typeof value === 'string') return value;
48
+ if (typeof value === 'boolean') return value ? 'true' : 'false';
49
+ if (typeof value === 'number') return String(value);
50
+ if (typeof value === 'function') return 'Function';
51
+ if (Array.isArray(value)) return JSON.stringify(value);
52
+ if (typeof value === 'object') return JSON.stringify(value);
53
+ return String(value);
54
+ }
55
+
56
+ function getDescription(argType: ArgTypes[string]): string {
57
+ return argType.description ?? '-';
58
+ }
59
+
60
+ function isRequired(argType: ArgTypes[string]): boolean {
61
+ return argType.required === true;
62
+ }
63
+
64
+ // Control helpers
65
+ function getControlType(key: string, argType: ArgType): string | false {
66
+ if (argType.control === false) return false;
67
+ if (typeof argType.control === 'string') return argType.control;
68
+ if (typeof argType.control === 'object') return argType.control.type;
69
+ // Infer from value
70
+ const value = args[key];
71
+ if (typeof value === 'boolean') return 'boolean';
72
+ if (typeof value === 'number') return 'number';
73
+ return 'text';
74
+ }
75
+
76
+ function getControlOptions(argType: ArgType): string[] | undefined {
77
+ if (argType && typeof argType.control === 'object') {
78
+ return argType.control.options;
79
+ }
80
+ return undefined;
81
+ }
82
+
83
+ function getControlConfig(argType: ArgType): { min?: number; max?: number; step?: number } {
84
+ if (argType && typeof argType.control === 'object') {
85
+ return { min: argType.control.min, max: argType.control.max, step: argType.control.step };
86
+ }
87
+ return {};
88
+ }
89
+
90
+ function isFunctionType(argType: ArgType): boolean {
91
+ const typeName = typeof argType.type === 'string' ? argType.type : argType.type?.name ?? '';
92
+ return typeName.includes('=>') || typeName.toLowerCase() === 'function' || typeName.startsWith('(');
93
+ }
94
+
95
+ export function bangProp(name: string) {
96
+ bangRefs[name]?.bang();
97
+ }
98
+
99
+ function updateArg(key: string, value: unknown) {
100
+ onchange?.({ ...args, [key]: value });
101
+ }
102
+
103
+ function handleInput(key: string, event: Event) {
104
+ const target = event.target as HTMLInputElement;
105
+ const argType = argTypes[key];
106
+ const controlType = getControlType(key, argType);
107
+ const currentValue = args[key];
108
+
109
+ if (controlType === 'boolean') {
110
+ updateArg(key, target.checked);
111
+ } else if (controlType === 'number' || controlType === 'range') {
112
+ updateArg(key, Number(target.value));
113
+ } else if ((controlType === 'radio' || controlType === 'select') && typeof currentValue === 'number') {
114
+ updateArg(key, Number(target.value));
115
+ } else {
116
+ updateArg(key, target.value);
117
+ }
118
+ }
119
+ </script>
120
+
121
+ {#if propNames.length > 0}
122
+ <Table compact fixed borderless>
123
+ <Table.Head>
124
+ <Table.Row>
125
+ <Table.Header width="15%">Name</Table.Header>
126
+ <Table.Header width="18%">Type</Table.Header>
127
+ <Table.Header width="12%">Default</Table.Header>
128
+ <Table.Header width={isInteractive ? '25%' : '55%'}>Description</Table.Header>
129
+ {#if isInteractive}
130
+ <Table.Header width="30%">Control</Table.Header>
131
+ {/if}
132
+ </Table.Row>
133
+ </Table.Head>
134
+ <Table.Body>
135
+ {#each propNames as name (name)}
136
+ {@const argType = argTypes[name]}
137
+ {@const controlType = getControlType(name, argType)}
138
+ {@const options = getControlOptions(argType)}
139
+ {@const config = getControlConfig(argType)}
140
+ <Table.Row>
141
+ <Table.Cell>
142
+ <span class="prop-name">
143
+ <code>{name}</code>
144
+ {#if isRequired(argType)}
145
+ <span class="required">*</span>
146
+ {/if}
147
+ </span>
148
+ </Table.Cell>
149
+ <Table.Cell>
150
+ <code class="prop-type">{getTypeName(argType)}</code>
151
+ </Table.Cell>
152
+ <Table.Cell>
153
+ <code class="prop-default">{getDefaultValue(name, argType)}</code>
154
+ </Table.Cell>
155
+ <Table.Cell>
156
+ <span class="prop-description">{getDescription(argType)}</span>
157
+ </Table.Cell>
158
+ {#if isInteractive}
159
+ <Table.Cell>
160
+ <div class="prop-control">
161
+ {#if controlType === false && isFunctionType(argType)}
162
+ <Placeholder bind:this={bangRefs[name]} height="28px" radius={6} />
163
+ {:else if controlType === false}
164
+ <span class="no-control">-</span>
165
+ {:else if controlType === 'boolean'}
166
+ <Checkbox
167
+ checked={Boolean(args[name])}
168
+ size="s"
169
+ onchange={(v) => updateArg(name, v)}
170
+ />
171
+ {:else if controlType === 'select' && options}
172
+ <select
173
+ value={String(args[name])}
174
+ onchange={(e) => handleInput(name, e)}
175
+ >
176
+ {#each options as option (option)}
177
+ <option value={option} selected={String(args[name]) === option}>{option}</option>
178
+ {/each}
179
+ </select>
180
+ {:else if controlType === 'radio' && options}
181
+ <SegmentControl
182
+ {options}
183
+ value={String(args[name])}
184
+ size="s"
185
+ onchange={(v) => updateArg(name, typeof args[name] === 'number' ? Number(v) : v)}
186
+ />
187
+ {:else if controlType === 'number'}
188
+ <InputNumber
189
+ value={Number(args[name])}
190
+ min={config.min}
191
+ max={config.max}
192
+ step={config.step}
193
+ size="s"
194
+ oninput={(v) => updateArg(name, v)}
195
+ />
196
+ {:else if controlType === 'range'}
197
+ <div class="range-control">
198
+ <input
199
+ type="range"
200
+ value={Number(args[name])}
201
+ min={config.min ?? 0}
202
+ max={config.max ?? 100}
203
+ step={config.step ?? 1}
204
+ oninput={(e) => handleInput(name, e)}
205
+ />
206
+ <span class="range-value">{args[name]}</span>
207
+ </div>
208
+ {:else if controlType === 'color'}
209
+ <input
210
+ type="color"
211
+ value={String(args[name])}
212
+ oninput={(e) => handleInput(name, e)}
213
+ />
214
+ {:else}
215
+ <InputText
216
+ value={String(args[name])}
217
+ size="s"
218
+ oninput={(v: string) => updateArg(name, v)}
219
+ />
220
+ {/if}
221
+ </div>
222
+ </Table.Cell>
223
+ {/if}
224
+ </Table.Row>
225
+ {/each}
226
+ </Table.Body>
227
+ </Table>
228
+ {:else}
229
+ <p class="no-props">No props defined</p>
230
+ {/if}
231
+
232
+ <style>
233
+ .prop-name {
234
+ white-space: nowrap;
235
+ }
236
+
237
+ .prop-name code {
238
+ font-family: var(--font-mono);
239
+ font-weight: 600;
240
+ color: var(--color-text);
241
+ background: none;
242
+ padding: 0;
243
+ }
244
+
245
+ .required {
246
+ color: var(--danger-500);
247
+ margin-left: 2px;
248
+ }
249
+
250
+ .prop-type {
251
+ font-family: var(--font-mono);
252
+ color: var(--pink-600);
253
+ background: var(--pink-50);
254
+ padding: 2px 6px;
255
+ border-radius: 4px;
256
+ font-size: 12px;
257
+ white-space: nowrap;
258
+ }
259
+
260
+ .prop-default {
261
+ font-family: var(--font-mono);
262
+ color: var(--color-text-secondary);
263
+ background: var(--color-bg-hover);
264
+ padding: 2px 6px;
265
+ border-radius: 4px;
266
+ font-size: 12px;
267
+ white-space: nowrap;
268
+ }
269
+
270
+ .prop-description {
271
+ color: var(--color-text-secondary);
272
+ line-height: 1.5;
273
+ }
274
+
275
+ .no-props {
276
+ color: var(--color-text-muted);
277
+ font-style: italic;
278
+ margin: 0;
279
+ }
280
+
281
+ /* Control column */
282
+ .prop-control {
283
+ overflow: hidden;
284
+ }
285
+
286
+ .prop-control :global(input.InputText) {
287
+ width: 100%;
288
+ max-width: 100%;
289
+ box-sizing: border-box;
290
+ }
291
+
292
+ .prop-control input[type='color'] {
293
+ width: 32px;
294
+ height: 28px;
295
+ border: 1px solid var(--color-border);
296
+ border-radius: 4px;
297
+ cursor: pointer;
298
+ padding: 2px;
299
+ }
300
+
301
+ .prop-control select {
302
+ width: 100%;
303
+ max-width: 160px;
304
+ height: 28px;
305
+ padding: 0 8px;
306
+ border: 1px solid var(--color-border);
307
+ border-radius: 4px;
308
+ font-size: 12px;
309
+ font-family: var(--font-mono);
310
+ background: var(--color-bg-elevated);
311
+ color: var(--color-text);
312
+ cursor: pointer;
313
+ }
314
+
315
+ .prop-control select:focus {
316
+ outline: none;
317
+ border-color: var(--color-primary);
318
+ }
319
+
320
+ .range-control {
321
+ display: flex;
322
+ align-items: center;
323
+ gap: 8px;
324
+ }
325
+
326
+ .range-control input[type='range'] {
327
+ flex: 1;
328
+ accent-color: var(--action-500);
329
+ }
330
+
331
+ .range-value {
332
+ min-width: 32px;
333
+ font-size: 12px;
334
+ color: var(--color-text-secondary);
335
+ font-weight: 500;
336
+ text-align: right;
337
+ }
338
+
339
+ .no-control {
340
+ color: var(--color-text-muted);
341
+ }
342
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { ArgTypes } from '../types.js';
2
+ interface Props {
3
+ argTypes: ArgTypes;
4
+ args: Record<string, unknown>;
5
+ /** Callback when args change (enables interactive controls) */
6
+ onchange?: (args: Record<string, unknown>) => void;
7
+ }
8
+ declare const PropsTable: import("svelte").Component<Props, {
9
+ bangProp: (name: string) => void;
10
+ }, "">;
11
+ type PropsTable = ReturnType<typeof PropsTable>;
12
+ export default PropsTable;
@@ -0,0 +1,130 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { ArgType, CssProps, MethodType } from '../types.js';
4
+ import PropsTable from './PropsTable.svelte';
5
+ import CssPropsTable from './CssPropsTable.svelte';
6
+ import MethodsTable from './MethodsTable.svelte';
7
+ import { CodeBlock, CollapsiblePanel } from '../ui/index.js';
8
+ import ComponentPreview from './ComponentPreview.svelte';
9
+
10
+ interface Props {
11
+ /** The render function for the component preview */
12
+ render: Snippet<[Record<string, unknown>]>;
13
+ /** Current args values */
14
+ args: Record<string, unknown>;
15
+ /** Arg type definitions for controls and props table */
16
+ argTypes?: Record<string, ArgType>;
17
+ /** CSS custom properties that can be set on the component */
18
+ cssProps?: CssProps;
19
+ /** Exported component methods */
20
+ methods?: MethodType[];
21
+ /** Callback when args change */
22
+ onchange?: (args: Record<string, unknown>) => void;
23
+ /** Optional source code to display */
24
+ source?: string;
25
+ }
26
+
27
+ let {
28
+ render,
29
+ args,
30
+ argTypes = {},
31
+ cssProps,
32
+ methods,
33
+ onchange,
34
+ source
35
+ }: Props = $props();
36
+
37
+ // State for CSS prop values
38
+ let cssValues = $state<Record<string, string>>({});
39
+
40
+ // Expand source to include CSS props when they're set
41
+ let expandedSource = $derived.by(() => {
42
+ if (!source) return source;
43
+
44
+ const activeCssProps = Object.entries(cssValues).filter(([_, v]) => v);
45
+ if (activeCssProps.length === 0) return source;
46
+
47
+ // Build CSS props string with proper indentation
48
+ const cssPropsStr = activeCssProps
49
+ .map(([k, v]) => `\t${k}="${v}"`)
50
+ .join('\n');
51
+
52
+ // Insert before the closing /> (self-closing tag)
53
+ return source.replace(/(\n?\t*)(\/>)/, `\n${cssPropsStr}$1$2`);
54
+ });
55
+
56
+ let propsTableRef: PropsTable | undefined;
57
+
58
+ function isFunctionType(argType: ArgType): boolean {
59
+ const typeName = typeof argType.type === 'string' ? argType.type : argType.type?.name ?? '';
60
+ return typeName.includes('=>') || typeName.toLowerCase() === 'function' || typeName.startsWith('(');
61
+ }
62
+
63
+ // Create wrapper functions for function-type props that trigger bang in PropsTable
64
+ let renderArgs = $derived.by(() => {
65
+ const result = { ...args };
66
+ for (const [name, argType] of Object.entries(argTypes)) {
67
+ if (argType.control === false && isFunctionType(argType)) {
68
+ result[name] = (...fnArgs: unknown[]) => {
69
+ propsTableRef?.bangProp(name);
70
+ };
71
+ }
72
+ }
73
+ return result;
74
+ });
75
+
76
+ function handleArgsChange(newArgs: Record<string, unknown>) {
77
+ onchange?.(newArgs);
78
+ }
79
+
80
+ function handleCssChange(newValues: Record<string, string>) {
81
+ cssValues = newValues;
82
+ }
83
+
84
+ let hasProps = $derived(Object.keys(argTypes).length > 0);
85
+ let hasCssProps = $derived(cssProps && Object.keys(cssProps).length > 0);
86
+ let hasMethods = $derived(methods && methods.length > 0);
87
+ </script>
88
+
89
+ <div class="Showcase">
90
+ <ComponentPreview cssVars={cssValues}>
91
+ {@render render(renderArgs)}
92
+ </ComponentPreview>
93
+
94
+ {#if hasProps}
95
+ <CollapsiblePanel title="Props" no_content_padding>
96
+ <PropsTable bind:this={propsTableRef} {argTypes} {args} onchange={onchange ? handleArgsChange : undefined} />
97
+ </CollapsiblePanel>
98
+ {/if}
99
+
100
+ {#if hasCssProps && cssProps}
101
+ <CollapsiblePanel title="CSS Props" no_content_padding>
102
+ <CssPropsTable {cssProps} values={cssValues} onchange={handleCssChange} />
103
+ </CollapsiblePanel>
104
+ {/if}
105
+
106
+ {#if hasMethods && methods}
107
+ <CollapsiblePanel title="Methods" no_content_padding>
108
+ <MethodsTable {methods} />
109
+ </CollapsiblePanel>
110
+ {/if}
111
+
112
+ {#if expandedSource}
113
+ <CollapsiblePanel title="Code" open={false} no_content_padding>
114
+ <CodeBlock code={expandedSource} />
115
+ </CollapsiblePanel>
116
+ {/if}
117
+ </div>
118
+
119
+ <style>
120
+ .Showcase {
121
+ display: flex;
122
+ flex-direction: column;
123
+ gap: 1px;
124
+ background: var(--color-border);
125
+ border: 1px solid var(--color-border);
126
+ border-radius: 8px;
127
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
128
+ overflow: hidden;
129
+ }
130
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { ArgType, CssProps, MethodType } from '../types.js';
3
+ interface Props {
4
+ /** The render function for the component preview */
5
+ render: Snippet<[Record<string, unknown>]>;
6
+ /** Current args values */
7
+ args: Record<string, unknown>;
8
+ /** Arg type definitions for controls and props table */
9
+ argTypes?: Record<string, ArgType>;
10
+ /** CSS custom properties that can be set on the component */
11
+ cssProps?: CssProps;
12
+ /** Exported component methods */
13
+ methods?: MethodType[];
14
+ /** Callback when args change */
15
+ onchange?: (args: Record<string, unknown>) => void;
16
+ /** Optional source code to display */
17
+ source?: string;
18
+ }
19
+ declare const Showcase: import("svelte").Component<Props, {}, "">;
20
+ type Showcase = ReturnType<typeof Showcase>;
21
+ export default Showcase;
@@ -0,0 +1,162 @@
1
+ import type { Component, Snippet } from 'svelte';
2
+ /**
3
+ * Control types for the props panel
4
+ */
5
+ export type ControlType = 'text' | 'number' | 'boolean' | 'select' | 'radio' | 'color' | 'range';
6
+ /**
7
+ * Control configuration for a single arg
8
+ */
9
+ export interface ArgType {
10
+ /** Control type or false to disable control (prop still shows in table) */
11
+ control: ControlType | {
12
+ type: ControlType;
13
+ options?: string[];
14
+ min?: number;
15
+ max?: number;
16
+ step?: number;
17
+ } | false;
18
+ /** Description of the prop */
19
+ description?: string;
20
+ /** Type information for the props table */
21
+ type?: {
22
+ name: string;
23
+ summary?: string;
24
+ };
25
+ /** Whether this prop is required */
26
+ required?: boolean;
27
+ /** Default value for display in props table */
28
+ defaultValue?: unknown;
29
+ }
30
+ /**
31
+ * Map of prop names to their ArgType configuration
32
+ */
33
+ export type ArgTypes = Record<string, ArgType>;
34
+ /**
35
+ * Control types for CSS custom properties
36
+ */
37
+ export type CssControlType = 'color' | 'text' | 'length' | 'number' | 'select';
38
+ /**
39
+ * Configuration for a CSS custom property
40
+ */
41
+ export interface CssPropType {
42
+ /** Description of the CSS prop */
43
+ description?: string;
44
+ /** Default value */
45
+ default?: string;
46
+ /** Control type or config. Use false to disable control. */
47
+ control?: CssControlType | {
48
+ type: CssControlType;
49
+ options?: string[];
50
+ } | false;
51
+ }
52
+ /**
53
+ * Map of CSS prop names to their configuration
54
+ */
55
+ export type CssProps = Record<string, CssPropType>;
56
+ /**
57
+ * Exported component method
58
+ */
59
+ export interface MethodType {
60
+ name: string;
61
+ params?: string;
62
+ returnType?: string;
63
+ description?: string;
64
+ }
65
+ /**
66
+ * Metadata exported from a .docs.svelte or .docs.svx file
67
+ */
68
+ export interface DocMeta {
69
+ title?: string;
70
+ /** Component description (extracted from JSDoc) */
71
+ description?: string;
72
+ /** Component to document (if this is a component doc) */
73
+ component?: Component<any>;
74
+ /** Initial values for props (only for props that exist in the component) */
75
+ args?: Record<string, unknown>;
76
+ }
77
+ /**
78
+ * Parsed metadata with auto-generated fields (internal use)
79
+ */
80
+ export interface ParsedDocMeta extends DocMeta {
81
+ /** Auto-generated from component props */
82
+ args?: Record<string, unknown>;
83
+ /** Auto-generated from component interface Props */
84
+ argTypes?: Record<string, ArgType>;
85
+ /** Auto-generated from @cssvar JSDoc tags */
86
+ cssProps?: CssProps;
87
+ /** Auto-generated from exported functions */
88
+ methods?: MethodType[];
89
+ }
90
+ /**
91
+ * A single example extracted from a doc file
92
+ */
93
+ export interface Example {
94
+ name: string;
95
+ render: Snippet<[args: Record<string, unknown>]> | Snippet<[]>;
96
+ /** Source code of the snippet (extracted by vite plugin) */
97
+ source?: string;
98
+ }
99
+ /**
100
+ * Parsed doc file with metadata and examples
101
+ */
102
+ export interface DocFile {
103
+ path: string;
104
+ meta: ParsedDocMeta;
105
+ examples: Example[];
106
+ module: Record<string, unknown>;
107
+ /** Type of doc: 'component' has a component in meta, 'page' is standalone documentation */
108
+ type: 'component' | 'page';
109
+ /** Whether this file is a markdown (.svx) file */
110
+ isMarkdown?: boolean;
111
+ }
112
+ /**
113
+ * Sidebar configuration options
114
+ */
115
+ export interface SidebarOptions {
116
+ /**
117
+ * Custom order for sidebar items. Use '*' for "everything else" (alphabetically).
118
+ *
119
+ * Can be an array for top-level ordering, or an object for nested folder ordering.
120
+ * Use path keys (e.g., 'Components/Forms') for deep nesting.
121
+ * @example
122
+ * // Top-level only
123
+ * order: ['Specs', 'Components', '*']
124
+ *
125
+ * // With nested folder ordering
126
+ * order: {
127
+ * root: ['Specs', '*'],
128
+ * Specs: ['Sidebar', 'Doc Files', '*'],
129
+ * 'Components/Forms': ['Input', 'Select', '*']
130
+ * }
131
+ */
132
+ order?: string[] | Record<string, string[]>;
133
+ /**
134
+ * Paths to expand by default in the sidebar.
135
+ * @example
136
+ * open: ['Layout', 'Layout/Frame', 'Components']
137
+ */
138
+ open?: string[];
139
+ }
140
+ /**
141
+ * Sdocs configuration options
142
+ */
143
+ export interface SdocsOptions {
144
+ /** Sidebar configuration */
145
+ sidebar?: SidebarOptions;
146
+ }
147
+ /**
148
+ * Props for the main Sdocs component
149
+ */
150
+ export interface SdocsProps {
151
+ /**
152
+ * Configuration options for Sdocs.
153
+ * @example
154
+ * options: {
155
+ * sidebar: {
156
+ * order: { root: ['Layout', '*'] },
157
+ * open: ['Layout']
158
+ * }
159
+ * }
160
+ */
161
+ options?: SdocsOptions;
162
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};