chore: sync feature into next

This commit is contained in:
thinkasany
2025-10-25 10:50:22 +08:00
13 changed files with 83 additions and 39 deletions

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useEffectEvent } from 'react';
import React, { useCallback, useEffect } from 'react';
const ANT_SYNC_STORAGE_EVENT_KEY = 'ANT_SYNC_STORAGE_EVENT_KEY';
@@ -95,7 +95,7 @@ const useLocalStorage = <T>(key: string, options: Options<T> = {}) => {
};
}, [key, onNativeStorage, onCustomStorage]);
return [state, useEffectEvent(updateState)] as const;
return [state, updateState] as const;
};
export default useLocalStorage;

View File

@@ -79,7 +79,7 @@ const ColorTrigger = forwardRef<HTMLDivElement, ColorTriggerProps>((props, ref)
default:
return alpha < 100 ? `${hexString.slice(0, 7)},${alpha}%` : hexString;
}
}, [color, format, showText, activeIndex]);
}, [color, format, showText, activeIndex, locale.transparent, colorTextCellPrefixCls]);
// ============================= Render =============================
const containerNode = useMemo<React.ReactNode>(

View File

@@ -56,7 +56,7 @@ export default function useModeColor(
pushOption('gradient', locale.gradientColor);
return [optionList, modes];
}, [mode]);
}, [mode, locale.singleColor, locale.gradientColor]);
// ======================== Post ========================
// We need align `mode` with `color` state

View File

