chore: rever util to js

pull/2935/head
undefined 2020-10-02 15:44:10 +08:00
parent 609de24f19
commit b7db5b31ba
60 changed files with 492 additions and 543 deletions

View File

@ -2,7 +2,7 @@ import { getOptionProps } from './props-util';
export default { export default {
methods: { methods: {
setState(state = {}, callback: () => void) { setState(state = {}, callback) {
let newState = typeof state === 'function' ? state(this.$data, this.$props) : state; let newState = typeof state === 'function' ? state(this.$data, this.$props) : state;
if (this.getDerivedStateFromProps) { if (this.getDerivedStateFromProps) {
const s = this.getDerivedStateFromProps(getOptionProps(this), { const s = this.getDerivedStateFromProps(getOptionProps(this), {
@ -25,7 +25,6 @@ export default {
}, },
__emit() { __emit() {
// 直接调用事件底层组件不需要vueTool记录events // 直接调用事件底层组件不需要vueTool记录events
// eslint-disable-next-line prefer-rest-params
const args = [].slice.call(arguments, 0); const args = [].slice.call(arguments, 0);
let eventName = args[0]; let eventName = args[0];
eventName = `on${eventName[0].toUpperCase()}${eventName.substring(1)}`; eventName = `on${eventName[0].toUpperCase()}${eventName.substring(1)}`;

View File

@ -2,7 +2,7 @@ import { getOptionProps } from './props-util';
export default { export default {
methods: { methods: {
setState(state = {}, callback: () => any) { setState(state = {}, callback) {
let newState = typeof state === 'function' ? state(this, this.$props) : state; let newState = typeof state === 'function' ? state(this, this.$props) : state;
if (this.getDerivedStateFromProps) { if (this.getDerivedStateFromProps) {
const s = this.getDerivedStateFromProps(getOptionProps(this), { const s = this.getDerivedStateFromProps(getOptionProps(this), {
@ -25,7 +25,6 @@ export default {
}, },
__emit() { __emit() {
// 直接调用事件底层组件不需要vueTool记录events // 直接调用事件底层组件不需要vueTool记录events
// eslint-disable-next-line prefer-rest-params
const args = [].slice.call(arguments, 0); const args = [].slice.call(arguments, 0);
let eventName = args[0]; let eventName = args[0];
eventName = `on${eventName[0].toUpperCase()}${eventName.substring(1)}`; eventName = `on${eventName[0].toUpperCase()}${eventName.substring(1)}`;

View File

@ -0,0 +1,98 @@
import PropTypes from './vue-types';
export default {
props: {
autoMount: PropTypes.bool.def(true),
autoDestroy: PropTypes.bool.def(true),
visible: PropTypes.bool,
forceRender: PropTypes.bool.def(false),
parent: PropTypes.any,
getComponent: PropTypes.func.isRequired,
getContainer: PropTypes.func.isRequired,
children: PropTypes.func.isRequired,
},
mounted() {
if (this.autoMount) {
this.renderComponent();
}
},
updated() {
if (this.autoMount) {
this.renderComponent();
}
},
beforeUnmount() {
if (this.autoDestroy) {
this.removeContainer();
}
},
methods: {
removeContainer() {
if (this.container) {
this._component && this._component.$destroy();
this.container.parentNode.removeChild(this.container);
this.container = null;
this._component = null;
}
},
renderComponent(props = {}, ready) {
const { visible, forceRender, getContainer, parent } = this;
const self = this;
if (visible || parent._component || parent.$refs._component || forceRender) {
let el = this.componentEl;
if (!this.container) {
this.container = getContainer();
el = document.createElement('div');
this.componentEl = el;
this.container.appendChild(el);
}
// self.getComponent render render
const com = { component: self.getComponent(props) };
if (!this._component) {
this._component = new this.$root.constructor({
el,
parent: self,
data: {
_com: com,
},
mounted() {
this.$nextTick(() => {
if (ready) {
ready.call(self);
}
});
},
updated() {
this.$nextTick(() => {
if (ready) {
ready.call(self);
}
});
},
methods: {
setComponent(_com) {
this.$data._com = _com;
},
},
render() {
return this.$data._com.component;
},
});
} else {
this._component.setComponent(com);
}
}
},
},
render() {
return this.children({
renderComponent: this.renderComponent,
removeContainer: this.removeContainer,
});
},
};

View File

@ -1,10 +0,0 @@
export function antDecorator(Vue) {
return Vue.directive('decorator', {});
}
export default {
// just for tag
install: Vue => {
antDecorator(Vue);
},
};

View File

@ -425,13 +425,13 @@ const KeyCode = {
* WIN_IME * WIN_IME
*/ */
WIN_IME: 229, WIN_IME: 229,
};
// ======================== Function ======================== /*
/** whether text and modified key is entered at the same time.
* whether text and modified key is entered at the same time.
*/ */
isTextModifyingKeyEvent: function isTextModifyingKeyEvent(e: KeyboardEvent) { KeyCode.isTextModifyingKeyEvent = function isTextModifyingKeyEvent(e) {
const { keyCode } = e; const keyCode = e.keyCode;
if ( if (
(e.altKey && !e.ctrlKey) || (e.altKey && !e.ctrlKey) ||
e.metaKey || e.metaKey ||
@ -471,12 +471,12 @@ const KeyCode = {
default: default:
return true; return true;
} }
}, };
/** /*
* whether character is entered. whether character is entered.
*/ */
isCharacterKey: function isCharacterKey(keyCode: number) { KeyCode.isCharacterKey = function isCharacterKey(keyCode) {
if (keyCode >= KeyCode.ZERO && keyCode <= KeyCode.NINE) { if (keyCode >= KeyCode.ZERO && keyCode <= KeyCode.NINE) {
return true; return true;
} }
@ -490,7 +490,7 @@ const KeyCode = {
} }
// Safari sends zero key code for non-latin characters. // Safari sends zero key code for non-latin characters.
if (window.navigator.userAgent.indexOf('WebKit') !== -1 && keyCode === 0) { if (window.navigation.userAgent.indexOf('WebKit') !== -1 && keyCode === 0) {
return true; return true;
} }
@ -516,7 +516,6 @@ const KeyCode = {
default: default:
return false; return false;
} }
},
}; };
export default KeyCode; export default KeyCode;

View File

@ -1,18 +1,16 @@
import PropTypes from './vue-types'; import PropTypes from './vue-types';
import { Teleport, defineComponent, PropType } from 'vue'; import { Teleport } from 'vue';
export default defineComponent({ export default {
name: 'Portal', name: 'Portal',
props: { props: {
getContainer: { getContainer: PropTypes.func.isRequired,
type: Function as PropType<(triggerNode: HTMLElement) => HTMLElement>,
required: true,
},
children: PropTypes.any.isRequired, children: PropTypes.any.isRequired,
didUpdate: PropTypes.func, didUpdate: PropTypes.func,
}, },
beforeCreate() { data() {
this._container = null; this._container = null;
return {};
}, },
mounted() { mounted() {
this.createContainer(); this.createContainer();
@ -47,4 +45,4 @@ export default defineComponent({
} }
return null; return null;
}, },
}); };

View File

@ -1,31 +1,25 @@
function onCompositionStart(e: Event) { function onCompositionStart(e) {
(e.target as any).composing = true; e.target.composing = true;
} }
function onCompositionEnd(e: Event) { function onCompositionEnd(e) {
const target = e.target as any; // prevent triggering an input event for no reason
if (target.composing) { if (!e.target.composing) return;
target.composing = false; e.target.composing = false;
trigger(target, 'input'); trigger(e.target, 'input');
}
} }
function trigger(el: HTMLElement, type: string) { function trigger(el, type) {
const e = document.createEvent('HTMLEvents'); const e = document.createEvent('HTMLEvents');
e.initEvent(type, true, true); e.initEvent(type, true, true);
el.dispatchEvent(e); el.dispatchEvent(e);
} }
export function addEventListener( export function addEventListener(el, event, handler, options) {
el: Element,
event: string,
handler: EventListener,
options?: EventListenerOptions,
) {
el.addEventListener(event, handler, options); el.addEventListener(event, handler, options);
} }
const antInput = { const antInput = {
created(el: Element, binding: { modifiers: { lazy: any } }) { created(el, binding) {
if (!binding.modifiers || !binding.modifiers.lazy) { if (!binding.modifiers || !binding.modifiers.lazy) {
addEventListener(el, 'compositionstart', onCompositionStart); addEventListener(el, 'compositionstart', onCompositionStart);
addEventListener(el, 'compositionend', onCompositionEnd); addEventListener(el, 'compositionend', onCompositionEnd);

View File

@ -1,27 +1,9 @@
import { isArray, isString, isObject } from './util'; import { isArray, isString, isObject } from './util';
function classNames() {
export type ClassArray = ClassValue[]; let classes = [];
for (let i = 0; i < arguments.length; i++) {
export interface ClassDictionary { const value = arguments[i];
[id: string]: any; if (!value) continue;
}
export type ClassValue =
| string
| number
| ClassDictionary
| ClassArray
| undefined
| null
| boolean;
function classNames(...args: ClassValue[]): string {
const classes: string[] = [];
for (let i = 0; i < args.length; i++) {
const value = args[i];
if (!value) {
continue;
}
if (isString(value)) { if (isString(value)) {
classes.push(value); classes.push(value);
} else if (isArray(value)) { } else if (isArray(value)) {

View File

@ -0,0 +1,17 @@
import { tuple } from './type';
export const PresetColorTypes = tuple(
'pink',
'red',
'yellow',
'orange',
'cyan',
'green',
'blue',
'purple',
'geekblue',
'magenta',
'volcano',
'gold',
'lime',
);

View File

@ -1,22 +0,0 @@
import { ElementOf, tuple } from './type';
export const PresetStatusColorTypes = tuple('success', 'processing', 'error', 'default', 'warning');
export const PresetColorTypes = tuple(
'pink',
'red',
'yellow',
'orange',
'cyan',
'green',
'blue',
'purple',
'geekblue',
'magenta',
'volcano',
'gold',
'lime',
);
export type PresetColorType = ElementOf<typeof PresetColorTypes>;
export type PresetStatusColorType = ElementOf<typeof PresetStatusColorTypes>;

View File

@ -0,0 +1,8 @@
function createRef() {
const func = function setRef(node) {
func.current = node;
};
return func;
}
export default createRef;

View File

@ -1,12 +0,0 @@
interface RefObject<T> extends Function {
current?: T | null;
}
function createRef<T>(): RefObject<T> {
const func: RefObject<T> = (node: T | null) => {
func.current = node;
};
return func;
}
export default createRef;

View File

@ -1,4 +1,4 @@
const START_EVENT_NAME_MAP: Record<string, Record<string, string>> = { const START_EVENT_NAME_MAP = {
transitionstart: { transitionstart: {
transition: 'transitionstart', transition: 'transitionstart',
WebkitTransition: 'webkitTransitionStart', WebkitTransition: 'webkitTransitionStart',
@ -16,7 +16,7 @@ const START_EVENT_NAME_MAP: Record<string, Record<string, string>> = {
}, },
}; };
const END_EVENT_NAME_MAP: Record<string, Record<string, string>> = { const END_EVENT_NAME_MAP = {
transitionend: { transitionend: {
transition: 'transitionend', transition: 'transitionend',
WebkitTransition: 'webkitTransitionEnd', WebkitTransition: 'webkitTransitionEnd',
@ -34,8 +34,8 @@ const END_EVENT_NAME_MAP: Record<string, Record<string, string>> = {
}, },
}; };
const startEvents: any[] = []; const startEvents = [];
const endEvents: any[] = []; const endEvents = [];
function detectEvents() { function detectEvents() {
const testEl = document.createElement('div'); const testEl = document.createElement('div');
@ -51,7 +51,7 @@ function detectEvents() {
delete END_EVENT_NAME_MAP.transitionend.transition; delete END_EVENT_NAME_MAP.transitionend.transition;
} }
function process(EVENT_NAME_MAP: Record<string, Record<string, string>>, events: any[]) { function process(EVENT_NAME_MAP, events) {
for (const baseEventName in EVENT_NAME_MAP) { for (const baseEventName in EVENT_NAME_MAP) {
if (EVENT_NAME_MAP.hasOwnProperty(baseEventName)) { if (EVENT_NAME_MAP.hasOwnProperty(baseEventName)) {
const baseEvents = EVENT_NAME_MAP[baseEventName]; const baseEvents = EVENT_NAME_MAP[baseEventName];
@ -73,11 +73,11 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
detectEvents(); detectEvents();
} }
function addEventListener(node: Element, eventName: string, eventListener: any) { function addEventListener(node, eventName, eventListener) {
node.addEventListener(eventName, eventListener, false); node.addEventListener(eventName, eventListener, false);
} }
function removeEventListener(node: Element, eventName: string, eventListener: any) { function removeEventListener(node, eventName, eventListener) {
node.removeEventListener(eventName, eventListener, false); node.removeEventListener(eventName, eventListener, false);
} }
@ -85,7 +85,7 @@ const TransitionEvents = {
// Start events // Start events
startEvents, startEvents,
addStartEventListener(node: Element, eventListener: any) { addStartEventListener(node, eventListener) {
if (startEvents.length === 0) { if (startEvents.length === 0) {
window.setTimeout(eventListener, 0); window.setTimeout(eventListener, 0);
return; return;
@ -95,7 +95,7 @@ const TransitionEvents = {
}); });
}, },
removeStartEventListener(node: Element, eventListener: any) { removeStartEventListener(node, eventListener) {
if (startEvents.length === 0) { if (startEvents.length === 0) {
return; return;
} }
@ -107,7 +107,7 @@ const TransitionEvents = {
// End events // End events
endEvents, endEvents,
addEndEventListener(node: Element, eventListener: any) { addEndEventListener(node, eventListener) {
if (endEvents.length === 0) { if (endEvents.length === 0) {
window.setTimeout(eventListener, 0); window.setTimeout(eventListener, 0);
return; return;
@ -117,7 +117,7 @@ const TransitionEvents = {
}); });
}, },
removeEndEventListener(node: Element, eventListener: any) { removeEndEventListener(node, eventListener) {
if (endEvents.length === 0) { if (endEvents.length === 0) {
return; return;
} }

View File

@ -14,13 +14,7 @@ const capitalPrefixes = [
]; ];
const prefixes = ['-webkit-', '-moz-', '-o-', 'ms-', '']; const prefixes = ['-webkit-', '-moz-', '-o-', 'ms-', ''];
interface CustomHTMLElement extends HTMLElement { function getStyleProperty(node, name) {
rcEndAnimTimeout?: any;
rcAnimTimeout?: any;
rcEndListener?: Function | null;
}
function getStyleProperty(node: HTMLElement, name: string) {
// old ff need null, https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle // old ff need null, https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
const style = window.getComputedStyle(node, null); const style = window.getComputedStyle(node, null);
let ret = ''; let ret = '';
@ -33,7 +27,7 @@ function getStyleProperty(node: HTMLElement, name: string) {
return ret; return ret;
} }
function fixBrowserByTimeout(node: CustomHTMLElement) { function fixBrowserByTimeout(node) {
if (isCssAnimationSupported) { if (isCssAnimationSupported) {
const transitionDelay = parseFloat(getStyleProperty(node, 'transition-delay')) || 0; const transitionDelay = parseFloat(getStyleProperty(node, 'transition-delay')) || 0;
const transitionDuration = parseFloat(getStyleProperty(node, 'transition-duration')) || 0; const transitionDuration = parseFloat(getStyleProperty(node, 'transition-duration')) || 0;
@ -50,29 +44,20 @@ function fixBrowserByTimeout(node: CustomHTMLElement) {
} }
} }
function clearBrowserBugTimeout(node: CustomHTMLElement) { function clearBrowserBugTimeout(node) {
if (node.rcEndAnimTimeout) { if (node.rcEndAnimTimeout) {
clearTimeout(node.rcEndAnimTimeout); clearTimeout(node.rcEndAnimTimeout);
node.rcEndAnimTimeout = null; node.rcEndAnimTimeout = null;
} }
} }
interface TransitionName {
name?: string; const cssAnimation = (node, transitionName, endCallback) => {
active?: string;
}
const cssAnimation = (
node: CustomHTMLElement,
transitionName: string | TransitionName,
endCallback?: any,
) => {
const nameIsObj = typeof transitionName === 'object'; const nameIsObj = typeof transitionName === 'object';
const className = nameIsObj ? (transitionName as TransitionName).name : transitionName; const className = nameIsObj ? transitionName.name : transitionName;
const activeClassName = nameIsObj const activeClassName = nameIsObj ? transitionName.active : `${transitionName}-active`;
? (transitionName as TransitionName).active
: `${transitionName}-active`;
let end = endCallback; let end = endCallback;
let start; let start;
let active: any; let active;
const nodeClasses = classes(node); const nodeClasses = classes(node);
if (endCallback && Object.prototype.toString.call(endCallback) === '[object Object]') { if (endCallback && Object.prototype.toString.call(endCallback) === '[object Object]') {
@ -85,7 +70,7 @@ const cssAnimation = (
node.rcEndListener(); node.rcEndListener();
} }
node.rcEndListener = (e: Event) => { node.rcEndListener = e => {
if (e && e.target !== node) { if (e && e.target !== node) {
return; return;
} }
@ -139,12 +124,12 @@ const cssAnimation = (
}; };
}; };
cssAnimation.style = (node: CustomHTMLElement, style: Record<string, any>, callback?: Function) => { cssAnimation.style = (node, style, callback) => {
if (node.rcEndListener) { if (node.rcEndListener) {
node.rcEndListener(); node.rcEndListener();
} }
node.rcEndListener = (e: Event) => { node.rcEndListener = e => {
if (e && e.target !== node) { if (e && e.target !== node) {
return; return;
} }
@ -171,7 +156,7 @@ cssAnimation.style = (node: CustomHTMLElement, style: Record<string, any>, callb
node.rcAnimTimeout = requestAnimationTimeout(() => { node.rcAnimTimeout = requestAnimationTimeout(() => {
for (const s in style) { for (const s in style) {
if (style.hasOwnProperty(s)) { if (style.hasOwnProperty(s)) {
node.style[s as any] = style[s]; node.style[s] = style[s];
} }
} }
node.rcAnimTimeout = null; node.rcAnimTimeout = null;
@ -179,7 +164,7 @@ cssAnimation.style = (node: CustomHTMLElement, style: Record<string, any>, callb
}, 0); }, 0);
}; };
cssAnimation.setTransition = (node: HTMLElement, p?: any, value?: any) => { cssAnimation.setTransition = (node, p, value) => {
let property = p; let property = p;
let v = value; let v = value;
if (value === undefined) { if (value === undefined) {
@ -188,7 +173,7 @@ cssAnimation.setTransition = (node: HTMLElement, p?: any, value?: any) => {
} }
property = property || ''; property = property || '';
capitalPrefixes.forEach(prefix => { capitalPrefixes.forEach(prefix => {
node.style[`${prefix}Transition${property}` as any] = v; node.style[`${prefix}Transition${property}`] = v;
}); });
}; };

View File

@ -1,9 +1,8 @@
export function easeInOutCubic(t: number, b: number, c: number, d: number) { export function easeInOutCubic(t, b, c, d) {
const cc = c - b; const cc = c - b;
t /= d / 2; t /= d / 2;
if (t < 1) { if (t < 1) {
return (cc / 2) * t * t * t + b; return (cc / 2) * t * t * t + b;
} }
// eslint-disable-next-line no-return-assign
return (cc / 2) * ((t -= 2) * t * t + 2) + b; return (cc / 2) * ((t -= 2) * t * t + 2) + b;
} }

View File

@ -0,0 +1,17 @@
export default function getScroll(target, top) {
if (typeof window === 'undefined') {
return 0;
}
const prop = top ? 'pageYOffset' : 'pageXOffset';
const method = top ? 'scrollTop' : 'scrollLeft';
const isWindow = target === window;
let ret = isWindow ? target[prop] : target[method];
// ie6,7,8 standard mode
if (isWindow && typeof ret !== 'number') {
ret = window.document.documentElement[method];
}
return ret;
}

View File

@ -1,25 +0,0 @@
export function isWindow(obj: any) {
return obj !== null && obj !== undefined && obj === obj.window;
}
export default function getScroll(target: HTMLElement | Window | Document | null, top: Boolean) {
if (typeof window === 'undefined') {
return 0;
}
const method = top ? 'scrollTop' : 'scrollLeft';
let result = 0;
if (isWindow(target)) {
result = (target as Window)[top ? 'pageYOffset' : 'pageXOffset'];
} else if (target instanceof Document) {
result = target.documentElement[method];
} else if (target) {
result = (target as HTMLElement)[method];
}
if (target && !isWindow(target) && typeof result !== 'number') {
result = ((target as HTMLElement).ownerDocument || (target as Document)).documentElement[
method
];
}
return result;
}

View File

@ -1,6 +1,6 @@
let cached: number | undefined; let cached;
export default function getScrollBarSize(fresh?: boolean) { export default function getScrollBarSize(fresh) {
if (fresh || cached === undefined) { if (fresh || cached === undefined) {
const inner = document.createElement('div'); const inner = document.createElement('div');
inner.style.width = '100%'; inner.style.width = '100%';
@ -10,8 +10,8 @@ export default function getScrollBarSize(fresh?: boolean) {
const outerStyle = outer.style; const outerStyle = outer.style;
outerStyle.position = 'absolute'; outerStyle.position = 'absolute';
outerStyle.top = '0'; outerStyle.top = 0;
outerStyle.left = '0'; outerStyle.left = 0;
outerStyle.pointerEvents = 'none'; outerStyle.pointerEvents = 'none';
outerStyle.visibility = 'hidden'; outerStyle.visibility = 'hidden';
outerStyle.width = '200px'; outerStyle.width = '200px';

View File

@ -1,5 +1,4 @@
const isNumeric = (value: any): boolean => { const isNumeric = value => {
return !isNaN(parseFloat(value)) && isFinite(value); return !isNaN(parseFloat(value)) && isFinite(value);
}; };
export default isNumeric; export default isNumeric;

View File

@ -1,5 +1,4 @@
const isValid = (value: unknown) => { const isValid = value => {
return value !== undefined && value !== null && value !== ''; return value !== undefined && value !== null && value !== '';
}; };
export default isValid; export default isValid;

View File

@ -2,10 +2,10 @@ import cssAnimation from './css-animation';
import raf from 'raf'; import raf from 'raf';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
function animate(node: HTMLElement, show: boolean, done: () => void) { function animate(node, show, done) {
let height: number; let height;
let requestAnimationFrameId: number; let requestAnimationFrameId;
let appearRequestAnimationFrameId: number; let appearRequestAnimationFrameId;
return cssAnimation(node, 'ant-motion-collapse-legacy', { return cssAnimation(node, 'ant-motion-collapse-legacy', {
start() { start() {
if (appearRequestAnimationFrameId) { if (appearRequestAnimationFrameId) {
@ -54,12 +54,12 @@ function animate(node: HTMLElement, show: boolean, done: () => void) {
} }
const animation = { const animation = {
onEnter(node: HTMLElement, done: () => void) { onEnter(node, done) {
nextTick(() => { nextTick(() => {
animate(node, true, done); animate(node, true, done);
}); });
}, },
onLeave(node: HTMLElement, done: () => void) { onLeave(node, done) {
return animate(node, false, done); return animate(node, false, done);
}, },
}; };

View File

@ -11,13 +11,13 @@ const attributes = `accept acceptCharset accessKey action allowFullScreen allowT
shape size sizes span spellCheck src srcDoc srcLang srcSet start step style shape size sizes span spellCheck src srcDoc srcLang srcSet start step style
summary tabIndex target title type useMap value width wmode wrap`; summary tabIndex target title type useMap value width wmode wrap`;
const eventsName = `onCopy onCut onPaste onCompositionend onCompositionstart onCompositionupdate onKeydown const eventsName = `onCopy onCut onPaste onCompositionEnd onCompositionStart onCompositionUpdate onKeyDown
onKeypress onKeyup onFocus onBlur onChange onInput onSubmit onClick onContextmenu onDoubleclick onDblclick onKeyPress onKeyUp onFocus onBlur onChange onInput onSubmit onClick onContextMenu onDoubleClick
onDrag onDragend onDragenter onDragexit onDragleave onDragover onDragstart onDrop onMousedown onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown
onMouseenter onMouseleave onMousemove onMouseout onMouseover onMouseup onSelect onTouchcancel onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp onSelect onTouchCancel
onTouchend onTouchmove onTouchstart onScroll onWheel onAbort onCanplay onCanplaythrough onTouchEnd onTouchMove onTouchStart onScroll onWheel onAbort onCanPlay onCanPlayThrough
onDurationchange onEmptied onEncrypted onEnded onError onLoadedsata onLoadedmetadata onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata
onLoadstart onPause onPlay onPlaying onProgress onRatechange onSeeked onSeeking onStalled onSuspend onTimeupdate onVolumechange onWaiting onLoad onError`; onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting onLoad onError`;
const propList = `${attributes} ${eventsName}`.split(/[\s\n]+/); const propList = `${attributes} ${eventsName}`.split(/[\s\n]+/);
@ -25,23 +25,17 @@ const propList = `${attributes} ${eventsName}`.split(/[\s\n]+/);
const ariaPrefix = 'aria-'; const ariaPrefix = 'aria-';
const dataPrefix = 'data-'; const dataPrefix = 'data-';
function match(key: string, prefix: string) { function match(key, prefix) {
return key.indexOf(prefix) === 0; return key.indexOf(prefix) === 0;
} }
export interface PickConfig {
aria?: boolean;
data?: boolean;
attr?: boolean;
}
/** /**
* Picker props from exist props with filter * Picker props from exist props with filter
* @param props Passed props * @param props Passed props
* @param ariaOnly boolean | { aria?: boolean; data?: boolean; attr?: boolean; } filter config * @param ariaOnly boolean | { aria?: boolean; data?: boolean; attr?: boolean; } filter config
*/ */
export default function pickAttrs(props: object, ariaOnly: boolean | PickConfig = false) { export default function pickAttrs(props, ariaOnly = false) {
let mergedConfig: PickConfig; let mergedConfig;
if (ariaOnly === false) { if (ariaOnly === false) {
mergedConfig = { mergedConfig = {
aria: true, aria: true,

View File

@ -1,18 +1,18 @@
import { isVNode, Fragment, Comment, Text, h, VNode, ComponentPublicInstance, Slots } from 'vue';
import isPlainObject from 'lodash-es/isPlainObject'; import isPlainObject from 'lodash-es/isPlainObject';
import classNames from './classNames';
import { isVNode, Fragment, Comment, Text, h } from 'vue';
import { camelize, hyphenate, isOn, resolvePropValue } from './util'; import { camelize, hyphenate, isOn, resolvePropValue } from './util';
import isValid from './isValid'; import isValid from './isValid';
import { Data, PropOptions } from './type';
// function getType(fn) { // function getType(fn) {
// const match = fn && fn.toString().match(/^\s*function (\w+)/); // const match = fn && fn.toString().match(/^\s*function (\w+)/);
// return match ? match[1] : ''; // return match ? match[1] : '';
// } // }
const splitAttrs = (attrs: Data) => { const splitAttrs = attrs => {
const allAttrs = Object.keys(attrs); const allAttrs = Object.keys(attrs);
const eventAttrs: Data = {}; const eventAttrs = {};
const onEvents: Data = {}; const onEvents = {};
const extraAttrs: Data = {}; const extraAttrs = {};
for (let i = 0, l = allAttrs.length; i < l; i++) { for (let i = 0, l = allAttrs.length; i < l; i++) {
const key = allAttrs[i]; const key = allAttrs[i];
if (isOn(key)) { if (isOn(key)) {
@ -24,8 +24,8 @@ const splitAttrs = (attrs: Data) => {
} }
return { onEvents, events: eventAttrs, extraAttrs }; return { onEvents, events: eventAttrs, extraAttrs };
}; };
const parseStyleText = (cssText = '', camel: boolean) => { const parseStyleText = (cssText = '', camel) => {
const res: Record<string, string> = {}; const res = {};
const listDelimiter = /;(?![^(]*\))/g; const listDelimiter = /;(?![^(]*\))/g;
const propertyDelimiter = /:(.+)/; const propertyDelimiter = /:(.+)/;
cssText.split(listDelimiter).forEach(function(item) { cssText.split(listDelimiter).forEach(function(item) {
@ -40,7 +40,11 @@ const parseStyleText = (cssText = '', camel: boolean) => {
return res; return res;
}; };
const hasProp = (instance: ComponentPublicInstance, prop: string) => { const getComponentFromSetup = (props, slots, name, options) => {
return props[name] ? props[name] : slots[name]?.(options);
};
const hasProp = (instance, prop) => {
return prop in getOptionProps(instance); return prop in getOptionProps(instance);
}; };
// 重构后直接使用 hasProp 替换 // 重构后直接使用 hasProp 替换
@ -100,7 +104,7 @@ const getSlot = (self, name = 'default', options = {}) => {
return []; return [];
} }
} else { } else {
const res = self.$slots[name] && self.$slots[name](options); let res = self.$slots[name] && self.$slots[name](options);
return flattenChildren(res); return flattenChildren(res);
} }
}; };
@ -115,14 +119,14 @@ const getAllChildren = ele => {
const getSlotOptions = () => { const getSlotOptions = () => {
throw Error('使用 .type 直接取值'); throw Error('使用 .type 直接取值');
}; };
const findDOMNode = (instance: ComponentPublicInstance) => { const findDOMNode = instance => {
let node = instance && (instance.$el || instance); let node = instance && (instance.$el || instance);
while (node && !node.tagName) { while (node && !node.tagName) {
node = node.nextSibling; node = node.nextSibling;
} }
return node; return node;
}; };
const getOptionProps = (instance: ComponentPublicInstance) => { const getOptionProps = instance => {
const res = {}; const res = {};
if (instance.$ && instance.$.vnode) { if (instance.$ && instance.$.vnode) {
const props = instance.$.vnode.props || {}; const props = instance.$.vnode.props || {};
@ -149,22 +153,7 @@ const getOptionProps = (instance: ComponentPublicInstance) => {
} }
return res; return res;
}; };
const getComponent = (instance, prop = 'default', options = instance, execute = true) => {
const getComponentFromSetup = (
props: Record<string, unknown>,
slots: Slots,
name: string,
options?: unknown,
) => {
return props[name] ? props[name] : slots[name]?.(options);
};
const getComponent = (
instance: ComponentPublicInstance,
prop = 'default',
options = instance,
execute = true,
) => {
let com = undefined; let com = undefined;
if (instance.$) { if (instance.$) {
const temp = instance[prop]; const temp = instance[prop];
@ -243,7 +232,7 @@ const getAllProps = ele => {
return props; return props;
}; };
const getPropsData = (ins: ComponentPublicInstance) => { const getPropsData = ins => {
const vnode = ins.$ ? ins.$ : ins; const vnode = ins.$ ? ins.$ : ins;
const res = {}; const res = {};
const originProps = vnode.props || {}; const originProps = vnode.props || {};
@ -275,7 +264,7 @@ const getAttrs = ele => {
}; };
const getKey = ele => { const getKey = ele => {
const key = ele.key; let key = ele.key;
return key; return key;
}; };
@ -289,7 +278,7 @@ export function getEvents(ele = {}, on = true) {
return splitAttrs(props)[on ? 'onEvents' : 'events']; return splitAttrs(props)[on ? 'onEvents' : 'events'];
} }
export function getEvent(child: VNode, event: string) { export function getEvent(child, event) {
return child.props && child.props[event]; return child.props && child.props[event];
} }
@ -309,7 +298,7 @@ export function getListeners(context) {
} }
export function getClass(ele) { export function getClass(ele) {
const props = (isVNode(ele) ? ele.props : ele.$attrs) || {}; const props = (isVNode(ele) ? ele.props : ele.$attrs) || {};
const tempCls = props.class || {}; let tempCls = props.class || {};
let cls = {}; let cls = {};
if (typeof tempCls === 'string') { if (typeof tempCls === 'string') {
tempCls.split(' ').forEach(c => { tempCls.split(' ').forEach(c => {
@ -348,7 +337,7 @@ export function isFragment(c) {
return c.length === 1 && c[0].type === Fragment; return c.length === 1 && c[0].type === Fragment;
} }
export function isEmptyElement(c: VNode) { export function isEmptyElement(c) {
return ( return (
c.type === Comment || c.type === Comment ||
(c.type === Fragment && c.children.length === 0) || (c.type === Fragment && c.children.length === 0) ||
@ -356,12 +345,12 @@ export function isEmptyElement(c: VNode) {
); );
} }
export function isStringElement(c: VNode): boolean { export function isStringElement(c) {
return c && c.type === Text; return c && c.type === Text;
} }
export function filterEmpty(children: VNode[] = []) { export function filterEmpty(children = []) {
const res: VNode[] = []; const res = [];
children.forEach(child => { children.forEach(child => {
if (Array.isArray(child)) { if (Array.isArray(child)) {
res.push(...child); res.push(...child);
@ -373,14 +362,10 @@ export function filterEmpty(children: VNode[] = []) {
}); });
return res.filter(c => !isEmptyElement(c)); return res.filter(c => !isEmptyElement(c));
} }
const initDefaultProps = <T>( const initDefaultProps = (propTypes, defaultProps) => {
propTypes: T, Object.keys(defaultProps).forEach(k => {
defaultProps: { [K in Extract<keyof T, string>]?: T[K] }, if (propTypes[k]) {
): T => { propTypes[k].def && (propTypes[k] = propTypes[k].def(defaultProps[k]));
Object.keys(defaultProps).forEach((k: Extract<keyof T, string>) => {
const prop = propTypes[k] as PropOptions;
if (prop) {
prop.default = defaultProps[k];
} else { } else {
throw new Error(`not have ${k} prop`); throw new Error(`not have ${k} prop`);
} }
@ -388,11 +373,28 @@ const initDefaultProps = <T>(
return propTypes; return propTypes;
}; };
export function mergeProps() {
const args = [].slice.call(arguments, 0);
const props = {};
args.forEach((p = {}) => {
for (const [k, v] of Object.entries(p)) {
props[k] = props[k] || {};
if (isPlainObject(v)) {
Object.assign(props[k], v);
} else {
props[k] = v;
}
}
});
return props;
}
function isValidElement(element) { function isValidElement(element) {
return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node
} }
export { export {
getComponentFromSetup,
splitAttrs, splitAttrs,
hasProp, hasProp,
getOptionProps, getOptionProps,
@ -414,6 +416,5 @@ export {
getAllChildren, getAllChildren,
findDOMNode, findDOMNode,
flattenChildren, flattenChildren,
getComponentFromSetup,
}; };
export default hasProp; export default hasProp;

View File

@ -1,14 +1,10 @@
import raf from 'raf'; import raf from 'raf';
interface RafMap {
[id: number]: number;
}
let id = 0; let id = 0;
const ids: RafMap = {}; const ids = {};
// Support call raf with delay specified frame // Support call raf with delay specified frame
export default function wrapperRaf(callback: () => void, delayFrames = 1): number { export default function wrapperRaf(callback, delayFrames = 1) {
const myId = id++; const myId = id++;
let restFrames = delayFrames; let restFrames = delayFrames;
@ -28,10 +24,9 @@ export default function wrapperRaf(callback: () => void, delayFrames = 1): numbe
return myId; return myId;
} }
wrapperRaf.cancel = function(pid?: number) { wrapperRaf.cancel = function(pid) {
if (pid === undefined) return; if (pid === undefined) return;
raf.cancel(ids[pid]); raf.cancel(ids[pid]);
delete ids[pid]; delete ids[pid];
}; };
wrapperRaf.ids = ids; // export this for test usage wrapperRaf.ids = ids; // export this for test usage

View File

@ -1,10 +1,6 @@
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs'; export const responsiveArray = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
export type BreakpointMap = Partial<Record<Breakpoint, string>>;
export type ScreenMap = Partial<Record<Breakpoint, boolean>>;
export const responsiveArray: Breakpoint[] = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs']; export const responsiveMap = {
export const responsiveMap: BreakpointMap = {
xs: '(max-width: 575px)', xs: '(max-width: 575px)',
sm: '(min-width: 576px)', sm: '(min-width: 576px)',
md: '(min-width: 768px)', md: '(min-width: 768px)',
@ -13,36 +9,30 @@ export const responsiveMap: BreakpointMap = {
xxl: '(min-width: 1600px)', xxl: '(min-width: 1600px)',
}; };
type SubscribeFunc = (screens: ScreenMap) => void; const subscribers = new Map();
const subscribers = new Map<Number, SubscribeFunc>();
let subUid = -1; let subUid = -1;
let screens = {}; let screens = {};
const responsiveObserve = { const responsiveObserve = {
matchHandlers: {} as { matchHandlers: {},
[prop: string]: { dispatch(pointMap) {
mql: MediaQueryList;
listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
};
},
dispatch(pointMap: ScreenMap) {
screens = pointMap; screens = pointMap;
subscribers.forEach(func => func(screens)); subscribers.forEach(func => func(screens));
return subscribers.size >= 1; return subscribers.size >= 1;
}, },
subscribe(func: SubscribeFunc): number { subscribe(func) {
if (!subscribers.size) this.register(); if (!subscribers.size) this.register();
subUid += 1; subUid += 1;
subscribers.set(subUid, func); subscribers.set(subUid, func);
func(screens); func(screens);
return subUid; return subUid;
}, },
unsubscribe(token: number) { unsubscribe(token) {
subscribers.delete(token); subscribers.delete(token);
if (!subscribers.size) this.unregister(); if (!subscribers.size) this.unregister();
}, },
unregister() { unregister() {
Object.keys(responsiveMap).forEach((screen: Breakpoint) => { Object.keys(responsiveMap).forEach(screen => {
const matchMediaQuery = responsiveMap[screen]; const matchMediaQuery = responsiveMap[screen];
const handler = this.matchHandlers[matchMediaQuery]; const handler = this.matchHandlers[matchMediaQuery];
handler?.mql.removeListener(handler?.listener); handler?.mql.removeListener(handler?.listener);
@ -50,9 +40,9 @@ const responsiveObserve = {
subscribers.clear(); subscribers.clear();
}, },
register() { register() {
Object.keys(responsiveMap).forEach((screen: Breakpoint) => { Object.keys(responsiveMap).forEach(screen => {
const matchMediaQuery = responsiveMap[screen]; const matchMediaQuery = responsiveMap[screen];
const listener = ({ matches }: { matches: boolean }) => { const listener = ({ matches }) => {
this.dispatch({ this.dispatch({
...screens, ...screens,
[screen]: matches, [screen]: matches,

View File

@ -0,0 +1,37 @@
import raf from 'raf';
import getScroll from './getScroll';
import { easeInOutCubic } from './easings';
// interface ScrollToOptions {
// /** Scroll container, default as window */
// getContainer?: () => HTMLElement | Window;
// /** Scroll end callback */
// callback?: () => any;
// /** Animation duration, default as 450 */
// duration?: number;
// }
export default function scrollTo(y, options = {}) {
const { getContainer = () => window, callback, duration = 450 } = options;
const container = getContainer();
const scrollTop = getScroll(container, true);
const startTime = Date.now();
const frameFunc = () => {
const timestamp = Date.now();
const time = timestamp - startTime;
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
if (container === window) {
window.scrollTo(window.pageXOffset, nextScrollTop);
} else {
container.scrollTop = nextScrollTop;
}
if (time < duration) {
raf(frameFunc);
} else if (typeof callback === 'function') {
callback();
}
};
raf(frameFunc);
}

View File

@ -1,38 +0,0 @@
import raf from 'raf';
import getScroll, { isWindow } from './getScroll';
import { easeInOutCubic } from './easings';
interface ScrollToOptions {
/** Scroll container, default as window */
getContainer?: () => HTMLElement | Window | Document;
/** Scroll end callback */
callback?: () => any;
/** Animation duration, default as 450 */
duration?: number;
}
export default function scrollTo(y: number, options: ScrollToOptions = {}) {
const { getContainer = () => window, callback, duration = 450 } = options;
const container = getContainer();
const scrollTop = getScroll(container, true);
const startTime = Date.now();
const frameFunc = () => {
const timestamp = Date.now();
const time = timestamp - startTime;
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
if (isWindow(container)) {
(container as Window).scrollTo(window.pageXOffset, nextScrollTop);
} else if (container instanceof HTMLDocument || container.constructor.name === 'HTMLDocument') {
(container as HTMLDocument).documentElement.scrollTop = nextScrollTop;
} else {
(container as HTMLElement).scrollTop = nextScrollTop;
}
if (time < duration) {
raf(frameFunc);
} else if (typeof callback === 'function') {
callback();
}
};
raf(frameFunc);
}

View File

@ -1,4 +1,4 @@
const isStyleSupport = (styleName: string | string[]): boolean => { const isStyleSupport = styleName => {
if (typeof window !== 'undefined' && window.document && window.document.documentElement) { if (typeof window !== 'undefined' && window.document && window.document.documentElement) {
const styleNameList = Array.isArray(styleName) ? styleName : [styleName]; const styleNameList = Array.isArray(styleName) ? styleName : [styleName];
const { documentElement } = window.document; const { documentElement } = window.document;

View File

@ -1,6 +1,6 @@
import getScrollBarSize from './getScrollBarSize'; import getScrollBarSize from './getScrollBarSize';
export default (close?: boolean) => { export default close => {
const bodyIsOverflowing = const bodyIsOverflowing =
document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight) && document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight) &&
window.innerWidth > document.body.offsetWidth; window.innerWidth > document.body.offsetWidth;

View File

@ -2,8 +2,8 @@
* Wrap of sub component which need use as Button capacity (like Icon component). * Wrap of sub component which need use as Button capacity (like Icon component).
* This helps accessibility reader to tread as a interactive button to operation. * This helps accessibility reader to tread as a interactive button to operation.
*/ */
import { defineComponent, PropType } from 'vue';
import KeyCode from './KeyCode'; import KeyCode from './KeyCode';
import PropTypes from './vue-types';
const inlineStyle = { const inlineStyle = {
border: 0, border: 0,
@ -13,30 +13,30 @@ const inlineStyle = {
display: 'inline-block', display: 'inline-block',
}; };
const TransButton = defineComponent({ const TransButton = {
name: 'TransButton', name: 'TransButton',
inheritAttrs: false, inheritAttrs: false,
props: { props: {
noStyle: Boolean, noStyle: PropTypes.bool,
onClick: Function as PropType<(e: MouseEvent) => void>, onClick: PropTypes.func,
}, },
methods: { methods: {
onKeyDown(event: KeyboardEvent) { onKeyDown(event) {
const { keyCode } = event; const { keyCode } = event;
if (keyCode === KeyCode.ENTER) { if (keyCode === KeyCode.ENTER) {
event.preventDefault(); event.preventDefault();
} }
}, },
onKeyUp(event: KeyboardEvent) { onKeyUp(event) {
const { keyCode } = event; const { keyCode } = event;
if (keyCode === KeyCode.ENTER) { if (keyCode === KeyCode.ENTER) {
this.$emit('click', event); this.$emit('click', event);
} }
}, },
setRef(btn: HTMLDivElement) { setRef(btn) {
this.$refs.div = btn; this.$refs.div = btn;
}, },
@ -67,10 +67,10 @@ const TransButton = defineComponent({
onKeyup={this.onKeyUp} onKeyup={this.onKeyUp}
style={{ ...(!noStyle ? inlineStyle : null) }} style={{ ...(!noStyle ? inlineStyle : null) }}
> >
{this.$slots.default?.()} {this.$slots.default && this.$slots.default()}
</div> </div>
); );
}, },
}); };
export default TransButton; export default TransButton;

View File

@ -1,4 +1,4 @@
export default function triggerEvent(el: HTMLElement, type: string) { export default function triggerEvent(el, type) {
if ('createEvent' in document) { if ('createEvent' in document) {
// modern browsers, IE9+ // modern browsers, IE9+
const e = document.createEvent('HTMLEvents'); const e = document.createEvent('HTMLEvents');

4
components/_util/type.js Normal file
View File

@ -0,0 +1,4 @@
// https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
export const tuple = (...args) => args;
export const tupleNum = (...args) => args;

View File

@ -1,36 +0,0 @@
import { PropType, VNodeProps } from 'vue';
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
// https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
export const tuple = <T extends string[]>(...args: T) => args;
export const tupleNum = <T extends number[]>(...args: T) => args;
/**
* https://stackoverflow.com/a/59187769
* Extract the type of an element of an array/tuple without performing indexing
*/
export type ElementOf<T> = T extends (infer E)[] ? E : T extends readonly (infer E)[] ? E : never;
/**
* https://github.com/Microsoft/TypeScript/issues/29729
*/
export type LiteralUnion<T extends U, U> = T | (U & {});
export type StringKeyOf<T> = Extract<keyof T, string>;
export type EventHandlers<E> = {
[K in StringKeyOf<E>]?: E[K] extends Function ? E[K] : (payload: E[K]) => void;
};
export type Data = Record<string, unknown>;
export type Key = string | number;
export declare type DefaultFactory<T> = (props: Data) => T | null | undefined;
export declare interface PropOptions<T = any, D = T> {
type?: PropType<T> | true | null;
required?: boolean;
default?: D | DefaultFactory<D> | null | undefined | object;
validator?(value: unknown): boolean;
}

View File

@ -1,35 +1,35 @@
export const isFunction = (val: unknown): val is Function => typeof val === 'function'; export const isFunction = val => typeof val === 'function';
export const isArray = Array.isArray; export const isArray = Array.isArray;
export const isString = (val: unknown): val is string => typeof val === 'string'; export const isString = val => typeof val === 'string';
export const isSymbol = (val: unknown): val is symbol => typeof val === 'symbol'; export const isSymbol = val => typeof val === 'symbol';
export const isObject = (val: unknown): val is object => val !== null && typeof val === 'object'; export const isObject = val => val !== null && typeof val === 'object';
const onRE = /^on[^a-z]/; const onRE = /^on[^a-z]/;
const isOn = (key: string) => onRE.test(key); const isOn = key => onRE.test(key);
const cacheStringFunction = (fn: (str: string) => string) => { const cacheStringFunction = fn => {
const cache = Object.create(null); const cache = Object.create(null);
return (str: string) => { return str => {
const hit = cache[str]; const hit = cache[str];
return hit || (cache[str] = fn(str)); return hit || (cache[str] = fn(str));
}; };
}; };
const camelizeRE = /-(\w)/g; const camelizeRE = /-(\w)/g;
const camelize = cacheStringFunction((str: string) => { const camelize = cacheStringFunction(str => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')); return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
}); });
const hyphenateRE = /\B([A-Z])/g; const hyphenateRE = /\B([A-Z])/g;
const hyphenate = cacheStringFunction((str: string) => const hyphenate = cacheStringFunction(str => {
str.replace(hyphenateRE, '-$1').toLowerCase(), return str.replace(hyphenateRE, '-$1').toLowerCase();
); });
const capitalize = cacheStringFunction((str: string) => { const capitalize = cacheStringFunction(str => {
return str.charAt(0).toUpperCase() + str.slice(1); return str.charAt(0).toUpperCase() + str.slice(1);
}); });
const hasOwnProperty = Object.prototype.hasOwnProperty; const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val: object, key: string) => hasOwnProperty.call(val, key); const hasOwn = (val, key) => hasOwnProperty.call(val, key);
// change from vue sourcecode // change from vue sourcecode
function resolvePropValue(options, props, key, value) { function resolvePropValue(options, props, key, value) {
@ -53,8 +53,8 @@ function resolvePropValue(options, props, key, value) {
return value; return value;
} }
export function getDataAndAriaProps(props: Record<string, unknown>) { export function getDataAndAriaProps(props) {
return Object.keys(props).reduce((memo: Record<string, unknown>, key: string) => { return Object.keys(props).reduce((memo, key) => {
if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-') { if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-') {
memo[key] = props[key]; memo[key] = props[key];
} }

View File

@ -1,8 +1,8 @@
import { filterEmpty } from './props-util'; import { filterEmpty } from './props-util';
import { cloneVNode, VNode } from 'vue'; import { cloneVNode } from 'vue';
import warning from './warning'; import warning from './warning';
export function cloneElement(vnode: VNode, nodeProps = {}, override = true) { export function cloneElement(vnode, nodeProps = {}, override = true) {
let ele = vnode; let ele = vnode;
if (Array.isArray(vnode)) { if (Array.isArray(vnode)) {
ele = filterEmpty(vnode)[0]; ele = filterEmpty(vnode)[0];
@ -14,10 +14,10 @@ export function cloneElement(vnode: VNode, nodeProps = {}, override = true) {
// cloneVNode内部是合并属性这里改成覆盖属性 // cloneVNode内部是合并属性这里改成覆盖属性
node.props = override ? { ...node.props, ...nodeProps } : node.props; node.props = override ? { ...node.props, ...nodeProps } : node.props;
warning(typeof node.props!.class !== 'object', 'class must be string'); warning(typeof node.props.class !== 'object', 'class must be string');
return node; return node;
} }
export function cloneVNodes(vnodes: VNode[], nodeProps = {}, override = true) { export function cloneVNodes(vnodes, nodeProps = {}, override = true) {
return vnodes.map(vnode => cloneElement(vnode, nodeProps, override)); return vnodes.map(vnode => cloneElement(vnode, nodeProps, override));
} }

View File

@ -1,13 +1,6 @@
import { PropType } from 'vue';
import isPlainObject from 'lodash-es/isPlainObject'; import isPlainObject from 'lodash-es/isPlainObject';
import { toType, getType, isFunction, validateType, isInteger, isArray, warn } from './utils'; import { toType, getType, isFunction, validateType, isInteger, isArray, warn } from './utils';
// interface BaseTypes {
// type: any;
// def: Function;
// validator: Function;
// }
const PropTypes = { const PropTypes = {
get any() { get any() {
return toType('any', { return toType('any', {
@ -16,66 +9,66 @@ const PropTypes = {
}, },
get func() { get func() {
return { return toType('function', {
type: Function, type: Function,
}; }).def(currentDefaults.func);
}, },
get bool() { get bool() {
return { return toType('boolean', {
type: Boolean, type: Boolean,
}; }).def(currentDefaults.bool);
}, },
get string() { get string() {
return { return toType('string', {
type: String, type: String,
}; }).def(currentDefaults.string);
}, },
get number() { get number() {
return { return toType('number', {
type: Number, type: Number,
}; }).def(currentDefaults.number);
}, },
get array() { get array() {
return { return toType('array', {
type: Array, type: Array,
}; }).def(currentDefaults.array);
}, },
get object() { get object() {
return { return toType('object', {
type: Object, type: Object,
}; }).def(currentDefaults.object);
}, },
get integer() { get integer() {
return { return toType('integer', {
type: Number, type: Number,
validator(value: number) { validator(value) {
return isInteger(value); return isInteger(value);
}, },
}; }).def(currentDefaults.integer);
}, },
get symbol() { get symbol() {
return { return toType('symbol', {
type: null, type: null,
validator(value: Symbol) { validator(value) {
return typeof value === 'symbol'; return typeof value === 'symbol';
}, },
}; });
}, },
custom(validatorFn: Function, warnMsg = 'custom validation failed') { custom(validatorFn, warnMsg = 'custom validation failed') {
if (typeof validatorFn !== 'function') { if (typeof validatorFn !== 'function') {
throw new TypeError('[VueTypes error]: You must provide a function as argument'); throw new TypeError('[VueTypes error]: You must provide a function as argument');
} }
return toType(validatorFn.name || '<<anonymous function>>', { return toType(validatorFn.name || '<<anonymous function>>', {
validator(...args: any[]) { validator(...args) {
const valid = validatorFn(...args); const valid = validatorFn(...args);
if (!valid) warn(`${this._vueTypes_name} - ${warnMsg}`); if (!valid) warn(`${this._vueTypes_name} - ${warnMsg}`);
return valid; return valid;
@ -83,28 +76,21 @@ const PropTypes = {
}); });
}, },
tuple<T>() { oneOf(arr) {
return {
type: (String as unknown) as PropType<T>,
};
},
oneOf<T extends readonly any[]>(arr: T) {
if (!isArray(arr)) { if (!isArray(arr)) {
throw new TypeError('[VueTypes error]: You must provide an array as argument'); throw new TypeError('[VueTypes error]: You must provide an array as argument');
} }
const msg = `oneOf - value should be one of "${arr.join('", "')}"`; const msg = `oneOf - value should be one of "${arr.join('", "')}"`;
const allowedTypes = arr.reduce((ret, v) => { const allowedTypes = arr.reduce((ret, v) => {
if (v !== null && v !== undefined) { if (v !== null && v !== undefined) {
const constr = (v as any).constructor; ret.indexOf(v.constructor) === -1 && ret.push(v.constructor);
ret.indexOf(constr) === -1 && ret.push(constr);
} }
return ret; return ret;
}, []); }, []);
return toType('oneOf', { return toType('oneOf', {
type: allowedTypes.length > 0 ? allowedTypes : null, type: allowedTypes.length > 0 ? allowedTypes : null,
validator(value: unknown) { validator(value) {
const valid = arr.indexOf(value) !== -1; const valid = arr.indexOf(value) !== -1;
if (!valid) warn(msg); if (!valid) warn(msg);
return valid; return valid;
@ -112,13 +98,13 @@ const PropTypes = {
}); });
}, },
instanceOf<T>(instanceConstructor: T) { instanceOf(instanceConstructor) {
return { return toType('instanceOf', {
type: instanceConstructor, type: instanceConstructor,
}; });
}, },
oneOfType(arr: any[]) { oneOfType(arr) {
if (!isArray(arr)) { if (!isArray(arr)) {
throw new TypeError('[VueTypes error]: You must provide an array as argument'); throw new TypeError('[VueTypes error]: You must provide an array as argument');
} }
@ -160,7 +146,7 @@ const PropTypes = {
.reduce((ret, type) => ret.concat(isArray(type) ? type : [type]), []) .reduce((ret, type) => ret.concat(isArray(type) ? type : [type]), [])
.join('", "'); .join('", "');
return this.custom(function oneOfType(value: any) { return this.custom(function oneOfType(value) {
const valid = arr.some(type => { const valid = arr.some(type => {
if (type._vueTypes_name === 'oneOf') { if (type._vueTypes_name === 'oneOf') {
return type.type ? validateType(type.type, value, true) : true; return type.type ? validateType(type.type, value, true) : true;
@ -172,10 +158,10 @@ const PropTypes = {
}).def(undefined); }).def(undefined);
}, },
arrayOf<T extends object>(type: T) { arrayOf(type) {
return toType('arrayOf', { return toType('arrayOf', {
type: Array as PropType<T[]>, type: Array,
validator(values: T[]) { validator(values) {
const valid = values.every(value => validateType(type, value)); const valid = values.every(value => validateType(type, value));
if (!valid) warn(`arrayOf - value must be an array of "${getType(type)}"`); if (!valid) warn(`arrayOf - value must be an array of "${getType(type)}"`);
return valid; return valid;
@ -183,10 +169,10 @@ const PropTypes = {
}); });
}, },
objectOf(type: any) { objectOf(type) {
return toType('objectOf', { return toType('objectOf', {
type: Object, type: Object,
validator(obj: { [x: string]: any }) { validator(obj) {
const valid = Object.keys(obj).every(key => validateType(type, obj[key])); const valid = Object.keys(obj).every(key => validateType(type, obj[key]));
if (!valid) warn(`objectOf - value must be an object of "${getType(type)}"`); if (!valid) warn(`objectOf - value must be an object of "${getType(type)}"`);
return valid; return valid;
@ -194,13 +180,13 @@ const PropTypes = {
}); });
}, },
shape(obj: { [x: string]: any; subscribe?: any; setState?: any; getState?: any }) { shape(obj) {
const keys = Object.keys(obj); const keys = Object.keys(obj);
const requiredKeys = keys.filter(key => obj[key] && obj[key].required === true); const requiredKeys = keys.filter(key => obj[key] && obj[key].required === true);
const type = toType('shape', { const type = toType('shape', {
type: Object, type: Object,
validator(value: { [x: string]: any }) { validator(value) {
if (!isPlainObject(value)) { if (!isPlainObject(value)) {
return false; return false;
} }
@ -246,7 +232,7 @@ const PropTypes = {
}, },
}; };
const typeDefaults = (): object => ({ const typeDefaults = () => ({
func: undefined, func: undefined,
bool: undefined, bool: undefined,
string: undefined, string: undefined,

View File

@ -7,15 +7,13 @@ export const hasOwn = ObjProto.hasOwnProperty;
const FN_MATCH_REGEXP = /^\s*function (\w+)/; const FN_MATCH_REGEXP = /^\s*function (\w+)/;
// https://github.com/vuejs/vue/blob/dev/src/core/util/props.js#L159 // https://github.com/vuejs/vue/blob/dev/src/core/util/props.js#L159
export const getType = (fn: any) => { export const getType = fn => {
const type = fn !== null && fn !== undefined ? (fn.type ? fn.type : fn) : null; const type = fn !== null && fn !== undefined ? (fn.type ? fn.type : fn) : null;
const match = type && type.toString().match(FN_MATCH_REGEXP); const match = type && type.toString().match(FN_MATCH_REGEXP);
return match && match[1]; return match && match[1];
}; };
export const getNativeType = ( export const getNativeType = value => {
value: { constructor: { toString: () => string } } | null | undefined,
) => {
if (value === null || value === undefined) return null; if (value === null || value === undefined) return null;
const match = value.constructor.toString().match(FN_MATCH_REGEXP); const match = value.constructor.toString().match(FN_MATCH_REGEXP);
return match && match[1]; return match && match[1];
@ -24,7 +22,6 @@ export const getNativeType = (
/** /**
* No-op function * No-op function
*/ */
// eslint-disable-next-line @typescript-eslint/no-empty-function
export const noop = () => {}; export const noop = () => {};
/** /**
@ -33,7 +30,7 @@ export const noop = () => {};
* @param {object} obj - Object * @param {object} obj - Object
* @param {string} prop - Property to check * @param {string} prop - Property to check
*/ */
export const has = (obj: object, prop: string) => hasOwn.call(obj, prop); export const has = (obj, prop) => hasOwn.call(obj, prop);
/** /**
* Determines whether the passed value is an integer. Uses `Number.isInteger` if available * Determines whether the passed value is an integer. Uses `Number.isInteger` if available
@ -66,17 +63,16 @@ export const isArray =
* @param {any} value - Value to check * @param {any} value - Value to check
* @returns {boolean} * @returns {boolean}
*/ */
export const isFunction = (value: unknown): value is Function => export const isFunction = value => toString.call(value) === '[object Function]';
toString.call(value) === '[object Function]';
/** /**
* Adds a `def` method to the object returning a new object with passed in argument as `default` property * Adds a `def` method to the object returning a new object with passed in argument as `default` property
* *
* @param {object} type - Object to enhance * @param {object} type - Object to enhance
*/ */
export const withDefault = function(type: any) { export const withDefault = function(type) {
Object.defineProperty(type, 'def', { Object.defineProperty(type, 'def', {
value(def: undefined) { value(def) {
if (def === undefined && this.default === undefined) { if (def === undefined && this.default === undefined) {
this.default = undefined; this.default = undefined;
return this; return this;
@ -104,7 +100,7 @@ export const withDefault = function(type: any) {
* *
* @param {object} type - Object to enhance * @param {object} type - Object to enhance
*/ */
export const withRequired = function(type: any) { export const withRequired = function(type) {
Object.defineProperty(type, 'isRequired', { Object.defineProperty(type, 'isRequired', {
get() { get() {
this.required = true; this.required = true;
@ -121,7 +117,7 @@ export const withRequired = function(type: any) {
* @param {object} obj - Object to enhance * @param {object} obj - Object to enhance
* @returns {object} * @returns {object}
*/ */
export const toType = (name: string, obj: { type?: any; validator?: any; def?: any }) => { export const toType = (name, obj) => {
Object.defineProperty(obj, '_vueTypes_name', { Object.defineProperty(obj, '_vueTypes_name', {
enumerable: false, enumerable: false,
writable: false, writable: false,
@ -144,11 +140,7 @@ export const toType = (name: string, obj: { type?: any; validator?: any; def?: a
* @param {boolean} silent - Silence warnings * @param {boolean} silent - Silence warnings
* @returns {boolean} * @returns {boolean}
*/ */
export const validateType = ( export const validateType = (type, value, silent = false) => {
type: any,
value: { constructor: { toString: () => string } } | null | undefined,
silent = false,
) => {
let typeToCheck = type; let typeToCheck = type;
let valid = true; let valid = true;
let expectedType; let expectedType;
@ -159,8 +151,8 @@ export const validateType = (
if (hasOwn.call(typeToCheck, 'type') && typeToCheck.type !== null) { if (hasOwn.call(typeToCheck, 'type') && typeToCheck.type !== null) {
if (isArray(typeToCheck.type)) { if (isArray(typeToCheck.type)) {
valid = typeToCheck.type.some((type: any) => validateType(type, value, true)); valid = typeToCheck.type.some(type => validateType(type, value, true));
expectedType = typeToCheck.type.map((type: any) => getType(type)).join(' or '); expectedType = typeToCheck.type.map(type => getType(type)).join(' or ');
} else { } else {
expectedType = getType(typeToCheck); expectedType = getType(typeToCheck);
@ -194,11 +186,11 @@ export const validateType = (
return valid; return valid;
}; };
let warn: any = noop; let warn = noop;
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
const hasConsole = typeof console !== 'undefined'; const hasConsole = typeof console !== 'undefined';
warn = (msg: string) => { warn = msg => {
if (hasConsole) { if (hasConsole) {
console.warn(`[VueTypes warn]: ${msg}`); console.warn(`[VueTypes warn]: ${msg}`);
} }

View File

@ -1,18 +1,18 @@
import { nextTick, inject, defineComponent } from 'vue'; import { nextTick, inject } from 'vue';
import TransitionEvents from './css-animation/Event'; import TransitionEvents from './css-animation/Event';
import raf from './raf'; import raf from './raf';
import { defaultConfigProvider } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
import { findDOMNode } from './props-util'; import { findDOMNode } from './props-util';
let styleForPesudo: HTMLStyleElement | null; let styleForPesudo;
// Where el is the DOM element you'd like to test for visibility // Where el is the DOM element you'd like to test for visibility
function isHidden(element: HTMLElement) { function isHidden(element) {
if (process.env.NODE_ENV === 'test') { if (process.env.NODE_ENV === 'test') {
return false; return false;
} }
return !element || element.offsetParent === null; return !element || element.offsetParent === null;
} }
function isNotGrey(color: string) { function isNotGrey(color) {
// eslint-disable-next-line no-useless-escape // eslint-disable-next-line no-useless-escape
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/); const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/);
if (match && match[1] && match[2] && match[3]) { if (match && match[1] && match[2] && match[3]) {
@ -20,7 +20,7 @@ function isNotGrey(color: string) {
} }
return true; return true;
} }
export default defineComponent({ export default {
name: 'Wave', name: 'Wave',
props: ['insertExtraNode'], props: ['insertExtraNode'],
mounted() { mounted() {
@ -33,7 +33,7 @@ export default defineComponent({
}); });
}, },
setup() { setup() {
const configProvider = inject('configProvider', defaultConfigProvider); const configProvider = inject('configProvider', ConfigConsumerProps);
return { return {
configProvider, configProvider,
}; };
@ -47,7 +47,7 @@ export default defineComponent({
} }
}, },
methods: { methods: {
onClick(node: HTMLElement, waveColor: string) { onClick(node, waveColor) {
if (!node || isHidden(node) || node.className.indexOf('-leave') >= 0) { if (!node || isHidden(node) || node.className.indexOf('-leave') >= 0) {
return; return;
} }
@ -87,7 +87,7 @@ export default defineComponent({
TransitionEvents.addStartEventListener(node, this.onTransitionStart); TransitionEvents.addStartEventListener(node, this.onTransitionStart);
TransitionEvents.addEndEventListener(node, this.onTransitionEnd); TransitionEvents.addEndEventListener(node, this.onTransitionEnd);
}, },
onTransitionStart(e: AnimationEvent) { onTransitionStart(e) {
if (this._.isUnmounted) return; if (this._.isUnmounted) return;
const node = findDOMNode(this); const node = findDOMNode(this);
@ -99,7 +99,7 @@ export default defineComponent({
this.resetEffect(node); this.resetEffect(node);
} }
}, },
onTransitionEnd(e: AnimationEvent) { onTransitionEnd(e) {
if (!e || e.animationName !== 'fadeEffect') { if (!e || e.animationName !== 'fadeEffect') {
return; return;
} }
@ -109,7 +109,7 @@ export default defineComponent({
const { insertExtraNode } = this.$props; const { insertExtraNode } = this.$props;
return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node'; return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node';
}, },
bindAnimationEvent(node: HTMLElement) { bindAnimationEvent(node) {
if ( if (
!node || !node ||
!node.getAttribute || !node.getAttribute ||
@ -118,9 +118,9 @@ export default defineComponent({
) { ) {
return; return;
} }
const onClick = (e: MouseEvent) => { const onClick = e => {
// Fix radio button click twice // Fix radio button click twice
if ((e.target as HTMLElement).tagName === 'INPUT' || isHidden(e.target as HTMLElement)) { if (e.target.tagName === 'INPUT' || isHidden(e.target)) {
return; return;
} }
this.resetEffect(node); this.resetEffect(node);
@ -146,7 +146,7 @@ export default defineComponent({
}; };
}, },
resetEffect(node: HTMLElement) { resetEffect(node) {
if (!node || node === this.extraNode || !(node instanceof Element)) { if (!node || node === this.extraNode || !(node instanceof Element)) {
return; return;
} }
@ -171,4 +171,4 @@ export default defineComponent({
} }
return this.$slots.default && this.$slots.default()[0]; return this.$slots.default && this.$slots.default()[0];
}, },
}); };