refactor(frontend): bring tether-drop into vendor folder to build from source
This commit is contained in:
@@ -392,7 +392,6 @@
|
|||||||
"symbol-observable": "4.0.0",
|
"symbol-observable": "4.0.0",
|
||||||
"systemjs": "6.15.1",
|
"systemjs": "6.15.1",
|
||||||
"systemjs-cjs-extra": "0.2.1",
|
"systemjs-cjs-extra": "0.2.1",
|
||||||
"tether-drop": "https://github.com/torkelo/drop",
|
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
"tslib": "2.8.1",
|
"tslib": "2.8.1",
|
||||||
"tween-functions": "^1.2.0",
|
"tween-functions": "^1.2.0",
|
||||||
|
|||||||
Vendored
+495
@@ -0,0 +1,495 @@
|
|||||||
|
import {
|
||||||
|
extend,
|
||||||
|
addClass,
|
||||||
|
removeClass,
|
||||||
|
hasClass,
|
||||||
|
Evented,
|
||||||
|
} from "./tetherUtils";
|
||||||
|
|
||||||
|
function sortAttach(str) {
|
||||||
|
let [first, second] = str.split(" ");
|
||||||
|
if (["left", "right"].indexOf(first) >= 0) {
|
||||||
|
[first, second] = [second, first];
|
||||||
|
}
|
||||||
|
return [first, second].join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFromArray(arr, item) {
|
||||||
|
let index;
|
||||||
|
let results = [];
|
||||||
|
while ((index = arr.indexOf(item)) !== -1) {
|
||||||
|
results.push(arr.splice(index, 1));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
let clickEvents = ["click"];
|
||||||
|
if ("ontouchstart" in document.documentElement) {
|
||||||
|
clickEvents.push("touchstart");
|
||||||
|
}
|
||||||
|
|
||||||
|
const transitionEndEvents = {
|
||||||
|
WebkitTransition: "webkitTransitionEnd",
|
||||||
|
MozTransition: "transitionend",
|
||||||
|
OTransition: "otransitionend",
|
||||||
|
transition: "transitionend",
|
||||||
|
};
|
||||||
|
|
||||||
|
let transitionEndEvent = "";
|
||||||
|
for (let name in transitionEndEvents) {
|
||||||
|
if ({}.hasOwnProperty.call(transitionEndEvents, name)) {
|
||||||
|
let tempEl = document.createElement("p");
|
||||||
|
if (typeof tempEl.style[name] !== "undefined") {
|
||||||
|
transitionEndEvent = transitionEndEvents[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MIRROR_ATTACH = {
|
||||||
|
left: "right",
|
||||||
|
right: "left",
|
||||||
|
top: "bottom",
|
||||||
|
bottom: "top",
|
||||||
|
middle: "middle",
|
||||||
|
center: "center",
|
||||||
|
};
|
||||||
|
|
||||||
|
let allDrops = {};
|
||||||
|
|
||||||
|
// Drop can be included in external libraries. Calling createContext gives you a fresh
|
||||||
|
// copy of drop which won't interact with other copies on the page (beyond calling the document events).
|
||||||
|
|
||||||
|
function createContext(options = {}) {
|
||||||
|
let drop = (...args) => new DropInstance(...args);
|
||||||
|
|
||||||
|
extend(drop, {
|
||||||
|
createContext: createContext,
|
||||||
|
drops: [],
|
||||||
|
defaults: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
classPrefix: "drop",
|
||||||
|
defaults: {
|
||||||
|
position: "bottom left",
|
||||||
|
openOn: "click",
|
||||||
|
beforeClose: null,
|
||||||
|
constrainToScrollParent: true,
|
||||||
|
constrainToWindow: true,
|
||||||
|
classes: "",
|
||||||
|
remove: false,
|
||||||
|
openDelay: 0,
|
||||||
|
closeDelay: 50,
|
||||||
|
// inherited from openDelay and closeDelay if not explicitly defined
|
||||||
|
focusDelay: null,
|
||||||
|
blurDelay: null,
|
||||||
|
hoverOpenDelay: null,
|
||||||
|
hoverCloseDelay: null,
|
||||||
|
tetherOptions: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
extend(drop, defaultOptions, options);
|
||||||
|
extend(drop.defaults, defaultOptions.defaults, options.defaults);
|
||||||
|
|
||||||
|
if (typeof allDrops[drop.classPrefix] === "undefined") {
|
||||||
|
allDrops[drop.classPrefix] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
drop.updateBodyClasses = () => {
|
||||||
|
// There is only one body, so despite the context concept, we still iterate through all
|
||||||
|
// drops which share our classPrefix.
|
||||||
|
|
||||||
|
let anyOpen = false;
|
||||||
|
const drops = allDrops[drop.classPrefix];
|
||||||
|
const len = drops.length;
|
||||||
|
for (let i = 0; i < len; ++i) {
|
||||||
|
if (drops[i].isOpened()) {
|
||||||
|
anyOpen = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyOpen) {
|
||||||
|
addClass(document.body, `${drop.classPrefix}-open`);
|
||||||
|
} else {
|
||||||
|
removeClass(document.body, `${drop.classPrefix}-open`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DropInstance extends Evented {
|
||||||
|
constructor(opts) {
|
||||||
|
super();
|
||||||
|
this.options = extend({}, drop.defaults, opts);
|
||||||
|
this.target = this.options.target;
|
||||||
|
|
||||||
|
if (typeof this.target === "undefined") {
|
||||||
|
throw new Error("Drop Error: You must provide a target.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataPrefix = `data-${drop.classPrefix}`;
|
||||||
|
|
||||||
|
const contentAttr = this.target.getAttribute(dataPrefix);
|
||||||
|
if (contentAttr && this.options.content == null) {
|
||||||
|
this.options.content = contentAttr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attrsOverride = ["position", "openOn"];
|
||||||
|
for (let i = 0; i < attrsOverride.length; ++i) {
|
||||||
|
const override = this.target.getAttribute(
|
||||||
|
`${dataPrefix}-${attrsOverride[i]}`
|
||||||
|
);
|
||||||
|
if (override && this.options[attrsOverride[i]] == null) {
|
||||||
|
this.options[attrsOverride[i]] = override;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.classes && this.options.addTargetClasses !== false) {
|
||||||
|
addClass(this.target, this.options.classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
drop.drops.push(this);
|
||||||
|
allDrops[drop.classPrefix].push(this);
|
||||||
|
|
||||||
|
this._boundEvents = [];
|
||||||
|
this.bindMethods();
|
||||||
|
this.setupElements();
|
||||||
|
this.setupEvents();
|
||||||
|
this.setupTether();
|
||||||
|
}
|
||||||
|
|
||||||
|
_on(element, event, handler) {
|
||||||
|
this._boundEvents.push({ element, event, handler });
|
||||||
|
element.addEventListener(event, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
bindMethods() {
|
||||||
|
this.transitionEndHandler = this._transitionEndHandler.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupElements() {
|
||||||
|
this.drop = document.createElement("div");
|
||||||
|
addClass(this.drop, drop.classPrefix);
|
||||||
|
|
||||||
|
if (this.options.classes) {
|
||||||
|
addClass(this.drop, this.options.classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.content = document.createElement("div");
|
||||||
|
addClass(this.content, `${drop.classPrefix}-content`);
|
||||||
|
|
||||||
|
if (typeof this.options.content === "function") {
|
||||||
|
const generateAndSetContent = () => {
|
||||||
|
// content function might return a string or an element
|
||||||
|
const contentElementOrHTML = this.options.content.call(this, this);
|
||||||
|
|
||||||
|
if (typeof contentElementOrHTML === "string") {
|
||||||
|
this.content.innerHTML = contentElementOrHTML;
|
||||||
|
} else if (typeof contentElementOrHTML === "object") {
|
||||||
|
this.content.innerHTML = "";
|
||||||
|
this.content.appendChild(contentElementOrHTML);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"Drop Error: Content function should return a string or HTMLElement."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.on("beforeOpen", generateAndSetContent.bind(this));
|
||||||
|
} else if (typeof this.options.content === "object") {
|
||||||
|
this.content.appendChild(this.options.content);
|
||||||
|
} else {
|
||||||
|
this.content.innerHTML = this.options.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.drop.appendChild(this.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupTether() {
|
||||||
|
// Tether expects two attachment points, one in the target element, one in the
|
||||||
|
// drop. We use a single one, and use the order as well, to allow us to put
|
||||||
|
// the drop on either side of any of the four corners. This magic converts between
|
||||||
|
// the two:
|
||||||
|
let dropAttach = this.options.position.split(" ");
|
||||||
|
dropAttach[0] = MIRROR_ATTACH[dropAttach[0]];
|
||||||
|
dropAttach = dropAttach.join(" ");
|
||||||
|
|
||||||
|
let constraints = [];
|
||||||
|
if (this.options.constrainToScrollParent) {
|
||||||
|
constraints.push({
|
||||||
|
to: "scrollParent",
|
||||||
|
pin: "top, bottom",
|
||||||
|
attachment: "together none",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// To get 'out of bounds' classes
|
||||||
|
constraints.push({
|
||||||
|
to: "scrollParent",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.constrainToWindow !== false) {
|
||||||
|
constraints.push({
|
||||||
|
to: "window",
|
||||||
|
attachment: "together",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// To get 'out of bounds' classes
|
||||||
|
constraints.push({
|
||||||
|
to: "window",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
element: this.drop,
|
||||||
|
target: this.target,
|
||||||
|
attachment: sortAttach(dropAttach),
|
||||||
|
targetAttachment: sortAttach(this.options.position),
|
||||||
|
classPrefix: drop.classPrefix,
|
||||||
|
offset: "0 0",
|
||||||
|
targetOffset: "0 0",
|
||||||
|
enabled: false,
|
||||||
|
constraints: constraints,
|
||||||
|
addTargetClasses: this.options.addTargetClasses,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.options.tetherOptions !== false) {
|
||||||
|
this.tether = new Tether(extend({}, opts, this.options.tetherOptions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupEvents() {
|
||||||
|
if (!this.options.openOn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.openOn === "always") {
|
||||||
|
setTimeout(this.open.bind(this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const events = this.options.openOn.split(" ");
|
||||||
|
|
||||||
|
if (events.indexOf("click") >= 0) {
|
||||||
|
const openHandler = (event) => {
|
||||||
|
this.toggle(event);
|
||||||
|
event.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeHandler = (event) => {
|
||||||
|
if (!this.isOpened()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clicking inside dropdown
|
||||||
|
if (event.target === this.drop || this.drop.contains(event.target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clicking target
|
||||||
|
if (
|
||||||
|
event.target === this.target ||
|
||||||
|
this.target.contains(event.target)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.close(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let i = 0; i < clickEvents.length; ++i) {
|
||||||
|
const clickEvent = clickEvents[i];
|
||||||
|
this._on(this.target, clickEvent, openHandler);
|
||||||
|
this._on(document, clickEvent, closeHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let inTimeout = null;
|
||||||
|
let outTimeout = null;
|
||||||
|
|
||||||
|
const inHandler = (event) => {
|
||||||
|
if (outTimeout !== null) {
|
||||||
|
clearTimeout(outTimeout);
|
||||||
|
} else {
|
||||||
|
inTimeout = setTimeout(() => {
|
||||||
|
this.open(event);
|
||||||
|
inTimeout = null;
|
||||||
|
}, (event.type === "focus" ? this.options.focusDelay : this.options.hoverOpenDelay) || this.options.openDelay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const outHandler = (event) => {
|
||||||
|
if (inTimeout !== null) {
|
||||||
|
clearTimeout(inTimeout);
|
||||||
|
} else {
|
||||||
|
outTimeout = setTimeout(() => {
|
||||||
|
this.close(event);
|
||||||
|
outTimeout = null;
|
||||||
|
}, (event.type === "blur" ? this.options.blurDelay : this.options.hoverCloseDelay) || this.options.closeDelay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (events.indexOf("hover") >= 0) {
|
||||||
|
this._on(this.target, "mouseover", inHandler);
|
||||||
|
this._on(this.drop, "mouseover", inHandler);
|
||||||
|
this._on(this.target, "mouseout", outHandler);
|
||||||
|
this._on(this.drop, "mouseout", outHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events.indexOf("focus") >= 0) {
|
||||||
|
this._on(this.target, "focus", inHandler);
|
||||||
|
this._on(this.drop, "focus", inHandler);
|
||||||
|
this._on(this.target, "blur", outHandler);
|
||||||
|
this._on(this.drop, "blur", outHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isOpened() {
|
||||||
|
if (this.drop) {
|
||||||
|
return hasClass(this.drop, `${drop.classPrefix}-open`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle(event) {
|
||||||
|
if (this.isOpened()) {
|
||||||
|
this.close(event);
|
||||||
|
} else {
|
||||||
|
this.open(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open(event) {
|
||||||
|
/* eslint no-unused-vars: 0 */
|
||||||
|
if (this.isOpened()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.drop.parentNode) {
|
||||||
|
document.body.appendChild(this.drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.tether !== "undefined") {
|
||||||
|
this.tether.enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
addClass(this.drop, `${drop.classPrefix}-open`);
|
||||||
|
addClass(this.drop, `${drop.classPrefix}-open-transitionend`);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.drop) {
|
||||||
|
addClass(this.drop, `${drop.classPrefix}-after-open`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.trigger("beforeOpen");
|
||||||
|
|
||||||
|
if (typeof this.tether !== "undefined") {
|
||||||
|
this.tether.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger("open");
|
||||||
|
|
||||||
|
drop.updateBodyClasses();
|
||||||
|
}
|
||||||
|
|
||||||
|
_transitionEndHandler(e) {
|
||||||
|
if (e.target !== e.currentTarget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasClass(this.drop, `${drop.classPrefix}-open`)) {
|
||||||
|
removeClass(this.drop, `${drop.classPrefix}-open-transitionend`);
|
||||||
|
}
|
||||||
|
this.drop.removeEventListener(
|
||||||
|
transitionEndEvent,
|
||||||
|
this.transitionEndHandler
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeCloseHandler(event) {
|
||||||
|
let shouldClose = true;
|
||||||
|
|
||||||
|
if (!this.isClosing && typeof this.options.beforeClose === "function") {
|
||||||
|
this.isClosing = true;
|
||||||
|
shouldClose = this.options.beforeClose(event, this) !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isClosing = false;
|
||||||
|
|
||||||
|
return shouldClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(event) {
|
||||||
|
if (!this.isOpened()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.beforeCloseHandler(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeClass(this.drop, `${drop.classPrefix}-open`);
|
||||||
|
removeClass(this.drop, `${drop.classPrefix}-after-open`);
|
||||||
|
|
||||||
|
this.drop.addEventListener(transitionEndEvent, this.transitionEndHandler);
|
||||||
|
|
||||||
|
this.trigger("close");
|
||||||
|
|
||||||
|
if (typeof this.tether !== "undefined") {
|
||||||
|
this.tether.disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
drop.updateBodyClasses();
|
||||||
|
|
||||||
|
if (this.options.remove) {
|
||||||
|
this.remove(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(event) {
|
||||||
|
this.close(event);
|
||||||
|
if (this.drop.parentNode) {
|
||||||
|
this.drop.parentNode.removeChild(this.drop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
position() {
|
||||||
|
if (this.isOpened() && typeof this.tether !== "undefined") {
|
||||||
|
this.tether.position();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.remove();
|
||||||
|
|
||||||
|
if (typeof this.tether !== "undefined") {
|
||||||
|
this.tether.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < this._boundEvents.length; ++i) {
|
||||||
|
const { element, event, handler } = this._boundEvents[i];
|
||||||
|
element.removeEventListener(event, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._boundEvents = [];
|
||||||
|
|
||||||
|
this.tether = null;
|
||||||
|
this.drop = null;
|
||||||
|
this.content = null;
|
||||||
|
this.target = null;
|
||||||
|
|
||||||
|
removeFromArray(allDrops[drop.classPrefix], this);
|
||||||
|
removeFromArray(drop.drops, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return drop;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Drop = createContext();
|
||||||
|
|
||||||
|
export default Drop;
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
Drop.updateBodyClasses();
|
||||||
|
});
|
||||||
+378
@@ -0,0 +1,378 @@
|
|||||||
|
let TetherBase;
|
||||||
|
if (typeof TetherBase === "undefined") {
|
||||||
|
TetherBase = { modules: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
let zeroElement = null;
|
||||||
|
|
||||||
|
// Same as native getBoundingClientRect, except it takes into account parent <frame> offsets
|
||||||
|
// if the element lies within a nested document (<frame> or <iframe>-like).
|
||||||
|
function getActualBoundingClientRect(node) {
|
||||||
|
let boundingRect = node.getBoundingClientRect();
|
||||||
|
|
||||||
|
// The original object returned by getBoundingClientRect is immutable, so we clone it
|
||||||
|
// We can't use extend because the properties are not considered part of the object by hasOwnProperty in IE9
|
||||||
|
let rect = {};
|
||||||
|
for (var k in boundingRect) {
|
||||||
|
rect[k] = boundingRect[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (node.ownerDocument !== document) {
|
||||||
|
let frameElement = node.ownerDocument.defaultView.frameElement;
|
||||||
|
if (frameElement) {
|
||||||
|
let frameRect = getActualBoundingClientRect(frameElement);
|
||||||
|
rect.top += frameRect.top;
|
||||||
|
rect.bottom += frameRect.top;
|
||||||
|
rect.left += frameRect.left;
|
||||||
|
rect.right += frameRect.left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Ignore "Access is denied" in IE11/Edge
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScrollParents(el) {
|
||||||
|
// In firefox if the el is inside an iframe with display: none; window.getComputedStyle() will return null;
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=548397
|
||||||
|
const computedStyle = getComputedStyle(el) || {};
|
||||||
|
const position = computedStyle.position;
|
||||||
|
let parents = [];
|
||||||
|
|
||||||
|
if (position === "fixed") {
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = el;
|
||||||
|
while ((parent = parent.parentNode) && parent && parent.nodeType === 1) {
|
||||||
|
let style;
|
||||||
|
try {
|
||||||
|
style = getComputedStyle(parent);
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
if (typeof style === "undefined" || style === null) {
|
||||||
|
parents.push(parent);
|
||||||
|
return parents;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { overflow, overflowX, overflowY } = style;
|
||||||
|
if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
|
||||||
|
if (
|
||||||
|
position !== "absolute" ||
|
||||||
|
["relative", "absolute", "fixed"].indexOf(style.position) >= 0
|
||||||
|
) {
|
||||||
|
parents.push(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parents.push(el.ownerDocument.body);
|
||||||
|
|
||||||
|
// If the node is within a frame, account for the parent window scroll
|
||||||
|
if (el.ownerDocument !== document) {
|
||||||
|
parents.push(el.ownerDocument.defaultView);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parents;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uniqueId = (() => {
|
||||||
|
let id = 0;
|
||||||
|
return () => ++id;
|
||||||
|
})();
|
||||||
|
|
||||||
|
const zeroPosCache = {};
|
||||||
|
const getOrigin = () => {
|
||||||
|
// getBoundingClientRect is unfortunately too accurate. It introduces a pixel or two of
|
||||||
|
// jitter as the user scrolls that messes with our ability to detect if two positions
|
||||||
|
// are equivilant or not. We place an element at the top left of the page that will
|
||||||
|
// get the same jitter, so we can cancel the two out.
|
||||||
|
let node = zeroElement;
|
||||||
|
if (!node || !document.body.contains(node)) {
|
||||||
|
node = document.createElement("div");
|
||||||
|
node.setAttribute("data-tether-id", uniqueId());
|
||||||
|
extend(node.style, {
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
position: "absolute",
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.appendChild(node);
|
||||||
|
|
||||||
|
zeroElement = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = node.getAttribute("data-tether-id");
|
||||||
|
if (typeof zeroPosCache[id] === "undefined") {
|
||||||
|
zeroPosCache[id] = getActualBoundingClientRect(node);
|
||||||
|
|
||||||
|
// Clear the cache when this position call is done
|
||||||
|
defer(() => {
|
||||||
|
delete zeroPosCache[id];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return zeroPosCache[id];
|
||||||
|
};
|
||||||
|
|
||||||
|
function removeUtilElements() {
|
||||||
|
if (zeroElement) {
|
||||||
|
document.body.removeChild(zeroElement);
|
||||||
|
}
|
||||||
|
zeroElement = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBounds(el) {
|
||||||
|
let doc;
|
||||||
|
if (el === document) {
|
||||||
|
doc = document;
|
||||||
|
el = document.documentElement;
|
||||||
|
} else {
|
||||||
|
doc = el.ownerDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
const docEl = doc.documentElement;
|
||||||
|
|
||||||
|
const box = getActualBoundingClientRect(el);
|
||||||
|
|
||||||
|
const origin = getOrigin();
|
||||||
|
|
||||||
|
box.top -= origin.top;
|
||||||
|
box.left -= origin.left;
|
||||||
|
|
||||||
|
if (typeof box.width === "undefined") {
|
||||||
|
box.width = document.body.scrollWidth - box.left - box.right;
|
||||||
|
}
|
||||||
|
if (typeof box.height === "undefined") {
|
||||||
|
box.height = document.body.scrollHeight - box.top - box.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
box.top = box.top - docEl.clientTop;
|
||||||
|
box.left = box.left - docEl.clientLeft;
|
||||||
|
box.right = doc.body.clientWidth - box.width - box.left;
|
||||||
|
box.bottom = doc.body.clientHeight - box.height - box.top;
|
||||||
|
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOffsetParent(el) {
|
||||||
|
return el.offsetParent || document.documentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
let _scrollBarSize = null;
|
||||||
|
function getScrollBarSize() {
|
||||||
|
if (_scrollBarSize) {
|
||||||
|
return _scrollBarSize;
|
||||||
|
}
|
||||||
|
const inner = document.createElement("div");
|
||||||
|
inner.style.width = "100%";
|
||||||
|
inner.style.height = "200px";
|
||||||
|
|
||||||
|
const outer = document.createElement("div");
|
||||||
|
extend(outer.style, {
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
pointerEvents: "none",
|
||||||
|
visibility: "hidden",
|
||||||
|
width: "200px",
|
||||||
|
height: "150px",
|
||||||
|
overflow: "hidden",
|
||||||
|
});
|
||||||
|
|
||||||
|
outer.appendChild(inner);
|
||||||
|
|
||||||
|
document.body.appendChild(outer);
|
||||||
|
|
||||||
|
const widthContained = inner.offsetWidth;
|
||||||
|
outer.style.overflow = "scroll";
|
||||||
|
let widthScroll = inner.offsetWidth;
|
||||||
|
|
||||||
|
if (widthContained === widthScroll) {
|
||||||
|
widthScroll = outer.clientWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.removeChild(outer);
|
||||||
|
|
||||||
|
const width = widthContained - widthScroll;
|
||||||
|
|
||||||
|
_scrollBarSize = { width, height: width };
|
||||||
|
return _scrollBarSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extend(out = {}) {
|
||||||
|
const args = [];
|
||||||
|
|
||||||
|
Array.prototype.push.apply(args, arguments);
|
||||||
|
|
||||||
|
args.slice(1).forEach((obj) => {
|
||||||
|
if (obj) {
|
||||||
|
for (let key in obj) {
|
||||||
|
if ({}.hasOwnProperty.call(obj, key)) {
|
||||||
|
out[key] = obj[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeClass(el, name) {
|
||||||
|
if (typeof el.classList !== "undefined") {
|
||||||
|
name.split(" ").forEach((cls) => {
|
||||||
|
if (cls.trim()) {
|
||||||
|
el.classList.remove(cls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const regex = new RegExp(`(^| )${name.split(" ").join("|")}( |$)`, "gi");
|
||||||
|
const className = getClassName(el).replace(regex, " ");
|
||||||
|
setClassName(el, className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addClass(el, name) {
|
||||||
|
if (typeof el.classList !== "undefined") {
|
||||||
|
name.split(" ").forEach((cls) => {
|
||||||
|
if (cls.trim()) {
|
||||||
|
el.classList.add(cls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
removeClass(el, name);
|
||||||
|
const cls = getClassName(el) + ` ${name}`;
|
||||||
|
setClassName(el, cls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasClass(el, name) {
|
||||||
|
if (typeof el.classList !== "undefined") {
|
||||||
|
return el.classList.contains(name);
|
||||||
|
}
|
||||||
|
const className = getClassName(el);
|
||||||
|
return new RegExp(`(^| )${name}( |$)`, "gi").test(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClassName(el) {
|
||||||
|
// Can't use just SVGAnimatedString here since nodes within a Frame in IE have
|
||||||
|
// completely separately SVGAnimatedString base classes
|
||||||
|
if (el.className instanceof el.ownerDocument.defaultView.SVGAnimatedString) {
|
||||||
|
return el.className.baseVal;
|
||||||
|
}
|
||||||
|
return el.className;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setClassName(el, className) {
|
||||||
|
el.setAttribute("class", className);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateClasses(el, add, all) {
|
||||||
|
// Of the set of 'all' classes, we need the 'add' classes, and only the
|
||||||
|
// 'add' classes to be set.
|
||||||
|
all.forEach((cls) => {
|
||||||
|
if (add.indexOf(cls) === -1 && hasClass(el, cls)) {
|
||||||
|
removeClass(el, cls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add.forEach((cls) => {
|
||||||
|
if (!hasClass(el, cls)) {
|
||||||
|
addClass(el, cls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const deferred = [];
|
||||||
|
|
||||||
|
const defer = (fn) => {
|
||||||
|
deferred.push(fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
const flush = () => {
|
||||||
|
let fn;
|
||||||
|
while ((fn = deferred.pop())) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Evented {
|
||||||
|
on(event, handler, ctx, once = false) {
|
||||||
|
if (typeof this.bindings === "undefined") {
|
||||||
|
this.bindings = {};
|
||||||
|
}
|
||||||
|
if (typeof this.bindings[event] === "undefined") {
|
||||||
|
this.bindings[event] = [];
|
||||||
|
}
|
||||||
|
this.bindings[event].push({ handler, ctx, once });
|
||||||
|
}
|
||||||
|
|
||||||
|
once(event, handler, ctx) {
|
||||||
|
this.on(event, handler, ctx, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
off(event, handler) {
|
||||||
|
if (
|
||||||
|
typeof this.bindings === "undefined" ||
|
||||||
|
typeof this.bindings[event] === "undefined"
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof handler === "undefined") {
|
||||||
|
delete this.bindings[event];
|
||||||
|
} else {
|
||||||
|
let i = 0;
|
||||||
|
while (i < this.bindings[event].length) {
|
||||||
|
if (this.bindings[event][i].handler === handler) {
|
||||||
|
this.bindings[event].splice(i, 1);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trigger(event, ...args) {
|
||||||
|
if (typeof this.bindings !== "undefined" && this.bindings[event]) {
|
||||||
|
let i = 0;
|
||||||
|
while (i < this.bindings[event].length) {
|
||||||
|
const { handler, ctx, once } = this.bindings[event][i];
|
||||||
|
|
||||||
|
let context = ctx;
|
||||||
|
if (typeof context === "undefined") {
|
||||||
|
context = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.apply(context, args);
|
||||||
|
|
||||||
|
if (once) {
|
||||||
|
this.bindings[event].splice(i, 1);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getActualBoundingClientRect,
|
||||||
|
getScrollParents,
|
||||||
|
getBounds,
|
||||||
|
getOffsetParent,
|
||||||
|
extend,
|
||||||
|
addClass,
|
||||||
|
removeClass,
|
||||||
|
hasClass,
|
||||||
|
updateClasses,
|
||||||
|
defer,
|
||||||
|
flush,
|
||||||
|
uniqueId,
|
||||||
|
Evented,
|
||||||
|
getScrollBarSize,
|
||||||
|
removeUtilElements,
|
||||||
|
};
|
||||||
@@ -18497,7 +18497,6 @@ __metadata:
|
|||||||
systemjs: "npm:6.15.1"
|
systemjs: "npm:6.15.1"
|
||||||
systemjs-cjs-extra: "npm:0.2.1"
|
systemjs-cjs-extra: "npm:0.2.1"
|
||||||
testing-library-selector: "npm:0.3.1"
|
testing-library-selector: "npm:0.3.1"
|
||||||
tether-drop: "https://github.com/torkelo/drop"
|
|
||||||
tinycolor2: "npm:1.6.0"
|
tinycolor2: "npm:1.6.0"
|
||||||
tracelib: "npm:1.0.1"
|
tracelib: "npm:1.0.1"
|
||||||
ts-jest: "npm:29.2.5"
|
ts-jest: "npm:29.2.5"
|
||||||
@@ -29566,22 +29565,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"tether-drop@https://github.com/torkelo/drop":
|
|
||||||
version: 1.5.0
|
|
||||||
resolution: "tether-drop@https://github.com/torkelo/drop.git#commit=fc83ca88db0076fbf6359cbe1743a9ef0f1ee6e1"
|
|
||||||
dependencies:
|
|
||||||
tether: "npm:^1.1.0"
|
|
||||||
checksum: 10/178c3afb889ee6dc860f767ffd7a959774adce200148e067aff631888b98fd046123f887ca40152581a13c430ad1fa72e2a9dba9de4e79e3f7634e224c229188
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"tether@npm:^1.1.0":
|
|
||||||
version: 1.4.7
|
|
||||||
resolution: "tether@npm:1.4.7"
|
|
||||||
checksum: 10/4185215f28392733f6248ea5d1734cd411d921ba3d5ae92df977bc1d11bd88dcf469ed6ceb9195accd8facc136ddd87d286f18cab2544300412e3f2d073d8e68
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"text-extensions@npm:^1.0.0":
|
"text-extensions@npm:^1.0.0":
|
||||||
version: 1.9.0
|
version: 1.9.0
|
||||||
resolution: "text-extensions@npm:1.9.0"
|
resolution: "text-extensions@npm:1.9.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user