@frontfriend/tailwind 4.0.5 → 4.0.6

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 (2) hide show
  1. package/dist/cli.js +5 -5
  2. package/package.json +2 -1
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var O=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var Y=O((dn,H)=>{var he="https://app.frontfriend.dev",ye="https://registry-legacy.frontfriend.dev",ve=".cache/frontfriend",Ce={JS:["tokens.js","variables.js","semanticVariables.js","semanticDarkVariables.js","safelist.js","custom.js"],JSON:["fonts.json","icons.json","components-config.json","version.json","metadata.json"]},we={FF_ID:"FF_ID",FF_API_URL:"FF_API_URL",FF_USE_LOCAL:"FF_USE_LOCAL",FF_AUTH_TOKEN:"FF_AUTH_TOKEN"};H.exports={DEFAULT_API_URL:he,LEGACY_API_URL:ye,CACHE_DIR_NAME:ve,CACHE_TTL_DAYS:7,CACHE_TTL_MS:6048e5,CACHE_FILES:Ce,ENV_VARS:we}});var te=O((un,oe)=>{var F=require("fs"),z=require("path"),Se=require("os"),je=require("https"),xe=require("http"),{URL:Fe}=require("url"),{DEFAULT_API_URL:W}=Y(),K=z.join(Se.homedir(),".frontfriend"),k=z.join(K,"credentials");function ke(){return k}function Z(){try{return F.existsSync(k)?JSON.parse(F.readFileSync(k,"utf8")):null}catch{return null}}function X(e){F.mkdirSync(K,{recursive:!0,mode:448}),F.writeFileSync(k,`${JSON.stringify(e,null,2)}
3
- `,{mode:384});try{F.chmodSync(k,384)}catch{}}function $e(){return F.existsSync(k)?(F.unlinkSync(k),!0):!1}function Q(e,n=60*1e3){return!(e!=null&&e.accessToken)||!e.expiresAt||Date.now()+n>=e.expiresAt}function ee(e,n,o){return new Promise((t,s)=>{let r=new Fe(e),i=r.protocol==="https:"?je:xe,f=JSON.stringify(n||{}),l=i.request({hostname:r.hostname,port:r.port,path:`${r.pathname}${r.search}`,method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(f),...o?{authorization:`Bearer ${o}`}:{}}},u=>{let g="";u.on("data",c=>{g+=c}),u.on("end",()=>{let c=null;try{c=g?JSON.parse(g):null}catch(p){s(p);return}if(u.statusCode>=400){let p=new Error((c==null?void 0:c.error_description)||(c==null?void 0:c.error)||`HTTP ${u.statusCode}`);p.statusCode=u.statusCode,p.body=c,s(p);return}t(c)})});l.on("error",s),l.write(f),l.end()})}async function ne(e,n=W){if(!(e!=null&&e.refreshToken)||!(e!=null&&e.deviceId))return e;let o=await ee(`${n}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:e.refreshToken,device_id:e.deviceId}),t={accessToken:o.access_token,refreshToken:o.refresh_token,deviceId:o.device_id||e.deviceId,expiresAt:Date.now()+(o.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(o.refresh_expires_in||604800)*1e3,ffApiUrl:n};return X(t),t}async function be(e={}){if(!e.skipCredentials){let n=Z();if(n!=null&&n.accessToken){let o=e.baseURL||n.ffApiUrl||W;if(Q(n))try{let t=await ne(n,o);return(t==null?void 0:t.accessToken)||null}catch{return null}return n.accessToken}}return e.envToken?e.envToken:e.legacyToken?(e.silent||console.warn("\u26A0\uFE0F auth-token in frontfriend.config.js is deprecated. Run `frontfriend login` to store credentials outside the repo."),e.legacyToken):null}oe.exports={getCredentialsPath:ke,readCredentials:Z,writeCredentials:X,deleteCredentials:$e,isExpired:Q,postJson:ee,refreshCredentials:ne,resolveAuthToken:be}});var se=O((gn,Te)=>{Te.exports={name:"@frontfriend/tailwind",version:"4.0.5",description:"Design token management for Tailwind CSS",main:"./dist/index.js",types:"./dist/types/index.d.ts",bin:{frontfriend:"dist/cli.js"},exports:{".":{types:"./dist/types/index.d.ts",import:"./dist/index.mjs",require:"./dist/index.js",default:"./dist/index.js"},"./runtime":{types:"./dist/runtime.d.ts",default:"./dist/runtime.js"},"./next":{types:"./dist/next.d.ts",default:"./dist/next.js"},"./vite":{types:"./dist/vite.d.ts",default:"./dist/vite.mjs"},"./lib/react/utils":{types:"./dist/lib/react/utils.d.ts",default:"./dist/lib/react/utils.mjs"},"./lib/vue/utils":{types:"./dist/lib/vue/utils.d.ts",default:"./dist/lib/vue/utils.mjs"},"./ffdc":{types:"./dist/ffdc.d.ts",default:"./dist/ffdc.js"},"./theme":"./src/theme.css","./theme.css":"./src/theme.css","./components-config-schema":{types:"./dist/components-config-schema.d.ts",require:"./dist/components-config-schema.js",import:"./dist/components-config-schema.js",default:"./dist/components-config-schema.js"}},scripts:{test:"jest",build:"node scripts/build.js",prepublishOnly:"npm run build"},keywords:["tailwindcss","design-tokens","frontfriend"],author:"Donux",license:"SEE LICENSE IN LICENSE",files:["dist/","src/theme.css","scripts/","README.md","LICENSE"],dependencies:{commander:"^11.0.0",dotenv:"^16.0.0",color:"^4.2.3",clsx:"^2.0.0","tailwind-merge":"^2.0.0","tw-animate-css":"^1.3.4"},peerDependencies:{tailwindcss:"^3.0.0 || ^4.0.0",react:"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",vue:">=3.0.0"},devDependencies:{jest:"^29.0.0",esbuild:"^0.19.0",glob:"^10.0.0"}}});var L=O((pn,A)=>{var j=require("fs"),E=require("path");function re(e={}){let n=e.projectRoot||process.cwd(),o=E.join(n,"node_modules",".cache","frontfriend","icons.json"),t=e.outputPath||E.join(n,"types","frontfriend.d.ts");j.existsSync(o)||(console.error('[FrontFriend] Error: icons.json not found. Please run "npx frontfriend init" first.'),process.exit(1));try{let l=function(v){for(let h of Object.values(v))typeof h=="string"?f.add(h):typeof h=="object"&&h!==null&&l(h)},u=function(v,h=" "){let C=[];for(let[P,S]of Object.entries(v))typeof S=="string"?C.push(`${h}${P}: '${S}';`):typeof S=="object"&&S!==null&&(C.push(`${h}${P}: {`),C.push(u(S,h+" ")),C.push(`${h}};`));return C.join(`
3
+ `,{mode:384});try{F.chmodSync(k,384)}catch{}}function be(){return F.existsSync(k)?(F.unlinkSync(k),!0):!1}function Q(e,n=60*1e3){return!(e!=null&&e.accessToken)||!e.expiresAt||Date.now()+n>=e.expiresAt}function ee(e,n,o){return new Promise((t,s)=>{let r=new Fe(e),i=r.protocol==="https:"?je:xe,f=JSON.stringify(n||{}),l=i.request({hostname:r.hostname,port:r.port,path:`${r.pathname}${r.search}`,method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(f),...o?{authorization:`Bearer ${o}`}:{}}},u=>{let g="";u.on("data",c=>{g+=c}),u.on("end",()=>{let c=null;try{c=g?JSON.parse(g):null}catch(p){s(p);return}if(u.statusCode>=400){let p=new Error((c==null?void 0:c.error_description)||(c==null?void 0:c.error)||`HTTP ${u.statusCode}`);p.statusCode=u.statusCode,p.body=c,s(p);return}t(c)})});l.on("error",s),l.write(f),l.end()})}async function ne(e,n=W){if(!(e!=null&&e.refreshToken)||!(e!=null&&e.deviceId))return e;let o=await ee(`${n}/api/plugin/token`,{grant_type:"refresh_token",refresh_token:e.refreshToken,device_id:e.deviceId}),t={accessToken:o.access_token,refreshToken:o.refresh_token,deviceId:o.device_id||e.deviceId,expiresAt:Date.now()+(o.expires_in||900)*1e3,refreshExpiresAt:Date.now()+(o.refresh_expires_in||604800)*1e3,ffApiUrl:n};return X(t),t}async function $e(e={}){if(!e.skipCredentials){let n=Z();if(n!=null&&n.accessToken){let o=e.baseURL||n.ffApiUrl||W;if(Q(n))try{let t=await ne(n,o);return(t==null?void 0:t.accessToken)||null}catch{return null}return n.accessToken}}return e.envToken?e.envToken:e.legacyToken?(e.silent||console.warn("\u26A0\uFE0F auth-token in frontfriend.config.js is deprecated. Run `frontfriend login` to store credentials outside the repo."),e.legacyToken):null}oe.exports={getCredentialsPath:ke,readCredentials:Z,writeCredentials:X,deleteCredentials:be,isExpired:Q,postJson:ee,refreshCredentials:ne,resolveAuthToken:$e}});var se=O((gn,Te)=>{Te.exports={name:"@frontfriend/tailwind",version:"4.0.6",description:"Design token management for Tailwind CSS",main:"./dist/index.js",types:"./dist/types/index.d.ts",bin:{frontfriend:"dist/cli.js"},exports:{".":{types:"./dist/types/index.d.ts",browser:"./dist/browser.mjs",import:"./dist/index.mjs",require:"./dist/index.js",default:"./dist/index.js"},"./runtime":{types:"./dist/runtime.d.ts",default:"./dist/runtime.js"},"./next":{types:"./dist/next.d.ts",default:"./dist/next.js"},"./vite":{types:"./dist/vite.d.ts",default:"./dist/vite.mjs"},"./lib/react/utils":{types:"./dist/lib/react/utils.d.ts",default:"./dist/lib/react/utils.mjs"},"./lib/vue/utils":{types:"./dist/lib/vue/utils.d.ts",default:"./dist/lib/vue/utils.mjs"},"./ffdc":{types:"./dist/ffdc.d.ts",default:"./dist/ffdc.js"},"./theme":"./src/theme.css","./theme.css":"./src/theme.css","./components-config-schema":{types:"./dist/components-config-schema.d.ts",require:"./dist/components-config-schema.js",import:"./dist/components-config-schema.js",default:"./dist/components-config-schema.js"}},scripts:{test:"jest",build:"node scripts/build.js",prepublishOnly:"npm run build"},keywords:["tailwindcss","design-tokens","frontfriend"],author:"Donux",license:"SEE LICENSE IN LICENSE",files:["dist/","src/theme.css","scripts/","README.md","LICENSE"],dependencies:{commander:"^11.0.0",dotenv:"^16.0.0",color:"^4.2.3",clsx:"^2.0.0","tailwind-merge":"^2.0.0","tw-animate-css":"^1.3.4"},peerDependencies:{tailwindcss:"^3.0.0 || ^4.0.0",react:"^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",vue:">=3.0.0"},devDependencies:{jest:"^29.0.0",esbuild:"^0.19.0",glob:"^10.0.0"}}});var L=O((pn,A)=>{var j=require("fs"),E=require("path");function re(e={}){let n=e.projectRoot||process.cwd(),o=E.join(n,"node_modules",".cache","frontfriend","icons.json"),t=e.outputPath||E.join(n,"types","frontfriend.d.ts");j.existsSync(o)||(console.error('[FrontFriend] Error: icons.json not found. Please run "npx frontfriend init" first.'),process.exit(1));try{let l=function(v){for(let h of Object.values(v))typeof h=="string"?f.add(h):typeof h=="object"&&h!==null&&l(h)},u=function(v,h=" "){let C=[];for(let[P,S]of Object.entries(v))typeof S=="string"?C.push(`${h}${P}: '${S}';`):typeof S=="object"&&S!==null&&(C.push(`${h}${P}: {`),C.push(u(S,h+" ")),C.push(`${h}};`));return C.join(`
4
4
  `)};var s=l,r=u;let i=JSON.parse(j.readFileSync(o,"utf-8")),f=new Set;l(i);let g=Array.from(f).map(v=>`'${v}'`).join(" | "),c=`// Generated by @frontfriend/tailwind
5
5
  // DO NOT EDIT THIS FILE MANUALLY
6
6
 
@@ -36,8 +36,8 @@ declare module '@/src/components/ui/icon' {
36
36
  declare module '@/src/components/ui/icon/Icon.vue' {
37
37
  export type IconName = ${g||"string"};
38
38
  }
39
- `,p=E.dirname(t);j.existsSync(p)||j.mkdirSync(p,{recursive:!0}),j.writeFileSync(t,c),console.log("[FrontFriend] \u2713 Generated types at",E.relative(n,t));let T=E.join(n,"tsconfig.json");if(j.existsSync(T)){let v=JSON.parse(j.readFileSync(T,"utf-8"));v.include||(v.include=[]);let h="types/**/*.d.ts";v.include.includes(h)||(v.include.push(h),j.writeFileSync(T,JSON.stringify(v,null,2)),console.log("[FrontFriend] \u2713 Updated tsconfig.json to include generated types"))}}catch(i){console.error("[FrontFriend] Error generating icon types:",i.message),process.exit(1)}}require.main===A&&re();A.exports={generateIconTypes:re}});var{loadEnvLocal:_e}=require("./lib/core/env-utils");_e();var{Command:Ee}=require("commander"),I=require("./lib/core/config-loader"),D=require("./lib/core/cache-manager"),{APIClient:ae}=require("./lib/core/api-client"),{getCredentialsPath:Ie,writeCredentials:Pe,readCredentials:Oe,deleteCredentials:De,postJson:U}=te(),{ComponentDownloader:Ae}=require("./lib/core/component-downloader"),Le=require("./lib/core/token-processor"),{ConfigError:x,APIError:Ue,CacheError:M}=require("./lib/core/errors"),a=require("path"),d=require("fs"),{spawn:Ne}=require("child_process"),w=new Ee,{version:le}=se(),Re="https://registry.frontfriend.dev/r/v4",ie='@import "@frontfriend/tailwind/theme.css";';function Ve(e){return(e||process.env.FF_REGISTRY_URL||Re).replace(/\/+$/,"")}function b(e){try{return JSON.parse(d.readFileSync(e,"utf8"))}catch{return null}}function q(e,n){d.mkdirSync(a.dirname(e),{recursive:!0}),d.writeFileSync(e,`${JSON.stringify(n,null,2)}
40
- `)}var Me=a.join("node_modules",".cache","frontfriend","migrated-components.json");function qe(e){let n=b(a.join(e,"package.json"))||{},o={...n.dependencies||{},...n.devDependencies||{}};return o.vue||o["@vitejs/plugin-vue"]?"vue":"react"}function Ge(e){let n=b(a.join(e,"package.json"))||{},o={...n.dependencies||{},...n.devDependencies||{}};return o.next||d.existsSync(a.join(e,"next.config.js"))||d.existsSync(a.join(e,"next.config.mjs"))?"next":o.vite||d.existsSync(a.join(e,"vite.config.ts"))||d.existsSync(a.join(e,"vite.config.js"))?"vite":null}function Je(e,n,o){let t=a.join(e,"components.json");if(!d.existsSync(t))return!1;let s=b(t)||{};s.registries=s.registries||{};let r=`${Ve(o)}/${n}/{name}.json`;return s.registries["@frontfriend"]===r?!1:(s.registries["@frontfriend"]=r,q(t,s),!0)}function Be(e){let n=a.join(e,"package.json"),o=b(n);return o?(o.dependencies=o.dependencies||{},o.dependencies["@frontfriend/tailwind"]?!1:(o.dependencies["@frontfriend/tailwind"]="^4.0.0",q(n,o),!0)):!1}function He(e){let n=a.join(e,"next.config.js");return d.existsSync(n)&&d.readFileSync(n,"utf8").includes("@frontfriend/tailwind/next")?!1:(d.writeFileSync(n,`const frontfriend = require('@frontfriend/tailwind/next');
39
+ `,p=E.dirname(t);j.existsSync(p)||j.mkdirSync(p,{recursive:!0}),j.writeFileSync(t,c),console.log("[FrontFriend] \u2713 Generated types at",E.relative(n,t));let T=E.join(n,"tsconfig.json");if(j.existsSync(T)){let v=JSON.parse(j.readFileSync(T,"utf-8"));v.include||(v.include=[]);let h="types/**/*.d.ts";v.include.includes(h)||(v.include.push(h),j.writeFileSync(T,JSON.stringify(v,null,2)),console.log("[FrontFriend] \u2713 Updated tsconfig.json to include generated types"))}}catch(i){console.error("[FrontFriend] Error generating icon types:",i.message),process.exit(1)}}require.main===A&&re();A.exports={generateIconTypes:re}});var{loadEnvLocal:_e}=require("./lib/core/env-utils");_e();var{Command:Ee}=require("commander"),I=require("./lib/core/config-loader"),D=require("./lib/core/cache-manager"),{APIClient:ae}=require("./lib/core/api-client"),{getCredentialsPath:Ie,writeCredentials:Pe,readCredentials:Oe,deleteCredentials:De,postJson:U}=te(),{ComponentDownloader:Ae}=require("./lib/core/component-downloader"),Le=require("./lib/core/token-processor"),{ConfigError:x,APIError:Ue,CacheError:M}=require("./lib/core/errors"),a=require("path"),d=require("fs"),{spawn:Ne}=require("child_process"),w=new Ee,{version:le}=se(),Re="https://registry.frontfriend.dev/r/v4",ie='@import "@frontfriend/tailwind/theme.css";';function Ve(e){return(e||process.env.FF_REGISTRY_URL||Re).replace(/\/+$/,"")}function $(e){try{return JSON.parse(d.readFileSync(e,"utf8"))}catch{return null}}function q(e,n){d.mkdirSync(a.dirname(e),{recursive:!0}),d.writeFileSync(e,`${JSON.stringify(n,null,2)}
40
+ `)}var Me=a.join("node_modules",".cache","frontfriend","migrated-components.json");function qe(e){let n=$(a.join(e,"package.json"))||{},o={...n.dependencies||{},...n.devDependencies||{}};return o.vue||o["@vitejs/plugin-vue"]?"vue":"react"}function Ge(e){let n=$(a.join(e,"package.json"))||{},o={...n.dependencies||{},...n.devDependencies||{}};return o.next||d.existsSync(a.join(e,"next.config.js"))||d.existsSync(a.join(e,"next.config.mjs"))?"next":o.vite||d.existsSync(a.join(e,"vite.config.ts"))||d.existsSync(a.join(e,"vite.config.js"))?"vite":null}function Je(e,n,o){let t=a.join(e,"components.json");if(!d.existsSync(t))return!1;let s=$(t)||{};s.registries=s.registries||{};let r=`${Ve(o)}/${n}/{name}.json`;return s.registries["@frontfriend"]===r?!1:(s.registries["@frontfriend"]=r,q(t,s),!0)}function Be(e){let n=a.join(e,"package.json"),o=$(n);return o?(o.dependencies=o.dependencies||{},o.dependencies["@frontfriend/tailwind"]?!1:(o.dependencies["@frontfriend/tailwind"]="^4.0.0",q(n,o),!0)):!1}function He(e){let n=a.join(e,"next.config.js");return d.existsSync(n)&&d.readFileSync(n,"utf8").includes("@frontfriend/tailwind/next")?!1:(d.writeFileSync(n,`const frontfriend = require('@frontfriend/tailwind/next');
41
41
 
42
42
  module.exports = frontfriend({});
43
43
  `),!0)}function Ye(e){let n=d.existsSync(a.join(e,"vite.config.ts"))?a.join(e,"vite.config.ts"):a.join(e,"vite.config.js");return d.existsSync(n)&&d.readFileSync(n,"utf8").includes("@frontfriend/tailwind/vite")?!1:(d.writeFileSync(n,`import { defineConfig } from 'vite';
@@ -48,7 +48,7 @@ export default defineConfig({
48
48
  });
49
49
  `),!0)}function ze(e){let t=["app/globals.css","src/app/globals.css","styles/globals.css","src/styles/globals.css","src/index.css"].find(r=>d.existsSync(a.join(e,r)))||"app/globals.css",s=a.join(e,t);return d.mkdirSync(a.dirname(s),{recursive:!0}),d.existsSync(s)||d.writeFileSync(s,""),{fullPath:s,relativePath:t}}function We(e){let{fullPath:n,relativePath:o}=ze(e),t=d.readFileSync(n,"utf8");return t.includes(ie)?{changed:!1,relativePath:o}:(d.writeFileSync(n,`${ie}
50
50
  ${t}`),{changed:!0,relativePath:o})}function Ke(e,n={}){let o=a.join(e,"components.json");if(!d.existsSync(o))return{isShadcnProject:!1,changes:[]};let t=qe(e),s=Ge(e),r=[];Je(e,t,n.registryUrl)&&r.push(`registered @frontfriend registry for ${t}`),Be(e)&&r.push("added @frontfriend/tailwind dependency"),s==="next"&&He(e)&&r.push("wired Next.js plugin"),s==="vite"&&Ye(e)&&r.push("wired Vite plugin");let i=We(e);return i.changed&&r.push(`imported bundled theme in ${i.relativePath}`),{isShadcnProject:!0,changes:r,framework:t,buildTool:s}}function Ze(e){return new Promise(n=>setTimeout(n,e))}function Xe(e){let n=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",o=process.platform==="win32"?["/c","start","",e]:[e];try{return Ne(n,o,{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}function Qe(e){e.isShadcnProject&&(console.log("\u{1F9E9} shadcn project wiring"),e.changes.length===0?console.log(" \u2713 Already configured"):e.changes.forEach(n=>console.log(` \u2713 ${n}`)),console.log(` Next: npx shadcn add @frontfriend/button
51
- `))}function en(e,n){let o=e.indexOf(`${n}:`);if(o===-1)return null;let t=e.indexOf("{",o);if(t===-1)return null;let s=0;for(let r=t;r<e.length;r+=1){let i=e[r];if(i==="{"&&(s+=1),i==="}"&&(s-=1),s===0)return e.slice(t+1,r)}return null}function nn(e){let n={},o=/([A-Za-z0-9_-]+):\s*(['"`])([\s\S]*?)\2/g,t;for(;t=o.exec(e||"");)n[t[1]]=t[3].replace(/\s+/g," ").trim();return n}function on(e,n){let o=n;for(;/\s|,/.test(e[o]||"");)o+=1;let t=e[o];if(t==='"'||t==="'"||t==="`"){let r=e.indexOf(t,o+1);return r===-1?null:{name:e.slice(o+1,r),end:r+1}}let s=e.slice(o).match(/^([A-Za-z0-9_-]+)/);return s?{name:s[1],end:o+s[1].length}:null}function tn(e){let n={},o=0;for(;o<(e||"").length;){let t=on(e,o);if(!t){o+=1;continue}for(o=t.end;/\s/.test(e[o]||"");)o+=1;if(e[o]!==":")continue;for(o+=1;/\s/.test(e[o]||"");)o+=1;if(e[o]!=="{")continue;let s=0,r=o;for(;o<e.length;o+=1)if(e[o]==="{"&&(s+=1),e[o]==="}"&&(s-=1),s===0){n[t.name]=nn(e.slice(r+1,o)),o+=1;break}}return n}function N(e,n){if(!e.includes("cva(")||!e.includes("variants:"))return{skipped:!0,reason:`${n} source is not cva-structured`};let o=e.match(/cva\(\s*(['"`])([\s\S]*?)\1\s*,/),t=en(e,"variants"),s=tn(t);if(Object.values(s).every(f=>Object.keys(f).length===0))return{skipped:!0,reason:"no cva variant class maps found"};let r={default:"main",outline:"tertiary",destructive:"destructive",secondary:"secondary",ghost:"ghost",link:"link"},i={root:o?o[2].replace(/\s+/g," ").trim():"",variants:{}};for(let[f,l]of Object.entries(s)){i.variants[f]={};for(let[u,g]of Object.entries(l)){let c=n==="button"&&f==="variant"&&r[u]||u;i.variants[f][c]=g}}return{skipped:!1,config:{[n]:i}}}function R(...e){return e.reduce((n,o)=>({...n,...o||{}}),{})}function sn(e){let n=require("./lib/core/token-processor"),{mergeComponentsConfig:o}=require("./lib/core/default-config"),t=new n,s=o(e),r=t.extractClassesFromComponentsConfig(s);return{componentsConfig:s,icons:{},safelist:r,classesContent:t.generateClassesContent(r),themeCSS:t.generateThemeCSS({}),metadata:{version:"local-components"}}}function fe(e,n){let o=new D(e),t=o.exists()?o.load()||{}:{},s=R(t.componentsConfig,n),r=sn(s);return o.save({...t,...r,icons:t.icons||{}}),r.componentsConfig}function V(e){return a.basename(e).replace(/\.(tsx|ts|jsx|js|vue)$/,"").replace(/[-_]([a-z])/g,(n,o)=>o.toUpperCase())}var rn=["tsx","ts","jsx","js","vue"],de=/\.(tsx|ts|jsx|js|vue)$/;function cn(e){let n={};for(let o of["tsconfig.json","tsconfig.app.json","jsconfig.json"]){let t=b(a.join(e,o)),s=t&&t.compilerOptions&&t.compilerOptions.paths;s&&Object.assign(n,s)}return n}function an(e,n){if(!n)return null;let o=cn(e);for(let[t,s]of Object.entries(o))if(!(!Array.isArray(s)||s.length===0)){if(t.endsWith("/*")){let r=t.slice(0,-1);if(n.startsWith(r)){let i=n.slice(r.length),f=s[0].replace(/\*+$/,"");return a.resolve(e,f,i)}}else if(t===n)return a.resolve(e,s[0])}return n.startsWith("@/")?a.resolve(e,"src",n.slice(2)):a.resolve(e,n)}function ln(e){let n=b(a.join(e,"components.json")),o=n&&n.aliases&&n.aliases.ui,t=[o?an(e,o):null,a.join(e,"src","components","ui"),a.join(e,"components","ui")].filter(Boolean);return[...new Set(t)].filter(s=>d.existsSync(s))}function ce(e,n){for(let t of rn){let s=a.join(e,`${n}.${t}`);if(d.existsSync(s))return s}let o=a.join(e,n);if(d.existsSync(o)&&d.statSync(o).isDirectory()){let t=d.readdirSync(o).filter(i=>de.test(i)),s=t.filter(i=>!/^index\./i.test(i)),r=s.find(i=>i.toLowerCase().startsWith(`${n.toLowerCase()}.`))||s[0]||t.find(i=>/^index\./i.test(i));if(r)return a.join(o,r)}return null}function ue(e,n){let o=ln(e);if(n&&n!=="all"){for(let r of o){let i=ce(r,n);if(i)return[{component:n,inputPath:i}]}return[]}let t=new Set,s=[];for(let r of o)for(let i of d.readdirSync(r,{withFileTypes:!0})){let f,l=null;if(i.isFile()&&de.test(i.name)&&!/^index\./i.test(i.name)?(f=V(i.name),l=a.join(r,i.name)):i.isDirectory()&&(f=V(i.name),l=ce(r,i.name)),!l||!f)continue;let u=f.toLowerCase();t.has(u)||(t.add(u),s.push({component:f,inputPath:l}))}return s}function ge(e){let n={},o=[],t=ue(e,"all");for(let{component:s,inputPath:r}of t){let i=N(d.readFileSync(r,"utf8"),s);if(i.skipped){o.push({component:s,reason:i.reason});continue}Object.assign(n,i.config)}return{config:n,skipped:o}}w.name("frontfriend").description("FrontFriend Tailwind CLI - Manage design tokens and cache").version(le);w.command("login").description("Authenticate FrontFriend CLI with an 8-digit device code").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||"https://app.frontfriend.dev").option("--no-open","Do not open the browser automatically").action(async e=>{try{let n=e.apiUrl.replace(/\/$/,""),o=await U(`${n}/api/auth/device/start`,{}),t=o.interval||5,s=Date.now()+(o.expires_in||600)*1e3;for(console.log("\u{1F510} FrontFriend Login"),console.log(`====================
51
+ `))}function en(e,n){let o=e.indexOf(`${n}:`);if(o===-1)return null;let t=e.indexOf("{",o);if(t===-1)return null;let s=0;for(let r=t;r<e.length;r+=1){let i=e[r];if(i==="{"&&(s+=1),i==="}"&&(s-=1),s===0)return e.slice(t+1,r)}return null}function nn(e){let n={},o=/([A-Za-z0-9_-]+):\s*(['"`])([\s\S]*?)\2/g,t;for(;t=o.exec(e||"");)n[t[1]]=t[3].replace(/\s+/g," ").trim();return n}function on(e,n){let o=n;for(;/\s|,/.test(e[o]||"");)o+=1;let t=e[o];if(t==='"'||t==="'"||t==="`"){let r=e.indexOf(t,o+1);return r===-1?null:{name:e.slice(o+1,r),end:r+1}}let s=e.slice(o).match(/^([A-Za-z0-9_-]+)/);return s?{name:s[1],end:o+s[1].length}:null}function tn(e){let n={},o=0;for(;o<(e||"").length;){let t=on(e,o);if(!t){o+=1;continue}for(o=t.end;/\s/.test(e[o]||"");)o+=1;if(e[o]!==":")continue;for(o+=1;/\s/.test(e[o]||"");)o+=1;if(e[o]!=="{")continue;let s=0,r=o;for(;o<e.length;o+=1)if(e[o]==="{"&&(s+=1),e[o]==="}"&&(s-=1),s===0){n[t.name]=nn(e.slice(r+1,o)),o+=1;break}}return n}function N(e,n){if(!e.includes("cva(")||!e.includes("variants:"))return{skipped:!0,reason:`${n} source is not cva-structured`};let o=e.match(/cva\(\s*(['"`])([\s\S]*?)\1\s*,/),t=en(e,"variants"),s=tn(t);if(Object.values(s).every(f=>Object.keys(f).length===0))return{skipped:!0,reason:"no cva variant class maps found"};let r={default:"main",outline:"tertiary",destructive:"destructive",secondary:"secondary",ghost:"ghost",link:"link"},i={root:o?o[2].replace(/\s+/g," ").trim():"",variants:{}};for(let[f,l]of Object.entries(s)){i.variants[f]={};for(let[u,g]of Object.entries(l)){let c=n==="button"&&f==="variant"&&r[u]||u;i.variants[f][c]=g}}return{skipped:!1,config:{[n]:i}}}function R(...e){return e.reduce((n,o)=>({...n,...o||{}}),{})}function sn(e){let n=require("./lib/core/token-processor"),{mergeComponentsConfig:o}=require("./lib/core/default-config"),t=new n,s=o(e),r=t.extractClassesFromComponentsConfig(s);return{componentsConfig:s,icons:{},safelist:r,classesContent:t.generateClassesContent(r),themeCSS:t.generateThemeCSS({}),metadata:{version:"local-components"}}}function fe(e,n){let o=new D(e),t=o.exists()?o.load()||{}:{},s=R(t.componentsConfig,n),r=sn(s);return o.save({...t,...r,icons:t.icons||{}}),r.componentsConfig}function V(e){return a.basename(e).replace(/\.(tsx|ts|jsx|js|vue)$/,"").replace(/[-_]([a-z])/g,(n,o)=>o.toUpperCase())}var rn=["tsx","ts","jsx","js","vue"],de=/\.(tsx|ts|jsx|js|vue)$/;function cn(e){let n={};for(let o of["tsconfig.json","tsconfig.app.json","jsconfig.json"]){let t=$(a.join(e,o)),s=t&&t.compilerOptions&&t.compilerOptions.paths;s&&Object.assign(n,s)}return n}function an(e,n){if(!n)return null;let o=cn(e);for(let[t,s]of Object.entries(o))if(!(!Array.isArray(s)||s.length===0)){if(t.endsWith("/*")){let r=t.slice(0,-1);if(n.startsWith(r)){let i=n.slice(r.length),f=s[0].replace(/\*+$/,"");return a.resolve(e,f,i)}}else if(t===n)return a.resolve(e,s[0])}return n.startsWith("@/")?a.resolve(e,"src",n.slice(2)):a.resolve(e,n)}function ln(e){let n=$(a.join(e,"components.json")),o=n&&n.aliases&&n.aliases.ui,t=[o?an(e,o):null,a.join(e,"src","components","ui"),a.join(e,"components","ui")].filter(Boolean);return[...new Set(t)].filter(s=>d.existsSync(s))}function ce(e,n){for(let t of rn){let s=a.join(e,`${n}.${t}`);if(d.existsSync(s))return s}let o=a.join(e,n);if(d.existsSync(o)&&d.statSync(o).isDirectory()){let t=d.readdirSync(o).filter(i=>de.test(i)),s=t.filter(i=>!/^index\./i.test(i)),r=s.find(i=>i.toLowerCase().startsWith(`${n.toLowerCase()}.`))||s[0]||t.find(i=>/^index\./i.test(i));if(r)return a.join(o,r)}return null}function ue(e,n){let o=ln(e);if(n&&n!=="all"){for(let r of o){let i=ce(r,n);if(i)return[{component:n,inputPath:i}]}return[]}let t=new Set,s=[];for(let r of o)for(let i of d.readdirSync(r,{withFileTypes:!0})){let f,l=null;if(i.isFile()&&de.test(i.name)&&!/^index\./i.test(i.name)?(f=V(i.name),l=a.join(r,i.name)):i.isDirectory()&&(f=V(i.name),l=ce(r,i.name)),!l||!f)continue;let u=f.toLowerCase();t.has(u)||(t.add(u),s.push({component:f,inputPath:l}))}return s}function ge(e){let n={},o=[],t=ue(e,"all");for(let{component:s,inputPath:r}of t){let i=N(d.readFileSync(r,"utf8"),s);if(i.skipped){o.push({component:s,reason:i.reason});continue}Object.assign(n,i.config)}return{config:n,skipped:o}}w.name("frontfriend").description("FrontFriend Tailwind CLI - Manage design tokens and cache").version(le);w.command("login").description("Authenticate FrontFriend CLI with an 8-digit device code").option("--api-url <url>","FrontFriend API URL",process.env.FF_API_URL||"https://app.frontfriend.dev").option("--no-open","Do not open the browser automatically").action(async e=>{try{let n=e.apiUrl.replace(/\/$/,""),o=await U(`${n}/api/auth/device/start`,{}),t=o.interval||5,s=Date.now()+(o.expires_in||600)*1e3;for(console.log("\u{1F510} FrontFriend Login"),console.log(`====================
52
52
  `),console.log(`Go to ${o.verification_uri} and enter the code:`),console.log(`
53
53
  ${o.user_code}
54
54
  `),e.open!==!1&&Xe(o.verification_uri)&&console.log("Opened the browser for you."),console.log(`Waiting for approval...
@@ -65,7 +65,7 @@ ${t}`),{changed:!0,relativePath:o})}function Ke(e,n={}){let o=a.join(e,"componen
65
65
  `);let[p,T,v,h,C,P]=await Promise.all([u.fetchTokens(),u.fetchComponentsConfig(),u.fetchFonts(),u.fetchIcons(),u.fetchVersion(),u.fetchCustomCss()]),S=R(T,r.config);if(console.log(" \u2713 Tokens fetched"),p.global||p.colors||p.semantic||p.semanticDark){let m=[p.global?"global":null,p.colors?"colors":null,p.semantic?"semantic":null,p.semanticDark?"semanticDark":null].filter(Boolean).join(", ");console.log(` (Found: ${m})`)}console.log(" \u2713 Components config fetched"),Object.keys(r.config).length>0&&console.log(` \u2713 Preserved host component classes for ${Object.keys(r.config).join(", ")}`),console.log(" \u2713 Fonts fetched"),console.log(" \u2713 Icons fetched"),console.log(" \u2713 Version fetched"),console.log(` \u2713 Custom CSS fetched
66
66
  `),console.log("\u2699\uFE0F Processing tokens..."),console.log(" Processing raw token data...");let y=await g.process({colors:p.colors||p.global,semantic:p.semantic,semanticDark:p.semanticDark,fonts:v,globalTokens:p.global,animations:p.animations,version:C==null?void 0:C.version,ffId:t.ffId,customCss:P});console.log(" \u2713 Colors processed"),console.log(" \u2713 Semantic tokens processed"),y.fontFaces.length>0&&console.log(` \u2713 ${y.fontFaces.length} font faces processed`),Object.keys(y.animations).length>0&&console.log(` \u2713 ${Object.keys(y.animations).length} animations processed`),console.log(`
67
67
  `);let pe=g.extractClassesFromComponentsConfig(S),me=[...y.safelist||[],...pe||[]],G=[...new Set(me)].sort(),J,B;g.useTailwindV4&&(console.log("\u{1F3A8} Generating Tailwind v4 CSS artifacts..."),J=g.generateThemeCSS(y),B=g.generateClassesContent(G),console.log(" \u2713 theme.css generated"),console.log(` \u2713 classes.css generated for @source scanning
68
- `));let $={tokens:y.utilities,variables:y.variables,semanticVariables:y.semanticVariables,semanticDarkVariables:y.semanticDarkVariables,fonts:y.fontFaces,icons:h,componentsConfig:S,keyframes:y.keyframes,animations:y.animations,safelist:G,version:C,metadata:y.metadata,custom:y.custom,themeCSS:J,classesContent:B};if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&(console.log(" Cache data summary:"),console.log(` - Tokens: ${Object.keys($.tokens||{}).length} utilities`),console.log(` - Variables: ${Object.keys($.variables||{}).length} CSS variables`),console.log(` - Semantic variables: ${Object.keys($.semanticVariables||{}).length} semantic variables`),console.log(` - Font faces: ${($.fonts||[]).length} fonts`),console.log(` - Safelist: ${($.safelist||[]).length} safelist classes`)),l.save($),console.log(` \u2713 Cache saved successfully
68
+ `));let b={tokens:y.utilities,variables:y.variables,semanticVariables:y.semanticVariables,semanticDarkVariables:y.semanticDarkVariables,fonts:y.fontFaces,icons:h,componentsConfig:S,keyframes:y.keyframes,animations:y.animations,safelist:G,version:C,metadata:y.metadata,custom:y.custom,themeCSS:J,classesContent:B};if(console.log("\u{1F4BE} Saving cache..."),(process.env.FF_VERBOSE==="true"||e.verbose)&&(console.log(" Cache data summary:"),console.log(` - Tokens: ${Object.keys(b.tokens||{}).length} utilities`),console.log(` - Variables: ${Object.keys(b.variables||{}).length} CSS variables`),console.log(` - Semantic variables: ${Object.keys(b.semanticVariables||{}).length} semantic variables`),console.log(` - Font faces: ${(b.fonts||[]).length} fonts`),console.log(` - Safelist: ${(b.safelist||[]).length} safelist classes`)),l.save(b),console.log(` \u2713 Cache saved successfully
69
69
  `),console.log("\u2705 Setup complete!"),console.log(" Your FrontFriend configuration has been cached."),console.log(" The Tailwind plugin will now use this cached data."),t.types){console.log(`
70
70
  \u{1F524} Generating TypeScript types...`);try{let{generateIconTypes:m}=L(),_=t.aliases&&t.aliases.types?a.join(t.appRoot,t.aliases.types,"frontfriend.d.ts"):void 0;m({projectRoot:t.appRoot,outputPath:_})}catch(m){console.log(" \u26A0\uFE0F Type generation failed:",m.message),console.log(' Enable type generation in frontfriend.config.js with "types": true')}}process.exit(0)}catch(o){o instanceof x?console.error("\u274C Configuration Error:",o.message):o instanceof Ue?(console.error("\u274C API Error:",o.message),console.error(` Status: ${o.statusCode}`),console.error(` URL: ${o.url}`)):o instanceof M?(console.error("\u274C Cache Error:",o.message),console.error(` Operation: ${o.operation}`)):console.error("\u274C Setup failed:",o.message),process.exit(1)}});w.command("clean").description("Remove cached configuration").action(async()=>{try{console.log(`\u{1F9F9} Cleaning FrontFriend cache...
71
71
  `);let n=new I().load(),o=new D(n.appRoot);o.exists()?(o.clear(),console.log("\u2705 Cache cleared successfully")):console.log("\u2139\uFE0F No cache found"),process.exit(0)}catch(e){e instanceof M?(console.error("\u274C Cache Error:",e.message),console.error(` Operation: ${e.operation}`)):console.error("\u274C Clean failed:",e.message),process.exit(1)}});w.command("status").description("Show cache status and configuration").action(async()=>{try{console.log("\u{1F4CA} FrontFriend Status"),console.log(`===================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontfriend/tailwind",
3
- "version": "4.0.5",
3
+ "version": "4.0.6",
4
4
  "description": "Design token management for Tailwind CSS",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -10,6 +10,7 @@
10
10
  "exports": {
11
11
  ".": {
12
12
  "types": "./dist/types/index.d.ts",
13
+ "browser": "./dist/browser.mjs",
13
14
  "import": "./dist/index.mjs",
14
15
  "require": "./dist/index.js",
15
16
  "default": "./dist/index.js"