[READ-ONLY] Mirror of https://github.com/flo-bit/ui-kit. 🦊 fox ui, svelte 5 and tailwind 4 flo-bit.dev/ui-kit/
svelte tailwindcss ui-components
0

Configure Feed

Select the types of activity you want to include in your feed.

update cli

Florian (Mar 28, 2025, 12:33 PM +0100) 05ec15ec 1dd12aa4

+124 -57
+3 -1
.gitignore
··· 22 22 vite.config.js.timestamp-* 23 23 vite.config.ts.timestamp-* 24 24 25 - dist 25 + dist 26 + src/lib/fuchs 27 + src/lib/tmp
+45 -6
package-lock.json
··· 1 1 { 2 2 "name": "fuchs", 3 - "version": "0.0.18", 3 + "version": "0.0.25", 4 4 "lockfileVersion": 3, 5 5 "requires": true, 6 6 "packages": { 7 7 "": { 8 8 "name": "fuchs", 9 - "version": "0.0.18", 9 + "version": "0.0.25", 10 10 "license": "MIT", 11 11 "dependencies": { 12 12 "@atproto/api": "^0.14.7", 13 + "@clack/prompts": "^0.10.0", 13 14 "@number-flow/svelte": "^0.3.3", 14 15 "@sveltejs/adapter-static": "^3.0.8", 15 16 "@texel/color": "^1.1.9", ··· 22 23 "adm-zip": "^0.5.16", 23 24 "bits-ui": "^1.3.4", 24 25 "cheerio": "^1.0.0", 26 + "commander": "^13.1.0", 25 27 "hls.js": "^1.5.20", 26 28 "layerchart": "^1.0.0", 27 29 "node-fetch": "^3.3.2", 28 30 "paneforge": "^0.0.6", 29 31 "pdfjs-dist": "^5.0.375", 32 + "picocolors": "^1.1.1", 30 33 "plyr": "^3.7.8", 31 34 "simplex-noise": "^4.0.3", 32 35 "svelte-sonner": "^0.3.28", ··· 155 158 "zod": "^3.23.8" 156 159 } 157 160 }, 161 + "node_modules/@clack/core": { 162 + "version": "0.4.1", 163 + "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.4.1.tgz", 164 + "integrity": "sha512-Pxhij4UXg8KSr7rPek6Zowm+5M22rbd2g1nfojHJkxp5YkFqiZ2+YLEM/XGVIzvGOcM0nqjIFxrpDwWRZYWYjA==", 165 + "license": "MIT", 166 + "dependencies": { 167 + "picocolors": "^1.0.0", 168 + "sisteransi": "^1.0.5" 169 + } 170 + }, 171 + "node_modules/@clack/prompts": { 172 + "version": "0.10.0", 173 + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.10.0.tgz", 174 + "integrity": "sha512-H3rCl6CwW1NdQt9rE3n373t7o5cthPv7yUoxF2ytZvyvlJv89C5RYMJu83Hed8ODgys5vpBU0GKxIRG83jd8NQ==", 175 + "license": "MIT", 176 + "dependencies": { 177 + "@clack/core": "0.4.1", 178 + "picocolors": "^1.0.0", 179 + "sisteransi": "^1.0.5" 180 + } 181 + }, 158 182 "node_modules/@dagrejs/dagre": { 159 183 "version": "1.1.4", 160 184 "resolved": "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-1.1.4.tgz", ··· 3239 3263 } 3240 3264 }, 3241 3265 "node_modules/commander": { 3242 - "version": "7.2.0", 3243 - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", 3244 - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", 3266 + "version": "13.1.0", 3267 + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", 3268 + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", 3245 3269 "license": "MIT", 3246 3270 "engines": { 3247 - "node": ">= 10" 3271 + "node": ">=18" 3248 3272 } 3249 3273 }, 3250 3274 "node_modules/concat-map": { ··· 3410 3434 "node": ">=12" 3411 3435 } 3412 3436 }, 3437 + "node_modules/d3-dsv/node_modules/commander": { 3438 + "version": "7.2.0", 3439 + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", 3440 + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", 3441 + "license": "MIT", 3442 + "engines": { 3443 + "node": ">= 10" 3444 + } 3445 + }, 3413 3446 "node_modules/d3-force": { 3414 3447 "version": "3.0.0", 3415 3448 "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", ··· 6502 6535 "engines": { 6503 6536 "node": ">=18" 6504 6537 } 6538 + }, 6539 + "node_modules/sisteransi": { 6540 + "version": "1.0.5", 6541 + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", 6542 + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", 6543 + "license": "MIT" 6505 6544 }, 6506 6545 "node_modules/slice-source": { 6507 6546 "version": "0.4.1",
+5 -2
package.json
··· 1 1 { 2 2 "name": "fuchs", 3 - "version": "0.0.24", 3 + "version": "0.0.25", 4 4 "type": "module", 5 5 "description": "Beautiful UI components built with Tailwind 4 and Svelte 5", 6 6 "homepage": "https://flo-bit.dev/ui-kit", ··· 76 76 "svelte": "^5.0.0" 77 77 }, 78 78 "dependencies": { 79 - "@zerodevx/svelte-img": "^2.1.2", 80 79 "@atproto/api": "^0.14.7", 80 + "@clack/prompts": "^0.10.0", 81 81 "@number-flow/svelte": "^0.3.3", 82 82 "@sveltejs/adapter-static": "^3.0.8", 83 83 "@texel/color": "^1.1.9", ··· 86 86 "@threlte/extras": "^9.0.1", 87 87 "@types/three": "^0.173.0", 88 88 "@use-gesture/vanilla": "^10.3.1", 89 + "@zerodevx/svelte-img": "^2.1.2", 89 90 "adm-zip": "^0.5.16", 90 91 "bits-ui": "^1.3.4", 91 92 "cheerio": "^1.0.0", 93 + "commander": "^13.1.0", 92 94 "hls.js": "^1.5.20", 93 95 "layerchart": "^1.0.0", 94 96 "node-fetch": "^3.3.2", 95 97 "paneforge": "^0.0.6", 96 98 "pdfjs-dist": "^5.0.375", 99 + "picocolors": "^1.1.1", 97 100 "plyr": "^3.7.8", 98 101 "simplex-noise": "^4.0.3", 99 102 "svelte-sonner": "^0.3.28",
+71 -48
src/lib/cli.ts
··· 1 1 #!/usr/bin/env node 2 2 3 - import fs from 'fs'; 4 - import path from 'path'; 5 - import { fileURLToPath } from 'url'; 6 - import fetch from 'node-fetch'; 7 - import AdmZip from 'adm-zip'; 3 + import fs from 'node:fs'; 4 + import path from 'node:path'; 5 + import { fileURLToPath } from 'node:url'; 8 6 import components from './components.json' with { type: 'json' }; 9 7 10 - const __filename = fileURLToPath(import.meta.url); 11 - const __dirname = path.dirname(__filename); 12 - 13 - const args = process.argv.slice(2); 14 - if (args.length === 0) { 15 - console.error('Usage: cli <component-name>'); 16 - process.exit(1); 17 - } 8 + import fetch from 'node-fetch'; 9 + import AdmZip from 'adm-zip'; 10 + import { spinner, log } from '@clack/prompts'; 11 + import { Command } from 'commander'; 12 + import { version } from '../../package.json' with { type: 'json' }; 18 13 19 - const componentName = args[0].toLowerCase(); 20 - if (!components[componentName as keyof typeof components]) { 21 - console.error(`Component "${componentName}" not found in components.json`); 22 - process.exit(1); 23 - } 14 + const program = new Command(); 24 15 25 - const relativePath = components[componentName as keyof typeof components]; 16 + const s = spinner(); 26 17 18 + const __filename = fileURLToPath(import.meta.url); 19 + const __dirname = path.dirname(__filename); 27 20 const githubUser = 'flo-bit'; 28 21 const repoName = 'ui-kit'; 29 22 const branch = 'main'; 30 23 const zipUrl = `https://github.com/${githubUser}/${repoName}/archive/refs/heads/${branch}.zip`; 31 - 32 24 const tmpDir = path.join(__dirname, 'tmp'); 33 - if (!fs.existsSync(tmpDir)) { 34 - fs.mkdirSync(tmpDir); 35 - } 25 + const zipPath = path.join(tmpDir, `repo-${version}.zip`); 36 26 37 - const zipPath = path.join(tmpDir, 'repo.zip'); 27 + program.name('fuchs').description('CLI to install fox UI components').version(version); 28 + 29 + program 30 + .command('add') 31 + .description('Add a new component to the project') 32 + .argument('<component-name>', 'name of the component to add') 33 + .action((component) => { 34 + addComponent(component); 35 + }); 36 + 37 + program.parse(); 38 38 39 39 async function downloadZip(url: string, dest: string) { 40 - console.log(`Downloading ${url} ...`); 41 40 const response = await fetch(url); 42 41 if (!response.ok) { 43 - throw new Error(`Failed to download ZIP: ${response.statusText}`); 42 + throw new Error(`Failed to download repository: ${response.statusText}`); 44 43 } 45 44 const buffer = await response.arrayBuffer(); 46 45 fs.writeFileSync(dest, Buffer.from(buffer)); 47 - console.log('Download complete.'); 48 46 } 49 47 50 48 function copyRecursive(src: string, dest: string) { ··· 68 66 const fullPath = path.join(dir, entry.name); 69 67 if (entry.isDirectory()) { 70 68 replaceInFiles(fullPath, searchStr, replaceStr); 71 - } else { 72 - try { 73 - const content = fs.readFileSync(fullPath, 'utf8'); 74 - if (content.includes(searchStr)) { 75 - const newContent = content.split(searchStr).join(replaceStr); 76 - fs.writeFileSync(fullPath, newContent, 'utf8'); 77 - console.log(`Updated ${fullPath}`); 78 - } 79 - } catch (err) { 80 - console.error('Error:', (err as Error).message); 69 + continue; 70 + } 71 + try { 72 + const content = fs.readFileSync(fullPath, 'utf8'); 73 + if (content.includes(searchStr)) { 74 + const newContent = content.replaceAll(searchStr, replaceStr); 75 + fs.writeFileSync(fullPath, newContent, 'utf8'); 81 76 } 77 + } catch (err) { 78 + console.error('Error:', (err as Error).message); 82 79 } 83 80 } 84 81 } 85 82 86 - try { 83 + async function downloadRepo() { 84 + s.start('Downloading repository...'); 85 + const tmpDir = path.join(__dirname, 'tmp'); 86 + if (!fs.existsSync(tmpDir)) { 87 + fs.mkdirSync(tmpDir); 88 + } 89 + 87 90 await downloadZip(zipUrl, zipPath); 88 91 89 - console.log('Extracting ZIP archive...'); 90 92 const zip = new AdmZip(zipPath); 91 - const extractDir = path.join(tmpDir, 'extract'); 93 + const extractDir = path.join(tmpDir, `extract-${version}`); 92 94 if (!fs.existsSync(extractDir)) { 93 95 fs.mkdirSync(extractDir); 94 96 } 95 97 zip.extractAllTo(extractDir, true); 96 - console.log('Extraction complete.'); 98 + 99 + s.stop('Repository downloaded'); 100 + return extractDir; 101 + } 102 + 103 + async function addComponent(componentName: string) { 104 + if (!components[componentName as keyof typeof components]) { 105 + console.error(`Component "${componentName}" not found in components.json`); 106 + process.exit(1); 107 + } 108 + const relativePath = components[componentName as keyof typeof components]; 109 + 110 + let packageFolder = ''; 111 + // check if repository is already downloaded 112 + const tmpDir = path.join(__dirname, 'tmp'); 113 + if (!fs.existsSync(tmpDir)) { 114 + fs.mkdirSync(tmpDir); 115 + } 116 + const extractDir = path.join(tmpDir, `extract-${version}`); 117 + if (!fs.existsSync(extractDir)) { 118 + packageFolder = await downloadRepo(); 119 + } else { 120 + log.info('Repository already downloaded'); 121 + packageFolder = extractDir; 122 + } 123 + packageFolder = path.join(packageFolder, `${repoName}-${branch}`); 97 124 98 - const packageFolder = path.join(extractDir, `${repoName}-${branch}`); 99 125 const sourcePath = path.join(packageFolder, 'src', 'lib', relativePath); 100 126 if (!fs.existsSync(sourcePath)) { 101 - console.error(`Component folder "${relativePath}" not found in repository ${repoName}`); 127 + console.error(`Component folder "${relativePath}" not found in repository`); 102 128 process.exit(1); 103 129 } 104 130 105 - const destDir = path.join(process.cwd(), 'src', 'lib', 'ui', componentName); 131 + const destDir = path.join(process.cwd(), 'src', 'lib', 'fuchs', componentName); 106 132 if (!fs.existsSync(destDir)) { 107 133 fs.mkdirSync(destDir, { recursive: true }); 108 134 } 109 135 110 136 copyRecursive(sourcePath, destDir); 111 - console.log(`Component "${componentName}" successfully copied to ${destDir}`); 137 + log.success(`Component "${componentName}" successfully copied to src/lib/fuchs`); 112 138 113 139 replaceInFiles(destDir, '$lib', 'fuchs'); 114 140 115 141 // Optionally, clean up temporary files 116 142 // fs.rmSync(tmpDir, { recursive: true, force: true }); 117 - } catch (err) { 118 - console.error('Error:', (err as Error).message); 119 - process.exit(1); 120 143 }