@brightspace-ui/core 1.239.1 → 1.241.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.
Files changed (59) hide show
  1. package/components/alert/alert.js +1 -1
  2. package/components/breadcrumbs/breadcrumbs.js +1 -1
  3. package/components/calendar/calendar.js +1 -1
  4. package/components/count-badge/count-badge-mixin.js +1 -1
  5. package/components/dialog/dialog-fullscreen.js +1 -1
  6. package/components/dialog/dialog.js +1 -1
  7. package/components/dropdown/dropdown-content-mixin.js +1 -1
  8. package/components/filter/README.md +2 -2
  9. package/components/filter/filter.js +1 -1
  10. package/components/form/form-element-mixin.js +15 -1
  11. package/components/form/form-errory-summary.js +1 -1
  12. package/components/form/form-mixin.js +10 -2
  13. package/components/hierarchical-view/hierarchical-view-mixin.js +1 -0
  14. package/components/inputs/input-date-range.js +1 -1
  15. package/components/inputs/input-date-time-range-to.js +7 -11
  16. package/components/inputs/input-date-time-range.js +1 -1
  17. package/components/inputs/input-date-time.js +1 -1
  18. package/components/inputs/input-date.js +7 -1
  19. package/components/inputs/input-number.js +1 -1
  20. package/components/inputs/input-percent.js +1 -1
  21. package/components/inputs/input-search.js +1 -1
  22. package/components/inputs/input-time-range.js +1 -1
  23. package/components/inputs/input-time.js +5 -0
  24. package/components/list/list-header.js +1 -1
  25. package/components/list/list-item-checkbox-mixin.js +0 -1
  26. package/components/list/list-item-drag-handle.js +1 -1
  27. package/components/list/list-item-mixin.js +1 -1
  28. package/components/menu/menu-item-return.js +1 -1
  29. package/components/meter/meter-mixin.js +1 -1
  30. package/components/more-less/more-less.js +1 -1
  31. package/components/overflow-group/overflow-group.js +9 -4
  32. package/components/scroll-wrapper/scroll-wrapper.js +8 -1
  33. package/components/selection/selection-action-dropdown.js +1 -1
  34. package/components/selection/selection-action.js +1 -1
  35. package/components/selection/selection-select-all-pages.js +1 -1
  36. package/components/selection/selection-select-all.js +1 -1
  37. package/components/selection/selection-summary.js +1 -1
  38. package/components/switch/switch-visibility.js +1 -1
  39. package/components/tabs/tabs.js +6 -1
  40. package/helpers/localize-core-element.js +11 -0
  41. package/lang/da.js +2 -2
  42. package/lang/de.js +2 -2
  43. package/lang/en.js +2 -2
  44. package/lang/es-es.js +2 -2
  45. package/lang/es.js +2 -2
  46. package/lang/fr-fr.js +2 -2
  47. package/lang/fr.js +2 -2
  48. package/lang/hi.js +2 -2
  49. package/lang/ja.js +3 -3
  50. package/lang/ko.js +3 -3
  51. package/lang/nl.js +2 -2
  52. package/lang/pt.js +2 -2
  53. package/lang/sv.js +2 -2
  54. package/lang/tr.js +2 -2
  55. package/lang/{zh.js → zh-cn.js} +3 -3
  56. package/lang/zh-tw.js +3 -3
  57. package/package.json +5 -3
  58. package/templates/primary-secondary/primary-secondary.js +2 -1
  59. package/lang/localize-core-element.js +0 -74
@@ -4,7 +4,7 @@ import '../colors/colors.js';
4
4
  import { bodyCompactStyles, bodyStandardStyles } from '../typography/styles.js';
5
5
  import { css, html, LitElement } from 'lit-element/lit-element.js';
6
6
  import { classMap } from 'lit-html/directives/class-map.js';
7
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
7
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
8
8
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
9
9
 
