chore: Optimize multi-theme switching
parent
aa53353903
commit
6afed34437
|
@ -38,7 +38,6 @@
|
||||||
"@vben/styles": "workspace:*",
|
"@vben/styles": "workspace:*",
|
||||||
"@vben/types": "workspace:*",
|
"@vben/types": "workspace:*",
|
||||||
"@vben/universal-ui": "workspace:*",
|
"@vben/universal-ui": "workspace:*",
|
||||||
"@vben/chart-ui": "workspace:*",
|
|
||||||
"@vben/utils": "workspace:*",
|
"@vben/utils": "workspace:*",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"ant-design-vue": "^4.2.3",
|
"ant-design-vue": "^4.2.3",
|
||||||
|
|
|
@ -42,3 +42,50 @@ const tokenTheme = computed(() => {
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</GlobalProvider>
|
</GlobalProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- <style>
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 240 10% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 240 10% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 240 10% 3.9%;
|
||||||
|
--primary: 240 5.9% 10%;
|
||||||
|
--primary-foreground: 0 0% 98%;
|
||||||
|
--secondary: 240 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 240 5.9% 10%;
|
||||||
|
--muted: 240 4.8% 95.9%;
|
||||||
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
|
--accent: 240 4.8% 95.9%;
|
||||||
|
--accent-foreground: 240 5.9% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 5.9% 90%;
|
||||||
|
--input: 240 5.9% 90%;
|
||||||
|
--ring: 240 5.9% 10%;
|
||||||
|
--radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: 240 10% 3.9%;
|
||||||
|
--foreground: 0 0% 98%;
|
||||||
|
--card: 240 10% 3.9%;
|
||||||
|
--card-foreground: 0 0% 98%;
|
||||||
|
--popover: 240 10% 3.9%;
|
||||||
|
--popover-foreground: 0 0% 98%;
|
||||||
|
--primary: 0 0% 98%;
|
||||||
|
--primary-foreground: 240 5.9% 10%;
|
||||||
|
--secondary: 240 3.7% 15.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 240 3.7% 15.9%;
|
||||||
|
--muted-foreground: 240 5% 64.9%;
|
||||||
|
--accent: 240 3.7% 15.9%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 3.7% 15.9%;
|
||||||
|
--input: 240 3.7% 15.9%;
|
||||||
|
--ring: 240 4.9% 83.9%;
|
||||||
|
}
|
||||||
|
</style> -->
|
||||||
|
|
|
@ -1,249 +1,251 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
// import { ref } from 'vue';
|
||||||
|
|
||||||
|
// import { echartsInstance as echarts } from '@vben/chart-ui';
|
||||||
|
|
||||||
defineOptions({ name: 'WelCome' });
|
defineOptions({ name: 'WelCome' });
|
||||||
import { Dashboard } from '@vben/universal-ui';
|
|
||||||
import { echartsInstance as echarts } from '@vben/chart-ui';
|
|
||||||
const cardList = ref([
|
|
||||||
{
|
|
||||||
title: '访问数',
|
|
||||||
extra: '月',
|
|
||||||
leftContent: '2000',
|
|
||||||
rightContent: 'flat-color-icons:conference-call',
|
|
||||||
leftFooter: '总访问数',
|
|
||||||
color: 'green',
|
|
||||||
rightFooter: '5000',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '销售额',
|
|
||||||
extra: '日',
|
|
||||||
leftContent: '$1350',
|
|
||||||
rightContent: 'flat-color-icons:sales-performance',
|
|
||||||
leftFooter: '总销售额',
|
|
||||||
color: 'red',
|
|
||||||
rightFooter: '$550000',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const chartTabs = ref([
|
|
||||||
{
|
|
||||||
name: '1',
|
|
||||||
title: '流量趋势',
|
|
||||||
option: {
|
|
||||||
color: ['#80FFA5', '#00DDFF', '#37A2FF', '#FF0087', '#FFBF00'],
|
|
||||||
|
|
||||||
tooltip: {
|
// const cardList = ref([
|
||||||
trigger: 'axis',
|
// {
|
||||||
axisPointer: {
|
// color: 'green',
|
||||||
type: 'cross',
|
// extra: '月',
|
||||||
// label: {
|
// leftContent: '2000',
|
||||||
// backgroundColor: '#6a7985',
|
// leftFooter: '总访问数',
|
||||||
// },
|
// rightContent: 'flat-color-icons:conference-call',
|
||||||
},
|
// rightFooter: '5000',
|
||||||
},
|
// title: '访问数',
|
||||||
legend: {
|
// },
|
||||||
data: ['Line 1', 'Line 2', 'Line 3', 'Line 4', 'Line 5'],
|
// {
|
||||||
},
|
// color: 'red',
|
||||||
toolbox: {
|
// extra: '日',
|
||||||
feature: {
|
// leftContent: '$1350',
|
||||||
saveAsImage: {},
|
// leftFooter: '总销售额',
|
||||||
},
|
// rightContent: 'flat-color-icons:sales-performance',
|
||||||
},
|
// rightFooter: '$550000',
|
||||||
grid: {
|
// title: '销售额',
|
||||||
left: '3%',
|
// },
|
||||||
right: '4%',
|
// ]);
|
||||||
bottom: '3%',
|
// const chartTabs = ref([
|
||||||
containLabel: true,
|
// {
|
||||||
},
|
// name: '1',
|
||||||
xAxis: [
|
// option: {
|
||||||
{
|
// color: ['#80FFA5', '#00DDFF', '#37A2FF', '#FF0087', '#FFBF00'],
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
// grid: {
|
||||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
// bottom: '3%',
|
||||||
},
|
// containLabel: true,
|
||||||
],
|
// left: '3%',
|
||||||
yAxis: [
|
// right: '4%',
|
||||||
{
|
// },
|
||||||
type: 'value',
|
// legend: {
|
||||||
},
|
// data: ['Line 1', 'Line 2', 'Line 3', 'Line 4', 'Line 5'],
|
||||||
],
|
// },
|
||||||
series: [
|
// series: [
|
||||||
{
|
// {
|
||||||
name: 'Line 1',
|
// areaStyle: {
|
||||||
type: 'line',
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
stack: 'Total',
|
// {
|
||||||
smooth: true,
|
// color: 'rgb(128, 255, 165)',
|
||||||
lineStyle: {
|
// offset: 0,
|
||||||
width: 0,
|
// },
|
||||||
},
|
// {
|
||||||
showSymbol: false,
|
// color: 'rgb(1, 191, 236)',
|
||||||
areaStyle: {
|
// offset: 1,
|
||||||
opacity: 0.8,
|
// },
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
// ]),
|
||||||
{
|
// opacity: 0.8,
|
||||||
offset: 0,
|
// },
|
||||||
color: 'rgb(128, 255, 165)',
|
// data: [140, 232, 101, 264, 90, 340, 250],
|
||||||
},
|
// emphasis: {
|
||||||
{
|
// focus: 'series',
|
||||||
offset: 1,
|
// },
|
||||||
color: 'rgb(1, 191, 236)',
|
// lineStyle: {
|
||||||
},
|
// width: 0,
|
||||||
]),
|
// },
|
||||||
},
|
// name: 'Line 1',
|
||||||
emphasis: {
|
// showSymbol: false,
|
||||||
focus: 'series',
|
// smooth: true,
|
||||||
},
|
// stack: 'Total',
|
||||||
data: [140, 232, 101, 264, 90, 340, 250],
|
// type: 'line',
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: 'Line 2',
|
// areaStyle: {
|
||||||
type: 'line',
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
stack: 'Total',
|
// {
|
||||||
smooth: true,
|
// color: 'rgb(0, 221, 255)',
|
||||||
lineStyle: {
|
// offset: 0,
|
||||||
width: 0,
|
// },
|
||||||
},
|
// {
|
||||||
showSymbol: false,
|
// color: 'rgb(77, 119, 255)',
|
||||||
areaStyle: {
|
// offset: 1,
|
||||||
opacity: 0.8,
|
// },
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
// ]),
|
||||||
{
|
// opacity: 0.8,
|
||||||
offset: 0,
|
// },
|
||||||
color: 'rgb(0, 221, 255)',
|
// data: [120, 282, 111, 234, 220, 340, 310],
|
||||||
},
|
// emphasis: {
|
||||||
{
|
// focus: 'series',
|
||||||
offset: 1,
|
// },
|
||||||
color: 'rgb(77, 119, 255)',
|
// lineStyle: {
|
||||||
},
|
// width: 0,
|
||||||
]),
|
// },
|
||||||
},
|
// name: 'Line 2',
|
||||||
emphasis: {
|
// showSymbol: false,
|
||||||
focus: 'series',
|
// smooth: true,
|
||||||
},
|
// stack: 'Total',
|
||||||
data: [120, 282, 111, 234, 220, 340, 310],
|
// type: 'line',
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: 'Line 3',
|
// areaStyle: {
|
||||||
type: 'line',
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
stack: 'Total',
|
// {
|
||||||
smooth: true,
|
// color: 'rgb(55, 162, 255)',
|
||||||
lineStyle: {
|
// offset: 0,
|
||||||
width: 0,
|
// },
|
||||||
},
|
// {
|
||||||
showSymbol: false,
|
// color: 'rgb(116, 21, 219)',
|
||||||
areaStyle: {
|
// offset: 1,
|
||||||
opacity: 0.8,
|
// },
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
// ]),
|
||||||
{
|
// opacity: 0.8,
|
||||||
offset: 0,
|
// },
|
||||||
color: 'rgb(55, 162, 255)',
|
// data: [320, 132, 201, 334, 190, 130, 220],
|
||||||
},
|
// emphasis: {
|
||||||
{
|
// focus: 'series',
|
||||||
offset: 1,
|
// },
|
||||||
color: 'rgb(116, 21, 219)',
|
// lineStyle: {
|
||||||
},
|
// width: 0,
|
||||||
]),
|
// },
|
||||||
},
|
// name: 'Line 3',
|
||||||
emphasis: {
|
// showSymbol: false,
|
||||||
focus: 'series',
|
// smooth: true,
|
||||||
},
|
// stack: 'Total',
|
||||||
data: [320, 132, 201, 334, 190, 130, 220],
|
// type: 'line',
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: 'Line 4',
|
// areaStyle: {
|
||||||
type: 'line',
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
stack: 'Total',
|
// {
|
||||||
smooth: true,
|
// color: 'rgb(255, 0, 135)',
|
||||||
lineStyle: {
|
// offset: 0,
|
||||||
width: 0,
|
// },
|
||||||
},
|
// {
|
||||||
showSymbol: false,
|
// color: 'rgb(135, 0, 157)',
|
||||||
areaStyle: {
|
// offset: 1,
|
||||||
opacity: 0.8,
|
// },
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
// ]),
|
||||||
{
|
// opacity: 0.8,
|
||||||
offset: 0,
|
// },
|
||||||
color: 'rgb(255, 0, 135)',
|
// data: [220, 402, 231, 134, 190, 230, 120],
|
||||||
},
|
// emphasis: {
|
||||||
{
|
// focus: 'series',
|
||||||
offset: 1,
|
// },
|
||||||
color: 'rgb(135, 0, 157)',
|
// lineStyle: {
|
||||||
},
|
// width: 0,
|
||||||
]),
|
// },
|
||||||
},
|
// name: 'Line 4',
|
||||||
emphasis: {
|
// showSymbol: false,
|
||||||
focus: 'series',
|
// smooth: true,
|
||||||
},
|
// stack: 'Total',
|
||||||
data: [220, 402, 231, 134, 190, 230, 120],
|
// type: 'line',
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
name: 'Line 5',
|
// areaStyle: {
|
||||||
type: 'line',
|
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
stack: 'Total',
|
// {
|
||||||
smooth: true,
|
// color: 'rgb(255, 191, 0)',
|
||||||
lineStyle: {
|
// offset: 0,
|
||||||
width: 0,
|
// },
|
||||||
},
|
// {
|
||||||
showSymbol: false,
|
// color: 'rgb(224, 62, 76)',
|
||||||
label: {
|
// offset: 1,
|
||||||
show: true,
|
// },
|
||||||
position: 'top',
|
// ]),
|
||||||
},
|
// opacity: 0.8,
|
||||||
areaStyle: {
|
// },
|
||||||
opacity: 0.8,
|
// data: [220, 302, 181, 234, 210, 290, 150],
|
||||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
// emphasis: {
|
||||||
{
|
// focus: 'series',
|
||||||
offset: 0,
|
// },
|
||||||
color: 'rgb(255, 191, 0)',
|
// label: {
|
||||||
},
|
// position: 'top',
|
||||||
{
|
// show: true,
|
||||||
offset: 1,
|
// },
|
||||||
color: 'rgb(224, 62, 76)',
|
// lineStyle: {
|
||||||
},
|
// width: 0,
|
||||||
]),
|
// },
|
||||||
},
|
// name: 'Line 5',
|
||||||
emphasis: {
|
// showSymbol: false,
|
||||||
focus: 'series',
|
// smooth: true,
|
||||||
},
|
// stack: 'Total',
|
||||||
data: [220, 302, 181, 234, 210, 290, 150],
|
// type: 'line',
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// toolbox: {
|
||||||
},
|
// feature: {
|
||||||
{
|
// saveAsImage: {},
|
||||||
name: '2',
|
// },
|
||||||
title: '访问量',
|
// },
|
||||||
option: {
|
// tooltip: {
|
||||||
xAxis: {
|
// axisPointer: {
|
||||||
type: 'category',
|
// type: 'cross',
|
||||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
// // label: {
|
||||||
},
|
// // backgroundColor: '#6a7985',
|
||||||
yAxis: {
|
// // },
|
||||||
type: 'value',
|
// },
|
||||||
},
|
// trigger: 'axis',
|
||||||
series: [
|
// },
|
||||||
{
|
// xAxis: [
|
||||||
data: [
|
// {
|
||||||
120,
|
// boundaryGap: false,
|
||||||
{
|
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||||
value: 200,
|
// type: 'category',
|
||||||
itemStyle: {
|
// },
|
||||||
color: '#a90000',
|
// ],
|
||||||
},
|
// yAxis: [
|
||||||
},
|
// {
|
||||||
150,
|
// type: 'value',
|
||||||
80,
|
// },
|
||||||
70,
|
// ],
|
||||||
110,
|
// },
|
||||||
130,
|
// title: '流量趋势',
|
||||||
],
|
// },
|
||||||
type: 'bar',
|
// {
|
||||||
},
|
// name: '2',
|
||||||
],
|
// option: {
|
||||||
},
|
// series: [
|
||||||
},
|
// {
|
||||||
]);
|
// data: [
|
||||||
|
// 120,
|
||||||
|
// {
|
||||||
|
// itemStyle: {
|
||||||
|
// color: '#a90000',
|
||||||
|
// },
|
||||||
|
// value: 200,
|
||||||
|
// },
|
||||||
|
// 150,
|
||||||
|
// 80,
|
||||||
|
// 70,
|
||||||
|
// 110,
|
||||||
|
// 130,
|
||||||
|
// ],
|
||||||
|
// type: 'bar',
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// xAxis: {
|
||||||
|
// data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||||
|
// type: 'category',
|
||||||
|
// },
|
||||||
|
// yAxis: {
|
||||||
|
// type: 'value',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// title: '访问量',
|
||||||
|
// },
|
||||||
|
// ]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dashboard :cardList="cardList" :chartTabs="chartTabs"></Dashboard>
|
<div>dashboard</div>
|
||||||
|
<!-- <Dashboard :card-list="cardList" :chart-tabs="chartTabs" /> -->
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.5.0",
|
"@eslint/js": "^9.5.0",
|
||||||
"@types/eslint": "^8.56.10",
|
"@types/eslint": "^8.56.10",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||||
"@typescript-eslint/parser": "^7.13.1",
|
"@typescript-eslint/parser": "^7.14.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||||
|
|
|
@ -24,6 +24,31 @@ packages.forEach((pkg) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function createColorsPattern(name: string) {
|
||||||
|
return {
|
||||||
|
100: `hsl(var(--${name}-100))`,
|
||||||
|
200: `hsl(var(--${name}-200))`,
|
||||||
|
300: `hsl(var(--${name}-300))`,
|
||||||
|
400: `hsl(var(--${name}-400))`,
|
||||||
|
500: `hsl(var(--${name}-500))`,
|
||||||
|
600: `hsl(var(--${name}-600))`,
|
||||||
|
700: `hsl(var(--${name}-700))`,
|
||||||
|
800: `hsl(var(--${name}-800))`,
|
||||||
|
900: `hsl(var(--${name}-900))`,
|
||||||
|
1000: `hsl(var(--${name}-1000))`,
|
||||||
|
active: `hsl(var(--${name}-700))`,
|
||||||
|
background: `hsl(var(--${name}-100))`,
|
||||||
|
'background-hover': `hsl(var(--${name}-200))`,
|
||||||
|
border: `hsl(var(--${name}-300))`,
|
||||||
|
'border-hover': `hsl(var(--${name}-400))`,
|
||||||
|
foreground: `hsl(var(--${name}-foreground))`,
|
||||||
|
hover: `hsl(var(--${name}-500))`,
|
||||||
|
text: `hsl(var(--${name}-900))`,
|
||||||
|
'text-active': `hsl(var(--${name}-1000))`,
|
||||||
|
'text-hover': `hsl(var(--${name}-800))`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
content: [
|
content: [
|
||||||
'./index.html',
|
'./index.html',
|
||||||
|
@ -73,17 +98,23 @@ export default {
|
||||||
foreground: 'hsl(var(--accent-foreground))',
|
foreground: 'hsl(var(--accent-foreground))',
|
||||||
hover: 'hsl(var(--accent-hover))',
|
hover: 'hsl(var(--accent-hover))',
|
||||||
},
|
},
|
||||||
|
authentication: 'hsl(var(--authentication))',
|
||||||
background: 'hsl(var(--background))',
|
background: 'hsl(var(--background))',
|
||||||
border: 'hsl(var(--border))',
|
border: 'hsl(var(--border))',
|
||||||
card: {
|
card: {
|
||||||
DEFAULT: 'hsl(var(--card))',
|
DEFAULT: 'hsl(var(--card))',
|
||||||
foreground: 'hsl(var(--card-foreground))',
|
foreground: 'hsl(var(--card-foreground))',
|
||||||
},
|
},
|
||||||
|
|
||||||
destructive: {
|
destructive: {
|
||||||
|
...createColorsPattern('destructive'),
|
||||||
DEFAULT: 'hsl(var(--destructive))',
|
DEFAULT: 'hsl(var(--destructive))',
|
||||||
foreground: 'hsl(var(--destructive-foreground))',
|
|
||||||
},
|
},
|
||||||
foreground: 'hsl(var(--foreground) / <alpha-value>)',
|
foreground: 'hsl(var(--foreground))',
|
||||||
|
green: {
|
||||||
|
...createColorsPattern('green'),
|
||||||
|
foreground: 'hsl(var(--success-foreground))',
|
||||||
|
},
|
||||||
heavy: {
|
heavy: {
|
||||||
DEFAULT: 'hsl(var(--heavy))',
|
DEFAULT: 'hsl(var(--heavy))',
|
||||||
foreground: 'hsl(var(--heavy-foreground))',
|
foreground: 'hsl(var(--heavy-foreground))',
|
||||||
|
@ -102,21 +133,30 @@ export default {
|
||||||
foreground: 'hsl(var(--popover-foreground))',
|
foreground: 'hsl(var(--popover-foreground))',
|
||||||
},
|
},
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
|
...createColorsPattern('primary'),
|
||||||
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)',
|
DEFAULT: 'hsl(var(--primary))',
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
...createColorsPattern('red'),
|
||||||
|
foreground: 'hsl(var(--destructive-foreground))',
|
||||||
},
|
},
|
||||||
ring: 'hsl(var(--ring))',
|
ring: 'hsl(var(--ring))',
|
||||||
secondary: {
|
secondary: {
|
||||||
DEFAULT: 'hsl(var(--secondary) / <alpha-value>)',
|
DEFAULT: 'hsl(var(--secondary))',
|
||||||
desc: 'hsl(var(--secondary-desc) / <alpha-value>)',
|
desc: 'hsl(var(--secondary-desc))',
|
||||||
foreground: 'hsl(var(--secondary-foreground) / <alpha-value>)',
|
foreground: 'hsl(var(--secondary-foreground))',
|
||||||
},
|
},
|
||||||
|
|
||||||
success: {
|
success: {
|
||||||
|
...createColorsPattern('success'),
|
||||||
DEFAULT: 'hsl(var(--success))',
|
DEFAULT: 'hsl(var(--success))',
|
||||||
foreground: 'hsl(var(--success-foreground))',
|
|
||||||
},
|
},
|
||||||
warning: {
|
warning: {
|
||||||
|
...createColorsPattern('warning'),
|
||||||
DEFAULT: 'hsl(var(--warning))',
|
DEFAULT: 'hsl(var(--warning))',
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
...createColorsPattern('yellow'),
|
||||||
foreground: 'hsl(var(--warning-foreground))',
|
foreground: 'hsl(var(--warning-foreground))',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
"rollup": "^4.18.0",
|
"rollup": "^4.18.0",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"sass": "^1.77.6",
|
"sass": "^1.77.6",
|
||||||
"unplugin-turbo-console": "^1.8.6",
|
"unplugin-turbo-console": "^1.8.7",
|
||||||
"vite": "^5.3.1",
|
"vite": "^5.3.1",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-dts": "^3.9.1",
|
"vite-plugin-dts": "^3.9.1",
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"@changesets/cli": "^2.27.6",
|
"@changesets/cli": "^2.27.6",
|
||||||
"@ls-lint/ls-lint": "^2.2.3",
|
"@ls-lint/ls-lint": "^2.2.3",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/node": "^20.14.8",
|
"@types/node": "^20.14.9",
|
||||||
"@vben/commitlint-config": "workspace:*",
|
"@vben/commitlint-config": "workspace:*",
|
||||||
"@vben/eslint-config": "workspace:*",
|
"@vben/eslint-config": "workspace:*",
|
||||||
"@vben/lint-staged-config": "workspace:*",
|
"@vben/lint-staged-config": "workspace:*",
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
"jsdom": "^24.1.0",
|
"jsdom": "^24.1.0",
|
||||||
"rimraf": "^5.0.7",
|
"rimraf": "^5.0.7",
|
||||||
"taze": "^0.13.8",
|
"taze": "^0.13.8",
|
||||||
"turbo": "^2.0.4",
|
"turbo": "^2.0.5",
|
||||||
"typescript": "^5.5.2",
|
"typescript": "^5.5.2",
|
||||||
"unbuild": "^2.0.0",
|
"unbuild": "^2.0.0",
|
||||||
"vite": "^5.3.1",
|
"vite": "^5.3.1",
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vben-core/cache": "workspace:*",
|
"@vben-core/cache": "workspace:*",
|
||||||
|
"@vben-core/colorful": "workspace:*",
|
||||||
"@vben-core/toolkit": "workspace:*",
|
"@vben-core/toolkit": "workspace:*",
|
||||||
"@vben-core/typings": "workspace:*",
|
"@vben-core/typings": "workspace:*",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
|
|
|
@ -18,7 +18,6 @@ const defaultPreferences: Preferences = {
|
||||||
name: 'Vben Admin Pro',
|
name: 'Vben Admin Pro',
|
||||||
semiDarkMenu: true,
|
semiDarkMenu: true,
|
||||||
showPreference: true,
|
showPreference: true,
|
||||||
themeMode: 'dark',
|
|
||||||
},
|
},
|
||||||
breadcrumb: {
|
breadcrumb: {
|
||||||
enable: true,
|
enable: true,
|
||||||
|
@ -67,7 +66,13 @@ const defaultPreferences: Preferences = {
|
||||||
showIcon: true,
|
showIcon: true,
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
colorPrimary: 'hsl(211 91% 39%)',
|
builtinType: 'default',
|
||||||
|
colorDestructive: 'hsl(348 100% 61%)',
|
||||||
|
colorPrimary: 'hsl(245 82% 67%)',
|
||||||
|
colorSuccess: 'hsl(144 57% 58%)',
|
||||||
|
colorWarning: 'hsl(42 84% 61%)',
|
||||||
|
mode: 'dark',
|
||||||
|
radius: '0.5',
|
||||||
},
|
},
|
||||||
transition: {
|
transition: {
|
||||||
enable: true,
|
enable: true,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { BuiltinThemeType } from '@vben-core/typings';
|
||||||
|
|
||||||
import type { SupportedLanguagesType } from './types';
|
import type { SupportedLanguagesType } from './types';
|
||||||
|
|
||||||
interface Language {
|
interface Language {
|
||||||
|
@ -5,17 +7,17 @@ interface Language {
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const COLOR_PRIMARY_RESETS = [
|
interface BuiltinThemePreset {
|
||||||
'hsl(211 91% 39%)',
|
color: string;
|
||||||
'hsl(212 100% 45%)',
|
darkPrimaryColor?: string;
|
||||||
'hsl(181 84% 32%)',
|
primaryColor?: string;
|
||||||
'hsl(161 90% 43%)',
|
type: BuiltinThemeType;
|
||||||
'hsl(231 98% 65%)',
|
}
|
||||||
'hsl(245 82% 67%)',
|
|
||||||
'hsl(347 77% 60%)',
|
|
||||||
];
|
|
||||||
|
|
||||||
export const SUPPORT_LANGUAGES: Language[] = [
|
/**
|
||||||
|
* Supported languages
|
||||||
|
*/
|
||||||
|
const SUPPORT_LANGUAGES: Language[] = [
|
||||||
{
|
{
|
||||||
key: 'zh-CN',
|
key: 'zh-CN',
|
||||||
text: '简体中文',
|
text: '简体中文',
|
||||||
|
@ -25,3 +27,80 @@ export const SUPPORT_LANGUAGES: Language[] = [
|
||||||
text: 'English',
|
text: 'English',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const BUILT_IN_THEME_PRESETS: BuiltinThemePreset[] = [
|
||||||
|
{
|
||||||
|
color: 'hsl(245 82% 67%)',
|
||||||
|
type: 'default',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(231 98% 65%)',
|
||||||
|
type: 'violet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(347 77% 60%)',
|
||||||
|
type: 'pink',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(0 75% 42%)',
|
||||||
|
type: 'rose',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(212 100% 45%)',
|
||||||
|
type: 'sky-blue',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(211 91% 39%)',
|
||||||
|
type: 'deep-blue',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(161 90% 43%)',
|
||||||
|
type: 'green',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(181 84% 32%)',
|
||||||
|
type: 'deep-green',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(18 89% 40%)',
|
||||||
|
type: 'orange',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(42 84% 61%)',
|
||||||
|
type: 'yellow',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(240 5% 26%)',
|
||||||
|
darkPrimaryColor: 'hsl(0 0 98%)',
|
||||||
|
primaryColor: 'hsl(240 5.9% 10%)',
|
||||||
|
type: 'zinc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(0 0% 25%)',
|
||||||
|
darkPrimaryColor: 'hsl(0 0 98%)',
|
||||||
|
primaryColor: 'hsl(240 5.9% 10%)',
|
||||||
|
type: 'neutral',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(215 25% 27%)',
|
||||||
|
darkPrimaryColor: 'hsl(0 0 98%)',
|
||||||
|
primaryColor: 'hsl(240 5.9% 10%)',
|
||||||
|
type: 'slate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: 'hsl(217 19% 27%)',
|
||||||
|
darkPrimaryColor: 'hsl(0 0 98%)',
|
||||||
|
primaryColor: 'hsl(240 5.9% 10%)',
|
||||||
|
type: 'gray',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: '',
|
||||||
|
type: 'custom',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const COLOR_PRESETS = [...BUILT_IN_THEME_PRESETS].slice(0, 7);
|
||||||
|
|
||||||
|
export { BUILT_IN_THEME_PRESETS, SUPPORT_LANGUAGES };
|
||||||
|
|
||||||
|
export type { BuiltinThemePreset };
|
||||||
|
|
|
@ -55,7 +55,6 @@ describe('preferences', () => {
|
||||||
const overrides: any = {
|
const overrides: any = {
|
||||||
app: {
|
app: {
|
||||||
locale: 'en-US',
|
locale: 'en-US',
|
||||||
themeMode: 'light',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
await preferenceManager.initPreferences({
|
await preferenceManager.initPreferences({
|
||||||
|
@ -79,10 +78,12 @@ describe('preferences', () => {
|
||||||
|
|
||||||
it('updates theme mode correctly', () => {
|
it('updates theme mode correctly', () => {
|
||||||
preferenceManager.updatePreferences({
|
preferenceManager.updatePreferences({
|
||||||
app: { themeMode: 'light' },
|
theme: {
|
||||||
|
mode: 'light',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(preferenceManager.getPreferences().app.themeMode).toBe('light');
|
expect(preferenceManager.getPreferences().theme.mode).toBe('light');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('updates color modes correctly', () => {
|
it('updates color modes correctly', () => {
|
||||||
|
@ -97,7 +98,9 @@ describe('preferences', () => {
|
||||||
it('resets preferences to default', () => {
|
it('resets preferences to default', () => {
|
||||||
// 先更新一些偏好设置
|
// 先更新一些偏好设置
|
||||||
preferenceManager.updatePreferences({
|
preferenceManager.updatePreferences({
|
||||||
app: { themeMode: 'light' },
|
theme: {
|
||||||
|
mode: 'light',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 然后重置偏好设置
|
// 然后重置偏好设置
|
||||||
|
@ -146,10 +149,10 @@ describe('preferences', () => {
|
||||||
});
|
});
|
||||||
it('updates the sidebar collapse state correctly', () => {
|
it('updates the sidebar collapse state correctly', () => {
|
||||||
preferenceManager.updatePreferences({
|
preferenceManager.updatePreferences({
|
||||||
sidebar: { collapse: true },
|
sidebar: { collapsed: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(preferenceManager.getPreferences().sidebar.collapse).toBe(true);
|
expect(preferenceManager.getPreferences().sidebar.collapsed).toBe(true);
|
||||||
});
|
});
|
||||||
it('updates the navigation style type correctly', () => {
|
it('updates the navigation style type correctly', () => {
|
||||||
preferenceManager.updatePreferences({
|
preferenceManager.updatePreferences({
|
||||||
|
@ -164,8 +167,11 @@ describe('preferences', () => {
|
||||||
it('resets preferences to default correctly', () => {
|
it('resets preferences to default correctly', () => {
|
||||||
// 先更新一些偏好设置
|
// 先更新一些偏好设置
|
||||||
preferenceManager.updatePreferences({
|
preferenceManager.updatePreferences({
|
||||||
app: { locale: 'en-US', themeMode: 'light' },
|
app: { locale: 'en-US' },
|
||||||
sidebar: { collapse: true, width: 200 },
|
sidebar: { collapsed: true, width: 200 },
|
||||||
|
theme: {
|
||||||
|
mode: 'light',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 然后重置偏好设置
|
// 然后重置偏好设置
|
||||||
|
@ -232,10 +238,10 @@ describe('preferences', () => {
|
||||||
await preferenceManager.initPreferences(overrides);
|
await preferenceManager.initPreferences(overrides);
|
||||||
|
|
||||||
preferenceManager.updatePreferences({
|
preferenceManager.updatePreferences({
|
||||||
app: { themeMode: 'light' },
|
theme: { mode: 'light' },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(preferenceManager.getPreferences().app.themeMode).toBe('light');
|
expect(preferenceManager.getPreferences().theme.mode).toBe('light');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,17 @@ import type { Preferences } from './types';
|
||||||
import { markRaw, reactive, readonly, watch } from 'vue';
|
import { markRaw, reactive, readonly, watch } from 'vue';
|
||||||
|
|
||||||
import { StorageManager } from '@vben-core/cache';
|
import { StorageManager } from '@vben-core/cache';
|
||||||
import { convertToHslCssVar, merge } from '@vben-core/toolkit';
|
import { generatorColorVariables } from '@vben-core/colorful';
|
||||||
|
import { merge, updateCSSVariables } from '@vben-core/toolkit';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
breakpointsTailwind,
|
breakpointsTailwind,
|
||||||
useBreakpoints,
|
useBreakpoints,
|
||||||
useCssVar,
|
|
||||||
useDebounceFn,
|
useDebounceFn,
|
||||||
} from '@vueuse/core';
|
} from '@vueuse/core';
|
||||||
|
|
||||||
import { defaultPreferences } from './config';
|
import { defaultPreferences } from './config';
|
||||||
|
import { BUILT_IN_THEME_PRESETS } from './constants';
|
||||||
|
|
||||||
const STORAGE_KEY = 'preferences';
|
const STORAGE_KEY = 'preferences';
|
||||||
const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`;
|
const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`;
|
||||||
|
@ -59,7 +60,7 @@ class PreferenceManager {
|
||||||
private _savePreferences(preference: Preferences) {
|
private _savePreferences(preference: Preferences) {
|
||||||
this.cache?.setItem(STORAGE_KEY, preference);
|
this.cache?.setItem(STORAGE_KEY, preference);
|
||||||
this.cache?.setItem(STORAGE_KEY_LOCALE, preference.app.locale);
|
this.cache?.setItem(STORAGE_KEY_LOCALE, preference.app.locale);
|
||||||
this.cache?.setItem(STORAGE_KEY_THEME, preference.app.themeMode);
|
this.cache?.setItem(STORAGE_KEY_THEME, preference.theme.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,11 +73,7 @@ class PreferenceManager {
|
||||||
const themeUpdates = updates.theme || {};
|
const themeUpdates = updates.theme || {};
|
||||||
const appUpdates = updates.app || {};
|
const appUpdates = updates.app || {};
|
||||||
|
|
||||||
if (themeUpdates.colorPrimary) {
|
if (themeUpdates && Object.keys(themeUpdates).length > 0) {
|
||||||
this.updateCssVar(this.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appUpdates.themeMode) {
|
|
||||||
this.updateTheme(this.state);
|
this.updateTheme(this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +146,7 @@ class PreferenceManager {
|
||||||
.matchMedia('(prefers-color-scheme: dark)')
|
.matchMedia('(prefers-color-scheme: dark)')
|
||||||
.addEventListener('change', ({ matches: isDark }) => {
|
.addEventListener('change', ({ matches: isDark }) => {
|
||||||
this.updatePreferences({
|
this.updatePreferences({
|
||||||
app: { themeMode: isDark ? 'dark' : 'light' },
|
theme: { mode: isDark ? 'dark' : 'light' },
|
||||||
});
|
});
|
||||||
this.updateTheme(this.state);
|
this.updateTheme(this.state);
|
||||||
});
|
});
|
||||||
|
@ -178,15 +175,37 @@ class PreferenceManager {
|
||||||
* 更新 CSS 变量
|
* 更新 CSS 变量
|
||||||
* @param preference - 当前偏好设置对象,它的颜色值将被转换成 HSL 格式并设置为 CSS 变量。
|
* @param preference - 当前偏好设置对象,它的颜色值将被转换成 HSL 格式并设置为 CSS 变量。
|
||||||
*/
|
*/
|
||||||
private updateCssVar(preference: Preferences) {
|
private updateMainColors(preference: Preferences) {
|
||||||
if (preference.theme) {
|
if (!preference.theme) {
|
||||||
for (const [key, value] of Object.entries(preference.theme)) {
|
return;
|
||||||
if (['colorPrimary'].includes(key)) {
|
|
||||||
const cssVarValue = useCssVar(`--primary`);
|
|
||||||
cssVarValue.value = convertToHslCssVar(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const { colorDestructive, colorPrimary, colorSuccess, colorWarning } =
|
||||||
|
preference.theme;
|
||||||
|
|
||||||
|
const colorVariables = generatorColorVariables([
|
||||||
|
{ color: colorPrimary, name: 'primary' },
|
||||||
|
{ alias: 'warning', color: colorWarning, name: 'yellow' },
|
||||||
|
{ alias: 'success', color: colorSuccess, name: 'green' },
|
||||||
|
{ alias: 'destructive', color: colorDestructive, name: 'red' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (colorPrimary) {
|
||||||
|
document.documentElement.style.setProperty(
|
||||||
|
'--primary',
|
||||||
|
colorVariables['--primary-600'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorVariables['--green-600']) {
|
||||||
|
colorVariables['--success'] = colorVariables['--green-600'];
|
||||||
|
}
|
||||||
|
if (colorVariables['--yellow-600']) {
|
||||||
|
colorVariables['--warning'] = colorVariables['--yellow-600'];
|
||||||
|
}
|
||||||
|
if (colorVariables['--red-600']) {
|
||||||
|
colorVariables['--destructive'] = colorVariables['--red-600'];
|
||||||
|
}
|
||||||
|
updateCSSVariables(colorVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -206,14 +225,61 @@ class PreferenceManager {
|
||||||
private updateTheme(preferences: Preferences) {
|
private updateTheme(preferences: Preferences) {
|
||||||
// 当修改到颜色变量时,更新 css 变量
|
// 当修改到颜色变量时,更新 css 变量
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
if (root) {
|
if (!root) {
|
||||||
const themeMode = preferences?.app?.themeMode;
|
return;
|
||||||
if (!themeMode) {
|
}
|
||||||
return;
|
|
||||||
}
|
const {
|
||||||
const dark = isDarkTheme(themeMode);
|
builtinType,
|
||||||
|
colorDestructive,
|
||||||
|
colorPrimary,
|
||||||
|
colorSuccess,
|
||||||
|
colorWarning,
|
||||||
|
mode,
|
||||||
|
radius,
|
||||||
|
} = preferences?.theme ?? {};
|
||||||
|
|
||||||
|
if (mode) {
|
||||||
|
const dark = isDarkTheme(mode);
|
||||||
root.classList.toggle('dark', dark);
|
root.classList.toggle('dark', dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (builtinType) {
|
||||||
|
const rootTheme = root.dataset.theme;
|
||||||
|
if (rootTheme !== builtinType) {
|
||||||
|
root.dataset.theme = builtinType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentBuiltType = BUILT_IN_THEME_PRESETS.find(
|
||||||
|
(item) => item.type === builtinType,
|
||||||
|
);
|
||||||
|
|
||||||
|
let builtinTypeColorPrimary: string | undefined = '';
|
||||||
|
|
||||||
|
if (currentBuiltType) {
|
||||||
|
const isDark = isDarkTheme(this.state.theme.mode);
|
||||||
|
|
||||||
|
const color = isDark
|
||||||
|
? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor
|
||||||
|
: currentBuiltType.primaryColor;
|
||||||
|
builtinTypeColorPrimary = color || currentBuiltType.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
builtinTypeColorPrimary ||
|
||||||
|
colorPrimary ||
|
||||||
|
colorDestructive ||
|
||||||
|
colorSuccess ||
|
||||||
|
colorWarning
|
||||||
|
) {
|
||||||
|
preferences.theme.colorPrimary = builtinTypeColorPrimary || colorPrimary;
|
||||||
|
this.updateMainColors(preferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (radius) {
|
||||||
|
document.documentElement.style.setProperty('--radius', `${radius}rem`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public getFlatPreferences() {
|
// public getFlatPreferences() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type {
|
import type {
|
||||||
|
BuiltinThemeType,
|
||||||
ContentCompactType,
|
ContentCompactType,
|
||||||
LayoutHeaderModeType,
|
LayoutHeaderModeType,
|
||||||
LayoutType,
|
LayoutType,
|
||||||
|
@ -45,8 +46,6 @@ interface AppPreferences {
|
||||||
semiDarkMenu: boolean;
|
semiDarkMenu: boolean;
|
||||||
/** 是否显示偏好设置 */
|
/** 是否显示偏好设置 */
|
||||||
showPreference: boolean;
|
showPreference: boolean;
|
||||||
/** 当前主题 */
|
|
||||||
themeMode: ThemeModeType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BreadcrumbPreferences {
|
interface BreadcrumbPreferences {
|
||||||
|
@ -132,8 +131,20 @@ interface TabbarPreferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ThemePreferences {
|
interface ThemePreferences {
|
||||||
|
/** 内置主题名 */
|
||||||
|
builtinType: BuiltinThemeType;
|
||||||
|
/** 错误色 */
|
||||||
|
colorDestructive: string;
|
||||||
/** 主题色 */
|
/** 主题色 */
|
||||||
colorPrimary: string;
|
colorPrimary: string;
|
||||||
|
/** 成功色 */
|
||||||
|
colorSuccess: string;
|
||||||
|
/** 警告色 */
|
||||||
|
colorWarning: string;
|
||||||
|
/** 当前主题 */
|
||||||
|
mode: ThemeModeType;
|
||||||
|
/** 圆角 */
|
||||||
|
radius: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TransitionPreferences {
|
interface TransitionPreferences {
|
||||||
|
|
|
@ -24,7 +24,7 @@ function usePreferences() {
|
||||||
* @returns 如果主题为暗黑模式,返回 true,否则返回 false。
|
* @returns 如果主题为暗黑模式,返回 true,否则返回 false。
|
||||||
*/
|
*/
|
||||||
const isDark = computed(() => {
|
const isDark = computed(() => {
|
||||||
return isDarkTheme(appPreferences.value.themeMode);
|
return isDarkTheme(preferences.theme.mode);
|
||||||
});
|
});
|
||||||
|
|
||||||
const theme = computed(() => {
|
const theme = computed(() => {
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { defineBuildConfig } from 'unbuild';
|
||||||
|
|
||||||
|
export default defineBuildConfig({
|
||||||
|
clean: true,
|
||||||
|
declaration: true,
|
||||||
|
entries: ['src/index'],
|
||||||
|
});
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"name": "@vben-core/colorful",
|
||||||
|
"version": "5.0.0",
|
||||||
|
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||||
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||||
|
"directory": "packages/@vben-core/shared/colorful"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "pnpm unbuild",
|
||||||
|
"stub": "pnpm unbuild --stub"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"sideEffects": false,
|
||||||
|
"main": "./dist/index.mjs",
|
||||||
|
"module": "./dist/index.mjs",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"development": "./src/index.ts",
|
||||||
|
"default": "./dist/index.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.mjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@ant-design/colors": "^7.0.2",
|
||||||
|
"@ctrl/tinycolor": "4.1.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { generate } from '@ant-design/colors';
|
||||||
|
|
||||||
|
import { convertToHslCssVar } from './utils';
|
||||||
|
|
||||||
|
export * from '@ant-design/colors';
|
||||||
|
|
||||||
|
interface Opts {
|
||||||
|
backgroundColor?: string;
|
||||||
|
theme?: 'dark' | 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ColorItem {
|
||||||
|
alias?: string;
|
||||||
|
color: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generatorColorVariables(colorItems: ColorItem[], opts?: Opts) {
|
||||||
|
const colorVariables: Record<string, string> = {};
|
||||||
|
|
||||||
|
colorItems.forEach(({ alias, color, name }) => {
|
||||||
|
if (color) {
|
||||||
|
const colors = generate(color, opts);
|
||||||
|
let mainColor = colors[5];
|
||||||
|
colors.forEach((colorValue, colorIndex) => {
|
||||||
|
const hslColor = convertToHslCssVar(colorValue);
|
||||||
|
colorVariables[`--${name}-${colorIndex + 1}00`] = hslColor;
|
||||||
|
if (alias) {
|
||||||
|
colorVariables[`--${alias}-${colorIndex + 1}00`] = hslColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorIndex === 5) {
|
||||||
|
mainColor = hslColor;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (alias) {
|
||||||
|
colorVariables[`--${alias}`] = mainColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return colorVariables;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { generatorColorVariables };
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './generator';
|
||||||
|
export * from './utils';
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { convertToHsl, convertToHslCssVar, isValidColor } from './color';
|
import { convertToHsl, convertToHslCssVar, isValidColor } from './utils';
|
||||||
|
|
||||||
describe('color conversion functions', () => {
|
describe('color conversion functions', () => {
|
||||||
it('should correctly convert color to HSL format', () => {
|
it('should correctly convert color to HSL format', () => {
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "@vben/tsconfig/library.json",
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
:root.dark {
|
:root.dark,
|
||||||
|
:root.dark[data-theme='custom'],
|
||||||
|
:root.dark[data-theme='default'] {
|
||||||
/* Default background color of <body />...etc */
|
/* Default background color of <body />...etc */
|
||||||
--background: 220deg 13.04% 8%;
|
--background: 220deg 13.04% 8%;
|
||||||
--foreground: 220 13% 91%;
|
--foreground: 220 13% 91%;
|
||||||
|
@ -16,18 +18,22 @@
|
||||||
--muted-foreground: 215 20.2% 65.1%;
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
|
||||||
/* 主题颜色 */
|
/* 主题颜色 */
|
||||||
--primary: 211 91% 39%;
|
|
||||||
|
/* --primary: 245 82% 67%; */
|
||||||
--primary-foreground: 0 0 98%;
|
--primary-foreground: 0 0 98%;
|
||||||
|
|
||||||
/* Used for destructive actions such as <Button variant="destructive"> */
|
/* Used for destructive actions such as <Button variant="destructive"> */
|
||||||
--destructive: 0 63% 31%;
|
|
||||||
|
--destructive: 0 78% 68%;
|
||||||
--destructive-foreground: 0 0 98%;
|
--destructive-foreground: 0 0 98%;
|
||||||
|
|
||||||
/* Used for success actions such as <message> */
|
/* Used for success actions such as <message> */
|
||||||
|
|
||||||
--success: 144 57% 58%;
|
--success: 144 57% 58%;
|
||||||
--success-foreground: 0 0 98%;
|
--success-foreground: 0 0 98%;
|
||||||
|
|
||||||
/* Used for warning actions such as <message> */
|
/* Used for warning actions such as <message> */
|
||||||
|
|
||||||
--warning: 42 84% 61%;
|
--warning: 42 84% 61%;
|
||||||
--warning-foreground: 0 0 98%;
|
--warning-foreground: 0 0 98%;
|
||||||
|
|
||||||
|
@ -64,5 +70,283 @@
|
||||||
/* 基本圆角大小 */
|
/* 基本圆角大小 */
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
|
|
||||||
|
/* =============component & UI============= */
|
||||||
|
|
||||||
|
/* authentication */
|
||||||
|
--authentication: 240deg 11% 2%;
|
||||||
|
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='violet'] {
|
||||||
|
--background: 224 71.4% 4.1%;
|
||||||
|
--foreground: 210 20% 98%;
|
||||||
|
--card: 224 71.4% 4.1%;
|
||||||
|
--card-foreground: 210 20% 98%;
|
||||||
|
--popover: 224 71.4% 4.1%;
|
||||||
|
--popover-foreground: 210 20% 98%;
|
||||||
|
--primary-foreground: 210 20% 98%;
|
||||||
|
--secondary: 215 27.9% 16.9%;
|
||||||
|
--secondary-foreground: 210 20% 98%;
|
||||||
|
--muted: 215 27.9% 16.9%;
|
||||||
|
--muted-foreground: 217.9 10.6% 64.9%;
|
||||||
|
--accent: 215 27.9% 16.9%;
|
||||||
|
--accent-foreground: 210 20% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 20% 98%;
|
||||||
|
--border: 215 27.9% 16.9%;
|
||||||
|
--input: 215 27.9% 16.9%;
|
||||||
|
--ring: 263.4 70% 50.4%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='pink'] {
|
||||||
|
--background: 20 14.3% 4.1%;
|
||||||
|
--foreground: 0 0% 95%;
|
||||||
|
--card: 24 9.8% 10%;
|
||||||
|
--card-foreground: 0 0% 95%;
|
||||||
|
--popover: 0 0% 9%;
|
||||||
|
--popover-foreground: 0 0% 95%;
|
||||||
|
--primary-foreground: 355.7 100% 97.3%;
|
||||||
|
--secondary: 240 3.7% 15.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 0 0% 15%;
|
||||||
|
--muted-foreground: 240 5% 64.9%;
|
||||||
|
--accent: 12 6.5% 15.1%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 85.7% 97.3%;
|
||||||
|
--border: 240 3.7% 15.9%;
|
||||||
|
--input: 240 3.7% 15.9%;
|
||||||
|
--ring: 346.8 77.2% 49.8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='rose'] {
|
||||||
|
--background: 0 0% 3.9%;
|
||||||
|
--foreground: 0 0% 98%;
|
||||||
|
--card: 0 0% 3.9%;
|
||||||
|
--card-foreground: 0 0% 98%;
|
||||||
|
--popover: 0 0% 3.9%;
|
||||||
|
--popover-foreground: 0 0% 98%;
|
||||||
|
--primary-foreground: 0 85.7% 97.3%;
|
||||||
|
--secondary: 0 0% 14.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 0 0% 14.9%;
|
||||||
|
--muted-foreground: 0 0% 63.9%;
|
||||||
|
--accent: 0 0% 14.9%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 0 0% 14.9%;
|
||||||
|
--input: 0 0% 14.9%;
|
||||||
|
--ring: 0 72.2% 50.6%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='sky-blue'] {
|
||||||
|
--background: 222.2 84% 4.9%;
|
||||||
|
--foreground: 210 40% 98%;
|
||||||
|
--card: 222.2 84% 4.9%;
|
||||||
|
--card-foreground: 210 40% 98%;
|
||||||
|
--popover: 222.2 84% 4.9%;
|
||||||
|
--popover-foreground: 210 40% 98%;
|
||||||
|
--primary-foreground: 210 20% 98%;
|
||||||
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
--muted: 217.2 32.6% 17.5%;
|
||||||
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
--accent: 217.2 32.6% 17.5%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
--border: 217.2 32.6% 17.5%;
|
||||||
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
--ring: 224.3 76.3% 48%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='deep-blue'] {
|
||||||
|
--background: 222.2 84% 4.9%;
|
||||||
|
--foreground: 210 40% 98%;
|
||||||
|
--card: 222.2 84% 4.9%;
|
||||||
|
--card-foreground: 210 40% 98%;
|
||||||
|
--popover: 222.2 84% 4.9%;
|
||||||
|
--popover-foreground: 210 40% 98%;
|
||||||
|
--primary-foreground: 210 20% 98%;
|
||||||
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
--muted: 217.2 32.6% 17.5%;
|
||||||
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
--accent: 217.2 32.6% 17.5%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
--border: 217.2 32.6% 17.5%;
|
||||||
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
--ring: 224.3 76.3% 48%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='green'] {
|
||||||
|
--background: 20 14.3% 4.1%;
|
||||||
|
--foreground: 0 0% 95%;
|
||||||
|
--card: 24 9.8% 10%;
|
||||||
|
--card-foreground: 0 0% 95%;
|
||||||
|
--popover: 0 0% 9%;
|
||||||
|
--popover-foreground: 0 0% 95%;
|
||||||
|
--primary-foreground: 210 20% 98%;
|
||||||
|
--secondary: 240 3.7% 15.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 0 0% 15%;
|
||||||
|
--muted-foreground: 240 5% 64.9%;
|
||||||
|
--accent: 12 6.5% 15.1%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 85.7% 97.3%;
|
||||||
|
--border: 240 3.7% 15.9%;
|
||||||
|
--input: 240 3.7% 15.9%;
|
||||||
|
--ring: 142.4 71.8% 29.2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='deep-green'] {
|
||||||
|
--background: 20 14.3% 4.1%;
|
||||||
|
--foreground: 0 0% 95%;
|
||||||
|
--card: 24 9.8% 10%;
|
||||||
|
--card-foreground: 0 0% 95%;
|
||||||
|
--popover: 0 0% 9%;
|
||||||
|
--popover-foreground: 0 0% 95%;
|
||||||
|
--primary-foreground: 210 20% 98%;
|
||||||
|
--secondary: 240 3.7% 15.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 0 0% 15%;
|
||||||
|
--muted-foreground: 240 5% 64.9%;
|
||||||
|
--accent: 12 6.5% 15.1%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 85.7% 97.3%;
|
||||||
|
--border: 240 3.7% 15.9%;
|
||||||
|
--input: 240 3.7% 15.9%;
|
||||||
|
--ring: 142.4 71.8% 29.2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='orange'] {
|
||||||
|
--background: 20 14.3% 4.1%;
|
||||||
|
--foreground: 60 9.1% 97.8%;
|
||||||
|
--card: 20 14.3% 4.1%;
|
||||||
|
--card-foreground: 60 9.1% 97.8%;
|
||||||
|
--popover: 20 14.3% 4.1%;
|
||||||
|
--popover-foreground: 60 9.1% 97.8%;
|
||||||
|
--primary-foreground: 60 9.1% 97.8%;
|
||||||
|
--secondary: 12 6.5% 15.1%;
|
||||||
|
--secondary-foreground: 60 9.1% 97.8%;
|
||||||
|
--muted: 12 6.5% 15.1%;
|
||||||
|
--muted-foreground: 24 5.4% 63.9%;
|
||||||
|
--accent: 12 6.5% 15.1%;
|
||||||
|
--accent-foreground: 60 9.1% 97.8%;
|
||||||
|
--destructive: 0 72.2% 50.6%;
|
||||||
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
|
--border: 12 6.5% 15.1%;
|
||||||
|
--input: 12 6.5% 15.1%;
|
||||||
|
--ring: 20.5 90.2% 48.2%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='yellow'] {
|
||||||
|
--background: 20 14.3% 4.1%;
|
||||||
|
--foreground: 60 9.1% 97.8%;
|
||||||
|
--card: 20 14.3% 4.1%;
|
||||||
|
--card-foreground: 60 9.1% 97.8%;
|
||||||
|
--popover: 20 14.3% 4.1%;
|
||||||
|
--popover-foreground: 60 9.1% 97.8%;
|
||||||
|
--primary-foreground: 26 83.3% 14.1%;
|
||||||
|
--secondary: 12 6.5% 15.1%;
|
||||||
|
--secondary-foreground: 60 9.1% 97.8%;
|
||||||
|
--muted: 12 6.5% 15.1%;
|
||||||
|
--muted-foreground: 24 5.4% 63.9%;
|
||||||
|
--accent: 12 6.5% 15.1%;
|
||||||
|
--accent-foreground: 60 9.1% 97.8%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
|
--border: 12 6.5% 15.1%;
|
||||||
|
--input: 12 6.5% 15.1%;
|
||||||
|
--ring: 35.5 91.7% 32.9%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='zinc'] {
|
||||||
|
--background: 240 10% 3.9%;
|
||||||
|
--foreground: 0 0% 98%;
|
||||||
|
--card: 240 10% 3.9%;
|
||||||
|
--card-foreground: 0 0% 98%;
|
||||||
|
--popover: 240 10% 3.9%;
|
||||||
|
--popover-foreground: 0 0% 98%;
|
||||||
|
--primary-foreground: 240 5.9% 10%;
|
||||||
|
--secondary: 240 3.7% 15.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 240 3.7% 15.9%;
|
||||||
|
--muted-foreground: 240 5% 64.9%;
|
||||||
|
--accent: 240 3.7% 15.9%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 3.7% 15.9%;
|
||||||
|
--input: 240 3.7% 15.9%;
|
||||||
|
--ring: 240 4.9% 83.9%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='neutral'] {
|
||||||
|
--background: 0 0% 3.9%;
|
||||||
|
--foreground: 0 0% 98%;
|
||||||
|
--card: 0 0% 3.9%;
|
||||||
|
--card-foreground: 0 0% 98%;
|
||||||
|
--popover: 0 0% 3.9%;
|
||||||
|
--popover-foreground: 0 0% 98%;
|
||||||
|
--primary-foreground: 0 0% 9%;
|
||||||
|
--secondary: 0 0% 14.9%;
|
||||||
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
--muted: 0 0% 14.9%;
|
||||||
|
--muted-foreground: 0 0% 63.9%;
|
||||||
|
--accent: 0 0% 14.9%;
|
||||||
|
--accent-foreground: 0 0% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 0 0% 14.9%;
|
||||||
|
--input: 0 0% 14.9%;
|
||||||
|
--ring: 0 0% 83.1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='slate'] {
|
||||||
|
--background: 222.2 84% 4.9%;
|
||||||
|
--foreground: 210 40% 98%;
|
||||||
|
--card: 222.2 84% 4.9%;
|
||||||
|
--card-foreground: 210 40% 98%;
|
||||||
|
--popover: 222.2 84% 4.9%;
|
||||||
|
--popover-foreground: 210 40% 98%;
|
||||||
|
--primary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
--muted: 217.2 32.6% 17.5%;
|
||||||
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
--accent: 217.2 32.6% 17.5%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
--border: 217.2 32.6% 17.5%;
|
||||||
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
--ring: 212.7 26.8% 83.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark[data-theme='gray'] {
|
||||||
|
--background: 224 71.4% 4.1%;
|
||||||
|
--foreground: 210 20% 98%;
|
||||||
|
--card: 224 71.4% 4.1%;
|
||||||
|
--card-foreground: 210 20% 98%;
|
||||||
|
--popover: 224 71.4% 4.1%;
|
||||||
|
--popover-foreground: 210 20% 98%;
|
||||||
|
--primary-foreground: 220.9 39.3% 11%;
|
||||||
|
--secondary: 215 27.9% 16.9%;
|
||||||
|
--secondary-foreground: 210 20% 98%;
|
||||||
|
--muted: 215 27.9% 16.9%;
|
||||||
|
--muted-foreground: 217.9 10.6% 64.9%;
|
||||||
|
--accent: 215 27.9% 16.9%;
|
||||||
|
--accent-foreground: 210 20% 98%;
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 20% 98%;
|
||||||
|
--border: 215 27.9% 16.9%;
|
||||||
|
--input: 215 27.9% 16.9%;
|
||||||
|
--ring: 216 12.2% 83.9%;
|
||||||
|
}
|
||||||
|
|
|
@ -17,22 +17,27 @@
|
||||||
--muted-foreground: 215.4 16.3% 46.9%;
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
|
||||||
/* 主题颜色 */
|
/* 主题颜色 */
|
||||||
|
|
||||||
--primary: 211 91% 39%;
|
--primary: 211 91% 39%;
|
||||||
--primary-foreground: 0 0 98%;
|
--primary-foreground: 0 0 98%;
|
||||||
|
|
||||||
/* Used for destructive actions such as <Button variant="destructive"> */
|
/* Used for destructive actions such as <Button variant="destructive"> */
|
||||||
|
|
||||||
--destructive: 0 78% 68%;
|
--destructive: 0 78% 68%;
|
||||||
--destructive-foreground: 0 0 98%;
|
--destructive-foreground: 0 0 98%;
|
||||||
|
|
||||||
/* Used for success actions such as <message> */
|
/* Used for success actions such as <message> */
|
||||||
|
|
||||||
--success: 144 57% 58%;
|
--success: 144 57% 58%;
|
||||||
--success-foreground: 0 0 98%;
|
--success-foreground: 0 0 98%;
|
||||||
|
|
||||||
/* Used for warning actions such as <message> */
|
/* Used for warning actions such as <message> */
|
||||||
|
|
||||||
--warning: 42 84% 61%;
|
--warning: 42 84% 61%;
|
||||||
--warning-foreground: 0 0 98%;
|
--warning-foreground: 0 0 98%;
|
||||||
|
|
||||||
/* Secondary colors for <Button /> */
|
/* Secondary colors for <Button /> */
|
||||||
|
|
||||||
--secondary: 240 5% 96%;
|
--secondary: 240 5% 96%;
|
||||||
--secondary-foreground: 240 6% 10%;
|
--secondary-foreground: 240 6% 10%;
|
||||||
|
|
||||||
|
@ -73,6 +78,9 @@
|
||||||
|
|
||||||
/* =============component & UI============= */
|
/* =============component & UI============= */
|
||||||
|
|
||||||
|
/* authentication */
|
||||||
|
--authentication: 231deg 61% 44%;
|
||||||
|
|
||||||
/* menu */
|
/* menu */
|
||||||
--menu: 0deg 0% 100%;
|
--menu: 0deg 0% 100%;
|
||||||
--menu-darken: 0deg 0% 95%;
|
--menu-darken: 0deg 0% 95%;
|
||||||
|
@ -84,3 +92,276 @@
|
||||||
accent-color: var(--primary);
|
accent-color: var(--primary);
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root[data-theme='violet'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 224 71.4% 4.1%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 224 71.4% 4.1%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 224 71.4% 4.1%;
|
||||||
|
--primary-foreground: 210 20% 98%;
|
||||||
|
--secondary: 220 14.3% 95.9%;
|
||||||
|
--secondary-foreground: 220.9 39.3% 11%;
|
||||||
|
--muted: 220 14.3% 95.9%;
|
||||||
|
--muted-foreground: 220 8.9% 46.1%;
|
||||||
|
--accent: 220 14.3% 95.9%;
|
||||||
|
--accent-foreground: 220.9 39.3% 11%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 20% 98%;
|
||||||
|
--border: 220 13% 91%;
|
||||||
|
--input: 220 13% 91%;
|
||||||
|
--ring: 262.1 83.3% 57.8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='pink'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 240 10% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 240 10% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 240 10% 3.9%;
|
||||||
|
--primary-foreground: 355.7 100% 97.3%;
|
||||||
|
--secondary: 240 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 240 5.9% 10%;
|
||||||
|
--muted: 240 4.8% 95.9%;
|
||||||
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
|
--accent: 240 4.8% 95.9%;
|
||||||
|
--accent-foreground: 240 5.9% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 5.9% 90%;
|
||||||
|
--input: 240 5.9% 90%;
|
||||||
|
--ring: 346.8 77.2% 49.8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='rose'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 240 10% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 240 10% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 240 10% 3.9%;
|
||||||
|
--primary-foreground: 355.7 100% 97.3%;
|
||||||
|
--secondary: 240 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 240 5.9% 10%;
|
||||||
|
--muted: 240 4.8% 95.9%;
|
||||||
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
|
--accent: 240 4.8% 95.9%;
|
||||||
|
--accent-foreground: 240 5.9% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 5.9% 90%;
|
||||||
|
--input: 240 5.9% 90%;
|
||||||
|
--ring: 346.8 77.2% 49.8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='sky-blue'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 222.2 84% 4.9%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
--ring: 221.2 83.2% 53.3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='deep-blue'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 222.2 84% 4.9%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
--ring: 221.2 83.2% 53.3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='green'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 240 10% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 240 10% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 240 10% 3.9%;
|
||||||
|
--primary-foreground: 355.7 100% 97.3%;
|
||||||
|
--secondary: 240 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 240 5.9% 10%;
|
||||||
|
--muted: 240 4.8% 95.9%;
|
||||||
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
|
--accent: 240 4.8% 95.9%;
|
||||||
|
--accent-foreground: 240 5.9% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 5.9% 90%;
|
||||||
|
--input: 240 5.9% 90%;
|
||||||
|
--ring: 142.1 76.2% 36.3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='deep-green'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 240 10% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 240 10% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 240 10% 3.9%;
|
||||||
|
--primary-foreground: 355.7 100% 97.3%;
|
||||||
|
--secondary: 240 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 240 5.9% 10%;
|
||||||
|
--muted: 240 4.8% 95.9%;
|
||||||
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
|
--accent: 240 4.8% 95.9%;
|
||||||
|
--accent-foreground: 240 5.9% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 5.9% 90%;
|
||||||
|
--input: 240 5.9% 90%;
|
||||||
|
--ring: 142.1 76.2% 36.3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='orange'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 20 14.3% 4.1%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 20 14.3% 4.1%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 20 14.3% 4.1%;
|
||||||
|
--primary-foreground: 60 9.1% 97.8%;
|
||||||
|
--secondary: 60 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 24 9.8% 10%;
|
||||||
|
--muted: 60 4.8% 95.9%;
|
||||||
|
--muted-foreground: 25 5.3% 44.7%;
|
||||||
|
--accent: 60 4.8% 95.9%;
|
||||||
|
--accent-foreground: 24 9.8% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
|
--border: 20 5.9% 90%;
|
||||||
|
--input: 20 5.9% 90%;
|
||||||
|
--ring: 24.6 95% 53.1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='yellow'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 20 14.3% 4.1%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 20 14.3% 4.1%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 20 14.3% 4.1%;
|
||||||
|
--primary-foreground: 26 83.3% 14.1%;
|
||||||
|
--secondary: 60 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 24 9.8% 10%;
|
||||||
|
--muted: 60 4.8% 95.9%;
|
||||||
|
--muted-foreground: 25 5.3% 44.7%;
|
||||||
|
--accent: 60 4.8% 95.9%;
|
||||||
|
--accent-foreground: 24 9.8% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
|
--border: 20 5.9% 90%;
|
||||||
|
--input: 20 5.9% 90%;
|
||||||
|
--ring: 20 14.3% 4.1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='zinc'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 240 10% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 240 10% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 240 10% 3.9%;
|
||||||
|
--primary-foreground: 0 0% 98%;
|
||||||
|
--secondary: 240 4.8% 95.9%;
|
||||||
|
--secondary-foreground: 240 5.9% 10%;
|
||||||
|
--muted: 240 4.8% 95.9%;
|
||||||
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
|
--accent: 240 4.8% 95.9%;
|
||||||
|
--accent-foreground: 240 5.9% 10%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 240 5.9% 90%;
|
||||||
|
--input: 240 5.9% 90%;
|
||||||
|
--ring: 240 5.9% 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='neutral'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 0 0% 3.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 0 0% 3.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 0 0% 3.9%;
|
||||||
|
--primary-foreground: 0 0% 98%;
|
||||||
|
--secondary: 0 0% 96.1%;
|
||||||
|
--secondary-foreground: 0 0% 9%;
|
||||||
|
--muted: 0 0% 96.1%;
|
||||||
|
--muted-foreground: 0 0% 45.1%;
|
||||||
|
--accent: 0 0% 96.1%;
|
||||||
|
--accent-foreground: 0 0% 9%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
--border: 0 0% 89.8%;
|
||||||
|
--input: 0 0% 89.8%;
|
||||||
|
--ring: 0 0% 3.9%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='slate'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 222.2 84% 4.9%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
--ring: 222.2 84% 4.9%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-theme='gray'] {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 224 71.4% 4.1%;
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 224 71.4% 4.1%;
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 224 71.4% 4.1%;
|
||||||
|
--primary-foreground: 210 20% 98%;
|
||||||
|
--secondary: 220 14.3% 95.9%;
|
||||||
|
--secondary-foreground: 220.9 39.3% 11%;
|
||||||
|
--muted: 220 14.3% 95.9%;
|
||||||
|
--muted-foreground: 220 8.9% 46.1%;
|
||||||
|
--accent: 220 14.3% 95.9%;
|
||||||
|
--accent-foreground: 220.9 39.3% 11%;
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 20% 98%;
|
||||||
|
--border: 220 13% 91%;
|
||||||
|
--input: 220 13% 91%;
|
||||||
|
--ring: 224 71.4% 4.1%;
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ctrl/tinycolor": "4.1.0",
|
|
||||||
"@vue/shared": "^3.4.30",
|
"@vue/shared": "^3.4.30",
|
||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
export * from './cn';
|
export * from './cn';
|
||||||
export * from './color';
|
|
||||||
export * from './diff';
|
export * from './diff';
|
||||||
export * from './hash';
|
export * from './hash';
|
||||||
export * from './inference';
|
export * from './inference';
|
||||||
|
@ -8,4 +7,5 @@ export * from './merge';
|
||||||
export * from './namespace';
|
export * from './namespace';
|
||||||
export * from './nprogress';
|
export * from './nprogress';
|
||||||
export * from './tree';
|
export * from './tree';
|
||||||
|
export * from './update-css-variables';
|
||||||
export * from './window';
|
export * from './window';
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { updateCSSVariables } from './update-css-variables';
|
||||||
|
|
||||||
|
it('updateCSSVariables should update CSS variables in :root selector', () => {
|
||||||
|
// 模拟初始的内联样式表内容
|
||||||
|
const initialStyleContent = ':root { --primaryColor: red; }';
|
||||||
|
document.head.innerHTML = `<style id="custom-styles">${initialStyleContent}</style>`;
|
||||||
|
|
||||||
|
// 要更新的CSS变量和它们的新值
|
||||||
|
const updatedVariables = {
|
||||||
|
fontSize: '16px',
|
||||||
|
primaryColor: 'blue',
|
||||||
|
secondaryColor: 'green',
|
||||||
|
};
|
||||||
|
|
||||||
|
// 调用函数来更新CSS变量
|
||||||
|
updateCSSVariables(updatedVariables, 'custom-styles');
|
||||||
|
|
||||||
|
// 获取更新后的样式内容
|
||||||
|
const styleElement = document.querySelector('#custom-styles');
|
||||||
|
const updatedStyleContent = styleElement ? styleElement.textContent : '';
|
||||||
|
|
||||||
|
// 检查更新后的样式内容是否包含正确的更新值
|
||||||
|
expect(
|
||||||
|
updatedStyleContent?.includes('primaryColor: blue;') &&
|
||||||
|
updatedStyleContent?.includes('secondaryColor: green;') &&
|
||||||
|
updatedStyleContent?.includes('fontSize: 16px;'),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* 更新 CSS 变量的函数
|
||||||
|
* @param variables 要更新的 CSS 变量与其新值的映射
|
||||||
|
*/
|
||||||
|
function updateCSSVariables(
|
||||||
|
variables: { [key: string]: string },
|
||||||
|
id = '__vben-styles__',
|
||||||
|
): void {
|
||||||
|
// 获取或创建内联样式表元素
|
||||||
|
const styleElement =
|
||||||
|
document.querySelector(`#${id}`) || document.createElement('style');
|
||||||
|
|
||||||
|
styleElement.id = id;
|
||||||
|
|
||||||
|
// 构建要更新的 CSS 变量的样式文本
|
||||||
|
let cssText = ':root {';
|
||||||
|
for (const key in variables) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(variables, key)) {
|
||||||
|
cssText += `${key}: ${variables[key]};`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cssText += '}';
|
||||||
|
|
||||||
|
// 将样式文本赋值给内联样式表
|
||||||
|
styleElement.textContent = cssText;
|
||||||
|
|
||||||
|
// 将内联样式表添加到文档头部
|
||||||
|
if (!document.querySelector(`#${id}`)) {
|
||||||
|
setTimeout(() => {
|
||||||
|
document.head.append(styleElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { updateCSSVariables };
|
|
@ -9,11 +9,32 @@ type LayoutType =
|
||||||
|
|
||||||
type ThemeModeType = 'auto' | 'dark' | 'light';
|
type ThemeModeType = 'auto' | 'dark' | 'light';
|
||||||
|
|
||||||
|
type BuiltinThemeType =
|
||||||
|
| 'custom'
|
||||||
|
| 'deep-blue'
|
||||||
|
| 'deep-green'
|
||||||
|
| 'default'
|
||||||
|
| 'default'
|
||||||
|
| 'gray'
|
||||||
|
| 'green'
|
||||||
|
| 'neutral'
|
||||||
|
| 'orange'
|
||||||
|
| 'pink'
|
||||||
|
| 'red'
|
||||||
|
| 'rose'
|
||||||
|
| 'sky-blue'
|
||||||
|
| 'slate'
|
||||||
|
| 'stone'
|
||||||
|
| 'violet'
|
||||||
|
| 'yellow'
|
||||||
|
| 'zinc';
|
||||||
|
|
||||||
type ContentCompactType = 'compact' | 'wide';
|
type ContentCompactType = 'compact' | 'wide';
|
||||||
|
|
||||||
type LayoutHeaderModeType = 'auto' | 'auto-scroll' | 'fixed' | 'static';
|
type LayoutHeaderModeType = 'auto' | 'auto-scroll' | 'fixed' | 'static';
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
|
BuiltinThemeType,
|
||||||
ContentCompactType,
|
ContentCompactType,
|
||||||
LayoutHeaderModeType,
|
LayoutHeaderModeType,
|
||||||
LayoutType,
|
LayoutType,
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-icons/vue": "^1.0.0",
|
"@radix-icons/vue": "^1.0.0",
|
||||||
|
"@vben-core/colorful": "workspace:*",
|
||||||
"@vben-core/iconify": "workspace:*",
|
"@vben-core/iconify": "workspace:*",
|
||||||
"@vben-core/toolkit": "workspace:*",
|
"@vben-core/toolkit": "workspace:*",
|
||||||
"@vben-core/typings": "workspace:*",
|
"@vben-core/typings": "workspace:*",
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type { MenuRecordBadgeRaw } from '@vben-core/typings';
|
||||||
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { isValidColor } from '@vben-core/toolkit';
|
import { isValidColor } from '@vben-core/colorful';
|
||||||
|
|
||||||
import BadgeDot from './menu-badge-dot.vue';
|
import BadgeDot from './menu-badge-dot.vue';
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ export const badgeVariants = cva(
|
||||||
default:
|
default:
|
||||||
'border-transparent bg-accent hover:bg-accent text-primary-foreground shadow',
|
'border-transparent bg-accent hover:bg-accent text-primary-foreground shadow',
|
||||||
destructive:
|
destructive:
|
||||||
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
|
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive-hover',
|
||||||
outline: 'text-foreground',
|
outline: 'text-foreground',
|
||||||
secondary:
|
secondary:
|
||||||
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const buttonVariants = cva(
|
||||||
default:
|
default:
|
||||||
'bg-primary text-primary-foreground shadow hover:bg-primary/90',
|
'bg-primary text-primary-foreground shadow hover:bg-primary/90',
|
||||||
destructive:
|
destructive:
|
||||||
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive-hover',
|
||||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||||
heavy: 'hover:bg-heavy hover:text-heavy-foreground',
|
heavy: 'hover:bg-heavy hover:text-heavy-foreground',
|
||||||
icon: 'hover:bg-accent hover:text-accent-foreground text-foreground/80',
|
icon: 'hover:bg-accent hover:text-accent-foreground text-foreground/80',
|
||||||
|
|
|
@ -17,9 +17,7 @@ const appName = computed(() => preferences.app.name);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="flex min-h-full flex-1 select-none overflow-x-hidden">
|
||||||
class="bg-background flex min-h-full flex-1 select-none overflow-x-hidden"
|
|
||||||
>
|
|
||||||
<AuthenticationFromView
|
<AuthenticationFromView
|
||||||
v-if="authPanelLeft"
|
v-if="authPanelLeft"
|
||||||
class="-enter-x min-h-full w-2/5"
|
class="-enter-x min-h-full w-2/5"
|
||||||
|
@ -47,9 +45,7 @@ const appName = computed(() => preferences.app.name);
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!authPanelCenter" class="relative hidden w-0 flex-1 lg:block">
|
<div v-if="!authPanelCenter" class="relative hidden w-0 flex-1 lg:block">
|
||||||
<div
|
<div class="bg-authentication absolute inset-0 h-full w-full">
|
||||||
class="absolute inset-0 h-full w-full bg-[var(--color-authentication)]"
|
|
||||||
>
|
|
||||||
<div class="flex-col-center -enter-x mr-20 h-full">
|
<div class="flex-col-center -enter-x mr-20 h-full">
|
||||||
<SloganIcon :alt="appName" class="animate-float h-64 w-2/5" />
|
<SloganIcon :alt="appName" class="animate-float h-64 w-2/5" />
|
||||||
<div class="text-1xl mt-6 font-sans text-white lg:text-2xl">
|
<div class="text-1xl mt-6 font-sans text-white lg:text-2xl">
|
||||||
|
@ -61,10 +57,7 @@ const appName = computed(() => preferences.app.name);
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="authPanelCenter" class="flex-center bg-authentication w-full">
|
||||||
v-if="authPanelCenter"
|
|
||||||
class="flex-center w-full dark:bg-[var(--color-authentication)]"
|
|
||||||
>
|
|
||||||
<AuthenticationFromView
|
<AuthenticationFromView
|
||||||
class="enter-y md:bg-background w-full rounded-3xl pb-20 shadow-2xl md:w-2/3 lg:w-1/2 xl:w-2/5"
|
class="enter-y md:bg-background w-full rounded-3xl pb-20 shadow-2xl md:w-2/3 lg:w-1/2 xl:w-2/5"
|
||||||
>
|
>
|
||||||
|
|
|
@ -12,7 +12,7 @@ defineOptions({
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="flex-center bg-background absolute right-2 top-4 rounded-3xl px-3 py-1 dark:bg-[var(--color-authentication)]"
|
class="flex-center bg-accent absolute right-2 top-4 rounded-3xl px-3 py-1"
|
||||||
>
|
>
|
||||||
<div class="hidden md:flex">
|
<div class="hidden md:flex">
|
||||||
<AuthenticationColorToggle />
|
<AuthenticationColorToggle />
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
"@vben-core/design": "workspace:*"
|
"@vben-core/design": "workspace:*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vben-core/colorful": "workspace:*",
|
||||||
"@vben-core/design": "workspace:*",
|
"@vben-core/design": "workspace:*",
|
||||||
"@vben-core/iconify": "workspace:*",
|
"@vben-core/iconify": "workspace:*",
|
||||||
"@vben-core/preferences": "workspace:*",
|
"@vben-core/preferences": "workspace:*",
|
||||||
|
@ -49,7 +50,6 @@
|
||||||
"@vben/locales": "workspace:*",
|
"@vben/locales": "workspace:*",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"@vueuse/integrations": "^10.11.0",
|
"@vueuse/integrations": "^10.11.0",
|
||||||
"@vben/chart-ui": "workspace:*",
|
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"vue": "^3.4.30",
|
"vue": "^3.4.30",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.0"
|
||||||
|
|
|
@ -189,11 +189,12 @@ function handleGo(path: string) {
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="showForgetPassword"
|
v-if="showForgetPassword"
|
||||||
class="text-primary hover:text-primary/80 cursor-pointer text-sm font-normal"
|
class="text-primary hover:text-primary-hover active:text-primary-active cursor-pointer text-sm font-normal"
|
||||||
@click="handleGo(forgetPasswordPath)"
|
@click="handleGo(forgetPasswordPath)"
|
||||||
>
|
>
|
||||||
{{ $t('authentication.forget-password') }}
|
{{ $t('authentication.forget-password') }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- <VbenButton variant="ghost" @click="handleGo('/auth/forget-password')">
|
<!-- <VbenButton variant="ghost" @click="handleGo('/auth/forget-password')">
|
||||||
忘记密码?
|
忘记密码?
|
||||||
</VbenButton> -->
|
</VbenButton> -->
|
||||||
|
@ -235,7 +236,7 @@ function handleGo(path: string) {
|
||||||
<div v-if="showRegister" class="text-center text-sm">
|
<div v-if="showRegister" class="text-center text-sm">
|
||||||
{{ $t('authentication.account-tip') }}
|
{{ $t('authentication.account-tip') }}
|
||||||
<span
|
<span
|
||||||
class="text-primary hover:text-primary/80 cursor-pointer text-sm font-normal"
|
class="text-primary hover:text-primary-hover active:text-primary-active cursor-pointer text-sm font-normal"
|
||||||
@click="handleGo(registerPath)"
|
@click="handleGo(registerPath)"
|
||||||
>
|
>
|
||||||
{{ $t('authentication.create-account') }}
|
{{ $t('authentication.create-account') }}
|
||||||
|
|
|
@ -132,11 +132,11 @@ function goLogin() {
|
||||||
name="agreePolicy"
|
name="agreePolicy"
|
||||||
>
|
>
|
||||||
{{ $t('authentication.sign-up-agree') }}
|
{{ $t('authentication.sign-up-agree') }}
|
||||||
<span class="text-primary hover:text-primary/80">{{
|
<span class="text-primary hover:text-primary-hover">{{
|
||||||
$t('authentication.sign-up-privacy-policy')
|
$t('authentication.sign-up-privacy-policy')
|
||||||
}}</span>
|
}}</span>
|
||||||
&
|
&
|
||||||
<span class="text-primary hover:text-primary/80">
|
<span class="text-primary hover:text-primary-hover">
|
||||||
{{ $t('authentication.sign-up-terms') }}
|
{{ $t('authentication.sign-up-terms') }}
|
||||||
</span>
|
</span>
|
||||||
</VbenCheckbox>
|
</VbenCheckbox>
|
||||||
|
@ -158,7 +158,7 @@ function goLogin() {
|
||||||
<div class="mt-4 text-center text-sm">
|
<div class="mt-4 text-center text-sm">
|
||||||
{{ $t('authentication.already-account') }}
|
{{ $t('authentication.already-account') }}
|
||||||
<span
|
<span
|
||||||
class="text-primary hover:text-primary/80 cursor-pointer text-sm font-normal"
|
class="text-primary hover:text-primary-hover cursor-pointer text-sm font-normal"
|
||||||
@click="goLogin()"
|
@click="goLogin()"
|
||||||
>
|
>
|
||||||
{{ $t('authentication.go-login') }}
|
{{ $t('authentication.go-login') }}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { BuiltinThemeType } from '@vben/types';
|
||||||
|
|
||||||
import { IcRoundColorLens } from '@vben-core/iconify';
|
import { IcRoundColorLens } from '@vben-core/iconify';
|
||||||
import {
|
import {
|
||||||
COLOR_PRIMARY_RESETS,
|
COLOR_PRESETS,
|
||||||
preferences,
|
preferences,
|
||||||
updatePreferences,
|
updatePreferences,
|
||||||
} from '@vben-core/preferences';
|
} from '@vben-core/preferences';
|
||||||
|
@ -11,10 +13,10 @@ defineOptions({
|
||||||
name: 'AuthenticationColorToggle',
|
name: 'AuthenticationColorToggle',
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleUpdate(value: string) {
|
function handleUpdate(value: BuiltinThemeType) {
|
||||||
updatePreferences({
|
updatePreferences({
|
||||||
theme: {
|
theme: {
|
||||||
colorPrimary: value,
|
builtinType: value,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -23,22 +25,32 @@ function handleUpdate(value: string) {
|
||||||
<template>
|
<template>
|
||||||
<div class="group relative flex items-center overflow-hidden">
|
<div class="group relative flex items-center overflow-hidden">
|
||||||
<div
|
<div
|
||||||
class="ease-ou flex w-0 overflow-hidden transition-all duration-500 group-hover:w-48"
|
class="ease-ou flex w-0 overflow-hidden transition-all duration-500 group-hover:w-60"
|
||||||
>
|
>
|
||||||
<template v-for="color in COLOR_PRIMARY_RESETS" :key="color">
|
<template v-for="preset in COLOR_PRESETS" :key="preset.color">
|
||||||
<VbenIconButton
|
<VbenIconButton
|
||||||
class="flex-center flex-shrink-0"
|
class="flex-center flex-shrink-0"
|
||||||
@click="handleUpdate(color)"
|
@click="handleUpdate(preset.type)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:style="{ backgroundColor: preset.color }"
|
||||||
preferences.theme.colorPrimary === color
|
class="flex-center relative size-5 rounded-full hover:scale-110"
|
||||||
? `before:opacity-100`
|
>
|
||||||
: '',
|
<svg
|
||||||
]"
|
v-if="preferences.theme.builtinType === preset.type"
|
||||||
:style="{ backgroundColor: color }"
|
class="h-3.5 w-3.5 text-white"
|
||||||
class="relative h-3.5 w-3.5 rounded-[2px] before:absolute before:left-0.5 before:top-0.5 before:h-2.5 before:w-2.5 before:rounded-[2px] before:border before:border-gray-900 before:opacity-0 before:transition-all before:duration-150 before:content-[''] hover:scale-110"
|
height="1em"
|
||||||
></div>
|
viewBox="0 0 15 15"
|
||||||
|
width="1em"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M11.467 3.727c.289.189.37.576.181.865l-4.25 6.5a.625.625 0 0 1-.944.12l-2.75-2.5a.625.625 0 0 1 .841-.925l2.208 2.007l3.849-5.886a.625.625 0 0 1 .865-.181"
|
||||||
|
fill="currentColor"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
</VbenIconButton>
|
</VbenIconButton>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export * from './authentication';
|
export * from './authentication';
|
||||||
export * from './coze-assistant';
|
export * from './coze-assistant';
|
||||||
|
export * from './dashboard';
|
||||||
export * from './fallback';
|
export * from './fallback';
|
||||||
export * from './global-provider';
|
export * from './global-provider';
|
||||||
export * from './global-search';
|
export * from './global-search';
|
||||||
|
@ -8,4 +9,3 @@ export * from './notification';
|
||||||
export * from './preferences';
|
export * from './preferences';
|
||||||
export * from './theme-toggle';
|
export * from './theme-toggle';
|
||||||
export * from './user-dropdown';
|
export * from './user-dropdown';
|
||||||
export * from './dashboard';
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ export { default as Sidebar } from './layout/sidebar.vue';
|
||||||
export { default as Tabbar } from './layout/tabbar.vue';
|
export { default as Tabbar } from './layout/tabbar.vue';
|
||||||
export { default as GlobalShortcutKeys } from './shortcut-keys/global.vue';
|
export { default as GlobalShortcutKeys } from './shortcut-keys/global.vue';
|
||||||
export { default as SwitchItem } from './switch-item.vue';
|
export { default as SwitchItem } from './switch-item.vue';
|
||||||
export { default as ThemeColor } from './theme/color.vue';
|
export { default as BuiltinTheme } from './theme/builtin.vue';
|
||||||
export { default as ColorMode } from './theme/color-mode.vue';
|
export { default as ColorMode } from './theme/color-mode.vue';
|
||||||
|
export { default as Radius } from './theme/radius.vue';
|
||||||
export { default as Theme } from './theme/theme.vue';
|
export { default as Theme } from './theme/theme.vue';
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { BuiltinThemeType } from '@vben/types';
|
||||||
|
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
import { TinyColor, convertToHsl } from '@vben-core/colorful';
|
||||||
|
import { MdiEditBoxOutline } from '@vben-core/iconify';
|
||||||
|
import {
|
||||||
|
BUILT_IN_THEME_PRESETS,
|
||||||
|
type BuiltinThemePreset,
|
||||||
|
} from '@vben-core/preferences';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'PreferenceBuiltinTheme',
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{ isDark: boolean }>();
|
||||||
|
|
||||||
|
const colorInput = ref();
|
||||||
|
const modelValue = defineModel<BuiltinThemeType>({ default: 'default' });
|
||||||
|
const themeColorPrimary = defineModel<string>('themeColorPrimary');
|
||||||
|
|
||||||
|
const inputValue = computed(() => {
|
||||||
|
return new TinyColor(themeColorPrimary.value).toHexString();
|
||||||
|
});
|
||||||
|
|
||||||
|
function typeView(name: BuiltinThemeType) {
|
||||||
|
switch (name) {
|
||||||
|
case 'default': {
|
||||||
|
return $t('preferences.theme.default');
|
||||||
|
}
|
||||||
|
case 'violet': {
|
||||||
|
return $t('preferences.theme.violet');
|
||||||
|
}
|
||||||
|
case 'pink': {
|
||||||
|
return $t('preferences.theme.pink');
|
||||||
|
}
|
||||||
|
case 'rose': {
|
||||||
|
return $t('preferences.theme.rose');
|
||||||
|
}
|
||||||
|
case 'sky-blue': {
|
||||||
|
return $t('preferences.theme.sky-blue');
|
||||||
|
}
|
||||||
|
case 'deep-blue': {
|
||||||
|
return $t('preferences.theme.deep-blue');
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'green': {
|
||||||
|
return $t('preferences.theme.green');
|
||||||
|
}
|
||||||
|
case 'deep-green': {
|
||||||
|
return $t('preferences.theme.deep-green');
|
||||||
|
}
|
||||||
|
case 'orange': {
|
||||||
|
return $t('preferences.theme.orange');
|
||||||
|
}
|
||||||
|
case 'yellow': {
|
||||||
|
return $t('preferences.theme.yellow');
|
||||||
|
}
|
||||||
|
case 'zinc': {
|
||||||
|
return $t('preferences.theme.zinc');
|
||||||
|
}
|
||||||
|
case 'neutral': {
|
||||||
|
return $t('preferences.theme.neutral');
|
||||||
|
}
|
||||||
|
case 'slate': {
|
||||||
|
return $t('preferences.theme.slate');
|
||||||
|
}
|
||||||
|
case 'gray': {
|
||||||
|
return $t('preferences.theme.gray');
|
||||||
|
}
|
||||||
|
case 'custom': {
|
||||||
|
return $t('preferences.theme.custom');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelect(theme: BuiltinThemePreset) {
|
||||||
|
modelValue.value = theme.type;
|
||||||
|
const primaryColor = props.isDark
|
||||||
|
? theme.darkPrimaryColor || theme.primaryColor
|
||||||
|
: theme.primaryColor;
|
||||||
|
|
||||||
|
themeColorPrimary.value = primaryColor || theme.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleInputChange(e: Event) {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
themeColorPrimary.value = convertToHsl(target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectColor() {
|
||||||
|
colorInput.value?.[0]?.click?.();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex w-full flex-wrap justify-between">
|
||||||
|
<template v-for="theme in BUILT_IN_THEME_PRESETS" :key="theme.type">
|
||||||
|
<div class="flex cursor-pointer flex-col" @click="handleSelect(theme)">
|
||||||
|
<div
|
||||||
|
:class="{
|
||||||
|
'outline-box-active': theme.type === modelValue,
|
||||||
|
}"
|
||||||
|
class="outline-box flex-center group cursor-pointer"
|
||||||
|
>
|
||||||
|
<template v-if="theme.type !== 'custom'">
|
||||||
|
<div
|
||||||
|
:style="{ backgroundColor: theme.color }"
|
||||||
|
class="mx-10 my-2 size-5 rounded-md"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="size-full px-10 py-2" @click.stop="selectColor">
|
||||||
|
<div class="flex-center relative size-5 rounded-sm">
|
||||||
|
<MdiEditBoxOutline
|
||||||
|
class="absolute z-10 size-5 opacity-60 group-hover:opacity-100"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
ref="colorInput"
|
||||||
|
:value="inputValue"
|
||||||
|
class="absolute inset-0 opacity-0"
|
||||||
|
type="color"
|
||||||
|
@input="handleInputChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="text-muted-foreground my-2 text-center text-xs">
|
||||||
|
{{ typeView(theme.type) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,90 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import type { CSSProperties } from 'vue';
|
|
||||||
import { computed, ref, watch, watchEffect } from 'vue';
|
|
||||||
|
|
||||||
import { MdiEditBoxOutline } from '@vben-core/iconify';
|
|
||||||
import { TinyColor, convertToHsl } from '@vben-core/toolkit';
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
name: 'PreferenceColor',
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
|
|
||||||
colorPrimaryPresets: () => [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const colorInput = ref();
|
|
||||||
const currentColor = ref(props.colorPrimaryPresets?.[0]);
|
|
||||||
|
|
||||||
const modelValue = defineModel<string>();
|
|
||||||
|
|
||||||
const activeColor = computed((): CSSProperties => {
|
|
||||||
return {
|
|
||||||
outlineColor: currentColor.value,
|
|
||||||
outlineWidth: '2px',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
function isActive(color: string): string[] {
|
|
||||||
return color === currentColor.value ? ['outline-box-active'] : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputStyle = computed((): CSSProperties => {
|
|
||||||
return props.colorPrimaryPresets.includes(currentColor.value)
|
|
||||||
? {}
|
|
||||||
: activeColor.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
const inputValue = computed(() => {
|
|
||||||
return new TinyColor(modelValue.value).toHexString();
|
|
||||||
});
|
|
||||||
|
|
||||||
function selectColor() {
|
|
||||||
colorInput.value.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleInputChange(e: Event) {
|
|
||||||
const target = e.target as HTMLInputElement;
|
|
||||||
modelValue.value = convertToHsl(target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听颜色变化,转成系统可识别的 hsl 格式
|
|
||||||
watch(currentColor, (val) => {
|
|
||||||
modelValue.value = convertToHsl(val);
|
|
||||||
});
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
if (modelValue.value) {
|
|
||||||
currentColor.value = modelValue.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex w-full flex-wrap justify-between">
|
|
||||||
<template v-for="color in colorPrimaryPresets" :key="color">
|
|
||||||
<div
|
|
||||||
:class="isActive(color)"
|
|
||||||
class="outline-box p-2"
|
|
||||||
@click="currentColor = color"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
:style="{ backgroundColor: color }"
|
|
||||||
class="h-5 w-5 rounded-md"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div :style="inputStyle" class="outline-box p-2" @click="selectColor">
|
|
||||||
<div class="flex-center bg-accent relative h-5 w-5 rounded-md">
|
|
||||||
<MdiEditBoxOutline class="absolute z-10" />
|
|
||||||
<input
|
|
||||||
ref="colorInput"
|
|
||||||
:value="inputValue"
|
|
||||||
class="absolute inset-0 opacity-0"
|
|
||||||
type="color"
|
|
||||||
@input="handleInputChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ToggleGroup, ToggleGroupItem } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'PreferenceColorMode',
|
||||||
|
});
|
||||||
|
|
||||||
|
const modelValue = defineModel<string | undefined>('themeRadius', {
|
||||||
|
default: '0.5',
|
||||||
|
});
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{ label: '0', value: '0' },
|
||||||
|
{ label: '0.25', value: '0.25' },
|
||||||
|
{ label: '0.5', value: '0.5' },
|
||||||
|
{ label: '0.75', value: '0.75' },
|
||||||
|
{ label: '1', value: '1' },
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ToggleGroup
|
||||||
|
v-model="modelValue"
|
||||||
|
class="gap-2"
|
||||||
|
size="sm"
|
||||||
|
type="single"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
<template v-for="item in items" :key="item.value">
|
||||||
|
<ToggleGroupItem
|
||||||
|
:value="item.value"
|
||||||
|
class="data-[state=on]:bg-primary data-[state=on]:text-primary-foreground h-7 w-16 rounded-sm"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</ToggleGroupItem>
|
||||||
|
</template>
|
||||||
|
</ToggleGroup>
|
||||||
|
</template>
|
|
@ -1,4 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { ThemeModeType } from '@vben-core/preferences';
|
||||||
|
|
||||||
|
import type { Component } from 'vue';
|
||||||
|
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import {
|
import {
|
||||||
IcRoundMotionPhotosAuto,
|
IcRoundMotionPhotosAuto,
|
||||||
|
@ -17,7 +21,7 @@ const appSemiDarkMenu = defineModel<boolean>('appSemiDarkMenu', {
|
||||||
default: true,
|
default: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const THEME_PRESET = [
|
const THEME_PRESET: Array<{ icon: Component; name: ThemeModeType }> = [
|
||||||
{
|
{
|
||||||
icon: IcRoundWbSunny,
|
icon: IcRoundWbSunny,
|
||||||
name: 'light',
|
name: 'light',
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M19.9 12.66a1 1 0 0 1 0-1.32l1.28-1.44a1 1 0 0 0 .12-1.17l-2-3.46a1 1 0 0 0-1.07-.48l-1.88.38a1 1 0 0 1-1.15-.66l-.61-1.83a1 1 0 0 0-.95-.68h-4a1 1 0 0 0-1 .68l-.56 1.83a1 1 0 0 1-1.15.66L5 4.79a1 1 0 0 0-1 .48L2 8.73a1 1 0 0 0 .1 1.17l1.27 1.44a1 1 0 0 1 0 1.32L2.1 14.1a1 1 0 0 0-.1 1.17l2 3.46a1 1 0 0 0 1.07.48l1.88-.38a1 1 0 0 1 1.15.66l.61 1.83a1 1 0 0 0 1 .68h4a1 1 0 0 0 .95-.68l.61-1.83a1 1 0 0 1 1.15-.66l1.88.38a1 1 0 0 0 1.07-.48l2-3.46a1 1 0 0 0-.12-1.17ZM18.41 14l.8.9l-1.28 2.22l-1.18-.24a3 3 0 0 0-3.45 2L12.92 20h-2.56L10 18.86a3 3 0 0 0-3.45-2l-1.18.24l-1.3-2.21l.8-.9a3 3 0 0 0 0-4l-.8-.9l1.28-2.2l1.18.24a3 3 0 0 0 3.45-2L10.36 4h2.56l.38 1.14a3 3 0 0 0 3.45 2l1.18-.24l1.28 2.22l-.8.9a3 3 0 0 0 0 3.98m-6.77-6a4 4 0 1 0 4 4a4 4 0 0 0-4-4m0 6a2 2 0 1 1 2-2a2 2 0 0 1-2 2"
|
d="M19.9 12.66a1 1 0 0 1 0-1.32l1.28-1.44a1 1 0 0 0 .12-1.17l-2-3.46a1 1 0 0 0-1.07-.48l-1.88.38a1 1 0 0 1-1.15-.66l-.61-1.83a1 1 0 0 0-.95-.68h-4a1 1 0 0 0-1 .68l-.56 1.83a1 1 0 0 1-1.15.66L5 4.79a1 1 0 0 0-1 .48L2 8.73a1 1 0 0 0 .1 1.17l1.27 1.44a1 1 0 0 1 0 1.32L2.1 14.1a1 1 0 0 0-.1 1.17l2 3.46a1 1 0 0 0 1.07.48l1.88-.38a1 1 0 0 1 1.15.66l.61 1.83a1 1 0 0 0 1 .68h4a1 1 0 0 0 .95-.68l.61-1.83a1 1 0 0 1 1.15-.66l1.88.38a1 1 0 0 0 1.07-.48l2-3.46a1 1 0 0 0-.12-1.17ZM18.41 14l.8.9l-1.28 2.22l-1.18-.24a3 3 0 0 0-3.45 2L12.92 20h-2.56L10 18.86a3 3 0 0 0-3.45-2l-1.18.24l-1.3-2.21l.8-.9a3 3 0 0 0 0-4l-.8-.9l1.28-2.2l1.18.24a3 3 0 0 0 3.45-2L10.36 4h2.56l.38 1.14a3 3 0 0 0 3.45 2l1.18-.24l1.28 2.22l-.8.9a3 3 0 0 0 0 3.98m-6.77-6a4 4 0 1 0 4 4a4 4 0 0 0-4-4m0 6a2 2 0 1 1 2-2a2 2 0 0 1-2 2"
|
||||||
fill="white"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { loadLocaleMessages } from '@vben/locales';
|
import { loadLocaleMessages } from '@vben/locales';
|
||||||
import {
|
import { preferences, updatePreferences } from '@vben-core/preferences';
|
||||||
COLOR_PRIMARY_RESETS,
|
|
||||||
preferences,
|
|
||||||
updatePreferences,
|
|
||||||
} from '@vben-core/preferences';
|
|
||||||
|
|
||||||
import Preferences from './preferences.vue';
|
import Preferences from './preferences.vue';
|
||||||
</script>
|
</script>
|
||||||
|
@ -18,13 +14,11 @@ import Preferences from './preferences.vue';
|
||||||
:app-layout="preferences.app.layout"
|
:app-layout="preferences.app.layout"
|
||||||
:app-locale="preferences.app.locale"
|
:app-locale="preferences.app.locale"
|
||||||
:app-semi-dark-menu="preferences.app.semiDarkMenu"
|
:app-semi-dark-menu="preferences.app.semiDarkMenu"
|
||||||
:app-theme-mode="preferences.app.themeMode"
|
|
||||||
:breadcrumb-enable="preferences.breadcrumb.enable"
|
:breadcrumb-enable="preferences.breadcrumb.enable"
|
||||||
:breadcrumb-hide-only-one="preferences.breadcrumb.hideOnlyOne"
|
:breadcrumb-hide-only-one="preferences.breadcrumb.hideOnlyOne"
|
||||||
:breadcrumb-home="preferences.breadcrumb.showHome"
|
:breadcrumb-home="preferences.breadcrumb.showHome"
|
||||||
:breadcrumb-icon="preferences.breadcrumb.showIcon"
|
:breadcrumb-icon="preferences.breadcrumb.showIcon"
|
||||||
:breadcrumb-style-type="preferences.breadcrumb.styleType"
|
:breadcrumb-style-type="preferences.breadcrumb.styleType"
|
||||||
:color-primary-presets="COLOR_PRIMARY_RESETS"
|
|
||||||
:footer-enable="preferences.footer.enable"
|
:footer-enable="preferences.footer.enable"
|
||||||
:footer-fixed="preferences.footer.fixed"
|
:footer-fixed="preferences.footer.fixed"
|
||||||
:header-enable="preferences.header.enable"
|
:header-enable="preferences.header.enable"
|
||||||
|
@ -43,7 +37,10 @@ import Preferences from './preferences.vue';
|
||||||
:sidebar-enable="preferences.sidebar.enable"
|
:sidebar-enable="preferences.sidebar.enable"
|
||||||
:tabbar-enable="preferences.tabbar.enable"
|
:tabbar-enable="preferences.tabbar.enable"
|
||||||
:tabbar-show-icon="preferences.tabbar.showIcon"
|
:tabbar-show-icon="preferences.tabbar.showIcon"
|
||||||
|
:theme-builtin-type="preferences.theme.builtinType"
|
||||||
:theme-color-primary="preferences.theme.colorPrimary"
|
:theme-color-primary="preferences.theme.colorPrimary"
|
||||||
|
:theme-mode="preferences.theme.mode"
|
||||||
|
:theme-radius="preferences.theme.radius"
|
||||||
:transition-enable="preferences.transition.enable"
|
:transition-enable="preferences.transition.enable"
|
||||||
:transition-name="preferences.transition.name"
|
:transition-name="preferences.transition.name"
|
||||||
:transition-progress="preferences.transition.progress"
|
:transition-progress="preferences.transition.progress"
|
||||||
|
@ -72,9 +69,6 @@ import Preferences from './preferences.vue';
|
||||||
@update:app-semi-dark-menu="
|
@update:app-semi-dark-menu="
|
||||||
(val) => updatePreferences({ app: { semiDarkMenu: val } })
|
(val) => updatePreferences({ app: { semiDarkMenu: val } })
|
||||||
"
|
"
|
||||||
@update:app-theme-mode="
|
|
||||||
(val) => updatePreferences({ app: { themeMode: val } })
|
|
||||||
"
|
|
||||||
@update:breadcrumb-enable="
|
@update:breadcrumb-enable="
|
||||||
(val) => updatePreferences({ breadcrumb: { enable: val } })
|
(val) => updatePreferences({ breadcrumb: { enable: val } })
|
||||||
"
|
"
|
||||||
|
@ -136,9 +130,16 @@ import Preferences from './preferences.vue';
|
||||||
@update:tabbar-show-icon="
|
@update:tabbar-show-icon="
|
||||||
(val) => updatePreferences({ tabbar: { showIcon: val } })
|
(val) => updatePreferences({ tabbar: { showIcon: val } })
|
||||||
"
|
"
|
||||||
|
@update:theme-builtin-type="
|
||||||
|
(val) => updatePreferences({ theme: { builtinType: val } })
|
||||||
|
"
|
||||||
@update:theme-color-primary="
|
@update:theme-color-primary="
|
||||||
(val) => updatePreferences({ theme: { colorPrimary: val } })
|
(val) => updatePreferences({ theme: { colorPrimary: val } })
|
||||||
"
|
"
|
||||||
|
@update:theme-mode="(val) => updatePreferences({ theme: { mode: val } })"
|
||||||
|
@update:theme-radius="
|
||||||
|
(val) => updatePreferences({ theme: { radius: val } })
|
||||||
|
"
|
||||||
@update:transition-enable="
|
@update:transition-enable="
|
||||||
(val) => updatePreferences({ transition: { enable: val } })
|
(val) => updatePreferences({ transition: { enable: val } })
|
||||||
"
|
"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {
|
import type {
|
||||||
|
BuiltinThemeType,
|
||||||
ContentCompactType,
|
ContentCompactType,
|
||||||
LayoutHeaderModeType,
|
LayoutHeaderModeType,
|
||||||
LayoutType,
|
LayoutType,
|
||||||
|
@ -35,6 +36,7 @@ import {
|
||||||
Animation,
|
Animation,
|
||||||
Block,
|
Block,
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
|
BuiltinTheme,
|
||||||
ColorMode,
|
ColorMode,
|
||||||
Content,
|
Content,
|
||||||
Footer,
|
Footer,
|
||||||
|
@ -43,19 +45,14 @@ import {
|
||||||
Header,
|
Header,
|
||||||
Layout,
|
Layout,
|
||||||
Navigation,
|
Navigation,
|
||||||
|
Radius,
|
||||||
Sidebar,
|
Sidebar,
|
||||||
Tabbar,
|
Tabbar,
|
||||||
Theme,
|
Theme,
|
||||||
ThemeColor,
|
|
||||||
} from './blocks';
|
} from './blocks';
|
||||||
import Trigger from './trigger.vue';
|
import Trigger from './trigger.vue';
|
||||||
import { useOpenPreferences } from './use-open-preferences';
|
import { useOpenPreferences } from './use-open-preferences';
|
||||||
|
|
||||||
withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
|
|
||||||
colorPrimaryPresets: () => [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const appThemeMode = defineModel<ThemeModeType>('appThemeMode');
|
|
||||||
const appLocale = defineModel<SupportedLanguagesType>('appLocale');
|
const appLocale = defineModel<SupportedLanguagesType>('appLocale');
|
||||||
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
|
const appDynamicTitle = defineModel<boolean>('appDynamicTitle');
|
||||||
const appAiAssistant = defineModel<boolean>('appAiAssistant');
|
const appAiAssistant = defineModel<boolean>('appAiAssistant');
|
||||||
|
@ -70,6 +67,9 @@ const transitionName = defineModel<string>('transitionName');
|
||||||
const transitionEnable = defineModel<boolean>('transitionEnable');
|
const transitionEnable = defineModel<boolean>('transitionEnable');
|
||||||
|
|
||||||
const themeColorPrimary = defineModel<string>('themeColorPrimary');
|
const themeColorPrimary = defineModel<string>('themeColorPrimary');
|
||||||
|
const themeBuiltinType = defineModel<BuiltinThemeType>('themeBuiltinType');
|
||||||
|
const themeMode = defineModel<ThemeModeType>('themeMode');
|
||||||
|
const themeRadius = defineModel<string>('themeRadius');
|
||||||
|
|
||||||
const sidebarEnable = defineModel<boolean>('sidebarEnable');
|
const sidebarEnable = defineModel<boolean>('sidebarEnable');
|
||||||
const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
|
const sidebarCollapsed = defineModel<boolean>('sidebarCollapsed');
|
||||||
|
@ -115,6 +115,7 @@ const shortcutKeysGlobalPreferences = defineModel<boolean>(
|
||||||
|
|
||||||
const {
|
const {
|
||||||
diffPreference,
|
diffPreference,
|
||||||
|
isDark,
|
||||||
isFullContent,
|
isFullContent,
|
||||||
isHeaderNav,
|
isHeaderNav,
|
||||||
isMixedNav,
|
isMixedNav,
|
||||||
|
@ -124,14 +125,10 @@ const {
|
||||||
} = usePreferences();
|
} = usePreferences();
|
||||||
const { copy } = useClipboard();
|
const { copy } = useClipboard();
|
||||||
|
|
||||||
const activeTab = ref('general');
|
const activeTab = ref('appearance');
|
||||||
|
|
||||||
const tabs = computed((): SegmentedItem[] => {
|
const tabs = computed((): SegmentedItem[] => {
|
||||||
return [
|
return [
|
||||||
{
|
|
||||||
label: $t('preferences.general'),
|
|
||||||
value: 'general',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: $t('preferences.appearance'),
|
label: $t('preferences.appearance'),
|
||||||
value: 'appearance',
|
value: 'appearance',
|
||||||
|
@ -140,11 +137,14 @@ const tabs = computed((): SegmentedItem[] => {
|
||||||
label: $t('preferences.layout'),
|
label: $t('preferences.layout'),
|
||||||
value: 'layout',
|
value: 'layout',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: $t('preferences.shortcut-keys.title'),
|
label: $t('preferences.shortcut-keys.title'),
|
||||||
value: 'shortcutKey',
|
value: 'shortcutKey',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: $t('preferences.general'),
|
||||||
|
value: 'general',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -200,18 +200,45 @@ function handleReset() {
|
||||||
|
|
||||||
<div class="p-4 pt-4">
|
<div class="p-4 pt-4">
|
||||||
<VbenSegmented v-model="activeTab" :tabs="tabs">
|
<VbenSegmented v-model="activeTab" :tabs="tabs">
|
||||||
|
<template #general>
|
||||||
|
<Block :title="$t('preferences.general')">
|
||||||
|
<General
|
||||||
|
v-model:app-ai-assistant="appAiAssistant"
|
||||||
|
v-model:app-dynamic-title="appDynamicTitle"
|
||||||
|
v-model:app-locale="appLocale"
|
||||||
|
/>
|
||||||
|
</Block>
|
||||||
|
|
||||||
|
<Block :title="$t('preferences.animation')">
|
||||||
|
<Animation
|
||||||
|
v-model:transition-enable="transitionEnable"
|
||||||
|
v-model:transition-name="transitionName"
|
||||||
|
v-model:transition-progress="transitionProgress"
|
||||||
|
/>
|
||||||
|
</Block>
|
||||||
|
</template>
|
||||||
<template #appearance>
|
<template #appearance>
|
||||||
<Block :title="$t('preferences.theme')">
|
<Block :title="$t('preferences.theme.name')">
|
||||||
<Theme
|
<Theme
|
||||||
v-model="appThemeMode"
|
v-model="themeMode"
|
||||||
v-model:app-semi-dark-menu="appSemiDarkMenu"
|
v-model:app-semi-dark-menu="appSemiDarkMenu"
|
||||||
/>
|
/>
|
||||||
</Block>
|
</Block>
|
||||||
<Block :title="$t('preferences.theme-color')">
|
<!-- <Block :title="$t('preferences.theme-color')">
|
||||||
<ThemeColor
|
<ThemeColor
|
||||||
v-model="themeColorPrimary"
|
v-model="themeColorPrimary"
|
||||||
:color-primary-presets="colorPrimaryPresets"
|
:color-primary-presets="colorPrimaryPresets"
|
||||||
/>
|
/>
|
||||||
|
</Block> -->
|
||||||
|
<Block :title="$t('preferences.theme.builtin')">
|
||||||
|
<BuiltinTheme
|
||||||
|
v-model="themeBuiltinType"
|
||||||
|
v-model:theme-color-primary="themeColorPrimary"
|
||||||
|
:is-dark="isDark"
|
||||||
|
/>
|
||||||
|
</Block>
|
||||||
|
<Block :title="$t('preferences.theme.radius')">
|
||||||
|
<Radius v-model="themeRadius" />
|
||||||
</Block>
|
</Block>
|
||||||
<Block :title="$t('preferences.other')">
|
<Block :title="$t('preferences.other')">
|
||||||
<ColorMode
|
<ColorMode
|
||||||
|
@ -281,23 +308,7 @@ function handleReset() {
|
||||||
/>
|
/>
|
||||||
</Block>
|
</Block>
|
||||||
</template>
|
</template>
|
||||||
<template #general>
|
|
||||||
<Block :title="$t('preferences.general')">
|
|
||||||
<General
|
|
||||||
v-model:app-ai-assistant="appAiAssistant"
|
|
||||||
v-model:app-dynamic-title="appDynamicTitle"
|
|
||||||
v-model:app-locale="appLocale"
|
|
||||||
/>
|
|
||||||
</Block>
|
|
||||||
|
|
||||||
<Block :title="$t('preferences.animation')">
|
|
||||||
<Animation
|
|
||||||
v-model:transition-enable="transitionEnable"
|
|
||||||
v-model:transition-name="transitionName"
|
|
||||||
v-model:transition-progress="transitionProgress"
|
|
||||||
/>
|
|
||||||
</Block>
|
|
||||||
</template>
|
|
||||||
<template #shortcutKey>
|
<template #shortcutKey>
|
||||||
<Block :title="$t('preferences.shortcut-keys.global')">
|
<Block :title="$t('preferences.shortcut-keys.global')">
|
||||||
<GlobalShortcutKeys
|
<GlobalShortcutKeys
|
||||||
|
|
|
@ -14,6 +14,8 @@ defineOptions({
|
||||||
:title="$t('preferences.name')"
|
:title="$t('preferences.name')"
|
||||||
class="bg-primary flex-col-center h-12 w-12 cursor-pointer rounded-l-lg rounded-r-none border-none"
|
class="bg-primary flex-col-center h-12 w-12 cursor-pointer rounded-l-lg rounded-r-none border-none"
|
||||||
>
|
>
|
||||||
<IconSetting class="duration-3000 animate-spin text-2xl" />
|
<IconSetting
|
||||||
|
class="duration-3000 fill-primary-foreground animate-spin text-2xl"
|
||||||
|
/>
|
||||||
</VbenButton>
|
</VbenButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -29,7 +29,7 @@ withDefaults(defineProps<{ shouldOnHover?: boolean }>(), {
|
||||||
|
|
||||||
function handleChange(isDark: boolean) {
|
function handleChange(isDark: boolean) {
|
||||||
updatePreferences({
|
updatePreferences({
|
||||||
app: { themeMode: isDark ? 'dark' : 'light' },
|
theme: { mode: isDark ? 'dark' : 'light' },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +64,12 @@ const PRESETS = [
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<ToggleGroup
|
<ToggleGroup
|
||||||
:model-value="preferences.app.themeMode"
|
:model-value="preferences.theme.mode"
|
||||||
class="gap-2"
|
class="gap-2"
|
||||||
type="single"
|
type="single"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
(val) =>
|
(val) => updatePreferences({ theme: { mode: val as ThemeModeType } })
|
||||||
updatePreferences({ app: { themeMode: val as ThemeModeType } })
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<ToggleGroupItem
|
<ToggleGroupItem
|
||||||
|
|
|
@ -121,7 +121,6 @@ preferences:
|
||||||
name: Preferences
|
name: Preferences
|
||||||
subtitle: Customize Preferences & Preview in Real Time
|
subtitle: Customize Preferences & Preview in Real Time
|
||||||
reset-tip: The data has changed, click to reset
|
reset-tip: The data has changed, click to reset
|
||||||
theme: Theme
|
|
||||||
ai-assistant: Ai Assistant
|
ai-assistant: Ai Assistant
|
||||||
appearance: Appearance
|
appearance: Appearance
|
||||||
theme-color: Theme Color
|
theme-color: Theme Color
|
||||||
|
@ -181,6 +180,25 @@ preferences:
|
||||||
tabs-icon: Display Tabbar Icon
|
tabs-icon: Display Tabbar Icon
|
||||||
mode: Mode
|
mode: Mode
|
||||||
logo-visible: Display Logo
|
logo-visible: Display Logo
|
||||||
|
theme:
|
||||||
|
name: Theme
|
||||||
|
builtin: Built-in
|
||||||
|
radius: Radius
|
||||||
|
default: Default
|
||||||
|
violet: Violet
|
||||||
|
pink: Pink
|
||||||
|
rose: Rose
|
||||||
|
sky-blue: Sky Blue
|
||||||
|
deep-blue: Deep Blue
|
||||||
|
green: Green
|
||||||
|
deep-green: Deep Green
|
||||||
|
orange: Orange
|
||||||
|
yellow: Yellow
|
||||||
|
zinc: Zinc
|
||||||
|
neutral: Neutral
|
||||||
|
slate: Slate
|
||||||
|
gray: Gray
|
||||||
|
custom: Custom
|
||||||
header:
|
header:
|
||||||
name: Header
|
name: Header
|
||||||
visible: Display Header
|
visible: Display Header
|
||||||
|
|
|
@ -120,7 +120,6 @@ preferences:
|
||||||
name: 偏好设置
|
name: 偏好设置
|
||||||
subtitle: 自定义偏好设置 & 实时预览
|
subtitle: 自定义偏好设置 & 实时预览
|
||||||
reset-tip: 数据有变化,点击可进行重置
|
reset-tip: 数据有变化,点击可进行重置
|
||||||
theme: 主题
|
|
||||||
appearance: 外观
|
appearance: 外观
|
||||||
theme-color: 主题色
|
theme-color: 主题色
|
||||||
layout: 布局
|
layout: 布局
|
||||||
|
@ -180,6 +179,25 @@ preferences:
|
||||||
tabs-icon: 显示标签栏图标
|
tabs-icon: 显示标签栏图标
|
||||||
mode: 模式
|
mode: 模式
|
||||||
logo-visible: 显示 Logo
|
logo-visible: 显示 Logo
|
||||||
|
theme:
|
||||||
|
name: 主题
|
||||||
|
builtin: 内置主题
|
||||||
|
radius: 圆角
|
||||||
|
default: 默认
|
||||||
|
violet: 紫罗兰
|
||||||
|
pink: 樱花粉
|
||||||
|
rose: 玫瑰红
|
||||||
|
sky-blue: 天蓝色
|
||||||
|
deep-blue: 深蓝色
|
||||||
|
green: 浅绿色
|
||||||
|
deep-green: 深绿色
|
||||||
|
orange: 橙黄色
|
||||||
|
yellow: 柠檬黄
|
||||||
|
zinc: 锌色灰
|
||||||
|
neutral: 中性色
|
||||||
|
slate: 石板灰
|
||||||
|
gray: 中灰色
|
||||||
|
custom: 自定义
|
||||||
header:
|
header:
|
||||||
name: 顶栏
|
name: 顶栏
|
||||||
mode-static: 静止
|
mode-static: 静止
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
:root.dark {
|
|
||||||
/* authentication */
|
|
||||||
--color-authentication: hsl(240deg 11% 2%);
|
|
||||||
}
|
|
|
@ -5,5 +5,4 @@
|
||||||
'Segoe UI Symbol';
|
'Segoe UI Symbol';
|
||||||
|
|
||||||
/* authentication */
|
/* authentication */
|
||||||
--color-authentication: hsl(231deg 61% 44%);
|
|
||||||
}
|
}
|
||||||
|
|
2174
pnpm-lock.yaml
2174
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -60,6 +60,10 @@
|
||||||
"name": "@vben-core/cache",
|
"name": "@vben-core/cache",
|
||||||
"path": "packages/@core/shared/cache",
|
"path": "packages/@core/shared/cache",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "@vben-core/colorful",
|
||||||
|
"path": "packages/@core/shared/colorful",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "@vben-core/design",
|
"name": "@vben-core/design",
|
||||||
"path": "packages/@core/shared/design",
|
"path": "packages/@core/shared/design",
|
||||||
|
|
Loading…
Reference in New Issue