@oscarpalmer/toretto 0.26.1 → 0.27.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.
@@ -1,5 +1,5 @@
1
- import { isHTMLOrSVGElement } from "../internal/is.js";
2
1
  import { getAttributeValue } from "../internal/get-value.js";
2
+ import { isHTMLOrSVGElement } from "../internal/is.js";
3
3
  function getAttribute(element, name, parseValues) {
4
4
  if (isHTMLOrSVGElement(element) && typeof name === "string") return getAttributeValue(element, name, parseValues !== false);
5
5
  }
@@ -1,4 +1,4 @@
1
- import { booleanAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute } from "../internal/attribute.js";
2
1
  import { getAttribute, getAttributes } from "./get.js";
2
+ import { booleanAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute } from "../internal/attribute.js";
3
3
  import { setAttribute, setAttributes, setProperties, setProperty } from "./set.js";
4
4
  export { booleanAttributes, getAttribute, getAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute, setAttribute, setAttributes, setProperties, setProperty };
@@ -1,14 +1,14 @@
1
- import { updateAttribute, updateProperty, updateValue, updateValues } from "./update.js";
1
+ import { updateValue, updateValues } from "../internal/attribute.js";
2
2
  function setAttribute(element, first, second) {
3
- updateValue(element, first, second, updateAttribute);
3
+ updateValue(element, first, second);
4
4
  }
5
5
  function setAttributes(element, attributes) {
6
6
  updateValues(element, attributes);
7
7
  }
8
8
  function setProperty(element, first, second) {
9
- updateValue(element, first, second, updateProperty);
9
+ updateValue(element, first, second);
10
10
  }
11
11
  function setProperties(element, properties) {
12
- updateValues(element, properties, updateProperty);
12
+ updateValues(element, properties);
13
13
  }
14
14
  export { setAttribute, setAttributes, setProperties, setProperty };
package/dist/data.js CHANGED
@@ -1,6 +1,6 @@
1
+ import { EXPRESSION_DATA_PREFIX } from "./internal/get-value.js";
1
2
  import { isHTMLOrSVGElement } from "./internal/is.js";
2
3
  import { setElementValues, updateElementValue } from "./internal/element-value.js";
3
- import { EXPRESSION_DATA_PREFIX } from "./internal/get-value.js";
4
4
  import { kebabCase, parse } from "@oscarpalmer/atoms/string";
5
5
  function getData(element, keys, parseValues) {
6
6
  if (!isHTMLOrSVGElement(element)) return;
@@ -1,5 +1,5 @@
1
- import { isEventTarget } from "../internal/is.js";
2
1
  import { getBoolean } from "../internal/get-value.js";
2
+ 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";
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
- import touch_default from "./touch.js";
2
1
  import { isEventTarget, isHTMLOrSVGElement } from "./internal/is.js";
3
- import { isChildNode, isInDocument } from "./is.js";
4
- import { getStyle, getStyles, getTextDirection, setStyle, setStyles, toggleStyles } from "./style.js";
5
- import { booleanAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute } from "./internal/attribute.js";
6
2
  import { getAttribute, getAttributes } from "./attribute/get.js";
3
+ import { booleanAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute } from "./internal/attribute.js";
7
4
  import { setAttribute, setAttributes, setProperties, setProperty } from "./attribute/set.js";
8
5
  import "./attribute/index.js";
6
+ import { isChildNode, isInDocument } from "./is.js";
9
7
  import { getData, setData } from "./data.js";
10
8
  import { dispatch, getPosition, off, on } from "./event/index.js";
11
9
  import { findAncestor, findRelatives } from "./find/relative.js";
12
10
  import { $ as findElement, $$ as findElements, getElementUnderPointer } from "./find/index.js";
13
11
  import { getFocusable, getTabbable, isFocusable, isTabbable } from "./focusable.js";
14
12
  import { html, sanitize } from "./html.js";
13
+ import touch_default from "./touch.js";
14
+ import { getStyle, getStyles, getTextDirection, setStyle, setStyles, toggleStyles } from "./style.js";
15
15
  export { findElement as $, findElement, findElements as $$, findElements, booleanAttributes, dispatch, findAncestor, findRelatives, getAttribute, getAttributes, getData, getElementUnderPointer, getFocusable, getPosition, getStyle, getStyles, getTabbable, getTextDirection, html, isBadAttribute, isBooleanAttribute, isChildNode, isEmptyNonBooleanAttribute, isEventTarget, isFocusable, isHTMLOrSVGElement, isInDocument, isInvalidBooleanAttribute, isTabbable, off, on, sanitize, setAttribute, setAttributes, setData, setProperties, setProperty, setStyle, setStyles, touch_default as supportsTouch, toggleStyles };
@@ -1,3 +1,5 @@
1
+ import { isHTMLOrSVGElement } from "./is.js";
2
+ import { getString } from "@oscarpalmer/atoms/string";
1
3
  import { isPlainObject } from "@oscarpalmer/atoms/is";
2
4
  function isAttribute(value) {
3
5
  return value instanceof Attr || isPlainObject(value) && typeof value.name === "string" && typeof value.value === "string";
@@ -19,6 +21,9 @@ function isInvalidBooleanAttribute(first, second) {
19
21
  return !(normalized.length === 0 || normalized === attribute.name);
20
22
  }, first, second);
21
23
  }
