@oscarpalmer/toretto 0.46.0 → 0.47.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/aria.d.mts +68 -0
- package/dist/aria.mjs +49 -0
- package/dist/attribute/get.attribute.d.mts +1 -0
- package/dist/attribute/get.attribute.mjs +2 -3
- package/dist/attribute/index.d.mts +1 -1
- package/dist/attribute/set.attribute.mjs +1 -1
- package/dist/create.d.mts +2 -2
- package/dist/create.mjs +1 -1
- package/dist/data.mjs +1 -2
- package/dist/event/delegation.mjs +3 -4
- package/dist/event/index.mjs +1 -2
- package/dist/html/index.d.mts +5 -4
- package/dist/html/index.mjs +3 -3
- package/dist/index.d.mts +99 -18
- package/dist/index.mjs +184 -139
- package/dist/internal/attribute.mjs +2 -2
- package/dist/internal/element-value.mjs +2 -4
- package/dist/internal/is.d.mts +2 -2
- package/dist/internal/is.mjs +2 -2
- package/dist/is.mjs +1 -1
- package/dist/models.d.mts +21 -1
- package/dist/property/get.property.mjs +2 -3
- package/dist/property/set.property.mjs +2 -4
- package/dist/style.mjs +3 -4
- package/package.json +8 -4
- package/src/aria.ts +166 -0
- package/src/attribute/get.attribute.ts +3 -3
- package/src/create.ts +3 -3
- package/src/data.ts +7 -6
- package/src/event/delegation.ts +5 -6
- package/src/event/index.ts +1 -7
- package/src/html/index.ts +7 -9
- package/src/index.ts +1 -0
- package/src/internal/attribute.ts +4 -2
- package/src/internal/element-value.ts +2 -3
- package/src/internal/is.ts +2 -2
- package/src/models.ts +122 -0
- package/src/property/get.property.ts +4 -5
- package/src/property/set.property.ts +2 -3
- package/src/style.ts +5 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/toretto",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"description": "A collection of badass DOM utilities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dom",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"types": "./dist/index.d.mts",
|
|
31
31
|
"default": "./dist/index.mjs"
|
|
32
32
|
},
|
|
33
|
+
"./aria": {
|
|
34
|
+
"types": "./dist/aria.d.mts",
|
|
35
|
+
"default": "./dist/aria.mjs"
|
|
36
|
+
},
|
|
33
37
|
"./attribute": {
|
|
34
38
|
"types": "./dist/attribute/index.d.mts",
|
|
35
39
|
"default": "./dist/attribute/index.mjs"
|
|
@@ -86,11 +90,11 @@
|
|
|
86
90
|
"test:leak": "npx vp test run --detect-async-leaks --coverage"
|
|
87
91
|
},
|
|
88
92
|
"dependencies": {
|
|
89
|
-
"@oscarpalmer/atoms": "^0.
|
|
93
|
+
"@oscarpalmer/atoms": "^0.188.1"
|
|
90
94
|
},
|
|
91
95
|
"devDependencies": {
|
|
92
|
-
"@oxlint/plugins": "^1.
|
|
93
|
-
"@types/node": "^
|
|
96
|
+
"@oxlint/plugins": "^1.73",
|
|
97
|
+
"@types/node": "^26.1",
|
|
94
98
|
"@vitest/coverage-istanbul": "^4.1",
|
|
95
99
|
"jsdom": "^29.1",
|
|
96
100
|
"tsdown": "^0.22",
|
package/src/aria.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import {setElementValues, updateElementValue} from './internal/element-value';
|
|
2
|
+
import type {AriaAttribute, AriaAttributeUnprefixed, AriaRole} from './models';
|
|
3
|
+
|
|
4
|
+
// #region Types
|
|
5
|
+
|
|
6
|
+
type AnyAriaAttribute = AriaAttribute | AriaAttributeUnprefixed;
|
|
7
|
+
|
|
8
|
+
type AriaAttributeItem = {
|
|
9
|
+
name: AnyAriaAttribute;
|
|
10
|
+
value?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// #endregion
|
|
14
|
+
|
|
15
|
+
// #region Functions
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get the value of a specific _ARIA_ attribute from an element
|
|
19
|
+
*
|
|
20
|
+
* @param element Element to get _ARIA_ attribute from
|
|
21
|
+
* @param name _ARIA_ name
|
|
22
|
+
* @returns _ARIA_ value _(or `undefined`)_
|
|
23
|
+
*/
|
|
24
|
+
export function getAria(element: Element, attribute: AnyAriaAttribute): string | undefined;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get specific _ARIA_ attributes from an element
|
|
28
|
+
*
|
|
29
|
+
* @param element Element to get _ARIA_ attributes from
|
|
30
|
+
* @param names _ARIA_ attribute names
|
|
31
|
+
* @returns Object of named _ARIA_ attributes
|
|
32
|
+
*/
|
|
33
|
+
export function getAria<Attribute extends AnyAriaAttribute>(
|
|
34
|
+
element: Element,
|
|
35
|
+
attributes: Attribute[],
|
|
36
|
+
): Record<Attribute, string | undefined>;
|
|
37
|
+
|
|
38
|
+
export function getAria(element: Element, value: string | string[]): unknown {
|
|
39
|
+
if (!(element instanceof Element)) {
|
|
40
|
+
return Array.isArray(value) ? {} : undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!Array.isArray(value)) {
|
|
44
|
+
return typeof value === 'string' ? getAriaValue(element, value) : undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const arias = {} as Record<string, string | undefined>;
|
|
48
|
+
|
|
49
|
+
const {length} = value;
|
|
50
|
+
|
|
51
|
+
for (let index = 0; index < length; index += 1) {
|
|
52
|
+
const attribute = value[index];
|
|
53
|
+
|
|
54
|
+
if (typeof attribute === 'string') {
|
|
55
|
+
arias[attribute.replace(ATTRIBUTE_ARIA_PREFIX, '')] = getAriaValue(element, attribute);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return arias;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getAriaValue(element: Element, attribute: string): string | undefined {
|
|
63
|
+
return element.getAttribute(getName(attribute)) ?? undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getName(value: string): string {
|
|
67
|
+
return EXPRESSION_ARIA_PREFIX.test(value) ? value : `${ATTRIBUTE_ARIA_PREFIX}${value}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get the role of an element
|
|
72
|
+
*
|
|
73
|
+
* @param element Element to get role from
|
|
74
|
+
* @returns Element role _(or `undefined`)_
|
|
75
|
+
*/
|
|
76
|
+
export function getRole(element: Element): unknown {
|
|
77
|
+
if (element instanceof Element) {
|
|
78
|
+
return element.getAttribute('role') ?? undefined;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Set an _ARIA_ attribute on an element
|
|
84
|
+
*
|
|
85
|
+
* _(Or remove it, if value is `null` or `undefined`)_
|
|
86
|
+
*
|
|
87
|
+
* @param element Element for _ARIA_ attribute
|
|
88
|
+
* @param attribute _ARIA_ attribute to set
|
|
89
|
+
* @param value _ARIA_ attribute value
|
|
90
|
+
*/
|
|
91
|
+
export function setAria(element: Element, attribute: AnyAriaAttribute, value?: string): void;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Set one or more _ARIA_ attributes on an element
|
|
95
|
+
*
|
|
96
|
+
* _(Or remove them, if their value is `null` or `undefined`)_
|
|
97
|
+
*
|
|
98
|
+
* @param element Element for _ARIA_ attributes
|
|
99
|
+
* @param attributes _ARIA_ attributes to set
|
|
100
|
+
*/
|
|
101
|
+
export function setAria(element: Element, attributes: AriaAttributeItem[]): void;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Set one or more _ARIA_ attributes on an element
|
|
105
|
+
*
|
|
106
|
+
* _(Or remove them, if their value is `null` or `undefined`)_
|
|
107
|
+
*
|
|
108
|
+
* @param element Element for _ARIA_ attributes
|
|
109
|
+
* @param attributes _ARIA_ attributes to set
|
|
110
|
+
*/
|
|
111
|
+
export function setAria(
|
|
112
|
+
element: Element,
|
|
113
|
+
attributes: Partial<Record<AnyAriaAttribute, unknown>>,
|
|
114
|
+
): void;
|
|
115
|
+
|
|
116
|
+
export function setAria(
|
|
117
|
+
element: Element,
|
|
118
|
+
first: AnyAriaAttribute | AriaAttributeItem[] | Partial<Record<AnyAriaAttribute, unknown>>,
|
|
119
|
+
second?: unknown,
|
|
120
|
+
): void {
|
|
121
|
+
setElementValues(element, first, second, null, updateAriaAttribute);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Set the role of an element
|
|
126
|
+
*
|
|
127
|
+
* @param element Element for role
|
|
128
|
+
* @param role Role to set _(or `undefined` to remove it)_
|
|
129
|
+
*/
|
|
130
|
+
export function setRole(element: Element, role?: AriaRole): void {
|
|
131
|
+
if (!(element instanceof Element)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (typeof role === 'string') {
|
|
136
|
+
element.setAttribute('role', role);
|
|
137
|
+
} else {
|
|
138
|
+
element.removeAttribute('role');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function updateAriaAttribute(element: Element, key: string, value: unknown): void {
|
|
143
|
+
updateElementValue(
|
|
144
|
+
element,
|
|
145
|
+
getName(key),
|
|
146
|
+
value,
|
|
147
|
+
// Using `.call` in `updateElementValue`
|
|
148
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
149
|
+
element.setAttribute,
|
|
150
|
+
// Using `.call` in `updateElementValue`
|
|
151
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
152
|
+
element.removeAttribute,
|
|
153
|
+
false,
|
|
154
|
+
false,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// #endregion
|
|
159
|
+
|
|
160
|
+
// #region Variables
|
|
161
|
+
|
|
162
|
+
const ATTRIBUTE_ARIA_PREFIX = 'aria-';
|
|
163
|
+
|
|
164
|
+
const EXPRESSION_ARIA_PREFIX = /^aria-/i;
|
|
165
|
+
|
|
166
|
+
// #endregion
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {kebabCase} from '@oscarpalmer/atoms/string/case';
|
|
2
2
|
import {getAttributeValue} from '../internal/get-value';
|
|
3
|
-
import {isHTMLOrSVGElement} from '../internal/is';
|
|
4
3
|
|
|
5
4
|
// #region Types
|
|
6
5
|
|
|
@@ -12,6 +11,7 @@ type DataPrefixedName = `data-${string}`;
|
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Get the value of a specific attribute from an element
|
|
14
|
+
*
|
|
15
15
|
* @param element Element to get attribute from
|
|
16
16
|
* @param name Attribute name
|
|
17
17
|
* @param parse Parse value? _(defaults to `true`)_
|
|
@@ -29,7 +29,7 @@ export function getAttribute(element: Element, name: DataPrefixedName, parse?: b
|
|
|
29
29
|
export function getAttribute(element: Element, name: string): unknown;
|
|
30
30
|
|
|
31
31
|
export function getAttribute(element: Element, name: string, parseValues?: boolean): unknown {
|
|
32
|
-
if (
|
|
32
|
+
if (element instanceof Element && typeof name === 'string') {
|
|
33
33
|
return getAttributeValue(element, kebabCase(name), parseValues !== false);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -49,7 +49,7 @@ export function getAttributes<Key extends string>(
|
|
|
49
49
|
): Record<Key, unknown> {
|
|
50
50
|
const attributes: Record<string, unknown> = {};
|
|
51
51
|
|
|
52
|
-
if (!(
|
|
52
|
+
if (!(element instanceof Element && Array.isArray(names))) {
|
|
53
53
|
return attributes;
|
|
54
54
|
}
|
|
55
55
|
|
package/src/create.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {Primitive} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {setAttributes} from './attribute';
|
|
3
|
-
import {setStyles} from './style';
|
|
4
3
|
import {setProperties} from './property';
|
|
4
|
+
import {setStyles} from './style';
|
|
5
5
|
|
|
6
6
|
// #region Types
|
|
7
7
|
|
|
@@ -16,7 +16,7 @@ type Styles = Partial<Record<keyof CSSStyleDeclaration, unknown>>;
|
|
|
16
16
|
// #region Functions
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* Creates an
|
|
19
|
+
* Creates an _HTML_ element with the specified tag name together with optional properties, attributes, and styles
|
|
20
20
|
*
|
|
21
21
|
* @param tag Tag name
|
|
22
22
|
* @param properties Element properties
|
|
@@ -32,7 +32,7 @@ export function createElement<TagName extends keyof HTMLElementTagNameMap>(
|
|
|
32
32
|
): HTMLElementTagNameMap[TagName];
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* Creates an
|
|
35
|
+
* Creates an _HTML_ element with the specified tag name together with optional properties, attributes, and styles
|
|
36
36
|
*
|
|
37
37
|
* @param tag Tag name
|
|
38
38
|
* @param properties Element properties
|
package/src/data.ts
CHANGED
|
@@ -3,7 +3,6 @@ import {parse} from '@oscarpalmer/atoms/string';
|
|
|
3
3
|
import {camelCase, kebabCase} from '@oscarpalmer/atoms/string/case';
|
|
4
4
|
import {setElementValues, updateElementValue} from './internal/element-value';
|
|
5
5
|
import {EXPRESSION_DATA_PREFIX} from './internal/get-value';
|
|
6
|
-
import {isHTMLOrSVGElement} from './internal/is';
|
|
7
6
|
|
|
8
7
|
// #region Functions
|
|
9
8
|
|
|
@@ -32,14 +31,14 @@ export function getData<Key extends string>(
|
|
|
32
31
|
): Record<Key, unknown>;
|
|
33
32
|
|
|
34
33
|
export function getData(element: Element, keys: string | string[], parseValues?: boolean): unknown {
|
|
35
|
-
if (!
|
|
34
|
+
if (!(element instanceof Element)) {
|
|
36
35
|
return;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
const noParse = parseValues === false;
|
|
40
39
|
|
|
41
40
|
if (typeof keys === 'string') {
|
|
42
|
-
const value = element.dataset[camelCase(keys)];
|
|
41
|
+
const value = (element as HTMLElement).dataset[camelCase(keys)];
|
|
43
42
|
|
|
44
43
|
if (value === undefined) {
|
|
45
44
|
return;
|
|
@@ -54,7 +53,7 @@ export function getData(element: Element, keys: string | string[], parseValues?:
|
|
|
54
53
|
|
|
55
54
|
for (let index = 0; index < length; index += 1) {
|
|
56
55
|
const key = keys[index];
|
|
57
|
-
const value = element.dataset[camelCase(key)];
|
|
56
|
+
const value = (element as HTMLElement).dataset[camelCase(key)];
|
|
58
57
|
|
|
59
58
|
if (value == null) {
|
|
60
59
|
data[key] = undefined;
|
|
@@ -96,9 +95,11 @@ function updateDataAttribute(element: Element, key: string, value: unknown): voi
|
|
|
96
95
|
element,
|
|
97
96
|
getName(key),
|
|
98
97
|
value,
|
|
99
|
-
//
|
|
98
|
+
// Using `.call` in `updateElementValue`
|
|
99
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
100
100
|
element.setAttribute,
|
|
101
|
-
//
|
|
101
|
+
// Using `.call` in `updateElementValue`
|
|
102
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
102
103
|
element.removeAttribute,
|
|
103
104
|
false,
|
|
104
105
|
true,
|
package/src/event/delegation.ts
CHANGED
|
@@ -43,7 +43,7 @@ export function addDelegatedListener(
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function delegatedEventHandler(this: boolean, event: Event): void {
|
|
46
|
-
const key =
|
|
46
|
+
const key = `@${event.type}${this ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
|
|
47
47
|
|
|
48
48
|
const items = event.composedPath();
|
|
49
49
|
const {length} = items;
|
|
@@ -51,7 +51,8 @@ function delegatedEventHandler(this: boolean, event: Event): void {
|
|
|
51
51
|
let cancelled = false;
|
|
52
52
|
let target = items[0];
|
|
53
53
|
|
|
54
|
-
//
|
|
54
|
+
// Using `.call` to ensure correct `this` context
|
|
55
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
55
56
|
const originalStopPropagation = event.stopPropagation;
|
|
56
57
|
|
|
57
58
|
event.stopPropagation = function () {
|
|
@@ -108,7 +109,7 @@ export function getDelegatedName(
|
|
|
108
109
|
!options.once &&
|
|
109
110
|
options.signal == null
|
|
110
111
|
) {
|
|
111
|
-
return
|
|
112
|
+
return `@${type}${options.passive ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
|
|
@@ -138,13 +139,11 @@ export function removeDelegatedListener(
|
|
|
138
139
|
|
|
139
140
|
const DELEGATED = new Set<string>();
|
|
140
141
|
|
|
141
|
-
const EVENT_PREFIX = '@';
|
|
142
|
-
|
|
143
142
|
const EVENT_SUFFIX_ACTIVE = ':active';
|
|
144
143
|
|
|
145
144
|
const EVENT_SUFFIX_PASSIVE = ':passive';
|
|
146
145
|
|
|
147
|
-
const EVENT_TYPES
|
|
146
|
+
const EVENT_TYPES = new Set([
|
|
148
147
|
'beforeinput',
|
|
149
148
|
'click',
|
|
150
149
|
'dblclick',
|
package/src/event/index.ts
CHANGED
|
@@ -35,7 +35,7 @@ function createDispatchOptions(options: EventInit): EventInit {
|
|
|
35
35
|
function createEvent(type: string, options?: CustomEventInit): Event {
|
|
36
36
|
const hasOptions = isPlainObject(options);
|
|
37
37
|
|
|
38
|
-
if (hasOptions &&
|
|
38
|
+
if (hasOptions && 'detail' in (options as CustomEventInit)) {
|
|
39
39
|
return new CustomEvent(type, {
|
|
40
40
|
...createDispatchOptions(options as CustomEventInit),
|
|
41
41
|
detail: options?.detail,
|
|
@@ -231,9 +231,3 @@ export function on(
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
// #endregion
|
|
234
|
-
|
|
235
|
-
// #region Variables
|
|
236
|
-
|
|
237
|
-
const PROPERTY_DETAIL = 'detail';
|
|
238
|
-
|
|
239
|
-
// #endregion
|
package/src/html/index.ts
CHANGED
|
@@ -5,9 +5,9 @@ import {sanitizeNodes} from './sanitize';
|
|
|
5
5
|
|
|
6
6
|
// #region Types
|
|
7
7
|
|
|
8
|
-
type HtmlOptions = {
|
|
8
|
+
export type HtmlOptions = {
|
|
9
9
|
/**
|
|
10
|
-
* Cache template element for the
|
|
10
|
+
* Cache template element for the _HTML_ string? _(defaults to `true`)_
|
|
11
11
|
*/
|
|
12
12
|
cache?: boolean;
|
|
13
13
|
};
|
|
@@ -181,9 +181,9 @@ function hasNodes(value: unknown): value is HTMLCollection | NodeList | Node[] {
|
|
|
181
181
|
export function html(strings: TemplateStringsArray, ...values: unknown[]): Node[];
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
|
-
* Create nodes from an
|
|
184
|
+
* Create nodes from an _HTML_ string or a template element
|
|
185
185
|
*
|
|
186
|
-
* @param value
|
|
186
|
+
* @param value _HTML_ string or ID for a template element
|
|
187
187
|
* @param options Options for creating nodes
|
|
188
188
|
* @returns Created nodes
|
|
189
189
|
*/
|
|
@@ -216,9 +216,9 @@ html.clear = (): void => {
|
|
|
216
216
|
};
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
|
-
* Remove cached template element for an
|
|
219
|
+
* Remove cached template element for an _HTML_ string or _ID_
|
|
220
220
|
*
|
|
221
|
-
* @param template
|
|
221
|
+
* @param template _HTML_ string or ID for a template element
|
|
222
222
|
*/
|
|
223
223
|
html.remove = (template: string): void => {
|
|
224
224
|
templates.delete(template);
|
|
@@ -253,6 +253,7 @@ function replaceComments(origin: NodeList | Node[], replacements: Node[]): void
|
|
|
253
253
|
|
|
254
254
|
/**
|
|
255
255
|
* Sanitize one or more nodes, recursively
|
|
256
|
+
*
|
|
256
257
|
* @param value Node or nodes to sanitize
|
|
257
258
|
* @param options Sanitization options
|
|
258
259
|
* @returns Sanitized nodes
|
|
@@ -283,7 +284,4 @@ const templates = new SizedMap<string, HTMLTemplateElement>(128);
|
|
|
283
284
|
|
|
284
285
|
let parser: DOMParser;
|
|
285
286
|
|
|
286
|
-
// @ts-expect-error debug
|
|
287
|
-
window.templates = templates;
|
|
288
|
-
|
|
289
287
|
// #endregion
|
package/src/index.ts
CHANGED
|
@@ -142,9 +142,11 @@ export function updateAttribute(
|
|
|
142
142
|
element,
|
|
143
143
|
name,
|
|
144
144
|
isBoolean ? (next ? '' : null) : value,
|
|
145
|
-
//
|
|
145
|
+
// Using `.call` in `updateElementValue`
|
|
146
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
146
147
|
element.setAttribute,
|
|
147
|
-
//
|
|
148
|
+
// Using `.call` in `updateElementValue`
|
|
149
|
+
// oxlint-disable-next-line typescript/unbound-method
|
|
148
150
|
element.removeAttribute,
|
|
149
151
|
isBoolean,
|
|
150
152
|
false,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
|
|
2
2
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
3
3
|
import {kebabCase} from '@oscarpalmer/atoms/string/case';
|
|
4
|
-
import {isHTMLOrSVGElement} from '../is';
|
|
5
4
|
import {isAttribute} from './attribute';
|
|
6
5
|
|
|
7
6
|
// #region Functions
|
|
@@ -26,7 +25,7 @@ export function setElementValue(
|
|
|
26
25
|
callback: (element: Element, key: string, value: unknown, dispatch: boolean) => void,
|
|
27
26
|
style?: boolean,
|
|
28
27
|
): void {
|
|
29
|
-
if (!
|
|
28
|
+
if (!(element instanceof Element)) {
|
|
30
29
|
return;
|
|
31
30
|
}
|
|
32
31
|
|
|
@@ -45,7 +44,7 @@ export function setElementValues(
|
|
|
45
44
|
callback: (element: Element, key: string, value: unknown, dispatch: boolean) => void,
|
|
46
45
|
style?: boolean,
|
|
47
46
|
): void {
|
|
48
|
-
if (!
|
|
47
|
+
if (!(element instanceof Element)) {
|
|
49
48
|
return;
|
|
50
49
|
}
|
|
51
50
|
|
package/src/internal/is.ts
CHANGED
|
@@ -34,10 +34,10 @@ export function isEventTarget(value: unknown): value is EventTarget {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Is the value an
|
|
37
|
+
* Is the value an _HTML_ or _SVG_ element?
|
|
38
38
|
*
|
|
39
39
|
* @param value Value to check
|
|
40
|
-
* @returns `true` if it's an
|
|
40
|
+
* @returns `true` if it's an _HTML_ or _SVG_ element, otherwise `false`
|
|
41
41
|
*/
|
|
42
42
|
export function isHTMLOrSVGElement(value: unknown): value is HTMLElement | SVGElement {
|
|
43
43
|
return value instanceof HTMLElement || value instanceof SVGElement;
|
package/src/models.ts
CHANGED
|
@@ -1,3 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _ARIA_ attribute for an element
|
|
3
|
+
*
|
|
4
|
+
* _(https://www.w3.org/TR/wai-aria-1.3/#aria-attributes)_
|
|
5
|
+
*/
|
|
6
|
+
export type AriaAttribute = keyof AriaAttributes;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* _ARIA_ attribute for an element without the `aria-` prefix
|
|
10
|
+
*
|
|
11
|
+
* _(https://www.w3.org/TR/wai-aria-1.3/#aria-attributes)_
|
|
12
|
+
*/
|
|
13
|
+
export type AriaAttributeUnprefixed = keyof {
|
|
14
|
+
[Key in AriaAttribute as Key extends `aria-${infer Name}` ? Name : never]: string | null;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type AriaAttributes = {
|
|
18
|
+
[Key in keyof ARIAMixin as NormalizedName<Key>]: string | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type NormalizedName<Key extends string> = Key extends `aria${infer Name}`
|
|
22
|
+
? Name extends `${infer Part}Element`
|
|
23
|
+
? `aria-${Lowercase<Part>}`
|
|
24
|
+
: Name extends `${infer Part}Elements`
|
|
25
|
+
? `aria-${Lowercase<Part>}`
|
|
26
|
+
: `aria-${Lowercase<Name>}`
|
|
27
|
+
: never;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* _ARIA_ role for an element
|
|
31
|
+
*
|
|
32
|
+
* _(https://www.w3.org/TR/wai-aria-1.3/#role_definitions)_
|
|
33
|
+
*/
|
|
34
|
+
export type AriaRole =
|
|
35
|
+
| 'alert'
|
|
36
|
+
| 'alertdialog'
|
|
37
|
+
| 'application'
|
|
38
|
+
| 'article'
|
|
39
|
+
| 'banner'
|
|
40
|
+
| 'blockquote'
|
|
41
|
+
| 'button'
|
|
42
|
+
| 'caption'
|
|
43
|
+
| 'cell'
|
|
44
|
+
| 'checkbox'
|
|
45
|
+
| 'code'
|
|
46
|
+
| 'columnheader'
|
|
47
|
+
| 'combobox'
|
|
48
|
+
| 'comment'
|
|
49
|
+
| 'complementary'
|
|
50
|
+
| 'contentinfo'
|
|
51
|
+
| 'definition'
|
|
52
|
+
| 'deletion'
|
|
53
|
+
| 'dialog'
|
|
54
|
+
| 'directory'
|
|
55
|
+
| 'document'
|
|
56
|
+
| 'emphasis'
|
|
57
|
+
| 'feed'
|
|
58
|
+
| 'figure'
|
|
59
|
+
| 'form'
|
|
60
|
+
| 'generic'
|
|
61
|
+
| 'grid'
|
|
62
|
+
| 'gridcell'
|
|
63
|
+
| 'group'
|
|
64
|
+
| 'heading'
|
|
65
|
+
| 'img'
|
|
66
|
+
| 'insertion'
|
|
67
|
+
| 'link'
|
|
68
|
+
| 'list'
|
|
69
|
+
| 'listbox'
|
|
70
|
+
| 'listitem'
|
|
71
|
+
| 'log'
|
|
72
|
+
| 'main'
|
|
73
|
+
| 'mark'
|
|
74
|
+
| 'marquee'
|
|
75
|
+
| 'math'
|
|
76
|
+
| 'menu'
|
|
77
|
+
| 'menubar'
|
|
78
|
+
| 'menuitem'
|
|
79
|
+
| 'menuitemcheckbox'
|
|
80
|
+
| 'menuitemradio'
|
|
81
|
+
| 'meter'
|
|
82
|
+
| 'navigation'
|
|
83
|
+
| 'none'
|
|
84
|
+
| 'note'
|
|
85
|
+
| 'option'
|
|
86
|
+
| 'paragraph'
|
|
87
|
+
| 'presentation'
|
|
88
|
+
| 'progressbar'
|
|
89
|
+
| 'radio'
|
|
90
|
+
| 'radiogroup'
|
|
91
|
+
| 'region'
|
|
92
|
+
| 'row'
|
|
93
|
+
| 'rowgroup'
|
|
94
|
+
| 'rowheader'
|
|
95
|
+
| 'scrollbar'
|
|
96
|
+
| 'search'
|
|
97
|
+
| 'searchbox'
|
|
98
|
+
| 'sectionfooter'
|
|
99
|
+
| 'sectionheader'
|
|
100
|
+
| 'separator'
|
|
101
|
+
| 'slider'
|
|
102
|
+
| 'spinbutton'
|
|
103
|
+
| 'status'
|
|
104
|
+
| 'strong'
|
|
105
|
+
| 'subscript'
|
|
106
|
+
| 'suggestion'
|
|
107
|
+
| 'superscript'
|
|
108
|
+
| 'switch'
|
|
109
|
+
| 'tab'
|
|
110
|
+
| 'table'
|
|
111
|
+
| 'tablist'
|
|
112
|
+
| 'tabpanel'
|
|
113
|
+
| 'term'
|
|
114
|
+
| 'textbox'
|
|
115
|
+
| 'time'
|
|
116
|
+
| 'timer'
|
|
117
|
+
| 'toolbar'
|
|
118
|
+
| 'tooltip'
|
|
119
|
+
| 'tree'
|
|
120
|
+
| 'treegrid'
|
|
121
|
+
| 'treeitem';
|
|
122
|
+
|
|
1
123
|
/**
|
|
2
124
|
* Attribute for an element
|
|
3
125
|
*/
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type {Primitive} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {camelCase} from '@oscarpalmer/atoms/string/case';
|
|
3
|
-
import {isHTMLOrSVGElement} from '../internal/is';
|
|
4
3
|
|
|
5
4
|
// #region Types
|
|
6
5
|
|
|
@@ -27,7 +26,7 @@ export function getProperties<Target extends Element, Property extends keyof Get
|
|
|
27
26
|
): Pick<GetProperties<Target>, Property> {
|
|
28
27
|
const values: Partial<GetProperties<Target>> = {};
|
|
29
28
|
|
|
30
|
-
if (!
|
|
29
|
+
if (!(target instanceof Element && Array.isArray(properties))) {
|
|
31
30
|
return values as Pick<GetProperties<Target>, Property>;
|
|
32
31
|
}
|
|
33
32
|
|
|
@@ -55,12 +54,12 @@ export function getProperty<Target extends Element, Property extends keyof GetPr
|
|
|
55
54
|
target: Target,
|
|
56
55
|
property: Property,
|
|
57
56
|
): GetProperties<Target>[Property] {
|
|
58
|
-
if (
|
|
57
|
+
if (target instanceof Element && typeof property === 'string') {
|
|
59
58
|
return getPropertyValue(target, property) as GetProperties<Target>[Property];
|
|
60
59
|
}
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
function getPropertyValue(element:
|
|
62
|
+
function getPropertyValue(element: Element, property: string): unknown {
|
|
64
63
|
let actual = property;
|
|
65
64
|
|
|
66
65
|
if (!(actual in element)) {
|
|
@@ -68,7 +67,7 @@ function getPropertyValue(element: HTMLElement, property: string): unknown {
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
if (actual in element) {
|
|
71
|
-
return element[actual as keyof
|
|
70
|
+
return element[actual as keyof Element];
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
73
|
|
|
@@ -4,7 +4,6 @@ import {setAttribute} from '../attribute';
|
|
|
4
4
|
import type {DispatchedAttributeName} from '../attribute/set.attribute';
|
|
5
5
|
import {booleanAttributesSet, dispatchedAttributes} from '../internal/attribute';
|
|
6
6
|
import {updateProperty} from '../internal/property';
|
|
7
|
-
import {isHTMLOrSVGElement} from '../is';
|
|
8
7
|
|
|
9
8
|
// #region Types
|
|
10
9
|
|
|
@@ -37,7 +36,7 @@ export function setProperties<Target extends Element>(
|
|
|
37
36
|
properties: SetProperties<Target>,
|
|
38
37
|
dispatch?: boolean,
|
|
39
38
|
): void {
|
|
40
|
-
if (!
|
|
39
|
+
if (!(target instanceof Element) || !isPlainObject(properties)) {
|
|
41
40
|
return;
|
|
42
41
|
}
|
|
43
42
|
|
|
@@ -85,7 +84,7 @@ export function setProperty<Target extends Element, Property extends keyof SetPr
|
|
|
85
84
|
value: SetProperties<Target>[Property],
|
|
86
85
|
dispatch?: boolean,
|
|
87
86
|
): void {
|
|
88
|
-
if (
|
|
87
|
+
if (target instanceof Element && typeof property === 'string') {
|
|
89
88
|
setPropertyValue(target, property, value, dispatch !== false);
|
|
90
89
|
}
|
|
91
90
|
}
|