@vaadin/a11y-base 25.3.0-alpha7 → 25.3.0-alpha9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/a11y-base",
3
- "version": "25.3.0-alpha7",
3
+ "version": "25.3.0-alpha9",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -32,15 +32,15 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@open-wc/dedupe-mixin": "^1.3.0",
35
- "@vaadin/component-base": "25.3.0-alpha7",
35
+ "@vaadin/component-base": "25.3.0-alpha9",
36
36
  "lit": "^3.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@vaadin/chai-plugins": "25.3.0-alpha7",
40
- "@vaadin/test-runner-commands": "25.3.0-alpha7",
39
+ "@vaadin/chai-plugins": "25.3.0-alpha9",
40
+ "@vaadin/test-runner-commands": "25.3.0-alpha9",
41
41
  "@vaadin/testing-helpers": "^2.0.0",
42
42
  "sinon": "^22.0.0"
43
43
  },
44
44
  "customElements": "custom-elements.json",
45
- "gitHead": "ae7b9823df5598faebd7a482993029ee489c35ae"
45
+ "gitHead": "cb915ebde095ec5b94a87af93dd4530f51984c52"
46
46
  }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * Adds the element to the target's `ariaDescribedByElements` or
9
+ * `ariaLabelledByElements` property, based on the given attribute.
10
+ * Unlike ID references, element references also work across shadow roots.
11
+ */
12
+ export function addAriaElementReference(
13
+ target: HTMLElement,
14
+ attr: 'aria-describedby' | 'aria-labelledby',
15
+ element: HTMLElement,
16
+ ): void;
17
+
18
+ /**
19
+ * Removes the element from the target's `ariaDescribedByElements` or
20
+ * `ariaLabelledByElements` property, based on the given attribute.
21
+ * When the last element is removed, the property is reset to `null`
22
+ * so it no longer overrides the content attribute.
23
+ */
24
+ export function removeAriaElementReference(
25
+ target: HTMLElement,
26
+ attr: 'aria-describedby' | 'aria-labelledby',
27
+ element: HTMLElement,
28
+ ): void;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2000 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ const ARIA_REFERENCE_PROPERTIES = {
8
+ 'aria-describedby': 'ariaDescribedByElements',
9
+ 'aria-labelledby': 'ariaLabelledByElements',
10
+ };
11
+
12
+ /**
13
+ * Adds the element to the target's `ariaDescribedByElements` or
14
+ * `ariaLabelledByElements` property, based on the given attribute.
15
+ * Unlike ID references, element references also work across shadow roots.
16
+ *
17
+ * @param {HTMLElement} target
18
+ * @param {'aria-describedby' | 'aria-labelledby'} attr
19
+ * @param {HTMLElement} element
20
+ */
21
+ export function addAriaElementReference(target, attr, element) {
22
+ const property = ARIA_REFERENCE_PROPERTIES[attr];
23
+ const elements = new Set(target[property]);
24
+ elements.add(element);
25
+ target[property] = [...elements];
26
+ }
27
+
28
+ /**
29
+ * Removes the element from the target's `ariaDescribedByElements` or
30
+ * `ariaLabelledByElements` property, based on the given attribute.
31
+ * When the last element is removed, the property is reset to `null`
32
+ * so it no longer overrides the content attribute.
33
+ *
34
+ * @param {HTMLElement} target
35
+ * @param {'aria-describedby' | 'aria-labelledby'} attr
36
+ * @param {HTMLElement} element
37
+ */
38
+ export function removeAriaElementReference(target, attr, element) {
39
+ const property = ARIA_REFERENCE_PROPERTIES[attr];
40
+ const elements = new Set(target[property]);
41
+ elements.delete(element);
42
+ target[property] = elements.size > 0 ? [...elements] : null;
43
+ }
@@ -4,6 +4,7 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { dedupeMixin } from '@open-wc/dedupe-mixin';
7
+ import { setOrRemoveAttribute } from '@vaadin/component-base/src/dom-utils.js';
7
8
 
8
9
  /**
9
10
  * A mixin to provide disabled property for field components.
@@ -38,11 +39,7 @@ const DisabledMixinImplementation = (superclass) => {
38
39
  * @protected
39
40
  */