24
+ function isProperty(value) {
25
+ return isPlainObject(value) && typeof value.name === "string";
26
+ }
22
27
  function isValidAttribute(callback, first, second) {
23
28
  let attribute;
24
29
  if (isAttribute(first)) attribute = first;
@@ -28,6 +33,32 @@ function isValidAttribute(callback, first, second) {
28
33
  };
29
34
  return callback(attribute);
30
35
  }
36
+ function updateAttribute(element, name, value) {
37
+ const isBoolean = booleanAttributes.includes(name.toLowerCase());
38
+ if (isBoolean) updateProperty(element, name, value);
39
+ if (isBoolean ? value !== true : value == null) element.removeAttribute(name);
40
+ else element.setAttribute(name, isBoolean ? "" : getString(value));
41
+ }
42
+ function updateProperty(element, name, value) {
43
+ const actual = name.toLowerCase();
44
+ element[actual] = value === "" || typeof value === "string" && value.toLowerCase() === actual || value === true;
45
+ }
46
+ function updateValue(element, first, second) {
47
+ if (!isHTMLOrSVGElement(element)) return;
48
+ if (isProperty(first)) updateAttribute(element, first.name, first.value);
49
+ else if (typeof first === "string") updateAttribute(element, first, second);
50
+ }
51
+ function updateValues(element, values) {
52
+ if (!isHTMLOrSVGElement(element)) return;
53
+ const isArray = Array.isArray(values);
54
+ const entries = Object.entries(values);
55
+ const { length } = entries;
56
+ for (let index = 0; index < length; index += 1) {
57
+ const entry = entries[index];
58
+ if (isArray) updateAttribute(element, entry[1].name, entry[1].value);
59
+ else updateAttribute(element, entry[0], entry[1]);
60
+ }
61
+ }
31
62
  var EXPRESSION_ON_PREFIX = /^on/i;
32
63
  var EXPRESSION_SOURCE_PREFIX = /^(href|src|xlink:href)$/i;
33
64
  var EXPRESSION_VALUE_PREFIX = /(data:text\/html|javascript:)/i;
@@ -57,4 +88,4 @@ const booleanAttributes = Object.freeze([
57
88
  "reversed",
58
89
  "selected"
59
90
  ]);
60
- export { booleanAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute };
91
+ export { booleanAttributes, isBadAttribute, isBooleanAttribute, isEmptyNonBooleanAttribute, isInvalidBooleanAttribute, isProperty, updateValue, updateValues };
package/dist/style.js CHANGED
@@ -1,6 +1,6 @@
1
+ import { getStyleValue } from "./internal/get-value.js";
1
2
  import { isHTMLOrSVGElement } from "./internal/is.js";
2
3
  import { setElementValues, updateElementValue } from "./internal/element-value.js";
