fix: 添加 StyleProvider 以支持 Tailwind 样式覆盖;移除 InputNumber 组件的宽度样式,优化组件适配;antdv 暂不支持
This commit is contained in:
@@ -726,9 +726,7 @@ async function initComponentAdapter() {
|
|||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
||||||
style: { width: '100%' },
|
|
||||||
}),
|
|
||||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||||
// 自定义主要按钮
|
// 自定义主要按钮
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { computed, watch } from 'vue';
|
|||||||
import { useAntdDesignTokens } from '@vben/hooks';
|
import { useAntdDesignTokens } from '@vben/hooks';
|
||||||
import { preferences, usePreferences } from '@vben/preferences';
|
import { preferences, usePreferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { App, ConfigProvider, theme } from 'antdv-next';
|
import { App, ConfigProvider, StyleProvider, theme } from 'antdv-next';
|
||||||
|
|
||||||
import { antdLocale } from '#/locales';
|
import { antdLocale } from '#/locales';
|
||||||
|
|
||||||
@@ -39,9 +39,12 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ConfigProvider :locale="antdLocale" :theme="tokenTheme">
|
<!-- layer: antd 组件样式注入 @layer antd,让 Tailwind 工具类可以覆盖组件样式 -->
|
||||||
<App>
|
<StyleProvider layer>
|
||||||
<RouterView />
|
<ConfigProvider :locale="antdLocale" :theme="tokenTheme">
|
||||||
</App>
|
<App>
|
||||||
</ConfigProvider>
|
<RouterView />
|
||||||
|
</App>
|
||||||
|
</ConfigProvider>
|
||||||
|
</StyleProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -284,9 +284,7 @@ async function initComponentAdapter() {
|
|||||||
inputComponent: ElInput,
|
inputComponent: ElInput,
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(ElInput, 'input'),
|
Input: withDefaultPlaceholder(ElInput, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(ElInputNumber, 'input', {
|
InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
|
||||||
style: { width: '100%' },
|
|
||||||
}),
|
|
||||||
RadioGroup: (props, { attrs, slots }) => {
|
RadioGroup: (props, { attrs, slots }) => {
|
||||||
let defaultSlot;
|
let defaultSlot;
|
||||||
if (Reflect.has(slots, 'default')) {
|
if (Reflect.has(slots, 'default')) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defineConfig } from '@vben/vite-config';
|
import { defineConfig, viteCssLayerPlugin } from '@vben/vite-config';
|
||||||
|
|
||||||
import ElementPlus from 'unplugin-element-plus/vite';
|
import ElementPlus from 'unplugin-element-plus/vite';
|
||||||
|
|
||||||
@@ -7,9 +7,9 @@ export default defineConfig(async () => {
|
|||||||
application: {},
|
application: {},
|
||||||
vite: {
|
vite: {
|
||||||
plugins: [
|
plugins: [
|
||||||
ElementPlus({
|
// element-plus 的 css 包进 @layer el,使 Tailwind 工具类可覆盖组件样式
|
||||||
format: 'esm',
|
viteCssLayerPlugin({ layerName: 'el', packageName: 'element-plus' }),
|
||||||
}),
|
ElementPlus({ format: 'esm' }),
|
||||||
],
|
],
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
|
|||||||
@@ -225,9 +225,7 @@ async function initComponentAdapter() {
|
|||||||
inputComponent: NInput,
|
inputComponent: NInput,
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(NInput, 'input'),
|
Input: withDefaultPlaceholder(NInput, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(NInputNumber, 'input', {
|
InputNumber: withDefaultPlaceholder(NInputNumber, 'input'),
|
||||||
style: { width: '100%' },
|
|
||||||
}),
|
|
||||||
RadioGroup: (props, { attrs, slots }) => {
|
RadioGroup: (props, { attrs, slots }) => {
|
||||||
let defaultSlot;
|
let defaultSlot;
|
||||||
if (Reflect.has(slots, 'default')) {
|
if (Reflect.has(slots, 'default')) {
|
||||||
|
|||||||
@@ -239,9 +239,7 @@ async function initComponentAdapter() {
|
|||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
||||||
style: { width: '100%' },
|
|
||||||
}),
|
|
||||||
// InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
// InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
// Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
// Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||||
// 自定义主要按钮
|
// 自定义主要按钮
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
import { defineConfig } from '@vben/vite-config';
|
import { defineConfig, viteCssLayerPlugin } from '@vben/vite-config';
|
||||||
|
|
||||||
export default defineConfig(async () => {
|
export default defineConfig(async () => {
|
||||||
return {
|
return {
|
||||||
application: {},
|
application: {},
|
||||||
vite: {
|
vite: {
|
||||||
|
plugins: [
|
||||||
|
// tdesign 的 css 包进 @layer td,使 Tailwind 工具类可覆盖组件样式
|
||||||
|
viteCssLayerPlugin({
|
||||||
|
layerName: 'td',
|
||||||
|
packageName: 'tdesign-vue-next',
|
||||||
|
}),
|
||||||
|
],
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 级联层顺序声明(必须先于 @import 'tailwindcss' 首次出现):
|
||||||
|
* preflight(base) < UI 库组件样式(antd / el / td) < Tailwind 工具类,
|
||||||
|
* 使组件库样式(antdv-next 经 StyleProvider layer 注入 @layer antd;
|
||||||
|
* element-plus / tdesign 经各自应用的 vite css-layer 插件包入对应层)
|
||||||
|
* 能被工具类覆盖
|
||||||
|
*/
|
||||||
|
@layer theme, base, ant, antd, el, td, components, utilities;
|
||||||
|
|
||||||
@import 'tailwindcss';
|
@import 'tailwindcss';
|
||||||
@import 'tw-animate-css';
|
@import 'tw-animate-css';
|
||||||
|
|
||||||
@@ -301,7 +310,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@apply text-foreground bg-background font-sans;
|
@apply bg-background font-sans text-foreground;
|
||||||
|
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
font-size: var(--font-size-base, 16px);
|
font-size: var(--font-size-base, 16px);
|
||||||
@@ -369,7 +378,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
@apply bg-border rounded-sm border-none;
|
@apply rounded-sm border-none bg-border;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
@@ -407,7 +416,7 @@
|
|||||||
* 见:https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layering */
|
* 见:https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layering */
|
||||||
@layer components {
|
@layer components {
|
||||||
.outline-box {
|
.outline-box {
|
||||||
@apply outline-border relative cursor-pointer rounded-md p-1 outline-1;
|
@apply relative cursor-pointer rounded-md p-1 outline-1 outline-border;
|
||||||
}
|
}
|
||||||
|
|
||||||
.outline-box::after {
|
.outline-box::after {
|
||||||
@@ -415,7 +424,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.outline-box.outline-box-active {
|
.outline-box.outline-box-active {
|
||||||
@apply outline-primary outline-2;
|
@apply outline-2 outline-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.outline-box.outline-box-active::after {
|
.outline-box.outline-box-active::after {
|
||||||
@@ -423,15 +432,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.outline-box:not(.outline-box-active):hover::after {
|
.outline-box:not(.outline-box-active):hover::after {
|
||||||
@apply outline-primary top-0 left-0 h-full w-full p-1 opacity-100;
|
@apply top-0 left-0 h-full w-full p-1 opacity-100 outline-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vben-link {
|
.vben-link {
|
||||||
@apply text-primary hover:text-primary-hover active:text-primary-active cursor-pointer;
|
@apply cursor-pointer text-primary hover:text-primary-hover active:text-primary-active;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-box {
|
.card-box {
|
||||||
@apply bg-card text-card-foreground border-border rounded-xl border;
|
@apply rounded-xl border border-border bg-card text-card-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
45
internal/vite-config/src/plugins/css-layer.ts
Normal file
45
internal/vite-config/src/plugins/css-layer.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import type { Plugin } from 'vite';
|
||||||
|
|
||||||
|
interface CssLayerRule {
|
||||||
|
/** 层名,需在 css 中先于 @import 'tailwindcss' 声明层顺序(见 internal/tailwind-config/theme.css) */
|
||||||
|
layerName: string;
|
||||||
|
/** 需要包层的包名(匹配该包在 node_modules 下的 css 模块 id) */
|
||||||
|
packageName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeRegExp(value: string): string {
|
||||||
|
return value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把指定包内的 css 包进 @layer:
|
||||||
|
* 组件库的 css 是无层样式,无层样式在级联中永远压过 @layer 内的 Tailwind 工具类;
|
||||||
|
* 包层后由 theme.css 的层声明决定顺序(utilities 排在组件库层之后),
|
||||||
|
* 使 Tailwind 工具类可以覆盖组件库样式。
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* plugins: [viteCssLayerPlugin({ packageName: 'element-plus', layerName: 'el' })]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function viteCssLayerPlugin(
|
||||||
|
rules: CssLayerRule | CssLayerRule[],
|
||||||
|
): Plugin {
|
||||||
|
const list = Array.isArray(rules) ? rules : [rules];
|
||||||
|
const matchers = list.map(({ layerName, packageName }) => ({
|
||||||
|
layerName,
|
||||||
|
regex: new RegExp(`${escapeRegExp(packageName)}[\\\\/].+\\.css$`, 'i'),
|
||||||
|
}));
|
||||||
|
return {
|
||||||
|
name: 'vite-plugin-css-layer',
|
||||||
|
enforce: 'pre',
|
||||||
|
transform(code, id) {
|
||||||
|
const [file] = id.split('?', 1);
|
||||||
|
if (!file) return;
|
||||||
|
const matched = matchers.find((m) => m.regex.test(file));
|
||||||
|
if (matched) {
|
||||||
|
return { code: `@layer ${matched.layerName} {\n${code}\n}`, map: null };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -248,6 +248,8 @@ async function loadLibraryPlugins(
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { viteCssLayerPlugin } from './css-layer';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
loadApplicationPlugins,
|
loadApplicationPlugins,
|
||||||
loadLibraryPlugins,
|
loadLibraryPlugins,
|
||||||
|
|||||||
@@ -726,9 +726,7 @@ async function initComponentAdapter() {
|
|||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
||||||
style: { width: '100%' },
|
|
||||||
}),
|
|
||||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||||
// 自定义主要按钮
|
// 自定义主要按钮
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { computed, watch } from 'vue';
|
|||||||
import { useAntdDesignTokens } from '@vben/hooks';
|
import { useAntdDesignTokens } from '@vben/hooks';
|
||||||
import { preferences, usePreferences } from '@vben/preferences';
|
import { preferences, usePreferences } from '@vben/preferences';
|
||||||
|
|
||||||
import { App, ConfigProvider, theme } from 'antdv-next';
|
import { App, ConfigProvider, StyleProvider, theme } from 'antdv-next';
|
||||||
|
|
||||||
import { antdLocale } from '#/locales';
|
import { antdLocale } from '#/locales';
|
||||||
|
|
||||||
@@ -39,9 +39,12 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ConfigProvider :locale="antdLocale" :theme="tokenTheme">
|
<!-- layer: antd 组件样式注入 @layer antd,让 Tailwind 工具类可以覆盖组件样式 -->
|
||||||
<App>
|
<StyleProvider layer>
|
||||||
<RouterView />
|
<ConfigProvider :locale="antdLocale" :theme="tokenTheme">
|
||||||
</App>
|
<App>
|
||||||
</ConfigProvider>
|
<RouterView />
|
||||||
|
</App>
|
||||||
|
</ConfigProvider>
|
||||||
|
</StyleProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user