@@ -2,14 +2,14 @@ import type { render } from '../../../tests/utils';
import { fireEvent } from '../../../tests/utils';
export function openPicker(wrapper: ReturnType<typeof render>, index = 0) {
const inputEle = wrapper.container?.querySelectorAll<HTMLInputElement>('input')?.[index]!;
const inputEle = wrapper.container?.querySelectorAll<HTMLInputElement>('input')?.[index];
fireEvent.mouseDown(inputEle);
fireEvent.focus(inputEle);
fireEvent.click(inputEle);
}
export function closePicker(wrapper: ReturnType<typeof render>, index = 0) {
fireEvent.blur(wrapper.container?.querySelectorAll('input')[index]!);
fireEvent.blur(wrapper.container?.querySelectorAll('input')[index]);
}
export function selectCell(wrapper: ReturnType<typeof render>, text: string | number, index = 0) {

View File

@@ -19,6 +19,8 @@ const App: React.FC = () => (
itemSize: 20,
itemSizeSM: 12,
itemActiveBg: '#e7cc87',
itemActiveColor: '#eee',
itemActiveColorHover: '#fff',
itemLinkBg: '#344324',
itemActiveBgDisabled: '#9c1515',
itemInputBg: '#9c1515',

View File

@@ -29,6 +29,16 @@ export interface ComponentToken {
* @descEN Background color of active Pagination item
*/
itemActiveBg: string;
/**
* @desc 页码激活态文字颜色
* @descEN Text color of active Pagination item
*/
itemActiveColor: string;
/**
* @desc 页码激活态文字颜色悬停态
* @descEN Text color of active Pagination item hover
*/
itemActiveColorHover: string;
/**
* @desc 小号页码尺寸
* @descEN Size of small Pagination item
@@ -594,7 +604,7 @@ const genPaginationItemStyle: GenerateStyle<PaginationToken, CSSObject> = (token
borderColor: token.colorPrimary,
a: {
color: token.colorPrimary,
color: token.itemActiveColor,
},
'&:hover': {
@@ -602,7 +612,7 @@ const genPaginationItemStyle: GenerateStyle<PaginationToken, CSSObject> = (token
},
'&:hover a': {
color: token.colorPrimaryHover,
color: token.itemActiveColorHover,
},
},
},
@@ -723,6 +733,8 @@ export const prepareComponentToken: GetDefaultToken<'Pagination'> = (token) => (
itemSize: token.controlHeight,
itemSizeSM: token.controlHeightSM,
itemActiveBg: token.colorBgContainer,
itemActiveColor: token.colorPrimary,
itemActiveColorHover: token.colorPrimaryHover,
itemLinkBg: token.colorBgContainer,
itemActiveColorDisabled: token.colorTextDisabled,
itemActiveBgDisabled: token.controlItemBgActiveDisabled,

View File

@@ -133,15 +133,18 @@ const InternalSpace = React.forwardRef<HTMLDivElement, SpaceProps>((props, ref)
const itemClassName = clsx(`${prefixCls}-item`, mergedClassNames.item);
const memoizedLatestIndex = React.useMemo(() => {
return childNodes.reduce<number>((latest, child, i) => {
if (child !== null && child !== undefined) {
return i;
}
return latest;
}, 0);
}, [childNodes]);
// Calculate latest one
let latestIndex = 0;
const nodes = childNodes.map<React.ReactNode>((child, i) => {
if (child !== null && child !== undefined) {
latestIndex = i;
}
const key = child?.key || `${itemClassName}-${i}`;
return (
<Item
prefix={prefixCls}
@@ -170,7 +173,10 @@ const InternalSpace = React.forwardRef<HTMLDivElement, SpaceProps>((props, ref)
});
}
const spaceContext = React.useMemo<SpaceContextType>(() => ({ latestIndex }), [latestIndex]);
const spaceContext = React.useMemo<SpaceContextType>(
() => ({ latestIndex: memoizedLatestIndex }),
[memoizedLatestIndex],
);
// =========================== Render ===========================
if (childNodes.length === 0) {

View File

@@ -10,22 +10,31 @@ export interface LinkProps
ellipsis?: boolean;
}
const Link = React.forwardRef<HTMLElement, LinkProps>(({ ellipsis, rel, ...restProps }, ref) => {
const Link = React.forwardRef<HTMLElement, LinkProps>((props, ref) => {
const {
ellipsis,
rel,
children,
// @ts-expect-error: https://github.com/ant-design/ant-design/issues/26622
navigate: _navigate,
...restProps
} = props;
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Typography.Link');
warning(typeof ellipsis !== 'object', 'usage', '`ellipsis` only supports boolean value.');
}
const mergedProps = {
const mergedProps: LinkProps = {
...restProps,
rel: rel === undefined && restProps.target === '_blank' ? 'noopener noreferrer' : rel,
};
// @ts-expect-error: https://github.com/ant-design/ant-design/issues/26622
delete mergedProps.navigate;
return <Base {...mergedProps} ref={ref} ellipsis={!!ellipsis} component="a" />;
return (
<Base {...mergedProps} ref={ref} ellipsis={!!ellipsis} component="a">
{children}
</Base>
);
});
export default Link;

View File

@@ -7,8 +7,13 @@ export interface ParagraphProps
extends BlockProps<'div'>,
Omit<React.HTMLAttributes<HTMLDivElement>, 'type' | keyof BlockProps<'div'>> {}
const Paragraph = React.forwardRef<HTMLElement, ParagraphProps>((props, ref) => (
<Base ref={ref} {...props} component="div" />
));
const Paragraph = React.forwardRef<HTMLElement, ParagraphProps>((props, ref) => {
const { children, ...restProps } = props;
return (
<Base ref={ref} {...restProps} component="div">
{children}
</Base>
);
});
export default Paragraph;

View File

@@ -11,10 +11,8 @@ export interface TextProps
ellipsis?: boolean | Omit<EllipsisConfig, 'expandable' | 'rows' | 'onExpand'>;
}
const Text: React.ForwardRefRenderFunction<HTMLSpanElement, TextProps> = (
{ ellipsis, ...restProps },
ref,
) => {
const Text: React.ForwardRefRenderFunction<HTMLSpanElement, TextProps> = (props, ref) => {
const { ellipsis, children, ...restProps } = props;
const mergedEllipsis = React.useMemo(() => {
if (ellipsis && typeof ellipsis === 'object') {
return omit(ellipsis as EllipsisConfig, ['expandable', 'rows']);
@@ -34,7 +32,11 @@ const Text: React.ForwardRefRenderFunction<HTMLSpanElement, TextProps> = (
);
}
return <Base ref={ref} {...restProps} ellipsis={mergedEllipsis} component="span" />;
return (
<Base ref={ref} {...restProps} ellipsis={mergedEllipsis} component="span">
{children}
</Base>
);
};
export default React.forwardRef(Text);

View File

@@ -17,7 +17,7 @@ export interface TitleProps
}
const Title = React.forwardRef<HTMLElement, TitleProps>((props, ref) => {
const { level = 1, ...restProps } = props;
const { level = 1, children, ...restProps } = props;
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning('Typography.Title');
@@ -30,7 +30,11 @@ const Title = React.forwardRef<HTMLElement, TitleProps>((props, ref) => {
const component: keyof JSX.IntrinsicElements = TITLE_ELE_LIST.includes(level)
? `h${level}`
: `h1`;
return <Base ref={ref} {...restProps} component={component} />;
return (
<Base ref={ref} {...restProps} component={component}>
{children}
</Base>
);
});
export default Title;

View File

@@ -6,17 +6,21 @@ import Upload from './Upload';
export type DraggerProps<T = any> = UploadProps<T> & { height?: number };
const Dragger = React.forwardRef<UploadRef, DraggerProps>(
({ style, height, hasControlInside = false, ...restProps }, ref) => (
const Dragger = React.forwardRef<UploadRef, DraggerProps<any>>((props, ref) => {
const { style, height, hasControlInside = false, children, ...restProps } = props;
const mergedStyle: React.CSSProperties = { ...style, height };
return (
<Upload
ref={ref}
hasControlInside={hasControlInside}
{...restProps}
style={mergedStyle}
type="drag"
style={{ ...style, height }}
/>
),
);
>
{children}
</Upload>
);
});
if (process.env.NODE_ENV !== 'production') {
Dragger.displayName = 'Dragger';

View File

@@ -103,8 +103,8 @@ const InternalUpload: React.ForwardRefRenderFunction<UploadRef, UploadProps> = (
// Control mode will auto fill file uid if not provided
React.useMemo(() => {
// eslint-disable-next-line react-hooks/purity
const timestamp = Date.now();
(fileList || []).forEach((file, index) => {
if (!file.uid && !Object.isFrozen(file)) {
file.uid = `__AUTO__${timestamp}_${index}__`;