This commit is contained in:
bietiaop
2025-02-09 00:47:00 +08:00
parent 024a3eb760
commit 7ce04cf781
6 changed files with 461 additions and 146 deletions

View File

@@ -13,6 +13,7 @@
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0", "@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2", "@dnd-kit/utilities": "^3.2.2",
"@heroui/accordion": "^2.2.8",
"@heroui/avatar": "2.2.7", "@heroui/avatar": "2.2.7",
"@heroui/breadcrumbs": "2.2.7", "@heroui/breadcrumbs": "2.2.7",
"@heroui/button": "2.2.10", "@heroui/button": "2.2.10",

View File

@@ -58,14 +58,13 @@ const renderItems = (items: MenuItem[], children = false) => {
color="primary" color="primary"
endContent={ endContent={
canOpen ? ( canOpen ? (
// div实现箭头V效果
<div <div
className={clsx( className={clsx(
'ml-auto relative w-3 h-3 transition-transform', 'ml-auto relative w-3 h-3 transition-transform',
open && 'transform rotate-180', open && 'transform rotate-180',
isActive isActive
? 'text-primary-500' ? 'text-primary-500'
: 'text-red-300 dark:text-white', : 'text-primary-200 dark:text-white',
'before:rounded-full', 'before:rounded-full',
'before:content-[""]', 'before:content-[""]',
'before:block', 'before:block',
@@ -98,7 +97,7 @@ const renderItems = (items: MenuItem[], children = false) => {
'w-3 h-1.5 rounded-full ml-auto shadow-lg', 'w-3 h-1.5 rounded-full ml-auto shadow-lg',
isActive isActive
? 'bg-primary-500 animate-spinner-ease-spin' ? 'bg-primary-500 animate-spinner-ease-spin'
: 'bg-red-300 dark:bg-white' : 'bg-primary-200 dark:bg-white'
)} )}
/> />
) )

View File

@@ -0,0 +1,5 @@
import nc_pink from './themes/nc_pink'
const themes: ThemeInfo[] = [nc_pink]
export default themes

View File

@@ -0,0 +1,258 @@
const theme: ThemeConfig = {
dark: {
'--heroui-background': '0 0% 0%',
'--heroui-foreground-50': '240 5.88% 10%',
'--heroui-foreground-100': '240 3.7% 15.88%',
'--heroui-foreground-200': '240 5.26% 26.08%',
'--heroui-foreground-300': '240 5.2% 33.92%',
'--heroui-foreground-400': '240 3.83% 46.08%',
'--heroui-foreground-500': '240 5.03% 64.9%',
'--heroui-foreground-600': '240 4.88% 83.92%',
'--heroui-foreground-700': '240 5.88% 90%',
'--heroui-foreground-800': '240 4.76% 95.88%',
'--heroui-foreground-900': '0 0% 98.04%',
'--heroui-foreground': '210 5.56% 92.94%',
'--heroui-focus': '212.01999999999998 100% 46.67%',
'--heroui-overlay': '0 0% 0%',
'--heroui-divider': '0 0% 100%',
'--heroui-divider-opacity': '0.15',
'--heroui-content1': '240 5.88% 10%',
'--heroui-content1-foreground': '0 0% 98.04%',
'--heroui-content2': '240 3.7% 15.88%',
'--heroui-content2-foreground': '240 4.76% 95.88%',
'--heroui-content3': '240 5.26% 26.08%',
'--heroui-content3-foreground': '240 5.88% 90%',
'--heroui-content4': '240 5.2% 33.92%',
'--heroui-content4-foreground': '240 4.88% 83.92%',
'--heroui-default-50': '240 5.88% 10%',
'--heroui-default-100': '240 3.7% 15.88%',
'--heroui-default-200': '240 5.26% 26.08%',
'--heroui-default-300': '240 5.2% 33.92%',
'--heroui-default-400': '240 3.83% 46.08%',
'--heroui-default-500': '240 5.03% 64.9%',
'--heroui-default-600': '240 4.88% 83.92%',
'--heroui-default-700': '240 5.88% 90%',
'--heroui-default-800': '240 4.76% 95.88%',
'--heroui-default-900': '0 0% 98.04%',
'--heroui-default-foreground': '0 0% 100%',
'--heroui-default': '240 5.26% 26.08%',
'--heroui-danger-50': '301.89 82.61% 22.55%',
'--heroui-danger-100': '308.18 76.39% 28.24%',
'--heroui-danger-200': '313.85 70.65% 36.08%',
'--heroui-danger-300': '319.73 65.64% 44.51%',
'--heroui-danger-400': '325.82 69.62% 53.53%',
'--heroui-danger-500': '331.82 75% 65.49%',
'--heroui-danger-600': '337.84 83.46% 73.92%',
'--heroui-danger-700': '343.42 90.48% 83.53%',
'--heroui-danger-800': '350.53 90.48% 91.76%',
'--heroui-danger-900': '324 90.91% 95.69%',
'--heroui-danger-foreground': '0 0% 100%',
'--heroui-danger': '325.82 69.62% 53.53%',
'--heroui-primary-50': '340 84.91% 10.39%',
'--heroui-primary-100': '339.33 86.54% 20.39%',
'--heroui-primary-200': '339.11 85.99% 30.78%',
'--heroui-primary-300': '339 86.54% 40.78%',
'--heroui-primary-400': '339.2 90.36% 51.18%',
'--heroui-primary-500': '339 90% 60.78%',
'--heroui-primary-600': '339.11 90.6% 70.78%',
'--heroui-primary-700': '339.33 90% 80.39%',
'--heroui-primary-800': '340 91.84% 90.39%',
'--heroui-primary-900': '339.13 92% 95.1%',
'--heroui-primary-foreground': '0 0% 100%',
'--heroui-primary': '339.2 90.36% 51.18%',
'--heroui-secondary-50': '270 66.67% 9.41%',
'--heroui-secondary-100': '270 66.67% 18.82%',
'--heroui-secondary-200': '270 66.67% 28.24%',
'--heroui-secondary-300': '270 66.67% 37.65%',
'--heroui-secondary-400': '270 66.67% 47.06%',
'--heroui-secondary-500': '270 59.26% 57.65%',
'--heroui-secondary-600': '270 59.26% 68.24%',
'--heroui-secondary-700': '270 59.26% 78.82%',
'--heroui-secondary-800': '270 59.26% 89.41%',
'--heroui-secondary-900': '270 61.54% 94.9%',
'--heroui-secondary-foreground': '0 0% 100%',
'--heroui-secondary': '270 59.26% 57.65%',
'--heroui-success-50': '145.71 77.78% 8.82%',
'--heroui-success-100': '146.2 79.78% 17.45%',
'--heroui-success-200': '145.79 79.26% 26.47%',
'--heroui-success-300': '146.01 79.89% 35.1%',
'--heroui-success-400': '145.96 79.46% 43.92%',
'--heroui-success-500': '146.01 62.45% 55.1%',
'--heroui-success-600': '145.79 62.57% 66.47%',
'--heroui-success-700': '146.2 61.74% 77.45%',
'--heroui-success-800': '145.71 61.4% 88.82%',
'--heroui-success-900': '146.67 64.29% 94.51%',
'--heroui-success-foreground': '0 0% 0%',
'--heroui-success': '145.96 79.46% 43.92%',
'--heroui-warning-50': '37.14 75% 10.98%',
'--heroui-warning-100': '37.14 75% 21.96%',
'--heroui-warning-200': '36.96 73.96% 33.14%',
'--heroui-warning-300': '37.01 74.22% 44.12%',
'--heroui-warning-400': '37.03 91.27% 55.1%',
'--heroui-warning-500': '37.01 91.26% 64.12%',
'--heroui-warning-600': '36.96 91.24% 73.14%',
'--heroui-warning-700': '37.14 91.3% 81.96%',
'--heroui-warning-800': '37.14 91.3% 90.98%',
'--heroui-warning-900': '54.55 91.67% 95.29%',
'--heroui-warning-foreground': '0 0% 0%',
'--heroui-warning': '37.03 91.27% 55.1%',
'--heroui-code-background': '240 5.56% 7.06%',
'--heroui-strong': '190.14 94.67% 44.12%',
'--heroui-code-mdx': '190.14 94.67% 44.12%',
'--heroui-divider-weight': '1px',
'--heroui-disabled-opacity': '.5',
'--heroui-font-size-tiny': '0.75rem',
'--heroui-font-size-small': '0.875rem',
'--heroui-font-size-medium': '1rem',
'--heroui-font-size-large': '1.125rem',
'--heroui-line-height-tiny': '1rem',
'--heroui-line-height-small': '1.25rem',
'--heroui-line-height-medium': '1.5rem',
'--heroui-line-height-large': '1.75rem',
'--heroui-radius-small': '8px',
'--heroui-radius-medium': '12px',
'--heroui-radius-large': '14px',
'--heroui-border-width-small': '1px',
'--heroui-border-width-medium': '2px',
'--heroui-border-width-large': '3px',
'--heroui-box-shadow-small':
'0px 0px 5px 0px rgba(0, 0, 0, .05), 0px 2px 10px 0px rgba(0, 0, 0, .2), inset 0px 0px 1px 0px hsla(0, 0%, 100%, .15)',
'--heroui-box-shadow-medium':
'0px 0px 15px 0px rgba(0, 0, 0, .06), 0px 2px 30px 0px rgba(0, 0, 0, .22), inset 0px 0px 1px 0px hsla(0, 0%, 100%, .15)',
'--heroui-box-shadow-large':
'0px 0px 30px 0px rgba(0, 0, 0, .07), 0px 30px 60px 0px rgba(0, 0, 0, .26), inset 0px 0px 1px 0px hsla(0, 0%, 100%, .15)',
'--heroui-hover-opacity': '.9'
},
light: {
'--heroui-background': '0 0% 100%',
'--heroui-foreground-50': '240 5.88% 95%',
'--heroui-foreground-100': '240 3.7% 90%',
'--heroui-foreground-200': '240 5.26% 80%',
'--heroui-foreground-300': '240 5.2% 70%',
'--heroui-foreground-400': '240 3.83% 60%',
'--heroui-foreground-500': '240 5.03% 50%',
'--heroui-foreground-600': '240 4.88% 40%',
'--heroui-foreground-700': '240 5.88% 30%',
'--heroui-foreground-800': '240 4.76% 20%',
'--heroui-foreground-900': '0 0% 10%',
'--heroui-foreground': '210 5.56% 7.06%',
'--heroui-focus': '212.01999999999998 100% 53.33%',
'--heroui-overlay': '0 0% 100%',
'--heroui-divider': '0 0% 0%',
'--heroui-divider-opacity': '0.85',
'--heroui-content1': '240 5.88% 95%',
'--heroui-content1-foreground': '0 0% 10%',
'--heroui-content2': '240 3.7% 90%',
'--heroui-content2-foreground': '240 4.76% 20%',
'--heroui-content3': '240 5.26% 80%',
'--heroui-content3-foreground': '240 5.88% 30%',
'--heroui-content4': '240 5.2% 70%',
'--heroui-content4-foreground': '240 4.88% 40%',
'--heroui-default-50': '240 5.88% 95%',
'--heroui-default-100': '240 3.7% 90%',
'--heroui-default-200': '240 5.26% 80%',
'--heroui-default-300': '240 5.2% 70%',
'--heroui-default-400': '240 3.83% 60%',
'--heroui-default-500': '240 5.03% 50%',
'--heroui-default-600': '240 4.88% 40%',
'--heroui-default-700': '240 5.88% 30%',
'--heroui-default-800': '240 4.76% 20%',
'--heroui-default-900': '0 0% 10%',
'--heroui-default-foreground': '0 0% 0%',
'--heroui-default': '240 5.26% 80%',
'--heroui-danger-50': '324 90.91% 95.69%',
'--heroui-danger-100': '350.53 90.48% 91.76%',
'--heroui-danger-200': '343.42 90.48% 83.53%',
'--heroui-danger-300': '337.84 83.46% 73.92%',
'--heroui-danger-400': '331.82 75% 65.49%',
'--heroui-danger-500': '325.82 69.62% 53.53%',
'--heroui-danger-600': '319.73 65.64% 44.51%',
'--heroui-danger-700': '313.85 70.65% 36.08%',
'--heroui-danger-800': '308.18 76.39% 28.24%',
'--heroui-danger-900': '301.89 82.61% 22.55%',
'--heroui-danger-foreground': '0 0% 100%',
'--heroui-danger': '325.82 69.62% 53.53%',
'--heroui-primary-50': '339.13 92% 95.1%',
'--heroui-primary-100': '340 91.84% 90.39%',
'--heroui-primary-200': '339.33 90% 80.39%',
'--heroui-primary-300': '339.11 90.6% 70.78%',
'--heroui-primary-400': '339 90% 60.78%',
'--heroui-primary-500': '339.2 90.36% 51.18%',
'--heroui-primary-600': '339 86.54% 40.78%',
'--heroui-primary-700': '339.11 85.99% 30.78%',
'--heroui-primary-800': '339.33 86.54% 20.39%',
'--heroui-primary-900': '340 84.91% 10.39%',
'--heroui-primary-foreground': '0 0% 100%',
'--heroui-primary': '339.2 90.36% 51.18%',
'--heroui-secondary-50': '270 61.54% 94.9%',
'--heroui-secondary-100': '270 59.26% 89.41%',
'--heroui-secondary-200': '270 59.26% 78.82%',
'--heroui-secondary-300': '270 59.26% 68.24%',
'--heroui-secondary-400': '270 59.26% 57.65%',
'--heroui-secondary-500': '270 66.67% 47.06%',
'--heroui-secondary-600': '270 66.67% 37.65%',
'--heroui-secondary-700': '270 66.67% 28.24%',
'--heroui-secondary-800': '270 66.67% 18.82%',
'--heroui-secondary-900': '270 66.67% 9.41%',
'--heroui-secondary-foreground': '0 0% 100%',
'--heroui-secondary': '270 66.67% 47.06%',
'--heroui-success-50': '146.67 64.29% 94.51%',
'--heroui-success-100': '145.71 61.4% 88.82%',
'--heroui-success-200': '146.2 61.74% 77.45%',
'--heroui-success-300': '145.79 62.57% 66.47%',
'--heroui-success-400': '146.01 62.45% 55.1%',
'--heroui-success-500': '145.96 79.46% 43.92%',
'--heroui-success-600': '146.01 79.89% 35.1%',
'--heroui-success-700': '145.79 79.26% 26.47%',
'--heroui-success-800': '146.2 79.78% 17.45%',
'--heroui-success-900': '145.71 77.78% 8.82%',
'--heroui-success-foreground': '0 0% 0%',
'--heroui-success': '145.96 79.46% 43.92%',
'--heroui-warning-50': '54.55 91.67% 95.29%',
'--heroui-warning-100': '37.14 91.3% 90.98%',
'--heroui-warning-200': '37.14 91.3% 81.96%',
'--heroui-warning-300': '36.96 91.24% 73.14%',
'--heroui-warning-400': '37.01 91.26% 64.12%',
'--heroui-warning-500': '37.03 91.27% 55.1%',
'--heroui-warning-600': '37.01 74.22% 44.12%',
'--heroui-warning-700': '36.96 73.96% 33.14%',
'--heroui-warning-800': '37.14 75% 21.96%',
'--heroui-warning-900': '37.14 75% 10.98%',
'--heroui-warning-foreground': '0 0% 0%',
'--heroui-warning': '37.03 91.27% 55.1%',
'--heroui-code-background': '221.25 17.39% 18.04%',
'--heroui-strong': '316.95 100% 65.29%',
'--heroui-code-mdx': '316.95 100% 65.29%',
'--heroui-divider-weight': '1px',
'--heroui-disabled-opacity': '.5',
'--heroui-font-size-tiny': '0.75rem',
'--heroui-font-size-small': '0.875rem',
'--heroui-font-size-medium': '1rem',
'--heroui-font-size-large': '1.125rem',
'--heroui-line-height-tiny': '1rem',
'--heroui-line-height-small': '1.25rem',
'--heroui-line-height-medium': '1.5rem',
'--heroui-line-height-large': '1.75rem',
'--heroui-radius-small': '8px',
'--heroui-radius-medium': '12px',
'--heroui-radius-large': '14px',
'--heroui-border-width-small': '1px',
'--heroui-border-width-medium': '2px',
'--heroui-border-width-large': '3px',
'--heroui-box-shadow-small':
'0px 0px 5px 0px rgba(0, 0, 0, .02), 0px 2px 10px 0px rgba(0, 0, 0, .06), 0px 0px 1px 0px rgba(0, 0, 0, .3)',
'--heroui-box-shadow-medium':
'0px 0px 15px 0px rgba(0, 0, 0, .03), 0px 2px 30px 0px rgba(0, 0, 0, .08), 0px 0px 1px 0px rgba(0, 0, 0, .3)',
'--heroui-box-shadow-large':
'0px 0px 30px 0px rgba(0, 0, 0, .04), 0px 30px 60px 0px rgba(0, 0, 0, .12), 0px 0px 1px 0px rgba(0, 0, 0, .3)',
'--heroui-hover-opacity': '.8'
}
}
export default {
theme,
author: 'NapCat',
name: 'nc_pink',
bgColor: 'hsl(339.2,90.36%,51.18%)',
textColor: 'hsl(0,0%,100%)',
description: 'NapCat Pink Theme'
} satisfies ThemeInfo

View File

@@ -1,8 +1,11 @@
import { Accordion, AccordionItem } from '@heroui/accordion'
import { useRequest } from 'ahooks' import { useRequest } from 'ahooks'
import { useEffect } from 'react' import { useEffect } from 'react'
import { Controller, useForm } from 'react-hook-form' import { Controller, useForm } from 'react-hook-form'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import themes from '@/const/themes'
import ColorPicker from '@/components/ColorPicker' import ColorPicker from '@/components/ColorPicker'
import SaveButtons from '@/components/button/save_buttons' import SaveButtons from '@/components/button/save_buttons'
import PageLoading from '@/components/page_loading' import PageLoading from '@/components/page_loading'
@@ -11,6 +14,117 @@ import { loadTheme } from '@/utils/theme'
import WebUIManager from '@/controllers/webui_manager' import WebUIManager from '@/controllers/webui_manager'
// 将颜色 key 补全为 ThemeConfigItem 中定义的所有颜色相关属性
const colorKeys = [
'--heroui-background',
'--heroui-foreground-50',
'--heroui-foreground-100',
'--heroui-foreground-200',
'--heroui-foreground-300',
'--heroui-foreground-400',
'--heroui-foreground-500',
'--heroui-foreground-600',
'--heroui-foreground-700',
'--heroui-foreground-800',
'--heroui-foreground-900',
'--heroui-foreground',
'--heroui-content1',
'--heroui-content1-foreground',
'--heroui-content2',
'--heroui-content2-foreground',
'--heroui-content3',
'--heroui-content3-foreground',
'--heroui-content4',
'--heroui-content4-foreground',
'--heroui-default-50',
'--heroui-default-100',
'--heroui-default-200',
'--heroui-default-300',
'--heroui-default-400',
'--heroui-default-500',
'--heroui-default-600',
'--heroui-default-700',
'--heroui-default-800',
'--heroui-default-900',
'--heroui-default-foreground',
'--heroui-default',
'--heroui-danger-50',
'--heroui-danger-100',
'--heroui-danger-200',
'--heroui-danger-300',
'--heroui-danger-400',
'--heroui-danger-500',
'--heroui-danger-600',
'--heroui-danger-700',
'--heroui-danger-800',
'--heroui-danger-900',
'--heroui-danger-foreground',
'--heroui-danger',
'--heroui-primary-50',
'--heroui-primary-100',
'--heroui-primary-200',
'--heroui-primary-300',
'--heroui-primary-400',
'--heroui-primary-500',
'--heroui-primary-600',
'--heroui-primary-700',
'--heroui-primary-800',
'--heroui-primary-900',
'--heroui-primary-foreground',
'--heroui-primary',
'--heroui-secondary-50',
'--heroui-secondary-100',
'--heroui-secondary-200',
'--heroui-secondary-300',
'--heroui-secondary-400',
'--heroui-secondary-500',
'--heroui-secondary-600',
'--heroui-secondary-700',
'--heroui-secondary-800',
'--heroui-secondary-900',
'--heroui-secondary-foreground',
'--heroui-secondary',
'--heroui-success-50',
'--heroui-success-100',
'--heroui-success-200',
'--heroui-success-300',
'--heroui-success-400',
'--heroui-success-500',
'--heroui-success-600',
'--heroui-success-700',
'--heroui-success-800',
'--heroui-success-900',
'--heroui-success-foreground',
'--heroui-success',
'--heroui-warning-50',
'--heroui-warning-100',
'--heroui-warning-200',
'--heroui-warning-300',
'--heroui-warning-400',
'--heroui-warning-500',
'--heroui-warning-600',
'--heroui-warning-700',
'--heroui-warning-800',
'--heroui-warning-900',
'--heroui-warning-foreground',
'--heroui-warning',
'--heroui-focus',
'--heroui-overlay',
'--heroui-divider',
'--heroui-code-background',
'--heroui-strong',
'--heroui-code-mdx'
] as const
const ThemeConfigCard = () => { const ThemeConfigCard = () => {
const { data, loading, error, refreshAsync } = useRequest( const { data, loading, error, refreshAsync } = useRequest(
WebUIManager.getThemeConfig WebUIManager.getThemeConfig
@@ -67,155 +181,85 @@ const ThemeConfigCard = () => {
<div className="py-24 text-danger-500 text-center">{error.message}</div> <div className="py-24 text-danger-500 text-center">{error.message}</div>
) )
// 将颜色 key 补全为 ThemeConfigItem 中定义的所有颜色相关属性
const colorKeys = [
'--heroui-background',
'--heroui-foreground-50',
'--heroui-foreground-100',
'--heroui-foreground-200',
'--heroui-foreground-300',
'--heroui-foreground-400',
'--heroui-foreground-500',
'--heroui-foreground-600',
'--heroui-foreground-700',
'--heroui-foreground-800',
'--heroui-foreground-900',
'--heroui-foreground',
'--heroui-content1',
'--heroui-content1-foreground',
'--heroui-content2',
'--heroui-content2-foreground',
'--heroui-content3',
'--heroui-content3-foreground',
'--heroui-content4',
'--heroui-content4-foreground',
'--heroui-default-50',
'--heroui-default-100',
'--heroui-default-200',
'--heroui-default-300',
'--heroui-default-400',
'--heroui-default-500',
'--heroui-default-600',
'--heroui-default-700',
'--heroui-default-800',
'--heroui-default-900',
'--heroui-default-foreground',
'--heroui-default',
'--heroui-danger-50',
'--heroui-danger-100',
'--heroui-danger-200',
'--heroui-danger-300',
'--heroui-danger-400',
'--heroui-danger-500',
'--heroui-danger-600',
'--heroui-danger-700',
'--heroui-danger-800',
'--heroui-danger-900',
'--heroui-danger-foreground',
'--heroui-danger',
'--heroui-primary-50',
'--heroui-primary-100',
'--heroui-primary-200',
'--heroui-primary-300',
'--heroui-primary-400',
'--heroui-primary-500',
'--heroui-primary-600',
'--heroui-primary-700',
'--heroui-primary-800',
'--heroui-primary-900',
'--heroui-primary-foreground',
'--heroui-primary',
'--heroui-secondary-50',
'--heroui-secondary-100',
'--heroui-secondary-200',
'--heroui-secondary-300',
'--heroui-secondary-400',
'--heroui-secondary-500',
'--heroui-secondary-600',
'--heroui-secondary-700',
'--heroui-secondary-800',
'--heroui-secondary-900',
'--heroui-secondary-foreground',
'--heroui-secondary',
'--heroui-success-50',
'--heroui-success-100',
'--heroui-success-200',
'--heroui-success-300',
'--heroui-success-400',
'--heroui-success-500',
'--heroui-success-600',
'--heroui-success-700',
'--heroui-success-800',
'--heroui-success-900',
'--heroui-success-foreground',
'--heroui-success',
'--heroui-warning-50',
'--heroui-warning-100',
'--heroui-warning-200',
'--heroui-warning-300',
'--heroui-warning-400',
'--heroui-warning-500',
'--heroui-warning-600',
'--heroui-warning-700',
'--heroui-warning-800',
'--heroui-warning-900',
'--heroui-warning-foreground',
'--heroui-warning',
'--heroui-focus',
'--heroui-overlay',
'--heroui-divider',
'--heroui-code-background',
'--heroui-strong',
'--heroui-code-mdx'
] as const
return ( return (
<> <>
<title> - NapCat WebUI</title> <title> - NapCat WebUI</title>
<div className="flex-shrink-0 w-full"></div> <Accordion variant="splitted">
{(['dark', 'light'] as const).map((mode) => ( <AccordionItem
<div key={mode}> key="select"
<h3>{mode === 'dark' ? '暗色主题' : '亮色主题'}</h3> aria-label="Pick Color"
{colorKeys.map((key) => ( title="选择主题"
<div key={key} className="grid grid-cols-2 items-center mb-2 gap-2"> subtitle="点击立即生效"
<label className="text-right">{key}</label> className="shadow-small"
<Controller >
control={control} <div className="flex flex-wrap gap-2">
name={`theme.${mode}.${key}`} {themes.map((theme) => (
render={({ field: { value, onChange } }) => { <div
const hslArray = value?.split(' ') ?? [0, 0, 0] key={theme.name}
const color = `hsl(${hslArray[0]}, ${hslArray[1]}, ${hslArray[2]})` className="p-4 rounded-md cursor-pointer"
return ( style={{
<ColorPicker backgroundColor: theme.bgColor,
color={color} color: theme.textColor
onChange={(result) => {
onChange(
`${result.hsl.h} ${result.hsl.s * 100}% ${result.hsl.l * 100}%`
)
}}
/>
)
}} }}
/> onClick={() => {
setOnebotValue('theme', theme.theme)
onSubmit()
}}
>
<div>{theme.name}</div>
<div>{theme.author}</div>
</div>
))}
</div>
</AccordionItem>
<AccordionItem
key="pick"
aria-label="Pick Color"
title="自定义配色"
subtitle="需手动点击保存"
className="shadow-small"
>
{(['dark', 'light'] as const).map((mode) => (
<div key={mode}>
<h3>{mode === 'dark' ? '暗色主题' : '亮色主题'}</h3>
{colorKeys.map((key) => (
<div
key={key}
className="grid grid-cols-2 items-center mb-2 gap-2"
>
<label className="text-right">{key}</label>
<Controller
control={control}
name={`theme.${mode}.${key}`}
render={({ field: { value, onChange } }) => {
const hslArray = value?.split(' ') ?? [0, 0, 0]
const color = `hsl(${hslArray[0]}, ${hslArray[1]}, ${hslArray[2]})`
return (
<ColorPicker
color={color}
onChange={(result) => {
onChange(
`${result.hsl.h} ${result.hsl.s * 100}% ${result.hsl.l * 100}%`
)
}}
/>
)
}}
/>
</div>
))}
</div> </div>
))} ))}
</div>
))} <SaveButtons
<SaveButtons onSubmit={onSubmit}
onSubmit={onSubmit} reset={reset}
reset={reset} isSubmitting={isSubmitting}
isSubmitting={isSubmitting} refresh={onRefresh}
refresh={onRefresh} />
/> </AccordionItem>
</Accordion>
</> </>
) )
} }

8
napcat.webui/src/types/theme.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
interface ThemeInfo {
theme: ThemeConfig
name: string
bgColor: string
textColor: string
description?: string
author?: string
}