10
10
  /**
@@ -1,6 +1,6 @@
1
1
  import './breadcrumb.js';
2
2
  import { css, html, LitElement } from 'lit-element/lit-element.js';
3
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
3
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
4
4
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
5
5
 
6
6
  /**
@@ -8,7 +8,7 @@ import { findComposedAncestor } from '../../helpers/dom.js';
8
8
  import { formatDate } from '@brightspace-ui/intl/lib/dateTime.js';
9
9
  import { getUniqueId } from '../../helpers/uniqueId.js';
10
10
  import { ifDefined } from 'lit-html/directives/if-defined.js';
11
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
11
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
12
12
  import { offscreenStyles } from '../offscreen/offscreen.js';
13
13
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
14
14
 
@@ -3,7 +3,7 @@ import '../tooltip/tooltip.js';
3
3
  import { css, html } from 'lit-element/lit-element.js';
4
4
  import { formatNumber } from '@brightspace-ui/intl/lib/number.js';
5
5
  import { getUniqueId } from '../../helpers/uniqueId.js';
6
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
6
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
7
7
  import { offscreenStyles } from '../offscreen/offscreen.js';
8
8
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
9
9
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
@@ -7,7 +7,7 @@ import { classMap } from 'lit-html/directives/class-map.js';
7
7
  import { DialogMixin } from './dialog-mixin.js';
8
8
  import { dialogStyles } from './dialog-styles.js';
9
9
  import { getUniqueId } from '../../helpers/uniqueId.js';
10
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
10
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
11
11
  import { styleMap } from 'lit-html/directives/style-map.js';
12
12
 
13
13
  const mediaQueryList = window.matchMedia('(max-width: 615px), (max-height: 420px) and (max-width: 900px)');
@@ -9,7 +9,7 @@ import { dialogStyles } from './dialog-styles.js';
9
9
  import { getUniqueId } from '../../helpers/uniqueId.js';
10
10
  import { heading3Styles } from '../typography/styles.js';
11
11
  import { ifDefined } from 'lit-html/directives/if-defined.js';
12
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
12
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
13
13
  import { styleMap } from 'lit-html/directives/style-map.js';
14
14
 
15
15
  const mediaQueryList = window.matchMedia('(max-width: 615px), (max-height: 420px) and (max-width: 900px)');
@@ -6,7 +6,7 @@ import { findComposedAncestor, getBoundingAncestor, isComposedAncestor, isVisibl
6
6
  import { getComposedActiveElement, getFirstFocusableDescendant, getPreviousFocusableAncestor } from '../../helpers/focus.js';
7
7
  import { classMap } from 'lit-html/directives/class-map.js';
8
8
  import { html } from 'lit-element/lit-element.js';
9
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
9
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
10
10
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
11
11
  import { styleMap } from 'lit-html/directives/style-map.js';
12
12
  import { tryGetIfrauBackdropService } from '../../helpers/ifrauBackdropService.js';
@@ -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
- ## Filter Dimension: Tags [d2l-filter-dimension-tags]
211
+ ## Tags for Applied Filters [d2l-filter-tags]
212
212
 
213
- **Coming Soon!**
213
+ **This is in progress now! Stable API expected by May.**
214
214
 
215
215
  <!-- docs: start hidden content -->
216
216
  ## Future Improvements
@@ -21,7 +21,7 @@ import { announce } from '../../helpers/announce.js';
21
21
  import { classMap } from 'lit-html/directives/class-map.js';
22
22
  import { FocusMixin } from '../../mixins/focus-mixin.js';
23
23
  import { ifDefined } from 'lit-html/directives/if-defined.js';
24
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
24
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
25
25
  import { offscreenStyles } from '../offscreen/offscreen.js';
26
26
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
27
27
  import { SubscriberRegistryController } from '../../controllers/subscriber/subscriberControllers.js';
@@ -1,5 +1,5 @@
1
1
  import { isCustomFormElement } from './form-helper.js';
2
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
2
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
3
3
 
4
4
  export class FormElementValidityState {
5
5
 
@@ -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]);
@@ -2,7 +2,7 @@ import '../alert/alert.js';
2
2
  import '../expand-collapse/expand-collapse-content.js';
3
3
  import { css, html, LitElement } from 'lit-element/lit-element.js';
4
4
  import { linkStyles } from '../link/link.js';
5
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
5
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
6
6
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
7
7
 
8
8
  class FormErrorSummary extends LocalizeCoreElement(RtlMixin(LitElement)) {
@@ -4,7 +4,7 @@ import '../link/link.js';
4
4
  import { isCustomFormElement, isNativeFormElement } from './form-helper.js';
5
5
  import { getComposedActiveElement } from '../../helpers/focus.js';
6
6
  import { getUniqueId } from '../../helpers/uniqueId.js';
7
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
7
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
8
8
  import { localizeFormElement } from './form-element-localize-helper.js';
9
9
 
10
10
  export const FormMixin = superclass => class extends LocalizeCoreElement(superclass) {
@@ -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) {
@@ -8,7 +8,7 @@ import { FocusMixin } from '../../mixins/focus-mixin.js';
8
8
  import { FormElementMixin } from '../form/form-element-mixin.js';
9
9
  import { getUniqueId } from '../../helpers/uniqueId.js';
10
10
  import { ifDefined } from 'lit-html/directives/if-defined.js';
11
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
11
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
12
12
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
13
13
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
14
14
 
@@ -2,7 +2,7 @@ import './input-text.js';
2
2
  import { css, html, LitElement } from 'lit-element/lit-element.js';
3
3
  import { bodySmallStyles } from '../typography/styles.js';
4
4
  import { classMap } from 'lit-html/directives/class-map.js';
5
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
5
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
6
6
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
7
7
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
8
8
 
@@ -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
- this._leftElemHeight = Math.ceil(parseFloat(getComputedStyle(leftElem).getPropertyValue('height')));
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(this.shadowRoot.querySelector('.d2l-input-date-time-range-to-container')).getPropertyValue('height')));
195
- if (height >= (this._leftElemHeight * 2)) this._blockDisplay = true; // switch to _blockDisplay styles if content has wrapped (needed for "to" to occupy its own line)
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();
@@ -9,7 +9,7 @@ import { FocusMixin } from '../../mixins/focus-mixin.js';
9
9
  import { FormElementMixin } from '../form/form-element-mixin.js';
10
10
  import { getUniqueId } from '../../helpers/uniqueId.js';
11
11
  import { ifDefined } from 'lit-html/directives/if-defined.js';
12
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
12
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
13
13
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
14
14
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
15
15
 
@@ -20,7 +20,7 @@ import { getDocumentLocaleSettings } from '@brightspace-ui/intl/lib/common.js';
20
20
  import { getUniqueId } from '../../helpers/uniqueId.js';
21
21
  import { ifDefined } from 'lit-html/directives/if-defined.js';
22
22
  import { LabelledMixin } from '../../mixins/labelled-mixin.js';
23
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
23
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
24
24
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
25
25
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
26
26
  import { styleMap } from 'lit-html/directives/style-map.js';
@@ -13,7 +13,7 @@ import { FormElementMixin } from '../form/form-element-mixin.js';
13
13
  import { getUniqueId } from '../../helpers/uniqueId.js';
14
14
  import { ifDefined } from 'lit-html/directives/if-defined.js';
15
15
  import { LabelledMixin } from '../../mixins/labelled-mixin.js';
16
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
16
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
17
17
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
18
18
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
19
19
  import { styleMap } from 'lit-html/directives/style-map.js';
@@ -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
 
@@ -6,7 +6,7 @@ import { FormElementMixin } from '../form/form-element-mixin.js';
6
6
  import { getUniqueId } from '../../helpers/uniqueId.js';
7
7
  import { ifDefined } from 'lit-html/directives/if-defined.js';
8
8
  import { LabelledMixin } from '../../mixins/labelled-mixin.js';
9
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
9
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
10
10
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
11
11
 
12
12
  const HINT_TYPES = {
@@ -4,7 +4,7 @@ import { FocusMixin } from '../../mixins/focus-mixin.js';
4
4
  import { FormElementMixin } from '../form/form-element-mixin.js';
5
5
  import { ifDefined } from 'lit-html/directives/if-defined.js';
6
6
  import { LabelledMixin } from '../../mixins/labelled-mixin.js';
7
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
7
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
8
8
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
9
9
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
10
10
 
@@ -5,7 +5,7 @@ import { css, html, LitElement } from 'lit-element/lit-element.js';
5
5
  import { FocusMixin } from '../../mixins/focus-mixin.js';
6
6
  import { ifDefined } from 'lit-html/directives/if-defined.js';
7
7
  import { inputStyles } from './input-styles.js';
8
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
8
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
9
9
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
10
10
 
11
11
  /**
@@ -8,7 +8,7 @@ import { FocusMixin } from '../../mixins/focus-mixin.js';
8
8
  import { FormElementMixin } from '../form/form-element-mixin.js';
9
9
  import { getUniqueId } from '../../helpers/uniqueId.js';
10
10
  import { ifDefined } from 'lit-html/directives/if-defined.js';
11
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
11
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
12
12
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
13
13
  import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
14
14
 
@@ -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
 
@@ -5,7 +5,7 @@ import '../selection/selection-summary.js';
5
5
  import { css, html, LitElement } from 'lit-element/lit-element.js';
6
6
  import { classMap } from 'lit-html/directives/class-map.js';
7
7
  import { findComposedAncestor } from '../../helpers/dom.js';
8
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
8
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
9
9
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
10
10
 
11
11
  /**
@@ -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);
@@ -6,7 +6,7 @@ import { buttonStyles } from '../button/button-styles.js';
6
6
  import { findComposedAncestor } from '../../helpers/dom.js';
7
7
  import { getFirstFocusableDescendant } from '../../helpers/focus.js';
8
8
  import { getUniqueId } from '../../helpers/uniqueId.js';
9
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
9
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
10
10
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
11
11
 
12
12
  const keyCodes = Object.freeze({
@@ -11,7 +11,7 @@ import { ifDefined } from 'lit-html/directives/if-defined.js';
11
11
  import { ListItemCheckboxMixin } from './list-item-checkbox-mixin.js';
12
12
  import { ListItemDragDropMixin } from './list-item-drag-drop-mixin.js';
13
13
  import { ListItemRoleMixin } from './list-item-role-mixin.js';
14
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
14
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
15
15
  import { nothing } from 'lit-html';
16
16
  import ResizeObserver from 'resize-observer-polyfill';
17
17
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
@@ -1,6 +1,6 @@
1
1
  import '../icons/icon.js';
2
2
  import { css, html, LitElement } from 'lit-element/lit-element.js';
3
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
3
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
4
4
  import { MenuItemMixin } from './menu-item-mixin.js';
5
5
  import { menuItemStyles } from './menu-item-styles.js';
6
6
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
@@ -1,5 +1,5 @@
1
1
  import { formatPercent } from '@brightspace-ui/intl/lib/number.js';
2
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
2
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
3
3
 
4
4
  export const MeterMixin = superclass => class extends LocalizeCoreElement(superclass) {
5
5
 
@@ -4,7 +4,7 @@ import { getComposedChildren, isComposedAncestor } from '../../helpers/dom.js';
4
4
  import { classMap } from 'lit-html/directives/class-map.js';
5
5
  import { getUniqueId } from '../../helpers/uniqueId.js';
6
6
  import { ifDefined } from 'lit-html/directives/if-defined.js';
7
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
7
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
8
8
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
9
9
  import { styleMap } from 'lit-html/directives/style-map.js';
10
10
 
@@ -12,7 +12,7 @@ import '../menu/menu-item-separator.js';
12
12
  import '../menu/menu-item-link.js';
13
13
  import { css, html, LitElement } from 'lit-element/lit-element.js';
14
14
  import { ifDefined } from 'lit-html/directives/if-defined.js';
15
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
15
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
16
16
  import { offscreenStyles } from '../offscreen/offscreen.js';
17
17
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
18
18
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
@@ -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
- const resizeObserver = new ResizeObserver(this._throttledResize);
265
- resizeObserver.observe(this._container);
269
+ this._resizeObserver = new ResizeObserver(this._throttledResize);
270
+ this._resizeObserver.observe(this._container);
266
271
  }
267
272
 
268
273
  render() {
@@ -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())).observe(this._container);
159
+ this._resizeObserver = new ResizeObserver(() => requestAnimationFrame(() => this.checkScrollbar()));
160
+ this._resizeObserver.observe(this._container);
154
161
  }
155
162
 
156
163
  render() {
@@ -4,7 +4,7 @@ import { DropdownOpenerMixin } from '../dropdown/dropdown-opener-mixin.js';
4
4
  import { dropdownOpenerStyles } from '../dropdown/dropdown-opener-styles.js';
5
5
  import { FocusMixin } from '../../mixins/focus-mixin.js';
6
6
  import { ifDefined } from 'lit-html/directives/if-defined.js';
7
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
7
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
8
8
  import { SelectionActionMixin } from './selection-action-mixin.js';
9
9
 
10
10
  /**
@@ -3,7 +3,7 @@ import { css, html, LitElement } from 'lit-element/lit-element.js';
3
3
  import { ButtonMixin } from '../button/button-mixin.js';
4
4
  import { FocusMixin } from '../../mixins/focus-mixin.js';
5
5
  import { ifDefined } from 'lit-html/directives/if-defined.js';
6
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
6
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
7
7
  import { SelectionActionMixin } from './selection-action-mixin.js';
8
8
  import { SelectionInfo } from './selection-mixin.js';
9
9
 
@@ -1,7 +1,7 @@
1
1
  import '../button/button-subtle.js';
2
2
  import { css, html, LitElement } from 'lit-element/lit-element.js';
3
3
  import { FocusMixin } from '../../mixins/focus-mixin.js';
4
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
4
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
5
5
  import { SelectionInfo } from './selection-mixin.js';
6
6
  import { SelectionObserverMixin } from './selection-observer-mixin.js';
7
7
 
@@ -2,7 +2,7 @@ import '../inputs/input-checkbox.js';
2
2
  import { css, html, LitElement } from 'lit-element/lit-element.js';
3
3
  import { FocusMixin } from '../../mixins/focus-mixin.js';
4
4
  import { ifDefined } from 'lit-html/directives/if-defined.js';
5
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
5
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
6
6
  import { SelectionInfo } from './selection-mixin.js';
7
7
  import { SelectionObserverMixin } from './selection-observer-mixin.js';
8
8
 
@@ -1,6 +1,6 @@
1
1
  import { css, html, LitElement } from 'lit-element/lit-element.js';
2
2
  import { bodyCompactStyles } from '../typography/styles.js';
3
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
3
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
4
4
  import { SelectionInfo } from './selection-mixin.js';
5
5
  import { SelectionObserverMixin } from './selection-observer-mixin.js';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import '../icons/icon.js';
2
2
  import { html, LitElement } from 'lit-element/lit-element.js';
3
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
3
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
4
4
  import { SwitchMixin } from './switch-mixin.js';
5
5
 
6
6
  /**
@@ -9,7 +9,7 @@ import { ArrowKeysMixin } from '../../mixins/arrow-keys-mixin.js';
9
9
  import { bodyCompactStyles } from '../typography/styles.js';
10
10
  import { classMap } from 'lit-html/directives/class-map.js';
11
11
  import { FocusVisiblePolyfillMixin } from '../../mixins/focus-visible-polyfill-mixin.js';
12
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
12
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
13
13
  import { repeat } from 'lit-html/directives/repeat.js';
14
14
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
15
15
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
@@ -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
 
@@ -0,0 +1,11 @@
1
+ import { LocalizeDynamicMixin } from '../mixins/localize-dynamic-mixin.js';
2
+
3
+ export const LocalizeCoreElement = superclass => class extends LocalizeDynamicMixin(superclass) {
4
+
5
+ static get localizeConfig() {
6
+ return {
7
+ importFunc: async lang => (await import(`../lang/${lang}.js`)).default
8
+ };
9
+ }
10
+
11
+ };
package/lang/da.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Ryd filtre for: {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Ryd filtre",
20
20
  "components.filter.loading": "Indlæser filtre",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Ingen filtre anvendt.} one {1 filter anvendt.} other {{number} filtre anvendt.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Ingen filtre anvendt.} one {1 filter anvendt.} other {{number} filtre anvendt.}}",
22
22
  "components.filter.filters": "Filtre",
23
23
  "components.filter.noFilters": "Ingen tilgængelige filtre",
24
- "components.filter.searchResults": "{number, plural, zero {No search results} one {1 search result} other {{number} search results}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {No search results} one {1 search result} other {{number} search results}}",
25
25
  "components.filter.singleDimensionDescription": "Filtrer efter: {filterName}",
26
26
  "components.form-element.defaultError": "{label} er ugyldigt.",
27
27
  "components.form-element.defaultFieldLabel": "Felt",
package/lang/de.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Filter für {filterName} löschen",
19
19
  "components.filter.clearDescriptionSingle": "Filter löschen",
20
20
  "components.filter.loading": "Filter werden geladen",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Keine Filter angewendet.} one {1 Filter angewendet.} other {{number} Filter angewendet.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Keine Filter angewendet.} one {1 Filter angewendet.} other {{number} Filter angewendet.}}",
22
22
  "components.filter.filters": "Filter",
23
23
  "components.filter.noFilters": "Keine verfügbaren Filter",
24
- "components.filter.searchResults": "{number, plural, zero {Keine Suchergebnisse} one {1 Suchergebnis} other {{number} Suchergebnisse}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {Keine Suchergebnisse} one {1 Suchergebnis} other {{number} Suchergebnisse}}",
25
25
  "components.filter.singleDimensionDescription": "Filtern nach: {filterName}",
26
26
  "components.form-element.defaultError": "{label} ist ungültig.",
27
27
  "components.form-element.defaultFieldLabel": "Feld",
package/lang/en.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Clear filters for: {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Clear filters",
20
20
  "components.filter.loading": "Loading filters",
21
- "components.filter.filterCountDescription": "{number, plural, zero {No filters applied.} one {1 filter applied.} other {{number} filters applied.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {No filters applied.} one {1 filter applied.} other {{number} filters applied.}}",
22
22
  "components.filter.filters": "Filters",
23
23
  "components.filter.noFilters": "No available filters",
24
- "components.filter.searchResults": "{number, plural, zero {No search results} one {1 search result} other {{number} search results}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {No search results} one {1 search result} other {{number} search results}}",
25
25
  "components.filter.singleDimensionDescription": "Filter by: {filterName}",
26
26
  "components.form-element.defaultError": "{label} is invalid.",
27
27
  "components.form-element.defaultFieldLabel": "Field",
package/lang/es-es.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Borrar filtros para: {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Borrar filtros",
20
20
  "components.filter.loading": "Cargando filtros",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Sin filtros aplicados.} one {1 filtro aplicado.} other {{number} filtros aplicados.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Sin filtros aplicados.} one {1 filtro aplicado.} other {{number} filtros aplicados.}}",
22
22
  "components.filter.filters": "Filtros",
23
23
  "components.filter.noFilters": "No hay filtros disponibles",
24
- "components.filter.searchResults": "{number, plural, zero {No hay resultados de búsqueda} one {1 resultado de búsqueda} other {{number} resultados de búsqueda}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {No hay resultados de búsqueda} one {1 resultado de búsqueda} other {{number} resultados de búsqueda}}",
25
25
  "components.filter.singleDimensionDescription": "Filtrar por: {filterName}",
26
26
  "components.form-element.defaultError": "{label} no es válido.",
27
27
  "components.form-element.defaultFieldLabel": "Campo",
package/lang/es.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Borrar filtros para: {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Borrar filtros",
20
20
  "components.filter.loading": "Cargando filtros",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Sin filtros aplicados.} one {1 filtro aplicado.} other {{number} filtros aplicados.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Sin filtros aplicados.} one {1 filtro aplicado.} other {{number} filtros aplicados.}}",
22
22
  "components.filter.filters": "Filtros",
23
23
  "components.filter.noFilters": "No hay filtros disponibles",
24
- "components.filter.searchResults": "{number, plural, zero {No se encontraron resultados de búsqueda} one {1 resultado de búsqueda} other {{number} resultados de búsqueda}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {No se encontraron resultados de búsqueda} one {1 resultado de búsqueda} other {{number} resultados de búsqueda}}",
25
25
  "components.filter.singleDimensionDescription": "Filtrar por: {filterName}",
26
26
  "components.form-element.defaultError": "{label} no es válida.",
27
27
  "components.form-element.defaultFieldLabel": "Campo",
package/lang/fr-fr.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Supprimer les filtres pour : {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Supprimer les filtres",
20
20
  "components.filter.loading": "Chargement des filtres",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Aucun filtre appliqué.} one {1 filtre appliqué.} other {{number} filtres appliqués.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Aucun filtre appliqué.} one {1 filtre appliqué.} other {{number} filtres appliqués.}}",
22
22
  "components.filter.filters": "Filtres",
23
23
  "components.filter.noFilters": "Aucun filtre disponible",
24
- "components.filter.searchResults": "{number, plural, zero {aucun résultat de recherche} one {1 résultat de recherche} other {{number} résultats de recherche}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {aucun résultat de recherche} one {1 résultat de recherche} other {{number} résultats de recherche}}",
25
25
  "components.filter.singleDimensionDescription": "Filtrer par : {filterName}",
26
26
  "components.form-element.defaultError": "{label} n'est pas valide.",
27
27
  "components.form-element.defaultFieldLabel": "Champ",
package/lang/fr.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Effacer les filtres pour : {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Effacer les filtres",
20
20
  "components.filter.loading": "Chargement des filtres",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Aucun filtre appliqué.} one {1 filtre appliqué.} other {{number} filtres appliqués.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Aucun filtre appliqué.} one {1 filtre appliqué.} other {{number} filtres appliqués.}}",
22
22
  "components.filter.filters": "Filtres",
23
23
  "components.filter.noFilters": "Aucun filtre disponible",
24
- "components.filter.searchResults": "{number, plural, zero {Aucun résultat de recherche} one {1 résultat de recherche} other {{number} résultats de recherche}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {Aucun résultat de recherche} one {1 résultat de recherche} other {{number} résultats de recherche}}",
25
25
  "components.filter.singleDimensionDescription": "Filtrer par : {filterName}",
26
26
  "components.form-element.defaultError": "{label} n'est pas valide.",
27
27
  "components.form-element.defaultFieldLabel": "Champ",
package/lang/hi.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "इसके लिए फ़िल्टर्स साफ़ करें: {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "फ़िल्टर साफ़ करें",
20
20
  "components.filter.loading": "फिल्टर्स लोड किए जा रहे हैं",
21
- "components.filter.filterCountDescription": "{number, plural, zero {कोई फ़िल्टर लागू नहीं किए गए} one {1 फ़िल्टर लागू किया गया।} other {{number} फ़िल्टर्स लागू किए गए।}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {कोई फ़िल्टर लागू नहीं किए गए} one {1 फ़िल्टर लागू किया गया।} other {{number} फ़िल्टर्स लागू किए गए।}}",
22
22
  "components.filter.filters": "फ़िल्टर्स",
23
23
  "components.filter.noFilters": "कोई उपलब्ध फ़िल्टर्स नहीं",
24
- "components.filter.searchResults": "{number, plural, zero {कोई खोज परिणाम नहीं} one {1 खोज परिणाम} other {{number} खोज परिणाम}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {कोई खोज परिणाम नहीं} one {1 खोज परिणाम} other {{number} खोज परिणाम}}",
25
25
  "components.filter.singleDimensionDescription": "इसके अनुसार फ़िल्टर करें: {filterName}",
26
26
  "components.form-element.defaultError": "{label} अमान्य है।",
27
27
  "components.form-element.defaultFieldLabel": "फ़ील्ड",
package/lang/ja.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "{filterName} フィルタのクリア",
19
19
  "components.filter.clearDescriptionSingle": "フィルタのクリア",
20
20
  "components.filter.loading": "フィルタのロード中",
21
- "components.filter.filterCountDescription": "{number, plural, zero {フィルタは適用されていません。} one {1 つのフィルタが適用されています。} other {{number} 個のフィルタが適用されています。}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {フィルタは適用されていません。} other {{number} 個のフィルタが適用されています。}}",
22
22
  "components.filter.filters": "フィルタ",
23
23
  "components.filter.noFilters": "使用可能なフィルタはありません",
24
- "components.filter.searchResults": "{number, plural, zero {検索結果なし} one {1 件の検索結果} other {{number} 件の検索結果}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {検索結果なし} other {{number} 件の検索結果}}",
25
25
  "components.filter.singleDimensionDescription": "フィルタ条件: {filterName}",
26
26
  "components.form-element.defaultError": "{label} は無効です。",
27
27
  "components.form-element.defaultFieldLabel": "フィールド",
@@ -32,7 +32,7 @@ export default {
32
32
  "components.form-element.input.text.tooShort": "{label} は {minlength} 文字以上である必要があります",
33
33
  "components.form-element.input.url.typeMismatch": "URL が有効ではありません",
34
34
  "components.form-element.valueMissing": "{label} は必須です。",
35
- "components.form-error-summary.errorSummary": "送信した情報に {count, plural, one {1 件のエラー} other {{count} 件のエラー}} が見つかりました",
35
+ "components.form-error-summary.errorSummary": "送信した情報に {count, plural, other {{count} 件のエラー}} が見つかりました",
36
36
  "components.input-date-range.endDate": "終了日",
37
37
  "components.input-date-range.errorBadInput": "{startLabel} は {endLabel} より前にする必要があります",
38
38
  "components.input-date-range.startDate": "開始日",
package/lang/ko.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "{filterName}에 대한 필터를 지웁니다.",
19
19
  "components.filter.clearDescriptionSingle": "필터 지우기",
20
20
  "components.filter.loading": "필터 로드 중",
21
- "components.filter.filterCountDescription": "{number, plural, zero {적용된 필터 없음.} one {1개 필터 적용.} other {{number}개 필터 적용.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {적용된 필터 없음.} other {{number}개 필터 적용.}}",
22
22
  "components.filter.filters": "개 필터",
23
23
  "components.filter.noFilters": "사용 가능한 필터가 없습니다",
24
- "components.filter.searchResults": "{number, plural, zero {검색 결과 없음} one {1개 검색 결과} other {{number}개 검색 결과}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {검색 결과 없음} other {{number}개 검색 결과}}",
25
25
  "components.filter.singleDimensionDescription": "필터 기준: {filterName}",
26
26
  "components.form-element.defaultError": "{label}이(가) 잘못되었습니다.",
27
27
  "components.form-element.defaultFieldLabel": "필드",
@@ -32,7 +32,7 @@ export default {
32
32
  "components.form-element.input.text.tooShort": "{label}은(는) {minlength}자 이상이어야 합니다",
33
33
  "components.form-element.input.url.typeMismatch": "URL이 유효하지 않습니다",
34
34
  "components.form-element.valueMissing": "{label}이(가) 필요합니다.",
35
- "components.form-error-summary.errorSummary": "제출{count, plural, one { 한 정보에서 1개의 오류} other {하신 정보에서 {count}개의 오류}}가 발견되었습니다",
35
+ "components.form-error-summary.errorSummary": "제출{count, plural, other {하신 정보에서 {count}개의 오류}}가 발견되었습니다",
36
36
  "components.input-date-range.endDate": "종료일",
37
37
  "components.input-date-range.errorBadInput": "{startLabel}은(는) {endLabel} 앞에 있어야 합니다",
38
38
  "components.input-date-range.startDate": "시작일",
package/lang/nl.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Filters wissen voor {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Filters wissen",
20
20
  "components.filter.loading": "Laden van filters",
21
- "components.filter.filterCountDescription": "{number, plural, zero {No filters applied.} one {1 filter applied.} other {{number} filters applied.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {No filters applied.} one {1 filter applied.} other {{number} filters applied.}}",
22
22
  "components.filter.filters": "Filters",
23
23
  "components.filter.noFilters": "Geen beschikbare filters",
24
- "components.filter.searchResults": "{number, plural, zero {Geen zoekresultaten} one {1 zoekresultaat} other {{number} zoekresultaten}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {Geen zoekresultaten} one {1 zoekresultaat} other {{number} zoekresultaten}}",
25
25
  "components.filter.singleDimensionDescription": "Filter op {filterName}",
26
26
  "components.form-element.defaultError": "{label} is ongeldig.",
27
27
  "components.form-element.defaultFieldLabel": "Veld",
package/lang/pt.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Limpar filtros para: {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Limpar filtros",
20
20
  "components.filter.loading": "Carregar filtros",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Nenhum filtro aplicado.} one {Um filtro aplicado.} other {{number} filtros aplicados.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Nenhum filtro aplicado.} one {Um filtro aplicado.} other {{number} filtros aplicados.}}",
22
22
  "components.filter.filters": "Filtros",
23
23
  "components.filter.noFilters": "Não há filtros disponíveis",
24
- "components.filter.searchResults": "{number, plural, zero {Sem resultados para a pesquisa} one {1 resultado para a pesquisa} other {{number} resultados para a pesquisa}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {Sem resultados para a pesquisa} one {1 resultado para a pesquisa} other {{number} resultados para a pesquisa}}",
25
25
  "components.filter.singleDimensionDescription": "Filtrar por: {filterName}",
26
26
  "components.form-element.defaultError": "{label} é inválido.",
27
27
  "components.form-element.defaultFieldLabel": "Campo",
package/lang/sv.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "Rensa filter för {filterName}",
19
19
  "components.filter.clearDescriptionSingle": "Rensa filter",
20
20
  "components.filter.loading": "Läser in filter",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Inga filter tillämpade.} one {1 filter tillämpat.} other {{number} filter tillämpade.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Inga filter tillämpade.} one {1 filter tillämpat.} other {{number} filter tillämpade.}}",
22
22
  "components.filter.filters": "Filter",
23
23
  "components.filter.noFilters": "Inga tillgängliga filter",
24
- "components.filter.searchResults": "{number, plural, zero {No search results} one {1 search result} other {{number} search results}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {No search results} one {1 search result} other {{number} search results}}",
25
25
  "components.filter.singleDimensionDescription": "Filtrera efter: {filterName}",
26
26
  "components.form-element.defaultError": "{label} är ogiltig.",
27
27
  "components.form-element.defaultFieldLabel": "Fält",
package/lang/tr.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "{filterName} için filtreleri temizle",
19
19
  "components.filter.clearDescriptionSingle": "Filtreleri temizle",
20
20
  "components.filter.loading": "Filtreler yükleniyor",
21
- "components.filter.filterCountDescription": "{number, plural, zero {Filtre uygulanmadı.} one {1 filtre uygulandı.} other {{number} filtre uygulandı.}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {Filtre uygulanmadı.} one {1 filtre uygulandı.} other {{number} filtre uygulandı.}}",
22
22
  "components.filter.filters": "Filtre",
23
23
  "components.filter.noFilters": "Uygun filtre yok",
24
- "components.filter.searchResults": "{number, plural, zero {Arama sonucu yok} one {1 arama sonucu} other {{number} arama sonucu}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {Arama sonucu yok} one {1 arama sonucu} other {{number} arama sonucu}}",
25
25
  "components.filter.singleDimensionDescription": "Filtreleme ölçütü: {filterName}",
26
26
  "components.form-element.defaultError": "{label} geçersiz.",
27
27
  "components.form-element.defaultFieldLabel": "Alan",
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "清除筛选条件:{ filterName }",
19
19
  "components.filter.clearDescriptionSingle": "清除筛选",
20
20
  "components.filter.loading": "正在加载筛选器",
21
- "components.filter.filterCountDescription": "{number, plural, zero {未应用筛选器。} one {已应用 1 个筛选器。} other {已应用 {number} 个筛选器。}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {未应用筛选器。} other {已应用 {number} 个筛选器。}}",
22
22
  "components.filter.filters": "个筛选条件",
23
23
  "components.filter.noFilters": "无可用筛选器",
24
- "components.filter.searchResults": "{number, plural, zero {无搜索结果} one {1 个搜索结果} other {{number} 个搜索结果}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {无搜索结果} other {{number} 个搜索结果}}",
25
25
  "components.filter.singleDimensionDescription": "筛选依据:{filterName}",
26
26
  "components.form-element.defaultError": "{label} 无效。",
27
27
  "components.form-element.defaultFieldLabel": "字段",
@@ -32,7 +32,7 @@ export default {
32
32
  "components.form-element.input.text.tooShort": "{label} 必须至少为 {minlength} 个字符",
33
33
  "components.form-element.input.url.typeMismatch": "URL 无效",
34
34
  "components.form-element.valueMissing": "{label} 为必填项。",
35
- "components.form-error-summary.errorSummary": "您提交的信息中出现 {count, plural, one {1 处错误} other {{count} 处错误}} 处错误",
35
+ "components.form-error-summary.errorSummary": "您提交的信息中出现 {count, plural, other {{count} 处错误}} 处错误",
36
36
  "components.input-date-range.endDate": "结束日期",
37
37
  "components.input-date-range.errorBadInput": "{startLabel} 必须早于 {endLabel}",
38
38
  "components.input-date-range.startDate": "开始日期",
package/lang/zh-tw.js CHANGED
@@ -18,10 +18,10 @@ export default {
18
18
  "components.filter.clearDescription": "清除 {filterName} 的篩選器",
19
19
  "components.filter.clearDescriptionSingle": "清除篩選器",
20
20
  "components.filter.loading": "正在載入篩選條件",
21
- "components.filter.filterCountDescription": "{number, plural, zero {未套用篩選條件。} one {已套用 1 項篩選條件。} other {已套用 {number} 項篩選條件。}}",
21
+ "components.filter.filterCountDescription": "{number, plural, =0 {未套用篩選條件。} other {已套用 {number} 項篩選條件。}}",
22
22
  "components.filter.filters": "篩選器",
23
23
  "components.filter.noFilters": "沒有可用的篩選條件",
24
- "components.filter.searchResults": "{number, plural, zero {無搜尋結果} one {1 個搜尋結果} other {{number} 個搜尋結果}}",
24
+ "components.filter.searchResults": "{number, plural, =0 {無搜尋結果} other {{number} 個搜尋結果}}",
25
25
  "components.filter.singleDimensionDescription": "按此條件篩選:{filterName}",
26
26
  "components.form-element.defaultError": "{label} 無效。",
27
27
  "components.form-element.defaultFieldLabel": "欄位",
@@ -32,7 +32,7 @@ export default {
32
32
  "components.form-element.input.text.tooShort": "{label} 必須至少為 {minlength} 個字元",
33
33
  "components.form-element.input.url.typeMismatch": "URL 無效",
34
34
  "components.form-element.valueMissing": "{label} 為必填。",
35
- "components.form-error-summary.errorSummary": "您提交的資訊中發現 {count, plural, one {1 個錯誤} other {{count} 個錯誤}}",
35
+ "components.form-error-summary.errorSummary": "您提交的資訊中發現 {count, plural, other {{count} 個錯誤}}",
36
36
  "components.input-date-range.endDate": "結束日期",
37
37
  "components.input-date-range.errorBadInput": "{startLabel} 必須早於 {endLabel}",
38
38
  "components.input-date-range.startDate": "開始日期",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "1.239.1",
3
+ "version": "1.241.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",
@@ -17,10 +17,11 @@
17
17
  "lint:lit": "lit-analyzer \"{components,controllers,directives,helpers,mixins,templates,test,tools}/**/*.js\" --strict --rules.no-unknown-tag-name off",
