type: fix .dumi type error (#44916)

This commit is contained in:
lijianan 2023-09-17 23:32:14 +08:00 committed by GitHub
parent de6232c352
commit a0699ea1a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 93 additions and 109 deletions

View File

@ -1,11 +1,11 @@
export default function use<T>(promise: PromiseLike<T>): T { function use<T>(promise: PromiseLike<T>): T {
const internal: PromiseLike<T> & { const internal: PromiseLike<T> & {
status?: 'pending' | 'fulfilled' | 'rejected'; status?: 'pending' | 'fulfilled' | 'rejected';
value?: T; value?: T;
reason?: any; reason?: any;
} = promise; } = promise;
if (internal.status === 'fulfilled') { if (internal.status === 'fulfilled') {
return internal.value; return internal.value as T;
} }
if (internal.status === 'rejected') { if (internal.status === 'rejected') {
throw internal.reason; throw internal.reason;
@ -26,3 +26,5 @@ export default function use<T>(promise: PromiseLike<T>): T {
throw internal; throw internal;
} }
} }
export default use;

View File

@ -5,10 +5,12 @@ export interface LocaleMap<Key extends string> {
en: Record<Key, string>; en: Record<Key, string>;
} }
export default function useLocale<Key extends string>( function useLocale<Key extends string>(
localeMap?: LocaleMap<Key>, localeMap?: LocaleMap<Key>,
): [Record<Key, string>, 'cn' | 'en'] { ): [Record<Key, string>, 'cn' | 'en'] {
const { id } = useDumiLocale(); const { id } = useDumiLocale();
const localeType = id === 'zh-CN' ? 'cn' : 'en'; const localeType = id === 'zh-CN' ? ('cn' as const) : ('en' as const);
return [localeMap?.[localeType], localeType]; return [localeMap?.[localeType]!, localeType];
} }
export default useLocale;

View File

@ -1,7 +1,8 @@
import { useFullSidebarData, useSidebarData } from 'dumi';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import type { MenuProps } from 'antd'; import type { MenuProps } from 'antd';
import { Tag, version } from 'antd'; import { Tag, version } from 'antd';
import { useFullSidebarData, useSidebarData } from 'dumi';
import Link from '../theme/common/Link'; import Link from '../theme/common/Link';
import useLocation from './useLocation'; import useLocation from './useLocation';
@ -136,7 +137,7 @@ const useMenu = (options: UseMenuOptions = {}): [MenuProps['items'], string] =>
const list = group.children || []; const list = group.children || [];
// 如果有 date 字段,我们就对其进行排序 // 如果有 date 字段,我们就对其进行排序
if (list.every((info) => info?.frontmatter?.date)) { if (list.every((info) => info?.frontmatter?.date)) {
list.sort((a, b) => (a.frontmatter.date > b.frontmatter.date ? -1 : 1)); list.sort((a, b) => (a.frontmatter?.date > b.frontmatter?.date ? -1 : 1));
} }
result.push( result.push(

View File

@ -32,11 +32,7 @@ const useThemeAnimation = () => {
token: { colorBgElevated }, token: { colorBgElevated },
} = theme.useToken(); } = theme.useToken();
const animateRef = useRef<{ const animateRef = useRef<{ colorBgElevated: string }>({ colorBgElevated });
colorBgElevated: string;
}>({
colorBgElevated,
});
const startAnimationTheme = (clipPath: string[], isDark: boolean) => { const startAnimationTheme = (clipPath: string[], isDark: boolean) => {
updateCSS( updateCSS(
@ -64,9 +60,14 @@ const useThemeAnimation = () => {
}); });
}; };
const toggleAnimationTheme = (event: MouseEvent, isDark: boolean) => { const toggleAnimationTheme = (
event: React.MouseEvent<HTMLElement, MouseEvent>,
isDark: boolean,
) => {
// @ts-ignore // @ts-ignore
if (!(event && typeof document.startViewTransition === 'function')) return; if (!(event && typeof document.startViewTransition === 'function')) {
return;
}
const x = event.clientX; const x = event.clientX;
const y = event.clientY; const y = event.clientY;
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)); const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));

