@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.
- package/dist/index.cjs +7 -0
- package/dist/index.js +6 -1
- package/package.json +26 -5
- package/.lintstagedrc.json +0 -4
- package/CHANGELOG.md +0 -7
- package/dist/components/Accordion/Accordion.tsx +0 -281
- package/dist/components/Accordion/index.tsx +0 -37
- package/dist/components/Accordion/useAccordionHeight.ts +0 -25
- package/dist/components/Avatar/Avatar.tsx +0 -18
- package/dist/components/Avatar/useAvatar.ts +0 -73
- package/dist/components/Button/index.tsx +0 -32
- package/dist/components/Primitive/index.tsx +0 -58
- package/dist/components/RovingIndex/RovingItem.tsx +0 -47
- package/dist/components/RovingIndex/RovingTabIndexRoot.tsx +0 -92
- package/dist/components/RovingIndex/index.ts +0 -3
- package/dist/components/RovingIndex/useRovingTabIndex.tsx +0 -76
- package/dist/components/Select/index.tsx +0 -231
- package/dist/components/Slider/index.tsx +0 -141
- package/dist/components/Slider/style.ts +0 -29
- package/dist/components/Tabs/Tab.tsx +0 -39
- package/dist/components/Tabs/TabContent.tsx +0 -62
- package/dist/components/Tabs/TabIndicator.tsx +0 -6
- package/dist/components/Tabs/TabList.tsx +0 -117
- package/dist/components/Tabs/index.ts +0 -43
- package/dist/components/Tabs/useRovingTabIndex.tsx +0 -171
- package/dist/components/Tabs/useTabContext.ts +0 -11
- package/dist/components/TagButton/TagButton.tsx +0 -75
- package/dist/components/TagButton/style.ts +0 -35
- package/dist/components/core/Polymorphic/index.ts +0 -26
- package/dist/components/index.ts +0 -5
- package/dist/index.d.ts +0 -1
- package/src/copyComponent.ts +0 -29
- package/src/getConfig.ts +0 -56
- package/src/index.ts +0 -46
- package/tsconfig.json +0 -14
- 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
|
|
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.
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
}
|
package/.lintstagedrc.json
DELETED
package/CHANGELOG.md
DELETED
|
@@ -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
|
-
)
|