feat: update vc-tree-select

feat-dayjs^2
tanjinzhou 2020-10-20 17:41:11 +08:00
parent 4be3da0701
commit 7a2e2e3c3b
13 changed files with 102 additions and 106 deletions

View File

@ -3,18 +3,18 @@ const getTransitionGroupProps = (transitionName, opt = {}) => {
if (process.env.NODE_ENV === 'test') { if (process.env.NODE_ENV === 'test') {
return { css: false, ...opt }; return { css: false, ...opt };
} }
const transitionProps = { const transitionProps = transitionName ? {
appear: true, appear: true,
appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`, appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
appearActiveClass: `${transitionName}`, appearActiveClass: `${transitionName}`,
appearToClass: `${transitionName}-appear-active`, appearToClass: `${transitionName}-appear ${transitionName}-appear-active`,
enterFromClass: `${transitionName}-appear ${transitionName}-enter ${transitionName}-appear-prepare ${transitionName}-enter-prepare`, enterFromClass: `${transitionName}-appear ${transitionName}-enter ${transitionName}-appear-prepare ${transitionName}-enter-prepare`,
enterActiveClass: `${transitionName}`, enterActiveClass: `${transitionName}`,
enterToClass: `${transitionName}-appear-active ${transitionName}-enter-active`, enterToClass: `${transitionName}-enter ${transitionName}-appear ${transitionName}-appear-active ${transitionName}-enter-active`,
leaveActiveClass: `${transitionName} ${transitionName}-leave`, leaveActiveClass: `${transitionName} ${transitionName}-leave`,
leaveToClass: `${transitionName}-leave-active`, leaveToClass: `${transitionName}-leave-active`,
...opt, ...opt,
}; } : { css: false, ...opt };
return transitionProps; return transitionProps;
}; };

View File

@ -2,7 +2,7 @@ const getTransitionProps = (transitionName, opt = {}) => {
if (process.env.NODE_ENV === 'test') { if (process.env.NODE_ENV === 'test') {
return { css: false, ...opt }; return { css: false, ...opt };
} }
const transitionProps = { const transitionProps = transitionName ? {
appear: true, appear: true,
appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`, appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
// appearActiveClass: `antdv-base-transtion`, // appearActiveClass: `antdv-base-transtion`,
@ -14,7 +14,7 @@ const getTransitionProps = (transitionName, opt = {}) => {
leaveActiveClass: `${transitionName}-leave ${transitionName}-leave-active`, leaveActiveClass: `${transitionName}-leave ${transitionName}-leave-active`,
leaveToClass: `${transitionName}-leave ${transitionName}-leave-active`, leaveToClass: `${transitionName}-leave ${transitionName}-leave-active`,
...opt, ...opt,
}; }: { css: false, ...opt };
return transitionProps; return transitionProps;
}; };

View File

