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