sdocs 0.0.15 → 0.0.17

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 (133) hide show
  1. package/bin/sdocs.js +1 -1
  2. package/dist/client/App.svelte +16 -39
  3. package/dist/client/App.svelte.d.ts +1 -1
  4. package/dist/client/favicon.png +0 -0
  5. package/dist/client/tree-builder.js +57 -14
  6. package/dist/client/{CollapsiblePanel.svelte → views/CollapsiblePanel.svelte} +5 -5
  7. package/dist/client/{ComponentView.svelte → views/ComponentView.svelte} +39 -13
  8. package/dist/client/{ComponentView.svelte.d.ts → views/ComponentView.svelte.d.ts} +1 -1
  9. package/dist/client/{ControlsPanel.svelte → views/ControlsPanel.svelte} +10 -15
  10. package/dist/client/{ControlsPanel.svelte.d.ts → views/ControlsPanel.svelte.d.ts} +1 -1
  11. package/dist/client/{DataTable.svelte → views/DataTable.svelte} +8 -8
  12. package/dist/client/{HomePage.svelte → views/HomePage.svelte} +10 -8
  13. package/dist/client/{HomePage.svelte.d.ts → views/HomePage.svelte.d.ts} +1 -1
  14. package/dist/client/{LayoutView.svelte → views/LayoutView.svelte} +1 -1
  15. package/dist/client/{LayoutView.svelte.d.ts → views/LayoutView.svelte.d.ts} +1 -1
  16. package/dist/client/{PageView.svelte → views/PageView.svelte} +7 -7
  17. package/dist/client/{PageView.svelte.d.ts → views/PageView.svelte.d.ts} +1 -1
  18. package/dist/client/{PreviewFrame.svelte → views/PreviewFrame.svelte} +10 -3
  19. package/dist/client/views/Sidebar.svelte +369 -0
  20. package/dist/client/{Sidebar.svelte.d.ts → views/Sidebar.svelte.d.ts} +2 -2
  21. package/dist/commands/build.js +2 -2
  22. package/dist/commands/dev.js +2 -2
  23. package/dist/commands/init.js +4 -4
  24. package/dist/commands/preview.js +1 -1
  25. package/dist/{app-gen.d.ts → server/app-gen.d.ts} +1 -1
  26. package/dist/{app-gen.js → server/app-gen.js} +4 -4
  27. package/dist/{cli.js → server/cli.js} +4 -4
  28. package/dist/{config.d.ts → server/config.d.ts} +1 -1
  29. package/dist/{config.js → server/config.js} +7 -2
  30. package/dist/server/discovery.d.ts +1 -1
  31. package/dist/server/discovery.js +1 -1
  32. package/dist/server/meta-parser.js +1 -1
  33. package/dist/server/prop-parser.js +12 -4
  34. package/dist/server/snippet-compiler.js +8 -0
  35. package/dist/server/snippet-extractor.d.ts +1 -1
  36. package/dist/server/snippet-extractor.js +40 -5
  37. package/dist/server/toc-extractor.d.ts +0 -2
  38. package/dist/server/toc-extractor.js +0 -14
  39. package/dist/types.d.ts +3 -3
  40. package/dist/ui/About.page.sdoc +37 -0
  41. package/dist/ui/Button/Button.sdoc +51 -0
  42. package/dist/ui/Button/Button.svelte +90 -0
  43. package/dist/ui/Button/Button.svelte.d.ts +27 -0
  44. package/dist/ui/Button/index.d.ts +1 -0
  45. package/dist/ui/Button/index.js +1 -0
  46. package/dist/ui/Control/Checkbox.sdoc +17 -0
  47. package/dist/{client/controls/CheckboxControl.svelte → ui/Control/Checkbox.svelte} +1 -1
  48. package/dist/ui/Control/Checkbox.svelte.d.ts +8 -0
  49. package/dist/ui/Control/Color.sdoc +17 -0
  50. package/dist/{client/controls/ColorControl.svelte → ui/Control/Color.svelte} +4 -4
  51. package/dist/ui/Control/Color.svelte.d.ts +8 -0
  52. package/dist/ui/Control/Dimension.sdoc +17 -0
  53. package/dist/{client/controls/DimensionControl.svelte → ui/Control/Dimension.svelte} +5 -5
  54. package/dist/ui/Control/Dimension.svelte.d.ts +8 -0
  55. package/dist/ui/Control/Number.sdoc +17 -0
  56. package/dist/{client/controls/NumberControl.svelte → ui/Control/Number.svelte} +4 -4
  57. package/dist/ui/Control/Number.svelte.d.ts +8 -0
  58. package/dist/ui/Control/Select.sdoc +18 -0
  59. package/dist/{client/controls/SelectControl.svelte → ui/Control/Select.svelte} +4 -4
  60. package/dist/ui/Control/Select.svelte.d.ts +9 -0
  61. package/dist/ui/Control/Text.sdoc +17 -0
  62. package/dist/{client/controls/TextControl.svelte → ui/Control/Text.svelte} +4 -4
  63. package/dist/ui/Control/Text.svelte.d.ts +8 -0
  64. package/dist/ui/Control/index.d.ts +6 -0
  65. package/dist/ui/Control/index.js +6 -0
  66. package/dist/ui/Dashboard.layout.sdoc +60 -0
  67. package/dist/ui/Frame/Frame.sdoc +54 -0
  68. package/dist/ui/Frame/Frame.svelte +88 -0
  69. package/dist/ui/Frame/Frame.svelte.d.ts +15 -0
  70. package/dist/ui/Frame/index.d.ts +1 -0
  71. package/dist/ui/Frame/index.js +1 -0
  72. package/dist/ui/Icon/Icon.sdoc +45 -0
  73. package/dist/ui/Icon/Icon.svelte +73 -0
  74. package/dist/ui/Icon/Icon.svelte.d.ts +16 -0
  75. package/dist/ui/Icon/icons/bookmark.svg +1 -0
  76. package/dist/ui/Icon/icons/chevron-down.svg +1 -0
  77. package/dist/ui/Icon/icons/chevron-left.svg +1 -0
  78. package/dist/ui/Icon/icons/chevron-right.svg +1 -0
  79. package/dist/ui/Icon/icons/chevron-up.svg +1 -0
  80. package/dist/ui/Icon/icons/code.svg +1 -0
  81. package/dist/ui/Icon/icons/component.svg +1 -0
  82. package/dist/ui/Icon/icons/copy.svg +1 -0
  83. package/dist/ui/Icon/icons/diamond.svg +1 -0
  84. package/dist/ui/Icon/icons/file-code.svg +1 -0
  85. package/dist/ui/Icon/icons/file-text.svg +1 -0
  86. package/dist/ui/Icon/icons/folder-open.svg +1 -0
  87. package/dist/ui/Icon/icons/folder.svg +1 -0
  88. package/dist/ui/Icon/icons/panels-top-left.svg +1 -0
  89. package/dist/ui/Icon/icons/sdocs.svg +8 -0
  90. package/dist/ui/Icon/index.d.ts +1 -0
  91. package/dist/ui/Icon/index.js +1 -0
  92. package/dist/ui/NavTree/Group.sdoc +46 -0
  93. package/dist/ui/NavTree/Group.svelte +82 -0
  94. package/dist/ui/NavTree/Group.svelte.d.ts +11 -0
  95. package/dist/ui/NavTree/Item.sdoc +70 -0
  96. package/dist/ui/NavTree/Item.svelte +164 -0
  97. package/dist/ui/NavTree/Item.svelte.d.ts +33 -0
  98. package/dist/ui/NavTree/NavTree.sdoc +119 -0
  99. package/dist/ui/NavTree/NavTree.svelte +31 -0
  100. package/dist/ui/NavTree/NavTree.svelte.d.ts +8 -0
  101. package/dist/ui/NavTree/index.js +6 -0
  102. package/dist/ui/Stack/Stack.sdoc +44 -0
  103. package/dist/ui/Stack/Stack.svelte +41 -0
  104. package/dist/ui/Stack/Stack.svelte.d.ts +19 -0
  105. package/dist/ui/Stack/index.d.ts +1 -0
  106. package/dist/ui/Stack/index.js +1 -0
  107. package/dist/ui/index.d.ts +6 -0
  108. package/dist/ui/index.js +6 -0
  109. package/dist/{client/theme.css → ui/styles/fonts.css} +0 -37
  110. package/dist/ui/styles/theme.css +910 -0
  111. package/dist/vite.js +47 -51
  112. package/package.json +5 -2
  113. package/dist/client/Sidebar.svelte +0 -329
  114. package/dist/client/controls/CheckboxControl.svelte.d.ts +0 -8
  115. package/dist/client/controls/ColorControl.svelte.d.ts +0 -8
  116. package/dist/client/controls/DimensionControl.svelte.d.ts +0 -8
  117. package/dist/client/controls/NumberControl.svelte.d.ts +0 -8
  118. package/dist/client/controls/SelectControl.svelte.d.ts +0 -9
  119. package/dist/client/controls/TextControl.svelte.d.ts +0 -8
  120. package/dist/server/sdocx-parser.d.ts +0 -11
  121. package/dist/server/sdocx-parser.js +0 -197
  122. /package/dist/client/{CollapsiblePanel.svelte.d.ts → views/CollapsiblePanel.svelte.d.ts} +0 -0
  123. /package/dist/client/{DataTable.svelte.d.ts → views/DataTable.svelte.d.ts} +0 -0
  124. /package/dist/client/{PreviewFrame.svelte.d.ts → views/PreviewFrame.svelte.d.ts} +0 -0
  125. /package/dist/{cli.d.ts → server/cli.d.ts} +0 -0
  126. /package/dist/{client → ui/styles}/fonts/figtree-italic-latin-ext.woff2 +0 -0
  127. /package/dist/{client → ui/styles}/fonts/figtree-italic-latin.woff2 +0 -0
  128. /package/dist/{client → ui/styles}/fonts/figtree-latin-ext.woff2 +0 -0
  129. /package/dist/{client → ui/styles}/fonts/figtree-latin.woff2 +0 -0
  130. /package/dist/{client → ui/styles}/fonts/jetbrains-mono-italic-latin-ext.woff2 +0 -0
  131. /package/dist/{client → ui/styles}/fonts/jetbrains-mono-italic-latin.woff2 +0 -0
  132. /package/dist/{client → ui/styles}/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
  133. /package/dist/{client → ui/styles}/fonts/jetbrains-mono-latin.woff2 +0 -0
