@brightspace-ui/core 3.126.3 → 3.126.4

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.
@@ -30,7 +30,6 @@ import { formatNumber } from '@brightspace-ui/intl/lib/number.js';
30
30
  import { ifDefined } from 'lit/directives/if-defined.js';
31
31
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
32
32
  import { offscreenStyles } from '../offscreen/offscreen.js';
33
- import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
34
33
  import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
35
34
  import { SubscriberRegistryController } from '../../controllers/subscriber/subscriberControllers.js';
36
35
 
@@ -237,6 +236,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
237
236
  this._displayKeyboardTooltip = false;
238
237
  this._minWidth = 285;
239
238
  this._openedDimensions = [];
239
+ this._resized = false;
240
240
  this._totalAppliedCount = 0;
241
241
 
242
242
  this._activeFilters = null;
@@ -351,16 +351,6 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
351
351
  super.update(changedProperties);
352
352
  }
353
353
 
354
- updated(changedProperties) {
355
- super.updated(changedProperties);
356
- const search = this.shadowRoot.querySelector('d2l-input-search');
357
- if (search) {
358
- if (this.#resizeObserver) this.#resizeObserver.disconnect();
359
- this.#resizeObserver = new ResizeObserver(() => requestAnimationFrame(() => this.#handleSearchResize()));
360
- this.#resizeObserver.observe(search);
361
- }
362
- }
363
-
364
354
  requestFilterClearAll() {
365
355
  this._handleClearAll();
366
356
  }
@@ -455,6 +445,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
455
445
  const search = dimension.searchType === 'none' ? nothing : html`
456
446
  <d2l-input-search
457
447
  @d2l-input-search-searched="${this._handleSearch}"
448
+ @d2l-input-search-layout-updated="${this.#handleSearchLayoutUpdated}"
458
449
  ?disabled="${this._isDimensionEmpty(dimension)}"
459
450
  label="${this.localize('components.input-search.search')}"
460
451
  value="${ifDefined(dimension.searchValue)}">
@@ -684,6 +675,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
684
675
  this._changeEventsToDispatch = new Map();
685
676
  clearTimeout(this._changeEventTimeout);
686
677
  this._activeFiltersSubscribers.updateSubscribers();
678
+ this.#handleSearchLayoutUpdated(); // in order to update dropdown position if count-badge size changes pointer position
687
679
  }
688
680
 
689
681
  _dispatchChangeEventValueDataChange(dimension, value, valueKey) {
@@ -1153,7 +1145,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
1153
1145
  }
1154
1146
  }
1155
1147
 
1156
- #handleSearchResize() {
1148
+ #handleSearchLayoutUpdated() {
1157
1149
  const content = this.shadowRoot.querySelector(`.${FILTER_CONTENT_CLASS}`);
1158
1150
  content.resize();
1159
1151
  }
@@ -132,6 +132,7 @@ class InputSearch extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement)))
132
132
  <d2l-input-text
133
133
  label="${ifDefined(this.label)}"
134
134
  label-hidden
135
+ @d2l-input-text-layout-updated="${this.#handleLayoutUpdated}"
135
136
  description="${this.description}"
136
137
  ?disabled="${this.disabled}"
137
138
  @input="${this._handleInput}"
@@ -213,5 +214,15 @@ class InputSearch extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement)))
213
214
  return (oldVal !== val);
214
215
  }
215
216
 
217
+ #handleLayoutUpdated() {
218
+ requestAnimationFrame(() => {
219
+ /** @ignore */
220
+ this.dispatchEvent(new CustomEvent(
221
+ 'd2l-input-search-layout-updated',
222
+ { bubbles: false, composed: false }
223
+ ));
224
+ });
225
+ }
226
+
216
227
  }
217
228
  customElements.define('d2l-input-search', InputSearch);
@@ -678,6 +678,14 @@ class InputText extends InputInlineHelpMixin(PropertyRequiredMixin(FocusMixin(La
678
678
  this._lastSlotWidth = 0;
679
679
  }
680
680
 
681
+ requestAnimationFrame(() => {
682
+ /** @ignore */
683
+ this.dispatchEvent(new CustomEvent(
684
+ 'd2l-input-text-layout-updated',
685
+ { bubbles: false, composed: false }
686
+ ));
687
+ });
688
+
681
689
  }
682
690
 
683
691
  }
@@ -17,6 +17,40 @@
17
17
  <body unresolved>
18
18
 
19
19
  <d2l-demo-page page-title="d2l-menu">
20
+ <h2>Basic Menu (demo of focus bug)</h2>
21
+ <d2l-demo-snippet>
22
+ <template>
23
+ <div role="menu">
24
+ <div role="menuitem" tabindex="0">
25
+ <span>Menu Item 1</span>
26
+ </div><div role="menuitem" tabindex="-1">
27
+ <span>Menu Item 2</span>
28
+ </div><div role="menuitem" tabindex="-1">
29
+ <span>Menu Item 3</span>
30
+ </div>
31
+ </div>
32
+ <script>
33
+ const menu = document.querySelector('div[role="menu"]');
34
+ const menuItems = menu.querySelectorAll('div[role="menuitem"]');
35
+
36
+ menuItems.forEach(item => {
37
+ item.addEventListener('keydown', (e) => {
38
+ if (e.keyCode === 40 || e.keyCode === 38) {
39
+ // prevent scrolling when up/down arrows pressed
40
+ e.preventDefault();
41
+ e.stopPropagation();
42
+ if (e.keyCode === 40) {
43
+ if (item.nextSibling) item.nextSibling.focus();
44
+ } else if (e.keyCode === 38) {
45
+ if (item.previousSibling) item.previousSibling.focus();
46
+ }
47
+ return;
48
+ }
49
+ });
50
+ });
51
+ </script>
52
+ </template>
53
+ </d2l-demo-snippet>
20
54
 
21
55
  <h2>Menu</h2>
22
56
 
@@ -166,6 +166,7 @@ export const MenuItemMixin = superclass => class extends superclass {
166
166
  return;
167
167
  }
168
168
  this.focus();
169
+ this.setAttribute('tabindex', '0');
169
170
  }
170
171
 
171
172
  __onKeyDown(e) {
@@ -102,6 +102,7 @@ class Menu extends ThemeMixin(HierarchicalViewMixin(LitElement)) {
102
102
  this.addEventListener('d2l-menu-item-visibility-change', this._onMenuItemsChanged);
103
103
  this.addEventListener('keydown', this._onKeyDown);
104
104
  this.addEventListener('keypress', this._onKeyPress);
105
+ this.addEventListener('focusout', this._onFocusOut);
105
106
 
106
107
  this._labelChanged();
107
108
 
@@ -175,28 +176,33 @@ class Menu extends ThemeMixin(HierarchicalViewMixin(LitElement)) {
175
176
 
176
177
  _focusFirst() {
177
178
  const item = this._tryGetNextFocusable();
178
- if (item) item.focus();
179
+ if (item) this._focusItem(item);
180
+ }
181
+
182
+ _focusItem(item) {
183
+ item.setAttribute('tabindex', '0');
184
+ item.focus();
179
185
  }
180
186
 
181
187
  _focusLast() {
182
188
  const item = this._tryGetPreviousFocusable();
183
- if (item) item.focus();
189
+ if (item) this._focusItem(item);
184
190
  }
185
191
 
186
192
  _focusNext(item) {
187
193
  item = this._tryGetNextFocusable(item);
188
- item ? item.focus() : this._focusFirst();
194
+ item ? this._focusItem(item) : this._focusFirst();
189
195
  }
190
196
 
191
197
  _focusPrevious(item) {
192
198
  item = this._tryGetPreviousFocusable(item);
193
- item ? item.focus() : this._focusLast();
199
+ item ? this._focusItem(item) : this._focusLast();
194
200
  }
195
201
 
196
202
  _focusSelected() {
197
203
  const selected = this.querySelector('[selected]');
198
204
  if (selected) {
199
- selected.focus();
205
+ this._focusItem(selected);
200
206
  } else {
201
207
  this._focusFirst();
202
208
  }
@@ -260,6 +266,13 @@ class Menu extends ThemeMixin(HierarchicalViewMixin(LitElement)) {
260
266
  if (returnItem) returnItem.setAttribute('text', this.label);
261
267
  }
262
268
 
269
+ _onFocusOut(e) {
270
+ e.stopPropagation();
271
+ const isMenuItem = e.target.role === 'menuitem' || e.target.role === 'menuitemcheckbox' || e.target.role === 'menuitemradio';
272
+ if (!isMenuItem || e.target.hasAttribute('first') || e.target.hasChildView) return;
273
+ e.target.setAttribute('tabindex', '-1');
274
+ }
275
+
263
276
  _onKeyDown(e) {
264
277
  const rootTarget = e.composedPath()[0];
265
278
  if (this._items.indexOf(rootTarget) === -1) return;
@@ -321,7 +334,7 @@ class Menu extends ThemeMixin(HierarchicalViewMixin(LitElement)) {
321
334
  while (itemIndex !== targetItemIndex) {
322
335
  const item = focusableItems[itemIndex];
323
336
  if (startsWith(item, searchChar)) {
324
- item.focus();
337
+ this._focusItem(item);
325
338
  return;
326
339
  }
327
340
  itemIndex = getNextOrFirstIndex(itemIndex);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.126.3",
3
+ "version": "3.126.4",
4
4
  "description": "A collection of accessible, free, open-source web components for building Brightspace applications",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/BrightspaceUI/core.git",