@ -15,6 +15,7 @@ import Tooltip from '../tooltip';
import Progress from '../progress'; import Progress from '../progress';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import { UploadListProps } from './interface'; import { UploadListProps } from './interface';
import getTransitionGroupProps from '../_util/getTransitionGroupProps';
export default { export default {
name: 'AUploadList', name: 'AUploadList',
@ -265,7 +266,7 @@ export default {
[`${prefixCls}-list-${listType}`]: true, [`${prefixCls}-list-${listType}`]: true,
}); });
const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate'; const animationDirection = listType === 'picture-card' ? 'animate-inline' : 'animate';
const transitionGroupProps = getTransitionProps(`${prefixCls}-${animationDirection}`); const transitionGroupProps = getTransitionGroupProps(`${prefixCls}-${animationDirection}`);
return ( return (
<TransitionGroup {...transitionGroupProps} tag="div" class={listClassNames}> <TransitionGroup {...transitionGroupProps} tag="div" class={listClassNames}>
{list} {list}

View File

@ -3,8 +3,8 @@ import PropTypes from '../_util/vue-types';
import { getComponent } from '../_util/props-util'; import { getComponent } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import createChainedFunction from '../_util/createChainedFunction'; import createChainedFunction from '../_util/createChainedFunction';
import getTransitionProps from '../_util/getTransitionProps';
import Notice from './Notice'; import Notice from './Notice';
import getTransitionGroupProps from '../_util/getTransitionGroupProps';
function noop() {} function noop() {}
@ -75,7 +75,7 @@ const Notification = defineComponent({
render() { render() {
const { prefixCls, notices, remove, getTransitionName, $attrs } = this; const { prefixCls, notices, remove, getTransitionName, $attrs } = this;
const transitionProps = getTransitionProps(getTransitionName()); const transitionProps = getTransitionGroupProps(getTransitionName());
const noticeNodes = notices.map((notice, index) => { const noticeNodes = notices.map((notice, index) => {
const update = Boolean(index === notices.length - 1 && notice.updateKey); const update = Boolean(index === notices.length - 1 && notice.updateKey);
const key = notice.updateKey ? notice.updateKey : notice.key; const key = notice.updateKey ? notice.updateKey : notice.key;

View File

@ -158,11 +158,9 @@ const SelectSelector = defineComponent<SelectorProps>({
: maxTagPlaceholder, : maxTagPlaceholder,
}); });
} }
const transitionProps = choiceTransitionName const transitionProps = getTransitionGroupProps(choiceTransitionName, {
? getTransitionGroupProps(choiceTransitionName, { appear: motionAppear,
appear: motionAppear, })
})
: { css: false };
selectionNode.value = ( selectionNode.value = (
<TransitionGroup {...transitionProps}> <TransitionGroup {...transitionProps}>
{...displayValues.map( {...displayValues.map(

View File

@ -30,10 +30,12 @@ export const selectorPropTypes = () => ({
placeholder: PropTypes.any, placeholder: PropTypes.any,
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,
focused: PropTypes.looseBool, focused: PropTypes.looseBool,
isMultiple: PropTypes.looseBool,
showSearch: PropTypes.looseBool,
}); });
function noop() {} function noop() {}
export default function(modeName) { export default function() {
const BaseSelector = { const BaseSelector = {
name: 'BaseSelector', name: 'BaseSelector',
inheritAttrs: false, inheritAttrs: false,
@ -101,7 +103,7 @@ export default function(modeName) {
} }
const clearIcon = getComponent(this, 'clearIcon'); const clearIcon = getComponent(this, 'clearIcon');
return ( return (
<span key="clear" class={`${prefixCls}-selection__clear`} onClick={onSelectorClear}> <span key="clear" unselectable="on" aria-hidden="true" style="user-select: none;" class={`${prefixCls}-clear`} onClick={onSelectorClear}>
{clearIcon} {clearIcon}
</span> </span>
); );
@ -114,7 +116,7 @@ export default function(modeName) {
} }
const inputIcon = getComponent(this, 'inputIcon'); const inputIcon = getComponent(this, 'inputIcon');
return ( return (
<span key="arrow" class={`${prefixCls}-arrow`} style={{ outline: 'none' }}> <span key="arrow" class={`${prefixCls}-arrow`} style={{ outline: 'none', userSelect: 'none' }}>
{inputIcon} {inputIcon}
</span> </span>
); );
@ -132,6 +134,9 @@ export default function(modeName) {
renderSelection, renderSelection,
renderPlaceholder, renderPlaceholder,
tabindex, tabindex,
isMultiple,
showArrow,
showSearch,
} = this.$props; } = this.$props;
const { class: className, style, onClick = noop } = this.$attrs; const { class: className, style, onClick = noop } = this.$attrs;
const { const {
@ -142,18 +147,21 @@ export default function(modeName) {
if (disabled) { if (disabled) {
myTabIndex = null; myTabIndex = null;
} }
const mergedClassName = classNames(prefixCls, className, {
[`${prefixCls}-focused`]: open || focused,
[`${prefixCls}-multiple`]: isMultiple,
[`${prefixCls}-single`]: !isMultiple,
[`${prefixCls}-allow-clear`]: allowClear,
[`${prefixCls}-show-arrow`]: showArrow,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-open`]: open,
[`${prefixCls}-show-search`]: showSearch,
});
return ( return (
<span <div
style={style} style={style}
onClick={onClick} onClick={onClick}
class={classNames(className, prefixCls, { class={mergedClassName}
[`${prefixCls}-open`]: open,
[`${prefixCls}-focused`]: open || focused,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-enabled`]: !disabled,
[`${prefixCls}-allow-clear`]: allowClear,
})}
ref={this.domRef} ref={this.domRef}
role="combobox" role="combobox"
aria-expanded={open} aria-expanded={open}
@ -166,17 +174,13 @@ export default function(modeName) {
onBlur={this.onBlur} onBlur={this.onBlur}
onKeydown={onSelectorKeyDown} onKeydown={onSelectorKeyDown}
> >
<span <span class={`${prefixCls}-selector`}>
key="selection"
class={classNames(`${prefixCls}-selection`, `${prefixCls}-selection--${modeName}`)}
>
{renderSelection()} {renderSelection()}
{this.renderClear()}
{this.renderArrow()}
{renderPlaceholder && renderPlaceholder()} {renderPlaceholder && renderPlaceholder()}
</span> </span>
</span> {this.renderArrow()}
{this.renderClear()}
</div>
); );
}, },
}; };

View File

@ -40,7 +40,7 @@ const SinglePopup = {
display: searchValue ? 'none' : 'block', display: searchValue ? 'none' : 'block',
}} }}
onClick={this.onPlaceholderClick} onClick={this.onPlaceholderClick}
class={`${prefixCls}-search__field__placeholder`} class={`${prefixCls}-selection-placeholder`}
> >
{searchPlaceholder} {searchPlaceholder}
</span> </span>

View File

@ -4,7 +4,7 @@
* - multiple: in the selector * - multiple: in the selector
* Move the code as a SearchInput for easy management. * Move the code as a SearchInput for easy management.
*/ */
import { inject, withDirectives } from 'vue'; import { inject, withDirectives, ref, onMounted, computed, watch } from 'vue';
import antInput from '../../_util/antInputDirective'; import antInput from '../../_util/antInputDirective';
import PropTypes from '../../_util/vue-types'; import PropTypes from '../../_util/vue-types';
import { createRef } from './util'; import { createRef } from './util';
@ -21,8 +21,22 @@ const SearchInput = {
needAlign: PropTypes.looseBool, needAlign: PropTypes.looseBool,
ariaId: PropTypes.string, ariaId: PropTypes.string,
}, },
setup() { setup(props) {
const measureRef = ref();
const inputWidth = ref(0);
// We measure width and set to the input immediately
onMounted(() => {
watch(
computed(()=>props.searchValue),
() => {
inputWidth.value = measureRef.value.scrollWidth;
},
{ flush: 'post' },
);
});
return { return {
measureRef,
inputWidth,
vcTreeSelect: inject('vcTreeSelect', {}), vcTreeSelect: inject('vcTreeSelect', {}),
}; };
}, },
@ -38,7 +52,7 @@ const SearchInput = {
}, },
created() { created() {
this.inputRef = createRef(); this.inputRef = createRef();
this.mirrorInputRef = createRef(); // this.mirrorInputRef = createRef();
this.prevProps = { ...this.$props }; this.prevProps = { ...this.$props };
}, },
mounted() { mounted() {
@ -55,15 +69,15 @@ const SearchInput = {
}, },
updated() { updated() {
const { open, searchValue, needAlign } = this.$props; const { open } = this.$props;
const { prevProps } = this; const { prevProps } = this;
this.$nextTick(() => { this.$nextTick(() => {
if (open && prevProps.open !== open) { if (open && prevProps.open !== open) {
this.focus(); this.focus();
} }
if (needAlign && searchValue !== prevProps.searchValue) { // if (needAlign && searchValue !== prevProps.searchValue) {
this.alignInputWidth(); // this.alignInputWidth();
} // }
this.prevProps = { ...this.$props }; this.prevProps = { ...this.$props };
}); });
}, },
@ -73,10 +87,10 @@ const SearchInput = {
* ref: https://github.com/react-component/tree-select/issues/65 * ref: https://github.com/react-component/tree-select/issues/65
* clientWidth 0 when mounted in vue. why? * clientWidth 0 when mounted in vue. why?
*/ */
alignInputWidth() { // alignInputWidth() {
this.inputRef.current.style.width = `${this.mirrorInputRef.current.clientWidth || // this.inputRef.current.style.width = `${this.mirrorInputRef.current.clientWidth ||
this.mirrorInputRef.current.offsetWidth}px`; // this.mirrorInputRef.current.offsetWidth}px`;
}, // },
/** /**
* Need additional timeout for focus cause parent dom is not ready when didMount trigger * Need additional timeout for focus cause parent dom is not ready when didMount trigger
@ -116,31 +130,34 @@ const SearchInput = {
vcTreeSelect: { onSearchInputKeyDown }, vcTreeSelect: { onSearchInputKeyDown },
handleInputChange, handleInputChange,
mirrorSearchValue, mirrorSearchValue,
inputWidth,
} = this; } = this;
return ( return (
<span class={`${prefixCls}-search__field__wrap`}> <>
{withDirectives( <span class={`${prefixCls}-selection-search`} style={{ width: inputWidth + 'px' }}>
<input {withDirectives(
type="text" <input
ref={this.inputRef} type="text"
onInput={handleInputChange} ref={this.inputRef}
onChange={handleInputChange} onInput={handleInputChange}
onKeydown={onSearchInputKeyDown} onChange={handleInputChange}
value={searchValue} onKeydown={onSearchInputKeyDown}
disabled={disabled} value={searchValue}
class={`${prefixCls}-search__field`} disabled={disabled}
aria-label="filter select" class={`${prefixCls}-selection-search-input`}
aria-autocomplete="list" aria-label="filter select"
aria-controls={open ? ariaId : undefined} aria-autocomplete="list"
aria-multiline="false" aria-controls={open ? ariaId : undefined}
/>, aria-multiline="false"
[[antInput]], />,
)} [[antInput]],
<span ref={this.mirrorInputRef} class={`${prefixCls}-search__field__mirror`}> )}
{mirrorSearchValue}&nbsp; <span ref="measureRef" class={`${prefixCls}-selection-search-mirror`} aria-hidden>
{mirrorSearchValue}&nbsp;
</span>
</span> </span>
{renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null} {renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null}
</span> </>
); );
}, },
}; };

View File

@ -1096,7 +1096,7 @@ const Select = defineComponent({
const $popup = <Popup {...popupProps} __propsSymbol__={[]} />; const $popup = <Popup {...popupProps} __propsSymbol__={[]} />;
const Selector = isMultiple ? MultipleSelector : SingleSelector; const Selector = isMultiple ? MultipleSelector : SingleSelector;
const $selector = <Selector {...passProps} ref={this.selectorRef} />; const $selector = <Selector {...passProps} isMultiple={isMultiple} ref={this.selectorRef} />;
const selectTriggerProps = { const selectTriggerProps = {
...passProps, ...passProps,
popupElement: $popup, popupElement: $popup,

View File

@ -32,20 +32,20 @@ const Selection = {
} }
const { class: className, style, onRemove } = this.$attrs; const { class: className, style, onRemove } = this.$attrs;
return ( return (
<li <span
style={{ ...UNSELECTABLE_STYLE, ...style }} style={{ ...UNSELECTABLE_STYLE, ...style }}
{...UNSELECTABLE_ATTRIBUTE} {...UNSELECTABLE_ATTRIBUTE}
role="menuitem" role="menuitem"
class={classNames(`${prefixCls}-selection__choice`, className)} class={classNames(`${prefixCls}-selection-item`, className)}
title={toTitle(label)} title={toTitle(label)}
> >
<span class={`${prefixCls}-selection-item-content`}>{content}</span>
{onRemove && ( {onRemove && (
<span class={`${prefixCls}-selection__choice__remove`} onClick={this.onRemove}> <span class={`${prefixCls}-selection-item-remove`} onClick={this.onRemove}>
{getComponent(this, 'removeIcon')} {getComponent(this, 'removeIcon')}
</span> </span>
)} )}
<span class={`${prefixCls}-selection__choice__content`}>{content}</span> </span>
</li>
); );
}, },
}; };

View File

@ -1,11 +1,10 @@
import { inject, TransitionGroup } from 'vue'; import { inject } from 'vue';
import PropTypes from '../../../../_util/vue-types'; import PropTypes from '../../../../_util/vue-types';
import { createRef } from '../../util'; import { createRef } from '../../util';
import generateSelector, { selectorPropTypes } from '../../Base/BaseSelector'; import generateSelector, { selectorPropTypes } from '../../Base/BaseSelector';
import SearchInput from '../../SearchInput'; import SearchInput from '../../SearchInput';
import Selection from './Selection'; import Selection from './Selection';
import { getComponent, getSlot } from '../../../../_util/props-util'; import { getComponent, getSlot } from '../../../../_util/props-util';
import getTransitionProps from '../../../../_util/getTransitionProps';
import BaseMixin from '../../../../_util/BaseMixin'; import BaseMixin from '../../../../_util/BaseMixin';
const TREE_SELECT_EMPTY_VALUE_KEY = 'RC_TREE_SELECT_EMPTY_VALUE_KEY'; const TREE_SELECT_EMPTY_VALUE_KEY = 'RC_TREE_SELECT_EMPTY_VALUE_KEY';
@ -73,7 +72,7 @@ const MultipleSelector = {
display: hidden ? 'none' : 'block', display: hidden ? 'none' : 'block',
}} }}
onClick={this.onPlaceholderClick} onClick={this.onPlaceholderClick}
class={`${prefixCls}-search__field__placeholder`} class={`${prefixCls}-selection-placeholder`}
> >
{currentPlaceholder} {currentPlaceholder}
</span> </span>
@ -85,8 +84,6 @@ const MultipleSelector = {
renderSelection() { renderSelection() {
const { const {
selectorValueList, selectorValueList,
choiceTransitionName,
prefixCls,
labelInValue, labelInValue,
maxTagCount, maxTagCount,
} = this.$props; } = this.$props;
@ -144,7 +141,6 @@ const MultipleSelector = {
} }
selectedValueNodes.push( selectedValueNodes.push(
<li class={`${prefixCls}-search ${prefixCls}-search--inline`} key="__input">
<SearchInput <SearchInput
{...{ {...{
...this.$props, ...this.$props,
@ -154,26 +150,10 @@ const MultipleSelector = {
ref={this.inputRef} ref={this.inputRef}
> >
{children} {children}
</SearchInput> </SearchInput>,
</li>,
);
const className = `${prefixCls}-selection__rendered`;
if (choiceTransitionName) {
const transitionProps = getTransitionProps(choiceTransitionName, {
tag: 'ul',
onAfterLeave: this.onChoiceAnimationLeave,
});
return (
<TransitionGroup class={className} {...transitionProps}>
{selectedValueNodes}
</TransitionGroup>
);
}
return (
<ul class={className} role="menubar">
{selectedValueNodes}
</ul>
); );
return selectedValueNodes;
}, },
}, },

View File

@ -21,24 +21,20 @@ const SingleSelector = {
renderSelection() { renderSelection() {
const { selectorValueList, placeholder, prefixCls } = this.$props; const { selectorValueList, placeholder, prefixCls } = this.$props;
let innerNode;
if (selectorValueList.length) { if (selectorValueList.length) {
const { label, value } = selectorValueList[0]; const { label, value } = selectorValueList[0];
innerNode = ( return (
<span key="value" title={toTitle(label)} class={`${prefixCls}-selection-selected-value`}> <span key="value" title={toTitle(label)} class={`${prefixCls}-selection-item`}>
{label || value} {label || value}
</span> </span>
); );
} else { } else {
innerNode = ( return (
<span key="placeholder" class={`${prefixCls}-selection__placeholder`}> <span key="placeholder" class={`${prefixCls}-selection-placeholder`}>
{placeholder} {placeholder}
</span> </span>
); );
} }
return <span class={`${prefixCls}-selection__rendered`}>{innerNode}</span>;
}, },
}, },