feat: Nuxt module (#197)
* feat: add nuxt module * chore: bundle module * chore: update package, readme * docs: update nuxt installation with new module * docs: remove Ui prefix to prevent confusion * chore: cleanup
This commit is contained in:
parent
caa8994d22
commit
7586b5e15c
|
|
@ -26,31 +26,28 @@ npm install -D typescript
|
||||||
npm install -D @nuxtjs/tailwindcss
|
npm install -D @nuxtjs/tailwindcss
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Install `shadcn-nuxt` module (New ✨)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -D shadcn-nuxt
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Configure `nuxt.config.ts`
|
### Configure `nuxt.config.ts`
|
||||||
|
|
||||||
<Callout class="mt-4">
|
|
||||||
|
|
||||||
**Tip:** It's better to use Nuxt `components:dirs` hook to extend auto-import components directories.
|
|
||||||
|
|
||||||
If you use `components` key in `nuxt.config.ts` default config will disposed
|
|
||||||
|
|
||||||
</Callout>
|
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
modules: ['@nuxtjs/tailwindcss'],
|
modules: ['@nuxtjs/tailwindcss', 'shadcn-nuxt'],
|
||||||
hooks: {
|
shadcn: {
|
||||||
'components:dirs': (dirs) => {
|
/**
|
||||||
dirs.unshift({
|
* Prefix for all the imported component
|
||||||
path: '~/components/ui',
|
*/
|
||||||
// this is required else Nuxt will autoImport `.ts` file
|
prefix: '',
|
||||||
extensions: ['.vue'],
|
/**
|
||||||
// prefix for your components, eg: UiButton
|
* Directory that the component lives in.
|
||||||
prefix: 'Ui',
|
* @default "./components/ui"
|
||||||
// prevent adding another prefix component by it's path.
|
*/
|
||||||
pathPrefix: false
|
componentDir: './components/ui'
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
@ -133,7 +130,7 @@ The command above will add the `Button` component to your project. Nuxt autoImpo
|
||||||
```vue {3}
|
```vue {3}
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<UiButton>Click me</UiButton>
|
<Button>Click me</Button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
56
packages/module/.gitignore
vendored
Normal file
56
packages/module/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log*
|
||||||
|
|
||||||
|
# Temp directories
|
||||||
|
.temp
|
||||||
|
.tmp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Yarn
|
||||||
|
**/.yarn/cache
|
||||||
|
**/.yarn/*state*
|
||||||
|
|
||||||
|
# Generated dirs
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Nuxt
|
||||||
|
.nuxt
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.vercel_build_output
|
||||||
|
.build-*
|
||||||
|
.netlify
|
||||||
|
|
||||||
|
# Env
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
reports
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
|
# Intellij idea
|
||||||
|
*.iml
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# OSX
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
1
packages/module/.npmrc
Normal file
1
packages/module/.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
shamefully-hoist=true
|
||||||
104
packages/module/README.md
Normal file
104
packages/module/README.md
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
<!--
|
||||||
|
Get your module up and running quickly.
|
||||||
|
|
||||||
|
Find and replace all on all files (CMD+SHIFT+F):
|
||||||
|
- Name: Shadcn Nuxt
|
||||||
|
- Package name: shadcn-nuxt
|
||||||
|
- Description: My new Nuxt module
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Shadcn Nuxt
|
||||||
|
|
||||||
|
[![npm version][npm-version-src]][npm-version-href]
|
||||||
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||||||
|
[![License][license-src]][license-href]
|
||||||
|
[![Nuxt][nuxt-src]][nuxt-href]
|
||||||
|
|
||||||
|
Shadcn Vue module for Nuxt.
|
||||||
|
|
||||||
|
- [✨ Release Notes](/CHANGELOG.md)
|
||||||
|
<!-- - [🏀 Online playground](https://stackblitz.com/github/radix-vue/shadcn-vue?file=playground%2Fapp.vue) -->
|
||||||
|
- [📖 Documentation](https://www.shadcn-vue.com/docs/installation/nuxt.html)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
<!-- Highlight some of the features your module provide here -->
|
||||||
|
- ⛰ Auto-import correct and relevant components
|
||||||
|
- more to come...
|
||||||
|
|
||||||
|
## Quick Setup
|
||||||
|
|
||||||
|
1. Add `shadcn-nuxt` dependency to your project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using pnpm
|
||||||
|
pnpm add -D shadcn-nuxt
|
||||||
|
|
||||||
|
# Using yarn
|
||||||
|
yarn add --dev shadcn-nuxt
|
||||||
|
|
||||||
|
# Using npm
|
||||||
|
npm install --save-dev shadcn-nuxt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add `shadcn-nuxt` to the `modules` section of `nuxt.config.ts`
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
modules: [
|
||||||
|
'shadcn-nuxt'
|
||||||
|
],
|
||||||
|
shadcn: {
|
||||||
|
/**
|
||||||
|
* Prefix for all the imported component
|
||||||
|
*/
|
||||||
|
prefix: '',
|
||||||
|
/**
|
||||||
|
* Directory that the component lives in.
|
||||||
|
* @default "./components/ui"
|
||||||
|
*/
|
||||||
|
componentDir: './components/ui'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! You can now use Shadcn Nuxt in your Nuxt app ✨
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Generate type stubs
|
||||||
|
npm run dev:prepare
|
||||||
|
|
||||||
|
# Develop with the playground
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Build the playground
|
||||||
|
npm run dev:build
|
||||||
|
|
||||||
|
# Run ESLint
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# Run Vitest
|
||||||
|
npm run test
|
||||||
|
npm run test:watch
|
||||||
|
|
||||||
|
# Release new version
|
||||||
|
npm run release
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- Badges -->
|
||||||
|
[npm-version-src]: https://img.shields.io/npm/v/shadcn-nuxt/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||||
|
[npm-version-href]: https://npmjs.com/package/shadcn-nuxt
|
||||||
|
|
||||||
|
[npm-downloads-src]: https://img.shields.io/npm/dm/shadcn-nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||||
|
[npm-downloads-href]: https://npmjs.com/package/shadcn-nuxt
|
||||||
|
|
||||||
|
[license-src]: https://img.shields.io/npm/l/shadcn-nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||||
|
[license-href]: https://npmjs.com/package/shadcn-nuxt
|
||||||
|
|
||||||
|
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
|
||||||
|
[nuxt-href]: https://nuxt.com
|
||||||
51
packages/module/package.json
Normal file
51
packages/module/package.json
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
{
|
||||||
|
"name": "shadcn-nuxt",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Add shadcn-vue module to Nuxt",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/radix-vue/shadcn-vue.git",
|
||||||
|
"directory": "packages/module"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/types.d.ts",
|
||||||
|
"import": "./dist/module.mjs",
|
||||||
|
"require": "./dist/module.cjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"main": "./dist/module.cjs",
|
||||||
|
"types": "./dist/types.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"prepack": "nuxt-module-build build",
|
||||||
|
"dev": "nuxi dev playground",
|
||||||
|
"dev:build": "nuxi build playground",
|
||||||
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"test": "vitest run",
|
||||||
|
"test:watch": "vitest watch",
|
||||||
|
"release": "pnpm run prepack && pnpm publish && git push --follow-tags"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxt/kit": "^3.8.2",
|
||||||
|
"ts-morph": "^19.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nuxt/devtools": "latest",
|
||||||
|
"@nuxt/eslint-config": "^0.2.0",
|
||||||
|
"@nuxt/module-builder": "^0.5.4",
|
||||||
|
"@nuxt/schema": "^3.8.2",
|
||||||
|
"@nuxt/test-utils": "^3.8.1",
|
||||||
|
"@types/node": "^20.9.3",
|
||||||
|
"nuxt": "^3.8.2",
|
||||||
|
"vitest": "^0.33.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
packages/module/playground/app.vue
Normal file
11
packages/module/playground/app.vue
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<UiButton :variant="'destructive'">
|
||||||
|
hi
|
||||||
|
</UiButton>
|
||||||
|
Nuxt module playground!
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
15
packages/module/playground/components.json
Normal file
15
packages/module/playground/components.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"style": "default",
|
||||||
|
"typescript": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.js",
|
||||||
|
"css": "assets/css/tailwind.css",
|
||||||
|
"baseColor": "slate",
|
||||||
|
"cssVariables": true
|
||||||
|
},
|
||||||
|
"framework": "nuxt",
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils"
|
||||||
|
}
|
||||||
|
}
|
||||||
23
packages/module/playground/components/ui/button/Button.vue
Normal file
23
packages/module/playground/components/ui/button/Button.vue
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { buttonVariants } from '.'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
variant?: NonNullable<Parameters<typeof buttonVariants>[0]>['variant']
|
||||||
|
size?: NonNullable<Parameters<typeof buttonVariants>[0]>['size']
|
||||||
|
as?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
as: 'button',
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<component
|
||||||
|
:is="as"
|
||||||
|
:class="cn(buttonVariants({ variant, size }), $attrs.class ?? '')"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
32
packages/module/playground/components/ui/button/index.ts
Normal file
32
packages/module/playground/components/ui/button/index.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { cva } from 'class-variance-authority'
|
||||||
|
|
||||||
|
export { default as Button } from './Button.vue'
|
||||||
|
|
||||||
|
export const buttonVariants = cva(
|
||||||
|
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
||||||
|
destructive:
|
||||||
|
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
||||||
|
outline:
|
||||||
|
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
||||||
|
secondary:
|
||||||
|
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||||
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||||
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: 'h-10 px-4 py-2',
|
||||||
|
sm: 'h-9 rounded-md px-3',
|
||||||
|
lg: 'h-11 rounded-md px-8',
|
||||||
|
icon: 'h-10 w-10',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'default',
|
||||||
|
size: 'default',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { DropdownMenuRoot, type DropdownMenuRootEmits, type DropdownMenuRootProps, useEmitAsProps, useForwardPropsEmits } from 'radix-vue'
|
||||||
|
|
||||||
|
const props = defineProps<DropdownMenuRootProps>()
|
||||||
|
const emits = defineEmits<DropdownMenuRootEmits>()
|
||||||
|
|
||||||
|
const forwarded = useForwardPropsEmits(props, emits)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DropdownMenuRoot v-bind="forwarded">
|
||||||
|
<slot />
|
||||||
|
</DropdownMenuRoot>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
DropdownMenuCheckboxItem,
|
||||||
|
type DropdownMenuCheckboxItemEmits,
|
||||||
|
type DropdownMenuCheckboxItemProps,
|
||||||
|
DropdownMenuItemIndicator,
|
||||||
|
useEmitAsProps,
|
||||||
|
} from 'radix-vue'
|
||||||
|
import { Check } from 'lucide-vue-next'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const props = defineProps<DropdownMenuCheckboxItemProps & { class?: string }>()
|
||||||
|
const emits = defineEmits<DropdownMenuCheckboxItemEmits>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DropdownMenuCheckboxItem
|
||||||
|
v-bind="{ ...props, ...useEmitAsProps(emits) }"
|
||||||
|
:class=" cn(
|
||||||
|
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||||
|
props.class,
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||||
|
<DropdownMenuItemIndicator>
|
||||||
|
<Check class="w-4 h-4" />
|
||||||
|
</DropdownMenuItemIndicator>
|
||||||
|
</span>
|
||||||
|
<slot />
|
||||||
|
</DropdownMenuCheckboxItem>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export { DropdownMenuPortal } from 'radix-vue'
|
||||||
|
|
||||||
|
export { default as DropdownMenu } from './DropdownMenu.vue'
|
||||||
|
export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue'
|
||||||
7
packages/module/playground/lib/utils.ts
Normal file
7
packages/module/playground/lib/utils.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { type ClassValue, clsx } from 'clsx'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
import { camelize, getCurrentInstance, toHandlerKey } from 'vue'
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
7
packages/module/playground/nuxt.config.ts
Normal file
7
packages/module/playground/nuxt.config.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
modules: ['../src/module'],
|
||||||
|
shadcn: {
|
||||||
|
prefix: 'Ui',
|
||||||
|
},
|
||||||
|
devtools: { enabled: true },
|
||||||
|
})
|
||||||
22
packages/module/playground/package.json
Normal file
22
packages/module/playground/package.json
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "my-module-playground",
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nuxi dev",
|
||||||
|
"build": "nuxi build",
|
||||||
|
"generate": "nuxi generate"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nuxtjs/tailwindcss": "^6.10.1",
|
||||||
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"clsx": "^2.0.0",
|
||||||
|
"lucide-vue-next": "^0.276.0",
|
||||||
|
"radix-vue": "^1.2.2",
|
||||||
|
"tailwind-merge": "^2.0.0",
|
||||||
|
"tailwindcss-animate": "^1.0.7"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nuxt": "latest"
|
||||||
|
}
|
||||||
|
}
|
||||||
73
packages/module/playground/tailwind.config.js
Normal file
73
packages/module/playground/tailwind.config.js
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
const animate = require('tailwindcss-animate')
|
||||||
|
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
darkMode: ['class'],
|
||||||
|
|
||||||
|
theme: {
|
||||||
|
container: {
|
||||||
|
center: true,
|
||||||
|
padding: '2rem',
|
||||||
|
screens: {
|
||||||
|
'2xl': '1400px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
border: 'hsl(var(--border))',
|
||||||
|
input: 'hsl(var(--input))',
|
||||||
|
ring: 'hsl(var(--ring))',
|
||||||
|
background: 'hsl(var(--background))',
|
||||||
|
foreground: 'hsl(var(--foreground))',
|
||||||
|
primary: {
|
||||||
|
DEFAULT: 'hsl(var(--primary))',
|
||||||
|
foreground: 'hsl(var(--primary-foreground))',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: 'hsl(var(--secondary))',
|
||||||
|
foreground: 'hsl(var(--secondary-foreground))',
|
||||||
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: 'hsl(var(--destructive))',
|
||||||
|
foreground: 'hsl(var(--destructive-foreground))',
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
DEFAULT: 'hsl(var(--muted))',
|
||||||
|
foreground: 'hsl(var(--muted-foreground))',
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: 'hsl(var(--accent))',
|
||||||
|
foreground: 'hsl(var(--accent-foreground))',
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
DEFAULT: 'hsl(var(--popover))',
|
||||||
|
foreground: 'hsl(var(--popover-foreground))',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
DEFAULT: 'hsl(var(--card))',
|
||||||
|
foreground: 'hsl(var(--card-foreground))',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: 'var(--radius)',
|
||||||
|
md: 'calc(var(--radius) - 2px)',
|
||||||
|
sm: 'calc(var(--radius) - 4px)',
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
'accordion-down': {
|
||||||
|
from: { height: 0 },
|
||||||
|
to: { height: 'var(--radix-accordion-content-height)' },
|
||||||
|
},
|
||||||
|
'accordion-up': {
|
||||||
|
from: { height: 'var(--radix-accordion-content-height)' },
|
||||||
|
to: { height: 0 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||||
|
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [animate],
|
||||||
|
}
|
||||||
3
packages/module/playground/tsconfig.json
Normal file
3
packages/module/playground/tsconfig.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
||||||
65
packages/module/src/module.ts
Normal file
65
packages/module/src/module.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { readdirSync } from 'node:fs'
|
||||||
|
import { addComponent, createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||||
|
import { Project } from 'ts-morph'
|
||||||
|
|
||||||
|
// Module options TypeScript interface definition
|
||||||
|
export interface ModuleOptions {
|
||||||
|
/**
|
||||||
|
* Prefix for all the imported component
|
||||||
|
*/
|
||||||
|
prefix?: string
|
||||||
|
/**
|
||||||
|
* Directory that the component lives in.
|
||||||
|
* @default "./components/ui"
|
||||||
|
*/
|
||||||
|
componentDir?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineNuxtModule<ModuleOptions>({
|
||||||
|
meta: {
|
||||||
|
name: 'shadcn',
|
||||||
|
configKey: 'shadcn',
|
||||||
|
},
|
||||||
|
defaults: {
|
||||||
|
prefix: '',
|
||||||
|
componentDir: './components/ui',
|
||||||
|
},
|
||||||
|
async setup(options, nuxt) {
|
||||||
|
const IGNORE_DIR = '**/components/ui'
|
||||||
|
const COMPONENT_DIR_PATH = options.componentDir!
|
||||||
|
const ROOT_DIR_PATH = nuxt.options.rootDir
|
||||||
|
|
||||||
|
const { resolve } = createResolver(ROOT_DIR_PATH)
|
||||||
|
|
||||||
|
nuxt.options.ignore.push(IGNORE_DIR)
|
||||||
|
nuxt._ignore?.add(IGNORE_DIR)
|
||||||
|
nuxt._ignorePatterns?.push(IGNORE_DIR)
|
||||||
|
|
||||||
|
try {
|
||||||
|
readdirSync(resolve(COMPONENT_DIR_PATH))
|
||||||
|
.forEach(async (dir) => {
|
||||||
|
const filePath = resolve(COMPONENT_DIR_PATH, dir, 'index.ts')
|
||||||
|
|
||||||
|
const project = new Project()
|
||||||
|
project.addSourceFileAtPath(filePath)
|
||||||
|
const sourceFile = project.getSourceFileOrThrow(filePath)
|
||||||
|
const exportedDeclarations = sourceFile.getExportedDeclarations()
|
||||||
|
|
||||||
|
// Filter out non-component export
|
||||||
|
const exportedKeys = Array.from(exportedDeclarations.keys()).filter(key => /^[A-Z]/.test(key))
|
||||||
|
|
||||||
|
exportedKeys.forEach((key) => {
|
||||||
|
addComponent({
|
||||||
|
name: `${options.prefix}${key}`, // name of the component to be used in vue templates
|
||||||
|
export: key, // (optional) if the component is a named (rather than default) export
|
||||||
|
filePath: resolve(filePath),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err instanceof Error)
|
||||||
|
console.warn(err.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
15
packages/module/test/basic.test.ts
Normal file
15
packages/module/test/basic.test.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { $fetch, setup } from '@nuxt/test-utils'
|
||||||
|
|
||||||
|
describe('ssr', async () => {
|
||||||
|
await setup({
|
||||||
|
rootDir: fileURLToPath(new URL('./fixtures/basic', import.meta.url)),
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders the index page', async () => {
|
||||||
|
// Get response to a server-rendered page with `$fetch`.
|
||||||
|
const html = await $fetch('/')
|
||||||
|
expect(html).toContain('<div>basic</div>')
|
||||||
|
})
|
||||||
|
})
|
||||||
6
packages/module/test/fixtures/basic/app.vue
vendored
Normal file
6
packages/module/test/fixtures/basic/app.vue
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<script setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>basic</div>
|
||||||
|
</template>
|
||||||
7
packages/module/test/fixtures/basic/nuxt.config.ts
vendored
Normal file
7
packages/module/test/fixtures/basic/nuxt.config.ts
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import MyModule from '../../../src/module'
|
||||||
|
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
modules: [
|
||||||
|
MyModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
5
packages/module/test/fixtures/basic/package.json
vendored
Normal file
5
packages/module/test/fixtures/basic/package.json
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name": "basic",
|
||||||
|
"type": "module",
|
||||||
|
"private": true
|
||||||
|
}
|
||||||
3
packages/module/tsconfig.json
Normal file
3
packages/module/tsconfig.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
||||||
5366
pnpm-lock.yaml
5366
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user