mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
merge featrue into master (#30636)
* feat: add Table expandable fixed (#29959) * fix: Use flex gap of space (#30023) * fix: use flex gap when supported * test: update snapshot * refactor: Use single hooks * feat: Allow breadcrumb component in PageHeader (#30019) * Allow breadcrumb component in PageHeader * Allow breadcrumb component in PageHeader * Allow breadcrumb component in PageHeader * Rename variable rename var from _breadcrumbRender to breadcrumbRenderDomFromProps * feat: add onChange for Statistic.Countdown (#30265) * feat: add onChange for countdown * update the demo * feat(upload): add onDrop (#30319) * feat(upload): Add onDrop * Replace "if prop" logic with existential operator * Remove redundant conditional * feat(upload): itemRender add actions params (#30236) * feat(upload): itemRender add actions params * chore: optimize type definition * chore: update doc * chore: rename actions * chore: trigger ci * chore: rename method name of actions * feat: Add missing dutch translations (#30389) * feat: Add missing dutch translations * fix: Translate remaining english values * fix: Update snapshot for ui tests * test: increase code coverage to 100% (#30415) * test: fix Space code coverage * test: should use nl_BE locale for DatePicker * fix: Switch tabIndex type (#30416) * feat: updated Romanian internationalization (#30419) * feat: updated Romanian internationalization * fixed lint error * feat: Menu support accessibility & keyboard access (#30382) * chore: Use focus style * fix: prefixCls * fix: prefixCls * fix: inline tooltip * fix: inlineCollapse logic * fix: ts definition * test: Update snapshot * test: Update snapshot * fix: dropdown logic * test: Update snapshot * test: Fix some test case * bump rc-menu * test: More test case * fix test finder * test: fix test case * test: Update snapshot * test: Update snapshot * chore: Update ssr effect * test: Update ConfigProvider snapshot * test: Fix Table Filter test case * test: Fix table test case * chore: Update style * chore: beauti css * bump rc-menu * test: update snapshot * test: update snapshot * test: Fix menu test * test: Fix test case * test: Coverage * chore: clean up * bump rc-menu * ehance accessibility style * feat(radioGroup): support data-* and aria-* props (#30507) close #30501 * feat: Typography add italic type (#30458) * Typography增加斜体字支持 * update snapshot * 文档添加版本号 Co-authored-by: lidahao <lidahao@sisyphe.com.cn> * chore: alpha Menu fix merge (#30546) * chore: Update script * bump alpha version * chore: Update script desc * chore: bump rc-tabs & rc-mentions * chore: Adjust style * chore: 4.16.0-alpha.1 * test: Fix mention test case * fix: sider of layout width style * chore: bump 4.16.0-alpha.2 * fix: Tabs tabBarGutter should work as expected (#30545) close #30526 * feat: Table summary support sticky mode (#30631) * chore: Bump rc-table * feat: Patch summary fixed color * fix: style className * test: Update snapshot Co-authored-by: xrkffgg <xrkffgg@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: 二货机器人 <smith3816@gmail.com> Co-authored-by: gepd <guillermoepd@hotmail.com> Co-authored-by: appleshell <appleshell@outlook.com> Co-authored-by: Eric Bonow <ebonow@hotmail.com> Co-authored-by: xrkffgg <xrkffgg@vip.qq.com> Co-authored-by: Kermit <kermitlx@outlook.com> Co-authored-by: Lewis <lewisfidlers@gmail.com> Co-authored-by: afc163 <afc163@gmail.com> Co-authored-by: Ștefan Filip <stefy.filip@gmail.com> Co-authored-by: vldh <alwaysloseall@sina.com> Co-authored-by: lidahao <lidahao@sisyphe.com.cn>
This commit is contained in:
parent
9275866f24
commit
0d1b1c40a6
@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { detectFlexGapSupported } from '../../_util/styleChecker';
|
||||
import { detectFlexGapSupported } from '../styleChecker';
|
||||
|
||||
export default () => {
|
||||
const [flexible, setFlexible] = React.useState(false);
|
@ -15038,20 +15038,22 @@ exports[`ConfigProvider components List prefixCls 1`] = `
|
||||
|
||||
exports[`ConfigProvider components Menu configProvider 1`] = `
|
||||
<ul
|
||||
class="config-menu config-menu-light config-menu-root config-menu-inline"
|
||||
class="config-menu config-menu-root config-menu-inline config-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="config-menu-submenu config-menu-submenu-inline config-menu-submenu-open"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-owns="bamboo$Menu"
|
||||
class="config-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
tabindex="-1"
|
||||
title="bamboo"
|
||||
>
|
||||
bamboo
|
||||
@ -15061,11 +15063,10 @@ exports[`ConfigProvider components Menu configProvider 1`] = `
|
||||
</div>
|
||||
<ul
|
||||
class="config-menu config-menu-sub config-menu-inline"
|
||||
id="bamboo$Menu"
|
||||
role="menu"
|
||||
data-menu-list="true"
|
||||
>
|
||||
<li
|
||||
class=" config-menu-item-group"
|
||||
class="config-menu-item-group"
|
||||
>
|
||||
<div
|
||||
class="config-menu-item-group-title"
|
||||
@ -15080,6 +15081,7 @@ exports[`ConfigProvider components Menu configProvider 1`] = `
|
||||
class="config-menu-item config-menu-item-only-child"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
tabindex="-1"
|
||||
>
|
||||
Light
|
||||
</li>
|
||||
@ -15092,20 +15094,22 @@ exports[`ConfigProvider components Menu configProvider 1`] = `
|
||||
|
||||
exports[`ConfigProvider components Menu configProvider componentSize large 1`] = `
|
||||
<ul
|
||||
class="config-menu config-menu-light config-menu-root config-menu-inline"
|
||||
class="config-menu config-menu-root config-menu-inline config-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="config-menu-submenu config-menu-submenu-inline config-menu-submenu-open"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-owns="bamboo$Menu"
|
||||
class="config-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
tabindex="-1"
|
||||
title="bamboo"
|
||||
>
|
||||
bamboo
|
||||
@ -15115,11 +15119,10 @@ exports[`ConfigProvider components Menu configProvider componentSize large 1`] =
|
||||
</div>
|
||||
<ul
|
||||
class="config-menu config-menu-sub config-menu-inline"
|
||||
id="bamboo$Menu"
|
||||
role="menu"
|
||||
data-menu-list="true"
|
||||
>
|
||||
<li
|
||||
class=" config-menu-item-group"
|
||||
class="config-menu-item-group"
|
||||
>
|
||||
<div
|
||||
class="config-menu-item-group-title"
|
||||
@ -15134,6 +15137,7 @@ exports[`ConfigProvider components Menu configProvider componentSize large 1`] =
|
||||
class="config-menu-item config-menu-item-only-child"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
tabindex="-1"
|
||||
>
|
||||
Light
|
||||
</li>
|
||||
@ -15146,20 +15150,22 @@ exports[`ConfigProvider components Menu configProvider componentSize large 1`] =
|
||||
|
||||
exports[`ConfigProvider components Menu configProvider componentSize middle 1`] = `
|
||||
<ul
|
||||
class="config-menu config-menu-light config-menu-root config-menu-inline"
|
||||
class="config-menu config-menu-root config-menu-inline config-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="config-menu-submenu config-menu-submenu-inline config-menu-submenu-open"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-owns="bamboo$Menu"
|
||||
class="config-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
tabindex="-1"
|
||||
title="bamboo"
|
||||
>
|
||||
bamboo
|
||||
@ -15169,11 +15175,10 @@ exports[`ConfigProvider components Menu configProvider componentSize middle 1`]
|
||||
</div>
|
||||
<ul
|
||||
class="config-menu config-menu-sub config-menu-inline"
|
||||
id="bamboo$Menu"
|
||||
role="menu"
|
||||
data-menu-list="true"
|
||||
>
|
||||
<li
|
||||
class=" config-menu-item-group"
|
||||
class="config-menu-item-group"
|
||||
>
|
||||
<div
|
||||
class="config-menu-item-group-title"
|
||||
@ -15188,6 +15193,7 @@ exports[`ConfigProvider components Menu configProvider componentSize middle 1`]
|
||||
class="config-menu-item config-menu-item-only-child"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
tabindex="-1"
|
||||
>
|
||||
Light
|
||||
</li>
|
||||
@ -15200,20 +15206,22 @@ exports[`ConfigProvider components Menu configProvider componentSize middle 1`]
|
||||
|
||||
exports[`ConfigProvider components Menu configProvider virtual and dropdownMatchSelectWidth 1`] = `
|
||||
<ul
|
||||
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
|
||||
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-owns="bamboo$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
tabindex="-1"
|
||||
title="bamboo"
|
||||
>
|
||||
bamboo
|
||||
@ -15223,11 +15231,10 @@ exports[`ConfigProvider components Menu configProvider virtual and dropdownMatch
|
||||
</div>
|
||||
<ul
|
||||
class="ant-menu ant-menu-sub ant-menu-inline"
|
||||
id="bamboo$Menu"
|
||||
role="menu"
|
||||
data-menu-list="true"
|
||||
>
|
||||
<li
|
||||
class=" ant-menu-item-group"
|
||||
class="ant-menu-item-group"
|
||||
>
|
||||
<div
|
||||
class="ant-menu-item-group-title"
|
||||
@ -15242,6 +15249,7 @@ exports[`ConfigProvider components Menu configProvider virtual and dropdownMatch
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
tabindex="-1"
|
||||
>
|
||||
Light
|
||||
</li>
|
||||
@ -15254,20 +15262,22 @@ exports[`ConfigProvider components Menu configProvider virtual and dropdownMatch
|
||||
|
||||
exports[`ConfigProvider components Menu normal 1`] = `
|
||||
<ul
|
||||
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
|
||||
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-inline ant-menu-submenu-open"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-owns="bamboo$Menu"
|
||||
class="ant-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
tabindex="-1"
|
||||
title="bamboo"
|
||||
>
|
||||
bamboo
|
||||
@ -15277,11 +15287,10 @@ exports[`ConfigProvider components Menu normal 1`] = `
|
||||
</div>
|
||||
<ul
|
||||
class="ant-menu ant-menu-sub ant-menu-inline"
|
||||
id="bamboo$Menu"
|
||||
role="menu"
|
||||
data-menu-list="true"
|
||||
>
|
||||
<li
|
||||
class=" ant-menu-item-group"
|
||||
class="ant-menu-item-group"
|
||||
>
|
||||
<div
|
||||
class="ant-menu-item-group-title"
|
||||
@ -15296,6 +15305,7 @@ exports[`ConfigProvider components Menu normal 1`] = `
|
||||
class="ant-menu-item ant-menu-item-only-child"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
tabindex="-1"
|
||||
>
|
||||
Light
|
||||
</li>
|
||||
@ -15308,20 +15318,22 @@ exports[`ConfigProvider components Menu normal 1`] = `
|
||||
|
||||
exports[`ConfigProvider components Menu prefixCls 1`] = `
|
||||
<ul
|
||||
class="prefix-Menu prefix-Menu-light prefix-Menu-root prefix-Menu-inline"
|
||||
class="prefix-Menu prefix-Menu-root prefix-Menu-inline prefix-Menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="prefix-Menu-submenu prefix-Menu-submenu-inline prefix-Menu-submenu-open"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-owns="bamboo$Menu"
|
||||
class="prefix-Menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
style="padding-left:24px"
|
||||
tabindex="-1"
|
||||
title="bamboo"
|
||||
>
|
||||
bamboo
|
||||
@ -15331,11 +15343,11 @@ exports[`ConfigProvider components Menu prefixCls 1`] = `
|
||||
</div>
|
||||
<ul
|
||||
class="prefix-Menu prefix-Menu-sub prefix-Menu-inline"
|
||||
id="bamboo$Menu"
|
||||
role="menu"
|
||||
data-menu-list="true"
|
||||
>
|
||||
<li
|
||||
class=" prefix-Menu-item-group"
|
||||
class="prefix-Menu-item-group"
|
||||
prefixcls="prefix-Menu"
|
||||
>
|
||||
<div
|
||||
class="prefix-Menu-item-group-title"
|
||||
@ -15348,8 +15360,10 @@ exports[`ConfigProvider components Menu prefixCls 1`] = `
|
||||
>
|
||||
<li
|
||||
class="prefix-Menu-item prefix-Menu-item-only-child"
|
||||
prefixcls="prefix-Menu"
|
||||
role="menuitem"
|
||||
style="padding-left:48px"
|
||||
tabindex="-1"
|
||||
>
|
||||
Light
|
||||
</li>
|
||||
@ -22853,12 +22867,15 @@ exports[`ConfigProvider components Table configProvider 1`] = `
|
||||
class="config-table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="config-dropdown-menu config-dropdown-menu-light config-dropdown-menu-root config-dropdown-menu-vertical"
|
||||
class="config-dropdown-menu config-dropdown-menu-root config-dropdown-menu-vertical config-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="config-dropdown-menu-item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="config-checkbox-wrapper"
|
||||
@ -22881,13 +22898,14 @@ exports[`ConfigProvider components Table configProvider 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="config-dropdown-menu-submenu config-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="config-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Submenu"
|
||||
>
|
||||
Submenu
|
||||
@ -23124,12 +23142,15 @@ exports[`ConfigProvider components Table configProvider componentSize large 1`]
|
||||
class="config-table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="config-dropdown-menu config-dropdown-menu-light config-dropdown-menu-root config-dropdown-menu-vertical"
|
||||
class="config-dropdown-menu config-dropdown-menu-root config-dropdown-menu-vertical config-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="config-dropdown-menu-item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="config-checkbox-wrapper"
|
||||
@ -23152,13 +23173,14 @@ exports[`ConfigProvider components Table configProvider componentSize large 1`]
|
||||
</li>
|
||||
<li
|
||||
class="config-dropdown-menu-submenu config-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="config-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Submenu"
|
||||
>
|
||||
Submenu
|
||||
@ -23395,12 +23417,15 @@ exports[`ConfigProvider components Table configProvider componentSize middle 1`]
|
||||
class="config-table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="config-dropdown-menu config-dropdown-menu-light config-dropdown-menu-root config-dropdown-menu-vertical"
|
||||
class="config-dropdown-menu config-dropdown-menu-root config-dropdown-menu-vertical config-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="config-dropdown-menu-item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="config-checkbox-wrapper"
|
||||
@ -23423,13 +23448,14 @@ exports[`ConfigProvider components Table configProvider componentSize middle 1`]
|
||||
</li>
|
||||
<li
|
||||
class="config-dropdown-menu-submenu config-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="config-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Submenu"
|
||||
>
|
||||
Submenu
|
||||
@ -23666,12 +23692,15 @@ exports[`ConfigProvider components Table configProvider virtual and dropdownMatc
|
||||
class="ant-table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
@ -23694,13 +23723,14 @@ exports[`ConfigProvider components Table configProvider virtual and dropdownMatc
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Submenu"
|
||||
>
|
||||
Submenu
|
||||
@ -23937,12 +23967,15 @@ exports[`ConfigProvider components Table normal 1`] = `
|
||||
class="ant-table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
@ -23965,13 +23998,14 @@ exports[`ConfigProvider components Table normal 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Submenu"
|
||||
>
|
||||
Submenu
|
||||
@ -24208,12 +24242,15 @@ exports[`ConfigProvider components Table prefixCls 1`] = `
|
||||
class="prefix-Table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
@ -24236,13 +24273,14 @@ exports[`ConfigProvider components Table prefixCls 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Submenu"
|
||||
>
|
||||
Submenu
|
||||
|
@ -77,10 +77,10 @@ The following APIs are shared by DatePicker, RangePicker.
|
||||
|
||||
### Common Methods
|
||||
|
||||
| Name | Description | Version |
|
||||
| --- | --- | --- |
|
||||
| blur() | Remove focus | |
|
||||
| focus() | Get focus | |
|
||||
| Name | Description | Version |
|
||||
| ------- | ------------ | ------- |
|
||||
| blur() | Remove focus | |
|
||||
| focus() | Get focus | |
|
||||
|
||||
### DatePicker
|
||||
|
||||
|
@ -5,8 +5,15 @@ import { PickerLocale } from '../generatePicker';
|
||||
// Merge into a locale object
|
||||
const locale: PickerLocale = {
|
||||
lang: {
|
||||
monthPlaceholder: 'Selecteer maand',
|
||||
placeholder: 'Selecteer datum',
|
||||
quarterPlaceholder: 'Selecteer kwartaal',
|
||||
rangeMonthPlaceholder: ['Begin maand', 'Eind maand'],
|
||||
rangePlaceholder: ['Begin datum', 'Eind datum'],
|
||||
rangeWeekPlaceholder: ['Begin week', 'Eind week'],
|
||||
rangeYearPlaceholder: ['Begin jaar', 'Eind jaar'],
|
||||
weekPlaceholder: 'Selecteer week',
|
||||
yearPlaceholder: 'Selecteer jaar',
|
||||
...CalendarLocale,
|
||||
},
|
||||
timePickerLocale: {
|
||||
|
@ -5,8 +5,15 @@ import { PickerLocale } from '../generatePicker';
|
||||
// Merge into a locale object
|
||||
const locale: PickerLocale = {
|
||||
lang: {
|
||||
monthPlaceholder: 'Selecteer maand',
|
||||
placeholder: 'Selecteer datum',
|
||||
quarterPlaceholder: 'Selecteer kwartaal',
|
||||
rangeMonthPlaceholder: ['Begin maand', 'Eind maand'],
|
||||
rangePlaceholder: ['Begin datum', 'Eind datum'],
|
||||
rangeWeekPlaceholder: ['Begin week', 'Eind week'],
|
||||
rangeYearPlaceholder: ['Begin jaar', 'Eind jaar'],
|
||||
weekPlaceholder: 'Selecteer week',
|
||||
yearPlaceholder: 'Selecteer jaar',
|
||||
...CalendarLocale,
|
||||
},
|
||||
timePickerLocale: {
|
||||
|
@ -71,7 +71,9 @@ describe('DropdownButton', () => {
|
||||
<Menu.Item>foo</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
const wrapper = mount(<Dropdown.Button mouseEnterDelay={1} mouseLeaveDelay={2} overlay={menu} />);
|
||||
const wrapper = mount(
|
||||
<Dropdown.Button mouseEnterDelay={1} mouseLeaveDelay={2} overlay={menu} />,
|
||||
);
|
||||
expect(wrapper.find('Dropdown').props().mouseEnterDelay).toBe(1);
|
||||
expect(wrapper.find('Dropdown').props().mouseLeaveDelay).toBe(2);
|
||||
});
|
||||
|
@ -29,9 +29,11 @@ interface DropdownButtonInterface extends React.FC<DropdownButtonProps> {
|
||||
}
|
||||
|
||||
const DropdownButton: DropdownButtonInterface = props => {
|
||||
const { getPopupContainer: getContextPopupContainer, getPrefixCls, direction } = React.useContext(
|
||||
ConfigContext,
|
||||
);
|
||||
const {
|
||||
getPopupContainer: getContextPopupContainer,
|
||||
getPrefixCls,
|
||||
direction,
|
||||
} = React.useContext(ConfigContext);
|
||||
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
|
@ -101,8 +101,7 @@ const Dropdown: DropdownInterface = props => {
|
||||
);
|
||||
|
||||
// menu cannot be selectable in dropdown defaultly
|
||||
// menu should be focusable in dropdown defaultly
|
||||
const { selectable = false, focusable = true, expandIcon } = overlayProps;
|
||||
const { selectable = false, expandIcon } = overlayProps;
|
||||
|
||||
const overlayNodeExpandIcon =
|
||||
typeof expandIcon !== 'undefined' && React.isValidElement(expandIcon) ? (
|
||||
@ -119,7 +118,6 @@ const Dropdown: DropdownInterface = props => {
|
||||
: cloneElement(overlayNode, {
|
||||
mode: 'vertical',
|
||||
selectable,
|
||||
focusable,
|
||||
expandIcon: overlayNodeExpandIcon,
|
||||
});
|
||||
|
||||
|
@ -43,7 +43,8 @@
|
||||
}
|
||||
|
||||
&-hidden,
|
||||
&-menu-hidden {
|
||||
&-menu-hidden,
|
||||
&-menu-submenu-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import ResponsiveObserve, {
|
||||
ScreenMap,
|
||||
responsiveArray,
|
||||
} from '../_util/responsiveObserve';
|
||||
import useFlexGapSupport from './hooks/useFlexGapSupport';
|
||||
import useFlexGapSupport from '../_util/hooks/useFlexGapSupport';
|
||||
|
||||
const RowAligns = tuple('top', 'middle', 'bottom', 'stretch');
|
||||
const RowJustify = tuple('start', 'end', 'center', 'space-around', 'space-between');
|
||||
|
@ -21,7 +21,6 @@ const dimensionMaxMap = {
|
||||
|
||||
export interface SiderContextProps {
|
||||
siderCollapsed?: boolean;
|
||||
collapsedWidth?: number | string;
|
||||
}
|
||||
|
||||
export const SiderContext: React.Context<SiderContextProps> = React.createContext({});
|
||||
@ -219,7 +218,6 @@ const Sider = React.forwardRef<HTMLDivElement, SiderProps>(
|
||||
<SiderContext.Provider
|
||||
value={{
|
||||
siderCollapsed: collapsed,
|
||||
collapsedWidth,
|
||||
}}
|
||||
>
|
||||
{renderSider()}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -204,16 +204,16 @@ describe('Layout', () => {
|
||||
</Sider>,
|
||||
);
|
||||
|
||||
wrapper.find('.ant-menu-item').simulate('mouseenter');
|
||||
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter');
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
|
||||
wrapper.find('.ant-menu-item').simulate('mouseout');
|
||||
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseout');
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
wrapper.setProps({ collapsed: true });
|
||||
wrapper.find('.ant-menu-item').simulate('mouseenter');
|
||||
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter');
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBeTruthy();
|
||||
|
@ -2,6 +2,7 @@
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
@layout-prefix-cls: ~'@{ant-prefix}-layout';
|
||||
@layout-menu-prefix-cls: ~'@{ant-prefix}-menu';
|
||||
|
||||
.@{layout-prefix-cls} {
|
||||
display: flex;
|
||||
@ -66,6 +67,10 @@
|
||||
// https://github.com/ant-design/ant-design/issues/7967
|
||||
// solution from https://stackoverflow.com/a/33132624/3040605
|
||||
padding-top: 0.1px;
|
||||
|
||||
.@{layout-menu-prefix-cls}.@{layout-menu-prefix-cls}-inline-collapsed {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-has-trigger {
|
||||
|
@ -211251,7 +211251,7 @@ exports[`Locale Provider should display the text as nl 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Annuleren
|
||||
Annuleer
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
@ -211329,7 +211329,7 @@ exports[`Locale Provider should display the text as nl 1`] = `
|
||||
>
|
||||
<input
|
||||
class="ant-input ant-transfer-list-search"
|
||||
placeholder="Zoeken"
|
||||
placeholder="Zoek hier"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -211521,7 +211521,7 @@ exports[`Locale Provider should display the text as nl 1`] = `
|
||||
>
|
||||
<input
|
||||
class="ant-input ant-transfer-list-search"
|
||||
placeholder="Zoeken"
|
||||
placeholder="Zoek hier"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -212763,7 +212763,7 @@ exports[`Locale Provider should display the text as nl 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Annuleren
|
||||
Annuleer
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
|
@ -1,11 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import ConfigProvider from '../../config-provider';
|
||||
|
||||
import { Modal } from '../..';
|
||||
|
||||
import zhCN from '../zh_CN';
|
||||
|
||||
class Demo extends React.Component {
|
||||
|
@ -1,21 +1,37 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import Pagination from 'rc-pagination/lib/locale/nl_BE';
|
||||
import DatePicker from '../date-picker/locale/nl_BE';
|
||||
import TimePicker from '../time-picker/locale/nl_BE';
|
||||
import Calendar from '../calendar/locale/nl_BE';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
const typeTemplate = '${label} is geen geldige ${type}';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'nl-be',
|
||||
Pagination,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Calendar,
|
||||
global: {
|
||||
placeholder: 'Maak een selectie',
|
||||
},
|
||||
Table: {
|
||||
filterTitle: 'FilterMenu',
|
||||
cancelSort: 'Klik om sortering te annuleren',
|
||||
collapse: 'Rij inklappen',
|
||||
emptyText: 'Geen data',
|
||||
expand: 'Rij uitklappen',
|
||||
filterConfirm: 'OK',
|
||||
filterEmptyText: 'Geen filters',
|
||||
filterReset: 'Reset',
|
||||
filterTitle: 'Filteren',
|
||||
selectAll: 'Selecteer huidige pagina',
|
||||
selectInvert: 'Selecteer huidige pagina',
|
||||
selectInvert: 'Keer volgorde om',
|
||||
selectNone: 'Maak selectie leeg',
|
||||
selectionAll: 'Selecteer alle data',
|
||||
sortTitle: 'Sorteren',
|
||||
triggerAsc: 'Klik om oplopend te sorteren',
|
||||
triggerDesc: 'Klik om aflopend te sorteren',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
@ -27,20 +43,92 @@ const localeValues: Locale = {
|
||||
cancelText: 'Annuleer',
|
||||
},
|
||||
Transfer: {
|
||||
searchPlaceholder: 'Zoek hier',
|
||||
itemUnit: 'item',
|
||||
itemsUnit: 'items',
|
||||
remove: 'Verwijder',
|
||||
removeAll: 'Verwijder alles',
|
||||
removeCurrent: 'Verwijder huidige pagina',
|
||||
searchPlaceholder: 'Zoek hier',
|
||||
selectAll: 'Selecteer alles',
|
||||
selectCurrent: 'Selecteer huidige pagina',
|
||||
selectInvert: 'Huidige pagina omkeren',
|
||||
titles: ['', ''],
|
||||
},
|
||||
Upload: {
|
||||
downloadFile: 'Bestand downloaden',
|
||||
previewFile: 'Preview file',
|
||||
removeFile: 'Verwijder bestand',
|
||||
uploadError: 'Fout tijdens uploaden',
|
||||
uploading: 'Uploaden...',
|
||||
removeFile: 'Bestand verwijderen',
|
||||
uploadError: 'Upload fout',
|
||||
previewFile: 'Preview bestand',
|
||||
downloadFile: 'Download bestand',
|
||||
},
|
||||
Empty: {
|
||||
description: 'Geen gegevens',
|
||||
},
|
||||
Icon: {
|
||||
icon: 'icoon',
|
||||
},
|
||||
Text: {
|
||||
edit: 'Bewerken',
|
||||
copy: 'kopiëren',
|
||||
copied: 'Gekopieerd',
|
||||
expand: 'Uitklappen',
|
||||
},
|
||||
PageHeader: {
|
||||
back: 'Terug',
|
||||
},
|
||||
Form: {
|
||||
optional: '(optioneel)',
|
||||
defaultValidateMessages: {
|
||||
default: 'Validatiefout voor ${label}',
|
||||
required: 'Gelieve ${label} in te vullen',
|
||||
enum: '${label} moet één van [${enum}] zijn',
|
||||
whitespace: '${label} mag geen blanco teken zijn',
|
||||
date: {
|
||||
format: '${label} heeft een ongeldig formaat',
|
||||
parse: '${label} kan niet naar een datum omgezet worden',
|
||||
invalid: '${label} is een ongeldige datum',
|
||||
},
|
||||
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} moet ${len} karakters lang zijn',
|
||||
min: '${label} moet minimaal ${min} karakters lang zijn',
|
||||
max: '${label} mag maximaal ${max} karakters lang zijn',
|
||||
range: '${label} moet tussen ${min}-${max} karakters lang zijn',
|
||||
},
|
||||
number: {
|
||||
len: '${label} moet gelijk zijn aan ${len}',
|
||||
min: '${label} moet minimaal ${min} zijn',
|
||||
max: '${label} mag maximaal ${max} zijn',
|
||||
range: '${label} moet tussen ${min}-${max} liggen',
|
||||
},
|
||||
array: {
|
||||
len: 'Moeten ${len} ${label} zijn',
|
||||
min: 'Minimaal ${min} ${label}',
|
||||
max: 'maximaal ${max} ${label}',
|
||||
range: 'Het aantal ${label} moet tussen ${min}-${max} liggen',
|
||||
},
|
||||
pattern: {
|
||||
mismatch: '${label} komt niet overeen met het patroon ${pattern}',
|
||||
},
|
||||
},
|
||||
},
|
||||
Image: {
|
||||
preview: 'Voorbeeld',
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -1,9 +1,12 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import Pagination from 'rc-pagination/lib/locale/nl_NL';
|
||||
import DatePicker from '../date-picker/locale/nl_NL';
|
||||
import TimePicker from '../time-picker/locale/nl_NL';
|
||||
import Calendar from '../calendar/locale/nl_NL';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
const typeTemplate = '${label} is geen geldige ${type}';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'nl',
|
||||
Pagination,
|
||||
@ -14,36 +17,49 @@ const localeValues: Locale = {
|
||||
placeholder: 'Maak een selectie',
|
||||
},
|
||||
Table: {
|
||||
filterTitle: 'Filteren',
|
||||
filterConfirm: 'OK',
|
||||
filterReset: 'Reset',
|
||||
selectAll: 'Selecteer huidige pagina',
|
||||
selectInvert: 'Deselecteer huidige pagina',
|
||||
sortTitle: 'Sorteren',
|
||||
expand: 'Rij uitklappen',
|
||||
cancelSort: 'Klik om sortering te annuleren',
|
||||
collapse: 'Rij inklappen',
|
||||
emptyText: 'Geen data',
|
||||
expand: 'Rij uitklappen',
|
||||
filterConfirm: 'OK',
|
||||
filterEmptyText: 'Geen filters',
|
||||
filterReset: 'Reset',
|
||||
filterTitle: 'Filteren',
|
||||
selectAll: 'Selecteer huidige pagina',
|
||||
selectInvert: 'Keer volgorde om',
|
||||
selectNone: 'Maak selectie leeg',
|
||||
selectionAll: 'Selecteer alle data',
|
||||
sortTitle: 'Sorteren',
|
||||
triggerAsc: 'Klik om oplopend te sorteren',
|
||||
triggerDesc: 'Klik om aflopend te sorteren',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
cancelText: 'Annuleren',
|
||||
cancelText: 'Annuleer',
|
||||
justOkText: 'OK',
|
||||
},
|
||||
Popconfirm: {
|
||||
okText: 'OK',
|
||||
cancelText: 'Annuleren',
|
||||
cancelText: 'Annuleer',
|
||||
},
|
||||
Transfer: {
|
||||
titles: ['', ''],
|
||||
searchPlaceholder: 'Zoeken',
|
||||
itemUnit: 'item',
|
||||
itemsUnit: 'items',
|
||||
remove: 'Verwijder',
|
||||
removeAll: 'Verwijder alles',
|
||||
removeCurrent: 'Verwijder huidige pagina',
|
||||
searchPlaceholder: 'Zoek hier',
|
||||
selectAll: 'Selecteer alles',
|
||||
selectCurrent: 'Selecteer huidige pagina',
|
||||
selectInvert: 'Huidige pagina omkeren',
|
||||
titles: ['', ''],
|
||||
},
|
||||
Upload: {
|
||||
uploading: 'Uploaden...',
|
||||
downloadFile: 'Bestand downloaden',
|
||||
previewFile: 'Preview file',
|
||||
removeFile: 'Verwijder bestand',
|
||||
uploadError: 'Fout tijdens uploaden',
|
||||
previewFile: 'Bekijk bestand',
|
||||
downloadFile: 'Downloaden bestand',
|
||||
uploading: 'Uploaden...',
|
||||
},
|
||||
Empty: {
|
||||
description: 'Geen gegevens',
|
||||
@ -53,13 +69,66 @@ const localeValues: Locale = {
|
||||
},
|
||||
Text: {
|
||||
edit: 'Bewerken',
|
||||
copy: 'Kopieren',
|
||||
copy: 'kopiëren',
|
||||
copied: 'Gekopieerd',
|
||||
expand: 'Uitklappen',
|
||||
},
|
||||
PageHeader: {
|
||||
back: 'Terug',
|
||||
},
|
||||
Form: {
|
||||
optional: '(optioneel)',
|
||||
defaultValidateMessages: {
|
||||
default: 'Validatiefout voor ${label}',
|
||||
required: 'Gelieve ${label} in te vullen',
|
||||
enum: '${label} moet één van [${enum}] zijn',
|
||||
whitespace: '${label} mag geen blanco teken zijn',
|
||||
date: {
|
||||
format: '${label} heeft een ongeldig formaat',
|
||||
parse: '${label} kan niet naar een datum omgezet worden',
|
||||
invalid: '${label} is een ongeldige datum',
|
||||
},
|
||||
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} moet ${len} karakters lang zijn',
|
||||
min: '${label} moet minimaal ${min} karakters lang zijn',
|
||||
max: '${label} mag maximaal ${max} karakters lang zijn',
|
||||
range: '${label} moet tussen ${min}-${max} karakters lang zijn',
|
||||
},
|
||||
number: {
|
||||
len: '${label} moet gelijk zijn aan ${len}',
|
||||
min: '${label} moet minimaal ${min} zijn',
|
||||
max: '${label} mag maximaal ${max} zijn',
|
||||
range: '${label} moet tussen ${min}-${max} liggen',
|
||||
},
|
||||
array: {
|
||||
len: 'Moeten ${len} ${label} zijn',
|
||||
min: 'Minimaal ${min} ${label}',
|
||||
max: 'maximaal ${max} ${label}',
|
||||
range: 'Het aantal ${label} moet tussen ${min}-${max} liggen',
|
||||
},
|
||||
pattern: {
|
||||
mismatch: '${label} komt niet overeen met het patroon ${pattern}',
|
||||
},
|
||||
},
|
||||
},
|
||||
Image: {
|
||||
preview: 'Voorbeeld',
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -1,9 +1,12 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import Pagination from 'rc-pagination/lib/locale/ro_RO';
|
||||
import DatePicker from '../date-picker/locale/ro_RO';
|
||||
import TimePicker from '../time-picker/locale/ro_RO';
|
||||
import Calendar from '../calendar/locale/ro_RO';
|
||||
import { Locale } from '../locale-provider';
|
||||
|
||||
const typeTemplate = '${label} nu conține tipul corect (${type})';
|
||||
|
||||
const localeValues: Locale = {
|
||||
locale: 'ro',
|
||||
Pagination,
|
||||
@ -17,11 +20,18 @@ const localeValues: Locale = {
|
||||
filterTitle: 'Filtrează',
|
||||
filterConfirm: 'OK',
|
||||
filterReset: 'Resetează',
|
||||
filterEmptyText: 'Fără filtre',
|
||||
emptyText: 'Nu există date',
|
||||
selectAll: 'Selectează pagina curentă',
|
||||
selectInvert: 'Inversează pagina curentă',
|
||||
selectNone: 'Șterge selecția',
|
||||
selectionAll: 'Selectează toate datele',
|
||||
sortTitle: 'Ordonează',
|
||||
expand: 'Extinde rândul',
|
||||
collapse: 'Micșorează rândul',
|
||||
triggerDesc: 'Apasă pentru ordonare descrescătoare',
|
||||
triggerAsc: 'Apasă pentru ordonare crescătoare',
|
||||
cancelSort: 'Apasă pentru a anula ordonarea',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
@ -37,6 +47,12 @@ const localeValues: Locale = {
|
||||
searchPlaceholder: 'Căutare',
|
||||
itemUnit: 'element',
|
||||
itemsUnit: 'elemente',
|
||||
remove: 'Șterge',
|
||||
selectCurrent: 'Selectează pagina curentă',
|
||||
removeCurrent: 'Șterge pagina curentă',
|
||||
selectAll: 'Selectează toate datele',
|
||||
removeAll: 'Șterge toate datele',
|
||||
selectInvert: 'Inversează pagina curentă',
|
||||
},
|
||||
Upload: {
|
||||
uploading: 'Se transferă...',
|
||||
@ -60,6 +76,59 @@ const localeValues: Locale = {
|
||||
PageHeader: {
|
||||
back: 'înapoi',
|
||||
},
|
||||
Form: {
|
||||
optional: '(opțional)',
|
||||
defaultValidateMessages: {
|
||||
default: 'Eroare la validarea câmpului ${label}',
|
||||
required: 'Vă rugăm introduceți ${label}',
|
||||
enum: '${label} trebuie să fie una din valorile [${enum}]',
|
||||
whitespace: '${label} nu poate fi gol',
|
||||
date: {
|
||||
format: '${label} - data nu este în formatul corect',
|
||||
parse: '${label} nu poate fi convertit la o dată',
|
||||
invalid: '${label} este o dată invalidă',
|
||||
},
|
||||
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} trebuie să conțină ${len} caractere',
|
||||
min: '${label} trebuie să conțină cel puțin ${min} caractere',
|
||||
max: '${label} trebuie să conțină cel mult ${max} caractere',
|
||||
range: '${label} trebuie să conțină între ${min}-${max} caractere',
|
||||
},
|
||||
number: {
|
||||
len: '${label} trebuie să conțină ${len} cifre',
|
||||
min: '${label} trebuie să fie minim ${min}',
|
||||
max: '${label} trebuie să fie maxim ${max}',
|
||||
range: '${label} trebuie să fie între ${min}-${max}',
|
||||
},
|
||||
array: {
|
||||
len: '${label} trebuie să conțină ${len} elemente',
|
||||
min: '${label} trebuie să conțină cel puțin ${min} elemente',
|
||||
max: '${label} trebuie să conțină cel mult ${max} elemente',
|
||||
range: '${label} trebuie să conțină între ${min}-${max} elemente',
|
||||
},
|
||||
pattern: {
|
||||
mismatch: '${label} nu respectă șablonul ${pattern}',
|
||||
},
|
||||
},
|
||||
},
|
||||
Image: {
|
||||
preview: 'Preview',
|
||||
},
|
||||
};
|
||||
|
||||
export default localeValues;
|
||||
|
@ -81,14 +81,14 @@ describe('Mentions', () => {
|
||||
it('loading', () => {
|
||||
const wrapper = mount(<Mentions loading />);
|
||||
simulateInput(wrapper, '@');
|
||||
expect(wrapper.find('.ant-mentions-dropdown-menu-item').length).toBe(1);
|
||||
expect(wrapper.find('li.ant-mentions-dropdown-menu-item').length).toBe(1);
|
||||
expect(wrapper.find('.ant-spin').length).toBeTruthy();
|
||||
});
|
||||
|
||||
it('notFoundContent', () => {
|
||||
const wrapper = mount(<Mentions notFoundContent={<span className="bamboo-light" />} />);
|
||||
simulateInput(wrapper, '@');
|
||||
expect(wrapper.find('.ant-mentions-dropdown-menu-item').length).toBe(1);
|
||||
expect(wrapper.find('li.ant-mentions-dropdown-menu-item').length).toBe(1);
|
||||
expect(wrapper.find('.bamboo-light').length).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -4,12 +4,16 @@ import { DirectionType } from '../config-provider';
|
||||
export type MenuTheme = 'light' | 'dark';
|
||||
|
||||
export interface MenuContextProps {
|
||||
prefixCls: string;
|
||||
inlineCollapsed: boolean;
|
||||
antdMenuTheme?: MenuTheme;
|
||||
direction?: DirectionType;
|
||||
firstLevel: boolean;
|
||||
}
|
||||
|
||||
const MenuContext = createContext<MenuContextProps>({
|
||||
prefixCls: '',
|
||||
firstLevel: true,
|
||||
inlineCollapsed: false,
|
||||
});
|
||||
|
||||
|
@ -14,77 +14,72 @@ export interface MenuItemProps extends Omit<RcMenuItemProps, 'title'> {
|
||||
}
|
||||
|
||||
export default class MenuItem extends React.Component<MenuItemProps> {
|
||||
static isMenuItem = true;
|
||||
static contextType = MenuContext;
|
||||
|
||||
context: MenuContextProps;
|
||||
|
||||
renderItemChildren(inlineCollapsed: boolean) {
|
||||
const { icon, children, level, rootPrefixCls } = this.props;
|
||||
const { prefixCls, firstLevel } = this.context;
|
||||
const { icon, children } = this.props;
|
||||
// inline-collapsed.md demo 依赖 span 来隐藏文字,有 icon 属性,则内部包裹一个 span
|
||||
// ref: https://github.com/ant-design/ant-design/pull/23456
|
||||
if (!icon || (isValidElement(children) && children.type === 'span')) {
|
||||
if (children && inlineCollapsed && level === 1 && typeof children === 'string') {
|
||||
return (
|
||||
<div className={`${rootPrefixCls}-inline-collapsed-noicon`}>{children.charAt(0)}</div>
|
||||
);
|
||||
if (children && inlineCollapsed && firstLevel && typeof children === 'string') {
|
||||
return <div className={`${prefixCls}-inline-collapsed-noicon`}>{children.charAt(0)}</div>;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
return <span>{children}</span>;
|
||||
return <span className={`${prefixCls}-title-content`}>{children}</span>;
|
||||
}
|
||||
|
||||
renderItem = ({ siderCollapsed }: SiderContextProps) => {
|
||||
const { level, className, children, rootPrefixCls } = this.props;
|
||||
const { prefixCls, firstLevel, inlineCollapsed, direction } = this.context;
|
||||
const { className, children } = this.props;
|
||||
const { title, icon, danger, ...rest } = this.props;
|
||||
|
||||
return (
|
||||
<MenuContext.Consumer>
|
||||
{({ inlineCollapsed, direction }: MenuContextProps) => {
|
||||
let tooltipTitle = title;
|
||||
if (typeof title === 'undefined') {
|
||||
tooltipTitle = level === 1 ? children : '';
|
||||
} else if (title === false) {
|
||||
tooltipTitle = '';
|
||||
}
|
||||
const tooltipProps: TooltipProps = {
|
||||
title: tooltipTitle,
|
||||
};
|
||||
let tooltipTitle = title;
|
||||
if (typeof title === 'undefined') {
|
||||
tooltipTitle = firstLevel ? children : '';
|
||||
} else if (title === false) {
|
||||
tooltipTitle = '';
|
||||
}
|
||||
const tooltipProps: TooltipProps = {
|
||||
title: tooltipTitle,
|
||||
};
|
||||
|
||||
if (!siderCollapsed && !inlineCollapsed) {
|
||||
tooltipProps.title = null;
|
||||
// Reset `visible` to fix control mode tooltip display not correct
|
||||
// ref: https://github.com/ant-design/ant-design/issues/16742
|
||||
tooltipProps.visible = false;
|
||||
}
|
||||
const childrenLength = toArray(children).length;
|
||||
return (
|
||||
<Tooltip
|
||||
{...tooltipProps}
|
||||
placement={direction === 'rtl' ? 'left' : 'right'}
|
||||
overlayClassName={`${rootPrefixCls}-inline-collapsed-tooltip`}
|
||||
>
|
||||
<Item
|
||||
{...rest}
|
||||
className={classNames(
|
||||
{
|
||||
[`${rootPrefixCls}-item-danger`]: danger,
|
||||
[`${rootPrefixCls}-item-only-child`]:
|
||||
(icon ? childrenLength + 1 : childrenLength) === 1,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
title={title}
|
||||
>
|
||||
{cloneElement(icon, {
|
||||
className: classNames(
|
||||
isValidElement(icon) ? icon.props?.className : '',
|
||||
`${rootPrefixCls}-item-icon`,
|
||||
),
|
||||
})}
|
||||
{this.renderItemChildren(inlineCollapsed)}
|
||||
</Item>
|
||||
</Tooltip>
|
||||
);
|
||||
}}
|
||||
</MenuContext.Consumer>
|
||||
if (!siderCollapsed && !inlineCollapsed) {
|
||||
tooltipProps.title = null;
|
||||
// Reset `visible` to fix control mode tooltip display not correct
|
||||
// ref: https://github.com/ant-design/ant-design/issues/16742
|
||||
tooltipProps.visible = false;
|
||||
}
|
||||
const childrenLength = toArray(children).length;
|
||||
return (
|
||||
<Tooltip
|
||||
{...tooltipProps}
|
||||
placement={direction === 'rtl' ? 'left' : 'right'}
|
||||
overlayClassName={`${prefixCls}-inline-collapsed-tooltip`}
|
||||
>
|
||||
<Item
|
||||
{...rest}
|
||||
className={classNames(
|
||||
{
|
||||
[`${prefixCls}-item-danger`]: danger,
|
||||
[`${prefixCls}-item-only-child`]: (icon ? childrenLength + 1 : childrenLength) === 1,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
title={typeof title === 'string' ? title : undefined}
|
||||
>
|
||||
{cloneElement(icon, {
|
||||
className: classNames(
|
||||
isValidElement(icon) ? icon.props?.className : '',
|
||||
`${prefixCls}-item-icon`,
|
||||
),
|
||||
})}
|
||||
{this.renderItemChildren(inlineCollapsed)}
|
||||
</Item>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -7,11 +7,10 @@ import { isValidElement } from '../_util/reactNode';
|
||||
|
||||
interface TitleEventEntity {
|
||||
key: string;
|
||||
domEvent: Event;
|
||||
domEvent: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>;
|
||||
}
|
||||
|
||||
export interface SubMenuProps {
|
||||
rootPrefixCls?: string;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
level?: number;
|
||||
@ -28,14 +27,15 @@ export interface SubMenuProps {
|
||||
class SubMenu extends React.Component<SubMenuProps, any> {
|
||||
static contextType = MenuContext;
|
||||
|
||||
// fix issue:https://github.com/ant-design/ant-design/issues/8666
|
||||
static isSubMenu = 1;
|
||||
context: MenuContextProps;
|
||||
|
||||
renderTitle(inlineCollapsed: boolean) {
|
||||
const { icon, title, level, rootPrefixCls } = this.props;
|
||||
const { icon, title, level } = this.props;
|
||||
const { prefixCls } = this.context;
|
||||
|
||||
if (!icon) {
|
||||
return inlineCollapsed && level === 1 && title && typeof title === 'string' ? (
|
||||
<div className={`${rootPrefixCls}-inline-collapsed-noicon`}>{title.charAt(0)}</div>
|
||||
<div className={`${prefixCls}-inline-collapsed-noicon`}>{title.charAt(0)}</div>
|
||||
) : (
|
||||
title
|
||||
);
|
||||
@ -46,27 +46,27 @@ class SubMenu extends React.Component<SubMenuProps, any> {
|
||||
return (
|
||||
<>
|
||||
{icon}
|
||||
{titleIsSpan ? title : <span>{title}</span>}
|
||||
{titleIsSpan ? title : <span className={`${prefixCls}-title-content`}>{title}</span>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { rootPrefixCls, popupClassName } = this.props;
|
||||
const { popupClassName } = this.props;
|
||||
const { prefixCls, inlineCollapsed, antdMenuTheme } = this.context;
|
||||
return (
|
||||
<MenuContext.Consumer>
|
||||
{({ inlineCollapsed, antdMenuTheme }: MenuContextProps) => (
|
||||
<RcSubMenu
|
||||
{...omit(this.props, ['icon'])}
|
||||
title={this.renderTitle(inlineCollapsed)}
|
||||
popupClassName={classNames(
|
||||
rootPrefixCls,
|
||||
`${rootPrefixCls}-${antdMenuTheme}`,
|
||||
popupClassName,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</MenuContext.Consumer>
|
||||
<MenuContext.Provider
|
||||
value={{
|
||||
...this.context,
|
||||
firstLevel: false,
|
||||
}}
|
||||
>
|
||||
<RcSubMenu
|
||||
{...omit(this.props, ['icon'])}
|
||||
title={this.renderTitle(inlineCollapsed)}
|
||||
popupClassName={classNames(prefixCls, `${prefixCls}-${antdMenuTheme}`, popupClassName)}
|
||||
/>
|
||||
</MenuContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,12 +2,16 @@
|
||||
|
||||
exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
|
||||
<ul
|
||||
class="ant-menu ant-menu-light ant-menu-root ant-menu-vertical"
|
||||
class="ant-menu ant-menu-root ant-menu-vertical ant-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-1"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="mail"
|
||||
@ -28,13 +32,17 @@ exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
Navigation One
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-2"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="mail"
|
||||
@ -61,13 +69,16 @@ exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-controls="rc-menu-uuid-test-3-popup"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-menu-submenu-title"
|
||||
role="button"
|
||||
data-menu-id="rc-menu-uuid-test-3"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="mail"
|
||||
@ -88,7 +99,9 @@ exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
Navigation One
|
||||
</span>
|
||||
<i
|
||||
@ -98,13 +111,16 @@ exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-controls="rc-menu-uuid-test-4-popup"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-menu-submenu-title"
|
||||
role="button"
|
||||
data-menu-id="rc-menu-uuid-test-4"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="mail"
|
||||
@ -138,16 +154,19 @@ exports[`Menu Menu.Item with icon children auto wrap span 1`] = `
|
||||
|
||||
exports[`Menu rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<ul
|
||||
class="ant-menu ant-menu-light ant-menu-root ant-menu-rtl ant-menu-vertical"
|
||||
direction="rtl"
|
||||
class="ant-menu ant-menu-root ant-menu-vertical ant-menu-light ant-menu-rtl"
|
||||
data-menu-list="true"
|
||||
dir="rtl"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
/>
|
||||
<li
|
||||
class=" ant-menu-item-group"
|
||||
class="ant-menu-item-group"
|
||||
>
|
||||
<div
|
||||
class="ant-menu-item-group-title"
|
||||
@ -158,14 +177,14 @@ exports[`Menu rtl render component should be rendered correctly in RTL direction
|
||||
</li>
|
||||
<li
|
||||
class="ant-menu-submenu ant-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-menu-submenu-title"
|
||||
role="button"
|
||||
title=""
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<i
|
||||
class="ant-menu-submenu-arrow"
|
||||
@ -177,13 +196,17 @@ exports[`Menu rtl render component should be rendered correctly in RTL direction
|
||||
|
||||
exports[`Menu should controlled collapse work 1`] = `
|
||||
<ul
|
||||
class="ant-menu ant-menu-light ant-menu-root ant-menu-inline"
|
||||
class="ant-menu ant-menu-root ant-menu-inline ant-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-1"
|
||||
role="menuitem"
|
||||
style="padding-left: 24px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="pie-chart"
|
||||
@ -204,7 +227,9 @@ exports[`Menu should controlled collapse work 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
Option 1
|
||||
</span>
|
||||
</li>
|
||||
@ -213,13 +238,17 @@ exports[`Menu should controlled collapse work 1`] = `
|
||||
|
||||
exports[`Menu should controlled collapse work 2`] = `
|
||||
<ul
|
||||
class="ant-menu ant-menu-light ant-menu-inline-collapsed ant-menu-root ant-menu-inline"
|
||||
class="ant-menu ant-menu-root ant-menu-vertical ant-menu-light ant-menu-inline-collapsed"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-1"
|
||||
role="menuitem"
|
||||
style="padding-left: 24px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
aria-label="pie-chart"
|
||||
@ -240,7 +269,9 @@ exports[`Menu should controlled collapse work 2`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span>
|
||||
<span
|
||||
class="ant-menu-title-content"
|
||||
>
|
||||
Option 1
|
||||
</span>
|
||||
</li>
|
||||
|
@ -14,7 +14,6 @@ import Tooltip from '../../tooltip';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import collapseMotion from '../../_util/motion';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
@ -22,35 +21,45 @@ const noop = () => {};
|
||||
|
||||
const expectSubMenuBehavior = (menu, enter = noop, leave = noop) => {
|
||||
if (!menu.prop('openKeys') && !menu.prop('defaultOpenKeys')) {
|
||||
expect(menu.find('.ant-menu-sub').length).toBe(0);
|
||||
expect(menu.find('ul.ant-menu-sub').length).toBe(0);
|
||||
}
|
||||
menu.update();
|
||||
expect(menu.find('.ant-menu-sub').length).toBe(0);
|
||||
expect(menu.find('ul.ant-menu-sub').length).toBe(0);
|
||||
const AnimationClassNames = {
|
||||
horizontal: 'ant-slide-up-leave',
|
||||
inline: 'ant-motion-collapse-leave',
|
||||
vertical: 'ant-zoom-big-leave',
|
||||
};
|
||||
const mode = menu.prop('mode') || 'horizontal';
|
||||
enter();
|
||||
menu.update();
|
||||
|
||||
act(() => {
|
||||
enter();
|
||||
jest.runAllTimers();
|
||||
menu.update();
|
||||
});
|
||||
|
||||
function getSubMenu() {
|
||||
if (mode === 'inline') {
|
||||
return menu.find('.ant-menu-sub.ant-menu-inline').hostNodes().at(0);
|
||||
return menu.find('ul.ant-menu-sub.ant-menu-inline').hostNodes().at(0);
|
||||
}
|
||||
return menu.find('.ant-menu-submenu-popup').hostNodes().at(0);
|
||||
return menu.find('div.ant-menu-submenu-popup').hostNodes().at(0);
|
||||
}
|
||||
|
||||
expect(
|
||||
getSubMenu().hasClass('ant-menu-hidden') || getSubMenu().hasClass(AnimationClassNames[mode]),
|
||||
).toBe(false);
|
||||
leave();
|
||||
menu.update();
|
||||
).toBeFalsy();
|
||||
|
||||
expect(
|
||||
getSubMenu().hasClass('ant-menu-hidden') || getSubMenu().hasClass(AnimationClassNames[mode]),
|
||||
).toBe(true);
|
||||
act(() => {
|
||||
leave();
|
||||
jest.runAllTimers();
|
||||
menu.update();
|
||||
});
|
||||
|
||||
if (getSubMenu().length) {
|
||||
expect(
|
||||
getSubMenu().hasClass('ant-menu-hidden') || getSubMenu().hasClass(AnimationClassNames[mode]),
|
||||
).toBeTruthy();
|
||||
}
|
||||
};
|
||||
|
||||
describe('Menu', () => {
|
||||
@ -93,11 +102,16 @@ describe('Menu', () => {
|
||||
</Menu>
|
||||
));
|
||||
|
||||
let div;
|
||||
|
||||
beforeEach(() => {
|
||||
div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(div);
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
@ -115,7 +129,7 @@ describe('Menu', () => {
|
||||
<Menu.Item key="2">menu2</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('.ant-menu-submenu-selected').length).toBe(1);
|
||||
expect(wrapper.find('li.ant-menu-submenu-selected').length).toBe(1);
|
||||
});
|
||||
|
||||
it('forceSubMenuRender', () => {
|
||||
@ -145,7 +159,7 @@ describe('Menu', () => {
|
||||
<Menu.Item key="2">menu2</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
|
||||
expect(wrapper.exists('.ant-menu-sub')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should accept defaultOpenKeys in mode inline', () => {
|
||||
@ -171,7 +185,7 @@ describe('Menu', () => {
|
||||
<Menu.Item key="2">menu2</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
|
||||
expect(wrapper.find('PopupTrigger').first().prop('visible')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should accept openKeys in mode horizontal', () => {
|
||||
@ -184,7 +198,7 @@ describe('Menu', () => {
|
||||
<Menu.Item key="2">menu2</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
|
||||
expect(wrapper.find('PopupTrigger').first().prop('visible')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should accept openKeys in mode inline', () => {
|
||||
@ -197,7 +211,7 @@ describe('Menu', () => {
|
||||
<Menu.Item key="2">menu2</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
|
||||
expect(wrapper.find('InlineSubMenuList').first().prop('open')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should accept openKeys in mode vertical', () => {
|
||||
@ -210,7 +224,7 @@ describe('Menu', () => {
|
||||
<Menu.Item key="2">menu2</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
|
||||
expect(wrapper.find('PopupTrigger').first().prop('visible')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('test submenu in mode horizontal', () => {
|
||||
@ -309,29 +323,28 @@ describe('Menu', () => {
|
||||
</SubMenu>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true);
|
||||
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
|
||||
|
||||
expect(wrapper.find('InlineSubMenuList').prop('open')).toBeTruthy();
|
||||
|
||||
// inlineCollapsed
|
||||
wrapper.setProps({ inlineCollapsed: true });
|
||||
// 动画结束后套样式;
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
wrapper.simulate('transitionEnd', { propertyName: 'width' });
|
||||
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(wrapper.find('ul.ant-menu-root').at(0).hasClass('ant-menu-vertical')).toBe(true);
|
||||
expect(wrapper.find('ul.ant-menu-sub:not(.ant-menu-hidden)').length).toBe(0);
|
||||
expect(wrapper.find('ul.ant-menu-root').hasClass('ant-menu-vertical')).toBeTruthy();
|
||||
expect(wrapper.find('PopupTrigger').prop('visible')).toBeFalsy();
|
||||
|
||||
// !inlineCollapsed
|
||||
wrapper.setProps({ inlineCollapsed: false });
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true);
|
||||
expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false);
|
||||
expect(wrapper.find('ul.ant-menu-sub').last().hasClass('ant-menu-inline')).toBeTruthy();
|
||||
expect(wrapper.find('InlineSubMenuList').prop('open')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('inlineCollapsed should works well when specify a not existed default openKeys', () => {
|
||||
@ -435,11 +448,16 @@ describe('Menu', () => {
|
||||
});
|
||||
|
||||
it('inline menu collapseMotion should be triggered', async () => {
|
||||
jest.useRealTimers();
|
||||
const onAppearEnd = jest.spyOn(collapseMotion, 'onAppearEnd');
|
||||
collapseMotion.motionDeadline = 1;
|
||||
const cloneMotion = {
|
||||
...collapseMotion,
|
||||
motionDeadline: 1,
|
||||
};
|
||||
|
||||
const onOpenChange = jest.fn();
|
||||
const onEnterEnd = jest.spyOn(cloneMotion, 'onEnterEnd');
|
||||
|
||||
const wrapper = mount(
|
||||
<Menu mode="inline">
|
||||
<Menu mode="inline" motion={cloneMotion} onOpenChange={onOpenChange}>
|
||||
<SubMenu key="1" title="submenu1">
|
||||
<Menu.Item key="submenu1">Option 1</Menu.Item>
|
||||
<Menu.Item key="submenu2">Option 2</Menu.Item>
|
||||
@ -447,10 +465,16 @@ describe('Menu', () => {
|
||||
<Menu.Item key="2">menu2</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
wrapper.find('.ant-menu-submenu-title').simulate('click');
|
||||
await sleep(3000);
|
||||
expect(onAppearEnd).toHaveBeenCalledTimes(1);
|
||||
onAppearEnd.mockRestore();
|
||||
|
||||
wrapper.find('div.ant-menu-submenu-title').simulate('click');
|
||||
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(onOpenChange).toHaveBeenCalled();
|
||||
expect(onEnterEnd).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('vertical with hover(default)', () => {
|
||||
@ -539,7 +563,7 @@ describe('Menu', () => {
|
||||
</Menu>,
|
||||
);
|
||||
|
||||
wrapper.find('.ant-menu-item').simulate('mouseenter');
|
||||
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter');
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
});
|
||||
@ -601,7 +625,7 @@ describe('Menu', () => {
|
||||
<Menu.Item key="test2">Navigation Two</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
wrapper.find('Menu').at(1).simulate('mouseenter');
|
||||
wrapper.find('ul.ant-menu-root').simulate('mouseenter');
|
||||
expect(onMouseEnter).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@ -620,10 +644,16 @@ describe('Menu', () => {
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Menu>,
|
||||
{ attachTo: div },
|
||||
);
|
||||
wrapper.find('MenuItem').first().simulate('mouseenter');
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
wrapper.find('li.ant-menu-item').first().simulate('mouseenter');
|
||||
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(wrapper.find('.ant-tooltip-inner').length).toBe(0);
|
||||
});
|
||||
|
||||
@ -664,7 +694,7 @@ describe('Menu', () => {
|
||||
</Menu>,
|
||||
);
|
||||
|
||||
wrapper.find('.ant-menu-item').simulate('mouseenter');
|
||||
wrapper.find('.ant-menu-item').hostNodes().simulate('mouseenter');
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
@ -715,20 +745,25 @@ describe('Menu', () => {
|
||||
</Menu.SubMenu>
|
||||
</Menu>,
|
||||
);
|
||||
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 1');
|
||||
wrapper.find('.ant-menu-item').at(1).simulate('click');
|
||||
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
|
||||
expect(wrapper.find('li.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 1');
|
||||
wrapper.find('li.ant-menu-item').at(1).simulate('click');
|
||||
expect(wrapper.find('li.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
|
||||
wrapper.setProps({ inlineCollapsed: true });
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('Trigger')
|
||||
.find('PopupTrigger')
|
||||
.map(node => node.prop('popupVisible'))
|
||||
.findIndex(node => !!node),
|
||||
).toBe(-1);
|
||||
|
||||
wrapper.setProps({ inlineCollapsed: false });
|
||||
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
|
||||
expect(wrapper.find('li.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
@ -776,4 +811,14 @@ describe('Menu', () => {
|
||||
wrapper.find('button').simulate('click');
|
||||
expect(onOpenChange).toHaveBeenCalledWith([]);
|
||||
});
|
||||
|
||||
it('Use first char as Icon when collapsed', () => {
|
||||
const wrapper = mount(
|
||||
<Menu mode="inline" inlineCollapsed>
|
||||
<Menu.Item>Bamboo</Menu.Item>
|
||||
</Menu>,
|
||||
);
|
||||
|
||||
expect(wrapper.find('.ant-menu-inline-collapsed-noicon').text()).toEqual('B');
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import RcMenu, { Divider, ItemGroup, MenuProps as RcMenuProps } from 'rc-menu';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
import SubMenu, { SubMenuProps } from './SubMenu';
|
||||
import Item, { MenuItemProps } from './MenuItem';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
@ -17,16 +18,16 @@ export type MenuMode = 'vertical' | 'vertical-left' | 'vertical-right' | 'horizo
|
||||
export interface MenuProps extends RcMenuProps {
|
||||
theme?: MenuTheme;
|
||||
inlineIndent?: number;
|
||||
focusable?: boolean;
|
||||
}
|
||||
|
||||
type InternalMenuProps = MenuProps & SiderContextProps;
|
||||
type InternalMenuProps = MenuProps &
|
||||
SiderContextProps & {
|
||||
collapsedWidth?: string | number;
|
||||
};
|
||||
|
||||
class InternalMenu extends React.Component<InternalMenuProps> {
|
||||
static defaultProps: Partial<MenuProps> = {
|
||||
className: '',
|
||||
theme: 'light', // or dark
|
||||
focusable: false,
|
||||
};
|
||||
|
||||
constructor(props: InternalMenuProps) {
|
||||
@ -56,7 +57,17 @@ class InternalMenu extends React.Component<InternalMenuProps> {
|
||||
renderMenu = ({ getPopupContainer, getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const rootPrefixCls = getPrefixCls();
|
||||
|
||||
const { prefixCls: customizePrefixCls, className, theme, expandIcon } = this.props;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
theme,
|
||||
expandIcon,
|
||||
...restProps
|
||||
} = this.props;
|
||||
|
||||
const passedProps = omit(restProps, ['siderCollapsed', 'collapsedWidth']);
|
||||
const inlineCollapsed = this.getInlineCollapsed();
|
||||
|
||||
const defaultMotions = {
|
||||
horizontal: { motionName: `${rootPrefixCls}-slide-up` },
|
||||
inline: collapseMotion,
|
||||
@ -64,25 +75,22 @@ class InternalMenu extends React.Component<InternalMenuProps> {
|
||||
};
|
||||
|
||||
const prefixCls = getPrefixCls('menu', customizePrefixCls);
|
||||
const menuClassName = classNames(
|
||||
`${prefixCls}-${theme}`,
|
||||
{
|
||||
[`${prefixCls}-inline-collapsed`]: this.getInlineCollapsed(),
|
||||
},
|
||||
className,
|
||||
);
|
||||
const menuClassName = classNames(`${prefixCls}-${theme}`, className);
|
||||
|
||||
return (
|
||||
<MenuContext.Provider
|
||||
value={{
|
||||
inlineCollapsed: this.getInlineCollapsed() || false,
|
||||
prefixCls,
|
||||
inlineCollapsed: inlineCollapsed || false,
|
||||
antdMenuTheme: theme,
|
||||
direction,
|
||||
firstLevel: true,
|
||||
}}
|
||||
>
|
||||
<RcMenu
|
||||
getPopupContainer={getPopupContainer}
|
||||
{...this.props}
|
||||
{...passedProps}
|
||||
inlineCollapsed={inlineCollapsed}
|
||||
className={menuClassName}
|
||||
prefixCls={prefixCls}
|
||||
direction={direction}
|
||||
|
@ -3,6 +3,13 @@
|
||||
@import './status';
|
||||
|
||||
@menu-prefix-cls: ~'@{ant-prefix}-menu';
|
||||
@menu-animation-duration-normal: 0.15s;
|
||||
|
||||
.accessibility-focus() {
|
||||
box-shadow: 0 0 0 2px fade(@primary-color, 20%);
|
||||
}
|
||||
|
||||
// TODO: Should remove icon style compatible in v5
|
||||
|
||||
// default theme
|
||||
.@{menu-prefix-cls} {
|
||||
@ -18,9 +25,14 @@
|
||||
background: @menu-bg;
|
||||
outline: none;
|
||||
box-shadow: @box-shadow-base;
|
||||
transition: background 0.3s, width 0.3s cubic-bezier(0.2, 0, 0, 1) 0s;
|
||||
transition: background @animation-duration-slow,
|
||||
width @animation-duration-slow cubic-bezier(0.2, 0, 0, 1) 0s;
|
||||
.clearfix();
|
||||
|
||||
&&-root:focus-visible {
|
||||
.accessibility-focus();
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
margin: 0;
|
||||
@ -28,7 +40,8 @@
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
&-hidden {
|
||||
&-hidden,
|
||||
&-submenu-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -38,16 +51,18 @@
|
||||
color: @menu-item-group-title-color;
|
||||
font-size: @menu-item-group-title-font-size;
|
||||
line-height: @menu-item-group-height;
|
||||
transition: all 0.3s;
|
||||
transition: all @animation-duration-slow;
|
||||
}
|
||||
|
||||
&-horizontal &-submenu {
|
||||
transition: border-color 0.3s @ease-in-out, background 0.3s @ease-in-out;
|
||||
transition: border-color @animation-duration-slow @ease-in-out,
|
||||
background @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
&-submenu,
|
||||
&-submenu-inline {
|
||||
transition: border-color 0.3s @ease-in-out, background 0.3s @ease-in-out,
|
||||
padding 0.15s @ease-in-out;
|
||||
transition: border-color @animation-duration-slow @ease-in-out,
|
||||
background @animation-duration-slow @ease-in-out,
|
||||
padding @menu-animation-duration-normal @ease-in-out;
|
||||
}
|
||||
|
||||
&-submenu-selected {
|
||||
@ -61,7 +76,8 @@
|
||||
|
||||
&-submenu &-sub {
|
||||
cursor: initial;
|
||||
transition: background 0.3s @ease-in-out, padding 0.3s @ease-in-out;
|
||||
transition: background @animation-duration-slow @ease-in-out,
|
||||
padding @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
||||
&-item a {
|
||||
@ -172,7 +188,7 @@
|
||||
|
||||
&-horizontal &-item,
|
||||
&-horizontal &-submenu-title {
|
||||
transition: border-color 0.3s, background 0.3s;
|
||||
transition: border-color @animation-duration-slow, background @animation-duration-slow;
|
||||
}
|
||||
|
||||
&-item,
|
||||
@ -183,17 +199,22 @@
|
||||
padding: @menu-item-padding;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.3s, background 0.3s, padding 0.15s @ease-in-out;
|
||||
transition: border-color @animation-duration-slow, background @animation-duration-slow,
|
||||
padding @animation-duration-slow @ease-in-out;
|
||||
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
.@{iconfont-css-prefix} {
|
||||
min-width: 14px;
|
||||
margin-right: @menu-icon-margin-right;
|
||||
font-size: @menu-icon-size;
|
||||
transition: font-size 0.15s @ease-out, margin 0.3s @ease-in-out, color 0.3s;
|
||||
transition: font-size @menu-animation-duration-normal @ease-out,
|
||||
margin @animation-duration-slow @ease-in-out, color @animation-duration-slow;
|
||||
+ span {
|
||||
margin-left: @menu-icon-margin-right;
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s @ease-in-out, width 0.3s @ease-in-out, color 0.3s;
|
||||
// transition: opacity @animation-duration-slow @ease-in-out,
|
||||
// width @animation-duration-slow @ease-in-out, color @animation-duration-slow;
|
||||
transition: opacity @animation-duration-slow @ease-in-out, margin @animation-duration-slow,
|
||||
color @animation-duration-slow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,6 +224,10 @@
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
.accessibility-focus();
|
||||
}
|
||||
}
|
||||
|
||||
& > &-item-divider {
|
||||
@ -248,7 +273,7 @@
|
||||
background-color: @menu-bg;
|
||||
border-radius: @border-radius-base;
|
||||
&-submenu-title::after {
|
||||
transition: transform 0.3s @ease-in-out;
|
||||
transition: transform @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,10 +289,11 @@
|
||||
width: 10px;
|
||||
color: @menu-item-color;
|
||||
transform: translateY(-50%);
|
||||
transition: transform 0.3s @ease-in-out;
|
||||
transition: transform @animation-duration-slow @ease-in-out;
|
||||
}
|
||||
|
||||
&-arrow {
|
||||
// →
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
@ -275,8 +301,9 @@
|
||||
height: 1.5px;
|
||||
background-color: currentColor;
|
||||
border-radius: 2px;
|
||||
transition: background 0.3s @ease-in-out, transform 0.3s @ease-in-out, top 0.3s @ease-in-out,
|
||||
color 0.3s @ease-in-out;
|
||||
transition: background @animation-duration-slow @ease-in-out,
|
||||
transform @animation-duration-slow @ease-in-out, top @animation-duration-slow @ease-in-out,
|
||||
color @animation-duration-slow @ease-in-out;
|
||||
content: '';
|
||||
}
|
||||
&::before {
|
||||
@ -292,7 +319,9 @@
|
||||
color: @menu-highlight-color;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-inline-collapsed &-arrow,
|
||||
&-inline &-arrow {
|
||||
// ↓
|
||||
&::before {
|
||||
transform: rotate(-45deg) translateX(2.5px);
|
||||
}
|
||||
@ -306,6 +335,7 @@
|
||||
}
|
||||
|
||||
&-open&-inline > &-title > &-arrow {
|
||||
// ↑
|
||||
transform: translateY(-2px);
|
||||
&::after {
|
||||
transform: rotate(-45deg) translateX(-2.5px);
|
||||
@ -398,7 +428,8 @@
|
||||
border-right: @menu-item-active-border-width solid @menu-highlight-color;
|
||||
transform: scaleY(0.0001);
|
||||
opacity: 0;
|
||||
transition: transform 0.15s @ease-out, opacity 0.15s @ease-out;
|
||||
transition: transform @menu-animation-duration-normal @ease-out,
|
||||
opacity @menu-animation-duration-normal @ease-out;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
@ -444,7 +475,8 @@
|
||||
&::after {
|
||||
transform: scaleY(1);
|
||||
opacity: 1;
|
||||
transition: transform 0.15s @ease-in-out, opacity 0.15s @ease-in-out;
|
||||
transition: transform @menu-animation-duration-normal @ease-in-out,
|
||||
opacity @menu-animation-duration-normal @ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,12 +489,33 @@
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
padding-right: 34px;
|
||||
}
|
||||
|
||||
// Motion enhance for first level
|
||||
&.@{menu-prefix-cls}-root {
|
||||
.@{menu-prefix-cls}-item,
|
||||
.@{menu-prefix-cls}-submenu-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: border-color @animation-duration-slow, background @animation-duration-slow,
|
||||
padding 0.1s @ease-out;
|
||||
|
||||
> .@{menu-prefix-cls}-title-content {
|
||||
flex: auto;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
> * {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-inline-collapsed {
|
||||
&:not(.@{ant-prefix}-layout-sider-children > ul) {
|
||||
width: @menu-collapsed-width;
|
||||
}
|
||||
&&-inline-collapsed {
|
||||
width: @menu-collapsed-width;
|
||||
|
||||
> .@{menu-prefix-cls}-item,
|
||||
> .@{menu-prefix-cls}-item-group
|
||||
> .@{menu-prefix-cls}-item-group-list
|
||||
@ -475,8 +528,9 @@
|
||||
left: 0;
|
||||
padding: 0 ~'calc(50% - @{menu-icon-size-lg} / 2)';
|
||||
text-overflow: clip;
|
||||
|
||||
.@{menu-prefix-cls}-submenu-arrow {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.@{menu-prefix-cls}-item-icon,
|
||||
@ -486,7 +540,6 @@
|
||||
line-height: @menu-item-height;
|
||||
+ span {
|
||||
display: inline-block;
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import PageHeader from '..';
|
||||
import Breadcrumb from '../../breadcrumb';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
@ -50,6 +51,20 @@ describe('PageHeader', () => {
|
||||
expect(wrapper.find('.ant-page-header-back')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('pageHeader should have breadcrumb (component)', () => {
|
||||
const routes = [
|
||||
{
|
||||
path: 'index',
|
||||
breadcrumbName: 'First-level Menu',
|
||||
},
|
||||
];
|
||||
const wrapper = mount(
|
||||
<PageHeader title="Page Title" breadcrumb={<Breadcrumb routes={routes} />} />,
|
||||
);
|
||||
expect(wrapper.find('.ant-breadcrumb')).toHaveLength(1);
|
||||
expect(wrapper.find('.ant-page-header-back')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('pageHeader support breadcrumbRender', () => {
|
||||
const wrapper = mount(
|
||||
<PageHeader title="Page Title" breadcrumbRender={() => <div id="test">test</div>} />,
|
||||
|
@ -16,7 +16,7 @@ export interface PageHeaderProps {
|
||||
title?: React.ReactNode;
|
||||
subTitle?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
breadcrumb?: BreadcrumbProps;
|
||||
breadcrumb?: BreadcrumbProps | React.ReactElement<typeof Breadcrumb>;
|
||||
breadcrumbRender?: (props: PageHeaderProps, defaultDom: React.ReactNode) => React.ReactNode;
|
||||
tags?: React.ReactElement<TagType> | React.ReactElement<TagType>[];
|
||||
footer?: React.ReactNode;
|
||||
@ -156,10 +156,13 @@ const PageHeader: React.FC<PageHeaderProps> = props => {
|
||||
|
||||
const defaultBreadcrumbDom = getDefaultBreadcrumbDom();
|
||||
|
||||
const isBreadcrumbComponent = breadcrumb && 'props' in breadcrumb;
|
||||
// support breadcrumbRender function
|
||||
const breadcrumbDom =
|
||||
const breadcrumbRenderDomFromProps =
|
||||
breadcrumbRender?.(props, defaultBreadcrumbDom) || defaultBreadcrumbDom;
|
||||
|
||||
const breadcrumbDom = isBreadcrumbComponent ? breadcrumb : breadcrumbRenderDomFromProps;
|
||||
|
||||
const className = classNames(prefixCls, customizeClassName, {
|
||||
'has-breadcrumb': !!breadcrumbDom,
|
||||
'has-footer': !!footer,
|
||||
|
@ -192,4 +192,15 @@ describe('Radio Group', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should support data-* or aria-* props', () => {
|
||||
const wrapper = mount(
|
||||
createRadioGroup({
|
||||
'data-radio-group-id': 'radio-group-id',
|
||||
'aria-label': 'radio-group',
|
||||
}),
|
||||
);
|
||||
expect(wrapper.getDOMNode().getAttribute('data-radio-group-id')).toBe('radio-group-id');
|
||||
expect(wrapper.getDOMNode().getAttribute('aria-label')).toBe('radio-group');
|
||||
});
|
||||
});
|
||||
|
@ -6,6 +6,7 @@ import { RadioGroupProps, RadioChangeEvent, RadioGroupButtonStyle } from './inte
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import SizeContext from '../config-provider/SizeContext';
|
||||
import { RadioGroupContextProvider } from './context';
|
||||
import getDataOrAriaProps from '../_util/getDataOrAriaProps';
|
||||
|
||||
const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref) => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
@ -91,6 +92,7 @@ const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref
|
||||
);
|
||||
return (
|
||||
<div
|
||||
{...getDataOrAriaProps(props)}
|
||||
className={classString}
|
||||
style={style}
|
||||
onMouseEnter={onMouseEnter}
|
||||
|
@ -20,19 +20,23 @@ export default function Item({
|
||||
split,
|
||||
wrap,
|
||||
}: ItemProps) {
|
||||
const { horizontalSize, verticalSize, latestIndex } = React.useContext(SpaceContext);
|
||||
const { horizontalSize, verticalSize, latestIndex, supportFlexGap } = React.useContext(
|
||||
SpaceContext,
|
||||
);
|
||||
|
||||
let style: React.CSSProperties = {};
|
||||
|
||||
if (direction === 'vertical') {
|
||||
if (index < latestIndex) {
|
||||
style = { marginBottom: horizontalSize / (split ? 2 : 1) };
|
||||
if (!supportFlexGap) {
|
||||
if (direction === 'vertical') {
|
||||
if (index < latestIndex) {
|
||||
style = { marginBottom: horizontalSize / (split ? 2 : 1) };
|
||||
}
|
||||
} else {
|
||||
style = {
|
||||
...(index < latestIndex && { [marginDirection]: horizontalSize / (split ? 2 : 1) }),
|
||||
...(wrap && { paddingBottom: verticalSize }),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
style = {
|
||||
...(index < latestIndex && { [marginDirection]: horizontalSize / (split ? 2 : 1) }),
|
||||
...(wrap && { paddingBottom: verticalSize }),
|
||||
};
|
||||
}
|
||||
|
||||
if (children === null || children === undefined) {
|
||||
|
@ -408,6 +408,61 @@ exports[`renders ./components/space/demo/debug.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/space/demo/gap-in-line.md correctly 1`] = `
|
||||
Array [
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-switch-handle"
|
||||
/>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-space ant-space-horizontal ant-space-align-center"
|
||||
style="flex-wrap:wrap;margin-bottom:-8px;width:310px;background:blue"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-right:8px;padding-bottom:8px"
|
||||
>
|
||||
<div
|
||||
style="width:150px;height:100px;background:red"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-right:8px;padding-bottom:8px"
|
||||
>
|
||||
<div
|
||||
style="width:150px;height:100px;background:red"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-right:8px;padding-bottom:8px"
|
||||
>
|
||||
<div
|
||||
style="width:150px;height:100px;background:red"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="padding-bottom:8px"
|
||||
>
|
||||
<div
|
||||
style="width:150px;height:100px;background:red"
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/space/demo/size.md correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
|
24
components/space/__tests__/gap.test.js
Normal file
24
components/space/__tests__/gap.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Space from '..';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import * as styleChecker from '../../_util/styleChecker';
|
||||
|
||||
jest.mock('../../_util/styleChecker', () => ({
|
||||
canUseDocElement: () => true,
|
||||
isStyleSupport: () => true,
|
||||
detectFlexGapSupported: () => true,
|
||||
}));
|
||||
|
||||
describe('flex gap', () => {
|
||||
it('should render width empty children', () => {
|
||||
const wrapper = mount(
|
||||
<Space>
|
||||
<span />
|
||||
<span />
|
||||
</Space>,
|
||||
);
|
||||
expect(wrapper.getDOMNode().style['column-gap']).toBe('8px');
|
||||
expect(wrapper.getDOMNode().style['row-gap']).toBe('8px');
|
||||
});
|
||||
});
|
48
components/space/demo/gap-in-line.md
Normal file
48
components/space/demo/gap-in-line.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
order: 99
|
||||
title:
|
||||
zh-CN: Flex gap 样式
|
||||
en-US: Flex gap style
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
Debug usage
|
||||
|
||||
## en-US
|
||||
|
||||
Debug usage
|
||||
|
||||
```tsx
|
||||
import { Space, Switch } from 'antd';
|
||||
|
||||
const style: React.CSSProperties = {
|
||||
width: 150,
|
||||
height: 100,
|
||||
background: 'red',
|
||||
};
|
||||
|
||||
const Demo = () => {
|
||||
const [singleCol, setSingleCol] = React.useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Switch
|
||||
checked={singleCol}
|
||||
onChange={() => {
|
||||
setSingleCol(!singleCol);
|
||||
}}
|
||||
/>
|
||||
<Space style={{ width: singleCol ? 307 : 310, background: 'blue' }} size={[8, 8]} wrap>
|
||||
<div style={style} />
|
||||
<div style={style} />
|
||||
<div style={style} />
|
||||
<div style={style} />
|
||||
</Space>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
@ -4,11 +4,13 @@ import toArray from 'rc-util/lib/Children/toArray';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { SizeType } from '../config-provider/SizeContext';
|
||||
import Item from './Item';
|
||||
import useFlexGapSupport from '../_util/hooks/useFlexGapSupport';
|
||||
|
||||
export const SpaceContext = React.createContext({
|
||||
latestIndex: 0,
|
||||
horizontalSize: 0,
|
||||
verticalSize: 0,
|
||||
supportFlexGap: false,
|
||||
});
|
||||
|
||||
export type SpaceSize = SizeType | number;
|
||||
@ -51,6 +53,8 @@ const Space: React.FC<SpaceProps> = props => {
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const supportFlexGap = useFlexGapSupport();
|
||||
|
||||
const [horizontalSize, verticalSize] = React.useMemo(
|
||||
() =>
|
||||
((Array.isArray(size) ? size : [size, size]) as [SpaceSize, SpaceSize]).map(item =>
|
||||
@ -61,10 +65,6 @@ const Space: React.FC<SpaceProps> = props => {
|
||||
|
||||
const childNodes = toArray(children, { keepEmpty: true });
|
||||
|
||||
if (childNodes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align;
|
||||
const prefixCls = getPrefixCls('space', customizePrefixCls);
|
||||
const cn = classNames(
|
||||
@ -105,18 +105,33 @@ const Space: React.FC<SpaceProps> = props => {
|
||||
/* eslint-enable */
|
||||
});
|
||||
|
||||
const spaceContext = React.useMemo(
|
||||
() => ({ horizontalSize, verticalSize, latestIndex, supportFlexGap }),
|
||||
[horizontalSize, verticalSize, latestIndex, supportFlexGap],
|
||||
);
|
||||
|
||||
// =========================== Render ===========================
|
||||
if (childNodes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gapStyle: React.CSSProperties = {};
|
||||
if (supportFlexGap) {
|
||||
gapStyle.columnGap = horizontalSize;
|
||||
gapStyle.rowGap = verticalSize;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn}
|
||||
style={{
|
||||
...gapStyle,
|
||||
...(wrap && { flexWrap: 'wrap', marginBottom: -verticalSize }),
|
||||
...style,
|
||||
}}
|
||||
{...otherProps}
|
||||
>
|
||||
<SpaceContext.Provider value={{ horizontalSize, verticalSize, latestIndex }}>
|
||||
{nodes}
|
||||
</SpaceContext.Provider>
|
||||
<SpaceContext.Provider value={spaceContext}>{nodes}</SpaceContext.Provider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -9,6 +9,7 @@ interface CountdownProps extends StatisticProps {
|
||||
value?: countdownValueType;
|
||||
format?: string;
|
||||
onFinish?: () => void;
|
||||
onChange?: (value?: countdownValueType) => void;
|
||||
}
|
||||
|
||||
function getTime(value?: countdownValueType) {
|
||||
@ -48,8 +49,15 @@ class Countdown extends React.Component<CountdownProps, {}> {
|
||||
startTimer = () => {
|
||||
if (this.countdownId) return;
|
||||
|
||||
const { onChange, value } = this.props;
|
||||
const timestamp = getTime(value);
|
||||
|
||||
this.countdownId = window.setInterval(() => {
|
||||
this.forceUpdate();
|
||||
|
||||
if (onChange && timestamp > Date.now()) {
|
||||
onChange(timestamp - Date.now());
|
||||
}
|
||||
}, REFRESH_INTERVAL);
|
||||
};
|
||||
|
||||
|
@ -325,6 +325,29 @@ exports[`renders ./components/statistic/demo/countdown.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-12"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-statistic"
|
||||
>
|
||||
<div
|
||||
class="ant-statistic-title"
|
||||
>
|
||||
Countdown
|
||||
</div>
|
||||
<div
|
||||
class="ant-statistic-content"
|
||||
>
|
||||
<span
|
||||
class="ant-statistic-content-value"
|
||||
>
|
||||
00:00:10
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -116,6 +116,21 @@ describe('Statistic', () => {
|
||||
expect(onMouseLeave).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('time onchange', () => {
|
||||
it("called if time has't passed", async () => {
|
||||
const deadline = Date.now() + 10 * 1000;
|
||||
let remainingTime;
|
||||
|
||||
const onChange = value => {
|
||||
remainingTime = value;
|
||||
};
|
||||
const wrapper = mount(<Statistic.Countdown value={deadline} onChange={onChange} />);
|
||||
wrapper.update();
|
||||
await sleep(100)
|
||||
expect(remainingTime).toBeGreaterThan(0)
|
||||
});
|
||||
});
|
||||
|
||||
describe('time finished', () => {
|
||||
it('not call if time already passed', () => {
|
||||
const now = Date.now() - 1000;
|
||||
|
@ -23,6 +23,12 @@ function onFinish() {
|
||||
console.log('finished!');
|
||||
}
|
||||
|
||||
function onChange(val) {
|
||||
if (4.95 * 1000 < val && val < 5 * 1000) {
|
||||
console.log('changed!');
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
@ -34,6 +40,9 @@ ReactDOM.render(
|
||||
<Col span={24} style={{ marginTop: 32 }}>
|
||||
<Countdown title="Day Level" value={deadline} format="D 天 H 时 m 分 s 秒" />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Countdown title="Countdown" value={Date.now() + 10 * 1000} onChange={onChange} />
|
||||
</Col>
|
||||
</Row>,
|
||||
mountNode,
|
||||
);
|
||||
|
@ -40,3 +40,4 @@ Display statistic number.
|
||||
| value | Set target countdown time | number \| moment | - | |
|
||||
| valueStyle | Set value css style | CSSProperties | - | |
|
||||
| onFinish | Trigger when time's up | () => void | - | |
|
||||
| onChange | Trigger when time's changing | (value: number) => void | - | 4.16.0 |
|
||||
|
@ -41,3 +41,4 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/rcBNhLBrKbE/Statistic.svg
|
||||
| value | 数值内容 | number \| moment | - | |
|
||||
| valueStyle | 设置数值的样式 | CSSProperties | - | |
|
||||
| onFinish | 倒计时完成时触发 | () => void | - | |
|
||||
| onChange | 倒计时时间变化时触发 | (value: number) => void | - | 4.16.0 |
|
||||
|
@ -27,6 +27,7 @@ export interface SwitchProps {
|
||||
autoFocus?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
title?: string;
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
interface CompoundedComponent
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import Table from '..';
|
||||
import Input from '../../input';
|
||||
import Tooltip from '../../tooltip';
|
||||
@ -11,11 +12,12 @@ import ConfigProvider from '../../config-provider';
|
||||
// https://github.com/Semantic-Org/Semantic-UI-React/blob/72c45080e4f20b531fda2e3e430e384083d6766b/test/specs/modules/Dropdown/Dropdown-test.js#L73
|
||||
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => {} } };
|
||||
|
||||
function getDropdownWrapper(wrapper) {
|
||||
return mount(wrapper.find('Trigger').first().instance().getComponent());
|
||||
}
|
||||
|
||||
describe('Table.filter', () => {
|
||||
window.requestAnimationFrame = function (callback) {
|
||||
return window.setTimeout(callback, 16);
|
||||
};
|
||||
window.cancelAnimationFrame = window.clearTimeout;
|
||||
|
||||
const filterFn = (value, record) => record.name.indexOf(value) !== -1;
|
||||
const column = {
|
||||
title: 'Name',
|
||||
@ -96,6 +98,8 @@ describe('Table.filter', () => {
|
||||
});
|
||||
|
||||
it('renders empty menu correctly', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||
const wrapper = mount(
|
||||
createTable({
|
||||
@ -108,11 +112,18 @@ describe('Table.filter', () => {
|
||||
}),
|
||||
);
|
||||
wrapper.find('span.ant-dropdown-trigger').simulate('click', nativeEvent);
|
||||
expect(wrapper.find('Empty').length).toBe(1);
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
expect(wrapper.find('Empty').length).toBeTruthy();
|
||||
// eslint-disable-next-line no-console
|
||||
expect(console.error).not.toHaveBeenCalled();
|
||||
// eslint-disable-next-line no-console
|
||||
console.error.mockRestore();
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('renders radio filter correctly', () => {
|
||||
@ -548,24 +559,44 @@ describe('Table.filter', () => {
|
||||
// Open
|
||||
wrapper.find('.ant-table-filter-trigger').simulate('click');
|
||||
|
||||
let dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
function getFilterMenu() {
|
||||
return wrapper.find('FilterDropdown');
|
||||
}
|
||||
|
||||
// Seems raf not trigger when in useEffect for async update
|
||||
// Need trigger multiple times
|
||||
function refreshTimer() {
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Open Level2
|
||||
getFilterMenu().find('div.ant-dropdown-menu-submenu-title').at(0).simulate('mouseEnter');
|
||||
refreshTimer();
|
||||
|
||||
// Open Level3
|
||||
getFilterMenu().find('div.ant-dropdown-menu-submenu-title').at(1).simulate('mouseEnter');
|
||||
refreshTimer();
|
||||
|
||||
// Select Level3 value
|
||||
getFilterMenu().find('li.ant-dropdown-menu-item').last().simulate('click');
|
||||
getFilterMenu().find('.ant-table-filter-dropdown-btns .ant-btn-primary').simulate('click');
|
||||
refreshTimer();
|
||||
|
||||
// select
|
||||
dropdownWrapper.find('.ant-dropdown-menu-submenu-title').at(0).simulate('mouseEnter');
|
||||
jest.runAllTimers();
|
||||
dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
dropdownWrapper.find('.ant-dropdown-menu-submenu-title').at(1).simulate('mouseEnter');
|
||||
jest.runAllTimers();
|
||||
dropdownWrapper = getDropdownWrapper(wrapper);
|
||||
dropdownWrapper.find('MenuItem').last().simulate('click');
|
||||
dropdownWrapper.find('.ant-table-filter-dropdown-btns .ant-btn-primary').simulate('click');
|
||||
onChange.mock.calls.forEach(([, currentFilters]) => {
|
||||
const [, val] = Object.entries(currentFilters)[0];
|
||||
expect(val).toEqual(['Jack']);
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
expect(renderedNames(wrapper)).toEqual(['Jack']);
|
||||
dropdownWrapper.find('MenuItem').last().simulate('click');
|
||||
|
||||
// What's this? Is that a coverage case?
|
||||
getFilterMenu().find('li.ant-dropdown-menu-item').last().simulate('click');
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mount, render } from 'enzyme';
|
||||
import Table from '..';
|
||||
import Checkbox from '../../checkbox';
|
||||
@ -6,6 +7,9 @@ import { resetWarned } from '../../_util/devWarning';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
|
||||
describe('Table.rowSelection', () => {
|
||||
window.requestAnimationFrame = callback => window.setTimeout(callback, 16);
|
||||
window.cancelAnimationFrame = window.clearTimeout;
|
||||
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
afterEach(() => {
|
||||
@ -335,6 +339,8 @@ describe('Table.rowSelection', () => {
|
||||
});
|
||||
|
||||
it('fires selectInvert event', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const order = [];
|
||||
const handleSelectInvert = jest.fn().mockImplementation(() => {
|
||||
order.push('onSelectInvert');
|
||||
@ -353,14 +359,24 @@ describe('Table.rowSelection', () => {
|
||||
checkboxes.at(1).simulate('change', { target: { checked: true } });
|
||||
|
||||
// Open
|
||||
wrapper.find('Trigger').setState({ popupVisible: true });
|
||||
wrapper.find('span.ant-dropdown-trigger').simulate('mouseEnter');
|
||||
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').first().instance().getComponent());
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item').at(1).simulate('click');
|
||||
// enzyme has bug for state sync.
|
||||
// Let fresh multiple times to force sync back.
|
||||
for (let i = 0; i < 3; i += 1) {
|
||||
act(() => {
|
||||
jest.runAllTimers();
|
||||
wrapper.update();
|
||||
});
|
||||
}
|
||||
|
||||
wrapper.find('li.ant-dropdown-menu-item').at(1).simulate('click');
|
||||
|
||||
expect(handleSelectInvert).toHaveBeenCalledWith([1, 2, 3]);
|
||||
|
||||
expect(order).toEqual(['onChange', 'onSelectInvert', 'onChange']);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('fires selectNone event', () => {
|
||||
@ -416,12 +432,12 @@ describe('Table.rowSelection', () => {
|
||||
wrapper.find('Trigger').setState({ popupVisible: true });
|
||||
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').first().instance().getComponent());
|
||||
expect(dropdownWrapper.find('.ant-dropdown-menu-item').length).toBe(4);
|
||||
expect(dropdownWrapper.find('li.ant-dropdown-menu-item').length).toBe(4);
|
||||
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item').at(2).simulate('click');
|
||||
dropdownWrapper.find('li.ant-dropdown-menu-item').at(2).simulate('click');
|
||||
expect(handleSelectOdd).toHaveBeenCalledWith([0, 1, 2, 3]);
|
||||
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item').at(3).simulate('click');
|
||||
dropdownWrapper.find('li.ant-dropdown-menu-item').at(3).simulate('click');
|
||||
expect(handleSelectEven).toHaveBeenCalledWith([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
@ -456,12 +472,12 @@ describe('Table.rowSelection', () => {
|
||||
wrapper.find('Trigger').setState({ popupVisible: true });
|
||||
|
||||
const dropdownWrapper = mount(wrapper.find('Trigger').first().instance().getComponent());
|
||||
expect(dropdownWrapper.find('.ant-dropdown-menu-item').length).toBe(2);
|
||||
expect(dropdownWrapper.find('li.ant-dropdown-menu-item').length).toBe(2);
|
||||
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item').at(0).simulate('click');
|
||||
dropdownWrapper.find('li.ant-dropdown-menu-item').at(0).simulate('click');
|
||||
expect(handleSelectOdd).toHaveBeenCalledWith([0, 1, 2, 3]);
|
||||
|
||||
dropdownWrapper.find('.ant-dropdown-menu-item').at(1).simulate('click');
|
||||
dropdownWrapper.find('li.ant-dropdown-menu-item').at(1).simulate('click');
|
||||
expect(handleSelectEven).toHaveBeenCalledWith([0, 1, 2, 3]);
|
||||
});
|
||||
|
||||
|
@ -601,12 +601,16 @@ exports[`Table.filter should support getPopupContainer 1`] = `
|
||||
class="ant-table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-boy"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
@ -630,7 +634,9 @@ exports[`Table.filter should support getPopupContainer 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-girl"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
@ -654,13 +660,16 @@ exports[`Table.filter should support getPopupContainer 1`] = `
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-controls="rc-menu-uuid-test-title-popup"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
data-menu-id="rc-menu-uuid-test-title"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Title"
|
||||
>
|
||||
Title
|
||||
@ -833,12 +842,16 @@ exports[`Table.filter should support getPopupContainer from ConfigProvider 1`] =
|
||||
class="ant-table-filter-dropdown"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-boy"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
@ -862,7 +875,9 @@ exports[`Table.filter should support getPopupContainer from ConfigProvider 1`] =
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-item"
|
||||
data-menu-id="rc-menu-uuid-test-girl"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
@ -886,13 +901,16 @@ exports[`Table.filter should support getPopupContainer from ConfigProvider 1`] =
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-submenu ant-dropdown-menu-submenu-vertical"
|
||||
role="menuitem"
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
aria-controls="rc-menu-uuid-test-title-popup"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-dropdown-menu-submenu-title"
|
||||
role="button"
|
||||
data-menu-id="rc-menu-uuid-test-title"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
title="Title"
|
||||
>
|
||||
Title
|
||||
|
@ -1051,25 +1051,32 @@ exports[`Table.rowSelection should support getPopupContainer 1`] = `
|
||||
style="opacity: 0; pointer-events: none;"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-all"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
Select all data
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-invert"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
Invert current page
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-none"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
Clear all data
|
||||
</li>
|
||||
@ -1384,25 +1391,32 @@ exports[`Table.rowSelection should support getPopupContainer from ConfigProvider
|
||||
style="opacity: 0; pointer-events: none;"
|
||||
>
|
||||
<ul
|
||||
class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical"
|
||||
class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-vertical ant-dropdown-menu-light"
|
||||
data-menu-list="true"
|
||||
role="menu"
|
||||
tabindex="0"
|
||||
>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-all"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
Select all data
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-invert"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
Invert current page
|
||||
</li>
|
||||
<li
|
||||
class="ant-dropdown-menu-item ant-dropdown-menu-item-only-child"
|
||||
data-menu-id="rc-menu-uuid-test-none"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
Clear all data
|
||||
</li>
|
||||
|
@ -15882,7 +15882,7 @@ exports[`renders ./components/table/demo/sticky.md correctly 1`] = `
|
||||
class="ant-table-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table-header ant-table-sticky-header"
|
||||
class="ant-table-header ant-table-sticky-holder"
|
||||
style="overflow:hidden;top:0"
|
||||
>
|
||||
<table
|
||||
@ -16756,6 +16756,41 @@ exports[`renders ./components/table/demo/sticky.md correctly 1`] = `
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div
|
||||
class="ant-table-summary ant-table-sticky-holder"
|
||||
style="overflow:hidden;bottom:0"
|
||||
>
|
||||
<table
|
||||
style="table-layout:fixed;visibility:hidden"
|
||||
>
|
||||
<colgroup />
|
||||
<tfoot
|
||||
class="ant-table-summary"
|
||||
>
|
||||
<tr>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-left ant-table-cell-fix-left-last ant-table-cell-fix-sticky"
|
||||
colspan="2"
|
||||
style="position:sticky;left:0"
|
||||
>
|
||||
Fix Left
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
colspan="8"
|
||||
>
|
||||
Scroll Context
|
||||
</td>
|
||||
<td
|
||||
class="ant-table-cell ant-table-cell-fix-right ant-table-cell-fix-right-first ant-table-cell-fix-sticky"
|
||||
style="position:sticky;right:0"
|
||||
>
|
||||
Fix Right
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
|
@ -94,7 +94,25 @@ for (let i = 0; i < 100; i++) {
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<Table columns={columns} dataSource={data} scroll={{ x: 1500 }} sticky />,
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
scroll={{ x: 1500 }}
|
||||
summary={pageData => (
|
||||
<Table.Summary fixed>
|
||||
<Table.Summary.Row>
|
||||
<Table.Summary.Cell index={0} colSpan={2}>
|
||||
Fix Left
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={2} colSpan={8}>
|
||||
Scroll Context
|
||||
</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={10}>Fix Right</Table.Summary.Cell>
|
||||
</Table.Summary.Row>
|
||||
</Table.Summary>
|
||||
)}
|
||||
sticky
|
||||
/>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
@ -37,19 +37,21 @@ function renderFilterItems({
|
||||
// wrapped with <div /> to avoid react warning
|
||||
// https://github.com/ant-design/ant-design/issues/25979
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
margin: '16px 0',
|
||||
}}
|
||||
>
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description={locale.filterEmptyText}
|
||||
imageStyle={{
|
||||
height: 24,
|
||||
<MenuItem key="empty">
|
||||
<div
|
||||
style={{
|
||||
margin: '16px 0',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
>
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description={locale.filterEmptyText}
|
||||
imageStyle={{
|
||||
height: 24,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
return filters.map((filter, index) => {
|
||||
|
@ -148,9 +148,9 @@ One of the Table `columns` prop for describing the table's columns, Column has t
|
||||
|
||||
### ColumnGroup
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| title | Title of the column group | ReactNode | - |
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ------------------------- | --------- | ------- |
|
||||
| title | Title of the column group | ReactNode | - |
|
||||
|
||||
### pagination
|
||||
|
||||
@ -166,22 +166,27 @@ More about pagination, please check [`Pagination`](/components/pagination/).
|
||||
|
||||
Properties for expandable.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| childrenColumnName | The column contains children to display | string | children |
|
||||
| columnWidth | Set the width of the expand column | string \| number | - |
|
||||
| defaultExpandAllRows | Expand all rows initially | boolean | false |
|
||||
| defaultExpandedRowKeys | Initial expanded row keys | string\[] | - |
|
||||
| expandedRowClassName | Expanded row's className | function(record, index, indent): string | - |
|
||||
| expandedRowKeys | Current expanded row keys | string\[] | - |
|
||||
| expandedRowRender | Expanded container render for each row | function(record, index, indent, expanded): ReactNode | - |
|
||||
| expandIcon | Customize row expand Icon. Ref [example](https://codesandbox.io/s/fervent-bird-nuzpr) | function(props): ReactNode | - |
|
||||
| expandIconColumnIndex | Customize expand icon column index. Not render when `-1` | number | - |
|
||||
| expandRowByClick | Whether to expand row by clicking anywhere in the whole row | boolean | false |
|
||||
| indentSize | Indent size in pixels of tree data | number | 15 |
|
||||
| rowExpandable | Enable row can be expandable | (record) => boolean | - |
|
||||
| onExpand | Callback executed when the row expand icon is clicked | function(expanded, record) | - |
|
||||
| onExpandedRowsChange | Callback executed when the expanded rows change | function(expandedRows) | - |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| childrenColumnName | The column contains children to display | string | children | |
|
||||
| columnWidth | Set the width of the expand column | string \| number | - | |
|
||||
| defaultExpandAllRows | Expand all rows initially | boolean | false | |
|
||||
| defaultExpandedRowKeys | Initial expanded row keys | string\[] | - | |
|
||||
| expandedRowClassName | Expanded row's className | function(record, index, indent): string | - | |
|
||||
| expandedRowKeys | Current expanded row keys | string\[] | - | |
|
||||
| expandedRowRender | Expanded container render for each row | function(record, index, indent, expanded): ReactNode | - | |
|
||||
| expandIcon | Customize row expand Icon. Ref [example](https://codesandbox.io/s/fervent-bird-nuzpr) | function(props): ReactNode | - | |
|
||||
| expandIconColumnIndex | Customize expand icon column index. Not render when `-1` | number | - | |
|
||||
| expandRowByClick | Whether to expand row by clicking anywhere in the whole row | boolean | false | |
|
||||
| fixed | Whether the expansion icon is fixed. Optional true `left` `right` | boolean \| string | false | 4.16.0 |
|
||||
| indentSize | Indent size in pixels of tree data | number | 15 | |
|
||||
| rowExpandable | Enable row can be expandable | (record) => boolean | - | |
|
||||
| onExpand | Callback executed when the row expand icon is clicked | function(expanded, record) | - | |
|
||||
| onExpandedRowsChange | Callback executed when the expanded rows change | function(expandedRows) | - | |
|
||||
|
||||
- `fixed`
|
||||
- When set to true or `left` and `expandIconColumnIndex` is not set or is 0, enable fixed
|
||||
- When set to true or `right` and `expandIconColumnIndex` is set to the number of table columns, enable fixed
|
||||
|
||||
### rowSelection
|
||||
|
||||
|
@ -173,22 +173,27 @@ const columns = [
|
||||
|
||||
展开功能的配置。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| childrenColumnName | 指定树形结构的列名 | string | children |
|
||||
| columnWidth | 自定义展开列宽度 | string \| number | - |
|
||||
| defaultExpandAllRows | 初始时,是否展开所有行 | boolean | false |
|
||||
| defaultExpandedRowKeys | 默认展开的行 | string\[] | - |
|
||||
| expandedRowClassName | 展开行的 className | function(record, index, indent): string | - |
|
||||
| expandedRowKeys | 展开的行,控制属性 | string\[] | - |
|
||||
| expandedRowRender | 额外的展开行 | function(record, index, indent, expanded): ReactNode | - |
|
||||
| expandIcon | 自定义展开图标,参考[示例](https://codesandbox.io/s/fervent-bird-nuzpr) | function(props): ReactNode | - |
|
||||
| expandIconColumnIndex | 自定义展开按钮的列顺序,`-1` 时不展示 | number | - |
|
||||
| expandRowByClick | 通过点击行来展开子行 | boolean | false |
|
||||
| indentSize | 展示树形数据时,每层缩进的宽度,以 px 为单位 | number | 15 |
|
||||
| rowExpandable | 设置是否允许行展开 | (record) => boolean | - |
|
||||
| onExpand | 点击展开图标时触发 | function(expanded, record) | - |
|
||||
| onExpandedRowsChange | 展开的行变化时触发 | function(expandedRows) | - |
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| childrenColumnName | 指定树形结构的列名 | string | children | |
|
||||
| columnWidth | 自定义展开列宽度 | string \| number | - | |
|
||||
| defaultExpandAllRows | 初始时,是否展开所有行 | boolean | false | |
|
||||
| defaultExpandedRowKeys | 默认展开的行 | string\[] | - | |
|
||||
| expandedRowClassName | 展开行的 className | function(record, index, indent): string | - | |
|
||||
| expandedRowKeys | 展开的行,控制属性 | string\[] | - | |
|
||||
| expandedRowRender | 额外的展开行 | function(record, index, indent, expanded): ReactNode | - | |
|
||||
| expandIcon | 自定义展开图标,参考[示例](https://codesandbox.io/s/fervent-bird-nuzpr) | function(props): ReactNode | - | |
|
||||
| expandIconColumnIndex | 自定义展开按钮的列顺序,`-1` 时不展示 | number | - | |
|
||||
| expandRowByClick | 通过点击行来展开子行 | boolean | false | |
|
||||
| fixed | 控制展开图标是否固定,可选 true `left` `right` | boolean \| string | false | 4.16.0 |
|
||||
| indentSize | 展示树形数据时,每层缩进的宽度,以 px 为单位 | number | 15 | |
|
||||
| rowExpandable | 设置是否允许行展开 | (record) => boolean | - | |
|
||||
| onExpand | 点击展开图标时触发 | function(expanded, record) | - | |
|
||||
| onExpandedRowsChange | 展开的行变化时触发 | function(expandedRows) | - | |
|
||||
|
||||
- `fixed`
|
||||
- 当设置为 true 或 `left` 且 `expandIconColumnIndex` 未设置或为 0 时,开启固定
|
||||
- 当设置为 true 或 `right` 且 `expandIconColumnIndex` 设置为表格列数时,开启固定
|
||||
|
||||
### rowSelection
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
@table-header-icon-color: #bfbfbf;
|
||||
@table-header-icon-color-hover: darken(@table-header-icon-color, 10%);
|
||||
@table-header-sort-active-filter-bg: lighten(@table-header-sort-active-bg, 2%);
|
||||
@table-sticky-zindex: calc(@zindex-table-fixed + 1);
|
||||
@table-sticky-zindex: (@zindex-table-fixed + 1);
|
||||
@table-sticky-scroll-bar-active-bg: fade(@table-sticky-scroll-bar-bg, 80%);
|
||||
|
||||
.@{table-prefix-cls}-wrapper {
|
||||
@ -147,7 +147,13 @@
|
||||
}
|
||||
|
||||
// =========================== Summary ============================
|
||||
tfoot {
|
||||
&-summary {
|
||||
background: @table-bg;
|
||||
|
||||
div& {
|
||||
box-shadow: 0 -@border-width-base 0 @table-border-color;
|
||||
}
|
||||
|
||||
> tr {
|
||||
> th,
|
||||
> td {
|
||||
@ -622,7 +628,7 @@
|
||||
}
|
||||
}
|
||||
&-sticky {
|
||||
&-header {
|
||||
&-holder {
|
||||
position: sticky;
|
||||
z-index: @table-sticky-zindex;
|
||||
}
|
||||
|
@ -111,6 +111,242 @@ exports[`Tabs rtl render component should be rendered correctly in RTL direction
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Tabs tabBarGutter should work 1`] = `
|
||||
<div
|
||||
class="ant-tabs ant-tabs-top"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-wrap"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-list"
|
||||
style="transform:translate(0px, 0px)"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-tab ant-tabs-tab-active"
|
||||
style="margin-left:0"
|
||||
>
|
||||
<div
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-btn"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-tab ant-tabs-tab-active"
|
||||
style="margin-left:0"
|
||||
>
|
||||
<div
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-btn"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-tab ant-tabs-tab-active"
|
||||
style="margin-left:0"
|
||||
>
|
||||
<div
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-btn"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-nav-operations ant-tabs-nav-operations-hidden"
|
||||
>
|
||||
<button
|
||||
aria-controls="null-more-popup"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-nav-more"
|
||||
id="null-more"
|
||||
style="margin-left:0;visibility:hidden;order:1"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="ellipsis"
|
||||
class="anticon anticon-ellipsis"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="ellipsis"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-content-holder"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-top"
|
||||
>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Tabs tabBarGutter should work 2`] = `
|
||||
<div
|
||||
class="ant-tabs ant-tabs-left"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-wrap"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-nav-list"
|
||||
style="transform:translate(0px, 0px)"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-tab ant-tabs-tab-active"
|
||||
style="margin-top:0"
|
||||
>
|
||||
<div
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-btn"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-tab ant-tabs-tab-active"
|
||||
style="margin-top:0"
|
||||
>
|
||||
<div
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-btn"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-tab ant-tabs-tab-active"
|
||||
style="margin-top:0"
|
||||
>
|
||||
<div
|
||||
aria-selected="true"
|
||||
class="ant-tabs-tab-btn"
|
||||
role="tab"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-ink-bar ant-tabs-ink-bar-animated"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-nav-operations ant-tabs-nav-operations-hidden"
|
||||
>
|
||||
<button
|
||||
aria-controls="null-more-popup"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-hidden="true"
|
||||
class="ant-tabs-nav-more"
|
||||
id="null-more"
|
||||
style="margin-left:0;visibility:hidden;order:1"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="ellipsis"
|
||||
class="anticon anticon-ellipsis"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="ellipsis"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-tabs-content-holder"
|
||||
>
|
||||
<div
|
||||
class="ant-tabs-content ant-tabs-content-left"
|
||||
>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-hidden="false"
|
||||
class="ant-tabs-tabpane ant-tabs-tabpane-active"
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Tabs tabPosition remove card 1`] = `
|
||||
<div
|
||||
class="ant-tabs ant-tabs-left"
|
||||
|
@ -85,4 +85,11 @@ describe('Tabs', () => {
|
||||
);
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('tabBarGutter should work', () => {
|
||||
const wrapper = mount(<Tabs tabBarGutter={0}><TabPane /><TabPane /><TabPane /></Tabs>);
|
||||
expect(wrapper).toMatchRenderedSnapshot();
|
||||
const wrapper2 = mount(<Tabs tabBarGutter={0} tabPosition="left"><TabPane /><TabPane /><TabPane /></Tabs>);
|
||||
expect(wrapper2).toMatchRenderedSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -2,6 +2,7 @@ import { TimePickerLocale } from '../index';
|
||||
|
||||
const locale: TimePickerLocale = {
|
||||
placeholder: 'Selecteer tijd',
|
||||
rangePlaceholder: ['Start tijd', 'Eind tijd'],
|
||||
};
|
||||
|
||||
export default locale;
|
||||
|
@ -2,6 +2,7 @@ import { TimePickerLocale } from '../index';
|
||||
|
||||
const locale: TimePickerLocale = {
|
||||
placeholder: 'Selecteer tijd',
|
||||
rangePlaceholder: ['Start tijd', 'Eind tijd'],
|
||||
};
|
||||
|
||||
export default locale;
|
||||
|
@ -67,10 +67,11 @@ export interface BlockProps extends TypographyProps {
|
||||
delete?: boolean;
|
||||
strong?: boolean;
|
||||
keyboard?: boolean;
|
||||
italic?: boolean;
|
||||
}
|
||||
|
||||
function wrapperDecorations(
|
||||
{ mark, code, underline, delete: del, strong, keyboard }: BlockProps,
|
||||
{ mark, code, underline, delete: del, strong, keyboard, italic }: BlockProps,
|
||||
content: React.ReactNode,
|
||||
) {
|
||||
let currentContent = content;
|
||||
@ -87,6 +88,7 @@ function wrapperDecorations(
|
||||
wrap(code, 'code');
|
||||
wrap(mark, 'mark');
|
||||
wrap(keyboard, 'kbd');
|
||||
wrap(italic, 'i');
|
||||
|
||||
return currentContent;
|
||||
}
|
||||
|
@ -997,6 +997,18 @@ exports[`renders ./components/typography/demo/text.md correctly 1`] = `
|
||||
</strong>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-bottom:8px"
|
||||
>
|
||||
<span
|
||||
class="ant-typography"
|
||||
>
|
||||
<i>
|
||||
Ant Design (italic)
|
||||
</i>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
|
@ -32,6 +32,7 @@ ReactDOM.render(
|
||||
<Text underline>Ant Design (underline)</Text>
|
||||
<Text delete>Ant Design (delete)</Text>
|
||||
<Text strong>Ant Design (strong)</Text>
|
||||
<Text italic>Ant Design (italic)</Text>
|
||||
<Link href="https://ant.design" target="_blank">
|
||||
Ant Design (Link)
|
||||
</Link>
|
||||
|
@ -29,6 +29,7 @@ Basic text writing, including headings, body text, lists, and more.
|
||||
| mark | Marked style | boolean | false | |
|
||||
| onClick | Set the handler to handle click event | (event) => void | - | |
|
||||
| strong | Bold style | boolean | false | |
|
||||
| italic | Italic style | boolean | false | 4.16.0 |
|
||||
| type | Content type | `secondary` \| `success` \| `warning` \| `danger` | - | success: 4.6.0 |
|
||||
| underline | Underlined style | boolean | false | |
|
||||
|
||||
@ -45,6 +46,7 @@ Basic text writing, including headings, body text, lists, and more.
|
||||
| level | Set content importance. Match with `h1`, `h2`, `h3`, `h4`, `h5` | number: 1, 2, 3, 4, 5 | 1 | 5: 4.6.0 |
|
||||
| mark | Marked style | boolean | false | |
|
||||
| onClick | Set the handler to handle click event | (event) => void | - | |
|
||||
| italic | Italic style | boolean | false | 4.16.0 |
|
||||
| type | Content type | `secondary` \| `success` \| `warning` \| `danger` | - | success: 4.6.0 |
|
||||
| underline | Underlined style | boolean | false | |
|
||||
|
||||
@ -61,6 +63,7 @@ Basic text writing, including headings, body text, lists, and more.
|
||||
| mark | Marked style | boolean | false | |
|
||||
| onClick | Set the handler to handle click event | (event) => void | - | |
|
||||
| strong | Bold style | boolean | false | |
|
||||
| italic | Italic style | boolean | false | 4.16.0 |
|
||||
| type | Content type | `secondary` \| `success` \| `warning` \| `danger` | - | success: 4.6.0 |
|
||||
| underline | Underlined style | boolean | false | |
|
||||
|
||||
|
@ -30,6 +30,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
||||
| mark | 添加标记样式 | boolean | false | |
|
||||
| onClick | 点击 Text 时的回调 | (event) => void | - | |
|
||||
| strong | 是否加粗 | boolean | false | |
|
||||
| italic | 是否斜体 | boolean | false | 4.16.0 |
|
||||
| type | 文本类型 | `secondary` \| `success` \| `warning` \| `danger` | - | success: 4.6.0 |
|
||||
| underline | 添加下划线样式 | boolean | false | |
|
||||
|
||||
@ -46,6 +47,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
||||
| level | 重要程度,相当于 `h1`、`h2`、`h3`、`h4`、`h5` | number: 1, 2, 3, 4, 5 | 1 | 5: 4.6.0 |
|
||||
| mark | 添加标记样式 | boolean | false | |
|
||||
| onClick | 点击 Title 时的回调 | (event) => void | - | |
|
||||
| italic | 是否斜体 | boolean | false | 4.16.0 |
|
||||
| type | 文本类型 | `secondary` \| `success` \| `warning` \| `danger` | - | success: 4.6.0 |
|
||||
| underline | 添加下划线样式 | boolean | false | |
|
||||
|
||||
@ -62,6 +64,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
||||
| mark | 添加标记样式 | boolean | false | |
|
||||
| onClick | 点击 Paragraph 时的回调 | (event) => void | - | |
|
||||
| strong | 是否加粗 | boolean | false | |
|
||||
| italic | 是否斜体 | boolean | false | 4.16.0 |
|
||||
| type | 文本类型 | `secondary` \| `success` \| `warning` \| `danger` | - | success: 4.6.0 |
|
||||
| underline | 添加下划线样式 | boolean | false | |
|
||||
|
||||
|
@ -34,6 +34,7 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
|
||||
onPreview,
|
||||
onDownload,
|
||||
onChange,
|
||||
onDrop,
|
||||
previewFile,
|
||||
disabled,
|
||||
locale: propLocale,
|
||||
@ -278,8 +279,11 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
|
||||
};
|
||||
|
||||
const onFileDrop = (e: React.DragEvent<HTMLDivElement>) => {
|
||||
e.stopPropagation();
|
||||
setDragState(e.type);
|
||||
|
||||
if (e.type === 'drop') {
|
||||
onDrop?.(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Test needs
|
||||
|
@ -272,7 +272,13 @@ const ListItem = React.forwardRef(
|
||||
|
||||
return (
|
||||
<div className={listContainerNameClass} style={style} ref={ref}>
|
||||
{itemRender ? itemRender(item, file, items) : item}
|
||||
{itemRender
|
||||
? itemRender(item, file, items, {
|
||||
download: onDownload.bind(null, file),
|
||||
preview: onPreview.bind(null, file),
|
||||
remove: onClose.bind(null, file),
|
||||
})
|
||||
: item}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@ -80,11 +80,11 @@ const InternalUploadList: React.ForwardRefRenderFunction<unknown, UploadListProp
|
||||
}, []);
|
||||
|
||||
// ============================= Events =============================
|
||||
const onInternalPreview = (file: UploadFile, e: React.SyntheticEvent<HTMLElement>) => {
|
||||
const onInternalPreview = (file: UploadFile, e?: React.SyntheticEvent<HTMLElement>) => {
|
||||
if (!onPreview) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
e?.preventDefault();
|
||||
return onPreview(file);
|
||||
};
|
||||
|
||||
|
@ -114,20 +114,54 @@ exports[`Upload List itemRender 1`] = `
|
||||
<div
|
||||
class="ant-upload-list-text-container"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
class="custom-item-render"
|
||||
>
|
||||
uid:-1 name: xxx.png status: removed url: https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png 1/2
|
||||
</span>
|
||||
<span>
|
||||
uid:-1 name: xxx.png status: removed url: https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png 1/2
|
||||
</span>
|
||||
<span
|
||||
class="custom-item-render-action-remove"
|
||||
>
|
||||
remove
|
||||
</span>
|
||||
<span
|
||||
class="custom-item-render-action-download"
|
||||
>
|
||||
download
|
||||
</span>
|
||||
<span
|
||||
class="custom-item-render-action-preview"
|
||||
>
|
||||
preview
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-upload-list-text-container"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
class="custom-item-render"
|
||||
>
|
||||
uid:-2 name: yyy.png status: removed url: https://zos.alipayobjects.com/rmsportal/IQKRngzUuFzJzGzRJXUs.png 2/2
|
||||
</span>
|
||||
<span>
|
||||
uid:-2 name: yyy.png status: removed url: https://zos.alipayobjects.com/rmsportal/IQKRngzUuFzJzGzRJXUs.png 2/2
|
||||
</span>
|
||||
<span
|
||||
class="custom-item-render-action-remove"
|
||||
>
|
||||
remove
|
||||
</span>
|
||||
<span
|
||||
class="custom-item-render-action-download"
|
||||
>
|
||||
download
|
||||
</span>
|
||||
<span
|
||||
class="custom-item-render-action-preview"
|
||||
>
|
||||
preview
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -35,4 +35,21 @@ describe('Upload.Dragger', () => {
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('support onDrop when files are dropped onto upload area', () => {
|
||||
const onDrop = jest.fn();
|
||||
const wrapper = mount(
|
||||
<Upload.Dragger onDrop={onDrop}>
|
||||
<div />
|
||||
</Upload.Dragger>,
|
||||
);
|
||||
|
||||
wrapper.find('.ant-upload-drag-container').simulate('drop', {
|
||||
dataTransfer: {
|
||||
files: [new File(['foo'], 'foo.png', { type: 'image/png' })],
|
||||
},
|
||||
});
|
||||
|
||||
expect(onDrop).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -100,7 +100,24 @@ describe('Upload.typescript', () => {
|
||||
},
|
||||
];
|
||||
const upload = (
|
||||
<Upload fileList={fileList} defaultFileList={fileList}>
|
||||
<Upload fileList={fileList} defaultFileList={fileList} />
|
||||
)
|
||||
expect(upload).toBeTruthy();
|
||||
});
|
||||
it('itemRender', () => {
|
||||
const upload = (
|
||||
<Upload
|
||||
itemRender={(node, file, list, actions) => (
|
||||
<div>
|
||||
{node}
|
||||
{file.name}
|
||||
{list.length}
|
||||
<span onClick={actions.remove}>remove</span>
|
||||
<span onClick={actions.download}>download</span>
|
||||
<span onClick={actions.preview}>preview</span>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<span>click to upload</span>
|
||||
</Upload>
|
||||
);
|
||||
|
@ -1162,20 +1162,52 @@ describe('Upload List', () => {
|
||||
});
|
||||
|
||||
it('itemRender', () => {
|
||||
const itemRender = (originNode, file, currFileList) => {
|
||||
const onDownload = jest.fn();
|
||||
const onRemove = jest.fn();
|
||||
const onPreview = jest.fn();
|
||||
const itemRender = (originNode, file, currFileList, actions) => {
|
||||
const { name, status, uid, url } = file;
|
||||
const index = currFileList.indexOf(file);
|
||||
return (
|
||||
<span className="custom-item-render">
|
||||
{`uid:${uid} name: ${name} status: ${status} url: ${url} ${index + 1}/${
|
||||
currFileList.length
|
||||
}`}
|
||||
</span>
|
||||
<div className="custom-item-render">
|
||||
<span>
|
||||
{`uid:${uid} name: ${name} status: ${status} url: ${url} ${index + 1}/${
|
||||
currFileList.length
|
||||
}`}
|
||||
</span>
|
||||
<span onClick={actions.remove} className="custom-item-render-action-remove">
|
||||
remove
|
||||
</span>
|
||||
<span onClick={actions.download} className="custom-item-render-action-download">
|
||||
download
|
||||
</span>
|
||||
<span onClick={actions.preview} className="custom-item-render-action-preview">
|
||||
preview
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const wrapper = mount(<UploadList locale={{}} items={fileList} itemRender={itemRender} />);
|
||||
const wrapper = mount(
|
||||
<UploadList
|
||||
onDownload={onDownload}
|
||||
onPreview={onPreview}
|
||||
onRemove={onRemove}
|
||||
locale={{}}
|
||||
items={fileList}
|
||||
itemRender={itemRender}
|
||||
/>,
|
||||
);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
|
||||
wrapper.find('.custom-item-render-action-remove').first().simulate('click');
|
||||
expect(onRemove.mock.calls[0][0]).toEqual(fileList[0]);
|
||||
|
||||
wrapper.find('.custom-item-render-action-download').first().simulate('click');
|
||||
expect(onDownload.mock.calls[0][0]).toEqual(fileList[0]);
|
||||
|
||||
wrapper.find('.custom-item-render-action-preview').first().simulate('click');
|
||||
expect(onPreview.mock.calls[0][0]).toEqual(fileList[0]);
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
|
@ -38,6 +38,9 @@ const props = {
|
||||
message.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
},
|
||||
onDrop(e) {
|
||||
console.log('Dropped files', e.dataTransfer.files);
|
||||
},
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -31,7 +31,7 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
||||
| headers | Set request headers, valid above IE10 | object | - | |
|
||||
| iconRender | Custom show icon | (file: UploadFile, listType?: UploadListType) => ReactNode | - | |
|
||||
| isImageUrl | Customize if render <img /> in thumbnail | (file: UploadFile) => boolean | [(inside implementation)](https://github.com/ant-design/ant-design/blob/4ad5830eecfb87471cd8ac588c5d992862b70770/components/upload/utils.tsx#L47-L68) | |
|
||||
| itemRender | Custom item of uploadList | (originNode: ReactElement, file: UploadFile, fileList?: object\[]) => React.ReactNode | - | 4.7.0 |
|
||||
| itemRender | Custom item of uploadList | (originNode: ReactElement, file: UploadFile, fileList: object\[], actions: { download: function, preview: function, remove: function }) => React.ReactNode | - | 4.16.0 |
|
||||
| listType | Built-in stylesheets, support for three types: `text`, `picture` or `picture-card` | string | `text` | |
|
||||
| maxCount | Limit the number of uploaded files. Will replace current one when `maxCount` is `1` | number | - | 4.10.0 |
|
||||
| method | The http method of upload request | string | `post` | |
|
||||
@ -43,6 +43,7 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
||||
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` and `downloadIcon` individually | boolean \| { showPreviewIcon?: boolean, showDownloadIcon?: boolean, showRemoveIcon?: boolean, removeIcon?: ReactNode \| (file: UploadFile) => ReactNode, downloadIcon?: ReactNode \| (file: UploadFile) => ReactNode } | true | function: 4.7.0 |
|
||||
| withCredentials | The ajax upload with cookie sent | boolean | false | |
|
||||
| onChange | A callback function, can be executed when uploading state is changing, see [onChange](#onChange) | function | - | |
|
||||
| onDrop | A callback function executed when files are dragged and dropped into upload area | (event: React.DragEvent) => void | - | 4.16.0 |
|
||||
| onDownload | Click the method to download the file, pass the method to perform the method logic, do not pass the default jump to the new TAB | function(file): void | (Jump to new TAB) | |
|
||||
| onPreview | A callback function, will be executed when file link or preview icon is clicked | function(file) | - | |
|
||||
| onRemove | A callback function, will be executed when removing file button is clicked, remove event will be prevented when return value is false or a Promise which resolve(false) or reject | function(file): boolean \| Promise | - | |
|
||||
|
@ -32,7 +32,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
|
||||
| headers | 设置上传的请求头部,IE10 以上有效 | object | - | |
|
||||
| iconRender | 自定义显示 icon | (file: UploadFile, listType?: UploadListType) => ReactNode | - | |
|
||||
| isImageUrl | 自定义缩略图是否使用 <img /> 标签进行显示 | (file: UploadFile) => boolean | [(内部实现)](https://github.com/ant-design/ant-design/blob/4ad5830eecfb87471cd8ac588c5d992862b70770/components/upload/utils.tsx#L47-L68) | |
|
||||
| itemRender | 自定义上传列表项 | (originNode: ReactElement, file: UploadFile, fileList?: object\[]) => React.ReactNode | - | 4.7.0 |
|
||||
| itemRender | 自定义上传列表项 | (originNode: ReactElement, file: UploadFile, fileList: object\[], actions: { download: function, preview: function, remove: function }) => React.ReactNode | - | 4.16.0 |
|
||||
| listType | 上传列表的内建样式,支持三种基本样式 `text`, `picture` 和 `picture-card` | string | `text` | |
|
||||
| maxCount | 限制上传数量。当为 1 时,始终用最新上传的文件代替当前文件 | number | - | 4.10.0 |
|
||||
| method | 上传请求的 http method | string | `post` | |
|
||||
@ -44,6 +44,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/QaeBt_ZMg/Upload.svg
|
||||
| showUploadList | 是否展示文件列表, 可设为一个对象,用于单独设定 `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` 和 `downloadIcon` | boolean \| { showPreviewIcon?: boolean, showRemoveIcon?: boolean, showDownloadIcon?: boolean, removeIcon?: ReactNode \| (file: UploadFile) => ReactNode, downloadIcon?: ReactNode \| (file: UploadFile) => ReactNode } | true | function: 4.7.0 |
|
||||
| withCredentials | 上传请求时是否携带 cookie | boolean | false | |
|
||||
| onChange | 上传文件改变时的状态,详见 [onChange](#onChange) | function | - | |
|
||||
| onDrop | 当文件被拖入上传区域时执行的回调功能 | (event: React.DragEvent) => void | - | 4.16.0 |
|
||||
| onDownload | 点击下载文件时的回调,如果没有指定,则默认跳转到文件 url 对应的标签页 | function(file): void | (跳转新标签页) | |
|
||||
| onPreview | 点击文件链接或预览图标时的回调 | function(file) | - | |
|
||||
| onRemove | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象,Promise 对象 resolve(false) 或 reject 时不移除 | function(file): boolean \| Promise | - | |
|
||||
|
@ -69,7 +69,12 @@ export type UploadListProgressProps = Omit<ProgressProps, 'percent' | 'type'>;
|
||||
export type ItemRender<T = any> = (
|
||||
originNode: React.ReactElement,
|
||||
file: UploadFile,
|
||||
fileList?: Array<UploadFile<T>>,
|
||||
fileList: Array<UploadFile<T>>,
|
||||
actions: {
|
||||
download: () => void;
|
||||
preview: () => void;
|
||||
remove: () => void;
|
||||
},
|
||||
) => React.ReactNode;
|
||||
|
||||
type PreviewFileHandler = (file: File | Blob) => PromiseLike<string>;
|
||||
@ -96,6 +101,7 @@ export interface UploadProps<T = any> {
|
||||
FileList: RcFile[],
|
||||
) => BeforeUploadValueType | Promise<BeforeUploadValueType>;
|
||||
onChange?: (info: UploadChangeParam) => void;
|
||||
onDrop?: (event: React.DragEvent<HTMLDivElement>) => void;
|
||||
listType?: UploadListType;
|
||||
className?: string;
|
||||
onPreview?: (file: UploadFile<T>) => void;
|
||||
|
@ -125,8 +125,8 @@
|
||||
"rc-field-form": "~1.20.0",
|
||||
"rc-image": "~5.2.4",
|
||||
"rc-input-number": "~7.1.0",
|
||||
"rc-mentions": "~1.5.0",
|
||||
"rc-menu": "~8.10.0",
|
||||
"rc-mentions": "~1.6.0",
|
||||
"rc-menu": "~9.0.0-alpha.6",
|
||||
"rc-motion": "^2.4.0",
|
||||
"rc-notification": "~4.5.2",
|
||||
"rc-pagination": "~3.1.6",
|
||||
@ -138,8 +138,8 @@
|
||||
"rc-slider": "~9.7.1",
|
||||
"rc-steps": "~4.1.0",
|
||||
"rc-switch": "~3.2.0",
|
||||
"rc-table": "~7.13.0",
|
||||
"rc-tabs": "~11.7.0",
|
||||
"rc-table": "~7.15.1",
|
||||
"rc-tabs": "~11.9.0",
|
||||
"rc-textarea": "~0.3.0",
|
||||
"rc-tooltip": "~5.1.1",
|
||||
"rc-tree": "~4.1.0",
|
||||
|
@ -24,7 +24,9 @@ async function checkVersion() {
|
||||
}
|
||||
|
||||
async function checkBranch({ current }) {
|
||||
if (current !== 'master' && current !== '4.0-prepare') {
|
||||
if (version.includes('-alpha.')) {
|
||||
console.log(chalk.cyan('😃 Alpha version. Skip branch check.'));
|
||||
} else if (current !== 'master' && current !== '4.0-prepare') {
|
||||
console.log(chalk.yellow('🤔 You are not in the master branch!'));
|
||||
exitProcess();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user