package/dist/vite.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { readFile } from 'node:fs/promises';
2
- import { loadConfig, resolveConfig } from './config.js';
2
+ import { loadConfig, resolveConfig } from './server/config.js';
3
3
  import { discoverDocFiles, getSdocKind } from './server/discovery.js';
4
4
  import { parseDocSource } from './server/meta-parser.js';
5
5
  import { parseComponent } from './server/prop-parser.js';
6
6
  import { extractSnippets, extractMarkupBody, hasDefaultSnippet, generateAutoDefault, } from './server/snippet-extractor.js';
7
7
  import { highlight, disposeHighlighter } from './server/highlighter.js';
8
8
  import { extractTocFromHtml } from './server/toc-extractor.js';
9
- import { parseSdocx } from './server/sdocx-parser.js';
10
9
  import { parseIframeId, parsePreviewUrl, resolveImportsToAbsolute, generateIframeComponent, generatePreviewHtml, iframeVirtualId, previewUrl, buildPreviewUrl, } from './server/snippet-compiler.js';
11
10
  const VIRTUAL_MODULE_ID = 'virtual:sdocs';
12
11
  const RESOLVED_VIRTUAL_ID = '\0virtual:sdocs';
@@ -68,7 +67,7 @@ export function sdocsPlugin(userConfig) {
68
67
  if (isDocFile(filePath)) {
69
68
  console.log(`[sdocs] New doc file: ${filePath}`);
70
69
  await processDocFile(filePath);
71
- invalidateVirtualModule();
70
+ invalidateVirtualModule(filePath);
72
71
  }
73
72
  });
