@aurodesignsystem/auro-library 5.3.2 → 5.4.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Semantic Release Automated Changelog
|
|
2
2
|
|
|
3
|
+
# [5.4.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.3.3...v5.4.0) (2025-08-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add a11yTransporter util ([817bb3a](https://github.com/AlaskaAirlines/auro-library/commit/817bb3acb9d20e99bc25a89f17db3a8f2ac91ab5))
|
|
9
|
+
|
|
10
|
+
## [5.3.3](https://github.com/AlaskaAirlines/auro-library/compare/v5.3.2...v5.3.3) (2025-08-08)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* move test related dependencies to devDependencies ([3d877f8](https://github.com/AlaskaAirlines/auro-library/commit/3d877f86c8a98b9ecdb44d83329fe391a8379483))
|
|
16
|
+
|
|
3
17
|
## [5.3.2](https://github.com/AlaskaAirlines/auro-library/compare/v5.3.1...v5.3.2) (2025-07-16)
|
|
4
18
|
|
|
5
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurodesignsystem/auro-library",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"description": "This repository holds shared scripts, utilities, and workflows utilized across repositories along the Auro Design System.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,7 +14,16 @@
|
|
|
14
14
|
"bin": {
|
|
15
15
|
"generateDocs": "./bin/generateDocs.mjs"
|
|
16
16
|
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@floating-ui/dom": "^1.6.11",
|
|
19
|
+
"handlebars": "^4.7.8",
|
|
20
|
+
"markdown-magic": "^2.6.1"
|
|
21
|
+
},
|
|
17
22
|
"devDependencies": {
|
|
23
|
+
"sinon": "^20.0.0",
|
|
24
|
+
"npm-run-all": "^4.1.5",
|
|
25
|
+
"@open-wc/testing": "^4.0.0",
|
|
26
|
+
"@aurodesignsystem/auro-cli": "^2.5.0",
|
|
18
27
|
"@aurodesignsystem/eslint-config": "1.3.4",
|
|
19
28
|
"@commitlint/cli": "^18.5.0",
|
|
20
29
|
"@commitlint/config-conventional": "^18.5.0",
|
|
@@ -79,14 +88,5 @@
|
|
|
79
88
|
},
|
|
80
89
|
"bugs": {
|
|
81
90
|
"url": "https://github.com/AlaskaAirlines/auro-library/issues"
|
|
82
|
-
},
|
|
83
|
-
"dependencies": {
|
|
84
|
-
"@aurodesignsystem/auro-cli": "^2.5.0",
|
|
85
|
-
"@floating-ui/dom": "^1.6.11",
|
|
86
|
-
"@open-wc/testing": "^4.0.0",
|
|
87
|
-
"handlebars": "^4.7.8",
|
|
88
|
-
"markdown-magic": "^2.6.1",
|
|
89
|
-
"npm-run-all": "^4.1.5",
|
|
90
|
-
"sinon": "^20.0.0"
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
## Functions
|
|
2
|
+
|
|
3
|
+
<dl>
|
|
4
|
+
<dt><a href="#transportAriaAttributes">transportAriaAttributes</a></dt>
|
|
5
|
+
<dd><p>Transfers all ARIA attributes from the host element to the target element.
|
|
6
|
+
This function allows optional removal of the original attributes and the ability to ignore specific attributes.</p>
|
|
7
|
+
</dd>
|
|
8
|
+
<dt><a href="#transportRoleAttribute">transportRoleAttribute</a></dt>
|
|
9
|
+
<dd><p>Transfers the 'role' attribute from the host element to the target element.
|
|
10
|
+
This function can optionally remove the original attribute from the host after transport.</p>
|
|
11
|
+
</dd>
|
|
12
|
+
<dt><a href="#transportTabIndexAttribute">transportTabIndexAttribute</a></dt>
|
|
13
|
+
<dd><p>Transfers the 'tabindex' attribute from the host element to the target element.
|
|
14
|
+
This function can optionally remove the original attribute from the host after transport.</p>
|
|
15
|
+
</dd>
|
|
16
|
+
<dt><a href="#transportAllA11yAttributes">transportAllA11yAttributes</a></dt>
|
|
17
|
+
<dd><p>Transfers all accessibility-related attributes (ARIA, role, tabindex) from the host element to the target element.
|
|
18
|
+
This function allows optional removal of the original attributes and the ability to ignore specific attributes.</p>
|
|
19
|
+
</dd>
|
|
20
|
+
</dl>
|
|
21
|
+
|
|
22
|
+
<a name="transportAriaAttributes"></a>
|
|
23
|
+
|
|
24
|
+
## transportAriaAttributes
|
|
25
|
+
Transfers all ARIA attributes from the host element to the target element.
|
|
26
|
+
This function allows optional removal of the original attributes and the ability to ignore specific attributes.
|
|
27
|
+
|
|
28
|
+
**Kind**: global constant
|
|
29
|
+
**Returns**: <code>function</code> - Function to detach the specific matcher and target pairing.
|
|
30
|
+
|
|
31
|
+
| Param | Type | Default | Description |
|
|
32
|
+
| --- | --- | --- | --- |
|
|
33
|
+
| params | <code>Object</code> | | The parameters object. |
|
|
34
|
+
| params.host | <code>HTMLElement</code> | | The host element to observe. |
|
|
35
|
+
| params.target | <code>HTMLElement</code> | | The target element to receive attributes. |
|
|
36
|
+
| [params.removeOriginal] | <code>boolean</code> | <code>true</code> | Whether to remove original attributes. |
|
|
37
|
+
| [params.ignore] | <code>Array.<String></code> | | The list of attributes not to transport. |
|
|
38
|
+
|
|
39
|
+
<a name="transportRoleAttribute"></a>
|
|
40
|
+
|
|
41
|
+
## transportRoleAttribute
|
|
42
|
+
Transfers the 'role' attribute from the host element to the target element.
|
|
43
|
+
This function can optionally remove the original attribute from the host after transport.
|
|
44
|
+
|
|
45
|
+
**Kind**: global constant
|
|
46
|
+
**Returns**: <code>function</code> - Function to detach the specific matcher and target pairing.} param.
|
|
47
|
+
|
|
48
|
+
| Param | Type | Default | Description |
|
|
49
|
+
| --- | --- | --- | --- |
|
|
50
|
+
| params | <code>Object</code> | | The parameters object. |
|
|
51
|
+
| params.host | <code>HTMLElement</code> | | The host element to observe. |
|
|
52
|
+
| params.target | <code>HTMLElement</code> | | The target element to receive attributes. |
|
|
53
|
+
| [params.removeOriginal] | <code>boolean</code> | <code>true</code> | Whether to remove original attributes. |
|
|
54
|
+
|
|
55
|
+
<a name="transportTabIndexAttribute"></a>
|
|
56
|
+
|
|
57
|
+
## transportTabIndexAttribute
|
|
58
|
+
Transfers the 'tabindex' attribute from the host element to the target element.
|
|
59
|
+
This function can optionally remove the original attribute from the host after transport.
|
|
60
|
+
|
|
61
|
+
**Kind**: global constant
|
|
62
|
+
**Returns**: <code>function</code> - Function to detach the specific matcher and target pairing.} param.
|
|
63
|
+
|
|
64
|
+
| Param | Type | Default | Description |
|
|
65
|
+
| --- | --- | --- | --- |
|
|
66
|
+
| params | <code>Object</code> | | The parameters object. |
|
|
67
|
+
| params.host | <code>HTMLElement</code> | | The host element to observe. |
|
|
68
|
+
| params.target | <code>HTMLElement</code> | | The target element to receive attributes. |
|
|
69
|
+
| [params.removeOriginal] | <code>boolean</code> | <code>true</code> | Whether to remove original attributes. |
|
|
70
|
+
|
|
71
|
+
<a name="transportAllA11yAttributes"></a>
|
|
72
|
+
|
|
73
|
+
## transportAllA11yAttributes
|
|
74
|
+
Transfers all accessibility-related attributes (ARIA, role, tabindex) from the host element to the target element.
|
|
75
|
+
This function allows optional removal of the original attributes and the ability to ignore specific attributes.
|
|
76
|
+
|
|
77
|
+
**Kind**: global constant
|
|
78
|
+
**Returns**: <code>function</code> - Function to detach the specific matcher and target pairing.} param.
|
|
79
|
+
|
|
80
|
+
| Param | Type | Default | Description |
|
|
81
|
+
| --- | --- | --- | --- |
|
|
82
|
+
| params | <code>Object</code> | | The parameters object. |
|
|
83
|
+
| params.host | <code>HTMLElement</code> | | The host element to observe. |
|
|
84
|
+
| params.target | <code>HTMLElement</code> | | The target element to receive attributes. |
|
|
85
|
+
| [params.removeOriginal] | <code>boolean</code> | <code>true</code> | Whether to remove original attributes. |
|
|
86
|
+
| [params.ignore] | <code>Array.<String></code> | | The list of attributes not to transport. |
|
|
87
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { transportAttributes } from "./transportAttributes.js";
|
|
2
|
+
|
|
3
|
+
const _matchers = {
|
|
4
|
+
'aria-': attr => attr.startsWith('aria-'),
|
|
5
|
+
'role': attr => attr.match(/^role$/),
|
|
6
|
+
'tabindex': attr => attr.match(/^tabindex$/),
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Transfers all ARIA attributes from the host element to the target element.
|
|
11
|
+
* This function allows optional removal of the original attributes and the ability to ignore specific attributes.
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} params - The parameters object.
|
|
14
|
+
* @param {HTMLElement} params.host - The host element to observe.
|
|
15
|
+
* @param {HTMLElement} params.target - The target element to receive attributes.
|
|
16
|
+
* @param {boolean} [params.removeOriginal=true] - Whether to remove original attributes.
|
|
17
|
+
* @param {Array<String>} [params.ignore] - The list of attributes not to transport.
|
|
18
|
+
*
|
|
19
|
+
* @returns {Function} Function to detach the specific matcher and target pairing.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export const transportAriaAttributes = ({ host, target, removeOriginal = true, ignore = undefined }) => {
|
|
23
|
+
return transportAttributes({
|
|
24
|
+
host,
|
|
25
|
+
target,
|
|
26
|
+
match: attr => {
|
|
27
|
+
if (ignore && ignore.includes(attr)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return _matchers['aria-'](attr);
|
|
31
|
+
},
|
|
32
|
+
removeOriginal
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Transfers the 'role' attribute from the host element to the target element.
|
|
38
|
+
* This function can optionally remove the original attribute from the host after transport.
|
|
39
|
+
*
|
|
40
|
+
* @param {Object} params - The parameters object.
|
|
41
|
+
* @param {HTMLElement} params.host - The host element to observe.
|
|
42
|
+
* @param {HTMLElement} params.target - The target element to receive attributes.
|
|
43
|
+
* @param {boolean} [params.removeOriginal=true] - Whether to remove original attributes.
|
|
44
|
+
*
|
|
45
|
+
* @returns {Function} Function to detach the specific matcher and target pairing.} param.
|
|
46
|
+
*/
|
|
47
|
+
export const transportRoleAttribute = ({ host, target, removeOriginal = true }) => {
|
|
48
|
+
return transportAttributes({
|
|
49
|
+
host,
|
|
50
|
+
target,
|
|
51
|
+
match: _matchers['role'],
|
|
52
|
+
removeOriginal
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Transfers the 'tabindex' attribute from the host element to the target element.
|
|
58
|
+
* This function can optionally remove the original attribute from the host after transport.
|
|
59
|
+
*
|
|
60
|
+
* @param {Object} params - The parameters object.
|
|
61
|
+
* @param {HTMLElement} params.host - The host element to observe.
|
|
62
|
+
* @param {HTMLElement} params.target - The target element to receive attributes.
|
|
63
|
+
* @param {boolean} [params.removeOriginal=true] - Whether to remove original attributes.
|
|
64
|
+
*
|
|
65
|
+
* @returns {Function} Function to detach the specific matcher and target pairing.} param.
|
|
66
|
+
*/
|
|
67
|
+
export const transportTabIndexAttribute = ({ host, target, removeOriginal = true }) => {
|
|
68
|
+
return transportAttributes({
|
|
69
|
+
host,
|
|
70
|
+
target,
|
|
71
|
+
match: _matchers['tabindex'],
|
|
72
|
+
removeOriginal
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Transfers all accessibility-related attributes (ARIA, role, tabindex) from the host element to the target element.
|
|
78
|
+
* This function allows optional removal of the original attributes and the ability to ignore specific attributes.
|
|
79
|
+
*
|
|
80
|
+
* @param {Object} params - The parameters object.
|
|
81
|
+
* @param {HTMLElement} params.host - The host element to observe.
|
|
82
|
+
* @param {HTMLElement} params.target - The target element to receive attributes.
|
|
83
|
+
* @param {boolean} [params.removeOriginal=true] - Whether to remove original attributes.
|
|
84
|
+
* @param {Array<String>} [params.ignore] - The list of attributes not to transport.
|
|
85
|
+
*
|
|
86
|
+
* @returns {Function} Function to detach the specific matcher and target pairing.} param.
|
|
87
|
+
*/
|
|
88
|
+
export const transportAllA11yAttributes = ({ host, target, removeOriginal = true, ignore = undefined }) => {
|
|
89
|
+
return transportAttributes({
|
|
90
|
+
host,
|
|
91
|
+
target,
|
|
92
|
+
match: attr => {
|
|
93
|
+
if (ignore && ignore.includes(attr)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
for (const key in _matchers) {
|
|
97
|
+
if (_matchers[key](attr)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
},
|
|
103
|
+
removeOriginal
|
|
104
|
+
});
|
|
105
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Private module-level WeakMap to hold MutationObservers for each host element.
|
|
3
|
+
*/
|
|
4
|
+
const _observers = new WeakMap();
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Private module-level WeakMap to hold attribute matchers and targets for each host element.
|
|
8
|
+
* Structure: {
|
|
9
|
+
* host: {
|
|
10
|
+
* matchers: Set<Function>,
|
|
11
|
+
* targets: Map<HTMLElement, Map<Function, {removeOriginal: boolean, currentAttributes: Map<string, string>}>>
|
|
12
|
+
* }
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
const _transportConfig = new WeakMap();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Transfers all matching attributes from a host element to a target element and observes for future changes.
|
|
19
|
+
*
|
|
20
|
+
* @param {Object} params - The parameters for the function.
|
|
21
|
+
* @param {HTMLElement} params.host - The host element from which attributes will be transported.
|
|
22
|
+
* @param {HTMLElement} params.target - The target element to which attributes will be transported.
|
|
23
|
+
* @param {boolean} [params.removeOriginal=true] - Whether to remove the attributes from the host element.
|
|
24
|
+
* @param {boolean} [params.observe=true] - Whether to attach a MutationObserver to the host element.
|
|
25
|
+
* @returns {Function} A function to detach the observer when no longer needed.
|
|
26
|
+
* @throws {TypeError} If the host or target parameters are not instances of HTMLElement.
|
|
27
|
+
*/
|
|
28
|
+
export const transportAttributes = ({ host, target, match, removeOriginal = true }) => {
|
|
29
|
+
// Guard Clause: Ensure host is valid HTMLElement instance
|
|
30
|
+
if (typeof host !== 'object' || !(host instanceof HTMLElement)) {
|
|
31
|
+
throw new TypeError('a11yUtilities.js | transportAttributes | The "host" parameter must be an instance of HTMLElement.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Guard Clause: Ensure target is valid HTMLElement instance
|
|
35
|
+
if (typeof target !== 'object' || !(target instanceof HTMLElement)) {
|
|
36
|
+
throw new TypeError('a11yUtilities.js | transportAttributes | The "target" parameter must be an instance of HTMLElement.');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Guard Clause: Ensure match is a function
|
|
40
|
+
if (typeof match !== 'function') {
|
|
41
|
+
throw new TypeError('a11yUtilities.js | transportAttributes | The "match" parameter must be a function.');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Guard Clause: Ensure removeOriginal is a boolean
|
|
45
|
+
if (typeof removeOriginal !== 'boolean') {
|
|
46
|
+
throw new TypeError('a11yUtilities.js | transportAttributes | The "removeOriginal" parameter must be a boolean.');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Register this transport and get cleanup function
|
|
50
|
+
return _registerTransport({
|
|
51
|
+
host,
|
|
52
|
+
target,
|
|
53
|
+
matcher: match,
|
|
54
|
+
removeOriginal
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Registers a matcher and target for a host element and attaches an observer if needed.
|
|
60
|
+
*
|
|
61
|
+
* @param {Object} params - The parameters object.
|
|
62
|
+
* @param {HTMLElement} params.host - The host element to observe.
|
|
63
|
+
* @param {HTMLElement} params.target - The target element to receive attributes.
|
|
64
|
+
* @param {Function} params.matcher - Function that determines which attributes to transport.
|
|
65
|
+
* @param {boolean} [params.removeOriginal=true] - Whether to remove original attributes.
|
|
66
|
+
* @returns {Function} Function to detach the specific matcher and target pairing.
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
const _registerTransport = ({ host, target, matcher, removeOriginal = true }) => {
|
|
70
|
+
// Initialize config for this host if it doesn't exist
|
|
71
|
+
if (!_transportConfig.has(host)) {
|
|
72
|
+
_transportConfig.set(host, {
|
|
73
|
+
matchers: new Set(),
|
|
74
|
+
targets: new Map()
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const config = _transportConfig.get(host);
|
|
79
|
+
|
|
80
|
+
// Add the matcher to the set of matchers for this host
|
|
81
|
+
config.matchers.add(matcher);
|
|
82
|
+
|
|
83
|
+
// Initialize target entry if it doesn't exist
|
|
84
|
+
if (!config.targets.has(target)) {
|
|
85
|
+
config.targets.set(target, new Map());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Store the matcher with its removeOriginal setting for this target
|
|
89
|
+
config.targets.get(target).set(matcher, {
|
|
90
|
+
removeOriginal,
|
|
91
|
+
currentAttributes: new Map()
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Perform initial attribute transport
|
|
95
|
+
_transportAttributes({ host, target, matcher, removeOriginal });
|
|
96
|
+
|
|
97
|
+
// Attach observer
|
|
98
|
+
_attachObserver(host);
|
|
99
|
+
|
|
100
|
+
// Return cleanup function and utility functions
|
|
101
|
+
return {
|
|
102
|
+
cleanup: () => _cleanupTransport(host, target, matcher),
|
|
103
|
+
getObservedAttributes: () => _getObservedAttributes(host, target, matcher),
|
|
104
|
+
getObservedAttribute: (attr) => _getObservedAttribute(host, target, matcher, attr),
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Cleans up resources associated with a specific matcher and target for a host element.
|
|
110
|
+
*
|
|
111
|
+
* @param {HTMLElement} host - The host element.
|
|
112
|
+
* @param {HTMLElement} target - The target element.
|
|
113
|
+
* @param {Function} matcher - The matcher function.
|
|
114
|
+
* @private
|
|
115
|
+
*/
|
|
116
|
+
const _cleanupTransport = (host, target, matcher) => {
|
|
117
|
+
const config = _transportConfig.get(host);
|
|
118
|
+
if (!config) return;
|
|
119
|
+
|
|
120
|
+
// Remove this matcher from this target
|
|
121
|
+
const targetMatchers = config.targets.get(target);
|
|
122
|
+
if (targetMatchers) {
|
|
123
|
+
targetMatchers.delete(matcher);
|
|
124
|
+
|
|
125
|
+
// If this target has no more matchers, remove it
|
|
126
|
+
if (targetMatchers.size === 0) {
|
|
127
|
+
config.targets.delete(target);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Check if this matcher is still used by any target
|
|
132
|
+
let matcherStillUsed = false;
|
|
133
|
+
for (const matcherMap of config.targets.values()) {
|
|
134
|
+
if (matcherMap.has(matcher)) {
|
|
135
|
+
matcherStillUsed = true;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// If not used anymore, remove from matchers set
|
|
141
|
+
if (!matcherStillUsed) {
|
|
142
|
+
config.matchers.delete(matcher);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// If no more targets or matchers, detach observer
|
|
146
|
+
if (config.targets.size === 0 || config.matchers.size === 0) {
|
|
147
|
+
_detachObserver(host);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Generic function to transport attributes from a host element to a target element.
|
|
153
|
+
*
|
|
154
|
+
* @param {Object} params - The parameters object.
|
|
155
|
+
* @param {HTMLElement} params.host - The host element from which to transport attributes.
|
|
156
|
+
* @param {HTMLElement} params.target - The target element to which attributes will be transported.
|
|
157
|
+
* @param {Function} params.matcher - Function that takes an attribute name and returns true if it should be transported.
|
|
158
|
+
* @param {boolean} [params.removeOriginal=true] - Whether to remove original attributes from host.
|
|
159
|
+
* @returns {void}
|
|
160
|
+
* @private
|
|
161
|
+
*/
|
|
162
|
+
const _transportAttributes = ({ host, target, matcher, removeOriginal = true }) => {
|
|
163
|
+
// Get a list of all matching attributes on the host element and their values
|
|
164
|
+
const matchingAttributes = host.getAttributeNames()
|
|
165
|
+
.filter(attr => matcher(attr))
|
|
166
|
+
.reduce((acc, attr) => {
|
|
167
|
+
acc[attr] = host.getAttribute(attr);
|
|
168
|
+
return acc;
|
|
169
|
+
}, {});
|
|
170
|
+
|
|
171
|
+
// Move matching attributes to the target element, removing them from the host if removeOriginal is true
|
|
172
|
+
Object.entries(matchingAttributes).forEach(([key, value]) => {
|
|
173
|
+
_setObservedAttribute(host, target, matcher, key, value);
|
|
174
|
+
target.setAttribute(key, value);
|
|
175
|
+
if (removeOriginal) {
|
|
176
|
+
host.removeAttribute(key);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Attaches a MutationObserver to the host element to monitor attribute changes.
|
|
183
|
+
*
|
|
184
|
+
* @param {HTMLElement} host - The element to observe for attribute changes.
|
|
185
|
+
* @returns {MutationObserver} The observer instance.
|
|
186
|
+
* @private
|
|
187
|
+
*/
|
|
188
|
+
const _attachObserver = (host) => {
|
|
189
|
+
// If an observer for this host already exists, return it
|
|
190
|
+
if (_observers.has(host)) {
|
|
191
|
+
return _observers.get(host);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Create a new MutationObserver
|
|
195
|
+
const observer = new MutationObserver((mutations) => {
|
|
196
|
+
const config = _transportConfig.get(host);
|
|
197
|
+
if (!config) return;
|
|
198
|
+
|
|
199
|
+
// For each mutation affecting attributes
|
|
200
|
+
mutations
|
|
201
|
+
.filter(mutation => mutation.type === 'attributes')
|
|
202
|
+
.forEach(mutation => {
|
|
203
|
+
const attributeName = mutation.attributeName;
|
|
204
|
+
|
|
205
|
+
// Find matchers that care about this attribute
|
|
206
|
+
for (const matcher of config.matchers) {
|
|
207
|
+
if (matcher(attributeName)) {
|
|
208
|
+
// For each target that uses this matcher
|
|
209
|
+
for (const [target, matcherConfigs] of config.targets.entries()) {
|
|
210
|
+
if (matcherConfigs.has(matcher)) {
|
|
211
|
+
const { removeOriginal } = matcherConfigs.get(matcher);
|
|
212
|
+
_transportAttributes({
|
|
213
|
+
host,
|
|
214
|
+
target,
|
|
215
|
+
matcher,
|
|
216
|
+
removeOriginal
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Start observing attribute changes
|
|
226
|
+
observer.observe(host, { attributes: true });
|
|
227
|
+
|
|
228
|
+
// Store the observer
|
|
229
|
+
_observers.set(host, observer);
|
|
230
|
+
|
|
231
|
+
return observer;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Detaches and cleans up the MutationObserver for a given host element.
|
|
236
|
+
*
|
|
237
|
+
* @param {HTMLElement} host - The element whose observer should be detached.
|
|
238
|
+
* @private
|
|
239
|
+
*/
|
|
240
|
+
const _detachObserver = (host) => {
|
|
241
|
+
if (_observers.has(host)) {
|
|
242
|
+
const observer = _observers.get(host);
|
|
243
|
+
observer.disconnect();
|
|
244
|
+
_observers.delete(host);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Clean up the transport config as well
|
|
248
|
+
if (_transportConfig.has(host)) {
|
|
249
|
+
_transportConfig.delete(host);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Gets the matcher configuration for a specific host, target, and matcher.
|
|
255
|
+
* @param {HTMLElement} host - The host element.
|
|
256
|
+
* @param {HTMLElement} target - The target element.
|
|
257
|
+
* @param {Function} matcher - The matcher function.
|
|
258
|
+
* @returns {Object|undefined} The matcher configuration if found.
|
|
259
|
+
* @private
|
|
260
|
+
*/
|
|
261
|
+
const _getMatcherConfig = (host, target, matcher) => {
|
|
262
|
+
const config = _transportConfig.get(host);
|
|
263
|
+
if (!config) return undefined;
|
|
264
|
+
|
|
265
|
+
const targetMatchers = config.targets.get(target);
|
|
266
|
+
if (!targetMatchers) return undefined;
|
|
267
|
+
|
|
268
|
+
return targetMatchers.get(matcher);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Sets an observed attribute value.
|
|
273
|
+
* @param {HTMLElement} host - The host element.
|
|
274
|
+
* @param {HTMLElement} target - The target element.
|
|
275
|
+
* @param {Function} matcher - The matcher function.
|
|
276
|
+
* @param {string} key - The attribute name.
|
|
277
|
+
* @param {string} value - The attribute value.
|
|
278
|
+
* @private
|
|
279
|
+
*/
|
|
280
|
+
const _setObservedAttribute = (host, target, matcher, key, value) => {
|
|
281
|
+
const matcherConfig = _getMatcherConfig(host, target, matcher);
|
|
282
|
+
if (matcherConfig) {
|
|
283
|
+
matcherConfig.currentAttributes.set(key, value);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const _getObservedAttribute = (host, target, matcher, attr) => {
|
|
288
|
+
const matcherConfig = _getMatcherConfig(host, target, matcher);
|
|
289
|
+
if (matcherConfig) return matcherConfig.currentAttributes.get(attr);
|
|
290
|
+
return undefined;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
const _getObservedAttributes = (host, target, matcher) => {
|
|
294
|
+
const matcherConfig = _getMatcherConfig(host, target, matcher);
|
|
295
|
+
if (matcherConfig) return Array.from(matcherConfig.currentAttributes.entries());
|
|
296
|
+
return [];
|
|
297
|
+
};
|