mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-16 13:08:06 +01:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5af9da4d3c | ||
|
|
1d995136a5 | ||
|
|
ba15add4db | ||
|
|
0aca478c57 | ||
|
|
0ee4f2b75b | ||
|
|
6e53cb6281 | ||
|
|
de715304dc | ||
|
|
81854112e3 | ||
|
|
87526b9ec5 | ||
|
|
f79187825f | ||
|
|
0443ac2c9d | ||
|
|
d2c51e3667 | ||
|
|
d15d7fa01d |
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"git": {
|
||||
"commitMessage": "chore(release): ${version}"
|
||||
"commitMessage": "chore(release): ${version}",
|
||||
"tagName": "v${version}"
|
||||
},
|
||||
"npm": {
|
||||
"publish": false
|
||||
@@ -11,7 +12,7 @@
|
||||
"web": true
|
||||
},
|
||||
"hooks": {
|
||||
"before:init": ["pnpm lint"]
|
||||
"before:init": ["pnpm lint", "pnpm typecheck"]
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/conventional-changelog": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## [2.14.1](https://github.com/nuxt/ui/compare/v2.14.0...v2.14.1) (2024-02-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **module:** revert tailwind config from [#1272](https://github.com/nuxt/ui/issues/1272) ([#1404](https://github.com/nuxt/ui/issues/1404)) ([ba15add](https://github.com/nuxt/ui/commit/ba15add4db5d2f84e987819628cbbf88edcbad57))
|
||||
|
||||
## [2.14.0](https://github.com/nuxt/ui/compare/v2.13.0...v2.14.0) (2024-02-22)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<div>
|
||||
<NuxtLoadingIndicator />
|
||||
|
||||
<Banner />
|
||||
|
||||
<Header v-if="!$route.path.startsWith('/examples')" :links="links" />
|
||||
|
||||
<NuxtLayout>
|
||||
@@ -12,7 +14,7 @@
|
||||
<Footer v-if="!$route.path.startsWith('/examples')" />
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUDocsSearch ref="searchRef" :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" />
|
||||
<LazyUContentSearch ref="searchRef" :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" />
|
||||
</ClientOnly>
|
||||
|
||||
<UNotifications>
|
||||
|
||||
76
docs/components/Banner.vue
Normal file
76
docs/components/Banner.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<script setup lang="ts">
|
||||
import { isAfter } from 'date-fns'
|
||||
|
||||
const id = 'nuxt-ui-banner-1'
|
||||
const to = '/pro/pricing'
|
||||
const date = new Date('2024-02-25T20:00:00Z')
|
||||
|
||||
const timeAgo = useTimeAgo(date)
|
||||
|
||||
const hideBanner = () => {
|
||||
localStorage.setItem(id, 'true')
|
||||
|
||||
document.querySelector('html')?.classList.add('hide-banner')
|
||||
}
|
||||
|
||||
if (process.server) {
|
||||
useHead({
|
||||
script: [{
|
||||
key: 'prehydrate-template-banner',
|
||||
innerHTML: `
|
||||
if (localStorage.getItem('${id}') === 'true') {
|
||||
document.querySelector('html').classList.add('hide-banner')
|
||||
}`.replace(/\s+/g, ' '),
|
||||
type: 'text/javascript'
|
||||
}]
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (isAfter(new Date(), date)) {
|
||||
hideBanner()
|
||||
return
|
||||
}
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (isAfter(new Date(), date)) {
|
||||
hideBanner()
|
||||
clearInterval(interval)
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative bg-primary hover:bg-primary/90 transition-[background] backdrop-blur z-50 app-banner">
|
||||
<UContainer class="py-2">
|
||||
<NuxtLink v-if="to" :to="to" class="focus:outline-none" tabindex="-1">
|
||||
<span class="absolute inset-0 " aria-hidden="true" />
|
||||
</NuxtLink>
|
||||
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="lg:flex-1 hidden lg:flex items-center" />
|
||||
|
||||
<p class="text-sm font-medium text-white dark:text-gray-900">
|
||||
<UIcon name="i-heroicons-gift" class="w-5 h-5 align-top flex-shrink-0 pointer-events-none mr-2" />
|
||||
<span class="font-semibold">Nuxt UI Pro v1.0</span> is out with dashboard components! Discount ends <span class="font-semibold">{{ timeAgo }}</span>.
|
||||
</p>
|
||||
|
||||
<div class="flex items-center justify-end lg:flex-1">
|
||||
<button
|
||||
class="p-1.5 rounded-md inline-flex hover:bg-primary/90"
|
||||
@click.prevent="hideBanner"
|
||||
>
|
||||
<UIcon name="i-heroicons-x-mark-20-solid" class="w-5 h-5 text-white dark:text-gray-900" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</UContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.hide-banner .app-banner {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -18,8 +18,8 @@
|
||||
<template #right>
|
||||
<ColorPicker />
|
||||
|
||||
<UTooltip text="Search" :shortcuts="[metaSymbol, 'K']">
|
||||
<UDocsSearchButton :label="null" />
|
||||
<UTooltip text="Search" :shortcuts="[metaSymbol, 'K']" :popper="{ strategy: 'absolute' }">
|
||||
<UContentSearchButton :label="null" />
|
||||
</UTooltip>
|
||||
|
||||
<UColorModeButton />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<UPopover mode="hover">
|
||||
<UPopover mode="hover" :popper="{ strategy: 'absolute' }" :ui="{ width: 'w-[156px]' }">
|
||||
<template #default="{ open }">
|
||||
<UButton color="gray" variant="ghost" square :class="[open && 'bg-gray-50 dark:bg-gray-800']" aria-label="Color picker">
|
||||
<UIcon name="i-heroicons-swatch-20-solid" class="w-5 h-5 text-primary-500 dark:text-primary-400" />
|
||||
|
||||
@@ -79,10 +79,10 @@ pro:
|
||||
title: Upgrade to <span class="text-primary">Nuxt UI Pro</span>
|
||||
description: 'Nuxt UI Pro is a collection of premium Vue components built on top of Nuxt UI to create beautiful & responsive Nuxt applications in minutes.<br>It includes all primitives to build landing pages, documentations, blogs, dashboards or entire SaaS products.'
|
||||
links:
|
||||
- label: View plans
|
||||
- label: Buy now
|
||||
to: /pro/pricing
|
||||
color: gray
|
||||
icon: i-heroicons-credit-card
|
||||
color: black
|
||||
trailingIcon: i-heroicons-arrow-right-20-solid
|
||||
size: lg
|
||||
- label: Explore templates
|
||||
to: /pro/templates
|
||||
@@ -178,7 +178,7 @@ pro:
|
||||
</UPageBody>
|
||||
|
||||
<template #right>
|
||||
<UDocsToc :links="page.body.toc.links" />
|
||||
<UContentToc :links="page.body.toc.links" />
|
||||
</template>
|
||||
</UPage>
|
||||
</template>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<Footer />
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUDocsSearch :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" />
|
||||
<LazyUContentSearch :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" />
|
||||
</ClientOnly>
|
||||
|
||||
<UNotifications>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createResolver } from '@nuxt/kit'
|
||||
import colors from 'tailwindcss/colors'
|
||||
import module from '../src/module'
|
||||
import { excludeColors } from '../src/runtime/utils/colors'
|
||||
import { excludeColors } from '../src/colors'
|
||||
import pkg from '../package.json'
|
||||
|
||||
const { resolve } = createResolver(import.meta.url)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"@nuxt/devtools": "^1.0.8",
|
||||
"@nuxt/eslint-config": "^0.2.0",
|
||||
"@nuxt/image": "^1.3.0",
|
||||
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@0.7.5-28475621.09eb8fa",
|
||||
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@1.0.0-28476869.809f447",
|
||||
"@nuxtjs/fontaine": "^0.4.1",
|
||||
"@nuxtjs/google-fonts": "^3.1.3",
|
||||
"@nuxtjs/plausible": "^0.2.4",
|
||||
@@ -20,8 +20,8 @@
|
||||
"@vueuse/nuxt": "^10.8.0",
|
||||
"date-fns": "^3.3.1",
|
||||
"eslint": "^8.56.0",
|
||||
"joi": "^17.12.1",
|
||||
"nuxt": "^3.10.2",
|
||||
"joi": "^17.12.2",
|
||||
"nuxt": "^3.10.3",
|
||||
"nuxt-cloudflare-analytics": "^1.0.8",
|
||||
"nuxt-component-meta": "^0.6.3",
|
||||
"nuxt-og-image": "^2.2.4",
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
<hr v-if="surround?.length">
|
||||
|
||||
<UDocsSurround :surround="surround" />
|
||||
<UContentSurround :surround="surround" />
|
||||
</UPageBody>
|
||||
|
||||
<template v-if="page?.body?.toc?.links?.length" #right>
|
||||
<UDocsToc :links="page.body.toc.links">
|
||||
<UContentToc :links="page.body.toc.links">
|
||||
<template #bottom>
|
||||
<div class="hidden lg:block space-y-6 !mt-6">
|
||||
<UDivider v-if="page.body?.toc?.links?.length" type="dashed" />
|
||||
@@ -30,7 +30,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UDocsToc>
|
||||
</UContentToc>
|
||||
</template>
|
||||
</UPage>
|
||||
</template>
|
||||
|
||||
@@ -164,7 +164,13 @@
|
||||
</ULandingSection>
|
||||
|
||||
<template v-if="navigation.find(item => item._path === '/pro')">
|
||||
<ULandingHero id="pro" :links="page.pro.links" :ui="{ title: 'sm:text-6xl' }">
|
||||
<div class="relative">
|
||||
<UDivider class="absolute inset-x-0" />
|
||||
|
||||
<div class="w-full relative overflow-hidden h-px bg-gradient-to-r from-gray-800 via-primary-400 to-gray-800 max-w-5xl mx-auto" />
|
||||
</div>
|
||||
|
||||
<ULandingHero id="pro" :links="page.pro.links" :ui="{ title: 'sm:text-6xl' }" class="bg-gradient-to-b from-gray-50 dark:from-gray-950/50 to-white dark:to-gray-900 relative">
|
||||
<template #title>
|
||||
<span v-html="page.pro.title" />
|
||||
</template>
|
||||
@@ -173,11 +179,13 @@
|
||||
<span v-html="page.pro.description" />
|
||||
</template>
|
||||
|
||||
<video poster="https://res.cloudinary.com/nuxt/video/upload/so_14.8/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg" controls class="rounded-lg">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.webm" type="video/webm">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.mp4" type="video/mp4">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.ogg" type="video/ogg">
|
||||
</video>
|
||||
<div class="bg-gray-900/5 dark:bg-white/5 ring-1 ring-inset ring-gray-900/10 dark:ring-white/10 rounded-xl lg:-m-4 p-4">
|
||||
<video poster="https://res.cloudinary.com/nuxt/video/upload/so_3.3/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg" controls class="rounded-lg">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.webm" type="video/webm">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.mp4" type="video/mp4">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.ogg" type="video/ogg">
|
||||
</video>
|
||||
</div>
|
||||
</ULandingHero>
|
||||
|
||||
<ULandingSection v-for="(section, index) in page.pro.sections" :key="index" v-bind="section" class="!pt-0">
|
||||
@@ -246,7 +254,7 @@
|
||||
</template>
|
||||
|
||||
<template #aside-top>
|
||||
<UDocsSearchButton size="md" class="w-full" />
|
||||
<UContentSearchButton size="md" class="w-full" />
|
||||
</template>
|
||||
|
||||
<template #aside-default>
|
||||
@@ -275,7 +283,7 @@
|
||||
</template>
|
||||
|
||||
<template #docs-surround>
|
||||
<UDocsSurround
|
||||
<UContentSurround
|
||||
:surround="(surround as unknown as ParsedContent[])"
|
||||
class="w-full gap-4"
|
||||
:ui="{
|
||||
@@ -294,7 +302,7 @@
|
||||
|
||||
<template #docs-toc>
|
||||
<div class="absolute top-0 left-0 right-0 space-y-3">
|
||||
<UDocsToc :links="toc" class="bg-transparent relative max-h-full overflow-hidden top-0" :ui="({ container: { base: '!pt-0 !pb-4' } } as any)" />
|
||||
<UContentToc :links="toc" class="bg-transparent relative max-h-full overflow-hidden top-0" :ui="({ container: { base: '!pt-0 !pb-4' } } as any)" />
|
||||
|
||||
<UDivider type="dashed" :ui="{ border: { base: 'border-gray-800/10 dark:border-gray-200/10' } }" />
|
||||
|
||||
@@ -612,8 +620,8 @@ const docsBlocks = computed(() => [isAfterStep(steps.docs) && {
|
||||
slot: 'docs-surround',
|
||||
class: 'bottom-4 inset-x-4 h-28'
|
||||
} : {
|
||||
name: 'UDocsSurround',
|
||||
to: '/pro/components/docs-surround',
|
||||
name: 'UContentSurround',
|
||||
to: '/pro/components/content-surround',
|
||||
class: 'bottom-4 inset-x-4 h-28',
|
||||
inactive: false
|
||||
}]
|
||||
@@ -621,8 +629,8 @@ const docsBlocks = computed(() => [isAfterStep(steps.docs) && {
|
||||
name: '#default',
|
||||
class: 'left-4 right-72 inset-y-4'
|
||||
}]), isAfterStep(steps.docs + 13) ? {
|
||||
name: 'UDocsToc',
|
||||
to: '/pro/components/docs-toc',
|
||||
name: 'UContentToc',
|
||||
to: '/pro/components/content-toc',
|
||||
class: 'right-4 inset-y-4 w-64',
|
||||
inactive: isAfterStep(steps.docs + 14),
|
||||
children: [{
|
||||
|
||||
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nuxt/ui",
|
||||
"version": "2.14.0",
|
||||
"version": "2.14.1",
|
||||
"repository": "nuxt/ui",
|
||||
"homepage": "https://ui.nuxt.com",
|
||||
"type": "module",
|
||||
@@ -37,7 +37,7 @@
|
||||
"@headlessui/tailwindcss": "^0.2.0",
|
||||
"@headlessui/vue": "^1.7.19",
|
||||
"@iconify-json/heroicons": "^1.1.20",
|
||||
"@nuxt/kit": "^3.10.2",
|
||||
"@nuxt/kit": "^3.10.3",
|
||||
"@nuxtjs/color-mode": "^3.3.2",
|
||||
"@nuxtjs/tailwindcss": "^6.11.4",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
@@ -64,9 +64,9 @@
|
||||
"@release-it/conventional-changelog": "^8.0.1",
|
||||
"@vue/test-utils": "^2.4.4",
|
||||
"eslint": "^8.56.0",
|
||||
"happy-dom": "^13.3.8",
|
||||
"joi": "^17.12.1",
|
||||
"nuxt": "^3.10.2",
|
||||
"happy-dom": "^13.4.1",
|
||||
"joi": "^17.12.2",
|
||||
"nuxt": "^3.10.3",
|
||||
"release-it": "^17.1.1",
|
||||
"typescript": "^5.3.3",
|
||||
"unbuild": "^2.0.0",
|
||||
@@ -78,10 +78,10 @@
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"@nuxt/kit": "^3.10.2",
|
||||
"@nuxt/schema": "3.10.2",
|
||||
"@nuxt/kit": "3.10.3",
|
||||
"@nuxt/schema": "3.10.3",
|
||||
"tailwindcss": "3.4.1",
|
||||
"@headlessui/vue": "^1.7.19",
|
||||
"@headlessui/vue": "1.7.19",
|
||||
"vue": "3.4.19"
|
||||
}
|
||||
}
|
||||
|
||||
795
pnpm-lock.yaml
generated
795
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
import { omit } from './lodash'
|
||||
import { omit } from './runtime/utils/lodash'
|
||||
import { kebabCase, camelCase, upperFirst } from 'scule'
|
||||
|
||||
const colorsToExclude = [
|
||||
112
src/module.ts
112
src/module.ts
@@ -1,10 +1,22 @@
|
||||
import { createRequire } from 'node:module'
|
||||
import { defineNuxtModule, installModule, addComponentsDir, addImportsDir, createResolver, addPlugin } from '@nuxt/kit'
|
||||
import type { CollectionNames, IconsPluginOptions } from '@egoist/tailwindcss-icons'
|
||||
import { defaultExtractor as createDefaultExtractor } from 'tailwindcss/lib/lib/defaultExtractor.js'
|
||||
import { iconsPlugin, getIconCollections, type CollectionNames, type IconsPluginOptions } from '@egoist/tailwindcss-icons'
|
||||
import { name, version } from '../package.json'
|
||||
import createTemplates from './templates'
|
||||
import { generateSafelist, excludeColors, customSafelistExtractor } from './colors'
|
||||
import * as config from './runtime/ui.config'
|
||||
import type { DeepPartial, Strategy } from './runtime/types/utils'
|
||||
import installTailwind from './tailwind'
|
||||
|
||||
const defaultExtractor = createDefaultExtractor({ tailwindConfig: { separator: ':' } })
|
||||
const _require = createRequire(import.meta.url)
|
||||
const defaultColors = _require('tailwindcss/colors.js')
|
||||
|
||||
delete defaultColors.lightBlue
|
||||
delete defaultColors.warmGray
|
||||
delete defaultColors.trueGray
|
||||
delete defaultColors.coolGray
|
||||
delete defaultColors.blueGray
|
||||
|
||||
type UI = {
|
||||
primary?: string
|
||||
@@ -76,13 +88,107 @@ export default defineNuxtModule<ModuleOptions>({
|
||||
nuxt.options.css.push(resolve(runtimeDir, 'ui.css'))
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
nuxt.hook('tailwindcss:config', function (tailwindConfig) {
|
||||
tailwindConfig.theme = tailwindConfig.theme || {}
|
||||
tailwindConfig.theme.extend = tailwindConfig.theme.extend || {}
|
||||
tailwindConfig.theme.extend.colors = tailwindConfig.theme.extend.colors || {}
|
||||
|
||||
const globalColors: any = {
|
||||
...(tailwindConfig.theme.colors || defaultColors),
|
||||
...tailwindConfig.theme.extend?.colors
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
globalColors.primary = tailwindConfig.theme.extend.colors.primary = {
|
||||
50: 'rgb(var(--color-primary-50) / <alpha-value>)',
|
||||
100: 'rgb(var(--color-primary-100) / <alpha-value>)',
|
||||
200: 'rgb(var(--color-primary-200) / <alpha-value>)',
|
||||
300: 'rgb(var(--color-primary-300) / <alpha-value>)',
|
||||
400: 'rgb(var(--color-primary-400) / <alpha-value>)',
|
||||
500: 'rgb(var(--color-primary-500) / <alpha-value>)',
|
||||
600: 'rgb(var(--color-primary-600) / <alpha-value>)',
|
||||
700: 'rgb(var(--color-primary-700) / <alpha-value>)',
|
||||
800: 'rgb(var(--color-primary-800) / <alpha-value>)',
|
||||
900: 'rgb(var(--color-primary-900) / <alpha-value>)',
|
||||
950: 'rgb(var(--color-primary-950) / <alpha-value>)',
|
||||
DEFAULT: 'rgb(var(--color-primary-DEFAULT) / <alpha-value>)'
|
||||
}
|
||||
|
||||
if (globalColors.gray) {
|
||||
// @ts-ignore
|
||||
globalColors.cool = tailwindConfig.theme.extend.colors.cool = defaultColors.gray
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
globalColors.gray = tailwindConfig.theme.extend.colors.gray = {
|
||||
50: 'rgb(var(--color-gray-50) / <alpha-value>)',
|
||||
100: 'rgb(var(--color-gray-100) / <alpha-value>)',
|
||||
200: 'rgb(var(--color-gray-200) / <alpha-value>)',
|
||||
300: 'rgb(var(--color-gray-300) / <alpha-value>)',
|
||||
400: 'rgb(var(--color-gray-400) / <alpha-value>)',
|
||||
500: 'rgb(var(--color-gray-500) / <alpha-value>)',
|
||||
600: 'rgb(var(--color-gray-600) / <alpha-value>)',
|
||||
700: 'rgb(var(--color-gray-700) / <alpha-value>)',
|
||||
800: 'rgb(var(--color-gray-800) / <alpha-value>)',
|
||||
900: 'rgb(var(--color-gray-900) / <alpha-value>)',
|
||||
950: 'rgb(var(--color-gray-950) / <alpha-value>)'
|
||||
}
|
||||
|
||||
const colors = excludeColors(globalColors)
|
||||
|
||||
// @ts-ignore
|
||||
nuxt.options.appConfig.ui = {
|
||||
primary: 'green',
|
||||
gray: 'cool',
|
||||
colors,
|
||||
strategy: 'merge'
|
||||
}
|
||||
|
||||
tailwindConfig.safelist = tailwindConfig.safelist || []
|
||||
tailwindConfig.safelist.push(...generateSafelist(options.safelistColors || [], colors))
|
||||
})
|
||||
|
||||
createTemplates(nuxt)
|
||||
|
||||
// Modules
|
||||
|
||||
await installModule('nuxt-icon')
|
||||
await installModule('@nuxtjs/color-mode', { classSuffix: '' })
|
||||
await installTailwind(options, nuxt, { resolve, runtimeDir })
|
||||
await installModule('@nuxtjs/tailwindcss', {
|
||||
exposeConfig: true,
|
||||
config: {
|
||||
darkMode: 'class',
|
||||
plugins: [
|
||||
require('@tailwindcss/forms')({ strategy: 'class' }),
|
||||
require('@tailwindcss/aspect-ratio'),
|
||||
require('@tailwindcss/typography'),
|
||||
require('@tailwindcss/container-queries'),
|
||||
require('@headlessui/tailwindcss'),
|
||||
iconsPlugin(Array.isArray(options.icons) || options.icons === 'all' ? { collections: getIconCollections(options.icons) } : typeof options.icons === 'object' ? options.icons as IconsPluginOptions : {})
|
||||
],
|
||||
content: {
|
||||
files: [
|
||||
resolve(runtimeDir, 'components/**/*.{vue,mjs,ts}'),
|
||||
resolve(runtimeDir, 'ui.config/**/*.{mjs,js,ts}')
|
||||
],
|
||||
transform: {
|
||||
vue: (content) => {
|
||||
return content.replaceAll(/(?:\r\n|\r|\n)/g, ' ')
|
||||
}
|
||||
},
|
||||
extract: {
|
||||
vue: (content) => {
|
||||
return [
|
||||
...defaultExtractor(content),
|
||||
// @ts-ignore
|
||||
...customSafelistExtractor(options.prefix, content, nuxt.options.appConfig.ui.colors, options.safelistColors)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Plugins
|
||||
|
||||
|
||||
135
src/tailwind.ts
135
src/tailwind.ts
@@ -1,135 +0,0 @@
|
||||
import { createRequire } from 'node:module'
|
||||
import { join } from 'pathe'
|
||||
import { addTemplate, installModule, useNuxt } from '@nuxt/kit'
|
||||
import { excludeColors, generateSafelist } from './runtime/utils/colors'
|
||||
import type { ModuleOptions } from './module'
|
||||
|
||||
const _require = createRequire(import.meta.url)
|
||||
const defaultColors = _require('tailwindcss/colors.js')
|
||||
|
||||
delete defaultColors.lightBlue
|
||||
delete defaultColors.warmGray
|
||||
delete defaultColors.trueGray
|
||||
delete defaultColors.coolGray
|
||||
delete defaultColors.blueGray
|
||||
|
||||
export default async function installTailwind (moduleOptions: ModuleOptions, nuxt = useNuxt(), { resolve, runtimeDir }) {
|
||||
// 1. register hook
|
||||
// @ts-ignore
|
||||
nuxt.hook('tailwindcss:config', function (tailwindConfig) {
|
||||
tailwindConfig.theme = tailwindConfig.theme || {}
|
||||
tailwindConfig.theme.extend = tailwindConfig.theme.extend || {}
|
||||
tailwindConfig.theme.extend.colors =
|
||||
tailwindConfig.theme.extend.colors || {}
|
||||
|
||||
const globalColors: any = {
|
||||
...(tailwindConfig.theme.colors || defaultColors),
|
||||
...tailwindConfig.theme.extend?.colors
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
globalColors.primary = tailwindConfig.theme.extend.colors.primary = {
|
||||
50: 'rgb(var(--color-primary-50) / <alpha-value>)',
|
||||
100: 'rgb(var(--color-primary-100) / <alpha-value>)',
|
||||
200: 'rgb(var(--color-primary-200) / <alpha-value>)',
|
||||
300: 'rgb(var(--color-primary-300) / <alpha-value>)',
|
||||
400: 'rgb(var(--color-primary-400) / <alpha-value>)',
|
||||
500: 'rgb(var(--color-primary-500) / <alpha-value>)',
|
||||
600: 'rgb(var(--color-primary-600) / <alpha-value>)',
|
||||
700: 'rgb(var(--color-primary-700) / <alpha-value>)',
|
||||
800: 'rgb(var(--color-primary-800) / <alpha-value>)',
|
||||
900: 'rgb(var(--color-primary-900) / <alpha-value>)',
|
||||
950: 'rgb(var(--color-primary-950) / <alpha-value>)',
|
||||
DEFAULT: 'rgb(var(--color-primary-DEFAULT) / <alpha-value>)'
|
||||
}
|
||||
|
||||
if (globalColors.gray) {
|
||||
// @ts-ignore
|
||||
globalColors.cool = tailwindConfig.theme.extend.colors.cool =
|
||||
defaultColors.gray
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
globalColors.gray = tailwindConfig.theme.extend.colors.gray = {
|
||||
50: 'rgb(var(--color-gray-50) / <alpha-value>)',
|
||||
100: 'rgb(var(--color-gray-100) / <alpha-value>)',
|
||||
200: 'rgb(var(--color-gray-200) / <alpha-value>)',
|
||||
300: 'rgb(var(--color-gray-300) / <alpha-value>)',
|
||||
400: 'rgb(var(--color-gray-400) / <alpha-value>)',
|
||||
500: 'rgb(var(--color-gray-500) / <alpha-value>)',
|
||||
600: 'rgb(var(--color-gray-600) / <alpha-value>)',
|
||||
700: 'rgb(var(--color-gray-700) / <alpha-value>)',
|
||||
800: 'rgb(var(--color-gray-800) / <alpha-value>)',
|
||||
900: 'rgb(var(--color-gray-900) / <alpha-value>)',
|
||||
950: 'rgb(var(--color-gray-950) / <alpha-value>)'
|
||||
}
|
||||
|
||||
const colors = excludeColors(globalColors)
|
||||
|
||||
// @ts-ignore
|
||||
nuxt.options.appConfig.ui = {
|
||||
primary: 'green',
|
||||
gray: 'cool',
|
||||
colors,
|
||||
strategy: 'merge'
|
||||
}
|
||||
|
||||
tailwindConfig.safelist = tailwindConfig.safelist || []
|
||||
tailwindConfig.safelist.push(
|
||||
...generateSafelist(moduleOptions.safelistColors || [], colors)
|
||||
)
|
||||
})
|
||||
|
||||
// 2. add config template
|
||||
const configTemplate = addTemplate({
|
||||
filename: 'nuxtui-tailwind.config.cjs',
|
||||
write: true,
|
||||
getContents: () => `
|
||||
const { defaultExtractor: createDefaultExtractor } = require('tailwindcss/lib/lib/defaultExtractor.js')
|
||||
const { customSafelistExtractor } = require(${JSON.stringify(resolve(runtimeDir, 'utils', 'colors'))})
|
||||
const { iconsPlugin, getIconCollections } = require('@egoist/tailwindcss-icons')
|
||||
|
||||
const defaultExtractor = createDefaultExtractor({ tailwindConfig: { separator: ':' } })
|
||||
|
||||
module.exports = {
|
||||
darkMode: 'class',
|
||||
plugins: [
|
||||
require('@tailwindcss/forms')({ strategy: 'class' }),
|
||||
require('@tailwindcss/aspect-ratio'),
|
||||
require('@tailwindcss/typography'),
|
||||
require('@tailwindcss/container-queries'),
|
||||
require('@headlessui/tailwindcss'),
|
||||
iconsPlugin(${Array.isArray(moduleOptions.icons) || moduleOptions.icons === 'all' ? `{ collections: getIconCollections(${JSON.stringify(moduleOptions.icons)}) }` : typeof moduleOptions.icons === 'object' ? JSON.stringify(moduleOptions.icons) : '{}'})
|
||||
],
|
||||
content: {
|
||||
files: [
|
||||
${JSON.stringify(resolve(runtimeDir, 'components/**/*.{vue,mjs,ts}'))},
|
||||
${JSON.stringify(resolve(runtimeDir, 'ui.config/**/*.{mjs,js,ts}'))}
|
||||
],
|
||||
transform: {
|
||||
vue: (content) => {
|
||||
return content.replaceAll(/(?:\\r\\n|\\r|\\n)/g, ' ')
|
||||
}
|
||||
},
|
||||
extract: {
|
||||
vue: (content) => {
|
||||
return [
|
||||
...defaultExtractor(content),
|
||||
...customSafelistExtractor(${JSON.stringify(moduleOptions.prefix)}, content, ${JSON.stringify(nuxt.options.appConfig.ui.colors)}, ${JSON.stringify(moduleOptions.safelistColors)})
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
// 3. install module
|
||||
await installModule('@nuxtjs/tailwindcss', {
|
||||
exposeConfig: true,
|
||||
configPath: [
|
||||
configTemplate.dst,
|
||||
join(nuxt.options.rootDir, 'tailwind.config')
|
||||
]
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user