2021-01-28 22:10:45 +08:00
|
|
|
import type { Ref } from 'vue'
|
2020-10-31 15:20:38 +08:00
|
|
|
import { getCurrentInstance } from 'vue'
|
2020-07-28 00:32:04 +08:00
|
|
|
|
2021-01-28 22:10:45 +08:00
|
|
|
import { camelize, capitalize, extend, hasOwn, hyphenate, isArray, isObject, isString, looseEqual, toRawType } from '@vue/shared'
|
2020-09-14 10:03:33 +08:00
|
|
|
|
|
|
|
import isServer from './isServer'
|
2020-08-24 15:38:30 +08:00
|
|
|
import type { AnyFunction } from './types'
|
2021-01-28 22:10:45 +08:00
|
|
|
import { warn } from './error'
|
|
|
|
|
2021-04-09 10:00:21 +08:00
|
|
|
// type polyfill for compat isIE method
|
|
|
|
declare global {
|
|
|
|
interface Document {
|
|
|
|
documentMode?: any
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-28 22:10:45 +08:00
|
|
|
export const SCOPE = 'Util'
|
2020-07-28 00:32:04 +08:00
|
|
|
|
2021-01-28 22:10:45 +08:00
|
|
|
export type PartialCSSStyleDeclaration = Partial<Pick<CSSStyleDeclaration, 'transform' | 'transition' | 'animation'>>
|
2020-07-28 00:32:04 +08:00
|
|
|
|
|
|
|
export function toObject<T>(arr: Array<T>): Record<string, T> {
|
|
|
|
const res = {}
|
|
|
|
for (let i = 0; i < arr.length; i++) {
|
|
|
|
if (arr[i]) {
|
|
|
|
extend(res, arr[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2021-05-13 17:55:04 +08:00
|
|
|
export const getValueByPath = (obj, paths = ''): unknown => {
|
2020-07-28 00:32:04 +08:00
|
|
|
let ret: unknown = obj
|
|
|
|
paths.split('.').map(path => {
|
|
|
|
ret = ret?.[path]
|
|
|
|
})
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2020-08-24 15:38:30 +08:00
|
|
|
export function getPropByPath(obj: any, path: string, strict: boolean): {
|
2020-08-02 21:29:35 +08:00
|
|
|
o: unknown
|
|
|
|
k: string
|
|
|
|
v: Nullable<unknown>
|
2020-07-28 00:32:04 +08:00
|
|
|
} {
|
2020-08-24 15:38:30 +08:00
|
|
|
let tempObj = obj
|
2020-07-28 00:32:04 +08:00
|
|
|
path = path.replace(/\[(\w+)\]/g, '.$1')
|
|
|
|
path = path.replace(/^\./, '')
|
|
|
|
|
|
|
|
const keyArr = path.split('.')
|
|
|
|
let i = 0
|
|
|
|
for (i; i < keyArr.length - 1; i++) {
|
|
|
|
if (!tempObj && !strict) break
|
|
|
|
const key = keyArr[i]
|
2020-12-08 21:04:04 +08:00
|
|
|
|
|
|
|
if (key in tempObj) {
|
|
|
|
tempObj = tempObj[key]
|
|
|
|
} else {
|
|
|
|
if (strict) {
|
|
|
|
throw new Error('please transfer a valid prop path to form item!')
|
|
|
|
}
|
|
|
|
break
|
2020-07-28 00:32:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
o: tempObj,
|
|
|
|
k: keyArr[i],
|
|
|
|
v: tempObj?.[keyArr[i]],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate random number in range [0, 1000]
|
|
|
|
* Maybe replace with [uuid](https://www.npmjs.com/package/uuid)
|
|
|
|
*/
|
|
|
|
export const generateId = (): number => Math.floor(Math.random() * 10000)
|
|
|
|
|
|
|
|
// use isEqual instead
|
|
|
|
// export const valueEquals
|
|
|
|
|
2020-08-24 15:38:30 +08:00
|
|
|
export const escapeRegexpString = (value = ''): string =>
|
2020-07-28 00:32:04 +08:00
|
|
|
String(value).replace(/[|\\{}()[\]^$+*?.]/g, '\\$&')
|
|
|
|
|
|
|
|
// Use native Array.find, Array.findIndex instead
|
|
|
|
|
|
|
|
// coerce truthy value to array
|
2020-09-16 14:49:21 +08:00
|
|
|
export const coerceTruthyValueToArray = arr => {
|
2021-01-28 22:10:45 +08:00
|
|
|
if (!arr && arr !== 0) {
|
|
|
|
return []
|
|
|
|
}
|
2020-11-10 14:24:09 +08:00
|
|
|
return Array.isArray(arr) ? arr : [arr]
|
2020-09-16 14:49:21 +08:00
|
|
|
}
|
2020-07-28 00:32:04 +08:00
|
|
|
|
2021-01-28 22:10:45 +08:00
|
|
|
export const isIE = function (): boolean {
|
2021-04-06 11:27:30 +08:00
|
|
|
return !isServer && !isNaN(Number(document.documentMode))
|
2020-07-28 00:32:04 +08:00
|
|
|
}
|
|
|
|
|
2021-01-28 22:10:45 +08:00
|
|
|
export const isEdge = function (): boolean {
|
2020-07-28 00:32:04 +08:00
|
|
|
return !isServer && navigator.userAgent.indexOf('Edge') > -1
|
|
|
|
}
|
|
|
|
|
2021-01-28 22:10:45 +08:00
|
|
|
export const isFirefox = function (): boolean {
|
2020-09-15 10:50:32 +08:00
|
|
|
return !isServer && !!window.navigator.userAgent.match(/firefox/i)
|
2020-07-28 00:32:04 +08:00
|
|
|
}
|
|
|
|
|
2021-01-28 22:10:45 +08:00
|
|
|
export const autoprefixer = function (
|
2020-09-15 10:50:32 +08:00
|
|
|
style: PartialCSSStyleDeclaration,
|
|
|
|
): PartialCSSStyleDeclaration {
|
2020-07-28 00:32:04 +08:00
|
|
|
const rules = ['transform', 'transition', 'animation']
|
|
|
|
const prefixes = ['ms-', 'webkit-']
|
|
|
|
rules.forEach(rule => {
|
|
|
|
const value = style[rule]
|
|
|
|
if (rule && value) {
|
|
|
|
prefixes.forEach(prefix => {
|
|
|
|
style[prefix + rule] = value
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return style
|
|
|
|
}
|
|
|
|
|
2020-08-24 15:38:30 +08:00
|
|
|
export const kebabCase = hyphenate
|
2020-07-28 00:32:04 +08:00
|
|
|
|
2020-09-14 10:03:33 +08:00
|
|
|
// reexport from lodash & vue shared
|
2020-07-28 00:32:04 +08:00
|
|
|
export {
|
2020-09-14 10:03:33 +08:00
|
|
|
hasOwn,
|
2020-09-30 18:21:47 +08:00
|
|
|
// isEmpty,
|
|
|
|
// isEqual,
|
2020-08-24 15:38:30 +08:00
|
|
|
isObject,
|
2020-09-14 10:03:33 +08:00
|
|
|
isArray,
|
2020-09-22 13:02:05 +08:00
|
|
|
isString,
|
2020-07-28 00:32:04 +08:00
|
|
|
capitalize,
|
2020-08-25 22:25:46 +08:00
|
|
|
camelize,
|
2020-08-24 15:38:30 +08:00
|
|
|
looseEqual,
|
|
|
|
extend,
|
2020-07-28 00:32:04 +08:00
|
|
|
}
|
|
|
|
|
2020-09-14 10:03:33 +08:00
|
|
|
export const isBool = (val: unknown) => typeof val === 'boolean'
|
|
|
|
export const isNumber = (val: unknown) => typeof val === 'number'
|
|
|
|
export const isHTMLElement = (val: unknown) => toRawType(val).startsWith('HTML')
|
|
|
|
|
2020-08-24 15:38:30 +08:00
|
|
|
export function rafThrottle<T extends AnyFunction<any>>(fn: T): AnyFunction<void> {
|
2020-07-28 00:32:04 +08:00
|
|
|
let locked = false
|
2021-01-28 22:10:45 +08:00
|
|
|
return function (...args: any[]) {
|
2020-07-28 00:32:04 +08:00
|
|
|
if (locked) return
|
|
|
|
locked = true
|
|
|
|
window.requestAnimationFrame(() => {
|
|
|
|
fn.apply(this, args)
|
|
|
|
locked = false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-09 21:18:08 +08:00
|
|
|
export const clearTimer = (timer: Ref<TimeoutHandle>) => {
|
|
|
|
clearTimeout(timer.value)
|
|
|
|
timer.value = null
|
|
|
|
}
|
|
|
|
|
2020-08-24 00:00:20 +08:00
|
|
|
/**
|
|
|
|
* Generating a random int in range (0, max - 1)
|
|
|
|
* @param max {number}
|
|
|
|
*/
|
|
|
|
export function getRandomInt(max: number) {
|
|
|
|
return Math.floor(Math.random() * Math.floor(max))
|
|
|
|
}
|
|
|
|
|
2020-09-11 15:17:40 +08:00
|
|
|
export function entries<T>(obj: Hash<T>): [string, T][] {
|
|
|
|
return Object
|
|
|
|
.keys(obj)
|
|
|
|
.map((key: string) => ([key, obj[key]]))
|
|
|
|
}
|
|
|
|
|
2020-10-30 23:26:33 +08:00
|
|
|
export function isUndefined(val: any): val is undefined {
|
2020-09-19 20:44:07 +08:00
|
|
|
return val === void 0
|
|
|
|
}
|
|
|
|
|
2020-07-29 15:09:29 +08:00
|
|
|
export { isVNode } from 'vue'
|
2020-10-03 16:02:53 +08:00
|
|
|
|
|
|
|
export function useGlobalConfig() {
|
|
|
|
const vm: any = getCurrentInstance()
|
|
|
|
if ('$ELEMENT' in vm.proxy) {
|
|
|
|
return vm.proxy.$ELEMENT
|
|
|
|
}
|
|
|
|
return {}
|
|
|
|
}
|
2021-01-28 22:10:45 +08:00
|
|
|
|
|
|
|
export const arrayFindIndex = function <T = any>(
|
2020-10-31 15:20:38 +08:00
|
|
|
arr: Array<T>,
|
|
|
|
pred: (args: T) => boolean,
|
2020-10-20 10:31:47 +08:00
|
|
|
): number {
|
|
|
|
return arr.findIndex(pred)
|
|
|
|
}
|
|
|
|
|
2021-05-13 17:55:04 +08:00
|
|
|
export const arrayFind = function <T>(
|
2020-10-31 15:20:38 +08:00
|
|
|
arr: Array<T>,
|
|
|
|
pred: (args: T) => boolean,
|
2021-05-13 17:55:04 +08:00
|
|
|
): T {
|
2020-10-20 10:31:47 +08:00
|
|
|
return arr.find(pred)
|
|
|
|
}
|
2020-10-30 23:26:33 +08:00
|
|
|
|
|
|
|
export function isEmpty(val: unknown) {
|
|
|
|
if (
|
|
|
|
!val && val !== 0 ||
|
|
|
|
isArray(val) && !val.length ||
|
|
|
|
isObject(val) && !Object.keys(val).length
|
|
|
|
) return true
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
export function arrayFlat(arr: unknown[]) {
|
|
|
|
return arr.reduce((acm: unknown[], item) => {
|
|
|
|
const val = Array.isArray(item) ? arrayFlat(item) : item
|
|
|
|
return acm.concat(val)
|
|
|
|
}, [])
|
|
|
|
}
|
|
|
|
|
|
|
|
export function deduplicate<T>(arr: T[]) {
|
2020-11-24 01:03:30 +08:00
|
|
|
return Array.from(new Set(arr))
|
2020-10-30 23:26:33 +08:00
|
|
|
}
|
2020-11-10 14:55:03 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unwraps refed value
|
|
|
|
* @param ref Refed value
|
|
|
|
*/
|
2021-01-28 22:10:45 +08:00
|
|
|
export function $<T>(ref: Ref<T>) {
|
2020-11-10 14:55:03 +08:00
|
|
|
return ref.value
|
|
|
|
}
|
2021-01-28 22:10:45 +08:00
|
|
|
|
|
|
|
export function addUnit(value: string | number) {
|
|
|
|
if (isString(value)) {
|
|
|
|
return value
|
|
|
|
} else if (isNumber(value)) {
|
|
|
|
return value + 'px'
|
|
|
|
}
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
|
|
warn(SCOPE, 'binding value must be a string or number')
|
|
|
|
}
|
|
|
|
return ''
|
|
|
|
}
|