refactor: carousel by ts
parent
93b64061db
commit
90059e6b45
|
@ -1,17 +1,17 @@
|
||||||
import { inject } from 'vue';
|
import { App, defineComponent, inject } from 'vue';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
import hasProp, { initDefaultProps, getComponent } from '../_util/props-util';
|
import hasProp, { getComponent } from '../_util/props-util';
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
import { defaultConfigProvider } from '../config-provider';
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
import SlickCarousel from '../vc-slick/src';
|
import SlickCarousel from '../vc-slick/src';
|
||||||
|
import { tuple } from '../_util/type';
|
||||||
|
|
||||||
export const CarouselEffect = PropTypes.oneOf(['scrollx', 'fade']);
|
|
||||||
// Carousel
|
// Carousel
|
||||||
export const CarouselProps = {
|
export const CarouselProps = {
|
||||||
effect: CarouselEffect,
|
effect: PropTypes.oneOf(tuple('scrollx', 'fade')),
|
||||||
dots: PropTypes.looseBool,
|
dots: PropTypes.looseBool.def(true),
|
||||||
vertical: PropTypes.looseBool,
|
vertical: PropTypes.looseBool,
|
||||||
autoplay: PropTypes.looseBool,
|
autoplay: PropTypes.looseBool,
|
||||||
easing: PropTypes.string,
|
easing: PropTypes.string,
|
||||||
|
@ -20,18 +20,18 @@ export const CarouselProps = {
|
||||||
// style: PropTypes.React.CSSProperties,
|
// style: PropTypes.React.CSSProperties,
|
||||||
prefixCls: PropTypes.string,
|
prefixCls: PropTypes.string,
|
||||||
accessibility: PropTypes.looseBool,
|
accessibility: PropTypes.looseBool,
|
||||||
nextArrow: PropTypes.any,
|
nextArrow: PropTypes.VNodeChild,
|
||||||
prevArrow: PropTypes.any,
|
prevArrow: PropTypes.VNodeChild,
|
||||||
pauseOnHover: PropTypes.looseBool,
|
pauseOnHover: PropTypes.looseBool,
|
||||||
// className: PropTypes.string,
|
// className: PropTypes.string,
|
||||||
adaptiveHeight: PropTypes.looseBool,
|
adaptiveHeight: PropTypes.looseBool,
|
||||||
arrows: PropTypes.looseBool,
|
arrows: PropTypes.looseBool.def(false),
|
||||||
autoplaySpeed: PropTypes.number,
|
autoplaySpeed: PropTypes.number,
|
||||||
centerMode: PropTypes.looseBool,
|
centerMode: PropTypes.looseBool,
|
||||||
centerPadding: PropTypes.string,
|
centerPadding: PropTypes.string,
|
||||||
cssEase: PropTypes.string,
|
cssEase: PropTypes.string,
|
||||||
dotsClass: PropTypes.string,
|
dotsClass: PropTypes.string,
|
||||||
draggable: PropTypes.looseBool,
|
draggable: PropTypes.looseBool.def(false),
|
||||||
fade: PropTypes.looseBool,
|
fade: PropTypes.looseBool,
|
||||||
focusOnSelect: PropTypes.looseBool,
|
focusOnSelect: PropTypes.looseBool,
|
||||||
infinite: PropTypes.looseBool,
|
infinite: PropTypes.looseBool,
|
||||||
|
@ -50,20 +50,18 @@ export const CarouselProps = {
|
||||||
useCSS: PropTypes.looseBool,
|
useCSS: PropTypes.looseBool,
|
||||||
slickGoTo: PropTypes.number,
|
slickGoTo: PropTypes.number,
|
||||||
responsive: PropTypes.array,
|
responsive: PropTypes.array,
|
||||||
dotPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
|
dotPosition: PropTypes.oneOf(tuple('top', 'bottom', 'left', 'right')),
|
||||||
};
|
};
|
||||||
|
|
||||||
const Carousel = {
|
const Carousel = defineComponent({
|
||||||
name: 'ACarousel',
|
name: 'ACarousel',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: initDefaultProps(CarouselProps, {
|
props: CarouselProps,
|
||||||
dots: true,
|
|
||||||
arrows: false,
|
|
||||||
draggable: false,
|
|
||||||
}),
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
configProvider: inject('configProvider', defaultConfigProvider),
|
configProvider: inject('configProvider', defaultConfigProvider),
|
||||||
|
slick: undefined,
|
||||||
|
innerSlider: undefined,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
|
@ -90,7 +88,7 @@ const Carousel = {
|
||||||
const { autoplay } = this;
|
const { autoplay } = this;
|
||||||
if (autoplay) {
|
if (autoplay) {
|
||||||
window.removeEventListener('resize', this.onWindowResized);
|
window.removeEventListener('resize', this.onWindowResized);
|
||||||
this.onWindowResized.cancel();
|
(this.onWindowResized as any).cancel();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -103,7 +101,7 @@ const Carousel = {
|
||||||
}
|
}
|
||||||
return 'bottom';
|
return 'bottom';
|
||||||
},
|
},
|
||||||
saveSlick(node) {
|
saveSlick(node: HTMLElement) {
|
||||||
this.slick = node;
|
this.slick = node;
|
||||||
},
|
},
|
||||||
onWindowResized() {
|
onWindowResized() {
|
||||||
|
@ -122,7 +120,7 @@ const Carousel = {
|
||||||
this.slick.slickPrev();
|
this.slick.slickPrev();
|
||||||
},
|
},
|
||||||
|
|
||||||
goTo(slide, dontAnimate = false) {
|
goTo(slide: number, dontAnimate = false) {
|
||||||
this.slick.slickGoTo(slide, dontAnimate);
|
this.slick.slickGoTo(slide, dontAnimate);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -134,7 +132,7 @@ const Carousel = {
|
||||||
if (props.effect === 'fade') {
|
if (props.effect === 'fade') {
|
||||||
props.fade = true;
|
props.fade = true;
|
||||||
}
|
}
|
||||||
const { class: cls, style, ...restAttrs } = this.$attrs;
|
const { class: cls, style, ...restAttrs } = this.$attrs as any;
|
||||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||||
let className = getPrefixCls('carousel', props.prefixCls);
|
let className = getPrefixCls('carousel', props.prefixCls);
|
||||||
const dotsClass = 'slick-dots';
|
const dotsClass = 'slick-dots';
|
||||||
|
@ -156,14 +154,18 @@ const Carousel = {
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div class={className} style={style}>
|
<div class={className} style={style}>
|
||||||
<SlickCarousel ref={this.saveSlick} {...SlickCarouselProps} vSlots={$slots}></SlickCarousel>
|
<SlickCarousel
|
||||||
|
ref={this.saveSlick}
|
||||||
|
{...SlickCarouselProps}
|
||||||
|
v-slots={$slots}
|
||||||
|
></SlickCarousel>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
Carousel.install = function(app) {
|
Carousel.install = function(app: App) {
|
||||||
app.component(Carousel.name, Carousel);
|
app.component(Carousel.name, Carousel);
|
||||||
return app;
|
return app;
|
||||||
};
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
import { inject, provide } from 'vue';
|
import { App, defineComponent, inject, provide, PropType } from 'vue';
|
||||||
import PropTypes, { withUndefined } from '../_util/vue-types';
|
import PropTypes, { withUndefined } from '../_util/vue-types';
|
||||||
import VcCascader from '../vc-cascader';
|
import VcCascader from '../vc-cascader';
|
||||||
import arrayTreeFilter from 'array-tree-filter';
|
import arrayTreeFilter from 'array-tree-filter';
|
||||||
|
@ -23,35 +23,74 @@ import BaseMixin from '../_util/BaseMixin';
|
||||||
import { cloneElement } from '../_util/vnode';
|
import { cloneElement } from '../_util/vnode';
|
||||||
import warning from '../_util/warning';
|
import warning from '../_util/warning';
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
import { defaultConfigProvider } from '../config-provider';
|
||||||
|
import { tuple, VueNode } from 'components/_util/type';
|
||||||
|
|
||||||
const CascaderOptionType = PropTypes.shape({
|
export interface CascaderOptionType {
|
||||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
value?: string | number;
|
||||||
label: PropTypes.any,
|
label?: VueNode;
|
||||||
disabled: PropTypes.looseBool,
|
disabled?: boolean;
|
||||||
children: PropTypes.array,
|
isLeaf?: boolean;
|
||||||
key: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
loading?: boolean;
|
||||||
}).loose;
|
children?: Array<CascaderOptionType>;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
const FieldNamesType = PropTypes.shape({
|
export interface FieldNamesType {
|
||||||
value: PropTypes.string.isRequired,
|
value?: string;
|
||||||
label: PropTypes.string.isRequired,
|
label?: string;
|
||||||
children: PropTypes.string,
|
children?: string;
|
||||||
}).loose;
|
}
|
||||||
|
|
||||||
const CascaderExpandTrigger = PropTypes.oneOf(['click', 'hover']);
|
export interface FilledFieldNamesType {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
children: string;
|
||||||
|
}
|
||||||
|
|
||||||
const ShowSearchType = PropTypes.shape({
|
// const CascaderOptionType = PropTypes.shape({
|
||||||
filter: PropTypes.func,
|
// value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
render: PropTypes.func,
|
// label: PropTypes.any,
|
||||||
sort: PropTypes.func,
|
// disabled: PropTypes.looseBool,
|
||||||
matchInputWidth: PropTypes.looseBool,
|
// children: PropTypes.array,
|
||||||
limit: withUndefined(PropTypes.oneOfType([Boolean, Number])),
|
// key: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
}).loose;
|
// }).loose;
|
||||||
|
|
||||||
|
// const FieldNamesType = PropTypes.shape({
|
||||||
|
// value: PropTypes.string.isRequired,
|
||||||
|
// label: PropTypes.string.isRequired,
|
||||||
|
// children: PropTypes.string,
|
||||||
|
// }).loose;
|
||||||
|
|
||||||
|
export interface ShowSearchType {
|
||||||
|
filter?: (inputValue: string, path: CascaderOptionType[], names: FilledFieldNamesType) => boolean;
|
||||||
|
render?: (
|
||||||
|
inputValue: string,
|
||||||
|
path: CascaderOptionType[],
|
||||||
|
prefixCls: string | undefined,
|
||||||
|
names: FilledFieldNamesType,
|
||||||
|
) => VueNode;
|
||||||
|
sort?: (
|
||||||
|
a: CascaderOptionType[],
|
||||||
|
b: CascaderOptionType[],
|
||||||
|
inputValue: string,
|
||||||
|
names: FilledFieldNamesType,
|
||||||
|
) => number;
|
||||||
|
matchInputWidth?: boolean;
|
||||||
|
limit?: number | false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// const ShowSearchType = PropTypes.shape({
|
||||||
|
// filter: PropTypes.func,
|
||||||
|
// render: PropTypes.func,
|
||||||
|
// sort: PropTypes.func,
|
||||||
|
// matchInputWidth: PropTypes.looseBool,
|
||||||
|
// limit: withUndefined(PropTypes.oneOfType([Boolean, Number])),
|
||||||
|
// }).loose;
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
const CascaderProps = {
|
const CascaderProps = {
|
||||||
/** 可选项数据源 */
|
/** 可选项数据源 */
|
||||||
options: PropTypes.arrayOf(CascaderOptionType).def([]),
|
options: { type: Array as PropType<CascaderOptionType>, default: [] },
|
||||||
/** 默认的选中项 */
|
/** 默认的选中项 */
|
||||||
defaultValue: PropTypes.array,
|
defaultValue: PropTypes.array,
|
||||||
/** 指定选中项 */
|
/** 指定选中项 */
|
||||||
|
@ -65,22 +104,25 @@ const CascaderProps = {
|
||||||
/** 自定义浮层类名 */
|
/** 自定义浮层类名 */
|
||||||
popupClassName: PropTypes.string,
|
popupClassName: PropTypes.string,
|
||||||
/** 浮层预设位置:`bottomLeft` `bottomRight` `topLeft` `topRight` */
|
/** 浮层预设位置:`bottomLeft` `bottomRight` `topLeft` `topRight` */
|
||||||
popupPlacement: PropTypes.oneOf(['bottomLeft', 'bottomRight', 'topLeft', 'topRight']).def(
|
popupPlacement: PropTypes.oneOf(tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight')).def(
|
||||||
'bottomLeft',
|
'bottomLeft',
|
||||||
),
|
),
|
||||||
/** 输入框占位文本*/
|
/** 输入框占位文本*/
|
||||||
placeholder: PropTypes.string.def('Please select'),
|
placeholder: PropTypes.string.def('Please select'),
|
||||||
/** 输入框大小,可选 `large` `default` `small` */
|
/** 输入框大小,可选 `large` `default` `small` */
|
||||||
size: PropTypes.oneOf(['large', 'default', 'small']),
|
size: PropTypes.oneOf(tuple('large', 'default', 'small')),
|
||||||
/** 禁用*/
|
/** 禁用*/
|
||||||
disabled: PropTypes.looseBool.def(false),
|
disabled: PropTypes.looseBool.def(false),
|
||||||
/** 是否支持清除*/
|
/** 是否支持清除*/
|
||||||
allowClear: PropTypes.looseBool.def(true),
|
allowClear: PropTypes.looseBool.def(true),
|
||||||
showSearch: withUndefined(PropTypes.oneOfType([Boolean, ShowSearchType])),
|
showSearch: {
|
||||||
notFoundContent: PropTypes.any,
|
type: [Boolean, Object] as PropType<ShowSearchType>,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
notFoundContent: PropTypes.VNodeChild,
|
||||||
loadData: PropTypes.func,
|
loadData: PropTypes.func,
|
||||||
/** 次级菜单的展开方式,可选 'click' 和 'hover' */
|
/** 次级菜单的展开方式,可选 'click' 和 'hover' */
|
||||||
expandTrigger: CascaderExpandTrigger,
|
expandTrigger: PropTypes.oneOf(tuple('click', 'hover')),
|
||||||
/** 当此项为 true 时,点选每级菜单选项值都会发生变化 */
|
/** 当此项为 true 时,点选每级菜单选项值都会发生变化 */
|
||||||
changeOnSelect: PropTypes.looseBool,
|
changeOnSelect: PropTypes.looseBool,
|
||||||
/** 浮层可见变化时回调 */
|
/** 浮层可见变化时回调 */
|
||||||
|
@ -89,9 +131,9 @@ const CascaderProps = {
|
||||||
inputPrefixCls: PropTypes.string,
|
inputPrefixCls: PropTypes.string,
|
||||||
getPopupContainer: PropTypes.func,
|
getPopupContainer: PropTypes.func,
|
||||||
popupVisible: PropTypes.looseBool,
|
popupVisible: PropTypes.looseBool,
|
||||||
fieldNames: FieldNamesType,
|
fieldNames: { type: Object as PropType<FieldNamesType> },
|
||||||
autofocus: PropTypes.looseBool,
|
autofocus: PropTypes.looseBool,
|
||||||
suffixIcon: PropTypes.any,
|
suffixIcon: PropTypes.VNodeChild,
|
||||||
showSearchRender: PropTypes.any,
|
showSearchRender: PropTypes.any,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
onPopupVisibleChange: PropTypes.func,
|
onPopupVisibleChange: PropTypes.func,
|
||||||
|
@ -101,14 +143,25 @@ const CascaderProps = {
|
||||||
'onUpdate:value': PropTypes.func,
|
'onUpdate:value': PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type CascaderPropsTypes = typeof CascaderProps;
|
||||||
|
|
||||||
// We limit the filtered item count by default
|
// We limit the filtered item count by default
|
||||||
const defaultLimit = 50;
|
const defaultLimit = 50;
|
||||||
|
|
||||||
function defaultFilterOption(inputValue, path, names) {
|
function defaultFilterOption(
|
||||||
|
inputValue: string,
|
||||||
|
path: CascaderOptionType[],
|
||||||
|
names: FilledFieldNamesType,
|
||||||
|
) {
|
||||||
return path.some(option => option[names.label].indexOf(inputValue) > -1);
|
return path.some(option => option[names.label].indexOf(inputValue) > -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function defaultSortFilteredOption(a, b, inputValue, names) {
|
function defaultSortFilteredOption(
|
||||||
|
a: CascaderOptionType[],
|
||||||
|
b: CascaderOptionType[],
|
||||||
|
inputValue: string,
|
||||||
|
names: FilledFieldNamesType,
|
||||||
|
) {
|
||||||
function callback(elem) {
|
function callback(elem) {
|
||||||
return elem[names.label].indexOf(inputValue) > -1;
|
return elem[names.label].indexOf(inputValue) > -1;
|
||||||
}
|
}
|
||||||
|
@ -116,8 +169,9 @@ function defaultSortFilteredOption(a, b, inputValue, names) {
|
||||||
return a.findIndex(callback) - b.findIndex(callback);
|
return a.findIndex(callback) - b.findIndex(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFilledFieldNames({ fieldNames = {} }) {
|
function getFilledFieldNames(props: CascaderPropsTypes) {
|
||||||
const names = {
|
const fieldNames = (props.fieldNames || {}) as FieldNamesType;
|
||||||
|
const names: FilledFieldNamesType = {
|
||||||
children: fieldNames.children || 'children',
|
children: fieldNames.children || 'children',
|
||||||
label: fieldNames.label || 'label',
|
label: fieldNames.label || 'label',
|
||||||
value: fieldNames.value || 'value',
|
value: fieldNames.value || 'value',
|
||||||
|
@ -125,8 +179,12 @@ function getFilledFieldNames({ fieldNames = {} }) {
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
function flattenTree(options = [], props, ancestor = []) {
|
function flattenTree(
|
||||||
const names = getFilledFieldNames(props);
|
options: CascaderOptionType[],
|
||||||
|
props: CascaderPropsTypes,
|
||||||
|
ancestor: CascaderOptionType[] = [],
|
||||||
|
) {
|
||||||
|
const names: FilledFieldNamesType = getFilledFieldNames(props);
|
||||||
let flattenOptions = [];
|
let flattenOptions = [];
|
||||||
const childrenName = names.children;
|
const childrenName = names.children;
|
||||||
options.forEach(option => {
|
options.forEach(option => {
|
||||||
|
@ -163,7 +221,7 @@ const Cascader = {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
this.cachedOptions = [];
|
this.cachedOptions = [];
|
||||||
const { value, defaultValue, popupVisible, showSearch, options } = this;
|
const { value, defaultValue, popupVisible, showSearch, options } = this.$props;
|
||||||
return {
|
return {
|
||||||
sValue: value || defaultValue || [],
|
sValue: value || defaultValue || [],
|
||||||
inputValue: '',
|
inputValue: '',
|
||||||
|
@ -553,7 +611,7 @@ const Cascader = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Cascader.install = function(app) {
|
Cascader.install = function(app: App) {
|
||||||
app.component(Cascader.name, Cascader);
|
app.component(Cascader.name, Cascader);
|
||||||
return app;
|
return app;
|
||||||
};
|
};
|
Loading…
Reference in New Issue