3
- import { getStyleValue } from "./internal/get-value.js";
4
4
  function getStyle(element, property, computed) {
5
5
  if (!isHTMLOrSVGElement(element) || typeof property !== "string") return;
6
6
  return getStyleValue(element, property, computed === true);
@@ -84,6 +84,70 @@ function isNullableOrWhitespace(value) {
84
84
  }
85
85
  var EXPRESSION_WHITESPACE = /^\s*$/;
86
86
 
87
+ function camelCase(value) {
88
+ return toCase(value, "", true);
89
+ }
90
+ function capitalize(value) {
91
+ if (typeof value !== "string" || value.length === 0) return "";
92
+ return value.length === 1 ? value.toLocaleUpperCase() : `${value.charAt(0).toLocaleUpperCase()}${value.slice(1).toLocaleLowerCase()}`;
93
+ }
94
+ function kebabCase(value) {
95
+ return toCase(value, "-", false);
96
+ }
97
+ function toCase(value, delimiter, capitalizeAny, capitalizeFirst) {
98
+ if (typeof value !== "string") return "";
99
+ if (value.length < 1) return value;
100
+ const parts = words(value);
101
+ const partsLength = parts.length;
102
+ const result = [];
103
+ for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
104
+ const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === "s" ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, "$1-$2").split("-");
105
+ const itemsLength = items.length;
106
+ const partResult = [];
107
+ let itemCount = 0;
108
+ for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
109
+ const item = items[itemIndex];
110
+ if (item.length === 0) continue;
111
+ if (!capitalizeAny || itemCount === 0 && partIndex === 0 && true) partResult.push(item.toLocaleLowerCase());
112
+ else partResult.push(capitalize(item));
113
+ itemCount += 1;
114
+ }
115
+ result.push(join(partResult, delimiter));
116
+ }
117
+ return join(result, delimiter);
118
+ }
119
+ var EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
120
+ var EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
121
+
122
+ function parse(value, reviver) {
123
+ try {
124
+ return JSON.parse(value, reviver);
125
+ } catch {
126
+ return;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Is the value an event target?
132
+ * @param value Value to check
133
+ * @returns `true` if it's an event target, otherwise `false`
134
+ */
135
+ function isEventTarget(value) {
136
+ return (typeof value === 'object' &&
137
+ value != null &&
138
+ typeof value.addEventListener === 'function' &&
139
+ typeof value.removeEventListener === 'function' &&
140
+ typeof value.dispatchEvent === 'function');
141
+ }
142
+ /**
143
+ * Is the value an HTML or SVG element?
144
+ * @param value Value to check
145
+ * @returns `true` if it's an HTML or SVG element, otherwise `false`
146
+ */
147
+ function isHTMLOrSVGElement(value) {
148
+ return value instanceof HTMLElement || value instanceof SVGElement;
149
+ }
150
+
87
151
  function isAttribute(value) {
88
152
  return (value instanceof Attr ||
89
153
  (isPlainObject(value) &&
@@ -117,6 +181,9 @@ function isInvalidBooleanAttribute(first, second) {
117
181
  return !(normalized.length === 0 || normalized === attribute.name);
118
182
  }, first, second);
119
183
  }
184
+ function isProperty(value) {
185
+ return (isPlainObject(value) && typeof value.name === 'string');
186
+ }
120
187
  function isValidAttribute(callback, first, second) {
121
188
  let attribute;
122
189
  if (isAttribute(first)) {
@@ -127,6 +194,53 @@ function isValidAttribute(callback, first, second) {
127
194
  }
128
195
  return callback(attribute);
129
196
  }
197
+ function updateAttribute(element, name, value) {
198
+ const isBoolean = booleanAttributes.includes(name.toLowerCase());
199
+ if (isBoolean) {
200
+ updateProperty(element, name, value);
201
+ }
202
+ if (isBoolean ? value !== true : value == null) {
203
+ element.removeAttribute(name);
204
+ }
205
+ else {
206
+ element.setAttribute(name, isBoolean ? '' : getString(value));
207
+ }
208
+ }
209
+ function updateProperty(element, name, value) {
210
+ const actual = name.toLowerCase();
211
+ element[actual] =
212
+ value === '' ||
213
+ (typeof value === 'string' && value.toLowerCase() === actual) ||
214
+ value === true;
215
+ }
216
+ function updateValue(element, first, second) {
217
+ if (!isHTMLOrSVGElement(element)) {
218
+ return;
219
+ }
220
+ if (isProperty(first)) {
221
+ updateAttribute(element, first.name, first.value);
222
+ }
223
+ else if (typeof first === 'string') {
224
+ updateAttribute(element, first, second);
225
+ }
226
+ }
227
+ function updateValues(element, values) {
228
+ if (!isHTMLOrSVGElement(element)) {
229
+ return;
230
+ }
231
+ const isArray = Array.isArray(values);
232
+ const entries = Object.entries(values);
233
+ const { length } = entries;
234
+ for (let index = 0; index < length; index += 1) {
235
+ const entry = entries[index];
236
+ if (isArray) {
237
+ updateAttribute(element, entry[1].name, entry[1].value);
238
+ }
239
+ else {
240
+ updateAttribute(element, entry[0], entry[1]);
241
+ }
242
+ }
243
+ }
130
244
  //
131
245
  const EXPRESSION_ON_PREFIX = /^on/i;
132
246
  const EXPRESSION_SOURCE_PREFIX = /^(href|src|xlink:href)$/i;
@@ -161,49 +275,6 @@ const booleanAttributes = Object.freeze([
161
275
  'selected',
162
276
  ]);
163
277
 
164
- function camelCase(value) {
165
- return toCase(value, "", true);
166
- }
167
- function capitalize(value) {
168
- if (typeof value !== "string" || value.length === 0) return "";
169
- return value.length === 1 ? value.toLocaleUpperCase() : `${value.charAt(0).toLocaleUpperCase()}${value.slice(1).toLocaleLowerCase()}`;
170
- }
171
- function kebabCase(value) {
172
- return toCase(value, "-", false);
173
- }
174
- function toCase(value, delimiter, capitalizeAny, capitalizeFirst) {
175
- if (typeof value !== "string") return "";
176
- if (value.length < 1) return value;
177
- const parts = words(value);
178
- const partsLength = parts.length;
179
- const result = [];
180
- for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
181
- const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === "s" ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, "$1-$2").split("-");
182
- const itemsLength = items.length;
183
- const partResult = [];
184
- let itemCount = 0;
185
- for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
186
- const item = items[itemIndex];
187
- if (item.length === 0) continue;
188
- if (!capitalizeAny || itemCount === 0 && partIndex === 0 && true) partResult.push(item.toLocaleLowerCase());
189
- else partResult.push(capitalize(item));
190
- itemCount += 1;
191
- }
192
- result.push(join(partResult, delimiter));
193
- }
194
- return join(result, delimiter);
195
- }
196
- var EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
197
- var EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
198
-
199
- function parse(value, reviver) {
200
- try {
201
- return JSON.parse(value, reviver);
202
- } catch {
203
- return;
204
- }
205
- }
206
-
207
278
  function getBoolean(value, defaultValue) {
208
279
  return typeof value === 'boolean' ? value : (defaultValue ?? false);
209
280
  }
@@ -225,27 +296,6 @@ function getStyleValue(element, property, computed) {
225
296
  }
226
297
  const EXPRESSION_DATA_PREFIX = /^data-/i;
227
298
 
228
- /**
229
- * Is the value an event target?
230
- * @param value Value to check
231
- * @returns `true` if it's an event target, otherwise `false`
232
- */
233
- function isEventTarget(value) {
234
- return (typeof value === 'object' &&
235
- value != null &&
236
- typeof value.addEventListener === 'function' &&
237
- typeof value.removeEventListener === 'function' &&
238
- typeof value.dispatchEvent === 'function');
239
- }
240
- /**
241
- * Is the value an HTML or SVG element?
242
- * @param value Value to check
243
- * @returns `true` if it's an HTML or SVG element, otherwise `false`
244
- */
245
- function isHTMLOrSVGElement(value) {
246
- return value instanceof HTMLElement || value instanceof SVGElement;
247
- }
248
-
249
299
  function getAttribute(element, name, parseValues) {
250
300
  if (isHTMLOrSVGElement(element) && typeof name === 'string') {
251
301
  return getAttributeValue(element, name, parseValues !== false);
@@ -274,73 +324,17 @@ function getAttributes(element, names, parseData) {
274
324
  return attributes;
275
325
  }
276
326
 
277
- function isProperty(value) {
278
- return (isPlainObject(value) && typeof value.name === 'string');
279
- }
280
-
281
- function updateAttribute(element, name, value) {
282
- if (booleanAttributes.includes(name.toLowerCase())) {
283
- updateProperty(element, name, value, false);
284
- }
285
- else if (value == null) {
286
- element.removeAttribute(name);
287
- }
288
- else {
289
- element.setAttribute(name, typeof value === 'string' ? value : getString(value));
290
- }
291
- }
292
- function updateProperty(element, name, value, validate) {
293
- const actual = (validate ?? true) ? name.toLowerCase() : name;
294
- if (actual === 'hidden') {
295
- element.hidden = value === '' || value === true;
296
- }
297
- else {
298
- element[actual] =
299
- value === '' ||
300
- (typeof value === 'string' && value.toLowerCase() === actual) ||
301
- value === true;
302
- }
303
- }
304
- function updateValue(element, first, second, callback) {
305
- if (!isHTMLOrSVGElement(element)) {
306
- return;
307
- }
308
- if (isProperty(first)) {
309
- callback(element, first.name, first.value);
310
- }
311
- else if (typeof first === 'string') {
312
- callback(element, first, second);
313
- }
314
- }
315
- function updateValues(element, values, callback) {
316
- if (!isHTMLOrSVGElement(element)) {
317
- return;
318
- }
319
- const isArray = Array.isArray(values);
320
- const entries = Object.entries(values);
321
- const { length } = entries;
322
- for (let index = 0; index < length; index += 1) {
323
- const entry = entries[index];
324
- if (isArray) {
325
- (callback ?? updateAttribute)(element, entry[1].name, entry[1].value);
326
- }
327
- else {
328
- (callback ?? updateAttribute)(element, entry[0], entry[1]);
329
- }
330
- }
331
- }
332
-
333
327
  function setAttribute(element, first, second) {
334
- updateValue(element, first, second, updateAttribute);
328
+ updateValue(element, first, second);
335
329
  }
336
330
  function setAttributes(element, attributes) {
337
331
  updateValues(element, attributes);
338
332
  }
339
333
  function setProperty(element, first, second) {
340
- updateValue(element, first, second, updateProperty);
334
+ updateValue(element, first, second);
341
335
  }
342
336
  function setProperties(element, properties) {
343
- updateValues(element, properties, updateProperty);
337
+ updateValues(element, properties);
344
338
  }
345
339
 
346
340
  /**
package/package.json CHANGED
@@ -13,7 +13,6 @@
13
13
  "@rollup/plugin-typescript": "^12.3",
14
14
  "@types/node": "^24.10",
15
15
  "@vitest/coverage-istanbul": "^4",
16
- "glob": "^11",
17
16
  "jsdom": "^27.2",
18
17
  "rollup": "^4.53",
19
18
  "tslib": "^2.8",
@@ -93,5 +92,5 @@
93
92
  },
94
93
  "type": "module",
95
94
  "types": "types/index.d.ts",
96
- "version": "0.26.1"
95
+ "version": "0.27.0"
97
96
  }
@@ -1,21 +1,18 @@
1
+ import {updateValue, updateValues} from '../internal/attribute';
1
2
  import type {Attribute, HTMLOrSVGElement, Property} from '../models';
2
- import {
3
- updateAttribute,
4
- updateProperty,
5
- updateValue,
6
- updateValues,
7
- } from './update';
8
3
 
9
4
  /**
10
5
  * Set an attribute on an element
11
6
  *
12
7
  * _(Or remove it, if value is `null` or `undefined`)_
13
8
  * @param element Element for attribute
14
- * @param attribute Attribute to set
9
+ * @param name Attribute name
10
+ * @param value Attribute value
15
11
  */
16
12
  export function setAttribute(
17
13
  element: HTMLOrSVGElement,
18
- attribute: Attr | Attribute,
14
+ name: string,
15
+ value?: unknown,
19
16
  ): void;
20
17
 
21
18
  /**
@@ -23,13 +20,11 @@ export function setAttribute(
23
20
  *
24
21
  * _(Or remove it, if value is `null` or `undefined`)_
25
22
  * @param element Element for attribute
26
- * @param name Attribute name
27
- * @param value Attribute value
23
+ * @param attribute Attribute to set
28
24
  */
29
25
  export function setAttribute(
30
26
  element: HTMLOrSVGElement,
31
- name: string,
32
- value?: unknown,
27
+ attribute: Attr | Attribute,
33
28
  ): void;
34
29
 
35
30
  export function setAttribute(
@@ -37,7 +32,7 @@ export function setAttribute(
37
32
  first: unknown,
38
33
  second?: unknown,
39
34
  ): void {
40
- updateValue(element, first, second, updateAttribute);
35
+ updateValue(element, first, second);
41
36
  }
42
37
 
43
38
  /**
@@ -76,11 +71,13 @@ export function setAttributes(
76
71
  *
77
72
  * _(Or remove it, if value is not an empty string or does not match the name)_
78
73
  * @param element Element for property
79
- * @param property Property to set
74
+ * @param name Property name
75
+ * @param value Property value
80
76
  */
81
77
  export function setProperty(
82
78
  element: HTMLOrSVGElement,
83
- property: Property,
79
+ name: string,
80
+ value: boolean | string,
84
81
  ): void;
85
82
 
86
83
  /**
@@ -88,13 +85,11 @@ export function setProperty(
88
85
  *
89
86
  * _(Or remove it, if value is not an empty string or does not match the name)_
90
87
  * @param element Element for property
91
- * @param name Property name
92
- * @param value Property value
88
+ * @param property Property to set
93
89
  */
94
90
  export function setProperty(
95
91
  element: HTMLOrSVGElement,
96
- name: string,
97
- value: boolean | string,
92
+ property: Property,
98
93
  ): void;
99
94
 
100
95
  export function setProperty(
@@ -102,7 +97,7 @@ export function setProperty(
102
97
  first: unknown,
103
98
  second?: unknown,
104
99
  ): void {
105
- updateValue(element, first, second, updateProperty);
100
+ updateValue(element, first, second);
106
101
  }
107
102
 
108
103
  /**
@@ -133,5 +128,5 @@ export function setProperties(
133
128
  element: HTMLOrSVGElement,
134
129
  properties: Property[] | Record<string, unknown>,
135
130
  ): void {
136
- updateValues(element, properties, updateProperty);
131
+ updateValues(element, properties);
137
132
  }
@@ -111,6 +111,34 @@ export function getPosition(
111
111
  return typeof x === 'number' && typeof y === 'number' ? {x, y} : undefined;
112
112
  }
113
113
 
114
+ /**
115
+ * Remove an event listener
116
+ * @param target Event target
117
+ * @param type Type of event
118
+ * @param listener Event listener
119
+ * @param options Options for event
120
+ */
121
+ export function off(
122
+ target: EventTarget,
123
+ type: keyof HTMLElementEventMap,
124
+ listener: EventListener | CustomEventListener,
125
+ options?: EventListenerOptions,
126
+ ): void;
127
+
128
+ /**
129
+ * Remove an event listener
130
+ * @param target Event target
131
+ * @param type Type of event
132
+ * @param listener Event listener
133
+ * @param options Options for event
134
+ */
135
+ export function off(
136
+ target: EventTarget,
137
+ type: string,
138
+ listener: EventListener | CustomEventListener,
139
+ options?: EventListenerOptions,
140
+ ): void;
141
+
114
142
  /**
115
143
  * Remove an event listener
116
144
  * @param target Event target
package/src/html.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {isPlainObject} from '@oscarpalmer/atoms/is';
2
2
  import {
3
- type SanitizeOptions,
4
3
  getSanitizeOptions,
4
+ type SanitizeOptions,
5
5
  sanitizeNodes,
6
6
  } from './internal/sanitize';
7
7
 
@@ -1,6 +1,8 @@
1
1
  import type {PlainObject} from '@oscarpalmer/atoms';
2
2
  import {isPlainObject} from '@oscarpalmer/atoms/is';
3
- import type {Attribute} from '../models';
3
+ import {getString} from '@oscarpalmer/atoms/string';
4
+ import type {Attribute, HTMLOrSVGElement, Property} from '../models';
5
+ import {isHTMLOrSVGElement} from './is';
4
6
 
5
7
  function isAttribute(value: unknown): value is Attr | Attribute {
6
8
  return (
@@ -141,6 +143,12 @@ export function isInvalidBooleanAttribute(
141
143
  );
142
144
  }
143
145
 
146
+ export function isProperty(value: unknown): value is Property {
147
+ return (
148
+ isPlainObject(value) && typeof (value as PlainObject).name === 'string'
149
+ );
150
+ }
151
+
144
152
  function isValidAttribute(
145
153
  callback: (attribute: Attr | Attribute | undefined) => boolean,
146
154
  first: string | Attr | Attribute,
@@ -157,6 +165,84 @@ function isValidAttribute(
157
165
  return callback(attribute);
158
166
  }
159
167
 
168
+ function updateAttribute(
169
+ element: HTMLOrSVGElement,
170
+ name: string,
171
+ value: unknown,
172
+ ): void {
173
+ const isBoolean = booleanAttributes.includes(name.toLowerCase());
174
+
175
+ if (isBoolean) {
176
+ updateProperty(element, name, value);
177
+ }
178
+
179
+ if (isBoolean ? value !== true : value == null) {
180
+ element.removeAttribute(name);
181
+ } else {
182
+ element.setAttribute(name, isBoolean ? '' : getString(value));
183
+ }
184
+ }
185
+
186
+ function updateProperty(
187
+ element: HTMLOrSVGElement,
188
+ name: string,
189
+ value: unknown,
190
+ ): void {
191
+ const actual = name.toLowerCase();
192
+
193
+ (element as unknown as PlainObject)[actual] =
194
+ value === '' ||
195
+ (typeof value === 'string' && value.toLowerCase() === actual) ||
196
+ value === true;
197
+ }
198
+
199
+ export function updateValue(
200
+ element: HTMLOrSVGElement,
201
+ first: unknown,
202
+ second: unknown,
203
+ ): void {
204
+ if (!isHTMLOrSVGElement(element)) {
205
+ return;
206
+ }
207
+
208
+ if (isProperty(first)) {
209
+ updateAttribute(
210
+ element,
211
+ (first as Attribute).name,
212
+ (first as Attribute).value,
213
+ );
214
+ } else if (typeof first === 'string') {
215
+ updateAttribute(element, first as string, second);
216
+ }
217
+ }
218
+
219
+ export function updateValues(
220
+ element: HTMLOrSVGElement,
221
+ values: Attribute<unknown>[] | Record<string, unknown>,
222
+ ): void {
223
+ if (!isHTMLOrSVGElement(element)) {
224
+ return;
225
+ }
226
+
227
+ const isArray = Array.isArray(values);
228
+ const entries = Object.entries(values);
229
+ const {length} = entries;
230
+
231
+ for (let index = 0; index < length; index += 1) {
232
+ const entry = entries[index];
233
+
234
+ if (isArray) {
235
+ updateAttribute(
236
+ element,
237
+ (entry[1] as Attribute).name,
238
+ (entry[1] as Attribute).value,
239
+ );
240
+ } else {
241
+ updateAttribute(element, entry[0], entry[1]);
242
+ }
243
+ }
244
+ }
245
+
160
246
  //
161
247
 
162
248
  const EXPRESSION_ON_PREFIX = /^on/i;
@@ -4,18 +4,18 @@ import type { Attribute, HTMLOrSVGElement, Property } from '../models';
4
4
  *
5
5
  * _(Or remove it, if value is `null` or `undefined`)_
6
6
  * @param element Element for attribute
7
- * @param attribute Attribute to set
7
+ * @param name Attribute name
8
+ * @param value Attribute value
8
9
  */
9
- export declare function setAttribute(element: HTMLOrSVGElement, attribute: Attr | Attribute): void;
10
+ export declare function setAttribute(element: HTMLOrSVGElement, name: string, value?: unknown): void;
10
11
  /**
11
12
  * Set an attribute on an element
12
13
  *
13
14
  * _(Or remove it, if value is `null` or `undefined`)_
14
15
  * @param element Element for attribute
15
- * @param name Attribute name
16
- * @param value Attribute value
16
+ * @param attribute Attribute to set
17
17
  */
18
- export declare function setAttribute(element: HTMLOrSVGElement, name: string, value?: unknown): void;
18
+ export declare function setAttribute(element: HTMLOrSVGElement, attribute: Attr | Attribute): void;
19
19
  /**
20
20
  * Set one or more attributes on an element
21
21
  *
@@ -37,18 +37,18 @@ export declare function setAttributes(element: HTMLOrSVGElement, attributes: Rec
37
37
  *
38
38
  * _(Or remove it, if value is not an empty string or does not match the name)_
39
39
  * @param element Element for property
40
- * @param property Property to set
40
+ * @param name Property name
41
+ * @param value Property value
41
42
  */
42
- export declare function setProperty(element: HTMLOrSVGElement, property: Property): void;
43
+ export declare function setProperty(element: HTMLOrSVGElement, name: string, value: boolean | string): void;
43
44
  /**
44
45
  * Set a property on an element
45
46
  *
46
47
  * _(Or remove it, if value is not an empty string or does not match the name)_
47
48
  * @param element Element for property
48
- * @param name Property name
49
- * @param value Property value
49
+ * @param property Property to set
50
50
  */
51
- export declare function setProperty(element: HTMLOrSVGElement, name: string, value: boolean | string): void;
51
+ export declare function setProperty(element: HTMLOrSVGElement, property: Property): void;
52
52
  /**
53
53
  * Set one or more properties on an element
54
54
  *
@@ -19,6 +19,14 @@ export declare function dispatch(target: EventTarget, type: string, options?: Cu
19
19
  * @returns X- and Y-coordinates
20
20
  */
21
21
  export declare function getPosition(event: MouseEvent | TouchEvent): EventPosition | undefined;
22
+ /**
23
+ * Remove an event listener
24
+ * @param target Event target
25
+ * @param type Type of event
26
+ * @param listener Event listener
27
+ * @param options Options for event
28
+ */
29
+ export declare function off(target: EventTarget, type: keyof HTMLElementEventMap, listener: EventListener | CustomEventListener, options?: EventListenerOptions): void;
22
30
  /**
23
31
  * Remove an event listener
24
32
  * @param target Event target
@@ -1,4 +1,4 @@
1
- import type { Attribute } from '../models';
1
+ import type { Attribute, HTMLOrSVGElement, Property } from '../models';
2
2
  /**
3
3
  * Is the attribute considered bad and potentially harmful?
4
4
  * @param attribute Attribute to check
@@ -54,6 +54,9 @@ export declare function isInvalidBooleanAttribute(attribute: Attr | Attribute):
54
54
  * @returns `true` if attribute is an invalid boolean attribute
55
55
  */
56
56
  export declare function isInvalidBooleanAttribute(name: string, value: string): boolean;
57
+ export declare function isProperty(value: unknown): value is Property;
58
+ export declare function updateValue(element: HTMLOrSVGElement, first: unknown, second: unknown): void;
59
+ export declare function updateValues(element: HTMLOrSVGElement, values: Attribute<unknown>[] | Record<string, unknown>): void;
57
60
  /**
58
61
  * List of boolean attributes
59
62
  */
@@ -1,5 +0,0 @@
1
- import { isPlainObject } from "@oscarpalmer/atoms/is";
2
- function isProperty(value) {
3
- return isPlainObject(value) && typeof value.name === "string";
4
- }
5
- export { isProperty };
File without changes
@@ -1,31 +0,0 @@
1
- import { isHTMLOrSVGElement } from "../internal/is.js";
2
- import { booleanAttributes } from "../internal/attribute.js";
3
- import { isProperty } from "./is.js";
4
- import { getString } from "@oscarpalmer/atoms/string";
5
- function updateAttribute(element, name, value) {
6
- if (booleanAttributes.includes(name.toLowerCase())) updateProperty(element, name, value, false);
7
- else if (value == null) element.removeAttribute(name);
8
- else element.setAttribute(name, typeof value === "string" ? value : getString(value));
9
- }
10
- function updateProperty(element, name, value, validate) {
11
- const actual = validate ?? true ? name.toLowerCase() : name;
12
- if (actual === "hidden") element.hidden = value === "" || value === true;
13
- else element[actual] = value === "" || typeof value === "string" && value.toLowerCase() === actual || value === true;
14
- }
15
- function updateValue(element, first, second, callback) {
16
- if (!isHTMLOrSVGElement(element)) return;
17
- if (isProperty(first)) callback(element, first.name, first.value);
18
- else if (typeof first === "string") callback(element, first, second);
19
- }
20
- function updateValues(element, values, callback) {
21
- if (!isHTMLOrSVGElement(element)) return;
22
- const isArray = Array.isArray(values);
23
- const entries = Object.entries(values);
24
- const { length } = entries;
25
- for (let index = 0; index < length; index += 1) {
26
- const entry = entries[index];
27
- if (isArray) (callback ?? updateAttribute)(element, entry[1].name, entry[1].value);
28
- else (callback ?? updateAttribute)(element, entry[0], entry[1]);
29
- }
30
- }
31
- export { updateAttribute, updateProperty, updateValue, updateValues };
@@ -1,9 +0,0 @@
1
- import type {PlainObject} from '@oscarpalmer/atoms';
2
- import {isPlainObject} from '@oscarpalmer/atoms/is';
3
- import type {Property} from '../models';
4
-
5
- export function isProperty(value: unknown): value is Property {
6
- return (
7
- isPlainObject(value) && typeof (value as PlainObject).name === 'string'
8
- );
9
- }
File without changes
@@ -1,86 +0,0 @@
1
- import type {PlainObject} from '@oscarpalmer/atoms';
2
- import {getString} from '@oscarpalmer/atoms/string';
3
- import {booleanAttributes} from '../internal/attribute';
4
- import {isHTMLOrSVGElement} from '../internal/is';
5
- import type {Attribute, HTMLOrSVGElement} from '../models';
6
- import {isProperty} from './is';
7
-
8
- export function updateAttribute(
9
- element: HTMLOrSVGElement,
10
- name: string,
11
- value: unknown,
12
- ): void {
13
- if (booleanAttributes.includes(name.toLowerCase())) {
14
- updateProperty(element, name, value, false);
15
- } else if (value == null) {
16
- element.removeAttribute(name);
17
- } else {
18
- element.setAttribute(
19
- name,
20
- typeof value === 'string' ? value : getString(value),
21
- );
22
- }
23
- }
24
-
25
- export function updateProperty(
26
- element: HTMLOrSVGElement,
27
- name: string,
28
- value: unknown,
29
- validate?: boolean,
30
- ): void {
31
- const actual = (validate ?? true) ? name.toLowerCase() : name;
32
-
33
- if (actual === 'hidden') {
34
- (element as HTMLElement).hidden = value === '' || value === true;
35
- } else {
36
- (element as unknown as PlainObject)[actual] =
37
- value === '' ||
38
- (typeof value === 'string' && value.toLowerCase() === actual) ||
39
- value === true;
40
- }
41
- }
42
-
43
- export function updateValue(
44
- element: HTMLOrSVGElement,
45
- first: unknown,
46
- second: unknown,
47
- callback: (element: HTMLOrSVGElement, name: string, value: unknown) => void,
48
- ): void {
49
- if (!isHTMLOrSVGElement(element)) {
50
- return;
51
- }
52
-
53
- if (isProperty(first)) {
54
- callback(element, (first as Attribute).name, (first as Attribute).value);
55
- } else if (typeof first === 'string') {
56
- callback(element, first as string, second);
57
- }
58
- }
59
-
60
- export function updateValues(
61
- element: HTMLOrSVGElement,
62
- values: Attribute<unknown>[] | Record<string, unknown>,
63
- callback?: (element: HTMLOrSVGElement, name: string, value: unknown) => void,
64
- ): void {
65
- if (!isHTMLOrSVGElement(element)) {
66
- return;
67
- }
68
-
69
- const isArray = Array.isArray(values);
70
- const entries = Object.entries(values);
71
- const {length} = entries;
72
-
73
- for (let index = 0; index < length; index += 1) {
74
- const entry = entries[index];
75
-
76
- if (isArray) {
77
- (callback ?? updateAttribute)(
78
- element,
79
- (entry[1] as Attribute).name,
80
- (entry[1] as Attribute).value,
81
- );
82
- } else {
83
- (callback ?? updateAttribute)(element, entry[0], entry[1]);
84
- }
85
- }
86
- }
@@ -1,2 +0,0 @@
1
- import type { Property } from '../models';
2
- export declare function isProperty(value: unknown): value is Property;
@@ -1 +0,0 @@
1
- export {};
@@ -1,5 +0,0 @@
1
- import type { Attribute, HTMLOrSVGElement } from '../models';
2
- export declare function updateAttribute(element: HTMLOrSVGElement, name: string, value: unknown): void;
3
- export declare function updateProperty(element: HTMLOrSVGElement, name: string, value: unknown, validate?: boolean): void;
4
- export declare function updateValue(element: HTMLOrSVGElement, first: unknown, second: unknown, callback: (element: HTMLOrSVGElement, name: string, value: unknown) => void): void;
5
- export declare function updateValues(element: HTMLOrSVGElement, values: Attribute<unknown>[] | Record<string, unknown>, callback?: (element: HTMLOrSVGElement, name: string, value: unknown) => void): void;