leshi-ui
Version:
Modern CLI for building and managing React Native UI components with copy-paste simplicity, custom theming, and open source design system support
118 lines (117 loc) • 4.88 kB
JavaScript
import { Command } from 'commander';
import { ComponentRegistryService } from '../services/component-registry.js';
import { GitHubProjectService } from '../services/github-project-service.js';
import { Logger } from '../utils/logger.js';
import { colors, icons } from '../utils/colors.js';
export function createListCommand() {
return new Command('list')
.alias('ls')
.description('List available components and themes');
}
export function createListComponentCommand() {
return new Command('component')
.description('List all available components')
.option('--rn', 'Show React Native StyleSheet components (default)')
.option('--unistyles', 'Show Unistyles components')
.action(async (options) => {
try {
await listComponents(options);
}
catch (error) {
Logger.error(`Failed to list components: ${error instanceof Error ? error.message : 'Unknown error'}`);
process.exit(1);
}
});
}
export function createListThemeCommand() {
return new Command('theme')
.description('List all available themes')
.option('--rn', 'Show React Native StyleSheet themes (default)')
.option('--unistyles', 'Show Unistyles themes')
.action(async (options) => {
try {
await listThemes(options);
}
catch (error) {
Logger.error(`Failed to list themes: ${error instanceof Error ? error.message : 'Unknown error'}`);
process.exit(1);
}
});
}
async function listComponents(options) {
let framework = 'rn';
if (options.unistyles) {
framework = 'unistyles';
}
Logger.title(`${icons.list} Available Components`);
Logger.subtitle(`Framework: ${framework === 'rn' ? 'React Native StyleSheet' : 'Unistyles'}`);
Logger.break();
try {
const components = await ComponentRegistryService.getComponentsWithDetails();
if (components.length === 0) {
Logger.warning('No components found');
return;
}
Logger.log(`${colors.bold('Component'.padEnd(20))} ${colors.bold('Dependencies'.padEnd(25))} ${colors.bold('External Deps')}`);
Logger.log('─'.repeat(70));
components.forEach(comp => {
const name = comp.name.padEnd(20);
const deps = (comp.dependencies || 'None').padEnd(25);
const hasExternalDeps = comp.externalDeps ? icons.success : '─';
Logger.log(`${colors.primary(name)} ${colors.dim(deps)} ${hasExternalDeps}`);
});
Logger.break();
Logger.tip(`Add a component: ${colors.primary('npx leshi-ui@latest add component button')}`);
Logger.tip(`View component guide: ${colors.primary('npx leshi-ui@latest guide component button')}`);
}
catch (error) {
Logger.error('Failed to load components');
throw error;
}
}
async function listThemes(options) {
let framework = 'rn';
if (options.unistyles) {
framework = 'unistyles';
}
Logger.title(`${icons.theme} Available Themes`);
Logger.subtitle(`Framework: ${framework === 'rn' ? 'React Native StyleSheet' : 'Unistyles'}`);
Logger.break();
try {
const themes = await GitHubProjectService.getAvailableThemes(framework);
if (themes.length === 0) {
Logger.warning('No themes found');
return;
}
const lightThemes = themes.filter(theme => theme.includes('light') || (!theme.includes('dark') && !theme.includes('spotify')));
const darkThemes = themes.filter(theme => theme.includes('dark'));
const specialThemes = themes.filter(theme => theme.includes('spotify') || (!theme.includes('light') && !theme.includes('dark') && !lightThemes.includes(theme)));
if (lightThemes.length > 0) {
Logger.log(`${colors.bold('Light Themes:')}`);
lightThemes.forEach(theme => {
Logger.log(` • ${colors.primary(theme)}`);
});
Logger.break();
}
if (darkThemes.length > 0) {
Logger.log(`${colors.bold('Dark Themes:')}`);
darkThemes.forEach(theme => {
Logger.log(` • ${colors.primary(theme)}`);
});
Logger.break();
}
if (specialThemes.length > 0) {
Logger.log(`${colors.bold('Special Themes:')}`);
specialThemes.forEach(theme => {
Logger.log(` • ${colors.primary(theme)}`);
});
Logger.break();
}
Logger.tip(`Add a theme: ${colors.primary('npx leshi-ui@latest add theme ocean-dark')}`);
Logger.tip(`Learn about themes: ${colors.primary('npx leshi-ui@latest guide theme')}`);
}
catch (error) {
Logger.error('Failed to load themes');
throw error;
}
}