@oscarpalmer/toretto 0.41.0 → 0.42.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.
Files changed (55) hide show
  1. package/dist/attribute/{get.d.mts → get.attribute.d.mts} +3 -2
  2. package/dist/attribute/{get.mjs → get.attribute.mjs} +4 -3
  3. package/dist/attribute/index.d.mts +3 -16
  4. package/dist/attribute/index.mjs +4 -7
  5. package/dist/attribute/{set.d.mts → set.attribute.d.mts} +4 -4
  6. package/dist/attribute/{set.mjs → set.attribute.mjs} +2 -2
  7. package/dist/create.d.mts +25 -0
  8. package/dist/create.mjs +17 -0
  9. package/dist/data.mjs +7 -7
  10. package/dist/event/delegation.mjs +8 -1
  11. package/dist/html/index.d.mts +23 -26
  12. package/dist/html/index.mjs +85 -18
  13. package/dist/html/sanitize.mjs +6 -5
  14. package/dist/index.d.mts +113 -52
  15. package/dist/index.mjs +510 -361
  16. package/dist/internal/attribute.d.mts +4 -3
  17. package/dist/internal/attribute.mjs +13 -23
  18. package/dist/internal/element-value.d.mts +2 -2
  19. package/dist/internal/element-value.mjs +4 -2
  20. package/dist/internal/get-value.mjs +1 -1
  21. package/dist/internal/property.d.mts +4 -0
  22. package/dist/internal/property.mjs +21 -0
  23. package/dist/property/get.property.d.mts +20 -0
  24. package/dist/property/get.property.mjs +35 -0
  25. package/dist/property/index.d.mts +3 -0
  26. package/dist/property/index.mjs +3 -0
  27. package/dist/property/set.property.d.mts +32 -0
  28. package/dist/property/set.property.mjs +34 -0
  29. package/dist/style.d.mts +12 -7
  30. package/dist/style.mjs +14 -18
  31. package/package.json +12 -5
  32. package/src/attribute/{get.ts → get.attribute.ts} +14 -3
  33. package/src/attribute/index.ts +10 -22
  34. package/src/attribute/{set.ts → set.attribute.ts} +9 -5
  35. package/src/create.ts +81 -0
  36. package/src/data.ts +16 -8
  37. package/src/event/delegation.ts +24 -3
  38. package/src/event/index.ts +9 -3
  39. package/src/find/index.ts +11 -3
  40. package/src/find/relative.ts +4 -0
  41. package/src/focusable.ts +10 -2
  42. package/src/html/index.ts +166 -58
  43. package/src/html/sanitize.ts +14 -11
  44. package/src/index.ts +2 -1
  45. package/src/internal/attribute.ts +23 -42
  46. package/src/internal/element-value.ts +11 -4
  47. package/src/internal/get-value.ts +8 -0
  48. package/src/internal/is.ts +4 -0
  49. package/src/internal/property.ts +42 -0
  50. package/src/is.ts +10 -2
  51. package/src/property/get.property.ts +73 -0
  52. package/src/property/index.ts +2 -0
  53. package/src/property/set.property.ts +102 -0
  54. package/src/style.ts +52 -27
  55. package/src/touch.ts +14 -2
package/src/index.ts CHANGED
@@ -6,11 +6,11 @@ export {
6
6
  getAttributes,
7
7
  isBadAttribute,
8
8
  isBooleanAttribute,
9
- isEmptyNonBooleanAttribute,
10
9
  isInvalidBooleanAttribute,
11
10
  setAttribute,
12
11
  setAttributes,
13
12
  } from './attribute/index';
13
+ export * from './create';
14
14
  export * from './data';
15
15
  export * from './event/index';
16
16
  export * from './find/index';
@@ -18,6 +18,7 @@ export * from './focusable';
18
18
  export * from './html/index';
19
19
  export * from './is';
20
20
  export * from './models';
21
+ export * from './property/index';
21
22
  export * from './style';
22
23
 
23
24
  export {supportsTouch};
@@ -1,7 +1,11 @@
1
- import type {PlainObject} from '@oscarpalmer/atoms/models';
2
1
  import {isPlainObject} from '@oscarpalmer/atoms/is';