40
41
  _setAriaDisabled(disabled) {
41
- if (disabled) {
42
- this.setAttribute('aria-disabled', 'true');
43
- } else {
44
- this.removeAttribute('aria-disabled');
45
- }
42
+ setOrRemoveAttribute(this, 'aria-disabled', disabled);
46
43
  }
47
44
 
48
45
  /**
@@ -33,31 +33,34 @@ export class FieldAriaController {
33
33
  *
34
34
  * To remove the attribute, pass `null` as `label`.
35
35
  */
36
- setAriaLabel(label: string | null): void;
36
+ setLabel(label: string | null): void;
37
37
 
38
38
  /**
39
- * Links the target element with a slotted label element
40
- * via the target's attribute `aria-labelledby`.
39
+ * Links the target element to one or more elements via the `aria-labelledby` attribute.
41
40
  *
42
- * To unlink the previous slotted label element, pass `null` as `labelId`.
41
+ * Pass a space-delimited list of IDs, or `null` to remove the previously linked IDs.
43
42
  */
44
- setLabelId(labelId: string | null, fromUser: boolean | null): void;
43
+ setLabelledBy(labelledBy: string | null): void;
45
44
 
46
45
  /**
47
- * Links the target element with a slotted error element via the target's attribute:
48
- * - `aria-labelledby` if the target is the host component (e.g a field group).
49
- * - `aria-describedby` otherwise.
46
+ * Links the target element to one or more elements via the `aria-describedby` attribute.
50
47
  *
51
- * To unlink the previous slotted error element, pass `null` as `errorId`.
48
+ * @param describedBy the space-delimited list of IDs,
49
+ * or `null` to remove the previously linked IDs
50
+ */
51
+ setDescribedBy(describedBy: string | null): void;
52
+
53
+ /**
54
+ * Links the target element to a slotted error element via the `aria-describedby` attribute.
55
+ *
56
+ * Pass the ID of the error element, or `null` to remove the previously linked ID.
52
57
  */
53
58
  setErrorId(errorId: string | null): void;
54
59
 
55
60
  /**
56
- * Links the target element with a slotted helper element via the target's attribute:
57
- * - `aria-labelledby` if the target is the host component (e.g a field group).
58
- * - `aria-describedby` otherwise.
61
+ * Links the target element to a slotted helper element via the `aria-describedby` attribute.
59
62
  *
60
- * To unlink the previous slotted helper element, pass `null` as `helperId`.
63
+ * Pass the ID of the helper element, or `null` to remove the previously linked ID.
61
64
  */
62
65
  setHelperId(helperId: string | null): void;
63
66
  }
@@ -3,7 +3,11 @@
3
3
  * Copyright (c) 2021 - 2026 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { removeAriaIDReference, restoreGeneratedAriaIDReference, setAriaIDReference } from './aria-id-reference.js';
6
+ import {
7
+ addValuesToAttribute,
8
+ removeValuesFromAttribute,
9
+ setOrRemoveAttribute,
10
+ } from '@vaadin/component-base/src/dom-utils.js';
7
11
 
8
12
  /**
9
13
  * A controller for managing ARIA attributes for a field element:
@@ -20,10 +24,10 @@ export class FieldAriaController {
20
24
  #label;
21
25
 
22
26
  /** @type {string | null | undefined} */
23
- #labelId;
27
+ #labelledBy;
24
28
 
25
29
  /** @type {string | null | undefined} */
26
- #labelIdFromUser;
30
+ #describedBy;
27
31
 
28
32
  /** @type {string | null | undefined} */
29
33
  #errorId;
