mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 06:30:10 +08:00
* refactor(ui): migrate switch component from heroui to radix-ui replace heroui switch implementation with radix-ui for better maintainability update package.json and yarn.lock to include new dependency * fix(eslint): enable heroui import restriction for deprecated Switch component * refactor(ui): update Switch component props from isSelected/onValueChange to checked/onCheckedChange Standardize Switch component props across the codebase to use checked/onCheckedChange instead of isSelected/onValueChange for better consistency with common React patterns. Also updates loading state prop from isLoading to loading and removes size prop where unnecessary. The changes include: - Replacing isSelected with checked - Replacing onValueChange with onCheckedChange - Updating isLoading to loading - Removing redundant size props - Adjusting styling to accommodate new loading state * refactor(switch): improve switch component styling and structure - Add default values for loading and disabled props - Update styling classes and add group cursor pointer - Restructure loading indicator and thumb positioning - Wrap DescriptionSwitch children in flex container * refactor(ui): improve switch component structure and usage - Restructure DescriptionSwitch to use explicit props instead of children - Add label, description, and position props for better customization - Update all switch usages in SettingsTab to use new props format * refactor(primitives): simplify switch props by omitting children Remove redundant children prop from CustomSwitchProps since it's already omitted from the parent type * fix(switch): add useId for label accessibility in DescriptionSwitch Ensure proper label association with switch input by generating unique ID using React's useId hook * refactor(settings): remove commented out SettingRowTitleSmall components * refactor(SettingsTab): add todo comment for memoization optimization * feat(switch): add size prop to customize switch dimensions Add sm, md, and lg size options to the Switch component with corresponding styles. This allows for better visual consistency across different UI contexts. * style(ui): adjust switch component styling and theme colors update switch component layout and spacing to improve consistency modify secondary-foreground color variable to use correct semantic token * feat(switch): add new switch component styles and animations - Add new switch.css file with gradient and transition styles - Update switch.tsx component with new styling classes and animations - Remove loader icon in favor of animated gradient effect * fix(i18n): Auto update translations for PR #11061 * style(primitives): remove redundant border style from switch component * refactor(switch): remove switch.css and update switch component styles Remove deprecated switch.css file and migrate styles to inline tailwind classes. Update disabled state styling to use opacity instead of linear gradient for better consistency. * refactor(switch): simplify switch thumb implementation Replace complex div structure with svg for loading state Adjust disabled opacity and loading state styling * style(switch): adjust thumb size and positioning for better consistency * feat(switch): add storybook documentation for switch component Add comprehensive Storybook documentation for the Switch component, including: - Basic usage examples - Different states (checked, disabled, loading) - Size variations - DescriptionSwitch variant - Real-world usage scenarios - Accessibility examples - Form integration examples Also remove redundant box-content class from switch styles * fix(switch): adjust thumb positioning for md and lg sizes * style(primitives): improve switch component styling and spacing - Add padding to the container - Simplify label height logic - Update typography classes for better consistency - Adjust switch container alignment * feat(switch): add size prop to DescriptionSwitch component Add support for sm, md, and lg sizes to DescriptionSwitch component with responsive text sizing. Also includes comprehensive Storybook documentation with examples of all sizes and states. * style(switch): align label text to right when isLeftSide is true * refactor(stories): clean up DescriptionSwitch stories by removing unused imports and simplifying JSX * refactor(ui): rename CustomizedSwitch to Switch for consistency Simplify component naming by removing redundant 'Customized' prefix and aligning with common naming conventions * refactor(switch): extract switch root styles into cva variants Improve maintainability by using class-variance-authority to manage switch root styles and variants * refactor(switch): extract thumb variants into separate cva function Improve maintainability by moving switch thumb styling logic into a dedicated variants configuration. This makes the component more readable and easier to modify. * feat(switch): add classNames prop for custom styling Allow custom class names to be applied to switch root, thumb, and thumbSvg elements for more flexible styling options. * feat(switch): add loading animation variants for switch thumb Extract loading animation logic into separate cva variants for better maintainability and reusability --------- Co-authored-by: GitHub Action <action@github.com>
230 lines
7.8 KiB
JavaScript
230 lines
7.8 KiB
JavaScript
import tseslint from '@electron-toolkit/eslint-config-ts'
|
|
import eslint from '@eslint/js'
|
|
import eslintReact from '@eslint-react/eslint-plugin'
|
|
import { defineConfig } from 'eslint/config'
|
|
import importZod from 'eslint-plugin-import-zod'
|
|
import oxlint from 'eslint-plugin-oxlint'
|
|
import reactHooks from 'eslint-plugin-react-hooks'
|
|
import simpleImportSort from 'eslint-plugin-simple-import-sort'
|
|
import unusedImports from 'eslint-plugin-unused-imports'
|
|
|
|
export default defineConfig([
|
|
eslint.configs.recommended,
|
|
tseslint.configs.recommended,
|
|
eslintReact.configs['recommended-typescript'],
|
|
reactHooks.configs['recommended-latest'],
|
|
{
|
|
plugins: {
|
|
'simple-import-sort': simpleImportSort,
|
|
'unused-imports': unusedImports,
|
|
'import-zod': importZod
|
|
},
|
|
rules: {
|
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
|
|
'simple-import-sort/imports': 'error',
|
|
'simple-import-sort/exports': 'error',
|
|
'unused-imports/no-unused-imports': 'error',
|
|
'@eslint-react/no-prop-types': 'error',
|
|
'import-zod/prefer-zod-namespace': 'error'
|
|
}
|
|
},
|
|
// Configuration for ensuring compatibility with the original ESLint(8.x) rules
|
|
{
|
|
rules: {
|
|
'@typescript-eslint/no-require-imports': 'off',
|
|
'@typescript-eslint/no-unused-vars': ['error', { caughtErrors: 'none' }],
|
|
'@typescript-eslint/no-unused-expressions': 'off',
|
|
'@typescript-eslint/no-empty-object-type': 'off',
|
|
'@eslint-react/hooks-extra/no-direct-set-state-in-use-effect': 'off',
|
|
'@eslint-react/web-api/no-leaked-event-listener': 'off',
|
|
'@eslint-react/web-api/no-leaked-timeout': 'off',
|
|
'@eslint-react/no-unknown-property': 'off',
|
|
'@eslint-react/no-nested-component-definitions': 'off',
|
|
'@eslint-react/dom/no-dangerously-set-innerhtml': 'off',
|
|
'@eslint-react/no-array-index-key': 'off',
|
|
'@eslint-react/no-unstable-default-props': 'off',
|
|
'@eslint-react/no-unstable-context-value': 'off',
|
|
'@eslint-react/hooks-extra/prefer-use-state-lazy-initialization': 'off',
|
|
'@eslint-react/hooks-extra/no-unnecessary-use-prefix': 'off',
|
|
'@eslint-react/no-children-to-array': 'off'
|
|
}
|
|
},
|
|
{
|
|
ignores: [
|
|
'node_modules/**',
|
|
'build/**',
|
|
'dist/**',
|
|
'out/**',
|
|
'local/**',
|
|
'tests/**',
|
|
'.yarn/**',
|
|
'.gitignore',
|
|
'scripts/cloudflare-worker.js',
|
|
'src/main/integration/nutstore/sso/lib/**',
|
|
'src/main/integration/cherryai/index.js',
|
|
'src/main/integration/nutstore/sso/lib/**',
|
|
'src/renderer/src/ui/**',
|
|
'packages/**/dist'
|
|
]
|
|
},
|
|
// turn off oxlint supported rules.
|
|
...oxlint.configs['flat/eslint'],
|
|
...oxlint.configs['flat/typescript'],
|
|
...oxlint.configs['flat/unicorn'],
|
|
// Custom rules should be after oxlint to overwrite
|
|
// LoggerService Custom Rules - only apply to src directory
|
|
{
|
|
files: ['src/**/*.{ts,tsx,js,jsx}'],
|
|
ignores: ['src/**/__tests__/**', 'src/**/__mocks__/**', 'src/**/*.test.*', 'src/preload/**'],
|
|
rules: {
|
|
'no-restricted-syntax': [
|
|
process.env.PRCI ? 'error' : 'warn',
|
|
{
|
|
selector: 'CallExpression[callee.object.name="console"]',
|
|
message:
|
|
'❗CherryStudio uses unified LoggerService: 📖 docs/technical/how-to-use-logger-en.md\n❗CherryStudio 使用统一的日志服务:📖 docs/technical/how-to-use-logger-zh.md\n\n'
|
|
}
|
|
]
|
|
}
|
|
},
|
|
// i18n
|
|
{
|
|
files: ['**/*.{ts,tsx,js,jsx}'],
|
|
languageOptions: {
|
|
ecmaVersion: 2022,
|
|
sourceType: 'module'
|
|
},
|
|
plugins: {
|
|
i18n: {
|
|
rules: {
|
|
'no-template-in-t': {
|
|
meta: {
|
|
type: 'problem',
|
|
docs: {
|
|
description: '⚠️不建议在 t() 函数中使用模板字符串,这样会导致渲染结果不可预料',
|
|
recommended: true
|
|
},
|
|
messages: {
|
|
noTemplateInT: '⚠️不建议在 t() 函数中使用模板字符串,这样会导致渲染结果不可预料'
|
|
}
|
|
},
|
|
create(context) {
|
|
return {
|
|
CallExpression(node) {
|
|
const { callee, arguments: args } = node
|
|
const isTFunction =
|
|
(callee.type === 'Identifier' && callee.name === 't') ||
|
|
(callee.type === 'MemberExpression' &&
|
|
callee.property.type === 'Identifier' &&
|
|
callee.property.name === 't')
|
|
|
|
if (isTFunction && args[0]?.type === 'TemplateLiteral') {
|
|
context.report({
|
|
node: args[0],
|
|
messageId: 'noTemplateInT'
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
rules: {
|
|
'i18n/no-template-in-t': 'warn'
|
|
}
|
|
},
|
|
// ui migration
|
|
{
|
|
// Component Rules - prevent importing antd components when migration completed
|
|
files: ['**/*.{ts,tsx,js,jsx}'],
|
|
ignores: [],
|
|
rules: {
|
|
'no-restricted-imports': [
|
|
'error',
|
|
{
|
|
paths: [
|
|
// {
|
|
// name: 'antd',
|
|
// importNames: ['Flex', 'Switch', 'message', 'Button', 'Tooltip'],
|
|
// message:
|
|
// '❌ Do not import this component from antd. Use our custom components instead: import { ... } from "@cherrystudio/ui"'
|
|
// },
|
|
{
|
|
name: 'antd',
|
|
importNames: ['Switch'],
|
|
message:
|
|
'❌ Do not import this component from antd. Use our custom components instead: import { ... } from "@cherrystudio/ui"'
|
|
},
|
|
{
|
|
name: '@heroui/react',
|
|
importNames: ['Switch'],
|
|
message:
|
|
'❌ Do not import the component from heroui directly. It\'s deprecated.'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
// Schema key naming convention (cache & preferences)
|
|
{
|
|
files: ['packages/shared/data/cache/cacheSchemas.ts', 'packages/shared/data/preference/preferenceSchemas.ts'],
|
|
plugins: {
|
|
'data-schema-key': {
|
|
rules: {
|
|
'valid-key': {
|
|
meta: {
|
|
type: 'problem',
|
|
docs: {
|
|
description: 'Enforce schema key naming convention: namespace.sub.key_name',
|
|
recommended: true
|
|
},
|
|
messages: {
|
|
invalidKey:
|
|
'Schema key "{{key}}" must follow format: namespace.sub.key_name (e.g., app.user.avatar).'
|
|
}
|
|
},
|
|
create(context) {
|
|
const VALID_KEY_PATTERN = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/
|
|
|
|
return {
|
|
TSPropertySignature(node) {
|
|
if (node.key.type === 'Literal' && typeof node.key.value === 'string') {
|
|
const key = node.key.value
|
|
if (!VALID_KEY_PATTERN.test(key)) {
|
|
context.report({
|
|
node: node.key,
|
|
messageId: 'invalidKey',
|
|
data: { key }
|
|
})
|
|
}
|
|
}
|
|
},
|
|
Property(node) {
|
|
if (node.key.type === 'Literal' && typeof node.key.value === 'string') {
|
|
const key = node.key.value
|
|
if (!VALID_KEY_PATTERN.test(key)) {
|
|
context.report({
|
|
node: node.key,
|
|
messageId: 'invalidKey',
|
|
data: { key }
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
rules: {
|
|
'data-schema-key/valid-key': 'error'
|
|
}
|
|
}
|
|
])
|