mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
chore: merge master into feature
This commit is contained in:
commit
78c1fca2f0
8
.github/workflows/issue-labeled.yml
vendored
8
.github/workflows/issue-labeled.yml
vendored
@ -81,3 +81,11 @@ jobs:
|
||||
Hello @${{ github.event.issue.user.login }}, your issue has been closed because it does not conform to our issue requirements. Please use the [Issue Helper](http://new-issue.ant.design) to create an issue, thank you!
|
||||
|
||||
你好 @${{ github.event.issue.user.login }},为了能够进行高效沟通,我们对 issue 有一定的格式要求,你的 issue 因为不符合要求而被自动关闭。你可以通过 [issue 助手](http://new-issue.ant.design) 来创建 issue 以方便我们定位错误。谢谢配合!
|
||||
|
||||
- name: remove unconfirmed label
|
||||
if: github.event.label.name != 'unconfirmed'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'unconfirmed'
|
||||
|
@ -16,6 +16,19 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.20.6
|
||||
|
||||
`2024-09-09`
|
||||
|
||||
- 🐞 Improve Menu collapse animation smoothness. [#50751](https://github.com/ant-design/ant-design/pull/50751) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Table cell overflow bug if edit with virtual scroll. [#50737](https://github.com/ant-design/ant-design/pull/50737) [@huiliangShen](https://github.com/huiliangShen)
|
||||
- 🐞 Fix Input.Search button radius not changing with `size`. [#50734](https://github.com/ant-design/ant-design/pull/50734) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fix Form password still can be toggle show/hide even if disabled. [#50616](https://github.com/ant-design/ant-design/pull/50616) [@Jarryxin](https://github.com/Jarryxin)
|
||||
- 🐞 Revert [#49899](https://github.com/ant-design/ant-design/pull/49899) to fix wrap behavior for Dropdown, and re-fix wrap when out of screen edge. [#50718](https://github.com/ant-design/ant-design/pull/50718) [@afc163](https://github.com/afc163)
|
||||
- 💄 Fix Badge background transition when mouse out. [#50743](https://github.com/ant-design/ant-design/pull/50743) [@coding-ice](https://github.com/coding-ice)
|
||||
- TypeScript
|
||||
- 🤖 Fix Collapse types for `onChange` arguments. [#50754](https://github.com/ant-design/ant-design/pull/50754) [@yuanliu147](https://github.com/yuanliu147)
|
||||
|
||||
## 5.20.5
|
||||
|
||||
`2024-09-03`
|
||||
|
@ -15,6 +15,19 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.20.6
|
||||
|
||||
`2024-09-09`
|
||||
|
||||
- 🐞 修复 Menu 折叠动画不够丝滑的问题。[#50751](https://github.com/ant-design/ant-design/pull/50751) [@afc163](https://github.com/afc163)
|
||||
- 🐞 修复 Table 虚拟滚动时单元格宽度可能溢出的问题。[#50737](https://github.com/ant-design/ant-design/pull/50737) [@huiliangShen](https://github.com/huiliangShen)
|
||||
- 🐞 修复 Input.Search 的按钮圆角不随 `size` 变化的问题。[#50734](https://github.com/ant-design/ant-design/pull/50734) [@afc163](https://github.com/afc163)
|
||||
- 🐞 修复 Form 禁用时仍可切换密码显隐的问题。[#50616](https://github.com/ant-design/ant-design/pull/50616) [@Jarryxin](https://github.com/Jarryxin)
|
||||
- 🐞 回滚 [#49899](https://github.com/ant-design/ant-design/pull/49899) 以修复 Dropdown 菜单项文字溢出菜单的问题,并重新修复屏幕视口外菜单项内容换行错误的问题。[#50752](https://github.com/ant-design/ant-design/pull/50752) [#50718](https://github.com/ant-design/ant-design/pull/50718) [@afc163](https://github.com/afc163)
|
||||
- 💄 修复 Badge 鼠标移出时无背景色过渡动画的问题。[#50743](https://github.com/ant-design/ant-design/pull/50743) [@coding-ice](https://github.com/coding-ice)
|
||||
- TypeScript
|
||||
- 🤖 修复 Collapse 的 `onChange` 的函数入参类型。[#50754](https://github.com/ant-design/ant-design/pull/50754) [@yuanliu147](https://github.com/yuanliu147)
|
||||
|
||||
## 5.20.5
|
||||
|
||||
`2024-09-03`
|
||||
|
@ -14,7 +14,9 @@
|
||||
|
||||
[更新日志](./CHANGELOG.zh-CN.md) · [报告问题][github-issues-url] · [特性需求][github-issues-url] · [English](./README.md) · 中文
|
||||
|
||||

|
||||
## ❤️ 赞助者  
|
||||
|
||||
[](https://opencollective.com/ant-design/contribute/sponsors-218/checkout) [](https://opencollective.com/ant-design/contribute/backers-217/checkout)
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
@ -136,11 +138,7 @@ export default App;
|
||||
|
||||
## ⌨️ 本地开发
|
||||
|
||||
你可以使用 Gitpod 进行在线开发:
|
||||
|
||||
[](https://gitpod.io/#https://github.com/ant-design/ant-design)
|
||||
|
||||
或者使用 opensumi.run 进行在线开发:
|
||||
推荐使用 [opensumi.run](https://opensumi.run) 进行在线开发:
|
||||
|
||||
[](https://opensumi.run/ide/ant-design/ant-design)
|
||||
|
||||
@ -206,8 +204,10 @@ $ npm start
|
||||
2. [Stack Overflow](http://stackoverflow.com/questions/tagged/antd)(英文)
|
||||
3. [Segment Fault](https://segmentfault.com/t/antd)(中文)
|
||||
|
||||
## ❤️ 赞助者  
|
||||
## Issue 赞助
|
||||
|
||||
[](https://opencollective.com/ant-design#support)
|
||||
我们使用 [Polar.sh](https://polar.sh/ant-design) 和 [Issuehunt](https://issuehunt.io/repos/3452688) 来推动您希望看到的针对 antd 的修复和改进,请查看我们的赞助列表:
|
||||
|
||||
[](https://opencollective.com/ant-design#support)
|
||||
<a href="https://polar.sh/ant-design"><img src="https://polar.sh/embed/fund-our-backlog.svg?org=ant-design" /></a>
|
||||
|
||||
[](https://issuehunt.io/repos/34526884)
|
||||
|
22
README.md
22
README.md
@ -14,7 +14,9 @@ An enterprise-class UI design language and React UI library.
|
||||
|
||||
[Changelog](./CHANGELOG.en-US.md) · [Report Bug][github-issues-url] · [Request Feature][github-issues-url] · English · [中文](./README-zh_CN.md)
|
||||
|
||||

|
||||
## ❤️ Sponsors and Backers [](https://opencollective.com/ant-design#support) [](https://opencollective.com/ant-design#support)
|
||||
|
||||
[](https://opencollective.com/ant-design/contribute/sponsors-218/checkout) [](https://opencollective.com/ant-design/contribute/backers-217/checkout)
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/antd.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/antd
|
||||
@ -117,11 +119,7 @@ export default () => (
|
||||
|
||||
## ⌨️ Development
|
||||
|
||||
Use Gitpod, a free online dev environment for GitHub.
|
||||
|
||||
[](https://gitpod.io/#https://github.com/ant-design/ant-design)
|
||||
|
||||
Or use opensumi.run, a free online pure front-end dev environment.
|
||||
Use [opensumi.run](https://opensumi.run), a free online pure front-end dev environment.
|
||||
|
||||
[](https://opensumi.run/ide/ant-design/ant-design)
|
||||
|
||||
@ -175,10 +173,10 @@ We warmly invite contributions from everyone. Before you get started, please tak
|
||||
|
||||
For collaborators, adhere to our [Pull Request Principle](https://github.com/ant-design/ant-design/wiki/PR-principle) and utilize our [Pull Request Template](https://github.com/ant-design/ant-design/wiki/PR-principle#pull-request-template) when creating a Pull Request.
|
||||
|
||||
## Issue funding
|
||||
|
||||
We use [Polar.sh](https://polar.sh/ant-design) and [Issuehunt](https://issuehunt.io/repos/3452688) to up-vote and promote specific features that you would like to see and implement. Check our backlog and help us:
|
||||
|
||||
<a href="https://polar.sh/ant-design"><img src="https://polar.sh/embed/fund-our-backlog.svg?org=ant-design" /></a>
|
||||
|
||||
[](https://issuehunt.io/repos/34526884)
|
||||
|
||||
## ❤️ Sponsors and Backers [](https://opencollective.com/ant-design#support) [](https://opencollective.com/ant-design#support)
|
||||
|
||||
[](https://opencollective.com/ant-design#support)
|
||||
|
||||
[](https://opencollective.com/ant-design#support)
|
||||
|
@ -57,7 +57,11 @@
|
||||
"noAccumulatingSpread": "off"
|
||||
},
|
||||
"a11y": {
|
||||
"useKeyWithClickEvents": "off"
|
||||
"noAriaHiddenOnFocusable": "off",
|
||||
"noLabelWithoutControl": "off",
|
||||
"useFocusableInteractive": "off",
|
||||
"useKeyWithClickEvents": "off",
|
||||
"useSemanticElements": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1,8 +1,11 @@
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import type { ImageProps, MenuProps } from 'antd';
|
||||
|
||||
import { waitFakeTimer } from '../../../tests/utils';
|
||||
import type { ImageProps, MenuProps } from '../../index';
|
||||
import {
|
||||
App,
|
||||
AutoComplete,
|
||||
Cascader,
|
||||
ColorPicker,
|
||||
@ -19,11 +22,10 @@ import {
|
||||
Tooltip,
|
||||
Tour,
|
||||
TreeSelect,
|
||||
} from 'antd';
|
||||
|
||||
import { waitFakeTimer } from '../../../tests/utils';
|
||||
} from '../../index';
|
||||
import type { ZIndexConsumer, ZIndexContainer } from '../hooks/useZIndex';
|
||||
import { consumerBaseZIndexOffset, containerBaseZIndexOffset, useZIndex } from '../hooks/useZIndex';
|
||||
import { resetWarned } from '../warning';
|
||||
import zIndexContext from '../zindexContext';
|
||||
|
||||
const WrapWithProvider: React.FC<PropsWithChildren<{ container: ZIndexContainer }>> = ({
|
||||
@ -222,6 +224,7 @@ const getConsumerSelector = (baseSelector: string, consumer: ZIndexConsumer): st
|
||||
|
||||
describe('Test useZIndex hooks', () => {
|
||||
beforeEach(() => {
|
||||
resetWarned();
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
afterEach(() => {
|
||||
@ -242,17 +245,28 @@ describe('Test useZIndex hooks', () => {
|
||||
return <div>Child</div>;
|
||||
};
|
||||
|
||||
<<<<<<< HEAD
|
||||
const App: React.FC = () => (
|
||||
<WrapWithProvider container={containerKey as ZIndexContainer}>
|
||||
<WrapWithProvider container={containerKey as ZIndexContainer}>
|
||||
<WrapWithProvider container={containerKey as ZIndexContainer}>
|
||||
=======
|
||||
const Demo = () => (
|
||||
<WrapWithProvider containerType={containerKey as ZIndexContainer}>
|
||||
<WrapWithProvider containerType={containerKey as ZIndexContainer}>
|
||||
<WrapWithProvider containerType={containerKey as ZIndexContainer}>
|
||||
>>>>>>> master
|
||||
<Child />
|
||||
</WrapWithProvider>
|
||||
</WrapWithProvider>
|
||||
</WrapWithProvider>
|
||||
);
|
||||
<<<<<<< HEAD
|
||||
render(<App />);
|
||||
|
||||
=======
|
||||
render(<Demo />);
|
||||
>>>>>>> master
|
||||
expect(fn).toHaveBeenLastCalledWith(
|
||||
1000 + containerZIndexValue * 3 + consumerZIndexValue,
|
||||
);
|
||||
@ -262,7 +276,11 @@ describe('Test useZIndex hooks', () => {
|
||||
const Container = containerComponent[containerKey as ZIndexContainer]!;
|
||||
const Consumer = consumerComponent[key as ZIndexConsumer]!;
|
||||
|
||||
<<<<<<< HEAD
|
||||
const App: React.FC = () => (
|
||||
=======
|
||||
const Demo = () => (
|
||||
>>>>>>> master
|
||||
<>
|
||||
<Consumer rootClassName="consumer1" />
|
||||
<Container rootClassName="container1">
|
||||
@ -274,7 +292,7 @@ describe('Test useZIndex hooks', () => {
|
||||
</>
|
||||
);
|
||||
|
||||
const { unmount } = render(<App />);
|
||||
const { unmount } = render(<Demo />);
|
||||
|
||||
await waitFakeTimer(1000);
|
||||
|
||||
@ -378,6 +396,7 @@ describe('Test useZIndex hooks', () => {
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
<<<<<<< HEAD
|
||||
it('FloatButton support zIndex', () => {
|
||||
const { container, rerender } = render(
|
||||
<WrapWithProvider container="FloatButton">
|
||||
@ -394,5 +413,29 @@ describe('Test useZIndex hooks', () => {
|
||||
</WrapWithProvider>,
|
||||
);
|
||||
expect(container.querySelector<HTMLElement>('.ant-float-btn')?.style.zIndex).toBe(String(666));
|
||||
=======
|
||||
it('not warning for static func', () => {
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const Demo = () => {
|
||||
const { modal } = App.useApp();
|
||||
|
||||
React.useEffect(() => {
|
||||
modal.confirm({ content: <Select open /> });
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
render(
|
||||
<App>
|
||||
<Demo />
|
||||
</App>,
|
||||
);
|
||||
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
|
||||
errorSpy.mockRestore();
|
||||
>>>>>>> master
|
||||
});
|
||||
});
|
||||
|
@ -25,6 +25,13 @@ const CONTAINER_OFFSET_MAX_COUNT = 10;
|
||||
|
||||
export const CONTAINER_MAX_OFFSET = CONTAINER_OFFSET * CONTAINER_OFFSET_MAX_COUNT;
|
||||
|
||||
/**
|
||||
* Static function will default be the `CONTAINER_MAX_OFFSET`.
|
||||
* But it still may have children component like Select, Dropdown.
|
||||
* So the warning zIndex should exceed the `CONTAINER_MAX_OFFSET`.
|
||||
*/
|
||||
const CONTAINER_MAX_OFFSET_WITH_CHILDREN = CONTAINER_MAX_OFFSET + CONTAINER_OFFSET;
|
||||
|
||||
export const containerBaseZIndexOffset: Record<ZIndexContainer, number> = {
|
||||
Modal: CONTAINER_OFFSET,
|
||||
Drawer: CONTAINER_OFFSET,
|
||||
@ -79,7 +86,7 @@ export const useZIndex = (
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const warning = devUseWarning(componentType);
|
||||
|
||||
const maxZIndex = token.zIndexPopupBase + CONTAINER_MAX_OFFSET;
|
||||
const maxZIndex = token.zIndexPopupBase + CONTAINER_MAX_OFFSET_WITH_CHILDREN;
|
||||
const currentZIndex = result[0] || 0;
|
||||
|
||||
warning(
|
||||
|
5
components/_util/toList.ts
Normal file
5
components/_util/toList.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default function toList<T>(candidate: T | T[], skipEmpty = false): T[] {
|
||||
if (skipEmpty && (candidate === undefined || candidate === null)) return [];
|
||||
|
||||
return Array.isArray(candidate) ? candidate : [candidate];
|
||||
}
|
@ -15,7 +15,7 @@ import useStyle from './style';
|
||||
|
||||
export type { ScrollNumberProps } from './ScrollNumber';
|
||||
|
||||
export interface BadgeProps {
|
||||
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
/** Number to show in badge */
|
||||
count?: React.ReactNode;
|
||||
showZero?: boolean;
|
||||
|
@ -27,7 +27,7 @@ export interface CollapseProps extends Pick<RcCollapseProps, 'items'> {
|
||||
/** 手风琴效果 */
|
||||
accordion?: boolean;
|
||||
destroyInactivePanel?: boolean;
|
||||
onChange?: (key: string | string[]) => void;
|
||||
onChange?: (key: string[]) => void;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
rootClassName?: string;
|
||||
|
@ -108,7 +108,7 @@ const ColorPicker: CompoundedComponent = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const onInternalChange: ColorPickerPanelProps['onChange'] = (data, pickColor) => {
|
||||
const onInternalChange: ColorPickerPanelProps['onChange'] = (data, changeFromPickerDrag) => {
|
||||
let color: AggregationColor = generateColor(data as AggregationColor);
|
||||
|
||||
// ignore alpha color
|
||||
@ -125,7 +125,7 @@ const ColorPicker: CompoundedComponent = (props) => {
|
||||
}
|
||||
|
||||
// Only for drag-and-drop color picking
|
||||
if (!pickColor) {
|
||||
if (!changeFromPickerDrag) {
|
||||
onInternalChangeComplete(color);
|
||||
}
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,15 +32,39 @@ exports[`renders components/color-picker/demo/base.tsx correctly 1`] = `
|
||||
|
||||
exports[`renders components/color-picker/demo/controlled.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-color-picker-trigger"
|
||||
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small"
|
||||
>
|
||||
<div
|
||||
class="ant-color-picker-color-block"
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-color-picker-color-block-inner"
|
||||
style="background:rgb(22,119,255)"
|
||||
/>
|
||||
class="ant-color-picker-trigger"
|
||||
>
|
||||
<div
|
||||
class="ant-color-picker-color-block"
|
||||
>
|
||||
<div
|
||||
class="ant-color-picker-color-block-inner"
|
||||
style="background:rgb(22,119,255)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-color-picker-trigger"
|
||||
>
|
||||
<div
|
||||
class="ant-color-picker-color-block"
|
||||
>
|
||||
<div
|
||||
class="ant-color-picker-color-block-inner"
|
||||
style="background:rgb(22,119,255)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -20,6 +20,7 @@ function doMouseMove(
|
||||
start: number,
|
||||
end: number,
|
||||
element: string | HTMLElement = 'ant-color-picker-handler',
|
||||
fireMouseUp = true,
|
||||
) {
|
||||
const ele =
|
||||
element instanceof HTMLElement ? element : container.getElementsByClassName(element)[0];
|
||||
@ -44,8 +45,10 @@ function doMouseMove(
|
||||
fireEvent(document, mouseMove);
|
||||
}
|
||||
|
||||
const mouseUp = createEvent.mouseUp(document);
|
||||
fireEvent(document, mouseUp);
|
||||
if (fireMouseUp) {
|
||||
const mouseUp = createEvent.mouseUp(document);
|
||||
fireEvent(document, mouseUp);
|
||||
}
|
||||
}
|
||||
|
||||
describe('ColorPicker', () => {
|
||||
@ -879,4 +882,70 @@ describe('ColorPicker', () => {
|
||||
|
||||
spyRect.mockRestore();
|
||||
});
|
||||
|
||||
describe('controlled with `onChangeComplete`', () => {
|
||||
let spyRect: ReturnType<typeof spyElementPrototypes>;
|
||||
|
||||
beforeEach(() => {
|
||||
spyRect = spyElementPrototypes(HTMLElement, {
|
||||
getBoundingClientRect: () => ({
|
||||
x: 0,
|
||||
y: 100,
|
||||
width: 100,
|
||||
height: 100,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
spyRect.mockRestore();
|
||||
});
|
||||
|
||||
it('lock value', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChangeComplete = jest.fn();
|
||||
const { container } = render(
|
||||
<ColorPicker value="#F00" open onChange={onChange} onChangeComplete={onChangeComplete} />,
|
||||
);
|
||||
|
||||
doMouseMove(container, 0, 50, 'ant-color-picker-slider-handle', false);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
// Safe to change with any value but (255/0/0)
|
||||
'rgb(0,255,255)',
|
||||
);
|
||||
expect(onChangeComplete).not.toHaveBeenCalled();
|
||||
|
||||
// Inline Color Block (locked)
|
||||
expect(container.querySelectorAll('.ant-color-picker-color-block-inner')[0]).toHaveStyle({
|
||||
background: 'rgb(255, 0, 0)',
|
||||
});
|
||||
|
||||
// Popup Color Block (follow operation)
|
||||
expect(container.querySelectorAll('.ant-color-picker-color-block-inner')[1]).toHaveStyle({
|
||||
background: 'rgb(0, 255, 255)',
|
||||
});
|
||||
|
||||
// Mouse up
|
||||
fireEvent.mouseUp(document);
|
||||
|
||||
// Lock color back
|
||||
expect(container.querySelectorAll('.ant-color-picker-color-block-inner')[1]).toHaveStyle({
|
||||
background: 'rgb(255, 0, 0)',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('input precision', async () => {
|
||||
const onChange = jest.fn();
|
||||
const { container } = render(<ColorPicker open onChange={onChange} />);
|
||||
|
||||
fireEvent.change(container.querySelector('.ant-color-picker-hex-input input')!, {
|
||||
target: { value: '2ddcb4' },
|
||||
});
|
||||
|
||||
const onChangeColor = onChange.mock.calls[0][0];
|
||||
expect(onChangeColor.toHexString()).toBe('#2ddcb4');
|
||||
});
|
||||
});
|
||||
|
@ -85,6 +85,16 @@ const PanelPicker: FC = () => {
|
||||
return colors[activeIndex]?.color;
|
||||
}, [value, activeIndex, isSingle, lockedColor, gradientDragging]);
|
||||
|
||||
// ========================= Picker Color =========================
|
||||
const [pickerColor, setPickerColor] = React.useState<AggregationColor | null>(activeColor);
|
||||
const [forceSync, setForceSync] = React.useState(0);
|
||||
|
||||
const mergedPickerColor = pickerColor?.equals(activeColor) ? activeColor : pickerColor;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setPickerColor(activeColor);
|
||||
}, [forceSync, activeColor?.toHexString()]);
|
||||
|
||||
// ============================ Change ============================
|
||||
const fillColor = (nextColor: AggregationColor | Color, info?: Info) => {
|
||||
let submitColor = generateColor(nextColor);
|
||||
@ -121,16 +131,28 @@ const PanelPicker: FC = () => {
|
||||
return new AggregationColor(nextColors);
|
||||
};
|
||||
|
||||
const onInternalChange = (
|
||||
const onPickerChange = (
|
||||
colorValue: AggregationColor | Color,
|
||||
fromPicker?: boolean,
|
||||
fromPicker: boolean,
|
||||
info?: Info,
|
||||
) => {
|
||||
onChange(fillColor(colorValue, info), fromPicker);
|
||||
const nextColor = fillColor(colorValue, info);
|
||||
setPickerColor(nextColor);
|
||||
onChange(nextColor, fromPicker);
|
||||
};
|
||||
|
||||
const onInternalChangeComplete = (nextColor: Color, info?: Info) => {
|
||||
// Trigger complete event
|
||||
onChangeComplete(fillColor(nextColor, info));
|
||||
|
||||
// Back of origin color in case in controlled
|
||||
// This will set after `onChangeComplete` to avoid `setState` trigger rerender
|
||||
// which will make `fillColor` get wrong `color.cleared` state
|
||||
setForceSync((ori) => ori + 1);
|
||||
};
|
||||
|
||||
const onInputChange = (colorValue: AggregationColor) => {
|
||||
onChange(fillColor(colorValue));
|
||||
};
|
||||
|
||||
// ============================ Render ============================
|
||||
@ -166,10 +188,10 @@ const PanelPicker: FC = () => {
|
||||
|
||||
<RcColorPicker
|
||||
prefixCls={prefixCls}
|
||||
value={activeColor?.toHsb()}
|
||||
value={mergedPickerColor?.toHsb()}
|
||||
disabledAlpha={disabledAlpha}
|
||||
onChange={(colorValue, info) => {
|
||||
onInternalChange(colorValue, true, info);
|
||||
onPickerChange(colorValue, true, info);
|
||||
}}
|
||||
onChangeComplete={(colorValue, info) => {
|
||||
onInternalChangeComplete(colorValue, info);
|
||||
@ -178,7 +200,7 @@ const PanelPicker: FC = () => {
|
||||
/>
|
||||
<ColorInput
|
||||
value={activeColor}
|
||||
onChange={onInternalChange}
|
||||
onChange={onInputChange}
|
||||
prefixCls={prefixCls}
|
||||
disabledAlpha={disabledAlpha}
|
||||
{...injectProps}
|
||||
|
@ -1,7 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
通过 `value` 和 `onChange` 设置组件为受控模式。
|
||||
通过 `value` 和 `onChange` 设置组件为受控模式,如果通过 `onChangeComplete` 受控则会锁定展示颜色。
|
||||
|
||||
## en-US
|
||||
|
||||
Set the component to controlled mode.
|
||||
Set the component to controlled mode. Will lock the display color if controlled by `onChangeComplete`.
|
||||
|
@ -1,12 +1,18 @@
|
||||
import React, { useState } from 'react';
|
||||
import { ColorPicker } from 'antd';
|
||||
import { ColorPicker, Space } from 'antd';
|
||||
import type { ColorPickerProps, GetProp } from 'antd';
|
||||
|
||||
type Color = GetProp<ColorPickerProps, 'value'>;
|
||||
|
||||
const Demo: React.FC = () => {
|
||||
const [color, setColor] = useState<Color>('#1677ff');
|
||||
return <ColorPicker value={color} onChange={setColor} />;
|
||||
|
||||
return (
|
||||
<Space>
|
||||
<ColorPicker value={color} onChange={setColor} />
|
||||
<ColorPicker value={color} onChangeComplete={setColor} />
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default Demo;
|
||||
|
@ -61,7 +61,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| trigger | ColorPicker trigger mode | `hover` \| `click` | `click` | |
|
||||
| value | Value of color | string \| `Color` | - | |
|
||||
| onChange | Callback when `value` is changed | `(value: Color, css: string) => void` | - | |
|
||||
| onChangeComplete | Called when color pick ends | `(value: Color) => void` | - | 5.7.0 |
|
||||
| onChangeComplete | Called when color pick ends. Will not change the display color when `value` controlled by `onChangeComplete` | `(value: Color) => void` | - | 5.7.0 |
|
||||
| onFormatChange | Callback when `format` is changed | `(format: 'hex' \| 'rgb' \| 'hsb') => void` | - | |
|
||||
| onOpenChange | Callback when `open` is changed | `(open: boolean) => void` | - | |
|
||||
| onClear | Called when clear | `() => void` | - | 5.6.0 |
|
||||
|
@ -62,7 +62,7 @@ group:
|
||||
| trigger | 颜色选择器的触发模式 | `hover` \| `click` | `click` | |
|
||||
| value | 颜色的值 | string \| `Color` | - | |
|
||||
| onChange | 颜色变化的回调 | `(value: Color, css: string) => void` | - | |
|
||||
| onChangeComplete | 颜色选择完成的回调 | `(value: Color) => void` | - | 5.7.0 |
|
||||
| onChangeComplete | 颜色选择完成的回调,通过 `onChangeComplete` 对 `value` 受控时拖拽不会改变展示颜色 | `(value: Color) => void` | - | 5.7.0 |
|
||||
| onFormatChange | 颜色格式变化的回调 | `(format: 'hex' \| 'rgb' \| 'hsb') => void` | - | |
|
||||
| onOpenChange | 当 `open` 被改变时的回调 | `(open: boolean) => void` | - | |
|
||||
| onClear | 清除的回调 | `() => void` | - | 5.6.0 |
|
||||
|
@ -19,9 +19,18 @@ export const getColorAlpha = (color: AggregationColor) => getRoundNumber(color.t
|
||||
|
||||
/** Return the color whose `alpha` is 1 */
|
||||
export const genAlphaColor = (color: AggregationColor, alpha?: number) => {
|
||||
const hsba = color.toHsb();
|
||||
hsba.a = alpha || 1;
|
||||
return generateColor(hsba);
|
||||
const rgba = color.toRgb();
|
||||
|
||||
// Color from hsb input may get `rgb` is (0/0/0) when `hsb.b` is 0
|
||||
// So if rgb is empty, we should get from hsb
|
||||
if (!rgba.r && !rgba.g && !rgba.b) {
|
||||
const hsba = color.toHsb();
|
||||
hsba.a = alpha || 1;
|
||||
return generateColor(hsba);
|
||||
}
|
||||
|
||||
rgba.a = alpha || 1;
|
||||
return generateColor(rgba);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -7,7 +7,15 @@ import type { PickerLocale } from '../generatePicker';
|
||||
const locale: PickerLocale = {
|
||||
lang: {
|
||||
placeholder: 'Επιλέξτε ημερομηνία',
|
||||
yearPlaceholder: 'Επιλέξτε έτος',
|
||||
quarterPlaceholder: 'Επιλέξτε τρίμηνο',
|
||||
monthPlaceholder: 'Επιλέξτε μήνα',
|
||||
weekPlaceholder: 'Επιλέξτε εβδομάδα',
|
||||
rangePlaceholder: ['Αρχική ημερομηνία', 'Τελική ημερομηνία'],
|
||||
rangeYearPlaceholder: ['Αρχικό έτος', 'Τελικό έτος'],
|
||||
rangeMonthPlaceholder: ['Αρχικός μήνας', 'Τελικός μήνας'],
|
||||
rangeQuarterPlaceholder: ['Αρχικό τρίμηνο', 'Τελικό τρίμηνο'],
|
||||
rangeWeekPlaceholder: ['Αρχική εβδομάδα', 'Τελική εβδομάδα'],
|
||||
...CalendarLocale,
|
||||
},
|
||||
timePickerLocale: {
|
||||
|
@ -265,7 +265,7 @@ const genBaseStyle: GenerateStyle<DropdownToken> = (token) => {
|
||||
|
||||
// =========================== Item ===========================
|
||||
[`${menuCls}-item, ${menuCls}-submenu-title`]: {
|
||||
clear: 'both',
|
||||
display: 'flex',
|
||||
margin: 0,
|
||||
padding: `${unit(paddingBlock!)} ${unit(controlPaddingHorizontal)}`,
|
||||
color: token.colorText,
|
||||
|
@ -58,6 +58,7 @@ const OTPInput = React.forwardRef<InputRef, OTPInputProps>((props, ref) => {
|
||||
// ========================= Render =========================
|
||||
return (
|
||||
<Input
|
||||
type={mask === true ? 'password' : 'text'}
|
||||
{...restProps}
|
||||
ref={inputRef}
|
||||
value={internalValue}
|
||||
@ -67,7 +68,6 @@ const OTPInput = React.forwardRef<InputRef, OTPInputProps>((props, ref) => {
|
||||
onKeyUp={onInternalKeyUp}
|
||||
onMouseDown={syncSelection}
|
||||
onMouseUp={syncSelection}
|
||||
type={mask === true ? 'password' : 'text'}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -7,12 +7,12 @@ import { getMergedStatus } from '../../_util/statusUtils';
|
||||
import type { InputStatus } from '../../_util/statusUtils';
|
||||
import { devUseWarning } from '../../_util/warning';
|
||||
import { ConfigContext } from '../../config-provider';
|
||||
import type { Variant } from '../../config-provider';
|
||||
import useCSSVarCls from '../../config-provider/hooks/useCSSVarCls';
|
||||
import useSize from '../../config-provider/hooks/useSize';
|
||||
import type { SizeType } from '../../config-provider/SizeContext';
|
||||
import { FormItemInputContext } from '../../form/context';
|
||||
import type { FormItemStatusContextProps } from '../../form/context';
|
||||
import type { Variant } from '../../config-provider';
|
||||
import type { InputRef } from '../Input';
|
||||
import useStyle from '../style/otp';
|
||||
import OTPInput from './OTPInput';
|
||||
@ -46,6 +46,8 @@ export interface OTPProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'on
|
||||
status?: InputStatus;
|
||||
|
||||
mask?: boolean | string;
|
||||
|
||||
type?: React.HTMLInputTypeAttribute;
|
||||
}
|
||||
|
||||
function strToArr(str: string) {
|
||||
@ -66,6 +68,7 @@ const OTP = React.forwardRef<OTPRef, OTPProps>((props, ref) => {
|
||||
status: customStatus,
|
||||
autoFocus,
|
||||
mask,
|
||||
type,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
@ -213,6 +216,7 @@ const OTP = React.forwardRef<OTPRef, OTPProps>((props, ref) => {
|
||||
disabled,
|
||||
status: mergedStatus as InputStatus,
|
||||
mask,
|
||||
type,
|
||||
};
|
||||
|
||||
return wrapCSSVar(
|
||||
|
@ -167,4 +167,9 @@ describe('Input.OTP', () => {
|
||||
expect(errSpy).not.toHaveBeenCalled();
|
||||
errSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('support type', () => {
|
||||
const { container } = render(<OTP type="number" />);
|
||||
expect(container.querySelector('input')).toHaveAttribute('type', 'number');
|
||||
});
|
||||
});
|
||||
|
@ -9,6 +9,7 @@ import omit from 'rc-util/lib/omit';
|
||||
import isNumeric from '../_util/isNumeric';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { LayoutContext } from './context';
|
||||
import useStyle from './style/sider';
|
||||
|
||||
const dimensionMaxMap = {
|
||||
xs: '479.98px',
|
||||
@ -97,6 +98,12 @@ const Sider = React.forwardRef<HTMLDivElement, SiderProps>((props, ref) => {
|
||||
onCollapse?.(value, type);
|
||||
};
|
||||
|
||||
// =========================== Prefix ===========================
|
||||
const { getPrefixCls } = useContext(ConfigContext);
|
||||
const prefixCls = getPrefixCls('layout-sider', customizePrefixCls);
|
||||
|
||||
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
|
||||
|
||||
// ========================= Responsive =========================
|
||||
const responsiveHandlerRef = useRef<(mql: MediaQueryListEvent | MediaQueryList) => void>();
|
||||
responsiveHandlerRef.current = (mql: MediaQueryListEvent | MediaQueryList) => {
|
||||
@ -145,10 +152,7 @@ const Sider = React.forwardRef<HTMLDivElement, SiderProps>((props, ref) => {
|
||||
handleSetCollapsed(!collapsed, 'clickTrigger');
|
||||
};
|
||||
|
||||
const { getPrefixCls } = useContext(ConfigContext);
|
||||
|
||||
const renderSider = () => {
|
||||
const prefixCls = getPrefixCls('layout-sider', customizePrefixCls);
|
||||
const divProps = omit(otherProps, ['collapsed']);
|
||||
const rawWidth = collapsed ? collapsedWidth : width;
|
||||
// use "px" as fallback unit for width
|
||||
@ -200,6 +204,8 @@ const Sider = React.forwardRef<HTMLDivElement, SiderProps>((props, ref) => {
|
||||
[`${prefixCls}-zero-width`]: parseFloat(siderWidth) === 0,
|
||||
},
|
||||
className,
|
||||
hashId,
|
||||
cssVarCls,
|
||||
);
|
||||
return (
|
||||
<aside className={siderCls} {...divProps} style={divStyle} ref={ref}>
|
||||
@ -211,7 +217,9 @@ const Sider = React.forwardRef<HTMLDivElement, SiderProps>((props, ref) => {
|
||||
|
||||
const contextValue = React.useMemo(() => ({ siderCollapsed: collapsed }), [collapsed]);
|
||||
|
||||
return <SiderContext.Provider value={contextValue}>{renderSider()}</SiderContext.Provider>;
|
||||
return wrapCSSVar(
|
||||
<SiderContext.Provider value={contextValue}>{renderSider()}</SiderContext.Provider>,
|
||||
);
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
|
@ -165,7 +165,15 @@ exports[`renders components/layout/demo/component-token.tsx extend context corre
|
||||
>
|
||||
<aside
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="background: rgb(255, 255, 255); flex: 0 0 200px; max-width: 200px; min-width: 200px; width: 200px;"
|
||||
style="flex: 0 0 32px; max-width: 32px; min-width: 32px; width: 32px;"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider-children"
|
||||
/>
|
||||
</aside>
|
||||
<aside
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="flex: 0 0 200px; max-width: 200px; min-width: 200px; width: 200px;"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider-children"
|
||||
@ -174,7 +182,7 @@ exports[`renders components/layout/demo/component-token.tsx extend context corre
|
||||
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
style="height: 100%; border-right: 0;"
|
||||
style="border-right: 0;"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
|
@ -163,7 +163,15 @@ exports[`renders components/layout/demo/component-token.tsx correctly 1`] = `
|
||||
>
|
||||
<aside
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="background:#ffffff;flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
style="flex:0 0 32px;max-width:32px;min-width:32px;width:32px"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider-children"
|
||||
/>
|
||||
</aside>
|
||||
<aside
|
||||
class="ant-layout-sider ant-layout-sider-dark"
|
||||
style="flex:0 0 200px;max-width:200px;min-width:200px;width:200px"
|
||||
>
|
||||
<div
|
||||
class="ant-layout-sider-children"
|
||||
@ -172,7 +180,7 @@ exports[`renders components/layout/demo/component-token.tsx correctly 1`] = `
|
||||
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
style="height:100%;border-right:0"
|
||||
style="border-right:0"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
|
@ -40,7 +40,7 @@ const App: React.FC = () => {
|
||||
headerHeight: 64,
|
||||
headerPadding: `0 24px`,
|
||||
headerColor: colorBgContainer,
|
||||
siderBg: colorBgContainer,
|
||||
siderBg: '#800080',
|
||||
},
|
||||
},
|
||||
}}
|
||||
@ -51,12 +51,23 @@ const App: React.FC = () => {
|
||||
<div style={{ marginInlineStart: 24, fontSize: 24 }}>Ant Design</div>
|
||||
</Header>
|
||||
<Layout>
|
||||
<Sider width={200} style={{ background: colorBgContainer }}>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
Layout: {
|
||||
siderBg: 'red',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Sider width={32} />
|
||||
</ConfigProvider>
|
||||
<Sider width={200}>
|
||||
<Menu
|
||||
mode="inline"
|
||||
defaultSelectedKeys={['1']}
|
||||
defaultOpenKeys={['sub1']}
|
||||
style={{ height: '100%', borderRight: 0 }}
|
||||
style={{ borderRight: 0 }}
|
||||
items={items2}
|
||||
/>
|
||||
</Sider>
|
||||
|
@ -4,7 +4,6 @@ import type { CSSObject } from '@ant-design/cssinjs';
|
||||
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks } from '../../theme/internal';
|
||||
import genLayoutLightStyle from './light';
|
||||
|
||||
export interface ComponentToken {
|
||||
/** @deprecated Use headerBg instead */
|
||||
@ -103,23 +102,14 @@ const genLayoutStyle: GenerateStyle<LayoutToken, CSSObject> = (token) => {
|
||||
antCls, // .ant
|
||||
componentCls, // .ant-layout
|
||||
colorText,
|
||||
triggerColor,
|
||||
footerBg,
|
||||
triggerBg,
|
||||
headerHeight,
|
||||
headerPadding,
|
||||
headerColor,
|
||||
footerPadding,
|
||||
triggerHeight,
|
||||
zeroTriggerHeight,
|
||||
zeroTriggerWidth,
|
||||
motionDurationMid,
|
||||
motionDurationSlow,
|
||||
fontSize,
|
||||
borderRadius,
|
||||
bodyBg,
|
||||
headerBg,
|
||||
siderBg,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
@ -148,98 +138,6 @@ const genLayoutStyle: GenerateStyle<LayoutToken, CSSObject> = (token) => {
|
||||
flex: '0 0 auto',
|
||||
},
|
||||
|
||||
[`${componentCls}-sider`]: {
|
||||
position: 'relative',
|
||||
|
||||
// fix firefox can't set width smaller than content on flex item
|
||||
minWidth: 0,
|
||||
background: siderBg,
|
||||
transition: `all ${motionDurationMid}, background 0s`,
|
||||
|
||||
'&-children': {
|
||||
height: '100%',
|
||||
// Hack for fixing margin collapse bug
|
||||
// https://github.com/ant-design/ant-design/issues/7967
|
||||
// solution from https://stackoverflow.com/a/33132624/3040605
|
||||
marginTop: -0.1,
|
||||
paddingTop: 0.1,
|
||||
|
||||
[`${antCls}-menu${antCls}-menu-inline-collapsed`]: {
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
|
||||
'&-has-trigger': {
|
||||
paddingBottom: triggerHeight,
|
||||
},
|
||||
|
||||
'&-right': {
|
||||
order: 1,
|
||||
},
|
||||
|
||||
'&-trigger': {
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
zIndex: 1,
|
||||
height: triggerHeight,
|
||||
color: triggerColor,
|
||||
lineHeight: unit(triggerHeight),
|
||||
textAlign: 'center',
|
||||
background: triggerBg,
|
||||
cursor: 'pointer',
|
||||
transition: `all ${motionDurationMid}`,
|
||||
},
|
||||
|
||||
'&-zero-width': {
|
||||
'> *': {
|
||||
overflow: 'hidden',
|
||||
},
|
||||
|
||||
'&-trigger': {
|
||||
position: 'absolute',
|
||||
top: headerHeight,
|
||||
insetInlineEnd: token.calc(zeroTriggerWidth).mul(-1).equal(),
|
||||
zIndex: 1,
|
||||
width: zeroTriggerWidth,
|
||||
height: zeroTriggerHeight,
|
||||
color: triggerColor,
|
||||
fontSize: token.fontSizeXL,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
background: siderBg,
|
||||
borderStartStartRadius: 0,
|
||||
borderStartEndRadius: borderRadius,
|
||||
borderEndEndRadius: borderRadius,
|
||||
borderEndStartRadius: 0,
|
||||
|
||||
cursor: 'pointer',
|
||||
transition: `background ${motionDurationSlow} ease`,
|
||||
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
background: 'transparent',
|
||||
transition: `all ${motionDurationSlow}`,
|
||||
content: '""',
|
||||
},
|
||||
|
||||
'&:hover::after': {
|
||||
background: `rgba(255, 255, 255, 0.2)`,
|
||||
},
|
||||
|
||||
'&-right': {
|
||||
insetInlineStart: token.calc(zeroTriggerWidth).mul(-1).equal(),
|
||||
borderStartStartRadius: borderRadius,
|
||||
borderStartEndRadius: 0,
|
||||
borderEndEndRadius: 0,
|
||||
borderEndStartRadius: borderRadius,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Light
|
||||
...genLayoutLightStyle(token),
|
||||
// RTL
|
||||
'&-rtl': {
|
||||
direction: 'rtl',
|
||||
@ -320,10 +218,12 @@ export const prepareComponentToken: GetDefaultToken<'Layout'> = (token) => {
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export const DEPRECATED_TOKENS: [keyof ComponentToken, keyof ComponentToken][] = [
|
||||
['colorBgBody', 'bodyBg'],
|
||||
['colorBgHeader', 'headerBg'],
|
||||
['colorBgTrigger', 'triggerBg'],
|
||||
];
|
||||
|
||||
export default genStyleHooks('Layout', (token) => [genLayoutStyle(token)], prepareComponentToken, {
|
||||
deprecatedTokens: [
|
||||
['colorBgBody', 'bodyBg'],
|
||||
['colorBgHeader', 'headerBg'],
|
||||
['colorBgTrigger', 'triggerBg'],
|
||||
],
|
||||
deprecatedTokens: DEPRECATED_TOKENS,
|
||||
});
|
||||
|
@ -1,28 +0,0 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
|
||||
import type { LayoutToken } from '.';
|
||||
import type { GenerateStyle } from '../../theme/internal';
|
||||
|
||||
const genLayoutLightStyle: GenerateStyle<LayoutToken, CSSObject> = (token) => {
|
||||
const { componentCls, bodyBg, lightSiderBg, lightTriggerBg, lightTriggerColor } = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-sider-light`]: {
|
||||
background: lightSiderBg,
|
||||
|
||||
[`${componentCls}-sider-trigger`]: {
|
||||
color: lightTriggerColor,
|
||||
background: lightTriggerBg,
|
||||
},
|
||||
|
||||
[`${componentCls}-sider-zero-width-trigger`]: {
|
||||
color: lightTriggerColor,
|
||||
background: lightTriggerBg,
|
||||
border: `1px solid ${bodyBg}`, // Safe to modify to any other color
|
||||
borderInlineStart: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default genLayoutLightStyle;
|
147
components/layout/style/sider.ts
Normal file
147
components/layout/style/sider.ts
Normal file
@ -0,0 +1,147 @@
|
||||
import { unit } from '@ant-design/cssinjs';
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
|
||||
import { DEPRECATED_TOKENS, prepareComponentToken } from '.';
|
||||
import type { LayoutToken } from '.';
|
||||
import type { GenerateStyle } from '../../theme/interface';
|
||||
import { genStyleHooks } from '../../theme/internal';
|
||||
|
||||
const genSiderStyle: GenerateStyle<LayoutToken, CSSObject> = (token) => {
|
||||
const {
|
||||
componentCls,
|
||||
siderBg,
|
||||
motionDurationMid,
|
||||
motionDurationSlow,
|
||||
antCls,
|
||||
triggerHeight,
|
||||
triggerColor,
|
||||
triggerBg,
|
||||
headerHeight,
|
||||
zeroTriggerWidth,
|
||||
zeroTriggerHeight,
|
||||
borderRadius,
|
||||
lightSiderBg,
|
||||
lightTriggerColor,
|
||||
lightTriggerBg,
|
||||
bodyBg,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}`]: {
|
||||
position: 'relative',
|
||||
|
||||
// fix firefox can't set width smaller than content on flex item
|
||||
minWidth: 0,
|
||||
background: siderBg,
|
||||
transition: `all ${motionDurationMid}, background 0s`,
|
||||
|
||||
'&-has-trigger': {
|
||||
paddingBottom: triggerHeight,
|
||||
},
|
||||
|
||||
'&-right': {
|
||||
order: 1,
|
||||
},
|
||||
|
||||
[`${componentCls}-children`]: {
|
||||
height: '100%',
|
||||
// Hack for fixing margin collapse bug
|
||||
// https://github.com/ant-design/ant-design/issues/7967
|
||||
// solution from https://stackoverflow.com/a/33132624/3040605
|
||||
marginTop: -0.1,
|
||||
paddingTop: 0.1,
|
||||
|
||||
[`${antCls}-menu${antCls}-menu-inline-collapsed`]: {
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-trigger`]: {
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
zIndex: 1,
|
||||
height: triggerHeight,
|
||||
color: triggerColor,
|
||||
lineHeight: unit(triggerHeight),
|
||||
textAlign: 'center',
|
||||
background: triggerBg,
|
||||
cursor: 'pointer',
|
||||
transition: `all ${motionDurationMid}`,
|
||||
},
|
||||
|
||||
'&-zero-width': {
|
||||
'> *': {
|
||||
overflow: 'hidden',
|
||||
},
|
||||
|
||||
[`${componentCls}-trigger`]: {
|
||||
position: 'absolute',
|
||||
top: headerHeight,
|
||||
insetInlineEnd: token.calc(zeroTriggerWidth).mul(-1).equal(),
|
||||
zIndex: 1,
|
||||
width: zeroTriggerWidth,
|
||||
height: zeroTriggerHeight,
|
||||
color: triggerColor,
|
||||
fontSize: token.fontSizeXL,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
background: siderBg,
|
||||
borderStartStartRadius: 0,
|
||||
borderStartEndRadius: borderRadius,
|
||||
borderEndEndRadius: borderRadius,
|
||||
borderEndStartRadius: 0,
|
||||
|
||||
cursor: 'pointer',
|
||||
transition: `background ${motionDurationSlow} ease`,
|
||||
|
||||
'&::after': {
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
background: 'transparent',
|
||||
transition: `all ${motionDurationSlow}`,
|
||||
content: '""',
|
||||
},
|
||||
|
||||
'&:hover::after': {
|
||||
background: `rgba(255, 255, 255, 0.2)`,
|
||||
},
|
||||
|
||||
'&-right': {
|
||||
insetInlineStart: token.calc(zeroTriggerWidth).mul(-1).equal(),
|
||||
borderStartStartRadius: borderRadius,
|
||||
borderStartEndRadius: 0,
|
||||
borderEndEndRadius: 0,
|
||||
borderEndStartRadius: borderRadius,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Light
|
||||
'&-light': {
|
||||
background: lightSiderBg,
|
||||
|
||||
[`${componentCls}-trigger`]: {
|
||||
color: lightTriggerColor,
|
||||
background: lightTriggerBg,
|
||||
},
|
||||
|
||||
[`${componentCls}-zero-width-trigger`]: {
|
||||
color: lightTriggerColor,
|
||||
background: lightTriggerBg,
|
||||
border: `1px solid ${bodyBg}`, // Safe to modify to any other color
|
||||
borderInlineStart: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default genStyleHooks(
|
||||
['Layout', 'Sider'],
|
||||
(token) => [genSiderStyle(token)],
|
||||
prepareComponentToken,
|
||||
{
|
||||
deprecatedTokens: DEPRECATED_TOKENS,
|
||||
},
|
||||
);
|
@ -114,6 +114,20 @@ const localeValues: Locale = {
|
||||
},
|
||||
},
|
||||
},
|
||||
Image: {
|
||||
preview: 'معاينة',
|
||||
},
|
||||
QRCode: {
|
||||
expired: 'انتهت صلاحية رمز الاستجابة السريعة',
|
||||
refresh: 'انقر للتحديث',
|
||||
scanned: 'تم المسح',
|
||||
},
|
||||
ColorPicker: {
|
||||
presetEmpty: 'لا يوجد',
|
||||
transparent: 'شفاف',
|
||||
singleColor: 'لون واحد',
|
||||
gradientColor: 'تدرج لوني',
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -5,23 +5,45 @@ import Calendar from '../calendar/locale/el_GR';
|
||||
import DatePicker from '../date-picker/locale/el_GR';
|
||||
import TimePicker from '../time-picker/locale/el_GR';
|
||||
|
||||
const typeTemplate = 'Το ${label} δεν είναι έγκυρο ${type}';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'el',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
global: {
|
||||
placeholder: 'Παρακαλώ επιλέξτε',
|
||||
},
|
||||
Table: {
|
||||
filterTitle: 'Μενού φίλτρων',
|
||||
filterConfirm: 'ΟΚ',
|
||||
filterReset: 'Επαναφορά',
|
||||
filterEmptyText: 'Χωρίς φίλτρα',
|
||||
filterCheckall: 'Επιλογή όλων',
|
||||
filterSearchPlaceholder: 'Αναζήτηση στα φίλτρα',
|
||||
emptyText: 'Δεν υπάρχουν δεδομένα',
|
||||
selectAll: 'Επιλογή τρέχουσας σελίδας',
|
||||
selectInvert: 'Αντιστροφή τρέχουσας σελίδας',
|
||||
selectNone: 'Εκκαθάριση όλων των δεδομένων',
|
||||
selectionAll: 'Επιλογή όλων των δεδομένων',
|
||||
sortTitle: 'Ταξινόμηση',
|
||||
expand: 'Ανάπτυξη σειράς',
|
||||
collapse: 'Σύμπτυξη σειράς',
|
||||
triggerDesc: 'Κλικ για φθίνουσα ταξινόμηση',
|
||||
triggerAsc: 'Κλικ για αύξουσα ταξινόμηση',
|
||||
cancelSort: 'Κλικ για ακύρωση ταξινόμησης',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'ΟΚ',
|
||||
cancelText: 'Άκυρο',
|
||||
justOkText: 'ΟΚ',
|
||||
justOkText: 'Εντάξει',
|
||||
},
|
||||
Tour: {
|
||||
Next: 'Επόμενο',
|
||||
Previous: 'Προηγούμενο',
|
||||
Finish: 'Τέλος',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: 'ΟΚ',
|
||||
@ -32,6 +54,12 @@ const localeValues: Locale = {
|
||||
searchPlaceholder: 'Αναζήτηση',
|
||||
itemUnit: 'αντικείμενο',
|
||||
itemsUnit: 'αντικείμενα',
|
||||
remove: 'Αφαίρεση',
|
||||
selectCurrent: 'Επιλογή τρέχουσας σελίδας',
|
||||
removeCurrent: 'Αφαίρεση τρέχουσας σελίδας',
|
||||
selectAll: 'Επιλογή όλων των δεδομένων',
|
||||
removeAll: 'Αφαίρεση όλων των δεδομένων',
|
||||
selectInvert: 'Αντιστροφή τρέχουσας σελίδας',
|
||||
},
|
||||
Upload: {
|
||||
uploading: 'Μεταφόρτωση...',
|
||||
@ -43,6 +71,80 @@ const localeValues: Locale = {
|
||||
Empty: {
|
||||
description: 'Δεν υπάρχουν δεδομένα',
|
||||
},
|
||||
Icon: {
|
||||
icon: 'εικονίδιο',
|
||||
},
|
||||
Text: {
|
||||
edit: 'Επεξεργασία',
|
||||
copy: 'Αντιγραφή',
|
||||
copied: 'Αντιγράφηκε',
|
||||
expand: 'Ανάπτυξη',
|
||||
collapse: 'Σύμπτυξη',
|
||||
},
|
||||
Form: {
|
||||
optional: '(προαιρετικό)',
|
||||
defaultValidateMessages: {
|
||||
default: 'Σφάλμα επικύρωσης πεδίου για ${label}',
|
||||
required: 'Παρακαλώ εισάγετε ${label}',
|
||||
enum: 'Το ${label} πρέπει να είναι ένα από [${enum}]',
|
||||
whitespace: 'Το ${label} δεν μπορεί να είναι κενός χαρακτήρας',
|
||||
date: {
|
||||
format: 'Η μορφή ημερομηνίας του ${label} είναι άκυρη',
|
||||
parse: 'Το ${label} δεν μπορεί να μετατραπεί σε ημερομηνία',
|
||||
invalid: 'Το ${label} είναι μια άκυρη ημερομηνία',
|
||||
},
|
||||
types: {
|
||||
string: typeTemplate,
|
||||
method: typeTemplate,
|
||||
array: typeTemplate,
|
||||
object: typeTemplate,
|
||||
number: typeTemplate,
|
||||
date: typeTemplate,
|
||||
boolean: typeTemplate,
|
||||
integer: typeTemplate,
|
||||
float: typeTemplate,
|
||||
regexp: typeTemplate,
|
||||
email: typeTemplate,
|
||||
url: typeTemplate,
|
||||
hex: typeTemplate,
|
||||
},
|
||||
string: {
|
||||
len: 'Το ${label} πρέπει να είναι ${len} χαρακτήρες',
|
||||
min: 'Το ${label} πρέπει να είναι τουλάχιστον ${min} χαρακτήρες',
|
||||
max: 'Το ${label} πρέπει να είναι το πολύ ${max} χαρακτήρες',
|
||||
range: 'Το ${label} πρέπει να είναι μεταξύ ${min}-${max} χαρακτήρων',
|
||||
},
|
||||
number: {
|
||||
len: 'Το ${label} πρέπει να είναι ίσο με ${len}',
|
||||
min: 'Το ${label} πρέπει να είναι τουλάχιστον ${min}',
|
||||
max: 'Το ${label} πρέπει να είναι το πολύ ${max}',
|
||||
range: 'Το ${label} πρέπει να είναι μεταξύ ${min}-${max}',
|
||||
},
|
||||
array: {
|
||||
len: 'Πρέπει να είναι ${len} ${label}',
|
||||
min: 'Τουλάχιστον ${min} ${label}',
|
||||
max: 'Το πολύ ${max} ${label}',
|
||||
range: 'Το ποσό του ${label} πρέπει να είναι μεταξύ ${min}-${max}',
|
||||
},
|
||||
pattern: {
|
||||
mismatch: 'Το ${label} δεν ταιριάζει με το μοτίβο ${pattern}',
|
||||
},
|
||||
},
|
||||
},
|
||||
Image: {
|
||||
preview: 'Προεπισκόπηση',
|
||||
},
|
||||
QRCode: {
|
||||
expired: 'Ο κωδικός QR έληξε',
|
||||
refresh: 'Ανανέωση',
|
||||
scanned: 'Σαρώθηκε',
|
||||
},
|
||||
ColorPicker: {
|
||||
presetEmpty: 'Κενό',
|
||||
transparent: 'Διαφανές',
|
||||
singleColor: 'Μονόχρωμο',
|
||||
gradientColor: 'Διαβάθμιση χρώματος',
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -36,6 +36,11 @@ const localeValues: Locale = {
|
||||
triggerAsc: 'Click para ordenar en orden ascendente',
|
||||
cancelSort: 'Click para cancelar ordenamiento',
|
||||
},
|
||||
Tour: {
|
||||
Next: 'Siguiente',
|
||||
Previous: 'Anterior',
|
||||
Finish: 'Finalizar',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'Aceptar',
|
||||
cancelText: 'Cancelar',
|
||||
|
@ -13,12 +13,13 @@ import getAllowClear from '../_util/getAllowClear';
|
||||
import genPurePanel from '../_util/PurePanel';
|
||||
import type { InputStatus } from '../_util/statusUtils';
|
||||
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
|
||||
import toList from '../_util/toList';
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import type { Variant } from '../config-provider';
|
||||
import DefaultRenderEmpty from '../config-provider/defaultRenderEmpty';
|
||||
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
|
||||
import { FormItemInputContext } from '../form/context';
|
||||
import type { Variant } from '../config-provider';
|
||||
import useVariant from '../form/hooks/useVariants';
|
||||
import Spin from '../spin';
|
||||
import useStyle from './style';
|
||||
@ -238,7 +239,7 @@ Mentions._InternalPanelDoNotUseOrYouWillBeFired = PurePanel;
|
||||
|
||||
Mentions.getMentions = (value = '', config: MentionsConfig = {}): MentionsEntity[] => {
|
||||
const { prefix = '@', split = ' ' } = config;
|
||||
const prefixList: string[] = Array.isArray(prefix) ? prefix : [prefix];
|
||||
const prefixList: string[] = toList(prefix);
|
||||
|
||||
return value
|
||||
.split(split)
|
||||
|
@ -424,7 +424,7 @@ const genMenuItemStyle = (token: MenuToken): CSSObject => {
|
||||
transition: [
|
||||
`border-color ${motionDurationSlow}`,
|
||||
`background ${motionDurationSlow}`,
|
||||
`padding ${motionDurationSlow} ${motionEaseInOut}`,
|
||||
`padding calc(${motionDurationSlow} + 0.1s) ${motionEaseInOut}`,
|
||||
].join(','),
|
||||
|
||||
[`${componentCls}-item-icon, ${iconCls}`]: {
|
||||
|
@ -58,11 +58,11 @@ const getVerticalStyle: GenerateStyle<MenuToken> = (token) => {
|
||||
colorTextLightSolid,
|
||||
dropdownWidth,
|
||||
controlHeightLG,
|
||||
motionDurationMid,
|
||||
motionEaseOut,
|
||||
paddingXL,
|
||||
itemMarginInline,
|
||||
fontSizeLG,
|
||||
motionDurationFast,
|
||||
motionDurationSlow,
|
||||
paddingXS,
|
||||
boxShadowSecondary,
|
||||
@ -128,7 +128,7 @@ const getVerticalStyle: GenerateStyle<MenuToken> = (token) => {
|
||||
transition: [
|
||||
`border-color ${motionDurationSlow}`,
|
||||
`background ${motionDurationSlow}`,
|
||||
`padding ${motionDurationMid} ${motionEaseOut}`,
|
||||
`padding ${motionDurationFast} ${motionEaseOut}`,
|
||||
].join(','),
|
||||
|
||||
[`> ${componentCls}-title-content`]: {
|
||||
|
@ -398,7 +398,6 @@ const genPaginationJumpStyle: GenerateStyle<PaginationToken, CSSObject> = (token
|
||||
display: 'block',
|
||||
margin: 'auto',
|
||||
color: token.colorTextDisabled,
|
||||
fontFamily: 'Arial, Helvetica, sans-serif',
|
||||
letterSpacing: token.paginationEllipsisLetterSpacing,
|
||||
textAlign: 'center',
|
||||
textIndent: token.paginationEllipsisTextIndent,
|
||||
@ -446,7 +445,6 @@ const genPaginationJumpStyle: GenerateStyle<PaginationToken, CSSObject> = (token
|
||||
},
|
||||
|
||||
[`${componentCls}-prev, ${componentCls}-next`]: {
|
||||
fontFamily: 'Arial, Helvetica, sans-serif',
|
||||
outline: 0,
|
||||
|
||||
button: {
|
||||
|
@ -1536,7 +1536,7 @@ exports[`renders components/select/demo/custom-label-render.tsx extend context c
|
||||
class="ant-select-selection-item"
|
||||
>
|
||||
<span>
|
||||
当前 value 没有对应的选项
|
||||
No option match
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -731,7 +731,7 @@ exports[`renders components/select/demo/custom-label-render.tsx correctly 1`] =
|
||||
class="ant-select-selection-item"
|
||||
>
|
||||
<span>
|
||||
当前 value 没有对应的选项
|
||||
No option match
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -17,7 +17,7 @@ const labelRender: LabelRender = (props) => {
|
||||
if (label) {
|
||||
return value;
|
||||
}
|
||||
return <span>当前 value 没有对应的选项</span>;
|
||||
return <span>No option match</span>;
|
||||
};
|
||||
|
||||
const App: React.FC = () => (
|
||||
|
@ -1698,6 +1698,127 @@ describe('Table.rowSelection', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('treeData cache with preserveSelectedRowKeys and checkStrictly false', () => {
|
||||
const onChange = jest.fn();
|
||||
const treeDataColumns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
];
|
||||
const { container, rerender } = render(
|
||||
<Table
|
||||
expandable={{
|
||||
defaultExpandAllRows: true,
|
||||
}}
|
||||
columns={treeDataColumns}
|
||||
dataSource={[
|
||||
{
|
||||
key: 1,
|
||||
name: 'a',
|
||||
children: [
|
||||
{
|
||||
key: 11,
|
||||
name: 'b',
|
||||
},
|
||||
{
|
||||
key: 12,
|
||||
name: 'c',
|
||||
children: [
|
||||
{
|
||||
key: 121,
|
||||
name: 'd',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
name: 'e',
|
||||
},
|
||||
]}
|
||||
rowSelection={{ onChange, preserveSelectedRowKeys: true, checkStrictly: false }}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(container.querySelector('th input')!);
|
||||
expect(onChange).toHaveBeenCalledWith(
|
||||
[1, 11, 12, 121, 2],
|
||||
[
|
||||
{
|
||||
key: 1,
|
||||
name: 'a',
|
||||
children: [
|
||||
{
|
||||
key: 11,
|
||||
name: 'b',
|
||||
},
|
||||
{
|
||||
key: 12,
|
||||
name: 'c',
|
||||
children: [
|
||||
{
|
||||
key: 121,
|
||||
name: 'd',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ key: 11, name: 'b' },
|
||||
{ key: 12, name: 'c', children: [{ key: 121, name: 'd' }] },
|
||||
{ key: 121, name: 'd' },
|
||||
{ key: 2, name: 'e' },
|
||||
],
|
||||
{ type: 'all' },
|
||||
);
|
||||
|
||||
rerender(
|
||||
<Table
|
||||
expandable={{
|
||||
defaultExpandAllRows: true,
|
||||
}}
|
||||
columns={treeDataColumns}
|
||||
dataSource={[
|
||||
{
|
||||
key: 1,
|
||||
name: 'a',
|
||||
children: [
|
||||
{
|
||||
key: 11,
|
||||
name: 'b',
|
||||
},
|
||||
{
|
||||
key: 12,
|
||||
name: 'c',
|
||||
children: [
|
||||
{
|
||||
key: 121,
|
||||
name: 'd',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
rowSelection={{ onChange, preserveSelectedRowKeys: true, checkStrictly: false }}
|
||||
/>,
|
||||
);
|
||||
fireEvent.click(container.querySelectorAll('tbody input[type="checkbox"]')[1]);
|
||||
expect(onChange).toHaveBeenCalledWith(
|
||||
[12, 121, 2],
|
||||
[
|
||||
{ key: 12, name: 'c', children: [{ key: 121, name: 'd' }] },
|
||||
{ key: 121, name: 'd' },
|
||||
{ key: 2, name: 'e' },
|
||||
],
|
||||
{ type: 'single' },
|
||||
);
|
||||
expect(getIndeterminateSelection(container)).toEqual([1]);
|
||||
});
|
||||
|
||||
it('works with receive selectedRowKeys from [] to undefined', () => {
|
||||
const onChange = jest.fn();
|
||||
const dataSource = [{ name: 'Jack' }];
|
||||
|
@ -28974,3 +28974,516 @@ Array [
|
||||
`;
|
||||
|
||||
exports[`renders components/table/demo/tree-table-ellipsis.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/table/demo/tree-table-preserveSelectedRowKeys.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small"
|
||||
style="margin-bottom: 16px;"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
CheckStrictly:
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner-checked"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner-unchecked"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
preserveSelectedRowKeys:
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner-checked"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner-unchecked"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-table-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-nested-loading"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table"
|
||||
>
|
||||
<div
|
||||
class="ant-table-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
>
|
||||
<table
|
||||
style="table-layout: auto;"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
class="ant-table-selection-col"
|
||||
/>
|
||||
<col />
|
||||
<col
|
||||
style="width: 12%;"
|
||||
/>
|
||||
<col
|
||||
style="width: 30%;"
|
||||
/>
|
||||
</colgroup>
|
||||
<thead
|
||||
class="ant-table-thead"
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
scope="col"
|
||||
>
|
||||
<div
|
||||
class="ant-table-selection"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
aria-label="Select all"
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
scope="col"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
scope="col"
|
||||
>
|
||||
Age
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
scope="col"
|
||||
>
|
||||
Address
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="ant-table-tbody"
|
||||
>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key0"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left: 0px;"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 0
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 0
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key1"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left: 0px;"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 1
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 1
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key2"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left: 0px;"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 2
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 2
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key3"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left: 0px;"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 3
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 3
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key4"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left: 0px;"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 4
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 4
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-pagination ant-table-pagination ant-table-pagination-right"
|
||||
>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-prev ant-pagination-disabled"
|
||||
title="Previous Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
||||
tabindex="0"
|
||||
title="1"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-2"
|
||||
tabindex="0"
|
||||
title="2"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
2
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-3"
|
||||
tabindex="0"
|
||||
title="3"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
3
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
aria-disabled="false"
|
||||
class="ant-pagination-next"
|
||||
tabindex="0"
|
||||
title="Next Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="right"
|
||||
class="anticon anticon-right"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/table/demo/tree-table-preserveSelectedRowKeys.tsx extend context correctly 2`] = `[]`;
|
||||
|
@ -28118,3 +28118,514 @@ Array [
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/table/demo/tree-table-preserveSelectedRowKeys.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center ant-space-gap-row-small ant-space-gap-col-small"
|
||||
style="margin-bottom:16px"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
CheckStrictly:
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner-checked"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner-unchecked"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
preserveSelectedRowKeys:
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner-checked"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner-unchecked"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-table-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-nested-loading"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table"
|
||||
>
|
||||
<div
|
||||
class="ant-table-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
>
|
||||
<table
|
||||
style="table-layout:auto"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
class="ant-table-selection-col"
|
||||
/>
|
||||
<col />
|
||||
<col
|
||||
style="width:12%"
|
||||
/>
|
||||
<col
|
||||
style="width:30%"
|
||||
/>
|
||||
</colgroup>
|
||||
<thead
|
||||
class="ant-table-thead"
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
scope="col"
|
||||
>
|
||||
<div
|
||||
class="ant-table-selection"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
aria-label="Select all"
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
scope="col"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
scope="col"
|
||||
>
|
||||
Age
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
scope="col"
|
||||
>
|
||||
Address
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="ant-table-tbody"
|
||||
>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key0"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 0
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 0
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key1"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 1
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 1
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key2"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 2
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 2
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key3"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 3
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 3
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="key4"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell ant-table-selection-column"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox ant-wave-target"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-with-append"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
style="padding-left:0px"
|
||||
/>
|
||||
<button
|
||||
aria-expanded="false"
|
||||
aria-label="Expand row"
|
||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
||||
type="button"
|
||||
/>
|
||||
Edward 4
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
32
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
London Park no. 4
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-pagination ant-table-pagination ant-table-pagination-right"
|
||||
>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-prev ant-pagination-disabled"
|
||||
title="Previous Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
||||
tabindex="0"
|
||||
title="1"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-2"
|
||||
tabindex="0"
|
||||
title="2"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
2
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-3"
|
||||
tabindex="0"
|
||||
title="3"
|
||||
>
|
||||
<a
|
||||
rel="nofollow"
|
||||
>
|
||||
3
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
aria-disabled="false"
|
||||
class="ant-pagination-next"
|
||||
tabindex="0"
|
||||
title="Next Page"
|
||||
>
|
||||
<button
|
||||
class="ant-pagination-item-link"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="right"
|
||||
class="anticon anticon-right"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
11
components/table/demo/tree-table-preserveSelectedRowKeys.md
Normal file
11
components/table/demo/tree-table-preserveSelectedRowKeys.md
Normal file
@ -0,0 +1,11 @@
|
||||
## zh-CN
|
||||
|
||||
treeData Table 使用 CheckStrictly: false & preserveSelectedRowKeys: true 的示例
|
||||
|
||||
https://github.com/ant-design/ant-design/issues/50621
|
||||
|
||||
## en-US
|
||||
|
||||
treeData Table using CheckStrictly: false & preserveSelectedRowKeys: true example
|
||||
|
||||
https://github.com/ant-design/ant-design/issues/50621
|
93
components/table/demo/tree-table-preserveSelectedRowKeys.tsx
Normal file
93
components/table/demo/tree-table-preserveSelectedRowKeys.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Space, Switch, Table } from 'antd';
|
||||
import type { TableColumnsType, TableProps } from 'antd';
|
||||
|
||||
type TableRowSelection<T extends object = object> = TableProps<T>['rowSelection'];
|
||||
|
||||
interface DataType {
|
||||
key: React.ReactNode;
|
||||
name: string;
|
||||
age: number;
|
||||
address: string;
|
||||
children?: DataType[];
|
||||
}
|
||||
|
||||
const columns: TableColumnsType<DataType> = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Age',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
width: '12%',
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
dataIndex: 'address',
|
||||
width: '30%',
|
||||
key: 'address',
|
||||
},
|
||||
];
|
||||
|
||||
const data: DataType[] = [];
|
||||
for (let i = 0; i < 15; i++) {
|
||||
data.push({
|
||||
key: `key${i}`,
|
||||
name: `Edward ${i}`,
|
||||
age: 32,
|
||||
address: `London Park no. ${i}`,
|
||||
children: [
|
||||
{
|
||||
key: `subKey${i}1`,
|
||||
name: 'Brown',
|
||||
age: 16,
|
||||
address: 'New York No. 3 Lake Park',
|
||||
},
|
||||
{
|
||||
key: `subKey${i}2`,
|
||||
name: 'Jimmy',
|
||||
age: 16,
|
||||
address: 'New York No. 3 Lake Park',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// rowSelection objects indicates the need for row selection
|
||||
const rowSelection: TableRowSelection<DataType> = {
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
|
||||
},
|
||||
onSelect: (record, selected, selectedRows) => {
|
||||
console.log(record, selected, selectedRows);
|
||||
},
|
||||
onSelectAll: (selected, selectedRows, changeRows) => {
|
||||
console.log(selected, selectedRows, changeRows);
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [checkStrictly, setCheckStrictly] = useState(false);
|
||||
const [preserveSelectedRowKeys, setPreserveSelectedRowKeys] = useState(true);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space align="center" style={{ marginBottom: 16 }}>
|
||||
CheckStrictly: <Switch checked={checkStrictly} onChange={setCheckStrictly} />
|
||||
preserveSelectedRowKeys:{' '}
|
||||
<Switch checked={preserveSelectedRowKeys} onChange={setPreserveSelectedRowKeys} />
|
||||
</Space>
|
||||
<Table
|
||||
columns={columns}
|
||||
rowSelection={{ ...rowSelection, checkStrictly, preserveSelectedRowKeys }}
|
||||
dataSource={data}
|
||||
pagination={{ defaultPageSize: 5 }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
@ -152,13 +152,20 @@ const useSelection = <RecordType extends AnyObject = AnyObject>(
|
||||
updatePreserveRecordsCache(mergedSelectedKeys);
|
||||
}, [mergedSelectedKeys]);
|
||||
|
||||
// Get flatten data
|
||||
const flattedData = useMemo(
|
||||
() => flattenData(childrenColumnName, pageData),
|
||||
[childrenColumnName, pageData],
|
||||
);
|
||||
|
||||
const { keyEntities } = useMemo(() => {
|
||||
if (checkStrictly) {
|
||||
return { keyEntities: null };
|
||||
}
|
||||
let convertData = data;
|
||||
if (preserveSelectedRowKeys) {
|
||||
const keysSet = new Set(data.map((record, index) => getRowKey(record, index)));
|
||||
// use flattedData keys
|
||||
const keysSet = new Set(flattedData.map((record, index) => getRowKey(record, index)));
|
||||
// remove preserveRecords that duplicate data
|
||||
const preserveRecords = Array.from(preserveRecordsRef.current).reduce(
|
||||
(total: RecordType[], [key, value]) => (keysSet.has(key) ? total : total.concat(value)),
|
||||
@ -170,13 +177,7 @@ const useSelection = <RecordType extends AnyObject = AnyObject>(
|
||||
externalGetKey: getRowKey as any,
|
||||
childrenPropName: childrenColumnName,
|
||||
});
|
||||
}, [data, getRowKey, checkStrictly, childrenColumnName, preserveSelectedRowKeys]);
|
||||
|
||||
// Get flatten data
|
||||
const flattedData = useMemo(
|
||||
() => flattenData(childrenColumnName, pageData),
|
||||
[childrenColumnName, pageData],
|
||||
);
|
||||
}, [data, getRowKey, checkStrictly, childrenColumnName, preserveSelectedRowKeys, flattedData]);
|
||||
|
||||
// Get all checkbox props
|
||||
const checkboxPropsMap = useMemo(() => {
|
||||
|
@ -87,7 +87,7 @@ const columns = [
|
||||
<code src="./demo/fixed-columns.tsx">Fixed Columns</code>
|
||||
<code src="./demo/fixed-gapped-columns.tsx" version="5.14.0">Stack Fixed Columns</code>
|
||||
<code src="./demo/fixed-columns-header.tsx">Fixed Columns and Header</code>
|
||||
<code src="./demo/hidden-columns.tsx">Hidden Columns</code>
|
||||
<code src="./demo/hidden-columns.tsx" version="5.13.0">Hidden Columns</code>
|
||||
<code src="./demo/grouping-columns.tsx">Grouping table head</code>
|
||||
<code src="./demo/edit-cell.tsx">Editable Cells</code>
|
||||
<code src="./demo/edit-row.tsx">Editable Rows</code>
|
||||
@ -100,7 +100,7 @@ const columns = [
|
||||
<code src="./demo/ellipsis-custom-tooltip.tsx">ellipsis column custom tooltip</code>
|
||||
<code src="./demo/custom-empty.tsx">Custom empty</code>
|
||||
<code src="./demo/summary.tsx">Summary</code>
|
||||
<code src="./demo/virtual-list.tsx" version=">= 5.9.0">Virtual list</code>
|
||||
<code src="./demo/virtual-list.tsx" version="5.9.0">Virtual list</code>
|
||||
<code src="./demo/responsive.tsx">Responsive</code>
|
||||
<code src="./demo/nest-table-border-debug.tsx" debug>Nested Bordered Table Debug</code>
|
||||
<code src="./demo/pagination.tsx">Pagination Settings</code>
|
||||
|
@ -84,11 +84,12 @@ const columns = [
|
||||
<code src="./demo/colspan-rowspan.tsx">表格行/列合并</code>
|
||||
<code src="./demo/tree-data.tsx">树形数据展示</code>
|
||||
<code src="./demo/tree-table-ellipsis.tsx" debug>树形数据省略情况测试</code>
|
||||
<code src="./demo/tree-table-preserveSelectedRowKeys.tsx" debug>树形数据保留key测试</code>
|
||||
<code src="./demo/fixed-header.tsx">固定表头</code>
|
||||
<code src="./demo/fixed-columns.tsx">固定列</code>
|
||||
<code src="./demo/fixed-gapped-columns.tsx" version="5.14.0">堆叠固定列</code>
|
||||
<code src="./demo/fixed-columns-header.tsx">固定头和列</code>
|
||||
<code src="./demo/hidden-columns.tsx">隐藏列</code>
|
||||
<code src="./demo/hidden-columns.tsx" version="5.13.0">隐藏列</code>
|
||||
<code src="./demo/grouping-columns.tsx">表头分组</code>
|
||||
<code src="./demo/edit-cell.tsx">可编辑单元格</code>
|
||||
<code src="./demo/edit-row.tsx">可编辑行</code>
|
||||
@ -101,7 +102,7 @@ const columns = [
|
||||
<code src="./demo/ellipsis-custom-tooltip.tsx">自定义单元格省略提示</code>
|
||||
<code src="./demo/custom-empty.tsx">自定义空状态</code>
|
||||
<code src="./demo/summary.tsx">总结栏</code>
|
||||
<code src="./demo/virtual-list.tsx" version=">= 5.9.0">虚拟列表</code>
|
||||
<code src="./demo/virtual-list.tsx" version="5.9.0">虚拟列表</code>
|
||||
<code src="./demo/responsive.tsx">响应式</code>
|
||||
<code src="./demo/nest-table-border-debug.tsx" debug>嵌套带边框的表格 Debug</code>
|
||||
<code src="./demo/pagination.tsx">分页设置</code>
|
||||
|
@ -352,4 +352,24 @@ describe('Typography copy', () => {
|
||||
fireEvent.click(container.querySelectorAll('.ant-typography-copy')[0]);
|
||||
expect(container.querySelector('.ant-tooltip-inner')?.textContent).toBe('Copied');
|
||||
});
|
||||
|
||||
it('copy array children', () => {
|
||||
const spy = jest.spyOn(copyObj, 'default');
|
||||
|
||||
const bamboo = 'bamboo';
|
||||
const little = 'little';
|
||||
|
||||
const { container } = render(
|
||||
<Base component="p" copyable>
|
||||
{bamboo}
|
||||
{little}
|
||||
</Base>,
|
||||
);
|
||||
fireEvent.click(container.querySelector('.ant-typography-copy')!);
|
||||
|
||||
// Check copy content
|
||||
expect(spy.mock.calls[0][0]).toBe(`${bamboo}${little}`);
|
||||
|
||||
spy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { useEvent } from 'rc-util';
|
||||
|
||||
import toList from '../../_util/toList';
|
||||
import type { CopyConfig } from '../Base';
|
||||
|
||||
const useCopyClick = ({
|
||||
@ -38,7 +39,7 @@ const useCopyClick = ({
|
||||
try {
|
||||
const text =
|
||||
typeof copyConfig.text === 'function' ? await copyConfig.text() : copyConfig.text;
|
||||
copy(text || String(children) || '', copyOptions);
|
||||
copy(text || toList(children, true).join('') || '', copyOptions);
|
||||
setCopyLoading(false);
|
||||
|
||||
setCopied(true);
|
||||
|
@ -10,6 +10,7 @@ import useClips, { FontGap } from './useClips';
|
||||
import useRafDebounce from './useRafDebounce';
|
||||
import useWatermark from './useWatermark';
|
||||
import { getPixelRatio, reRendering } from './utils';
|
||||
import toList from '../_util/toList';
|
||||
|
||||
export interface WatermarkProps {
|
||||
zIndex?: number;
|
||||
@ -145,7 +146,7 @@ const Watermark: React.FC<WatermarkProps> = (props) => {
|
||||
let defaultHeight = 64;
|
||||
if (!image && ctx.measureText) {
|
||||
ctx.font = `${Number(fontSize)}px ${fontFamily}`;
|
||||
const contents = Array.isArray(content) ? content : [content];
|
||||
const contents = toList(content);
|
||||
const sizes = contents.map((item) => {
|
||||
const metrics = ctx.measureText(item!);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { WatermarkProps } from '.';
|
||||
import toList from '../_util/toList';
|
||||
|
||||
export const FontGap = 3;
|
||||
|
||||
@ -55,7 +56,7 @@ export default function useClips() {
|
||||
ctx.fillStyle = color;
|
||||
ctx.textAlign = textAlign;
|
||||
ctx.textBaseline = 'top';
|
||||
const contents = Array.isArray(content) ? content : [content];
|
||||
const contents = toList(content);
|
||||
contents?.forEach((item, index) => {
|
||||
ctx.fillText(item ?? '', contentWidth / 2, index * (mergedFontSize + FontGap * ratio));
|
||||
});
|
||||
|
19
package.json
19
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "5.20.5",
|
||||
"version": "5.20.6",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"keywords": [
|
||||
"ant",
|
||||
@ -31,7 +31,13 @@
|
||||
"unpkg": "dist/antd.min.js",
|
||||
"module": "es/index.js",
|
||||
"typings": "es/index.d.ts",
|
||||
"files": ["dist", "es", "lib", "locale", "BUG_VERSIONS.json"],
|
||||
"files": [
|
||||
"dist",
|
||||
"es",
|
||||
"lib",
|
||||
"locale",
|
||||
"BUG_VERSIONS.json"
|
||||
],
|
||||
"scripts": {
|
||||
"api-collection": "antd-tools run api-collection",
|
||||
"authors": "tsx scripts/generate-authors.ts",
|
||||
@ -96,7 +102,12 @@
|
||||
"tsc:old": "tsc --noEmit -p tsconfig-old-react.json",
|
||||
"version": "tsx scripts/generate-version.ts"
|
||||
},
|
||||
"browserslist": ["> 0.5%", "last 2 versions", "Firefox ESR", "not dead"],
|
||||
"browserslist": [
|
||||
"> 0.5%",
|
||||
"last 2 versions",
|
||||
"Firefox ESR",
|
||||
"not dead"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.1.0",
|
||||
"@ant-design/cssinjs": "^1.21.0",
|
||||
@ -109,7 +120,7 @@
|
||||
"@rc-component/mutate-observer": "^1.1.0",
|
||||
"@rc-component/qrcode": "~1.0.0",
|
||||
"@rc-component/tour": "~1.15.1",
|
||||
"@rc-component/trigger": "^2.2.2",
|
||||
"@rc-component/trigger": "^2.2.3",
|
||||
"classnames": "^2.5.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.11",
|
||||
|
Loading…
Reference in New Issue
Block a user