import React, { useState } from "react";
import { ConfigProvider, Space, Tooltip } from 'antd';
import { ThemeConfig } from "antd/es/config-provider";
import { ThemeType } from '@/interfaces/interfaces';
import {
CheckOutlined,
} from '@ant-design/icons';
import store from '@/store';
//主题色组件接口接参类型类型
export interface ThemeSelectionProps {
themeColor: string,
colorName: string,
data?: ThemeType
}
//主题色组件 (该组件在使用时需在使用处最外层限定高度)
export function ThemeSelection(c: ThemeSelectionProps[]) {
const [selection, setSelection] = useState<string>(c[0].colorName)
return (
<>
<Space>
{
c.map((item: ThemeSelectionProps) => {
return (
<Tooltip key={item.themeColor} title={item.colorName}>
<div
style={{
backgroundColor: item.themeColor,
textAlign: "center",
width: "20px",
height: "20px",
cursor: "pointer",
}}
onClick={() => {
setSelection(item.colorName)
//采用了状态共享(https://www.npmjs.com/package/rekv)
store.setState({ colorData: item.data })
}}>
{item.colorName == selection &&
<CheckOutlined style={{ color: "white" }} />
}
</div>
</Tooltip>
)
})
}
</Space>
</>
)
}
//自定义ui组件主题接口接类型
interface ComponentTokenProps {
name: string,
componentToken: ThemeConfig
}
//主题色包裹 (原理:将需要换肤的组件传入,借助高阶组件优势,使其在传入组件外套一层ConfigProvider 借助antd5中的token属性实现样式控制)
//参数t有三种情况
//1.不传参数时组件采用 defaultTheme 值 使用场景:全局组件和局部组件的主题统一不冲突的情况。
//2.传参 string时(不能传空字符串,使用空字符串则会直接使用 defaultTheme 值),需要先在themeData 中定义组件名字(优先采用antd组件名称)和需要用到的ThemeConfig属性 使用场景:多个组件样式不统一的情况下
//3.直接传参 具有ThemeConfig 属性的值
export function ThemeControl(jsx: JSX.Element, t?: ThemeConfig | string) {
//采用了状态共享(https://www.npmjs.com/package/rekv)
const { colorData } = store.useState('colorData');
const defaultTheme: ThemeConfig = {
token: {
colorPrimary: "#ffffff",
colorBgContainer: colorData.sidebarOnebg,
colorText: colorData.modulehrbj,
motionDurationSlow: "0.3s",
controlItemBgActive: colorData.themebg,
colorBgElevated: colorData.sidebarTwobg,
}
}
const themeData: ComponentTokenProps[] = [
{
name: "Menu",
componentToken: {
token: {
colorPrimary: "#ffffff",
colorBgContainer: colorData.sidebarOnebg,
colorText: colorData.modulehrbj,
motionDurationSlow: "0.3s",
controlItemBgActive: colorData.themebg,
colorBgElevated: colorData.sidebarTwobg,
},
components: {
Menu: {
subMenuItemBg: colorData.sidebarTwobg,
itemSelectedBg: colorData.topbg,
popupBg: colorData.sidebarTwobg,
itemHoverBg: colorData.topbg,
collapsedWidth: 56,
iconSize: 18,
collapsedIconSize: 18,
}
}
}
},
{
name: "Modal",
componentToken: {
components: {
Modal: {
titleColor: colorData.themebg
}
}
}
}
]
const ComponentTheme = (data: ComponentTokenProps[], token?: ThemeConfig | string) => {
switch (typeof (token)) {
case "string":
return data.find((item: ComponentTokenProps) => {
return item.name === token ? item : ""
})?.componentToken
case "object":
return token
default:
return defaultTheme
}
}
return <>
<ConfigProvider
theme={ComponentTheme(themeData, t) || defaultTheme}
>
{jsx}
</ConfigProvider>
</>
}