mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 01:13:58 +08:00
feat: added rtl direction to all of ant-design components (#19380)
* rtl demo change en-us description * change bundlesize css limit * RTL: modal component (exclude confirm) * RTL: table component * RTL: pagination component * cleanup rtl demo * fix pagination.tsx compile error * RTL: button and button-group * RTL: Steps component * fix rtl demo style * fix input suffix icon alignment * fix select component arrow issue * RTL: form component * add pagination rtl test * fix test lint error * RTL: rate component * RTL: radio and radio group components * RTL: tree-select component * some fixes to RTL components * RTL: badge component * fix rtl issue in inline form * fix input component rtl padding issue * fix switch component text rtl issue * fix table grouped header text-align * add rtl support to whole demo with RTL button * Update rtl demo responsive * RTL: page-header component * RTL: typography component * RTL: Dropdown (Partial) * update config-provider doc * RTL: input component * RTL: select component * RTL: switch component * RTL: tree component * fix rtl demo lint * rtl demo change en-us description * RTL: modal component (exclude confirm) * RTL: table component * RTL: pagination component * cleanup rtl demo * RTL: button and button-group * RTL: Steps component * fix rtl demo style * fix input suffix icon alignment * RTL: form component * RTL: rate component * RTL: radio and radio group components * RTL: tree-select component * RTL: badge component * fix rtl issue in inline form * fix input component rtl padding issue * add rtl support to whole demo with RTL button * fix lost changes after rebase * fix lint errors * RTL: Transfer Component * RTL: upload component * RTL: update avatar demo * RTL: comment component * RTL: collapse component * RTL: carousel component * update snapshots * RTL: Card component * RTL: descriptions component * RTL: Empty component * RTL: list component * RTL: slider component * slider component import/order * add shared rtlTest * RTL: Statistic component * RTL: tooltip components * RTL: popover component * RTL: timeline component * RTL: tag component * RTL: alert component * RTL: drawer component * RTL: Tab component * change direction definition * RTL: progress component * input.tsx, remove duplicate after rebase * fix demo.less after rebase * fix ant-row-rtl after rebase * fix upload issues in rtl * badge rtl demo margin fix * fix: tabs with icon margin * fix: radio-wrapper margin * fix: table component after rebase * fix: centered modal text-align * update slider snapshot * RTL: popconfirm component * RTL: back-top component * RTL: spin component * RTL: result component * RTL: skeleton component * RTL: menu component * RTL: time-picker component * RTL: calendar component * RTL: date-picker component * RTL: home page * update snapshots * test: add auto-complete rtl test * test: add avatar component rtl tests * test: add badge component rtl tests * test: add breadcrumb component rtl tests * test: add button components rtl tests * test: add card component rtl tests * test: add carousel component rtl tests * test: add cascader component rtl tests * test: add checkbox component rtl tests * test: add collapse component rtl tests * test: add comment component rtl tests * test: add dropdown component rtl tests * test: add empty component rtl tests * test: add form component rtl tests * test: add grid component rtl tests * test: add input component rtl tests * test: add search component rtl tests * test: add input-number component rtl tests * test: add layout component rtl tests * test: add list component rtl tests * test: add mentions component rtl tests * test: add modal component rtl tests * test: add page-header component rtl tests * test: add pagination component rtl tests * test: add radio component rtl tests * test: add rate component rtl tests * test: add select component rtl tests * test: add slider component rtl tests * test: add steps component rtl tests * test: add switch component rtl tests * test: add table component rtl tests * test: add transfer component rtl tests * test: add tree component rtl tests * test: add tree-select component rtl tests * test: add typography component rtl tests * test: add upload component rtl tests * test: add affix component rtl tests * update calendar tests * increase css file maxSize * update snapshots * remove workflows to allow push * remove duplicate reverse prop from slider * fix: remove table demo from config-provider * fix: remove table demo from config-provider * fix lint error * Added direction property to ConfigProvider * cascader rtl tests added * update config-provider doc * RTL: grid system * RTL: input component * RTL: switch component * fix rtl demo lint * RTL: modal component (exclude confirm) * RTL: table component * RTL: pagination component * cleanup rtl demo * fix pagination.tsx compile error * RTL: button and button-group * RTL: Steps component * fix rtl demo style * RTL: form component * add pagination rtl test * RTL: rate component * RTL: radio and radio group components * RTL: tree-select component * RTL: badge component * fix rtl issue in inline form * fix input component rtl padding issue * add rtl support to whole demo with RTL button * RTL: input component * RTL: select component * RTL: switch component * RTL: tree component * fix rtl demo lint * rtl demo change en-us description * RTL: modal component (exclude confirm) * RTL: table component * RTL: pagination component * cleanup rtl demo * RTL: button and button-group * RTL: Steps component * fix rtl demo style * fix input suffix icon alignment * RTL: form component * RTL: rate component * RTL: radio and radio group components * RTL: tree-select component * RTL: badge component * fix rtl issue in inline form * fix input component rtl padding issue * add rtl support to whole demo with RTL button * input.tsx, remove duplicate after rebase * fix ant-row-rtl after rebase * update snapshots * test: add cascader component rtl tests * test: add pagination component rtl tests * update calendar tests * update snapshots * fix: remove table demo from config-provider * fix: remove table demo from config-provider * fix lint error * update direction.md icons * dropdown and cascader default placement in rtl * update snapshots * fix lint errors * remove duplicate import * update snapshots * update snapshot * update calendar snapshot * update snapshots * integrate with new rc-picker * update snapshots * fix lint errors * update snapshot * update snapshots * update snapshots * update snapshots :| * update snapshots * fix compile error. * fix typo after rebase * update snapshots * remove workflows to allow push * update snapshots * update snapshots * fix dist error * front-page css fix * update snapshots * fix lint and test issues * restore cascader index.less * update snapshots * fix logo in rtl and demo controls * ci errors * resolve steps/index.tsx conflicts * tooltip family demo remove inline style * resolve table/Table.tsx conflicts * resolve modal/Modal.tsx conflicts * resolve cascader/index.tsx conflicts * add workflows from upstream * update snapshots * revert logo to default * fix codebox demo direction of placements * resolve tooltip overlayClassName conflicts * update snapshots * update popover test * fix: cascader miss popupClassName * fix: fix select missing dropdownClassName * chore: Update snapshot * chore: Adjust menu use rtl logic * docs: Update demo line color Co-authored-by: 二货机器人 <smith3816@gmail.com>
This commit is contained in:
parent
37ca4f7884
commit
676de29eb4
@ -4,6 +4,7 @@ import Affix from '..';
|
||||
import { getObserverEntities } from '../utils';
|
||||
import Button from '../../button';
|
||||
import { spyElementPrototype } from '../../__tests__/util/domHook';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
const events = {};
|
||||
|
||||
@ -40,6 +41,8 @@ class AffixMounter extends React.Component {
|
||||
}
|
||||
|
||||
describe('Affix Render', () => {
|
||||
rtlTest(Affix);
|
||||
|
||||
let wrapper;
|
||||
let domMock;
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Affix Render rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class=""
|
||||
/>
|
||||
</div>
|
||||
`;
|
@ -21,3 +21,17 @@ exports[`Alert ErrorBoundary 1`] = `
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Alert rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-no-icon ant-alert-rtl"
|
||||
data-show="true"
|
||||
>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
/>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,10 +1,13 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Alert from '..';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
const { ErrorBoundary } = Alert;
|
||||
|
||||
describe('Alert', () => {
|
||||
rtlTest(Alert);
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
@ -95,7 +95,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
(this.props.afterClose || noop)();
|
||||
};
|
||||
|
||||
renderAlert = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderAlert = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
description,
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -133,6 +133,7 @@ export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
[`${prefixCls}-no-icon`]: !showIcon,
|
||||
[`${prefixCls}-banner`]: !!banner,
|
||||
[`${prefixCls}-closable`]: closable,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
@ -11,18 +11,33 @@
|
||||
word-wrap: break-word;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
&-rtl {
|
||||
padding: 8px 37px 8px 15px;
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&&-no-icon {
|
||||
padding: 8px 15px;
|
||||
}
|
||||
|
||||
&&-closable {
|
||||
padding-right: 30px;
|
||||
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
padding-right: 15px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
position: absolute;
|
||||
top: 8px + @font-size-base * @line-height-base / 2 - @font-size-base / 2;
|
||||
left: 16px;
|
||||
|
||||
.@{alert-prefix-cls}-rtl & {
|
||||
right: 16px;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-description {
|
||||
@ -81,6 +96,11 @@
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
.@{alert-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-close {
|
||||
color: @alert-close-color;
|
||||
transition: color 0.3s;
|
||||
@ -104,6 +124,10 @@
|
||||
color: @alert-text-color;
|
||||
line-height: @line-height-base;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
padding: 15px 64px 15px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-description&-no-icon {
|
||||
@ -115,6 +139,11 @@
|
||||
top: 16px;
|
||||
left: 24px;
|
||||
font-size: 24px;
|
||||
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
right: 24px;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-description &-close-icon {
|
||||
@ -123,6 +152,11 @@
|
||||
right: 16px;
|
||||
font-size: @font-size-base;
|
||||
cursor: pointer;
|
||||
|
||||
.@{alert-prefix-cls}-rtl& {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-description &-message {
|
||||
|
@ -0,0 +1,30 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AutoComplete with Custom Input Element Render rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-auto-complete ant-select-rtl ant-select-single ant-select-show-search"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
role="combobox"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -2,9 +2,11 @@ import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import AutoComplete from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('AutoComplete with Custom Input Element Render', () => {
|
||||
mountTest(AutoComplete);
|
||||
rtlTest(AutoComplete);
|
||||
|
||||
it('AutoComplete with custom Input render perfectly', () => {
|
||||
const wrapper = mount(
|
||||
|
@ -2,9 +2,11 @@ import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Avatar from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Avatar Render', () => {
|
||||
mountTest(Avatar);
|
||||
rtlTest(Avatar);
|
||||
|
||||
let originOffsetWidth;
|
||||
beforeAll(() => {
|
||||
|
@ -0,0 +1,12 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Avatar Render rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<span
|
||||
class="ant-avatar ant-avatar-circle"
|
||||
>
|
||||
<span
|
||||
class="ant-avatar-string"
|
||||
style="opacity:0"
|
||||
/>
|
||||
</span>
|
||||
`;
|
@ -3,7 +3,7 @@
|
||||
exports[`renders ./components/avatar/demo/badge.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
style="margin-right:24px"
|
||||
class="avatar-item"
|
||||
>
|
||||
<span
|
||||
class="ant-badge"
|
||||
|
@ -19,7 +19,7 @@ import { UserOutlined } from '@ant-design/icons';
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<span style={{ marginRight: 24 }}>
|
||||
<span className="avatar-item">
|
||||
<Badge count={1}>
|
||||
<Avatar shape="square" icon={<UserOutlined />} />
|
||||
</Badge>
|
||||
@ -33,3 +33,15 @@ ReactDOM.render(
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
|
||||
```css
|
||||
/* tile uploaded pictures */
|
||||
.avatar-item {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
[class*='-col-rtl'] .avatar-item {
|
||||
margin-right: 0;
|
||||
margin-left: 24px;
|
||||
}
|
||||
```
|
||||
|
@ -0,0 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BackTop rtl render component should be rendered correctly in RTL direction 1`] = `null`;
|
@ -2,10 +2,12 @@ import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import BackTop from '..';
|
||||
|
||||
describe('BackTop', () => {
|
||||
mountTest(BackTop);
|
||||
rtlTest(BackTop);
|
||||
|
||||
it('should scroll to top after click it', async () => {
|
||||
const wrapper = mount(<BackTop visibilityHeight={-1} />);
|
||||
|
@ -65,10 +65,12 @@ export default class BackTop extends React.Component<BackTopProps, any> {
|
||||
});
|
||||
};
|
||||
|
||||
renderBackTop = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderBackTop = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className = '', children } = this.props;
|
||||
const prefixCls = getPrefixCls('back-top', customizePrefixCls);
|
||||
const classString = classNames(prefixCls, className);
|
||||
const classString = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
const defaultElement = (
|
||||
<div className={`${prefixCls}-content`}>
|
||||
|
@ -14,6 +14,11 @@
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
|
||||
&-rtl {
|
||||
right: auto;
|
||||
left: 100px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
@ -724,6 +724,12 @@ exports[`Badge render correct with negative number 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Badge rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<span
|
||||
class="ant-badge ant-badge-not-a-wrapper ant-badge-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Badge should be compatible with borderColor style 1`] = `
|
||||
<span
|
||||
class="ant-badge ant-badge-not-a-wrapper"
|
||||
|
@ -3,9 +3,11 @@ import { mount, render } from 'enzyme';
|
||||
import Badge from '../index';
|
||||
import Tooltip from '../../tooltip';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Badge', () => {
|
||||
mountTest(Badge);
|
||||
rtlTest(Badge);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
|
@ -37,6 +37,10 @@ ReactDOM.render(
|
||||
.ant-badge:not(.ant-badge-not-a-wrapper) {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.ant-badge.ant-badge-rtl:not(.ant-badge-not-a-wrapper) {
|
||||
margin-right: 0;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.head-example {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
|
@ -40,6 +40,10 @@ ReactDOM.render(
|
||||
.ant-badge-not-a-wrapper:not(.ant-badge-status) {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.ant-badge.ant-badge-rtl:not(.ant-badge-not-a-wrapper) {
|
||||
margin-right: 0;
|
||||
margin-left: 20px;
|
||||
}
|
||||
[data-theme="dark"] .site-badge-count-4 .ant-badge-count {
|
||||
background-color: #141414;
|
||||
box-shadow: 0 0 0 1px #434343 inset;
|
||||
|
@ -31,6 +31,12 @@ ReactDOM.render(
|
||||
.ant-badge:not(.ant-badge-not-a-wrapper) {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.ant-badge.ant-badge-rtl:not(.ant-badge-not-a-wrapper) {
|
||||
margin-right: 0;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.head-example {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
|
@ -74,11 +74,12 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
: style;
|
||||
}
|
||||
|
||||
getBadgeClassName(prefixCls: string) {
|
||||
getBadgeClassName(prefixCls: string, direction: string = 'ltr') {
|
||||
const { className, children } = this.props;
|
||||
return classNames(className, prefixCls, {
|
||||
[`${prefixCls}-status`]: this.hasStatus(),
|
||||
[`${prefixCls}-not-a-wrapper`]: !children,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
}) as string;
|
||||
}
|
||||
|
||||
@ -156,7 +157,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
);
|
||||
}
|
||||
|
||||
renderBadge = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderBadge = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
scrollNumberPrefixCls: customizeScrollNumberPrefixCls,
|
||||
@ -200,7 +201,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
return (
|
||||
<span
|
||||
{...omit(restProps, omitArr)}
|
||||
className={this.getBadgeClassName(prefixCls)}
|
||||
className={this.getBadgeClassName(prefixCls, direction)}
|
||||
style={styleWithOffset}
|
||||
>
|
||||
<span className={statusCls} style={statusStyle} />
|
||||
@ -212,7 +213,7 @@ export default class Badge extends React.Component<BadgeProps, any> {
|
||||
}
|
||||
|
||||
return (
|
||||
<span {...omit(restProps, omitArr)} className={this.getBadgeClassName(prefixCls)}>
|
||||
<span {...omit(restProps, omitArr)} className={this.getBadgeClassName(prefixCls, direction)}>
|
||||
{children}
|
||||
<Animate
|
||||
component=""
|
||||
|
@ -12,6 +12,10 @@
|
||||
color: unset;
|
||||
line-height: 1;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-count {
|
||||
z-index: @zindex-badge;
|
||||
min-width: @badge-height;
|
||||
@ -53,6 +57,20 @@
|
||||
right: 0;
|
||||
transform: translate(50%, -50%);
|
||||
transform-origin: 100% 0%;
|
||||
|
||||
.@{badge-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 0;
|
||||
transform: translate(-50%, -50%);
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
}
|
||||
|
||||
.@{badge-prefix-cls}-rtl& .@{number-prefix-cls}-custom-component {
|
||||
right: auto;
|
||||
left: 0;
|
||||
transform: translate(-50%, -50%);
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
|
||||
&-status {
|
||||
@ -111,6 +129,11 @@
|
||||
margin-left: 8px;
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
|
||||
.@{badge-prefix-cls}-rtl & {
|
||||
margin-right: 8px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,11 +141,19 @@
|
||||
&-zoom-enter {
|
||||
animation: antZoomBadgeIn 0.3s @ease-out-back;
|
||||
animation-fill-mode: both;
|
||||
|
||||
.@{badge-prefix-cls}-rtl & {
|
||||
animation-name: antZoomBadgeInRtl;
|
||||
}
|
||||
}
|
||||
|
||||
&-zoom-leave {
|
||||
animation: antZoomBadgeOut 0.3s @ease-in-back;
|
||||
animation-fill-mode: both;
|
||||
|
||||
.@{badge-prefix-cls}-rtl & {
|
||||
animation-name: antZoomBadgeOutRtl;
|
||||
}
|
||||
}
|
||||
|
||||
&-not-a-wrapper {
|
||||
@ -189,3 +220,23 @@
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBadgeInRtl {
|
||||
0% {
|
||||
transform: scale(0) translate(-50%, -50%);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1) translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antZoomBadgeOutRtl {
|
||||
0% {
|
||||
transform: scale(1) translate(-50%, -50%);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0) translate(-50%, -50%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ import React from 'react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import Breadcrumb from '../index';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Breadcrumb', () => {
|
||||
mountTest(Breadcrumb);
|
||||
rtlTest(Breadcrumb);
|
||||
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
|
@ -32,6 +32,12 @@ exports[`Breadcrumb filter React.Fragment 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Breadcrumb rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-breadcrumb"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Breadcrumb should allow Breadcrumb.Item is null or undefined 1`] = `
|
||||
<div
|
||||
class="ant-breadcrumb"
|
||||
|
@ -215,6 +215,45 @@ exports[`Button renders correctly 1`] = `
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`Button rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-rtl"
|
||||
type="button"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button rtl render component should be rendered correctly in RTL direction 2`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-lg ant-btn-rtl"
|
||||
type="button"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button rtl render component should be rendered correctly in RTL direction 3`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-sm ant-btn-rtl"
|
||||
type="button"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button rtl render component should be rendered correctly in RTL direction 4`] = `
|
||||
<div
|
||||
class="ant-btn-group ant-btn-group-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button rtl render component should be rendered correctly in RTL direction 5`] = `
|
||||
<div
|
||||
class="ant-btn-group ant-btn-group-lg ant-btn-group-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button rtl render component should be rendered correctly in RTL direction 6`] = `
|
||||
<div
|
||||
class="ant-btn-group ant-btn-group-sm ant-btn-group-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Button should has click wave effect 1`] = `
|
||||
<button
|
||||
ant-click-animating-without-extra-node="true"
|
||||
|
@ -4,6 +4,7 @@ import renderer from 'react-test-renderer';
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import Button from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
import { sleep } from '../../../tests/utils';
|
||||
|
||||
describe('Button', () => {
|
||||
@ -14,6 +15,13 @@ describe('Button', () => {
|
||||
mountTest(() => <Button.Group size="large" />);
|
||||
mountTest(() => <Button.Group size="small" />);
|
||||
|
||||
rtlTest(Button);
|
||||
rtlTest(() => <Button size="large" />);
|
||||
rtlTest(() => <Button size="small" />);
|
||||
rtlTest(Button.Group);
|
||||
rtlTest(() => <Button.Group size="large" />);
|
||||
rtlTest(() => <Button.Group size="small" />);
|
||||
|
||||
it('renders correctly', () => {
|
||||
const wrapper = render(<Button>Follow</Button>);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
@ -12,7 +12,7 @@ export interface ButtonGroupProps {
|
||||
|
||||
const ButtonGroup: React.SFC<ButtonGroupProps> = props => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
{({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, size, className, ...others } = props;
|
||||
const prefixCls = getPrefixCls('btn-group', customizePrefixCls);
|
||||
|
||||
@ -34,6 +34,7 @@ const ButtonGroup: React.SFC<ButtonGroupProps> = props => (
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
@ -201,7 +201,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
return React.Children.count(children) === 1 && !icon && type !== 'link';
|
||||
}
|
||||
|
||||
renderButton = ({ getPrefixCls, autoInsertSpaceInButton }: ConfigConsumerProps) => {
|
||||
renderButton = ({ getPrefixCls, autoInsertSpaceInButton, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
type,
|
||||
@ -252,6 +252,7 @@ class Button extends React.Component<ButtonProps, ButtonState> {
|
||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace,
|
||||
[`${prefixCls}-block`]: block,
|
||||
[`${prefixCls}-dangerous`]: !!danger,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
const iconNode = loading ? <LoadingOutlined /> : icon || null;
|
||||
|
@ -24,6 +24,9 @@
|
||||
.btn;
|
||||
.btn-default;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
// Make sure that the target of Button's click event always be `button`
|
||||
// Ref: https://github.com/ant-design/ant-design/issues/7034
|
||||
> i,
|
||||
@ -48,6 +51,7 @@
|
||||
.@{btn-prefix-cls}-group &:first-child {
|
||||
&:not(:last-child) {
|
||||
border-right-color: @btn-group-border;
|
||||
|
||||
&[disabled] {
|
||||
border-right-color: @btn-default-border;
|
||||
}
|
||||
@ -57,8 +61,18 @@
|
||||
.@{btn-prefix-cls}-group &:last-child:not(:first-child),
|
||||
.@{btn-prefix-cls}-group & + & {
|
||||
border-left-color: @btn-group-border;
|
||||
|
||||
.@{btn-prefix-cls}-group-rtl& {
|
||||
border-right-color: @btn-group-border;
|
||||
border-left-color: @btn-default-border;
|
||||
}
|
||||
&[disabled] {
|
||||
border-left-color: @btn-default-border;
|
||||
|
||||
.@{btn-prefix-cls}-group-rtl& {
|
||||
border-right-color: @btn-default-border;
|
||||
border-left-color: @btn-group-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,15 +169,37 @@
|
||||
|
||||
&&-loading:not(&-circle):not(&-circle-outline):not(&-icon-only) {
|
||||
padding-left: 29px;
|
||||
|
||||
.@{btn-prefix-cls}-rtl& {
|
||||
padding-right: 29px;
|
||||
padding-left: @padding-md - 1px;
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}:not(:last-child) {
|
||||
margin-left: -14px;
|
||||
|
||||
.@{btn-prefix-cls}-rtl& {
|
||||
margin-right: -14px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-sm&-loading:not(&-circle):not(&-circle-outline):not(&-icon-only) {
|
||||
padding-left: 24px;
|
||||
|
||||
.@{btn-prefix-cls}-rtl& {
|
||||
padding-right: 24px;
|
||||
padding-left: @padding-xs - 1px;
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix} {
|
||||
margin-left: -17px;
|
||||
|
||||
.@{btn-prefix-cls}-rtl& {
|
||||
margin-right: -17px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,6 +217,11 @@
|
||||
> .@{iconfont-css-prefix} + span,
|
||||
> span + .@{iconfont-css-prefix} {
|
||||
margin-left: 8px;
|
||||
|
||||
.@{btn-prefix-cls}-rtl& {
|
||||
margin-right: 8px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-background-ghost {
|
||||
|
@ -400,6 +400,10 @@
|
||||
& + .@{btnClassName},
|
||||
& + & {
|
||||
margin-left: -1px;
|
||||
.@{btnClassName}-rtl& {
|
||||
margin-right: -1px;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
.@{btnClassName}-primary + .@{btnClassName}:not(.@{btnClassName}-primary):not([disabled]) {
|
||||
border-left-color: transparent;
|
||||
@ -407,6 +411,9 @@
|
||||
.@{btnClassName} {
|
||||
border-radius: 0;
|
||||
}
|
||||
&.@{btnClassName}-group-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
> .@{btnClassName}:first-child,
|
||||
> span:first-child > .@{btnClassName} {
|
||||
margin-left: 0;
|
||||
@ -421,11 +428,23 @@
|
||||
> span:first-child:not(:last-child) > .@{btnClassName} {
|
||||
border-top-left-radius: @btn-border-radius-base;
|
||||
border-bottom-left-radius: @btn-border-radius-base;
|
||||
.@{btnClassName}-group-rtl& {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: @btn-border-radius-base;
|
||||
border-bottom-right-radius: @btn-border-radius-base;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
> .@{btnClassName}:last-child:not(:first-child),
|
||||
> span:last-child:not(:first-child) > .@{btnClassName} {
|
||||
border-top-right-radius: @btn-border-radius-base;
|
||||
border-bottom-right-radius: @btn-border-radius-base;
|
||||
.@{btnClassName}-group-rtl& {
|
||||
border-top-left-radius: @btn-border-radius-base;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: @btn-border-radius-base;
|
||||
}
|
||||
}
|
||||
&-sm {
|
||||
> .@{btnClassName}:only-child {
|
||||
@ -438,11 +457,23 @@
|
||||
> span:first-child:not(:last-child) > .@{btnClassName} {
|
||||
border-top-left-radius: @btn-border-radius-sm;
|
||||
border-bottom-left-radius: @btn-border-radius-sm;
|
||||
.@{btnClassName}-group-rtl& {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: @btn-border-radius-sm;
|
||||
border-bottom-right-radius: @btn-border-radius-sm;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
> .@{btnClassName}:last-child:not(:first-child),
|
||||
> span:last-child:not(:first-child) > .@{btnClassName} {
|
||||
border-top-right-radius: @btn-border-radius-sm;
|
||||
border-bottom-right-radius: @btn-border-radius-sm;
|
||||
.@{btnClassName}-group-rtl& {
|
||||
border-top-left-radius: @btn-border-radius-sm;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: @btn-border-radius-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
& > & {
|
||||
|
@ -951,3 +951,953 @@ exports[`Calendar Calendar should support locale 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Calendar rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-picker-calendar ant-picker-calendar-full"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-header"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-picker-calendar-year-select ant-select-rtl ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-item"
|
||||
>
|
||||
2000
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-picker-calendar-month-select ant-select-rtl ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-item"
|
||||
>
|
||||
Sep
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-radio-group ant-radio-group-outline ant-radio-group-default ant-radio-group-rtl ant-picker-calendar-mode-switch"
|
||||
>
|
||||
<label
|
||||
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked ant-radio-button-wrapper-rtl"
|
||||
>
|
||||
<span
|
||||
class="ant-radio-button ant-radio-button-checked"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="month"
|
||||
/>
|
||||
<span
|
||||
class="ant-radio-button-inner"
|
||||
/>
|
||||
</span>
|
||||
<span>
|
||||
Month
|
||||
</span>
|
||||
</label>
|
||||
<label
|
||||
class="ant-radio-button-wrapper ant-radio-button-wrapper-rtl"
|
||||
>
|
||||
<span
|
||||
class="ant-radio-button"
|
||||
>
|
||||
<input
|
||||
class="ant-radio-button-input"
|
||||
type="radio"
|
||||
value="year"
|
||||
/>
|
||||
<span
|
||||
class="ant-radio-button-inner"
|
||||
/>
|
||||
</span>
|
||||
<span>
|
||||
Year
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-panel"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-date-panel"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-body"
|
||||
>
|
||||
<table
|
||||
class="ant-picker-content"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Su
|
||||
</th>
|
||||
<th>
|
||||
Mo
|
||||
</th>
|
||||
<th>
|
||||
Tu
|
||||
</th>
|
||||
<th>
|
||||
We
|
||||
</th>
|
||||
<th>
|
||||
Th
|
||||
</th>
|
||||
<th>
|
||||
Fr
|
||||
</th>
|
||||
<th>
|
||||
Sa
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
class=""
|
||||
>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-08-27"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
27
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-08-28"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
28
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-08-29"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
29
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-08-30"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
30
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-08-31"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
31
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-01"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
01
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-02"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
02
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class=""
|
||||
>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-03"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
03
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-04"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
04
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-05"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
05
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-06"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
06
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-07"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
07
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-08"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
08
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-09"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
09
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class=""
|
||||
>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-10"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
10
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-11"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
11
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-12"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
12
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-13"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
13
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-14"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
14
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-15"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
15
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-16"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
16
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class=""
|
||||
>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-17"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
17
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-18"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
18
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-19"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
19
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-20"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
20
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-21"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
21
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-22"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
22
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-23"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
23
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class=""
|
||||
>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-24"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
24
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-25"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
25
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-26"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
26
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-27"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
27
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view ant-picker-cell-today ant-picker-cell-selected"
|
||||
title="2000-09-28"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date ant-picker-calendar-date-today"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
28
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-29"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
29
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell ant-picker-cell-in-view"
|
||||
title="2000-09-30"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
30
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class=""
|
||||
>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-10-01"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
01
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-10-02"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
02
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-10-03"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
03
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-10-04"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
04
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-10-05"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
05
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-10-06"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
06
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="ant-picker-cell"
|
||||
title="2000-10-07"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-cell-inner ant-picker-calendar-date"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-calendar-date-value"
|
||||
>
|
||||
07
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-calendar-date-content"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -9,9 +9,11 @@ import Select from '../../select';
|
||||
import Group from '../../radio/group';
|
||||
import Button from '../../radio/radioButton';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Calendar', () => {
|
||||
mountTest(Calendar);
|
||||
rtlTest(Calendar, true);
|
||||
|
||||
function openSelect(wrapper, className) {
|
||||
wrapper
|
||||
|
@ -1,5 +1,15 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Card rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-bordered ant-card-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Card should still have padding when card which set padding to 0 is loading 1`] = `
|
||||
<div
|
||||
class="ant-card ant-card-loading ant-card-bordered"
|
||||
|
@ -3,9 +3,11 @@ import { mount } from 'enzyme';
|
||||
import Card from '../index';
|
||||
import Button from '../../button/index';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Card', () => {
|
||||
mountTest(Card);
|
||||
rtlTest(Card);
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
|
@ -76,7 +76,7 @@ export default class Card extends React.Component<CardProps, {}> {
|
||||
return containGrid;
|
||||
}
|
||||
|
||||
renderCard = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderCard = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
@ -108,6 +108,7 @@ export default class Card extends React.Component<CardProps, {}> {
|
||||
[`${prefixCls}-contain-tabs`]: tabList && tabList.length,
|
||||
[`${prefixCls}-${size}`]: size !== 'default',
|
||||
[`${prefixCls}-type-${type}`]: !!type,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
const loadingBlockStyle =
|
||||
|
@ -17,6 +17,10 @@
|
||||
border-radius: @card-radius;
|
||||
transition: all 0.3s;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-hoverable {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
@ -76,6 +80,11 @@
|
||||
color: @text-color;
|
||||
font-weight: normal;
|
||||
font-size: @font-size-base;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
margin-right: auto;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-body {
|
||||
@ -98,6 +107,11 @@
|
||||
1px 1px 0 0 @border-color-split, 1px 0 0 0 @border-color-split inset,
|
||||
0 1px 0 0 @border-color-split inset;
|
||||
transition: all 0.3s;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
float: right;
|
||||
}
|
||||
|
||||
&-hoverable {
|
||||
&:hover {
|
||||
position: relative;
|
||||
@ -142,6 +156,10 @@
|
||||
color: @text-color-secondary;
|
||||
text-align: center;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
float: right;
|
||||
}
|
||||
|
||||
> span {
|
||||
position: relative;
|
||||
display: block;
|
||||
@ -205,6 +223,12 @@
|
||||
&-avatar {
|
||||
float: left;
|
||||
padding-right: 16px;
|
||||
|
||||
.@{card-prefix-cls}-rtl & {
|
||||
float: right;
|
||||
padding-right: 0;
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&-detail {
|
||||
|
@ -1,5 +1,24 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Carousel rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-carousel ant-carousel-rtl"
|
||||
>
|
||||
<div
|
||||
class="slick-slider slick-initialized"
|
||||
>
|
||||
<div
|
||||
class="slick-list"
|
||||
>
|
||||
<div
|
||||
class="slick-track"
|
||||
style="width:0%;left:NaN%"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Carousel should works for dotPosition bottom 1`] = `
|
||||
<div
|
||||
class="ant-carousel"
|
||||
|
@ -2,9 +2,11 @@ import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Carousel from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Carousel', () => {
|
||||
mountTest(Carousel);
|
||||
rtlTest(Carousel);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { Settings } from '@ant-design/react-slick';
|
||||
import classNames from 'classnames';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
|
||||
// Use require over import (will be lifted up)
|
||||
@ -92,7 +93,7 @@ export default class Carousel extends React.Component<CarouselProps, {}> {
|
||||
this.slick.slickGoTo(slide, dontAnimate);
|
||||
}
|
||||
|
||||
renderCarousel = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderCarousel = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const props = {
|
||||
...this.props,
|
||||
};
|
||||
@ -101,11 +102,15 @@ export default class Carousel extends React.Component<CarouselProps, {}> {
|
||||
props.fade = true;
|
||||
}
|
||||
|
||||
const className = getPrefixCls('carousel', props.prefixCls);
|
||||
const prefixCls = getPrefixCls('carousel', props.prefixCls);
|
||||
const dotsClass = 'slick-dots';
|
||||
const dotPosition = this.getDotPosition();
|
||||
props.dotsClass = `${dotsClass} ${dotsClass}-${dotPosition || 'bottom'}`;
|
||||
|
||||
const className = classNames(prefixCls, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<SlickCarousel ref={this.saveSlick} {...props} />
|
||||
|
@ -1,9 +1,15 @@
|
||||
@import '../../style/themes/index';
|
||||
@import '../../style/mixins/index';
|
||||
|
||||
.@{ant-prefix}-carousel {
|
||||
@carousel-prefix-cls: ~'@{ant-prefix}-carousel';
|
||||
|
||||
.@{carousel-prefix-cls} {
|
||||
.reset-component;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.slick-slider {
|
||||
position: relative;
|
||||
display: block;
|
||||
@ -47,6 +53,11 @@
|
||||
left: 0;
|
||||
display: block;
|
||||
|
||||
.@{carousel-prefix-cls}-rtl & {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
display: table;
|
||||
@ -66,9 +77,7 @@
|
||||
float: left;
|
||||
height: 100%;
|
||||
min-height: 1px;
|
||||
[dir='rtl'] & {
|
||||
float: right;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
@ -131,9 +140,19 @@
|
||||
|
||||
.slick-prev {
|
||||
left: -25px;
|
||||
|
||||
&::before {
|
||||
content: '←';
|
||||
}
|
||||
|
||||
.@{carousel-prefix-cls}-rtl & {
|
||||
right: -25px;
|
||||
left: auto;
|
||||
|
||||
&::before {
|
||||
content: '→';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slick-next {
|
||||
@ -141,18 +160,34 @@
|
||||
&::before {
|
||||
content: '→';
|
||||
}
|
||||
|
||||
.@{carousel-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: -25px;
|
||||
&::before {
|
||||
content: '←';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dots
|
||||
.slick-dots {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: @carousel-dot-height;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 15;
|
||||
display: flex !important;
|
||||
justify-content: center;
|
||||
margin-right: 15%;
|
||||
margin-left: 15%;
|
||||
padding-right: 0;
|
||||
list-style: none;
|
||||
|
||||
.@{carousel-prefix-cls}-rtl& {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&-bottom {
|
||||
bottom: 12px;
|
||||
}
|
||||
@ -162,13 +197,21 @@
|
||||
li {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
flex: 0 1 auto;
|
||||
box-sizing: content-box;
|
||||
width: @carousel-dot-width;
|
||||
height: @carousel-dot-height;
|
||||
margin: 0 2px;
|
||||
margin-right: 3px;
|
||||
margin-left: 3px;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
text-indent: -999px;
|
||||
vertical-align: top;
|
||||
transition: all 0.5s;
|
||||
button {
|
||||
display: block;
|
||||
width: @carousel-dot-width;
|
||||
width: 100%;
|
||||
height: @carousel-dot-height;
|
||||
padding: 0;
|
||||
color: transparent;
|
||||
@ -185,10 +228,12 @@
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
&.slick-active button {
|
||||
&.slick-active {
|
||||
width: @carousel-dot-active-width;
|
||||
background: @component-background;
|
||||
opacity: 1;
|
||||
& button {
|
||||
background: @component-background;
|
||||
opacity: 1;
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
@ -202,25 +247,41 @@
|
||||
.slick-dots {
|
||||
top: 50%;
|
||||
bottom: auto;
|
||||
flex-direction: column;
|
||||
width: @carousel-dot-height;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.@{carousel-prefix-cls}-rtl& {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&-left {
|
||||
right: auto;
|
||||
left: 12px;
|
||||
}
|
||||
&-right {
|
||||
right: 12px;
|
||||
left: auto;
|
||||
}
|
||||
li {
|
||||
margin: 0 2px;
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-width;
|
||||
margin: 4px 2px;
|
||||
vertical-align: baseline;
|
||||
button {
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-width;
|
||||
}
|
||||
&.slick-active button {
|
||||
&.slick-active {
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-active-width;
|
||||
|
||||
button {
|
||||
width: @carousel-dot-height;
|
||||
height: @carousel-dot-active-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +360,243 @@ exports[`Cascader can be selected 3`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Cascader can be selected in RTL direction 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-cascader-menus ant-cascader-menu-rtl"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
role="menuitem"
|
||||
title="Zhejiang"
|
||||
>
|
||||
Zhejiang
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
|
||||
role="menuitem"
|
||||
title="Jiangsu"
|
||||
>
|
||||
Jiangsu
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
|
||||
role="menuitem"
|
||||
title="Hangzhou"
|
||||
>
|
||||
Hangzhou
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Cascader can be selected in RTL direction 2`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-cascader-menus ant-cascader-menu-rtl"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
role="menuitem"
|
||||
title="Zhejiang"
|
||||
>
|
||||
Zhejiang
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
|
||||
role="menuitem"
|
||||
title="Jiangsu"
|
||||
>
|
||||
Jiangsu
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
role="menuitem"
|
||||
title="Hangzhou"
|
||||
>
|
||||
Hangzhou
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item"
|
||||
role="menuitem"
|
||||
title="West Lake"
|
||||
>
|
||||
West Lake
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Cascader have a notFoundContent that fit trigger input width 1`] = `
|
||||
<div>
|
||||
<div
|
||||
@ -641,6 +878,170 @@ exports[`Cascader popup correctly with defaultValue 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Cascader popup correctly with defaultValue RTL 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-cascader-menus ant-cascader-menu-rtl"
|
||||
style="opacity:0"
|
||||
>
|
||||
<div>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
role="menuitem"
|
||||
title="Zhejiang"
|
||||
>
|
||||
Zhejiang
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand"
|
||||
role="menuitem"
|
||||
title="Jiangsu"
|
||||
>
|
||||
Jiangsu
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item ant-cascader-menu-item-expand ant-cascader-menu-item-active"
|
||||
role="menuitem"
|
||||
title="Hangzhou"
|
||||
>
|
||||
Hangzhou
|
||||
<span
|
||||
class="ant-cascader-menu-item-expand-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul
|
||||
class="ant-cascader-menu"
|
||||
>
|
||||
<li
|
||||
class="ant-cascader-menu-item"
|
||||
role="menuitem"
|
||||
title="West Lake"
|
||||
>
|
||||
West Lake
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Cascader rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<span
|
||||
class="ant-cascader-picker ant-cascader-picker-rtl"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-cascader-picker-label"
|
||||
/>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="ant-input ant-input-rtl ant-cascader-input "
|
||||
placeholder="Please select"
|
||||
readonly=""
|
||||
tabindex="-1"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-cascader-picker-arrow"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Cascader should highlight keyword and filter when search in Cascader 1`] = `
|
||||
<Popup
|
||||
align={
|
||||
|
@ -2,8 +2,10 @@ import React from 'react';
|
||||
import { render, mount } from 'enzyme';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import Cascader from '..';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
const options = [
|
||||
{
|
||||
@ -47,6 +49,7 @@ function filter(inputValue, path) {
|
||||
describe('Cascader', () => {
|
||||
focusTest(Cascader);
|
||||
mountTest(Cascader);
|
||||
rtlTest(Cascader);
|
||||
|
||||
it('popup correctly when panel is hidden', () => {
|
||||
const wrapper = mount(<Cascader options={options} />);
|
||||
@ -442,4 +445,134 @@ describe('Cascader', () => {
|
||||
});
|
||||
expect(wrapper.find('input').prop('placeholder')).toBe(customPlaceholder);
|
||||
});
|
||||
it('popup correctly with defaultValue RTL', () => {
|
||||
const wrapper = mount(
|
||||
<ConfigProvider direction="rtl">
|
||||
<Cascader options={options} defaultValue={['zhejiang', 'hangzhou']} />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('input')
|
||||
.simulate('click');
|
||||
expect(
|
||||
render(
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
it('can be selected in RTL direction', () => {
|
||||
const options2 = [
|
||||
{
|
||||
value: 'zhejiang',
|
||||
label: 'Zhejiang',
|
||||
children: [
|
||||
{
|
||||
value: 'hangzhou',
|
||||
label: 'Hangzhou',
|
||||
children: [
|
||||
{
|
||||
value: 'xihu',
|
||||
label: 'West Lake',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'jiangsu',
|
||||
label: 'Jiangsu',
|
||||
children: [
|
||||
{
|
||||
value: 'nanjing',
|
||||
label: 'Nanjing',
|
||||
children: [
|
||||
{
|
||||
value: 'zhonghuamen',
|
||||
label: 'Zhong Hua Men',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const onChange = jest.fn();
|
||||
const wrapper = mount(
|
||||
<ConfigProvider direction="rtl">
|
||||
<Cascader
|
||||
options={options2}
|
||||
defaultValue={['zhejiang', 'hangzhou']}
|
||||
onChange={onChange}
|
||||
popupPlacement="bottomRight"
|
||||
/>
|
||||
</ConfigProvider>,
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('input')
|
||||
.simulate('click');
|
||||
let popupWrapper = mount(
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
popupWrapper
|
||||
.find('.ant-cascader-menu')
|
||||
.at(0)
|
||||
.find('.ant-cascader-menu-item')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
expect(
|
||||
render(
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
),
|
||||
).toMatchSnapshot();
|
||||
popupWrapper = mount(
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
popupWrapper
|
||||
.find('.ant-cascader-menu')
|
||||
.at(1)
|
||||
.find('.ant-cascader-menu-item')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
expect(
|
||||
render(
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
),
|
||||
).toMatchSnapshot();
|
||||
popupWrapper = mount(
|
||||
wrapper
|
||||
.find('Cascader')
|
||||
.find('Trigger')
|
||||
.instance()
|
||||
.getComponent(),
|
||||
);
|
||||
popupWrapper
|
||||
.find('.ant-cascader-menu')
|
||||
.at(2)
|
||||
.find('.ant-cascader-menu-item')
|
||||
.at(0)
|
||||
.simulate('click');
|
||||
expect(onChange).toHaveBeenCalledWith(['zhejiang', 'hangzhou', 'xihu'], expect.anything());
|
||||
});
|
||||
});
|
||||
|
@ -4,7 +4,13 @@ import arrayTreeFilter from 'array-tree-filter';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import { CloseCircleFilled, DownOutlined, RightOutlined, RedoOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
CloseCircleFilled,
|
||||
DownOutlined,
|
||||
RightOutlined,
|
||||
RedoOutlined,
|
||||
LeftOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
import Input from '../input';
|
||||
import { ConfigConsumer, ConfigConsumerProps, RenderEmptyHandler } from '../config-provider';
|
||||
@ -211,7 +217,6 @@ function warningValueNotExist(list: CascaderOptionType[], fieldNames: FieldNames
|
||||
class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
static defaultProps = {
|
||||
transitionName: 'slide-up',
|
||||
popupPlacement: 'bottomLeft',
|
||||
options: [],
|
||||
disabled: false,
|
||||
allowClear: true,
|
||||
@ -414,8 +419,21 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
getPopupPlacement(direction: string = 'ltr') {
|
||||
const { popupPlacement } = this.props;
|
||||
if (popupPlacement !== undefined) {
|
||||
return popupPlacement;
|
||||
}
|
||||
return direction === 'rtl' ? 'bottomRight' : 'bottomLeft';
|
||||
}
|
||||
|
||||
renderCascader = (
|
||||
{ getPopupContainer: getContextPopupContainer, getPrefixCls, renderEmpty }: ConfigConsumerProps,
|
||||
{
|
||||
getPopupContainer: getContextPopupContainer,
|
||||
getPrefixCls,
|
||||
renderEmpty,
|
||||
direction,
|
||||
}: ConfigConsumerProps,
|
||||
locale: CascaderLocale,
|
||||
) => {
|
||||
const { props, state } = this;
|
||||
@ -432,11 +450,14 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
showSearch = false,
|
||||
suffixIcon,
|
||||
notFoundContent,
|
||||
popupClassName,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const { value, inputFocused } = state;
|
||||
|
||||
const isRtlLayout = direction === 'rtl';
|
||||
|
||||
const prefixCls = getPrefixCls('cascader', customizePrefixCls);
|
||||
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
|
||||
|
||||
@ -453,6 +474,7 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
[`${prefixCls}-picker-arrow-expand`]: state.popupVisible,
|
||||
});
|
||||
const pickerCls = classNames(className, `${prefixCls}-picker`, {
|
||||
[`${prefixCls}-picker-rtl`]: isRtlLayout,
|
||||
[`${prefixCls}-picker-with-value`]: state.inputValue,
|
||||
[`${prefixCls}-picker-disabled`]: disabled,
|
||||
[`${prefixCls}-picker-${size}`]: !!size,
|
||||
@ -552,7 +574,10 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
</span>
|
||||
);
|
||||
|
||||
const expandIcon = <RightOutlined />;
|
||||
let expandIcon = <RightOutlined />;
|
||||
if (isRtlLayout) {
|
||||
expandIcon = <LeftOutlined />;
|
||||
}
|
||||
|
||||
const loadingIcon = (
|
||||
<span className={`${prefixCls}-menu-item-loading-icon`}>
|
||||
@ -562,7 +587,9 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
|
||||
const getPopupContainer = props.getPopupContainer || getContextPopupContainer;
|
||||
const rest = omit(props, ['inputIcon', 'expandIcon', 'loadingIcon']);
|
||||
|
||||
const rcCascaderRtlPopupClassName = classNames(popupClassName, {
|
||||
[`${prefixCls}-menu-${direction}`]: direction === 'rtl',
|
||||
});
|
||||
return (
|
||||
<RcCascader
|
||||
{...rest}
|
||||
@ -576,6 +603,8 @@ class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||
dropdownMenuColumnStyle={dropdownMenuColumnStyle}
|
||||
expandIcon={expandIcon}
|
||||
loadingIcon={loadingIcon}
|
||||
popupClassName={rcCascaderRtlPopupClassName}
|
||||
popupPlacement={this.getPopupPlacement(direction)}
|
||||
>
|
||||
{input}
|
||||
</RcCascader>
|
||||
|
@ -3,6 +3,8 @@
|
||||
@import '../../input/style/mixin';
|
||||
|
||||
@cascader-prefix-cls: ~'@{ant-prefix}-cascader';
|
||||
@picker-rtl-cls: ~'@{cascader-prefix-cls}-picker-rtl';
|
||||
@menu-rtl-cls: ~'@{cascader-prefix-cls}-menu-rtl';
|
||||
|
||||
.@{cascader-prefix-cls} {
|
||||
.reset-component;
|
||||
@ -17,6 +19,12 @@
|
||||
// because input.less will compile after cascader.less
|
||||
background-color: transparent !important;
|
||||
cursor: pointer;
|
||||
|
||||
.@{picker-rtl-cls} & {
|
||||
padding-right: @input-padding-horizontal-base;
|
||||
padding-left: 24px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
&-picker-show-search &-input.@{ant-prefix}-input {
|
||||
@ -67,6 +75,11 @@
|
||||
line-height: 20px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.@{picker-rtl-cls} & {
|
||||
padding: 0 @control-padding-horizontal 0 20px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
&-clear {
|
||||
@ -87,6 +100,11 @@
|
||||
&:hover {
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{picker-rtl-cls} & {
|
||||
right: auto;
|
||||
left: @control-padding-horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &-clear {
|
||||
@ -109,6 +127,11 @@
|
||||
&&-expand {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.@{picker-rtl-cls} & {
|
||||
right: auto;
|
||||
left: @control-padding-horizontal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,6 +143,11 @@
|
||||
&-picker-small &-picker-clear,
|
||||
&-picker-small &-picker-arrow {
|
||||
right: @control-padding-horizontal-sm;
|
||||
|
||||
.@{picker-rtl-cls} & {
|
||||
right: auto;
|
||||
left: @control-padding-horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
&-menus {
|
||||
@ -182,6 +210,17 @@
|
||||
&:only-child {
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
border-right: none;
|
||||
border-left: @border-width-base @border-style-base @border-color-split;
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
margin-left: -1px;
|
||||
border-left-color: transparent;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-menu-item {
|
||||
padding: @cascader-dropdown-vertical-padding @control-padding-horizontal;
|
||||
@ -209,6 +248,11 @@
|
||||
&-expand {
|
||||
position: relative;
|
||||
padding-right: 24px;
|
||||
|
||||
.@{menu-rtl-cls} & {
|
||||
padding-right: @control-padding-horizontal;
|
||||
padding-left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&-expand &-expand-icon,
|
||||
@ -218,6 +262,11 @@
|
||||
position: absolute;
|
||||
right: @control-padding-horizontal;
|
||||
color: @text-color-secondary;
|
||||
|
||||
.@{menu-rtl-cls} & {
|
||||
right: auto;
|
||||
left: @control-padding-horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
& &-keyword {
|
||||
|
@ -0,0 +1,19 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Checkbox rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
`;
|
@ -44,3 +44,9 @@ exports[`CheckboxGroup passes prefixCls down to checkbox 1`] = `
|
||||
</label>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`CheckboxGroup rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-checkbox-group"
|
||||
/>
|
||||
`;
|
||||
|
@ -4,10 +4,12 @@ import Checkbox from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import { resetWarned } from '../../_util/warning';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Checkbox', () => {
|
||||
focusTest(Checkbox);
|
||||
mountTest(Checkbox);
|
||||
rtlTest(Checkbox);
|
||||
|
||||
it('responses hover events', () => {
|
||||
const onMouseEnter = jest.fn();
|
||||
|
@ -2,9 +2,11 @@ import React from 'react';
|
||||
import { mount, render } from 'enzyme';
|
||||
import Checkbox from '../index';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('CheckboxGroup', () => {
|
||||
mountTest(Checkbox.Group);
|
||||
rtlTest(Checkbox.Group);
|
||||
|
||||
it('should work basically', () => {
|
||||
const onChange = jest.fn();
|
||||
|
@ -59,7 +59,7 @@ export default class Collapse extends React.Component<CollapseProps, any> {
|
||||
: icon;
|
||||
};
|
||||
|
||||
renderCollapse = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderCollapse = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className = '',
|
||||
@ -71,6 +71,7 @@ export default class Collapse extends React.Component<CollapseProps, any> {
|
||||
{
|
||||
[`${prefixCls}-borderless`]: !bordered,
|
||||
[`${prefixCls}-icon-position-${expandIconPosition}`]: true,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
@ -1,5 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Collapse rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-left ant-collapse-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Collapse should render extra node of panel 1`] = `
|
||||
<div
|
||||
class="ant-collapse ant-collapse-icon-position-left"
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Collapse', () => {
|
||||
// Fix css-animation deps on these
|
||||
@ -17,6 +18,7 @@ describe('Collapse', () => {
|
||||
// eslint-disable-next-line global-require
|
||||
const Collapse = require('..').default;
|
||||
mountTest(Collapse);
|
||||
rtlTest(Collapse);
|
||||
|
||||
it('should support remove expandIcon', () => {
|
||||
const wrapper = mount(
|
||||
|
@ -11,6 +11,10 @@
|
||||
border-bottom: 0;
|
||||
border-radius: @collapse-panel-border-radius;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
& > &-item {
|
||||
border-bottom: @border-width-base @border-style-base @border-color-base;
|
||||
|
||||
@ -30,6 +34,11 @@
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
.@{collapse-prefix-cls}-rtl & {
|
||||
padding: @collapse-header-padding;
|
||||
padding-right: @collapse-header-padding-extra;
|
||||
}
|
||||
|
||||
.@{collapse-prefix-cls}-arrow {
|
||||
.iconfont-mixin();
|
||||
|
||||
@ -42,11 +51,19 @@
|
||||
|
||||
& svg {
|
||||
transition: transform 0.24s;
|
||||
|
||||
.@{collapse-prefix-cls}-rtl& {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{collapse-prefix-cls}-extra {
|
||||
float: right;
|
||||
|
||||
.@{collapse-prefix-cls}-rtl& {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
@ -57,6 +74,11 @@
|
||||
&.@{collapse-prefix-cls}-no-arrow {
|
||||
> .@{collapse-prefix-cls}-header {
|
||||
padding-left: 12px;
|
||||
|
||||
.@{collapse-prefix-cls}-rtl& {
|
||||
padding-right: 12px;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ exports[`renders ./components/comment/demo/basic.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
style="padding-left:8px;cursor:auto"
|
||||
class="comment-action"
|
||||
>
|
||||
0
|
||||
</span>
|
||||
@ -104,7 +104,7 @@ exports[`renders ./components/comment/demo/basic.md correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
style="padding-left:8px;cursor:auto"
|
||||
class="comment-action"
|
||||
>
|
||||
0
|
||||
</span>
|
||||
|
@ -0,0 +1,25 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Comment rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-comment ant-comment-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-comment-inner"
|
||||
>
|
||||
<div
|
||||
class="ant-comment-avatar"
|
||||
/>
|
||||
<div
|
||||
class="ant-comment-content"
|
||||
>
|
||||
<div
|
||||
class="ant-comment-content-author"
|
||||
/>
|
||||
<div
|
||||
class="ant-comment-content-detail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,6 +1,8 @@
|
||||
import Comment from '../index';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Comment', () => {
|
||||
mountTest(Comment);
|
||||
rtlTest(Comment);
|
||||
});
|
||||
|
@ -51,7 +51,7 @@ class App extends React.Component {
|
||||
onClick: this.like,
|
||||
})}
|
||||
</Tooltip>
|
||||
<span style={{ paddingLeft: 8, cursor: 'auto' }}>{likes}</span>
|
||||
<span className="comment-action">{likes}</span>
|
||||
</span>,
|
||||
<span key=' key="comment-basic-dislike"'>
|
||||
<Tooltip title="Dislike">
|
||||
@ -59,7 +59,7 @@ class App extends React.Component {
|
||||
onClick: this.dislike,
|
||||
})}
|
||||
</Tooltip>
|
||||
<span style={{ paddingLeft: 8, cursor: 'auto' }}>{dislikes}</span>
|
||||
<span className="comment-action">{dislikes}</span>
|
||||
</span>,
|
||||
<span key="comment-basic-reply-to">Reply to</span>,
|
||||
];
|
||||
@ -93,3 +93,16 @@ class App extends React.Component {
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
```
|
||||
|
||||
```css
|
||||
/* tile uploaded pictures */
|
||||
.comment-action {
|
||||
padding-left: 8px;
|
||||
cursor: 'auto';
|
||||
}
|
||||
|
||||
[class*='-col-rtl'] .comment-action {
|
||||
padding-right: 8px;
|
||||
padding-left: 0;
|
||||
}
|
||||
```
|
||||
|
@ -37,7 +37,7 @@ export default class Comment extends React.Component<CommentProps, {}> {
|
||||
return <div className={classNames(`${prefixCls}-nested`)}>{children}</div>;
|
||||
};
|
||||
|
||||
renderComment = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderComment = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
actions,
|
||||
author,
|
||||
@ -86,8 +86,11 @@ export default class Comment extends React.Component<CommentProps, {}> {
|
||||
</div>
|
||||
);
|
||||
|
||||
const cls = classNames(prefixCls, className, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
return (
|
||||
<div {...otherProps} className={classNames(prefixCls, className)} style={style}>
|
||||
<div {...otherProps} className={cls} style={style}>
|
||||
{comment}
|
||||
{children ? this.renderNested(prefixCls, children) : null}
|
||||
</div>
|
||||
|
@ -7,6 +7,10 @@
|
||||
position: relative;
|
||||
background-color: @comment-bg;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-inner {
|
||||
display: flex;
|
||||
padding: @comment-padding-base;
|
||||
@ -17,6 +21,11 @@
|
||||
flex-shrink: 0;
|
||||
margin-right: 12px;
|
||||
cursor: pointer;
|
||||
|
||||
.@{comment-prefix-cls}-rtl & {
|
||||
margin-right: 0;
|
||||
margin-left: 12px;
|
||||
}
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@ -42,6 +51,11 @@
|
||||
padding-right: 8px;
|
||||
font-size: @comment-font-size-sm;
|
||||
line-height: 18px;
|
||||
|
||||
.@{comment-prefix-cls}-rtl & {
|
||||
padding-right: 0;
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&-name {
|
||||
@ -71,6 +85,10 @@
|
||||
&-actions {
|
||||
margin-top: 12px;
|
||||
padding-left: 0;
|
||||
|
||||
.@{comment-prefix-cls}-rtl & {
|
||||
padding-right: 0;
|
||||
}
|
||||
> li {
|
||||
display: inline-block;
|
||||
color: @comment-action-color;
|
||||
@ -81,6 +99,12 @@
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
user-select: none;
|
||||
|
||||
.@{comment-prefix-cls}-rtl & {
|
||||
padding-right: 0;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: @comment-action-hover-color;
|
||||
}
|
||||
@ -90,5 +114,10 @@
|
||||
|
||||
&-nested {
|
||||
margin-left: @comment-nest-indent;
|
||||
|
||||
.@{comment-prefix-cls}-rtl & {
|
||||
margin-right: @comment-nest-indent;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ export interface ConfigConsumerProps {
|
||||
pageHeader?: {
|
||||
ghost: boolean;
|
||||
};
|
||||
direction?: 'ltr' | 'rtl';
|
||||
}
|
||||
|
||||
export const ConfigContext = React.createContext<ConfigConsumerProps>({
|
||||
|
613
components/config-provider/demo/direction.md
Normal file
613
components/config-provider/demo/direction.md
Normal file
@ -0,0 +1,613 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 方向
|
||||
en-US: Direction
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
这里列出了支持 `rtl` 方向的组件,您可以在演示中切换方向。
|
||||
|
||||
## en-US
|
||||
|
||||
Components which support rtl direction are listed here, you can toggle the direction in the demo.
|
||||
|
||||
```jsx
|
||||
import {
|
||||
Input,
|
||||
Col,
|
||||
Row,
|
||||
Select,
|
||||
InputNumber,
|
||||
ConfigProvider,
|
||||
Cascader,
|
||||
Radio,
|
||||
Switch,
|
||||
Tree,
|
||||
TreeSelect,
|
||||
Modal,
|
||||
Button,
|
||||
Pagination,
|
||||
Steps,
|
||||
Rate,
|
||||
Badge,
|
||||
} from 'antd';
|
||||
|
||||
import {
|
||||
SearchOutlined as SearchIcon,
|
||||
SmileOutlined,
|
||||
DownloadOutlined,
|
||||
LeftOutlined,
|
||||
RightOutlined,
|
||||
MinusOutlined,
|
||||
PlusOutlined,
|
||||
} from '@ant-design/icons';
|
||||
|
||||
const InputGroup = Input.Group;
|
||||
const ButtonGroup = Button.Group;
|
||||
const { Option } = Select;
|
||||
const { TreeNode } = Tree;
|
||||
const { Search } = Input;
|
||||
const { Step } = Steps;
|
||||
|
||||
const cascaderOptions = [
|
||||
{
|
||||
value: 'tehran',
|
||||
label: 'تهران',
|
||||
children: [
|
||||
{
|
||||
value: 'tehran-c',
|
||||
label: 'تهران',
|
||||
children: [
|
||||
{
|
||||
value: 'saadat-abad',
|
||||
label: 'سعادت آیاد',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'ardabil',
|
||||
label: 'اردبیل',
|
||||
children: [
|
||||
{
|
||||
value: 'ardabil-c',
|
||||
label: 'اردبیل',
|
||||
children: [
|
||||
{
|
||||
value: 'primadar',
|
||||
label: 'پیرمادر',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'gilan',
|
||||
label: 'گیلان',
|
||||
children: [
|
||||
{
|
||||
value: 'rasht',
|
||||
label: 'رشت',
|
||||
children: [
|
||||
{
|
||||
value: 'district-3',
|
||||
label: 'منطقه ۳',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
class Page extends React.Component {
|
||||
state = {
|
||||
currentStep: 0,
|
||||
modalVisible: false,
|
||||
|
||||
badgeCount: 5,
|
||||
showBadge: true,
|
||||
};
|
||||
|
||||
selectBefore = (
|
||||
<Select defaultValue="Http://" style={{ width: 90 }}>
|
||||
<Option value="Http://">Http://</Option>
|
||||
<Option value="Https://">Https://</Option>
|
||||
</Select>
|
||||
);
|
||||
|
||||
selectAfter = (
|
||||
<Select defaultValue=".com" style={{ width: 80 }}>
|
||||
<Option value=".com">.com</Option>
|
||||
<Option value=".jp">.jp</Option>
|
||||
<Option value=".cn">.cn</Option>
|
||||
<Option value=".org">.org</Option>
|
||||
</Select>
|
||||
);
|
||||
|
||||
// ==== Cascader ====
|
||||
cascaderFilter = (inputValue, path) => {
|
||||
return path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
|
||||
};
|
||||
|
||||
onCascaderChange = value => {
|
||||
console.log(value);
|
||||
};
|
||||
// ==== End Cascader ====
|
||||
|
||||
// ==== Modal ====
|
||||
showModal = () => {
|
||||
this.setState({
|
||||
modalVisible: true,
|
||||
});
|
||||
};
|
||||
|
||||
handleOk = e => {
|
||||
console.log(e);
|
||||
this.setState({
|
||||
modalVisible: false,
|
||||
});
|
||||
};
|
||||
|
||||
handleCancel = e => {
|
||||
console.log(e);
|
||||
this.setState({
|
||||
modalVisible: false,
|
||||
});
|
||||
};
|
||||
// ==== End Modal ====
|
||||
|
||||
onStepsChange = currentStep => {
|
||||
console.log('onChange:', currentStep);
|
||||
this.setState({ currentStep });
|
||||
};
|
||||
|
||||
// ==== Badge ====
|
||||
|
||||
increaseBadge = () => {
|
||||
const badgeCount = this.state.badgeCount + 1;
|
||||
this.setState({ badgeCount });
|
||||
};
|
||||
|
||||
declineBadge = () => {
|
||||
let badgeCount = this.state.badgeCount - 1;
|
||||
if (badgeCount < 0) {
|
||||
badgeCount = 0;
|
||||
}
|
||||
this.setState({ badgeCount });
|
||||
};
|
||||
|
||||
onChangeBadge = showBadge => {
|
||||
this.setState({ showBadge });
|
||||
};
|
||||
// ==== End Badge ====
|
||||
|
||||
render() {
|
||||
const { currentStep } = this.state;
|
||||
return (
|
||||
<div className="direction-components example">
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<h3 className="demo-block-title">Cascader example:</h3>
|
||||
<Cascader
|
||||
suffixIcon={<SearchIcon />}
|
||||
options={cascaderOptions}
|
||||
onChange={this.onCascaderChange}
|
||||
placeholder="یک مورد انتخاب کنید"
|
||||
popupPlacement={this.props.popupPlacement}
|
||||
/>
|
||||
With search:
|
||||
<Cascader
|
||||
suffixIcon={<SmileOutlined />}
|
||||
options={cascaderOptions}
|
||||
onChange={this.onCascaderChange}
|
||||
placeholder="Select an item"
|
||||
popupPlacement={this.props.popupPlacement}
|
||||
showSearch={this.cascaderFilter}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">Switch example:</h3>
|
||||
|
||||
<Switch defaultChecked />
|
||||
|
||||
<Switch loading defaultChecked />
|
||||
|
||||
<Switch size="small" loading />
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">Radio Group example:</h3>
|
||||
|
||||
<Radio.Group defaultValue="c" buttonStyle="solid">
|
||||
<Radio.Button value="a">تهران</Radio.Button>
|
||||
<Radio.Button value="b" disabled>
|
||||
اصفهان
|
||||
</Radio.Button>
|
||||
<Radio.Button value="c">فارس</Radio.Button>
|
||||
<Radio.Button value="d">خوزستان</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">Button example:</h3>
|
||||
<div className="button-demo">
|
||||
<Button type="primary" icon={<DownloadOutlined />} />
|
||||
<Button type="primary" shape="circle" icon={<DownloadOutlined />} />
|
||||
<Button type="primary" shape="round" icon={<DownloadOutlined />} />
|
||||
<Button type="primary" shape="round" icon={<DownloadOutlined />}>
|
||||
Download
|
||||
</Button>
|
||||
<Button type="primary" icon={<DownloadOutlined />}>
|
||||
Download
|
||||
</Button>
|
||||
<br />
|
||||
<Button.Group>
|
||||
<Button type="primary">
|
||||
<LeftOutlined />
|
||||
Backward
|
||||
</Button>
|
||||
<Button type="primary">
|
||||
Forward
|
||||
<RightOutlined />
|
||||
</Button>
|
||||
</Button.Group>
|
||||
<Button type="primary" loading>
|
||||
Loading
|
||||
</Button>
|
||||
<Button type="primary" size="small" loading>
|
||||
Loading
|
||||
</Button>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">Tree example:</h3>
|
||||
<Tree
|
||||
showLine
|
||||
checkable
|
||||
defaultExpandedKeys={['0-0-0', '0-0-1']}
|
||||
defaultSelectedKeys={['0-0-0', '0-0-1']}
|
||||
defaultCheckedKeys={['0-0-0', '0-0-1']}
|
||||
>
|
||||
<TreeNode title="parent 1" key="0-0">
|
||||
<TreeNode title="parent 1-0" key="0-0-0" disabled>
|
||||
<TreeNode title="leaf" key="0-0-0-0" disableCheckbox />
|
||||
<TreeNode title="leaf" key="0-0-0-1" />
|
||||
</TreeNode>
|
||||
<TreeNode title="parent 1-1" key="0-0-1">
|
||||
<TreeNode title={<span style={{ color: '#1890ff' }}>sss</span>} key="0-0-1-0" />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</Tree>
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<h3 className="demo-block-title">Input (Input Group) example:</h3>
|
||||
<InputGroup size="large">
|
||||
<Row gutter={8}>
|
||||
<Col span={5}>
|
||||
<Input defaultValue="0571" />
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Input defaultValue="26888888" />
|
||||
</Col>
|
||||
</Row>
|
||||
</InputGroup>
|
||||
<br />
|
||||
<InputGroup compact>
|
||||
<Input style={{ width: '20%' }} defaultValue="0571" />
|
||||
<Input style={{ width: '30%' }} defaultValue="26888888" />
|
||||
</InputGroup>
|
||||
<br />
|
||||
<InputGroup compact>
|
||||
<Select defaultValue="Option1">
|
||||
<Option value="Option1">Option1</Option>
|
||||
<Option value="Option2">Option2</Option>
|
||||
</Select>
|
||||
<Input style={{ width: '50%' }} defaultValue="input content" />
|
||||
<InputNumber />
|
||||
</InputGroup>
|
||||
<br />
|
||||
<Search placeholder="input search text" enterButton="Search" size="large" />
|
||||
<br />
|
||||
<br />
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<Input
|
||||
addonBefore={this.selectBefore}
|
||||
addonAfter={this.selectAfter}
|
||||
defaultValue="mysite"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">Select example:</h3>
|
||||
<Select mode="multiple" defaultValue="مورچه" style={{ width: 120 }}>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="مورچه">مورچه</Option>
|
||||
<Option value="disabled" disabled>
|
||||
Disabled
|
||||
</Option>
|
||||
<Option value="Yiminghe">yiminghe</Option>
|
||||
</Select>
|
||||
<Select defaultValue="مورچه" style={{ width: 120 }} disabled>
|
||||
<Option value="مورچه">مورچه</Option>
|
||||
</Select>
|
||||
<Select defaultValue="مورچه" style={{ width: 120 }} loading>
|
||||
<Option value="مورچه">مورچه</Option>
|
||||
</Select>
|
||||
<Select
|
||||
showSearch
|
||||
style={{ width: 200 }}
|
||||
placeholder="Select a person"
|
||||
optionFilterProp="children"
|
||||
filterOption={(input, option) =>
|
||||
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="سعید">سعید</Option>
|
||||
<Option value="tom">Tom</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">TreeSelect example:</h3>
|
||||
<div>
|
||||
<TreeSelect
|
||||
showSearch
|
||||
style={{ width: '100%' }}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
treeDefaultExpandAll
|
||||
>
|
||||
<TreeNode value="parent 1" title="parent 1" key="0-1">
|
||||
<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
|
||||
<TreeNode value="leaf1" title="my leaf" key="random" />
|
||||
<TreeNode value="leaf2" title="your leaf" key="random1" />
|
||||
</TreeNode>
|
||||
<TreeNode value="parent 1-1" title="parent 1-1" key="random2">
|
||||
<TreeNode
|
||||
value="sss"
|
||||
title={<b style={{ color: '#08c' }}>sss</b>}
|
||||
key="random3"
|
||||
/>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<h3 className="demo-block-title">Modal example:</h3>
|
||||
<div>
|
||||
<Button type="primary" onClick={this.showModal}>
|
||||
Open Modal
|
||||
</Button>
|
||||
<Modal
|
||||
title="پنچره ساده"
|
||||
visible={this.state.modalVisible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
>
|
||||
<p>نگاشتههای خود را اینجا قراردهید</p>
|
||||
<p>نگاشتههای خود را اینجا قراردهید</p>
|
||||
<p>نگاشتههای خود را اینجا قراردهید</p>
|
||||
</Modal>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<h3 className="demo-block-title">Steps example:</h3>
|
||||
<div>
|
||||
<Steps progressDot current={currentStep}>
|
||||
<Step title="Finished" description="This is a description." />
|
||||
<Step title="In Progress" description="This is a description." />
|
||||
<Step title="Waiting" description="This is a description." />
|
||||
</Steps>
|
||||
<br />
|
||||
<Steps current={currentStep} onChange={this.onStepsChange}>
|
||||
<Step title="Step 1" description="This is a description." />
|
||||
<Step title="Step 2" description="This is a description." />
|
||||
<Step title="Step 3" description="This is a description." />
|
||||
</Steps>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">Rate example:</h3>
|
||||
<div>
|
||||
<Rate defaultValue={2.5} />
|
||||
<br />
|
||||
<strong>* Note:</strong> Half star not implemented in RTL direction, it will be
|
||||
supported after <a href="https://github.com/react-component/rate">rc-rate</a>{' '}
|
||||
implement rtl support.
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<h3 className="demo-block-title">Badge example:</h3>
|
||||
<div>
|
||||
<div>
|
||||
<Badge count={this.state.badgeCount}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
<ButtonGroup>
|
||||
<Button onClick={this.declineBadge}>
|
||||
<MinusOutlined />
|
||||
</Button>
|
||||
<Button onClick={this.increaseBadge}>
|
||||
<PlusOutlined />
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<div style={{ marginTop: 10 }}>
|
||||
<Badge dot={this.state.showBadge}>
|
||||
<a href="#" className="head-example" />
|
||||
</Badge>
|
||||
<Switch onChange={this.onChangeBadge} checked={this.state.showBadge} />
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<h3 className="demo-block-title">Pagination example:</h3>
|
||||
<Pagination showSizeChanger defaultCurrent={3} total={500} />
|
||||
</Col>
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<h3 className="demo-block-title">Grid System example:</h3>
|
||||
<div className="grid-demo">
|
||||
<div className="code-box-demo">
|
||||
<p>
|
||||
<strong>* Note:</strong> Every calculation in RTL grid system is from right side
|
||||
(offset, push, etc.)
|
||||
</p>
|
||||
<Row>
|
||||
<Col span={8}>col-8</Col>
|
||||
<Col span={8} offset={8}>
|
||||
col-8
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={6} offset={6}>
|
||||
col-6 col-offset-6
|
||||
</Col>
|
||||
<Col span={6} offset={6}>
|
||||
col-6 col-offset-6
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={12} offset={6}>
|
||||
col-12 col-offset-6
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={18} push={6}>
|
||||
col-18 col-push-6
|
||||
</Col>
|
||||
<Col span={6} pull={18}>
|
||||
col-6 col-pull-18
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
direction: 'ltr',
|
||||
popupPlacement: 'bottomLeft',
|
||||
};
|
||||
|
||||
changeDirection = e => {
|
||||
const directionValue = e.target.value;
|
||||
this.setState({ direction: directionValue });
|
||||
if (directionValue === 'rtl') {
|
||||
this.setState({ popupPlacement: 'bottomRight' });
|
||||
} else {
|
||||
this.setState({ popupPlacement: 'bottomLeft' });
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { direction } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<div className="change-direction">
|
||||
<span style={{ marginRight: 16 }}>Change direction of components: </span>
|
||||
<Radio.Group defaultValue="ltr" onChange={this.changeDirection}>
|
||||
<Radio.Button key="ltr" value="ltr">
|
||||
LTR
|
||||
</Radio.Button>
|
||||
<Radio.Button key="rtl" value="rtl">
|
||||
RTL
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
<ConfigProvider direction={direction}>
|
||||
<Page className={direction} popupPlacement={this.state.popupPlacement} />
|
||||
</ConfigProvider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
```
|
||||
|
||||
```css
|
||||
.direction-components {
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid rgba(150, 150, 150, 0.5);
|
||||
}
|
||||
|
||||
.example {
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.example > * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.change-direction {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.demo-block-title {
|
||||
margin: 0 8px 18px 8px;
|
||||
border-bottom: 1px solid rgba(150, 150, 150, 0.5);
|
||||
}
|
||||
.button-demo .ant-btn,
|
||||
.button-demo .ant-btn-group {
|
||||
margin-right: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.button-demo .ant-btn-group > .ant-btn,
|
||||
.button-demo .ant-btn-group > span > .ant-btn {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
.head-example {
|
||||
display: inline-block;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
vertical-align: middle;
|
||||
background: #eee;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ant-badge:not(.ant-badge-not-a-wrapper) {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.ant-badge-rtl:not(.ant-badge-not-a-wrapper) {
|
||||
margin-right: 0;
|
||||
margin-left: 20px;
|
||||
}
|
||||
```
|
@ -45,6 +45,7 @@ Some components use dynamic style to support wave effect. You can config `csp` p
|
||||
| locale | language package setting, you can find the packages in [antd/es/locale](http://unpkg.com/antd/es/locale/) | object | |
|
||||
| prefixCls | set prefix class | string | ant | |
|
||||
| pageHeader | Unify the ghost of pageHeader ,Ref [pageHeader](<(/components/page-header)> | { ghost:boolean } | 'true' | |
|
||||
| direction | set direction of layout. See [demo](#components-config-provider-demo-direction) | string: 'ltr', 'rtl' | ltr | |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -36,6 +36,7 @@ export interface ConfigProviderProps {
|
||||
pageHeader?: {
|
||||
ghost: boolean;
|
||||
};
|
||||
direction?: 'ltr' | 'rtl';
|
||||
}
|
||||
|
||||
class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
@ -57,6 +58,7 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
form,
|
||||
locale,
|
||||
pageHeader,
|
||||
direction,
|
||||
} = this.props;
|
||||
|
||||
const config: ConfigConsumerProps = {
|
||||
@ -65,6 +67,7 @@ class ConfigProvider extends React.Component<ConfigProviderProps> {
|
||||
csp,
|
||||
autoInsertSpaceInButton,
|
||||
locale: locale || legacyLocale,
|
||||
direction,
|
||||
};
|
||||
|
||||
if (getPopupContainer) {
|
||||
|
@ -46,6 +46,7 @@ return (
|
||||
| locale | 语言包配置,语言包可到 [antd/es/locale](http://unpkg.com/antd/es/locale/) 目录下寻找 | object | - | |
|
||||
| prefixCls | 设置统一样式前缀 | string | ant | |
|
||||
| pageHeader | 统一设置 pageHeader 的 ghost,参考 [pageHeader](<(/components/page-header)>) | { ghost: boolean } | 'true' | |
|
||||
| direction | 设置文本展示方向。 [示例](#components-config-provider-demo-direction) | string: 'ltr', 'rtl' | ltr | |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
@ -0,0 +1,188 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`mount rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-picker ant-picker-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
placeholder="Select date"
|
||||
readonly=""
|
||||
size="12"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-picker-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="calendar"
|
||||
class="anticon anticon-calendar"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="calendar"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`mount rtl render component should be rendered correctly in RTL direction 2`] = `
|
||||
<div
|
||||
class="ant-picker ant-picker-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
placeholder="Select month"
|
||||
readonly=""
|
||||
size="12"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-picker-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="calendar"
|
||||
class="anticon anticon-calendar"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="calendar"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`mount rtl render component should be rendered correctly in RTL direction 3`] = `
|
||||
<div
|
||||
class="ant-picker ant-picker-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
placeholder="Select week"
|
||||
readonly=""
|
||||
size="12"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-picker-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="calendar"
|
||||
class="anticon anticon-calendar"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="calendar"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`mount rtl render component should be rendered correctly in RTL direction 4`] = `
|
||||
<div
|
||||
class="ant-picker ant-picker-range ant-picker-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-picker-input ant-picker-input-active"
|
||||
>
|
||||
<input
|
||||
placeholder="Start date"
|
||||
readonly=""
|
||||
size="12"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-range-separator"
|
||||
>
|
||||
<span
|
||||
class="ant-picker-separator"
|
||||
>
|
||||
→
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-input"
|
||||
>
|
||||
<input
|
||||
placeholder="End date"
|
||||
readonly=""
|
||||
size="12"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-picker-active-bar"
|
||||
style="right:0;width:0;position:absolute"
|
||||
/>
|
||||
<span
|
||||
class="ant-picker-suffix"
|
||||
>
|
||||
<span
|
||||
aria-label="calendar"
|
||||
class="anticon anticon-calendar"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="calendar"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zm-40 656H184V460h656v380zM184 392V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v136H184z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
@ -1,5 +1,6 @@
|
||||
import DatePicker from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
const { MonthPicker, WeekPicker, RangePicker } = DatePicker;
|
||||
|
||||
@ -8,4 +9,9 @@ describe('mount', () => {
|
||||
mountTest(MonthPicker);
|
||||
mountTest(WeekPicker);
|
||||
mountTest(RangePicker);
|
||||
|
||||
rtlTest(DatePicker);
|
||||
rtlTest(MonthPicker);
|
||||
rtlTest(WeekPicker);
|
||||
rtlTest(RangePicker);
|
||||
});
|
||||
|
@ -142,7 +142,7 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
};
|
||||
|
||||
renderPicker = (locale: any) => {
|
||||
const { getPrefixCls } = this.context;
|
||||
const { getPrefixCls, direction } = this.context;
|
||||
const { prefixCls: customizePrefixCls, className, size, ...restProps } = this.props;
|
||||
const { format, showTime } = this.props as any;
|
||||
const prefixCls = getPrefixCls('picker', customizePrefixCls);
|
||||
@ -187,6 +187,7 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
superPrevIcon={<span className={`${prefixCls}-super-prev-icon`} />}
|
||||
superNextIcon={<span className={`${prefixCls}-super-next-icon`} />}
|
||||
components={Components}
|
||||
direction={direction}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -247,7 +248,7 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
};
|
||||
|
||||
renderPicker = (locale: any) => {
|
||||
const { getPrefixCls } = this.context;
|
||||
const { getPrefixCls, direction } = this.context;
|
||||
const { prefixCls: customizePrefixCls, className, size, ...restProps } = this.props;
|
||||
const { format, showTime, picker } = this.props as any;
|
||||
const prefixCls = getPrefixCls('picker', customizePrefixCls);
|
||||
@ -282,6 +283,7 @@ function generatePicker<DateType>(generateConfig: GenerateConfig<DateType>) {
|
||||
superPrevIcon={<span className={`${prefixCls}-super-prev-icon`} />}
|
||||
superNextIcon={<span className={`${prefixCls}-super-next-icon`} />}
|
||||
components={Components}
|
||||
direction={direction}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -32,6 +32,10 @@
|
||||
border-radius: @border-radius-base;
|
||||
transition: border @animation-duration-slow, box-shadow @animation-duration-slow;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&-focused {
|
||||
.hover();
|
||||
@ -99,6 +103,11 @@
|
||||
margin-left: @padding-xs / 2;
|
||||
color: @disabled-color;
|
||||
pointer-events: none;
|
||||
|
||||
.@{picker-prefix-cls}-rtl & {
|
||||
margin-right: @padding-xs / 2;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-clear {
|
||||
@ -115,6 +124,11 @@
|
||||
&:hover {
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{picker-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-separator {
|
||||
@ -126,6 +140,11 @@
|
||||
font-size: @font-size-lg;
|
||||
line-height: @font-size-lg;
|
||||
text-align: center;
|
||||
|
||||
.@{picker-prefix-cls}-rtl & {
|
||||
transform: rotate(180deg);
|
||||
transform-origin: 50% 60%;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== Range =========================
|
||||
@ -136,6 +155,11 @@
|
||||
// Clear
|
||||
.@{picker-prefix-cls}-clear {
|
||||
right: @input-padding-horizontal-base;
|
||||
|
||||
.@{picker-prefix-cls}-rtl& {
|
||||
right: auto;
|
||||
left: @input-padding-horizontal-base;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@ -211,6 +235,10 @@
|
||||
text-align: left;
|
||||
list-style: none;
|
||||
|
||||
.@{picker-prefix-cls}-dropdown-rtl & {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
> li {
|
||||
display: inline-block;
|
||||
}
|
||||
@ -222,6 +250,12 @@
|
||||
.@{picker-prefix-cls}-ok {
|
||||
float: right;
|
||||
margin-left: @padding-xs;
|
||||
|
||||
.@{picker-prefix-cls}-dropdown-rtl & {
|
||||
float: left;
|
||||
margin-right: @padding-xs;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,10 @@
|
||||
border-radius: @border-radius-base;
|
||||
outline: none;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-focused {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
@ -126,11 +130,19 @@
|
||||
&-prev-icon,
|
||||
&-super-prev-icon {
|
||||
transform: rotate(-45deg);
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
}
|
||||
|
||||
&-next-icon,
|
||||
&-super-next-icon {
|
||||
transform: rotate(135deg);
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== Body ========================
|
||||
@ -226,9 +238,19 @@
|
||||
|
||||
&-in-view&-range-start::before {
|
||||
left: 50%;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: 50%;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
&-in-view&-range-end::before {
|
||||
right: 50%;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: 0;
|
||||
left: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// >>> Range Hover
|
||||
@ -289,18 +311,38 @@
|
||||
.@{cellClassName}::after {
|
||||
right: -6px - @border-width-base;
|
||||
left: 0;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: 0;
|
||||
left: -6px - @border-width-base;
|
||||
}
|
||||
}
|
||||
.@{picker-prefix-cls}-date-panel &-in-view&-in-range&-range-hover-end .@{cellClassName}::after {
|
||||
right: 0;
|
||||
left: -6px - @border-width-base;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: -6px - @border-width-base;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Hover with range start & end
|
||||
&-range-hover&-range-start::after {
|
||||
right: 50%;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: 0;
|
||||
left: 50%;
|
||||
}
|
||||
}
|
||||
&-range-hover&-range-end::after {
|
||||
left: 50%;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: 50%;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Edge start
|
||||
@ -312,6 +354,15 @@
|
||||
border-left: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-top-left-radius: @border-radius-base;
|
||||
border-bottom-left-radius: @border-radius-base;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: 6px;
|
||||
left: 0;
|
||||
border-right: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-left: none;
|
||||
border-top-right-radius: @border-radius-base;
|
||||
border-bottom-right-radius: @border-radius-base;
|
||||
}
|
||||
}
|
||||
|
||||
// Edge end
|
||||
@ -323,6 +374,15 @@
|
||||
border-right: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-top-right-radius: @border-radius-base;
|
||||
border-bottom-right-radius: @border-radius-base;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: 0;
|
||||
left: 6px;
|
||||
border-right: none;
|
||||
border-left: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-top-left-radius: @border-radius-base;
|
||||
border-bottom-left-radius: @border-radius-base;
|
||||
}
|
||||
}
|
||||
|
||||
// >>> Disabled
|
||||
@ -451,11 +511,23 @@
|
||||
left: @hover-cell-fixed-distance;
|
||||
border-left: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
right: @hover-cell-fixed-distance;
|
||||
border-right: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
}
|
||||
}
|
||||
.@{picker-prefix-cls}-cell-range-hover-end::after {
|
||||
right: @hover-cell-fixed-distance;
|
||||
border-right: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
left: @hover-cell-fixed-distance;
|
||||
border-left: @border-width-base dashed @picker-date-hover-range-border-color;
|
||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -548,6 +620,10 @@
|
||||
width: auto;
|
||||
min-width: auto;
|
||||
|
||||
.@{picker-prefix-cls}-panel-rtl & {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.@{picker-prefix-cls}-content {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
|
@ -224,7 +224,7 @@ class Descriptions extends React.Component<
|
||||
render() {
|
||||
return (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
{({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
className,
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -258,6 +258,7 @@ class Descriptions extends React.Component<
|
||||
className={classNames(prefixCls, className, {
|
||||
[`${prefixCls}-${size}`]: size !== 'default',
|
||||
[`${prefixCls}-bordered`]: !!bordered,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
})}
|
||||
style={style}
|
||||
>
|
||||
|
@ -8,6 +8,10 @@
|
||||
@descriptions-small-padding: 8px 16px;
|
||||
|
||||
.@{descriptions-prefix-cls} {
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-title {
|
||||
margin-bottom: 20px;
|
||||
color: @heading-color;
|
||||
@ -48,6 +52,10 @@
|
||||
top: -0.5px;
|
||||
margin: 0 8px 0 2px;
|
||||
content: ' ';
|
||||
|
||||
.@{descriptions-prefix-cls}-rtl & {
|
||||
margin: 0 2px 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,11 @@ import React from 'react';
|
||||
import { render } from 'enzyme';
|
||||
import Drawer from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Drawer', () => {
|
||||
mountTest(Drawer);
|
||||
rtlTest(Drawer);
|
||||
|
||||
it('render correctly', () => {
|
||||
const wrapper = render(
|
||||
|
@ -350,6 +350,8 @@ exports[`Drawer render top drawer 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Drawer rtl render component should be rendered correctly in RTL direction 1`] = `null`;
|
||||
|
||||
exports[`Drawer style/drawerStyle/headerStyle/bodyStyle should work 1`] = `
|
||||
<div
|
||||
class=""
|
||||
|
@ -69,14 +69,7 @@ class App extends React.Component {
|
||||
This is two-level drawer
|
||||
</Drawer>
|
||||
<div className="site-multi-level-drawer-footer">
|
||||
<Button
|
||||
style={{
|
||||
marginRight: 8,
|
||||
}}
|
||||
onClick={this.onClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={this.onClose}>Cancel</Button>
|
||||
<Button onClick={this.onClose} type="primary">
|
||||
Submit
|
||||
</Button>
|
||||
@ -102,6 +95,21 @@ ReactDOM.render(<App />, mountNode);
|
||||
border-radius: 0 0 4px 4px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.site-multi-level-drawer-footer button:first-child {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
[class*='-drawer-rtl'] .site-multi-level-drawer-footer {
|
||||
text-align: left;
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
[class*='-drawer-rtl'] .site-multi-level-drawer-footer button:first-child {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
```
|
||||
|
||||
<style>
|
||||
|
@ -206,7 +206,7 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
||||
|
||||
// render Provider for Multi-level drawer
|
||||
renderProvider = (value: Drawer) => {
|
||||
const { prefixCls, placement, className, width, height, mask, ...rest } = this.props;
|
||||
const { prefixCls, placement, className, width, height, mask, direction, ...rest } = this.props;
|
||||
const haveMask = mask ? '' : 'no-mask';
|
||||
this.parentDrawer = value;
|
||||
const offsetStyle: any = {};
|
||||
@ -215,6 +215,9 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
||||
} else {
|
||||
offsetStyle.height = height;
|
||||
}
|
||||
const drawerClassName = classNames(className, haveMask, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
return (
|
||||
<DrawerContext.Provider value={this}>
|
||||
<RcDrawer
|
||||
@ -244,7 +247,7 @@ class Drawer extends React.Component<DrawerProps & ConfigConsumerProps, IDrawerS
|
||||
showMask={mask}
|
||||
placement={placement}
|
||||
style={this.getRcDrawerStyle()}
|
||||
className={classNames(className, haveMask)}
|
||||
className={drawerClassName}
|
||||
>
|
||||
{this.renderBody()}
|
||||
</RcDrawer>
|
||||
|
@ -14,6 +14,10 @@
|
||||
box-shadow @animation-duration-slow @ease-base-out;
|
||||
}
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-content-wrapper {
|
||||
position: absolute;
|
||||
}
|
||||
@ -40,6 +44,14 @@
|
||||
}
|
||||
|
||||
&-left {
|
||||
left: 0;
|
||||
|
||||
.@{drawer-prefix-cls} {
|
||||
&-content-wrapper {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.@{drawer-prefix-cls}-open {
|
||||
.@{drawer-prefix-cls}-content-wrapper {
|
||||
box-shadow: @shadow-1-right;
|
||||
@ -166,6 +178,11 @@
|
||||
transition: color @animation-duration-slow;
|
||||
text-rendering: auto;
|
||||
|
||||
.@{drawer-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: @icon-color-hover;
|
||||
|
@ -1,5 +1,47 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`DropdownButton rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<span
|
||||
class="ant-dropdown-trigger ant-dropdown-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`DropdownButton rtl render component should be rendered correctly in RTL direction 2`] = `
|
||||
<div
|
||||
class="ant-btn-group ant-btn-group-rtl ant-dropdown-button"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-default ant-btn-rtl"
|
||||
type="button"
|
||||
/>
|
||||
<button
|
||||
class="ant-btn ant-dropdown-trigger ant-dropdown-rtl ant-btn-default ant-btn-rtl"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="ellipsis"
|
||||
class="anticon anticon-ellipsis"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
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>
|
||||
`;
|
||||
|
||||
exports[`DropdownButton should support href like Button 1`] = `
|
||||
<div
|
||||
class="ant-btn-group ant-dropdown-button"
|
||||
|
@ -3,6 +3,7 @@ import { mount } from 'enzyme';
|
||||
import Dropdown from '..';
|
||||
import Menu from '../../menu';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('DropdownButton', () => {
|
||||
mountTest(() => (
|
||||
@ -12,6 +13,13 @@ describe('DropdownButton', () => {
|
||||
));
|
||||
mountTest(Dropdown.Button);
|
||||
|
||||
rtlTest(() => (
|
||||
<Dropdown menu={<Menu />}>
|
||||
<span />
|
||||
</Dropdown>
|
||||
));
|
||||
rtlTest(Dropdown.Button);
|
||||
|
||||
it('pass appropriate props to Dropdown', () => {
|
||||
const props = {
|
||||
align: {
|
||||
|
@ -59,7 +59,6 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
static defaultProps = {
|
||||
mouseEnterDelay: 0.15,
|
||||
mouseLeaveDelay: 0.1,
|
||||
placement: 'bottomLeft' as Placement,
|
||||
};
|
||||
|
||||
getTransitionName() {
|
||||
@ -118,9 +117,18 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
return fixedModeOverlay as React.ReactElement;
|
||||
};
|
||||
|
||||
getPlacement(direction: string = 'ltr') {
|
||||
const { placement } = this.props;
|
||||
if (placement !== undefined) {
|
||||
return placement;
|
||||
}
|
||||
return direction === 'rtl' ? ('bottomRight' as Placement) : ('bottomLeft' as Placement);
|
||||
}
|
||||
|
||||
renderDropDown = ({
|
||||
getPopupContainer: getContextPopupContainer,
|
||||
getPrefixCls,
|
||||
direction,
|
||||
}: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -128,16 +136,23 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
trigger,
|
||||
disabled,
|
||||
getPopupContainer,
|
||||
overlayClassName,
|
||||
} = this.props;
|
||||
|
||||
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
|
||||
const child = React.Children.only(children) as React.ReactElement<any>;
|
||||
|
||||
const dropdownTrigger = React.cloneElement(child, {
|
||||
className: classNames(child.props.className, `${prefixCls}-trigger`),
|
||||
className: classNames(child.props.className, `${prefixCls}-trigger`, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
}),
|
||||
disabled,
|
||||
});
|
||||
|
||||
const overlayClassNameCustomized = classNames(overlayClassName, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
const triggerActions = disabled ? [] : trigger;
|
||||
let alignPoint;
|
||||
if (triggerActions && triggerActions.indexOf('contextMenu') !== -1) {
|
||||
@ -148,11 +163,13 @@ export default class Dropdown extends React.Component<DropDownProps, any> {
|
||||
<RcDropdown
|
||||
alignPoint={alignPoint}
|
||||
{...this.props}
|
||||
overlayClassName={overlayClassNameCustomized}
|
||||
prefixCls={prefixCls}
|
||||
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
||||
transitionName={this.getTransitionName()}
|
||||
trigger={triggerActions}
|
||||
overlay={() => this.renderOverlay(prefixCls)}
|
||||
placement={this.getPlacement(direction)}
|
||||
>
|
||||
{dropdownTrigger}
|
||||
</RcDropdown>
|
||||
|
@ -12,6 +12,10 @@
|
||||
z-index: @zindex-dropdown;
|
||||
display: block;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
@ -21,6 +25,11 @@
|
||||
z-index: -9999;
|
||||
opacity: 0.0001;
|
||||
content: ' ';
|
||||
|
||||
.@{dropdown-prefix-cls}-rtl& {
|
||||
right: -7px;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-wrap {
|
||||
@ -76,6 +85,10 @@
|
||||
ul,
|
||||
li {
|
||||
list-style: none;
|
||||
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
@ -98,11 +111,20 @@
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
> .anticon:first-child,
|
||||
> span > .anticon:first-child {
|
||||
min-width: 12px;
|
||||
margin-right: 8px;
|
||||
font-size: @font-size-sm;
|
||||
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
@ -160,6 +182,12 @@
|
||||
.@{dropdown-prefix-cls}-menu-submenu-arrow {
|
||||
position: absolute;
|
||||
right: @padding-xs;
|
||||
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: @padding-xs;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
color: @text-color-secondary;
|
||||
font-style: normal;
|
||||
@ -176,6 +204,11 @@
|
||||
|
||||
&-submenu-title {
|
||||
padding-right: 26px;
|
||||
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
padding-right: @control-padding-horizontal;
|
||||
padding-left: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
&-submenu-vertical {
|
||||
@ -189,6 +222,13 @@
|
||||
min-width: 100%;
|
||||
margin-left: 4px;
|
||||
transform-origin: 0 0;
|
||||
|
||||
.@{dropdown-prefix-cls}-rtl & {
|
||||
right: 100%;
|
||||
left: 0;
|
||||
margin-right: 4px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-submenu&-submenu-disabled .@{dropdown-prefix-cls}-menu-submenu-title {
|
||||
|
151
components/empty/__tests__/__snapshots__/index.test.js.snap
Normal file
151
components/empty/__tests__/__snapshots__/index.test.js.snap
Normal file
@ -0,0 +1,151 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Empty rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-empty ant-empty-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-empty-image"
|
||||
>
|
||||
<svg
|
||||
class="ant-empty-img-default"
|
||||
height="152"
|
||||
viewBox="0 0 184 152"
|
||||
width="184"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
>
|
||||
<g
|
||||
transform="translate(24 31.67)"
|
||||
>
|
||||
<ellipse
|
||||
class="ant-empty-img-default-ellipse"
|
||||
cx="67.797"
|
||||
cy="106.89"
|
||||
rx="67.797"
|
||||
ry="12.668"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-1"
|
||||
d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-2"
|
||||
d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
|
||||
transform="translate(13.56)"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-3"
|
||||
d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-4"
|
||||
d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
class="ant-empty-img-default-path-5"
|
||||
d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
|
||||
/>
|
||||
<g
|
||||
class="ant-empty-img-default-g"
|
||||
transform="translate(149.65 15.383)"
|
||||
>
|
||||
<ellipse
|
||||
cx="20.654"
|
||||
cy="3.167"
|
||||
rx="2.849"
|
||||
ry="2.815"
|
||||
/>
|
||||
<path
|
||||
d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<p
|
||||
class="ant-empty-description"
|
||||
>
|
||||
No Data
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Empty should render in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-empty ant-empty-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-empty-image"
|
||||
>
|
||||
<svg
|
||||
class="ant-empty-img-default"
|
||||
height="152"
|
||||
viewBox="0 0 184 152"
|
||||
width="184"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
>
|
||||
<g
|
||||
transform="translate(24 31.67)"
|
||||
>
|
||||
<ellipse
|
||||
class="ant-empty-img-default-ellipse"
|
||||
cx="67.797"
|
||||
cy="106.89"
|
||||
rx="67.797"
|
||||
ry="12.668"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-1"
|
||||
d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-2"
|
||||
d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
|
||||
transform="translate(13.56)"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-3"
|
||||
d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-default-path-4"
|
||||
d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
class="ant-empty-img-default-path-5"
|
||||
d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
|
||||
/>
|
||||
<g
|
||||
class="ant-empty-img-default-g"
|
||||
transform="translate(149.65 15.383)"
|
||||
>
|
||||
<ellipse
|
||||
cx="20.654"
|
||||
cy="3.167"
|
||||
rx="2.849"
|
||||
ry="2.815"
|
||||
/>
|
||||
<path
|
||||
d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<p
|
||||
class="ant-empty-description"
|
||||
>
|
||||
No Data
|
||||
</p>
|
||||
</div>
|
||||
`;
|
@ -1,10 +1,13 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { render, mount } from 'enzyme';
|
||||
import Empty from '..';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Empty', () => {
|
||||
mountTest(Empty);
|
||||
rtlTest(Empty);
|
||||
|
||||
it('image size should change', () => {
|
||||
const wrapper = mount(<Empty imageStyle={{ height: 20 }} />);
|
||||
@ -15,4 +18,13 @@ describe('Empty', () => {
|
||||
const wrapper = mount(<Empty description={false} />);
|
||||
expect(wrapper.find('.ant-empty-description').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should render in RTL direction', () => {
|
||||
const wrapper = mount(
|
||||
<ConfigProvider direction="rtl">
|
||||
<Empty />
|
||||
</ConfigProvider>,
|
||||
);
|
||||
expect(render(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -32,7 +32,7 @@ interface EmptyType extends React.FC<EmptyProps> {
|
||||
|
||||
const Empty: EmptyType = (props: EmptyProps) => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
{({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
className,
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -64,6 +64,7 @@ const Empty: EmptyType = (props: EmptyProps) => (
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-normal`]: image === simpleEmptyImg,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
)}
|
||||
|
@ -10,6 +10,10 @@
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
&-image {
|
||||
height: 100px;
|
||||
margin-bottom: 8px;
|
||||
|
@ -24,7 +24,7 @@ export interface FormProps extends Omit<RcFormProps, 'form'> {
|
||||
}
|
||||
|
||||
const InternalForm: React.FC<FormProps> = (props, ref) => {
|
||||
const { getPrefixCls }: ConfigConsumerProps = React.useContext(ConfigContext);
|
||||
const { getPrefixCls, direction }: ConfigConsumerProps = React.useContext(ConfigContext);
|
||||
|
||||
const {
|
||||
form,
|
||||
@ -45,6 +45,7 @@ const InternalForm: React.FC<FormProps> = (props, ref) => {
|
||||
{
|
||||
[`${prefixCls}-${layout}`]: true,
|
||||
[`${prefixCls}-hide-required-mark`]: hideRequiredMark,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
@ -22,3 +22,23 @@ exports[`Form Form.Item should support data-*、aria-* and custom attribute 1`]
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
|
||||
exports[`Form rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<form
|
||||
class="ant-form ant-form-horizontal ant-form-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Form rtl render component should be rendered correctly in RTL direction 2`] = `
|
||||
<div
|
||||
class="ant-row ant-row-rtl ant-form-item"
|
||||
>
|
||||
<div
|
||||
class="ant-col ant-form-item-control ant-col-rtl"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -5,6 +5,7 @@ import Form from '..';
|
||||
import Input from '../../input';
|
||||
import Button from '../../button';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
jest.mock('scroll-into-view-if-needed');
|
||||
|
||||
@ -17,6 +18,9 @@ describe('Form', () => {
|
||||
mountTest(Form);
|
||||
mountTest(Form.Item);
|
||||
|
||||
rtlTest(Form);
|
||||
rtlTest(Form.Item);
|
||||
|
||||
scrollIntoView.mockImplementation(() => {});
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
|
@ -21,6 +21,10 @@
|
||||
display: inline-block;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
@ -140,11 +144,21 @@
|
||||
.@{ant-prefix}-input-search:not(.@{ant-prefix}-input-search-enter-button) {
|
||||
.@{ant-prefix}-input-suffix {
|
||||
right: 28px;
|
||||
|
||||
.@{form-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{ant-prefix}-input-password-icon {
|
||||
margin-right: 18px;
|
||||
|
||||
.@{form-prefix-cls}-rtl & {
|
||||
margin-right: 0;
|
||||
margin-left: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== Switch =========================
|
||||
@ -162,21 +176,41 @@
|
||||
> .@{ant-prefix}-select
|
||||
.@{ant-prefix}-select-selection__clear {
|
||||
right: 28px;
|
||||
|
||||
.@{form-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 28px;
|
||||
}
|
||||
}
|
||||
> .@{ant-prefix}-select .@{ant-prefix}-select-selection-selected-value,
|
||||
:not(.@{ant-prefix}-input-group-addon)
|
||||
> .@{ant-prefix}-select
|
||||
.@{ant-prefix}-select-selection-selected-value {
|
||||
padding-right: 42px;
|
||||
|
||||
.@{form-prefix-cls}-rtl & {
|
||||
padding-right: 0;
|
||||
padding-left: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================= Cascader ========================
|
||||
.@{ant-prefix}-cascader-picker {
|
||||
&-arrow {
|
||||
margin-right: 17px;
|
||||
|
||||
.@{form-prefix-cls}-rtl & {
|
||||
margin-right: 0;
|
||||
margin-left: 17px;
|
||||
}
|
||||
}
|
||||
&-clear {
|
||||
right: 28px;
|
||||
|
||||
.@{form-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,6 +250,11 @@
|
||||
animation: zoomIn 0.3s @ease-out-back;
|
||||
pointer-events: none;
|
||||
|
||||
.@{form-prefix-cls}-rtl & {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
& svg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -10,6 +10,11 @@
|
||||
margin-right: 16px;
|
||||
margin-bottom: 0;
|
||||
|
||||
.@{form-prefix-cls}-rtl& {
|
||||
margin-right: 0;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
&-with-help {
|
||||
margin-bottom: @form-item-margin-bottom;
|
||||
}
|
||||
|
@ -8,6 +8,9 @@
|
||||
white-space: initial;
|
||||
text-align: left;
|
||||
|
||||
.@{form-prefix-cls}-rtl& {
|
||||
text-align: right;
|
||||
}
|
||||
> label {
|
||||
margin: 0;
|
||||
|
||||
|
@ -18,6 +18,18 @@ exports[`Grid renders wrapped Col correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Grid rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-row ant-row-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Grid rtl render component should be rendered correctly in RTL direction 2`] = `
|
||||
<div
|
||||
class="ant-col ant-col-rtl"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Grid should render Col 1`] = `
|
||||
<div
|
||||
class="ant-col ant-col-2"
|
||||
|
@ -2,11 +2,15 @@ import React from 'react';
|
||||
import { render, mount } from 'enzyme';
|
||||
import { Col, Row } from '..';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('Grid', () => {
|
||||
mountTest(Row);
|
||||
mountTest(Col);
|
||||
|
||||
rtlTest(Row);
|
||||
rtlTest(Col);
|
||||
|
||||
it('should render Col', () => {
|
||||
const wrapper = render(<Col span={2} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
@ -45,7 +45,7 @@ function parseFlex(flex: FlexType): string {
|
||||
}
|
||||
|
||||
export default class Col extends React.Component<ColProps, {}> {
|
||||
renderCol = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderCol = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { props } = this;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
@ -81,6 +81,7 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
sizeProps.offset || sizeProps.offset === 0,
|
||||
[`${prefixCls}-${size}-push-${sizeProps.push}`]: sizeProps.push || sizeProps.push === 0,
|
||||
[`${prefixCls}-${size}-pull-${sizeProps.pull}`]: sizeProps.pull || sizeProps.pull === 0,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
};
|
||||
});
|
||||
const classes = classNames(
|
||||
|
@ -72,7 +72,7 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
return results;
|
||||
}
|
||||
|
||||
renderRow = ({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
renderRow = ({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
justify,
|
||||
@ -89,6 +89,7 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
{
|
||||
[`${prefixCls}-${justify}`]: justify,
|
||||
[`${prefixCls}-${align}`]: align,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
@ -11,6 +11,10 @@
|
||||
&::after {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
}
|
||||
|
||||
// x轴原点
|
||||
@ -59,6 +63,10 @@
|
||||
max-width: 100%;
|
||||
// Prevent columns from collapsing when empty
|
||||
min-height: 1px;
|
||||
|
||||
&&-rtl {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.make-grid();
|
||||
|
@ -11,12 +11,30 @@
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-push-@{index} {
|
||||
left: percentage((@index / @grid-columns));
|
||||
|
||||
// reset property in RTL direction
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
right: percentage((@index / @grid-columns));
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-pull-@{index} {
|
||||
right: percentage((@index / @grid-columns));
|
||||
|
||||
// reset property in RTL direction
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
right: auto;
|
||||
left: percentage((@index / @grid-columns));
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-offset-@{index} {
|
||||
margin-left: percentage((@index / @grid-columns));
|
||||
|
||||
// reset property in RTL direction
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
margin-right: percentage((@index / @grid-columns));
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-order-@{index} {
|
||||
order: @index;
|
||||
@ -30,18 +48,39 @@
|
||||
}
|
||||
.@{ant-prefix}-col-push-@{index} {
|
||||
left: auto;
|
||||
|
||||
// reset property in RTL direction
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
right: auto;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col-pull-@{index} {
|
||||
right: auto;
|
||||
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-push-@{index} {
|
||||
left: auto;
|
||||
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
right: auto;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-pull-@{index} {
|
||||
right: auto;
|
||||
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-offset-@{index} {
|
||||
margin-left: 0;
|
||||
|
||||
&.@{ant-prefix}-col-rtl {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
.@{ant-prefix}-col@{class}-order-@{index} {
|
||||
order: 0;
|
||||
|
@ -0,0 +1,81 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`InputNumber rtl render component should be rendered correctly in RTL direction 1`] = `
|
||||
<div
|
||||
class="ant-input-number"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up "
|
||||
role="button"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down "
|
||||
role="button"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-valuemin="-9007199254740991"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
min="-9007199254740991"
|
||||
role="spinbutton"
|
||||
step="1"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -3,10 +3,12 @@ import { mount } from 'enzyme';
|
||||
import InputNumber from '..';
|
||||
import focusTest from '../../../tests/shared/focusTest';
|
||||
import mountTest from '../../../tests/shared/mountTest';
|
||||
import rtlTest from '../../../tests/shared/rtlTest';
|
||||
|
||||
describe('InputNumber', () => {
|
||||
focusTest(InputNumber);
|
||||
mountTest(InputNumber);
|
||||
rtlTest(InputNumber);
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/13896
|
||||
it('should return null when blur a empty input number', () => {
|
||||
|
@ -24,6 +24,7 @@ interface BasicProps {
|
||||
className?: string;
|
||||
style?: object;
|
||||
disabled?: boolean;
|
||||
direction?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,6 +82,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||
[`${prefixCls}-affix-wrapper-lg`]: props.size === 'large',
|
||||
[`${prefixCls}-affix-wrapper-input-with-clear-btn`]:
|
||||
props.suffix && props.allowClear && this.props.value,
|
||||
[`${prefixCls}-affix-wrapper-rtl`]: props.direction === 'rtl',
|
||||
});
|
||||
return (
|
||||
<span className={affixWrapperCls} style={props.style}>
|
||||
@ -96,7 +98,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||
}
|
||||
|
||||
renderInputWithLabel(prefixCls: string, labeledElement: React.ReactElement<any>) {
|
||||
const { addonBefore, addonAfter, style, size, className } = this.props;
|
||||
const { addonBefore, addonAfter, style, size, className, direction } = this.props;
|
||||
// Not wrap when there is not addons
|
||||
if (!addonBefore && !addonAfter) {
|
||||
return labeledElement;
|
||||
@ -111,11 +113,13 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||
|
||||
const mergedWrapperClassName = classNames(`${prefixCls}-wrapper`, {
|
||||
[wrapperClassName]: addonBefore || addonAfter,
|
||||
[`${wrapperClassName}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
const mergedGroupClassName = classNames(className, `${prefixCls}-group-wrapper`, {
|
||||
[`${prefixCls}-group-wrapper-sm`]: size === 'small',
|
||||
[`${prefixCls}-group-wrapper-lg`]: size === 'large',
|
||||
[`${prefixCls}-group-wrapper-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
// Need another wrapper for changing display:table to display:inline-block
|
||||
|
@ -17,7 +17,7 @@ export interface GroupProps {
|
||||
|
||||
const Group: React.StatelessComponent<GroupProps> = props => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls }: ConfigConsumerProps) => {
|
||||
{({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, className = '' } = props;
|
||||
const prefixCls = getPrefixCls('input-group', customizePrefixCls);
|
||||
const cls = classNames(
|
||||
@ -26,6 +26,7 @@ const Group: React.StatelessComponent<GroupProps> = props => (
|
||||
[`${prefixCls}-lg`]: props.size === 'large',
|
||||
[`${prefixCls}-sm`]: props.size === 'small',
|
||||
[`${prefixCls}-compact`]: props.compact,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user