2
+ import type {PlainObject} from '@oscarpalmer/atoms/models';
3
+ import {kebabCase} from '@oscarpalmer/atoms/string/case';
3
4
  import type {Attribute} from '../models';
4
5
  import {updateElementValue} from './element-value';
6
+ import {updateProperty} from './property';
7
+
8
+ // #region Functions
5
9
 
6
10
  function badAttributeHandler(name?: string, value?: string): boolean {
7
11
  if (typeof name !== 'string' || name.trim().length === 0 || typeof value !== 'string') {
@@ -67,6 +71,10 @@ function handleAttribute(
67
71
  value = second;
68
72
  }
69
73
 
74
+ if (name != null) {
75
+ name = kebabCase(name);
76
+ }
77
+
70
78
  if (decode && value != null) {
71
79
  value = decodeAttribute(value);
72
80
  }
@@ -96,20 +104,6 @@ export function _isBooleanAttribute(first: unknown, decode: boolean): boolean {
96
104
  );
97
105
  }
98
106
 
99
- export function _isEmptyNonBooleanAttribute(
100
- first: unknown,
101
- second: unknown,
102
- decode: boolean,
103
- ): boolean {
104
- return handleAttribute(
105
- (name, value) =>
106
- name != null && value != null && !booleanAttributesSet.has(name) && value.trim().length === 0,
107
- decode,
108
- first,
109
- second,
110
- );
111
- }
112
-
113
107
  export function _isInvalidBooleanAttribute(
114
108
  first: unknown,
115
109
  second: unknown,
@@ -126,49 +120,39 @@ export function updateAttribute(
126
120
  element: Element,
127
121
  name: string,
128
122
  value: unknown,
129
- dispatch?: unknown,
123
+ dispatch: boolean,
130
124
  ): void {
131
- const normalizedName = name.toLowerCase();
125
+ const lowerCaseName = name.toLowerCase();
132
126
 
133
- const isBoolean = booleanAttributesSet.has(normalizedName);
127
+ const isBoolean = booleanAttributesSet.has(lowerCaseName);
134
128
 
135
129
  const next = isBoolean
136
130
  ? value === true ||
137
- (typeof value === 'string' && (value === '' || value.toLowerCase() === normalizedName))
131
+ (typeof value === 'string' && (value === '' || value.toLowerCase() === lowerCaseName))
138
132
  : value == null
139
133
  ? ''
140
134
  : value;
141
135
 
142
- if (name in element) {
143
- updateProperty(element, normalizedName, next, dispatch);
136
+ if (isBoolean || dispatchedAttributes.has(name)) {
137
+ updateProperty(element, name, next, dispatch);
144
138
  }
145
139
 
146
140
  updateElementValue(
147
141
  element,
148
142
  name,
149
143
  isBoolean ? (next ? '' : null) : value,
144
+ // oxlint-disable-next-line typescript/unbound-method: using `.call` in `updateElementValue`
150
145
  element.setAttribute,
146
+ // oxlint-disable-next-line typescript/unbound-method: using `.call` in `updateElementValue`
151
147
  element.removeAttribute,
152
148
  isBoolean,
153
149
  false,
154
150
  );
155
151
  }
156
152
 
157
- function updateProperty(element: Element, name: string, value: unknown, dispatch?: unknown): void {
158
- if (Object.is((element as unknown as PlainObject)[name], value)) {
159
- return;
160
- }
161
-
162
- (element as unknown as PlainObject)[name] = value;
153
+ // #endregion
163
154
 
164
- const event = dispatch !== false && elementEvents[element.tagName]?.[name];
165
-
166
- if (typeof event === 'string') {
167
- element.dispatchEvent(new Event(event, {bubbles: true}));
168
- }
169
- }
170
-
171
- //
155
+ // #region Variables
172
156
 
173
157
  const EXPRESSION_CLOBBERED_NAME = /^(id|name)$/i;
174
158
 
@@ -220,15 +204,12 @@ export const booleanAttributes: readonly string[] = Object.freeze([
220
204
  'selected',
221
205
  ]);
222
206
 
223
- const booleanAttributesSet = new Set(booleanAttributes);
207
+ export const booleanAttributesSet = new Set(booleanAttributes);
224
208
 
225
- const elementEvents: Record<string, Record<string, string>> = {
226
- DETAILS: {open: 'toggle'},
227
- INPUT: {checked: 'change', value: 'input'},
228
- SELECT: {value: 'change'},
229
- TEXTAREA: {value: 'input'},
230
- };
209
+ export const dispatchedAttributes = new Set(['checked', 'open', 'value']);
231
210
 
232
211
  const formElement = document.createElement('form');
233
212
 
234
213
  let textArea: HTMLTextAreaElement;
214
+
215
+ // #endregion
@@ -1,13 +1,16 @@
1
1
  import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
2
+ import {kebabCase} from '@oscarpalmer/atoms/string/case';
2
3
  import {isHTMLOrSVGElement} from '../is';
3
4
  import {isAttribute} from './attribute';
4
5
 
6
+ // #region Functions
7
+
5
8
  export function setElementValue(
6
9
  element: Element,
7
10
  first: unknown,
8
11
  second: unknown,
9
12
  third: unknown,
10
- callback: (element: Element, key: string, value: unknown) => void,
13
+ callback: (element: Element, key: string, value: unknown, dispatch: boolean) => void,
11
14
  ): void {
12
15
  if (!isHTMLOrSVGElement(element)) {
13
16
  return;
@@ -25,14 +28,16 @@ export function setElementValues(
25
28
  first: unknown,
26
29
  second: unknown,
27
30
  third: unknown,
28
- callback: (element: Element, key: string, value: unknown, dispatch?: unknown) => void,
31
+ callback: (element: Element, key: string, value: unknown, dispatch: boolean) => void,
29
32
  ): void {
30
33
  if (!isHTMLOrSVGElement(element)) {
31
34
  return;
32
35
  }
33
36
 
37
+ const dispatch = third !== false;
38
+
34
39
  if (typeof first === 'string') {
35
- callback(element, first, second, third);
40
+ callback(element, kebabCase(first), second, dispatch);
36
41
 
37
42
  return;
38
43
  }
@@ -50,7 +55,7 @@ export function setElementValues(
50
55
  const entry = entries[index];
51
56
 
52
57
  if (typeof entry === 'object' && typeof entry?.name === 'string') {
53
- callback(element, entry.name, entry.value, third);
58
+ callback(element, kebabCase(entry.name), entry.value, dispatch);
54
59
  }
55
60
  }
56
61
  }
@@ -70,3 +75,5 @@ export function updateElementValue(
70
75
  set.call(element, key, json ? JSON.stringify(value) : String(value));
71
76
  }
72
77
  }
78
+
79
+ // #endregion Functions
@@ -1,6 +1,8 @@
1
1
  import {parse} from '@oscarpalmer/atoms/string';
2
2
  import {camelCase, kebabCase} from '@oscarpalmer/atoms/string/case';
3
3
 
4
+ // #region Functions
5
+
4
6
  export function getBoolean(value: unknown, defaultValue?: boolean): boolean {
5
7
  return typeof value === 'boolean' ? value : (defaultValue ?? false);
6
8
  }
@@ -27,4 +29,10 @@ export function getStyleValue(
27
29
  : (element as HTMLElement).style[name as never];
28
30
  }
29
31
 
32
+ // #endregion
33
+
34
+ // #region Variables
35
+
30
36
  export const EXPRESSION_DATA_PREFIX = /^data-/i;
37
+
38
+ // #endregion
@@ -1,3 +1,5 @@
1
+ // #region Functions
2
+
1
3
  /**
2
4
  * Is the value an event target?
3
5
  * @param value Value to check
@@ -21,3 +23,5 @@ export function isEventTarget(value: unknown): value is EventTarget {
21
23
  export function isHTMLOrSVGElement(value: unknown): value is HTMLElement | SVGElement {
22
24
  return value instanceof HTMLElement || value instanceof SVGElement;
23
25
  }
26
+
27
+ // #endregion
@@ -0,0 +1,42 @@
1
+ import type {PlainObject} from '@oscarpalmer/atoms/models';
2
+ import {camelCase} from '@oscarpalmer/atoms/string/case';
3
+
4
+ // #region Functions
5
+
6
+ export function updateProperty(
7
+ element: Element,
8
+ name: string,
9
+ value: unknown,
10
+ dispatch: boolean,
11
+ ): void {
12
+ let property = name;
13
+
14
+ if (!(property in element)) {
15
+ property = camelCase(name);
16
+ }
17
+
18
+ if (!(property in element) || Object.is((element as unknown as PlainObject)[property], value)) {
19
+ return;
20
+ }
21
+
22
+ (element as unknown as PlainObject)[property] = value;
23
+
24
+ const event = dispatch && elementEvents[element.tagName]?.[property];
25
+
26
+ if (typeof event === 'string') {
27
+ element.dispatchEvent(new Event(event, {bubbles: true}));
28
+ }
29
+ }
30
+
31
+ // #endregion
32
+
33
+ // #region Variables
34
+
35
+ const elementEvents: Record<string, Record<string, string>> = {
36
+ DETAILS: {open: 'toggle'},
37
+ INPUT: {checked: 'change', value: 'input'},
38
+ SELECT: {value: 'change'},
39
+ TEXTAREA: {value: 'input'},
40
+ };
41
+
42
+ // #endregion
package/src/is.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // #region Functions
2
+
1
3
  /**
2
4
  * Is the value a child node?
3
5
  * @param value Value to check
@@ -36,7 +38,9 @@ export function isInDocument(node: Node, doc?: Document): boolean {
36
38
  : node.ownerDocument === doc && doc.contains(node);
37
39
  }
38
40
 
39
- //
41
+ // #endregion
42
+
43
+ // #region Variables
40
44
 
41
45
  const CHILD_NODE_TYPES: Set<number> = new Set([
42
46
  Node.ELEMENT_NODE,
@@ -46,6 +50,10 @@ const CHILD_NODE_TYPES: Set<number> = new Set([
46
50
  Node.DOCUMENT_TYPE_NODE,
47
51
  ]);
48
52
 
49
- //
53
+ // #endregion
54
+
55
+ // #region Exports
50
56
 
51
57
  export {isEventTarget, isHTMLOrSVGElement} from './internal/is';
58
+
59
+ // #endregion
@@ -0,0 +1,73 @@
1
+ import type {Primitive} from '@oscarpalmer/atoms/models';
2
+ import {camelCase} from '@oscarpalmer/atoms/string/case';
3
+ import {isHTMLOrSVGElement} from '../internal/is';
4
+
5
+ // #region Types
6
+
7
+ type GetProperties<Target extends Element> = {
8
+ [Property in keyof Target as Target[Property] extends Primitive
9
+ ? Property
10
+ : never]?: Target[Property];
11
+ };
12
+
13
+ // #endregion
14
+
15
+ // #region Functions
16
+
17
+ /**
18
+ * Get the values of one or more properties on an element
19
+ * @param target Target element
20
+ * @param properties Properties to get
21
+ * @returns Property values
22
+ */
23
+ export function getProperties<Target extends Element, Property extends keyof GetProperties<Target>>(
24
+ target: Target,
25
+ properties: Property[],
26
+ ): Pick<GetProperties<Target>, Property> {
27
+ const values: Partial<GetProperties<Target>> = {};
28
+
29
+ if (!isHTMLOrSVGElement(target) || !Array.isArray(properties)) {
30
+ return values as Pick<GetProperties<Target>, Property>;
31
+ }
32
+
33
+ const {length} = properties;
34
+
35
+ for (let index = 0; index < length; index += 1) {
36
+ const property = properties[index];
37
+
38
+ if (typeof property === 'string') {
39
+ values[property] = getPropertyValue(target, property) as GetProperties<Target>[Property];
40
+ }
41
+ }
42
+
43
+ return values as Pick<GetProperties<Target>, Property>;
44
+ }
45
+
46
+ /**
47
+ * Get the value of a property on an element
48
+ * @param target Target element
49
+ * @param property Property to get
50
+ * @returns Property value
51
+ */
52
+ export function getProperty<Target extends Element, Property extends keyof GetProperties<Target>>(
53
+ target: Target,
54
+ property: Property,
55
+ ): GetProperties<Target>[Property] {
56
+ if (isHTMLOrSVGElement(target) && typeof property === 'string') {
57
+ return getPropertyValue(target, property) as GetProperties<Target>[Property];
58
+ }
59
+ }
60
+
61
+ function getPropertyValue(element: HTMLElement, property: string): unknown {
62
+ let actual = property;
63
+
64
+ if (!(actual in element)) {
65
+ actual = camelCase(actual);
66
+ }
67
+
68
+ if (actual in element) {
69
+ return element[actual as keyof HTMLElement];
70
+ }
71
+ }
72
+
73
+ // #endregion
@@ -0,0 +1,2 @@
1
+ export * from './get.property';
2
+ export * from './set.property';
@@ -0,0 +1,102 @@
1
+ import {isPlainObject} from '@oscarpalmer/atoms/is';
2
+ import type {PlainObject, Primitive} from '@oscarpalmer/atoms/models';
3
+ import {setAttribute} from '../attribute';
4
+ import type {DispatchedAttributeName} from '../attribute/set.attribute';
5
+ import {booleanAttributesSet, dispatchedAttributes} from '../internal/attribute';
6
+ import {updateProperty} from '../internal/property';
7
+ import {isHTMLOrSVGElement} from '../is';
8
+
9
+ // #region Types
10
+
11
+ type DispatchedPropertyValue<
12
+ Target extends Element,
13
+ Property extends DispatchedAttributeName,
14
+ > = Property extends keyof SetProperties<Target> ? SetProperties<Target>[Property] : never;
15
+
16
+ type SetProperties<Target extends Element> = {
17
+ [Property in keyof Target as Target[Property] extends Primitive
18
+ ? Property
19
+ : never]?: Target[Property];
20
+ };
21
+
22
+ // #endregion
23
+
24
+ // #region Functions
25
+
26
+ /**
27
+ * Set the values of one or more properties on an element
28
+ *
29
+ * Also updates attributes for boolean/dispatchable properties, and if `dispatch` is `true`, will dispatch events for dispatchable properties
30
+ * @param target Target element
31
+ * @param properties Properties to set
32
+ * @param dispatch Dispatch events for properties? _(defaults to `true`)_
33
+ */
34
+ export function setProperties<Target extends Element>(
35
+ target: Target,
36
+ properties: SetProperties<Target>,
37
+ dispatch?: boolean,
38
+ ): void {
39
+ if (!isHTMLOrSVGElement(target) || !isPlainObject(properties)) {
40
+ return;
41
+ }
42
+
43
+ const shouldDispatch = dispatch !== false;
44
+
45
+ const keys = Object.keys(properties);
46
+ const {length} = keys;
47
+
48
+ for (let index = 0; index < length; index += 1) {
49
+ const key = keys[index];
50
+
51
+ if (booleanAttributesSet.has(key.toLowerCase()) || dispatchedAttributes.has(key)) {
52
+ setAttribute(target, key as never, (properties as PlainObject)[key], shouldDispatch);
53
+ } else {
54
+ updateProperty(target, key, (properties as PlainObject)[key], shouldDispatch);
55
+ }
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Set the value for a dispatchable property on an element
61
+ * @param target Target element
62
+ * @param property Property to set
63
+ * @param value Value to set
64
+ * @param dispatch Dispatch event for property? _(defaults to `true`)_
65
+ */
66
+ export function setProperty<Target extends Element, Property extends DispatchedAttributeName>(
67
+ target: Target,
68
+ property: Property,
69
+ value: DispatchedPropertyValue<Target, Property>,
70
+ dispatch?: boolean,
71
+ ): void;
72
+
73
+ /**
74
+ * Set the value for a property on an element
75
+ * @param target Target element
76
+ * @param property Property to set
77
+ * @param value Value to set
78
+ */
79
+ export function setProperty<Target extends Element, Property extends keyof SetProperties<Target>>(
80
+ target: Target,
81
+ property: Property,
82
+ value: SetProperties<Target>[Property],
83
+ ): void;
84
+
85
+ export function setProperty<Target extends Element, Property extends keyof SetProperties<Target>>(
86
+ target: Target,
87
+ property: Property,
88
+ value: SetProperties<Target>[Property],
89
+ dispatch?: boolean,
90
+ ): void {
91
+ if (!isHTMLOrSVGElement(target) || typeof property !== 'string') {
92
+ return;
93
+ }
94
+
95
+ if (booleanAttributesSet.has(property.toLowerCase()) || dispatchedAttributes.has(property)) {
96
+ setAttribute(target, property as never, value, dispatch !== false);
97
+ } else {
98
+ updateProperty(target, property, value, dispatch !== false);
99
+ }
100
+ }
101
+
102
+ // #endregion
package/src/style.ts CHANGED
@@ -3,6 +3,8 @@ import {getStyleValue} from './internal/get-value';
3
3
  import {isHTMLOrSVGElement} from './internal/is';
4
4
  import type {TextDirection} from './models';
5
5
 
6
+ // #region Types
7
+
6
8
  export type StyleToggler = {
7
9
  /**
8
10
  * Set the provided styles on the element
@@ -14,6 +16,12 @@ export type StyleToggler = {
14
16
  remove(): void;
15
17
  };
16
18
 
19
+ type Styles = Partial<Record<keyof CSSStyleDeclaration, unknown>>;
20
+
21
+ // #endregion
22
+
23
+ // #region Functions
24
+
17
25
  /**
18
26
  * Get a style from an element
19
27
  * @param element Element to get the style from
@@ -26,11 +34,9 @@ export function getStyle(
26
34
  property: keyof CSSStyleDeclaration,
27
35
  computed?: boolean,
28
36
  ): string | undefined {
29
- if (!isHTMLOrSVGElement(element) || typeof property !== 'string') {
30
- return undefined;
37
+ if (isHTMLOrSVGElement(element) && typeof property === 'string') {
38
+ return getStyleValue(element, property, computed === true);
31
39
  }
32
-
33
- return getStyleValue(element, property, computed === true);
34
40
  }
35
41
 
36
42
  /**
@@ -65,25 +71,37 @@ export function getStyles<Property extends keyof CSSStyleDeclaration>(
65
71
  }
66
72
 
67
73
  /**
68
- * Get the text direction of an element
69
- * @param element Element to get the text direction from
70
- * @param computed Get the computed text direction? _(defaults to `false`)_
74
+ * Get the text direction of a node or element _(or document, if element is invalid)_
75
+ * @param node Node or element to get the text direction from
71
76
  * @returns Text direction
72
77
  */
73
- export function getTextDirection(element: Element, computed?: boolean): TextDirection {
74
- if (!(element instanceof Element)) {
75
- return undefined as never;
78
+ export function getTextDirection(node: Element | Node): TextDirection;
79
+
80
+ /**
81
+ * Get the text direction of the document
82
+ * @returns Text direction
83
+ */
84
+ export function getTextDirection(): TextDirection;
85
+
86
+ export function getTextDirection(node?: Element | Node): TextDirection {
87
+ let target: HTMLElement | SVGElement;
88
+
89
+ if (isHTMLOrSVGElement(node)) {
90
+ target = node;
91
+ } else {
92
+ target =
93
+ node instanceof Node
94
+ ? (node.ownerDocument?.documentElement ?? document.documentElement)
95
+ : document.documentElement;
76
96
  }
77
97
 
78
- const direction = element.getAttribute(ATTRIBUTE_DIRECTION);
98
+ let {direction} = target.style;
79
99
 
80
- if (direction != null && EXPRESSION_DIRECTION.test(direction)) {
81
- return direction.toLowerCase() as TextDirection;
100
+ if (direction === '') {
101
+ direction = getStyleValue(target, PROPETY_DIRECTION, true)!;
82
102
  }
83
103
 
84
- const value = getStyleValue(element, 'direction', computed === true);
85
-
86
- return value === 'rtl' ? value : 'ltr';
104
+ return direction === DIRECTION_RTL ? DIRECTION_RTL : DIRECTION_LTR;
87
105
  }
88
106
 
89
107
  /**
@@ -95,7 +113,7 @@ export function getTextDirection(element: Element, computed?: boolean): TextDire
95
113
  export function setStyle(
96
114
  element: Element,
97
115
  property: keyof CSSStyleDeclaration,
98
- value?: string,
116
+ value?: unknown,
99
117
  ): void {
100
118
  setElementValues(element, property as string, value, null, updateStyleProperty);
101
119
  }
@@ -105,7 +123,7 @@ export function setStyle(
105
123
  * @param element Element to set the styles on
106
124
  * @param styles Styles to set
107
125
  */
108
- export function setStyles(element: Element, styles: Partial<CSSStyleDeclaration>): void {
126
+ export function setStyles(element: Element, styles: Styles): void {
109
127
  setElementValues(element, styles as never, null, null, updateStyleProperty);
110
128
  }
111
129
 
@@ -115,11 +133,11 @@ export function setStyles(element: Element, styles: Partial<CSSStyleDeclaration>
115
133
  * @param styles Styles to be set or removed
116
134
  * @returns Style toggler
117
135
  */
118
- export function toggleStyles(element: Element, styles: Partial<CSSStyleDeclaration>): StyleToggler {
136
+ export function toggleStyles(element: Element, styles: Styles): StyleToggler {
119
137
  function toggle(set: boolean): void {
120
138
  hasSet = set;
121
139
 
122
- let next: Partial<CSSStyleDeclaration>;
140
+ let next: Styles;
123
141
 
124
142
  if (set) {
125
143
  values = getStyles(element, keys);
@@ -130,8 +148,8 @@ export function toggleStyles(element: Element, styles: Partial<CSSStyleDeclarati
130
148
 
131
149
  values = {};
132
150
 
133
- for (const key of keys) {
134
- values[key as never] = undefined;
151
+ for (let index = 0; index < length; index += 1) {
152
+ values[keys[index] as never] = undefined;
135
153
  }
136
154
  }
137
155
 
@@ -139,6 +157,7 @@ export function toggleStyles(element: Element, styles: Partial<CSSStyleDeclarati
139
157
  }
140
158
 
141
159
  const keys = Object.keys(styles) as (keyof CSSStyleDeclaration)[];
160
+ const {length} = keys;
142
161
 
143
162
  let hasSet = false;
144
163
  let values: Record<string, string | undefined> = {};
@@ -162,8 +181,8 @@ function updateStyleProperty(element: Element, key: string, value: unknown): voi
162
181
  element,
163
182
  key,
164
183
  value,
165
- function (this: Element, property: string, style: string) {
166
- (this as HTMLElement).style[property as never] = style;
184
+ function (this: Element, property: string, style: unknown) {
185
+ (this as HTMLElement).style[property as never] = String(style);
167
186
  },
168
187
  function (this: Element, property: string) {
169
188
  (this as HTMLElement).style[property as never] = '';
@@ -173,8 +192,14 @@ function updateStyleProperty(element: Element, key: string, value: unknown): voi
173
192
  );
174
193
  }
175
194
 
176
- //
195
+ // #endregion
196
+
197
+ // #region Variables
198
+
199
+ const DIRECTION_LTR = 'ltr';
200
+
201
+ const DIRECTION_RTL = 'rtl';
177
202
 
178
- const ATTRIBUTE_DIRECTION = 'dir';
203
+ const PROPETY_DIRECTION = 'direction';
179
204
 
180
- const EXPRESSION_DIRECTION = /^(ltr|rtl)$/i;
205
+ // #endregion
package/src/touch.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // #region Types
2
+
1
3
  type NavigatorWithMsMaxTouchPoints = Navigator & {
2
4
  msMaxTouchPoints: number;
3
5
  };
@@ -17,7 +19,9 @@ type SupporsTouch = {
17
19
  update(): boolean;
18
20
  };
19
21
 
20
- //
22
+ // #endregion
23
+
24
+ // #region Functions
21
25
 
22
26
  function getSupport(): boolean {
23
27
  if (window == null || navigator == null) {
@@ -50,7 +54,9 @@ function getSupport(): boolean {
50
54
  return false;
51
55
  }
52
56
 
53
- //
57
+ // #endregion
58
+
59
+ // #region Variables
54
60
 
55
61
  /**
56
62
  * Does the device support touch events?
@@ -78,4 +84,10 @@ const supportsTouch: SupporsTouch = (() => {
78
84
  return instance;
79
85
  })();
80
86
 
87
+ // #endregion
88
+
89
+ // #region Exports
90
+
81
91
  export default supportsTouch;
92
+
93
+ // #endregion