mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-01 03:28:42 +08:00
style: vc-select2 to ts
This commit is contained in:
parent
47e5df9103
commit
4b4fc9266c
@ -31,7 +31,8 @@
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
"@typescript-eslint/ban-types": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
||||
"@typescript-eslint/no-empty-function": 0
|
||||
"@typescript-eslint/no-empty-function": 0,
|
||||
"@typescript-eslint/no-non-null-assertion": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -1,8 +0,0 @@
|
||||
function createRef() {
|
||||
const func = function setRef(node) {
|
||||
func.current = node;
|
||||
};
|
||||
return func;
|
||||
}
|
||||
|
||||
export default createRef;
|
12
components/_util/createRef.ts
Normal file
12
components/_util/createRef.ts
Normal file
@ -0,0 +1,12 @@
|
||||
interface RefObject extends Function {
|
||||
current?: any;
|
||||
}
|
||||
|
||||
function createRef(): RefObject {
|
||||
const func: RefObject = (node: any) => {
|
||||
func.current = node;
|
||||
};
|
||||
return func;
|
||||
}
|
||||
|
||||
export default createRef;
|
@ -1,6 +1,10 @@
|
||||
export const responsiveArray = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
||||
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||
export type BreakpointMap = Partial<Record<Breakpoint, string>>;
|
||||
export type ScreenMap = Partial<Record<Breakpoint, boolean>>;
|
||||
|
||||
export const responsiveMap = {
|
||||
export const responsiveArray: Breakpoint[] = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
||||
|
||||
export const responsiveMap: BreakpointMap = {
|
||||
xs: '(max-width: 575px)',
|
||||
sm: '(min-width: 576px)',
|
||||
md: '(min-width: 768px)',
|
||||
@ -9,40 +13,46 @@ export const responsiveMap = {
|
||||
xxl: '(min-width: 1600px)',
|
||||
};
|
||||
|
||||
const subscribers = new Map();
|
||||
type SubscribeFunc = (screens: ScreenMap) => void;
|
||||
const subscribers = new Map<Number, SubscribeFunc>();
|
||||
let subUid = -1;
|
||||
let screens = {};
|
||||
|
||||
const responsiveObserve = {
|
||||
matchHandlers: {},
|
||||
dispatch(pointMap) {
|
||||
matchHandlers: {} as {
|
||||
[prop: string]: {
|
||||
mql: MediaQueryList;
|
||||
listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
|
||||
};
|
||||
},
|
||||
dispatch(pointMap: ScreenMap) {
|
||||
screens = pointMap;
|
||||
subscribers.forEach(func => func(screens));
|
||||
return subscribers.size >= 1;
|
||||
},
|
||||
subscribe(func) {
|
||||
subscribe(func: SubscribeFunc): number {
|
||||
if (!subscribers.size) this.register();
|
||||
subUid += 1;
|
||||
subscribers.set(subUid, func);
|
||||
func(screens);
|
||||
return subUid;
|
||||
},
|
||||
unsubscribe(token) {
|
||||
unsubscribe(token: number) {
|
||||
subscribers.delete(token);
|
||||
if (!subscribers.size) this.unregister();
|
||||
},
|
||||
unregister() {
|
||||
Object.keys(responsiveMap).forEach(screen => {
|
||||
const matchMediaQuery = responsiveMap[screen];
|
||||
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
|
||||
const matchMediaQuery = responsiveMap[screen]!;
|
||||
const handler = this.matchHandlers[matchMediaQuery];
|
||||
handler?.mql.removeListener(handler?.listener);
|
||||
});
|
||||
subscribers.clear();
|
||||
},
|
||||
register() {
|
||||
Object.keys(responsiveMap).forEach(screen => {
|
||||
const matchMediaQuery = responsiveMap[screen];
|
||||
const listener = ({ matches }) => {
|
||||
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
|
||||
const matchMediaQuery = responsiveMap[screen]!;
|
||||
const listener = ({ matches }: { matches: boolean }) => {
|
||||
this.dispatch({
|
||||
...screens,
|
||||
[screen]: matches,
|
@ -1,10 +1,11 @@
|
||||
// based on rc-resize-observer 0.1.3
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
import { defineComponent } from 'vue';
|
||||
import BaseMixin from '../_util/BaseMixin';
|
||||
import { findDOMNode } from '../_util/props-util';
|
||||
|
||||
// Still need to be compatible with React 15, we use class component here
|
||||
const VueResizeObserver = {
|
||||
const VueResizeObserver = defineComponent({
|
||||
name: 'ResizeObserver',
|
||||
mixins: [BaseMixin],
|
||||
props: {
|
||||
@ -84,6 +85,6 @@ const VueResizeObserver = {
|
||||
render() {
|
||||
return this.$slots.default && this.$slots.default()[0];
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default VueResizeObserver;
|
||||
|
@ -5,7 +5,7 @@ import classNames from '../_util/classNames';
|
||||
import pickAttrs from '../_util/pickAttrs';
|
||||
import { isValidElement } from '../_util/props-util';
|
||||
import createRef from '../_util/createRef';
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { computed, defineComponent, reactive, watch } from 'vue';
|
||||
import List from '../vc-virtual-list/List';
|
||||
|
||||
const OptionListProps = {
|
||||
@ -39,7 +39,7 @@ const OptionListProps = {
|
||||
* Using virtual list of option display.
|
||||
* Will fallback to dom if use customize render.
|
||||
*/
|
||||
const OptionList = {
|
||||
const OptionList = defineComponent({
|
||||
props: OptionListProps,
|
||||
name: 'OptionList',
|
||||
inheritAttrs: false,
|
||||
@ -138,7 +138,7 @@ const OptionList = {
|
||||
const mergedLabel = props.childrenAsData ? children : label;
|
||||
return item ? (
|
||||
<div
|
||||
aria-label={typeof mergedLabel === 'string' ? mergedLabel : null}
|
||||
aria-label={typeof mergedLabel === 'string' ? mergedLabel : undefined}
|
||||
{...attrs}
|
||||
key={index}
|
||||
role="option"
|
||||
@ -343,6 +343,6 @@ const OptionList = {
|
||||
</>
|
||||
);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default OptionList;
|
@ -3,8 +3,10 @@ import PropTypes from '../_util/vue-types';
|
||||
import { getSlot } from '../_util/props-util';
|
||||
import classNames from '../_util/classNames';
|
||||
import createRef from '../_util/createRef';
|
||||
import { CSSProperties, defineComponent, VNodeChild } from 'vue';
|
||||
import { RenderDOMFunc } from './interface';
|
||||
|
||||
const getBuiltInPlacements = dropdownMatchSelectWidth => {
|
||||
const getBuiltInPlacements = (dropdownMatchSelectWidth: number | boolean) => {
|
||||
// Enable horizontal overflow auto-adjustment when a custom dropdown width is provided
|
||||
const adjustX = typeof dropdownMatchSelectWidth !== 'number' ? 0 : 1;
|
||||
|
||||
@ -43,33 +45,27 @@ const getBuiltInPlacements = dropdownMatchSelectWidth => {
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
export interface SelectTriggerProps {
|
||||
prefixCls: string;
|
||||
disabled: boolean;
|
||||
visible: boolean;
|
||||
popupElement: VNodeChild;
|
||||
animation?: string;
|
||||
transitionName?: string;
|
||||
containerWidth: number;
|
||||
dropdownStyle: CSSProperties;
|
||||
dropdownClassName: string;
|
||||
direction: string;
|
||||
dropdownMatchSelectWidth?: boolean | number;
|
||||
dropdownRender?: (menu: VNodeChild) => VNodeChild;
|
||||
getPopupContainer?: RenderDOMFunc;
|
||||
dropdownAlign: object;
|
||||
empty: boolean;
|
||||
getTriggerDOMNode: () => HTMLElement;
|
||||
}
|
||||
const SelectTrigger = defineComponent<SelectTriggerProps>({
|
||||
name: 'SelectTrigger',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
// onPopupFocus: PropTypes.func,
|
||||
// onPopupScroll: PropTypes.func,
|
||||
dropdownAlign: PropTypes.object,
|
||||
visible: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
dropdownClassName: PropTypes.string,
|
||||
dropdownStyle: PropTypes.object,
|
||||
empty: PropTypes.bool,
|
||||
prefixCls: PropTypes.string,
|
||||
popupClassName: PropTypes.string,
|
||||
// children: PropTypes.any,
|
||||
animation: PropTypes.string,
|
||||
transitionName: PropTypes.string,
|
||||
getPopupContainer: PropTypes.func,
|
||||
dropdownRender: PropTypes.func,
|
||||
containerWidth: PropTypes.number,
|
||||
dropdownMatchSelectWidth: PropTypes.oneOfType([Number, Boolean]).def(true),
|
||||
popupElement: PropTypes.any,
|
||||
direction: PropTypes.string,
|
||||
getTriggerDOMNode: PropTypes.func,
|
||||
},
|
||||
|
||||
created() {
|
||||
this.popupRef = createRef();
|
||||
},
|
||||
@ -89,7 +85,7 @@ export default {
|
||||
},
|
||||
|
||||
render() {
|
||||
const { empty, ...props } = { ...this.$props, ...this.$attrs };
|
||||
const { empty = false, ...props } = { ...this.$props, ...this.$attrs };
|
||||
const {
|
||||
visible,
|
||||
dropdownAlign,
|
||||
@ -122,7 +118,6 @@ export default {
|
||||
showAction={[]}
|
||||
hideAction={[]}
|
||||
popupPlacement={this.direction === 'rtl' ? 'bottomRight' : 'bottomLeft'}
|
||||
popupPlacement="bottomLeft"
|
||||
builtinPlacements={builtInPlacements}
|
||||
prefixCls={dropdownPrefixCls}
|
||||
popupTransitionName={this.getDropdownTransitionName()}
|
||||
@ -141,4 +136,24 @@ export default {
|
||||
</Trigger>
|
||||
);
|
||||
},
|
||||
});
|
||||
SelectTrigger.props = {
|
||||
dropdownAlign: PropTypes.object,
|
||||
visible: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
dropdownClassName: PropTypes.string,
|
||||
dropdownStyle: PropTypes.object,
|
||||
empty: PropTypes.bool,
|
||||
prefixCls: PropTypes.string,
|
||||
popupClassName: PropTypes.string,
|
||||
animation: PropTypes.string,
|
||||
transitionName: PropTypes.string,
|
||||
getPopupContainer: PropTypes.func,
|
||||
dropdownRender: PropTypes.func,
|
||||
containerWidth: PropTypes.number,
|
||||
dropdownMatchSelectWidth: PropTypes.oneOfType([Number, Boolean]).def(true),
|
||||
popupElement: PropTypes.any,
|
||||
direction: PropTypes.string,
|
||||
getTriggerDOMNode: PropTypes.func,
|
||||
};
|
||||
export default SelectTrigger;
|
@ -1,41 +0,0 @@
|
||||
const TransBtn = (
|
||||
_,
|
||||
{ attrs: { class: className, customizeIcon, customizeIconProps, onMousedown, onClick }, slots },
|
||||
) => {
|
||||
let icon;
|
||||
|
||||
if (typeof customizeIcon === 'function') {
|
||||
icon = customizeIcon(customizeIconProps);
|
||||
} else {
|
||||
icon = customizeIcon;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
class={className}
|
||||
onMousedown={event => {
|
||||
event.preventDefault();
|
||||
if (onMousedown) {
|
||||
onMousedown(event);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
userSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
}}
|
||||
unselectable="on"
|
||||
onClick={onClick}
|
||||
aria-hidden
|
||||
>
|
||||
{icon !== undefined ? (
|
||||
icon
|
||||
) : (
|
||||
<span class={className.split(/\s+/).map(cls => `${cls}-icon`)}>{slots?.default()}</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
TransBtn.inheritAttrs = false;
|
||||
|
||||
export default TransBtn;
|
59
components/vc-select2/TransBtn.tsx
Normal file
59
components/vc-select2/TransBtn.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import { SetupContext, VNodeChild } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
|
||||
export interface TransBtnProps {
|
||||
class: string;
|
||||
customizeIcon: VNodeChild | ((props?: any) => VNodeChild);
|
||||
customizeIconProps?: any;
|
||||
onMousedown?: (payload: MouseEvent) => void;
|
||||
onClick?: (payload: MouseEvent) => void;
|
||||
}
|
||||
|
||||
const TransBtn = (props: TransBtnProps, { slots }: SetupContext) => {
|
||||
const { class: className, customizeIcon, customizeIconProps, onMousedown, onClick } = props;
|
||||
let icon: VNodeChild;
|
||||
|
||||
if (typeof customizeIcon === 'function') {
|
||||
icon = customizeIcon(customizeIconProps);
|
||||
} else {
|
||||
icon = customizeIcon;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
class={className}
|
||||
onMousedown={event => {
|
||||
event.preventDefault();
|
||||
if (onMousedown) {
|
||||
onMousedown(event);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
userSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
}}
|
||||
unselectable="on"
|
||||
onClick={onClick}
|
||||
aria-hidden
|
||||
>
|
||||
{icon !== undefined ? (
|
||||
icon
|
||||
) : (
|
||||
<span class={className.split(/\s+/).map((cls: any) => `${cls}-icon`)}>
|
||||
{slots.default && slots.default()}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
TransBtn.inheritAttrs = false;
|
||||
TransBtn.props = {
|
||||
class: PropTypes.string,
|
||||
customizeIcon: PropTypes.any,
|
||||
customizeIconProps: PropTypes.any,
|
||||
onMousedown: PropTypes.func,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default TransBtn;
|
64
components/vc-select2/interface/generator.ts
Normal file
64
components/vc-select2/interface/generator.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import * as Vue from 'vue';
|
||||
import { SelectProps, RefSelectProps } from '../generate';
|
||||
|
||||
export type SelectSource = 'option' | 'selection' | 'input';
|
||||
|
||||
export const INTERNAL_PROPS_MARK = 'RC_SELECT_INTERNAL_PROPS_MARK';
|
||||
|
||||
// =================================== Shared Type ===================================
|
||||
export type Key = string | number;
|
||||
|
||||
export type RawValueType = string | number;
|
||||
|
||||
export interface LabelValueType {
|
||||
key?: Key;
|
||||
value?: RawValueType;
|
||||
label?: Vue.VNodeChild;
|
||||
}
|
||||
export type DefaultValueType = RawValueType | RawValueType[] | LabelValueType | LabelValueType[];
|
||||
|
||||
export interface DisplayLabelValueType extends LabelValueType {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export type SingleType<MixType> = MixType extends (infer Single)[] ? Single : MixType;
|
||||
|
||||
export type OnClear = () => void;
|
||||
|
||||
export type CustomTagProps = {
|
||||
label: DefaultValueType;
|
||||
value: DefaultValueType;
|
||||
disabled: boolean;
|
||||
onClose: (event?: MouseEvent) => void;
|
||||
closable: boolean;
|
||||
};
|
||||
|
||||
// ==================================== Generator ====================================
|
||||
export type GetLabeledValue<FOT extends FlattenOptionsType> = (
|
||||
value: RawValueType,
|
||||
config: {
|
||||
options: FOT;
|
||||
prevValue: DefaultValueType;
|
||||
labelInValue: boolean;
|
||||
optionLabelProp: string;
|
||||
},
|
||||
) => LabelValueType;
|
||||
|
||||
export type FilterOptions<OptionsType extends object[]> = (
|
||||
searchValue: string,
|
||||
options: OptionsType,
|
||||
/** Component props, since Select & TreeSelect use different prop name, use any here */
|
||||
config: {
|
||||
optionFilterProp: string;
|
||||
filterOption: boolean | FilterFunc<OptionsType[number]>;
|
||||
},
|
||||
) => OptionsType;
|
||||
|
||||
export type FilterFunc<OptionType> = (inputValue: string, option?: OptionType) => boolean;
|
||||
|
||||
export type FlattenOptionsType<OptionsType extends object[] = object[]> = {
|
||||
key: Key;
|
||||
data: OptionsType[number];
|
||||
/** Used for customize data */
|
||||
[name: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}[];
|
54
components/vc-select2/interface/index.ts
Normal file
54
components/vc-select2/interface/index.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import * as Vue from 'vue';
|
||||
import { Key, RawValueType } from './generator';
|
||||
|
||||
export type RenderDOMFunc = (props: any) => HTMLElement;
|
||||
|
||||
export type RenderNode = Vue.VNodeChild | ((props: any) => Vue.VNodeChild);
|
||||
|
||||
export type Mode = 'multiple' | 'tags' | 'combobox';
|
||||
|
||||
// ======================== Option ========================
|
||||
export type OnActiveValue = (
|
||||
active: RawValueType,
|
||||
index: number,
|
||||
info?: { source?: 'keyboard' | 'mouse' },
|
||||
) => void;
|
||||
|
||||
export interface OptionCoreData {
|
||||
key?: Key;
|
||||
disabled?: boolean;
|
||||
value: Key;
|
||||
title?: string;
|
||||
className?: string;
|
||||
class?: string;
|
||||
style?: Vue.CSSProperties;
|
||||
label?: Vue.VNodeChild;
|
||||
/** @deprecated Only works when use `children` as option data */
|
||||
children?: Vue.VNodeChild;
|
||||
}
|
||||
|
||||
export interface OptionData extends OptionCoreData {
|
||||
/** Save for customize data */
|
||||
[prop: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
export interface OptionGroupData {
|
||||
key?: Key;
|
||||
label?: Vue.VNodeChild;
|
||||
options: OptionData[];
|
||||
className?: string;
|
||||
class?: string;
|
||||
style?: Vue.CSSProperties;
|
||||
|
||||
/** Save for customize data */
|
||||
[prop: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
export type OptionsType = (OptionData | OptionGroupData)[];
|
||||
|
||||
export interface FlattenOptionData {
|
||||
group?: boolean;
|
||||
groupOption?: boolean;
|
||||
key: string | number;
|
||||
data: OptionData | OptionGroupData;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { inject, provide } from 'vue';
|
||||
import { defineComponent, inject, provide } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import contains from '../vc-util/Dom/contains';
|
||||
import {
|
||||
@ -37,7 +37,7 @@ const ALL_HANDLERS = [
|
||||
'onContextmenu',
|
||||
];
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'Trigger',
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
@ -653,4 +653,4 @@ export default {
|
||||
}
|
||||
return [portal, trigger];
|
||||
},
|
||||
};
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user