2379 lines
68 KiB
JavaScript
2379 lines
68 KiB
JavaScript
/*!
|
|
* @thednp/shorty ESM v2.0.14 (https://github.com/thednp/shorty)
|
|
* Copyright 2026 © thednp
|
|
* Licensed under MIT (https://github.com/thednp/shorty/blob/master/LICENSE)
|
|
*/
|
|
//#region package.json
|
|
var version = "2.0.14";
|
|
//#endregion
|
|
//#region src/strings/ariaChecked.ts
|
|
/**
|
|
* A global namespace for aria-checked.
|
|
*/
|
|
const ariaChecked = "aria-checked";
|
|
//#endregion
|
|
//#region src/strings/ariaDescription.ts
|
|
/**
|
|
* A global namespace for aria-description.
|
|
*/
|
|
const ariaDescription = "aria-description";
|
|
//#endregion
|
|
//#region src/strings/ariaDescribedBy.ts
|
|
/**
|
|
* A global namespace for aria-describedby.
|
|
*/
|
|
const ariaDescribedBy = "aria-describedby";
|
|
//#endregion
|
|
//#region src/strings/ariaExpanded.ts
|
|
/**
|
|
* A global namespace for aria-expanded.
|
|
*/
|
|
const ariaExpanded = "aria-expanded";
|
|
//#endregion
|
|
//#region src/strings/ariaHasPopup.ts
|
|
/**
|
|
* A global namespace for aria-haspopup.
|
|
*/
|
|
const ariaHasPopup = "aria-haspopup";
|
|
//#endregion
|
|
//#region src/strings/ariaHidden.ts
|
|
/**
|
|
* A global namespace for aria-hidden.
|
|
*/
|
|
const ariaHidden = "aria-hidden";
|
|
//#endregion
|
|
//#region src/strings/ariaLabel.ts
|
|
/**
|
|
* A global namespace for aria-label.
|
|
*/
|
|
const ariaLabel = "aria-label";
|
|
//#endregion
|
|
//#region src/strings/ariaLabelledBy.ts
|
|
/**
|
|
* A global namespace for aria-labelledby.
|
|
*/
|
|
const ariaLabelledBy = "aria-labelledby";
|
|
//#endregion
|
|
//#region src/strings/ariaModal.ts
|
|
/**
|
|
* A global namespace for aria-modal.
|
|
*/
|
|
const ariaModal = "aria-modal";
|
|
//#endregion
|
|
//#region src/strings/ariaPressed.ts
|
|
/**
|
|
* A global namespace for aria-pressed.
|
|
*/
|
|
const ariaPressed = "aria-pressed";
|
|
//#endregion
|
|
//#region src/strings/ariaSelected.ts
|
|
/**
|
|
* A global namespace for aria-selected.
|
|
*/
|
|
const ariaSelected = "aria-selected";
|
|
//#endregion
|
|
//#region src/strings/ariaValueMin.ts
|
|
/**
|
|
* A global namespace for aria-valuemin.
|
|
*/
|
|
const ariaValueMin = "aria-valuemin";
|
|
//#endregion
|
|
//#region src/strings/ariaValueMax.ts
|
|
/**
|
|
* A global namespace for aria-valuemax.
|
|
*/
|
|
const ariaValueMax = "aria-valuemax";
|
|
//#endregion
|
|
//#region src/strings/ariaValueNow.ts
|
|
/**
|
|
* A global namespace for aria-valuenow.
|
|
*/
|
|
const ariaValueNow = "aria-valuenow";
|
|
//#endregion
|
|
//#region src/strings/ariaValueText.ts
|
|
/**
|
|
* A global namespace for aria-valuetext.
|
|
*/
|
|
const ariaValueText = "aria-valuetext";
|
|
//#endregion
|
|
//#region src/strings/abortEvent.ts
|
|
/**
|
|
* A global namespace for `abort` event.
|
|
*/
|
|
const abortEvent = "abort";
|
|
//#endregion
|
|
//#region src/strings/beforeunloadEvent.ts
|
|
/**
|
|
* A global namespace for `beforeunload` event.
|
|
*/
|
|
const beforeunloadEvent = "beforeunload";
|
|
//#endregion
|
|
//#region src/strings/blurEvent.ts
|
|
/**
|
|
* A global namespace for `blur` event.
|
|
*/
|
|
const blurEvent = "blur";
|
|
//#endregion
|
|
//#region src/strings/changeEvent.ts
|
|
/**
|
|
* A global namespace for `change` event.
|
|
*/
|
|
const changeEvent = "change";
|
|
//#endregion
|
|
//#region src/strings/contextmenuEvent.ts
|
|
/**
|
|
* A global namespace for `contextmenu` event.
|
|
*/
|
|
const contextmenuEvent = "contextmenu";
|
|
//#endregion
|
|
//#region src/strings/DOMContentLoadedEvent.ts
|
|
/**
|
|
* A global namespace for `DOMContentLoaded` event.
|
|
*/
|
|
const DOMContentLoadedEvent = "DOMContentLoaded";
|
|
//#endregion
|
|
//#region src/strings/DOMMouseScrollEvent.ts
|
|
/**
|
|
* A global namespace for `DOMMouseScroll` event.
|
|
*/
|
|
const DOMMouseScrollEvent = "DOMMouseScroll";
|
|
//#endregion
|
|
//#region src/strings/errorEvent.ts
|
|
/**
|
|
* A global namespace for `error` event.
|
|
*/
|
|
const errorEvent = "error";
|
|
//#endregion
|
|
//#region src/strings/focusEvent.ts
|
|
/**
|
|
* A global namespace for `focus` event.
|
|
*/
|
|
const focusEvent = "focus";
|
|
//#endregion
|
|
//#region src/strings/focusinEvent.ts
|
|
/**
|
|
* A global namespace for `focusin` event.
|
|
*/
|
|
const focusinEvent = "focusin";
|
|
//#endregion
|
|
//#region src/strings/focusoutEvent.ts
|
|
/**
|
|
* A global namespace for `focusout` event.
|
|
*/
|
|
const focusoutEvent = "focusout";
|
|
//#endregion
|
|
//#region src/strings/gesturechangeEvent.ts
|
|
/**
|
|
* A global namespace for `gesturechange` event.
|
|
*/
|
|
const gesturechangeEvent = "gesturechange";
|
|
//#endregion
|
|
//#region src/strings/gestureendEvent.ts
|
|
/**
|
|
* A global namespace for `gestureend` event.
|
|
*/
|
|
const gestureendEvent = "gestureend";
|
|
//#endregion
|
|
//#region src/strings/gesturestartEvent.ts
|
|
/**
|
|
* A global namespace for `gesturestart` event.
|
|
*/
|
|
const gesturestartEvent = "gesturestart";
|
|
//#endregion
|
|
//#region src/strings/keydownEvent.ts
|
|
/**
|
|
* A global namespace for `keydown` event.
|
|
*/
|
|
const keydownEvent = "keydown";
|
|
//#endregion
|
|
//#region src/strings/keypressEvent.ts
|
|
/**
|
|
* A global namespace for `keypress` event.
|
|
*/
|
|
const keypressEvent = "keypress";
|
|
//#endregion
|
|
//#region src/strings/keyupEvent.ts
|
|
/**
|
|
* A global namespace for `keyup` event.
|
|
*/
|
|
const keyupEvent = "keyup";
|
|
//#endregion
|
|
//#region src/strings/loadEvent.ts
|
|
/**
|
|
* A global namespace for `load` event.
|
|
*/
|
|
const loadEvent = "load";
|
|
//#endregion
|
|
//#region src/strings/mouseclickEvent.ts
|
|
/**
|
|
* A global namespace for `click` event.
|
|
*/
|
|
const mouseclickEvent = "click";
|
|
//#endregion
|
|
//#region src/strings/mousedblclickEvent.ts
|
|
/**
|
|
* A global namespace for `dblclick` event.
|
|
*/
|
|
const mousedblclickEvent = "dblclick";
|
|
//#endregion
|
|
//#region src/strings/mousedownEvent.ts
|
|
/**
|
|
* A global namespace for `mousedown` event.
|
|
*/
|
|
const mousedownEvent = "mousedown";
|
|
//#endregion
|
|
//#region src/strings/mouseupEvent.ts
|
|
/**
|
|
* A global namespace for `mouseup` event.
|
|
*/
|
|
const mouseupEvent = "mouseup";
|
|
//#endregion
|
|
//#region src/strings/mousehoverEvent.ts
|
|
/**
|
|
* A global namespace for `hover` event.
|
|
*/
|
|
const mousehoverEvent = "hover";
|
|
//#endregion
|
|
//#region src/strings/mouseenterEvent.ts
|
|
/**
|
|
* A global namespace for `mouseenter` event.
|
|
*/
|
|
const mouseenterEvent = "mouseenter";
|
|
//#endregion
|
|
//#region src/strings/mouseleaveEvent.ts
|
|
/**
|
|
* A global namespace for `mouseleave` event.
|
|
*/
|
|
const mouseleaveEvent = "mouseleave";
|
|
//#endregion
|
|
//#region src/strings/mouseinEvent.ts
|
|
/**
|
|
* A global namespace for `mousein` event.
|
|
*/
|
|
const mouseinEvent = "mousein";
|
|
//#endregion
|
|
//#region src/strings/mouseoutEvent.ts
|
|
/**
|
|
* A global namespace for `mouseout` event.
|
|
*/
|
|
const mouseoutEvent = "mouseout";
|
|
//#endregion
|
|
//#region src/strings/mouseoverEvent.ts
|
|
/**
|
|
* A global namespace for `mouseover` event.
|
|
*/
|
|
const mouseoverEvent = "mouseover";
|
|
//#endregion
|
|
//#region src/strings/mousemoveEvent.ts
|
|
/**
|
|
* A global namespace for `mousemove` event.
|
|
*/
|
|
const mousemoveEvent = "mousemove";
|
|
//#endregion
|
|
//#region src/strings/mousewheelEvent.ts
|
|
/**
|
|
* A global namespace for `mousewheel` event.
|
|
*/
|
|
const mousewheelEvent = "mousewheel";
|
|
//#endregion
|
|
//#region src/strings/moveEvent.ts
|
|
/**
|
|
* A global namespace for `move` event.
|
|
*/
|
|
const moveEvent = "move";
|
|
//#endregion
|
|
//#region src/strings/orientationchangeEvent.ts
|
|
/**
|
|
* A global namespace for `orientationchange` event.
|
|
*/
|
|
const orientationchangeEvent = "orientationchange";
|
|
//#endregion
|
|
//#region src/strings/pointercancelEvent.ts
|
|
/**
|
|
* A global namespace for `pointercancel` event.
|
|
*/
|
|
const pointercancelEvent = "pointercancel";
|
|
//#endregion
|
|
//#region src/strings/pointerdownEvent.ts
|
|
/**
|
|
* A global namespace for `pointerdown` event.
|
|
*/
|
|
const pointerdownEvent = "pointerdown";
|
|
//#endregion
|
|
//#region src/strings/pointerleaveEvent.ts
|
|
/**
|
|
* A global namespace for `pointerleave` event.
|
|
*/
|
|
const pointerleaveEvent = "pointerleave";
|
|
//#endregion
|
|
//#region src/strings/pointermoveEvent.ts
|
|
/**
|
|
* A global namespace for `pointermove` event.
|
|
*/
|
|
const pointermoveEvent = "pointermove";
|
|
//#endregion
|
|
//#region src/strings/pointerupEvent.ts
|
|
/**
|
|
* A global namespace for `pointerup` event.
|
|
*/
|
|
const pointerupEvent = "pointerup";
|
|
//#endregion
|
|
//#region src/strings/readystatechangeEvent.ts
|
|
/**
|
|
* A global namespace for `readystatechange` event.
|
|
*/
|
|
const readystatechangeEvent = "readystatechange";
|
|
//#endregion
|
|
//#region src/strings/resetEvent.ts
|
|
/**
|
|
* A global namespace for `reset` event.
|
|
*/
|
|
const resetEvent = "reset";
|
|
//#endregion
|
|
//#region src/strings/resizeEvent.ts
|
|
/**
|
|
* A global namespace for `resize` event.
|
|
*/
|
|
const resizeEvent = "resize";
|
|
//#endregion
|
|
//#region src/strings/selectEvent.ts
|
|
/**
|
|
* A global namespace for `select` event.
|
|
*/
|
|
const selectEvent = "select";
|
|
//#endregion
|
|
//#region src/strings/selectendEvent.ts
|
|
/**
|
|
* A global namespace for the `selectend` event.
|
|
*/
|
|
const selectendEvent = "selectend";
|
|
//#endregion
|
|
//#region src/strings/selectstartEvent.ts
|
|
/**
|
|
* A global namespace for the `selectstart` event.
|
|
*/
|
|
const selectstartEvent = "selectstart";
|
|
//#endregion
|
|
//#region src/strings/scrollEvent.ts
|
|
/**
|
|
* A global namespace for `scroll` event.
|
|
*/
|
|
const scrollEvent = "scroll";
|
|
//#endregion
|
|
//#region src/strings/submitEvent.ts
|
|
/**
|
|
* A global namespace for `submit` event.
|
|
*/
|
|
const submitEvent = "submit";
|
|
//#endregion
|
|
//#region src/strings/touchstartEvent.ts
|
|
/**
|
|
* A global namespace for `touchstart` event.
|
|
*/
|
|
const touchstartEvent = "touchstart";
|
|
//#endregion
|
|
//#region src/strings/touchmoveEvent.ts
|
|
/**
|
|
* A global namespace for `touchmove` event.
|
|
*/
|
|
const touchmoveEvent = "touchmove";
|
|
//#endregion
|
|
//#region src/strings/touchcancelEvent.ts
|
|
/**
|
|
* A global namespace for `touchcancel` event.
|
|
*/
|
|
const touchcancelEvent = "touchcancel";
|
|
//#endregion
|
|
//#region src/strings/touchendEvent.ts
|
|
/**
|
|
* A global namespace for `touchend` event.
|
|
*/
|
|
const touchendEvent = "touchend";
|
|
//#endregion
|
|
//#region src/strings/unloadEvent.ts
|
|
/**
|
|
* A global namespace for `unload` event.
|
|
*/
|
|
const unloadEvent = "unload";
|
|
//#endregion
|
|
//#region src/strings/nativeEvents.ts
|
|
/**
|
|
* A global namespace for all browser native events.
|
|
*/
|
|
const nativeEvents = {
|
|
DOMContentLoaded: DOMContentLoadedEvent,
|
|
DOMMouseScroll: DOMMouseScrollEvent,
|
|
abort: abortEvent,
|
|
beforeunload: beforeunloadEvent,
|
|
blur: blurEvent,
|
|
change: changeEvent,
|
|
click: mouseclickEvent,
|
|
contextmenu: contextmenuEvent,
|
|
dblclick: mousedblclickEvent,
|
|
error: errorEvent,
|
|
focus: focusEvent,
|
|
focusin: focusinEvent,
|
|
focusout: focusoutEvent,
|
|
gesturechange: gesturechangeEvent,
|
|
gestureend: gestureendEvent,
|
|
gesturestart: gesturestartEvent,
|
|
hover: mousehoverEvent,
|
|
keydown: keydownEvent,
|
|
keypress: keypressEvent,
|
|
keyup: keyupEvent,
|
|
load: loadEvent,
|
|
mousedown: mousedownEvent,
|
|
mousemove: mousemoveEvent,
|
|
mousein: mouseinEvent,
|
|
mouseout: mouseoutEvent,
|
|
mouseenter: mouseenterEvent,
|
|
mouseleave: mouseleaveEvent,
|
|
mouseover: mouseoverEvent,
|
|
mouseup: mouseupEvent,
|
|
mousewheel: mousewheelEvent,
|
|
move: moveEvent,
|
|
orientationchange: orientationchangeEvent,
|
|
pointercancel: pointercancelEvent,
|
|
pointerdown: pointerdownEvent,
|
|
pointerleave: pointerleaveEvent,
|
|
pointermove: pointermoveEvent,
|
|
pointerup: pointerupEvent,
|
|
readystatechange: readystatechangeEvent,
|
|
reset: resetEvent,
|
|
resize: resizeEvent,
|
|
scroll: scrollEvent,
|
|
select: selectEvent,
|
|
selectend: selectendEvent,
|
|
selectstart: selectstartEvent,
|
|
submit: submitEvent,
|
|
touchcancel: touchcancelEvent,
|
|
touchend: touchendEvent,
|
|
touchmove: touchmoveEvent,
|
|
touchstart: touchstartEvent,
|
|
unload: unloadEvent
|
|
};
|
|
//#endregion
|
|
//#region src/strings/dragEvent.ts
|
|
/**
|
|
* A global namespace for `drag` event.
|
|
*/
|
|
const dragEvent = "drag";
|
|
//#endregion
|
|
//#region src/strings/dragstartEvent.ts
|
|
/**
|
|
* A global namespace for `dragstart` event.
|
|
*/
|
|
const dragstartEvent = "dragstart";
|
|
//#endregion
|
|
//#region src/strings/dragenterEvent.ts
|
|
/**
|
|
* A global namespace for `dragenter` event.
|
|
*/
|
|
const dragenterEvent = "dragenter";
|
|
//#endregion
|
|
//#region src/strings/dragleaveEvent.ts
|
|
/**
|
|
* A global namespace for `dragleave` event.
|
|
*/
|
|
const dragleaveEvent = "dragleave";
|
|
//#endregion
|
|
//#region src/strings/dragoverEvent.ts
|
|
/**
|
|
* A global namespace for `dragover` event.
|
|
*/
|
|
const dragoverEvent = "dragover";
|
|
//#endregion
|
|
//#region src/strings/dragendEvent.ts
|
|
/**
|
|
* A global namespace for `dragend` event.
|
|
*/
|
|
const dragendEvent = "dragend";
|
|
//#endregion
|
|
//#region src/strings/loadstartEvent.ts
|
|
/**
|
|
* A global namespace for `loadstart` event.
|
|
*/
|
|
const loadstartEvent = "loadstart";
|
|
//#endregion
|
|
//#region src/strings/mouseSwipeEvents.ts
|
|
/**
|
|
* A global namespace for mouse events equivalent to touch events.
|
|
*/
|
|
const mouseSwipeEvents = {
|
|
start: "mousedown",
|
|
end: "mouseup",
|
|
move: "mousemove",
|
|
cancel: "mouseleave"
|
|
};
|
|
//#endregion
|
|
//#region src/strings/mouseClickEvents.ts
|
|
/**
|
|
* A global namespace for mouse click events.
|
|
*/
|
|
const mouseClickEvents = {
|
|
down: "mousedown",
|
|
up: "mouseup"
|
|
};
|
|
//#endregion
|
|
//#region src/strings/mouseHoverEvents.ts
|
|
/**
|
|
* A global namespace for mouse hover events.
|
|
*/
|
|
const mouseHoverEvents = "onmouseleave" in document ? ["mouseenter", "mouseleave"] : ["mouseover", "mouseout"];
|
|
//#endregion
|
|
//#region src/strings/touchEvents.ts
|
|
/**
|
|
* A global namespace for touch events.
|
|
*/
|
|
const touchEvents = {
|
|
start: "touchstart",
|
|
end: "touchend",
|
|
move: "touchmove",
|
|
cancel: "touchcancel"
|
|
};
|
|
//#endregion
|
|
//#region src/strings/focusEvents.ts
|
|
/**
|
|
* A global namespace for focus event names.
|
|
*/
|
|
const focusEvents = {
|
|
in: "focusin",
|
|
out: "focusout"
|
|
};
|
|
//#endregion
|
|
//#region src/strings/focusableSelector.ts
|
|
const focusableSelector = "a[href], button, input, textarea, select, details, [tabindex]:not([tabindex=\"-1\"]";
|
|
//#endregion
|
|
//#region src/strings/keyboardEventKeys.ts
|
|
/**
|
|
* A global namespace for keyboard event keys.
|
|
*/
|
|
const keyboardEventKeys = {
|
|
Backspace: "Backspace",
|
|
Tab: "Tab",
|
|
Enter: "Enter",
|
|
Shift: "Shift",
|
|
Control: "Control",
|
|
Alt: "Alt",
|
|
Pause: "Pause",
|
|
CapsLock: "CapsLock",
|
|
Escape: "Escape",
|
|
Scape: "Space",
|
|
ArrowLeft: "ArrowLeft",
|
|
ArrowUp: "ArrowUp",
|
|
ArrowRight: "ArrowRight",
|
|
ArrowDown: "ArrowDown",
|
|
Insert: "Insert",
|
|
Delete: "Delete",
|
|
Meta: "Meta",
|
|
ContextMenu: "ContextMenu",
|
|
ScrollLock: "ScrollLock"
|
|
};
|
|
//#endregion
|
|
//#region src/strings/keyAlt.ts
|
|
/**
|
|
* A global namespace for `Alt` key.
|
|
* e.which = 18
|
|
*/
|
|
const keyAlt = "Alt";
|
|
//#endregion
|
|
//#region src/strings/keyArrowDown.ts
|
|
/**
|
|
* A global namespace for `ArrowDown` key.
|
|
* e.which = 40 equivalent
|
|
*/
|
|
const keyArrowDown = "ArrowDown";
|
|
//#endregion
|
|
//#region src/strings/keyArrowUp.ts
|
|
/**
|
|
* A global namespace for `ArrowUp` key.
|
|
* e.which = 38 equivalent
|
|
*/
|
|
const keyArrowUp = "ArrowUp";
|
|
//#endregion
|
|
//#region src/strings/keyArrowLeft.ts
|
|
/**
|
|
* A global namespace for `ArrowLeft` key.
|
|
* e.which = 37 equivalent
|
|
*/
|
|
const keyArrowLeft = "ArrowLeft";
|
|
//#endregion
|
|
//#region src/strings/keyArrowRight.ts
|
|
/**
|
|
* A global namespace for `ArrowRight` key.
|
|
* e.which = 39 equivalent
|
|
*/
|
|
const keyArrowRight = "ArrowRight";
|
|
//#endregion
|
|
//#region src/strings/keyBackspace.ts
|
|
/**
|
|
* A global namespace for `Backspace` key.
|
|
* e.which === 8 equivalent
|
|
*/
|
|
const keyBackspace = "Backspace";
|
|
//#endregion
|
|
//#region src/strings/keyCapsLock.ts
|
|
/**
|
|
* A global namespace for `CapsLock` key.
|
|
* e.which = 20 equivalent
|
|
*/
|
|
const keyCapsLock = "CapsLock";
|
|
//#endregion
|
|
//#region src/strings/keyControl.ts
|
|
/**
|
|
* A global namespace for `Control` key.
|
|
* e.which = 17
|
|
*/
|
|
const keyControl = "Control";
|
|
//#endregion
|
|
//#region src/strings/keyDelete.ts
|
|
/**
|
|
* A global namespace for `Delete` key.
|
|
* e.which = 46 equivalent
|
|
*/
|
|
const keyDelete = "Delete";
|
|
//#endregion
|
|
//#region src/strings/keyEnter.ts
|
|
/**
|
|
* A global namespace for `Enter` key.
|
|
* e.which = 13 equivalent
|
|
*/
|
|
const keyEnter = "Enter";
|
|
//#endregion
|
|
//#region src/strings/keyNumpadEnter.ts
|
|
/**
|
|
* A global namespace for `Enter` key.
|
|
* e.which = 13 equivalent
|
|
*/
|
|
const keyNumpadEnter = "NumpadEnter";
|
|
//#endregion
|
|
//#region src/strings/keyEscape.ts
|
|
/**
|
|
* A global namespace for `Escape` key.
|
|
* e.which = 27 equivalent
|
|
*/
|
|
const keyEscape = "Escape";
|
|
//#endregion
|
|
//#region src/strings/keyInsert.ts
|
|
/**
|
|
* A global namespace for `Insert` key.
|
|
* e.which = 45 equivalent
|
|
*/
|
|
const keyInsert = "Insert";
|
|
//#endregion
|
|
//#region src/strings/keyMeta.ts
|
|
/**
|
|
* A global namespace for `Meta` key.
|
|
* e.which = 93 equivalent
|
|
*/
|
|
const keyMeta = "Meta";
|
|
//#endregion
|
|
//#region src/strings/keyPause.ts
|
|
/**
|
|
* A global namespace for `Pause` key.
|
|
* e.which = 19
|
|
*/
|
|
const keyPause = "Pause";
|
|
//#endregion
|
|
//#region src/strings/keyScrollLock.ts
|
|
/**
|
|
* A global namespace for `ScrollLock` key.
|
|
* e.which = 145 equivalent
|
|
*/
|
|
const keyScrollLock = "ScrollLock";
|
|
//#endregion
|
|
//#region src/strings/keyShift.ts
|
|
/**
|
|
* A global namespace for `Shift` key.
|
|
* e.which = 16
|
|
*/
|
|
const keyShift = "Shift";
|
|
//#endregion
|
|
//#region src/strings/keySpace.ts
|
|
/**
|
|
* A global namespace for `Space` key.
|
|
* e.which = 32 equivalent
|
|
*/
|
|
const keySpace = "Space";
|
|
//#endregion
|
|
//#region src/strings/keyTab.ts
|
|
/**
|
|
* A global namespace for `Tab` key.
|
|
* e.which = 9 equivalent
|
|
*/
|
|
const keyTab = "Tab";
|
|
//#endregion
|
|
//#region src/strings/animationDuration.ts
|
|
/**
|
|
* A global namespace for 'animationDuration' string.
|
|
*/
|
|
const animationDuration = "animationDuration";
|
|
//#endregion
|
|
//#region src/strings/animationDelay.ts
|
|
/**
|
|
* A global namespace for 'animationDelay' string.
|
|
*/
|
|
const animationDelay = "animationDelay";
|
|
//#endregion
|
|
//#region src/strings/animationName.ts
|
|
/**
|
|
* A global namespace for 'animationName' string.
|
|
*/
|
|
const animationName = "animationName";
|
|
//#endregion
|
|
//#region src/strings/animationEndEvent.ts
|
|
/**
|
|
* A global namespace for 'animationend' string.
|
|
*/
|
|
const animationEndEvent = "animationend";
|
|
//#endregion
|
|
//#region src/strings/transitionDuration.ts
|
|
/**
|
|
* A global namespace for 'transitionDuration' string.
|
|
*/
|
|
const transitionDuration = "transitionDuration";
|
|
//#endregion
|
|
//#region src/strings/transitionDelay.ts
|
|
/**
|
|
* A global namespace for 'transitionDelay' string.
|
|
*/
|
|
const transitionDelay = "transitionDelay";
|
|
//#endregion
|
|
//#region src/strings/transitionEndEvent.ts
|
|
/**
|
|
* A global namespace for 'transitionend' string.
|
|
*/
|
|
const transitionEndEvent = "transitionend";
|
|
//#endregion
|
|
//#region src/strings/transitionProperty.ts
|
|
/**
|
|
* A global namespace for `transitionProperty` string for modern browsers.
|
|
*/
|
|
const transitionProperty = "transitionProperty";
|
|
//#endregion
|
|
//#region src/strings/addEventListener.ts
|
|
/**
|
|
* A global namespace for 'addEventListener' string.
|
|
*/
|
|
const addEventListener = "addEventListener";
|
|
//#endregion
|
|
//#region src/strings/removeEventListener.ts
|
|
/**
|
|
* A global namespace for 'removeEventListener' string.
|
|
*/
|
|
const removeEventListener = "removeEventListener";
|
|
//#endregion
|
|
//#region src/strings/bezierEasings.ts
|
|
/**
|
|
* A global namespace for predefined
|
|
* CSS3 'cubic-bezier()' easing functions.
|
|
*/
|
|
const bezierEasings = {
|
|
linear: "linear",
|
|
easingSinusoidalIn: "cubic-bezier(0.47,0,0.745,0.715)",
|
|
easingSinusoidalOut: "cubic-bezier(0.39,0.575,0.565,1)",
|
|
easingSinusoidalInOut: "cubic-bezier(0.445,0.05,0.55,0.95)",
|
|
easingQuadraticIn: "cubic-bezier(0.550,0.085,0.680,0.530)",
|
|
easingQuadraticOut: "cubic-bezier(0.250,0.460,0.450,0.940)",
|
|
easingQuadraticInOut: "cubic-bezier(0.455,0.030,0.515,0.955)",
|
|
easingCubicIn: "cubic-bezier(0.55,0.055,0.675,0.19)",
|
|
easingCubicOut: "cubic-bezier(0.215,0.61,0.355,1)",
|
|
easingCubicInOut: "cubic-bezier(0.645,0.045,0.355,1)",
|
|
easingQuarticIn: "cubic-bezier(0.895,0.03,0.685,0.22)",
|
|
easingQuarticOut: "cubic-bezier(0.165,0.84,0.44,1)",
|
|
easingQuarticInOut: "cubic-bezier(0.77,0,0.175,1)",
|
|
easingQuinticIn: "cubic-bezier(0.755,0.05,0.855,0.06)",
|
|
easingQuinticOut: "cubic-bezier(0.23,1,0.32,1)",
|
|
easingQuinticInOut: "cubic-bezier(0.86,0,0.07,1)",
|
|
easingExponentialIn: "cubic-bezier(0.95,0.05,0.795,0.035)",
|
|
easingExponentialOut: "cubic-bezier(0.19,1,0.22,1)",
|
|
easingExponentialInOut: "cubic-bezier(1,0,0,1)",
|
|
easingCircularIn: "cubic-bezier(0.6,0.04,0.98,0.335)",
|
|
easingCircularOut: "cubic-bezier(0.075,0.82,0.165,1)",
|
|
easingCircularInOut: "cubic-bezier(0.785,0.135,0.15,0.86)",
|
|
easingBackIn: "cubic-bezier(0.6,-0.28,0.735,0.045)",
|
|
easingBackOut: "cubic-bezier(0.175,0.885,0.32,1.275)",
|
|
easingBackInOut: "cubic-bezier(0.68,-0.55,0.265,1.55)"
|
|
};
|
|
//#endregion
|
|
//#region src/strings/offsetHeight.ts
|
|
/**
|
|
* A global namespace for `offsetHeight` property.
|
|
*/
|
|
const offsetHeight = "offsetHeight";
|
|
//#endregion
|
|
//#region src/strings/offsetWidth.ts
|
|
/**
|
|
* A global namespace for `offsetWidth` property.
|
|
*/
|
|
const offsetWidth = "offsetWidth";
|
|
//#endregion
|
|
//#region src/strings/scrollHeight.ts
|
|
/**
|
|
* A global namespace for `scrollHeight` property.
|
|
*/
|
|
const scrollHeight = "scrollHeight";
|
|
//#endregion
|
|
//#region src/strings/scrollWidth.ts
|
|
/**
|
|
* A global namespace for `scrollWidth` property.
|
|
*/
|
|
const scrollWidth = "scrollWidth";
|
|
//#endregion
|
|
//#region src/strings/tabindex.ts
|
|
/**
|
|
* A global namespace for `touchcancel` event.
|
|
*/
|
|
const tabindex = "tabindex";
|
|
//#endregion
|
|
//#region src/strings/userAgentData.ts
|
|
/**
|
|
* A global namespace for `userAgentData` object.
|
|
*/
|
|
const userAgentData = navigator.userAgentData;
|
|
//#endregion
|
|
//#region src/strings/userAgent.ts
|
|
const { userAgent: userAgentString } = navigator;
|
|
/**
|
|
* A global namespace for `navigator.userAgent` string.
|
|
*/
|
|
const userAgent = userAgentString;
|
|
//#endregion
|
|
//#region src/boolean/isMobile.ts
|
|
/**
|
|
* An accessor that checks for mobile detection.
|
|
*/
|
|
const isMobile = () => {
|
|
const mobileBrands = /iPhone|iPad|iPod|Android/i;
|
|
return navigator?.userAgentData?.brands.some((x) => mobileBrands.test(x.brand)) || mobileBrands.test(navigator?.userAgent) || false;
|
|
};
|
|
//#endregion
|
|
//#region src/boolean/isApple.ts
|
|
/**
|
|
* An accessor that checks for Apple browsers.
|
|
*/
|
|
const isApple = () => {
|
|
const appleBrands = /(iPhone|iPod|iPad)/;
|
|
return navigator?.userAgentData?.brands.some((x) => appleBrands.test(x.brand)) || appleBrands.test(navigator?.userAgent) || false;
|
|
};
|
|
//#endregion
|
|
//#region src/boolean/isFirefox.ts
|
|
/**
|
|
* An accessor that checks for Gecko browsers. When writing this file,
|
|
* Gecko was not supporting `userAgentData`.
|
|
*/
|
|
const isFirefox = () => navigator?.userAgent?.includes("Firefox") || false;
|
|
//#endregion
|
|
//#region src/boolean/isWebKit.ts
|
|
const isWebKit = () => {
|
|
if (typeof CSS === "undefined" || !CSS.supports) return false;
|
|
return CSS.supports("-webkit-backdrop-filter", "none");
|
|
};
|
|
//#endregion
|
|
//#region src/boolean/support3DTransform.ts
|
|
/**
|
|
* An accessor that checks for CSS3 3D transform support.
|
|
*/
|
|
const support3DTransform = () => ["webkitPerspective", "perspective"].some((p) => p in document.head.style);
|
|
//#endregion
|
|
//#region src/misc/noop.ts
|
|
/** A generic function with empty body. */
|
|
const noop = () => {};
|
|
//#endregion
|
|
//#region src/event/on.ts
|
|
/**
|
|
* Add eventListener to an `EventTarget` object.
|
|
*/
|
|
const on = (element, eventName, listener, options) => {
|
|
const ops = options || false;
|
|
element.addEventListener(eventName, listener, ops);
|
|
};
|
|
//#endregion
|
|
//#region src/event/off.ts
|
|
/**
|
|
* Remove eventListener from an `EventTarget` object.
|
|
*/
|
|
const off = (element, eventName, listener, options) => {
|
|
const ops = options || false;
|
|
element.removeEventListener(eventName, listener, ops);
|
|
};
|
|
//#endregion
|
|
//#region src/event/one.ts
|
|
/**
|
|
* Add an `eventListener` to an `EventTarget`
|
|
* element and remove it once callback is called.
|
|
*/
|
|
const one = (element, eventName, listener, options) => {
|
|
/** Wrap the listener for easy on -> off */
|
|
const handlerWrapper = (e) => {
|
|
if (e.target === element || e.currentTarget === element) {
|
|
listener.apply(element, [e]);
|
|
off(element, eventName, handlerWrapper, options);
|
|
}
|
|
};
|
|
on(element, eventName, handlerWrapper, options);
|
|
};
|
|
//#endregion
|
|
//#region src/boolean/supportPassive.ts
|
|
/**
|
|
* An accessor that checks for passive events support,
|
|
* in general event options are not suited for scroll prevention.
|
|
*
|
|
* @see https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
|
|
*/
|
|
const supportPassive = () => {
|
|
let result = false;
|
|
try {
|
|
const opts = Object.defineProperty({}, "passive", { get: () => {
|
|
result = true;
|
|
return result;
|
|
} });
|
|
one(document, DOMContentLoadedEvent, noop, opts);
|
|
} catch (_e) {}
|
|
return result;
|
|
};
|
|
//#endregion
|
|
//#region src/boolean/supportTransform.ts
|
|
/**
|
|
* An accessor that checks for CSS3 transform support.
|
|
*/
|
|
const supportTransform = () => ["webkitTransform", "transform"].some((p) => p in document.head.style);
|
|
//#endregion
|
|
//#region src/boolean/supportTouch.ts
|
|
/**
|
|
* An accessor that checks for touch events support.
|
|
*/
|
|
const supportTouch = () => "ontouchstart" in window || "msMaxTouchPoints" in navigator;
|
|
//#endregion
|
|
//#region src/boolean/supportAnimation.ts
|
|
/**
|
|
* An accessor that checks for CSS3 animation support.
|
|
*/
|
|
const supportAnimation = () => ["webkitAnimation", "animation"].some((p) => p in document.head.style);
|
|
//#endregion
|
|
//#region src/boolean/supportTransition.ts
|
|
/**
|
|
* An accessor that checks for CSS3 transition support.
|
|
*/
|
|
const supportTransition = () => ["webkitTransition", "transition"].some((p) => p in document.head.style);
|
|
//#endregion
|
|
//#region src/attr/getAttribute.ts
|
|
/**
|
|
* Shortcut for `Element.getAttribute()` method.
|
|
*
|
|
* @param element target element
|
|
* @param att attribute name
|
|
* @returns attribute value
|
|
*/
|
|
const getAttribute = (element, att) => element.getAttribute(att);
|
|
//#endregion
|
|
//#region src/attr/getAttributeNS.ts
|
|
/**
|
|
* Shortcut for `Element.getAttributeNS()` method.
|
|
*
|
|
* @param ns attribute namespace
|
|
* @param element target element
|
|
* @param att attribute name
|
|
* @returns attribute value
|
|
*/
|
|
const getAttributeNS = (ns, element, att) => element.getAttributeNS(ns, att);
|
|
//#endregion
|
|
//#region src/attr/hasAttribute.ts
|
|
/**
|
|
* Shortcut for `Element.hasAttribute()` method.
|
|
*
|
|
* @param element target element
|
|
* @param att attribute name
|
|
* @returns the query result
|
|
*/
|
|
const hasAttribute = (element, att) => element.hasAttribute(att);
|
|
//#endregion
|
|
//#region src/attr/hasAttributeNS.ts
|
|
/**
|
|
* Shortcut for `Element.hasAttributeNS()` method.
|
|
*
|
|
* @param ns attribute namespace
|
|
* @param element target element
|
|
* @param att attribute name
|
|
* @returns the query result
|
|
*/
|
|
const hasAttributeNS = (ns, element, att) => element.hasAttributeNS(ns, att);
|
|
//#endregion
|
|
//#region src/attr/setAttribute.ts
|
|
/**
|
|
* Shortcut for `Element.setAttribute()` method.
|
|
*
|
|
* @param element target element
|
|
* @param att attribute name
|
|
* @param value attribute value
|
|
*/
|
|
const setAttribute = (element, att, value) => element.setAttribute(att, value);
|
|
//#endregion
|
|
//#region src/attr/setAttributeNS.ts
|
|
/**
|
|
* Shortcut for `Element.setAttributeNS()` method.
|
|
*
|
|
* @param ns attribute namespace
|
|
* @param element target element
|
|
* @param att attribute name
|
|
* @param value attribute value
|
|
*/
|
|
const setAttributeNS = (ns, element, att, value) => element.setAttributeNS(ns, att, value);
|
|
//#endregion
|
|
//#region src/attr/removeAttribute.ts
|
|
/**
|
|
* Shortcut for `Element.removeAttribute()` method.
|
|
*
|
|
* @param element target element
|
|
* @param att attribute name
|
|
*/
|
|
const removeAttribute = (element, att) => element.removeAttribute(att);
|
|
//#endregion
|
|
//#region src/attr/removeAttributeNS.ts
|
|
/**
|
|
* Shortcut for `Element.removeAttributeNS()` method.
|
|
*
|
|
* @param ns attribute namespace
|
|
* @param element target element
|
|
* @param att attribute name
|
|
*/
|
|
const removeAttributeNS = (ns, element, att) => element.removeAttributeNS(ns, att);
|
|
//#endregion
|
|
//#region src/class/addClass.ts
|
|
/**
|
|
* Add one or more CSS classes to `Element.classList`.
|
|
*
|
|
* @param element target
|
|
* @param classNAME to add
|
|
*/
|
|
const addClass = (element, ...classNAME) => {
|
|
element.classList.add(...classNAME);
|
|
};
|
|
//#endregion
|
|
//#region src/class/removeClass.ts
|
|
/**
|
|
* Remove one or more classes from `Element.classList`.
|
|
*
|
|
* @param element target
|
|
* @param classNAME to remove
|
|
*/
|
|
const removeClass = (element, ...classNAME) => {
|
|
element.classList.remove(...classNAME);
|
|
};
|
|
//#endregion
|
|
//#region src/class/hasClass.ts
|
|
/**
|
|
* Check class in `Element.classList`.
|
|
*
|
|
* @param element target
|
|
* @param classNAME to check
|
|
*/
|
|
const hasClass = (element, classNAME) => {
|
|
return element.classList.contains(classNAME);
|
|
};
|
|
//#endregion
|
|
//#region src/blocks/documentBody.ts
|
|
/**
|
|
* A global namespace for `document.body`.
|
|
*/
|
|
const { body: documentBody } = document;
|
|
//#endregion
|
|
//#region src/blocks/documentElement.ts
|
|
/**
|
|
* A global namespace for `document.documentElement` or the `<HTML>`.
|
|
*/
|
|
const { documentElement } = document;
|
|
//#endregion
|
|
//#region src/blocks/documentHead.ts
|
|
/**
|
|
* A global namespace for `document.head`.
|
|
*/
|
|
const { head: documentHead } = document;
|
|
//#endregion
|
|
//#region src/misc/ArrayFrom.ts
|
|
/**
|
|
* Shortie for `Array.from()` static method.
|
|
* The utility should also work with any typed arrays
|
|
* like Float64Array or Int32Array.
|
|
*
|
|
* @param arr array-like iterable object
|
|
* @returns a new array from iterable object
|
|
*/
|
|
const ArrayFrom = (arr) => Array.from(arr);
|
|
//#endregion
|
|
//#region src/is/isObject.ts
|
|
/**
|
|
* Checks if a value is an `Object`.
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isObject = (obj) => obj !== null && obj !== void 0 && typeof obj === "object" || false;
|
|
//#endregion
|
|
//#region src/is/isNode.ts
|
|
/**
|
|
* Checks if an object is a `Node`.
|
|
*
|
|
* @param node the target object
|
|
* @see https://dom.spec.whatwg.org/#node
|
|
*
|
|
* ```
|
|
* ELEMENT_NODE = 1;
|
|
* ATTRIBUTE_NODE = 2;
|
|
* TEXT_NODE = 3;
|
|
* CDATA_SECTION_NODE = 4;
|
|
* ENTITY_REFERENCE_NODE = 5; // legacy
|
|
* ENTITY_NODE = 6; // legacy
|
|
* PROCESSING_INSTRUCTION_NODE = 7;
|
|
* COMMENT_NODE = 8;
|
|
* DOCUMENT_NODE = 9;
|
|
* DOCUMENT_TYPE_NODE = 10;
|
|
* DOCUMENT_FRAGMENT_NODE = 11;
|
|
* @returns the query result
|
|
*/
|
|
const isNode = (node) => isObject(node) && typeof node.nodeType === "number" && [
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
9,
|
|
10,
|
|
11
|
|
].some((x) => node.nodeType === x) || false;
|
|
//#endregion
|
|
//#region src/is/isElement.ts
|
|
/**
|
|
* Checks if an object is an `Element`.
|
|
*
|
|
* @param element the target object
|
|
* @returns the query result
|
|
*/
|
|
const isElement = (element) => isNode(element) && element.nodeType === 1 || false;
|
|
//#endregion
|
|
//#region src/misc/data.ts
|
|
const componentData = /* @__PURE__ */ new Map();
|
|
/**
|
|
* An interface for web components background data.
|
|
*
|
|
* @see https://github.com/thednp/bootstrap.native/blob/master/src/components/base-component.js
|
|
*/
|
|
const Data = {
|
|
data: componentData,
|
|
set: (element, component, instance) => {
|
|
if (!isElement(element)) return;
|
|
if (!componentData.has(component)) componentData.set(component, /* @__PURE__ */ new Map());
|
|
componentData.get(component).set(element, instance);
|
|
},
|
|
getAllFor: (component) => {
|
|
return componentData.get(component) || null;
|
|
},
|
|
get: (element, component) => {
|
|
if (!isElement(element) || !component) return null;
|
|
const instanceMap = Data.getAllFor(component);
|
|
return element && instanceMap && instanceMap.get(element) || null;
|
|
},
|
|
remove: (element, component) => {
|
|
const instanceMap = Data.getAllFor(component);
|
|
if (!instanceMap || !isElement(element)) return;
|
|
instanceMap.delete(element);
|
|
if (instanceMap.size === 0) componentData.delete(component);
|
|
}
|
|
};
|
|
//#endregion
|
|
//#region src/misc/getInstance.ts
|
|
/**
|
|
* An alias for `Data.get()`.
|
|
*/
|
|
const getInstance = (target, component) => Data.get(target, component);
|
|
//#endregion
|
|
//#region src/misc/capitalize.ts
|
|
/**
|
|
* Capitalize first character in a string.
|
|
* @param input source string
|
|
*/
|
|
const capitalize = (input) => input?.charAt(0).toUpperCase() + input?.slice(1);
|
|
//#endregion
|
|
//#region src/misc/camelCase.ts
|
|
/**
|
|
* Transform a string to camel case.
|
|
* @param input source string
|
|
*/
|
|
const camelCase = (input) => input?.trim().replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => index === 0 ? word.toLowerCase() : word.toUpperCase()).replace(/\s+/g, "");
|
|
//#endregion
|
|
//#region src/is/isString.ts
|
|
/**
|
|
* Shortie for `typeof SOMETHING === "string"`.
|
|
*
|
|
* @param str input value
|
|
* @returns the query result
|
|
*/
|
|
const isString = (str) => typeof str === "string" || false;
|
|
//#endregion
|
|
//#region src/is/isWindow.ts
|
|
/**
|
|
* Check if a target object is `Window`.
|
|
* => equivalent to `object instanceof Window`
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isWindow = (obj) => isObject(obj) && obj.constructor.name === "Window" || false;
|
|
//#endregion
|
|
//#region src/is/isDocument.ts
|
|
/**
|
|
* Checks if an object is a `Document`.
|
|
*
|
|
* @see https://dom.spec.whatwg.org/#node
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isDocument = (obj) => isNode(obj) && obj.nodeType === 9 || false;
|
|
//#endregion
|
|
//#region src/get/getDocument.ts
|
|
/**
|
|
* Returns the `document` or the `#document` element.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param node the reference node
|
|
* @returns the parent document of the given node
|
|
*/
|
|
const getDocument = (node) => {
|
|
if (isDocument(node)) return node;
|
|
if (isNode(node)) return node.ownerDocument;
|
|
if (isWindow(node)) return node.document;
|
|
return globalThis.document;
|
|
};
|
|
//#endregion
|
|
//#region src/misc/ObjectAssign.ts
|
|
/**
|
|
* Shortcut for `Object.assign()` static method.
|
|
*
|
|
* @param obj a target object
|
|
* @param source source object(s)
|
|
* @see https://github.com/devinrhode2/ObjectTyped/blob/master/src/index.ts
|
|
*/
|
|
const ObjectAssign = (obj, ...source) => Object.assign(obj, ...source);
|
|
//#endregion
|
|
//#region src/misc/createElement.ts
|
|
/**
|
|
* Shortie for `document.createElement` method
|
|
* which allows you to create a new `HTMLElement` for a given `tagName`
|
|
* or based on an object with specific non-readonly attributes with string values:
|
|
* `id`, `className`, `textContent`, `style`, etc.
|
|
*
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
|
|
*
|
|
* @param param `tagName` or object
|
|
* @return a new `HTMLElement`
|
|
*/
|
|
const createElement = (param) => {
|
|
if (!param) return void 0;
|
|
if (isString(param)) return getDocument().createElement(param);
|
|
const { tagName } = param;
|
|
const newElement = createElement(tagName);
|
|
if (!newElement) return void 0;
|
|
const attr = { ...param };
|
|
delete attr.tagName;
|
|
return ObjectAssign(newElement, attr);
|
|
};
|
|
//#endregion
|
|
//#region src/misc/createElementNS.ts
|
|
/**
|
|
* Shortie for `document.createElementNS` method
|
|
* which allows you to create a new `Element` for a given `tagName`
|
|
* or based on an object with specific non-readonly attributes with string values:
|
|
* `id`, `className`, `textContent`, `style`, etc.
|
|
* Note: some elements resulted from this function call may not be compatible with
|
|
* some attributes.
|
|
*
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
|
|
*
|
|
* @param ns `namespaceURI` to associate with the new `Element`
|
|
* @param param `tagName` or object
|
|
* @return a new `Element`
|
|
*/
|
|
const createElementNS = (ns, param) => {
|
|
if (!ns || !param) return void 0;
|
|
if (isString(param)) return getDocument().createElementNS(ns, param);
|
|
const { tagName } = param;
|
|
const newElement = createElementNS(ns, tagName);
|
|
if (!newElement) return void 0;
|
|
const attr = { ...param };
|
|
delete attr.tagName;
|
|
return ObjectAssign(newElement, attr);
|
|
};
|
|
//#endregion
|
|
//#region src/misc/dispatchEvent.ts
|
|
/**
|
|
* Shortcut for the `Element.dispatchEvent(Event)` method.
|
|
*
|
|
* @param element is the target
|
|
* @param event is the `Event` object
|
|
*/
|
|
const dispatchEvent = (element, event) => element.dispatchEvent(event);
|
|
//#endregion
|
|
//#region src/misc/distinct.ts
|
|
/**
|
|
* JavaScript `Array` distinct.
|
|
*
|
|
* @see https://codeburst.io/javascript-array-distinct-5edc93501dc4
|
|
*
|
|
* @example
|
|
* ```
|
|
* [0,1,1,2].filter(distinct)
|
|
* // => [0,1,2]
|
|
* ```
|
|
* @param value array item value
|
|
* @param index array item index
|
|
* @param arr a clone of the target array
|
|
* @returns the query result
|
|
*/
|
|
const distinct = (value, index, arr) => arr.indexOf(value) === index;
|
|
//#endregion
|
|
//#region src/get/getElementStyle.ts
|
|
/**
|
|
* Shortcut for `window.getComputedStyle(element).propertyName`
|
|
* static method.
|
|
*
|
|
* * If `element` parameter is not an `Element`, `getComputedStyle`
|
|
* throws a `ReferenceError`.
|
|
*
|
|
* @param element target `Element`
|
|
* @param property the css property
|
|
* @param pseudoElt pseudo-elements
|
|
* @return the css property value
|
|
*/
|
|
const getElementStyle = (element, property, pseudoElt) => {
|
|
const computedStyle = getComputedStyle(element, pseudoElt);
|
|
const prop = property.replace("webkit", "Webkit").replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
return computedStyle.getPropertyValue(prop);
|
|
};
|
|
//#endregion
|
|
//#region src/get/getElementAnimationDelay.ts
|
|
/**
|
|
* Utility to get the computed `animationDelay`
|
|
* from Element in miliseconds.
|
|
*
|
|
* @param element target
|
|
* @return the `animationDelay` value in miliseconds
|
|
*/
|
|
const getElementAnimationDelay = (element) => {
|
|
const propertyValue = getElementStyle(element, animationName);
|
|
const durationValue = getElementStyle(element, animationDelay);
|
|
const durationScale = durationValue.includes("ms") ? 1 : 1e3;
|
|
const duration = propertyValue && propertyValue !== "none" ? parseFloat(durationValue) * durationScale : 0;
|
|
return !Number.isNaN(duration) ? duration : 0;
|
|
};
|
|
//#endregion
|
|
//#region src/get/getElementAnimationDuration.ts
|
|
/**
|
|
* Utility to get the computed `animationDuration`
|
|
* from `Element` in miliseconds.
|
|
*
|
|
* @param element target
|
|
* @return the `animationDuration` value in miliseconds
|
|
*/
|
|
const getElementAnimationDuration = (element) => {
|
|
const propertyValue = getElementStyle(element, animationName);
|
|
const durationValue = getElementStyle(element, animationDuration);
|
|
const durationScale = durationValue.includes("ms") ? 1 : 1e3;
|
|
const duration = propertyValue && propertyValue !== "none" ? parseFloat(durationValue) * durationScale : 0;
|
|
return !Number.isNaN(duration) ? duration : 0;
|
|
};
|
|
//#endregion
|
|
//#region src/misc/emulateAnimationEnd.ts
|
|
/**
|
|
* Utility to make sure callbacks are consistently
|
|
* called when animation ends.
|
|
*
|
|
* @param element target
|
|
* @param handler `animationend` callback
|
|
*/
|
|
const emulateAnimationEnd = (element, handler) => {
|
|
let called = 0;
|
|
const endEvent = new Event(animationEndEvent);
|
|
const duration = getElementAnimationDuration(element);
|
|
const delay = getElementAnimationDelay(element);
|
|
if (duration) {
|
|
const animationEndWrapper = (e) => {
|
|
if (e.target === element) {
|
|
handler.apply(element, [e]);
|
|
element.removeEventListener(animationEndEvent, animationEndWrapper);
|
|
called = 1;
|
|
}
|
|
};
|
|
element.addEventListener(animationEndEvent, animationEndWrapper);
|
|
setTimeout(() => {
|
|
if (!called) dispatchEvent(element, endEvent);
|
|
}, duration + delay + 17);
|
|
} else handler.apply(element, [endEvent]);
|
|
};
|
|
//#endregion
|
|
//#region src/get/getElementTransitionDelay.ts
|
|
/**
|
|
* Utility to get the computed `transitionDelay`
|
|
* from Element in miliseconds.
|
|
*
|
|
* @param element target
|
|
* @return the `transitionDelay` value in miliseconds
|
|
*/
|
|
const getElementTransitionDelay = (element) => {
|
|
const propertyValue = getElementStyle(element, transitionProperty);
|
|
const delayValue = getElementStyle(element, transitionDelay);
|
|
const delayScale = delayValue.includes("ms") ? 1 : 1e3;
|
|
const duration = propertyValue && propertyValue !== "none" ? parseFloat(delayValue) * delayScale : 0;
|
|
return !Number.isNaN(duration) ? duration : 0;
|
|
};
|
|
//#endregion
|
|
//#region src/get/getElementTransitionDuration.ts
|
|
/**
|
|
* Utility to get the computed `transitionDuration`
|
|
* from Element in miliseconds.
|
|
*
|
|
* @param element target
|
|
* @return the `transitionDuration` value in miliseconds
|
|
*/
|
|
const getElementTransitionDuration = (element) => {
|
|
const propertyValue = getElementStyle(element, transitionProperty);
|
|
const durationValue = getElementStyle(element, transitionDuration);
|
|
const durationScale = durationValue.includes("ms") ? 1 : 1e3;
|
|
const duration = propertyValue && propertyValue !== "none" ? parseFloat(durationValue) * durationScale : 0;
|
|
return !Number.isNaN(duration) ? duration : 0;
|
|
};
|
|
//#endregion
|
|
//#region src/misc/emulateTransitionEnd.ts
|
|
/**
|
|
* Utility to make sure callbacks are consistently
|
|
* called when transition ends.
|
|
*
|
|
* @param element element target
|
|
* @param handler `transitionend` callback
|
|
*/
|
|
const emulateTransitionEnd = (element, handler) => {
|
|
let called = 0;
|
|
const endEvent = new Event(transitionEndEvent);
|
|
const duration = getElementTransitionDuration(element);
|
|
const delay = getElementTransitionDelay(element);
|
|
if (duration) {
|
|
const transitionEndWrapper = (e) => {
|
|
if (e.target === element) {
|
|
handler.apply(element, [e]);
|
|
element.removeEventListener(transitionEndEvent, transitionEndWrapper);
|
|
called = 1;
|
|
}
|
|
};
|
|
element.addEventListener(transitionEndEvent, transitionEndWrapper);
|
|
setTimeout(() => {
|
|
if (!called) dispatchEvent(element, endEvent);
|
|
}, duration + delay + 17);
|
|
} else handler.apply(element, [endEvent]);
|
|
};
|
|
//#endregion
|
|
//#region src/misc/Float32ArrayFrom.ts
|
|
/**
|
|
* Shortcut for `Float32Array.from()` static method.
|
|
*
|
|
* @param arr array-like iterable object
|
|
* @returns a new Float32Array
|
|
*/
|
|
const Float32ArrayFrom = (arr) => Float32Array.from(Array.from(arr));
|
|
//#endregion
|
|
//#region src/misc/Float64ArrayFrom.ts
|
|
/**
|
|
* Shortcut for `Float64Array.from()` static method.
|
|
*
|
|
* @param arr array-like iterable object
|
|
* @returns a new Float64Array
|
|
*/
|
|
const Float64ArrayFrom = (arr) => Float64Array.from(Array.from(arr));
|
|
//#endregion
|
|
//#region src/misc/focus.ts
|
|
/**
|
|
* Shortie for `HTMLOrSVGElement.focus()` method.
|
|
*
|
|
* @param element is the target
|
|
* @param options allows to pass additional options such as `preventScroll: boolean`
|
|
*/
|
|
const focus = (element, options) => element.focus(options);
|
|
//#endregion
|
|
//#region src/misc/kebabCase.ts
|
|
/**
|
|
* Transform a string to kebab case.
|
|
* @param input source string
|
|
*/
|
|
const kebabCase = (input) => input?.trim().replace(/([a-z])([A-Z])/g, "$1-$2").replace(/\s+/g, "-").toLowerCase();
|
|
//#endregion
|
|
//#region src/misc/normalizeValue.ts
|
|
/**
|
|
* Utility to normalize component options
|
|
*
|
|
* @param value the input value
|
|
* @return the normalized value
|
|
*/
|
|
const normalizeValue = (value) => {
|
|
if (["true", true].includes(value)) return true;
|
|
if (["false", false].includes(value)) return false;
|
|
if ([
|
|
"null",
|
|
"",
|
|
null,
|
|
void 0
|
|
].includes(value)) return null;
|
|
if (value !== "" && !Number.isNaN(+value)) return +value;
|
|
return value;
|
|
};
|
|
//#endregion
|
|
//#region src/misc/ObjectEntries.ts
|
|
/**
|
|
* Shortcut for `Object.entries()` static method.
|
|
*
|
|
* @param obj a target object
|
|
* @returns the entries of an object in an array format [key, value][]
|
|
* @see https://github.com/devinrhode2/ObjectTyped/blob/master/src/index.ts
|
|
*/
|
|
const ObjectEntries = (obj) => Object.entries(obj);
|
|
//#endregion
|
|
//#region src/misc/normalizeOptions.ts
|
|
/**
|
|
* Utility to normalize component options.
|
|
*
|
|
* @param element target
|
|
* @param defaultOps component default options
|
|
* @param inputOps component instance options
|
|
* @param ns component namespace
|
|
* @return normalized component options object
|
|
*/
|
|
const normalizeOptions = (element, defaultOps, inputOps, ns) => {
|
|
if (!isElement(element)) return defaultOps;
|
|
const INPUT = { ...inputOps };
|
|
const data = { ...element.dataset };
|
|
const normalOps = { ...defaultOps };
|
|
const dataOps = {};
|
|
const title = "title";
|
|
ObjectEntries(data).forEach(([k, v]) => {
|
|
const key = ns && typeof k === "string" && k.includes(ns) ? camelCase(k.replace(ns, "")) : camelCase(k);
|
|
dataOps[key] = normalizeValue(v);
|
|
});
|
|
ObjectEntries(INPUT).forEach(([k, v]) => {
|
|
INPUT[k] = normalizeValue(v);
|
|
});
|
|
ObjectEntries(defaultOps).forEach(([k, v]) => {
|
|
if (k in INPUT) normalOps[k] = INPUT[k];
|
|
else if (k in dataOps) normalOps[k] = dataOps[k];
|
|
else normalOps[k] = k === title ? getAttribute(element, title) : v;
|
|
});
|
|
return normalOps;
|
|
};
|
|
//#endregion
|
|
//#region src/misc/ObjectHasOwn.ts
|
|
/**
|
|
* A shortcut to `Object.hasOwn()` static method to work
|
|
* with regular `Object` elements.
|
|
*
|
|
* @see https://fettblog.eu/typescript-hasownproperty/
|
|
* @param obj the target object
|
|
* @param prop the property to check
|
|
* @returns the query result
|
|
*/
|
|
const ObjectHasOwn = (obj, prop) => isObject(obj) && (Object.hasOwn(obj, prop) || prop in obj);
|
|
//#endregion
|
|
//#region src/misc/ObjectKeys.ts
|
|
/**
|
|
* Shortcut for `Object.keys()` static method.
|
|
*
|
|
* @param obj a target object
|
|
* @returns an array with object keys
|
|
* @see https://github.com/devinrhode2/ObjectTyped/blob/master/src/index.ts
|
|
*/
|
|
const ObjectKeys = (obj) => Object.keys(obj);
|
|
//#endregion
|
|
//#region src/misc/ObjectValues.ts
|
|
/**
|
|
* Shortcut for `Object.values()` static method.
|
|
*
|
|
* @param obj a target object
|
|
* @returns an array with the object values
|
|
* @see https://github.com/devinrhode2/ObjectTyped/blob/master/src/index.ts
|
|
*/
|
|
const ObjectValues = (obj) => Object.values(obj);
|
|
//#endregion
|
|
//#region src/misc/ObjectFromEntries.ts
|
|
/**
|
|
* Shortcut for `Object.fromEntries()` static method.
|
|
*
|
|
* @param entries a target entries object
|
|
* @returns a new Object created from the specified entries in array format [key, value][]
|
|
* @see https://github.com/devinrhode2/ObjectTyped/blob/master/src/index.ts
|
|
*/
|
|
const ObjectFromEntries = (entries) => Object.fromEntries(entries);
|
|
//#endregion
|
|
//#region src/misc/createCustomEvent.ts
|
|
/**
|
|
* Returns a namespaced `CustomEvent` specific to each component.
|
|
*
|
|
* @param eventType Event.type
|
|
* @param config Event.options | Event.properties
|
|
* @returns a new namespaced event
|
|
*/
|
|
const createCustomEvent = (eventType, config) => {
|
|
const OriginalCustomEvent = new CustomEvent(eventType, {
|
|
cancelable: true,
|
|
bubbles: true
|
|
});
|
|
if (isObject(config)) ObjectAssign(OriginalCustomEvent, config);
|
|
return OriginalCustomEvent;
|
|
};
|
|
//#endregion
|
|
//#region src/misc/passiveHandler.ts
|
|
/**
|
|
* A global namespace for most scroll event listeners.
|
|
*/
|
|
const passiveHandler = { passive: true };
|
|
//#endregion
|
|
//#region src/misc/reflow.ts
|
|
/**
|
|
* Utility to force re-paint of an `HTMLElement` target.
|
|
*
|
|
* @param element is the target
|
|
* @return the `Element.offsetHeight` value
|
|
*/
|
|
const reflow = (element) => element.offsetHeight;
|
|
//#endregion
|
|
//#region src/misc/setElementStyle.ts
|
|
/**
|
|
* Shortcut for multiple uses of `HTMLElement.style.propertyName` method.
|
|
*
|
|
* @param element target element
|
|
* @param styles attribute value
|
|
*/
|
|
const setElementStyle = (element, styles) => {
|
|
ObjectEntries(styles).forEach(([key, value]) => {
|
|
if (value && isString(key) && key.includes("--")) element.style.setProperty(key, value);
|
|
else {
|
|
const propObject = {};
|
|
propObject[key] = value;
|
|
ObjectAssign(element.style, propObject);
|
|
}
|
|
});
|
|
};
|
|
//#endregion
|
|
//#region src/is/isMap.ts
|
|
/**
|
|
* Checks if an element is a `Map`.
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isMap = (obj) => isObject(obj) && obj.constructor.name === "Map" || false;
|
|
//#endregion
|
|
//#region src/is/isNumber.ts
|
|
/**
|
|
* Shortie for `typeof SOMETHING === "number"`.
|
|
*
|
|
* @param num input value
|
|
* @returns the query result
|
|
*/
|
|
const isNumber = (num) => typeof num === "number" || false;
|
|
//#endregion
|
|
//#region src/misc/timer.ts
|
|
const TimeCache = /* @__PURE__ */ new Map();
|
|
/**
|
|
* An interface for one or more `TimerHandler`s per `Element`.
|
|
*
|
|
* @see https://github.com/thednp/navbar/
|
|
*/
|
|
const Timer = {
|
|
set: (element, callback, delay, key) => {
|
|
if (!isElement(element)) return;
|
|
// @license test comment
|
|
/* @license comment */
|
|
/* test @license comment */
|
|
if (key && key.length) {
|
|
if (!TimeCache.has(element)) TimeCache.set(element, /* @__PURE__ */ new Map());
|
|
TimeCache.get(element).set(key, setTimeout(callback, delay));
|
|
} else TimeCache.set(element, setTimeout(callback, delay));
|
|
},
|
|
get: (element, key) => {
|
|
if (!isElement(element)) return null;
|
|
const keyTimers = TimeCache.get(element);
|
|
if (key && keyTimers && isMap(keyTimers)) return keyTimers.get(key) || null;
|
|
else if (isNumber(keyTimers)) return keyTimers;
|
|
return null;
|
|
},
|
|
clear: (element, key) => {
|
|
if (!isElement(element)) return;
|
|
const keyTimers = TimeCache.get(element);
|
|
if (key && key.length && isMap(keyTimers)) {
|
|
clearTimeout(keyTimers.get(key));
|
|
keyTimers.delete(key);
|
|
if (keyTimers.size === 0) TimeCache.delete(element);
|
|
} else {
|
|
clearTimeout(keyTimers);
|
|
TimeCache.delete(element);
|
|
}
|
|
}
|
|
};
|
|
//#endregion
|
|
//#region src/misc/toLowerCase.ts
|
|
/**
|
|
* Shortcut for `String.toLowerCase()`.
|
|
*
|
|
* @param source input string
|
|
* @returns lowercase output string
|
|
*/
|
|
const toLowerCase = (source) => source.toLowerCase();
|
|
//#endregion
|
|
//#region src/misc/toUpperCase.ts
|
|
/**
|
|
* Shortcut for `String.toUpperCase()`.
|
|
*
|
|
* @param source input string
|
|
* @returns uppercase output string
|
|
*/
|
|
const toUpperCase = (source) => source.toUpperCase();
|
|
//#endregion
|
|
//#region src/selectors/querySelectorAll.ts
|
|
/**
|
|
* A shortcut for `(document|Element).querySelectorAll`.
|
|
*
|
|
* @param selector the input selector
|
|
* @param parent optional node to look into
|
|
* @return the query result
|
|
*/
|
|
const querySelectorAll = (selector, parent) => {
|
|
return (isNode(parent) ? parent : getDocument()).querySelectorAll(selector);
|
|
};
|
|
//#endregion
|
|
//#region src/misc/focusTrap.ts
|
|
const focusTrapMap = /* @__PURE__ */ new Map();
|
|
function handleKeyboardNavigation(event) {
|
|
const { shiftKey, code } = event;
|
|
const doc = getDocument(this);
|
|
const focusableElements = [...querySelectorAll(focusableSelector, this)].filter((el) => !hasAttribute(el, "disabled") && !getAttribute(el, "aria-hidden"));
|
|
if (!focusableElements.length) return;
|
|
const firstFocusable = focusableElements[0];
|
|
const lastFocusable = focusableElements[focusableElements.length - 1];
|
|
if (code === "Tab") {
|
|
if (shiftKey && doc.activeElement === firstFocusable) {
|
|
lastFocusable.focus();
|
|
event.preventDefault();
|
|
} else if (!shiftKey && doc.activeElement === lastFocusable) {
|
|
firstFocusable.focus();
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Utility to check if a designated element is affected by focus trap;
|
|
* @param target
|
|
*/
|
|
const hasFocusTrap = (target) => focusTrapMap.has(target) === true;
|
|
/**
|
|
* Utility to add focus trap inside a designated target element;
|
|
* @param target
|
|
*/
|
|
const addFocusTrap = (target) => {
|
|
if (hasFocusTrap(target)) return;
|
|
on(target, "keydown", handleKeyboardNavigation);
|
|
focusTrapMap.set(target, true);
|
|
};
|
|
/**
|
|
* Utility to remove focus trap inside a designated target element;
|
|
* @param target
|
|
*/
|
|
const removeFocusTrap = (target) => {
|
|
if (!hasFocusTrap(target)) return;
|
|
off(target, "keydown", handleKeyboardNavigation);
|
|
focusTrapMap.delete(target);
|
|
};
|
|
/**
|
|
* Utility to toggle focus trap inside a designated target element;
|
|
* @param target
|
|
*/
|
|
const toggleFocusTrap = (target) => {
|
|
if (hasFocusTrap(target)) removeFocusTrap(target);
|
|
else addFocusTrap(target);
|
|
};
|
|
//#endregion
|
|
//#region src/is/isHTMLElement.ts
|
|
/**
|
|
* Checks if an element is an `HTMLElement`.
|
|
*
|
|
* @see https://dom.spec.whatwg.org/#node
|
|
*
|
|
* @param element the target object
|
|
* @returns the query result
|
|
*/
|
|
const isHTMLElement = (element) => isElement(element) && "offsetWidth" in element || false;
|
|
//#endregion
|
|
//#region src/get/getBoundingClientRect.ts
|
|
/**
|
|
* Returns the bounding client rect of a target `Element`.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param element event.target
|
|
* @param includeScale when *true*, the target scale is also computed
|
|
* @returns the bounding client rect object
|
|
*/
|
|
const getBoundingClientRect = (element, includeScale) => {
|
|
const { width, height, top, right, bottom, left } = element.getBoundingClientRect();
|
|
let scaleX = 1;
|
|
let scaleY = 1;
|
|
if (includeScale && isHTMLElement(element)) {
|
|
const { offsetWidth, offsetHeight } = element;
|
|
scaleX = offsetWidth > 0 ? Math.round(width) / offsetWidth : 1;
|
|
scaleY = offsetHeight > 0 ? Math.round(height) / offsetHeight : 1;
|
|
}
|
|
return {
|
|
width: width / scaleX,
|
|
height: height / scaleY,
|
|
top: top / scaleY,
|
|
right: right / scaleX,
|
|
bottom: bottom / scaleY,
|
|
left: left / scaleX,
|
|
x: left / scaleX,
|
|
y: top / scaleY
|
|
};
|
|
};
|
|
//#endregion
|
|
//#region src/get/getDocumentBody.ts
|
|
/**
|
|
* Returns the `document.body` or the `<body>` element.
|
|
*
|
|
* @param node the reference node
|
|
* @returns the parent `<body>` of the specified node
|
|
*/
|
|
const getDocumentBody = (node) => {
|
|
return getDocument(node).body;
|
|
};
|
|
//#endregion
|
|
//#region src/get/getDocumentElement.ts
|
|
/**
|
|
* Returns the `document.documentElement` or the `<HTML>` element.
|
|
*
|
|
* @param node the reference node
|
|
* @returns the parent `<HTML>` of the node's parent document
|
|
*/
|
|
const getDocumentElement = (node) => {
|
|
return getDocument(node).documentElement;
|
|
};
|
|
//#endregion
|
|
//#region src/get/getDocumentHead.ts
|
|
/**
|
|
* Returns the `document.head` or the `<head>` element.
|
|
*
|
|
* @param node the reference node
|
|
* @returns the `<head>` of the node's parent document
|
|
*/
|
|
const getDocumentHead = (node) => {
|
|
return getDocument(node).head;
|
|
};
|
|
//#endregion
|
|
//#region src/get/getNodeName.ts
|
|
/**
|
|
* Returns the value of `node.nodeName` for the given node.
|
|
* @param node target node
|
|
* @returns the node name
|
|
*/
|
|
const getNodeName = (node) => {
|
|
if (isNode(node)) return (node.nodeName || "").toLowerCase();
|
|
return "#document";
|
|
};
|
|
//#endregion
|
|
//#region src/get/getNodeScroll.ts
|
|
/**
|
|
* Returns an `{x, y}` object with the target
|
|
* `Element` / `Node` scroll position.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param element target node / element
|
|
* @returns the scroll tuple
|
|
*/
|
|
const getNodeScroll = (element) => {
|
|
const isWin = isWindow(element);
|
|
return {
|
|
x: isWin ? element.scrollX : element.scrollLeft,
|
|
y: isWin ? element.scrollY : element.scrollTop
|
|
};
|
|
};
|
|
//#endregion
|
|
//#region src/is/isShadowRoot.ts
|
|
/**
|
|
* Check if target is a `ShadowRoot`.
|
|
*
|
|
* @param element target
|
|
* @returns the query result
|
|
*/
|
|
const isShadowRoot = (element) => isNode(element) && element.constructor.name === "ShadowRoot" || false;
|
|
//#endregion
|
|
//#region src/get/getParentNode.ts
|
|
/**
|
|
* Returns the `parentNode` also going through `ShadowRoot`.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param node the target node
|
|
* @returns the apropriate parent node
|
|
*/
|
|
const getParentNode = (node) => {
|
|
if (node.nodeName === "HTML") return node;
|
|
return isElement(node) && node.assignedSlot || isNode(node) && node.parentNode || isShadowRoot(node) && node.host || getDocumentElement(node);
|
|
};
|
|
//#endregion
|
|
//#region src/get/getWindow.ts
|
|
/**
|
|
* Returns the `Window` object of a target node.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param node target node
|
|
* @returns the `Window` object
|
|
*/
|
|
const getWindow = (node) => {
|
|
if (!node) return window;
|
|
if (isDocument(node)) return node.defaultView;
|
|
if (isNode(node)) return node?.ownerDocument?.defaultView;
|
|
return node;
|
|
};
|
|
//#endregion
|
|
//#region src/is/isTableElement.ts
|
|
/**
|
|
* Check if a target element is a `<table>`, `<td>` or `<th>`.
|
|
* This specific check is important for determining
|
|
* the `offsetParent` of a given element.
|
|
*
|
|
* @param element the target element
|
|
* @returns the query result
|
|
*/
|
|
const isTableElement = (element) => isNode(element) && [
|
|
"TABLE",
|
|
"TD",
|
|
"TH"
|
|
].includes(element.nodeName) || false;
|
|
//#endregion
|
|
//#region src/selectors/matches.ts
|
|
/**
|
|
* Check if element matches a CSS selector.
|
|
*
|
|
* @param target the target element
|
|
* @param selector the selector to match
|
|
* @returns the query result
|
|
*/
|
|
const matches = (target, selector) => target.matches(selector);
|
|
//#endregion
|
|
//#region src/get/getOffsetParent.ts
|
|
const isStaticPositioned = (element) => {
|
|
return getElementStyle(element, "position") === "static";
|
|
};
|
|
const isFixedPositioned = (element) => {
|
|
return getElementStyle(element, "position") === "fixed";
|
|
};
|
|
const isTopLayer = (element) => {
|
|
return [":popover-open", ":modal"].some((selector) => {
|
|
try {
|
|
return matches(element, selector);
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
});
|
|
};
|
|
const isContainingBlock = (elementOrCss) => {
|
|
const webkit = isWebKit();
|
|
const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;
|
|
return css.transform !== "none" || css.perspective !== "none" || (css.containerType ? css.containerType !== "normal" : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== "none" : false) || !webkit && (css.filter ? css.filter !== "none" : false) || [
|
|
"transform",
|
|
"perspective",
|
|
"filter"
|
|
].some((value) => (css.willChange || "").includes(value)) || [
|
|
"paint",
|
|
"layout",
|
|
"strict",
|
|
"content"
|
|
].some((value) => (css.contain || "").includes(value));
|
|
};
|
|
const getContainingBlock = (element) => {
|
|
let currentNode = getParentNode(element);
|
|
while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
|
|
if (isContainingBlock(currentNode)) return currentNode;
|
|
else if (isTopLayer(currentNode)) return null;
|
|
currentNode = getParentNode(currentNode);
|
|
}
|
|
return null;
|
|
};
|
|
const isLastTraversableNode = (node) => {
|
|
return [
|
|
"html",
|
|
"body",
|
|
"#document"
|
|
].includes(getNodeName(node));
|
|
};
|
|
const getTrueOffsetParent = (element) => {
|
|
if (!isHTMLElement(element) || isFixedPositioned(element)) return null;
|
|
let rawOffsetParent = element.offsetParent;
|
|
if (getDocumentElement(element) === rawOffsetParent) rawOffsetParent = rawOffsetParent.ownerDocument.body;
|
|
return rawOffsetParent;
|
|
};
|
|
/**
|
|
* Returns the `offsetParent` for a given target.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param element the target node
|
|
* @returns the offset parent node
|
|
*/
|
|
const getOffsetParent = (element) => {
|
|
const win = getWindow(element);
|
|
if (!isNode(element) || isTopLayer(element)) return win;
|
|
if (!isHTMLElement(element)) {
|
|
let svgOffsetParent = getParentNode(element);
|
|
while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {
|
|
if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) return svgOffsetParent;
|
|
svgOffsetParent = getParentNode(svgOffsetParent);
|
|
}
|
|
return win;
|
|
}
|
|
let offsetParent = getTrueOffsetParent(element);
|
|
while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) offsetParent = getTrueOffsetParent(offsetParent);
|
|
if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) return win;
|
|
return offsetParent || getContainingBlock(element) || win;
|
|
};
|
|
//#endregion
|
|
//#region src/is/isScaledElement.ts
|
|
/**
|
|
* Checks if a target `Element` is affected by scale.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param element target
|
|
* @returns the query result
|
|
*/
|
|
const isScaledElement = (element) => {
|
|
if (!isHTMLElement(element)) return false;
|
|
const { width, height } = getBoundingClientRect(element);
|
|
const { offsetWidth, offsetHeight } = element;
|
|
return Math.round(width) !== offsetWidth || Math.round(height) !== offsetHeight;
|
|
};
|
|
//#endregion
|
|
//#region src/get/getRectRelativeToOffsetParent.ts
|
|
/**
|
|
* Returns the rect relative to a given offset parent and its scroll position.
|
|
*
|
|
* @see https://github.com/floating-ui/floating-ui
|
|
*
|
|
* @param element target
|
|
* @param offsetParent the container / offset parent
|
|
* @param scroll the offsetParent scroll position
|
|
* @returns a DOMRect like object
|
|
*/
|
|
const getRectRelativeToOffsetParent = (element, offsetParent, scroll) => {
|
|
const isParentAnElement = isHTMLElement(offsetParent);
|
|
const rect = getBoundingClientRect(element, isParentAnElement && isScaledElement(offsetParent));
|
|
const offsets = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
if (isParentAnElement) {
|
|
const offsetRect = getBoundingClientRect(offsetParent, true);
|
|
offsets.x = offsetRect.x + offsetParent.clientLeft;
|
|
offsets.y = offsetRect.y + offsetParent.clientTop;
|
|
}
|
|
return {
|
|
x: rect.left + scroll.x - offsets.x,
|
|
y: rect.top + scroll.y - offsets.y,
|
|
width: rect.width,
|
|
height: rect.height
|
|
};
|
|
};
|
|
//#endregion
|
|
//#region src/get/getUID.ts
|
|
let elementUID = 0;
|
|
let elementMapUID = 0;
|
|
const elementIDMap = /* @__PURE__ */ new Map();
|
|
/**
|
|
* Returns a unique identifier for popover, tooltip, scrollspy.
|
|
*
|
|
* @param element target element
|
|
* @param key optional identifier key
|
|
* @returns an existing or new unique ID
|
|
*/
|
|
const getUID = (element, key) => {
|
|
let result = key ? elementUID : elementMapUID;
|
|
if (key) {
|
|
const elID = getUID(element);
|
|
const elMap = elementIDMap.get(elID) || /* @__PURE__ */ new Map();
|
|
if (!elementIDMap.has(elID)) elementIDMap.set(elID, elMap);
|
|
if (isMap(elMap) && !elMap.has(key)) {
|
|
elMap.set(key, result);
|
|
elementUID += 1;
|
|
} else result = elMap.get(key);
|
|
} else {
|
|
const elkey = element.id || element;
|
|
if (!elementIDMap.has(elkey)) {
|
|
elementIDMap.set(elkey, result);
|
|
elementMapUID += 1;
|
|
} else result = elementIDMap.get(elkey);
|
|
}
|
|
return result;
|
|
};
|
|
//#endregion
|
|
//#region src/is/isArray.ts
|
|
/**
|
|
* Shortie for the `Array.isArray()` static method.
|
|
*
|
|
* @param obj array-like iterable object
|
|
* @returns the query result
|
|
*/
|
|
const isArray = (obj) => Array.isArray(obj) || false;
|
|
//#endregion
|
|
//#region src/is/isCanvas.ts
|
|
/**
|
|
* Checks if an element is an `HTMLCanvasElement` or `<canvas>`.
|
|
*
|
|
* @param element the target element
|
|
* @returns the query result
|
|
*/
|
|
const isCanvas = (element) => isNode(element) && element.nodeName === "CANVAS" || false;
|
|
//#endregion
|
|
//#region src/is/isCustomElement.ts
|
|
/**
|
|
* Checks if an object is a `CustomElement`.
|
|
*
|
|
* @param element the target object
|
|
* @returns the query result
|
|
*/
|
|
const isCustomElement = (element) => isHTMLElement(element) && !!element.shadowRoot || false;
|
|
//#endregion
|
|
//#region src/is/isElementInScrollRange.ts
|
|
/**
|
|
* Utility to determine if an `Element`
|
|
* is partially visible in viewport.
|
|
*
|
|
* @param element target
|
|
* @return the query result
|
|
*/
|
|
const isElementInScrollRange = (element) => {
|
|
if (!isNode(element)) return false;
|
|
const { top, bottom } = getBoundingClientRect(element);
|
|
const { clientHeight } = getDocumentElement(element);
|
|
return top <= clientHeight && bottom >= 0;
|
|
};
|
|
//#endregion
|
|
//#region src/is/isElementInViewport.ts
|
|
/**
|
|
* Utility to determine if an `Element`
|
|
* is fully visible in the viewport.
|
|
*
|
|
* @param element target
|
|
* @return the query result
|
|
*/
|
|
const isElementInViewport = (element) => {
|
|
if (!isElement(element)) return false;
|
|
const { clientWidth, clientHeight } = getDocumentElement(element);
|
|
const { top, left, bottom, right } = getBoundingClientRect(element, true);
|
|
return top >= 0 && left >= 0 && bottom <= clientHeight && right <= clientWidth;
|
|
};
|
|
//#endregion
|
|
//#region src/is/isElementsArray.ts
|
|
/**
|
|
* Checks if an object is an `Array` in which all items are `Element`.
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isElementsArray = (obj) => isArray(obj) && obj.every(isElement) || false;
|
|
//#endregion
|
|
//#region src/is/isFunction.ts
|
|
/**
|
|
* Checks if an object is a `Function`.
|
|
*
|
|
* @param fn the target object
|
|
* @returns the query result
|
|
*/
|
|
const isFunction = (fn) => typeof fn === "function" || false;
|
|
//#endregion
|
|
//#region src/is/isHTMLCollection.ts
|
|
/**
|
|
* Checks if an object is an `HTMLCollection`.
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isHTMLCollection = (obj) => isObject(obj) && obj.constructor.name === "HTMLCollection" || false;
|
|
//#endregion
|
|
//#region src/is/isHTMLImageElement.ts
|
|
/**
|
|
* Check if a target element is an `<img>`.
|
|
*
|
|
* @param element the target element
|
|
* @returns the query result
|
|
*/
|
|
const isHTMLImageElement = (element) => isHTMLElement(element) && element.tagName === "IMG" || false;
|
|
//#endregion
|
|
//#region src/is/isJSON.ts
|
|
/**
|
|
* Checks if a string is a `JSON` string.
|
|
*
|
|
* @param str the target string
|
|
* @returns the query result
|
|
*/
|
|
const isJSON = (str) => {
|
|
if (!isString(str)) return false;
|
|
try {
|
|
JSON.parse(str);
|
|
} catch (_e) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
//#endregion
|
|
//#region src/is/isWeakMap.ts
|
|
/**
|
|
* Checks if an element is a `WeakMap`.
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isWeakMap = (obj) => isObject(obj) && obj.constructor.name === "WeakMap" || false;
|
|
//#endregion
|
|
//#region src/is/isMedia.ts
|
|
/**
|
|
* Checks if an element is an `<svg>` (or any type of SVG element),
|
|
* `<img>`, `<video>` or `<canvas>`.
|
|
*
|
|
* *Tooltip* / *Popover* works different with media elements.
|
|
*
|
|
* @param element the target element
|
|
* @returns the query result
|
|
*/
|
|
const isMedia = (element) => isNode(element) && [
|
|
"SVG",
|
|
"Image",
|
|
"Video",
|
|
"Canvas"
|
|
].some((s) => element.constructor.name.includes(s)) || false;
|
|
//#endregion
|
|
//#region src/is/isNodeList.ts
|
|
/**
|
|
* Checks if an object is a `NodeList`.
|
|
* => equivalent to `object instanceof NodeList`
|
|
*
|
|
* @param obj the target object
|
|
* @returns the query result
|
|
*/
|
|
const isNodeList = (obj) => isObject(obj) && obj.constructor.name === "NodeList" || false;
|
|
//#endregion
|
|
//#region src/is/isRTL.ts
|
|
/**
|
|
* Checks if a page is Right To Left.
|
|
*
|
|
* @param node the target
|
|
* @returns the query result
|
|
*/
|
|
const isRTL = (node) => getDocumentElement(node).dir === "rtl";
|
|
//#endregion
|
|
//#region src/is/isSVGElement.ts
|
|
/**
|
|
* Check if an element is an `<svg>` or any other SVG element,
|
|
* an equivalent to `SOMETHING instanceof SVGElement`.
|
|
*
|
|
* @param element the target element
|
|
* @returns the query result
|
|
*/
|
|
const isSVGElement = (element) => isNode(element) && element.constructor.name.includes("SVG") || false;
|
|
//#endregion
|
|
//#region src/selectors/closest.ts
|
|
/**
|
|
* Shortcut for `HTMLElement.closest` method which also works
|
|
* with children of `ShadowRoot`. The order of the parameters
|
|
* is intentional since they're both required.
|
|
*
|
|
* @see https://stackoverflow.com/q/54520554/803358
|
|
*
|
|
* @param element target Element to check
|
|
* @param selector the selector string
|
|
* @return the query result
|
|
*/
|
|
const closest = (element, selector) => {
|
|
if (!element || !selector) return null;
|
|
return element.closest(selector) || closest(element.getRootNode().host, selector) || null;
|
|
};
|
|
//#endregion
|
|
//#region src/selectors/querySelector.ts
|
|
/**
|
|
* Utility to check if target is typeof `Element`, `Node`
|
|
* or find one that matches a selector.
|
|
*
|
|
* @param selector the input selector or target element
|
|
* @param parent optional node to look into
|
|
* @return the `Element` or null
|
|
*/
|
|
const querySelector = (selector, parent) => {
|
|
if (isElement(selector)) return selector;
|
|
return (isElement(parent) ? parent : getDocument()).querySelector(selector);
|
|
};
|
|
//#endregion
|
|
//#region src/selectors/getElementsByTagName.ts
|
|
/**
|
|
* Shortcut for `Element.getElementsByTagName` method. Some `Node` elements
|
|
* like `ShadowRoot` do not support `getElementsByTagName`.
|
|
*
|
|
* @param selector the tag name
|
|
* @param parent optional Element to look into
|
|
* @return the 'HTMLCollection'
|
|
*/
|
|
const getElementsByTagName = (selector, parent) => {
|
|
return (isNode(parent) ? parent : getDocument()).getElementsByTagName(selector);
|
|
};
|
|
//#endregion
|
|
//#region src/selectors/getCustomElements.ts
|
|
/**
|
|
* Returns an `Array` of `Node` elements that are registered as
|
|
* `CustomElement`.
|
|
*
|
|
* @see https://stackoverflow.com/questions/27334365/how-to-get-list-of-registered-custom-elements
|
|
*
|
|
* @param parent parent to look into
|
|
* @returns the query result
|
|
*/
|
|
const getCustomElements = (parent) => {
|
|
return [...getElementsByTagName("*", parent)].filter(isCustomElement);
|
|
};
|
|
//#endregion
|
|
//#region src/selectors/getElementById.ts
|
|
/**
|
|
* Returns an `HTMLElement` that matches the id in the document.
|
|
* Within multiple <iframe> elements, a `parent` parameter
|
|
* would decisively locate the correct element.
|
|
*
|
|
* @param id the ID selector
|
|
* @param context an element in it's document or document
|
|
* @returns the requested element
|
|
*/
|
|
const getElementById = (id, context) => {
|
|
return getDocument(context).getElementById(id);
|
|
};
|
|
//#endregion
|
|
//#region src/selectors/getElementsByClassName.ts
|
|
/**
|
|
* Shortcut for `Element.getElementsByClassName` method. Some `Node` elements
|
|
* like `ShadowRoot` do not support `getElementsByClassName`.
|
|
*
|
|
* @param selector the class name
|
|
* @param parent optional Element to look into
|
|
* @return the 'HTMLCollection'
|
|
*/
|
|
const getElementsByClassName = (selector, parent) => {
|
|
return (parent && isNode(parent) ? parent : getDocument()).getElementsByClassName(selector);
|
|
};
|
|
//#endregion
|
|
export { ArrayFrom, DOMContentLoadedEvent, DOMMouseScrollEvent, Data, Float32ArrayFrom, Float64ArrayFrom, ObjectAssign, ObjectEntries, ObjectFromEntries, ObjectHasOwn, ObjectKeys, ObjectValues, Timer, abortEvent, addClass, addEventListener, addFocusTrap, animationDelay, animationDuration, animationEndEvent, animationName, ariaChecked, ariaDescribedBy, ariaDescription, ariaExpanded, ariaHasPopup, ariaHidden, ariaLabel, ariaLabelledBy, ariaModal, ariaPressed, ariaSelected, ariaValueMax, ariaValueMin, ariaValueNow, ariaValueText, beforeunloadEvent, bezierEasings, blurEvent, camelCase, capitalize, changeEvent, closest, contextmenuEvent, createCustomEvent, createElement, createElementNS, dispatchEvent, distinct, documentBody, documentElement, documentHead, dragEvent, dragendEvent, dragenterEvent, dragleaveEvent, dragoverEvent, dragstartEvent, emulateAnimationEnd, emulateTransitionEnd, errorEvent, focus, focusEvent, focusEvents, focusableSelector, focusinEvent, focusoutEvent, gesturechangeEvent, gestureendEvent, gesturestartEvent, getAttribute, getAttributeNS, getBoundingClientRect, getCustomElements, getDocument, getDocumentBody, getDocumentElement, getDocumentHead, getElementAnimationDelay, getElementAnimationDuration, getElementById, getElementStyle, getElementTransitionDelay, getElementTransitionDuration, getElementsByClassName, getElementsByTagName, getInstance, getNodeName, getNodeScroll, getOffsetParent, getParentNode, getRectRelativeToOffsetParent, getUID, getWindow, handleKeyboardNavigation, hasAttribute, hasAttributeNS, hasClass, hasFocusTrap, isApple, isArray, isCanvas, isCustomElement, isDocument, isElement, isElementInScrollRange, isElementInViewport, isElementsArray, isFirefox, isFunction, isHTMLCollection, isHTMLElement, isHTMLImageElement, isJSON, isMap, isMedia, isMobile, isNode, isNodeList, isNumber, isObject, isRTL, isSVGElement, isScaledElement, isShadowRoot, isString, isTableElement, isWeakMap, isWebKit, isWindow, kebabCase, keyAlt, keyArrowDown, keyArrowLeft, keyArrowRight, keyArrowUp, keyBackspace, keyCapsLock, keyControl, keyDelete, keyEnter, keyEscape, keyInsert, keyMeta, keyNumpadEnter, keyPause, keyScrollLock, keyShift, keySpace, keyTab, keyboardEventKeys, keydownEvent, keypressEvent, keyupEvent, loadEvent, loadstartEvent, matches, mouseClickEvents, mouseHoverEvents, mouseSwipeEvents, mouseclickEvent, mousedblclickEvent, mousedownEvent, mouseenterEvent, mousehoverEvent, mouseinEvent, mouseleaveEvent, mousemoveEvent, mouseoutEvent, mouseoverEvent, mouseupEvent, mousewheelEvent, moveEvent, nativeEvents, noop, normalizeOptions, normalizeValue, off, offsetHeight, offsetWidth, on, one, orientationchangeEvent, passiveHandler, pointercancelEvent, pointerdownEvent, pointerleaveEvent, pointermoveEvent, pointerupEvent, querySelector, querySelectorAll, readystatechangeEvent, reflow, removeAttribute, removeAttributeNS, removeClass, removeEventListener, removeFocusTrap, resetEvent, resizeEvent, scrollEvent, scrollHeight, scrollWidth, selectEvent, selectendEvent, selectstartEvent, setAttribute, setAttributeNS, setElementStyle, submitEvent, support3DTransform, supportAnimation, supportPassive, supportTouch, supportTransform, supportTransition, tabindex, toLowerCase, toUpperCase, toggleFocusTrap, touchEvents, touchcancelEvent, touchendEvent, touchmoveEvent, touchstartEvent, transitionDelay, transitionDuration, transitionEndEvent, transitionProperty, unloadEvent, userAgent, userAgentData, version };
|
|
|
|
//# sourceMappingURL=index.js.map
|