18
18
  "lint:style": "stylelint \"**/*.{js,html}\"",
19
19
  "start": "web-dev-server --node-resolve --watch --open",
20
- "test": "npm run lint && npm run test:headless && npm run test:axe",
20
+ "test": "npm run lint && npm run test:translations && npm run test:headless && npm run test:axe",
21
21
  "test:axe": "web-test-runner --group aXe",
22
22
  "test:headless": "web-test-runner --group default",
23
- "test:headless:watch": "web-test-runner --group default --watch"
23
+ "test:headless:watch": "web-test-runner --group default --watch",
24
+ "test:translations": "mfv -e -s en -p ./lang/"
24
25
  },
25
26
  "files": [
26
27
  "custom-elements.json",
@@ -57,6 +58,7 @@
57
58
  "eslint-plugin-lit": "^1",
58
59
  "eslint-plugin-sort-class-members": "^1",
59
60
  "lit-analyzer": "^1",
61
+ "messageformat-validator": "^2",
60
62
  "node-sass": "^7",
61
63
  "sinon": "^13",
62
64
  "stylelint": "^14"
@@ -7,7 +7,7 @@ import { classMap } from 'lit-html/directives/class-map.js';
7
7
  import { FocusVisiblePolyfillMixin } from '../../mixins/focus-visible-polyfill-mixin.js';
8
8
  import { getUniqueId } from '../../helpers/uniqueId.js';
9
9
  import { ifDefined } from 'lit-html/directives/if-defined.js';
10
- import { LocalizeCoreElement } from '../../lang/localize-core-element.js';
10
+ import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
11
11
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
12
12
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
13
13
  import { styleMap } from 'lit-html/directives/style-map.js';
@@ -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) {
@@ -1,74 +0,0 @@
1
- import { LocalizeMixin } from '../mixins/localize-mixin.js';
2
-
3
- export const LocalizeCoreElement = superclass => class extends LocalizeMixin(superclass) {
4
-
5
- static async getLocalizeResources(langs) {
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');
69
- return {
70
- language: 'en',
71
- resources: translations.default
72
- };
73
- }
74
- };