{"_id":"@adamkindberg/tailwind-typed","_rev":"2-3a99c86433e53ecb3049112388fafec6","name":"@adamkindberg/tailwind-typed","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.1":{"name":"@adamkindberg/tailwind-typed","version":"0.0.1","keywords":["tailwind","tailwindcss","tailwind-v4","typescript","css-variables","design-tokens","vite-plugin","codegen"],"author":{"name":"WeeWee"},"license":"Apache-2.0","_id":"@adamkindberg/tailwind-typed@0.0.1","maintainers":[{"name":"adamkindberg","email":"kindbergadam@gmail.com"}],"homepage":"https://github.com/WeeWee/tailwind-typed#readme","bugs":{"url":"https://github.com/WeeWee/tailwind-typed/issues"},"bin":{"tw-typed":"dist/cli.js"},"dist":{"shasum":"a9a179dbc534c8b778bbffd5036611768b199f63","tarball":"https://registry.npmjs.org/@adamkindberg/tailwind-typed/-/tailwind-typed-0.0.1.tgz","fileCount":22,"integrity":"sha512-WJo99jJucMxgbH64g6FeUMjbaaIKOd4jL7hcu59SF/z9t7ZMS7nAMaYAhD1PoOSVp1VLmbE868beHVJYlJ910Q==","signatures":[{"sig":"MEYCIQD4ZokltYNRxO0w34KwaALAJKqIJ/zVgIA6iGQyX3UytwIhAJASe+FhLxtuFZ0zthwHB/PxOTi66r5MnVYLjdGZgb10","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":235529},"main":"./dist/index.cjs","pnpm":{"onlyBuiltDependencies":["esbuild","@tailwindcss/oxide"]},"type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./vite":{"types":"./dist/vite.d.ts","import":"./dist/vite.js","require":"./dist/vite.cjs"}},"gitHead":"b7f8f292a18364d4fbe142102b605e1ef760737e","scripts":{"dev":"tsup --watch","e2e":"node e2e/verify.mjs","test":"vitest run","build":"tsup","verify":"vitest run && tsc --noEmit && tsup && node e2e/verify.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"tsup"},"_npmUser":{"name":"adamkindberg","email":"kindbergadam@gmail.com"},"repository":{"url":"git+https://github.com/WeeWee/tailwind-typed.git","type":"git"},"_npmVersion":"9.6.3","description":"Generate fully-typed, importable access to your Tailwind v4 theme tokens (CSS variables + resolved values) for use anywhere, including non-Tailwind contexts.","directories":{},"_nodeVersion":"24.2.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","vite":"^6.0.0","vitest":"^2.1.0","typescript":"^5.7.0","@types/node":"^22.10.0","tailwindcss":"^4.0.0"},"peerDependencies":{"vite":"^5.0.0 || ^6.0.0 || ^7.0.0","tailwindcss":"^4.0.0"},"peerDependenciesMeta":{"vite":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/tailwind-typed_0.0.1_1780490155835_0.9978961668319519","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@adamkindberg/tailwind-typed","version":"0.0.2","description":"Generate fully-typed, importable access to your Tailwind v4 theme tokens (CSS variables + resolved values) for use anywhere, including non-Tailwind contexts.","author":{"name":"WeeWee"},"license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/WeeWee/tailwind-typed.git"},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./vite":{"types":"./dist/vite.d.ts","import":"./dist/vite.js","require":"./dist/vite.cjs"},"./package.json":"./package.json"},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","bin":{"tw-typed":"dist/cli.js"},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","e2e":"node e2e/verify.mjs","verify":"vitest run && tsc --noEmit && tsup && node e2e/verify.mjs","prepublishOnly":"tsup"},"engines":{"node":">=18"},"peerDependencies":{"tailwindcss":"^4.0.0","vite":"^5.0.0 || ^6.0.0 || ^7.0.0"},"peerDependenciesMeta":{"vite":{"optional":true}},"devDependencies":{"@types/node":"^22.10.0","tailwindcss":"^4.0.0","tsup":"^8.3.0","typescript":"^5.7.0","vite":"^6.0.0","vitest":"^2.1.0"},"keywords":["tailwind","tailwindcss","tailwind-v4","typescript","css-variables","design-tokens","vite-plugin","codegen"],"publishConfig":{"access":"public"},"pnpm":{"onlyBuiltDependencies":["esbuild","@tailwindcss/oxide"]},"gitHead":"7475aaa76c9960703aeac846d69200f1c51cbe4f","bugs":{"url":"https://github.com/WeeWee/tailwind-typed/issues"},"homepage":"https://github.com/WeeWee/tailwind-typed#readme","_id":"@adamkindberg/tailwind-typed@0.0.2","_nodeVersion":"24.2.0","_npmVersion":"9.6.3","dist":{"integrity":"sha512-mor33zYkGUbSq2q4npmffswULcutG+1+OsekcQ86rqJx/PkTgN8fCZIzWLu2u3brgX1XhrITL8hnog8cFU+TLA==","shasum":"d6b0dd03e127a5e092096dcafa25cf5a5020cd73","tarball":"https://registry.npmjs.org/@adamkindberg/tailwind-typed/-/tailwind-typed-0.0.2.tgz","fileCount":22,"unpackedSize":239453,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCTJhcfQpaa3xGUILemZLuiQZWIFKCwfMlCvOvMVP876gIhAP8u9xxZ70JpMWEK0lJCwpJ9VkhaXuVlu2GxsVJTj7JY"}]},"_npmUser":{"name":"adamkindberg","email":"kindbergadam@gmail.com"},"directories":{},"maintainers":[{"name":"adamkindberg","email":"kindbergadam@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tailwind-typed_0.0.2_1782911144133_0.059833672304042906"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-03T12:35:55.567Z","modified":"2026-07-01T13:05:44.402Z","0.0.1":"2026-06-03T12:35:55.966Z","0.0.2":"2026-07-01T13:05:44.309Z"},"bugs":{"url":"https://github.com/WeeWee/tailwind-typed/issues"},"author":{"name":"WeeWee"},"license":"Apache-2.0","homepage":"https://github.com/WeeWee/tailwind-typed#readme","keywords":["tailwind","tailwindcss","tailwind-v4","typescript","css-variables","design-tokens","vite-plugin","codegen"],"repository":{"type":"git","url":"git+https://github.com/WeeWee/tailwind-typed.git"},"description":"Generate fully-typed, importable access to your Tailwind v4 theme tokens (CSS variables + resolved values) for use anywhere, including non-Tailwind contexts.","maintainers":[{"name":"adamkindberg","email":"kindbergadam@gmail.com"}],"readme":"# @adamkindberg/tailwind-typed\r\n\r\n> Turn your **Tailwind v4** theme into a fully-typed, importable module — so you can use your colors, spacing, and brand tokens **anywhere**, including places Tailwind classes can't reach (OG-image / metadata generators, emails, inline styles, CSS-in-JS, canvas…).\r\n\r\nIn Tailwind v4 your theme lives in CSS (`@theme { --color-brand: … }`), which TypeScript can't see. `tailwind-typed` reads your theme — **the built-in defaults *and* your custom `@theme` additions** — and generates a self-contained `.ts` module with:\r\n\r\n- a typed `tokens` object (`tokens.color.brand.value` → `\"#5b21b6\"`, `.var` → `\"var(--color-brand)\"`)\r\n- typed helpers `cssVar()` / `value()`\r\n- typed Tailwind class-name builders (`cn.bg('brand')` → `\"bg-brand\"`)\r\n- an iterable `allTokens` list (browse / render a palette / build a design-token explorer)\r\n\r\nThe generated file is **self-contained** — your app has zero runtime dependency on this package (it can be a `devDependency`).\r\n\r\n## Install\r\n\r\n```bash\r\npnpm add -D @adamkindberg/tailwind-typed\r\n```\r\nRequires tailwindcss v4 (peer)\r\n## Quick start (Vite)\r\n\r\n```ts\r\n// vite.config.ts\r\nimport { defineConfig } from 'vite'\r\nimport tailwindTyped from '@adamkindberg/tailwind-typed/vite'\r\n\r\nexport default defineConfig({\r\n  plugins: [tailwindTyped()], // auto-detects your CSS entry; regenerates on @theme changes (HMR)\r\n})\r\n```\r\n\r\nGiven a CSS entry like:\r\n\r\n```css\r\n/* src/index.css */\r\n@import \"tailwindcss\";\r\n@theme {\r\n  --color-brand: #5b21b6;\r\n}\r\n```\r\n\r\n…a `src/tailwind-theme.gen.ts` is generated and kept in sync:\r\n\r\n```ts\r\nimport { tokens, cssVar, value, cn, allTokens } from './tailwind-theme.gen'\r\n\r\ntokens.color.brand.value   // \"#5b21b6\"\r\ntokens.color.brand.var     // \"var(--color-brand)\"\r\n\r\ncssVar('color', 'brand')   // \"var(--color-brand)\"   ✓ autocompleted, typo-safe\r\nvalue('spacing', '4')      // resolved value\r\ncn.bg('brand')             // \"bg-brand\"\r\n\r\nfor (const t of allTokens) { /* t.namespace, t.key, t.var, t.value, t.isDefault */ }\r\n```\r\n\r\n## The headline use case: tokens outside Tailwind\r\n\r\nWhen you generate raw CSS or inline styles in a context that **doesn't load Tailwind's `:root` variables** (e.g. an OG-image / metadata generator), `var(--color-brand)` resolves to nothing. Use the **resolved value** instead:\r\n\r\n```ts\r\nimport { tokens } from './src/tailwind-theme.gen' // a plain import — works in any Node script\r\n\r\nexport function ogStyles() {\r\n  return {\r\n    background: tokens.color.brand.value, // \"#5b21b6\" — safe; no :root needed\r\n    color: tokens.color.white.value,\r\n  }\r\n}\r\n```\r\n\r\n- `.value` → the literal value. Safe everywhere.\r\n- `.var` → `var(--…)`. Use inside your app where the Tailwind theme CSS is present.\r\n\r\nBecause the generated module is a **real file** (not a Vite virtual module), it imports cleanly from standalone scripts, SSR, CI tasks — anywhere, not just inside your Vite bundle.\r\n\r\n## CLI\r\n\r\nThe Vite plugin covers in-app dev. For CI and contexts that run outside Vite (a standalone generator, a build step), use the CLI:\r\n\r\n```bash\r\ntw-typed generate              # write the typed module (auto-detects input/out)\r\ntw-typed generate --watch      # regenerate on CSS changes\r\ntw-typed check                 # exit non-zero if the module is stale (CI guard)\r\n\r\ntw-typed generate -i src/app.css -o src/theme.gen.ts\r\n```\r\n\r\nWire it into your scripts so the module always exists before other tooling runs:\r\n\r\n```jsonc\r\n{\r\n  \"scripts\": {\r\n    \"predev\": \"tw-typed generate\",\r\n    \"prebuild\": \"tw-typed generate\",\r\n    \"lint:theme\": \"tw-typed check\"   // fail CI if someone forgot to regenerate\r\n  }\r\n}\r\n```\r\n\r\n## Configuration\r\n\r\nOptions can come from CLI flags, the Vite plugin argument, or a `tailwind-typed` field in `package.json` (lowest priority). Explicit options win.\r\n\r\n| Option  | Default                      | Description                                             |\r\n| ------- | ---------------------------- | ------------------------------------------------------- |\r\n| `input` | auto-detected¹               | CSS entry containing your `@theme`.                     |\r\n| `out`   | `src/tailwind-theme.gen.ts`  | Where to write the generated module.                    |\r\n| `cwd`   | `process.cwd()` / Vite root  | Project root.                                           |\r\n| `header`| package banner               | Override the header comment in the generated file.      |\r\n\r\n```jsonc\r\n// package.json\r\n{\r\n  \"tailwind-typed\": { \"input\": \"app/app.css\", \"out\": \"app/theme.gen.ts\" }\r\n}\r\n```\r\n\r\n¹ Auto-detect tries common locations: `src/index.css`, `src/app.css`, `src/styles/index.css`, `app/app.css`, `styles/globals.css`, … If none are found you'll get a clear error listing what was searched.\r\n\r\n> **Tip:** commit the generated file (works everywhere, no setup) **or** gitignore it and regenerate via `predev`/`prebuild` + the `check` guard in CI. Either is fine.\r\n\r\n## How it works\r\n\r\n`tailwind-typed` loads Tailwind v4's default theme (`tailwindcss/theme.css`) plus your `@theme` block(s) and resolves the merged set through Tailwind's own design-system loader — so you get every token, with your overrides applied, exactly as Tailwind sees them. Namespaces (`color`, `spacing`, `font-weight`, `text-shadow`, …) are detected by longest-prefix match.\r\n\r\n## Notes & limitations (v1)\r\n\r\n- Targets **Tailwind v4** (CSS-first) only.\r\n- Reads `@theme` from the configured CSS entry. `@theme` blocks inside *imported* CSS files aren't followed yet.\r\n- Paired sub-properties (e.g. `--text-lg--line-height`) are omitted; the primary token (`--text-lg`) is included.\r\n- `.var` references only resolve at runtime where the theme's `:root` variables are present — prefer `.value` for isolated contexts.\r\n\r\n## Programmatic API\r\n\r\n```ts\r\nimport { generate, check, buildModule, resolveTheme, generateModule } from '@adamkindberg/tailwind-typed'\r\n\r\nawait generate({ cwd, input, out })   // build + write (returns { changed, outPath, tokenCount, … })\r\nawait check({ cwd, input, out })      // build + compare (returns { upToDate, … })\r\nconst { content } = await buildModule({ input })  // build the module source without writing\r\nconst tokenSet = await resolveTheme({ css })      // low-level: CSS -> normalized TokenSet\r\n```\r\n\r\n## License\r\n\r\nApache-2.0\r\n","readmeFilename":"README.md"}