@momentum-design/components 0.127.6 → 0.127.8

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.
@@ -106,5 +106,12 @@ const styles = css `
106
106
  :host([variant='informational']:active) {
107
107
  --mdc-chip-background-color: var(--mds-color-theme-background-alert-theme-active);
108
108
  }
109
+
110
+ /* High Contrast Mode */
111
+ @media (forced-colors: active) {
112
+ :host([variant='neutral'])::part(icon) {
113
+ --mdc-chip-icon-color: ButtonText;
114
+ }
115
+ }
109
116
  `;
110
117
  export default [hostFitContentStyles, styles, ...hostFocusRingStyles()];
@@ -103,6 +103,11 @@ declare class ScreenreaderAnnouncer extends Component {
103
103
  * Clears all timeouts and removes all announcements from the screen reader.
104
104
  */
105
105
  private clearTimeOutsAndAnnouncements;
106
+ /**
107
+ * Gets an element by ID, searching in both light DOM and modal dialog shadow root.
108
+ * @internal
109
+ */
110
+ private getElementByIdAcrossShadowRoot;
106
111
  /**
107
112
  * Creates a div element with id as identity attribute in the DOM.
108
113
  *
@@ -110,6 +115,11 @@ declare class ScreenreaderAnnouncer extends Component {
110
115
  * `mdc-screenreaderannouncer-identity`.
111
116
  */
112
117
  private createAnnouncementAriaLiveRegion;
118
+ /**
119
+ * Finds the closest modal dialog ancestor, traversing through shadow DOM boundaries.
120
+ * @internal
121
+ */
122
+ private findModalAncestor;
113
123
  /**
114
124
  * Creates a single debounced function that will read the latest this.announcement when executed.
115
125
  *
@@ -118,15 +118,14 @@ class ScreenreaderAnnouncer extends Component {
118
118
  const announcementContainer = document.createElement('div');
119
119
  announcementContainer.setAttribute('id', announcementId);
120
120
  announcementContainer.setAttribute('aria-live', ariaLive);
121
- (_a = document.getElementById(this.identity)) === null || _a === void 0 ? void 0 : _a.appendChild(announcementContainer);
121
+ (_a = this.getElementByIdAcrossShadowRoot(this.identity)) === null || _a === void 0 ? void 0 : _a.appendChild(announcementContainer);
122
122
  const timeOutId = window.setTimeout(() => {
123
123
  const announcementElement = document.createElement('p');
124
124
  announcementElement.textContent = announcement;
125
125
  announcementContainer.appendChild(announcementElement);
126
126
  this.ariaLiveAnnouncementIds.push(announcementId);
127
127
  const timeOutId = window.setTimeout(() => {
128
- var _a;
129
- (_a = document.getElementById(announcementId)) === null || _a === void 0 ? void 0 : _a.remove();
128
+ announcementContainer.remove();
130
129
  }, timeout);
131
130
  this.timeOutIds.push(timeOutId);
132
131
  }, delay);
@@ -142,9 +141,22 @@ class ScreenreaderAnnouncer extends Component {
142
141
  });
143
142
  this.ariaLiveAnnouncementIds.forEach(announcementId => {
144
143
  var _a;
145
- (_a = document.getElementById(announcementId)) === null || _a === void 0 ? void 0 : _a.remove();
144
+ (_a = this.getElementByIdAcrossShadowRoot(announcementId)) === null || _a === void 0 ? void 0 : _a.remove();
146
145
  });
147
146
  }
147
+ /**
148
+ * Gets an element by ID, searching in both light DOM and modal dialog shadow root.
149
+ * @internal
150
+ */
151
+ getElementByIdAcrossShadowRoot(id) {
152
+ var _a;
153
+ const element = document.getElementById(id);
154
+ if (element) {
155
+ return element;
156
+ }
157
+ const modalDialog = this.findModalAncestor();
158
+ return ((_a = modalDialog === null || modalDialog === void 0 ? void 0 : modalDialog.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById(id)) || null;
159
+ }
148
160
  /**
149
161
  * Creates a div element with id as identity attribute in the DOM.
150
162
  *
@@ -152,7 +164,7 @@ class ScreenreaderAnnouncer extends Component {
152
164
  * `mdc-screenreaderannouncer-identity`.
153
165
  */
154
166
  createAnnouncementAriaLiveRegion() {
155
- let liveRegionLightDom = document.getElementById(this.identity);
167
+ let liveRegionLightDom = this.getElementByIdAcrossShadowRoot(this.identity);
156
168
  if (!liveRegionLightDom) {
157
169
  liveRegionLightDom = document.createElement('div');
158
170
  liveRegionLightDom.id = this.identity;
@@ -170,8 +182,37 @@ class ScreenreaderAnnouncer extends Component {
170
182
  `;
171
183
  liveRegionLightDom.appendChild(styleElement);
172
184
  liveRegionLightDom.classList.add('mdc-screenreaderannouncer__visually-hidden');
173
- document.body.appendChild(liveRegionLightDom);
185
+ // If inside a modal dialog, append to its shadow root, otherwise to document.body
186
+ const modalDialog = this.findModalAncestor();
187
+ if (modalDialog === null || modalDialog === void 0 ? void 0 : modalDialog.shadowRoot) {
188
+ modalDialog.shadowRoot.appendChild(liveRegionLightDom);
189
+ }
190
+ else {
191
+ document.body.appendChild(liveRegionLightDom);
192
+ }
193
+ }
194
+ }
195
+ /**
196
+ * Finds the closest modal dialog ancestor, traversing through shadow DOM boundaries.
197
+ * @internal
198
+ */
199
+ findModalAncestor() {
200
+ let element = this;
201
+ while (element) {
202
+ const modal = element.closest('[aria-modal="true"]');
203
+ if (modal) {
204
+ return modal;
205
+ }
206
+ // Traverse up through shadow DOM boundary
207
+ const root = element.getRootNode();
208
+ if (root instanceof ShadowRoot && root.host) {
209
+ element = root.host;
210
+ }
211
+ else {
212
+ break;
213
+ }
174
214
  }
215
+ return null;
175
216
  }
176
217
  /**
177
218
  * Creates a single debounced function that will read the latest this.announcement when executed.
@@ -182,15 +182,6 @@ declare class Textarea extends Textarea_base {
182
182
  */
183
183
  handleValueChange(): void;
184
184
  protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
185
- /**
186
- * This function is called when the attribute changes.
187
- * It updates the validity of the textarea field based on the textarea field's validity.
188
- *
189
- * @param name - attribute name
190
- * @param old - old value
191
- * @param value - new value
192
- */
193
- attributeChangedCallback(name: string, old: string | null, value: string | null): void;
194
185
  /**
195
186
  * Dispatches the character overflow state change event.
196
187
  * @returns void
@@ -265,28 +265,9 @@ class Textarea extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMix
265
265
  this.handleValueChange();
266
266
  this.handleCharacterOverflowStateChange();
267
267
  }
268
- }
269
- /**
270
- * This function is called when the attribute changes.
271
- * It updates the validity of the textarea field based on the textarea field's validity.
272
- *
273
- * @param name - attribute name
274
- * @param old - old value
275
- * @param value - new value
276
- */
277
- attributeChangedCallback(name, old, value) {
278
- super.attributeChangedCallback(name, old, value);
279
- const validationRelatedAttributes = ['maxlength', 'minlength', 'required'];
280
- if (validationRelatedAttributes.includes(name)) {
281
- this.updateComplete
282
- .then(() => {
283
- this.setTextareaValidity();
284
- })
285
- .catch(error => {
286
- if (this.onerror) {
287
- this.onerror(error);
288
- }
289
- });
268
+ // When helpText gets changed, we need to re-announce the max length warning
269
+ if (changedProperties.has('helpText')) {
270
+ this.announceMaxLengthWarning();
290
271
  }
291
272
  }
292
273
  /**
@@ -442,20 +423,23 @@ class Textarea extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMix
442
423
  identity="${this.inputId}"
443
424
  announcement="${ifDefined(this.ariaLiveAnnouncer)}"
444
425
  data-aria-live="polite"
426
+ delay="500"
445
427
  ></mdc-screenreaderannouncer>
446
- ${this.resizable ? html `
447
- <mdc-button
448
- part="resize-button"
449
- class="own-focus-ring"
450
- variant="tertiary"
451
- size="24"
452
- prefix-icon="resize-corner-regular"
453
- aria-label=${(_b = this.resizeButtonAriaLabel) !== null && _b !== void 0 ? _b : ''}
454
- ?disabled="${this.disabled || this.readonly}"
455
- @keydown=${this.handleResizeKeyDown}
456
- @pointerdown=${this.handlePointerDown}
457
- ></mdc-button>
458
- ` : nothing}
428
+ ${this.resizable
429
+ ? html `
430
+ <mdc-button
431
+ part="resize-button"
432
+ class="own-focus-ring"
433
+ variant="tertiary"
434
+ size="24"
435
+ prefix-icon="resize-corner-regular"
436
+ aria-label=${(_b = this.resizeButtonAriaLabel) !== null && _b !== void 0 ? _b : ''}
437
+ ?disabled="${this.disabled || this.readonly}"
438
+ @keydown=${this.handleResizeKeyDown}
439
+ @pointerdown=${this.handlePointerDown}
440
+ ></mdc-button>
441
+ `
442
+ : nothing}
459
443
  </div>
460
444
  ${this.renderTextareaFooter()}
461
445
  `;