smoothui-cli
Advanced tools
+3
-1
| #!/usr/bin/env node | ||
| import{confirm as Le,isCancel as ae,select as Ne,spinner as De}from"@clack/prompts";var _="https://smoothui.dev",O={"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"]},Y=["src/components/ui","components/ui","src/components","components","app/components/ui"],H=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],J={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as ge,emitKeypressEvents as fe}from"readline";import a from"picocolors";var h={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",pointer:"\u276F",bar:"\u2502"},Q=(e,t)=>{if(!t)return e;let o=t.toLowerCase();return e.filter(s=>s.label.toLowerCase().includes(o)||s.value.toLowerCase().includes(o)||s.category?.toLowerCase().includes(o))},ue=(e,t=3)=>{let o=[...e];return o.length===0?"":o.length<=t?o.join(", "):`${o.slice(0,t).join(", ")} +${o.length-t} more`},he=(e,t,o,s)=>{let r=Q(t,o.searchQuery),n=r.length;process.stdout.write("\x1B[2J\x1B[H"),console.log(`${a.green(h.active)} ${e} ${a.dim("(space to toggle)")}`),console.log(`${a.dim(h.bar)}`);let i=o.searchQuery||a.dim("Type to search...");console.log(`${a.dim(h.bar)} ${a.cyan("Search:")} ${i}${a.inverse(" ")}`),console.log(`${a.dim(h.bar)}`);let l=Math.floor(s/2),p=Math.max(0,o.cursorIndex-l),c=Math.min(n,p+s);c-p<s&&p>0&&(p=Math.max(0,c-s)),p>0&&console.log(`${a.dim(h.bar)} ${a.dim(`\u2191 ${p} more`)}`);for(let m=p;m<c;m++){let g=r[m],f=o.selected.has(g.value),b=m===o.cursorIndex,x=b?a.cyan(h.pointer):" ",u=f?a.green(h.selected):a.dim(h.unselected),v=b?a.cyan(g.label):g.label,N=g.category?a.dim(` (${g.category})`):"";console.log(`${a.dim(h.bar)} ${x} ${u} ${v}${N}`)}let d=n-c;d>0&&console.log(`${a.dim(h.bar)} ${a.dim(`\u2193 ${d} more`)}`),n===0&&console.log(`${a.dim(h.bar)} ${a.dim("No components found")}`),console.log(`${a.dim(h.bar)}`);let $=ue(o.selected);$&&(console.log(`${a.dim(h.bar)} ${a.green("Selected:")} ${$}`),console.log(`${a.dim(h.bar)}`)),console.log(`${a.dim(h.bar)} ${a.dim("\u2191\u2193 navigate \u2022 space select \u2022 enter confirm \u2022 esc cancel")}`)},K=(e,t)=>{t&&process.stdin.removeListener("keypress",t),process.stdin.isTTY&&process.stdin.setRawMode(!1),e.close(),process.stdout.write("\x1B[?25h")},W=e=>{let{message:t,items:o,maxVisible:s=8}=e;return new Promise(r=>{let n={selected:new Set,searchQuery:"",cursorIndex:0},i=ge({input:process.stdin,output:process.stdout});process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdout.write("\x1B[?25l")),fe(process.stdin,i);let l=()=>he(t,o,n,s),p=(c,d)=>{let $=Q(o,n.searchQuery),m=$.length;if(d.name==="escape"||d.ctrl&&d.name==="c"){K(i,p),process.stdout.write("\x1B[2J\x1B[H"),r(null);return}if(d.name==="return"){K(i,p),process.stdout.write("\x1B[2J\x1B[H"),r([...n.selected]);return}if(d.name==="up")n.cursorIndex=Math.max(0,n.cursorIndex-1);else if(d.name==="down")n.cursorIndex=Math.min(m-1,n.cursorIndex+1);else if(d.name==="space"){let g=$[n.cursorIndex];g&&(n.selected.has(g.value)?n.selected.delete(g.value):n.selected.add(g.value))}else d.name==="backspace"?(n.searchQuery=n.searchQuery.slice(0,-1),n.cursorIndex=0):c&&c.length===1&&!d.ctrl&&!d.meta&&(n.searchQuery+=c,n.cursorIndex=0);m===0?n.cursorIndex=0:n.cursorIndex>=m&&(n.cursorIndex=m-1),l()};process.stdin.on("keypress",p),l()})};import S from"picocolors";var k=J,R=S.dim,ye=S.cyan,be=S.green,xe=S.red,Ke=S.yellow,q=S.bold,D=S.gray,$e=["\x1B[38;5;252m","\x1B[38;5;249m","\x1B[38;5;246m","\x1B[38;5;243m","\x1B[38;5;240m","\x1B[38;5;237m"],we="\x1B[0m",B=["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D"],ve="1.1.0";function T(e,t){console.log(`${e} ${t}`)}function E(e){T(ye(k.active),e)}function w(e){T(R(k.done),e)}function V(e){T(be(k.success),e)}function P(e){T(xe(k.error),e)}function y(e=""){console.log(`${R(k.bar)} ${e}`)}function j(){console.log();for(let e=0;e<B.length;e++)console.log(`${$e[e]}${B[e]}${we}`);console.log(),console.log(` ${R(`v${ve}`)}`),console.log()}import{existsSync as M,readFileSync as X}from"fs";import{join as A}from"path";var Se=/^(npm|pnpm|yarn|bun)@/,Ie=()=>{let e=process.cwd();for(let{file:o,cmd:s}of H)if(M(A(e,o)))return s;let t=A(e,"package.json");if(M(t))try{let o=JSON.parse(X(t,"utf-8"));if(o.packageManager){let s=o.packageManager.match(Se);if(s)return s[1]}}catch{}return"npm"},Re=()=>{let e=process.cwd();for(let t of Y)if(M(A(e,t)))return t;return null},je=()=>{let e=process.cwd(),t=["tsconfig.json","jsconfig.json"];for(let o of t){let s=A(e,o);if(M(s))try{let n=X(s,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),l=JSON.parse(n).compilerOptions?.paths;if(l){for(let[p,c]of Object.entries(l))if(p.endsWith("/*")&&Array.isArray(c))return p.slice(0,-2)}}catch{}}return"@"},z=()=>({componentPath:Re()||"components/ui",alias:je(),packageManager:Ie()});import{spawnSync as Z}from"child_process";import{existsSync as ee,mkdirSync as Ce,readFileSync as Ze,writeFileSync as ke}from"fs";import{dirname as Pe,isAbsolute as Oe,relative as Te,resolve as te}from"path";var Ee=(e,t)=>t==="@"?e:e.replace(/@\/components\//g,`${t}/components/`);var oe=async(e,t,o,s)=>{let r=[],n=[],i=o,l=te(process.cwd(),t.componentPath);for(let p of e.files){let c=p.target||p.path;c.startsWith("components/")&&(c=c.slice(11));let d=te(l,c),$=Te(l,d);if($.startsWith("..")||Oe($))throw new Error(`Invalid registry file path: ${c}`);let m=Pe(d);if(ee(m)||Ce(m,{recursive:!0}),ee(d)&&!i){let f=await s(c);if(f==="skip"){n.push(c);continue}f==="all"&&(i=!0)}let g=Ee(p.content,t.alias);ke(d,g,"utf-8"),r.push(c)}return{written:r,skipped:n}},ne=(e,t,o)=>{let s=!0;if(e.length>0){let r={npm:["npm","install",...e],pnpm:["pnpm","add",...e],yarn:["yarn","add",...e],bun:["bun","add",...e]},[n,...i]=r[o];Z(n,i,{stdio:"pipe"}).status!==0&&(s=!1)}if(t.length>0){let r={npm:["npm","install","-D",...t],pnpm:["pnpm","add","-D",...t],yarn:["yarn","add","-D",...t],bun:["bun","add","-d",...t]},[n,...i]=r[o];Z(n,i,{stdio:"pipe"}).status!==0&&(s=!1)}return s};var se=process.env.SMOOTHUI_REGISTRY_URL||_,Me=/\/r\/([^/]+)\.json$/;async function Ae(){let e=`${se}/r/registry.json`,t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch registry: ${t.status}`);return t.json()}async function re(e){let t=`${se}/r/${e}.json`,o=await fetch(t);if(!o.ok)throw new Error(`Component "${e}" not found`);return o.json()}function ie(e){let t=e.match(Me);return t?t[1]:e}async function L(){return(await Ae()).items.map(t=>t.name)}async function F(e,t=new Set){let o=await re(e);t.add(e);let s=[];if(o.registryDependencies)for(let r of o.registryDependencies){let n=ie(r);if(t.has(n)||!r.includes("smoothui.dev"))continue;let i=await F(n,t);s.push(i)}return{component:o,children:s}}function U(e){let t=[e.component];for(let o of e.children)t.push(...U(o));return t}function ce(e){let t=new Set,o=new Set,s=new Set(["react","react-dom","next","tailwindcss","@types/react","@types/react-dom","@types/node","typescript"]);for(let r of e){for(let n of r.dependencies||[])s.has(n)||t.add(n);for(let n of r.devDependencies||[])s.has(n)||o.add(n)}return{dependencies:[...t],devDependencies:[...o]}}function G(e,t="",o=!0){y(`${t}${o?"\u2514\u2500":"\u251C\u2500"} ${e.component.name}`);let r=t+(o?" ":"\u2502 "),n=[...e.component.dependencies||[]].filter(i=>!["react","react-dom","next"].includes(i));n.length>0&&e.children.length===0&&y(`${r}\u2514\u2500 ${D(`npm: ${n.join(", ")}`)}`);for(let i=0;i<e.children.length;i++){let l=e.children[i],p=i===e.children.length-1&&n.length===0;G(l,r,p)}n.length>0&&e.children.length>0&&y(`${r}\u2514\u2500 ${D(`npm: ${n.join(", ")}`)}`)}async function le(e,t){j();let o=z();t.path&&(o.componentPath=t.path),w(`Detected: ${o.componentPath}/ (${o.packageManager})`),console.log();let s=e;if(s.length===0){let b=(await L()).map(u=>{let v="Other";for(let[N,me]of Object.entries(O))if(me.includes(u)){v=N;break}return{value:u,label:u,category:v}}),x=await W({message:"Select components to install:",items:b});if(!x||x.length===0){console.log(),w("No components selected.");return}s=x,w(`Selected: ${s.join(", ")}`),console.log()}E("Resolving dependencies..."),y();let r=[],n=new Set;for(let f of s)if(!n.has(f))try{let b=await F(f),x=U(b);for(let u of x)n.has(u.name)||(n.add(u.name),r.push(u));G(b)}catch(b){P(`Failed to resolve ${f}: ${b.message}`);return}y();let{dependencies:i,devDependencies:l}=ce(r),p=[...i,...l],c=r.length,d=i.length+l.length,$=d>0?`Install ${c} component${c>1?"s":""} + ${d} npm package${d>1?"s":""}?`:`Install ${c} component${c>1?"s":""}?`,m=await Le({message:$});if(ae(m)||!m){w("Installation cancelled.");return}console.log();let g=t.force??!1;for(let f of r){let{written:b,skipped:x}=await oe(f,o,g,async u=>{let v=await Ne({message:`File exists: ${u}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return ae(v)?"skip":(v==="all"&&(g=!0),v)});for(let u of b)w(`Written: ${o.componentPath}/${u}`);for(let u of x)w(`Skipped: ${u}`)}if(i.length>0||l.length>0){let f=De();if(f.start(`Installing ${p.join(", ")}`),ne(i,l,o.packageManager))f.stop(`Installed: ${p.join(", ")}`);else if(f.stop("Failed to install dependencies"),i.length>0&&y(`Run manually: ${o.packageManager} add ${i.join(" ")}`),l.length>0){let x=o.packageManager==="bun"?"-d":"-D";y(`Run manually: ${o.packageManager} add ${x} ${l.join(" ")}`)}}console.log(),V(`Done! ${c} component${c>1?"s":""} installed.`)}async function pe(e){let t=await L();if(e.json){console.log(JSON.stringify(t,null,2));return}j(),E(`Available components (${t.length})`),y();let o=new Map;for(let s of t){let r="Other";for(let[i,l]of Object.entries(O))if(l.includes(s)){r=i;break}let n=o.get(r);n?n.push(s):o.set(r,[s])}for(let[s,r]of o){y(q(R(s)));for(let n of r.sort())y(` ${n}`);y()}w(`Use ${R("npx smoothui add <component>")} to install`)}var C=process.argv.slice(2),I=C[0];function de(){j(),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(!I||I==="--help"||I==="-h"){de();return}if(I==="add"){let e=[],t,o=!1;for(let s=1;s<C.length;s++){let r=C[s];r==="--path"&&C[s+1]?(t=C[s+1],s++):r==="--force"||r==="-f"?o=!0:r.startsWith("-")||e.push(r)}await le(e,{path:t,force:o});return}if(I==="list"||I==="ls"){let e=C.includes("--json");await pe({json:e});return}P(`Unknown command: ${I}`),de(),process.exit(1)}catch(e){let t=e instanceof Error?e.message:String(e);P(t||"An unknown error occurred"),process.exit(1)}}Fe(); | ||
| import{confirm as et,isCancel as be,select as tt,spinner as nt}from"@clack/prompts";var X="https://smoothui.dev",D={"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"]},Z=["src/components/ui","components/ui","src/components","components","app/components/ui"],ee=[{file:"bun.lockb",cmd:"bun"},{file:"pnpm-lock.yaml",cmd:"pnpm"},{file:"yarn.lock",cmd:"yarn"},{file:"package-lock.json",cmd:"npm"}],te={active:"\u25C6",done:"\u25C7",selected:"\u25CF",unselected:"\u25CB",cursor:"\u276F",success:"\u2713",error:"\u2717",bar:"\u2502"};import{createInterface as je,emitKeypressEvents as Ee}from"readline";import{Writable as Te}from"stream";import m from"picocolors";var Ae=new Te({write(e,t,n){n()}}),Pe=m.green("\u25C6"),ke=m.red("\u25A0"),Oe=m.green("\u25C7"),Me=m.green("\u25CF"),Le=m.dim("\u25CB"),x=m.dim("\u2502"),ne=e=>{let{message:t,items:n,maxVisible:o=8}=e;return new Promise(s=>{let r=je({input:process.stdin,output:Ae,terminal:!1});process.stdin.isTTY&&process.stdin.setRawMode(!0),Ee(process.stdin,r);let c="",a=0,d=new Set,l=0,y=(p,i)=>{if(!i)return!0;let b=i.toLowerCase();return p.label.toLowerCase().includes(b)||p.value.toLowerCase().includes(b)},I=()=>n.filter(p=>y(p,c)),j=()=>{if(l>0){process.stdout.write(`\x1B[${l}A`);for(let p=0;p<l;p++)process.stdout.write("\x1B[2K\x1B[1B");process.stdout.write(`\x1B[${l}A`)}},h=(p="active")=>{j();let i=[],b=I(),A=p==="active"?Pe:p==="cancel"?ke:Oe;if(i.push(`${A} ${m.bold(t)}`),p==="active"){let K=`${x} ${m.dim("Search:")} ${c}${m.inverse(" ")}`;i.push(K),i.push(`${x} ${m.dim("\u2191\u2193 move, space select, enter confirm")}`),i.push(`${x}`);let R=Math.max(0,Math.min(a-Math.floor(o/2),b.length-o)),q=Math.min(b.length,R+o),z=b.slice(R,q);if(b.length===0)i.push(`${x} ${m.dim("No matches found")}`);else{for(let $=0;$<z.length;$++){let L=z[$],xe=R+$,ye=d.has(L.value),Q=xe===a,Se=ye?Me:Le,Re=Q?m.underline(L.label):L.label,Ce=L.hint?m.dim(` (${L.hint})`):"",Ie=Q?m.cyan("\u276F"):" ";i.push(`${x} ${Ie} ${Se} ${Re}${Ce}`)}let C=R,M=b.length-q;if(C>0||M>0){let $=[];C>0&&$.push(`\u2191 ${C} more`),M>0&&$.push(`\u2193 ${M} more`),i.push(`${x} ${m.dim($.join(" "))}`)}}if(i.push(`${x}`),d.size===0)i.push(`${x} ${m.dim("Selected: (none)")}`);else{let C=n.filter($=>d.has($.value)).map($=>$.label),M=C.length<=3?C.join(", "):`${C.slice(0,3).join(", ")} +${C.length-3} more`;i.push(`${x} ${m.green("Selected:")} ${M}`)}i.push(`${m.dim("\u2514")}`)}else if(p==="submit"){let K=n.filter(R=>d.has(R.value)).map(R=>R.label);i.push(`${x} ${m.dim(K.join(", "))}`)}else p==="cancel"&&i.push(`${x} ${m.strikethrough(m.dim("Cancelled"))}`);process.stdout.write(`${i.join(` | ||
| `)} | ||
| `),l=i.length},f=()=>{process.stdin.removeListener("keypress",g),process.stdin.isTTY&&process.stdin.setRawMode(!1),r.close()},v=()=>{h("submit"),f(),s([...d])},w=()=>{h("cancel"),f(),s(null)},g=(p,i)=>{if(!i)return;let b=I();if(i.name==="return"){v();return}if(i.name==="escape"||i.ctrl&&i.name==="c"){w();return}if(i.name==="up"){a=Math.max(0,a-1),h();return}if(i.name==="down"){a=Math.min(b.length-1,a+1),h();return}if(i.name==="space"){let A=b[a];A&&(d.has(A.value)?d.delete(A.value):d.add(A.value)),h();return}if(i.name==="backspace"){c=c.slice(0,-1),a=0,h();return}i.sequence&&!i.ctrl&&!i.meta&&i.sequence.length===1&&(c+=i.sequence,a=0,h())};process.stdin.on("keypress",g),h()})};import E from"picocolors";var N=te,P=E.dim,Ne=E.cyan,_e=E.green,De=E.red,mt=E.yellow,se=E.bold,H=E.gray,Fe=["\x1B[38;5;252m","\x1B[38;5;249m","\x1B[38;5;246m","\x1B[38;5;243m","\x1B[38;5;240m","\x1B[38;5;237m"],Ue="\x1B[0m",oe=["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551","\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D"],Ge="1.1.1";function F(e,t){console.log(`${e} ${t}`)}function U(e){F(Ne(N.active),e)}function S(e){F(P(N.done),e)}function re(e){F(_e(N.success),e)}function _(e){F(De(N.error),e)}function u(e=""){console.log(`${P(N.bar)} ${e}`)}function k(){console.log();for(let e=0;e<oe.length;e++)console.log(`${Fe[e]}${oe[e]}${Ue}`);console.log(),console.log(` ${P(`v${Ge}`)}`),console.log()}import{existsSync as G,readFileSync as ie}from"fs";import{join as Y}from"path";var Ye=/^(npm|pnpm|yarn|bun)@/,Be=()=>{let e=process.cwd();for(let{file:n,cmd:o}of ee)if(G(Y(e,n)))return o;let t=Y(e,"package.json");if(G(t))try{let n=JSON.parse(ie(t,"utf-8"));if(n.packageManager){let o=n.packageManager.match(Ye);if(o)return o[1]}}catch{}return"npm"},Ke=()=>{let e=process.cwd();for(let t of Z)if(G(Y(e,t)))return t;return null},He=()=>{let e=process.cwd(),t=["tsconfig.json","jsconfig.json"];for(let n of t){let o=Y(e,n);if(G(o))try{let r=ie(o,"utf-8").replace(/\/\*[\s\S]*?\*\/|\/\/.*/g,""),a=JSON.parse(r).compilerOptions?.paths;if(a){for(let[d,l]of Object.entries(a))if(d.endsWith("/*")&&Array.isArray(l))return d.slice(0,-2)}}catch{}}return"@"},ce=()=>({componentPath:Ke()||"components/ui",alias:He(),packageManager:Be()});import{spawnSync as ae}from"child_process";import{existsSync as le,mkdirSync as Ve,readFileSync as vt,writeFileSync as We}from"fs";import{dirname as Je,isAbsolute as qe,relative as ze,resolve as pe}from"path";var Qe=(e,t)=>t==="@"?e:e.replace(/@\/components\//g,`${t}/components/`);var me=async(e,t,n,o)=>{let s=[],r=[],c=n,a=pe(process.cwd(),t.componentPath);for(let d of e.files){let l=d.target||d.path;l.startsWith("components/")&&(l=l.slice(11));let y=pe(a,l),I=ze(a,y);if(I.startsWith("..")||qe(I))throw new Error(`Invalid registry file path: ${l}`);let j=Je(y);if(le(j)||Ve(j,{recursive:!0}),le(y)&&!c){let f=await o(l);if(f==="skip"){r.push(l);continue}f==="all"&&(c=!0)}let h=Qe(d.content,t.alias);We(y,h,"utf-8"),s.push(l)}return{written:s,skipped:r}},de=(e,t,n)=>{let o=!0;if(e.length>0){let s={npm:["npm","install",...e],pnpm:["pnpm","add",...e],yarn:["yarn","add",...e],bun:["bun","add",...e]},[r,...c]=s[n];ae(r,c,{stdio:"pipe"}).status!==0&&(o=!1)}if(t.length>0){let s={npm:["npm","install","-D",...t],pnpm:["pnpm","add","-D",...t],yarn:["yarn","add","-D",...t],bun:["bun","add","-d",...t]},[r,...c]=s[n];ae(r,c,{stdio:"pipe"}).status!==0&&(o=!1)}return o};var fe=process.env.SMOOTHUI_REGISTRY_URL||X,Xe=/\/r\/([^/]+)\.json$/;async function Ze(){let e=`${fe}/r/registry.json`,t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch registry: ${t.status}`);return t.json()}async function ge(e){let t=`${fe}/r/${e}.json`,n=await fetch(t);if(!n.ok)throw new Error(`Component "${e}" not found`);return n.json()}function ue(e){let t=e.match(Xe);return t?t[1]:e}async function B(){return(await Ze()).items.map(t=>t.name)}async function V(e,t=new Set){let n=await ge(e);t.add(e);let o=[];if(n.registryDependencies)for(let s of n.registryDependencies){let r=ue(s);if(t.has(r)||!s.includes("smoothui.dev"))continue;let c=await V(r,t);o.push(c)}return{component:n,children:o}}function W(e){let t=[e.component];for(let n of e.children)t.push(...W(n));return t}function he(e){let t=new Set,n=new Set,o=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||[])o.has(r)||t.add(r);for(let r of s.devDependencies||[])o.has(r)||n.add(r)}return{dependencies:[...t],devDependencies:[...n]}}function J(e,t="",n=!0){u(`${t}${n?"\u2514\u2500":"\u251C\u2500"} ${e.component.name}`);let s=t+(n?" ":"\u2502 "),r=[...e.component.dependencies||[]].filter(c=>!["react","react-dom","next"].includes(c));r.length>0&&e.children.length===0&&u(`${s}\u2514\u2500 ${H(`npm: ${r.join(", ")}`)}`);for(let c=0;c<e.children.length;c++){let a=e.children[c],d=c===e.children.length-1&&r.length===0;J(a,s,d)}r.length>0&&e.children.length>0&&u(`${s}\u2514\u2500 ${H(`npm: ${r.join(", ")}`)}`)}async function $e(e,t){k();let n=ce();t.path&&(n.componentPath=t.path),S(`Detected: ${n.componentPath}/ (${n.packageManager})`),console.log();let o=e;if(o.length===0){let v=(await B()).map(g=>{let p="Other";for(let[i,b]of Object.entries(D))if(b.includes(g)){p=i;break}return{value:g,label:g,category:p}}),w=await ne({message:"Select components to install:",items:v});if(!w||w.length===0){console.log(),S("No components selected.");return}o=w,S(`Selected: ${o.join(", ")}`),console.log()}U("Resolving dependencies..."),u();let s=[],r=new Set;for(let f of o)if(!r.has(f))try{let v=await V(f),w=W(v);for(let g of w)r.has(g.name)||(r.add(g.name),s.push(g));J(v)}catch(v){_(`Failed to resolve ${f}: ${v.message}`);return}u();let{dependencies:c,devDependencies:a}=he(s),d=[...c,...a],l=s.length,y=c.length+a.length,I=y>0?`Install ${l} component${l>1?"s":""} + ${y} npm package${y>1?"s":""}?`:`Install ${l} component${l>1?"s":""}?`,j=await et({message:I});if(be(j)||!j){S("Installation cancelled.");return}console.log();let h=t.force??!1;for(let f of s){let{written:v,skipped:w}=await me(f,n,h,async g=>{let p=await tt({message:`File exists: ${g}`,options:[{value:"overwrite",label:"Overwrite"},{value:"skip",label:"Skip"},{value:"all",label:"Overwrite all"}]});return be(p)?"skip":(p==="all"&&(h=!0),p)});for(let g of v)S(`Written: ${n.componentPath}/${g}`);for(let g of w)S(`Skipped: ${g}`)}if(c.length>0||a.length>0){let f=nt();if(f.start(`Installing ${d.join(", ")}`),de(c,a,n.packageManager))f.stop(`Installed: ${d.join(", ")}`);else if(f.stop("Failed to install dependencies"),c.length>0&&u(`Run manually: ${n.packageManager} add ${c.join(" ")}`),a.length>0){let w=n.packageManager==="bun"?"-d":"-D";u(`Run manually: ${n.packageManager} add ${w} ${a.join(" ")}`)}}console.log(),re(`Done! ${l} component${l>1?"s":""} installed.`)}async function ve(e){let t=await B();if(e.json){console.log(JSON.stringify(t,null,2));return}k(),U(`Available components (${t.length})`),u();let n=new Map;for(let o of t){let s="Other";for(let[c,a]of Object.entries(D))if(a.includes(o)){s=c;break}let r=n.get(s);r?r.push(o):n.set(s,[o])}for(let[o,s]of n){u(se(P(o)));for(let r of s.sort())u(` ${r}`);u()}S(`Use ${P("npx smoothui add <component>")} to install`)}var O=process.argv.slice(2),T=O[0];function we(){k(),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 ot(){try{if(!T||T==="--help"||T==="-h"){we();return}if(T==="add"){let e=[],t,n=!1;for(let o=1;o<O.length;o++){let s=O[o];s==="--path"&&O[o+1]?(t=O[o+1],o++):s==="--force"||s==="-f"?n=!0:s.startsWith("-")||e.push(s)}await $e(e,{path:t,force:n});return}if(T==="list"||T==="ls"){let e=O.includes("--json");await ve({json:e});return}_(`Unknown command: ${T}`),we(),process.exit(1)}catch(e){let t=e instanceof Error?e.message:String(e);_(t||"An unknown error occurred"),process.exit(1)}}ot(); |
+1
-1
| { | ||
| "name": "smoothui-cli", | ||
| "version": "1.1.0", | ||
| "version": "1.1.1", | ||
| "author": "educalvolpz", | ||
@@ -5,0 +5,0 @@ "description": "CLI to install SmoothUI components - beautifully designed React components with smooth animations", |
+31
-373
@@ -1,99 +0,15 @@ | ||
| # SmoothUI | ||
| # smoothui-cli | ||
|  | ||
| CLI to install [SmoothUI](https://smoothui.dev) components - beautifully designed React components with smooth animations. | ||
| <div align="center"> | ||
| ## Installation | ||
|  | ||
|  | ||
|  | ||
| [](https://actions-badge.atrox.dev/educlopez/smoothui/goto?ref=main) | ||
|  | ||
|  | ||
|  | ||
|  | ||
| [](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 |
55
1.85%21296
-32.8%