vuikit
Version:
A responsive Vue UI library for web site interfaces based on UIkit
331 lines (320 loc) • 8.74 kB
JavaScript
/**
* Vuikit 0.8.10
* (c) 2018 Miljan Aleksic
* @license MIT
**/
/* Substantial part of the code is adapted from UIkit,
Copyright (c) 2013-2018 YOOtheme GmbH, getuikit.com */
import { on } from './util/event';
import { within } from './util/filter';
import { isTouch } from './util/touch';
import { findParent, mergeData, findParents } from './util/vue';
import { pointerEnter, pointerLeave, hasTouch, isRtl } from './util/env';
import { Transition } from './core/transition';
import VkPosition, { BEFORE_POSITION } from './core/v-position';
import { css } from './util/style';
import { offset } from './util/dimensions';
import { addClass, removeClass } from './util/class';
import VkRoot from './core/v-root';
import EventsMixin from './mixins/events';
import { $ } from './util/core';
import { get } from './util/misc';
import { MouseTracker } from './util/mouse';
import { includes, isNode, isString } from './util/lang';
var SHOW = 'show';
var HIDE = 'hide';
var constants = /*#__PURE__*/Object.freeze({
SHOW: SHOW,
HIDE: HIDE
});
var active;
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
on(window, 'resize', function (ref) {
var defaultPrevented = ref.defaultPrevented;
var justified = active && /justify/.test(active.position);
if (!defaultPrevented && justified) {
active.$forceUpdate();
}
});
on(document.documentElement, 'click', function (ref) {
var target = ref.target;
var defaultPrevented = ref.defaultPrevented;
if (defaultPrevented || !active) {
return
}
var clickedInside = function (drop) { return within(target, drop.$el); };
var clickedTarget = function (drop) { return within(target, drop.$refs.target); };
while (active && !clickedInside(active) && !clickedTarget(active)) {
var parent = findParent(active);
active._hide();
active = parent;
}
});
}
var toggle = {
data: function () { return ({
shown: false
}); },
methods: {
show: function show () {
this.clearTimers();
this.showTimer = setTimeout(this._show, this.delayShow);
},
_show: function _show () {
while (active && !this.isChildOf(active) && !this.isParentOf(active)) {
var parent = findParent(active);
active._hide();
active = parent;
}
this.shown = true;
this.tracker.init();
active = this;
this.$emit(SHOW);
},
hide: function hide () {
var hoverIdle = 200;
this.clearTimers();
this.isDelaying = this.tracker.movesTo(this.$el);
if (this.isDelaying) {
this.hideTimer = setTimeout(this.hide, hoverIdle);
} else {
this.hideTimer = setTimeout(this._hide, this.delayHide);
}
},
_hide: function _hide () {
this.shown = false;
this.tracker.cancel();
if (active === this) {
var parent = findParent(active);
active = parent || null;
}
this.$emit(HIDE);
},
clearTimers: function clearTimers () {
clearTimeout(this.showTimer);
clearTimeout(this.hideTimer);
this.showTimer = null;
this.hideTimer = null;
},
toggle: function toggle () {
this.shown ? this._hide() : this.show();
}
},
mounted: function mounted () {
var this$1 = this;
var ref = this;
var on$$1 = ref.on;
var show = ref.show;
var hide = ref.hide;
var toggle = ref.toggle;
var mode = ref.mode;
var clearTimers = ref.clearTimers;
this.$nextTick(function () {
if (/click/.test(mode) || hasTouch) {
on$$1(this$1.$refs.target, 'click', toggle);
}
if (/hover/.test(mode)) {
on$$1(this$1.$refs.target, pointerEnter, function (e) {
if (isTouch(e)) {
return
}
e.preventDefault();
show();
});
on$$1(this$1.$refs.target, pointerLeave, function (e) {
if (isTouch(e)) {
return
}
e.preventDefault();
hide();
});
on$$1(this$1.$el, pointerLeave, hide);
on$$1(this$1.$el, pointerEnter, clearTimers);
}
});
}
}
var ElementDrop = {
functional: true,
props: {
show: {
type: Boolean,
default: false
}
},
render: function render (h, ref) {
var children = ref.children;
var data = ref.data;
var props = ref.props;
var show = props.show;
return h('div', mergeData(data, {
class: {
'uk-open': show
},
style: {
display: show ? 'block' : null
}
}), children)
}
}
var props = {
target: {},
boundary: {},
boundaryAlign: {
type: Boolean,
default: false
},
flip: {
type: [String, Boolean],
default: true
},
position: {
type: String,
default: ("bottom-" + (isRtl ? 'right' : 'left')),
validator: function (pos) { return /^(top|bottom)-(left|right|center|justify)$/.test(pos) ||
/^(left|right)-(top|bottom|center|justify)$/.test(pos); }
},
offset: {
type: [Boolean, Number],
default: false
},
animation: {
type: String,
default: 'fade'
},
duration: {
type: Number,
default: 200
},
mode: {
type: String,
default: 'click hover'
},
delayShow: {
type: Number,
default: 0
},
delayHide: {
type: Number,
default: 800
},
mainClass: {
type: String,
default: 'uk-drop'
}
}
var render = {
mounted: function mounted () {
this.$refs.target = this.queryElement(this.target) || this.$el.previousElementSibling;
this.$refs.boundary = this.queryElement(this.boundary) || window;
this.$forceUpdate();
},
render: function render (h) {
var this$1 = this;
var obj, obj$1;
var ref = this;
var position = ref.position;
var ref$1 = this.$refs;
var boundary = ref$1.boundary;
var target = ref$1.target;
var ref$2 = position.split('-');
var align = ref$2[1];
var ref$3 = this;
var boundaryAlign = ref$3.boundaryAlign;
var animation = ref$3.animation;
var duration = ref$3.duration;
var mainClass = ref$3.mainClass;
var flip = ref$3.flip;
var offset$$1 = ref$3.offset;
if (!target || !boundary) { return }
position = position.replace('justify', 'center');
target = boundaryAlign ? boundary : target;
var def = {
on: ( obj = {}, obj[BEFORE_POSITION] = function (e) {
var ref = this$1;
var $el = ref.$el;
var alignTo = offset(target);
var boundaryOffset = offset(boundary);
css($el, { width: '', height: '' });
removeClass($el, (mainClass + "-stack"));
if (align === 'justify') {
var prop = getAxis(position) === 'y' ? 'width' : 'height';
css($el, prop, alignTo[prop]);
} else if ($el.offsetWidth > Math.max(boundaryOffset.right - alignTo.left, alignTo.right - boundaryOffset.left)) {
addClass($el, (mainClass + "-stack"));
}
}, obj),
props: {
show: this.shown
},
class: [mainClass, ( obj$1 = {}, obj$1[(mainClass + "-boundary")] = this.boundaryAlign, obj$1)],
directives: [
{
name: 'show',
value: this.shown
},
{
name: 'vk-position',
value: {
flip: flip,
offset: offset$$1,
target: target,
boundary: boundary,
position: position,
mainClass: mainClass
}
}
]
};
return h(Transition, {
props: {
name: [animation],
duration: duration
}
}, [
h(ElementDrop, def, this.$slots.default)
])
}
}
function getAxis (position) {
var ref = position.split('-');
var dir = ref[0];
return dir === 'top' || dir === 'bottom'
? 'y'
: 'x'
}
var index = {
name: 'VkDrop',
mixins: [render, toggle, EventsMixin],
directives: {
VkRoot: VkRoot,
VkPosition: VkPosition
},
props: props,
methods: {
isParentOf: function isParentOf (instance) {
var parents = findParents(instance);
return includes(parents, this)
},
isChildOf: function isChildOf (instance) {
var parents = findParents(this);
return includes(parents, instance)
},
queryElement: function queryElement (el) {
return isNode(el)
? el
: isString(el)
? (get(this.$vnode.context.$refs, el) || $(el, this.$el))
: el
}
},
created: function created () {
this.tracker = new MouseTracker();
},
beforeDestroy: function beforeDestroy () {
if (this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el);
}
}
}
export { constants, active, ElementDrop, index as Drop };