@@ -31,6 +35,12 @@ export class FieldAriaController {
31
35
  /** @type {string | null | undefined} */
32
36
  #helperId;
33
37
 
38
+ /** @type {string[]} */
39
+ #ariaLabelledByAttributeIds = [];
40
+
41
+ /** @type {string[]} */
42
+ #ariaDescribedByAttributeIds = [];
43
+
34
44
  constructor(host) {
35
45
  this.host = host;
36
46
  }
@@ -42,15 +52,10 @@ export class FieldAriaController {
42
52
  */
43
53
  setTarget(target) {
44
54
  this.#target = target;
45
- this.#setAriaRequiredAttribute(this.#required);
46
- // We need to make sure that value in #labelId is stored
47
- this.#setLabelIdToAriaAttribute(this.#labelId, this.#labelId);
48
- if (this.#labelIdFromUser != null) {
49
- this.#setLabelIdToAriaAttribute(this.#labelIdFromUser, this.#labelIdFromUser, true);
50
- }
51
- this.#setErrorIdToAriaAttribute(this.#errorId);
52
- this.#setHelperIdToAriaAttribute(this.#helperId);
53
- this.setAriaLabel(this.#label);
55
+ this.#updateAriaLabelAttribute();
56
+ this.#updateAriaLabelledByAttribute();
57
+ this.#updateAriaDescribedByAttribute();
58
+ this.#updateAriaRequiredAttribute();
54
59
  }
55
60
 
56
61
  /**
@@ -61,8 +66,8 @@ export class FieldAriaController {
61
66
  * @param {boolean} required
62
67
  */
63
68
  setRequired(required) {
64
- this.#setAriaRequiredAttribute(required);
65
69
  this.#required = required;
70
+ this.#updateAriaRequiredAttribute();
66
71
  }
67
72
 
68
73
  /**
@@ -72,102 +77,88 @@ export class FieldAriaController {
72
77
  *
73
78
  * @param {string | null | undefined} label
74
79
  */
75
- setAriaLabel(label) {
76
- this.#setAriaLabelToAttribute(label);
80
+ setLabel(label) {
77
81
  this.#label = label;
82
+ this.#updateAriaLabelAttribute();
78
83
  }
79
84
 
80
85
  /**
81
- * Links the target element with a slotted label element
82
- * via the target's attribute `aria-labelledby`.
86
+ * Links the target element to one or more elements via the `aria-labelledby` attribute.
83
87
  *
84
- * To unlink the previous slotted label element, pass `null` as `labelId`.
85
- *
86
- * @param {string | null} labelId
88
+ * @param {string | null} labelledBy the space-delimited list of IDs,
89
+ * or `null` to remove the previously linked IDs
87
90
  */
88
- setLabelId(labelId, fromUser = false) {
89
- const oldLabelId = fromUser ? this.#labelIdFromUser : this.#labelId;
90
- this.#setLabelIdToAriaAttribute(labelId, oldLabelId, fromUser);
91
- if (fromUser) {
92
- this.#labelIdFromUser = labelId;
93
- } else {
94
- this.#labelId = labelId;
95
- }
91
+ setLabelledBy(labelledBy) {
92
+ this.#labelledBy = labelledBy;
93
+ this.#updateAriaLabelledByAttribute();
96
94
  }
97
95
 
98
96
  /**
99
- * Links the target element with a slotted error element via the target's attribute:
100
- * - `aria-labelledby` if the target is the host component (e.g a field group).
101
- * - `aria-describedby` otherwise.
97
+ * Links the target element to one or more elements via the `aria-describedby` attribute.
102
98
  *
103
- * To unlink the previous slotted error element, pass `null` as `errorId`.
99
+ * @param {string | null} describedBy the space-delimited list of IDs,
100
+ * or `null` to remove the previously linked IDs
101
+ */
102
+ setDescribedBy(describedBy) {
103
+ this.#describedBy = describedBy;
104
+ this.#updateAriaDescribedByAttribute();
105
+ }
106
+
107
+ /**
108
+ * Links the target element to a slotted error element via the `aria-describedby` attribute.
104
109
  *
105
- * @param {string | null} errorId
110
+ * @param {string | null} errorId the ID of the error element,
111
+ * or `null` to remove the previously linked ID
106
112
  */
107
113
  setErrorId(errorId) {
108
- this.#setErrorIdToAriaAttribute(errorId, this.#errorId);
109
114
  this.#errorId = errorId;
115
+ this.#updateAriaDescribedByAttribute();
110
116
  }
111
117
 
112
118
  /**
113
- * Links the target element with a slotted helper element via the target's attribute:
114
- * - `aria-labelledby` if the target is the host component (e.g a field group).
115
- * - `aria-describedby` otherwise.
116
- *
117
- * To unlink the previous slotted helper element, pass `null` as `helperId`.
119
+ * Links the target element to a slotted helper element via the `aria-describedby` attribute.
118
120
  *
119
- * @param {string | null} helperId
121
+ * @param {string | null} helperId the ID of the helper element,
122
+ * or `null` to remove the previously linked ID
120
123
  */
121
124
  setHelperId(helperId) {
122
- this.#setHelperIdToAriaAttribute(helperId, this.#helperId);
123
125
  this.#helperId = helperId;
126
+ this.#updateAriaDescribedByAttribute();
124
127
  }
125
128
 
126
- /**
127
- * @param {string | null | undefined} label
128
- */
129
- #setAriaLabelToAttribute(label) {
129
+ #updateAriaLabelAttribute() {
130
130
  if (!this.#target) {
131
131
  return;
132
132
  }
133
- if (label) {
134
- removeAriaIDReference(this.#target, 'aria-labelledby');
135
- this.#target.setAttribute('aria-label', label);
136
- } else if (this.#label) {
137
- restoreGeneratedAriaIDReference(this.#target, 'aria-labelledby');
138
- this.#target.removeAttribute('aria-label');
139
- }
140
- }
141
133
 
142
- /**
143
- * @param {string | null | undefined} labelId
144
- * @param {string | null | undefined} oldLabelId
145
- * @param {boolean | null | undefined} fromUser
146
- */
147
- #setLabelIdToAriaAttribute(labelId, oldLabelId, fromUser) {
148
- setAriaIDReference(this.#target, 'aria-labelledby', { newId: labelId, oldId: oldLabelId, fromUser });
134
+ setOrRemoveAttribute(this.#target, 'aria-label', this.#label);
149
135
  }
150
136
 
151
- /**
152
- * @param {string | null | undefined} errorId
153
- * @param {string | null | undefined} oldErrorId
154
- */
155
- #setErrorIdToAriaAttribute(errorId, oldErrorId) {
156
- setAriaIDReference(this.#target, 'aria-describedby', { newId: errorId, oldId: oldErrorId, fromUser: false });
137
+ #updateAriaLabelledByAttribute() {
138
+ if (!this.#target) {
139
+ return;
140
+ }
141
+
142
+ removeValuesFromAttribute(this.#target, 'aria-labelledby', this.#ariaLabelledByAttributeIds);
143
+
144
+ this.#ariaLabelledByAttributeIds = [this.#labelledBy];
145
+
146
+ addValuesToAttribute(this.#target, 'aria-labelledby', this.#ariaLabelledByAttributeIds);
157
147
  }
158
148
 
159
- /**
160
- * @param {string | null | undefined} helperId
161
- * @param {string | null | undefined} oldHelperId
162
- */
163
- #setHelperIdToAriaAttribute(helperId, oldHelperId) {
164
- setAriaIDReference(this.#target, 'aria-describedby', { newId: helperId, oldId: oldHelperId, fromUser: false });
149
+ #updateAriaDescribedByAttribute() {
150
+ if (!this.#target) {
151
+ return;
152
+ }
153
+
154
+ removeValuesFromAttribute(this.#target, 'aria-describedby', this.#ariaDescribedByAttributeIds);
155
+
156
+ this.#ariaDescribedByAttributeIds = [this.#describedBy, this.#helperId, this.#errorId];
157
+
158
+ addValuesToAttribute(this.#target, 'aria-describedby', this.#ariaDescribedByAttributeIds);
165
159
  }
166
160
 
167
- /**
168
- * @param {boolean} required
169
- */
170
- #setAriaRequiredAttribute(required) {
161
+ #updateAriaRequiredAttribute() {
171
162
  if (!this.#target) {
172
163
  return;
173
164
  }
@@ -177,10 +168,6 @@ export class FieldAriaController {
177
168
  return;
178
169
  }
179
170
 
180
- if (required) {
181
- this.#target.setAttribute('aria-required', 'true');
182
- } else {
183
- this.#target.removeAttribute('aria-required');
184
- }
171
+ setOrRemoveAttribute(this.#target, 'aria-required', this.#required);
185
172
  }
186
173
  }
package/src/list-mixin.js CHANGED
@@ -6,6 +6,7 @@
6
6
  import { timeOut } from '@vaadin/component-base/src/async.js';
7
7
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
8
8
  import { getNormalizedScrollLeft, setNormalizedScrollLeft } from '@vaadin/component-base/src/dir-utils.js';
9
+ import { setOrRemoveAttribute } from '@vaadin/component-base/src/dom-utils.js';
9
10
  import { SlotObserver } from '@vaadin/component-base/src/slot-observer.js';
10
11
  import { isElementHidden } from './focus-utils.js';
11
12
  import { KeyboardDirectionMixin } from './keyboard-direction-mixin.js';
@@ -163,13 +164,7 @@ export const ListMixin = (superClass) =>
163
164
  if (!disabled) {
164
165
  if (items) {
165
166
  this.setAttribute('aria-orientation', orientation || 'vertical');
166
- items.forEach((item) => {
167
- if (orientation) {
168
- item.setAttribute('orientation', orientation);
169
- } else {
170
- item.removeAttribute('orientation');
171
- }
172
- });
167
+ items.forEach((item) => setOrRemoveAttribute(item, 'orientation', orientation));
173
168
 
174
169
  // When selected is set to -1, focus the first available item.
175
170
  this._setFocusable(selected < 0 || !selected ? 0 : selected);
@@ -1,41 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2023 - 2026 Vaadin Ltd.
4
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
- */
6
-
7
- export type AriaIDReferenceConfig = {
8
- newId: string | null;
9
- oldId: string | null;
10
- fromUser: boolean | null;
11
- };
12
-
13
- /**
14
- * Sets a new ID reference for a target element and an ARIA attribute.
15
- *
16
- * @param config.newId
17
- * The new ARIA ID reference to set. If `null`, the attribute is removed,
18
- * and `config.fromUser` is `true`, any stored values are restored. If there
19
- * are stored values and `config.fromUser` is `false`, then `config.newId`
20
- * is added to the stored values set.
21
- * @param config.oldId
22
- * The ARIA ID reference to be removed from the attribute. If there are stored
23
- * values and `config.fromUser` is `false`, then `config.oldId` is removed from
24
- * the stored values set.
25
- * @param config.fromUser
26
- * Indicates whether the function is called by the user or internally.
27
- * When `config.fromUser` is called with `true` for the first time,
28
- * the function will clear and store the attribute value for the given element.
29
- */
30
- export function setAriaIDReference(target: HTMLElement, attr: string, config: AriaIDReferenceConfig): void;
31
-
32
- /**
33
- * Removes the attribute value of the given target element.
34
- * It also stores the current value, if no stored values are present.
35
- */
36
- export function removeAriaIDReference(target: HTMLElement, attr: string): void;
37
-
38
- /**
39
- * Restores the generated values of the attribute to the given target element.
40
- */
41
- export function restoreGeneratedAriaIDReference(target: HTMLElement, attr: string): void;
@@ -1,154 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2023 - 2026 Vaadin Ltd.
4
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
- */
6
- import {
7
- addValueToAttribute,
8
- deserializeAttributeValue,
9
- removeValueFromAttribute,
10
- serializeAttributeValue,
11
- } from '@vaadin/component-base/src/dom-utils.js';
12
-
13
- const attributeToTargets = new Map();
14
-
15
- /**
16
- * Gets or creates a Set with the stored values for each element controlled by this helper
17
- *
18
- * @param {string} attr the attribute name used as key in the map
19
- *
20
- * @return {WeakMap<HTMLElement, Set<string>>} a weak map with the stored values for the elements being controlled by the helper
21
- */
22
- function getAttrMap(attr) {
23
- if (!attributeToTargets.has(attr)) {
24
- attributeToTargets.set(attr, new WeakMap());
25
- }
26
- return attributeToTargets.get(attr);
27
- }
28
-
29
- /**
30
- * Cleans the values set on the attribute to the given element.
31
- * It also stores the current values in the map, if `storeValue` is `true`.
32
- *
33
- * @param {HTMLElement} target
34
- * @param {string} attr the attribute to be cleared
35
- */
36
- function cleanAriaIDReference(target, attr) {
37
- if (!target) {
38
- return;
39
- }
40
-
41
- target.removeAttribute(attr);
42
- }
43
-
44
- /**
45
- * Storing values of the accessible attributes in a Set inside of the WeakMap.
46
- *
47
- * @param {HTMLElement} target
48
- * @param {string} attr the attribute to be stored
49
- */
50
- function storeAriaIDReference(target, attr) {
51
- if (!target || !attr) {
52
- return;
53
- }
54
- const attributeMap = getAttrMap(attr);
55
- if (attributeMap.has(target)) {
56
- return;
57
- }
58
- const values = deserializeAttributeValue(target.getAttribute(attr));
59
- attributeMap.set(target, new Set(values));
60
- }
61
-
62
- /**
63
- * Restores the generated values of the attribute to the given element.
64
- *
65
- * @param {HTMLElement} target
66
- * @param {string} attr
67
- */
68
- export function restoreGeneratedAriaIDReference(target, attr) {
69
- if (!target || !attr) {
70
- return;
71
- }
72
- const attributeMap = getAttrMap(attr);
73
- const values = attributeMap.get(target);
74
- if (!values || values.size === 0) {
75
- target.removeAttribute(attr);
76
- } else {
77
- addValueToAttribute(target, attr, serializeAttributeValue(values));
78
- }
79
- attributeMap.delete(target);
80
- }
81
-
82
- /**
83
- * Sets a new ID reference for a target element and an ARIA attribute.
84
- *
85
- * @typedef {Object} AriaIdReferenceConfig
86
- * @property {string | null | undefined} newId
87
- * @property {string | null | undefined} oldId
88
- * @property {boolean | null | undefined} fromUser
89
- * @param {HTMLElement} target
90
- * @param {string} attr
91
- * @param {AriaIdReferenceConfig | null | undefined} config
92
- * @param config.newId The new ARIA ID reference to set. If `null`, the attribute is removed,
93
- * and `config.fromUser` is true, any stored values are restored. If there are stored values
94
- * and `config.fromUser` is `false`, then `config.newId` is added to the stored values set.
95
- * @param config.oldId The ARIA ID reference to be removed from the attribute. If there are
96
- * stored values and `config.fromUser` is `false`, then `config.oldId` is removed from the
97
- * stored values set.
98
- * @param config.fromUser Indicates whether the function is called by the user or internally.
99
- * When `config.fromUser` is called with `true` for the first time, the function will clear
100
- * and store the attribute value for the given element.
101
- */
102
- export function setAriaIDReference(target, attr, config = { newId: null, oldId: null, fromUser: false }) {
103
- if (!target || !attr) {
104
- return;
105
- }
106
-
107
- const { newId, oldId, fromUser } = config;
108
-
109
- const attributeMap = getAttrMap(attr);
110
- const storedValues = attributeMap.get(target);
111
-
112
- if (!fromUser && !!storedValues) {
113
- // If there's any stored values, it means the attribute is being handled by the user
114
- // Replace the "oldId" with "newId" on the stored values set and leave
115
- oldId && storedValues.delete(oldId);
116
- newId && storedValues.add(newId);
117
- return;
118
- }
119
-
120
- if (fromUser) {
121
- if (!storedValues) {
122
- // If it's called from user and there's no stored values for the attribute,
123
- // then store the current value
124
- storeAriaIDReference(target, attr);
125
- } else if (!newId) {
126
- // If called from user with newId == null, it means the attribute will no longer
127
- // be in control of the user and the stored values should be restored
128
- // Removing the entry on the map for this target
129
- attributeMap.delete(target);
130
- }
131
-
132
- // If it's from user, then clear the attribute value before setting newId
133
- cleanAriaIDReference(target, attr);
134
- }
135
-
136
- removeValueFromAttribute(target, attr, oldId);
137
-
138
- const attributeValue = !newId ? serializeAttributeValue(storedValues) : newId;
139
- if (attributeValue) {
140
- addValueToAttribute(target, attr, attributeValue);
141
- }
142
- }
143
-
144
- /**
145
- * Removes the {@link attr | attribute} value of the given {@link target} element.
146
- * It also stores the current value, if no stored values are present.
147
- *
148
- * @param {HTMLElement} target
149
- * @param {string} attr
150
- */
151
- export function removeAriaIDReference(target, attr) {
152
- storeAriaIDReference(target, attr);
153
- cleanAriaIDReference(target, attr);
154
- }