Compare commits

..

13 Commits

Author SHA1 Message Date
dayjoy
10d37978dd feat: 将 tocoModals 重命名为 tocoOverlays 以支持更多浮层类型 2025-05-09 16:27:16 +08:00
dayjoy
58406d2d54 fix: update theme import and algorithm handling in App component 2025-05-06 16:26:52 +08:00
jackycheng
aca60e107d fix: message theme 2025-05-06 15:57:04 +08:00
jackycheng
ea43542878 fix: primaryColor覆盖问题 2025-05-06 14:25:58 +08:00
dayjoy
f3fbbcc4ab feat(theme): 添加主题配置文件并集成到应用中 2025-05-06 14:22:07 +08:00
jackycheng
ceb48abc16 fix: 点击logo回到首页 2025-02-14 17:22:20 +08:00
jackycheng
f18aa76676 fix: menu parse 2025-02-14 10:49:38 +08:00
jackycheng
1216e08bb9 fix: @df/toco-ui => @toco-design/components 2025-01-08 11:18:06 +08:00
jackycheng
f2cba9f5c4 fix: dep 2024-12-29 12:16:42 +08:00
jackycheng
03a6d711c3 fix: 类型修正 2024-12-27 15:15:06 +08:00
jackycheng
aa8707cf6f fix: tsconfig alias 2024-12-27 15:14:10 +08:00
jackycheng
dc3228d313 fix: 限制react-intl的版本在6.6.x,更高版本会有@formatjs/fast-memoize 的sourcemap报错 2024-12-27 15:13:18 +08:00
jackycheng
4c3d3e0489 fix: 去掉eslint的prettier规则,生成的工程会因为这些规则大量报错 2024-12-27 15:12:54 +08:00
17 changed files with 91 additions and 77 deletions

View File

