@jongh/cli 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/index.cjs +7 -0
  2. package/dist/index.js +6 -1
  3. package/package.json +26 -5
  4. package/.lintstagedrc.json +0 -4
  5. package/CHANGELOG.md +0 -7
  6. package/dist/components/Accordion/Accordion.tsx +0 -281
  7. package/dist/components/Accordion/index.tsx +0 -37
  8. package/dist/components/Accordion/useAccordionHeight.ts +0 -25
  9. package/dist/components/Avatar/Avatar.tsx +0 -18
  10. package/dist/components/Avatar/useAvatar.ts +0 -73
  11. package/dist/components/Button/index.tsx +0 -32
  12. package/dist/components/Primitive/index.tsx +0 -58
  13. package/dist/components/RovingIndex/RovingItem.tsx +0 -47
  14. package/dist/components/RovingIndex/RovingTabIndexRoot.tsx +0 -92
  15. package/dist/components/RovingIndex/index.ts +0 -3
  16. package/dist/components/RovingIndex/useRovingTabIndex.tsx +0 -76
  17. package/dist/components/Select/index.tsx +0 -231
  18. package/dist/components/Slider/index.tsx +0 -141
  19. package/dist/components/Slider/style.ts +0 -29
  20. package/dist/components/Tabs/Tab.tsx +0 -39
  21. package/dist/components/Tabs/TabContent.tsx +0 -62
  22. package/dist/components/Tabs/TabIndicator.tsx +0 -6
  23. package/dist/components/Tabs/TabList.tsx +0 -117
  24. package/dist/components/Tabs/index.ts +0 -43
  25. package/dist/components/Tabs/useRovingTabIndex.tsx +0 -171
  26. package/dist/components/Tabs/useTabContext.ts +0 -11
  27. package/dist/components/TagButton/TagButton.tsx +0 -75
  28. package/dist/components/TagButton/style.ts +0 -35
  29. package/dist/components/core/Polymorphic/index.ts +0 -26
  30. package/dist/components/index.ts +0 -5
  31. package/dist/index.d.ts +0 -1
  32. package/src/copyComponent.ts +0 -29
  33. package/src/getConfig.ts +0 -56
  34. package/src/index.ts +0 -46
  35. package/tsconfig.json +0 -14
  36. package/tsup.config.ts +0 -14
