@brightspace-ui/core 2.13.2 → 2.14.1

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/README.md CHANGED
@@ -70,6 +70,7 @@ npm install @brightspace-ui/core
70
70
  * [FocusMixin](mixins/focus-mixin.md): delegate focus to a nested element when `focus()` is called
71
71
  * [FocusVisiblePolyfillMixin](mixins/focus-visible-polyfill-mixin.md): components can use the `:focus-visible` pseudo-class polyfill
72
72
  * [FormElementMixin](components/form/docs/form-element-mixin.md): allow components to participate in forms and validation
73
+ * [InteractiveMixin](mixins/interactive-mixin.md): enables toggling interactive elements inside of nested grids
73
74
  * [LabelledMixin](mixins/labelled-mixin.md): label custom elements by referencing elements across DOM scopes
74
75
  * [LocalizeMixin](mixins/localize-mixin.md): localize text in your components
75
76
  * [ProviderMixin](mixins/provider-mixin.md): provide and consume data across elements in a DI-like fashion
@@ -110,6 +110,38 @@
110
110
  </template>
111
111
  </d2l-demo-snippet>
112
112
 
113
+ <h2>HTML Block (large font)</h2>
114
+
115
+ <d2l-demo-snippet>
116
+ <template>
117
+ <d2l-html-block>
118
+ <div style="font-size: 42px;">
119
+ Just a text node...
120
+ <h1>heading 1</h1>
121
+ <h2>heading 2</h2>
122
+ <h3>heading 3</h3>
123
+ <h4>heading 4</h4>
124
+ <h5>heading 5</h5>
125
+ <h6>heading 6</h6>
126
+ <div><strong>strong</strong></div>
127
+ <div><b>bold</b></div>
128
+ <div>text</div>
129
+ <pre>preformatted</pre>
130
+ <p>paragraph</p>
131
+ <ul>
132
+ <li>unordered item 1</li>
133
+ <li>unordered item 2</li>
134
+ </ul>
135
+ <ol>
136
+ <li>ordered item 1</li>
137
+ <li>ordered item 2</li>
138
+ </ol>
139
+ <div><a href="https://d2l.com">anchor</a></div>
140
+ </div>
141
+ </d2l-html-block>
142
+ </template>
143
+ </d2l-demo-snippet>
144
+
113
145
  <h2>HTML Block (math)</h2>
114
146
 
115
147
  <d2l-demo-snippet>
@@ -6,10 +6,8 @@ import { requestInstance } from '../../mixins/provider-mixin.js';
6
6
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
7
7
 
8
8
  export const htmlBlockContentStyles = css`
9
- .d2l-html-block-compact {
10
- font-size: 0.8rem;
11
- font-weight: 400;
12
- line-height: 1.2rem;
9
+ .d2l-html-block-rendered {
10
+ line-height: 1.47; /* 1.4rem / 0.95rem */
13
11
  }
14
12
  .d2l-html-block-rendered > :first-child {
15
13
  margin-top: 0;
@@ -17,38 +15,43 @@ export const htmlBlockContentStyles = css`
17
15
  .d2l-html-block-rendered > :last-child {
18
16
  margin-bottom: 0;
19
17
  }
18
+ .d2l-html-block-compact {
19
+ font-size: 0.8rem;
20
+ font-weight: 400;
21
+ line-height: 1.5; /* 1.2rem / 0.8rem */
22
+ }
20
23
  h1, h2, h3, h4, h5, h6, b, strong, b *, strong * {
21
24
  font-weight: bold;
22
25
  }
23
26
  h1 {
24
27
  font-size: 2em;
25
- line-height: 37px;
26
- margin: 21.43px 0;
28
+ line-height: 1;
29
+ margin: 21px 0;
27
30
  }
28
31
  h2 {
29
32
  font-size: 1.5em;
30
- line-height: 27px;
31
- margin: 19.92px 0;
33
+ line-height: 1;
34
+ margin: 20px 0;
32
35
  }
