├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github └── workflows │ ├── ci.yml │ ├── release-please.yml │ └── release.yml ├── .gitignore ├── .npmrc ├── .nuxtrc ├── .prettierignore ├── .release-please-manifest.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.config.ts ├── docs ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .nuxtrc ├── README.md ├── app.config.ts ├── app.vue ├── components │ ├── Footer.vue │ ├── Header.vue │ ├── Logo.vue │ ├── OgImage │ │ └── OgImageDocs.vue │ └── PrimaryButton.vue ├── content │ ├── 1.getting-started │ │ ├── 1.setup.md │ │ └── _dir.yml │ └── index.yml ├── layouts │ └── docs.vue ├── nuxt.config.ts ├── nuxt.schema.ts ├── package.json ├── pages │ ├── [...slug].vue │ └── index.vue ├── public │ ├── cover.png │ ├── favicon.ico │ └── nuxt-panda.svg ├── server │ ├── api │ │ └── search.json.get.ts │ └── tsconfig.json ├── tailwind.config.ts └── tsconfig.json ├── package.json ├── playground ├── app.vue ├── assets │ └── css │ │ └── global.css ├── components │ └── PButton.vue ├── nuxt.config.ts ├── package.json ├── pages │ ├── atomic_recipes.vue │ ├── index.vue │ ├── patterns.vue │ └── slot_recipes.vue └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── release-please-config.json ├── renovate.json ├── src ├── css │ └── global.css ├── imports │ └── presets.ts ├── module.ts ├── resolvers.ts └── types.ts ├── test ├── basic.test.ts ├── fixtures │ └── basic │ │ ├── nuxt.config.ts │ │ └── package.json └── utils │ └── config-parser.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_size = 2 5 | indent_style = space 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["@nuxt/eslint-config"], 4 | "rules": { 5 | "vue/no-multiple-template-root": "off" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | test: 13 | runs-on: ${{ matrix.os }} 14 | 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest] 18 | node: [18] 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - run: corepack enable 23 | - uses: actions/setup-node@v4 24 | with: 25 | node-version: ${{ matrix.node }} 26 | cache: "pnpm" 27 | 28 | - name: Install dependencies 29 | run: pnpm install 30 | 31 | - name: Stub 32 | run: pnpm dev:prepare 33 | 34 | - name: Test 35 | run: pnpm test 36 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | 6 | permissions: 7 | contents: write 8 | pull-requests: write 9 | 10 | name: release-please 11 | 12 | jobs: 13 | release-please: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: google-github-actions/release-please-action@cc61a07e2da466bebbc19b3a7dd01d6aecb20d1e # v4.0.2 17 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "v*" 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: Install pnpm 18 | uses: pnpm/action-setup@v4.0.0 19 | 20 | - name: Use Node.js v18 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: v18 24 | registry-url: https://registry.npmjs.org/ 25 | cache: pnpm 26 | 27 | - run: pnpm i 28 | 29 | - name: Prepare 30 | run: pnpm run dev:prepare 31 | 32 | - name: PNPM build 33 | run: pnpm run prepack 34 | 35 | - name: Publish to NPM 36 | run: pnpm publish --access public --no-git-checks 37 | env: 38 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Logs 5 | *.log* 6 | 7 | # Temp directories 8 | .temp 9 | .tmp 10 | .cache 11 | 12 | # Yarn 13 | **/.yarn/cache 14 | **/.yarn/*state* 15 | 16 | # Generated dirs 17 | dist 18 | 19 | # Nuxt 20 | .nuxt 21 | .output 22 | .vercel_build_output 23 | .build-* 24 | .env 25 | .netlify 26 | 27 | # Env 28 | .env 29 | 30 | # Testing 31 | reports 32 | coverage 33 | *.lcov 34 | .nyc_output 35 | 36 | # VSCode 37 | .vscode/* 38 | !.vscode/settings.json 39 | !.vscode/tasks.json 40 | !.vscode/launch.json 41 | !.vscode/extensions.json 42 | !.vscode/*.code-snippets 43 | 44 | # Intellij idea 45 | *.iml 46 | .idea 47 | 48 | # OSX 49 | .DS_Store 50 | .AppleDouble 51 | .LSOverride 52 | .AppleDB 53 | .AppleDesktop 54 | Network Trash Folder 55 | Temporary Items 56 | .apdisk 57 | styled-system -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false -------------------------------------------------------------------------------- /.nuxtrc: -------------------------------------------------------------------------------- 1 | imports.autoImport=true 2 | typescript.includeWorkspace=true 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.md -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.7.0" 3 | } 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | ## v0.7.0 5 | 6 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/v0.4.1...v0.7.0) 7 | 8 | 9 | ### 🚀 Enhancements 10 | 11 | - Set outdir to alias ([#40](https://github.com/wattanx/nuxt-pandacss/pull/40)) 12 | 13 | ### 💅 Refactors 14 | 15 | - Refactor ModuleOptions type & fix related import ([#35](https://github.com/wattanx/nuxt-pandacss/pull/35)) 16 | 17 | ### 📖 Documentation 18 | 19 | - Migrate nuxt ui pro ([#34](https://github.com/wattanx/nuxt-pandacss/pull/34)) 20 | 21 | ### 🏡 Chore 22 | 23 | - **release:** 0.4.2 ([#28](https://github.com/wattanx/nuxt-pandacss/pull/28)) 24 | - **release:** 0.5.0 ([#29](https://github.com/wattanx/nuxt-pandacss/pull/29)) 25 | - **release:** 0.6.0 ([#32](https://github.com/wattanx/nuxt-pandacss/pull/32)) 26 | 27 | ### ❤️ Contributors 28 | 29 | - Ryota Watanabe 30 | - Gangan 31 | 32 | ## v0.5.0 33 | 34 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/v0.4.1...v0.5.0) 35 | 36 | 37 | ### 🏡 Chore 38 | 39 | - **release:** 0.4.2 ([#28](https://github.com/wattanx/nuxt-pandacss/pull/28)) 40 | 41 | ### ❤️ Contributors 42 | 43 | - Ryota Watanabe 44 | 45 | ## v0.4.2 46 | 47 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/v0.4.1...v0.4.2) 48 | 49 | ## v0.4.1 50 | 51 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/v0.4.0...v0.5.0) 52 | 53 | 54 | ### 🩹 Fixes 55 | 56 | - Add packageManager ([77fb178](https://github.com/wattanx/nuxt-pandacss/commit/77fb178)) 57 | - Add prepare ([0de1211](https://github.com/wattanx/nuxt-pandacss/commit/0de1211)) 58 | 59 | ### ❤️ Contributors 60 | 61 | - Wattanx <@wattanx> 62 | 63 | ## v0.4.0 64 | 65 | ### 🩹 Fixes 66 | 67 | - fix: settings are not reflected when settings configPath options. (#19) 68 | 69 | ### ❤️ Contributors 70 | 71 | - Gangan <@shinGangan> 72 | 73 | ## v0.3.0 74 | 75 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/0.2.0...v0.3.0) 76 | 77 | 78 | ### 🚀 Enhancements 79 | 80 | - Add ci ([f861e40](https://github.com/wattanx/nuxt-pandacss/commit/f861e40)) 81 | - Add 'cssPath' options for Nuxt module & add resolver ([9f4f5ea](https://github.com/wattanx/nuxt-pandacss/commit/9f4f5ea)) 82 | - Add panda.css template ([73cb2e7](https://github.com/wattanx/nuxt-pandacss/commit/73cb2e7)) 83 | 84 | ### 🩹 Fixes 85 | 86 | - Add stub ([68faf21](https://github.com/wattanx/nuxt-pandacss/commit/68faf21)) 87 | - Remove snapshot and verify the value of config. ([c5931af](https://github.com/wattanx/nuxt-pandacss/commit/c5931af)) 88 | - Add test & fix JSDoc ([02f266a](https://github.com/wattanx/nuxt-pandacss/commit/02f266a)) 89 | 90 | ### ❤️ Contributors 91 | 92 | - Gangan <@shinGangan> 93 | - Wattanx <@wattanx> 94 | 95 | ## v0.2.0 96 | 97 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/0.1.1...v0.2.0) 98 | 99 | 100 | ### 🚀 Enhancements 101 | 102 | - Support other panda config ([e23b3b9](https://github.com/wattanx/nuxt-pandacss/commit/e23b3b9)) 103 | - Add docs dir ([7eda780](https://github.com/wattanx/nuxt-pandacss/commit/7eda780)) 104 | 105 | ### 📖 Documentation 106 | 107 | - Update docs ([d481039](https://github.com/wattanx/nuxt-pandacss/commit/d481039)) 108 | 109 | ### 🏡 Chore 110 | 111 | - Add author ([9b4c2da](https://github.com/wattanx/nuxt-pandacss/commit/9b4c2da)) 112 | 113 | ### ❤️ Contributors 114 | 115 | - Wattanx <@wattanx> 116 | 117 | ## v0.1.1 118 | 119 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/0.1.0...v0.1.1) 120 | 121 | 122 | ### 🩹 Fixes 123 | 124 | - Execution order is different between prepare and build. ([bdc08dd](https://github.com/wattanx/nuxt-pandacss/commit/bdc08dd)) 125 | 126 | ### ❤️ Contributors 127 | 128 | - Wattanx <@wattanx> 129 | 130 | ## v0.1.0 131 | 132 | [compare changes](https://github.com/wattanx/nuxt-pandacss/compare/v0.0.2...v0.1.0) 133 | 134 | 135 | ### 🚀 Enhancements 136 | 137 | - Support theme config ([5675bd7](https://github.com/wattanx/nuxt-pandacss/commit/5675bd7)) 138 | 139 | ### 🩹 Fixes 140 | 141 | - Initialized config in buildDir. ([01c2e65](https://github.com/wattanx/nuxt-pandacss/commit/01c2e65)) 142 | 143 | ### ❤️ Contributors 144 | 145 | - Wattanx <@wattanx> 146 | 147 | ## v0.0.2 148 | 149 | 150 | ### 🚀 Enhancements 151 | 152 | - Support user config ([341d6ed](https://github.com/wattanx/nuxt-pandacss/commit/341d6ed)) 153 | 154 | ### 🏡 Chore 155 | 156 | - **release:** V0.0.1 ([58acffd](https://github.com/wattanx/nuxt-pandacss/commit/58acffd)) 157 | - **release:** V0.0.1 ([e99cd4a](https://github.com/wattanx/nuxt-pandacss/commit/e99cd4a)) 158 | 159 | ### ❤️ Contributors 160 | 161 | - Wattanx <@wattanx> 162 | 163 | ## v0.0.1 164 | 165 | 166 | ### 🚀 Enhancements 167 | 168 | - Support user config ([341d6ed](https://github.com/wattanx/nuxt-pandacss/commit/341d6ed)) 169 | 170 | ### 🏡 Chore 171 | 172 | - **release:** V0.0.1 ([58acffd](https://github.com/wattanx/nuxt-pandacss/commit/58acffd)) 173 | 174 | ### ❤️ Contributors 175 | 176 | - Wattanx <@wattanx> 177 | 178 | ## v0.0.1 179 | 180 | 181 | ### 🚀 Enhancements 182 | 183 | - Support user config ([341d6ed](https://github.com/wattanx/nuxt-pandacss/commit/341d6ed)) 184 | 185 | ### ❤️ Contributors 186 | 187 | - Wattanx <@wattanx> 188 | 189 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ryota Watanabe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt Panda CSS 2 | 3 | [![npm version][npm-version-src]][npm-version-href] 4 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 5 | [![License][license-src]][license-href] 6 | 7 | Panda CSS module for Nuxt. 8 | 9 | > **Warning** 10 | > This library is in active development. Use at your own risk. 11 | 12 | ## Features 13 | 14 | 15 | 16 | - Zero configuration to start 17 | 18 | ## Quick Setup 19 | 20 | You can install `@wattanx/nuxt-pandacss` using `nuxi`: 21 | 22 | 1. Add `@wattanx/nuxt-pandacss` dependency to your project 23 | 24 | ```bash 25 | npx nuxi@latest module add @wattanx/nuxt-pandacss 26 | ``` 27 | 28 | That's it! You can now use `@wattanx/nuxt-pandacss` in your Nuxt app ✨ 29 | 30 | ## Development 31 | 32 | ```bash 33 | # Install dependencies 34 | npm install 35 | 36 | # Generate type stubs 37 | npm run dev:prepare 38 | 39 | # Develop with the playground 40 | npm run dev 41 | 42 | # Build the playground 43 | npm run dev:build 44 | 45 | # Run ESLint 46 | npm run lint 47 | 48 | # Run Vitest 49 | npm run test 50 | npm run test:watch 51 | 52 | # Release new version 53 | npm run release 54 | ``` 55 | 56 | 57 | 58 | [npm-version-src]: https://img.shields.io/npm/v/@wattanx/nuxt-pandacss/latest.svg?style=flat&colorA=18181B&colorB=28CF8D 59 | [npm-version-href]: https://npmjs.com/package/@wattanx/nuxt-pandacss 60 | [npm-downloads-src]: https://img.shields.io/npm/dm/@wattanx/nuxt-pandacss.svg?style=flat&colorA=18181B&colorB=28CF8D 61 | [npm-downloads-href]: https://npmjs.com/package/@wattanx/nuxt-pandacss 62 | [license-src]: https://img.shields.io/npm/l/@wattanx/nuxt-pandacss.svg?style=flat&colorA=18181B&colorB=28CF8D 63 | [license-href]: https://npmjs.com/package/@wattanx/nuxt-pandacss 64 | -------------------------------------------------------------------------------- /build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from "unbuild"; 2 | export default defineBuildConfig({ 3 | failOnWarn: false, 4 | externals: [ 5 | "kleur", 6 | "lil-fp", 7 | "is-what", 8 | "esbuild", 9 | "pnpapi", 10 | "merge-anything", 11 | "bundle-n-require", 12 | "@pandacss/config", 13 | "escalade/sync", 14 | "@pandacss/error", 15 | "@pandacss/logger", 16 | "@pandacss/preset-base", 17 | "@pandacss/preset-panda", 18 | "@pandacss/types", 19 | ], 20 | }); 21 | -------------------------------------------------------------------------------- /docs/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .output 4 | .nuxt -------------------------------------------------------------------------------- /docs/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@nuxt/eslint-config', 4 | rules: { 5 | 'vue/max-attributes-per-line': 'off', 6 | 'vue/multi-word-component-names': 'off' 7 | } 8 | } -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | sw.* 11 | .env 12 | .output 13 | -------------------------------------------------------------------------------- /docs/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false -------------------------------------------------------------------------------- /docs/.nuxtrc: -------------------------------------------------------------------------------- 1 | imports.autoImport=true -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Docus Starter 2 | 3 | Starter template for [Docus](https://docus.dev). 4 | 5 | ## Clone 6 | 7 | Clone the repository (using `nuxi`): 8 | 9 | ```bash 10 | npx nuxi init -t themes/docus 11 | ``` 12 | 13 | ## Setup 14 | 15 | Install dependencies: 16 | 17 | ```bash 18 | yarn install 19 | ``` 20 | 21 | ## Development 22 | 23 | ```bash 24 | yarn dev 25 | ``` 26 | 27 | ## Edge Side Rendering 28 | 29 | Can be deployed to Vercel Functions, Netlify Functions, AWS, and most Node-compatible environments. 30 | 31 | Look at all the available presets [here](https://v3.nuxtjs.org/guide/deploy/presets). 32 | 33 | ```bash 34 | yarn build 35 | ``` 36 | 37 | ## Static Generation 38 | 39 | Use the `generate` command to build your application. 40 | 41 | The HTML files will be generated in the .output/public directory and ready to be deployed to any static compatible hosting. 42 | 43 | ```bash 44 | yarn generate 45 | ``` 46 | 47 | ## Preview build 48 | 49 | You might want to preview the result of your build locally, to do so, run the following command: 50 | 51 | ```bash 52 | yarn preview 53 | ``` 54 | 55 | --- 56 | 57 | For a detailed explanation of how things work, check out [Docus](https://docus.dev). 58 | -------------------------------------------------------------------------------- /docs/app.config.ts: -------------------------------------------------------------------------------- 1 | import { version as pkgVersion } from "../package.json"; 2 | 3 | export default defineAppConfig({ 4 | ui: { 5 | primary: "green", 6 | gray: "slate", 7 | footer: { 8 | bottom: { 9 | left: "text-sm text-gray-500 dark:text-gray-400", 10 | wrapper: "border-t border-gray-200 dark:border-gray-800", 11 | }, 12 | }, 13 | }, 14 | seo: { 15 | siteName: "Nuxt PandaCSS", 16 | }, 17 | header: { 18 | logo: { 19 | alt: "", 20 | light: "", 21 | dark: "", 22 | }, 23 | pkgVersion, 24 | search: true, 25 | colorMode: true, 26 | links: [ 27 | { 28 | icon: "i-simple-icons-github", 29 | to: "https://github.com/wattanx/nuxt-pandacss", 30 | target: "_blank", 31 | "aria-label": "Docs template on GitHub", 32 | }, 33 | ], 34 | }, 35 | footer: { 36 | credits: "Copyright © 2023", 37 | colorMode: false, 38 | links: [ 39 | { 40 | icon: "i-simple-icons-nuxtdotjs", 41 | to: "https://nuxt.com", 42 | target: "_blank", 43 | "aria-label": "Nuxt Website", 44 | }, 45 | ], 46 | }, 47 | toc: { 48 | title: "Table of Contents", 49 | bottom: { 50 | title: "Community", 51 | links: [ 52 | { 53 | icon: "i-heroicons-star", 54 | label: "Star on GitHub", 55 | to: "https://github.com/wattanx/nuxt-pandacss", 56 | target: "_blank", 57 | }, 58 | ], 59 | }, 60 | }, 61 | }); 62 | -------------------------------------------------------------------------------- /docs/app.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 49 | -------------------------------------------------------------------------------- /docs/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 24 | -------------------------------------------------------------------------------- /docs/components/Header.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 43 | -------------------------------------------------------------------------------- /docs/components/Logo.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /docs/components/OgImage/OgImageDocs.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 32 | -------------------------------------------------------------------------------- /docs/components/PrimaryButton.vue: -------------------------------------------------------------------------------- 1 | 8 | 18 | 35 | -------------------------------------------------------------------------------- /docs/content/1.getting-started/1.setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup 3 | description: Using Panda CSS in your Nuxt project is only one command away. 4 | --- 5 | 6 | ## Installation 7 | 8 | 1. Install the dependencies: 9 | 10 | ::code-group 11 | 12 | ```bash [npm] 13 | npm install -D @wattanx/nuxt-pandacss 14 | ``` 15 | 16 | ```bash [yarn] 17 | yarn add -D @wattanx/nuxt-pandacss 18 | ``` 19 | 20 | ```bash [pnpm] 21 | pnpm add -D @wattanx/nuxt-pandacss 22 | ``` 23 | 24 | :: 25 | 26 | 2. Add it to your modules section in your `nuxt.config`: 27 | 28 | ::code-group 29 | 30 | ```ts [nuxt.config.ts] 31 | export default defineNuxtConfig({ 32 | modules: ['@wattanx/nuxt-pandacss'], 33 | }) 34 | ``` 35 | 36 | :: 37 | 38 | 3. Run the `dev` command to start Docus in development mode: 39 | 40 | ::code-group 41 | 42 | ```bash [npm] 43 | npm run dev 44 | ``` 45 | 46 | ```bash [yarn] 47 | yarn dev 48 | ``` 49 | 50 | ```bash [pnpm] 51 | pnpm run dev 52 | ``` 53 | 54 | :: 55 | 56 | ::alert{type="success"} 57 | ✨ Well done! A browser window should automatically open for 58 | :: 59 | -------------------------------------------------------------------------------- /docs/content/1.getting-started/_dir.yml: -------------------------------------------------------------------------------- 1 | title: Getting Started 2 | icon: i-heroicons-bolt 3 | -------------------------------------------------------------------------------- /docs/content/index.yml: -------------------------------------------------------------------------------- 1 | title: "Panda CSS module for Nuxt." 2 | description: "Welcome to the Nuxt Panda CSS module documentation to help you set up Panda CSS" 3 | navigation: false 4 | hero: 5 | title: "Add Panda CSS to your [Nuxt Apps]{.text-primary}." 6 | description: "Welcome to the Nuxt Panda CSS module documentation to help you set up Panda CSS" 7 | orientation: horizontal 8 | links: 9 | - label: "Get started" 10 | icon: "i-heroicons-rocket-launch" 11 | to: "/getting-started/setup" 12 | size: lg 13 | - label: "Star on GitHub" 14 | icon: "i-simple-icons-github" 15 | color: "white" 16 | to: "https://github.com/wattanx/nuxt-pandacss" 17 | target: "_blank" 18 | size: lg 19 | code: | 20 | ```ts [nuxt.config.ts] 21 | export default defineNuxtConfig({ 22 | modules: ['@wattanx/nuxt-pandacss'] 23 | }) 24 | ``` 25 | features: 26 | title: "Shipped with many features." 27 | items: 28 | - title: "Zero Configuration" 29 | description: "This module enables a quick and easy setup of Panda CSS in your Nuxt application." 30 | to: "/getting-started/setup" 31 | -------------------------------------------------------------------------------- /docs/layouts/docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | -------------------------------------------------------------------------------- /docs/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | extends: ["@nuxt/ui-pro"], 3 | modules: [ 4 | "@nuxt/content", 5 | "@nuxt/ui", 6 | "@nuxthq/studio", 7 | "@nuxtjs/fontaine", 8 | "@nuxtjs/google-fonts", 9 | "nuxt-og-image", 10 | ], 11 | ui: { 12 | icons: ["heroicons", "simple-icons"], 13 | }, 14 | devtools: { enabled: true }, 15 | typescript: { 16 | strict: false, 17 | }, 18 | routeRules: { 19 | "/getting-started": { redirect: "/getting-started/setup" }, 20 | "/api/search.json": { prerender: true }, 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /docs/nuxt.schema.ts: -------------------------------------------------------------------------------- 1 | import { field, group } from "@nuxthq/studio/theme"; 2 | 3 | export default defineNuxtSchema({ 4 | appConfig: { 5 | ui: group({ 6 | title: "UI", 7 | description: "UI Customization.", 8 | icon: "i-mdi-palette-outline", 9 | fields: { 10 | icons: group({ 11 | title: "Icons", 12 | description: "Manage icons used in UI Pro.", 13 | icon: "i-mdi-application-settings-outline", 14 | fields: { 15 | search: field({ 16 | type: "icon", 17 | title: "Search Bar", 18 | description: "Icon to display in the search bar.", 19 | icon: "i-mdi-magnify", 20 | default: "i-heroicons-magnifying-glass-20-solid", 21 | }), 22 | dark: field({ 23 | type: "icon", 24 | title: "Dark mode", 25 | description: "Icon of color mode button for dark mode.", 26 | icon: "i-mdi-moon-waning-crescent", 27 | default: "i-heroicons-moon-20-solid", 28 | }), 29 | light: field({ 30 | type: "icon", 31 | title: "Light mode", 32 | description: "Icon of color mode button for light mode.", 33 | icon: "i-mdi-white-balance-sunny", 34 | default: "i-heroicons-sun-20-solid", 35 | }), 36 | external: field({ 37 | type: "icon", 38 | title: "External Link", 39 | description: "Icon for external link.", 40 | icon: "i-mdi-arrow-top-right", 41 | default: "i-heroicons-arrow-up-right-20-solid", 42 | }), 43 | chevron: field({ 44 | type: "icon", 45 | title: "Chevron", 46 | description: "Icon for chevron.", 47 | icon: "i-mdi-chevron-down", 48 | default: "i-heroicons-chevron-down-20-solid", 49 | }), 50 | hash: field({ 51 | type: "icon", 52 | title: "Hash", 53 | description: "Icon for hash anchors.", 54 | icon: "i-ph-hash", 55 | default: "i-heroicons-hashtag-20-solid", 56 | }), 57 | }, 58 | }), 59 | primary: field({ 60 | type: "string", 61 | title: "Primary", 62 | description: "Primary color of your UI.", 63 | icon: "i-mdi-palette-outline", 64 | default: "green", 65 | required: [ 66 | "sky", 67 | "mint", 68 | "rose", 69 | "amber", 70 | "violet", 71 | "emerald", 72 | "fuchsia", 73 | "indigo", 74 | "lime", 75 | "orange", 76 | "pink", 77 | "purple", 78 | "red", 79 | "teal", 80 | "yellow", 81 | "green", 82 | "blue", 83 | "cyan", 84 | "gray", 85 | "white", 86 | "black", 87 | ], 88 | }), 89 | gray: field({ 90 | type: "string", 91 | title: "Gray", 92 | description: "Gray color of your UI.", 93 | icon: "i-mdi-palette-outline", 94 | default: "slate", 95 | required: ["slate", "cool", "zinc", "neutral", "stone"], 96 | }), 97 | }, 98 | }), 99 | seo: group({ 100 | title: "SEO", 101 | description: "SEO configuration.", 102 | icon: "i-ph-app-window", 103 | fields: { 104 | siteName: field({ 105 | type: "string", 106 | title: "Site Name", 107 | description: 108 | "Name used in ogSiteName and used as second part of your page title (My page title - Nuxt UI Pro).", 109 | icon: "i-mdi-web", 110 | default: [], 111 | }), 112 | }, 113 | }), 114 | header: group({ 115 | title: "Header", 116 | description: "Header configuration.", 117 | icon: "i-mdi-page-layout-header", 118 | fields: { 119 | logo: group({ 120 | title: "Logo", 121 | description: "Footer logo configuration.", 122 | icon: "i-mdi-image-filter-center-focus-strong-outline", 123 | fields: { 124 | light: field({ 125 | type: "media", 126 | title: "Light Mode Logo", 127 | description: "Pick an image from your gallery.", 128 | icon: "i-mdi-white-balance-sunny", 129 | default: "", 130 | }), 131 | dark: field({ 132 | type: "media", 133 | title: "Dark Mode Logo", 134 | description: "Pick an image from your gallery.", 135 | icon: "i-mdi-moon-waning-crescent", 136 | default: "", 137 | }), 138 | alt: field({ 139 | type: "string", 140 | title: "Alt", 141 | description: "Alt to display for accessibility.", 142 | icon: "i-mdi-alphabet-latin", 143 | default: "", 144 | }), 145 | }, 146 | }), 147 | search: field({ 148 | type: "boolean", 149 | title: "Search Bar", 150 | description: "Hide or display the search bar.", 151 | icon: "i-mdi-magnify", 152 | default: true, 153 | }), 154 | colorMode: field({ 155 | type: "boolean", 156 | title: "Color Mode", 157 | description: "Hide or display the color mode button in your header.", 158 | icon: "i-mdi-moon-waning-crescent", 159 | default: true, 160 | }), 161 | links: field({ 162 | type: "array", 163 | title: "Links", 164 | description: "Array of link object displayed in header.", 165 | icon: "i-mdi-link-variant", 166 | default: [], 167 | }), 168 | }, 169 | }), 170 | footer: group({ 171 | title: "Footer", 172 | description: "Footer configuration.", 173 | icon: "i-mdi-page-layout-footer", 174 | fields: { 175 | credits: field({ 176 | type: "string", 177 | title: "Footer credits section", 178 | description: "Text to display as credits in the footer.", 179 | icon: "i-mdi-circle-edit-outline", 180 | default: "", 181 | }), 182 | colorMode: field({ 183 | type: "boolean", 184 | title: "Color Mode", 185 | description: "Hide or display the color mode button in the footer.", 186 | icon: "i-mdi-moon-waning-crescent", 187 | default: false, 188 | }), 189 | links: field({ 190 | type: "array", 191 | title: "Links", 192 | description: "Array of link object displayed in footer.", 193 | icon: "i-mdi-link-variant", 194 | default: [], 195 | }), 196 | }, 197 | }), 198 | toc: group({ 199 | title: "Table of contents", 200 | description: "TOC configuration.", 201 | icon: "i-mdi-table-of-contents", 202 | fields: { 203 | title: field({ 204 | type: "string", 205 | title: "Title", 206 | description: "Text to display as title of the main toc.", 207 | icon: "i-mdi-format-title", 208 | default: "", 209 | }), 210 | bottom: group({ 211 | title: "Bottom", 212 | description: "Bottom TOC configuration.", 213 | icon: "i-mdi-table-of-contents", 214 | fields: { 215 | title: field({ 216 | type: "string", 217 | title: "Title", 218 | description: "Text to display as title of the bottom toc.", 219 | icon: "i-mdi-format-title", 220 | default: "", 221 | }), 222 | edit: field({ 223 | type: "string", 224 | title: "Edit Page Link", 225 | description: "URL of your repository content folder.", 226 | icon: "i-ph-note-pencil", 227 | default: "", 228 | }), 229 | links: field({ 230 | type: "array", 231 | title: "Links", 232 | description: "Array of link object displayed in bottom toc.", 233 | icon: "i-mdi-link-variant", 234 | default: [], 235 | }), 236 | }, 237 | }), 238 | }, 239 | }), 240 | }, 241 | }); 242 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxi dev", 7 | "build": "nuxi build", 8 | "generate": "nuxi generate", 9 | "preview": "nuxi preview", 10 | "lint": "eslint .", 11 | "prepare": "nuxi prepare" 12 | }, 13 | "dependencies": { 14 | "@iconify-json/heroicons": "^1.1.19", 15 | "@iconify-json/simple-icons": "^1.1.90", 16 | "@nuxt/content": "^2.12.1", 17 | "@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@latest", 18 | "@nuxtjs/fontaine": "^0.4.1", 19 | "@nuxtjs/google-fonts": "^3.1.3", 20 | "nuxt-og-image": "^2.2.4" 21 | }, 22 | "devDependencies": { 23 | "@nuxthq/studio": "^1.0.10", 24 | "studio": "link:@@nuxthq/studio" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/pages/[...slug].vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 79 | -------------------------------------------------------------------------------- /docs/pages/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 71 | -------------------------------------------------------------------------------- /docs/public/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wattanx/nuxt-pandacss/3526bc000aec962ad2e1c57c7825b0d3882ff94b/docs/public/cover.png -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wattanx/nuxt-pandacss/3526bc000aec962ad2e1c57c7825b0d3882ff94b/docs/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/nuxt-panda.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/server/api/search.json.get.ts: -------------------------------------------------------------------------------- 1 | import { serverQueryContent } from "#content/server"; 2 | 3 | export default eventHandler(async (event) => { 4 | return serverQueryContent(event) 5 | .where({ _type: "markdown", navigation: { $ne: false } }) 6 | .find(); 7 | }); 8 | -------------------------------------------------------------------------------- /docs/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /docs/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | import defaultTheme from "tailwindcss/defaultTheme"; 3 | 4 | export default >{ 5 | theme: { 6 | extend: { 7 | fontFamily: { 8 | sans: ["DM Sans", "DM Sans fallback", ...defaultTheme.fontFamily.sans], 9 | }, 10 | colors: { 11 | green: { 12 | 50: "#EFFDF5", 13 | 100: "#D9FBE8", 14 | 200: "#B3F5D1", 15 | 300: "#75EDAE", 16 | 400: "#00DC82", 17 | 500: "#00C16A", 18 | 600: "#00A155", 19 | 700: "#007F45", 20 | 800: "#016538", 21 | 900: "#0A5331", 22 | 950: "#052e16", 23 | }, 24 | }, 25 | }, 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wattanx/nuxt-pandacss", 3 | "version": "0.7.0", 4 | "description": "Panda CSS module for Nuxt.", 5 | "configKey": "pandacss", 6 | "repository": "https://github.com/wattanx/nuxt-pandacss", 7 | "author": "wattanx", 8 | "license": "MIT", 9 | "type": "module", 10 | "exports": { 11 | ".": { 12 | "types": "./dist/types.d.ts", 13 | "import": "./dist/module.mjs", 14 | "require": "./dist/module.cjs" 15 | } 16 | }, 17 | "main": "./dist/module.cjs", 18 | "types": "./dist/types.d.ts", 19 | "files": [ 20 | "dist", 21 | "*.css" 22 | ], 23 | "scripts": { 24 | "prepack": "nuxt-module-build", 25 | "dev": "nuxi dev playground", 26 | "dev:build": "nuxi build playground", 27 | "dev:prepare": "nuxt-module-build --stub && nuxi prepare playground && nuxi prepare docs", 28 | "dev:docs": "nuxi dev docs", 29 | "release": "npm run lint && npm run test && npm run prepack && changelogen --release --major --no-commit --no-tag", 30 | "lint": "eslint .", 31 | "test": "vitest run", 32 | "test:watch": "vitest watch", 33 | "test:update": "vitest run -u" 34 | }, 35 | "dependencies": { 36 | "@nuxt/kit": "3.11.2", 37 | "@pandacss/dev": "^0.34.3", 38 | "@pandacss/node": "^0.34.3", 39 | "pathe": "^1.1.2" 40 | }, 41 | "devDependencies": { 42 | "@nuxt/devtools": "^1.3.1", 43 | "@nuxt/eslint-config": "^0.3.12", 44 | "@nuxt/module-builder": "^0.6.0", 45 | "@nuxt/schema": "3.11.2", 46 | "@nuxt/test-utils": "3.12.1", 47 | "@types/node": "^20.11.10", 48 | "changelogen": "^0.5.5", 49 | "eslint": "^8.56.0", 50 | "nuxt": "3.9.3", 51 | "vitest": "^2.0.5" 52 | }, 53 | "publishConfig": { 54 | "access": "public" 55 | }, 56 | "packageManager": "pnpm@9.9.0" 57 | } 58 | -------------------------------------------------------------------------------- /playground/app.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /playground/assets/css/global.css: -------------------------------------------------------------------------------- 1 | @layer reset, base, tokens, recipes, utilities; 2 | -------------------------------------------------------------------------------- /playground/components/PButton.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 38 | -------------------------------------------------------------------------------- /playground/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | modules: ["../src/module", "@nuxt/devtools"], 3 | pandacss: { 4 | theme: { extend: {} }, 5 | globalCss: { 6 | html: { 7 | h: "full", 8 | }, 9 | body: { 10 | bg: { base: "white", _dark: "#2C2C2C" }, 11 | }, 12 | }, 13 | jsxFramework: "vue", 14 | cssPath: "@/assets/css/global.css", 15 | outdir: "pandacss", 16 | }, 17 | devtools: { enabled: true }, 18 | }); 19 | -------------------------------------------------------------------------------- /playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "playground", 4 | "type": "module", 5 | "scripts": { 6 | "dev": "nuxi dev", 7 | "build": "nuxi build", 8 | "generate": "nuxi generate", 9 | "prepare": "nuxi prepare" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /playground/pages/atomic_recipes.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 33 | -------------------------------------------------------------------------------- /playground/pages/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 24 | -------------------------------------------------------------------------------- /playground/pages/patterns.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 39 | -------------------------------------------------------------------------------- /playground/pages/slot_recipes.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 37 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - docs/** 3 | - playgrounds/** 4 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", 3 | "packages": { 4 | ".": { 5 | "release-type": "node", 6 | "bump-minor-pre-major": true, 7 | "bump-patch-for-minor-pre-major": true 8 | } 9 | }, 10 | "bootstrap-sha": "0e63027c143ad99c7af2f9681a642017f1d43e35" 11 | } 12 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["@nuxtjs"], 4 | "packageRules": [ 5 | { 6 | "groupName": "nuxt core", 7 | "groupSlug": "nuxt", 8 | "matchPackageNames": ["nuxi"], 9 | "matchPackagePatterns": ["^@nuxt/"] 10 | }, 11 | { 12 | "groupName": "pandacss", 13 | "groupSlug": "pandacss", 14 | "matchPackagePatterns": ["^@pandacss/"] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /src/css/global.css: -------------------------------------------------------------------------------- 1 | @layer reset, base, tokens, recipes, utilities; 2 | -------------------------------------------------------------------------------- /src/imports/presets.ts: -------------------------------------------------------------------------------- 1 | import type { ModuleOptions } from "./../types"; 2 | import type { InlinePreset } from "unimport"; 3 | import { defineUnimportPreset } from "unimport"; 4 | 5 | export const createPresets = ({ 6 | outdir, 7 | }: Pick): InlinePreset[] => { 8 | return [ 9 | defineUnimportPreset({ 10 | from: `${outdir}/css`, 11 | imports: ["css", "cva", "sva", "cx"], 12 | }), 13 | // TODO: jsx doesn't work with auto imports 14 | // defineUnimportPreset({ 15 | // from: `${outdir}/jsx`, 16 | // imports: [ 17 | // "styled", 18 | // "AspectRatio", 19 | // "Bleed", 20 | // "Box", 21 | // "Center", 22 | // "Circle", 23 | // "Container", 24 | // "Divider", 25 | // "Flex", 26 | // "Float", 27 | // "GridItem", 28 | // "Grid", 29 | // "HStack", 30 | // "LinkBox", 31 | // "LinkOverlay", 32 | // "Spacer", 33 | // "Square", 34 | // "Stack", 35 | // "VisuallyHidden", 36 | // "VStack", 37 | // "Wrap", 38 | // ], 39 | // }), 40 | // TODO: pattenrs doesn't work with auto imports 41 | // defineUnimportPreset({ 42 | // from: `${outdir}/patterns`, 43 | // imports: [ 44 | // "aspectRatio", 45 | // "bleed", 46 | // "box", 47 | // "center", 48 | // "circle", 49 | // "container", 50 | // "divider", 51 | // "flex", 52 | // "float", 53 | // "gridItem", 54 | // "grid", 55 | // "hStack", 56 | // "linkBox", 57 | // "linkOverlay", 58 | // "spacer", 59 | // "square", 60 | // "stack", 61 | // "visuallyHidden", 62 | // "vStack", 63 | // "wrap", 64 | // ], 65 | // }), 66 | ]; 67 | }; 68 | -------------------------------------------------------------------------------- /src/module.ts: -------------------------------------------------------------------------------- 1 | import { 2 | addImportsSources, 3 | addTemplate, 4 | createResolver, 5 | defineNuxtModule, 6 | useLogger, 7 | } from "@nuxt/kit"; 8 | import { findConfig } from "@pandacss/config"; 9 | import { codegen, loadConfigAndCreateContext } from "@pandacss/node"; 10 | import { existsSync, promises as fsp } from "node:fs"; 11 | import { join } from "pathe"; 12 | import { configKey, name, version } from "../package.json"; 13 | import { resolveCSSPath } from "./resolvers"; 14 | import type { ModuleOptions } from "./types"; 15 | import { createPresets } from "./imports/presets"; 16 | 17 | const logger = useLogger("nuxt:pandacss"); 18 | 19 | export default defineNuxtModule({ 20 | meta: { name, version, configKey }, 21 | // Default configuration options of the Nuxt module 22 | defaults: (nuxt) => ({ 23 | preflight: true, 24 | include: [ 25 | `${nuxt.options.srcDir}/components/**/*.{js,jsx,ts,tsx,vue}`, 26 | `${nuxt.options.srcDir}/pages/**/*.{js,jsx,ts,tsx,vue}`, 27 | ], 28 | exclude: [], 29 | outdir: "styled-system", 30 | cwd: nuxt.options.buildDir, 31 | cssPath: `${nuxt.options.buildDir}/panda.css`, 32 | autoImports: true, 33 | }), 34 | async setup(options, nuxt) { 35 | const { resolve } = createResolver(import.meta.url); 36 | 37 | const cwd = resolve(options.cwd ?? nuxt.options.buildDir); 38 | 39 | // TODO: dot directory support 40 | nuxt.options.alias[options.outdir!] = join(cwd, options.outdir!); 41 | nuxt.options.alias[`${options.outdir!}/*`] = join( 42 | cwd, 43 | options.outdir!, 44 | "./*" 45 | ); 46 | 47 | if (options.autoImports) { 48 | addImportsSources(createPresets({ outdir: options.outdir })); 49 | } 50 | 51 | if (existsSync(resolve(nuxt.options.buildDir, "panda.config.mjs"))) { 52 | await fsp.rm(resolve(nuxt.options.buildDir, "panda.config.mjs")); 53 | } 54 | 55 | let configPath = ""; 56 | try { 57 | const configFile = findConfig({ cwd, file: options.configPath }); 58 | 59 | configPath = configFile ?? addPandaConfigTemplate(cwd, options); 60 | } catch (e) { 61 | const dst = addPandaConfigTemplate(cwd, options); 62 | configPath = dst; 63 | } 64 | 65 | const postcssOptions = nuxt.options.postcss; 66 | postcssOptions.plugins["@pandacss/dev/postcss"] = postcssOptions.plugins[ 67 | "@pandacss/dev/postcss" 68 | ] ?? { 69 | configPath, 70 | }; 71 | 72 | // Add CSS file 73 | const { resolvedCSSPath, loggerMessage } = await resolveCSSPath( 74 | options.cssPath, 75 | nuxt 76 | ); 77 | nuxt.options.css.push(resolvedCSSPath); 78 | logger.info(loggerMessage); 79 | 80 | function loadContext() { 81 | return loadConfigAndCreateContext({ 82 | cwd, 83 | config: { clean: options?.clean }, 84 | configPath, 85 | }); 86 | } 87 | 88 | async function createPandaContext() { 89 | const ctx = await loadContext(); 90 | 91 | const { msg } = await codegen(ctx); 92 | 93 | logger.log(msg); 94 | } 95 | 96 | nuxt.hook("app:templatesGenerated", async () => { 97 | if (!nuxt.options._prepare) { 98 | await createPandaContext(); 99 | } 100 | }); 101 | 102 | nuxt.hook("prepare:types", async ({ tsConfig }) => { 103 | // require tsconfig.json for panda css 104 | const GeneratedBy = "// Generated by nuxt-pandacss"; 105 | const tsConfigPath = resolve(nuxt.options.buildDir, "tsconfig.json"); 106 | await fsp.mkdir(nuxt.options.buildDir, { recursive: true }); 107 | await fsp.writeFile( 108 | tsConfigPath, 109 | GeneratedBy + "\n" + JSON.stringify(tsConfig, null, 2) 110 | ); 111 | 112 | if (nuxt.options._prepare) { 113 | await createPandaContext(); 114 | } 115 | }); 116 | }, 117 | }); 118 | 119 | function addPandaConfigTemplate(cwd: string, options: ModuleOptions) { 120 | return addTemplate({ 121 | filename: "panda.config.mjs", 122 | getContents: () => ` 123 | import { defineConfig } from "@pandacss/dev" 124 | 125 | export default defineConfig(${JSON.stringify({ ...options, cwd }, null, 2)})`, 126 | write: true, 127 | }).dst; 128 | } 129 | -------------------------------------------------------------------------------- /src/resolvers.ts: -------------------------------------------------------------------------------- 1 | import { addTemplate, createResolver, resolvePath, useNuxt } from "@nuxt/kit"; 2 | import { existsSync } from "node:fs"; 3 | import { relative } from "node:path"; 4 | import type { ModuleOptions } from "./types"; 5 | 6 | /** 7 | * 8 | * @param cssPath - ModuleOptions.cssPath 9 | * @param nuxt 10 | * @returns resolvedCSSPath 11 | * @returns loggerMessage 12 | * @example 13 | * ```ts 14 | * const { resolvedCSSPath, loggerMessage } = await resolveCSSPath('@/assets/css/global.css', nuxt); 15 | * ``` 16 | */ 17 | export async function resolveCSSPath( 18 | cssPath: ModuleOptions["cssPath"], 19 | nuxt = useNuxt() 20 | ): Promise<{ 21 | resolvedCSSPath: NonNullable; 22 | loggerMessage: string; 23 | }> { 24 | // if cssPath is string, find args.cssPath 25 | // else find cssPath from '@/assets/css/global.css' 26 | const resolvedCSSPath = 27 | typeof cssPath === "string" 28 | ? await resolvePath(cssPath, { extensions: [".css"] }) 29 | : await resolvePath(`${nuxt.options.dir.assets}/css/global.css`, { 30 | extensions: [".css"], 31 | }); 32 | 33 | return existsSync(resolvedCSSPath) 34 | ? { 35 | resolvedCSSPath, 36 | loggerMessage: `🐼 [info] Using Panda CSS file from @/${relative( 37 | nuxt.options.srcDir, 38 | resolvedCSSPath 39 | )}`, 40 | } 41 | : { 42 | resolvedCSSPath: createResolver(import.meta.url).resolve( 43 | addTemplate({ 44 | filename: "panda.css", 45 | write: true, 46 | getContents: () => 47 | "@layer reset, base, tokens, recipes, utilities;", 48 | }).dst 49 | ), 50 | loggerMessage: "🐼 [info] Using default Panda CSS file.", 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "@pandacss/types"; 2 | 3 | export interface ModuleOptions extends Config { 4 | /** 5 | * The path of the Panda config file. 6 | * If the file does not exist, it will be created automatically. 7 | * @default '/panda.config.mjs' 8 | * @example 'panda.config.ts' 9 | */ 10 | configPath?: string; 11 | /** 12 | * The path of the Panda CSS file. 13 | * If the file does not exist, it will be created automatically. 14 | * @default '/panda.css' 15 | * @example '@/assets/css/global.css' 16 | */ 17 | cssPath?: string; 18 | /** 19 | * Automatically add to the auto imports. 20 | * @default true 21 | */ 22 | autoImports?: boolean; 23 | } 24 | -------------------------------------------------------------------------------- /test/basic.test.ts: -------------------------------------------------------------------------------- 1 | import { parseConfig } from "./utils/config-parser"; 2 | import { describe, it, expect } from "vitest"; 3 | import { fileURLToPath } from "node:url"; 4 | import { setup, useTestContext } from "@nuxt/test-utils"; 5 | 6 | describe("basic test", async () => { 7 | await setup({ 8 | rootDir: fileURLToPath(new URL("./fixtures/basic", import.meta.url)), 9 | server: true, 10 | nuxtConfig: { 11 | buildDir: ".nuxt", 12 | }, 13 | }); 14 | 15 | it("generate default panda.config", async () => { 16 | const nuxt = useTestContext().nuxt!; 17 | 18 | const pandaConfig = nuxt.vfs["#build/panda.config"]; 19 | 20 | const config = await parseConfig(pandaConfig); 21 | 22 | expect(config.preflight).toBe(true); 23 | expect(config.include).toEqual([ 24 | `${nuxt.options.srcDir}/components/**/*.{js,jsx,ts,tsx,vue}`, 25 | `${nuxt.options.srcDir}/pages/**/*.{js,jsx,ts,tsx,vue}`, 26 | ]); 27 | expect(config.exclude).toEqual([]); 28 | expect(config.outdir).toBe("styled-system"); 29 | expect(config.cwd).toBe(nuxt.options.buildDir); 30 | expect(config.cssPath).toBe(`${nuxt.options.buildDir}/panda.css`); 31 | expect(config.theme).toEqual({ 32 | tokens: { 33 | colors: { 34 | primary: { value: "#0FEE0F" }, 35 | secondary: { value: "#EE0F0F" }, 36 | }, 37 | fonts: { 38 | body: { value: "system-ui, sans-serif" }, 39 | }, 40 | }, 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/fixtures/basic/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import MyModule from "../../../src/module"; 2 | 3 | export default defineNuxtConfig({ 4 | modules: [MyModule], 5 | pandacss: { 6 | theme: { 7 | tokens: { 8 | colors: { 9 | primary: { value: "#0FEE0F" }, 10 | secondary: { value: "#EE0F0F" }, 11 | }, 12 | fonts: { 13 | body: { value: "system-ui, sans-serif" }, 14 | }, 15 | }, 16 | }, 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /test/fixtures/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "basic", 4 | "type": "module" 5 | } 6 | -------------------------------------------------------------------------------- /test/utils/config-parser.ts: -------------------------------------------------------------------------------- 1 | import type { Node } from "estree-walker"; 2 | import { walk } from "estree-walker"; 3 | import type { ObjectExpression } from "estree"; 4 | import { transform } from "esbuild"; 5 | import { parse } from "acorn"; 6 | import type { ModuleOptions } from "../../src/types"; 7 | 8 | export const parseConfig = async (code: string): Promise => { 9 | const js = await transform(code, { loader: "ts" }); 10 | 11 | let config: any; 12 | 13 | walk( 14 | parse(js.code, { 15 | sourceType: "module", 16 | ecmaVersion: "latest", 17 | }) as Node, 18 | { 19 | enter(node) { 20 | if (node.type === "ExportDefaultDeclaration") { 21 | const callexpression = node.declaration; 22 | 23 | if (callexpression.type === "CallExpression") { 24 | const argument = callexpression.arguments[0] as ObjectExpression & { 25 | start: number; 26 | end: number; 27 | }; 28 | 29 | if (argument.type === "ObjectExpression") { 30 | const obj = js.code.slice(argument.start, argument.end); 31 | config = JSON.parse(obj) as ModuleOptions; 32 | } 33 | } 34 | } 35 | }, 36 | } 37 | ); 38 | return config; 39 | }; 40 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./playground/.nuxt/tsconfig.json" 3 | } 4 | --------------------------------------------------------------------------------