package/dist/index.cjs ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ "use strict";var Te=Object.create;var J=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var $e=Object.getOwnPropertyNames;var Ae=Object.getPrototypeOf,Ne=Object.prototype.hasOwnProperty;var De=(t,e,o,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of $e(e))!Ne.call(t,r)&&r!==o&&J(t,r,{get:()=>e[r],enumerable:!(a=Fe(e,r))||a.enumerable});return t};var f=(t,e,o)=>(o=t!=null?Te(Ae(t)):{},De(e||!t||!t.__esModule?J(o,"default",{value:t,enumerable:!0}):o,t));var X=require("pkg-dir");var W=f(require("path"),1),V=f(require("fs-extra"),1);async function G(t){return await V.default.pathExists(W.default.join(t,"components.json"))}var Y=f(require("fast-glob"),1),Me=f(require("fs-extra"),1),Q=require("tsconfig-paths");var H=t=>{let e={};for(let o of t)e[o]=o;return e},z=H(["config_not_found","resolve_path_fail","failed_to_fetch"]),Ge=H(["components.json","tsconfig.json","panda.config.*","package.json"]),v=class extends Error{issue;constructor(e){super(),this.name="NewError",this.issue=e}get format(){return this.issue.code+`
3
+ `+this.issue.message?.join(`
4
+ `)}},h=t=>{let e;switch(t.code){case z.config_not_found:e=`error occured while config ${t.configFile}`;break;case z.resolve_path_fail:e=`failed to resolve your path, current ${t.cwd}`;break;case z.failed_to_fetch:e=`failed to fetch ${t.target} [${t.statusCode}]`;break;default:e="error occured"}return new v({...t,message:[...t.message||"",e]})};function Z(t,e){let o=(0,Q.loadConfig)(t);if(o?.resultType==="failed"||!Object.entries(o?.paths).length)return{baseAlias:null,styledSystemAlias:null};let a=null,r=null;for(let[s,c]of Object.entries(o.paths))c[0].includes(e)&&(r=s.replace(/\/\*$/,"")),(c.includes("./*")||c.includes("./src/*")||c.includes("./app/*"))&&(a=s.replace(/\/\*$/,""));return a||(a=Object.keys(o?.paths)?.[0].replace(/\/\*$/,"")??null),r||(r="."),{baseAlias:a,styledSystemAlias:r}}async function N(t){try{let e=await Y.default.glob(["panda.config.*"],{cwd:t,deep:3});if(!e.length)throw h({code:"config_not_found",configFile:"panda.config.*",message:["failed to find panda.config file"]});return e[0]}catch(e){throw h({code:"config_not_found",configFile:"panda.config.*",message:[e instanceof Error?e.message:"unknown error occured finding panda.config"]})}}async function D(t){let e=t.match(/outdir:\s*["']([^"']+)["']/),o=t.match(/importMap:\s*({[^}]+}|["'][^"']+["'])/),a=e?e[1]:null,r=null;if(o){let s=o[1];if(s.startsWith("{")){let c=s.match(/css:\s*["']([^"']+)["']/);r=c?c[1].replace(/\/css$/,""):null}else r=s.replace(/["']/g,"")}return{outdir:a,importMap:r}}var P=f(require("path"),1);var d=require("zod"),b={fileName:"components.json",schema:d.z.object({utils:d.z.string(),components:d.z.string(),hooks:d.z.string(),styledsystem:d.z.string()}).strict()},Oe=["ui","hooks","utils"],ze=d.z.object({name:d.z.string(),content:d.z.string(),type:d.z.enum(Oe)}),q=d.z.object({name:d.z.string(),dependencies:d.z.array(d.z.string()).optional(),files:d.z.array(ze).optional()});var R=require("zod"),ee=require("commander"),L=f(require("fs-extra"),1),te=require("@clack/prompts"),M=require("ts-morph"),Re=R.z.object({cwd:R.z.string()}),oe=new ee.Command().name("init").description("Initialize the project").option("-c, --cwd <cwd>","current working directory, default to process.cwd()",process.cwd()).action(async t=>{let e=(0,te.spinner)();e.start("Initializing");try{let o=Re.parse({cwd:P.default.resolve(t.cwd)});await Le(o),e.stop("Initialized")}catch(o){o instanceof Error&&console.error(o.message),e.stop("Failed to initialize"),process.exit(0)}});async function Le(t){let e=t.cwd||await(0,X.packageDirectory)();if(!e)throw new Error("Failed to find package root");if(await G(e))throw new Error("Already initialized");let a=await N(e),r=await L.default.readFile(P.default.resolve(e,a),"utf-8"),s="styled-system",{outdir:c,importMap:g}=await D(r);c&&(s=c);let{baseAlias:y,styledSystemAlias:p}=Z(e,s);if(!y||!p)throw new Error("Failed to find tsconfig alias");g?s=g:s=p;let u={utils:`${y}/utils`,components:`${y}/components`,hooks:`${y}/hooks`,styledsystem:s};b.schema.parse(u);let l=new M.Project().addSourceFileAtPath(P.default.resolve(e,a));l.addImportDeclaration({namedImports:[{name:"preset"}],moduleSpecifier:"panda-animation"}),l.addImportDeclaration({namedImports:[{name:"defaultPreset"}],moduleSpecifier:"./preset"});let n=l.getFirstDescendantByKind(M.SyntaxKind.CallExpression)?.getArguments()[0];return n?(n.getProperty("presets")||n.addPropertyAssignment({name:"presets",initializer:"[preset(), @pandacss/preset-panda, defaultPreset]"}),l.saveSync()):console.warn("Could not find config object in panda.config.ts"),await L.default.writeFile(P.default.resolve(e,"components.json"),JSON.stringify(u),"utf-8"),u}var je=require("commander");var re={name:"@jongh/cli",version:"1.2.0",description:"",bin:"./dist/index.js",type:"module",scripts:{build:"tsup && npx tsx ./src/build-script.ts --all","build:cli":"tsup","build:registry":"npx tsx ./src/build-script.ts --all",release:"pnpm publish -no-git-checks",lint:"eslint . --max-warnings 0","check-type":"tsc --noEmit",test:"vitest run"},keywords:[],author:"",license:"ISC",publishConfig:{access:"public"},files:["dist","package.json"],dependencies:{"@babel/generator":"^7.26.3","@babel/parser":"^7.26.3","@babel/traverse":"^7.26.4","@clack/prompts":"^0.7.0","@effect/platform":"^0.69.13","@effect/schema":"^0.75.5","@types/babel__traverse":"^7.20.6",chalk:"^5.4.1",commander:"^13.0.0",effect:"^3.10.8",execa:"^9.5.2","fast-glob":"^3.3.2","fs-extra":"^11.2.0","package-manager-detector":"^0.2.8","pkg-dir":"^8.0.0","ts-morph":"^25.0.0","tsconfig-paths":"^4.2.0",yargs:"^17.7.2",zod:"^3.24.1"},devDependencies:{"@types/babel__generator":"^7.6.8","@types/fs-extra":"^11.0.4","@types/node":"^22.8.6","@types/yargs":"^17.0.33","ts-node":"^10.9.2",tsup:"^8.3.0",tsx:"^4.19.2"}};var ge=require("commander"),E=f(require("path"),1),k=require("zod"),F=f(require("fs-extra"),1),w=require("@clack/prompts");var ne=f(require("fs-extra"),1),ae=f(require("path"),1),ie=require("tsconfig-paths");var se=require("tsconfig-paths");async function T(t,e){let o=(0,se.createMatchPath)(e.absoluteBaseUrl,e.paths)(t,void 0,()=>!0);if(!o)throw h({code:"resolve_path_fail",target:t,cwd:process.cwd(),message:["resolve error"]});return o}function ce(t){try{return ne.default.readJsonSync(ae.default.resolve(t,b.fileName))}catch(e){return h({code:"config_not_found",configFile:b.fileName,message:[e instanceof Error?e.message:""]})}}async function pe(t){let e=(0,ie.loadConfig)(t);if(e.resultType==="failed")throw h({code:"config_not_found",configFile:"tsconfig.json",message:["cannot found tsconfig.json"]});return e}var I=require("ts-morph");function me(t,e){let o=t;return[{from:/@utils\//g,to:`${e.utils}/`},{from:/@hooks\//g,to:`${e.hooks}/`},{from:/@styled-system\//g,to:`${e.styledsystem}/`},{from:/@components\//g,to:`${e.components}/`}].forEach(({from:r,to:s})=>{o=o.replace(r,s)}),o}function le(t,e,o){let r=new I.Project().addSourceFileAtPath(t),s=r.getFirstDescendant(p=>I.Node.isCallExpression(p)&&p.getExpression().getText()==="definePreset");if(!s)return;let c=s?.getFirstDescendant(p=>I.Node.isPropertyAssignment(p)&&p.getName()==="recipes");if(!c)return;let g=c.getFirstDescendantByKind(I.SyntaxKind.ObjectLiteralExpression);if(!g)return;r.getImportDeclarations().some(p=>{let u=p.getModuleSpecifierValue(),m=p.getNamedImports();return u===o&&m.some(l=>l.getName()===`${e}Recipe`)})||(r.addImportDeclaration({moduleSpecifier:o,namedImports:[{name:`${e}Recipe`}]}),g.addPropertyAssignment({name:e,initializer:`${e}Recipe`})),r.saveSync()}var B=require("execa"),ue=require("package-manager-detector");var de=require("package-manager-detector");async function fe(t){let e=await(0,de.detect)({cwd:t});if(!e)throw new Error("package manager not found");return e.name==="pnpm"?"pnpm exec":e.name==="bun"?"bunx":e.name==="yarn"?"yarn dlx":"npx"}var K=f(require("chalk"),1),Ke=k.z.object({components:k.z.array(k.z.string()).optional(),cwd:k.z.string()}),Ue="https://whdgur.shop",he=new ge.Command().name("add").argument("[components...]").option("-c, --cwd <cwd>","current working directory, default to process.cwd()",process.cwd()).action(async(t,e)=>{let o=K.default.bold.red,a=K.default.bold.blue;try{let r=Ke.parse({components:t,...e});(0,w.intro)(a("install components..."));let s=b.schema.parse(ce(r.cwd)),c=await pe(r.cwd),g=await N(r.cwd),y=await F.default.readFile(E.default.resolve(r.cwd,g),"utf-8"),{outdir:p}=await D(y),u=b.schema.parse({utils:await T(s.utils,c),components:await T(s.components,c),hooks:await T(s.hooks,c),styledsystem:E.default.join(r.cwd,p||"styled-system")}),m=r.components?.map(i=>i.toLowerCase());if(!m?.length)return;(await Promise.allSettled(m?.map(async i=>{try{let n=await fetch(`${Ue}/${i}.json`);if(!n.ok)throw new Error("fetch error",{cause:{code:"failed_to_fetch",target:i,statusCode:n.status,message:[n.statusText]}});return await n.json()}catch(n){if(n instanceof TypeError)throw h({code:"failed_to_fetch",target:i,statusCode:null,message:[o(n.message),o(n.cause?JSON.stringify(n.cause):"cause by typeError")]});if(n instanceof Error)throw h(n.cause)}}))).forEach(async(i,n)=>{if(i.status==="rejected"){i.reason instanceof v&&console.log(o(i.reason.format));return}try{let x=q.parse(i.value),_=E.default.join(u.components,m[n]);if(F.default.pathExistsSync(_)&&!await(0,w.confirm)({message:`Component ${m[n]} already exists. Do you want to overwrite it?`}))return;x.files?.forEach(C=>{let U=me(C.content,s);C.name==="recipe.ts"&&le(E.default.join(r.cwd,"preset.ts"),`${m[n]}`,E.default.join(s.components,`${m[n]}`,"recipe")),C.type==="ui"?F.default.outputFileSync(E.default.join(_,C.name),U):F.default.outputFileSync(E.default.join(u[C.type],C.name),U,"utf-8")});let $=await(0,ue.detect)({cwd:r.cwd}),A=$?$.name:"";A||(A=await(0,w.select)({message:"cannot find package manager, select",options:[{value:"npm",label:"npm"},{value:"pnpm",label:"pnpm"},{value:"yarn",label:"yarn"}]})),x.dependencies?.length&&await(0,B.execa)(A,[A==="npm"?"install":"add",...x.dependencies]);let ve=await fe(r.cwd),[_e,...Pe]=ve.split(" ");(0,B.execa)(_e,[...Pe,"panda","codegen"]),(0,w.outro)(a(`${m[n]} completed successfully`))}catch(x){console.log(x)}})}catch(r){r instanceof k.ZodError&&o(r.message),r instanceof v&&o(r.format),r instanceof Error&&o(r.message),(0,w.outro)(a("error occured")),process.exit(1)}});var Ce=require("commander"),be=f(require("fast-glob"),1),Ee=f(require("path"),1);var S=require("ts-morph"),ye={"@radix-ui/react-accessible-icon":"AccessibleIcon","@radix-ui/react-accordion":"Accordion","@radix-ui/react-alert-dialog":"AlertDialog","@radix-ui/react-aspect-ratio":"AspectRatio","@radix-ui/react-avatar":"Avatar","@radix-ui/react-checkbox":"Checkbox","@radix-ui/react-collapsible":"Collapsible","@radix-ui/react-context-menu":"ContextMenu","@radix-ui/react-dialog":"Dialog","@radix-ui/react-direction":"Direction","@radix-ui/react-dropdown-menu":"DropdownMenu","@radix-ui/react-form":"Form","@radix-ui/react-hover-card":"HoverCard","@radix-ui/react-label":"Label","@radix-ui/react-menubar":"Menubar","@radix-ui/react-navigation-menu":"NavigationMenu","@radix-ui/react-popover":"Popover","@radix-ui/react-portal":"Portal","@radix-ui/react-progress":"Progress","@radix-ui/react-radio-group":"RadioGroup","@radix-ui/react-scroll-area":"ScrollArea","@radix-ui/react-select":"Select","@radix-ui/react-separator":"Separator","@radix-ui/react-slider":"Slider","@radix-ui/react-slot":"Slot","@radix-ui/react-switch":"Switch","@radix-ui/react-tabs":"Tabs","@radix-ui/react-toast":"Toast","@radix-ui/react-toggle":"Toggle","@radix-ui/react-toggle-group":"ToggleGroup","@radix-ui/react-toolbar":"Toolbar","@radix-ui/react-tooltip":"Tooltip","@radix-ui/react-visually-hidden":"VisuallyHidden"};function O(t,e,o){return o?t===o:t===e}function xe(t){return`import {${t}} from "radix-ui"`}function we(t){let e=[];return t.getImportDeclarations().forEach(o=>{let a=o.getModuleSpecifierValue();if(!(a in ye))return;let r=ye[a];e.push(a);let s=o.getNamespaceImport();if(s){let g=s.getText();r!==g&&(r+=` as ${g}`),o.replaceWithText(xe(r));return}let c=o.getNamedImports();if(c.length){let g=r;c.forEach(y=>{let p=y.getName(),u=y.getAliasNode()?.getText(),m=`${g}.${p}`;for(let l of[S.SyntaxKind.JsxOpeningElement,S.SyntaxKind.JsxClosingElement,S.SyntaxKind.JsxSelfClosingElement])t.getDescendantsOfKind(l).forEach(i=>{let n=i.getTagNameNode().getText();O(n,p,u)&&i.getTagNameNode().replaceWithText(m)});t.getDescendantsOfKind(S.SyntaxKind.TypeQuery).forEach(l=>{l.getChildren().forEach(i=>{let n=i.getText();O(n,p,u)&&i.replaceWithText(m)})}),t.getDescendantsOfKind(S.SyntaxKind.ExpressionStatement).forEach(l=>{l.getChildrenOfKind(S.SyntaxKind.BinaryExpression).forEach(n=>{n.getRight().getChildren().forEach(_=>{let $=_.getText();O($,p,u)&&_.replaceWithText(m)})})}),t.getDescendantsOfKind(S.SyntaxKind.VariableDeclaration).forEach(l=>{let i=l.getInitializer();i&&i.getChildren().forEach(n=>{let x=n.getText();O(x,p,u)&&n.replaceWithText(m)})})}),o.replaceWithText(xe(g))}}),{source:t.getFullText(),packages:e}}var Se=require("ts-morph"),j=require("@clack/prompts"),Ie=f(require("chalk"),1),ke=new Ce.Command().name("radix-ui-import").action(()=>{(0,j.intro)("find .tsx files...");let t=be.default.sync("**/*.tsx",{ignore:["**/node_modules/**"],dot:!1}),e=new Se.Project,o="";t.forEach(a=>{let r=e.addSourceFileAtPathIfExists(Ee.default.join(process.cwd(),a));if(r)try{let{packages:s}=we(r);o+=s.join(" "),r.save()}catch(s){j.log.error(`failed to transform ${a} ${s}`)}}),o.length?`copy this to delete and install new package
5
+ <your package manager's delete command> ${o}
6
+ <your package manager's install command> ${Ie.default.bgGreen("radix-ui")}`.split(`
7
+ `).forEach(j.log.step):(0,j.outro)("no transform occured")});async function Je(){new je.Command().name("design-system").version(re.version||"0.0.0").addCommand(oe).addCommand(he).addCommand(ke).parse()}Je();
package/dist/index.js CHANGED
@@ -1,2 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import P from"yargs";import{hideBin as C}from"yargs/helpers";import m from"node:path";import a from"fs-extra";import{packageDirectory as l}from"pkg-dir";import*as t from"@clack/prompts";var f="./src/components/ui",d="component.json";async function i(){let o=await l(),n=m.join(o||process.cwd(),d);try{return await a.readJSON(n)}catch{t.note("\uC124\uC815 \uD30C\uC77C\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");let e=await u();return await a.outputJSON(n,{...e},{spaces:2}),e}}var u=async()=>t.group({outputPath:()=>t.text({message:"\uCEF4\uD3EC\uB10C\uD2B8 \uC800\uC7A5 \uACBD\uB85C\uB97C \uC124\uC815\uD574\uC8FC\uC138\uC694",initialValue:f,validate:o=>{if(!o)return"Please enter a path.";if(!o.startsWith("."))return"Please enter a relative path to the project root."}})},{onCancel:()=>{t.cancel("Operation cancelled."),process.exit(0)}});import*as s from"@clack/prompts";import r from"node:path";import g from"fs-extra";import{fileURLToPath as h}from"node:url";var y=r.dirname(h(import.meta.url)),w=r.join(y,"./components/Button/index.tsx");async function c(o,n){try{let e=w,p=r.join(process.cwd(),n,`${o}.tsx`);await g.copy(e,p),console.log(`${o} copied to ${n}`)}catch(e){throw new Error(`Failed to copy component: ${e}`)}}var j=async()=>{await P(C(process.argv)).command("components add [components..]","Add components to your project",o=>o.positional("components",{describe:"List of components to add",type:"string",array:!0,default:[]}).option("all",{type:"boolean",description:"Add all components",default:!1}),async o=>{if(o.components.length===0&&!o.all){s.cancel("Error: You need to specify at least one component or use the --all flag"),console.log('Run "cli --help" for more information');return}let n=await i();await c(o.components[0],n.outputPath)}).demandCommand(1,"You need at least one command before moving on").strict().help().argv};j();
2
+ import{packageDirectory as fe}from"pkg-dir";import ie from"path";import ce from"fs-extra";async function D(t){return await ce.pathExists(ie.join(t,"components.json"))}import pe from"fast-glob";import qe from"fs-extra";import{loadConfig as me}from"tsconfig-paths";var M=t=>{let e={};for(let o of t)e[o]=o;return e},A=M(["config_not_found","resolve_path_fail","failed_to_fetch"]),He=M(["components.json","tsconfig.json","panda.config.*","package.json"]),E=class extends Error{issue;constructor(e){super(),this.name="NewError",this.issue=e}get format(){return this.issue.code+`
3
+ `+this.issue.message?.join(`
4
+ `)}},u=t=>{let e;switch(t.code){case A.config_not_found:e=`error occured while config ${t.configFile}`;break;case A.resolve_path_fail:e=`failed to resolve your path, current ${t.cwd}`;break;case A.failed_to_fetch:e=`failed to fetch ${t.target} [${t.statusCode}]`;break;default:e="error occured"}return new E({...t,message:[...t.message||"",e]})};function O(t,e){let o=me(t);if(o?.resultType==="failed"||!Object.entries(o?.paths).length)return{baseAlias:null,styledSystemAlias:null};let a=null,r=null;for(let[s,c]of Object.entries(o.paths))c[0].includes(e)&&(r=s.replace(/\/\*$/,"")),(c.includes("./*")||c.includes("./src/*")||c.includes("./app/*"))&&(a=s.replace(/\/\*$/,""));return a||(a=Object.keys(o?.paths)?.[0].replace(/\/\*$/,"")??null),r||(r="."),{baseAlias:a,styledSystemAlias:r}}async function v(t){try{let e=await pe.glob(["panda.config.*"],{cwd:t,deep:3});if(!e.length)throw u({code:"config_not_found",configFile:"panda.config.*",message:["failed to find panda.config file"]});return e[0]}catch(e){throw u({code:"config_not_found",configFile:"panda.config.*",message:[e instanceof Error?e.message:"unknown error occured finding panda.config"]})}}async function _(t){let e=t.match(/outdir:\s*["']([^"']+)["']/),o=t.match(/importMap:\s*({[^}]+}|["'][^"']+["'])/),a=e?e[1]:null,r=null;if(o){let s=o[1];if(s.startsWith("{")){let c=s.match(/css:\s*["']([^"']+)["']/);r=c?c[1].replace(/\/css$/,""):null}else r=s.replace(/["']/g,"")}return{outdir:a,importMap:r}}import P from"path";import{z as d}from"zod";var w={fileName:"components.json",schema:d.object({utils:d.string(),components:d.string(),hooks:d.string(),styledsystem:d.string()}).strict()},le=["ui","hooks","utils"],de=d.object({name:d.string(),content:d.string(),type:d.enum(le)}),z=d.object({name:d.string(),dependencies:d.array(d.string()).optional(),files:d.array(de).optional()});import{z as R}from"zod";import{Command as ge}from"commander";import L from"fs-extra";import{spinner as ue}from"@clack/prompts";import{Project as he,SyntaxKind as ye}from"ts-morph";var xe=R.object({cwd:R.string()}),B=new ge().name("init").description("Initialize the project").option("-c, --cwd <cwd>","current working directory, default to process.cwd()",process.cwd()).action(async t=>{let e=ue();e.start("Initializing");try{let o=xe.parse({cwd:P.resolve(t.cwd)});await we(o),e.stop("Initialized")}catch(o){o instanceof Error&&console.error(o.message),e.stop("Failed to initialize"),process.exit(0)}});async function we(t){let e=t.cwd||await fe();if(!e)throw new Error("Failed to find package root");if(await D(e))throw new Error("Already initialized");let a=await v(e),r=await L.readFile(P.resolve(e,a),"utf-8"),s="styled-system",{outdir:c,importMap:f}=await _(r);c&&(s=c);let{baseAlias:h,styledSystemAlias:p}=O(e,s);if(!h||!p)throw new Error("Failed to find tsconfig alias");f?s=f:s=p;let g={utils:`${h}/utils`,components:`${h}/components`,hooks:`${h}/hooks`,styledsystem:s};w.schema.parse(g);let l=new he().addSourceFileAtPath(P.resolve(e,a));l.addImportDeclaration({namedImports:[{name:"preset"}],moduleSpecifier:"panda-animation"}),l.addImportDeclaration({namedImports:[{name:"defaultPreset"}],moduleSpecifier:"./preset"});let n=l.getFirstDescendantByKind(ye.CallExpression)?.getArguments()[0];return n?(n.getProperty("presets")||n.addPropertyAssignment({name:"presets",initializer:"[preset(), @pandacss/preset-panda, defaultPreset]"}),l.saveSync()):console.warn("Could not find config object in panda.config.ts"),await L.writeFile(P.resolve(e,"components.json"),JSON.stringify(g),"utf-8"),g}import{Command as Ue}from"commander";var K={name:"@jongh/cli",version:"1.2.0",description:"",bin:"./dist/index.js",type:"module",scripts:{build:"tsup && npx tsx ./src/build-script.ts --all","build:cli":"tsup","build:registry":"npx tsx ./src/build-script.ts --all",release:"pnpm publish -no-git-checks",lint:"eslint . --max-warnings 0","check-type":"tsc --noEmit",test:"vitest run"},keywords:[],author:"",license:"ISC",publishConfig:{access:"public"},files:["dist","package.json"],dependencies:{"@babel/generator":"^7.26.3","@babel/parser":"^7.26.3","@babel/traverse":"^7.26.4","@clack/prompts":"^0.7.0","@effect/platform":"^0.69.13","@effect/schema":"^0.75.5","@types/babel__traverse":"^7.20.6",chalk:"^5.4.1",commander:"^13.0.0",effect:"^3.10.8",execa:"^9.5.2","fast-glob":"^3.3.2","fs-extra":"^11.2.0","package-manager-detector":"^0.2.8","pkg-dir":"^8.0.0","ts-morph":"^25.0.0","tsconfig-paths":"^4.2.0",yargs:"^17.7.2",zod:"^3.24.1"},devDependencies:{"@types/babel__generator":"^7.6.8","@types/fs-extra":"^11.0.4","@types/node":"^22.8.6","@types/yargs":"^17.0.33","ts-node":"^10.9.2",tsup:"^8.3.0",tsx:"^4.19.2"}};import{Command as _e}from"commander";import C from"path";import{z as T,ZodError as Pe}from"zod";import F from"fs-extra";import{confirm as Te,select as Fe,intro as $e,outro as Y}from"@clack/prompts";import Ee from"fs-extra";import Se from"path";import{loadConfig as Ie}from"tsconfig-paths";import{createMatchPath as be}from"tsconfig-paths";async function I(t,e){let o=be(e.absoluteBaseUrl,e.paths)(t,void 0,()=>!0);if(!o)throw u({code:"resolve_path_fail",target:t,cwd:process.cwd(),message:["resolve error"]});return o}function U(t){try{return Ee.readJsonSync(Se.resolve(t,w.fileName))}catch(e){return u({code:"config_not_found",configFile:w.fileName,message:[e instanceof Error?e.message:""]})}}async function J(t){let e=Ie(t);if(e.resultType==="failed")throw u({code:"config_not_found",configFile:"tsconfig.json",message:["cannot found tsconfig.json"]});return e}import{Project as ke,Node as W,SyntaxKind as je}from"ts-morph";function V(t,e){let o=t;return[{from:/@utils\//g,to:`${e.utils}/`},{from:/@hooks\//g,to:`${e.hooks}/`},{from:/@styled-system\//g,to:`${e.styledsystem}/`},{from:/@components\//g,to:`${e.components}/`}].forEach(({from:r,to:s})=>{o=o.replace(r,s)}),o}function G(t,e,o){let r=new ke().addSourceFileAtPath(t),s=r.getFirstDescendant(p=>W.isCallExpression(p)&&p.getExpression().getText()==="definePreset");if(!s)return;let c=s?.getFirstDescendant(p=>W.isPropertyAssignment(p)&&p.getName()==="recipes");if(!c)return;let f=c.getFirstDescendantByKind(je.ObjectLiteralExpression);if(!f)return;r.getImportDeclarations().some(p=>{let g=p.getModuleSpecifierValue(),m=p.getNamedImports();return g===o&&m.some(l=>l.getName()===`${e}Recipe`)})||(r.addImportDeclaration({moduleSpecifier:o,namedImports:[{name:`${e}Recipe`}]}),f.addPropertyAssignment({name:e,initializer:`${e}Recipe`})),r.saveSync()}import{execa as Q}from"execa";import{detect as Ae}from"package-manager-detector";import{detect as ve}from"package-manager-detector";async function H(t){let e=await ve({cwd:t});if(!e)throw new Error("package manager not found");return e.name==="pnpm"?"pnpm exec":e.name==="bun"?"bunx":e.name==="yarn"?"yarn dlx":"npx"}import Z from"chalk";var Ne=T.object({components:T.array(T.string()).optional(),cwd:T.string()}),De="https://whdgur.shop",q=new _e().name("add").argument("[components...]").option("-c, --cwd <cwd>","current working directory, default to process.cwd()",process.cwd()).action(async(t,e)=>{let o=Z.bold.red,a=Z.bold.blue;try{let r=Ne.parse({components:t,...e});$e(a("install components..."));let s=w.schema.parse(U(r.cwd)),c=await J(r.cwd),f=await v(r.cwd),h=await F.readFile(C.resolve(r.cwd,f),"utf-8"),{outdir:p}=await _(h),g=w.schema.parse({utils:await I(s.utils,c),components:await I(s.components,c),hooks:await I(s.hooks,c),styledsystem:C.join(r.cwd,p||"styled-system")}),m=r.components?.map(i=>i.toLowerCase());if(!m?.length)return;(await Promise.allSettled(m?.map(async i=>{try{let n=await fetch(`${De}/${i}.json`);if(!n.ok)throw new Error("fetch error",{cause:{code:"failed_to_fetch",target:i,statusCode:n.status,message:[n.statusText]}});return await n.json()}catch(n){if(n instanceof TypeError)throw u({code:"failed_to_fetch",target:i,statusCode:null,message:[o(n.message),o(n.cause?JSON.stringify(n.cause):"cause by typeError")]});if(n instanceof Error)throw u(n.cause)}}))).forEach(async(i,n)=>{if(i.status==="rejected"){i.reason instanceof E&&console.log(o(i.reason.format));return}try{let y=z.parse(i.value),S=C.join(g.components,m[n]);if(F.pathExistsSync(S)&&!await Te({message:`Component ${m[n]} already exists. Do you want to overwrite it?`}))return;y.files?.forEach(x=>{let N=V(x.content,s);x.name==="recipe.ts"&&G(C.join(r.cwd,"preset.ts"),`${m[n]}`,C.join(s.components,`${m[n]}`,"recipe")),x.type==="ui"?F.outputFileSync(C.join(S,x.name),N):F.outputFileSync(C.join(g[x.type],x.name),N,"utf-8")});let k=await Ae({cwd:r.cwd}),j=k?k.name:"";j||(j=await Fe({message:"cannot find package manager, select",options:[{value:"npm",label:"npm"},{value:"pnpm",label:"pnpm"},{value:"yarn",label:"yarn"}]})),y.dependencies?.length&&await Q(j,[j==="npm"?"install":"add",...y.dependencies]);let se=await H(r.cwd),[ne,...ae]=se.split(" ");Q(ne,[...ae,"panda","codegen"]),Y(a(`${m[n]} completed successfully`))}catch(y){console.log(y)}})}catch(r){r instanceof Pe&&o(r.message),r instanceof E&&o(r.format),r instanceof Error&&o(r.message),Y(a("error occured")),process.exit(1)}});import{Command as Me}from"commander";import Oe from"fast-glob";import ze from"path";import{SyntaxKind as b}from"ts-morph";var X={"@radix-ui/react-accessible-icon":"AccessibleIcon","@radix-ui/react-accordion":"Accordion","@radix-ui/react-alert-dialog":"AlertDialog","@radix-ui/react-aspect-ratio":"AspectRatio","@radix-ui/react-avatar":"Avatar","@radix-ui/react-checkbox":"Checkbox","@radix-ui/react-collapsible":"Collapsible","@radix-ui/react-context-menu":"ContextMenu","@radix-ui/react-dialog":"Dialog","@radix-ui/react-direction":"Direction","@radix-ui/react-dropdown-menu":"DropdownMenu","@radix-ui/react-form":"Form","@radix-ui/react-hover-card":"HoverCard","@radix-ui/react-label":"Label","@radix-ui/react-menubar":"Menubar","@radix-ui/react-navigation-menu":"NavigationMenu","@radix-ui/react-popover":"Popover","@radix-ui/react-portal":"Portal","@radix-ui/react-progress":"Progress","@radix-ui/react-radio-group":"RadioGroup","@radix-ui/react-scroll-area":"ScrollArea","@radix-ui/react-select":"Select","@radix-ui/react-separator":"Separator","@radix-ui/react-slider":"Slider","@radix-ui/react-slot":"Slot","@radix-ui/react-switch":"Switch","@radix-ui/react-tabs":"Tabs","@radix-ui/react-toast":"Toast","@radix-ui/react-toggle":"Toggle","@radix-ui/react-toggle-group":"ToggleGroup","@radix-ui/react-toolbar":"Toolbar","@radix-ui/react-tooltip":"Tooltip","@radix-ui/react-visually-hidden":"VisuallyHidden"};function $(t,e,o){return o?t===o:t===e}function ee(t){return`import {${t}} from "radix-ui"`}function te(t){let e=[];return t.getImportDeclarations().forEach(o=>{let a=o.getModuleSpecifierValue();if(!(a in X))return;let r=X[a];e.push(a);let s=o.getNamespaceImport();if(s){let f=s.getText();r!==f&&(r+=` as ${f}`),o.replaceWithText(ee(r));return}let c=o.getNamedImports();if(c.length){let f=r;c.forEach(h=>{let p=h.getName(),g=h.getAliasNode()?.getText(),m=`${f}.${p}`;for(let l of[b.JsxOpeningElement,b.JsxClosingElement,b.JsxSelfClosingElement])t.getDescendantsOfKind(l).forEach(i=>{let n=i.getTagNameNode().getText();$(n,p,g)&&i.getTagNameNode().replaceWithText(m)});t.getDescendantsOfKind(b.TypeQuery).forEach(l=>{l.getChildren().forEach(i=>{let n=i.getText();$(n,p,g)&&i.replaceWithText(m)})}),t.getDescendantsOfKind(b.ExpressionStatement).forEach(l=>{l.getChildrenOfKind(b.BinaryExpression).forEach(n=>{n.getRight().getChildren().forEach(S=>{let k=S.getText();$(k,p,g)&&S.replaceWithText(m)})})}),t.getDescendantsOfKind(b.VariableDeclaration).forEach(l=>{let i=l.getInitializer();i&&i.getChildren().forEach(n=>{let y=n.getText();$(y,p,g)&&n.replaceWithText(m)})})}),o.replaceWithText(ee(f))}}),{source:t.getFullText(),packages:e}}import{Project as Re}from"ts-morph";import{intro as Le,log as oe,outro as Be}from"@clack/prompts";import Ke from"chalk";var re=new Me().name("radix-ui-import").action(()=>{Le("find .tsx files...");let t=Oe.sync("**/*.tsx",{ignore:["**/node_modules/**"],dot:!1}),e=new Re,o="";t.forEach(a=>{let r=e.addSourceFileAtPathIfExists(ze.join(process.cwd(),a));if(r)try{let{packages:s}=te(r);o+=s.join(" "),r.save()}catch(s){oe.error(`failed to transform ${a} ${s}`)}}),o.length?`copy this to delete and install new package
5
+ <your package manager's delete command> ${o}
6
+ <your package manager's install command> ${Ke.bgGreen("radix-ui")}`.split(`
7
+ `).forEach(oe.step):Be("no transform occured")});async function Je(){new Ue().name("design-system").version(K.version||"0.0.0").addCommand(B).addCommand(q).addCommand(re).parse()}Je();
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@jongh/cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "",
5
- "main": "index.js",
6
5
  "bin": "./dist/index.js",
7
6
  "type": "module",
8
7
  "keywords": [],
@@ -11,16 +10,33 @@
11
10
  "publishConfig": {
12
11
  "access": "public"
13
12
  },
13
+ "files": [
14
+ "dist",
15
+ "package.json"
16
+ ],
14
17
  "dependencies": {
18
+ "@babel/generator": "^7.26.3",
19
+ "@babel/parser": "^7.26.3",
20
+ "@babel/traverse": "^7.26.4",
15
21
  "@clack/prompts": "^0.7.0",
16
22
  "@effect/platform": "^0.69.13",
17
23
  "@effect/schema": "^0.75.5",
24
+ "@types/babel__traverse": "^7.20.6",
25
+ "chalk": "^5.4.1",
26
+ "commander": "^13.0.0",
18
27
  "effect": "^3.10.8",
28
+ "execa": "^9.5.2",
29
+ "fast-glob": "^3.3.2",
19
30
  "fs-extra": "^11.2.0",
31
+ "package-manager-detector": "^0.2.8",
20
32
  "pkg-dir": "^8.0.0",
21
- "yargs": "^17.7.2"
33
+ "ts-morph": "^25.0.0",
34
+ "tsconfig-paths": "^4.2.0",
35
+ "yargs": "^17.7.2",
36
+ "zod": "^3.24.1"
22
37
  },
23
38
  "devDependencies": {
39
+ "@types/babel__generator": "^7.6.8",
24
40
  "@types/fs-extra": "^11.0.4",
25
41
  "@types/node": "^22.8.6",
26
42
  "@types/yargs": "^17.0.33",
@@ -29,7 +45,12 @@
29
45
  "tsx": "^4.19.2"
30
46
  },
31
47
  "scripts": {
32
- "build": "tsup",
33
- "release": "pnpm publish -no-git-checks"
48
+ "build": "tsup && npx tsx ./src/build-script.ts --all",
49
+ "build:cli": "tsup",
50
+ "build:registry": "npx tsx ./src/build-script.ts --all",
51
+ "release": "pnpm publish -no-git-checks",
52
+ "lint": "eslint . --max-warnings 0",
53
+ "check-type": "tsc --noEmit",
54
+ "test": "vitest run"
34
55
  }
35
56
  }
@@ -1,4 +0,0 @@
1
- {
2
- "**/*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"]
3
- }
4
-
package/CHANGELOG.md DELETED
@@ -1,7 +0,0 @@
1
- # @jongh/cli
2
-
3
- ## 1.1.0
4
-
5
- ### Minor Changes
6
-
7
- - cb4aefa: test changeset ci build issue
@@ -1,281 +0,0 @@
1
- import * as React from "react"
2
- import { createContext } from "../../hooks/createContext"
3
- import { useControlledState } from "../../hooks/useControllableState"
4
- import { useKeyboardEvent } from "../../hooks/useKeyboardEvent"
5
- import { Slot } from "@radix-ui/react-slot"
6
- import { composeRefs } from "src/hooks/useComposedRefs"
7
-
8
- const ACCORDION_KEYS = [
9
- "Home",
10
- "End",
11
- "ArrowDown",
12
- "ArrowUp",
13
- "ArrowLeft",
14
- "ArrowRight",
15
- ]
16
- export type TAccordionContext = {
17
- selected?: string[]
18
- onItemOpen: (value: string) => void
19
- onItemClose: (value: string) => void
20
- refs?: HTMLElement[]
21
- }
22
-
23
- const [AccordionProvider, useAccordionContext] =
24
- createContext<TAccordionContext>("accordion")
25
-
26
- export interface AccordionProps {
27
- value?: string[]
28
- defaultValue?: string[]
29
- onValueChange?: (value: string[]) => void
30
- asChild?: boolean
31
- type?: "single" | "multi"
32
- }
33
-
34
- export const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(
35
- (props, ref) => {
36
- const { type = "single", ...accordionProps } = props
37
- if (type === "single") {
38
- return <SingleAccordion {...accordionProps} ref={ref} />
39
- }
40
- if (type === "multi") {
41
- return <MultiAccordion {...accordionProps} />
42
- }
43
- },
44
- )
45
-
46
- Accordion.displayName = "Accordion"
47
-
48
- interface AccordionImplSingleProps {
49
- value?: string[] // 현재 선택되어있는 item들을 담아놓는 용도
50
- defaultValue?: string[]
51
- onValueChange?: (value: string[]) => void
52
- asChild?: boolean
53
- children?: React.ReactNode
54
- }
55
-
56
- const SingleAccordion = React.forwardRef<
57
- HTMLDivElement,
58
- AccordionImplSingleProps
59
- >(
60
- (
61
- { value, defaultValue = [], onValueChange, children, asChild, ...props },
62
- forwardedRef,
63
- ) => {
64
- const [selected = [], setSelected] = useControlledState({
65
- prop: value,
66
- defaultProp: defaultValue,
67
- onChange: onValueChange,
68
- })
69
-
70
- const { refs: accordionRefs, handleKeyDown } = useKeyboardEvent({
71
- keyList: ACCORDION_KEYS,
72
- })
73
-
74
- const Comp = asChild ? Slot : "div"
75
-
76
- return (
77
- <AccordionProvider
78
- selected={selected}
79
- onItemOpen={(value) => setSelected((_) => [value])}
80
- onItemClose={() => setSelected((_) => [])}
81
- refs={accordionRefs.current || []}
82
- >
83
- <Comp
84
- ref={composeRefs((node) => {
85
- accordionRefs.current = Array.from(
86
- node?.children || [],
87
- ) as HTMLElement[]
88
- }, forwardedRef)}
89
- onKeyDown={(e) => {
90
- handleKeyDown(e)
91
- }}
92
- {...props}
93
- >
94
- {children}
95
- </Comp>
96
- </AccordionProvider>
97
- )
98
- },
99
- )
100
-
101
- interface AccordionImplMultiProps {
102
- value?: string[] // 현재 선택되어있는 item들을 담아놓는 용도
103
- defaultValue?: string[]
104
- onValueChange?: (value: string[]) => void
105
- asChild?: boolean
106
- children?: React.ReactNode
107
- }
108
-
109
- const MultiAccordion = React.forwardRef<
110
- HTMLDivElement,
111
- AccordionImplMultiProps
112
- >(
113
- (
114
- { value, defaultValue, onValueChange, children, asChild, ...props },
115
- forwardedRef,
116
- ) => {
117
- const [selected, setSelected] = useControlledState({
118
- prop: value,
119
- defaultProp: defaultValue,
120
- onChange: onValueChange,
121
- })
122
-
123
- const handleItemOpen = React.useCallback(
124
- (item: string) => {
125
- setSelected((prev = []) => [...prev, item])
126
- },
127
- [setSelected],
128
- )
129
-
130
- const handleItemClose = React.useCallback(
131
- (item: string) =>
132
- setSelected((prev = []) => prev.filter((value) => value !== item)),
133
- [setSelected],
134
- )
135
-
136
- const { refs: accordionRefs, handleKeyDown } = useKeyboardEvent({
137
- keyList: ACCORDION_KEYS,
138
- })
139
-
140
- const Comp = asChild ? Slot : "div"
141
-
142
- return (
143
- <AccordionProvider
144
- selected={selected}
145
- onItemOpen={handleItemOpen}
146
- onItemClose={handleItemClose}
147
- >
148
- <Comp
149
- ref={(node) => {
150
- accordionRefs.current = Array.from(
151
- node?.children || [],
152
- ) as HTMLElement[]
153
- if (typeof forwardedRef === "function") {
154
- forwardedRef(node)
155
- } else if (forwardedRef) {
156
- ;(
157
- forwardedRef as React.MutableRefObject<HTMLDivElement | null>
158
- ).current = node
159
- }
160
- }}
161
- onKeyDown={handleKeyDown}
162
- {...props}
163
- >
164
- {children}
165
- </Comp>
166
- </AccordionProvider>
167
- )
168
- },
169
- )
170
- //AccordionItem
171
- interface TAccordionItemContext {
172
- isOpen: boolean
173
- onToggle: () => void
174
- value?: string
175
- }
176
-
177
- const [AccordionItemProvider, useAccordionItemProvider] =
178
- createContext<TAccordionItemContext>("accordionItem")
179
- export interface AccordionItemProps {
180
- value: string //unique value
181
- disabled?: boolean
182
- children: React.ReactNode
183
- asChild?: boolean
184
- }
185
-
186
- export const AccordionItem = React.forwardRef<
187
- HTMLDivElement,
188
- AccordionItemProps
189
- >(({ value, disabled = false, children, asChild, ...props }, forwardedRef) => {
190
- const { selected, onItemOpen, onItemClose } = useAccordionContext("accordion")
191
-
192
- const isOpen = selected?.includes(value) && !disabled
193
-
194
- const onToggle = () => {
195
- if (disabled) {
196
- return
197
- }
198
- isOpen ? onItemClose(value) : onItemOpen(value)
199
- }
200
-
201
- const Comp = asChild ? Slot : "div"
202
-
203
- return (
204
- <AccordionItemProvider isOpen={!!isOpen} onToggle={onToggle} value={value}>
205
- <Comp
206
- ref={forwardedRef}
207
- data-state={isOpen ? "open" : "close"}
208
- tabIndex={0}
209
- onKeyDown={(e) => {
210
- if (e.key === "Enter") {
211
- onToggle()
212
- }
213
- }}
214
- {...props}
215
- >
216
- {children}
217
- </Comp>
218
- </AccordionItemProvider>
219
- )
220
- })
221
-
222
- export interface AccordionTriggerProps extends React.PropsWithChildren {}
223
- export const AccordionTrigger = ({
224
- children,
225
- ...props
226
- }: AccordionTriggerProps) => {
227
- const { onToggle, isOpen, value } = useAccordionItemProvider("accordionItem")
228
- return (
229
- <h3 data-state={isOpen ? "open" : "close"} onClick={onToggle} {...props}>
230
- <button
231
- aria-expanded={isOpen ? "true" : "false"}
232
- aria-controls={`content-${value}`}
233
- id={`trigger-${value}`}
234
- >
235
- {children}
236
- </button>
237
- </h3>
238
- )
239
- }
240
- //AccordionContent
241
- export interface AccordionContentProps extends React.PropsWithChildren {
242
- duration?: number
243
- asChild?: boolean
244
- }
245
-
246
- export const AccordionContent = ({
247
- children,
248
- asChild,
249
- ...props
250
- }: AccordionContentProps) => {
251
- const Comp = asChild ? Slot : "div"
252
- const { isOpen, value } = useAccordionItemProvider("accordionItem")
253
- const contentRef = React.useRef<HTMLDivElement>(null)
254
-
255
- React.useEffect(() => {
256
- if (contentRef.current) {
257
- const element = contentRef.current
258
- if (isOpen) {
259
- element.style.setProperty(
260
- "--accordion-height",
261
- `${element.scrollHeight}px`,
262
- )
263
- } else {
264
- element.style.setProperty("--accordion-height", "0px")
265
- }
266
- }
267
- }, [isOpen])
268
-
269
- return (
270
- <Comp
271
- ref={contentRef}
272
- data-state={isOpen ? "open" : "close"}
273
- id={`content-${value}`}
274
- aria-labelledby={`trigger-${value}`}
275
- role="region"
276
- {...props}
277
- >
278
- {isOpen && children}
279
- </Comp>
280
- )
281
- }
@@ -1,37 +0,0 @@
1
- import { accordion, type AccordionVariantProps } from "@styled-system/recipes"
2
- import { createStyleContext } from "../../utils/createStyleContext"
3
- import type { ComponentProps, HTMLStyledProps } from "@styled-system/types"
4
- import type { Assign } from "../../types"
5
- import {
6
- Accordion as AccordionProvider,
7
- AccordionContent,
8
- AccordionItem,
9
- AccordionTrigger,
10
- type AccordionContentProps,
11
- type AccordionItemProps,
12
- type AccordionProps,
13
- type AccordionTriggerProps,
14
- } from "./Accordion"
15
-
16
- const { withProvider, withContext } = createStyleContext(accordion)
17
-
18
- export type RootProviderProps = ComponentProps<typeof AccordionProvider>
19
- export const Accordion = withProvider<
20
- HTMLDivElement,
21
- Assign<Assign<HTMLStyledProps<"div">, AccordionProps>, AccordionVariantProps>
22
- >(AccordionProvider, "root")
23
-
24
- export const Item = withContext<
25
- HTMLDivElement,
26
- Assign<HTMLStyledProps<"div">, AccordionItemProps>
27
- >(AccordionItem, "item")
28
-
29
- export const Trigger = withContext<
30
- HTMLButtonElement,
31
- Assign<HTMLStyledProps<"button">, AccordionTriggerProps>
32
- >(AccordionTrigger, "trigger")
33
-
34
- export const Content = withContext<
35
- HTMLDivElement,
36
- Assign<HTMLStyledProps<"div">, AccordionContentProps>
37
- >(AccordionContent, "content")
@@ -1,25 +0,0 @@
1
- import { useEffect, useRef } from "react"
2
-
3
- const ACCORDION_HEIGHT = "--accordion-height"
4
-
5
- export const useAccordionHeight = <T extends HTMLElement>(isOpen: boolean) => {
6
- const ref = useRef<T>(null)
7
-
8
- useEffect(() => {
9
- const element = ref.current
10
- if (!element) return
11
-
12
- if (isOpen) {
13
- // 열릴 때 높이를 scrollHeight로 설정
14
- const newHeight = element.scrollHeight
15
- element.style.setProperty(ACCORDION_HEIGHT, `${newHeight}px`)
16
- element.style.height = `${newHeight}px`
17
- } else {
18
- // 닫힐 때 높이를 0으로 설정
19
- element.style.setProperty(ACCORDION_HEIGHT, `0px`)
20
- element.style.height = "0px"
21
- }
22
- }, [isOpen])
23
-
24
- return ref
25
- }
@@ -1,18 +0,0 @@
1
- import { Slot } from "@radix-ui/react-slot"
2
- import { useAvatar, type UseAvatarStatusProps } from "./useAvatar"
3
- import { forwardRef } from "react"
4
-
5
- interface AvatarProps extends UseAvatarStatusProps {
6
- asChild?: boolean
7
- }
8
-
9
- export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>((props, ref) => {
10
- const { asChild, src, onStatusChange } = props
11
- const { getRootProps, getImgProps } = useAvatar({ src, onStatusChange })
12
- const Comp = asChild ? Slot : "span"
13
- return (
14
- <Comp ref={ref} {...getRootProps()}>
15
- <img {...getImgProps()}></img>
16
- </Comp>
17
- )
18
- })
@@ -1,73 +0,0 @@
1
- import {
2
- useLayoutEffect,
3
- useState,
4
- type ComponentProps,
5
- type HTMLAttributes,
6
- } from "react"
7
-
8
- type Status = "loading" | "loaded" | "error"
9
-
10
- export interface UseAvatarStatusProps {
11
- src?: string
12
- onStatusChange?: (status: Status) => void
13
- }
14
-
15
- export const useAvatarStatus = ({
16
- src,
17
- onStatusChange,
18
- }: UseAvatarStatusProps) => {
19
- const [status, setStatus] = useState<Status>("loading")
20
-
21
- useLayoutEffect(() => {
22
- if (!src) {
23
- setStatus("error")
24
- return
25
- }
26
- let isMounted: boolean = true
27
- const image = new window.Image()
28
-
29
- const updateStatus = (status: Status) => () => {
30
- if (!isMounted) return
31
- setStatus(status)
32
- onStatusChange?.(status)
33
- }
34
-
35
- setStatus("loading")
36
-
37
- image.src = src
38
- image.onload = updateStatus("loaded")
39
- image.onerror = updateStatus("error")
40
-
41
- return () => {
42
- isMounted = false
43
- }
44
- }, [src])
45
-
46
- return status
47
- }
48
-
49
- type DataAttr = Record<`data-${string}`, string | undefined>
50
-
51
- const elementProps = (props: HTMLAttributes<HTMLElement> & DataAttr) => props
52
-
53
- const imgProps = (props: ComponentProps<"img"> & DataAttr) => props
54
-
55
- interface UseAvatarProps extends UseAvatarStatusProps {}
56
- export const useAvatar = ({ src, onStatusChange }: UseAvatarProps) => {
57
- const status = useAvatarStatus({ src, onStatusChange })
58
- const isLoaded = status === "loaded"
59
- return {
60
- getRootProps() {
61
- return elementProps({
62
- "data-loading-state": status,
63
- })
64
- },
65
- getImgProps() {
66
- return imgProps({
67
- hidden: !isLoaded,
68
- "data-visible": `${isLoaded}`,
69
- src,
70
- })
71
- },
72
- }
73
- }
@@ -1,32 +0,0 @@
1
- import { forwardRef, ComponentPropsWithoutRef, type ReactNode } from "react"
2
- import { button, type ButtonVariant } from "@styled-system/recipes"
3
- import { Slot } from "@radix-ui/react-slot"
4
- import { cx } from "@styled-system/css"
5
-
6
- export type ButtonProps = ComponentPropsWithoutRef<"button"> & {
7
- children: ReactNode
8
- as?: boolean
9
- disabled?: boolean
10
- } & Partial<ButtonVariant>
11
-
12
- export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
13
- ({ as, disabled, id, onClick, children, ...rest }, ref) => {
14
- const [buttonProps] = button.splitVariantProps(rest)
15
-
16
- const Comp = as ? Slot : "button"
17
-
18
- return (
19
- <Comp
20
- role="button"
21
- ref={ref}
22
- disabled={disabled}
23
- id={id}
24
- onClick={onClick}
25
- className={cx(button(buttonProps))}
26
- {...rest}
27
- >
28
- {children}
29
- </Comp>
30
- )
31
- },
32
- )