mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
Merge branch 'master' into next-merge-master
This commit is contained in:
commit
eb9179464b
@ -15,6 +15,17 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.23.2
|
||||||
|
|
||||||
|
`2022-09-17`
|
||||||
|
|
||||||
|
- 🐞 Fix Card console warning when using `tabList` prop. [#37537](https://github.com/ant-design/ant-design/pull/37537) [@edc-hui](https://github.com/edc-hui)
|
||||||
|
- 🐞 Fix Table `filterSearch` is not executed when `filterMode="tree"`. [#37587](https://github.com/ant-design/ant-design/pull/37587) [@edc-hui](https://github.com/edc-hui)
|
||||||
|
- 🐞 Fix Tooltip should not replace children `className` when it's not a string type. [#37598](https://github.com/ant-design/ant-design/pull/37598)
|
||||||
|
- 🐞 Fix Tree that TreeNodes not aligned when draggable and some node is disabled. [#37534](https://github.com/ant-design/ant-design/pull/37534)
|
||||||
|
- TypeScript
|
||||||
|
- 🤖 Replace deprecated `React.ReactChild` type. [#37551](https://github.com/ant-design/ant-design/pull/37551) [@bowen-wu](https://github.com/bowen-wu)
|
||||||
|
|
||||||
## 4.23.1
|
## 4.23.1
|
||||||
|
|
||||||
`2022-09-09`
|
`2022-09-09`
|
||||||
@ -202,7 +213,7 @@ timeline: true
|
|||||||
- 💄 Fix nested Table margin style. [#36209](https://github.com/ant-design/ant-design/pull/36209)
|
- 💄 Fix nested Table margin style. [#36209](https://github.com/ant-design/ant-design/pull/36209)
|
||||||
- 🐞 Fix Table filter dropdown with multiple subMenu may not closed. [#36132](https://github.com/ant-design/ant-design/pull/36132)
|
- 🐞 Fix Table filter dropdown with multiple subMenu may not closed. [#36132](https://github.com/ant-design/ant-design/pull/36132)
|
||||||
- 🐞 Table reset the last selection key when deselect or bulk operations. [#34705](https://github.com/ant-design/ant-design/pull/34705) [@Dunqing](https://github.com/Dunqing)
|
- 🐞 Table reset the last selection key when deselect or bulk operations. [#34705](https://github.com/ant-design/ant-design/pull/34705) [@Dunqing](https://github.com/Dunqing)
|
||||||
- 🐞 Fix Popover arrow color with custom `color` prop. [#36241](https://github.com/ant-design/ant-design/pull/36241) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 Fix Popover arrow color with custom `color` prop. [#36241](https://github.com/ant-design/ant-design/pull/36241)
|
||||||
- 🐞 Fix Upload `listType="picture-card"` select button not being hidden when children is empty. [#36196](https://github.com/ant-design/ant-design/pull/36196)
|
- 🐞 Fix Upload `listType="picture-card"` select button not being hidden when children is empty. [#36196](https://github.com/ant-design/ant-design/pull/36196)
|
||||||
- 🐞 Fix Menu deprecated warning when `item={undefined}`. [#36190](https://github.com/ant-design/ant-design/pull/36190)
|
- 🐞 Fix Menu deprecated warning when `item={undefined}`. [#36190](https://github.com/ant-design/ant-design/pull/36190)
|
||||||
- 💄 Fix Button `loading` icon margin style lost. [#36168](https://github.com/ant-design/ant-design/pull/36168)
|
- 💄 Fix Button `loading` icon margin style lost. [#36168](https://github.com/ant-design/ant-design/pull/36168)
|
||||||
@ -425,7 +436,7 @@ timeline: true
|
|||||||
- Less
|
- Less
|
||||||
- 💄 Replace less html selector with related variable. [#35186](https://github.com/ant-design/ant-design/pull/35186) [@jeffdrumgod](https://github.com/jeffdrumgod)
|
- 💄 Replace less html selector with related variable. [#35186](https://github.com/ant-design/ant-design/pull/35186) [@jeffdrumgod](https://github.com/jeffdrumgod)
|
||||||
- 💄 Modify less `danger` value from the function to variable. [#35113](https://github.com/ant-design/ant-design/pull/35113) [@TrickyPi](https://github.com/TrickyPi)
|
- 💄 Modify less `danger` value from the function to variable. [#35113](https://github.com/ant-design/ant-design/pull/35113) [@TrickyPi](https://github.com/TrickyPi)
|
||||||
- 🐞 Arrow border radius variable use fixed value. [#35086](https://github.com/ant-design/ant-design/pull/35086) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 Arrow border radius variable use fixed value. [#35086](https://github.com/ant-design/ant-design/pull/35086)
|
||||||
- TypeScript
|
- TypeScript
|
||||||
- 🤖 Fixed `Upload` component `UploadChangeParam<T>` internal `fileList` not using generics. [#35158](https://github.com/ant-design/ant-design/pull/35158) [@rendaoer](https://github.com/rendaoer)
|
- 🤖 Fixed `Upload` component `UploadChangeParam<T>` internal `fileList` not using generics. [#35158](https://github.com/ant-design/ant-design/pull/35158) [@rendaoer](https://github.com/rendaoer)
|
||||||
- 🤖 Update TypeScript definition for `@types/react@18` compatible. [#35075](https://github.com/ant-design/ant-design/pull/35075) [@AliRezaBeigy](https://github.com/AliRezaBeigy) [#35076](https://github.com/ant-design/ant-design/pull/35076) [@littledian](https://github.com/littledian)
|
- 🤖 Update TypeScript definition for `@types/react@18` compatible. [#35075](https://github.com/ant-design/ant-design/pull/35075) [@AliRezaBeigy](https://github.com/AliRezaBeigy) [#35076](https://github.com/ant-design/ant-design/pull/35076) [@littledian](https://github.com/littledian)
|
||||||
@ -580,7 +591,7 @@ timeline: true
|
|||||||
- 💄 Improve Menu `:focus-visible` style. [#34008](https://github.com/ant-design/ant-design/pull/34008)
|
- 💄 Improve Menu `:focus-visible` style. [#34008](https://github.com/ant-design/ant-design/pull/34008)
|
||||||
- 💄 Fix Pagination and Rate style problem in Safari. [#34002](https://github.com/ant-design/ant-design/pull/34002)
|
- 💄 Fix Pagination and Rate style problem in Safari. [#34002](https://github.com/ant-design/ant-design/pull/34002)
|
||||||
- 💄 Fix Row and Col component styles when using prefixCls. [#33969](https://github.com/ant-design/ant-design/pull/33969) [@mic-web](https://github.com/mic-web)
|
- 💄 Fix Row and Col component styles when using prefixCls. [#33969](https://github.com/ant-design/ant-design/pull/33969) [@mic-web](https://github.com/mic-web)
|
||||||
- 🐞 Fix Timeline icons with custom color not working. [#33951](https://github.com/ant-design/ant-design/pull/33951) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 Fix Timeline icons with custom color not working. [#33951](https://github.com/ant-design/ant-design/pull/33951)
|
||||||
- TypeScript
|
- TypeScript
|
||||||
- 🤖 Optimize Cascader `onChange` definition with `multiple` prop. [#33947](https://github.com/ant-design/ant-design/pull/33947) [@babycannotsay](https://github.com/babycannotsay)
|
- 🤖 Optimize Cascader `onChange` definition with `multiple` prop. [#33947](https://github.com/ant-design/ant-design/pull/33947) [@babycannotsay](https://github.com/babycannotsay)
|
||||||
|
|
||||||
@ -663,7 +674,7 @@ timeline: true
|
|||||||
|
|
||||||
`2021-12-29`
|
`2021-12-29`
|
||||||
|
|
||||||
- 🐞 Fix Popconfirm throws `Can't perform a React state update on an unmounted component.` warning in some async case. [#33432](https://github.com/ant-design/ant-design/pull/33432) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 Fix Popconfirm throws `Can't perform a React state update on an unmounted component.` warning in some async case. [#33432](https://github.com/ant-design/ant-design/pull/33432)
|
||||||
- 🐞 Fix Input with `suffix` will crash when `value` is number type. [#33462](https://github.com/ant-design/ant-design/pull/33462)
|
- 🐞 Fix Input with `suffix` will crash when `value` is number type. [#33462](https://github.com/ant-design/ant-design/pull/33462)
|
||||||
- 🐞 Fix Divider with text dashed border color error. [#33452](https://github.com/ant-design/ant-design/pull/33452) [@chen-jingjie](https://github.com/chen-jingjie)
|
- 🐞 Fix Divider with text dashed border color error. [#33452](https://github.com/ant-design/ant-design/pull/33452) [@chen-jingjie](https://github.com/chen-jingjie)
|
||||||
- 🐞 Fix Dropdown.Button not support `destroyPopupOnHide`. [#33442](https://github.com/ant-design/ant-design/pull/33442) [@LongHaoo](https://github.com/LongHaoo)
|
- 🐞 Fix Dropdown.Button not support `destroyPopupOnHide`. [#33442](https://github.com/ant-design/ant-design/pull/33442) [@LongHaoo](https://github.com/LongHaoo)
|
||||||
|
@ -15,6 +15,17 @@ timeline: true
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.23.2
|
||||||
|
|
||||||
|
`2022-09-17`
|
||||||
|
|
||||||
|
- 🐞 修复 Card 传入 `tabList` 属性时控制台出现废弃警告的问题。[#37537](https://github.com/ant-design/ant-design/pull/37537) [@edc-hui](https://github.com/edc-hui)
|
||||||
|
- 🐞 修复 Table `filterMode="tree"` 时 `filterSearch` 函数未执行的问题。[#37587](https://github.com/ant-design/ant-design/pull/37587) [@edc-hui](https://github.com/edc-hui)
|
||||||
|
- 🐞 修复 Tooltip 的子元素 `className` 非 string 类型时会被覆盖的问题。[#37598](https://github.com/ant-design/ant-design/pull/37598)
|
||||||
|
- 🐞 修复 Tree 组件 TreeNode 在可拖拽并且禁用状态下不对齐的问题。[#37534](https://github.com/ant-design/ant-design/pull/37534)
|
||||||
|
- TypeScript
|
||||||
|
- 🤖 替换已废弃的 `React.ReactChild` 定义。[#37551](https://github.com/ant-design/ant-design/pull/37551) [@bowen-wu](https://github.com/bowen-wu)
|
||||||
|
|
||||||
## 4.23.1
|
## 4.23.1
|
||||||
|
|
||||||
`2022-09-09`
|
`2022-09-09`
|
||||||
@ -203,7 +214,7 @@ timeline: true
|
|||||||
- 🐞 Table 取消选择或批量操作时重置上一次选择的 key。[#34705](https://github.com/ant-design/ant-design/pull/34705) [@Dunqing](https://github.com/Dunqing)
|
- 🐞 Table 取消选择或批量操作时重置上一次选择的 key。[#34705](https://github.com/ant-design/ant-design/pull/34705) [@Dunqing](https://github.com/Dunqing)
|
||||||
- 🐞 修复 Table 过滤列表在某些场景下多级展开无法关闭的问题。[#36132](https://github.com/ant-design/ant-design/pull/36132)
|
- 🐞 修复 Table 过滤列表在某些场景下多级展开无法关闭的问题。[#36132](https://github.com/ant-design/ant-design/pull/36132)
|
||||||
- 🐞 修复 Upload `listType="picture-card"` 当 children 为空时上传文件按钮没有隐藏的问题。[#36196](https://github.com/ant-design/ant-design/pull/36196)
|
- 🐞 修复 Upload `listType="picture-card"` 当 children 为空时上传文件按钮没有隐藏的问题。[#36196](https://github.com/ant-design/ant-design/pull/36196)
|
||||||
- 🐞 修复 Popover 自定义 `color` 时箭头颜色问题。[#36241](https://github.com/ant-design/ant-design/pull/36241) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 修复 Popover 自定义 `color` 时箭头颜色问题。[#36241](https://github.com/ant-design/ant-design/pull/36241)
|
||||||
- 🐞 修复 Menu `item={undefined}` 时会有废弃警告的问题。[#36190](https://github.com/ant-design/ant-design/pull/36190)
|
- 🐞 修复 Menu `item={undefined}` 时会有废弃警告的问题。[#36190](https://github.com/ant-design/ant-design/pull/36190)
|
||||||
- 💄 修复 Button `loading` 图标的间距丢失的问题。[#36168](https://github.com/ant-design/ant-design/pull/36168)
|
- 💄 修复 Button `loading` 图标的间距丢失的问题。[#36168](https://github.com/ant-design/ant-design/pull/36168)
|
||||||
- 🐞 修复 Dropdown 中 Menu 分组下的 Item 点击不会关闭的问题。[#36148](https://github.com/ant-design/ant-design/pull/36148)
|
- 🐞 修复 Dropdown 中 Menu 分组下的 Item 点击不会关闭的问题。[#36148](https://github.com/ant-design/ant-design/pull/36148)
|
||||||
@ -421,12 +432,12 @@ timeline: true
|
|||||||
- 🐞 修复 Title、Text、Paragraph 组件不支持 `ref` 的问题。[#34847](https://github.com/ant-design/ant-design/pull/34847) [@MQuy](https://github.com/MQuy)
|
- 🐞 修复 Title、Text、Paragraph 组件不支持 `ref` 的问题。[#34847](https://github.com/ant-design/ant-design/pull/34847) [@MQuy](https://github.com/MQuy)
|
||||||
- Input
|
- Input
|
||||||
- 💄 Input.Group 对子组件屏蔽 Form.Item 的样式。[#34764](https://github.com/ant-design/ant-design/pull/34764)
|
- 💄 Input.Group 对子组件屏蔽 Form.Item 的样式。[#34764](https://github.com/ant-design/ant-design/pull/34764)
|
||||||
- 💄 调整 Form 下 TextArea 的样式。[#34714](https://github.com/ant-design/ant-design/pull/34714) [@MadCcc](https://github.com/MadCcc)
|
- 💄 调整 Form 下 TextArea 的样式。[#34714](https://github.com/ant-design/ant-design/pull/34714)
|
||||||
- ⌨️ 修复 Checkbox 缺少 `aria-checked` 属性导致屏幕阅读器识别错误的问题。[#34862](https://github.com/ant-design/ant-design/pull/34862) [@SpaNb4](https://github.com/SpaNb4)
|
- ⌨️ 修复 Checkbox 缺少 `aria-checked` 属性导致屏幕阅读器识别错误的问题。[#34862](https://github.com/ant-design/ant-design/pull/34862) [@SpaNb4](https://github.com/SpaNb4)
|
||||||
- Less
|
- Less
|
||||||
- 💄 替换 less 中的 html 选择器为对应变量。[#35186](https://github.com/ant-design/ant-design/pull/35186) [@jeffdrumgod](https://github.com/jeffdrumgod)
|
- 💄 替换 less 中的 html 选择器为对应变量。[#35186](https://github.com/ant-design/ant-design/pull/35186) [@jeffdrumgod](https://github.com/jeffdrumgod)
|
||||||
- 💄 修改 less 中 `danger` 值从函数改为变量。[#35113](https://github.com/ant-design/ant-design/pull/35113) [@TrickyPi](https://github.com/TrickyPi)
|
- 💄 修改 less 中 `danger` 值从函数改为变量。[#35113](https://github.com/ant-design/ant-design/pull/35113) [@TrickyPi](https://github.com/TrickyPi)
|
||||||
- 🐞 箭头圆角使用固定值 2px 变量。[#35086](https://github.com/ant-design/ant-design/pull/35086) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 箭头圆角使用固定值 2px 变量。[#35086](https://github.com/ant-design/ant-design/pull/35086)
|
||||||
- TypeScript
|
- TypeScript
|
||||||
- 🤖 修正 Upload 组件中 `UploadChangeParam<T>` 内部 `fileList` 不使用泛型问题。[#35158](https://github.com/ant-design/ant-design/pull/35158) [@rendaoer](https://github.com/rendaoer)
|
- 🤖 修正 Upload 组件中 `UploadChangeParam<T>` 内部 `fileList` 不使用泛型问题。[#35158](https://github.com/ant-design/ant-design/pull/35158) [@rendaoer](https://github.com/rendaoer)
|
||||||
- 🤖 更新 TypeScript 定义以兼容 `@types/react@18`。[#35075](https://github.com/ant-design/ant-design/pull/35075) [@AliRezaBeigy](https://github.com/AliRezaBeigy) [#35076](https://github.com/ant-design/ant-design/pull/35076) [@littledian](https://github.com/littledian)
|
- 🤖 更新 TypeScript 定义以兼容 `@types/react@18`。[#35075](https://github.com/ant-design/ant-design/pull/35075) [@AliRezaBeigy](https://github.com/AliRezaBeigy) [#35076](https://github.com/ant-design/ant-design/pull/35076) [@littledian](https://github.com/littledian)
|
||||||
@ -582,7 +593,7 @@ timeline: true
|
|||||||
- 💄 优化 Menu `:focus-visible` 的样式。[#34008](https://github.com/ant-design/ant-design/pull/34008)
|
- 💄 优化 Menu `:focus-visible` 的样式。[#34008](https://github.com/ant-design/ant-design/pull/34008)
|
||||||
- 💄 修复 Pagination 和 Rate 在 Safari 下部分样式丢失的问题,比如分页按钮禁用样式失效。[#34002](https://github.com/ant-design/ant-design/pull/34002)
|
- 💄 修复 Pagination 和 Rate 在 Safari 下部分样式丢失的问题,比如分页按钮禁用样式失效。[#34002](https://github.com/ant-design/ant-design/pull/34002)
|
||||||
- 💄 修复 Row 与 Col 在配置 `prefixCls` 的样式问题。[#33969](https://github.com/ant-design/ant-design/pull/33969) [@mic-web](https://github.com/mic-web)
|
- 💄 修复 Row 与 Col 在配置 `prefixCls` 的样式问题。[#33969](https://github.com/ant-design/ant-design/pull/33969) [@mic-web](https://github.com/mic-web)
|
||||||
- 🐞 修复 Timeline 的自定义图标颜色无效的问题。[#33951](https://github.com/ant-design/ant-design/pull/33951) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 修复 Timeline 的自定义图标颜色无效的问题。[#33951](https://github.com/ant-design/ant-design/pull/33951)
|
||||||
- TypeScript
|
- TypeScript
|
||||||
- 🤖 优化 Cascader `multiple` 属性对应的 `onChange` 类型推断。[#33947](https://github.com/ant-design/ant-design/pull/33947) [@babycannotsay](https://github.com/babycannotsay)
|
- 🤖 优化 Cascader `multiple` 属性对应的 `onChange` 类型推断。[#33947](https://github.com/ant-design/ant-design/pull/33947) [@babycannotsay](https://github.com/babycannotsay)
|
||||||
|
|
||||||
@ -665,7 +676,7 @@ timeline: true
|
|||||||
|
|
||||||
`2021-12-29`
|
`2021-12-29`
|
||||||
|
|
||||||
- 🐞 修复 Popconfirm 在某些情况下会出现 `Can't perform a React state update on an unmounted component.` 的错误。[#33432](https://github.com/ant-design/ant-design/pull/33432) [@MadCcc](https://github.com/MadCcc)
|
- 🐞 修复 Popconfirm 在某些情况下会出现 `Can't perform a React state update on an unmounted component.` 的错误。[#33432](https://github.com/ant-design/ant-design/pull/33432)
|
||||||
- 🐞 修复 Input 配置 `suffix` 时 `value` 为数字类型会崩溃的问题。[#33462](https://github.com/ant-design/ant-design/pull/33462)
|
- 🐞 修复 Input 配置 `suffix` 时 `value` 为数字类型会崩溃的问题。[#33462](https://github.com/ant-design/ant-design/pull/33462)
|
||||||
- 🐞 修复 Divider with text dashed 的边框颜色错误问题。[#33452](https://github.com/ant-design/ant-design/pull/33452) [@chen-jingjie](https://github.com/chen-jingjie)
|
- 🐞 修复 Divider with text dashed 的边框颜色错误问题。[#33452](https://github.com/ant-design/ant-design/pull/33452) [@chen-jingjie](https://github.com/chen-jingjie)
|
||||||
- 🐞 修复 Dropdown.Button 不支持 `destroyPopupOnHide` 的问题。[#33442](https://github.com/ant-design/ant-design/pull/33442) [@LongHaoo](https://github.com/LongHaoo)
|
- 🐞 修复 Dropdown.Button 不支持 `destroyPopupOnHide` 的问题。[#33442](https://github.com/ant-design/ant-design/pull/33442) [@LongHaoo](https://github.com/LongHaoo)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import { render, sleep, fireEvent } from '../../../tests/utils';
|
import { render, sleep, fireEvent, act } from '../../../tests/utils';
|
||||||
import ConfigProvider from '../../config-provider';
|
import ConfigProvider from '../../config-provider';
|
||||||
import Wave from '../wave';
|
import Wave from '../wave';
|
||||||
|
|
||||||
@ -270,4 +270,31 @@ describe('Wave component', () => {
|
|||||||
expect(styles[0].innerHTML).toContain('--antd-wave-shadow-color: red;');
|
expect(styles[0].innerHTML).toContain('--antd-wave-shadow-color: red;');
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Wave style should append to validate element', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const { container } = render(
|
||||||
|
<Wave>
|
||||||
|
<div className="bamboo" style={{ borderColor: 'red' }} />
|
||||||
|
</Wave>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mock shadow container
|
||||||
|
const fakeDoc = document.createElement('div');
|
||||||
|
fakeDoc.append('text');
|
||||||
|
fakeDoc.appendChild(document.createElement('span'));
|
||||||
|
expect(fakeDoc.childNodes).toHaveLength(2);
|
||||||
|
|
||||||
|
(container.querySelector('.bamboo') as any).getRootNode = () => fakeDoc;
|
||||||
|
|
||||||
|
// Click should not throw
|
||||||
|
fireEvent.click(container.querySelector('.bamboo')!);
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(fakeDoc.querySelector('style')).toBeTruthy();
|
||||||
|
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -18,6 +18,16 @@ function isHidden(element: HTMLElement) {
|
|||||||
return !element || element.offsetParent === null || element.hidden;
|
return !element || element.offsetParent === null || element.hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getValidateContainer(nodeRoot: Node): Element {
|
||||||
|
if (nodeRoot instanceof Document) {
|
||||||
|
return nodeRoot.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(nodeRoot.childNodes).find(
|
||||||
|
ele => ele?.nodeType === Node.ELEMENT_NODE,
|
||||||
|
) as Element;
|
||||||
|
}
|
||||||
|
|
||||||
function isNotGrey(color: string) {
|
function isNotGrey(color: string) {
|
||||||
// eslint-disable-next-line no-useless-escape
|
// eslint-disable-next-line no-useless-escape
|
||||||
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\d.]*)?\)/);
|
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\d.]*)?\)/);
|
||||||
@ -119,8 +129,7 @@ class InternalWave extends React.Component<WaveProps> {
|
|||||||
extraNode.style.borderColor = waveColor;
|
extraNode.style.borderColor = waveColor;
|
||||||
|
|
||||||
const nodeRoot = node.getRootNode?.() || node.ownerDocument;
|
const nodeRoot = node.getRootNode?.() || node.ownerDocument;
|
||||||
const nodeBody: Element =
|
const nodeBody = getValidateContainer(nodeRoot) ?? nodeRoot;
|
||||||
nodeRoot instanceof Document ? nodeRoot.body : (nodeRoot.firstChild as Element) ?? nodeRoot;
|
|
||||||
|
|
||||||
styleForPseudo = updateCSS(
|
styleForPseudo = updateCSS(
|
||||||
`
|
`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`Alert action of Alert custom action 1`] = `
|
exports[`Alert custom action 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-alert ant-alert-success"
|
class="ant-alert ant-alert-success"
|
||||||
data-show="true"
|
data-show="true"
|
||||||
@ -74,29 +74,6 @@ exports[`Alert action of Alert custom action 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Alert could accept none react element icon 1`] = `
|
|
||||||
<div
|
|
||||||
class="ant-alert ant-alert-success"
|
|
||||||
data-show="true"
|
|
||||||
role="alert"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-alert-icon"
|
|
||||||
>
|
|
||||||
icon
|
|
||||||
</span>
|
|
||||||
<div
|
|
||||||
class="ant-alert-content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-alert-message"
|
|
||||||
>
|
|
||||||
Success Tips
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`Alert rtl render component should be rendered correctly in RTL direction 1`] = `
|
exports[`Alert rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||||
<div
|
<div
|
||||||
class="ant-alert ant-alert-info ant-alert-no-icon ant-alert-rtl"
|
class="ant-alert ant-alert-info ant-alert-no-icon ant-alert-rtl"
|
||||||
@ -108,30 +85,3 @@ exports[`Alert rtl render component should be rendered correctly in RTL directio
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Alert support closeIcon 1`] = `
|
|
||||||
<div
|
|
||||||
class="ant-alert ant-alert-warning ant-alert-no-icon"
|
|
||||||
data-show="true"
|
|
||||||
role="alert"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-alert-content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-alert-message"
|
|
||||||
>
|
|
||||||
Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="ant-alert-close-icon"
|
|
||||||
tabindex="0"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
close
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import Alert from '..';
|
import Alert from '..';
|
||||||
import accessibilityTest from '../../../tests/shared/accessibilityTest';
|
import accessibilityTest from '../../../tests/shared/accessibilityTest';
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
import { fireEvent, render, sleep, act } from '../../../tests/utils';
|
import { render, act, screen } from '../../../tests/utils';
|
||||||
import Button from '../../button';
|
import Button from '../../button';
|
||||||
import Popconfirm from '../../popconfirm';
|
import Popconfirm from '../../popconfirm';
|
||||||
import Tooltip from '../../tooltip';
|
import Tooltip from '../../tooltip';
|
||||||
@ -21,9 +22,9 @@ describe('Alert', () => {
|
|||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('could be closed', () => {
|
it('should show close button and could be closed', async () => {
|
||||||
const onClose = jest.fn();
|
const onClose = jest.fn();
|
||||||
const { container } = render(
|
render(
|
||||||
<Alert
|
<Alert
|
||||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||||
type="warning"
|
type="warning"
|
||||||
@ -32,125 +33,102 @@ describe('Alert', () => {
|
|||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
jest.useFakeTimers();
|
await userEvent.click(screen.getByRole('button', { name: /close/i }));
|
||||||
fireEvent.click(container.querySelector('.ant-alert-close-icon')!);
|
|
||||||
act(() => {
|
act(() => {
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
});
|
});
|
||||||
expect(onClose).toHaveBeenCalled();
|
|
||||||
jest.useRealTimers();
|
expect(onClose).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('action of Alert', () => {
|
it('custom action', () => {
|
||||||
it('custom action', () => {
|
|
||||||
const { container } = render(
|
|
||||||
<Alert
|
|
||||||
message="Success Tips"
|
|
||||||
type="success"
|
|
||||||
showIcon
|
|
||||||
action={
|
|
||||||
<Button size="small" type="text">
|
|
||||||
UNDO
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
closable
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
expect(container.firstChild).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('support closeIcon', () => {
|
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<Alert
|
<Alert
|
||||||
|
message="Success Tips"
|
||||||
|
type="success"
|
||||||
|
showIcon
|
||||||
|
action={
|
||||||
|
<Button size="small" type="text">
|
||||||
|
UNDO
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
closable
|
closable
|
||||||
closeIcon={<span>close</span>}
|
|
||||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
|
||||||
type="warning"
|
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(container.firstChild).toMatchSnapshot();
|
expect(container.firstChild).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('data and aria props', () => {
|
it('should sets data attributes on alert when pass attributes to props', () => {
|
||||||
it('sets data attributes on input', () => {
|
render(
|
||||||
const { container } = render(<Alert data-test="test-id" data-id="12345" message={null} />);
|
<Alert data-test="test-id" data-id="12345" aria-describedby="some-label" message={null} />,
|
||||||
const input = container.querySelector('.ant-alert')!;
|
);
|
||||||
expect(input.getAttribute('data-test')).toBe('test-id');
|
const alert = screen.getByRole('alert');
|
||||||
expect(input.getAttribute('data-id')).toBe('12345');
|
expect(alert).toHaveAttribute('data-test', 'test-id');
|
||||||
});
|
expect(alert).toHaveAttribute('data-id', '12345');
|
||||||
|
expect(alert).toHaveAttribute('aria-describedby', 'some-label');
|
||||||
it('sets aria attributes on input', () => {
|
|
||||||
const { container } = render(<Alert aria-describedby="some-label" message={null} />);
|
|
||||||
const input = container.querySelector('.ant-alert')!;
|
|
||||||
expect(input.getAttribute('aria-describedby')).toBe('some-label');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets role attribute on input', () => {
|
|
||||||
const { container } = render(<Alert role="status" message={null} />);
|
|
||||||
const input = container.querySelector('.ant-alert')!;
|
|
||||||
expect(input.getAttribute('role')).toBe('status');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ErrorBoundary', () => {
|
it('sets role attribute on input', () => {
|
||||||
|
render(<Alert role="status" message={null} />);
|
||||||
|
|
||||||
|
expect(screen.getByRole('status')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show error as ErrorBoundary when children have error', () => {
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
expect(console.error).toHaveBeenCalledTimes(0);
|
expect(console.error).toHaveBeenCalledTimes(0);
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
// eslint-disable-next-line react/jsx-no-undef
|
// eslint-disable-next-line react/jsx-no-undef
|
||||||
const ThrowError = () => <NotExisted />;
|
const ThrowError = () => <NotExisted />;
|
||||||
const { container } = render(
|
render(
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<ThrowError />
|
<ThrowError />
|
||||||
</ErrorBoundary>,
|
</ErrorBoundary>,
|
||||||
);
|
);
|
||||||
// eslint-disable-next-line jest/no-standalone-expect
|
|
||||||
expect(container.textContent).toContain('ReferenceError: NotExisted is not defined');
|
expect(screen.getByRole('alert')).toHaveTextContent(
|
||||||
|
'ReferenceError: NotExisted is not defined',
|
||||||
|
);
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
(console.error as any).mockRestore();
|
(console.error as any).mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('could be used with Tooltip', async () => {
|
it('could be used with Tooltip', async () => {
|
||||||
const ref = React.createRef<any>();
|
render(
|
||||||
jest.useRealTimers();
|
<Tooltip title="xxx" mouseEnterDelay={0}>
|
||||||
const { container } = render(
|
|
||||||
<Tooltip title="xxx" mouseEnterDelay={0} ref={ref}>
|
|
||||||
<Alert
|
<Alert
|
||||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||||
type="warning"
|
type="warning"
|
||||||
/>
|
/>
|
||||||
</Tooltip>,
|
</Tooltip>,
|
||||||
);
|
);
|
||||||
// wrapper.find('.ant-alert').simulate('mouseenter');
|
|
||||||
fireEvent.mouseEnter(container.querySelector('.ant-alert')!);
|
await userEvent.hover(screen.getByRole('alert'));
|
||||||
await sleep(0);
|
|
||||||
expect(ref.current.getPopupDomNode()).toBeTruthy();
|
expect(screen.getByRole('tooltip')).toBeInTheDocument();
|
||||||
jest.useFakeTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('could be used with Popconfirm', async () => {
|
it('could be used with Popconfirm', async () => {
|
||||||
const ref = React.createRef<any>();
|
render(
|
||||||
jest.useRealTimers();
|
<Popconfirm title="xxx">
|
||||||
const { container } = render(
|
|
||||||
<Popconfirm ref={ref} title="xxx">
|
|
||||||
<Alert
|
<Alert
|
||||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||||
type="warning"
|
type="warning"
|
||||||
/>
|
/>
|
||||||
</Popconfirm>,
|
</Popconfirm>,
|
||||||
);
|
);
|
||||||
fireEvent.click(container.querySelector('.ant-alert')!);
|
await userEvent.click(screen.getByRole('alert'));
|
||||||
await sleep(0);
|
|
||||||
expect(ref.current.getPopupDomNode()).toBeTruthy();
|
expect(screen.getByRole('tooltip')).toBeInTheDocument();
|
||||||
jest.useFakeTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('could accept none react element icon', () => {
|
it('could accept none react element icon', () => {
|
||||||
const { container } = render(
|
render(<Alert message="Success Tips" type="success" showIcon icon="icon" />);
|
||||||
<Alert message="Success Tips" type="success" showIcon icon="icon" />,
|
|
||||||
);
|
expect(screen.getByRole('alert')).toHaveTextContent(/success tips/i);
|
||||||
expect(container.firstChild).toMatchSnapshot();
|
expect(screen.getByRole('alert')).toHaveTextContent(/icon/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render message div when no message', () => {
|
it('should not render message div when no message', () => {
|
||||||
|
@ -150,6 +150,8 @@ class Anchor extends React.Component<InternalAnchorProps, AnchorState, ConfigCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
|
const { getCurrentAnchor } = this.props;
|
||||||
|
const { activeLink } = this.state;
|
||||||
if (this.scrollEvent) {
|
if (this.scrollEvent) {
|
||||||
const currentContainer = this.getContainer();
|
const currentContainer = this.getContainer();
|
||||||
if (this.scrollContainer !== currentContainer) {
|
if (this.scrollContainer !== currentContainer) {
|
||||||
@ -159,6 +161,9 @@ class Anchor extends React.Component<InternalAnchorProps, AnchorState, ConfigCon
|
|||||||
this.handleScroll();
|
this.handleScroll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (typeof getCurrentAnchor === 'function') {
|
||||||
|
this.setCurrentActiveLink(getCurrentAnchor(activeLink || ''), false);
|
||||||
|
}
|
||||||
this.updateInk();
|
this.updateInk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +232,7 @@ class Anchor extends React.Component<InternalAnchorProps, AnchorState, ConfigCon
|
|||||||
this.inkNode = node;
|
this.inkNode = node;
|
||||||
};
|
};
|
||||||
|
|
||||||
setCurrentActiveLink = (link: string) => {
|
setCurrentActiveLink = (link: string, triggerChange = true) => {
|
||||||
const { activeLink } = this.state;
|
const { activeLink } = this.state;
|
||||||
const { onChange, getCurrentAnchor } = this.props;
|
const { onChange, getCurrentAnchor } = this.props;
|
||||||
if (activeLink === link) {
|
if (activeLink === link) {
|
||||||
@ -237,7 +242,9 @@ class Anchor extends React.Component<InternalAnchorProps, AnchorState, ConfigCon
|
|||||||
this.setState({
|
this.setState({
|
||||||
activeLink: typeof getCurrentAnchor === 'function' ? getCurrentAnchor(link) : link,
|
activeLink: typeof getCurrentAnchor === 'function' ? getCurrentAnchor(link) : link,
|
||||||
});
|
});
|
||||||
onChange?.(link);
|
if (triggerChange) {
|
||||||
|
onChange?.(link);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleScroll = () => {
|
handleScroll = () => {
|
||||||
|
@ -736,5 +736,21 @@ describe('Anchor Render', () => {
|
|||||||
fireEvent.click(container.querySelector(`a[href="#${hash2}"]`)!);
|
fireEvent.click(container.querySelector(`a[href="#${hash2}"]`)!);
|
||||||
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash2}`);
|
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash2}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// https://github.com/ant-design/ant-design/issues/37627
|
||||||
|
it('should update anchorLink when component is rerender', async () => {
|
||||||
|
const hash1 = getHashUrl();
|
||||||
|
const hash2 = getHashUrl();
|
||||||
|
const Demo: React.FC<{ current: string }> = ({ current }) => (
|
||||||
|
<Anchor getCurrentAnchor={() => `#${current}`}>
|
||||||
|
<Link href={`#${hash1}`} title={hash1} />
|
||||||
|
<Link href={`#${hash2}`} title={hash2} />
|
||||||
|
</Anchor>
|
||||||
|
);
|
||||||
|
const { container, rerender } = render(<Demo current={hash1} />);
|
||||||
|
expect(container.querySelector(`.ant-anchor-link-title-active`)?.textContent).toBe(hash1);
|
||||||
|
rerender(<Demo current={hash2} />);
|
||||||
|
expect(container.querySelector(`.ant-anchor-link-title-active`)?.textContent).toBe(hash2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -121,11 +121,12 @@ const Card = React.forwardRef((props: CardProps, ref: React.Ref<HTMLDivElement>)
|
|||||||
{...extraProps}
|
{...extraProps}
|
||||||
className={`${prefixCls}-head-tabs`}
|
className={`${prefixCls}-head-tabs`}
|
||||||
onChange={onTabChange}
|
onChange={onTabChange}
|
||||||
>
|
items={tabList.map(item => ({
|
||||||
{tabList.map(item => (
|
label: item.tab,
|
||||||
<Tabs.TabPane tab={item.tab} disabled={item.disabled} key={item.key} />
|
key: item.key,
|
||||||
))}
|
disabled: item.disabled ?? false,
|
||||||
</Tabs>
|
}))}
|
||||||
|
/>
|
||||||
) : null;
|
) : null;
|
||||||
if (title || extra || tabs) {
|
if (title || extra || tabs) {
|
||||||
head = (
|
head = (
|
||||||
|
@ -767,6 +767,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-tabtest"
|
aria-controls="rc-tabs-test-panel-tabtest"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="true"
|
aria-selected="true"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-tabtest"
|
id="rc-tabs-test-tab-tabtest"
|
||||||
@ -781,6 +782,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-tabtest"
|
aria-controls="rc-tabs-test-panel-tabtest"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-tabtest"
|
id="rc-tabs-test-tab-tabtest"
|
||||||
@ -907,6 +909,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-article"
|
aria-controls="rc-tabs-test-panel-article"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-article"
|
id="rc-tabs-test-tab-article"
|
||||||
@ -921,6 +924,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-app"
|
aria-controls="rc-tabs-test-panel-app"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="true"
|
aria-selected="true"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-app"
|
id="rc-tabs-test-tab-app"
|
||||||
@ -935,6 +939,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-project"
|
aria-controls="rc-tabs-test-panel-project"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-project"
|
id="rc-tabs-test-tab-project"
|
||||||
|
@ -767,6 +767,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-tabtest"
|
aria-controls="rc-tabs-test-panel-tabtest"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="true"
|
aria-selected="true"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-tabtest"
|
id="rc-tabs-test-tab-tabtest"
|
||||||
@ -781,6 +782,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-tabtest"
|
aria-controls="rc-tabs-test-panel-tabtest"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-tabtest"
|
id="rc-tabs-test-tab-tabtest"
|
||||||
@ -888,6 +890,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-article"
|
aria-controls="rc-tabs-test-panel-article"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-article"
|
id="rc-tabs-test-tab-article"
|
||||||
@ -902,6 +905,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-app"
|
aria-controls="rc-tabs-test-panel-app"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="true"
|
aria-selected="true"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-app"
|
id="rc-tabs-test-tab-app"
|
||||||
@ -916,6 +920,7 @@ Array [
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-controls="rc-tabs-test-panel-project"
|
aria-controls="rc-tabs-test-panel-project"
|
||||||
|
aria-disabled="false"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="ant-tabs-tab-btn"
|
class="ant-tabs-tab-btn"
|
||||||
id="rc-tabs-test-tab-project"
|
id="rc-tabs-test-tab-project"
|
||||||
|
@ -6,8 +6,6 @@ import Button from '../../button/index';
|
|||||||
import Card from '../index';
|
import Card from '../index';
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
|
|
||||||
console.log('fireEvent');
|
|
||||||
|
|
||||||
describe('Card', () => {
|
describe('Card', () => {
|
||||||
mountTest(Card);
|
mountTest(Card);
|
||||||
rtlTest(Card);
|
rtlTest(Card);
|
||||||
|
@ -12,6 +12,7 @@ describe('Icon', () => {
|
|||||||
it('should throw Error', () => {
|
it('should throw Error', () => {
|
||||||
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
render(<Icon />);
|
render(<Icon />);
|
||||||
expect(errSpy).toHaveBeenCalled();
|
expect(errSpy).toHaveBeenCalledWith('Warning: [antd: Icon] Empty Icon');
|
||||||
|
errSpy.mockRestore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -31,6 +31,8 @@ const localeValues: Locale = {
|
|||||||
searchPlaceholder: 'Procurar...',
|
searchPlaceholder: 'Procurar...',
|
||||||
itemUnit: 'item',
|
itemUnit: 'item',
|
||||||
itemsUnit: 'itens',
|
itemsUnit: 'itens',
|
||||||
|
selectAll: 'Seleccionar Tudo',
|
||||||
|
selectInvert: 'Inverter a página actual',
|
||||||
},
|
},
|
||||||
Upload: {
|
Upload: {
|
||||||
uploading: 'A carregar...',
|
uploading: 'A carregar...',
|
||||||
|
@ -132,6 +132,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
|||||||
close,
|
close,
|
||||||
zIndex,
|
zIndex,
|
||||||
afterClose,
|
afterClose,
|
||||||
|
visible,
|
||||||
open,
|
open,
|
||||||
keyboard,
|
keyboard,
|
||||||
centered,
|
centered,
|
||||||
@ -149,6 +150,14 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
|||||||
focusTriggerAfterClose,
|
focusTriggerAfterClose,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
warning(
|
||||||
|
visible === undefined,
|
||||||
|
'Modal',
|
||||||
|
`\`visible\` is deprecated, please use \`open\` instead.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const confirmPrefixCls = `${prefixCls}-confirm`;
|
const confirmPrefixCls = `${prefixCls}-confirm`;
|
||||||
|
|
||||||
const width = props.width || 416;
|
const width = props.width || 416;
|
||||||
|
@ -44,14 +44,7 @@ export default function confirm(config: ModalFuncProps) {
|
|||||||
reactUnmount(container);
|
reactUnmount(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
function render({
|
function render({ okText, cancelText, prefixCls: customizePrefixCls, ...props }: any) {
|
||||||
okText,
|
|
||||||
cancelText,
|
|
||||||
prefixCls: customizePrefixCls,
|
|
||||||
open,
|
|
||||||
visible,
|
|
||||||
...props
|
|
||||||
}: any) {
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/ant-design/ant-design/issues/23623
|
* https://github.com/ant-design/ant-design/issues/23623
|
||||||
*
|
*
|
||||||
@ -68,7 +61,6 @@ export default function confirm(config: ModalFuncProps) {
|
|||||||
reactRender(
|
reactRender(
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
{...props}
|
{...props}
|
||||||
open={open ?? visible}
|
|
||||||
prefixCls={prefixCls}
|
prefixCls={prefixCls}
|
||||||
rootPrefixCls={rootPrefixCls}
|
rootPrefixCls={rootPrefixCls}
|
||||||
iconPrefixCls={iconPrefixCls}
|
iconPrefixCls={iconPrefixCls}
|
||||||
@ -93,6 +85,12 @@ export default function confirm(config: ModalFuncProps) {
|
|||||||
destroy.apply(this, args);
|
destroy.apply(this, args);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Legacy support
|
||||||
|
if (currentConfig.visible) {
|
||||||
|
delete currentConfig.visible;
|
||||||
|
}
|
||||||
|
|
||||||
render(currentConfig);
|
render(currentConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ function InternalTable<RecordType extends object = any>(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [transformFilterColumns, filterStates, getFilters] = useFilter<RecordType>({
|
const [transformFilterColumns, filterStates, filters] = useFilter<RecordType>({
|
||||||
prefixCls,
|
prefixCls,
|
||||||
locale: tableLocale,
|
locale: tableLocale,
|
||||||
dropdownPrefixCls,
|
dropdownPrefixCls,
|
||||||
@ -321,16 +321,23 @@ function InternalTable<RecordType extends object = any>(
|
|||||||
});
|
});
|
||||||
const mergedData = getFilterData(sortedData, filterStates);
|
const mergedData = getFilterData(sortedData, filterStates);
|
||||||
|
|
||||||
changeEventInfo.filters = getFilters();
|
changeEventInfo.filters = filters;
|
||||||
changeEventInfo.filterStates = filterStates;
|
changeEventInfo.filterStates = filterStates;
|
||||||
|
|
||||||
// ============================ Column ============================
|
// ============================ Column ============================
|
||||||
const columnTitleProps = React.useMemo(
|
const columnTitleProps = React.useMemo(() => {
|
||||||
() => ({
|
const mergedFilters: Record<string, FilterValue> = {};
|
||||||
|
Object.keys(filters).forEach(filterKey => {
|
||||||
|
if (filters[filterKey] !== null) {
|
||||||
|
mergedFilters[filterKey] = filters[filterKey]!;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
...sorterTitleProps,
|
...sorterTitleProps,
|
||||||
}),
|
filters: mergedFilters,
|
||||||
[sorterTitleProps],
|
};
|
||||||
);
|
}, [sorterTitleProps, filters]);
|
||||||
|
|
||||||
const [transformTitleColumns] = useTitleColumns(columnTitleProps);
|
const [transformTitleColumns] = useTitleColumns(columnTitleProps);
|
||||||
|
|
||||||
// ========================== Pagination ==========================
|
// ========================== Pagination ==========================
|
||||||
|
@ -13,6 +13,7 @@ import type { SelectProps } from '../../select';
|
|||||||
import type { ColumnGroupType, ColumnType, TableProps } from '..';
|
import type { ColumnGroupType, ColumnType, TableProps } from '..';
|
||||||
import type { ColumnFilterItem, FilterDropdownProps, FilterValue } from '../interface';
|
import type { ColumnFilterItem, FilterDropdownProps, FilterValue } from '../interface';
|
||||||
import { resetWarned } from '../../_util/warning';
|
import { resetWarned } from '../../_util/warning';
|
||||||
|
import type { TreeColumnFilterItem } from '../hooks/useFilter/FilterDropdown';
|
||||||
|
|
||||||
// https://github.com/Semantic-Org/Semantic-UI-React/blob/72c45080e4f20b531fda2e3e430e384083d6766b/test/specs/modules/Dropdown/Dropdown-test.js#L73
|
// https://github.com/Semantic-Org/Semantic-UI-React/blob/72c45080e4f20b531fda2e3e430e384083d6766b/test/specs/modules/Dropdown/Dropdown-test.js#L73
|
||||||
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => {} } };
|
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => {} } };
|
||||||
@ -1950,6 +1951,35 @@ describe('Table.filter', () => {
|
|||||||
expect(container.querySelectorAll('li.ant-dropdown-menu-item').length).toBe(2);
|
expect(container.querySelectorAll('li.ant-dropdown-menu-item').length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should supports filterSearch has type of function when filterMode is tree', () => {
|
||||||
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
|
const { container } = render(
|
||||||
|
createTable({
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
...column,
|
||||||
|
filterMode: 'tree',
|
||||||
|
filters: [
|
||||||
|
{ text: '节点一', value: 'node1' },
|
||||||
|
{ text: '节点二', value: 'node2' },
|
||||||
|
{ text: '节点三', value: 'node3' },
|
||||||
|
],
|
||||||
|
filterSearch: (input: any, record: TreeColumnFilterItem) =>
|
||||||
|
(record.title as string).includes(input),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
fireEvent.click(container.querySelector('span.ant-dropdown-trigger')!, nativeEvent);
|
||||||
|
act(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
expect(container.querySelectorAll('.ant-table-filter-dropdown-tree').length).toBe(1);
|
||||||
|
expect(container.querySelectorAll('.ant-input').length).toBe(1);
|
||||||
|
fireEvent.change(container.querySelector('.ant-input')!, { target: { value: '节点二' } });
|
||||||
|
expect(container.querySelectorAll('.ant-tree-treenode.filter-node').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
it('supports check all items', () => {
|
it('supports check all items', () => {
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
@ -2457,4 +2487,26 @@ describe('Table.filter', () => {
|
|||||||
?.disabled,
|
?.disabled,
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('title render function support `filter`', () => {
|
||||||
|
const title = jest.fn(() => 'RenderTitle');
|
||||||
|
const { container } = render(
|
||||||
|
createTable({
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
...column,
|
||||||
|
title,
|
||||||
|
filteredValue: ['boy'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container.querySelector('.ant-table-column-title')?.textContent).toEqual('RenderTitle');
|
||||||
|
expect(title).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
filters: { name: ['boy'] },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { ColumnProps } from '..';
|
import type { ColumnProps } from '..';
|
||||||
|
import type { TreeColumnFilterItem } from '../hooks/useFilter/FilterDropdown';
|
||||||
import Table from '../Table';
|
import Table from '../Table';
|
||||||
|
|
||||||
const { Column, ColumnGroup } = Table;
|
const { Column, ColumnGroup } = Table;
|
||||||
@ -48,6 +49,8 @@ describe('Table.typescript types', () => {
|
|||||||
{
|
{
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
|
filterSearch: (input: any, record: TreeColumnFilterItem) =>
|
||||||
|
(record.title as string).includes(input),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ function renderFilterItems({
|
|||||||
filteredKeys: Key[];
|
filteredKeys: Key[];
|
||||||
filterMultiple: boolean;
|
filterMultiple: boolean;
|
||||||
searchValue: string;
|
searchValue: string;
|
||||||
filterSearch: FilterSearchType;
|
filterSearch: FilterSearchType<ColumnFilterItem>;
|
||||||
}): Required<MenuProps>['items'] {
|
}): Required<MenuProps>['items'] {
|
||||||
return filters.map((filter, index) => {
|
return filters.map((filter, index) => {
|
||||||
const key = String(filter.value);
|
const key = String(filter.value);
|
||||||
@ -103,6 +103,8 @@ function renderFilterItems({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TreeColumnFilterItem = ColumnFilterItem & FilterTreeDataNode;
|
||||||
|
|
||||||
export interface FilterDropdownProps<RecordType> {
|
export interface FilterDropdownProps<RecordType> {
|
||||||
tablePrefixCls: string;
|
tablePrefixCls: string;
|
||||||
prefixCls: string;
|
prefixCls: string;
|
||||||
@ -111,7 +113,7 @@ export interface FilterDropdownProps<RecordType> {
|
|||||||
filterState?: FilterState<RecordType>;
|
filterState?: FilterState<RecordType>;
|
||||||
filterMultiple: boolean;
|
filterMultiple: boolean;
|
||||||
filterMode?: 'menu' | 'tree';
|
filterMode?: 'menu' | 'tree';
|
||||||
filterSearch?: FilterSearchType;
|
filterSearch?: FilterSearchType<ColumnFilterItem | TreeColumnFilterItem>;
|
||||||
columnKey: Key;
|
columnKey: Key;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
triggerFilter: (filterState: FilterState<RecordType>) => void;
|
triggerFilter: (filterState: FilterState<RecordType>) => void;
|
||||||
@ -312,6 +314,12 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
const getFilterData = (node: FilterTreeDataNode): TreeColumnFilterItem => ({
|
||||||
|
...node,
|
||||||
|
text: node.title,
|
||||||
|
value: node.key,
|
||||||
|
children: node.children?.map(item => getFilterData(item)) || [],
|
||||||
|
});
|
||||||
|
|
||||||
let dropdownContent: React.ReactNode;
|
let dropdownContent: React.ReactNode;
|
||||||
|
|
||||||
@ -348,7 +356,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
if (filterMode === 'tree') {
|
if (filterMode === 'tree') {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FilterSearch
|
<FilterSearch<TreeColumnFilterItem>
|
||||||
filterSearch={filterSearch}
|
filterSearch={filterSearch}
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
onChange={onSearch}
|
onChange={onSearch}
|
||||||
@ -385,7 +393,12 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
|
|||||||
defaultExpandAll
|
defaultExpandAll
|
||||||
filterTreeNode={
|
filterTreeNode={
|
||||||
searchValue.trim()
|
searchValue.trim()
|
||||||
? node => searchValueMatched(searchValue, node.title)
|
? node => {
|
||||||
|
if (typeof filterSearch === 'function') {
|
||||||
|
return filterSearch(searchValue, getFilterData(node));
|
||||||
|
}
|
||||||
|
return searchValueMatched(searchValue, node.title);
|
||||||
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -3,21 +3,21 @@ import * as React from 'react';
|
|||||||
import Input from '../../../input';
|
import Input from '../../../input';
|
||||||
import type { FilterSearchType, TableLocale } from '../../interface';
|
import type { FilterSearchType, TableLocale } from '../../interface';
|
||||||
|
|
||||||
interface FilterSearchProps {
|
interface FilterSearchProps<RecordType = any> {
|
||||||
value: string;
|
value: string;
|
||||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
filterSearch: FilterSearchType;
|
filterSearch: FilterSearchType<RecordType>;
|
||||||
tablePrefixCls: string;
|
tablePrefixCls: string;
|
||||||
locale: TableLocale;
|
locale: TableLocale;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilterSearch: React.FC<FilterSearchProps> = ({
|
function FilterSearch<RecordType>({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
filterSearch,
|
filterSearch,
|
||||||
tablePrefixCls,
|
tablePrefixCls,
|
||||||
locale,
|
locale,
|
||||||
}) => {
|
}: FilterSearchProps<RecordType>) {
|
||||||
if (!filterSearch) {
|
if (!filterSearch) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -34,6 +34,6 @@ const FilterSearch: React.FC<FilterSearchProps> = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default FilterSearch;
|
export default FilterSearch;
|
||||||
|
@ -203,7 +203,7 @@ function useFilter<RecordType>({
|
|||||||
}: FilterConfig<RecordType>): [
|
}: FilterConfig<RecordType>): [
|
||||||
TransformColumns<RecordType>,
|
TransformColumns<RecordType>,
|
||||||
FilterState<RecordType>[],
|
FilterState<RecordType>[],
|
||||||
() => Record<string, FilterValue | null>,
|
Record<string, FilterValue | null>,
|
||||||
] {
|
] {
|
||||||
const [filterStates, setFilterStates] = React.useState<FilterState<RecordType>[]>(
|
const [filterStates, setFilterStates] = React.useState<FilterState<RecordType>[]>(
|
||||||
collectFilterStates(mergedColumns, true),
|
collectFilterStates(mergedColumns, true),
|
||||||
@ -235,10 +235,7 @@ function useFilter<RecordType>({
|
|||||||
return collectedStates;
|
return collectedStates;
|
||||||
}, [mergedColumns, filterStates]);
|
}, [mergedColumns, filterStates]);
|
||||||
|
|
||||||
const getFilters = React.useCallback(
|
const filters = React.useMemo(() => generateFilterInfo(mergedFilterStates), [mergedFilterStates]);
|
||||||
() => generateFilterInfo(mergedFilterStates),
|
|
||||||
[mergedFilterStates],
|
|
||||||
);
|
|
||||||
|
|
||||||
const triggerFilter = (filterState: FilterState<RecordType>) => {
|
const triggerFilter = (filterState: FilterState<RecordType>) => {
|
||||||
const newFilterStates = mergedFilterStates.filter(({ key }) => key !== filterState.key);
|
const newFilterStates = mergedFilterStates.filter(({ key }) => key !== filterState.key);
|
||||||
@ -258,7 +255,7 @@ function useFilter<RecordType>({
|
|||||||
tableLocale,
|
tableLocale,
|
||||||
);
|
);
|
||||||
|
|
||||||
return [transformColumns, mergedFilterStates, getFilters];
|
return [transformColumns, mergedFilterStates, filters];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useFilter;
|
export default useFilter;
|
||||||
|
@ -63,7 +63,7 @@ export interface ColumnTitleProps<RecordType> {
|
|||||||
sortColumn?: ColumnType<RecordType>;
|
sortColumn?: ColumnType<RecordType>;
|
||||||
sortColumns?: { column: ColumnType<RecordType>; order: SortOrder }[];
|
sortColumns?: { column: ColumnType<RecordType>; order: SortOrder }[];
|
||||||
|
|
||||||
filters?: Record<string, string[]>;
|
filters?: Record<string, FilterValue>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ColumnTitle<RecordType> =
|
export type ColumnTitle<RecordType> =
|
||||||
@ -72,7 +72,9 @@ export type ColumnTitle<RecordType> =
|
|||||||
|
|
||||||
export type FilterValue = (Key | boolean)[];
|
export type FilterValue = (Key | boolean)[];
|
||||||
export type FilterKey = Key[] | null;
|
export type FilterKey = Key[] | null;
|
||||||
export type FilterSearchType = boolean | ((input: string, record: {}) => boolean);
|
export type FilterSearchType<RecordType = Record<string, any>> =
|
||||||
|
| boolean
|
||||||
|
| ((input: string, record: RecordType) => boolean);
|
||||||
export interface FilterConfirmProps {
|
export interface FilterConfirmProps {
|
||||||
closeDropdown: boolean;
|
closeDropdown: boolean;
|
||||||
}
|
}
|
||||||
@ -112,7 +114,7 @@ export interface ColumnType<RecordType> extends Omit<RcColumnType<RecordType>, '
|
|||||||
defaultFilteredValue?: FilterValue | null;
|
defaultFilteredValue?: FilterValue | null;
|
||||||
filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode);
|
filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode);
|
||||||
filterMode?: 'menu' | 'tree';
|
filterMode?: 'menu' | 'tree';
|
||||||
filterSearch?: FilterSearchType;
|
filterSearch?: FilterSearchType<ColumnFilterItem>;
|
||||||
onFilter?: (value: string | number | boolean, record: RecordType) => boolean;
|
onFilter?: (value: string | number | boolean, record: RecordType) => boolean;
|
||||||
filterDropdownOpen?: boolean;
|
filterDropdownOpen?: boolean;
|
||||||
onFilterDropdownOpenChange?: (visible: boolean) => void;
|
onFilterDropdownOpenChange?: (visible: boolean) => void;
|
||||||
|
@ -14,10 +14,12 @@ describe('Tabs.Animated', () => {
|
|||||||
it('boolean: true', () => {
|
it('boolean: true', () => {
|
||||||
const { result } = renderHook(() => useAnimateConfig('test', true));
|
const { result } = renderHook(() => useAnimateConfig('test', true));
|
||||||
|
|
||||||
expect(result.current).toEqual({
|
expect(result.current).toEqual(
|
||||||
inkBar: true,
|
expect.objectContaining({
|
||||||
tabPane: false,
|
inkBar: true,
|
||||||
});
|
tabPane: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('config', () => {
|
it('config', () => {
|
||||||
|
@ -26,7 +26,7 @@ export default function useAnimateConfig(
|
|||||||
} else if (animated === true) {
|
} else if (animated === true) {
|
||||||
mergedAnimated = {
|
mergedAnimated = {
|
||||||
inkBar: true,
|
inkBar: true,
|
||||||
tabPane: false,
|
tabPane: true,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
mergedAnimated = {
|
mergedAnimated = {
|
||||||
|
@ -845,6 +845,7 @@ const genTabsStyle: GenerateStyle<TabsToken> = (token: TabsToken): CSSObject =>
|
|||||||
},
|
},
|
||||||
|
|
||||||
[`${componentCls}-tabpane`]: {
|
[`${componentCls}-tabpane`]: {
|
||||||
|
outline: 'none',
|
||||||
'&-hidden': {
|
'&-hidden': {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
|
@ -538,4 +538,16 @@ describe('Tooltip', () => {
|
|||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
errSpy.mockRestore();
|
errSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('not inject className when children className is not string type', () => {
|
||||||
|
const HOC = ({ className }: { className: Function }) => <span className={className()} />;
|
||||||
|
const { container } = render(
|
||||||
|
<Tooltip open>
|
||||||
|
<HOC className={() => 'bamboo'} />
|
||||||
|
</Tooltip>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container.querySelector('.bamboo')).toBeTruthy();
|
||||||
|
expect(container.querySelector('.ant-tooltip')).toBeTruthy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -30,7 +30,7 @@ The following APIs are shared by Tooltip, Popconfirm, Popover.
|
|||||||
| color | The background color | string | - | 4.3.0 |
|
| color | The background color | string | - | 4.3.0 |
|
||||||
| defaultOpen | Whether the floating tooltip card is open by default | boolean | false | 4.23.0 |
|
| defaultOpen | Whether the floating tooltip card is open by default | boolean | false | 4.23.0 |
|
||||||
| destroyTooltipOnHide | Whether destroy tooltip when hidden, parent container of tooltip will be destroyed when `keepParent` is false | boolean \| { keepParent?: boolean } | false | |
|
| destroyTooltipOnHide | Whether destroy tooltip when hidden, parent container of tooltip will be destroyed when `keepParent` is false | boolean \| { keepParent?: boolean } | false | |
|
||||||
| getPopupContainer | The DOM container of the tip, the default behavior is to create a `div` element in `body` | function(triggerNode) | () => document.body | |
|
| getPopupContainer | The DOM container of the tip, the default behavior is to create a `div` element in `body` | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
|
||||||
| mouseEnterDelay | Delay in seconds, before tooltip is shown on mouse enter | number | 0.1 | |
|
| mouseEnterDelay | Delay in seconds, before tooltip is shown on mouse enter | number | 0.1 | |
|
||||||
| mouseLeaveDelay | Delay in seconds, before tooltip is hidden on mouse leave | number | 0.1 | |
|
| mouseLeaveDelay | Delay in seconds, before tooltip is hidden on mouse leave | number | 0.1 | |
|
||||||
| overlayClassName | Class name of the tooltip card | string | - | |
|
| overlayClassName | Class name of the tooltip card | string | - | |
|
||||||
@ -40,7 +40,7 @@ The following APIs are shared by Tooltip, Popconfirm, Popover.
|
|||||||
| trigger | Tooltip trigger mode. Could be multiple by passing an array | `hover` \| `focus` \| `click` \| `contextMenu` \| Array<string> | `hover` | |
|
| trigger | Tooltip trigger mode. Could be multiple by passing an array | `hover` \| `focus` \| `click` \| `contextMenu` \| Array<string> | `hover` | |
|
||||||
| open | Whether the floating tooltip card is open or not. Use `visible` under 4.23.0 ([why?](/docs/react/faq#why-open)) | boolean | false | 4.23.0 |
|
| open | Whether the floating tooltip card is open or not. Use `visible` under 4.23.0 ([why?](/docs/react/faq#why-open)) | boolean | false | 4.23.0 |
|
||||||
| zIndex | Config `z-index` of Tooltip | number | - | |
|
| zIndex | Config `z-index` of Tooltip | number | - | |
|
||||||
| onOpenChange | Callback executed when visibility of the tooltip card is changed | (open) => void | - | 4.23.0 |
|
| onOpenChange | Callback executed when visibility of the tooltip card is changed | (open: boolean) => void | - | 4.23.0 |
|
||||||
|
|
||||||
## Note
|
## Note
|
||||||
|
|
||||||
|
@ -276,9 +276,12 @@ const Tooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => {
|
|||||||
prefixCls,
|
prefixCls,
|
||||||
);
|
);
|
||||||
const childProps = child.props;
|
const childProps = child.props;
|
||||||
const childCls = classNames(childProps.className, {
|
const childCls =
|
||||||
[openClassName || `${prefixCls}-open`]: true,
|
!childProps.className || typeof childProps.className === 'string'
|
||||||
});
|
? classNames(childProps.className, {
|
||||||
|
[openClassName || `${prefixCls}-open`]: true,
|
||||||
|
})
|
||||||
|
: childProps.className;
|
||||||
|
|
||||||
// Style
|
// Style
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls, !injectFromPopover);
|
const [wrapSSR, hashId] = useStyle(prefixCls, !injectFromPopover);
|
||||||
|
@ -32,7 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Vyyeu8jq2/Tooltp.svg
|
|||||||
| color | 背景颜色 | string | - | 4.3.0 |
|
| color | 背景颜色 | string | - | 4.3.0 |
|
||||||
| defaultOpen | 默认是否显隐 | boolean | false | 4.23.0 |
|
| defaultOpen | 默认是否显隐 | boolean | false | 4.23.0 |
|
||||||
| destroyTooltipOnHide | 关闭后是否销毁 Tooltip,当 `keepParent` 为 `false` 时销毁父容器 | boolean \| { keepParent?: boolean } | false | |
|
| destroyTooltipOnHide | 关闭后是否销毁 Tooltip,当 `keepParent` 为 `false` 时销毁父容器 | boolean \| { keepParent?: boolean } | false | |
|
||||||
| getPopupContainer | 浮层渲染父节点,默认渲染到 body 上 | function(triggerNode) | () => document.body | |
|
| getPopupContainer | 浮层渲染父节点,默认渲染到 body 上 | (triggerNode: HTMLElement) => HTMLElement | () => document.body | |
|
||||||
| mouseEnterDelay | 鼠标移入后延时多少才显示 Tooltip,单位:秒 | number | 0.1 | |
|
| mouseEnterDelay | 鼠标移入后延时多少才显示 Tooltip,单位:秒 | number | 0.1 | |
|
||||||
| mouseLeaveDelay | 鼠标移出后延时多少才隐藏 Tooltip,单位:秒 | number | 0.1 | |
|
| mouseLeaveDelay | 鼠标移出后延时多少才隐藏 Tooltip,单位:秒 | number | 0.1 | |
|
||||||
| overlayClassName | 卡片类名 | string | - | |
|
| overlayClassName | 卡片类名 | string | - | |
|
||||||
@ -42,7 +42,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Vyyeu8jq2/Tooltp.svg
|
|||||||
| trigger | 触发行为,可选 `hover` \| `focus` \| `click` \| `contextMenu`,可使用数组设置多个触发行为 | string \| string\[] | `hover` | |
|
| trigger | 触发行为,可选 `hover` \| `focus` \| `click` \| `contextMenu`,可使用数组设置多个触发行为 | string \| string\[] | `hover` | |
|
||||||
| open | 用于手动控制浮层显隐,小于 4.23.0 使用 `visible`([为什么?](/docs/react/faq#why-open)) | boolean | false | 4.23.0 |
|
| open | 用于手动控制浮层显隐,小于 4.23.0 使用 `visible`([为什么?](/docs/react/faq#why-open)) | boolean | false | 4.23.0 |
|
||||||
| zIndex | 设置 Tooltip 的 `z-index` | number | - | |
|
| zIndex | 设置 Tooltip 的 `z-index` | number | - | |
|
||||||
| onOpenChange | 显示隐藏的回调 | (open) => void | - | 4.23.0 |
|
| onOpenChange | 显示隐藏的回调 | (open: boolean) => void | - | 4.23.0 |
|
||||||
|
|
||||||
## 注意
|
## 注意
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ Basic text writing, including headings, body text, lists, and more.
|
|||||||
| delete | Deleted line style | boolean | false | |
|
| delete | Deleted line style | boolean | false | |
|
||||||
| disabled | Disabled content | boolean | false | |
|
| disabled | Disabled content | boolean | false | |
|
||||||
| editable | If editable. Can control edit state when is object | boolean \| [editable](#editable) | false | [editable](#editable) |
|
| editable | If editable. Can control edit state when is object | boolean \| [editable](#editable) | false | [editable](#editable) |
|
||||||
| ellipsis | Display ellipsis when text overflows,can't configure expandable、rows and onExpand by using object | boolean \| [Omit<ellipsis, 'expandable' \| 'rows' \| 'onExpand'>](#ellipsis) | false | [ellipsis](#ellipsis) |
|
| ellipsis | Display ellipsis when text overflows,can't configure expandable、rows and onExpand by using object. Diff with Typography.Paragraph, Text do not have 100% width style which means it will fix width on the first ellipsis. If you want to have responsive ellipsis, please set width manually | boolean \| [Omit<ellipsis, 'expandable' \| 'rows' \| 'onExpand'>](#ellipsis) | false | [ellipsis](#ellipsis) |
|
||||||
| keyboard | Keyboard style | boolean | false | 4.3.0 |
|
| keyboard | Keyboard style | boolean | false | 4.3.0 |
|
||||||
| mark | Marked style | boolean | false | |
|
| mark | Marked style | boolean | false | |
|
||||||
| onClick | Set the handler to handle click event | (event) => void | - | |
|
| onClick | Set the handler to handle click event | (event) => void | - | |
|
||||||
|
@ -25,7 +25,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
|||||||
| delete | 添加删除线样式 | boolean | false | |
|
| delete | 添加删除线样式 | boolean | false | |
|
||||||
| disabled | 禁用文本 | boolean | false | |
|
| disabled | 禁用文本 | boolean | false | |
|
||||||
| editable | 是否可编辑,为对象时可对编辑进行控制 | boolean \| [editable](#editable) | false | [editable](#editable) |
|
| editable | 是否可编辑,为对象时可对编辑进行控制 | boolean \| [editable](#editable) | false | [editable](#editable) |
|
||||||
| ellipsis | 自动溢出省略,为对象时不能设置省略行数、是否可展开、onExpand 展开事件 | boolean \| [Omit<ellipsis, 'expandable' \| 'rows' \| 'onExpand'>](#ellipsis) | false | [ellipsis](#ellipsis) |
|
| ellipsis | 自动溢出省略,为对象时不能设置省略行数、是否可展开、onExpand 展开事件。不同于 Typography.Paragraph,Text 组件自身不带 100% 宽度样式,因而默认情况下初次缩略后宽度便不再变化。如果需要自适应宽度,请手工配置宽度样式 | boolean \| [Omit<ellipsis, 'expandable' \| 'rows' \| 'onExpand'>](#ellipsis) | false | [ellipsis](#ellipsis) |
|
||||||
| keyboard | 添加键盘样式 | boolean | false | 4.3.0 |
|
| keyboard | 添加键盘样式 | boolean | false | 4.3.0 |
|
||||||
| mark | 添加标记样式 | boolean | false | |
|
| mark | 添加标记样式 | boolean | false | |
|
||||||
| onClick | 点击 Text 时的回调 | (event) => void | - | |
|
| onClick | 点击 Text 时的回调 | (event) => void | - | |
|
||||||
|
@ -83,6 +83,10 @@ toc: false
|
|||||||
- https://mastergo-local-default.oss-cn-beijing.aliyuncs.com/ant-design-mastergo.svg
|
- https://mastergo-local-default.oss-cn-beijing.aliyuncs.com/ant-design-mastergo.svg
|
||||||
- 可在「MasterGo」在线免费使用的全套组件和模板
|
- 可在「MasterGo」在线免费使用的全套组件和模板
|
||||||
- https://mastergo.com/community/?utm_source=antdesign&utm_medium=link&utm_campaign=resource&cata_name=AntDesign
|
- https://mastergo.com/community/?utm_source=antdesign&utm_medium=link&utm_campaign=resource&cata_name=AntDesign
|
||||||
|
- Raycast 拓展
|
||||||
|
- https://gw.alipayobjects.com/zos/basement_prod/5edc7f4d-3302-4710-963b-7b6c77ea8d06.svg
|
||||||
|
- mac 用户可使用 Raycast 快速打开 Ant Design 组件
|
||||||
|
- https://www.raycast.com/crazyair/antd-open-browser
|
||||||
|
|
||||||
## 文章
|
## 文章
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@
|
|||||||
"@ant-design/react-slick": "~0.29.1",
|
"@ant-design/react-slick": "~0.29.1",
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
"@ctrl/tinycolor": "^3.4.0",
|
"@ctrl/tinycolor": "^3.4.0",
|
||||||
|
"@testing-library/user-event": "^14.4.2",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"copy-to-clipboard": "^3.2.0",
|
"copy-to-clipboard": "^3.2.0",
|
||||||
"dayjs": "^1.11.1",
|
"dayjs": "^1.11.1",
|
||||||
@ -125,7 +126,7 @@
|
|||||||
"rc-field-form": "~1.27.0",
|
"rc-field-form": "~1.27.0",
|
||||||
"rc-image": "~5.7.0",
|
"rc-image": "~5.7.0",
|
||||||
"rc-input": "~0.1.2",
|
"rc-input": "~0.1.2",
|
||||||
"rc-input-number": "~7.3.5",
|
"rc-input-number": "~7.3.9",
|
||||||
"rc-mentions": "~1.9.1",
|
"rc-mentions": "~1.9.1",
|
||||||
"rc-menu": "~9.6.3",
|
"rc-menu": "~9.6.3",
|
||||||
"rc-motion": "^2.6.1",
|
"rc-motion": "^2.6.1",
|
||||||
@ -136,7 +137,7 @@
|
|||||||
"rc-rate": "~2.9.0",
|
"rc-rate": "~2.9.0",
|
||||||
"rc-resize-observer": "^1.2.0",
|
"rc-resize-observer": "^1.2.0",
|
||||||
"rc-segmented": "~2.1.0",
|
"rc-segmented": "~2.1.0",
|
||||||
"rc-select": "~14.1.1",
|
"rc-select": "~14.1.13",
|
||||||
"rc-slider": "~10.0.0",
|
"rc-slider": "~10.0.0",
|
||||||
"rc-steps": "~4.1.0",
|
"rc-steps": "~4.1.0",
|
||||||
"rc-switch": "~4.0.0",
|
"rc-switch": "~4.0.0",
|
||||||
@ -230,7 +231,7 @@
|
|||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"immer": "^9.0.1",
|
"immer": "^9.0.1",
|
||||||
"immutability-helper": "^3.0.0",
|
"immutability-helper": "^3.0.0",
|
||||||
"inquirer": "^8.0.0",
|
"inquirer": "^9.1.2",
|
||||||
"intersection-observer": "^0.12.0",
|
"intersection-observer": "^0.12.0",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"jest": "^28.0.3",
|
"jest": "^28.0.3",
|
||||||
|
@ -36,6 +36,7 @@ const MAINTAINERS = [
|
|||||||
'fireairforce',
|
'fireairforce',
|
||||||
'kerm1it',
|
'kerm1it',
|
||||||
'madccc',
|
'madccc',
|
||||||
|
'MadCcc',
|
||||||
].map(author => author.toLowerCase());
|
].map(author => author.toLowerCase());
|
||||||
|
|
||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
|
@ -4,14 +4,7 @@ import { FormattedMessage, injectIntl } from 'react-intl';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Row, Col, Affix, Tooltip } from 'antd';
|
import { Row, Col, Affix, Tooltip } from 'antd';
|
||||||
import { getChildren } from 'jsonml.js/lib/utils';
|
import { getChildren } from 'jsonml.js/lib/utils';
|
||||||
import {
|
import { CodeFilled, CodeOutlined, BugFilled, BugOutlined } from '@ant-design/icons';
|
||||||
CodeFilled,
|
|
||||||
CodeOutlined,
|
|
||||||
BugFilled,
|
|
||||||
BugOutlined,
|
|
||||||
ExperimentOutlined,
|
|
||||||
ExperimentFilled,
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
import Demo from './Demo';
|
import Demo from './Demo';
|
||||||
import EditButton from './EditButton';
|
import EditButton from './EditButton';
|
||||||
import { ping, getMetaDescription } from '../utils';
|
import { ping, getMetaDescription } from '../utils';
|
||||||
@ -25,7 +18,6 @@ class ComponentDoc extends React.Component {
|
|||||||
expandAll: false,
|
expandAll: false,
|
||||||
visibleAll: process.env.NODE_ENV !== 'production',
|
visibleAll: process.env.NODE_ENV !== 'production',
|
||||||
showRiddleButton: false,
|
showRiddleButton: false,
|
||||||
react17Demo: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -108,7 +100,7 @@ class ComponentDoc extends React.Component {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
const { content, meta } = doc;
|
const { content, meta } = doc;
|
||||||
const demoValues = Object.keys(demos).map(key => demos[key]);
|
const demoValues = Object.keys(demos).map(key => demos[key]);
|
||||||
const { expandAll, visibleAll, showRiddleButton, react17Demo } = this.state;
|
const { expandAll, visibleAll, showRiddleButton } = this.state;
|
||||||
const isSingleCol = meta.cols === 1;
|
const isSingleCol = meta.cols === 1;
|
||||||
const leftChildren = [];
|
const leftChildren = [];
|
||||||
const rightChildren = [];
|
const rightChildren = [];
|
||||||
@ -131,7 +123,6 @@ class ComponentDoc extends React.Component {
|
|||||||
location={location}
|
location={location}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
setIframeTheme={setIframeTheme}
|
setIframeTheme={setIframeTheme}
|
||||||
react18={react17Demo}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
if (index % 2 === 0 || isSingleCol) {
|
if (index % 2 === 0 || isSingleCol) {
|
||||||
@ -220,27 +211,6 @@ class ComponentDoc extends React.Component {
|
|||||||
<BugOutlined className={expandTriggerClass} onClick={this.handleVisibleToggle} />
|
<BugOutlined className={expandTriggerClass} onClick={this.handleVisibleToggle} />
|
||||||
)}
|
)}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
<FormattedMessage
|
|
||||||
id={`app.component.examples.${
|
|
||||||
react17Demo ? 'openDemoWithReact18' : 'openDemoNotReact18'
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{react17Demo ? (
|
|
||||||
<ExperimentFilled
|
|
||||||
className={expandTriggerClass}
|
|
||||||
onClick={this.handleDemoVersionToggle}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ExperimentOutlined
|
|
||||||
className={expandTriggerClass}
|
|
||||||
onClick={this.handleDemoVersionToggle}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
</section>
|
</section>
|
||||||
|
@ -48,14 +48,13 @@ class Demo extends React.Component {
|
|||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
const { codeExpand, copied, copyTooltipOpen } = this.state;
|
const { codeExpand, copied, copyTooltipOpen } = this.state;
|
||||||
const { expand, theme, showRiddleButton, react18 } = this.props;
|
const { expand, theme, showRiddleButton } = this.props;
|
||||||
return (
|
return (
|
||||||
(codeExpand || expand) !== (nextState.codeExpand || nextProps.expand) ||
|
(codeExpand || expand) !== (nextState.codeExpand || nextProps.expand) ||
|
||||||
copied !== nextState.copied ||
|
copied !== nextState.copied ||
|
||||||
copyTooltipOpen !== nextState.copyTooltipOpen ||
|
copyTooltipOpen !== nextState.copyTooltipOpen ||
|
||||||
nextProps.theme !== theme ||
|
nextProps.theme !== theme ||
|
||||||
nextProps.showRiddleButton !== showRiddleButton ||
|
nextProps.showRiddleButton !== showRiddleButton
|
||||||
nextProps.react18 !== react18
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +136,6 @@ class Demo extends React.Component {
|
|||||||
intl: { locale },
|
intl: { locale },
|
||||||
theme,
|
theme,
|
||||||
showRiddleButton,
|
showRiddleButton,
|
||||||
react18,
|
|
||||||
} = props;
|
} = props;
|
||||||
const { copied, copyTooltipOpen } = state;
|
const { copied, copyTooltipOpen } = state;
|
||||||
if (!this.liveDemo) {
|
if (!this.liveDemo) {
|
||||||
@ -206,13 +204,13 @@ class Demo extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
dependencies['@ant-design/icons'] = 'latest';
|
dependencies['@ant-design/icons'] = 'latest';
|
||||||
dependencies.react = react18 ? '^18.0.0' : '^17.0.0';
|
dependencies.react = '^18.0.0';
|
||||||
dependencies['react-dom'] = react18 ? '^18.0.0' : '^17.0.0';
|
dependencies['react-dom'] = '^18.0.0';
|
||||||
|
|
||||||
const codepenPrefillConfig = {
|
const codepenPrefillConfig = {
|
||||||
title: `${localizedTitle} - antd@${dependencies.antd}`,
|
title: `${localizedTitle} - antd@${dependencies.antd}`,
|
||||||
html,
|
html,
|
||||||
js: `${react18 ? 'const { createRoot } = ReactDOM;\n' : ''}${sourceCode
|
js: `${'const { createRoot } = ReactDOM;\n'}${sourceCode
|
||||||
.replace(/import\s+(?:React,\s+)?{(\s+[^}]*\s+)}\s+from\s+'react'/, `const { $1 } = React;`)
|
.replace(/import\s+(?:React,\s+)?{(\s+[^}]*\s+)}\s+from\s+'react'/, `const { $1 } = React;`)
|
||||||
.replace(/import\s+{(\s+[^}]*\s+)}\s+from\s+'antd';/, 'const { $1 } = antd;')
|
.replace(/import\s+{(\s+[^}]*\s+)}\s+from\s+'antd';/, 'const { $1 } = antd;')
|
||||||
.replace(/import\s+{(\s+[^}]*\s+)}\s+from\s+'@ant-design\/icons';/, 'const { $1 } = icons;')
|
.replace(/import\s+{(\s+[^}]*\s+)}\s+from\s+'@ant-design\/icons';/, 'const { $1 } = icons;')
|
||||||
@ -224,20 +222,17 @@ class Demo extends React.Component {
|
|||||||
'const { $1 } = ReactRouterDOM;',
|
'const { $1 } = ReactRouterDOM;',
|
||||||
)
|
)
|
||||||
.replace(/([A-Za-z]*)\s+as\s+([A-Za-z]*)/, '$1:$2')
|
.replace(/([A-Za-z]*)\s+as\s+([A-Za-z]*)/, '$1:$2')
|
||||||
.replace(/export default/, 'const ComponentDemo =')}\n\n${
|
.replace(
|
||||||
react18
|
/export default/,
|
||||||
? 'createRoot(mountNode).render(<ComponentDemo />)'
|
'const ComponentDemo =',
|
||||||
: 'ReactDOM.render(<ComponentDemo />, mountNode)'
|
)}\n\ncreateRoot(mountNode).render(<ComponentDemo />);\n`,
|
||||||
};\n`,
|
|
||||||
css: prefillStyle,
|
css: prefillStyle,
|
||||||
editors: '001',
|
editors: '001',
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
css_external: `https://unpkg.com/antd@${antdReproduceVersion}/dist/antd.css`,
|
css_external: `https://unpkg.com/antd@${antdReproduceVersion}/dist/antd.css`,
|
||||||
js_external: [
|
js_external: [
|
||||||
react18 ? 'react@18/umd/react.development.js' : 'react@16.x/umd/react.development.js',
|
'react@18/umd/react.development.js',
|
||||||
react18
|
'react-dom@18/umd/react-dom.development.js',
|
||||||
? 'react-dom@18/umd/react-dom.development.js'
|
|
||||||
: 'react-dom@16.x/umd/react-dom.development.js',
|
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
`antd@${antdReproduceVersion}/dist/antd-with-locales.js`,
|
`antd@${antdReproduceVersion}/dist/antd-with-locales.js`,
|
||||||
`@ant-design/icons/dist/index.umd.js`,
|
`@ant-design/icons/dist/index.umd.js`,
|
||||||
@ -253,15 +248,10 @@ class Demo extends React.Component {
|
|||||||
title: `${localizedTitle} - antd@${dependencies.antd}`,
|
title: `${localizedTitle} - antd@${dependencies.antd}`,
|
||||||
js: `${
|
js: `${
|
||||||
/import React(\D*)from 'react';/.test(sourceCode) ? '' : `import React from 'react';\n`
|
/import React(\D*)from 'react';/.test(sourceCode) ? '' : `import React from 'react';\n`
|
||||||
}${
|
}import { createRoot } from 'react-dom/client';\n${sourceCode.replace(
|
||||||
react18
|
/export default/,
|
||||||
? `import { createRoot } from 'react-dom/client';\n`
|
'const ComponentDemo =',
|
||||||
: `import ReactDOM from 'react-dom';\n`
|
)}\n\ncreateRoot(mountNode).render(<ComponentDemo />);\n`,
|
||||||
}${sourceCode.replace(/export default/, 'const ComponentDemo =')}\n\n${
|
|
||||||
react18
|
|
||||||
? 'createRoot(mountNode).render(<ComponentDemo />)'
|
|
||||||
: 'ReactDOM.render(<ComponentDemo />, mountNode)'
|
|
||||||
};\n`,
|
|
||||||
css: prefillStyle,
|
css: prefillStyle,
|
||||||
json: JSON.stringify(
|
json: JSON.stringify(
|
||||||
{
|
{
|
||||||
@ -296,20 +286,12 @@ ${parsedSourceCode}
|
|||||||
.replace('</style>', '')
|
.replace('</style>', '')
|
||||||
.replace('<style>', '');
|
.replace('<style>', '');
|
||||||
|
|
||||||
const indexJsContent = react18
|
const indexJsContent = `
|
||||||
? `
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import Demo from './demo';
|
import Demo from './demo';
|
||||||
|
|
||||||
createRoot(document.getElementById('container')).render(<Demo />);
|
createRoot(document.getElementById('container')).render(<Demo />);
|
||||||
`
|
|
||||||
: `
|
|
||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import Demo from './demo';
|
|
||||||
|
|
||||||
ReactDOM.render(<Demo />, document.getElementById('container'));
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const codesandboxPackage = {
|
const codesandboxPackage = {
|
||||||
@ -317,8 +299,8 @@ ReactDOM.render(<Demo />, document.getElementById('container'));
|
|||||||
main: 'index.js',
|
main: 'index.js',
|
||||||
dependencies: {
|
dependencies: {
|
||||||
...dependencies,
|
...dependencies,
|
||||||
react: react18 ? '^18.0.0' : '^16.14.0',
|
react: '^18.0.0',
|
||||||
'react-dom': react18 ? '^18.0.0' : '^16.14.0',
|
'react-dom': '^18.0.0',
|
||||||
'react-scripts': '^4.0.0',
|
'react-scripts': '^4.0.0',
|
||||||
},
|
},
|
||||||
devDependencies: {
|
devDependencies: {
|
||||||
|
Loading…
Reference in New Issue
Block a user