----
-
-## Component Library
-
-Interactive documentation for Superset's UI component library. **${totalComponents} components** documented across ${Object.keys(categories).filter(k => categories[k].length > 0).length} categories.
-
-${categoryList}
-
## Usage
All components are exported from \`@superset-ui/core/components\`:
@@ -1332,6 +1335,147 @@ ${sections}
`;
}
+/**
+ * Build metadata for a component (for JSON output)
+ */
+function buildComponentMetadata(component, storyContent) {
+ const { componentName, description, category, sourceConfig, resolvedImportPath, extensionCompatible } = component;
+ const { args, controls, gallery, liveExample } = extractArgsAndControls(storyContent, componentName);
+ const labels = CATEGORY_LABELS[category] || {
+ title: category.charAt(0).toUpperCase() + category.slice(1).replace(/-/g, ' '),
+ };
+
+ return {
+ name: componentName,
+ category,
+ categoryLabel: labels.title || category,
+ description: description || '',
+ importPath: resolvedImportPath || sourceConfig.importPrefix,
+ package: sourceConfig.docImportPrefix,
+ extensionCompatible: Boolean(extensionCompatible),
+ propsCount: Object.keys(args).length,
+ controlsCount: controls.length,
+ hasGallery: Boolean(gallery && gallery.sizes && gallery.styles),
+ hasLiveExample: Boolean(liveExample),
+ docPath: `developer-docs/components/${category}/${componentName.toLowerCase()}`,
+ storyFile: component.relativePath,
+ };
+}
+
+/**
+ * Extract type and component export declarations from a component source file.
+ * Used to generate .d.ts type declarations for extension-compatible components.
+ */
+function extractComponentTypes(componentPath) {
+ if (!fs.existsSync(componentPath)) return null;
+ const content = fs.readFileSync(componentPath, 'utf-8');
+
+ const types = [];
+ // Match "export type Name = {pkg}
+ ),
+ },
+ {
+ title: 'Tags',
+ key: 'tags',
+ width: 280,
+ filters: [
+ { text: 'Extension Compatible', value: 'extension' },
+ { text: 'Gallery', value: 'gallery' },
+ { text: 'Live Demo', value: 'demo' },
+ ],
+ onFilter: (value: React.Key | boolean, record: ComponentEntry) => {
+ switch (value) {
+ case 'extension':
+ return record.extensionCompatible;
+ case 'gallery':
+ return record.hasGallery;
+ case 'demo':
+ return record.hasLiveExample;
+ default:
+ return true;
+ }
+ },
+ render: (_: unknown, record: ComponentEntry) => (
+