74
73
  server.watcher.on('unlink', (filePath) => {
@@ -83,12 +82,12 @@ export function sdocsPlugin(userConfig) {
83
82
  if (isDocFile(filePath)) {
84
83
  console.log(`[sdocs] Doc file changed: ${filePath}`);
85
84
  await processDocFile(filePath);
86
- invalidateVirtualModule();
85
+ invalidateVirtualModule(filePath);
87
86
  }
88
87
  else if (isComponentReferencedByDoc(filePath)) {
89
88
  console.log(`[sdocs] Component changed: ${filePath}`);
90
89
  await reprocessComponentEntries(filePath);
91
- invalidateVirtualModule();
90
+ invalidateVirtualModule(filePath);
92
91
  }
93
92
  });
94
93
  },
@@ -99,6 +98,17 @@ export function sdocsPlugin(userConfig) {
99
98
  console.log(` - ${file}`);
100
99
  await processDocFile(file);
101
100
  }
101
+ // Explicitly watch doc files and their directories (outside Vite root)
102
+ if (server) {
103
+ const dirs = new Set();
104
+ for (const file of files) {
105
+ server.watcher.add(file);
106
+ dirs.add(file.substring(0, file.lastIndexOf('/')));
107
+ }
108
+ for (const dir of dirs) {
109
+ server.watcher.add(dir);
110
+ }
111
+ }
102
112
  },
