element-plus
Version:
A Component Library for Vue3.0
168 lines (162 loc) • 5.61 kB
JavaScript
import { on, once, off } from '../utils/dom';
import isServer from '../utils/isServer';
import { nextTick } from 'vue';
import { obtainAllFocusableElements, EVENT_CODE } from '../utils/aria';
import normalizeWheel from 'normalize-wheel';
const nodeList = new Map();
let startClick;
if (!isServer) {
on(document, 'mousedown', (e) => (startClick = e));
on(document, 'mouseup', (e) => {
for (const { documentHandler } of nodeList.values()) {
documentHandler(e, startClick);
}
});
}
function createDocumentHandler(el, binding) {
let excludes = [];
if (Array.isArray(binding.arg)) {
excludes = binding.arg;
}
else {
excludes.push(binding.arg);
}
return function (mouseup, mousedown) {
const popperRef = binding.instance.popperRef;
const mouseUpTarget = mouseup.target;
const mouseDownTarget = mousedown.target;
const isBound = !binding || !binding.instance;
const isTargetExists = !mouseUpTarget || !mouseDownTarget;
const isContainedByEl = el.contains(mouseUpTarget) || el.contains(mouseDownTarget);
const isSelf = el === mouseUpTarget;
const isTargetExcluded = (excludes.length &&
excludes.some(item => item === null || item === void 0 ? void 0 : item.contains(mouseUpTarget))) || (excludes.length && excludes.includes(mouseDownTarget));
const isContainedByPopper = (popperRef &&
(popperRef.contains(mouseUpTarget) ||
popperRef.contains(mouseDownTarget)));
if (isBound ||
isTargetExists ||
isContainedByEl ||
isSelf ||
isTargetExcluded ||
isContainedByPopper) {
return;
}
binding.value();
};
}
const ClickOutside = {
beforeMount(el, binding) {
nodeList.set(el, {
documentHandler: createDocumentHandler(el, binding),
bindingFn: binding.value,
});
},
updated(el, binding) {
nodeList.set(el, {
documentHandler: createDocumentHandler(el, binding),
bindingFn: binding.value,
});
},
unmounted(el) {
nodeList.delete(el);
},
};
var index = {
beforeMount(el, binding) {
let interval = null;
let startTime;
const handler = () => binding.value && binding.value();
const clear = () => {
if (Date.now() - startTime < 100) {
handler();
}
clearInterval(interval);
interval = null;
};
on(el, 'mousedown', e => {
if (e.button !== 0)
return;
startTime = Date.now();
once(document, 'mouseup', clear);
clearInterval(interval);
interval = setInterval(handler, 100);
});
},
};
const FOCUSABLE_CHILDREN = '_trap-focus-children';
const FOCUS_STACK = [];
const FOCUS_HANDLER = (e) => {
var _a;
if (FOCUS_STACK.length === 0)
return;
const focusableElement = FOCUS_STACK[FOCUS_STACK.length - 1][FOCUSABLE_CHILDREN];
if (focusableElement.length > 0 && e.code === EVENT_CODE.tab) {
if (focusableElement.length === 1) {
e.preventDefault();
if (document.activeElement !== focusableElement[0]) {
focusableElement[0].focus();
}
return;
}
const goingBackward = e.shiftKey;
const isFirst = e.target === focusableElement[0];
const isLast = e.target === focusableElement[focusableElement.length - 1];
if (isFirst && goingBackward) {
e.preventDefault();
focusableElement[focusableElement.length - 1].focus();
}
if (isLast && !goingBackward) {
e.preventDefault();
focusableElement[0].focus();
}
if (process.env.NODE_ENV === 'test') {
const index = focusableElement.findIndex((element) => element === e.target);
if (index !== -1) {
(_a = focusableElement[goingBackward ? index - 1 : index + 1]) === null || _a === void 0 ? void 0 : _a.focus();
}
}
}
};
const TrapFocus = {
beforeMount(el) {
el[FOCUSABLE_CHILDREN] = obtainAllFocusableElements(el);
FOCUS_STACK.push(el);
if (FOCUS_STACK.length <= 1) {
on(document, 'keydown', FOCUS_HANDLER);
}
},
updated(el) {
nextTick(() => {
el[FOCUSABLE_CHILDREN] = obtainAllFocusableElements(el);
});
},
unmounted() {
FOCUS_STACK.shift();
if (FOCUS_STACK.length === 0) {
off(document, 'keydown', FOCUS_HANDLER);
}
},
};
const isFirefox = typeof navigator !== 'undefined' &&
navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
const mousewheel = function (element, callback) {
if (element && element.addEventListener) {
const fn = function (event) {
const normalized = normalizeWheel(event);
callback && callback.apply(this, [event, normalized]);
};
if (isFirefox) {
element.addEventListener('DOMMouseScroll', fn);
}
else {
element.onmousewheel = fn;
}
}
};
const Mousewheel = {
beforeMount(el, binding) {
mousewheel(el, binding.value);
},
};
export { ClickOutside, Mousewheel, index as RepeatClick, TrapFocus };