@oscarpalmer/toretto 0.37.2 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attribute/get.js +9 -0
- package/dist/attribute/index.js +2 -0
- package/dist/attribute/set.js +2 -0
- package/dist/data.js +4 -1
- package/dist/event/delegation.js +2 -0
- package/dist/event/index.js +14 -0
- package/dist/find/index.js +10 -0
- package/dist/find/relative.js +8 -0
- package/dist/focusable.js +22 -0
- package/dist/html/index.js +8 -0
- package/dist/html/sanitize.js +7 -0
- package/dist/index.js +2 -2
- package/dist/internal/attribute.js +6 -1
- package/dist/internal/element-value.js +2 -0
- package/dist/internal/get-value.js +5 -2
- package/dist/internal/is.js +12 -0
- package/dist/is.js +7 -0
- package/dist/style.js +39 -0
- package/dist/toretto.full.js +424 -111
- package/dist/touch.js +7 -2
- package/package.json +8 -8
- package/src/data.ts +2 -1
- package/src/internal/get-value.ts +2 -1
package/dist/attribute/get.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { getAttributeValue } from "../internal/get-value.js";
|
|
2
2
|
import { isHTMLOrSVGElement } from "../internal/is.js";
|
|
3
|
+
//#region src/attribute/get.ts
|
|
3
4
|
function getAttribute(element, name, parseValues) {
|
|
4
5
|
if (isHTMLOrSVGElement(element) && typeof name === "string") return getAttributeValue(element, name, parseValues !== false);
|
|
5
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Get specific attributes from an element
|
|
9
|
+
* @param element Element to get attributes from
|
|
10
|
+
* @param names Attribute names
|
|
11
|
+
* @param parseData Parse data values? _(defaults to `true`)_
|
|
12
|
+
* @returns Object of named attributes
|
|
13
|
+
*/
|
|
6
14
|
function getAttributes(element, names, parseData) {
|
|
7
15
|
const attributes = {};
|
|
8
16
|
if (!(isHTMLOrSVGElement(element) && Array.isArray(names))) return attributes;
|
|
@@ -14,4 +22,5 @@ function getAttributes(element, names, parseData) {
|
|
|
14
22
|
}
|
|
15
23
|
return attributes;
|
|
16
24
|
}
|
|
25
|
+
//#endregion
|
|
17
26
|
export { getAttribute, getAttributes };
|
package/dist/attribute/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getAttribute, getAttributes } from "./get.js";
|
|
2
2
|
import { _isBadAttribute, _isBooleanAttribute, _isEmptyNonBooleanAttribute, _isInvalidBooleanAttribute, booleanAttributes } from "../internal/attribute.js";
|
|
3
3
|
import { setAttribute, setAttributes } from "./set.js";
|
|
4
|
+
//#region src/attribute/index.ts
|
|
4
5
|
function isBadAttribute(first, second) {
|
|
5
6
|
return _isBadAttribute(first, second, true);
|
|
6
7
|
}
|
|
@@ -13,4 +14,5 @@ function isEmptyNonBooleanAttribute(first, second) {
|
|
|
13
14
|
function isInvalidBooleanAttribute(first, second) {
|
|
14
15
|
return _isInvalidBooleanAttribute(first, second, true);
|
|
15
16
|
}
|
|
17
|
+
//#endregion
|
|
16
18
|
export { booleanAttributes, getAttribute, getAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute, setAttribute, setAttributes };
|
package/dist/attribute/set.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { setElementValue, setElementValues } from "../internal/element-value.js";
|
|
2
2
|
import { updateAttribute } from "../internal/attribute.js";
|
|
3
|
+
//#region src/attribute/set.ts
|
|
3
4
|
function setAttribute(element, first, second, third) {
|
|
4
5
|
setElementValue(element, first, second, third, updateAttribute);
|
|
5
6
|
}
|
|
6
7
|
function setAttributes(element, attributes, dispatch) {
|
|
7
8
|
setElementValues(element, attributes, null, dispatch, updateAttribute);
|
|
8
9
|
}
|
|
10
|
+
//#endregion
|
|
9
11
|
export { setAttribute, setAttributes };
|
package/dist/data.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { EXPRESSION_DATA_PREFIX } from "./internal/get-value.js";
|
|
2
2
|
import { isHTMLOrSVGElement } from "./internal/is.js";
|
|
3
3
|
import { setElementValues, updateElementValue } from "./internal/element-value.js";
|
|
4
|
-
import {
|
|
4
|
+
import { parse } from "@oscarpalmer/atoms/string";
|
|
5
|
+
import { kebabCase } from "@oscarpalmer/atoms/string/case";
|
|
6
|
+
//#region src/data.ts
|
|
5
7
|
function getData(element, keys, parseValues) {
|
|
6
8
|
if (!isHTMLOrSVGElement(element)) return;
|
|
7
9
|
const shouldParse = parseValues !== false;
|
|
@@ -30,4 +32,5 @@ function updateDataAttribute(element, key, value) {
|
|
|
30
32
|
updateElementValue(element, getName(key), value, element.setAttribute, element.removeAttribute, false, true);
|
|
31
33
|
}
|
|
32
34
|
var ATTRIBUTE_DATA_PREFIX = "data-";
|
|
35
|
+
//#endregion
|
|
33
36
|
export { getData, setData };
|
package/dist/event/delegation.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isEventTarget } from "../internal/is.js";
|
|
2
|
+
//#region src/event/delegation.ts
|
|
2
3
|
function addDelegatedHandler(doc, type, name, passive) {
|
|
3
4
|
if (DELEGATED.has(name)) return;
|
|
4
5
|
DELEGATED.add(name);
|
|
@@ -80,4 +81,5 @@ var EVENT_TYPES = new Set([
|
|
|
80
81
|
]);
|
|
81
82
|
var HANDLER_ACTIVE = delegatedEventHandler.bind(false);
|
|
82
83
|
var HANDLER_PASSIVE = delegatedEventHandler.bind(true);
|
|
84
|
+
//#endregion
|
|
83
85
|
export { addDelegatedListener, getDelegatedName, removeDelegatedListener };
|
package/dist/event/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { isEventTarget } from "../internal/is.js";
|
|
|
3
3
|
import { addDelegatedListener, getDelegatedName, removeDelegatedListener } from "./delegation.js";
|
|
4
4
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
5
5
|
import { noop } from "@oscarpalmer/atoms/function";
|
|
6
|
+
//#region src/event/index.ts
|
|
6
7
|
function createDispatchOptions(options) {
|
|
7
8
|
return {
|
|
8
9
|
bubbles: getBoolean(options?.bubbles, true),
|
|
@@ -29,6 +30,11 @@ function createEventOptions(options) {
|
|
|
29
30
|
function dispatch(target, type, options) {
|
|
30
31
|
if (isEventTarget(target) && typeof type === "string") target.dispatchEvent(createEvent(type, options));
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the X- and Y-coordinates from a pointer event
|
|
35
|
+
* @param event Pointer event
|
|
36
|
+
* @returns X- and Y-coordinates
|
|
37
|
+
*/
|
|
32
38
|
function getPosition(event) {
|
|
33
39
|
let x;
|
|
34
40
|
let y;
|
|
@@ -44,6 +50,13 @@ function getPosition(event) {
|
|
|
44
50
|
y
|
|
45
51
|
} : void 0;
|
|
46
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Remove an event listener
|
|
55
|
+
* @param target Event target
|
|
56
|
+
* @param type Type of event
|
|
57
|
+
* @param listener Event listener
|
|
58
|
+
* @param options Options for event
|
|
59
|
+
*/
|
|
47
60
|
function off(target, type, listener, options) {
|
|
48
61
|
if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return;
|
|
49
62
|
const extended = createEventOptions(options);
|
|
@@ -62,4 +75,5 @@ function on(target, type, listener, options) {
|
|
|
62
75
|
};
|
|
63
76
|
}
|
|
64
77
|
var PROPERTY_DETAIL = "detail";
|
|
78
|
+
//#endregion
|
|
65
79
|
export { dispatch, getPosition, off, on };
|
package/dist/find/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { findAncestor, findRelatives, getDistance } from "./relative.js";
|
|
2
|
+
//#region src/find/index.ts
|
|
2
3
|
function findElement(selector, context) {
|
|
3
4
|
return findElementOrElements(selector, context, true);
|
|
4
5
|
}
|
|
@@ -40,6 +41,14 @@ function findElementOrElementsFromNodes(array, context, contexts) {
|
|
|
40
41
|
function findElements(selector, context) {
|
|
41
42
|
return findElementOrElements(selector, context, false);
|
|
42
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the most specific element under the pointer
|
|
46
|
+
*
|
|
47
|
+
* - Ignores elements with `pointer-events: none` and `visibility: hidden`
|
|
48
|
+
* - _(If `skipIgnore` is `true`, no elements are ignored)_
|
|
49
|
+
* @param skipIgnore Skip ignored elements?
|
|
50
|
+
* @returns Found element or `null`
|
|
51
|
+
*/
|
|
43
52
|
function getElementUnderPointer(skipIgnore) {
|
|
44
53
|
const elements = [...document.querySelectorAll(SUFFIX_HOVER)];
|
|
45
54
|
const { length } = elements;
|
|
@@ -61,4 +70,5 @@ var STYLE_HIDDEN = "hidden";
|
|
|
61
70
|
var STYLE_NONE = "none";
|
|
62
71
|
var SUFFIX_HOVER = ":hover";
|
|
63
72
|
var TAG_HEAD = "HEAD";
|
|
73
|
+
//#endregion
|
|
64
74
|
export { findElement as $, findElement, findElements as $$, findElements, findAncestor, findRelatives, getDistance, getElementUnderPointer };
|
package/dist/find/relative.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/find/relative.ts
|
|
1
2
|
function findAncestor(origin, selector) {
|
|
2
3
|
const element = getElement(origin);
|
|
3
4
|
if (element == null || selector == null) return null;
|
|
@@ -34,6 +35,12 @@ function findRelatives(origin, selector, context) {
|
|
|
34
35
|
}
|
|
35
36
|
return distances.filter((found) => found.distance === minimum).map((found) => found.element);
|
|
36
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the distance between two elements _(i.e., the amount of nodes of between them)_
|
|
40
|
+
* @param origin Origin element
|
|
41
|
+
* @param target Target element
|
|
42
|
+
* @returns Distance between elements, or `-1` if distance cannot be calculated
|
|
43
|
+
*/
|
|
37
44
|
function getDistance(origin, target) {
|
|
38
45
|
if (origin === target) return 0;
|
|
39
46
|
if (origin.parentElement === target || target.parentElement === origin) return 1;
|
|
@@ -68,4 +75,5 @@ function traverse(from, to) {
|
|
|
68
75
|
parent = parent.parentElement;
|
|
69
76
|
}
|
|
70
77
|
}
|
|
78
|
+
//#endregion
|
|
71
79
|
export { findAncestor, findRelatives, getDistance };
|
package/dist/focusable.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
//#region src/focusable.ts
|
|
2
|
+
/**
|
|
3
|
+
* Get a list of focusable elements within a parent element
|
|
4
|
+
* @param parent Parent element
|
|
5
|
+
* @returns Focusable elements
|
|
6
|
+
*/
|
|
1
7
|
function getFocusable(parent) {
|
|
2
8
|
return getValidElements(parent, FILTERS_FOCUSABLE, false);
|
|
3
9
|
}
|
|
@@ -7,6 +13,11 @@ function getItem(element, tabbable) {
|
|
|
7
13
|
tabIndex: tabbable ? getTabIndex(element) : TABINDEX_DEFAULT
|
|
8
14
|
};
|
|
9
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Get a list of tabbable elements within a parent element
|
|
18
|
+
* @param parent Parent element
|
|
19
|
+
* @returns Tabbable elements
|
|
20
|
+
*/
|
|
10
21
|
function getTabbable(parent) {
|
|
11
22
|
return getValidElements(parent, FILTERS_TABBABLE, true);
|
|
12
23
|
}
|
|
@@ -61,6 +72,11 @@ function isDisabledFromFieldset(element) {
|
|
|
61
72
|
function isEditable(element) {
|
|
62
73
|
return EXPRESSION_TRUEISH.test(element.getAttribute(ATTRIBUTE_CONTENTEDITABLE));
|
|
63
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Is the element focusable?
|
|
77
|
+
* @param element Element to check
|
|
78
|
+
* @returns `true` if focusable, otherwise `false`
|
|
79
|
+
*/
|
|
64
80
|
function isFocusable(element) {
|
|
65
81
|
return element instanceof Element ? isValidElement(element, FILTERS_FOCUSABLE, false) : false;
|
|
66
82
|
}
|
|
@@ -91,6 +107,11 @@ function isNotTabbableRadio(item) {
|
|
|
91
107
|
function isSummarised(item) {
|
|
92
108
|
return item.element instanceof HTMLDetailsElement && [...item.element.children].some((child) => EXPRESSION_SUMMARY.test(child.tagName));
|
|
93
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Is the element tabbable?
|
|
112
|
+
* @param element Element to check
|
|
113
|
+
* @returns `true` if tabbable, otherwise `false`
|
|
114
|
+
*/
|
|
94
115
|
function isTabbable(element) {
|
|
95
116
|
return element instanceof Element ? isValidElement(element, FILTERS_TABBABLE, true) : false;
|
|
96
117
|
}
|
|
@@ -139,4 +160,5 @@ var STYLE_NONE = "none";
|
|
|
139
160
|
var TABINDEX_BASE = 0;
|
|
140
161
|
var TABINDEX_DEFAULT = -1;
|
|
141
162
|
var TYPE_RADIO = "radio";
|
|
163
|
+
//#endregion
|
|
142
164
|
export { getFocusable, getTabbable, isFocusable, isTabbable };
|
package/dist/html/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sanitizeNodes } from "./sanitize.js";
|
|
2
2
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
3
|
+
//#region src/html/index.ts
|
|
3
4
|
function createHtml(value) {
|
|
4
5
|
const parsed = getParser().parseFromString(getHtml(value), PARSE_TYPE_HTML);
|
|
5
6
|
parsed.body.normalize();
|
|
@@ -54,6 +55,12 @@ html.remove = (template) => {
|
|
|
54
55
|
}
|
|
55
56
|
templates = updated;
|
|
56
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Sanitize one or more nodes, recursively
|
|
60
|
+
* @param value Node or nodes to sanitize
|
|
61
|
+
* @param options Sanitization options
|
|
62
|
+
* @returns Sanitized nodes
|
|
63
|
+
*/
|
|
57
64
|
function sanitize(value) {
|
|
58
65
|
return sanitizeNodes(Array.isArray(value) ? value : [value], 0);
|
|
59
66
|
}
|
|
@@ -63,4 +70,5 @@ var TEMPLATE_TAG = "template";
|
|
|
63
70
|
var TEMPORARY_ELEMENT = "<toretto-temporary></toretto-temporary>";
|
|
64
71
|
var parser;
|
|
65
72
|
var templates = {};
|
|
73
|
+
//#endregion
|
|
66
74
|
export { html, sanitize };
|
package/dist/html/sanitize.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { _isBadAttribute, _isEmptyNonBooleanAttribute, _isInvalidBooleanAttribute } from "../internal/attribute.js";
|
|
2
2
|
import { setAttribute } from "../attribute/set.js";
|
|
3
|
+
//#region src/html/sanitize.ts
|
|
3
4
|
function handleElement(element, depth) {
|
|
4
5
|
if (depth === 0) {
|
|
5
6
|
const removable = element.querySelectorAll(REMOVE_SELECTOR);
|
|
@@ -7,6 +8,11 @@ function handleElement(element, depth) {
|
|
|
7
8
|
}
|
|
8
9
|
sanitizeAttributes(element, [...element.attributes]);
|
|
9
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Is the element clobbered?
|
|
13
|
+
*
|
|
14
|
+
* Thanks, DOMPurify _(https://github.com/cure53/DOMPurify)_
|
|
15
|
+
*/
|
|
10
16
|
function isClobbered(value) {
|
|
11
17
|
return value instanceof HTMLFormElement && (typeof value.nodeName !== "string" || typeof value.textContent !== "string" || typeof value.removeChild !== "function" || !(value.attributes instanceof NamedNodeMap) || typeof value.removeAttribute !== "function" || typeof value.setAttribute !== "function" || typeof value.namespaceURI !== "string" || typeof value.insertBefore !== "function" || typeof value.hasChildNodes !== "function");
|
|
12
18
|
}
|
|
@@ -52,4 +58,5 @@ function sanitizeNodes(nodes, depth) {
|
|
|
52
58
|
}
|
|
53
59
|
var COMMENT_HARMFUL = /<[/\w]/g;
|
|
54
60
|
var REMOVE_SELECTOR = "script, toretto-temporary";
|
|
61
|
+
//#endregion
|
|
55
62
|
export { sanitizeAttributes, sanitizeNodes };
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,6 @@ import { findAncestor, findRelatives, getDistance } from "./find/relative.js";
|
|
|
7
7
|
import { $ as findElement, $$ as findElements, getElementUnderPointer } from "./find/index.js";
|
|
8
8
|
import { getFocusable, getTabbable, isFocusable, isTabbable } from "./focusable.js";
|
|
9
9
|
import { html, sanitize } from "./html/index.js";
|
|
10
|
-
import
|
|
10
|
+
import supportsTouch from "./touch.js";
|
|
11
11
|
import { getStyle, getStyles, getTextDirection, setStyle, setStyles, toggleStyles } from "./style.js";
|
|
12
|
-
export { findElement as $, findElement, findElements as $$, findElements, dispatch, findAncestor, findRelatives, getData, getDistance, getElementUnderPointer, getFocusable, getPosition, getStyle, getStyles, getTabbable, getTextDirection, html, isBadAttribute, isBooleanAttribute, isChildNode, isEmptyNonBooleanAttribute, isEventTarget, isFocusable, isHTMLOrSVGElement, isInDocument, isInvalidBooleanAttribute, isTabbable, off, on, sanitize, setData, setStyle, setStyles,
|
|
12
|
+
export { findElement as $, findElement, findElements as $$, findElements, dispatch, findAncestor, findRelatives, getData, getDistance, getElementUnderPointer, getFocusable, getPosition, getStyle, getStyles, getTabbable, getTextDirection, html, isBadAttribute, isBooleanAttribute, isChildNode, isEmptyNonBooleanAttribute, isEventTarget, isFocusable, isHTMLOrSVGElement, isInDocument, isInvalidBooleanAttribute, isTabbable, off, on, sanitize, setData, setStyle, setStyles, supportsTouch, toggleStyles };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { updateElementValue } from "./element-value.js";
|
|
2
2
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
3
|
+
//#region src/internal/attribute.ts
|
|
3
4
|
function badAttributeHandler(name, value) {
|
|
4
5
|
if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
|
|
5
6
|
if (EXPRESSION_CLOBBERED_NAME.test(name) && (value in document || value in formElement) || EXPRESSION_EVENT_NAME.test(name)) return true;
|
|
@@ -70,7 +71,10 @@ var EXPRESSION_SOURCE_NAME = /^src$/i;
|
|
|
70
71
|
var EXPRESSION_SOURCE_VALUE = /^data:/i;
|
|
71
72
|
var EXPRESSION_URI_VALUE = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
|
|
72
73
|
var EXPRESSION_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
|
|
73
|
-
|
|
74
|
+
/**
|
|
75
|
+
* List of boolean attributes
|
|
76
|
+
*/
|
|
77
|
+
var booleanAttributes = Object.freeze([
|
|
74
78
|
"async",
|
|
75
79
|
"autofocus",
|
|
76
80
|
"autoplay",
|
|
@@ -108,4 +112,5 @@ var elementEvents = {
|
|
|
108
112
|
};
|
|
109
113
|
var formElement = document.createElement("form");
|
|
110
114
|
var textArea;
|
|
115
|
+
//#endregion
|
|
111
116
|
export { _isBadAttribute, _isBooleanAttribute, _isEmptyNonBooleanAttribute, _isInvalidBooleanAttribute, booleanAttributes, isAttribute, updateAttribute };
|
|
@@ -2,6 +2,7 @@ import { isHTMLOrSVGElement } from "./is.js";
|
|
|
2
2
|
import "../is.js";
|
|
3
3
|
import { isAttribute } from "./attribute.js";
|
|
4
4
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
5
|
+
//#region src/internal/element-value.ts
|
|
5
6
|
function setElementValue(element, first, second, third, callback) {
|
|
6
7
|
if (!isHTMLOrSVGElement(element)) return;
|
|
7
8
|
if (typeof first === "string") setElementValues(element, first, second, third, callback);
|
|
@@ -29,4 +30,5 @@ function updateElementValue(element, key, value, set, remove, isBoolean, json) {
|
|
|
29
30
|
if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
|
|
30
31
|
else set.call(element, key, json ? JSON.stringify(value) : String(value));
|
|
31
32
|
}
|
|
33
|
+
//#endregion
|
|
32
34
|
export { setElementValue, setElementValues, updateElementValue };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parse } from "@oscarpalmer/atoms/string";
|
|
2
|
+
import { camelCase, kebabCase } from "@oscarpalmer/atoms/string/case";
|
|
3
|
+
//#region src/internal/get-value.ts
|
|
2
4
|
function getBoolean(value, defaultValue) {
|
|
3
5
|
return typeof value === "boolean" ? value : defaultValue ?? false;
|
|
4
6
|
}
|
|
@@ -12,5 +14,6 @@ function getStyleValue(element, property, computed) {
|
|
|
12
14
|
const name = camelCase(property);
|
|
13
15
|
return computed ? getComputedStyle(element)[name] : element.style[name];
|
|
14
16
|
}
|
|
15
|
-
|
|
17
|
+
var EXPRESSION_DATA_PREFIX = /^data-/i;
|
|
18
|
+
//#endregion
|
|
16
19
|
export { EXPRESSION_DATA_PREFIX, getAttributeValue, getBoolean, getStyleValue };
|
package/dist/internal/is.js
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
//#region src/internal/is.ts
|
|
2
|
+
/**
|
|
3
|
+
* Is the value an event target?
|
|
4
|
+
* @param value Value to check
|
|
5
|
+
* @returns `true` if it's an event target, otherwise `false`
|
|
6
|
+
*/
|
|
1
7
|
function isEventTarget(value) {
|
|
2
8
|
return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
|
|
3
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Is the value an HTML or SVG element?
|
|
12
|
+
* @param value Value to check
|
|
13
|
+
* @returns `true` if it's an HTML or SVG element, otherwise `false`
|
|
14
|
+
*/
|
|
4
15
|
function isHTMLOrSVGElement(value) {
|
|
5
16
|
return value instanceof HTMLElement || value instanceof SVGElement;
|
|
6
17
|
}
|
|
18
|
+
//#endregion
|
|
7
19
|
export { isEventTarget, isHTMLOrSVGElement };
|
package/dist/is.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { isEventTarget, isHTMLOrSVGElement } from "./internal/is.js";
|
|
2
|
+
//#region src/is.ts
|
|
3
|
+
/**
|
|
4
|
+
* Is the value a child node?
|
|
5
|
+
* @param value Value to check
|
|
6
|
+
* @returns `true` if it's a child node, otherwise `false`
|
|
7
|
+
*/
|
|
2
8
|
function isChildNode(value) {
|
|
3
9
|
return value instanceof Node && CHILD_NODE_TYPES.has(value.nodeType);
|
|
4
10
|
}
|
|
@@ -14,4 +20,5 @@ var CHILD_NODE_TYPES = new Set([
|
|
|
14
20
|
Node.COMMENT_NODE,
|
|
15
21
|
Node.DOCUMENT_TYPE_NODE
|
|
16
22
|
]);
|
|
23
|
+
//#endregion
|
|
17
24
|
export { isChildNode, isEventTarget, isHTMLOrSVGElement, isInDocument };
|
package/dist/style.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import { getStyleValue } from "./internal/get-value.js";
|
|
2
2
|
import { isHTMLOrSVGElement } from "./internal/is.js";
|
|
3
3
|
import { setElementValues, updateElementValue } from "./internal/element-value.js";
|
|
4
|
+
//#region src/style.ts
|
|
5
|
+
/**
|
|
6
|
+
* Get a style from an element
|
|
7
|
+
* @param element Element to get the style from
|
|
8
|
+
* @param property Style name
|
|
9
|
+
* @param computed Get the computed style? _(defaults to `false`)_
|
|
10
|
+
* @returns Style value
|
|
11
|
+
*/
|
|
4
12
|
function getStyle(element, property, computed) {
|
|
5
13
|
if (!isHTMLOrSVGElement(element) || typeof property !== "string") return;
|
|
6
14
|
return getStyleValue(element, property, computed === true);
|
|
7
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Get styles from an element
|
|
18
|
+
* @param element Element to get the styles from
|
|
19
|
+
* @param properties Styles to get
|
|
20
|
+
* @param computed Get the computed styles? _(defaults to `false`)_
|
|
21
|
+
* @returns Style values
|
|
22
|
+
*/
|
|
8
23
|
function getStyles(element, properties, computed) {
|
|
9
24
|
const styles = {};
|
|
10
25
|
if (!(isHTMLOrSVGElement(element) && Array.isArray(properties))) return styles;
|
|
@@ -15,6 +30,12 @@ function getStyles(element, properties, computed) {
|
|
|
15
30
|
}
|
|
16
31
|
return styles;
|
|
17
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the text direction of an element
|
|
35
|
+
* @param element Element to get the text direction from
|
|
36
|
+
* @param computed Get the computed text direction? _(defaults to `false`)_
|
|
37
|
+
* @returns Text direction
|
|
38
|
+
*/
|
|
18
39
|
function getTextDirection(element, computed) {
|
|
19
40
|
if (!(element instanceof Element)) return;
|
|
20
41
|
const direction = element.getAttribute(ATTRIBUTE_DIRECTION);
|
|
@@ -22,12 +43,29 @@ function getTextDirection(element, computed) {
|
|
|
22
43
|
const value = getStyleValue(element, "direction", computed === true);
|
|
23
44
|
return value === "rtl" ? value : "ltr";
|
|
24
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Set a style on an element
|
|
48
|
+
* @param element Element to set the style on
|
|
49
|
+
* @param property Style name
|
|
50
|
+
* @param value Style value
|
|
51
|
+
*/
|
|
25
52
|
function setStyle(element, property, value) {
|
|
26
53
|
setElementValues(element, property, value, null, updateStyleProperty);
|
|
27
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Set styles on an element
|
|
57
|
+
* @param element Element to set the styles on
|
|
58
|
+
* @param styles Styles to set
|
|
59
|
+
*/
|
|
28
60
|
function setStyles(element, styles) {
|
|
29
61
|
setElementValues(element, styles, null, null, updateStyleProperty);
|
|
30
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Toggle styles for an element
|
|
65
|
+
* @param element Element to style
|
|
66
|
+
* @param styles Styles to be set or removed
|
|
67
|
+
* @returns Style toggler
|
|
68
|
+
*/
|
|
31
69
|
function toggleStyles(element, styles) {
|
|
32
70
|
function toggle(set) {
|
|
33
71
|
hasSet = set;
|
|
@@ -63,4 +101,5 @@ function updateStyleProperty(element, key, value) {
|
|
|
63
101
|
}
|
|
64
102
|
var ATTRIBUTE_DIRECTION = "dir";
|
|
65
103
|
var EXPRESSION_DIRECTION = /^(ltr|rtl)$/i;
|
|
104
|
+
//#endregion
|
|
66
105
|
export { getStyle, getStyles, getTextDirection, setStyle, setStyles, toggleStyles };
|
package/dist/toretto.full.js
CHANGED
|
@@ -9,7 +9,10 @@ function getSupport() {
|
|
|
9
9
|
if (typeof navigator.msMaxTouchPoints === "number" && navigator.msMaxTouchPoints > 0) return true;
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Does the device support touch events?
|
|
14
|
+
*/
|
|
15
|
+
const supportsTouch = (() => {
|
|
13
16
|
let support = getSupport();
|
|
14
17
|
const instance = Object.create({
|
|
15
18
|
get() {
|
|
@@ -25,9 +28,19 @@ var touch_default = (() => {
|
|
|
25
28
|
} });
|
|
26
29
|
return instance;
|
|
27
30
|
})();
|
|
31
|
+
/**
|
|
32
|
+
* Is the value a number?
|
|
33
|
+
* @param value Value to check
|
|
34
|
+
* @returns `true` if the value is a `number`, otherwise `false`
|
|
35
|
+
*/
|
|
28
36
|
function isNumber(value) {
|
|
29
37
|
return typeof value === "number" && !Number.isNaN(value);
|
|
30
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Is the value a plain object?
|
|
41
|
+
* @param value Value to check
|
|
42
|
+
* @returns `true` if the value is a plain object, otherwise `false`
|
|
43
|
+
*/
|
|
31
44
|
function isPlainObject(value) {
|
|
32
45
|
if (value === null || typeof value !== "object") return false;
|
|
33
46
|
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
@@ -45,6 +58,11 @@ function compact(array, strict) {
|
|
|
45
58
|
}
|
|
46
59
|
return compacted;
|
|
47
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Get the string value from any value
|
|
63
|
+
* @param value Original value
|
|
64
|
+
* @returns String representation of the value
|
|
65
|
+
*/
|
|
48
66
|
function getString(value) {
|
|
49
67
|
if (typeof value === "string") return value;
|
|
50
68
|
if (value == null) return "";
|
|
@@ -53,27 +71,54 @@ function getString(value) {
|
|
|
53
71
|
const asString = String(value.valueOf?.() ?? value);
|
|
54
72
|
return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
|
|
55
73
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Join an array of values into a string
|
|
76
|
+
* @param value Array of values
|
|
77
|
+
* @param delimiter Delimiter to use between values
|
|
78
|
+
* @returns Joined string
|
|
79
|
+
*/
|
|
59
80
|
function join(value, delimiter) {
|
|
60
81
|
return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
|
|
61
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Split a string into words _(and other readable parts)_
|
|
85
|
+
* @param value Original string
|
|
86
|
+
* @returns Array of words found in the string
|
|
87
|
+
*/
|
|
62
88
|
function words(value) {
|
|
63
89
|
return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
|
|
64
90
|
}
|
|
65
|
-
var EXPRESSION_IGNORED = /(^|\.)(__proto__|constructor|prototype)(\.|$)/i;
|
|
66
91
|
var EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
|
|
92
|
+
/**
|
|
93
|
+
* Is the value `undefined`, `null`, or a whitespace-only string?
|
|
94
|
+
* @param value Value to check
|
|
95
|
+
* @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
|
|
96
|
+
*/
|
|
67
97
|
function isNullableOrWhitespace(value) {
|
|
68
98
|
return value == null || EXPRESSION_WHITESPACE$1.test(getString(value));
|
|
69
99
|
}
|
|
70
100
|
var EXPRESSION_WHITESPACE$1 = /^\s*$/;
|
|
101
|
+
/**
|
|
102
|
+
* Is the value an event target?
|
|
103
|
+
* @param value Value to check
|
|
104
|
+
* @returns `true` if it's an event target, otherwise `false`
|
|
105
|
+
*/
|
|
71
106
|
function isEventTarget(value) {
|
|
72
107
|
return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
|
|
73
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Is the value an HTML or SVG element?
|
|
111
|
+
* @param value Value to check
|
|
112
|
+
* @returns `true` if it's an HTML or SVG element, otherwise `false`
|
|
113
|
+
*/
|
|
74
114
|
function isHTMLOrSVGElement(value) {
|
|
75
115
|
return value instanceof HTMLElement || value instanceof SVGElement;
|
|
76
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Is the value a child node?
|
|
119
|
+
* @param value Value to check
|
|
120
|
+
* @returns `true` if it's a child node, otherwise `false`
|
|
121
|
+
*/
|
|
77
122
|
function isChildNode(value) {
|
|
78
123
|
return value instanceof Node && CHILD_NODE_TYPES.has(value.nodeType);
|
|
79
124
|
}
|
|
@@ -186,6 +231,9 @@ const EXPRESSION_SOURCE_NAME = /^src$/i;
|
|
|
186
231
|
const EXPRESSION_SOURCE_VALUE = /^data:/i;
|
|
187
232
|
const EXPRESSION_URI_VALUE = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
|
|
188
233
|
const EXPRESSION_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
|
|
234
|
+
/**
|
|
235
|
+
* List of boolean attributes
|
|
236
|
+
*/
|
|
189
237
|
const booleanAttributes = Object.freeze([
|
|
190
238
|
"async",
|
|
191
239
|
"autofocus",
|
|
@@ -224,24 +272,27 @@ const elementEvents = {
|
|
|
224
272
|
};
|
|
225
273
|
const formElement = document.createElement("form");
|
|
226
274
|
let textArea;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
});
|
|
275
|
+
/**
|
|
276
|
+
* Parse a JSON string into its proper value _(or `undefined` if it fails)_
|
|
277
|
+
* @param value JSON string to parse
|
|
278
|
+
* @param reviver Reviver function to transform the parsed values
|
|
279
|
+
* @returns Parsed value or `undefined` if parsing fails
|
|
280
|
+
*/
|
|
281
|
+
function parse(value, reviver) {
|
|
282
|
+
try {
|
|
283
|
+
return JSON.parse(value, reviver);
|
|
284
|
+
} catch {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
240
287
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
288
|
+
/**
|
|
289
|
+
* Clamp a number between a minimum and maximum value
|
|
290
|
+
* @param value Value to clamp
|
|
291
|
+
* @param minimum Minimum value
|
|
292
|
+
* @param maximum Maximum value
|
|
293
|
+
* @param loop If `true`, the value will loop around when smaller than the minimum or larger than the maximum _(defaults to `false`)_
|
|
294
|
+
* @returns Clamped value
|
|
295
|
+
*/
|
|
245
296
|
function clamp(value, minimum, maximum, loop) {
|
|
246
297
|
if (![
|
|
247
298
|
value,
|
|
@@ -251,8 +302,27 @@ function clamp(value, minimum, maximum, loop) {
|
|
|
251
302
|
if (value < minimum) return loop === true ? maximum : minimum;
|
|
252
303
|
return value > maximum ? loop === true ? minimum : maximum : value;
|
|
253
304
|
}
|
|
305
|
+
function getSizedMaximum(first, second) {
|
|
306
|
+
let actual;
|
|
307
|
+
if (typeof first === "number") actual = first;
|
|
308
|
+
else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
|
|
309
|
+
return clamp(actual, 1, MAXIMUM_ABSOLUTE);
|
|
310
|
+
}
|
|
311
|
+
var MAXIMUM_ABSOLUTE = 16777216;
|
|
312
|
+
var MAXIMUM_DEFAULT = 1048576;
|
|
313
|
+
/**
|
|
314
|
+
* A Map with a maximum size
|
|
315
|
+
*
|
|
316
|
+
* Behavior is similar to a _LRU_-cache, where the least recently used entries are removed
|
|
317
|
+
*/
|
|
254
318
|
var SizedMap = class extends Map {
|
|
319
|
+
/**
|
|
320
|
+
* The maximum size of the Map
|
|
321
|
+
*/
|
|
255
322
|
#maximumSize;
|
|
323
|
+
/**
|
|
324
|
+
* Is the Map full?
|
|
325
|
+
*/
|
|
256
326
|
get full() {
|
|
257
327
|
return this.size >= this.#maximumSize;
|
|
258
328
|
}
|
|
@@ -260,7 +330,7 @@ var SizedMap = class extends Map {
|
|
|
260
330
|
return this.#maximumSize;
|
|
261
331
|
}
|
|
262
332
|
constructor(first, second) {
|
|
263
|
-
const maximum =
|
|
333
|
+
const maximum = getSizedMaximum(first, second);
|
|
264
334
|
super();
|
|
265
335
|
this.#maximumSize = maximum;
|
|
266
336
|
if (Array.isArray(first)) {
|
|
@@ -269,37 +339,41 @@ var SizedMap = class extends Map {
|
|
|
269
339
|
else for (let index = 0; index < maximum; index += 1) this.set(...first[length - maximum + index]);
|
|
270
340
|
}
|
|
271
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* @inheritdoc
|
|
344
|
+
*/
|
|
272
345
|
get(key) {
|
|
273
346
|
const value = super.get(key);
|
|
274
347
|
if (value !== void 0 || this.has(key)) this.set(key, value);
|
|
275
348
|
return value;
|
|
276
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* @inheritdoc
|
|
352
|
+
*/
|
|
277
353
|
set(key, value) {
|
|
278
354
|
if (this.has(key)) this.delete(key);
|
|
279
355
|
else if (this.size >= this.#maximumSize) this.delete(this.keys().next().value);
|
|
280
356
|
return super.set(key, value);
|
|
281
357
|
}
|
|
282
358
|
};
|
|
283
|
-
function getMaximum(first, second) {
|
|
284
|
-
let actual;
|
|
285
|
-
if (typeof first === "number") actual = first;
|
|
286
|
-
else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
|
|
287
|
-
return clamp(actual, 1, MAXIMUM_ABSOLUTE);
|
|
288
|
-
}
|
|
289
|
-
var MAXIMUM_ABSOLUTE = 16777216;
|
|
290
|
-
var MAXIMUM_DEFAULT = 1048576;
|
|
291
359
|
var Memoized = class {
|
|
292
360
|
#state;
|
|
361
|
+
/**
|
|
362
|
+
* Maximum cache size
|
|
363
|
+
*/
|
|
293
364
|
get maximum() {
|
|
294
365
|
return this.#state.cache?.maximum ?? NaN;
|
|
295
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Current cache size
|
|
369
|
+
*/
|
|
296
370
|
get size() {
|
|
297
371
|
return this.#state.cache?.size ?? NaN;
|
|
298
372
|
}
|
|
299
373
|
constructor(callback, options) {
|
|
300
374
|
const cache = new SizedMap(options.cacheSize);
|
|
301
375
|
const getter = (...parameters) => {
|
|
302
|
-
const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString),
|
|
376
|
+
const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), SEPARATOR));
|
|
303
377
|
if (cache.has(key)) return cache.get(key);
|
|
304
378
|
const value = callback(...parameters);
|
|
305
379
|
cache.set(key, value);
|
|
@@ -310,23 +384,49 @@ var Memoized = class {
|
|
|
310
384
|
getter
|
|
311
385
|
};
|
|
312
386
|
}
|
|
387
|
+
/**
|
|
388
|
+
* Clear the cache
|
|
389
|
+
*/
|
|
313
390
|
clear() {
|
|
314
391
|
this.#state.cache?.clear();
|
|
315
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Delete a result from the cache
|
|
395
|
+
* @param key Key to delete
|
|
396
|
+
* @returns `true` if the key existed and was removed, otherwise `false`
|
|
397
|
+
*/
|
|
316
398
|
delete(key) {
|
|
317
399
|
return this.#state.cache?.delete(key) ?? false;
|
|
318
400
|
}
|
|
401
|
+
/**
|
|
402
|
+
* Destroy the instance _(clearing its cache and removing its callback)_
|
|
403
|
+
*/
|
|
319
404
|
destroy() {
|
|
320
405
|
this.#state.cache?.clear();
|
|
321
406
|
this.#state.cache = void 0;
|
|
322
407
|
this.#state.getter = void 0;
|
|
323
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Get a result from the cache
|
|
411
|
+
* @param key Key to get
|
|
412
|
+
* @returns Cached result or `undefined` if it does not exist
|
|
413
|
+
*/
|
|
324
414
|
get(key) {
|
|
325
415
|
return this.#state.cache?.get(key);
|
|
326
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* Does the result exist?
|
|
419
|
+
* @param key Key to check
|
|
420
|
+
* @returns `true` if the result exists, otherwise `false`
|
|
421
|
+
*/
|
|
327
422
|
has(key) {
|
|
328
423
|
return this.#state.cache?.has(key) ?? false;
|
|
329
424
|
}
|
|
425
|
+
/**
|
|
426
|
+
* Run the callback with the provided parameters
|
|
427
|
+
* @param parameters Parameters to pass to the callback
|
|
428
|
+
* @returns Cached or computed _(then cached)_ result
|
|
429
|
+
*/
|
|
330
430
|
run(...parameters) {
|
|
331
431
|
if (this.#state.cache == null || this.#state.getter == null) throw new Error("The Memoized instance has been destroyed");
|
|
332
432
|
return this.#state.getter(...parameters);
|
|
@@ -339,20 +439,42 @@ function getMemoizationOptions(input) {
|
|
|
339
439
|
cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
|
|
340
440
|
};
|
|
341
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Memoize a function, caching and retrieving results based on the first parameter
|
|
444
|
+
* @param callback Callback to memoize
|
|
445
|
+
* @param options Memoization options
|
|
446
|
+
* @returns Memoized instance
|
|
447
|
+
*/
|
|
342
448
|
function memoize(callback, options) {
|
|
343
449
|
return new Memoized(callback, getMemoizationOptions(options));
|
|
344
450
|
}
|
|
345
451
|
var DEFAULT_CACHE_SIZE = 1024;
|
|
452
|
+
var SEPARATOR = "_";
|
|
453
|
+
/**
|
|
454
|
+
* Convert a string to camel case _(thisIsCamelCase)_
|
|
455
|
+
* @param value String to convert
|
|
456
|
+
* @returns Camel-cased string
|
|
457
|
+
*/
|
|
346
458
|
function camelCase(value) {
|
|
347
|
-
return toCase(
|
|
459
|
+
return toCase(CASE_CAMEL, value, true, false);
|
|
348
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* Capitalize the first letter of a string _(and lowercase the rest)_
|
|
463
|
+
* @param value String to capitalize
|
|
464
|
+
* @returns Capitalized string
|
|
465
|
+
*/
|
|
349
466
|
function capitalize(value) {
|
|
350
467
|
if (typeof value !== "string" || value.length === 0) return "";
|
|
351
468
|
memoizedCapitalize ??= memoize((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
|
|
352
469
|
return memoizedCapitalize.run(value);
|
|
353
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* Convert a string to kebab case _(this-is-kebab-case)_
|
|
473
|
+
* @param value String to convert
|
|
474
|
+
* @returns Kebab-cased string
|
|
475
|
+
*/
|
|
354
476
|
function kebabCase(value) {
|
|
355
|
-
return toCase(
|
|
477
|
+
return toCase(CASE_KEBAB, value, false, false);
|
|
356
478
|
}
|
|
357
479
|
function toCase(type, value, capitalizeAny, capitalizeFirst) {
|
|
358
480
|
caseMemoizers[type] ??= memoize(toCaseCallback.bind({
|
|
@@ -370,7 +492,7 @@ function toCaseCallback(value) {
|
|
|
370
492
|
const partsLength = parts.length;
|
|
371
493
|
const cased = [];
|
|
372
494
|
for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
|
|
373
|
-
const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three ===
|
|
495
|
+
const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === S ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, REPLACEMENT_CAMEL_CASE).split("-");
|
|
374
496
|
const itemsLength = items.length;
|
|
375
497
|
const partResult = [];
|
|
376
498
|
let itemCount = 0;
|
|
@@ -385,85 +507,25 @@ function toCaseCallback(value) {
|
|
|
385
507
|
}
|
|
386
508
|
return join(cased, delimiters[type]);
|
|
387
509
|
}
|
|
388
|
-
var
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
510
|
+
var CASE_CAMEL = "camel";
|
|
511
|
+
var CASE_KEBAB = "kebab";
|
|
512
|
+
var CASE_PASCAL = "pascal";
|
|
513
|
+
var CASE_SNAKE = "snake";
|
|
514
|
+
var DELIMTER_EMPTY = "";
|
|
515
|
+
var DELIMITER_HYPHEN = "-";
|
|
516
|
+
var DELIMITER_UNDERSCORE = "_";
|
|
394
517
|
var EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
|
|
395
518
|
var EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
|
|
396
|
-
var caseMemoizers = {};
|
|
397
519
|
var REPLACEMENT_CAMEL_CASE = "$1-$2";
|
|
398
|
-
var
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
406
|
-
function findKey(needle, haystack) {
|
|
407
|
-
const keys = Object.keys(haystack);
|
|
408
|
-
const index = keys.map((key) => key.toLowerCase()).indexOf(needle.toLowerCase());
|
|
409
|
-
return index > -1 ? keys[index] : needle;
|
|
410
|
-
}
|
|
411
|
-
function getPaths(path, lowercase) {
|
|
412
|
-
const normalized = lowercase ? path.toLowerCase() : path;
|
|
413
|
-
if (!EXPRESSION_NESTED.test(normalized)) return normalized;
|
|
414
|
-
return normalized.replace(EXPRESSION_BRACKET, ".$1").replace(EXPRESSION_DOTS, "").split(".");
|
|
415
|
-
}
|
|
416
|
-
function handleValue(data, path, value, get, ignoreCase) {
|
|
417
|
-
if (typeof data === "object" && data !== null && !ignoreKey(path)) {
|
|
418
|
-
const key = ignoreCase ? findKey(path, data) : path;
|
|
419
|
-
if (get) return data[key];
|
|
420
|
-
data[key] = typeof value === "function" ? value(data[key]) : value;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
var EXPRESSION_BRACKET = /\[(\w+)\]/g;
|
|
424
|
-
var EXPRESSION_DOTS = /^\.|\.$/g;
|
|
425
|
-
var EXPRESSION_NESTED = /\.|\[\w+\]/;
|
|
426
|
-
function getValue(data, path, ignoreCase) {
|
|
427
|
-
if (typeof data !== "object" || data === null || typeof path !== "string" || path.trim().length === 0) return;
|
|
428
|
-
const shouldIgnoreCase = ignoreCase === true;
|
|
429
|
-
const paths = getPaths(path, shouldIgnoreCase);
|
|
430
|
-
if (typeof paths === "string") return handleValue(data, paths, null, true, shouldIgnoreCase);
|
|
431
|
-
const { length } = paths;
|
|
432
|
-
let index = 0;
|
|
433
|
-
let value = data;
|
|
434
|
-
while (index < length && value != null) value = handleValue(value, paths[index++], null, true, shouldIgnoreCase);
|
|
435
|
-
return value;
|
|
436
|
-
}
|
|
437
|
-
function getTemplateOptions(input) {
|
|
438
|
-
const options = isPlainObject(input) ? input : {};
|
|
439
|
-
return {
|
|
440
|
-
ignoreCase: options.ignoreCase === true,
|
|
441
|
-
pattern: options.pattern instanceof RegExp ? options.pattern : EXPRESSION_VARIABLE
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
function handleTemplate(value, pattern, ignoreCase, variables) {
|
|
445
|
-
if (typeof value !== "string") return "";
|
|
446
|
-
if (typeof variables !== "object" || variables === null) return value;
|
|
447
|
-
const values = {};
|
|
448
|
-
return value.replace(pattern, (_, key) => {
|
|
449
|
-
if (values[key] == null) {
|
|
450
|
-
const templateValue = getValue(variables, key, ignoreCase);
|
|
451
|
-
values[key] = templateValue == null ? "" : getString(templateValue);
|
|
452
|
-
}
|
|
453
|
-
return values[key];
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
function template(value, variables, options) {
|
|
457
|
-
const { ignoreCase, pattern } = getTemplateOptions(options);
|
|
458
|
-
return handleTemplate(value, pattern, ignoreCase, variables);
|
|
459
|
-
}
|
|
460
|
-
template.initialize = function(options) {
|
|
461
|
-
const { ignoreCase, pattern } = getTemplateOptions(options);
|
|
462
|
-
return (value, variables) => {
|
|
463
|
-
return handleTemplate(value, pattern, ignoreCase, variables);
|
|
464
|
-
};
|
|
520
|
+
var S = "s";
|
|
521
|
+
var caseMemoizers = {};
|
|
522
|
+
var delimiters = {
|
|
523
|
+
[CASE_CAMEL]: DELIMTER_EMPTY,
|
|
524
|
+
[CASE_KEBAB]: DELIMITER_HYPHEN,
|
|
525
|
+
[CASE_PASCAL]: DELIMTER_EMPTY,
|
|
526
|
+
[CASE_SNAKE]: DELIMITER_UNDERSCORE
|
|
465
527
|
};
|
|
466
|
-
var
|
|
528
|
+
var memoizedCapitalize;
|
|
467
529
|
function getBoolean(value, defaultValue) {
|
|
468
530
|
return typeof value === "boolean" ? value : defaultValue ?? false;
|
|
469
531
|
}
|
|
@@ -515,6 +577,163 @@ function updateDataAttribute(element, key, value) {
|
|
|
515
577
|
updateElementValue(element, getName(key), value, element.setAttribute, element.removeAttribute, false, true);
|
|
516
578
|
}
|
|
517
579
|
const ATTRIBUTE_DATA_PREFIX = "data-";
|
|
580
|
+
/**
|
|
581
|
+
* A function that does nothing, which can be useful, I guess…
|
|
582
|
+
*/
|
|
583
|
+
function noop() {}
|
|
584
|
+
/**
|
|
585
|
+
* Asserts that a condition is true, throwing an error if it is not
|
|
586
|
+
* @param condition Condition to assert
|
|
587
|
+
* @param message Error message
|
|
588
|
+
* @param error Error constructor
|
|
589
|
+
*/
|
|
590
|
+
function assert(condition, message, error) {
|
|
591
|
+
if (!condition()) throw new (error ?? Error)(message);
|
|
592
|
+
}
|
|
593
|
+
assert.condition = assertCondition;
|
|
594
|
+
assert.defined = assertDefined;
|
|
595
|
+
assert.instanceOf = assertInstanceOf;
|
|
596
|
+
assert.is = assertIs;
|
|
597
|
+
/**
|
|
598
|
+
* Creates an asserter that asserts a condition is true, throwing an error if it is not
|
|
599
|
+
* @param condition Condition to assert
|
|
600
|
+
* @param message Error message
|
|
601
|
+
* @param error Error constructor
|
|
602
|
+
* @returns Asserter
|
|
603
|
+
*/
|
|
604
|
+
function assertCondition(condition, message, error) {
|
|
605
|
+
return (value) => {
|
|
606
|
+
assert(() => condition(value), message, error);
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Asserts that a value is defined throwing an error if it is not
|
|
611
|
+
* @param value Value to assert
|
|
612
|
+
* @param message Error message
|
|
613
|
+
*/
|
|
614
|
+
function assertDefined(value, message) {
|
|
615
|
+
assert(() => value != null, message ?? MESSAGE_VALUE_DEFINED);
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Creates an asserter that asserts a value is an instance of a constructor, throwing an error if it is not
|
|
619
|
+
* @param constructor Constructor to check against
|
|
620
|
+
* @param message Error message
|
|
621
|
+
* @param error Error constructor
|
|
622
|
+
* @returns Asserter
|
|
623
|
+
*/
|
|
624
|
+
function assertInstanceOf(constructor, message, error) {
|
|
625
|
+
return (value) => {
|
|
626
|
+
assert(() => value instanceof constructor, message, error);
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Creates an asserter that asserts a value is of a specific type, throwing an error if it is not
|
|
631
|
+
* @param condition Type guard function to check the value
|
|
632
|
+
* @param message Error message
|
|
633
|
+
* @param error Error constructor
|
|
634
|
+
* @returns Asserter
|
|
635
|
+
*/
|
|
636
|
+
function assertIs(condition, message, error) {
|
|
637
|
+
return (value) => {
|
|
638
|
+
assert(() => condition(value), message, error);
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
var MESSAGE_VALUE_DEFINED = "Expected value to be defined";
|
|
642
|
+
/**
|
|
643
|
+
* Create an asynchronous function that can only be called once, rejecting or resolving the same result on subsequent calls
|
|
644
|
+
* @param callback Callback to use once
|
|
645
|
+
* @returns Once callback
|
|
646
|
+
*/
|
|
647
|
+
function asyncOnce(callback) {
|
|
648
|
+
assert(() => typeof callback === "function", MESSAGE_EXPECTATION);
|
|
649
|
+
const state = {
|
|
650
|
+
called: false,
|
|
651
|
+
cleared: false,
|
|
652
|
+
error: false,
|
|
653
|
+
finished: false,
|
|
654
|
+
items: [],
|
|
655
|
+
value: void 0
|
|
656
|
+
};
|
|
657
|
+
const fn = (...parameters) => {
|
|
658
|
+
if (state.cleared) return Promise.reject(new Error(MESSAGE_CLEARED));
|
|
659
|
+
if (state.finished) return state.error ? Promise.reject(state.value) : Promise.resolve(state.value);
|
|
660
|
+
if (state.called) return new Promise((resolve, reject) => {
|
|
661
|
+
state.items.push({
|
|
662
|
+
reject,
|
|
663
|
+
resolve
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
state.called = true;
|
|
667
|
+
return new Promise((resolve, reject) => {
|
|
668
|
+
state.items.push({
|
|
669
|
+
reject,
|
|
670
|
+
resolve
|
|
671
|
+
});
|
|
672
|
+
callback(...parameters).then((value) => {
|
|
673
|
+
handleResult(state, value, false);
|
|
674
|
+
}).catch((error) => {
|
|
675
|
+
handleResult(state, error, true);
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
};
|
|
679
|
+
Object.defineProperties(fn, {
|
|
680
|
+
called: { get: () => state.called },
|
|
681
|
+
cleared: { get: () => state.cleared },
|
|
682
|
+
error: { get: () => state.error },
|
|
683
|
+
finished: { get: () => state.finished }
|
|
684
|
+
});
|
|
685
|
+
fn.clear = () => {
|
|
686
|
+
if (!state.called || !state.finished || state.cleared) return;
|
|
687
|
+
state.cleared = true;
|
|
688
|
+
state.value = void 0;
|
|
689
|
+
};
|
|
690
|
+
return fn;
|
|
691
|
+
}
|
|
692
|
+
function handleResult(state, value, error) {
|
|
693
|
+
state.error = error;
|
|
694
|
+
state.finished = true;
|
|
695
|
+
state.value = value;
|
|
696
|
+
const items = state.items.splice(0);
|
|
697
|
+
const { length } = items;
|
|
698
|
+
for (let index = 0; index < length; index += 1) {
|
|
699
|
+
const { reject, resolve } = items[index];
|
|
700
|
+
if (error) reject(value);
|
|
701
|
+
else resolve(value);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Create a function that can only be called once, returning the same value on subsequent calls
|
|
706
|
+
* @param callback Callback to use once
|
|
707
|
+
* @returns Once callback
|
|
708
|
+
*/
|
|
709
|
+
function once(callback) {
|
|
710
|
+
assert(() => typeof callback === "function", MESSAGE_EXPECTATION);
|
|
711
|
+
const state = {
|
|
712
|
+
called: false,
|
|
713
|
+
cleared: false,
|
|
714
|
+
value: void 0
|
|
715
|
+
};
|
|
716
|
+
const fn = (...parameters) => {
|
|
717
|
+
if (state.cleared) throw new Error(MESSAGE_CLEARED);
|
|
718
|
+
if (state.called) return state.value;
|
|
719
|
+
state.called = true;
|
|
720
|
+
state.value = callback(...parameters);
|
|
721
|
+
return state.value;
|
|
722
|
+
};
|
|
723
|
+
Object.defineProperties(fn, {
|
|
724
|
+
called: { get: () => state.called },
|
|
725
|
+
cleared: { get: () => state.cleared }
|
|
726
|
+
});
|
|
727
|
+
fn.clear = () => {
|
|
728
|
+
if (!state.called || state.cleared) return;
|
|
729
|
+
state.cleared = true;
|
|
730
|
+
state.value = void 0;
|
|
731
|
+
};
|
|
732
|
+
return fn;
|
|
733
|
+
}
|
|
734
|
+
once.async = asyncOnce;
|
|
735
|
+
var MESSAGE_CLEARED = "Once has been cleared";
|
|
736
|
+
var MESSAGE_EXPECTATION = "Once expected a function";
|
|
518
737
|
function addDelegatedHandler(doc, type, name, passive) {
|
|
519
738
|
if (DELEGATED.has(name)) return;
|
|
520
739
|
DELEGATED.add(name);
|
|
@@ -622,6 +841,11 @@ function createEventOptions(options) {
|
|
|
622
841
|
function dispatch(target, type, options) {
|
|
623
842
|
if (isEventTarget(target) && typeof type === "string") target.dispatchEvent(createEvent(type, options));
|
|
624
843
|
}
|
|
844
|
+
/**
|
|
845
|
+
* Get the X- and Y-coordinates from a pointer event
|
|
846
|
+
* @param event Pointer event
|
|
847
|
+
* @returns X- and Y-coordinates
|
|
848
|
+
*/
|
|
625
849
|
function getPosition(event) {
|
|
626
850
|
let x;
|
|
627
851
|
let y;
|
|
@@ -637,6 +861,13 @@ function getPosition(event) {
|
|
|
637
861
|
y
|
|
638
862
|
} : void 0;
|
|
639
863
|
}
|
|
864
|
+
/**
|
|
865
|
+
* Remove an event listener
|
|
866
|
+
* @param target Event target
|
|
867
|
+
* @param type Type of event
|
|
868
|
+
* @param listener Event listener
|
|
869
|
+
* @param options Options for event
|
|
870
|
+
*/
|
|
640
871
|
function off(target, type, listener, options) {
|
|
641
872
|
if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return;
|
|
642
873
|
const extended = createEventOptions(options);
|
|
@@ -691,6 +922,12 @@ function findRelatives(origin, selector, context) {
|
|
|
691
922
|
}
|
|
692
923
|
return distances.filter((found) => found.distance === minimum).map((found) => found.element);
|
|
693
924
|
}
|
|
925
|
+
/**
|
|
926
|
+
* Get the distance between two elements _(i.e., the amount of nodes of between them)_
|
|
927
|
+
* @param origin Origin element
|
|
928
|
+
* @param target Target element
|
|
929
|
+
* @returns Distance between elements, or `-1` if distance cannot be calculated
|
|
930
|
+
*/
|
|
694
931
|
function getDistance(origin, target) {
|
|
695
932
|
if (origin === target) return 0;
|
|
696
933
|
if (origin.parentElement === target || target.parentElement === origin) return 1;
|
|
@@ -766,6 +1003,14 @@ function findElementOrElementsFromNodes(array, context, contexts) {
|
|
|
766
1003
|
function findElements(selector, context) {
|
|
767
1004
|
return findElementOrElements(selector, context, false);
|
|
768
1005
|
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Get the most specific element under the pointer
|
|
1008
|
+
*
|
|
1009
|
+
* - Ignores elements with `pointer-events: none` and `visibility: hidden`
|
|
1010
|
+
* - _(If `skipIgnore` is `true`, no elements are ignored)_
|
|
1011
|
+
* @param skipIgnore Skip ignored elements?
|
|
1012
|
+
* @returns Found element or `null`
|
|
1013
|
+
*/
|
|
769
1014
|
function getElementUnderPointer(skipIgnore) {
|
|
770
1015
|
const elements = [...document.querySelectorAll(SUFFIX_HOVER)];
|
|
771
1016
|
const { length } = elements;
|
|
@@ -787,6 +1032,11 @@ const STYLE_HIDDEN$1 = "hidden";
|
|
|
787
1032
|
const STYLE_NONE$1 = "none";
|
|
788
1033
|
const SUFFIX_HOVER = ":hover";
|
|
789
1034
|
const TAG_HEAD = "HEAD";
|
|
1035
|
+
/**
|
|
1036
|
+
* Get a list of focusable elements within a parent element
|
|
1037
|
+
* @param parent Parent element
|
|
1038
|
+
* @returns Focusable elements
|
|
1039
|
+
*/
|
|
790
1040
|
function getFocusable(parent) {
|
|
791
1041
|
return getValidElements(parent, FILTERS_FOCUSABLE, false);
|
|
792
1042
|
}
|
|
@@ -796,6 +1046,11 @@ function getItem(element, tabbable) {
|
|
|
796
1046
|
tabIndex: tabbable ? getTabIndex(element) : TABINDEX_DEFAULT
|
|
797
1047
|
};
|
|
798
1048
|
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Get a list of tabbable elements within a parent element
|
|
1051
|
+
* @param parent Parent element
|
|
1052
|
+
* @returns Tabbable elements
|
|
1053
|
+
*/
|
|
799
1054
|
function getTabbable(parent) {
|
|
800
1055
|
return getValidElements(parent, FILTERS_TABBABLE, true);
|
|
801
1056
|
}
|
|
@@ -850,6 +1105,11 @@ function isDisabledFromFieldset(element) {
|
|
|
850
1105
|
function isEditable(element) {
|
|
851
1106
|
return EXPRESSION_TRUEISH.test(element.getAttribute(ATTRIBUTE_CONTENTEDITABLE));
|
|
852
1107
|
}
|
|
1108
|
+
/**
|
|
1109
|
+
* Is the element focusable?
|
|
1110
|
+
* @param element Element to check
|
|
1111
|
+
* @returns `true` if focusable, otherwise `false`
|
|
1112
|
+
*/
|
|
853
1113
|
function isFocusable(element) {
|
|
854
1114
|
return element instanceof Element ? isValidElement(element, FILTERS_FOCUSABLE, false) : false;
|
|
855
1115
|
}
|
|
@@ -880,6 +1140,11 @@ function isNotTabbableRadio(item) {
|
|
|
880
1140
|
function isSummarised(item) {
|
|
881
1141
|
return item.element instanceof HTMLDetailsElement && [...item.element.children].some((child) => EXPRESSION_SUMMARY.test(child.tagName));
|
|
882
1142
|
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Is the element tabbable?
|
|
1145
|
+
* @param element Element to check
|
|
1146
|
+
* @returns `true` if tabbable, otherwise `false`
|
|
1147
|
+
*/
|
|
883
1148
|
function isTabbable(element) {
|
|
884
1149
|
return element instanceof Element ? isValidElement(element, FILTERS_TABBABLE, true) : false;
|
|
885
1150
|
}
|
|
@@ -935,6 +1200,11 @@ function handleElement(element, depth) {
|
|
|
935
1200
|
}
|
|
936
1201
|
sanitizeAttributes(element, [...element.attributes]);
|
|
937
1202
|
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Is the element clobbered?
|
|
1205
|
+
*
|
|
1206
|
+
* Thanks, DOMPurify _(https://github.com/cure53/DOMPurify)_
|
|
1207
|
+
*/
|
|
938
1208
|
function isClobbered(value) {
|
|
939
1209
|
return value instanceof HTMLFormElement && (typeof value.nodeName !== "string" || typeof value.textContent !== "string" || typeof value.removeChild !== "function" || !(value.attributes instanceof NamedNodeMap) || typeof value.removeAttribute !== "function" || typeof value.setAttribute !== "function" || typeof value.namespaceURI !== "string" || typeof value.insertBefore !== "function" || typeof value.hasChildNodes !== "function");
|
|
940
1210
|
}
|
|
@@ -1034,6 +1304,12 @@ html.remove = (template) => {
|
|
|
1034
1304
|
}
|
|
1035
1305
|
templates = updated;
|
|
1036
1306
|
};
|
|
1307
|
+
/**
|
|
1308
|
+
* Sanitize one or more nodes, recursively
|
|
1309
|
+
* @param value Node or nodes to sanitize
|
|
1310
|
+
* @param options Sanitization options
|
|
1311
|
+
* @returns Sanitized nodes
|
|
1312
|
+
*/
|
|
1037
1313
|
function sanitize(value) {
|
|
1038
1314
|
return sanitizeNodes(Array.isArray(value) ? value : [value], 0);
|
|
1039
1315
|
}
|
|
@@ -1043,10 +1319,24 @@ const TEMPLATE_TAG = "template";
|
|
|
1043
1319
|
const TEMPORARY_ELEMENT = "<toretto-temporary></toretto-temporary>";
|
|
1044
1320
|
let parser;
|
|
1045
1321
|
let templates = {};
|
|
1322
|
+
/**
|
|
1323
|
+
* Get a style from an element
|
|
1324
|
+
* @param element Element to get the style from
|
|
1325
|
+
* @param property Style name
|
|
1326
|
+
* @param computed Get the computed style? _(defaults to `false`)_
|
|
1327
|
+
* @returns Style value
|
|
1328
|
+
*/
|
|
1046
1329
|
function getStyle(element, property, computed) {
|
|
1047
1330
|
if (!isHTMLOrSVGElement(element) || typeof property !== "string") return;
|
|
1048
1331
|
return getStyleValue(element, property, computed === true);
|
|
1049
1332
|
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Get styles from an element
|
|
1335
|
+
* @param element Element to get the styles from
|
|
1336
|
+
* @param properties Styles to get
|
|
1337
|
+
* @param computed Get the computed styles? _(defaults to `false`)_
|
|
1338
|
+
* @returns Style values
|
|
1339
|
+
*/
|
|
1050
1340
|
function getStyles(element, properties, computed) {
|
|
1051
1341
|
const styles = {};
|
|
1052
1342
|
if (!(isHTMLOrSVGElement(element) && Array.isArray(properties))) return styles;
|
|
@@ -1057,6 +1347,12 @@ function getStyles(element, properties, computed) {
|
|
|
1057
1347
|
}
|
|
1058
1348
|
return styles;
|
|
1059
1349
|
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Get the text direction of an element
|
|
1352
|
+
* @param element Element to get the text direction from
|
|
1353
|
+
* @param computed Get the computed text direction? _(defaults to `false`)_
|
|
1354
|
+
* @returns Text direction
|
|
1355
|
+
*/
|
|
1060
1356
|
function getTextDirection(element, computed) {
|
|
1061
1357
|
if (!(element instanceof Element)) return;
|
|
1062
1358
|
const direction = element.getAttribute(ATTRIBUTE_DIRECTION);
|
|
@@ -1064,12 +1360,29 @@ function getTextDirection(element, computed) {
|
|
|
1064
1360
|
const value = getStyleValue(element, "direction", computed === true);
|
|
1065
1361
|
return value === "rtl" ? value : "ltr";
|
|
1066
1362
|
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Set a style on an element
|
|
1365
|
+
* @param element Element to set the style on
|
|
1366
|
+
* @param property Style name
|
|
1367
|
+
* @param value Style value
|
|
1368
|
+
*/
|
|
1067
1369
|
function setStyle(element, property, value) {
|
|
1068
1370
|
setElementValues(element, property, value, null, updateStyleProperty);
|
|
1069
1371
|
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Set styles on an element
|
|
1374
|
+
* @param element Element to set the styles on
|
|
1375
|
+
* @param styles Styles to set
|
|
1376
|
+
*/
|
|
1070
1377
|
function setStyles(element, styles) {
|
|
1071
1378
|
setElementValues(element, styles, null, null, updateStyleProperty);
|
|
1072
1379
|
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Toggle styles for an element
|
|
1382
|
+
* @param element Element to style
|
|
1383
|
+
* @param styles Styles to be set or removed
|
|
1384
|
+
* @returns Style toggler
|
|
1385
|
+
*/
|
|
1073
1386
|
function toggleStyles(element, styles) {
|
|
1074
1387
|
function toggle(set) {
|
|
1075
1388
|
hasSet = set;
|
|
@@ -1105,4 +1418,4 @@ function updateStyleProperty(element, key, value) {
|
|
|
1105
1418
|
}
|
|
1106
1419
|
const ATTRIBUTE_DIRECTION = "dir";
|
|
1107
1420
|
const EXPRESSION_DIRECTION = /^(ltr|rtl)$/i;
|
|
1108
|
-
export { findElement as $, findElement, findElements as $$, findElements, dispatch, findAncestor, findRelatives, getData, getDistance, getElementUnderPointer, getFocusable, getPosition, getStyle, getStyles, getTabbable, getTextDirection, html, isBadAttribute, isBooleanAttribute, isChildNode, isEmptyNonBooleanAttribute, isEventTarget, isFocusable, isHTMLOrSVGElement, isInDocument, isInvalidBooleanAttribute, isTabbable, off, on, sanitize, setData, setStyle, setStyles,
|
|
1421
|
+
export { findElement as $, findElement, findElements as $$, findElements, dispatch, findAncestor, findRelatives, getData, getDistance, getElementUnderPointer, getFocusable, getPosition, getStyle, getStyles, getTabbable, getTextDirection, html, isBadAttribute, isBooleanAttribute, isChildNode, isEmptyNonBooleanAttribute, isEventTarget, isFocusable, isHTMLOrSVGElement, isInDocument, isInvalidBooleanAttribute, isTabbable, off, on, sanitize, setData, setStyle, setStyles, supportsTouch, toggleStyles };
|
package/dist/touch.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/touch.ts
|
|
1
2
|
function getSupport() {
|
|
2
3
|
if (window == null || navigator == null) return false;
|
|
3
4
|
if ("matchMedia" in window) {
|
|
@@ -9,7 +10,10 @@ function getSupport() {
|
|
|
9
10
|
if (typeof navigator.msMaxTouchPoints === "number" && navigator.msMaxTouchPoints > 0) return true;
|
|
10
11
|
return false;
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Does the device support touch events?
|
|
15
|
+
*/
|
|
16
|
+
var supportsTouch = (() => {
|
|
13
17
|
let support = getSupport();
|
|
14
18
|
const instance = Object.create({
|
|
15
19
|
get() {
|
|
@@ -25,4 +29,5 @@ var touch_default = (() => {
|
|
|
25
29
|
} });
|
|
26
30
|
return instance;
|
|
27
31
|
})();
|
|
28
|
-
|
|
32
|
+
//#endregion
|
|
33
|
+
export { supportsTouch as default };
|
package/package.json
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
"url": "https://oscarpalmer.se"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@oscarpalmer/atoms": "^0.
|
|
7
|
+
"@oscarpalmer/atoms": "^0.162"
|
|
8
8
|
},
|
|
9
9
|
"description": "A collection of badass DOM utilities.",
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"@types/node": "^25.
|
|
11
|
+
"@types/node": "^25.4",
|
|
12
12
|
"@vitest/coverage-istanbul": "^4",
|
|
13
|
-
"jsdom": "^
|
|
14
|
-
"oxfmt": "^0.
|
|
15
|
-
"oxlint": "^1.
|
|
16
|
-
"rolldown": "1.0.0-rc.
|
|
13
|
+
"jsdom": "^28.1",
|
|
14
|
+
"oxfmt": "^0.39",
|
|
15
|
+
"oxlint": "^1.54",
|
|
16
|
+
"rolldown": "1.0.0-rc.9",
|
|
17
17
|
"tslib": "^2.8",
|
|
18
18
|
"typescript": "^5.9",
|
|
19
|
-
"vite": "8.0.0-beta.
|
|
19
|
+
"vite": "8.0.0-beta.17",
|
|
20
20
|
"vitest": "^4"
|
|
21
21
|
},
|
|
22
22
|
"exports": {
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
},
|
|
94
94
|
"type": "module",
|
|
95
95
|
"types": "types/index.d.ts",
|
|
96
|
-
"version": "0.
|
|
96
|
+
"version": "0.39.0"
|
|
97
97
|
}
|
package/src/data.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {PlainObject} from '@oscarpalmer/atoms';
|
|
2
|
-
import {
|
|
2
|
+
import {parse} from '@oscarpalmer/atoms/string';
|
|
3
|
+
import {kebabCase} from '@oscarpalmer/atoms/string/case';
|
|
3
4
|
import {setElementValues, updateElementValue} from './internal/element-value';
|
|
4
5
|
import {EXPRESSION_DATA_PREFIX} from './internal/get-value';
|
|
5
6
|
import {isHTMLOrSVGElement} from './internal/is';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {parse} from '@oscarpalmer/atoms/string';
|
|
2
|
+
import {camelCase, kebabCase} from '@oscarpalmer/atoms/string/case';
|
|
2
3
|
|
|
3
4
|
export function getBoolean(value: unknown, defaultValue?: boolean): boolean {
|
|
4
5
|
return typeof value === 'boolean' ? value : (defaultValue ?? false);
|