View File

@ -83,8 +83,8 @@ const Group: React.FC<GroupProps> = (props) => {
</Typography.Title> </Typography.Title>
<Typography.Paragraph <Typography.Paragraph
style={{ style={{
marginBottom: isMobile ? token.marginXXL : token.marginFarXS,
color: titleColor, color: titleColor,
marginBottom: isMobile ? token.marginXXL : token.marginFarXS,
}} }}
> >
{description} {description}

View File

@ -1,7 +1,8 @@
import { createStyles, css } from 'antd-style';
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { CSSMotionList } from 'rc-motion'; import { createStyles, css } from 'antd-style';
import classNames from 'classnames'; import classNames from 'classnames';
import { CSSMotionList } from 'rc-motion';
import { COLOR_IMAGES, getClosetColor } from './colorUtil'; import { COLOR_IMAGES, getClosetColor } from './colorUtil';
export interface BackgroundImageProps { export interface BackgroundImageProps {
@ -36,7 +37,7 @@ const BackgroundImage: React.FC<BackgroundImageProps> = ({ colorPrimary, isLight
const [keyList, setKeyList] = useState<string[]>([]); const [keyList, setKeyList] = useState<string[]>([]);
React.useLayoutEffect(() => { React.useLayoutEffect(() => {
setKeyList([activeColor]); setKeyList([activeColor as string]);
}, [activeColor]); }, [activeColor]);
return ( return (
@ -56,7 +57,7 @@ const BackgroundImage: React.FC<BackgroundImageProps> = ({ colorPrimary, isLight
const entity = COLOR_IMAGES.find((ent) => ent.color === color); const entity = COLOR_IMAGES.find((ent) => ent.color === color);
if (!entity || !entity.url) { if (!entity || !entity.url) {
return null; return null as unknown as React.ReactElement;
} }
const { opacity } = style || {}; const { opacity } = style || {};

View File

@ -1,39 +1,47 @@
import { createStyles } from 'antd-style';
import type { FC } from 'react';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import classNames from 'classnames';
import { ColorPicker, Input, Space } from 'antd'; import { ColorPicker, Input, Space } from 'antd';
import type { Color, ColorPickerProps } from 'antd/es/color-picker'; import { createStyles } from 'antd-style';
import type { Color } from 'antd/es/color-picker';
import { generateColor } from 'antd/es/color-picker/util'; import { generateColor } from 'antd/es/color-picker/util';
import classNames from 'classnames';
import { PRESET_COLORS } from './colorUtil'; import { PRESET_COLORS } from './colorUtil';
const useStyle = createStyles(({ token, css }) => ({ const useStyle = createStyles(({ token, css }) => ({
color: css` color: css`
width: ${token.controlHeightLG / 2}px; width: ${token.controlHeightLG / 2}px;
height: ${token.controlHeightLG / 2}px; height: ${token.controlHeightLG / 2}px;
border-radius: 100%; border-radius: 100%;
cursor: pointer; cursor: pointer;
transition: all ${token.motionDurationFast}; transition: all ${token.motionDurationFast};
display: inline-block; display: inline-block;
& > input[type='radio'] { & > input[type='radio'] {
width: 0; width: 0;
height: 0; height: 0;
opacity: 0; opacity: 0;
} }
&:focus-within { &:focus-within {
// need // need
} }
`, `,
colorActive: css` colorActive: css`
box-shadow: 0 0 0 1px ${token.colorBgContainer}, box-shadow:
0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary}; 0 0 0 1px ${token.colorBgContainer},
`, 0 0 0 ${token.controlOutlineWidth * 2 + 1}px ${token.colorPrimary};
`,
})); }));
const DebouncedColorPicker: FC<ColorPickerProps> = ({ value: color, onChange, children }) => { export interface ColorPickerProps {
children?: React.ReactNode;
value?: string | Color;
onChange?: (value?: Color | string) => void;
}
const DebouncedColorPicker: React.FC<ColorPickerProps> = (props) => {
const { value: color, children, onChange } = props;
const [value, setValue] = useState(color); const [value, setValue] = useState(color);
useEffect(() => { useEffect(() => {
@ -51,40 +59,24 @@ const DebouncedColorPicker: FC<ColorPickerProps> = ({ value: color, onChange, ch
<ColorPicker <ColorPicker
value={value} value={value}
onChange={setValue} onChange={setValue}
presets={[ presets={[{ label: 'PresetColors', colors: PRESET_COLORS }]}
{
label: 'PresetColors',
colors: PRESET_COLORS,
},
]}
> >
{children} {children}
</ColorPicker> </ColorPicker>
); );
}; };
export interface RadiusPickerProps { const ThemeColorPicker: React.FC<ColorPickerProps> = ({ value, onChange }) => {
value?: string | Color;
onChange?: (value: string) => void;
}
export default function ThemeColorPicker({ value, onChange }: RadiusPickerProps) {
const { styles } = useStyle(); const { styles } = useStyle();
const matchColors = React.useMemo(() => { const matchColors = React.useMemo(() => {
const valueStr = generateColor(value).toRgbString(); const valueStr = generateColor(value || '').toRgbString();
let existActive = false; let existActive = false;
const colors = PRESET_COLORS.map((color) => { const colors = PRESET_COLORS.map((color) => {
const colorStr = generateColor(color).toRgbString(); const colorStr = generateColor(color).toRgbString();
const active = colorStr === valueStr; const active = colorStr === valueStr;
existActive = existActive || active; existActive = existActive || active;
return { color, active, picker: false };
return {
color,
active,
picker: false,
};
}); });
return [ return [
@ -100,10 +92,8 @@ export default function ThemeColorPicker({ value, onChange }: RadiusPickerProps)
return ( return (
<Space size="large"> <Space size="large">
<Input <Input
value={typeof value === 'string' ? value : value.toHexString()} value={typeof value === 'string' ? value : value?.toHexString()}
onChange={(event) => { onChange={(event) => onChange?.(event.target.value)}
onChange?.(event.target.value);
}}
style={{ width: 120 }} style={{ width: 120 }}
/> />
@ -114,9 +104,7 @@ export default function ThemeColorPicker({ value, onChange }: RadiusPickerProps)
<label <label
key={color} key={color}
className={classNames(styles.color, active && styles.colorActive)} className={classNames(styles.color, active && styles.colorActive)}
style={{ style={{ background: color }}
background: color,
}}
onClick={() => { onClick={() => {
if (!picker) { if (!picker) {
onChange?.(color); onChange?.(color);
@ -149,4 +137,6 @@ export default function ThemeColorPicker({ value, onChange }: RadiusPickerProps)
</Space> </Space>
</Space> </Space>
); );
} };
export default ThemeColorPicker;

View File

@ -1,3 +1,4 @@
import type { Color } from 'antd/es/color-picker';
import { generateColor } from 'antd/es/color-picker/util'; import { generateColor } from 'antd/es/color-picker/util';
export const DEFAULT_COLOR = '#1677FF'; export const DEFAULT_COLOR = '#1677FF';
@ -50,7 +51,8 @@ export const COLOR_IMAGES = [
export const PRESET_COLORS = COLOR_IMAGES.map(({ color }) => color); export const PRESET_COLORS = COLOR_IMAGES.map(({ color }) => color);
const DISTANCE = 33; const DISTANCE = 33;
export function getClosetColor(colorPrimary?: string | null) {
export function getClosetColor(colorPrimary?: Color | string | null) {
if (!colorPrimary) { if (!colorPrimary) {
return null; return null;
} }

View File

@ -197,7 +197,7 @@ const useStyle = createStyles(({ token, cx }) => {
}); });
// ========================== Menu Config ========================== // ========================== Menu Config ==========================
const subMenuItems: MenuProps['items'] = [ const subMenuItems = [
{ {
key: `Design Values`, key: `Design Values`,
label: `Design Values`, label: `Design Values`,
@ -287,11 +287,12 @@ const ThemesInfo: Record<THEME, Partial<ThemeData>> = {
}, },
}; };
const normalize = (value: number) => value / 255;
function rgbToColorMatrix(color: string) { function rgbToColorMatrix(color: string) {
const rgb = new TinyColor(color).toRgb(); const rgb = new TinyColor(color).toRgb();
const { r, g, b } = rgb; const { r, g, b } = rgb;
const normalize = (value) => value / 255;
const invertValue = normalize(r) * 100; const invertValue = normalize(r) * 100;
const sepiaValue = 100; const sepiaValue = 100;
const saturateValue = Math.max(normalize(r), normalize(g), normalize(b)) * 10000; const saturateValue = Math.max(normalize(r), normalize(g), normalize(b)) * 10000;
@ -360,10 +361,7 @@ export default function Theme() {
const isRootDark = useDark(); const isRootDark = useDark();
React.useEffect(() => { React.useEffect(() => {
onThemeChange(null, { onThemeChange({}, { ...themeData, themeType: isRootDark ? 'dark' : 'default' });
...themeData,
themeType: isRootDark ? 'dark' : 'default',
});
}, [isRootDark]); }, [isRootDark]);
// ================================ Tokens ================================ // ================================ Tokens ================================

View File

@ -1,4 +1,5 @@
import { unistUtilVisit, type UnifiedTransformer } from 'dumi'; import { unistUtilVisit } from 'dumi';
import type { UnifiedTransformer } from 'dumi';
function remarkMeta(): UnifiedTransformer<any> { function remarkMeta(): UnifiedTransformer<any> {
return (tree, vFile) => { return (tree, vFile) => {

View File

@ -1,10 +1,11 @@
import React, { useContext } from 'react';
import { theme as antdTheme, ConfigProvider } from 'antd';
import type { ThemeConfig } from 'antd';
import type { ThemeProviderProps } from 'antd-style'; import type { ThemeProviderProps } from 'antd-style';
import { ThemeProvider } from 'antd-style'; import { ThemeProvider } from 'antd-style';
import type { FC } from 'react';
import React, { useContext } from 'react';
import { ConfigProvider, theme as antdTheme } from 'antd';
interface NewToken { interface NewToken {
bannerHeight: number;
headerHeight: number; headerHeight: number;
menuItemBorder: number; menuItemBorder: number;
mobileMaxWidth: number; mobileMaxWidth: number;
@ -24,15 +25,13 @@ declare module 'antd-style' {
export interface CustomToken extends NewToken {} export interface CustomToken extends NewToken {}
} }
const SiteThemeProvider: FC<ThemeProviderProps> = ({ children, theme, ...rest }) => { const SiteThemeProvider: React.FC<ThemeProviderProps<any>> = ({ children, theme, ...rest }) => {
const { getPrefixCls, iconPrefixCls } = useContext(ConfigProvider.ConfigContext); const { getPrefixCls, iconPrefixCls } = useContext(ConfigProvider.ConfigContext);
const rootPrefixCls = getPrefixCls(); const rootPrefixCls = getPrefixCls();
const { token } = antdTheme.useToken(); const { token } = antdTheme.useToken();
React.useEffect(() => { React.useEffect(() => {
ConfigProvider.config({ ConfigProvider.config({ theme: theme as ThemeConfig });
theme,
});
}, [theme]); }, [theme]);
return ( return (

View File

@ -3,12 +3,12 @@ import React, { forwardRef, useLayoutEffect, useMemo, useTransition } from 'reac
import { useLocation, useNavigate } from 'dumi'; import { useLocation, useNavigate } from 'dumi';
import nprogress from 'nprogress'; import nprogress from 'nprogress';
export type LinkProps = { export interface LinkProps {
to?: string | { pathname?: string; search?: string; hash?: string }; to?: string | { pathname?: string; search?: string; hash?: string };
children?: React.ReactNode; children?: React.ReactNode;
style?: React.CSSProperties; style?: React.CSSProperties;
className?: string; className?: string;
}; }
const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => { const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
const { to, children, ...rest } = props; const { to, children, ...rest } = props;
@ -24,12 +24,14 @@ const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
}, [to]); }, [to]);
const handleClick = (e: MouseEvent<HTMLAnchorElement>) => { const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {
if (!href.startsWith('http')) { if (!href?.startsWith('http')) {
// Should support open in new tab // Should support open in new tab
if (!e.metaKey && !e.ctrlKey && !e.shiftKey) { if (!e.metaKey && !e.ctrlKey && !e.shiftKey) {
e.preventDefault(); e.preventDefault();
startTransition(() => { startTransition(() => {
navigate(href); if (href) {
navigate(href);
}
}); });
} }
} }

View File

@ -12,10 +12,10 @@ import ThemeIcon from './ThemeIcon';
export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off' | 'happy-work'; export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off' | 'happy-work';
export type ThemeSwitchProps = { export interface ThemeSwitchProps {
value?: ThemeName[]; value?: ThemeName[];
onChange: (value: ThemeName[]) => void; onChange: (value: ThemeName[]) => void;
}; }
const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => { const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => {
const { value = ['light'], onChange } = props; const { value = ['light'], onChange } = props;
@ -72,23 +72,6 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => {
}} }}
tooltip={<FormattedMessage id="app.theme.switch.compact" />} tooltip={<FormattedMessage id="app.theme.switch.compact" />}
/> />
{/* Too many float button. Hide motion one */}
{/* <FloatButton
icon={<Motion />}
type={!isMotionOff ? 'primary' : 'default'}
onClick={() => {
if (isMotionOff) {
onChange(value.filter((theme) => theme !== 'motion-off'));
} else {
onChange([...value, 'motion-off']);
}
}}
tooltip={
<FormattedMessage
id={isMotionOff ? 'app.theme.switch.motion.off' : 'app.theme.switch.motion.on'}
/>
}
/> */}
<FloatButton <FloatButton
badge={{ dot: true }} badge={{ dot: true }}
icon={<SmileOutlined />} icon={<SmileOutlined />}

View File

@ -1,5 +1,6 @@
import flatten from 'lodash/flatten'; import flatten from 'lodash/flatten';
import flattenDeep from 'lodash/flattenDeep'; import flattenDeep from 'lodash/flattenDeep';
import themeConfig from './themeConfig'; import themeConfig from './themeConfig';
interface Meta { interface Meta {

View File

@ -194,6 +194,7 @@
"@types/jquery": "^3.5.14", "@types/jquery": "^3.5.14",
"@types/lodash": "^4.14.139", "@types/lodash": "^4.14.139",
"@types/node": "^20.0.0", "@types/node": "^20.0.0",
"@types/nprogress": "^0.2.0",
"@types/prismjs": "^1.26.0", "@types/prismjs": "^1.26.0",
"@types/progress": "^2.0.5", "@types/progress": "^2.0.5",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",

View File

@ -7,6 +7,7 @@ import { globSync } from 'glob';
import { configureToMatchImageSnapshot } from 'jest-image-snapshot'; import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
import MockDate from 'mockdate'; import MockDate from 'mockdate';
import ReactDOMServer from 'react-dom/server'; import ReactDOMServer from 'react-dom/server';
import { App, ConfigProvider, theme } from '../../components'; import { App, ConfigProvider, theme } from '../../components';
const toMatchImageSnapshot = configureToMatchImageSnapshot({ const toMatchImageSnapshot = configureToMatchImageSnapshot({
@ -77,7 +78,6 @@ export default function imageTest(component: React.ReactElement, options: ImageT
const image = await page.screenshot({ const image = await page.screenshot({
fullPage: !options.onlyViewport, fullPage: !options.onlyViewport,
optimizeForSpeed: true,
}); });
expect(image).toMatchImageSnapshot(); expect(image).toMatchImageSnapshot();