Sign In

smoothui-cli

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

smoothui-cli - npm Package Compare versions

Comparing version
1.0.4
to
1.0.5
+1
-1
dist/index.js
#!/usr/bin/env node
import{confirm as Le,isCancel as ne,select as Ne,spinner as De}from"@clack/prompts";var _="https://smoothui.dev",k={"Basic UI":["accordion","animated-input","animated-progress-bar","animated-tabs","animated-toggle","basic-dropdown","basic-modal","basic-toast","notification-badge","searchable-dropdown","skeleton-loader","tweet-card"],Buttons:["button-copy","clip-corners-button","dot-morph-button","magnetic-button"],"Text Effects":["wave-text","reveal-text","typewriter-text","scramble-hover","scroll-reveal-paragraph"],AI:["ai-branch","ai-input"],"Cards & Layouts":["expandable-cards","glow-hover-card","scrollable-card-stack","switchboard-card","phototab","job-listing-component"],"Loaders & Effects":["grid-loader","siri-orb","cursor-follow","github-stars-animation"],Interactive:["animated-o-t-p-input","animated-tags","app-download-stack","apple-invites","contribution-graph","dynamic-island","figma-comment","image-metadata-preview","infinite-slider","interactive-image-selector","number-flow","power-off-slide","price-flow","rich-popover","reviews-carousel","social-selector","user-account-avatar"]},K=["src/components/ui","components/ui","src/components","components","app/components/ui"],Y=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],d={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as le,emitKeypressEvents as pe}from"readline";import p from"picocolors";var me=e=>{let t=new Map;for(let o of e){let n=o.category||"Other";t.has(n)||t.set(n,[]),t.get(n)?.push(o)}return t},de=(e,t)=>{console.log(`${p.cyan(d.active)} ${e}`),console.log(`${p.dim(d.bar)}`),console.log(`${p.dim(d.bar)} Search: ${t}${p.dim("\u258C")}`),console.log(`${p.dim(d.bar)}`)},fe=(e,t,o)=>{let n=t?p.green(d.selected):p.dim(d.unselected),s=o?p.cyan(d.cursor):" ",r=o?p.cyan(e.label):e.label;console.log(`${p.dim(d.bar)} ${s} ${n} ${r}`)},ge=e=>{console.log(`${p.dim(d.bar)}`),console.log(`${p.dim(d.bar)} ${p.dim(`${e} selected \u2502 \u2191\u2193 navigate \u2502 space select \u2502 enter confirm \u2502 esc cancel`)}`)},ue=(e,t,o)=>{let n=0,s=t.scrollOffset,r=t.scrollOffset+o;for(let[c,a]of e){if(n>=r)break;n>=s&&console.log(`${p.dim(d.bar)} ${p.bold(p.dim(c))}`),n++;for(let i of a){if(n>=r)break;if(n>=s){let m=t.selected.has(i.value),l=n-1===t.cursorIndex;fe(i,m,l)}n++}}},he=(e,t,o,n)=>()=>{let s=B(t,o.searchQuery);process.stdout.write("\x1B[2J\x1B[H"),de(e,o.searchQuery);let r=me(s);ue(r,o,n),ge(o.selected.size)},B=(e,t)=>{if(!t)return e;let o=t.toLowerCase();return e.filter(n=>n.label.toLowerCase().includes(o)||n.category?.toLowerCase().includes(o))},ye=(e,t,o,n)=>{e.name==="up"?(t.cursorIndex=Math.max(0,t.cursorIndex-1),t.cursorIndex<t.scrollOffset&&(t.scrollOffset=t.cursorIndex)):e.name==="down"&&(t.cursorIndex=Math.min(o-1,t.cursorIndex+1),t.cursorIndex>=t.scrollOffset+n&&(t.scrollOffset=t.cursorIndex-n+1))},be=(e,t)=>{let o=t[e.cursorIndex];o&&(e.selected.has(o.value)?e.selected.delete(o.value):e.selected.add(o.value))},xe=(e,t,o)=>{t.name==="backspace"?(o.searchQuery=o.searchQuery.slice(0,-1),o.cursorIndex=0,o.scrollOffset=0):e&&e.length===1&&!t.ctrl&&!t.meta&&(o.searchQuery+=e,o.cursorIndex=0,o.scrollOffset=0)},Q=e=>{process.stdin.isTTY&&process.stdin.setRawMode(!1),e.close()},H=e=>{let{message:t,items:o,maxVisible:n=10}=e;return new Promise(s=>{let r={selected:new Set,searchQuery:"",cursorIndex:0,scrollOffset:0},c=le({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),pe(process.stdin,c);let a=he(t,o,r,n),i=(m,l)=>{let b=B(o,r.searchQuery),R=b.length;if(l.name==="escape"||l.ctrl&&l.name==="c"){Q(c),s(null);return}if(l.name==="return"){Q(c),s([...r.selected]);return}l.name==="up"||l.name==="down"?ye(l,r,R,n):l.name==="space"?be(r,b):xe(m,l,r),a()};process.stdin.on("keypress",i),a()})};import v from"picocolors";var O=d,C=v.dim,ve=v.cyan,we=v.green,Se=v.red,He=v.yellow,L=v.bold,N=v.gray;function T(e,t){console.log(`${e} ${t}`)}function j(e){T(ve(O.active),e)}function y(e){T(C(O.done),e)}function J(e){T(we(O.success),e)}function P(e){T(Se(O.error),e)}function g(e=""){console.log(`${C(O.bar)} ${e}`)}function I(){console.log(),j(L("SmoothUI")),console.log()}import{existsSync as M,readFileSync as W}from"fs";import{join as E}from"path";var Ie=/^(npm|pnpm|yarn|bun)@/,$e=()=>{let e=process.cwd();for(let{file:o,cmd:n}of Y)if(M(E(e,o)))return n;let t=E(e,"package.json");if(M(t))try{let o=JSON.parse(W(t,"utf-8"));if(o.packageManager){let n=o.packageManager.match(Ie);if(n)return n[1]}}catch{}return"npm"},Oe=()=>{let e=process.cwd();for(let t of K)if(M(E(e,t)))return t;return null},Ce=()=>{let e=process.cwd(),t=["tsconfig.json","jsconfig.json"];for(let o of t){let n=E(e,o);if(M(n))try{let r=W(n,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),a=JSON.parse(r).compilerOptions?.paths;if(a){for(let[i,m]of Object.entries(a))if(i.endsWith("/*")&&Array.isArray(m))return i.slice(0,-2)}}catch{}}return"@"},q=()=>({componentPath:Oe()||"components/ui",alias:Ce(),packageManager:$e()});import{spawnSync as je}from"child_process";import{existsSync as z,mkdirSync as Pe,readFileSync as et,writeFileSync as Re}from"fs";import{dirname as ke,join as Te}from"path";var Me=(e,t)=>t==="@"?e:e.replace(/@\/components\//g,`${t}/components/`);var V=async(e,t,o,n)=>{let s=[],r=[],c=o;for(let a of e.files){let i=Te(process.cwd(),t.componentPath,a.path),m=ke(i);if(z(m)||Pe(m,{recursive:!0}),z(i)&&!c){let b=await n(a.path);if(b==="skip"){r.push(a.path);continue}b==="all"&&(c=!0)}let l=Me(a.content,t.alias);Re(i,l,"utf-8"),s.push(a.path)}return{written:s,skipped:r}},X=(e,t)=>{if(e.length===0)return!0;let o={npm:["npm","install",...e],pnpm:["pnpm","add",...e],yarn:["yarn","add",...e],bun:["bun","add",...e]},[n,...s]=o[t];return je(n,s,{stdio:"pipe",shell:!0}).status===0};var Z=process.env.SMOOTHUI_REGISTRY_URL||_,Ee=/\/r\/([^/]+)\.json$/;async function Ae(){let e=`${Z}/r/registry.json`,t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch registry: ${t.status}`);return t.json()}async function ee(e){let t=`${Z}/r/${e}.json`,o=await fetch(t);if(!o.ok)throw new Error(`Component "${e}" not found`);return o.json()}function te(e){let t=e.match(Ee);return t?t[1]:e}async function A(){return(await Ae()).items.map(t=>t.name)}async function D(e,t=new Set){let o=await ee(e);t.add(e);let n=[];if(o.registryDependencies)for(let s of o.registryDependencies){let r=te(s);if(t.has(r)||!s.includes("smoothui.dev"))continue;let c=await D(r,t);n.push(c)}return{component:o,children:n}}function F(e){let t=[e.component];for(let o of e.children)t.push(...F(o));return t}function oe(e){let t=new Set,o=new Set,n=new Set(["react","react-dom","next","tailwindcss","@types/react","@types/react-dom","@types/node","typescript"]);for(let s of e){for(let r of s.dependencies||[])n.has(r)||t.add(r);for(let r of s.devDependencies||[])n.has(r)||o.add(r)}return{dependencies:[...t],devDependencies:[...o]}}function U(e,t="",o=!0){g(`${t}${o?"\u2514\u2500":"\u251C\u2500"} ${e.component.name}`);let s=t+(o?" ":"\u2502 "),r=[...e.component.dependencies||[]].filter(c=>!["react","react-dom","next"].includes(c));r.length>0&&e.children.length===0&&g(`${s}\u2514\u2500 ${N(`npm: ${r.join(", ")}`)}`);for(let c=0;c<e.children.length;c++){let a=e.children[c],i=c===e.children.length-1&&r.length===0;U(a,s,i)}r.length>0&&e.children.length>0&&g(`${s}\u2514\u2500 ${N(`npm: ${r.join(", ")}`)}`)}async function re(e,t){I();let o=q();t.path&&(o.componentPath=t.path),y(`Detected: ${o.componentPath}/ (${o.packageManager})`),console.log();let n=e;if(n.length===0){let h=(await A()).map(f=>{let S="Other";for(let[ie,ae]of Object.entries(k))if(ae.includes(f)){S=ie;break}return{value:f,label:f,category:S}}),x=await H({message:"Select components to install:",items:h});if(!x||x.length===0){console.log(),y("No components selected.");return}n=x,y(`Selected: ${n.join(", ")}`),console.log()}j("Resolving dependencies..."),g();let s=[],r=new Set;for(let u of n)try{let h=await D(u,r),x=F(h);for(let f of x)r.has(f.name)||(r.add(f.name),s.push(f));U(h)}catch(h){P(`Failed to resolve ${u}: ${h.message}`);return}g();let{dependencies:c,devDependencies:a}=oe(s),i=[...c,...a],m=s.length,l=i.length,b=l>0?`Install ${m} component${m>1?"s":""} + ${l} npm package${l>1?"s":""}?`:`Install ${m} component${m>1?"s":""}?`,R=await Le({message:b});if(ne(R)||!R){y("Installation cancelled.");return}console.log();let G=t.force??!1;for(let u of s){let{written:h,skipped:x}=await V(u,o,G,async f=>{let S=await Ne({message:`File exists: ${f}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return ne(S)?"skip":(S==="all"&&(G=!0),S)});for(let f of h)y(`Written: ${o.componentPath}/${f}`);for(let f of x)y(`Skipped: ${f}`)}if(i.length>0){let u=De();u.start(`Installing ${i.join(", ")}`),X(i,o.packageManager)?u.stop(`Installed: ${i.join(", ")}`):(u.stop("Failed to install dependencies"),g(`Run manually: ${o.packageManager} add ${i.join(" ")}`))}console.log(),J(`Done! ${m} component${m>1?"s":""} installed.`)}async function se(e){let t=await A();if(e.json){console.log(JSON.stringify(t,null,2));return}I(),j(`Available components (${t.length})`),g();let o=new Map;for(let n of t){let s="Other";for(let[c,a]of Object.entries(k))if(a.includes(n)){s=c;break}let r=o.get(s);r?r.push(n):o.set(s,[n])}for(let[n,s]of o){g(L(C(n)));for(let r of s.sort())g(` ${r}`);g()}y(`Use ${C("npx smoothui add <component>")} to install`)}var $=process.argv.slice(2),w=$[0];function ce(){I(),console.log("Usage: npx smoothui <command> [options]"),console.log(),console.log("Commands:"),console.log(" add [components...] Add components to your project"),console.log(" list List available components"),console.log(),console.log("Options:"),console.log(" --path <path> Custom component install path"),console.log(" --force Overwrite existing files without asking"),console.log(" --json Output as JSON (list command)"),console.log(" --help Show this help message"),console.log(),console.log("Examples:"),console.log(" npx smoothui add siri-orb"),console.log(" npx smoothui add siri-orb grid-loader"),console.log(" npx smoothui add # Interactive mode"),console.log(" npx smoothui list")}async function Fe(){try{if(!w||w==="--help"||w==="-h"){ce();return}if(w==="add"){let e=[],t,o=!1;for(let n=1;n<$.length;n++){let s=$[n];s==="--path"&&$[n+1]?(t=$[n+1],n++):s==="--force"||s==="-f"?o=!0:s.startsWith("-")||e.push(s)}await re(e,{path:t,force:o});return}if(w==="list"||w==="ls"){let e=$.includes("--json");await se({json:e});return}P(`Unknown command: ${w}`),ce(),process.exit(1)}catch(e){P(e.message),process.exit(1)}}Fe();
import{confirm as De,isCancel as se,select as Fe,spinner as Ue}from"@clack/prompts";var _="https://smoothui.dev",M={"Basic UI":["accordion","animated-input","animated-progress-bar","animated-tabs","animated-toggle","basic-dropdown","basic-modal","basic-toast","notification-badge","searchable-dropdown","skeleton-loader","tweet-card"],Buttons:["button-copy","clip-corners-button","dot-morph-button","magnetic-button"],"Text Effects":["wave-text","reveal-text","typewriter-text","scramble-hover","scroll-reveal-paragraph"],AI:["ai-branch","ai-input"],"Cards & Layouts":["expandable-cards","glow-hover-card","scrollable-card-stack","switchboard-card","phototab","job-listing-component"],"Loaders & Effects":["grid-loader","siri-orb","cursor-follow","github-stars-animation"],Interactive:["animated-o-t-p-input","animated-tags","app-download-stack","apple-invites","contribution-graph","dynamic-island","figma-comment","image-metadata-preview","infinite-slider","interactive-image-selector","number-flow","power-off-slide","price-flow","rich-popover","reviews-carousel","social-selector","user-account-avatar"]},K=["src/components/ui","components/ui","src/components","components","app/components/ui"],Y=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],m={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as de,emitKeypressEvents as me}from"readline";import d from"picocolors";var fe=t=>{let e=new Map;for(let o of t){let n=o.category||"Other";e.has(n)||e.set(n,[]),e.get(n)?.push(o)}return e},ge=(t,e)=>{console.log(`${d.cyan(m.active)} ${t}`),console.log(`${d.dim(m.bar)}`),console.log(`${d.dim(m.bar)} Search: ${e}${d.dim("\u258C")}`),console.log(`${d.dim(m.bar)}`)},ue=(t,e,o)=>{let n=e?d.green(m.selected):d.dim(m.unselected),s=o?d.cyan(m.cursor):" ",r=o?d.cyan(t.label):t.label;console.log(`${d.dim(m.bar)} ${s} ${n} ${r}`)},he=t=>{console.log(`${d.dim(m.bar)}`),console.log(`${d.dim(m.bar)} ${d.dim(`${t} selected \u2502 \u2191\u2193 navigate \u2502 space select \u2502 enter confirm \u2502 esc cancel`)}`)},ye=(t,e,o)=>{let n=0,s=e.scrollOffset,r=e.scrollOffset+o;for(let[i,c]of t){if(n>=r)break;n>=s&&console.log(`${d.dim(m.bar)} ${d.bold(d.dim(i))}`),n++;for(let a of c){if(n>=r)break;if(n>=s){let p=e.selected.has(a.value),l=n-1===e.cursorIndex;ue(a,p,l)}n++}}},be=(t,e,o,n)=>()=>{let s=B(e,o.searchQuery);process.stdout.write("\x1B[2J\x1B[H"),ge(t,o.searchQuery);let r=fe(s);ye(r,o,n),he(o.selected.size)},B=(t,e)=>{if(!e)return t;let o=e.toLowerCase();return t.filter(n=>n.label.toLowerCase().includes(o)||n.category?.toLowerCase().includes(o))},xe=(t,e,o,n)=>{if(o<=0){e.cursorIndex=0,e.scrollOffset=0;return}t.name==="up"?(e.cursorIndex=Math.max(0,e.cursorIndex-1),e.cursorIndex<e.scrollOffset&&(e.scrollOffset=e.cursorIndex)):t.name==="down"&&(e.cursorIndex=Math.min(o-1,e.cursorIndex+1),e.cursorIndex>=e.scrollOffset+n&&(e.scrollOffset=e.cursorIndex-n+1))},ve=(t,e)=>{let o=e[t.cursorIndex];o&&(t.selected.has(o.value)?t.selected.delete(o.value):t.selected.add(o.value))},we=(t,e,o)=>{e.name==="backspace"?(o.searchQuery=o.searchQuery.slice(0,-1),o.cursorIndex=0,o.scrollOffset=0):t&&t.length===1&&!e.ctrl&&!e.meta&&(o.searchQuery+=t,o.cursorIndex=0,o.scrollOffset=0)},Q=(t,e)=>{e&&process.stdin.removeListener("keypress",e),process.stdin.isTTY&&process.stdin.setRawMode(!1),t.close()},H=t=>{let{message:e,items:o,maxVisible:n=10}=t;return new Promise(s=>{let r={selected:new Set,searchQuery:"",cursorIndex:0,scrollOffset:0},i=de({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),me(process.stdin,i);let c=be(e,o,r,n),a=(p,l)=>{let x=B(o,r.searchQuery),S=x.length;if(l.name==="escape"||l.ctrl&&l.name==="c"){Q(i,a),s(null);return}if(l.name==="return"){Q(i,a),s([...r.selected]);return}l.name==="up"||l.name==="down"?xe(l,r,S,n):l.name==="space"?ve(r,x):we(p,l,r),c()};process.stdin.on("keypress",a),c()})};import v from"picocolors";var R=m,P=v.dim,Se=v.cyan,$e=v.green,Ie=v.red,We=v.yellow,N=v.bold,D=v.gray;function T(t,e){console.log(`${t} ${e}`)}function j(t){T(Se(R.active),t)}function b(t){T(P(R.done),t)}function J(t){T($e(R.success),t)}function k(t){T(Ie(R.error),t)}function f(t=""){console.log(`${P(R.bar)} ${t}`)}function I(){console.log(),j(N("SmoothUI")),console.log()}import{existsSync as E,readFileSync as W}from"fs";import{join as A}from"path";var Oe=/^(npm|pnpm|yarn|bun)@/,Ce=()=>{let t=process.cwd();for(let{file:o,cmd:n}of Y)if(E(A(t,o)))return n;let e=A(t,"package.json");if(E(e))try{let o=JSON.parse(W(e,"utf-8"));if(o.packageManager){let n=o.packageManager.match(Oe);if(n)return n[1]}}catch{}return"npm"},Re=()=>{let t=process.cwd();for(let e of K)if(E(A(t,e)))return e;return null},Pe=()=>{let t=process.cwd(),e=["tsconfig.json","jsconfig.json"];for(let o of e){let n=A(t,o);if(E(n))try{let r=W(n,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),c=JSON.parse(r).compilerOptions?.paths;if(c){for(let[a,p]of Object.entries(c))if(a.endsWith("/*")&&Array.isArray(p))return a.slice(0,-2)}}catch{}}return"@"},q=()=>({componentPath:Re()||"components/ui",alias:Pe(),packageManager:Ce()});import{spawnSync as z}from"child_process";import{existsSync as V,mkdirSync as je,readFileSync as ot,writeFileSync as ke}from"fs";import{dirname as Me,isAbsolute as Te,relative as Ee,resolve as X}from"path";var Ae=(t,e)=>e==="@"?t:t.replace(/@\/components\//g,`${e}/components/`);var Z=async(t,e,o,n)=>{let s=[],r=[],i=o,c=X(process.cwd(),e.componentPath);for(let a of t.files){let p=X(c,a.path),l=Ee(c,p);if(l.startsWith("..")||Te(l))throw new Error(`Invalid registry file path: ${a.path}`);let x=Me(p);if(V(x)||je(x,{recursive:!0}),V(p)&&!i){let C=await n(a.path);if(C==="skip"){r.push(a.path);continue}C==="all"&&(i=!0)}let S=Ae(a.content,e.alias);ke(p,S,"utf-8"),s.push(a.path)}return{written:s,skipped:r}},ee=(t,e,o)=>{let n=!0;if(t.length>0){let s={npm:["npm","install",...t],pnpm:["pnpm","add",...t],yarn:["yarn","add",...t],bun:["bun","add",...t]},[r,...i]=s[o];z(r,i,{stdio:"pipe"}).status!==0&&(n=!1)}if(e.length>0){let s={npm:["npm","install","-D",...e],pnpm:["pnpm","add","-D",...e],yarn:["yarn","add","-D",...e],bun:["bun","add","-d",...e]},[r,...i]=s[o];z(r,i,{stdio:"pipe"}).status!==0&&(n=!1)}return n};var te=process.env.SMOOTHUI_REGISTRY_URL||_,Le=/\/r\/([^/]+)\.json$/;async function Ne(){let t=`${te}/r/registry.json`,e=await fetch(t);if(!e.ok)throw new Error(`Failed to fetch registry: ${e.status}`);return e.json()}async function oe(t){let e=`${te}/r/${t}.json`,o=await fetch(e);if(!o.ok)throw new Error(`Component "${t}" not found`);return o.json()}function ne(t){let e=t.match(Le);return e?e[1]:t}async function L(){return(await Ne()).items.map(e=>e.name)}async function F(t,e=new Set){let o=await oe(t);e.add(t);let n=[];if(o.registryDependencies)for(let s of o.registryDependencies){let r=ne(s);if(e.has(r)||!s.includes("smoothui.dev"))continue;let i=await F(r,e);n.push(i)}return{component:o,children:n}}function U(t){let e=[t.component];for(let o of t.children)e.push(...U(o));return e}function re(t){let e=new Set,o=new Set,n=new Set(["react","react-dom","next","tailwindcss","@types/react","@types/react-dom","@types/node","typescript"]);for(let s of t){for(let r of s.dependencies||[])n.has(r)||e.add(r);for(let r of s.devDependencies||[])n.has(r)||o.add(r)}return{dependencies:[...e],devDependencies:[...o]}}function G(t,e="",o=!0){f(`${e}${o?"\u2514\u2500":"\u251C\u2500"} ${t.component.name}`);let s=e+(o?" ":"\u2502 "),r=[...t.component.dependencies||[]].filter(i=>!["react","react-dom","next"].includes(i));r.length>0&&t.children.length===0&&f(`${s}\u2514\u2500 ${D(`npm: ${r.join(", ")}`)}`);for(let i=0;i<t.children.length;i++){let c=t.children[i],a=i===t.children.length-1&&r.length===0;G(c,s,a)}r.length>0&&t.children.length>0&&f(`${s}\u2514\u2500 ${D(`npm: ${r.join(", ")}`)}`)}async function ie(t,e){I();let o=q();e.path&&(o.componentPath=e.path),b(`Detected: ${o.componentPath}/ (${o.packageManager})`),console.log();let n=t;if(n.length===0){let h=(await L()).map(g=>{let $="Other";for(let[le,pe]of Object.entries(M))if(pe.includes(g)){$=le;break}return{value:g,label:g,category:$}}),y=await H({message:"Select components to install:",items:h});if(!y||y.length===0){console.log(),b("No components selected.");return}n=y,b(`Selected: ${n.join(", ")}`),console.log()}j("Resolving dependencies..."),f();let s=[],r=new Set;for(let u of n)if(!r.has(u))try{let h=await F(u),y=U(h);for(let g of y)r.has(g.name)||(r.add(g.name),s.push(g));G(h)}catch(h){k(`Failed to resolve ${u}: ${h.message}`);return}f();let{dependencies:i,devDependencies:c}=re(s),a=[...i,...c],p=s.length,l=i.length+c.length,x=l>0?`Install ${p} component${p>1?"s":""} + ${l} npm package${l>1?"s":""}?`:`Install ${p} component${p>1?"s":""}?`,S=await De({message:x});if(se(S)||!S){b("Installation cancelled.");return}console.log();let C=e.force??!1;for(let u of s){let{written:h,skipped:y}=await Z(u,o,C,async g=>{let $=await Fe({message:`File exists: ${g}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return se($)?"skip":($==="all"&&(C=!0),$)});for(let g of h)b(`Written: ${o.componentPath}/${g}`);for(let g of y)b(`Skipped: ${g}`)}if(i.length>0||c.length>0){let u=Ue();if(u.start(`Installing ${a.join(", ")}`),ee(i,c,o.packageManager))u.stop(`Installed: ${a.join(", ")}`);else if(u.stop("Failed to install dependencies"),i.length>0&&f(`Run manually: ${o.packageManager} add ${i.join(" ")}`),c.length>0){let y=o.packageManager==="bun"?"-d":"-D";f(`Run manually: ${o.packageManager} add ${y} ${c.join(" ")}`)}}console.log(),J(`Done! ${p} component${p>1?"s":""} installed.`)}async function ce(t){let e=await L();if(t.json){console.log(JSON.stringify(e,null,2));return}I(),j(`Available components (${e.length})`),f();let o=new Map;for(let n of e){let s="Other";for(let[i,c]of Object.entries(M))if(c.includes(n)){s=i;break}let r=o.get(s);r?r.push(n):o.set(s,[n])}for(let[n,s]of o){f(N(P(n)));for(let r of s.sort())f(` ${r}`);f()}b(`Use ${P("npx smoothui add <component>")} to install`)}var O=process.argv.slice(2),w=O[0];function ae(){I(),console.log("Usage: npx smoothui <command> [options]"),console.log(),console.log("Commands:"),console.log(" add [components...] Add components to your project"),console.log(" list List available components"),console.log(),console.log("Options:"),console.log(" --path <path> Custom component install path"),console.log(" --force Overwrite existing files without asking"),console.log(" --json Output as JSON (list command)"),console.log(" --help Show this help message"),console.log(),console.log("Examples:"),console.log(" npx smoothui add siri-orb"),console.log(" npx smoothui add siri-orb grid-loader"),console.log(" npx smoothui add # Interactive mode"),console.log(" npx smoothui list")}async function Ge(){try{if(!w||w==="--help"||w==="-h"){ae();return}if(w==="add"){let t=[],e,o=!1;for(let n=1;n<O.length;n++){let s=O[n];s==="--path"&&O[n+1]?(e=O[n+1],n++):s==="--force"||s==="-f"?o=!0:s.startsWith("-")||t.push(s)}await ie(t,{path:e,force:o});return}if(w==="list"||w==="ls"){let t=O.includes("--json");await ce({json:t});return}k(`Unknown command: ${w}`),ae(),process.exit(1)}catch(t){let e=t instanceof Error?t.message:String(t);k(e||"An unknown error occurred"),process.exit(1)}}Ge();
{
"name": "smoothui-cli",
"version": "1.0.4",
"version": "1.0.5",
"author": "educalvolpz",

@@ -5,0 +5,0 @@ "description": "CLI to install SmoothUI components - beautifully designed React components with smooth animations",

@@ -1,99 +0,15 @@

# SmoothUI
# smoothui-cli
![Screenshot of SmoothUI](/apps/docs/public/readme.png)
CLI to install [SmoothUI](https://smoothui.dev) components - beautifully designed React components with smooth animations.
<div align="center">
## Installation
![Next.js Badge](https://img.shields.io/badge/Next.js-000?logo=nextdotjs&logoColor=fff&style=flat)
![Tailwind CSS Badge](https://img.shields.io/badge/Tailwind%20CSS-06B6D4?logo=tailwindcss&logoColor=fff&style=flat)
![Motion Badge](https://img.shields.io/badge/Motion-ECD53F?style=flat)
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fpheralb%2Fsvgl%2Fbadge%3Fref%3Dmain&style=flat)](https://actions-badge.atrox.dev/educlopez/smoothui/goto?ref=main)
![GitHub stars](https://img.shields.io/github/stars/educlopez/smoothui)
![GitHub issues](https://img.shields.io/github/issues/educlopez/smoothui)
![GitHub forks](https://img.shields.io/github/forks/educlopez/smoothui)
![GitHub PRs](https://img.shields.io/github/issues-pr/educlopez/smoothui)
[![Website](https://img.shields.io/badge/website-smoothui.dev-blue)](https://smoothui.dev)
</div>
SmoothUI is a collection of beautifully designed components with smooth animations built with React, Tailwind CSS, and Motion. This project aims to provide developers with a set of reusable UI components that enhance user experience through delightful animations and modern design patterns.
## Table of Contents
- [SmoothUI](#smoothui)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [Quick Start](#quick-start)
- [Installation](#installation)
- [Using SmoothUI CLI](#using-smoothui-cli)
- [Using shadcn CLI](#using-shadcn-cli)
- [Manual Installation](#manual-installation)
- [Usage](#usage)
- [Basic Usage](#basic-usage)
- [Advanced Usage](#advanced-usage)
- [Available Components](#available-components)
- [UI Components](#ui-components)
- [Interactive Components](#interactive-components)
- [Layout Components](#layout-components)
- [Utility Components](#utility-components)
- [MCP Support](#mcp-support)
- [🤖 AI Assistant Integration](#-ai-assistant-integration)
- [Quick MCP Setup](#quick-mcp-setup)
- [Registry System](#registry-system)
- [Automatic Dependencies](#automatic-dependencies)
- [Component Structure](#component-structure)
- [Registry Features](#registry-features)
- [Troubleshooting](#troubleshooting)
- [Common Issues](#common-issues)
- [1. Authentication Error (401)](#1-authentication-error-401)
- [2. Registry Not Found](#2-registry-not-found)
- [3. Import Path Issues](#3-import-path-issues)
- [4. Missing Dependencies](#4-missing-dependencies)
- [Getting Help](#getting-help)
- [Contributing](#contributing)
- [Development Setup](#development-setup)
- [License](#license)
## Features
- **Modern Design System**: A cohesive and contemporary design language with a new mascot called Smoothy
- **Smooth Animations**: Built-in animations powered by Motion for delightful user experiences
- **Responsive Design**: Fully responsive components designed with Tailwind CSS
- **Dark Mode Support**: Components support both light and dark themes out of the box
- **Color Customization**: Dynamic color switcher for easy theme customization
- **Documentation**: Comprehensive documentation with props, examples, and usage guidelines
- **Accessibility**: Enhanced accessibility features across all components
- **TypeScript Support**: Full TypeScript support with type definitions
- **Easy Integration**: Simple API for integrating components into your projects
- **CLI Tools**: Dedicated SmoothUI CLI and shadcn registry support for easy component installation
## Quick Start
Get started with SmoothUI in just one command:
```bash
# Using SmoothUI CLI (recommended)
npx smoothui-cli add siri-orb
# Or using shadcn CLI
npx shadcn@latest add @smoothui/siri-orb
```
Then use the component:
## Usage
```tsx
import { SiriOrb } from "@/components/smoothui/ui/SiriOrb";
### Add components
export default function App() {
return <SiriOrb size="200px" />;
}
```
## Installation
### Using SmoothUI CLI
The SmoothUI CLI provides an interactive way to browse and install components with automatic dependency resolution.
```bash

@@ -104,311 +20,53 @@ # Add a single component

# Add multiple components
npx smoothui-cli add siri-orb rich-popover animated-input
npx smoothui-cli add siri-orb grid-loader animated-tabs
# Interactive mode - browse and select components
# Interactive mode - browse and select
npx smoothui-cli add
# List all available components
npx smoothui-cli list
```
**Features:**
### List components
- Interactive component picker with search and categories
- Auto-detects package manager (npm, pnpm, yarn, bun)
- Auto-detects component paths and tsconfig aliases
- Shows dependency tree before installation
- Handles file conflicts with overwrite prompts
- Auto-installs npm dependencies
### Using shadcn CLI
SmoothUI is an official shadcn registry, so you can install components directly using the `@smoothui` namespace:
```bash
# Install a single component
npx shadcn@latest add @smoothui/siri-orb
# Show all available components
npx smoothui-cli list
# Install multiple components
npx shadcn@latest add @smoothui/rich-popover @smoothui/animated-input
# JSON output
npx smoothui-cli list --json
```
### Manual Installation
### Options
If you prefer to install components manually, you can copy the component files directly:
1. **Install dependencies**:
```bash
pnpm add motion tailwindcss lucide-react clsx tailwind-merge
```
# Custom install path
npx smoothui-cli add siri-orb --path src/components/ui
2. **Copy component files** from the [components directory](src/components/smoothui/ui/)
3. **Set up utilities**:
```bash
# Create lib/utils/cn.ts
mkdir -p lib/utils
# Force overwrite existing files
npx smoothui-cli add siri-orb --force
```
```tsx
// lib/utils/cn.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
## Features
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
```
- Interactive component picker with search and categories
- Auto-detects package manager (npm, pnpm, yarn, bun)
- Auto-detects component paths and tsconfig aliases
- Shows dependency tree before installation
- Handles file conflicts with overwrite prompts
- Auto-installs npm dependencies
## Usage
## Alternative: shadcn CLI
### Basic Usage
You can also use the shadcn CLI with the `@smoothui` registry:
```tsx
import { SiriOrb } from "@/components/smoothui/ui/SiriOrb";
export default function App() {
return (
<div className="flex min-h-screen items-center justify-center">
<SiriOrb
size="200px"
colors={{
bg: "oklch(95% 0.02 264.695)",
c1: "oklch(75% 0.15 350)",
c2: "oklch(80% 0.12 200)",
c3: "oklch(78% 0.14 280)",
}}
animationDuration={20}
/>
</div>
);
}
```
### Advanced Usage
```tsx
import { RichPopover } from "@/components/smoothui/ui/RichPopover";
import { ScrollableCardStack } from "@/components/smoothui/ui/ScrollableCardStack";
export default function Dashboard() {
const cards = [
{
id: "1",
name: "John Doe",
handle: "@johndoe",
avatar: "/avatars/john.jpg",
video: "/videos/john.mp4",
href: "https://twitter.com/johndoe",
},
// ... more cards
];
return (
<div className="space-y-8">
<RichPopover />
<ScrollableCardStack items={cards} />
</div>
);
}
```
## Available Components
SmoothUI includes a wide variety of components:
### UI Components
- **SiriOrb** - Animated orb with smooth color transitions
- **RichPopover** - Advanced popover with rich content
- **ScrollableCardStack** - Interactive card stack with smooth scrolling
- **AnimatedInput** - Input field with smooth animations
- **DynamicIsland** - iOS-style dynamic island component
- **FluidMorph** - Fluid morphing animations
- **MatrixCard** - Matrix-style card with particle effects
### Interactive Components
- **CursorFollow** - Custom cursor following component
- **ScrambleHover** - Text scramble effect on hover
- **WaveText** - Animated wave text effect
- **TypewriterText** - Typewriter text animation
### Layout Components
- **ExpandableCards** - Expandable card layout
- **ScrollableCardStack** - Stack of scrollable cards
- **AppDownloadStack** - App download showcase
### Utility Components
- **ButtonCopy** - Copy button with feedback
- **ClipCornersButton** - Button with clipped corners
- **DotMorphButton** - Button with morphing dot animation
[View all components →](https://smoothui.dev)
## MCP Support
SmoothUI is fully compatible with the **shadcn MCP server**, enabling AI assistants to discover and install components automatically.
### 🤖 AI Assistant Integration
With MCP support, AI assistants like **Claude**, **Cursor**, and **GitHub Copilot** can:
- **Discover Components**: Browse all available SmoothUI components
- **Install Components**: Automatically install components with dependencies
- **Provide Usage Examples**: Get code examples and integration help
- **Smart Suggestions**: Receive intelligent component recommendations
### Quick MCP Setup
1. **Configure your registry** in `components.json`:
```json
{
"registries": {
"@smoothui": "https://smoothui.dev/r/{name}.json"
}
}
```
2. **Install MCP server**:
```bash
npx shadcn@latest mcp init --client claude
# or for Cursor: npx shadcn@latest mcp init --client cursor
# or for VS Code: npx shadcn@latest mcp init --client vscode
```
3. **Try these prompts**:
- "Show me the components in the smoothui registry"
- "Install the SiriOrb component from smoothui"
- "Create a landing page using smoothui components"
[Learn more about MCP support →](https://smoothui.dev/doc/mcp)
## Registry System
SmoothUI uses a custom registry system compatible with shadcn CLI v3. Each component includes:
### Automatic Dependencies
- **Package Dependencies**: Required npm packages are automatically included
- **Utility Files**: Shared utilities like `cn` are automatically bundled
- **Import Paths**: All import paths are automatically resolved
### Component Structure
When you install a component, you get:
```
components/smoothui/ui/
├── ComponentName.tsx # Main component file
lib/utils/
└── cn.ts # Utility functions (if needed)
```
### Registry Features
- **Self-contained**: Each component includes all necessary dependencies
- **Type-safe**: Full TypeScript support with proper types
- **Optimized**: Components are optimized for performance
- **Accessible**: Built-in accessibility features
## Troubleshooting
### Common Issues
#### 1. Authentication Error (401)
**Error**: `You are not authorized to access the item`
**Solution**: This usually happens with Vercel preview deployments. Use the production URL:
```json
{
"registries": {
"@smoothui": "https://smoothui.dev/r/{name}.json"
}
}
```
#### 2. Registry Not Found
**Error**: `The item at https://smoothui.dev/r/registry.json was not found`
**Solution**: The search command might not work as expected. Install components directly:
```bash
npx shadcn@latest add @smoothui/siri-orb
```
#### 3. Import Path Issues
## Links
**Error**: `Cannot find module '@/lib/utils/cn'`
- [Documentation](https://smoothui.dev)
- [Components](https://smoothui.dev/docs/components)
- [GitHub](https://github.com/educlopez/smoothui)
**Solution**: Make sure your `tsconfig.json` includes the path alias:
```json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
```
#### 4. Missing Dependencies
**Error**: `Cannot find module 'clsx'`
**Solution**: Install missing dependencies:
```bash
pnpm add clsx tailwind-merge motion
```
### Getting Help
- **Documentation**: Visit [smoothui.dev](https://smoothui.dev) for detailed documentation
- **Issues**: Report bugs on [GitHub Issues](https://github.com/educlopez/smoothui/issues)
- **Discussions**: Join discussions on [GitHub Discussions](https://github.com/educlopez/smoothui/discussions)
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
### Development Setup
1. **Clone the repository**:
```bash
git clone https://github.com/educlopez/smoothui.git
cd smoothui
```
2. **Install dependencies**:
```bash
pnpm install
```
3. **Start development server**:
```bash
pnpm dev
```
4. **Build registry**:
```bash
pnpm run build:registry
```
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
MIT