103
113
  resolveId(id) {
104
114
  if (id === VIRTUAL_MODULE_ID)
@@ -134,54 +144,27 @@ export function sdocsPlugin(userConfig) {
134
144
  async function processDocFile(filePath) {
135
145
  const source = await readFile(filePath, 'utf-8');
136
146
  const kind = getSdocKind(filePath);
137
- const isSdocx = filePath.endsWith('.sdocx');
138
- let meta;
139
- let componentPath = null;
140
- let imports = [];
147
+ const parsed = parseDocSource(source, filePath);
148
+ const meta = parsed.meta;
149
+ const componentPath = parsed.componentPath;
150
+ const imports = parsed.imports;
141
151
  let snippets;
142
152
  let toc;
143
- if (isSdocx) {
144
- // Markdown format: parse with mdsvex
145
- const result = await parseSdocx(source, filePath, kind);
146
- meta = result.meta;
147
- componentPath = result.componentPath;
148
- imports = result.imports;
149
- snippets = result.snippets;
150
- toc = result.toc;
151
- // For component kind, auto-generate Default if missing
152
- if (kind === 'component') {
153
- const hasDefault = snippets.some((s) => s.name === 'Default');
154
- if (!hasDefault && componentPath) {
155
- const componentName = componentPath.split('/').pop()?.replace('.svelte', '') ?? 'Component';
156
- snippets.unshift({
157
- name: 'Default',
158
- body: generateAutoDefault(componentName),
159
- });
160
- }
153
+ if (kind === 'page' || kind === 'layout') {
154
+ const body = extractMarkupBody(source);
155
+ snippets = [{ name: 'Content', body }];
156
+ if (kind === 'page') {
157
+ toc = extractTocFromHtml(body);
161
158
  }
162
159
  }
163
160
  else {
164
- // Svelte format: existing pipeline
165
- const parsed = parseDocSource(source, filePath);
166
- meta = parsed.meta;
167
- componentPath = parsed.componentPath;
168
- imports = parsed.imports;
169
- if (kind === 'page' || kind === 'layout') {
170
- const body = extractMarkupBody(source);
171
- snippets = [{ name: 'Content', body }];
172
- if (kind === 'page') {
173
- toc = extractTocFromHtml(body);
174
- }
175
- }
176
- else {
177
- snippets = extractSnippets(source);
178
- if (!hasDefaultSnippet(snippets)) {
179
- const componentName = componentPath?.split('/').pop()?.replace('.svelte', '') ?? 'Component';
180
- snippets.unshift({
181
- name: 'Default',
182
- body: generateAutoDefault(componentName),
183
- });
184
- }
161
+ snippets = extractSnippets(source);
162
+ if (!hasDefaultSnippet(snippets)) {
163
+ const componentName = componentPath?.split('/').pop()?.replace('.svelte', '') ?? 'Component';
164
+ snippets.unshift({
165
+ name: 'Default',
166
+ body: generateAutoDefault(componentName),
167
+ });
185
168
  }
186
169
  }
187
170
  // If component is specified as a path but not imported, auto-add the import
@@ -245,17 +228,30 @@ export function sdocsPlugin(userConfig) {
245
228
  return `export const docs = ${JSON.stringify(data)};\nexport const cssNames = ${JSON.stringify(cssNames)};\nexport default docs;`;
246
229
  }
247
230
  // ─── HMR helpers ───
248
- function invalidateVirtualModule() {
231
+ function invalidateVirtualModule(docFilePath) {
249
232
  if (!server)
250
233
  return;
251
234
  const mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);
252
235
  if (mod) {
253
236
  server.moduleGraph.invalidateModule(mod);
254
- server.ws.send({ type: 'full-reload' });
255
237
  }
238
+ // Also invalidate iframe virtual modules for the changed doc file
239
+ if (docFilePath) {
240
+ const entry = docEntries.get(docFilePath);
241
+ if (entry) {
242
+ for (const snippet of entry.snippets) {
243
+ const iframeId = '\0' + iframeVirtualId(docFilePath, snippet.name);
244
+ const iframeMod = server.moduleGraph.getModuleById(iframeId);
245
+ if (iframeMod) {
246
+ server.moduleGraph.invalidateModule(iframeMod);
247
+ }
248
+ }
249
+ }
250
+ }
251
+ server.ws.send({ type: 'full-reload' });
256
252
  }
257
253
  function isDocFile(filePath) {
258
- return filePath.endsWith('.sdoc') || filePath.endsWith('.sdocx');
254
+ return filePath.endsWith('.sdoc');
259
255
  }
260
256
  function isComponentReferencedByDoc(filePath) {
261
257
  for (const entry of docEntries.values()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdocs",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "A lightweight documentation tool for Svelte 5 components",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -18,6 +18,10 @@
18
18
  },
19
19
  "./client": {
20
20
  "svelte": "./dist/client/App.svelte"
21
+ },
22
+ "./ui": {
23
+ "types": "./dist/ui/index.d.ts",
24
+ "svelte": "./dist/ui/index.js"
21
25
  }
22
26
  },
23
27
  "files": [
@@ -45,7 +49,6 @@
45
49
  "test": "vitest run"
46
50
  },
47
51
  "dependencies": {
48
- "mdsvex": "^0.12.6",
49
52
  "shiki": "^3.22.0",
50
53
  "tinyglobby": "^0.2.15",
51
54
  "typescript": "^5.7.0"
@@ -1,329 +0,0 @@
1
- <script lang="ts">
2
- import { SvelteSet } from 'svelte/reactivity';
3
- import type { TreeNode } from './tree-builder.js';
4
- import { pathToHash } from './router.svelte.js';
5
-
6
- type ThemeMode = 'light' | 'dark' | 'system';
7
-
8
- interface Props {
9
- tree: TreeNode[];
10
- currentPath: string[];
11
- logo: string;
12
- cssNames?: string[];
13
- activeStylesheet?: string;
14
- theme?: ThemeMode;
15
- onToggleFullscreen?: () => void;
16
- onStylesheetChange?: (name: string) => void;
17
- onThemeChange?: (theme: ThemeMode) => void;
18
- }
19
-
20
- let { tree, currentPath, logo, cssNames = [], activeStylesheet, theme = 'system', onToggleFullscreen, onStylesheetChange, onThemeChange }: Props = $props();
21
-
22
- const themeIcons: Record<ThemeMode, string> = { light: '\u2600', dark: '\u263D', system: '\u25D1' };
23
- const themeLabels: Record<ThemeMode, string> = { light: 'Light', dark: 'Dark', system: 'System' };
24
- const themeCycle: Record<ThemeMode, ThemeMode> = { light: 'dark', dark: 'system', system: 'light' };
25
-
26
- function cycleTheme() {
27
- onThemeChange?.(themeCycle[theme]);
28
- }
29
- let searchQuery = $state('');
30
-
31
- // Track expanded state by path key (SvelteSet for reactivity)
32
- let expandedSet = new SvelteSet<string>();
33
- let initialized = false;
34
-
35
- // Initialize expanded state from tree defaults
36
- $effect(() => {
37
- if (!initialized && tree.length > 0) {
38
- collectDefaults(tree, expandedSet);
39
- initialized = true;
40
- }
41
- });
42
-
43
- function collectDefaults(nodes: TreeNode[], set: SvelteSet<string>) {
44
- for (const node of nodes) {
45
- if (node.defaultExpanded || node.type === 'group') {
46
- set.add(node.path.join('/'));
47
- }
48
- if (node.children.length > 0) {
49
- collectDefaults(node.children, set);
50
- }
51
- }
52
- }
53
-
54
- function toggleExpanded(pathKey: string) {
55
- if (expandedSet.has(pathKey)) {
56
- expandedSet.delete(pathKey);
57
- } else {
58
- expandedSet.add(pathKey);
59
- }
60
- }
61
-
62
- function isExpanded(pathKey: string): boolean {
63
- if (searchQuery.trim()) return true; // Auto-expand when searching
64
- return expandedSet.has(pathKey);
65
- }
66
-
67
- const filteredTree = $derived(
68
- searchQuery.trim() ? filterTree(tree, searchQuery.trim().toLowerCase()) : tree,
69
- );
70
-
71
- function filterTree(nodes: TreeNode[], query: string): TreeNode[] {
72
- const result: TreeNode[] = [];
73
- for (const node of nodes) {
74
- if (node.name.toLowerCase().includes(query)) {
75
- result.push(node);
76
- } else if (node.children.length > 0) {
77
- const filtered = filterTree(node.children, query);
78
- if (filtered.length > 0) {
79
- result.push({ ...node, children: filtered });
80
- }
81
- }
82
- }
83
- return result;
84
- }
85
-
86
- function isActive(nodePath: string[]): boolean {
87
- if (nodePath.length > currentPath.length) return false;
88
- return nodePath.every((seg, i) => seg === currentPath[i]);
89
- }
90
-
91
- function isExactActive(nodePath: string[]): boolean {
92
- return nodePath.length === currentPath.length && nodePath.every((seg, i) => seg === currentPath[i]);
93
- }
94
-
95
- function nodeIcon(node: TreeNode): string {
96
- switch (node.type) {
97
- case 'component': return '◆';
98
- case 'page': return '◇';
99
- case 'layout': return '▣';
100
- case 'folder': return '▸';
101
- default: return '';
102
- }
103
- }
104
- </script>
105
-
106
- <aside class="sdocs-sidebar">
107
- <div class="sdocs-sidebar-header">
108
- <span class="sdocs-logo">{logo}</span>
109
- <div class="sdocs-header-actions">
110
- {#if cssNames.length > 1}
111
- <select
112
- class="sdocs-css-picker"
113
- value={activeStylesheet}
114
- onchange={(e) => onStylesheetChange?.(e.currentTarget.value)}
115
- >
116
- {#each cssNames as name (name)}
117
- <option value={name}>{name}</option>
118
- {/each}
119
- </select>
120
- {/if}
121
- <button class="sdocs-theme-btn" onclick={cycleTheme} title="{themeLabels[theme]} theme">
122
- {themeIcons[theme]}
123
- </button>
124
- <button class="sdocs-fullscreen-btn" onclick={() => onToggleFullscreen?.()} title="Fullscreen">
125
- &#x26F6;
126
- </button>
127
- </div>
128
- </div>
129
-
130
- <div class="sdocs-sidebar-search">
131
- <input
132
- type="text"
133
- placeholder="Search..."
134
- bind:value={searchQuery}
135
- class="sdocs-search-input"
136
- />
137
- </div>
138
-
139
- <nav class="sdocs-sidebar-tree">
140
- {#each filteredTree as node (node.path.join('/'))}
141
- {@render treeItem(node, 0)}
142
- {/each}
143
- </nav>
144
- </aside>
145
-
146
- {#snippet treeItem(node: TreeNode, depth: number)}
147
- {@const pathKey = node.path.join('/')}
148
- {@const isExpandable = node.type === 'folder' || node.type === 'group' || (node.type === 'component' && node.children.length > 0)}
149
- {@const isGroup = node.type === 'group'}
150
- {@const isSelectable = node.type === 'page' || node.type === 'layout' || (node.type === 'component' && node.children.length === 0)}
151
- {@const activeExact = isExactActive(node.path)}
152
- {@const activeContains = isActive(node.path)}
153
-
154
- <div class="sdocs-tree-item" style:--depth={depth}>
155
- {#if isGroup}
156
- <div class="sdocs-group-label">{node.name.toUpperCase()}</div>
157
- {:else if isExpandable}
158
- <button
159
- class="sdocs-tree-btn"
160
- class:sdocs-active={activeContains}
161
- onclick={() => toggleExpanded(pathKey)}
162
- >
163
- <span class="sdocs-tree-arrow" class:expanded={isExpanded(pathKey)}>&#9654;</span>
164
- <span class="sdocs-tree-icon">{nodeIcon(node)}</span>
165
- <span>{node.name}</span>
166
- </button>
167
- {:else if isSelectable}
168
- <a
169
- href={pathToHash(node.path)}
170
- class="sdocs-tree-link"
171
- class:sdocs-active={activeExact}
172
- >
173
- <span class="sdocs-tree-icon">{nodeIcon(node)}</span>
174
- <span>{node.name}</span>
175
- </a>
176
- {:else}
177
- <a
178
- href={pathToHash(node.path)}
179
- class="sdocs-tree-link"
180
- class:sdocs-active={activeExact}
181
- >
182
- <span>{node.name}</span>
183
- </a>
184
- {/if}
185
-
186
- {#if (isExpandable || isGroup) && isExpanded(pathKey)}
187
- <div class="sdocs-tree-children">
188
- {#each node.children as child (child.path.join('/'))}
189
- {@render treeItem(child, depth + 1)}
190
- {/each}
191
- </div>
192
- {/if}
193
- </div>
194
- {/snippet}
195
-
196
- <style>
197
- .sdocs-sidebar {
198
- width: 260px;
199
- height: 100vh;
200
- overflow-y: auto;
201
- border-right: 1px solid var(--sdocs-border);
202
- background: var(--sdocs-bg-subtle);
203
- display: flex;
204
- flex-direction: column;
205
- font-family: var(--sdocs-font-sans);
206
- font-size: 13px;
207
- }
208
- .sdocs-sidebar-header {
209
- padding: 12px 16px;
210
- border-bottom: 1px solid var(--sdocs-border);
211
- display: flex;
212
- align-items: center;
213
- justify-content: space-between;
214
- }
215
- .sdocs-logo {
216
- font-weight: 700;
217
- font-size: 16px;
218
- color: var(--sdocs-text-heading);
219
- }
220
- .sdocs-header-actions {
221
- display: flex;
222
- align-items: center;
223
- gap: 6px;
224
- }
225
- .sdocs-css-picker {
226
- font-size: 12px;
227
- padding: 2px 4px;
228
- border: 1px solid var(--sdocs-border);
229
- border-radius: 4px;
230
- background: var(--sdocs-bg);
231
- color: var(--sdocs-text);
232
- }
233
- .sdocs-theme-btn {
234
- padding: 2px 6px;
235
- border: 1px solid var(--sdocs-border);
236
- border-radius: 4px;
237
- background: var(--sdocs-bg);
238
- color: var(--sdocs-text);
239
- cursor: pointer;
240
- font-size: 14px;
241
- line-height: 1;
242
- }
243
- .sdocs-theme-btn:hover {
244
- background: var(--sdocs-bg-hover);
245
- }
246
- .sdocs-fullscreen-btn {
247
- padding: 2px 6px;
248
- border: 1px solid var(--sdocs-border);
249
- border-radius: 4px;
250
- background: var(--sdocs-bg);
251
- color: var(--sdocs-text);
252
- cursor: pointer;
253
- font-size: 14px;
254
- line-height: 1;
255
- }
256
- .sdocs-fullscreen-btn:hover {
257
- background: var(--sdocs-bg-hover);
258
- }
259
- .sdocs-sidebar-search {
260
- padding: 8px 16px;
261
- }
262
- .sdocs-search-input {
263
- width: 100%;
264
- padding: 6px 10px;
265
- border: 1px solid var(--sdocs-border);
266
- border-radius: 6px;
267
- font-size: 13px;
268
- outline: none;
269
- box-sizing: border-box;
270
- background: var(--sdocs-bg);
271
- color: var(--sdocs-text);
272
- }
273
- .sdocs-search-input:focus {
274
- border-color: var(--sdocs-primary);
275
- box-shadow: 0 0 0 2px var(--sdocs-primary-bg);
276
- }
277
- .sdocs-sidebar-tree {
278
- flex: 1;
279
- overflow-y: auto;
280
- padding: 8px 0;
281
- }
282
- .sdocs-tree-item {
283
- padding-left: calc(var(--depth, 0) * 16px);
284
- }
285
- .sdocs-group-label {
286
- padding: 12px 16px 4px;
287
- font-size: 11px;
288
- font-weight: 600;
289
- color: var(--sdocs-text-muted);
290
- letter-spacing: 0.05em;
291
- }
292
- .sdocs-tree-btn,
293
- .sdocs-tree-link {
294
- display: flex;
295
- align-items: center;
296
- gap: 6px;
297
- width: 100%;
298
- padding: 4px 16px;
299
- border: none;
300
- background: none;
301
- font: inherit;
302
- color: var(--sdocs-text);
303
- text-decoration: none;
304
- cursor: pointer;
305
- text-align: left;
306
- }
307
- .sdocs-tree-btn:hover,
308
- .sdocs-tree-link:hover {
309
- background: var(--sdocs-border);
310
- }
311
- .sdocs-active {
312
- color: var(--sdocs-primary);
313
- font-weight: 500;
314
- }
315
- .sdocs-tree-arrow {
316
- font-size: 8px;
317
- transition: transform 0.15s;
318
- display: inline-block;
319
- width: 10px;
320
- }
321
- .sdocs-tree-arrow.expanded {
322
- transform: rotate(90deg);
323
- }
324
- .sdocs-tree-icon {
325
- font-size: 10px;
326
- width: 14px;
327
- text-align: center;
328
- }
329
- </style>
@@ -1,8 +0,0 @@
1
- interface Props {
2
- label: string;
3
- value: boolean;
4
- onchange: (value: boolean) => void;
5
- }
6
- declare const CheckboxControl: import("svelte").Component<Props, {}, "">;
7
- type CheckboxControl = ReturnType<typeof CheckboxControl>;
8
- export default CheckboxControl;
@@ -1,8 +0,0 @@
1
- interface Props {
2
- label: string;
3
- value: string;
4
- onchange: (value: string) => void;
5
- }
6
- declare const ColorControl: import("svelte").Component<Props, {}, "">;
7
- type ColorControl = ReturnType<typeof ColorControl>;
8
- export default ColorControl;
@@ -1,8 +0,0 @@
1
- interface Props {
2
- label: string;
3
- value: string;
4
- onchange: (value: string) => void;
5
- }
6
- declare const DimensionControl: import("svelte").Component<Props, {}, "">;
7
- type DimensionControl = ReturnType<typeof DimensionControl>;
8
- export default DimensionControl;
@@ -1,8 +0,0 @@
1
- interface Props {
2
- label: string;
3
- value: number;
4
- onchange: (value: number) => void;
5
- }
6
- declare const NumberControl: import("svelte").Component<Props, {}, "">;
7
- type NumberControl = ReturnType<typeof NumberControl>;
8
- export default NumberControl;
@@ -1,9 +0,0 @@
1
- interface Props {
2
- label: string;
3
- value: string;
4
- options: string[];
5
- onchange: (value: string) => void;
6
- }
7
- declare const SelectControl: import("svelte").Component<Props, {}, "">;
8
- type SelectControl = ReturnType<typeof SelectControl>;
9
- export default SelectControl;
@@ -1,8 +0,0 @@
1
- interface Props {
2
- label: string;
3
- value: string;
4
- onchange: (value: string) => void;
5
- }
6
- declare const TextControl: import("svelte").Component<Props, {}, "">;
7
- type TextControl = ReturnType<typeof TextControl>;
8
- export default TextControl;
@@ -1,11 +0,0 @@
1
- import type { SdocMeta, ExtractedSnippet, TocHeading } from '../types.js';
2
- interface SdocxParseResult {
3
- meta: SdocMeta;
4
- componentPath: string | null;
5
- imports: string[];
6
- snippets: ExtractedSnippet[];
7
- toc?: TocHeading[];
8
- }
9
- /** Parse a .sdocx file (markdown format) */
10
- export declare function parseSdocx(source: string, filePath: string, kind: 'component' | 'page' | 'layout'): Promise<SdocxParseResult>;
11
- export {};