@brightspace-ui/core 1.239.0 → 1.240.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/filter/README.md +2 -2
- package/components/form/form-element-mixin.js +14 -0
- package/components/form/form-mixin.js +9 -1
- package/components/hierarchical-view/hierarchical-view-mixin.js +1 -0
- package/components/inputs/input-date-time-range-to.js +6 -10
- package/components/inputs/input-date.js +6 -0
- package/components/inputs/input-time.js +5 -0
- package/components/list/list-item-checkbox-mixin.js +0 -1
- package/components/overflow-group/overflow-group.js +8 -3
- package/components/scroll-wrapper/README.md +7 -0
- package/components/scroll-wrapper/scroll-wrapper.js +10 -4
- package/components/tabs/tabs.js +5 -0
- package/lang/localize-core-element.js +5 -68
- package/lang/{zh.js → zh-cn.js} +0 -0
- package/package.json +1 -1
- package/templates/primary-secondary/primary-secondary.js +1 -0
|
@@ -208,9 +208,9 @@ This component is built to be used alongside the [d2l-filter-dimension-set](#fil
|
|
|
208
208
|
|
|
209
209
|
**Coming Soon!**
|
|
210
210
|
|
|
211
|
-
##
|
|
211
|
+
## Tags for Applied Filters [d2l-filter-tags]
|
|
212
212
|
|
|
213
|
-
**
|
|
213
|
+
**This is in progress now! Stable API expected by May.**
|
|
214
214
|
|
|
215
215
|
<!-- docs: start hidden content -->
|
|
216
216
|
## Future Improvements
|
|
@@ -118,6 +118,10 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
118
118
|
this._validationCustomConnected = this._validationCustomConnected.bind(this);
|
|
119
119
|
this._onFormElementErrorsChange = this._onFormElementErrorsChange.bind(this);
|
|
120
120
|
|
|
121
|
+
this._firstUpdateResolve = null;
|
|
122
|
+
this._firstUpdatePromise = new Promise((resolve) => {
|
|
123
|
+
this._firstUpdateResolve = resolve;
|
|
124
|
+
});
|
|
121
125
|
this._validationCustoms = new Set();
|
|
122
126
|
this._validity = new FormElementValidityState({});
|
|
123
127
|
/** @ignore */
|
|
@@ -168,6 +172,11 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
168
172
|
this.shadowRoot.removeEventListener('d2l-form-element-errors-change', this._onFormElementErrorsChange);
|
|
169
173
|
}
|
|
170
174
|
|
|
175
|
+
firstUpdated(changedProperties) {
|
|
176
|
+
super.firstUpdated(changedProperties);
|
|
177
|
+
this._firstUpdateResolve();
|
|
178
|
+
}
|
|
179
|
+
|
|
171
180
|
updated(changedProperties) {
|
|
172
181
|
if (changedProperties.has('_errors') || changedProperties.has('childErrors')) {
|
|
173
182
|
let errors = this._errors;
|
|
@@ -195,6 +204,11 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
195
204
|
if (this.noValidate) {
|
|
196
205
|
return [];
|
|
197
206
|
}
|
|
207
|
+
|
|
208
|
+
// validation can be requested before first update, which can cause issues
|
|
209
|
+
// if validation logic depends on rendered DOM
|
|
210
|
+
await this._firstUpdatePromise;
|
|
211
|
+
|
|
198
212
|
const customs = [...this._validationCustoms].filter(custom => custom.forElement === this || !isCustomFormElement(custom.forElement));
|
|
199
213
|
const results = await Promise.all(customs.map(custom => custom.validate()));
|
|
200
214
|
const errors = customs.map(custom => custom.failureText).filter((_, i) => !results[i]);
|
|
@@ -26,9 +26,13 @@ export const FormMixin = superclass => class extends LocalizeCoreElement(supercl
|
|
|
26
26
|
this._onNativeSubmit = this._onNativeSubmit.bind(this);
|
|
27
27
|
|
|
28
28
|
this.trackChanges = false;
|
|
29
|
+
this._errors = new Map();
|
|
30
|
+
this._firstUpdateResolve = null;
|
|
31
|
+
this._firstUpdatePromise = new Promise((resolve) => {
|
|
32
|
+
this._firstUpdateResolve = resolve;
|
|
33
|
+
});
|
|
29
34
|
this._tooltips = new Map();
|
|
30
35
|
this._validationCustoms = new Set();
|
|
31
|
-
this._errors = new Map();
|
|
32
36
|
|
|
33
37
|
this.addEventListener('d2l-form-errors-change', this._onErrorsChange);
|
|
34
38
|
this.addEventListener('d2l-form-element-errors-change', this._onErrorsChange);
|
|
@@ -50,6 +54,7 @@ export const FormMixin = superclass => class extends LocalizeCoreElement(supercl
|
|
|
50
54
|
this.addEventListener('change', this._onFormElementChange);
|
|
51
55
|
this.addEventListener('input', this._onFormElementChange);
|
|
52
56
|
this.addEventListener('focusout', this._onFormElementChange);
|
|
57
|
+
this._firstUpdateResolve();
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -150,6 +155,9 @@ export const FormMixin = superclass => class extends LocalizeCoreElement(supercl
|
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
async _validateFormElement(ele, showNewErrors) {
|
|
158
|
+
// if validation occurs before we've rendered,
|
|
159
|
+
// localization may not have loaded yet
|
|
160
|
+
await this._firstUpdatePromise;
|
|
153
161
|
ele.id = ele.id || getUniqueId();
|
|
154
162
|
if (isCustomFormElement(ele)) {
|
|
155
163
|
return ele.validate(showNewErrors);
|
|
@@ -149,6 +149,7 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
|
|
|
149
149
|
this.__intersectionObserver.disconnect();
|
|
150
150
|
this.__isAutoSized = false;
|
|
151
151
|
}
|
|
152
|
+
if (this.__resizeObserver) this.__resizeObserver.disconnect();
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
firstUpdated(changedProperties) {
|
|
@@ -116,16 +116,9 @@ class InputDateTimeRangeTo extends SkeletonMixin(LocalizeCoreElement(LitElement)
|
|
|
116
116
|
|
|
117
117
|
disconnectedCallback() {
|
|
118
118
|
super.disconnectedCallback();
|
|
119
|
-
|
|
120
119
|
this._disconnectObservers();
|
|
121
120
|
}
|
|
122
121
|
|
|
123
|
-
firstUpdated(changedProperties) {
|
|
124
|
-
super.firstUpdated(changedProperties);
|
|
125
|
-
|
|
126
|
-
this._startObserving();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
122
|
render() {
|
|
130
123
|
const containerClassMap = {
|
|
131
124
|
'd2l-input-date-time-range-to-container': true,
|
|
@@ -181,9 +174,12 @@ class InputDateTimeRangeTo extends SkeletonMixin(LocalizeCoreElement(LitElement)
|
|
|
181
174
|
_startObserving() {
|
|
182
175
|
if (!this.shadowRoot || !this._parentNode) return;
|
|
183
176
|
|
|
177
|
+
const container = this.shadowRoot.querySelector('.d2l-input-date-time-range-to-container');
|
|
184
178
|
const leftElem = this.shadowRoot.querySelector('.d2l-input-date-time-range-start-container');
|
|
179
|
+
let leftElemHeight = 0;
|
|
180
|
+
|
|
185
181
|
this._leftElemResizeObserver = this._leftElemResizeObserver || new ResizeObserver(() => {
|
|
186
|
-
|
|
182
|
+
leftElemHeight = Math.ceil(parseFloat(getComputedStyle(leftElem).getPropertyValue('height')));
|
|
187
183
|
});
|
|
188
184
|
this._leftElemResizeObserver.disconnect();
|
|
189
185
|
this._leftElemResizeObserver.observe(leftElem);
|
|
@@ -191,8 +187,8 @@ class InputDateTimeRangeTo extends SkeletonMixin(LocalizeCoreElement(LitElement)
|
|
|
191
187
|
this._parentElemResizeObserver = this._parentElemResizeObserver || new ResizeObserver(async() => {
|
|
192
188
|
this._blockDisplay = false;
|
|
193
189
|
await this.updateComplete;
|
|
194
|
-
const height = Math.ceil(parseFloat(getComputedStyle(
|
|
195
|
-
if (height >= (
|
|
190
|
+
const height = Math.ceil(parseFloat(getComputedStyle(container).getPropertyValue('height')));
|
|
191
|
+
if (height >= (leftElemHeight * 2)) this._blockDisplay = true; // switch to _blockDisplay styles if content has wrapped (needed for "to" to occupy its own line)
|
|
196
192
|
else this._blockDisplay = false;
|
|
197
193
|
});
|
|
198
194
|
this._parentElemResizeObserver.disconnect();
|
|
@@ -186,6 +186,12 @@ class InputDate extends FocusMixin(LabelledMixin(SkeletonMixin(FormElementMixin(
|
|
|
186
186
|
return super.validationMessage;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
disconnectedCallback() {
|
|
190
|
+
super.disconnectedCallback();
|
|
191
|
+
if (this._hiddenContentResizeObserver) this._hiddenContentResizeObserver.disconnect();
|
|
192
|
+
if (this._hiddenCalendarResizeObserver) this._hiddenCalendarResizeObserver.disconnect();
|
|
193
|
+
}
|
|
194
|
+
|
|
189
195
|
async firstUpdated(changedProperties) {
|
|
190
196
|
super.firstUpdated(changedProperties);
|
|
191
197
|
|
|
@@ -254,6 +254,11 @@ class InputTime extends FocusMixin(LabelledMixin(SkeletonMixin(FormElementMixin(
|
|
|
254
254
|
this.requestUpdate('value', oldValue);
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
disconnectedCallback() {
|
|
258
|
+
super.disconnectedCallback();
|
|
259
|
+
if (this._hiddenContentResizeObserver) this._hiddenContentResizeObserver.disconnect();
|
|
260
|
+
}
|
|
261
|
+
|
|
257
262
|
async firstUpdated(changedProperties) {
|
|
258
263
|
super.firstUpdated(changedProperties);
|
|
259
264
|
|
|
@@ -97,7 +97,6 @@ export const ListItemCheckboxMixin = superclass => class extends SkeletonMixin(L
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
setSelected(selected, suppressEvent = false) {
|
|
100
|
-
//if (this.selected === selected) return;
|
|
101
100
|
if (this.selected === selected || (this.selected === undefined && !selected)) return;
|
|
102
101
|
this.selected = selected;
|
|
103
102
|
if (!suppressEvent) this._dispatchSelected(selected);
|
|
@@ -249,10 +249,15 @@ class OverflowGroup extends RtlMixin(LocalizeCoreElement(LitElement)) {
|
|
|
249
249
|
this.openerStyle = OPENER_STYLE.DEFAULT;
|
|
250
250
|
this.openerType = OPENER_TYPE.DEFAULT;
|
|
251
251
|
this._mini = this.openerType === OPENER_TYPE.ICON;
|
|
252
|
-
|
|
252
|
+
this._resizeObserver = null;
|
|
253
253
|
this._slotItems = [];
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
disconnectedCallback() {
|
|
257
|
+
super.disconnectedCallback();
|
|
258
|
+
if (this._resizeObserver) this._resizeObserver.disconnect();
|
|
259
|
+
}
|
|
260
|
+
|
|
256
261
|
async firstUpdated() {
|
|
257
262
|
super.firstUpdated();
|
|
258
263
|
|
|
@@ -261,8 +266,8 @@ class OverflowGroup extends RtlMixin(LocalizeCoreElement(LitElement)) {
|
|
|
261
266
|
|
|
262
267
|
this._container = this.shadowRoot.querySelector('.d2l-overflow-group-container');
|
|
263
268
|
|
|
264
|
-
|
|
265
|
-
|
|
269
|
+
this._resizeObserver = new ResizeObserver(this._throttledResize);
|
|
270
|
+
this._resizeObserver.observe(this._container);
|
|
266
271
|
}
|
|
267
272
|
|
|
268
273
|
render() {
|
|
@@ -37,4 +37,11 @@ The `d2l-scroll-wrapper` element can be used to wrap content which may overflow
|
|
|
37
37
|
| Property | Type | Description |
|
|
38
38
|
|---|---|---|
|
|
39
39
|
| `hide-actions` | Boolean, default: `false` | Whether to hide left/right scroll buttons |
|
|
40
|
+
|
|
41
|
+
### Variables
|
|
42
|
+
|
|
43
|
+
| Variable | Type | Description |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `--d2l-scroll-wrapper-overflow-y` | [Any valid overflow-y setting](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-y), defaults to `visible` | Set the `overflow-y` property of the inner scroll wrapper |
|
|
46
|
+
|
|
40
47
|
<!-- docs: end hidden content -->
|
|
@@ -53,11 +53,11 @@ class ScrollWrapper extends FocusVisiblePolyfillMixin(RtlMixin(LitElement)) {
|
|
|
53
53
|
:host([hidden]) {
|
|
54
54
|
display: none;
|
|
55
55
|
}
|
|
56
|
-
|
|
57
56
|
.d2l-scroll-wrapper-container {
|
|
58
57
|
box-sizing: border-box;
|
|
59
58
|
outline: none;
|
|
60
59
|
overflow-x: auto;
|
|
60
|
+
overflow-y: var(--d2l-scroll-wrapper-overflow-y, visible);
|
|
61
61
|
}
|
|
62
62
|
.d2l-scroll-wrapper-container.focus-visible {
|
|
63
63
|
box-shadow: 0 0 0 2px #ffffff, 0 0 0 4px var(--d2l-color-celestine), 0 2px 12px 0 rgba(0, 0, 0, 0.15);
|
|
@@ -143,14 +143,21 @@ class ScrollWrapper extends FocusVisiblePolyfillMixin(RtlMixin(LitElement)) {
|
|
|
143
143
|
this.hideActions = false;
|
|
144
144
|
this._container = null;
|
|
145
145
|
this._hScrollbar = true;
|
|
146
|
+
this._resizeObserver = null;
|
|
146
147
|
this._scrollbarLeft = false;
|
|
147
148
|
this._scrollbarRight = false;
|
|
148
149
|
}
|
|
149
150
|
|
|
151
|
+
disconnectedCallback() {
|
|
152
|
+
super.disconnectedCallback();
|
|
153
|
+
if (this._resizeObserver) this._resizeObserver.disconnect();
|
|
154
|
+
}
|
|
155
|
+
|
|
150
156
|
firstUpdated(changedProperties) {
|
|
151
157
|
super.firstUpdated(changedProperties);
|
|
152
158
|
this._container = this.shadowRoot.querySelector('.d2l-scroll-wrapper-container');
|
|
153
|
-
new ResizeObserver(() => requestAnimationFrame(() => this.checkScrollbar()))
|
|
159
|
+
this._resizeObserver = new ResizeObserver(() => requestAnimationFrame(() => this.checkScrollbar()));
|
|
160
|
+
this._resizeObserver.observe(this._container);
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
render() {
|
|
@@ -172,8 +179,7 @@ class ScrollWrapper extends FocusVisiblePolyfillMixin(RtlMixin(LitElement)) {
|
|
|
172
179
|
|
|
173
180
|
checkScrollbar() {
|
|
174
181
|
if (!this._container) return;
|
|
175
|
-
|
|
176
|
-
this._hScrollbar = (hScrollbar > 0);
|
|
182
|
+
this._hScrollbar = this._container.offsetWidth !== this._container.scrollWidth;
|
|
177
183
|
this._checkScrollThresholds();
|
|
178
184
|
}
|
|
179
185
|
|
package/components/tabs/tabs.js
CHANGED
|
@@ -266,6 +266,11 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(RtlMixin(FocusVisiblePolyf
|
|
|
266
266
|
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
+
disconnectedCallback() {
|
|
270
|
+
super.disconnectedCallback();
|
|
271
|
+
if (this._resizeObserver) this._resizeObserver.disconnect();
|
|
272
|
+
}
|
|
273
|
+
|
|
269
274
|
firstUpdated(changedProperties) {
|
|
270
275
|
super.firstUpdated(changedProperties);
|
|
271
276
|
|
|
@@ -1,74 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LocalizeDynamicMixin } from '../mixins/localize-dynamic-mixin.js';
|
|
2
2
|
|
|
3
|
-
export const LocalizeCoreElement = superclass => class extends
|
|
3
|
+
export const LocalizeCoreElement = superclass => class extends LocalizeDynamicMixin(superclass) {
|
|
4
4
|
|
|
5
|
-
static
|
|
6
|
-
let translations;
|
|
7
|
-
for await (const lang of langs) {
|
|
8
|
-
switch (lang) {
|
|
9
|
-
case 'ar':
|
|
10
|
-
translations = await import('./ar.js');
|
|
11
|
-
break;
|
|
12
|
-
case 'cy':
|
|
13
|
-
translations = await import('./cy.js');
|
|
14
|
-
break;
|
|
15
|
-
case 'da':
|
|
16
|
-
translations = await import('./da.js');
|
|
17
|
-
break;
|
|
18
|
-
case 'de':
|
|
19
|
-
translations = await import('./de.js');
|
|
20
|
-
break;
|
|
21
|
-
case 'en':
|
|
22
|
-
translations = await import('./en.js');
|
|
23
|
-
break;
|
|
24
|
-
case 'es-es':
|
|
25
|
-
translations = await import('./es-es.js');
|
|
26
|
-
break;
|
|
27
|
-
case 'es':
|
|
28
|
-
translations = await import('./es.js');
|
|
29
|
-
break;
|
|
30
|
-
case 'fr-fr':
|
|
31
|
-
translations = await import('./fr-fr.js');
|
|
32
|
-
break;
|
|
33
|
-
case 'fr':
|
|
34
|
-
translations = await import('./fr.js');
|
|
35
|
-
break;
|
|
36
|
-
case 'ja':
|
|
37
|
-
translations = await import('./ja.js');
|
|
38
|
-
break;
|
|
39
|
-
case 'ko':
|
|
40
|
-
translations = await import('./ko.js');
|
|
41
|
-
break;
|
|
42
|
-
case 'nl':
|
|
43
|
-
translations = await import('./nl.js');
|
|
44
|
-
break;
|
|
45
|
-
case 'pt':
|
|
46
|
-
translations = await import('./pt.js');
|
|
47
|
-
break;
|
|
48
|
-
case 'sv':
|
|
49
|
-
translations = await import('./sv.js');
|
|
50
|
-
break;
|
|
51
|
-
case 'tr':
|
|
52
|
-
translations = await import('./tr.js');
|
|
53
|
-
break;
|
|
54
|
-
case 'zh-tw':
|
|
55
|
-
translations = await import('./zh-tw.js');
|
|
56
|
-
break;
|
|
57
|
-
case 'zh':
|
|
58
|
-
translations = await import('./zh.js');
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
if (translations && translations.default) {
|
|
62
|
-
return {
|
|
63
|
-
language: lang,
|
|
64
|
-
resources: translations.default
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
translations = await import('./en.js');
|
|
5
|
+
static get localizeConfig() {
|
|
69
6
|
return {
|
|
70
|
-
|
|
71
|
-
resources: translations.default
|
|
7
|
+
importFunc: async lang => (await import(`./${lang}.js`)).default
|
|
72
8
|
};
|
|
73
9
|
}
|
|
10
|
+
|
|
74
11
|
};
|
package/lang/{zh.js → zh-cn.js}
RENAMED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.240.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",
|
|
@@ -903,6 +903,7 @@ class TemplatePrimarySecondary extends FocusVisiblePolyfillMixin(RtlMixin(Locali
|
|
|
903
903
|
resizer.disconnect();
|
|
904
904
|
}
|
|
905
905
|
this._hasConnectedResizers = false;
|
|
906
|
+
if (this._resizeObserver) this._resizeObserver.disconnect();
|
|
906
907
|
}
|
|
907
908
|
|
|
908
909
|
firstUpdated(changedProperties) {
|