feat: update collapse (#2539)

pull/2682/head
zkwolf 2020-07-15 15:27:35 +08:00 committed by GitHub
parent 80599668df
commit 41e3630f8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 82 deletions

View File

@ -79,3 +79,7 @@ tabList[{scopedSlots}] -> tabList[{slots}]
## rate
v-model -> v-model:value
## Collapse
v-model -> v-model:activeKey

View File

@ -1,10 +1,11 @@
import { inject } from 'vue';
import animation from '../_util/openAnimation';
import {
getOptionProps,
initDefaultProps,
getComponentFromProp,
getComponent,
isValidElement,
getListeners,
getSlot,
} from '../_util/props-util';
import { cloneElement } from '../_util/vnode';
import VcCollapse, { collapseProps } from '../vc-collapse';
@ -13,21 +14,19 @@ import { ConfigConsumerProps } from '../config-provider';
export default {
name: 'ACollapse',
model: {
prop: 'activeKey',
event: 'change',
},
props: initDefaultProps(collapseProps(), {
bordered: true,
openAnimation: animation,
expandIconPosition: 'left',
}),
inject: {
configProvider: { default: () => ConfigConsumerProps },
setup() {
return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
},
methods: {
renderExpandIcon(panelProps, prefixCls) {
const expandIcon = getComponentFromProp(this, 'expandIcon', panelProps);
const expandIcon = getComponent(this, 'expandIcon', panelProps);
const icon = expandIcon || <RightOutlined rotate={panelProps.isActive ? 90 : undefined} />;
return isValidElement(Array.isArray(expandIcon) ? icon[0] : icon)
? cloneElement(icon, {
@ -46,14 +45,12 @@ export default {
[`${prefixCls}-icon-position-${expandIconPosition}`]: true,
};
const rcCollapeProps = {
props: {
...getOptionProps(this),
prefixCls,
expandIcon: panelProps => this.renderExpandIcon(panelProps, prefixCls),
},
...getOptionProps(this),
prefixCls,
expandIcon: panelProps => this.renderExpandIcon(panelProps, prefixCls),
class: collapseClassName,
on: getListeners(this),
};
return <VcCollapse {...rcCollapeProps}>{this.$slots.default}</VcCollapse>;
return <VcCollapse {...rcCollapeProps}>{getSlot(this)}</VcCollapse>;
},
};

View File

@ -1,4 +1,5 @@
import { getOptionProps, getComponentFromProp, getListeners } from '../_util/props-util';
import { inject } from 'vue';
import { getOptionProps, getComponent, getSlot } from '../_util/props-util';
import VcCollapse, { panelProps } from '../vc-collapse';
import { ConfigConsumerProps } from '../config-provider';
@ -7,8 +8,10 @@ export default {
props: {
...panelProps(),
},
inject: {
configProvider: { default: () => ConfigConsumerProps },
setup() {
return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
},
render() {
const { prefixCls: customizePrefixCls, showArrow = true } = this;
@ -18,21 +21,14 @@ export default {
const collapsePanelClassName = {
[`${prefixCls}-no-arrow`]: !showArrow,
};
const rcCollapePanelProps = {
props: {
...getOptionProps(this),
prefixCls,
extra: getComponentFromProp(this, 'extra'),
},
...getOptionProps(this),
header: getComponent(this, 'header'),
prefixCls,
extra: getComponent(this, 'extra'),
class: collapsePanelClassName,
on: getListeners(this),
};
const header = getComponentFromProp(this, 'header');
return (
<VcCollapse.Panel {...rcCollapePanelProps}>
{this.$slots.default}
{header ? <template slot="header">{header}</template> : null}
</VcCollapse.Panel>
);
return <VcCollapse.Panel {...rcCollapePanelProps}>{getSlot(this)}</VcCollapse.Panel>;
},
};

View File

@ -2,8 +2,10 @@
exports[`Collapse should support remove expandIcon 1`] = `
<div class="ant-collapse ant-collapse-icon-position-left">
<div role="tablist" class="ant-collapse-item">
<div role="button" tabindex="0" class="ant-collapse-header"><span role="img" aria-label="right" class="anticon anticon-right ant-collapse-arrow"><svg viewBox="64 64 896 896" focusable="false" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" class=""><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span>header</div>
<div class="ant-collapse-item" role="tablist">
<div class="ant-collapse-header" role="button" tabindex="0" aria-expanded="false"><span class="anticon anticon-right ant-collapse-arrow" role="img" aria-label="right"><svg class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span>header
<!---->
</div>
<!---->
</div>
</div>

View File

@ -1,14 +1,12 @@
import Collapse from './Collapse';
import CollapsePanel from './CollapsePanel';
import Base from '../base';
Collapse.Panel = CollapsePanel;
/* istanbul ignore next */
Collapse.install = function(Vue) {
Vue.use(Base);
Vue.component(Collapse.name, Collapse);
Vue.component(CollapsePanel.name, CollapsePanel);
Collapse.install = function(app) {
app.component(Collapse.name, Collapse);
app.component(CollapsePanel.name, CollapsePanel);
};
export default Collapse;

View File

@ -1,5 +1,11 @@
import BaseMixin from '../../_util/BaseMixin';
import { hasProp, getPropsData, isEmptyElement, initDefaultProps } from '../../_util/props-util';
import {
hasProp,
getPropsData,
isEmptyElement,
initDefaultProps,
getSlot,
} from '../../_util/props-util';
import { cloneElement } from '../../_util/vnode';
import openAnimationFactory from './openAnimationFactory';
import { collapseProps } from './commonProps';
@ -14,10 +20,6 @@ function _toArray(activeKey) {
export default {
name: 'Collapse',
mixins: [BaseMixin],
model: {
prop: 'activeKey',
event: 'change',
},
props: initDefaultProps(collapseProps(), {
prefixCls: 'rc-collapse',
accordion: false,
@ -84,32 +86,30 @@ export default {
let panelEvents = {};
if (!disabled && disabled !== '') {
panelEvents = {
itemClick: this.onClickItem,
onItemClick: this.onClickItem,
};
}
const props = {
key,
props: {
panelKey: key,
header,
headerClass,
isActive,
prefixCls,
destroyInactivePanel,
openAnimation: this.currentOpenAnimations,
accordion,
expandIcon,
},
on: panelEvents,
panelKey: key,
header,
headerClass,
isActive,
prefixCls,
destroyInactivePanel,
openAnimation: this.currentOpenAnimations,
accordion,
expandIcon,
...panelEvents,
};
return cloneElement(child, props);
},
getItems() {
const newChildren = [];
this.$slots.default &&
this.$slots.default.forEach((child, index) => {
getSlot(this) &&
getSlot(this).forEach((child, index) => {
newChildren.push(this.getNewChild(child, index));
});
return newChildren;
@ -117,6 +117,7 @@ export default {
setActiveKey(activeKey) {
this.setState({ stateActiveKey: activeKey });
this.$emit('change', this.accordion ? activeKey[0] : activeKey);
this.$emit('update:activeKey', this.accordion ? activeKey[0] : activeKey);
},
},
render() {

View File

@ -1,6 +1,7 @@
import PanelContent from './PanelContent';
import { initDefaultProps, getComponentFromProp } from '../../_util/props-util';
import { initDefaultProps, getComponent, getSlot } from '../../_util/props-util';
import { panelProps } from './commonProps';
import { Transition } from 'vue';
export default {
name: 'Panel',
@ -35,20 +36,18 @@ export default {
expandIcon,
extra,
} = this.$props;
const { $slots } = this;
const transitionProps = {
props: Object.assign({
appear: true,
css: false,
}),
on: { ...openAnimation },
appear: true,
css: false,
...openAnimation,
};
const headerCls = {
[`${prefixCls}-header`]: true,
[headerClass]: headerClass,
};
const header = getComponentFromProp(this, 'header');
const header = getComponent(this, 'header');
const itemCls = {
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-active`]: isActive,
@ -58,11 +57,24 @@ export default {
if (showArrow && typeof expandIcon === 'function') {
icon = expandIcon(this.$props);
}
const panelContent = (
<PanelContent
vShow={isActive}
prefixCls={prefixCls}
isActive={isActive}
destroyInactivePanel={destroyInactivePanel}
forceRender={forceRender}
role={accordion ? 'tabpanel' : null}
>
{getSlot(this)}
</PanelContent>
);
return (
<div class={itemCls} role="tablist">
<div
class={headerCls}
onClick={this.handleItemClick.bind(this)}
onClick={this.handleItemClick}
onKeypress={this.handleKeyPress}
role={accordion ? 'tab' : 'button'}
tabIndex={disabled ? -1 : 0}
@ -72,18 +84,7 @@ export default {
{header}
{extra && <div class={`${prefixCls}-extra`}>{extra}</div>}
</div>
<transition {...transitionProps}>
<PanelContent
v-show={isActive}
prefixCls={prefixCls}
isActive={isActive}
destroyInactivePanel={destroyInactivePanel}
forceRender={forceRender}
role={accordion ? 'tabpanel' : null}
>
{$slots.default}
</PanelContent>
</transition>
<Transition {...transitionProps}>{panelContent}</Transition>
</div>
);
},

View File

@ -1,4 +1,5 @@
import PropTypes from '../../_util/vue-types';
import { getSlot } from '../../_util/props-util';
export default {
name: 'PanelContent',
@ -20,14 +21,13 @@ export default {
return null;
}
const { prefixCls, isActive, destroyInactivePanel, forceRender, role } = this.$props;
const { $slots } = this;
const contentCls = {
[`${prefixCls}-content`]: true,
[`${prefixCls}-content-active`]: isActive,
};
const child =
!forceRender && !isActive && destroyInactivePanel ? null : (
<div class={`${prefixCls}-content-box`}>{$slots.default}</div>
<div class={`${prefixCls}-content-box`}>{getSlot(this)}</div>
);
return (
<div class={contentCls} role={role}>