33
36
  h3 {
34
37
  font-size: 1.2em;
35
- line-height: 23px;
36
- margin: 18.72px 0;
38
+ line-height: 1;
39
+ margin: 19px 0;
37
40
  }
38
41
  h4 {
39
42
  font-size: 1em;
40
- line-height: 20px;
41
- margin: 21.28px 0;
43
+ line-height: 1.05;
44
+ margin: 21px 0;
42
45
  }
43
46
  h5 {
44
47
  font-size: 0.83em;
45
- line-height: 16px;
46
- margin: 22.13px 0;
48
+ line-height: 1;
49
+ margin: 22px 0;
47
50
  }
48
51
  h6 {
49
52
  font-size: 0.67em;
50
- line-height: 13px;
51
- margin: 24.97px 0;
53
+ line-height: 1;
54
+ margin: 25px 0;
52
55
  }
53
56
  pre {
54
57
  font-family: Monospace;
@@ -71,6 +71,21 @@
71
71
  </script>
72
72
  </d2l-demo-snippet>
73
73
 
74
+ <h2>Tag List with Interactive</h2>
75
+ <d2l-demo-snippet fullscreen>
76
+ <div role="grid">
77
+ <d2l-tag-list description="A bunch of example tags" clearable>
78
+ <d2l-tag-list-item text="Example Tag"></d2l-tag-list-item>
79
+ <d2l-tag-list-item text="Longer Example Tag - much much much much much longer"></d2l-tag-list-item>
80
+ <d2l-tag-list-item text="Another Example Tag"></d2l-tag-list-item>
81
+ <d2l-tag-list-item-mixin-consumer name="Custom Tag List Item"></d2l-tag-list-item-mixin-consumer>
82
+ <d2l-tag-list-item text="Example Tag 5"></d2l-tag-list-item>
83
+ <d2l-tag-list-item text="Example Tag 6"></d2l-tag-list-item>
84
+ <d2l-tag-list-item text="Example Tag 7"></d2l-tag-list-item>
85
+ </d2l-tag-list>
86
+ </div>
87
+ </d2l-demo-snippet>
88
+
74
89
  </d2l-demo-page>
75
90
  </body>
76
91
  </html>
@@ -3,6 +3,7 @@ import { css, html, LitElement } from 'lit';
3
3
  import { announce } from '../../helpers/announce.js';
4
4
  import { ArrowKeysMixin } from '../../mixins/arrow-keys-mixin.js';
5
5
  import { classMap } from 'lit/directives/class-map.js';
6
+ import { InteractiveMixin } from '../../mixins/interactive-mixin.js';
6
7
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
7
8
  import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
8
9
  import { styleMap } from 'lit/directives/style-map.js';
@@ -16,7 +17,7 @@ const PAGE_SIZE_LINES = {
16
17
  medium: 2,
17
18
  small: 3
18
19
  };
19
- const MARGIN_TOP_RIGHT = 6;
20
+ const GAP = 6;
20
21
 
21
22
  async function filterAsync(arr, callback) {
22
23
  const fail = Symbol();
@@ -27,7 +28,7 @@ async function filterAsync(arr, callback) {
27
28
  return results.filter(i => i !== fail);
28
29
  }
29
30
 
30
- class TagList extends LocalizeCoreElement(ArrowKeysMixin(LitElement)) {
31
+ class TagList extends LocalizeCoreElement(InteractiveMixin(ArrowKeysMixin(LitElement))) {
31
32
 
32
33
  static get properties() {
33
34
  return {
@@ -48,7 +49,7 @@ class TagList extends LocalizeCoreElement(ArrowKeysMixin(LitElement)) {
48
49
  }
49
50
 
50
51
  static get styles() {
51
- return css`
52
+ return [super.styles, css`
52
53
  :host {
53
54
  display: block;
54
55
  }
@@ -79,7 +80,7 @@ class TagList extends LocalizeCoreElement(ArrowKeysMixin(LitElement)) {
79
80
  .tag-list-hidden {
80
81
  visibility: hidden;
81
82
  }
82
- `;
83
+ `];
83
84
  }
84
85
 
85
86
  constructor() {
@@ -184,26 +185,28 @@ class TagList extends LocalizeCoreElement(ArrowKeysMixin(LitElement)) {
184
185
  `;
185
186
 
186
187
  const outerContainerStyles = {
187
- maxHeight: (this._showHiddenTags || !this._lines) ? undefined : `${(this._itemHeight + MARGIN_TOP_RIGHT) * this._lines}px`,
188
+ maxHeight: (this._showHiddenTags || !this._lines) ? undefined : `${(this._itemHeight + GAP) * this._lines}px`,
188
189
  minHeight: `${Math.max(this._clearButtonHeight, this._itemHeight)}px`
189
190
  };
190
191
 
191
- return html`
192
- <div role="application" class="tag-list-outer-container" style="${styleMap(outerContainerStyles)}">
193
- <d2l-button-subtle aria-hidden="true" slim text="${this.localize('components.tag-list.num-hidden', { count: '##' })}" class="d2l-tag-list-hidden-button"></d2l-button-subtle>
194
- ${this.arrowKeysContainer(list)}
195
- </div>
196
- `;
192
+ return this.renderInteractiveContainer(
193
+ html`
194
+ <div role="application" class="tag-list-outer-container" style="${styleMap(outerContainerStyles)}">
195
+ <d2l-button-subtle aria-hidden="true" slim text="${this.localize('components.tag-list.num-hidden', { count: '##' })}" class="d2l-tag-list-hidden-button"></d2l-button-subtle>
196
+ ${this.arrowKeysContainer(list)}
197
+ </div>
198
+ `, this.localize('components.tag-list.interactive-label', { count: this._items ? this._items.length : 0 }),
199
+ () => {
200
+ if (this._items && this._items.length > 0) this._items[0].focus();
201
+ }
202
+ );
203
+
197
204
  }
198
205
 
199
206
  async arrowKeysFocusablesProvider() {
200
207
  return this._getVisibleEffectiveChildren();
201
208
  }
202
209
 
203
- focus() {
204
- if (this._items && this._items.length > 0) this._items[0].focus();
205
- }
206
-
207
210
  _chomp() {
208
211
  if (!this.shadowRoot || !this._lines || !this._itemLayouts) return;
209
212
 
@@ -226,9 +229,9 @@ class TagList extends LocalizeCoreElement(ArrowKeysMixin(LitElement)) {
226
229
 
227
230
  for (let i = overflowingIndex; i < this._itemLayouts.length; i++) {
228
231
  const itemLayout = this._itemLayouts[i];
229
- const itemWidth = Math.min(itemLayout.width + MARGIN_TOP_RIGHT, this._availableWidth);
232
+ const itemWidth = Math.min(itemLayout.width + GAP, this._availableWidth);
230
233
 
231
- if (!isOverflowing && ((showing.width + itemWidth) <= (this._availableWidth + MARGIN_TOP_RIGHT))) {
234
+ if (!isOverflowing && ((showing.width + itemWidth) <= (this._availableWidth + GAP))) {
232
235
  showing.width += itemWidth;
233
236
  showing.count += 1;
234
237
  itemLayout.trigger = 'soft-show';
package/lang/ar.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "وقت النهاية",
63
63
  "components.input-time-range.errorBadInput": "يجب أن يكون تاريخ {startLabel} قبل {endLabel}",
64
64
  "components.input-time-range.startTime": "وقت البدء",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "إعادة ترتيب إجراء المادة لـ {name}",
66
67
  "components.list-item-drag-handle.keyboard": "إعادة ترتيب المواد، الموضع الحالي {currentPosition} من أصل {size}. لنقل هذه المادة، اضغط على السهم المتجه إلى أعلى أو السهم المتجه إلى أسفل.",
67
68
  "components.list-item-tooltip.title": "التنقل عبر لوحة المفاتيح للقوائم:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/cy.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Amser Gorffen",
63
63
  "components.input-time-range.errorBadInput": "Rhaid i {startLabel} fod cyn {endLabel}",
64
64
  "components.input-time-range.startTime": "Amser Dechrau",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Aildrefnu gweithred eitem ar gyfer {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Aildrefnu eitemau, safle presennol {currentPosition} allan o {size}. I symud yr eitem hon, pwyswch y saeth i fyny neu'r saeth i lawr.",
67
68
  "components.list-item-tooltip.title": "Llywio Bysellfwrdd ar gyfer Rhestrau:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/da.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Sluttidspunkt",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} skal være før {endLabel}",
64
64
  "components.input-time-range.startTime": "Starttidspunkt",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Omarranger elementhandling for {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Omarranger element, aktuel position {currentPosition} ud af {size}. For at flytte dette element skal du trykke på pil op eller pil ned.",
67
68
  "components.list-item-tooltip.title": "Tastaturnavigering for lister:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/de.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Endzeit",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} muss vor {endLabel} liegen",
64
64
  "components.input-time-range.startTime": "Startzeit",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Elementaktion für {name} neu anordnen",
66
67
  "components.list-item-drag-handle.keyboard": "Elemente neu anordnen; aktuelle Position: {currentPosition} von {size}. Drücken Sie zum Bewegen dieses Elements auf den Pfeil nach oben oder den Pfeil nach unten.",
67
68
  "components.list-item-tooltip.title": "Tastaturnavigation für Listen:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/en.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "End Time",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} must be before {endLabel}",
64
64
  "components.input-time-range.startTime": "Start Time",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Reorder item action for {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Reorder item, current position {currentPosition} out of {size}. To move this item, press up or down arrows.",
67
68
  "components.list-item-tooltip.title": "Keyboard Navigation for Lists:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/es-es.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Hora de finalización",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} debe ser anterior a {endLabel}",
64
64
  "components.input-time-range.startTime": "Hora de inicio",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Reordenar acción de elemento para {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Reordenar elementos, posición actual {currentPosition} de {size}. Para mover este elemento, pulse las flechas arriba o abajo.",
67
68
  "components.list-item-tooltip.title": "Navegación de listas con el teclado:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/es.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Hora de finalización",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} debe estar antes de {endLabel}",
64
64
  "components.input-time-range.startTime": "Hora de inicio",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Acción de reordenar elemento de {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Reordenar elemento, posición actual {currentPosition} de {size}. Para mover este elemento, presione las flechas hacia arriba o hacia abajo.",
67
68
  "components.list-item-tooltip.title": "Navegación con el teclado para listas:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.cleared-all": "Removed all tag list items",
100
101
  "components.tag-list.cleared-item": "Removed tag list item {value}",
101
102
  "components.tag-list.clear-all": "Clear All",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/fr-fr.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Heure de fin",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} doit être antérieur à {endLabel}",
64
64
  "components.input-time-range.startTime": "Heure de début",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Action de réorganisation de l'élément pour {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Réordonner les éléments, position actuelle {currentPosition} sur {size}. Pour déplacer cet élément, appuyez sur les flèches vers le haut ou vers le bas.",
67
68
  "components.list-item-tooltip.title": "Navigation au clavier pour les listes :",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/fr.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Heure de fin",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} doit précéder {endLabel}",
64
64
  "components.input-time-range.startTime": "Heure de début",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Réordonner l'action de l'élément pour {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Réorganiser les éléments, position actuelle {currentPosition} de {size}. Pour déplacer cet élément, utilisez les flèches vers le haut et vers le bas.",
67
68
  "components.list-item-tooltip.title": "Navigation au clavier pour les listes :",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/hi.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "समाप्ति समय",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} {endLabel} से पहले का होना चाहिए",
64
64
  "components.input-time-range.startTime": "प्रारंभ समय",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "{name} के लिए आइटम कार्रवाई का क्रम बदलें",
66
67
  "components.list-item-drag-handle.keyboard": "आइटम का क्रम बदलें, {size} में से वर्तमान स्थिति {currentPosition} इस आइटम को ले जाने के लिए, ऊपर या नीचे तीर दबाएँ।",
67
68
  "components.list-item-tooltip.title": "सूचियों के लिए कीबोर्ड नेविगेशन:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/ja.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "終了時刻",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} は {endLabel} より前にする必要があります",
64
64
  "components.input-time-range.startTime": "開始時刻",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "{name} の項目並べ替えアクション",
66
67
  "components.list-item-drag-handle.keyboard": "項目の並べ替え、現在の位置 {currentPosition}、サイズ {size}。この項目を移動するには、上矢印または下矢印を押します。",
67
68
  "components.list-item-tooltip.title": "リストのキーボードナビゲーション:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/ko.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "종료 시각",
63
63
  "components.input-time-range.errorBadInput": "{startLabel}은(는) {endLabel} 앞에 있어야 합니다",
64
64
  "components.input-time-range.startTime": "시작 시각",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "{name}에 대한 항목 작업 재정렬",
66
67
  "components.list-item-drag-handle.keyboard": "전체 {size}에서 현재 위치 {currentPosition} 항목 재정렬 이 항목을 이동하라면 위쪽 또는 아래쪽 화살표를 누르십시오.",
67
68
  "components.list-item-tooltip.title": "목록에 대한 키보드 탐색:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/nl.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Eindtijd",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} moet voor {endLabel} liggen",
64
64
  "components.input-time-range.startTime": "Starttijd",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Itemactie voor {name} opnieuw rangschikken",
66
67
  "components.list-item-drag-handle.keyboard": "Items opnieuw rangschikken, huidige positie {currentPosition} van {size}. Als u dit item wilt verplaatsen, drukt u op de pijl omhoog of omlaag.",
67
68
  "components.list-item-tooltip.title": "Toetsenbordnavigatie voor lijsten:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/pt.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Hora final",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} precisa ser anterior a {endLabel}",
64
64
  "components.input-time-range.startTime": "Hora de início",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Reordenar ação de item para {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Reordenar item, posição atual {currentPosition} de {size}. Para mover este item, pressione as setas para cima ou para baixo.",
67
68
  "components.list-item-tooltip.title": "Navegação do teclado para listas:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/sv.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Sluttid",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} måste vara före {endLabel}",
64
64
  "components.input-time-range.startTime": "Starttid",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "Åtgärd för att ändra ordning på objekt för {name}",
66
67
  "components.list-item-drag-handle.keyboard": "Flytta objekt. Aktuell position: {currentPosition} av {size}. Om du vill flytta det här objektet trycker du på uppåt- eller nedåtpilen.",
67
68
  "components.list-item-tooltip.title": "Tangentbordsnavigering för listor:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/tr.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "Bitiş Saati",
63
63
  "components.input-time-range.errorBadInput": "{startLabel}, {endLabel} tarihinden önce olmalıdır",
64
64
  "components.input-time-range.startTime": "Başlangıç Saati",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "{name} için öğe eylemini yeniden sırala",
66
67
  "components.list-item-drag-handle.keyboard": "Öğeyi yeniden sırala, mevcut konum {currentPosition} / {size}. Bu öğeyi taşımak için yukarı veya aşağı oklara basın.",
67
68
  "components.list-item-tooltip.title": "Listeler için Klavye ile Gezinme:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/zh-cn.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "结束时间",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} 必须早于 {endLabel}",
64
64
  "components.input-time-range.startTime": "开始时间",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "对 {name} 的项目操作重新排序",
66
67
  "components.list-item-drag-handle.keyboard": "对项目重新排序,当前位置 {currentPosition} 超出 {size}。要移动此项目,请按向上或向下箭头。",
67
68
  "components.list-item-tooltip.title": "列表的键盘导航:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
package/lang/zh-tw.js CHANGED
@@ -62,6 +62,7 @@ export default {
62
62
  "components.input-time-range.endTime": "結束時間",
63
63
  "components.input-time-range.errorBadInput": "{startLabel} 必須早於 {endLabel}",
64
64
  "components.input-time-range.startTime": "開始時間",
65
+ "components.interactive.instructions": "Press Enter to interact, Escape to exit",
65
66
  "components.list-item-drag-handle.default": "重新排序 {name} 的項目動作",
66
67
  "components.list-item-drag-handle.keyboard": "重新排序項目,目前位置 {currentPosition},總共為 {size}。若要移除這個項目,請按向上或向下箭頭。",
67
68
  "components.list-item-tooltip.title": "清單的鍵盤導覽:",
@@ -99,6 +100,7 @@ export default {
99
100
  "components.tag-list.clear-all": "Clear All",
100
101
  "components.tag-list.cleared-all": "Removed all tag list items",
101
102
  "components.tag-list.cleared-item": "Removed tag list item {value}",
103
+ "components.tag-list.interactive-label": "Tag List, {count} items",
102
104
  "components.tag-list.num-hidden": "+ {count} more",
103
105
  "components.tag-list.show-less": "Show Less",
104
106
  "components.tag-list.show-more-description": "Select to show hidden tag list items",
@@ -0,0 +1,118 @@
1
+ import { css, html } from 'lit';
2
+ import { findComposedAncestor, isComposedAncestor } from '../helpers/dom.js';
3
+ import { forceFocusVisible, getNextFocusable } from '../helpers/focus.js';
4
+ import { ifDefined } from 'lit/directives/if-defined.js';
5
+ import { LocalizeCoreElement } from '../helpers/localize-core-element.js';
6
+
7
+ const keyCodes = {
8
+ ENTER: 13,
9
+ ESCAPE: 27
10
+ };
11
+
12
+ export const InteractiveMixin = superclass => class extends LocalizeCoreElement(superclass) {
13
+
14
+ static get properties() {
15
+ return {
16
+ _hasInteractiveAncestor: { state: true },
17
+ _interactive: { state: true }
18
+ };
19
+ }
20
+
21
+ static get styles() {
22
+ return css`
23
+ .interactive-container.focus-visible,
24
+ .interactive-container:focus-visible {
25
+ border-radius: 6px;
26
+ outline: 2px solid var(--d2l-color-celestine);
27
+ outline-offset: 2px;
28
+ }
29
+ `;
30
+ }
31
+
32
+ constructor() {
33
+ super();
34
+ this._hasInteractiveAncestor = false;
35
+ this._interactive = false;
36
+ }
37
+
38
+ connectedCallback() {
39
+ super.connectedCallback();
40
+
41
+ const parentGrid = findComposedAncestor(this.parentNode, node => {
42
+ return ((node.tagName === 'D2L-LIST' && node.grid) || (node.nodeType === Node.ELEMENT_NODE && node.getAttribute('role') === 'grid'));
43
+ });
44
+ this._hasInteractiveAncestor = (parentGrid !== null);
45
+ }
46
+
47
+ focus() {
48
+ if (!this.shadowRoot) return;
49
+ if (this._hasInteractiveAncestor && !this._interactive) forceFocusVisible(this.shadowRoot.querySelector('.interactive-container'));
50
+ else this._focusDelegate();
51
+ }
52
+
53
+ renderInteractiveContainer(inner, label, focusDelegate) {
54
+ if (!label) {
55
+ throw new Error(`InteractiveMixin: no label provided for "${this.tagName}"`);
56
+ }
57
+ if (!focusDelegate) {
58
+ throw new Error(`InteractiveMixin: no focus delegate provided for "${this.tagName}"`);
59
+ }
60
+ this._focusDelegate = focusDelegate;
61
+ if (!this._hasInteractiveAncestor) return inner;
62
+ return html`
63
+ <div class="interactive-container"
64
+ aria-label="${label}"
65
+ aria-description="${this.localize('components.interactive.instructions')}"
66
+ @keydown="${this._handleInteractiveKeyDown}"
67
+ role="button"
68
+ tabindex="${ifDefined(this._hasInteractiveAncestor && !this._interactive ? '0' : undefined)}">
69
+ <span class="interactive-trap-start" @focus="${this._handleInteractiveStartFocus}" tabindex="${ifDefined(this._hasInteractiveAncestor ? '0' : undefined)}"></span>
70
+ <div class="interactive-container-content" @focusin="${this._handleInteractiveContentFocusIn}" @focusout="${this._handleInteractiveContentFocusOut}">${inner}</div>
71
+ <span class="interactive-trap-end" @focus="${this._handleInteractiveEndFocus}" tabindex="${ifDefined(this._hasInteractiveAncestor ? '0' : undefined)}"></span>
72
+ </div>
73
+ `;
74
+ }
75
+
76
+ _handleInteractiveContentFocusIn() {
77
+ this._interactive = true;
78
+ }
79
+
80
+ _handleInteractiveContentFocusOut(e) {
81
+ if (isComposedAncestor(this.shadowRoot.querySelector('.interactive-container-content'), e.relatedTarget)) return;
82
+ // focus moved out of the interactive content
83
+ this._interactive = false;
84
+ }
85
+
86
+ async _handleInteractiveEndFocus() {
87
+ // focus moved to trap-end either forwards from contents or backwards from outside - focus interactive toggle
88
+ this._interactive = false;
89
+ await this.updateComplete;
90
+ this.shadowRoot.querySelector('.interactive-container').focus();
91
+ }
92
+
93
+ async _handleInteractiveKeyDown(e) {
94
+ if (!this._interactive && e.keyCode === keyCodes.ENTER) {
95
+ this._interactive = true;
96
+ await this.updateComplete;
97
+ this.focus();
98
+ } else if (this._interactive && e.keyCode === keyCodes.ESCAPE) {
99
+ this._interactive = false;
100
+ await this.updateComplete;
101
+ this.shadowRoot.querySelector('.interactive-container').focus();
102
+ }
103
+ }
104
+
105
+ async _handleInteractiveStartFocus(e) {
106
+ if (e.relatedTarget === this.shadowRoot.querySelector('.interactive-container')) {
107
+ // focus moved to trap-start while non-interactive - focus next focusable after this component
108
+ const nextFocusable = getNextFocusable(this.shadowRoot.querySelector('.interactive-trap-end'));
109
+ if (nextFocusable) nextFocusable.focus();
110
+ } else {
111
+ // focus moved to trap-start backwards from within contents - toggle to non-interactive and apply focus
112
+ this._interactive = false;
113
+ await this.updateComplete;
114
+ this.shadowRoot.querySelector('.interactive-container').focus();
115
+ }
116
+ }
117
+
118
+ };
@@ -0,0 +1,27 @@
1
+ # InteractiveMixin
2
+
3
+ The `InteractiveMixin` enables keyboard toggling of interactive elements (such as those that use arrow keys) inside nested grids. It addresses the issue of conflicting arrow key behaviour. If the component is rendered as a descendant of a grid, keyboard users use the `Enter` key to toggle into interactive mode, and the `Escape` key to toggle out.
4
+
5
+ ## Usage
6
+
7
+ Apply the mixin, call its `renderInteractiveContainer` method from `render`, providing the interactive content, label for the toggle, and a focus delegate that the mixin can call to focus on the contents.
8
+
9
+ **Note:** consumers _must_ provide a focus delegate as mentioned. They _should not_ implement a `focus` method, since the mixin manages focus with its own implementation.
10
+
11
+ ```js
12
+ import { InteractiveMixin } from '@brightspace-ui/core/mixins/interactive-mixin.js';
13
+
14
+ class MyComponent extends InteractiveMixin(LitElement) {
15
+
16
+ render() {
17
+ return this.renderInteractiveContainer(
18
+ html`<div>interactive content</div>`,
19
+ 'My Label',
20
+ () => {
21
+ // focus on interactive content element
22
+ }
23
+ );
24
+ }
25
+
26
+ }
27
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.13.2",
3
+ "version": "2.14.1",
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",
@@ -0,0 +1,12 @@
1
+
2
+ export function keyDown(element, keycode) {
3
+ const event = new CustomEvent('keydown', {
4
+ detail: 0,
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true
8
+ });
9
+ event.keyCode = keycode;
10
+ event.code = keycode;
11
+ element.dispatchEvent(event);
12
+ }