@@ -5,41 +5,27 @@ module.exports = {
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/prettier',
'plugin:prettier/recommended',
'plugin:react-hooks/recommended',
'plugin:json/recommended',
],
parser: '@typescript-eslint/parser',
plugins: ['react', '@typescript-eslint', 'simple-import-sort'],
plugins: ['react', '@typescript-eslint'],
rules: {
'prettier/prettier': ['error', { singleQuote: true }],
'@typescript-eslint/no-unused-vars': [
'off',
{ argsIgnorePattern: ['^_', 'tocoServices'] },
],
'simple-import-sort/exports': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
"@typescript-eslint/ban-types": 'off',
'react-hooks/exhaustive-deps': 'error',
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'react/no-children-prop': 'off',
'import/no-anonymous-default-export': 'off',
},
overrides: [
{
files: ['**/*.js'],
rules: {
'react/no-children-prop': 'off',
},
},
{
files: ['**/*.json'],
rules: {
'prettier/prettier': ['error', { singleQuote: false }],
},
},
{
files: ['**/*.config.js', '**/setupProxy.js', 'script/**/*.js'],
files: ['**/*.config.js'],
rules: {
'@typescript-eslint/no-var-requires': 'off',
},
@@ -47,6 +33,6 @@ module.exports = {
],
globals: {
tocoRefs: true,
tocoModals: true,
tocoOverlays: true,
},
};

View File

@@ -55,7 +55,7 @@
navigate页面跳转方法用法navigate('/path')
tocoServices页面的请求
tocoRefs页面上所有带 id 组件的 refs
tocoModals页面上所有带 id 弹窗的 refs
tocoOverlays页面上所有带 id 弹窗/抽屉等浮层的 refs
```
## 目录结构

View File

@@ -10,37 +10,31 @@
},
"dependencies": {
"@ant-design/icons": "^5.5.1",
"@df/toco-ui": "{{uiVersion}}",
"@toco-design/components": "{{uiVersion}}",
"@reduxjs/toolkit": "^1.9.7",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.5.2",
"axios": "^1.7.2",
"classnames": "^2.5.1",
"path-to-regexp": "^8.2.0",
"react": "^18.3.1",
"react-dom": "^18.2.0",
"react-intl": "^6.6.2",
"react-intl": "~6.6.2",
"react-redux": "^8.1.3",
"react-router-dom": "^6.22.2",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
"react-router-dom": "^6.22.2"
},
"devDependencies": {
"@craco/craco": "^7.1.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^27.5.2",
"@types/node": "^17.0.45",
"@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19",
"craco-alias": "^3.0.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-simple-import-sort": "^12.0.0",
"prettier": "^3.2.5",
"prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-packagejson": "^2.4.12",
"typescript": "^5"
"react-scripts": "5.0.1",
"typescript": "^5",
"web-vitals": "^2.1.4"
},
"browserslist": {
"production": [

View File

@@ -1,5 +1,5 @@
import { customValueTypeMap } from '@/components';
import { ConfigProvider, App as TocoApp, theme } from '@df/toco-ui';
import { customValueTypeMap } from '@components';
import { ConfigProvider, App as TocoApp, theme as antTheme, ProConfigProvider } from '@toco-design/components';
import { Router } from '@remix-run/router';
import enUS from 'antd/locale/en_US';
import zhCN from 'antd/locale/zh_CN';
@@ -10,14 +10,13 @@ import { RouterProvider } from 'react-router-dom';
import { Locale, Theme } from './enum';
import { useAppSelector } from './hooks';
import * as langs from './langs';
import globalMessage from './message';
import { store } from './store';
import appTheme from './theme';
const { darkAlgorithm } = theme;
const { darkAlgorithm } = antTheme;
const AppInternal: React.FC<{ router: Router }> = (props) => {
const { router } = props;
const { message } = TocoApp.useApp();
const locale = useAppSelector((state) => state.common.locale);
const theme = useAppSelector((state) => state.common.theme);
@@ -33,21 +32,29 @@ const AppInternal: React.FC<{ router: Router }> = (props) => {
};
const themeConfig = useMemo(() => {
const algorithmArr = Array.isArray(appTheme.algorithm) ? appTheme.algorithm : appTheme.algorithm ? [appTheme.algorithm] : [];
if (theme === Theme.DARK) {
if (!algorithmArr.includes(antTheme.darkAlgorithm)) {
algorithmArr.push(antTheme.darkAlgorithm);
}
} else {
const index = algorithmArr.indexOf(antTheme.darkAlgorithm);
if (index > -1) {
algorithmArr.splice(index, 1);
}
}
return {
algorithm: theme === Theme.DARK ? [darkAlgorithm] : [],
cssVar: true,
algorithm: algorithmArr,
cssVar: appTheme.cssVar ?? true,
token: primaryColor
? {
...appTheme.token,
colorPrimary: primaryColor,
}
: undefined,
: appTheme.token,
};
}, [primaryColor, theme]);
useEffect(() => {
globalMessage.setMessage(message);
}, [message]);
useEffect(() => {
document.documentElement.setAttribute(
'data-color-scheme',
@@ -60,9 +67,12 @@ const AppInternal: React.FC<{ router: Router }> = (props) => {
<ConfigProvider
locale={antdLocaleMap[locale]}
theme={themeConfig}
valueTypeMap={customValueTypeMap}
>
<ProConfigProvider valueTypeMap={customValueTypeMap}>
<TocoApp style={{ height: '100%' }}>
<RouterProvider router={router} />
</TocoApp>
</ProConfigProvider>
</ConfigProvider>
</IntlProvider>
);
@@ -71,9 +81,7 @@ const AppInternal: React.FC<{ router: Router }> = (props) => {
const App: React.FC<{ router: Router }> = (props) => {
return (
<StoreProvider store={store}>
<TocoApp style={{ height: '100%' }}>
<AppInternal {...props} />
</TocoApp>
</StoreProvider>
);
};

View File

@@ -2,7 +2,7 @@
* 带主题等上下文的、可全局使用的message api
* toco-ui/antd 组件库的message无法直接全局使用主题上下文会丢失
*/
import { message as tocoMessage } from '@df/toco-ui';
import { message as tocoMessage } from '@toco-design/components';
type Message = ReturnType<typeof tocoMessage.useMessage>[0];

7
src/app/theme.ts Normal file
View File

@@ -0,0 +1,7 @@
import { ThemeConfig, theme } from '@toco-design/components';
const appTheme: ThemeConfig = {
};
export default appTheme;

2
src/global.d.ts vendored
View File

@@ -3,7 +3,7 @@
declare global {
var tocoRefs: Record<string, any>;
var tocoModals: Record<string, any>;
var tocoOverlays: Record<string, any>;
}
export {};

View File

@@ -1,5 +1,5 @@
import '@/style/index.css';
import { tocoGlobal } from '@df/toco-ui';
import { tocoGlobal } from '@toco-design/components';
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './app';
@@ -22,4 +22,4 @@ reportWebVitals();
// global variables
globalThis.tocoRefs = tocoGlobal.getRefs();
globalThis.tocoModals = tocoGlobal.getModals();
globalThis.tocoOverlays = tocoGlobal.getOverlays();

View File

@@ -14,6 +14,7 @@
}
height: var(--header-height);
padding: 16px;
cursor: pointer;
.icon {
display: flex;

View File

@@ -1,9 +1,11 @@
import { Theme } from '@/app/enum';
import { useAppSelector } from '@/app/hooks';
import globalMessage from '@/app/message';
import { SettingOutlined } from '@ant-design/icons';
import { Button, Image, Popover } from '@df/toco-ui';
import { App, Button, Image, Popover } from '@toco-design/components';
import classNames from 'classnames';
import { useMemo } from 'react';
import { useCallback, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import styles from './index.module.css';
import { HeaderOnly, HeaderSider, SiderOnly } from './layouts';
import Settings from './settings';
@@ -22,6 +24,12 @@ type LayoutProps = {
const Layout: React.FC<LayoutProps> = (props) => {
const { type: typeProp } = props;
const theme = useAppSelector((state) => state.common.theme);
const navigate = useNavigate();
const { message } = App.useApp();
useEffect(() => {
globalMessage.setMessage(message);
}, [message]);
const Component = useMemo(() => {
const type = typeProp ?? LayoutType.Default;
@@ -37,6 +45,10 @@ const Layout: React.FC<LayoutProps> = (props) => {
return HeaderSider;
}, [typeProp]);
const gotoHome = useCallback(() => {
navigate('/');
}, [navigate]);
return (
<SuspenseLayout>
<Component
@@ -45,6 +57,7 @@ const Layout: React.FC<LayoutProps> = (props) => {
logo={
<div
className={classNames(styles.logo, { dark: theme === Theme.DARK })}
onClick={gotoHome}
>
<Image
className={styles.icon}

View File

@@ -1,7 +1,6 @@
import { Theme } from '@/app/enum';
import { routerConfig } from '@/router';
import { Layout, Menu, MenuProps } from '@df/toco-ui';
import { SelectInfo } from 'rc-menu/lib/interface';
import { Layout, Menu, MenuProps } from '@toco-design/components';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Outlet, useMatches, useNavigate } from 'react-router-dom';
import { LayoutProps } from '.';
@@ -26,7 +25,8 @@ const HeaderOnly: React.FC<LayoutProps> = (props) => {
}, []);
const onKeyChange = useCallback(
(info: SelectInfo) => {
(...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
const keys = info.keyPath;
setSelectedKeys(info.keyPath);
navigate(keys.reverse().join('/'));

View File

@@ -1,7 +1,6 @@
import { Theme } from '@/app/enum';
import { routerConfig } from '@/router';
import { Layout, Menu, MenuProps } from '@df/toco-ui';
import { SelectInfo } from 'rc-menu/lib/interface';
import { Layout, Menu, MenuProps } from '@toco-design/components';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Outlet, useMatches, useNavigate } from 'react-router-dom';
import { LayoutProps } from '.';
@@ -37,7 +36,8 @@ const HeaderSider: React.FC<LayoutProps> = (props) => {
}, []);
const onHeaderKeyChange = useCallback(
(info: SelectInfo) => {
(...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
setHeaderKey(info.key);
navigate(info.key);
},
@@ -50,7 +50,8 @@ const HeaderSider: React.FC<LayoutProps> = (props) => {
}, [headerKey]);
const onSiderKeyChange = useCallback(
(info: SelectInfo) => {
(...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
const keys = info.keyPath;
setSiderSelectedKeys(info.keyPath);
const parts = [headerKey, ...keys];

View File

@@ -1,7 +1,6 @@
import { Theme } from '@/app/enum';
import { routerConfig } from '@/router';
import { Layout, Menu, MenuProps } from '@df/toco-ui';
import { SelectInfo } from 'rc-menu/lib/interface';
import { Layout, Menu, MenuProps } from '@toco-design/components';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Outlet, useMatches, useNavigate } from 'react-router-dom';
import { LayoutProps } from '.';
@@ -34,7 +33,8 @@ const SiderOnly: React.FC<LayoutProps> = (props) => {
}, []);
const onKeyChange = useCallback(
(info: SelectInfo) => {
(...args: Parameters<Required<MenuProps>['onSelect']>) => {
const info = args[0];
const keys = info.keyPath;
setSelectedKeys(info.keyPath);
navigate(keys.reverse().join('/'));

View File

@@ -1,5 +1,5 @@
import { RootRoute } from '@/router';
import { MenuProps } from '@df/toco-ui';
import { MenuProps } from '@toco-design/components';
import { parse } from 'path-to-regexp';
import { UIMatch } from 'react-router-dom';
@@ -28,7 +28,7 @@ export const parseMenuItems = (
return {
key: removeLeadingSlashes(item.path),
label: item.menu.title,
children: children && children.length > 0 ? children : 0,
children: children && children.length > 0 ? children : undefined,
};
})
.filter((p) => !!p);

View File

@@ -6,7 +6,7 @@ import {
} from '@/app/common';
import { Locale, Theme } from '@/app/enum';
import { useAppDispatch, useAppSelector } from '@/app/hooks';
import { Radio, RadioChangeEvent, Tooltip } from '@df/toco-ui';
import { Radio, RadioChangeEvent, Tooltip } from '@toco-design/components';
import React, { useCallback } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
import ColorContainer, { changeColor } from './color';

View File

@@ -1,4 +1,4 @@
import { Spin as AntSpin, SpinProps } from '@df/toco-ui';
import { Spin as AntSpin, SpinProps } from '@toco-design/components';
const Spin = (props: SpinProps) => {
const { size = 'default' } = props;
const sizeMap = {

View File

@@ -17,7 +17,11 @@
"jsx": "react-jsx",
"baseUrl": "./src",
"paths": {
"@/*": ["./*"]
"@/*": ["./*"],
"@components": ["./components"],
"@components/*": ["./components/*"],
"@pages": ["./pages"],
"@pages/*": ["./pages/*"]
}
},
"include": ["src"]