trigger
parent
78d3332bb3
commit
2e07f98d40
|
@ -1,3 +1,4 @@
|
||||||
|
import Vue from 'vue'
|
||||||
function defaultGetContainer () {
|
function defaultGetContainer () {
|
||||||
const container = document.createElement('div')
|
const container = document.createElement('div')
|
||||||
document.body.appendChild(container)
|
document.body.appendChild(container)
|
||||||
|
@ -19,7 +20,7 @@ export default function getContainerRenderMixin (config) {
|
||||||
mixin = {
|
mixin = {
|
||||||
...mixin,
|
...mixin,
|
||||||
mounted () {
|
mounted () {
|
||||||
this.renderComponent()
|
// this.renderComponent()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +29,7 @@ export default function getContainerRenderMixin (config) {
|
||||||
mixin = {
|
mixin = {
|
||||||
...mixin,
|
...mixin,
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
this.removeContainer()
|
// this.removeContainer()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,21 +45,29 @@ export default function getContainerRenderMixin (config) {
|
||||||
},
|
},
|
||||||
renderComponent (componentArg) {
|
renderComponent (componentArg) {
|
||||||
if (
|
if (
|
||||||
!isVisible || isVisible(this) ||
|
!isVisible || this._component || isVisible(this) ||
|
||||||
(isForceRender && isForceRender(this))
|
(isForceRender && isForceRender(this))
|
||||||
) {
|
) {
|
||||||
if (!this._container) {
|
if (!this._container) {
|
||||||
this._container = getContainer(this)
|
this._container = getContainer(this)
|
||||||
}
|
}
|
||||||
this._container.appendChild(this.$el)
|
let component
|
||||||
|
if (this.getComponent) {
|
||||||
|
component = this.getComponent(componentArg)
|
||||||
|
} else {
|
||||||
|
component = getComponent(this, componentArg)
|
||||||
|
}
|
||||||
|
this._component = component
|
||||||
|
const vmC = document.createElement('div')
|
||||||
|
this._container.appendChild(vmC)
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: vmC,
|
||||||
|
render () {
|
||||||
|
return component
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
let component
|
|
||||||
if (this.getComponent) {
|
|
||||||
component = this.getComponent(componentArg)
|
|
||||||
} else {
|
|
||||||
component = getComponent(this, componentArg)
|
|
||||||
}
|
|
||||||
this._component = component
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,17 @@ export function cloneVNodes (vnodes, deep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cloneElement (node, nodeProps) {
|
export function cloneElement (node, nodeProps) {
|
||||||
const { props, key } = nodeProps
|
const { props, key, ref } = nodeProps
|
||||||
if (node.componentOptions) {
|
if (node.componentOptions) {
|
||||||
Object.assign(node.componentOptions.propsData, props)
|
Object.assign(node.componentOptions.propsData, props)
|
||||||
}
|
}
|
||||||
if (node.data) {
|
const data = node.data || {}
|
||||||
const data = node.data
|
const { style = data.style,
|
||||||
const { style = data.style, class: cls = data.class, attrs = data.attrs } = nodeProps
|
class: cls = data.class,
|
||||||
Object.assign(node.data, { style, attrs, class: cls })
|
attrs = data.attrs,
|
||||||
}
|
on = data.on,
|
||||||
|
} = nodeProps
|
||||||
|
Object.assign(node.data, { style, attrs, class: cls, on })
|
||||||
if (key !== undefined) {
|
if (key !== undefined) {
|
||||||
node.key = key
|
node.key = key
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
import isPlainObject from 'lodash.isplainobject'
|
||||||
|
import { noop, toType, getType, isFunction, validateType, isInteger, isArray, warn } from './utils'
|
||||||
|
|
||||||
|
const VuePropTypes = {
|
||||||
|
|
||||||
|
get any () {
|
||||||
|
return toType('any', {
|
||||||
|
type: null,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
get func () {
|
||||||
|
return toType('function', {
|
||||||
|
type: Function,
|
||||||
|
}).def(currentDefaults.func)
|
||||||
|
},
|
||||||
|
|
||||||
|
get bool () {
|
||||||
|
return toType('boolean', {
|
||||||
|
type: Boolean,
|
||||||
|
}).def(currentDefaults.bool)
|
||||||
|
},
|
||||||
|
|
||||||
|
get string () {
|
||||||
|
return toType('string', {
|
||||||
|
type: String,
|
||||||
|
}).def(currentDefaults.string)
|
||||||
|
},
|
||||||
|
|
||||||
|
get number () {
|
||||||
|
return toType('number', {
|
||||||
|
type: Number,
|
||||||
|
}).def(currentDefaults.number)
|
||||||
|
},
|
||||||
|
|
||||||
|
get array () {
|
||||||
|
return toType('array', {
|
||||||
|
type: Array,
|
||||||
|
}).def(currentDefaults.array)
|
||||||
|
},
|
||||||
|
|
||||||
|
get object () {
|
||||||
|
return toType('object', {
|
||||||
|
type: Object,
|
||||||
|
}).def(currentDefaults.object)
|
||||||
|
},
|
||||||
|
|
||||||
|
get integer () {
|
||||||
|
return toType('integer', {
|
||||||
|
type: Number,
|
||||||
|
validator (value) {
|
||||||
|
return isInteger(value)
|
||||||
|
},
|
||||||
|
}).def(currentDefaults.integer)
|
||||||
|
},
|
||||||
|
|
||||||
|
get symbol () {
|
||||||
|
return toType('symbol', {
|
||||||
|
type: null,
|
||||||
|
validator (value) {
|
||||||
|
return typeof value === 'symbol'
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
custom (validatorFn, warnMsg = 'custom validation failed') {
|
||||||
|
if (typeof validatorFn !== 'function') {
|
||||||
|
throw new TypeError('[VueTypes error]: You must provide a function as argument')
|
||||||
|
}
|
||||||
|
|
||||||
|
return toType(validatorFn.name || '<<anonymous function>>', {
|
||||||
|
validator (...args) {
|
||||||
|
const valid = validatorFn(...args)
|
||||||
|
if (!valid) warn(`${this._vueTypes_name} - ${warnMsg}`)
|
||||||
|
return valid
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
oneOf (arr) {
|
||||||
|
if (!isArray(arr)) {
|
||||||
|
throw new TypeError('[VueTypes error]: You must provide an array as argument')
|
||||||
|
}
|
||||||
|
const msg = `oneOf - value should be one of "${arr.join('", "')}"`
|
||||||
|
const allowedTypes = arr.reduce((ret, v) => {
|
||||||
|
if (v !== null && v !== undefined) {
|
||||||
|
ret.indexOf(v.constructor) === -1 && ret.push(v.constructor)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return toType('oneOf', {
|
||||||
|
type: allowedTypes.length > 0 ? allowedTypes : null,
|
||||||
|
validator (value) {
|
||||||
|
const valid = arr.indexOf(value) !== -1
|
||||||
|
if (!valid) warn(msg)
|
||||||
|
return valid
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
instanceOf (instanceConstructor) {
|
||||||
|
return toType('instanceOf', {
|
||||||
|
type: instanceConstructor,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
oneOfType (arr) {
|
||||||
|
if (!isArray(arr)) {
|
||||||
|
throw new TypeError('[VueTypes error]: You must provide an array as argument')
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasCustomValidators = false
|
||||||
|
|
||||||
|
const nativeChecks = arr.reduce((ret, type, i) => {
|
||||||
|
if (isPlainObject(type)) {
|
||||||
|
if (type._vueTypes_name === 'oneOf') {
|
||||||
|
return ret.concat(type.type || [])
|
||||||
|
}
|
||||||
|
if (type.type && !isFunction(type.validator)) {
|
||||||
|
if (isArray(type.type)) return ret.concat(type.type)
|
||||||
|
ret.push(type.type)
|
||||||
|
} else if (isFunction(type.validator)) {
|
||||||
|
hasCustomValidators = true
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
ret.push(type)
|
||||||
|
return ret
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (!hasCustomValidators) {
|
||||||
|
// we got just native objects (ie: Array, Object)
|
||||||
|
// delegate to Vue native prop check
|
||||||
|
return toType('oneOfType', {
|
||||||
|
type: nativeChecks,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const typesStr = arr.map((type) => {
|
||||||
|
if (type && isArray(type.type)) {
|
||||||
|
return type.type.map(getType)
|
||||||
|
}
|
||||||
|
return getType(type)
|
||||||
|
}).reduce((ret, type) => ret.concat(isArray(type) ? type : [type]), []).join('", "')
|
||||||
|
|
||||||
|
return this.custom(function oneOfType (value) {
|
||||||
|
const valid = arr.some((type) => {
|
||||||
|
if (type._vueTypes_name === 'oneOf') {
|
||||||
|
return type.type ? validateType(type.type, value, true) : true
|
||||||
|
}
|
||||||
|
return validateType(type, value, true)
|
||||||
|
})
|
||||||
|
if (!valid) warn(`oneOfType - value type should be one of "${typesStr}"`)
|
||||||
|
return valid
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
arrayOf (type) {
|
||||||
|
return toType('arrayOf', {
|
||||||
|
type: Array,
|
||||||
|
validator (values) {
|
||||||
|
const valid = values.every((value) => validateType(type, value))
|
||||||
|
if (!valid) warn(`arrayOf - value must be an array of "${getType(type)}"`)
|
||||||
|
return valid
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
objectOf (type) {
|
||||||
|
return toType('objectOf', {
|
||||||
|
type: Object,
|
||||||
|
validator (obj) {
|
||||||
|
const valid = Object.keys(obj).every((key) => validateType(type, obj[key]))
|
||||||
|
if (!valid) warn(`objectOf - value must be an object of "${getType(type)}"`)
|
||||||
|
return valid
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
shape (obj) {
|
||||||
|
const keys = Object.keys(obj)
|
||||||
|
const requiredKeys = keys.filter((key) => obj[key] && obj[key].required === true)
|
||||||
|
|
||||||
|
const type = toType('shape', {
|
||||||
|
type: Object,
|
||||||
|
validator (value) {
|
||||||
|
if (!isPlainObject(value)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const valueKeys = Object.keys(value)
|
||||||
|
|
||||||
|
// check for required keys (if any)
|
||||||
|
if (requiredKeys.length > 0 && requiredKeys.some((req) => valueKeys.indexOf(req) === -1)) {
|
||||||
|
warn(`shape - at least one of required properties "${requiredKeys.join('", "')}" is not present`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueKeys.every((key) => {
|
||||||
|
if (keys.indexOf(key) === -1) {
|
||||||
|
if (this._vueTypes_isLoose === true) return true
|
||||||
|
warn(`shape - object is missing "${key}" property`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const type = obj[key]
|
||||||
|
return validateType(type, value[key])
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.defineProperty(type, '_vueTypes_isLoose', {
|
||||||
|
enumerable: false,
|
||||||
|
writable: true,
|
||||||
|
value: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.defineProperty(type, 'loose', {
|
||||||
|
get () {
|
||||||
|
this._vueTypes_isLoose = true
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
return type
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeDefaults = () => ({
|
||||||
|
func: undefined,
|
||||||
|
bool: undefined,
|
||||||
|
string: undefined,
|
||||||
|
number: undefined,
|
||||||
|
array: undefined,
|
||||||
|
object: undefined,
|
||||||
|
integer: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
let currentDefaults = typeDefaults()
|
||||||
|
|
||||||
|
Object.defineProperty(VuePropTypes, 'sensibleDefaults', {
|
||||||
|
enumerable: false,
|
||||||
|
set (value) {
|
||||||
|
if (value === false) {
|
||||||
|
currentDefaults = {}
|
||||||
|
} else if (value === true) {
|
||||||
|
currentDefaults = typeDefaults()
|
||||||
|
} else if (isPlainObject(value)) {
|
||||||
|
currentDefaults = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get () {
|
||||||
|
return currentDefaults
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default VuePropTypes
|
|
@ -0,0 +1,188 @@
|
||||||
|
import isPlainObject from 'lodash.isplainobject'
|
||||||
|
|
||||||
|
const ObjProto = Object.prototype
|
||||||
|
const toString = ObjProto.toString
|
||||||
|
export const hasOwn = ObjProto.hasOwnProperty
|
||||||
|
|
||||||
|
const FN_MATCH_REGEXP = /^\s*function (\w+)/
|
||||||
|
|
||||||
|
// https://github.com/vuejs/vue/blob/dev/src/core/util/props.js#L159
|
||||||
|
export const getType = (fn) => {
|
||||||
|
const type = (fn !== null && fn !== undefined) ? (fn.type ? fn.type : fn) : null
|
||||||
|
const match = type && type.toString().match(FN_MATCH_REGEXP)
|
||||||
|
return match && match[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getNativeType = (value) => {
|
||||||
|
if (value === null || value === undefined) return null
|
||||||
|
const match = value.constructor.toString().match(FN_MATCH_REGEXP)
|
||||||
|
return match && match[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-op function
|
||||||
|
*/
|
||||||
|
export const noop = () => {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for a own property in an object
|
||||||
|
*
|
||||||
|
* @param {object} obj - Object
|
||||||
|
* @param {string} prop - Property to check
|
||||||
|
*/
|
||||||
|
export const has = (obj, prop) => hasOwn.call(obj, prop)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the passed value is an integer. Uses `Number.isInteger` if available
|
||||||
|
*
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
|
||||||
|
* @param {*} value - The value to be tested for being an integer.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export const isInteger = Number.isInteger || function (value) {
|
||||||
|
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the passed value is an Array.
|
||||||
|
*
|
||||||
|
* @param {*} value - The value to be tested for being an array.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export const isArray = Array.isArray || function (value) {
|
||||||
|
return toString.call(value) === '[object Array]'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a value is a function
|
||||||
|
*
|
||||||
|
* @param {any} value - Value to check
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export const isFunction = (value) => toString.call(value) === '[object Function]'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a `def` method to the object returning a new object with passed in argument as `default` property
|
||||||
|
*
|
||||||
|
* @param {object} type - Object to enhance
|
||||||
|
*/
|
||||||
|
export const withDefault = function (type) {
|
||||||
|
Object.defineProperty(type, 'def', {
|
||||||
|
value (def) {
|
||||||
|
if (def === undefined && this.default === undefined) {
|
||||||
|
this.default = undefined
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
if (!isFunction(def) && !validateType(this, def)) {
|
||||||
|
warn(`${this._vueTypes_name} - invalid default value: "${def}"`, def)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
this.default = (isArray(def) || isPlainObject(def)) ? function () {
|
||||||
|
return def
|
||||||
|
} : def
|
||||||
|
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
writable: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a `isRequired` getter returning a new object with `required: true` key-value
|
||||||
|
*
|
||||||
|
* @param {object} type - Object to enhance
|
||||||
|
*/
|
||||||
|
export const withRequired = function (type) {
|
||||||
|
Object.defineProperty(type, 'isRequired', {
|
||||||
|
get () {
|
||||||
|
this.required = true
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds `isRequired` and `def` modifiers to an object
|
||||||
|
*
|
||||||
|
* @param {string} name - Type internal name
|
||||||
|
* @param {object} obj - Object to enhance
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
export const toType = (name, obj) => {
|
||||||
|
Object.defineProperty(obj, '_vueTypes_name', {
|
||||||
|
enumerable: false,
|
||||||
|
writable: false,
|
||||||
|
value: name,
|
||||||
|
})
|
||||||
|
withRequired(obj)
|
||||||
|
withDefault(obj)
|
||||||
|
|
||||||
|
if (isFunction(obj.validator)) {
|
||||||
|
obj.validator = obj.validator.bind(obj)
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a given value against a prop type object
|
||||||
|
*
|
||||||
|
* @param {Object|*} type - Type to use for validation. Either a type object or a constructor
|
||||||
|
* @param {*} value - Value to check
|
||||||
|
* @param {boolean} silent - Silence warnings
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export const validateType = (type, value, silent = false) => {
|
||||||
|
let typeToCheck = type
|
||||||
|
let valid = true
|
||||||
|
let expectedType
|
||||||
|
if (!isPlainObject(type)) {
|
||||||
|
typeToCheck = { type }
|
||||||
|
}
|
||||||
|
const namePrefix = typeToCheck._vueTypes_name ? (typeToCheck._vueTypes_name + ' - ') : ''
|
||||||
|
|
||||||
|
if (hasOwn.call(typeToCheck, 'type') && typeToCheck.type !== null) {
|
||||||
|
if (isArray(typeToCheck.type)) {
|
||||||
|
valid = typeToCheck.type.some((type) => validateType(type, value, true))
|
||||||
|
expectedType = typeToCheck.type.map((type) => getType(type)).join(' or ')
|
||||||
|
} else {
|
||||||
|
expectedType = getType(typeToCheck)
|
||||||
|
|
||||||
|
if (expectedType === 'Array') {
|
||||||
|
valid = isArray(value)
|
||||||
|
} else if (expectedType === 'Object') {
|
||||||
|
valid = isPlainObject(value)
|
||||||
|
} else if (expectedType === 'String' || expectedType === 'Number' || expectedType === 'Boolean' || expectedType === 'Function') {
|
||||||
|
valid = getNativeType(value) === expectedType
|
||||||
|
} else {
|
||||||
|
valid = value instanceof typeToCheck.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
silent === false && warn(`${namePrefix}value "${value}" should be of type "${expectedType}"`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasOwn.call(typeToCheck, 'validator') && isFunction(typeToCheck.validator)) {
|
||||||
|
valid = typeToCheck.validator(value)
|
||||||
|
if (!valid && silent === false) warn(`${namePrefix}custom validation failed`)
|
||||||
|
return valid
|
||||||
|
}
|
||||||
|
return valid
|
||||||
|
}
|
||||||
|
|
||||||
|
let warn = noop
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
const hasConsole = typeof console !== 'undefined'
|
||||||
|
warn = (msg) => {
|
||||||
|
if (hasConsole) {
|
||||||
|
console.warn(`[VueTypes warn]: ${msg}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { warn }
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import PropTypes from 'vue-types'
|
import PropTypes from 'vue-types'
|
||||||
import align from 'dom-align'
|
import align from 'dom-align'
|
||||||
|
import clonedeep from 'lodash.clonedeep'
|
||||||
import addEventListener from '../_util/Dom/addEventListener'
|
import addEventListener from '../_util/Dom/addEventListener'
|
||||||
import { cloneElement } from '../_util/vnode.js'
|
import { cloneElement } from '../_util/vnode.js'
|
||||||
import isWindow from './isWindow'
|
import isWindow from './isWindow'
|
||||||
|
@ -38,7 +39,8 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$props': {
|
'$props': {
|
||||||
handler: function (props, prevProps) {
|
handler: function (props) {
|
||||||
|
const prevProps = this.prevProps
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
let reAlign = false
|
let reAlign = false
|
||||||
if (!props.disabled) {
|
if (!props.disabled) {
|
||||||
|
@ -106,16 +108,11 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
this.prevProps = clonedeep(this.$props)
|
||||||
const { childrenProps } = this.$props
|
const { childrenProps } = this.$props
|
||||||
const child = this.$slots.default[0]
|
const child = this.$slots.default[0]
|
||||||
if (childrenProps) {
|
if (childrenProps) {
|
||||||
const newProps = {}
|
return cloneElement(child, { props: childrenProps })
|
||||||
for (const prop in childrenProps) {
|
|
||||||
if (childrenProps.hasOwnProperty(prop)) {
|
|
||||||
newProps[prop] = this.props[childrenProps[prop]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cloneElement(child, { props: newProps })
|
|
||||||
}
|
}
|
||||||
return child
|
return child
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default {
|
||||||
hiddenClassName: PropTypes.string,
|
hiddenClassName: PropTypes.string,
|
||||||
},
|
},
|
||||||
render () {
|
render () {
|
||||||
const { hiddenClassName, visible } = this.props
|
const { hiddenClassName, visible } = this.$props
|
||||||
|
|
||||||
if (hiddenClassName || this.$slots.default.length > 1) {
|
if (hiddenClassName || this.$slots.default.length > 1) {
|
||||||
let cls = ''
|
let cls = ''
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import PropTypes from 'vue-types'
|
import PropTypes from '../_util/vue-types'
|
||||||
import Align from '../align'
|
import Align from '../align'
|
||||||
import PopupInner from './PopupInner'
|
import PopupInner from './PopupInner'
|
||||||
import LazyRenderBox from './LazyRenderBox'
|
import LazyRenderBox from './LazyRenderBox'
|
||||||
|
@ -12,10 +12,16 @@ export default {
|
||||||
align: PropTypes.any,
|
align: PropTypes.any,
|
||||||
destroyPopupOnHide: PropTypes.bool,
|
destroyPopupOnHide: PropTypes.bool,
|
||||||
prefixCls: PropTypes.string,
|
prefixCls: PropTypes.string,
|
||||||
|
getContainer: PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
this.rootNode = this.getPopupDomNode()
|
this.rootNode = this.getPopupDomNode()
|
||||||
|
this._container = this.getContainer()
|
||||||
|
this._container.appendChild(this.$el)
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
this._container && this._container.parentNode.removeChild(this._container)
|
||||||
|
this._container = null
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onAlign (popupDomNode, align) {
|
onAlign (popupDomNode, align) {
|
||||||
|
@ -75,7 +81,7 @@ export default {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
this.currentAlignClassName = null
|
this.currentAlignClassName = null
|
||||||
}
|
}
|
||||||
|
// visible = true
|
||||||
const popupInnerProps = {
|
const popupInnerProps = {
|
||||||
props: {
|
props: {
|
||||||
prefixCls,
|
prefixCls,
|
||||||
|
@ -89,12 +95,10 @@ export default {
|
||||||
ref: 'popupInstance',
|
ref: 'popupInstance',
|
||||||
style: { ...this.getZIndexStyle() },
|
style: { ...this.getZIndexStyle() },
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destroyPopupOnHide) {
|
if (destroyPopupOnHide) {
|
||||||
return (<Animate
|
return (<transition
|
||||||
component=''
|
name={this.getTransitionName()}
|
||||||
exclusive
|
|
||||||
transitionAppear
|
|
||||||
transitionName={this.getTransitionName()}
|
|
||||||
>
|
>
|
||||||
{visible ? (<Align
|
{visible ? (<Align
|
||||||
target={this.getTarget}
|
target={this.getTarget}
|
||||||
|
@ -110,23 +114,18 @@ export default {
|
||||||
{$slots.default}
|
{$slots.default}
|
||||||
</PopupInner>
|
</PopupInner>
|
||||||
</Align>) : null}
|
</Align>) : null}
|
||||||
</Animate>)
|
</transition>)
|
||||||
}
|
}
|
||||||
popupInnerProps.props.hiddenClassName = hiddenClassName
|
popupInnerProps.props.hiddenClassName = hiddenClassName
|
||||||
return (<Animate
|
return (<transition
|
||||||
component=''
|
name={this.getTransitionName()}
|
||||||
exclusive
|
|
||||||
transitionAppear
|
|
||||||
transitionName={this.getTransitionName()}
|
|
||||||
showProp='xVisible'
|
|
||||||
>
|
>
|
||||||
<Align
|
<Align
|
||||||
target={this.getTarget}
|
target={this.getTarget}
|
||||||
key='popup'
|
key='popup'
|
||||||
ref='alignInstance'
|
ref='alignInstance'
|
||||||
monitorWindowResize
|
monitorWindowResize
|
||||||
xVisible={visible}
|
childrenProps={{ visible }}
|
||||||
childrenProps={{ visible: 'xVisible' }}
|
|
||||||
disabled={!visible}
|
disabled={!visible}
|
||||||
align={align}
|
align={align}
|
||||||
onAlign={this.onAlign}
|
onAlign={this.onAlign}
|
||||||
|
@ -137,7 +136,7 @@ export default {
|
||||||
{$slots.default}
|
{$slots.default}
|
||||||
</PopupInner>
|
</PopupInner>
|
||||||
</Align>
|
</Align>
|
||||||
</Animate>)
|
</transition>)
|
||||||
},
|
},
|
||||||
|
|
||||||
getZIndexStyle () {
|
getZIndexStyle () {
|
||||||
|
@ -165,15 +164,11 @@ export default {
|
||||||
)
|
)
|
||||||
if (maskTransition) {
|
if (maskTransition) {
|
||||||
maskElement = (
|
maskElement = (
|
||||||
<Animate
|
<transition
|
||||||
key='mask'
|
name={maskTransition}
|
||||||
showProp='visible'
|
|
||||||
transitionAppear
|
|
||||||
component=''
|
|
||||||
transitionName={maskTransition}
|
|
||||||
>
|
>
|
||||||
{maskElement}
|
{maskElement}
|
||||||
</Animate>
|
</transition>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
hiddenClassName: PropTypes.string.def(''),
|
hiddenClassName: PropTypes.string.def(''),
|
||||||
prefixCls: PropTypes.string,
|
prefixCls: PropTypes.string,
|
||||||
|
visible: PropTypes.bool,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onMouseEnter (e) {
|
onMouseEnter (e) {
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
@triggerPrefixCls: rc-trigger-popup;
|
||||||
|
|
||||||
|
.@{triggerPrefixCls} {
|
||||||
|
position: absolute;
|
||||||
|
left: -9999px;
|
||||||
|
top: -9999px;
|
||||||
|
z-index: 1050;
|
||||||
|
|
||||||
|
&-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect() {
|
||||||
|
animation-duration: 0.3s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-enter,&-zoom-appear {
|
||||||
|
opacity: 0;
|
||||||
|
.effect();
|
||||||
|
animation-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-leave {
|
||||||
|
.effect();
|
||||||
|
animation-timing-function: cubic-bezier(0.6, -0.3, 0.74, 0.05);
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-enter&-zoom-enter-active, &-zoom-appear&-zoom-appear-active {
|
||||||
|
animation-name: rcTriggerZoomIn;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-zoom-leave&-zoom-leave-active {
|
||||||
|
animation-name: rcTriggerZoomOut;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rcTriggerZoomIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(0, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes rcTriggerZoomOut {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(1, 1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transform: scale(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@import "./mask";
|
|
@ -0,0 +1,63 @@
|
||||||
|
.@{triggerPrefixCls} {
|
||||||
|
&-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgb(55, 55, 55);
|
||||||
|
background-color: rgba(55, 55, 55, 0.6);
|
||||||
|
height: 100%;
|
||||||
|
filter: alpha(opacity=50);
|
||||||
|
z-index: 1050;
|
||||||
|
|
||||||
|
&-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-effect() {
|
||||||
|
animation-duration: 0.3s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fade-enter,&-fade-appear {
|
||||||
|
opacity: 0;
|
||||||
|
.fade-effect();
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fade-leave {
|
||||||
|
.fade-effect();
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fade-enter&-fade-enter-active,&-fade-appear&-fade-appear-active {
|
||||||
|
animation-name: rcTriggerMaskFadeIn;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fade-leave&-fade-leave-active {
|
||||||
|
animation-name: rcDialogFadeOut;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rcTriggerMaskFadeIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rcDialogFadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<script>
|
||||||
|
import Trigger from '../index'
|
||||||
|
import '../assets/index.less'
|
||||||
|
const builtinPlacements = {
|
||||||
|
left: {
|
||||||
|
points: ['cr', 'cl'],
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
points: ['cl', 'cr'],
|
||||||
|
},
|
||||||
|
top: {
|
||||||
|
points: ['bc', 'tc'],
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
points: ['tc', 'bc'],
|
||||||
|
},
|
||||||
|
topLeft: {
|
||||||
|
points: ['bl', 'tl'],
|
||||||
|
},
|
||||||
|
topRight: {
|
||||||
|
points: ['br', 'tr'],
|
||||||
|
},
|
||||||
|
bottomRight: {
|
||||||
|
points: ['tr', 'br'],
|
||||||
|
},
|
||||||
|
bottomLeft: {
|
||||||
|
points: ['tl', 'bl'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const popupBorderStyle = {
|
||||||
|
border: '1px solid red',
|
||||||
|
padding: '10px',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{ margin: '50px' }}>
|
||||||
|
<Trigger
|
||||||
|
popupPlacement='right'
|
||||||
|
action={['click']}
|
||||||
|
builtinPlacements={builtinPlacements}
|
||||||
|
>
|
||||||
|
<div style={popupBorderStyle} slot='popup' onClick={(e) => { e.stopPropagation() }}>
|
||||||
|
jjj
|
||||||
|
</div>
|
||||||
|
<span href='#' style={{ margin: '20px' }} onClick={console.log}>trigger</span>
|
||||||
|
</Trigger>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
|
@ -1,3 +1,3 @@
|
||||||
// export this package's api
|
// export this package's api
|
||||||
import Trigger from './src/'
|
import Trigger from './index.vue'
|
||||||
export default Trigger
|
export default Trigger
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import PropTypes from 'vue-types'
|
import PropTypes from '../_util/vue-types'
|
||||||
import contains from '../_util/Dom/contains'
|
import contains from '../_util/Dom/contains'
|
||||||
import addEventListener from '../_util/Dom/addEventListener'
|
import addEventListener from '../_util/Dom/addEventListener'
|
||||||
import Popup from './Popup'
|
import Popup from './Popup'
|
||||||
|
@ -16,8 +16,8 @@ function returnDocument () {
|
||||||
return window.document
|
return window.document
|
||||||
}
|
}
|
||||||
|
|
||||||
const ALL_HANDLERS = ['onClick', 'onMouseDown', 'onTouchStart', 'onMouseEnter',
|
const ALL_HANDLERS = ['click', 'mousedown', 'touchStart', 'mouseenter',
|
||||||
'onMouseLeave', 'onFocus', 'onBlur', 'onContextMenu']
|
'mouseleave', 'focus', 'blur', 'contextMenu']
|
||||||
|
|
||||||
const mixins = []
|
const mixins = []
|
||||||
|
|
||||||
|
@ -26,11 +26,11 @@ mixins.push(
|
||||||
autoMount: false,
|
autoMount: false,
|
||||||
|
|
||||||
isVisible (instance) {
|
isVisible (instance) {
|
||||||
return instance.state.sPopupVisible
|
return instance.$data.sPopupVisible
|
||||||
},
|
},
|
||||||
|
|
||||||
isForceRender (instance) {
|
isForceRender (instance) {
|
||||||
return instance.props.forceRender
|
return instance.$props.forceRender
|
||||||
},
|
},
|
||||||
|
|
||||||
getContainer (instance) {
|
getContainer (instance) {
|
||||||
|
@ -65,7 +65,7 @@ export default {
|
||||||
zIndex: PropTypes.number,
|
zIndex: PropTypes.number,
|
||||||
focusDelay: PropTypes.number.def(0),
|
focusDelay: PropTypes.number.def(0),
|
||||||
blurDelay: PropTypes.number.def(0.15),
|
blurDelay: PropTypes.number.def(0.15),
|
||||||
getPopupContainer: PropTypes.func,
|
getPopupContainer: Function,
|
||||||
getDocument: PropTypes.func.def(returnDocument),
|
getDocument: PropTypes.func.def(returnDocument),
|
||||||
forceRender: PropTypes.bool,
|
forceRender: PropTypes.bool,
|
||||||
destroyPopupOnHide: PropTypes.bool.def(false),
|
destroyPopupOnHide: PropTypes.bool.def(false),
|
||||||
|
@ -74,15 +74,15 @@ export default {
|
||||||
// onPopupAlign: PropTypes.func,
|
// onPopupAlign: PropTypes.func,
|
||||||
popupAlign: PropTypes.object.def({}),
|
popupAlign: PropTypes.object.def({}),
|
||||||
popupVisible: PropTypes.bool,
|
popupVisible: PropTypes.bool,
|
||||||
defaultPopupVisible: PropTypes.bool.def(false),
|
// defaultPopupVisible: PropTypes.bool.def(false),
|
||||||
maskTransitionName: PropTypes.oneOfType([
|
// maskTransitionName: PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
// PropTypes.string,
|
||||||
PropTypes.object,
|
// PropTypes.object,
|
||||||
]),
|
// ]),
|
||||||
maskAnimation: PropTypes.string,
|
// maskAnimation: PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [StateMixin, mixins],
|
mixins: [StateMixin, ...mixins],
|
||||||
data () {
|
data () {
|
||||||
const props = this.$props
|
const props = this.$props
|
||||||
let popupVisible
|
let popupVisible
|
||||||
|
@ -99,15 +99,14 @@ export default {
|
||||||
beforeCreate () {
|
beforeCreate () {
|
||||||
ALL_HANDLERS.forEach((h) => {
|
ALL_HANDLERS.forEach((h) => {
|
||||||
this[`fire${h}`] = (e) => {
|
this[`fire${h}`] = (e) => {
|
||||||
this.fireEvents(h, e)
|
const ev = `on${h[0].toUpperCase() + h.slice(1)}`
|
||||||
|
this.fireEvents(ev, e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
this.updated({}, {
|
this.updatedCal()
|
||||||
sPopupVisible: this.$data.sPopupVisible,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
popupVisible (val) {
|
popupVisible (val) {
|
||||||
|
@ -122,43 +121,8 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
updated (_, prevState) {
|
updated () {
|
||||||
const props = this.$props
|
this.updatedCal()
|
||||||
const state = this.$data
|
|
||||||
this.renderComponent()
|
|
||||||
|
|
||||||
// We must listen to `mousedown` or `touchstart`, edge case:
|
|
||||||
// https://github.com/ant-design/ant-design/issues/5804
|
|
||||||
// https://github.com/react-component/calendar/issues/250
|
|
||||||
// https://github.com/react-component/trigger/issues/50
|
|
||||||
if (state.sPopupVisible) {
|
|
||||||
let currentDocument
|
|
||||||
if (!this.clickOutsideHandler && (this.isClickToHide() || this.isContextMenuToShow())) {
|
|
||||||
currentDocument = props.getDocument()
|
|
||||||
this.clickOutsideHandler = addEventListener(currentDocument,
|
|
||||||
'mousedown', this.onDocumentClick)
|
|
||||||
}
|
|
||||||
// always hide on mobile
|
|
||||||
if (!this.touchOutsideHandler) {
|
|
||||||
currentDocument = currentDocument || props.getDocument()
|
|
||||||
this.touchOutsideHandler = addEventListener(currentDocument,
|
|
||||||
'touchstart', this.onDocumentClick)
|
|
||||||
}
|
|
||||||
// close popup when trigger type contains 'onContextMenu' and document is scrolling.
|
|
||||||
if (!this.contextMenuOutsideHandler1 && this.isContextMenuToShow()) {
|
|
||||||
currentDocument = currentDocument || props.getDocument()
|
|
||||||
this.contextMenuOutsideHandler1 = addEventListener(currentDocument,
|
|
||||||
'scroll', this.onContextMenuClose)
|
|
||||||
}
|
|
||||||
// close popup when trigger type contains 'onContextMenu' and window is blur.
|
|
||||||
if (!this.contextMenuOutsideHandler2 && this.isContextMenuToShow()) {
|
|
||||||
this.contextMenuOutsideHandler2 = addEventListener(window,
|
|
||||||
'blur', this.onContextMenuClose)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.clearOutsideHandler()
|
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
|
@ -166,21 +130,59 @@ export default {
|
||||||
this.clearOutsideHandler()
|
this.clearOutsideHandler()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onMouseEnter (e) {
|
updatedCal () {
|
||||||
this.fireEvents('onMouseEnter', e)
|
const props = this.$props
|
||||||
|
const state = this.$data
|
||||||
|
// this.renderComponent()
|
||||||
|
|
||||||
|
// We must listen to `mousedown` or `touchstart`, edge case:
|
||||||
|
// https://github.com/ant-design/ant-design/issues/5804
|
||||||
|
// https://github.com/react-component/calendar/issues/250
|
||||||
|
// https://github.com/react-component/trigger/issues/50
|
||||||
|
if (state.sPopupVisible) {
|
||||||
|
let currentDocument
|
||||||
|
if (!this.clickOutsideHandler && (this.isClickToHide() || this.isContextMenuToShow())) {
|
||||||
|
currentDocument = props.getDocument()
|
||||||
|
this.clickOutsideHandler = addEventListener(currentDocument,
|
||||||
|
'mousedown', this.onDocumentClick)
|
||||||
|
}
|
||||||
|
// always hide on mobile
|
||||||
|
if (!this.touchOutsideHandler) {
|
||||||
|
currentDocument = currentDocument || props.getDocument()
|
||||||
|
this.touchOutsideHandler = addEventListener(currentDocument,
|
||||||
|
'touchstart', this.onDocumentClick)
|
||||||
|
}
|
||||||
|
// close popup when trigger type contains 'onContextMenu' and document is scrolling.
|
||||||
|
if (!this.contextMenuOutsideHandler1 && this.isContextMenuToShow()) {
|
||||||
|
currentDocument = currentDocument || props.getDocument()
|
||||||
|
this.contextMenuOutsideHandler1 = addEventListener(currentDocument,
|
||||||
|
'scroll', this.onContextMenuClose)
|
||||||
|
}
|
||||||
|
// close popup when trigger type contains 'onContextMenu' and window is blur.
|
||||||
|
if (!this.contextMenuOutsideHandler2 && this.isContextMenuToShow()) {
|
||||||
|
this.contextMenuOutsideHandler2 = addEventListener(window,
|
||||||
|
'blur', this.onContextMenuClose)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.clearOutsideHandler()
|
||||||
|
},
|
||||||
|
onMouseenter (e) {
|
||||||
|
this.fireEvents('mouseenter', e)
|
||||||
this.delaySetPopupVisible(true, this.$props.mouseEnterDelay)
|
this.delaySetPopupVisible(true, this.$props.mouseEnterDelay)
|
||||||
},
|
},
|
||||||
|
|
||||||
onMouseLeave (e) {
|
onMouseleave (e) {
|
||||||
this.fireEvents('onMouseLeave', e)
|
this.fireEvents('mouseleave', e)
|
||||||
this.delaySetPopupVisible(false, this.$props.mouseLeaveDelay)
|
this.delaySetPopupVisible(false, this.$props.mouseLeaveDelay)
|
||||||
},
|
},
|
||||||
|
|
||||||
onPopupMouseEnter () {
|
onPopupMouseenter () {
|
||||||
this.clearDelayTimer()
|
this.clearDelayTimer()
|
||||||
},
|
},
|
||||||
|
|
||||||
onPopupMouseLeave (e) {
|
onPopupMouseleave (e) {
|
||||||
if (e.relatedTarget && !e.relatedTarget.setTimeout &&
|
if (e.relatedTarget && !e.relatedTarget.setTimeout &&
|
||||||
this._component &&
|
this._component &&
|
||||||
this._component.getPopupDomNode &&
|
this._component.getPopupDomNode &&
|
||||||
|
@ -191,7 +193,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
onFocus (e) {
|
onFocus (e) {
|
||||||
this.fireEvents('onFocus', e)
|
this.fireEvents('focus', e)
|
||||||
// incase focusin and focusout
|
// incase focusin and focusout
|
||||||
this.clearDelayTimer()
|
this.clearDelayTimer()
|
||||||
if (this.isFocusToShow()) {
|
if (this.isFocusToShow()) {
|
||||||
|
@ -200,18 +202,18 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onMouseDown (e) {
|
onMousedown (e) {
|
||||||
this.fireEvents('onMouseDown', e)
|
this.fireEvents('mousedown', e)
|
||||||
this.preClickTime = Date.now()
|
this.preClickTime = Date.now()
|
||||||
},
|
},
|
||||||
|
|
||||||
onTouchStart (e) {
|
onTouchStart (e) {
|
||||||
this.fireEvents('onTouchStart', e)
|
this.fireEvents('touchStart', e)
|
||||||
this.preTouchTime = Date.now()
|
this.preTouchTime = Date.now()
|
||||||
},
|
},
|
||||||
|
|
||||||
onBlur (e) {
|
onBlur (e) {
|
||||||
this.fireEvents('onBlur', e)
|
this.fireEvents('blur', e)
|
||||||
this.clearDelayTimer()
|
this.clearDelayTimer()
|
||||||
if (this.isBlurToHide()) {
|
if (this.isBlurToHide()) {
|
||||||
this.delaySetPopupVisible(false, this.$props.blurDelay)
|
this.delaySetPopupVisible(false, this.$props.blurDelay)
|
||||||
|
@ -220,7 +222,7 @@ export default {
|
||||||
|
|
||||||
onContextMenu (e) {
|
onContextMenu (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
this.fireEvents('onContextMenu', e)
|
this.fireEvents('contextMenu', e)
|
||||||
this.setPopupVisible(true)
|
this.setPopupVisible(true)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -231,7 +233,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
onClick (event) {
|
onClick (event) {
|
||||||
this.fireEvents('onClick', event)
|
this.fireEvents('click', event)
|
||||||
// focus will trigger click
|
// focus will trigger click
|
||||||
if (this.focusTime) {
|
if (this.focusTime) {
|
||||||
let preTime
|
let preTime
|
||||||
|
@ -276,10 +278,10 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
getRootDomNode () {
|
getRootDomNode () {
|
||||||
return this.$el
|
return this.$el.children[0] || this.$el
|
||||||
},
|
},
|
||||||
|
|
||||||
getPopupClassNameFromAlign (align) {
|
getPopupClassFromAlign (align) {
|
||||||
const className = []
|
const className = []
|
||||||
const props = this.$props
|
const props = this.$props
|
||||||
const { popupPlacement, builtinPlacements, prefixCls } = props
|
const { popupPlacement, builtinPlacements, prefixCls } = props
|
||||||
|
@ -301,21 +303,21 @@ export default {
|
||||||
return popupAlign
|
return popupAlign
|
||||||
},
|
},
|
||||||
onPopupAlign () {
|
onPopupAlign () {
|
||||||
this.emit('popupAlign', ...arguments)
|
this.$emit('popupAlign', ...arguments)
|
||||||
},
|
},
|
||||||
getComponent () {
|
getComponent () {
|
||||||
const mouseProps = {}
|
const mouseProps = {}
|
||||||
if (this.isMouseEnterToShow()) {
|
if (this.isMouseEnterToShow()) {
|
||||||
mouseProps.mouseenter = this.onPopupMouseEnter
|
mouseProps.mouseenter = this.onPopupMouseenter
|
||||||
}
|
}
|
||||||
if (this.isMouseLeaveToHide()) {
|
if (this.isMouseLeaveToHide()) {
|
||||||
mouseProps.mouseleave = this.onPopupMouseLeave
|
mouseProps.mouseleave = this.onPopupMouseleave
|
||||||
}
|
}
|
||||||
const { prefixCls, destroyPopupOnHide, sPopupVisible,
|
const { prefixCls, destroyPopupOnHide, sPopupVisible,
|
||||||
popupStyle, popupClassName, action, onPopupAlign,
|
popupStyle, popupClassName, action, onPopupAlign,
|
||||||
popupAnimation, getPopupClassNameFromAlign, getRootDomNode,
|
popupAnimation, getPopupClassFromAlign, getRootDomNode,
|
||||||
mask, zIndex, popupTransitionName, getPopupAlign,
|
mask, zIndex, popupTransitionName, getPopupAlign,
|
||||||
maskAnimation, maskTransitionName, popup, $slots } = this
|
maskAnimation, maskTransitionName, popup, $slots, getContainer } = this
|
||||||
const popupProps = {
|
const popupProps = {
|
||||||
props: {
|
props: {
|
||||||
prefixCls,
|
prefixCls,
|
||||||
|
@ -324,13 +326,14 @@ export default {
|
||||||
action,
|
action,
|
||||||
align: getPopupAlign(),
|
align: getPopupAlign(),
|
||||||
animation: popupAnimation,
|
animation: popupAnimation,
|
||||||
getClassNameFromAlign: getPopupClassNameFromAlign,
|
getClassNameFromAlign: getPopupClassFromAlign,
|
||||||
getRootDomNode,
|
getRootDomNode,
|
||||||
mask,
|
mask,
|
||||||
zIndex,
|
zIndex,
|
||||||
transitionName: popupTransitionName,
|
transitionName: popupTransitionName,
|
||||||
maskAnimation,
|
maskAnimation,
|
||||||
maskTransitionName,
|
maskTransitionName,
|
||||||
|
getContainer,
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
align: onPopupAlign,
|
align: onPopupAlign,
|
||||||
|
@ -343,6 +346,7 @@ export default {
|
||||||
return (
|
return (
|
||||||
<Popup
|
<Popup
|
||||||
{...popupProps}
|
{...popupProps}
|
||||||
|
ref='popup'
|
||||||
>
|
>
|
||||||
{typeof popup === 'function' ? popup() : popup}
|
{typeof popup === 'function' ? popup() : popup}
|
||||||
{popup === undefined ? $slots.popup : null}
|
{popup === undefined ? $slots.popup : null}
|
||||||
|
@ -368,10 +372,11 @@ export default {
|
||||||
setPopupVisible (sPopupVisible) {
|
setPopupVisible (sPopupVisible) {
|
||||||
this.clearDelayTimer()
|
this.clearDelayTimer()
|
||||||
if (this.$data.sPopupVisible !== sPopupVisible) {
|
if (this.$data.sPopupVisible !== sPopupVisible) {
|
||||||
if (this.$props.popupVisible !== undefined) {
|
if (this.$props.popupVisible === undefined) {
|
||||||
this.setState({
|
this.setState({
|
||||||
sPopupVisible,
|
sPopupVisible,
|
||||||
})
|
})
|
||||||
|
this.$forceUpdate()
|
||||||
}
|
}
|
||||||
this.$emit('popupVisibleChange', sPopupVisible)
|
this.$emit('popupVisibleChange', sPopupVisible)
|
||||||
}
|
}
|
||||||
|
@ -420,12 +425,17 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
createTwoChains (event) {
|
createTwoChains (event) {
|
||||||
const childPros = this.$props.children.props
|
const child = this.$slots.default[0]
|
||||||
const props = this.$props
|
let fn = () => {}
|
||||||
if (childPros[event] && props[event]) {
|
if (child && child.data && child.data.on) {
|
||||||
return this[`fire${event}`]
|
const childEvents = child.data.on
|
||||||
|
const events = (this.data ? this.data.on : {}) || {}
|
||||||
|
if (childEvents[event] && events[event]) {
|
||||||
|
return this[`fire${event}`]
|
||||||
|
}
|
||||||
|
fn = childEvents[event] || events[event] || fn
|
||||||
}
|
}
|
||||||
return childPros[event] || props[event]
|
return fn
|
||||||
},
|
},
|
||||||
|
|
||||||
isClickToShow () {
|
isClickToShow () {
|
||||||
|
@ -445,12 +455,12 @@ export default {
|
||||||
|
|
||||||
isMouseEnterToShow () {
|
isMouseEnterToShow () {
|
||||||
const { action, showAction } = this.$props
|
const { action, showAction } = this.$props
|
||||||
return action.indexOf('hover') !== -1 || showAction.indexOf('mouseEnter') !== -1
|
return action.indexOf('hover') !== -1 || showAction.indexOf('mouseenter') !== -1
|
||||||
},
|
},
|
||||||
|
|
||||||
isMouseLeaveToHide () {
|
isMouseLeaveToHide () {
|
||||||
const { action, hideAction } = this.$props
|
const { action, hideAction } = this.$props
|
||||||
return action.indexOf('hover') !== -1 || hideAction.indexOf('mouseLeave') !== -1
|
return action.indexOf('hover') !== -1 || hideAction.indexOf('mouseleave') !== -1
|
||||||
},
|
},
|
||||||
|
|
||||||
isFocusToShow () {
|
isFocusToShow () {
|
||||||
|
@ -463,18 +473,17 @@ export default {
|
||||||
return action.indexOf('focus') !== -1 || hideAction.indexOf('blur') !== -1
|
return action.indexOf('focus') !== -1 || hideAction.indexOf('blur') !== -1
|
||||||
},
|
},
|
||||||
forcePopupAlign () {
|
forcePopupAlign () {
|
||||||
if (this.state.popupVisible && this._component && this._component.$refs.alignInstance) {
|
if (this.$data.sPopupVisible && this._component && this._component.$refs.alignInstance) {
|
||||||
this._component.$refs.alignInstance.forceAlign()
|
this._component.$refs.alignInstance.forceAlign()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fireEvents (type, e) {
|
fireEvents (type, e) {
|
||||||
const childCallback = this.$props.children.props[type]
|
const child = this.$slots.default[0]
|
||||||
if (childCallback) {
|
if (child && child.data && child.on && child.on[type]) {
|
||||||
childCallback(e)
|
child.on[type](e)
|
||||||
}
|
}
|
||||||
const callback = this.$props[type]
|
if (this.data && this.data.on && this.data.on[type]) {
|
||||||
if (callback) {
|
this.data.on[type](e)
|
||||||
callback(e)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -494,39 +503,44 @@ export default {
|
||||||
if (this.isContextMenuToShow()) {
|
if (this.isContextMenuToShow()) {
|
||||||
newChildProps.on.contextMenu = this.onContextMenu
|
newChildProps.on.contextMenu = this.onContextMenu
|
||||||
} else {
|
} else {
|
||||||
newChildProps.on.contextMenu = this.createTwoChains('onContextMenu')
|
newChildProps.on.contextMenu = this.createTwoChains('contextMenu')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isClickToHide() || this.isClickToShow()) {
|
if (this.isClickToHide() || this.isClickToShow()) {
|
||||||
newChildProps.on.click = this.onClick
|
newChildProps.on.click = this.onClick
|
||||||
newChildProps.on.mousedown = this.onMouseDown
|
newChildProps.on.mousedown = this.onMousedown
|
||||||
// newChildProps.on.touchStart = this.onTouchStart
|
// newChildProps.on.touchStart = this.onTouchStart
|
||||||
} else {
|
} else {
|
||||||
newChildProps.on.click = this.createTwoChains('onClick')
|
newChildProps.on.click = this.createTwoChains('click')
|
||||||
newChildProps.on.mousedown = this.createTwoChains('onMouseDown')
|
newChildProps.on.mousedown = this.createTwoChains('mousedown')
|
||||||
// newChildProps.on.TouchStart = this.createTwoChains('onTouchStart')
|
// newChildProps.on.TouchStart = this.createTwoChains('onTouchStart')
|
||||||
}
|
}
|
||||||
if (this.isMouseEnterToShow()) {
|
if (this.isMouseEnterToShow()) {
|
||||||
newChildProps.on.mouseenter = this.onMouseEnter
|
newChildProps.on.mouseenter = this.onMouseenter
|
||||||
} else {
|
} else {
|
||||||
newChildProps.on.mouseenter = this.createTwoChains('onMouseEnter')
|
newChildProps.on.mouseenter = this.createTwoChains('mouseenter')
|
||||||
}
|
}
|
||||||
if (this.isMouseLeaveToHide()) {
|
if (this.isMouseLeaveToHide()) {
|
||||||
newChildProps.on.mouseleave = this.onMouseLeave
|
newChildProps.on.mouseleave = this.onMouseleave
|
||||||
} else {
|
} else {
|
||||||
newChildProps.on.mouseleave = this.createTwoChains('onMouseLeave')
|
newChildProps.on.mouseleave = this.createTwoChains('mouseleave')
|
||||||
}
|
}
|
||||||
if (this.isFocusToShow() || this.isBlurToHide()) {
|
if (this.isFocusToShow() || this.isBlurToHide()) {
|
||||||
newChildProps.on.focus = this.onFocus
|
newChildProps.on.focus = this.onFocus
|
||||||
newChildProps.on.blur = this.onBlur
|
newChildProps.on.blur = this.onBlur
|
||||||
} else {
|
} else {
|
||||||
newChildProps.on.focus = this.createTwoChains('onFocus')
|
newChildProps.on.focus = this.createTwoChains('focus')
|
||||||
newChildProps.on.blur = this.createTwoChains('onBlur')
|
newChildProps.on.blur = this.createTwoChains('blur')
|
||||||
}
|
}
|
||||||
|
|
||||||
const trigger = cloneElement(child, newChildProps)
|
const trigger = cloneElement(child, newChildProps)
|
||||||
|
|
||||||
return trigger
|
return (
|
||||||
|
<span>
|
||||||
|
{trigger}
|
||||||
|
{this.getComponent()}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
"eslint-plugin-vue": "^3.13.0",
|
"eslint-plugin-vue": "^3.13.0",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"lodash.isplainobject": "^4.0.6",
|
||||||
"omit.js": "^1.0.0",
|
"omit.js": "^1.0.0",
|
||||||
"vue-types": "^1.0.2",
|
"vue-types": "^1.0.2",
|
||||||
"warning": "^3.0.0"
|
"warning": "^3.0.0"
|
||||||
|
|
Loading…
Reference in New Issue