@oscarpalmer/toretto 0.41.0 → 0.43.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.d.mts → get.attribute.d.mts} +3 -2
- package/dist/attribute/{get.mjs → get.attribute.mjs} +4 -3
- package/dist/attribute/index.d.mts +3 -16
- package/dist/attribute/index.mjs +4 -7
- package/dist/attribute/{set.d.mts → set.attribute.d.mts} +4 -4
- package/dist/attribute/{set.mjs → set.attribute.mjs} +2 -2
- package/dist/create.d.mts +25 -0
- package/dist/create.mjs +17 -0
- package/dist/data.mjs +7 -7
- package/dist/event/delegation.mjs +8 -1
- package/dist/html/index.d.mts +23 -26
- package/dist/html/index.mjs +85 -18
- package/dist/html/sanitize.mjs +6 -5
- package/dist/index.d.mts +117 -54
- package/dist/index.mjs +541 -380
- package/dist/internal/attribute.d.mts +4 -3
- package/dist/internal/attribute.mjs +13 -23
- package/dist/internal/element-value.d.mts +2 -2
- package/dist/internal/element-value.mjs +12 -6
- package/dist/internal/get-value.mjs +3 -1
- package/dist/internal/property.d.mts +4 -0
- package/dist/internal/property.mjs +24 -0
- package/dist/property/get.property.d.mts +20 -0
- package/dist/property/get.property.mjs +35 -0
- package/dist/property/index.d.mts +3 -0
- package/dist/property/index.mjs +3 -0
- package/dist/property/set.property.d.mts +32 -0
- package/dist/property/set.property.mjs +32 -0
- package/dist/style.d.mts +16 -9
- package/dist/style.mjs +22 -21
- package/package.json +14 -6
- package/src/attribute/{get.ts → get.attribute.ts} +14 -3
- package/src/attribute/index.ts +10 -22
- package/src/attribute/{set.ts → set.attribute.ts} +9 -5
- package/src/create.ts +81 -0
- package/src/data.ts +16 -8
- package/src/event/delegation.ts +24 -3
- package/src/event/index.ts +9 -3
- package/src/find/index.ts +11 -3
- package/src/find/relative.ts +4 -0
- package/src/focusable.ts +10 -2
- package/src/html/index.ts +166 -58
- package/src/html/sanitize.ts +14 -11
- package/src/index.ts +2 -1
- package/src/internal/attribute.ts +23 -42
- package/src/internal/element-value.ts +25 -6
- package/src/internal/get-value.ts +14 -0
- package/src/internal/is.ts +4 -0
- package/src/internal/property.ts +42 -0
- package/src/is.ts +10 -2
- package/src/property/get.property.ts +73 -0
- package/src/property/index.ts +2 -0
- package/src/property/set.property.ts +103 -0
- package/src/style.ts +81 -36
- package/src/touch.ts +14 -2
|
@@ -4,12 +4,13 @@ import { Attribute } from "../models.mjs";
|
|
|
4
4
|
declare function isAttribute(value: unknown): value is Attr | Attribute;
|
|
5
5
|
declare function _isBadAttribute(first: unknown, second: unknown, decode: boolean): boolean;
|
|
6
6
|
declare function _isBooleanAttribute(first: unknown, decode: boolean): boolean;
|
|
7
|
-
declare function _isEmptyNonBooleanAttribute(first: unknown, second: unknown, decode: boolean): boolean;
|
|
8
7
|
declare function _isInvalidBooleanAttribute(first: unknown, second: unknown, decode: boolean): boolean;
|
|
9
|
-
declare function updateAttribute(element: Element, name: string, value: unknown, dispatch
|
|
8
|
+
declare function updateAttribute(element: Element, name: string, value: unknown, dispatch: boolean): void;
|
|
10
9
|
/**
|
|
11
10
|
* List of boolean attributes
|
|
12
11
|
*/
|
|
13
12
|
declare const booleanAttributes: readonly string[];
|
|
13
|
+
declare const booleanAttributesSet: Set<string>;
|
|
14
|
+
declare const dispatchedAttributes: Set<string>;
|
|
14
15
|
//#endregion
|
|
15
|
-
export { _isBadAttribute, _isBooleanAttribute,
|
|
16
|
+
export { _isBadAttribute, _isBooleanAttribute, _isInvalidBooleanAttribute, booleanAttributes, booleanAttributesSet, dispatchedAttributes, isAttribute, updateAttribute };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { updateElementValue } from "./element-value.mjs";
|
|
2
|
+
import { updateProperty } from "./property.mjs";
|
|
2
3
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
|
+
import { kebabCase } from "@oscarpalmer/atoms/string/case";
|
|
3
5
|
//#region src/internal/attribute.ts
|
|
4
6
|
function badAttributeHandler(name, value) {
|
|
5
7
|
if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
|
|
@@ -29,6 +31,7 @@ function handleAttribute(callback, decode, first, second) {
|
|
|
29
31
|
name = first;
|
|
30
32
|
value = second;
|
|
31
33
|
}
|
|
34
|
+
if (name != null) name = kebabCase(name);
|
|
32
35
|
if (decode && value != null) value = decodeAttribute(value);
|
|
33
36
|
return callback(name, value?.replace(EXPRESSION_WHITESPACE, ""));
|
|
34
37
|
}
|
|
@@ -41,9 +44,6 @@ function _isBadAttribute(first, second, decode) {
|
|
|
41
44
|
function _isBooleanAttribute(first, decode) {
|
|
42
45
|
return handleAttribute((name) => booleanAttributesSet.has(name?.toLowerCase()), decode, first, "");
|
|
43
46
|
}
|
|
44
|
-
function _isEmptyNonBooleanAttribute(first, second, decode) {
|
|
45
|
-
return handleAttribute((name, value) => name != null && value != null && !booleanAttributesSet.has(name) && value.trim().length === 0, decode, first, second);
|
|
46
|
-
}
|
|
47
47
|
function _isInvalidBooleanAttribute(first, second, decode) {
|
|
48
48
|
return handleAttribute(booleanAttributeHandler, decode, first, second);
|
|
49
49
|
}
|
|
@@ -51,18 +51,12 @@ function isValidSourceAttribute(name, value) {
|
|
|
51
51
|
return EXPRESSION_SOURCE_NAME.test(name) && EXPRESSION_SOURCE_VALUE.test(value);
|
|
52
52
|
}
|
|
53
53
|
function updateAttribute(element, name, value, dispatch) {
|
|
54
|
-
const
|
|
55
|
-
const isBoolean = booleanAttributesSet.has(
|
|
56
|
-
const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() ===
|
|
57
|
-
if (
|
|
54
|
+
const lowerCaseName = name.toLowerCase();
|
|
55
|
+
const isBoolean = booleanAttributesSet.has(lowerCaseName);
|
|
56
|
+
const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === lowerCaseName) : value == null ? "" : value;
|
|
57
|
+
if (isBoolean || dispatchedAttributes.has(name)) updateProperty(element, name, next, dispatch);
|
|
58
58
|
updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
|
|
59
59
|
}
|
|
60
|
-
function updateProperty(element, name, value, dispatch) {
|
|
61
|
-
if (Object.is(element[name], value)) return;
|
|
62
|
-
element[name] = value;
|
|
63
|
-
const event = dispatch !== false && elementEvents[element.tagName]?.[name];
|
|
64
|
-
if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
|
|
65
|
-
}
|
|
66
60
|
const EXPRESSION_CLOBBERED_NAME = /^(id|name)$/i;
|
|
67
61
|
const EXPRESSION_DATA_OR_SCRIPT = /^(?:data|\w+script):/i;
|
|
68
62
|
const EXPRESSION_EVENT_NAME = /^on/i;
|
|
@@ -101,16 +95,12 @@ const booleanAttributes = Object.freeze([
|
|
|
101
95
|
"selected"
|
|
102
96
|
]);
|
|
103
97
|
const booleanAttributesSet = new Set(booleanAttributes);
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
},
|
|
110
|
-
SELECT: { value: "change" },
|
|
111
|
-
TEXTAREA: { value: "input" }
|
|
112
|
-
};
|
|
98
|
+
const dispatchedAttributes = new Set([
|
|
99
|
+
"checked",
|
|
100
|
+
"open",
|
|
101
|
+
"value"
|
|
102
|
+
]);
|
|
113
103
|
const formElement = document.createElement("form");
|
|
114
104
|
let textArea;
|
|
115
105
|
//#endregion
|
|
116
|
-
export { _isBadAttribute, _isBooleanAttribute,
|
|
106
|
+
export { _isBadAttribute, _isBooleanAttribute, _isInvalidBooleanAttribute, booleanAttributes, booleanAttributesSet, dispatchedAttributes, isAttribute, updateAttribute };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/internal/element-value.d.ts
|
|
2
|
-
declare function setElementValue(element: Element, first: unknown, second: unknown, third: unknown, callback: (element: Element, key: string, value: unknown) => void): void;
|
|
3
|
-
declare function setElementValues(element: Element, first: unknown, second: unknown, third: unknown, callback: (element: Element, key: string, value: unknown, dispatch
|
|
2
|
+
declare function setElementValue(element: Element, first: unknown, second: unknown, third: unknown, callback: (element: Element, key: string, value: unknown, dispatch: boolean) => void, style?: boolean): void;
|
|
3
|
+
declare function setElementValues(element: Element, first: unknown, second: unknown, third: unknown, callback: (element: Element, key: string, value: unknown, dispatch: boolean) => void, style?: boolean): void;
|
|
4
4
|
declare function updateElementValue(element: Element, key: string, value: unknown, set: (key: string, value: string) => void, remove: (key: string) => void, isBoolean: boolean, json: boolean): void;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { setElementValue, setElementValues, updateElementValue };
|
|
@@ -2,16 +2,21 @@ import { isHTMLOrSVGElement } from "./is.mjs";
|
|
|
2
2
|
import "../is.mjs";
|
|
3
3
|
import { isAttribute } from "./attribute.mjs";
|
|
4
4
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
5
|
+
import { kebabCase } from "@oscarpalmer/atoms/string/case";
|
|
5
6
|
//#region src/internal/element-value.ts
|
|
6
|
-
function
|
|
7
|
+
function normalizeKey(key, style) {
|
|
8
|
+
return style && key.startsWith(CSS_VARIABLE_PREFIX) ? key : kebabCase(key);
|
|
9
|
+
}
|
|
10
|
+
function setElementValue(element, first, second, third, callback, style) {
|
|
7
11
|
if (!isHTMLOrSVGElement(element)) return;
|
|
8
|
-
if (typeof first === "string") setElementValues(element, first, second, third, callback);
|
|
9
|
-
else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback);
|
|
12
|
+
if (typeof first === "string") setElementValues(element, first, second, third, callback, style);
|
|
13
|
+
else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback, style);
|
|
10
14
|
}
|
|
11
|
-
function setElementValues(element, first, second, third, callback) {
|
|
15
|
+
function setElementValues(element, first, second, third, callback, style) {
|
|
12
16
|
if (!isHTMLOrSVGElement(element)) return;
|
|
17
|
+
const dispatch = third !== false;
|
|
13
18
|
if (typeof first === "string") {
|
|
14
|
-
callback(element, first, second,
|
|
19
|
+
callback(element, normalizeKey(first, style), second, dispatch);
|
|
15
20
|
return;
|
|
16
21
|
}
|
|
17
22
|
const isArray = Array.isArray(first);
|
|
@@ -23,12 +28,13 @@ function setElementValues(element, first, second, third, callback) {
|
|
|
23
28
|
const { length } = entries;
|
|
24
29
|
for (let index = 0; index < length; index += 1) {
|
|
25
30
|
const entry = entries[index];
|
|
26
|
-
if (typeof entry === "object" && typeof entry?.name === "string") callback(element, entry.name, entry.value,
|
|
31
|
+
if (typeof entry === "object" && typeof entry?.name === "string") callback(element, normalizeKey(entry.name, style), entry.value, dispatch);
|
|
27
32
|
}
|
|
28
33
|
}
|
|
29
34
|
function updateElementValue(element, key, value, set, remove, isBoolean, json) {
|
|
30
35
|
if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
|
|
31
36
|
else set.call(element, key, json ? JSON.stringify(value) : String(value));
|
|
32
37
|
}
|
|
38
|
+
const CSS_VARIABLE_PREFIX = "--";
|
|
33
39
|
//#endregion
|
|
34
40
|
export { setElementValue, setElementValues, updateElementValue };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parse } from "@oscarpalmer/atoms/string";
|
|
2
1
|
import { camelCase, kebabCase } from "@oscarpalmer/atoms/string/case";
|
|
2
|
+
import { parse } from "@oscarpalmer/atoms/string";
|
|
3
3
|
//#region src/internal/get-value.ts
|
|
4
4
|
function getBoolean(value, defaultValue) {
|
|
5
5
|
return typeof value === "boolean" ? value : defaultValue ?? false;
|
|
@@ -11,9 +11,11 @@ function getAttributeValue(element, name, parseValue) {
|
|
|
11
11
|
return EXPRESSION_DATA_PREFIX.test(normalized) && typeof value === "string" && parseValue ? parse(value) ?? value : value;
|
|
12
12
|
}
|
|
13
13
|
function getStyleValue(element, property, computed) {
|
|
14
|
+
if (property.startsWith(CSS_VARIABLE_PREFIX)) return element.style.getPropertyValue(property);
|
|
14
15
|
const name = camelCase(property);
|
|
15
16
|
return computed ? getComputedStyle(element)[name] : element.style[name];
|
|
16
17
|
}
|
|
17
18
|
const EXPRESSION_DATA_PREFIX = /^data-/i;
|
|
19
|
+
const CSS_VARIABLE_PREFIX = "--";
|
|
18
20
|
//#endregion
|
|
19
21
|
export { EXPRESSION_DATA_PREFIX, getAttributeValue, getBoolean, getStyleValue };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { camelCase } from "@oscarpalmer/atoms/string/case";
|
|
2
|
+
//#region src/internal/property.ts
|
|
3
|
+
function updateProperty(element, name, value, dispatch) {
|
|
4
|
+
let property = name;
|
|
5
|
+
if (!(property in element)) property = camelCase(name);
|
|
6
|
+
if (!(property in element) || Object.is(element[property], value)) return;
|
|
7
|
+
element[property] = value;
|
|
8
|
+
const event = dispatch && elementEvents[element.tagName]?.[property];
|
|
9
|
+
if (typeof event === "string") element.dispatchEvent(new Event(event, {
|
|
10
|
+
bubbles: true,
|
|
11
|
+
cancelable: true
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
const elementEvents = {
|
|
15
|
+
DETAILS: { open: "toggle" },
|
|
16
|
+
INPUT: {
|
|
17
|
+
checked: "change",
|
|
18
|
+
value: "input"
|
|
19
|
+
},
|
|
20
|
+
SELECT: { value: "change" },
|
|
21
|
+
TEXTAREA: { value: "input" }
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { updateProperty };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Primitive } from "@oscarpalmer/atoms/models";
|
|
2
|
+
|
|
3
|
+
//#region src/property/get.property.d.ts
|
|
4
|
+
type GetProperties<Target extends Element> = { [Property in keyof Target as Target[Property] extends Primitive ? Property : never]?: Target[Property] };
|
|
5
|
+
/**
|
|
6
|
+
* Get the values of one or more properties on an element
|
|
7
|
+
* @param target Target element
|
|
8
|
+
* @param properties Properties to get
|
|
9
|
+
* @returns Property values
|
|
10
|
+
*/
|
|
11
|
+
declare function getProperties<Target extends Element, Property extends keyof GetProperties<Target>>(target: Target, properties: Property[]): Pick<GetProperties<Target>, Property>;
|
|
12
|
+
/**
|
|
13
|
+
* Get the value of a property on an element
|
|
14
|
+
* @param target Target element
|
|
15
|
+
* @param property Property to get
|
|
16
|
+
* @returns Property value
|
|
17
|
+
*/
|
|
18
|
+
declare function getProperty<Target extends Element, Property extends keyof GetProperties<Target>>(target: Target, property: Property): GetProperties<Target>[Property];
|
|
19
|
+
//#endregion
|
|
20
|
+
export { getProperties, getProperty };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isHTMLOrSVGElement } from "../internal/is.mjs";
|
|
2
|
+
import { camelCase } from "@oscarpalmer/atoms/string/case";
|
|
3
|
+
//#region src/property/get.property.ts
|
|
4
|
+
/**
|
|
5
|
+
* Get the values of one or more properties on an element
|
|
6
|
+
* @param target Target element
|
|
7
|
+
* @param properties Properties to get
|
|
8
|
+
* @returns Property values
|
|
9
|
+
*/
|
|
10
|
+
function getProperties(target, properties) {
|
|
11
|
+
const values = {};
|
|
12
|
+
if (!isHTMLOrSVGElement(target) || !Array.isArray(properties)) return values;
|
|
13
|
+
const { length } = properties;
|
|
14
|
+
for (let index = 0; index < length; index += 1) {
|
|
15
|
+
const property = properties[index];
|
|
16
|
+
if (typeof property === "string") values[property] = getPropertyValue(target, property);
|
|
17
|
+
}
|
|
18
|
+
return values;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get the value of a property on an element
|
|
22
|
+
* @param target Target element
|
|
23
|
+
* @param property Property to get
|
|
24
|
+
* @returns Property value
|
|
25
|
+
*/
|
|
26
|
+
function getProperty(target, property) {
|
|
27
|
+
if (isHTMLOrSVGElement(target) && typeof property === "string") return getPropertyValue(target, property);
|
|
28
|
+
}
|
|
29
|
+
function getPropertyValue(element, property) {
|
|
30
|
+
let actual = property;
|
|
31
|
+
if (!(actual in element)) actual = camelCase(actual);
|
|
32
|
+
if (actual in element) return element[actual];
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { getProperties, getProperty };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DispatchedAttributeName } from "../attribute/set.attribute.mjs";
|
|
2
|
+
import { Primitive } from "@oscarpalmer/atoms/models";
|
|
3
|
+
|
|
4
|
+
//#region src/property/set.property.d.ts
|
|
5
|
+
type DispatchedPropertyValue<Target extends Element, Property extends DispatchedAttributeName> = Property extends keyof SetProperties<Target> ? SetProperties<Target>[Property] : never;
|
|
6
|
+
type SetProperties<Target extends Element> = { [Property in keyof Target as Target[Property] extends Primitive ? Property : never]?: Target[Property] };
|
|
7
|
+
/**
|
|
8
|
+
* Set the values of one or more properties on an element
|
|
9
|
+
*
|
|
10
|
+
* Also updates attributes for boolean/dispatchable properties, and if `dispatch` is `true`, will dispatch events for dispatchable properties
|
|
11
|
+
* @param target Target element
|
|
12
|
+
* @param properties Properties to set
|
|
13
|
+
* @param dispatch Dispatch events for properties? _(defaults to `true`)_
|
|
14
|
+
*/
|
|
15
|
+
declare function setProperties<Target extends Element>(target: Target, properties: SetProperties<Target>, dispatch?: boolean): void;
|
|
16
|
+
/**
|
|
17
|
+
* Set the value for a dispatchable property on an element
|
|
18
|
+
* @param target Target element
|
|
19
|
+
* @param property Property to set
|
|
20
|
+
* @param value Value to set
|
|
21
|
+
* @param dispatch Dispatch event for property? _(defaults to `true`)_
|
|
22
|
+
*/
|
|
23
|
+
declare function setProperty<Target extends Element, Property extends DispatchedAttributeName>(target: Target, property: Property, value: DispatchedPropertyValue<Target, Property>, dispatch?: boolean): void;
|
|
24
|
+
/**
|
|
25
|
+
* Set the value for a property on an element
|
|
26
|
+
* @param target Target element
|
|
27
|
+
* @param property Property to set
|
|
28
|
+
* @param value Value to set
|
|
29
|
+
*/
|
|
30
|
+
declare function setProperty<Target extends Element, Property extends keyof SetProperties<Target>>(target: Target, property: Property, value: SetProperties<Target>[Property]): void;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { setProperties, setProperty };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { isHTMLOrSVGElement } from "../internal/is.mjs";
|
|
2
|
+
import "../is.mjs";
|
|
3
|
+
import { updateProperty } from "../internal/property.mjs";
|
|
4
|
+
import { booleanAttributesSet, dispatchedAttributes } from "../internal/attribute.mjs";
|
|
5
|
+
import { setAttribute } from "../attribute/set.attribute.mjs";
|
|
6
|
+
import "../attribute/index.mjs";
|
|
7
|
+
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
8
|
+
//#region src/property/set.property.ts
|
|
9
|
+
/**
|
|
10
|
+
* Set the values of one or more properties on an element
|
|
11
|
+
*
|
|
12
|
+
* Also updates attributes for boolean/dispatchable properties, and if `dispatch` is `true`, will dispatch events for dispatchable properties
|
|
13
|
+
* @param target Target element
|
|
14
|
+
* @param properties Properties to set
|
|
15
|
+
* @param dispatch Dispatch events for properties? _(defaults to `true`)_
|
|
16
|
+
*/
|
|
17
|
+
function setProperties(target, properties, dispatch) {
|
|
18
|
+
if (!isHTMLOrSVGElement(target) || !isPlainObject(properties)) return;
|
|
19
|
+
const shouldDispatch = dispatch !== false;
|
|
20
|
+
const keys = Object.keys(properties);
|
|
21
|
+
const { length } = keys;
|
|
22
|
+
for (let index = 0; index < length; index += 1) setPropertyValue(target, keys[index], properties[keys[index]], shouldDispatch);
|
|
23
|
+
}
|
|
24
|
+
function setProperty(target, property, value, dispatch) {
|
|
25
|
+
if (isHTMLOrSVGElement(target) && typeof property === "string") setPropertyValue(target, property, value, dispatch !== false);
|
|
26
|
+
}
|
|
27
|
+
function setPropertyValue(element, property, value, dispatch) {
|
|
28
|
+
if (booleanAttributesSet.has(property.toLowerCase()) || dispatchedAttributes.has(property)) setAttribute(element, property, value, dispatch);
|
|
29
|
+
else updateProperty(element, property, value, dispatch);
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { setProperties, setProperty };
|
package/dist/style.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TextDirection } from "./models.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/style.d.ts
|
|
4
|
+
type CSSStyleValues = Variables & CSSStyleDeclaration;
|
|
4
5
|
type StyleToggler = {
|
|
5
6
|
/**
|
|
6
7
|
* Set the provided styles on the element
|
|
@@ -11,6 +12,8 @@ type StyleToggler = {
|
|
|
11
12
|
*/
|
|
12
13
|
remove(): void;
|
|
13
14
|
};
|
|
15
|
+
type Styles = Partial<Record<keyof CSSStyleValues, unknown>>;
|
|
16
|
+
type Variables<Value extends Record<string, string | undefined> = Record<string, string | undefined>> = { [property in keyof Value as `--${string & property}`]?: string | undefined };
|
|
14
17
|
/**
|
|
15
18
|
* Get a style from an element
|
|
16
19
|
* @param element Element to get the style from
|
|
@@ -18,7 +21,7 @@ type StyleToggler = {
|
|
|
18
21
|
* @param computed Get the computed style? _(defaults to `false`)_
|
|
19
22
|
* @returns Style value
|
|
20
23
|
*/
|
|
21
|
-
declare function getStyle(element: Element, property: keyof
|
|
24
|
+
declare function getStyle(element: Element, property: keyof CSSStyleValues, computed?: boolean): string | undefined;
|
|
22
25
|
/**
|
|
23
26
|
* Get styles from an element
|
|
24
27
|
* @param element Element to get the styles from
|
|
@@ -26,33 +29,37 @@ declare function getStyle(element: Element, property: keyof CSSStyleDeclaration,
|
|
|
26
29
|
* @param computed Get the computed styles? _(defaults to `false`)_
|
|
27
30
|
* @returns Style values
|
|
28
31
|
*/
|
|
29
|
-
declare function getStyles<Property extends keyof
|
|
32
|
+
declare function getStyles<Property extends keyof CSSStyleValues>(element: Element, properties: Property[], computed?: boolean): Record<Property, string | undefined>;
|
|
30
33
|
/**
|
|
31
|
-
* Get the text direction of
|
|
32
|
-
* @param element
|
|
33
|
-
* @param computed Get the computed text direction? _(defaults to `false`)_
|
|
34
|
+
* Get the text direction of a node or element _(or document, if element is invalid)_
|
|
35
|
+
* @param node Node or element to get the text direction from
|
|
34
36
|
* @returns Text direction
|
|
35
37
|
*/
|
|
36
|
-
declare function getTextDirection(
|
|
38
|
+
declare function getTextDirection(node: Element | Node): TextDirection;
|
|
39
|
+
/**
|
|
40
|
+
* Get the text direction of the document
|
|
41
|
+
* @returns Text direction
|
|
42
|
+
*/
|
|
43
|
+
declare function getTextDirection(): TextDirection;
|
|
37
44
|
/**
|
|
38
45
|
* Set a style on an element
|
|
39
46
|
* @param element Element to set the style on
|
|
40
47
|
* @param property Style name
|
|
41
48
|
* @param value Style value
|
|
42
49
|
*/
|
|
43
|
-
declare function setStyle(element: Element, property: keyof
|
|
50
|
+
declare function setStyle(element: Element, property: keyof CSSStyleValues, value?: unknown): void;
|
|
44
51
|
/**
|
|
45
52
|
* Set styles on an element
|
|
46
53
|
* @param element Element to set the styles on
|
|
47
54
|
* @param styles Styles to set
|
|
48
55
|
*/
|
|
49
|
-
declare function setStyles(element: Element, styles:
|
|
56
|
+
declare function setStyles(element: Element, styles: Styles): void;
|
|
50
57
|
/**
|
|
51
58
|
* Toggle styles for an element
|
|
52
59
|
* @param element Element to style
|
|
53
60
|
* @param styles Styles to be set or removed
|
|
54
61
|
* @returns Style toggler
|
|
55
62
|
*/
|
|
56
|
-
declare function toggleStyles(element: Element, styles:
|
|
63
|
+
declare function toggleStyles(element: Element, styles: Styles): StyleToggler;
|
|
57
64
|
//#endregion
|
|
58
65
|
export { StyleToggler, getStyle, getStyles, getTextDirection, setStyle, setStyles, toggleStyles };
|
package/dist/style.mjs
CHANGED
|
@@ -10,8 +10,7 @@ import { getStyleValue } from "./internal/get-value.mjs";
|
|
|
10
10
|
* @returns Style value
|
|
11
11
|
*/
|
|
12
12
|
function getStyle(element, property, computed) {
|
|
13
|
-
if (
|
|
14
|
-
return getStyleValue(element, property, computed === true);
|
|
13
|
+
if (isHTMLOrSVGElement(element) && typeof property === "string") return getStyleValue(element, property, computed === true);
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
16
|
* Get styles from an element
|
|
@@ -30,18 +29,13 @@ function getStyles(element, properties, computed) {
|
|
|
30
29
|
}
|
|
31
30
|
return styles;
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!(element instanceof Element)) return;
|
|
41
|
-
const direction = element.getAttribute(ATTRIBUTE_DIRECTION);
|
|
42
|
-
if (direction != null && EXPRESSION_DIRECTION.test(direction)) return direction.toLowerCase();
|
|
43
|
-
const value = getStyleValue(element, "direction", computed === true);
|
|
44
|
-
return value === "rtl" ? value : "ltr";
|
|
32
|
+
function getTextDirection(node) {
|
|
33
|
+
let target;
|
|
34
|
+
if (isHTMLOrSVGElement(node)) target = node;
|
|
35
|
+
else target = node instanceof Node ? node.ownerDocument?.documentElement ?? document.documentElement : document.documentElement;
|
|
36
|
+
let { direction } = target.style;
|
|
37
|
+
if (direction === "") direction = getStyleValue(target, PROPERTY_DIRECTION, true);
|
|
38
|
+
return direction === DIRECTION_RTL ? DIRECTION_RTL : DIRECTION_LTR;
|
|
45
39
|
}
|
|
46
40
|
/**
|
|
47
41
|
* Set a style on an element
|
|
@@ -50,7 +44,7 @@ function getTextDirection(element, computed) {
|
|
|
50
44
|
* @param value Style value
|
|
51
45
|
*/
|
|
52
46
|
function setStyle(element, property, value) {
|
|
53
|
-
setElementValues(element, property, value, null, updateStyleProperty);
|
|
47
|
+
setElementValues(element, property, value, null, updateStyleProperty, true);
|
|
54
48
|
}
|
|
55
49
|
/**
|
|
56
50
|
* Set styles on an element
|
|
@@ -58,7 +52,7 @@ function setStyle(element, property, value) {
|
|
|
58
52
|
* @param styles Styles to set
|
|
59
53
|
*/
|
|
60
54
|
function setStyles(element, styles) {
|
|
61
|
-
setElementValues(element, styles, null, null, updateStyleProperty);
|
|
55
|
+
setElementValues(element, styles, null, null, updateStyleProperty, true);
|
|
62
56
|
}
|
|
63
57
|
/**
|
|
64
58
|
* Toggle styles for an element
|
|
@@ -76,11 +70,12 @@ function toggleStyles(element, styles) {
|
|
|
76
70
|
} else {
|
|
77
71
|
next = { ...values };
|
|
78
72
|
values = {};
|
|
79
|
-
for (
|
|
73
|
+
for (let index = 0; index < length; index += 1) values[keys[index]] = void 0;
|
|
80
74
|
}
|
|
81
75
|
setStyles(element, next);
|
|
82
76
|
}
|
|
83
77
|
const keys = Object.keys(styles);
|
|
78
|
+
const { length } = keys;
|
|
84
79
|
let hasSet = false;
|
|
85
80
|
let values = {};
|
|
86
81
|
return {
|
|
@@ -94,12 +89,18 @@ function toggleStyles(element, styles) {
|
|
|
94
89
|
}
|
|
95
90
|
function updateStyleProperty(element, key, value) {
|
|
96
91
|
updateElementValue(element, key, value, function(property, style) {
|
|
97
|
-
this.style
|
|
92
|
+
if (property.startsWith(VARIABLE_PREFIX)) this.style.setProperty(property, String(style));
|
|
93
|
+
else this.style[property] = String(style);
|
|
98
94
|
}, function(property) {
|
|
99
|
-
this.style
|
|
95
|
+
if (property.startsWith(VARIABLE_PREFIX)) this.style.removeProperty(property);
|
|
96
|
+
else this.style[property] = "";
|
|
97
|
+
if (this.getAttribute(ATTRIBUTE_STYLE) === "") this.removeAttribute(ATTRIBUTE_STYLE);
|
|
100
98
|
}, false, false);
|
|
101
99
|
}
|
|
102
|
-
const
|
|
103
|
-
const
|
|
100
|
+
const ATTRIBUTE_STYLE = "style";
|
|
101
|
+
const DIRECTION_LTR = "ltr";
|
|
102
|
+
const DIRECTION_RTL = "rtl";
|
|
103
|
+
const PROPERTY_DIRECTION = "direction";
|
|
104
|
+
const VARIABLE_PREFIX = "--";
|
|
104
105
|
//#endregion
|
|
105
106
|
export { getStyle, getStyles, getTextDirection, setStyle, setStyles, toggleStyles };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/toretto",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"description": "A collection of badass DOM utilities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dom",
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"types": "./dist/attribute/index.d.mts",
|
|
35
35
|
"default": "./dist/attribute/index.mjs"
|
|
36
36
|
},
|
|
37
|
+
"./create": {
|
|
38
|
+
"types": "./dist/create.d.mts",
|
|
39
|
+
"default": "./dist/create.mjs"
|
|
40
|
+
},
|
|
37
41
|
"./data": {
|
|
38
42
|
"types": "./dist/data.d.mts",
|
|
39
43
|
"default": "./dist/data.mjs"
|
|
@@ -61,6 +65,10 @@
|
|
|
61
65
|
"./models": {
|
|
62
66
|
"types": "./dist/models.d.mts"
|
|
63
67
|
},
|
|
68
|
+
"./property": {
|
|
69
|
+
"types": "./dist/property/index.d.mts",
|
|
70
|
+
"default": "./dist/property/index.mjs"
|
|
71
|
+
},
|
|
64
72
|
"./style": {
|
|
65
73
|
"types": "./dist/style.d.mts",
|
|
66
74
|
"default": "./dist/style.mjs"
|
|
@@ -75,16 +83,16 @@
|
|
|
75
83
|
"tsdown:build": "npx tsdown -c ./tsdown.config.ts",
|
|
76
84
|
"tsdown:watch": "npx tsdown -c ./tsdown.config.ts --watch",
|
|
77
85
|
"test": "npx vp test run --coverage",
|
|
78
|
-
"test:leak": "npx vp test run --detect-async-leaks --coverage"
|
|
79
|
-
"watch": "npx vite build --watch"
|
|
86
|
+
"test:leak": "npx vp test run --detect-async-leaks --coverage"
|
|
80
87
|
},
|
|
81
88
|
"dependencies": {
|
|
82
|
-
"@oscarpalmer/atoms": "^0.
|
|
89
|
+
"@oscarpalmer/atoms": "^0.185"
|
|
83
90
|
},
|
|
84
91
|
"devDependencies": {
|
|
85
|
-
"@
|
|
92
|
+
"@oxlint/plugins": "^1.62",
|
|
93
|
+
"@types/node": "^25.6",
|
|
86
94
|
"@vitest/coverage-istanbul": "^4.1",
|
|
87
|
-
"jsdom": "^
|
|
95
|
+
"jsdom": "^29.1",
|
|
88
96
|
"tsdown": "^0.21",
|
|
89
97
|
"typescript": "^5.9",
|
|
90
98
|
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import {kebabCase} from '@oscarpalmer/atoms/string/case';
|
|
1
2
|
import {getAttributeValue} from '../internal/get-value';
|
|
2
3
|
import {isHTMLOrSVGElement} from '../internal/is';
|
|
3
4
|
|
|
5
|
+
// #region Types
|
|
6
|
+
|
|
7
|
+
type DataPrefixedName = `data-${string}`;
|
|
8
|
+
|
|
9
|
+
// #endregion
|
|
10
|
+
|
|
11
|
+
// #region Functions
|
|
12
|
+
|
|
4
13
|
/**
|
|
5
14
|
* Get the value of a specific attribute from an element
|
|
6
15
|
* @param element Element to get attribute from
|
|
@@ -8,7 +17,7 @@ import {isHTMLOrSVGElement} from '../internal/is';
|
|
|
8
17
|
* @param parse Parse value? _(defaults to `true`)_
|
|
9
18
|
* @returns Attribute value _(or `undefined`)_
|
|
10
19
|
*/
|
|
11
|
-
export function getAttribute(element: Element, name:
|
|
20
|
+
export function getAttribute(element: Element, name: DataPrefixedName, parse?: boolean): unknown;
|
|
12
21
|
|
|
13
22
|
/**
|
|
14
23
|
* Get the value of a specific attribute from an element
|
|
@@ -20,7 +29,7 @@ export function getAttribute(element: Element, name: string): unknown;
|
|
|
20
29
|
|
|
21
30
|
export function getAttribute(element: Element, name: string, parseValues?: boolean): unknown {
|
|
22
31
|
if (isHTMLOrSVGElement(element) && typeof name === 'string') {
|
|
23
|
-
return getAttributeValue(element, name, parseValues !== false);
|
|
32
|
+
return getAttributeValue(element, kebabCase(name), parseValues !== false);
|
|
24
33
|
}
|
|
25
34
|
}
|
|
26
35
|
|
|
@@ -50,9 +59,11 @@ export function getAttributes<Key extends string>(
|
|
|
50
59
|
const name = names[index];
|
|
51
60
|
|
|
52
61
|
if (typeof name === 'string') {
|
|
53
|
-
attributes[name] = getAttributeValue(element, name, shouldParse);
|
|
62
|
+
attributes[name] = getAttributeValue(element, kebabCase(name), shouldParse);
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
return attributes;
|
|
58
67
|
}
|
|
68
|
+
|
|
69
|
+
// #endregion
|
package/src/attribute/index.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
_isBadAttribute,
|
|
3
3
|
_isBooleanAttribute,
|
|
4
|
-
_isEmptyNonBooleanAttribute,
|
|
5
4
|
_isInvalidBooleanAttribute,
|
|
6
5
|
} from '../internal/attribute';
|
|
7
6
|
import type {Attribute} from '../models';
|
|
8
7
|
|
|
8
|
+
// #region Functions
|
|
9
|
+
|
|
9
10
|
/**
|
|
10
11
|
* Is the attribute considered bad and potentially harmful?
|
|
11
12
|
* @param attribute Attribute to check
|
|
@@ -43,25 +44,6 @@ export function isBooleanAttribute(first: unknown): boolean {
|
|
|
43
44
|
return _isBooleanAttribute(first, true);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
/**
|
|
47
|
-
* Is the attribute empty and not a boolean attribute?
|
|
48
|
-
* @param attribute Attribute to check
|
|
49
|
-
* @returns `true` if attribute is empty and not a boolean attribute
|
|
50
|
-
*/
|
|
51
|
-
export function isEmptyNonBooleanAttribute(attribute: Attr | Attribute): boolean;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Is the attribute empty and not a boolean attribute?
|
|
55
|
-
* @param name Attribute name
|
|
56
|
-
* @param value Attribute value
|
|
57
|
-
* @returns `true` if attribute is empty and not a boolean attribute
|
|
58
|
-
*/
|
|
59
|
-
export function isEmptyNonBooleanAttribute(name: string, value: string): boolean;
|
|
60
|
-
|
|
61
|
-
export function isEmptyNonBooleanAttribute(first: unknown, second?: unknown): boolean {
|
|
62
|
-
return _isEmptyNonBooleanAttribute(first, second, true);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
47
|
/**
|
|
66
48
|
* Is the attribute an invalid boolean attribute?
|
|
67
49
|
*
|
|
@@ -85,6 +67,12 @@ export function isInvalidBooleanAttribute(first: unknown, second?: unknown): boo
|
|
|
85
67
|
return _isInvalidBooleanAttribute(first, second, true);
|
|
86
68
|
}
|
|
87
69
|
|
|
70
|
+
// #endregion
|
|
71
|
+
|
|
72
|
+
// #region Exports
|
|
73
|
+
|
|
88
74
|
export {booleanAttributes} from '../internal/attribute';
|
|
89
|
-
export * from './get';
|
|
90
|
-
export
|
|
75
|
+
export * from './get.attribute';
|
|
76
|
+
export {setAttribute, setAttributes} from './set.attribute';
|
|
77
|
+
|
|
78
|
+
// #endregion
|