@brightspace-ui/core 3.225.0 → 3.226.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/components/backdrop/backdrop.js +16 -0
- package/components/button/README.md +1 -1
- package/components/hierarchical-view/hierarchical-view-mixin.js +15 -3
- package/components/inputs/demo/input-checkbox.html +13 -1
- package/components/inputs/docs/input-checkbox.md +1 -0
- package/components/inputs/input-checkbox.js +7 -1
- package/components/popover/popover-mixin.js +14 -3
- package/custom-elements.json +13 -0
- package/helpers/dom.js +38 -0
- package/package.json +1 -1
|
@@ -2,10 +2,12 @@ import '../colors/colors.js';
|
|
|
2
2
|
import { css, html, LitElement } from 'lit';
|
|
3
3
|
import { cssEscape, getComposedChildren, getComposedParent, isComposedAncestor, isVisible } from '../../helpers/dom.js';
|
|
4
4
|
import { getComposedActiveElement } from '../../helpers/focus.js';
|
|
5
|
+
import { getFlag } from '../../helpers/flags.js';
|
|
5
6
|
|
|
6
7
|
const BACKDROP_HIDDEN = 'data-d2l-backdrop-hidden';
|
|
7
8
|
const BACKDROP_ARIA_HIDDEN = 'data-d2l-backdrop-aria-hidden';
|
|
8
9
|
const BACKDROP_TABINDEX = 'data-d2l-backdrop-tabindex';
|
|
10
|
+
const BACKDROP_INERT = 'data-d2l-backdrop-inert';
|
|
9
11
|
const TRANSITION_DURATION = 200;
|
|
10
12
|
|
|
11
13
|
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
@@ -180,6 +182,13 @@ function hideAccessible(target) {
|
|
|
180
182
|
}
|
|
181
183
|
child.setAttribute('tabindex', '-1');
|
|
182
184
|
|
|
185
|
+
if (getFlag('GAUD-9398-make-backdrop-inert', false)) {
|
|
186
|
+
if (child.hasAttribute('inert')) {
|
|
187
|
+
child.setAttribute(BACKDROP_INERT, '');
|
|
188
|
+
}
|
|
189
|
+
child.setAttribute('inert', '');
|
|
190
|
+
}
|
|
191
|
+
|
|
183
192
|
child.setAttribute(BACKDROP_HIDDEN, BACKDROP_HIDDEN);
|
|
184
193
|
hiddenElements.push(child);
|
|
185
194
|
}
|
|
@@ -213,6 +222,13 @@ function showAccessible(elems) {
|
|
|
213
222
|
} else {
|
|
214
223
|
elem.removeAttribute('tabindex');
|
|
215
224
|
}
|
|
225
|
+
if (getFlag('GAUD-9398-make-backdrop-inert', false)) {
|
|
226
|
+
if (elem.hasAttribute(BACKDROP_INERT)) {
|
|
227
|
+
elem.removeAttribute(BACKDROP_INERT);
|
|
228
|
+
} else {
|
|
229
|
+
elem.removeAttribute('inert');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
216
232
|
elem.removeAttribute(BACKDROP_HIDDEN);
|
|
217
233
|
}
|
|
218
234
|
}
|
|
@@ -360,7 +360,7 @@ Use the Copy button to enable users to copy a text value to the clipboard. The `
|
|
|
360
360
|
|--|--|--|
|
|
361
361
|
| `disabled` | Boolean | Disables the button |
|
|
362
362
|
| `description` | String | A description to be added to the button for accessibility when text on button does not provide enough context |
|
|
363
|
-
| `
|
|
363
|
+
| `slim` | Boolean | Makes the button slimmer |
|
|
364
364
|
| `text` | String | Label text for the button |
|
|
365
365
|
<!-- docs: end hidden content -->
|
|
366
366
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { findComposedAncestor, getComposedParent, isComposedAncestor } from '../../helpers/dom.js';
|
|
1
|
+
import { addResizeNoopEventListener, findComposedAncestor, getComposedParent, isComposedAncestor, removeResizeNoopEventListener } from '../../helpers/dom.js';
|
|
2
2
|
import { getNextFocusable, getPreviousFocusable } from '../../helpers/focus.js';
|
|
3
3
|
import { css } from 'lit';
|
|
4
|
+
import { getFlag } from '../../helpers/flags.js';
|
|
5
|
+
|
|
6
|
+
const ignoreNoopResizeEventsFlag = getFlag('GAUD-9520-ignore-no-op-resize-events', true);
|
|
4
7
|
|
|
5
8
|
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
6
9
|
const __nativeFocus = document.createElement('div').focus;
|
|
@@ -141,7 +144,11 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
|
|
|
141
144
|
this.addEventListener('focus', this.__focusCapture, true);
|
|
142
145
|
this.addEventListener('focusout', this.__focusOutCapture, true);
|
|
143
146
|
this.__onWindowResize = this.__onWindowResize.bind(this);
|
|
144
|
-
|
|
147
|
+
if (ignoreNoopResizeEventsFlag) {
|
|
148
|
+
addResizeNoopEventListener(this.__onWindowResize);
|
|
149
|
+
} else {
|
|
150
|
+
window.addEventListener('resize', this.__onWindowResize);
|
|
151
|
+
}
|
|
145
152
|
}
|
|
146
153
|
});
|
|
147
154
|
}
|
|
@@ -151,7 +158,12 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
|
|
|
151
158
|
|
|
152
159
|
this.removeEventListener('focus', this.__focusCapture);
|
|
153
160
|
this.removeEventListener('focusout', this.__focusOutCapture);
|
|
154
|
-
|
|
161
|
+
if (ignoreNoopResizeEventsFlag) {
|
|
162
|
+
removeResizeNoopEventListener(this.__onWindowResize);
|
|
163
|
+
} else {
|
|
164
|
+
window.removeEventListener('resize', this.__onWindowResize);
|
|
165
|
+
}
|
|
166
|
+
|
|
155
167
|
if (this.__intersectionObserver) {
|
|
156
168
|
this.__intersectionObserver.disconnect();
|
|
157
169
|
this.__isAutoSized = false;
|
|
@@ -58,7 +58,19 @@
|
|
|
58
58
|
<d2l-demo-snippet>
|
|
59
59
|
<template>
|
|
60
60
|
<d2l-input-checkbox label="Label for checkbox">
|
|
61
|
-
<div slot="supporting"
|
|
61
|
+
<div slot="supporting">
|
|
62
|
+
Additional content can go here and will<br>
|
|
63
|
+
also line up nicely with the checkbox.
|
|
64
|
+
</div>
|
|
65
|
+
</d2l-input-checkbox>
|
|
66
|
+
</template>
|
|
67
|
+
</d2l-demo-snippet>
|
|
68
|
+
|
|
69
|
+
<h2>Checkbox with label and supporting content with progressive disclosure</h2>
|
|
70
|
+
<d2l-demo-snippet>
|
|
71
|
+
<template>
|
|
72
|
+
<d2l-input-checkbox label="Toggle content with checkbox" supporting-hidden-when-unchecked>
|
|
73
|
+
<div slot="supporting">
|
|
62
74
|
Additional content can go here and will<br>
|
|
63
75
|
also line up nicely with the checkbox.
|
|
64
76
|
</div>
|
|
@@ -88,6 +88,7 @@ When provided with a `name`, the checkbox will participate in forms if it is `ch
|
|
|
88
88
|
| `label-hidden` | Boolean | Hides the label visually (moves it to the input's `aria-label` attribute) |
|
|
89
89
|
| `name` | String | Name of the form control. Submitted with the form as part of a name/value pair. |
|
|
90
90
|
| `not-tabbable` | Boolean | Sets `tabindex="-1"` on the checkbox. Note that an alternative method of focusing is necessary to implement if using this property. |
|
|
91
|
+
| `supporting-hidden-when-unchecked` | Boolean | Hides the supporting slot when unchecked. |
|
|
91
92
|
| `value` | String | Value of the input |
|
|
92
93
|
|
|
93
94
|
### Events
|
|
@@ -176,6 +176,11 @@ class InputCheckbox extends FormElementMixin(InputInlineHelpMixin(FocusMixin(Ske
|
|
|
176
176
|
* @type {boolean}
|
|
177
177
|
*/
|
|
178
178
|
notTabbable: { type: Boolean, attribute: 'not-tabbable' },
|
|
179
|
+
/**
|
|
180
|
+
* Hides the supporting slot when unchecked
|
|
181
|
+
* @type {boolean}
|
|
182
|
+
*/
|
|
183
|
+
supportingHiddenWhenUnchecked: { type: Boolean, attribute: 'supporting-hidden-when-unchecked', reflect: true },
|
|
179
184
|
/**
|
|
180
185
|
* Value of the input
|
|
181
186
|
* @type {string}
|
|
@@ -254,6 +259,7 @@ class InputCheckbox extends FormElementMixin(InputInlineHelpMixin(FocusMixin(Ske
|
|
|
254
259
|
this.labelHidden = false;
|
|
255
260
|
this.name = '';
|
|
256
261
|
this.notTabbable = false;
|
|
262
|
+
this.supportingHiddenWhenUnchecked = false;
|
|
257
263
|
this.value = 'on';
|
|
258
264
|
this._hasSupporting = false;
|
|
259
265
|
this._isHovered = false;
|
|
@@ -267,7 +273,7 @@ class InputCheckbox extends FormElementMixin(InputInlineHelpMixin(FocusMixin(Ske
|
|
|
267
273
|
const tabindex = this.notTabbable ? -1 : undefined;
|
|
268
274
|
const supportingClasses = {
|
|
269
275
|
'd2l-input-checkbox-supporting': true,
|
|
270
|
-
'd2l-input-checkbox-supporting-visible': this._hasSupporting
|
|
276
|
+
'd2l-input-checkbox-supporting-visible': this._hasSupporting && (this.checked || !this.supportingHiddenWhenUnchecked)
|
|
271
277
|
};
|
|
272
278
|
const textClasses = {
|
|
273
279
|
'd2l-input-checkbox-text': true,
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import '../backdrop/backdrop.js';
|
|
2
2
|
import '../colors/colors.js';
|
|
3
3
|
import '../focus-trap/focus-trap.js';
|
|
4
|
+
import { addResizeNoopEventListener, getComposedParent, isComposedAncestor, removeResizeNoopEventListener } from '../../helpers/dom.js';
|
|
4
5
|
import { clearDismissible, setDismissible } from '../../helpers/dismissible.js';
|
|
5
6
|
import { css, html, nothing } from 'lit';
|
|
6
7
|
import { getComposedActiveElement, getFirstFocusableDescendant, getPreviousFocusableAncestor } from '../../helpers/focus.js';
|
|
7
|
-
import { getComposedParent, isComposedAncestor } from '../../helpers/dom.js';
|
|
8
8
|
import { _offscreenStyleDeclarations } from '../offscreen/offscreen.js';
|
|
9
9
|
import { classMap } from 'lit/directives/class-map.js';
|
|
10
|
+
import { getFlag } from '../../helpers/flags.js';
|
|
10
11
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
11
12
|
import { tryGetIfrauBackdropService } from '../../helpers/ifrauBackdropService.js';
|
|
12
13
|
|
|
14
|
+
const ignoreNoopResizeEventsFlag = getFlag('GAUD-9520-ignore-no-op-resize-events', true);
|
|
15
|
+
|
|
13
16
|
export const positionLocations = Object.freeze({
|
|
14
17
|
blockEnd: 'block-end',
|
|
15
18
|
blockStart: 'block-start',
|
|
@@ -612,7 +615,11 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
|
612
615
|
this.#removeRepositionHandlers();
|
|
613
616
|
this.#ancestorMutations = new Map();
|
|
614
617
|
|
|
615
|
-
|
|
618
|
+
if (ignoreNoopResizeEventsFlag) {
|
|
619
|
+
addResizeNoopEventListener(this.#handleResizeBound);
|
|
620
|
+
} else {
|
|
621
|
+
window.addEventListener('resize', this.#handleResizeBound);
|
|
622
|
+
}
|
|
616
623
|
|
|
617
624
|
this._ancestorMutationObserver ??= new MutationObserver(this.#handleAncestorMutationBound);
|
|
618
625
|
const mutationConfig = { attributes: true, childList: true, subtree: true };
|
|
@@ -1186,7 +1193,11 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
|
1186
1193
|
});
|
|
1187
1194
|
this._scrollablesObserved = null;
|
|
1188
1195
|
this._ancestorMutationObserver?.disconnect();
|
|
1189
|
-
|
|
1196
|
+
if (ignoreNoopResizeEventsFlag) {
|
|
1197
|
+
removeResizeNoopEventListener(this.#handleResizeBound);
|
|
1198
|
+
} else {
|
|
1199
|
+
window.removeEventListener('resize', this.#handleResizeBound);
|
|
1200
|
+
}
|
|
1190
1201
|
}
|
|
1191
1202
|
|
|
1192
1203
|
#reposition() {
|
package/custom-elements.json
CHANGED
|
@@ -5407,6 +5407,12 @@
|
|
|
5407
5407
|
"type": "boolean",
|
|
5408
5408
|
"default": "false"
|
|
5409
5409
|
},
|
|
5410
|
+
{
|
|
5411
|
+
"name": "supporting-hidden-when-unchecked",
|
|
5412
|
+
"description": "Hides the supporting slot when unchecked",
|
|
5413
|
+
"type": "boolean",
|
|
5414
|
+
"default": "false"
|
|
5415
|
+
},
|
|
5410
5416
|
{
|
|
5411
5417
|
"name": "value",
|
|
5412
5418
|
"description": "Value of the input",
|
|
@@ -5480,6 +5486,13 @@
|
|
|
5480
5486
|
"type": "boolean",
|
|
5481
5487
|
"default": "false"
|
|
5482
5488
|
},
|
|
5489
|
+
{
|
|
5490
|
+
"name": "supportingHiddenWhenUnchecked",
|
|
5491
|
+
"attribute": "supporting-hidden-when-unchecked",
|
|
5492
|
+
"description": "Hides the supporting slot when unchecked",
|
|
5493
|
+
"type": "boolean",
|
|
5494
|
+
"default": "false"
|
|
5495
|
+
},
|
|
5483
5496
|
{
|
|
5484
5497
|
"name": "value",
|
|
5485
5498
|
"attribute": "value",
|
package/helpers/dom.js
CHANGED
|
@@ -263,3 +263,41 @@ export function querySelectorComposed(node, selector) {
|
|
|
263
263
|
|
|
264
264
|
return null;
|
|
265
265
|
}
|
|
266
|
+
|
|
267
|
+
const resizeNoopEventListener = new Set();
|
|
268
|
+
const resizeNoopRect = {};
|
|
269
|
+
|
|
270
|
+
if (globalThis.addEventListener) {
|
|
271
|
+
globalThis.addEventListener('resize', e => {
|
|
272
|
+
if (resizeNoopEventListener.size === 0) return;
|
|
273
|
+
|
|
274
|
+
const frameElement = e.target.frameElement;
|
|
275
|
+
if (frameElement?.classList.contains('d2l-iframe-fit-user-content')) {
|
|
276
|
+
// ignore if the iframe is spamming no-op resize events
|
|
277
|
+
if (resizeNoopRect.height === frameElement.scrollHeight && resizeNoopRect.width === frameElement.scrollWidth) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
resizeNoopRect.height = frameElement.scrollHeight;
|
|
281
|
+
resizeNoopRect.width = frameElement.scrollWidth;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
resizeNoopEventListener.forEach(listener => {
|
|
285
|
+
listener(e);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function addResizeNoopEventListener(listener) {
|
|
291
|
+
resizeNoopEventListener.add(listener);
|
|
292
|
+
resizeNoopRect.height = null;
|
|
293
|
+
resizeNoopRect.width = null;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export function removeResizeNoopEventListener(listener) {
|
|
297
|
+
resizeNoopEventListener.delete(listener);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// testing only
|
|
301
|
+
export function clearResizeNoopEventListeners() {
|
|
302
|
+
resizeNoopEventListener.clear();
|
|
303
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.226.0",
|
|
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",
|