@brightspace-ui/core 2.41.0 → 2.42.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/filter/README.md +73 -2
- package/components/filter/filter-overflow-group.js +41 -4
- package/components/filter/filter-tags.js +1 -1
- package/components/html-block/demo/html-block.html +125 -0
- package/components/html-block/html-block.js +93 -37
- package/components/overflow-group/overflow-group-mixin.js +41 -7
- package/components/overflow-group/overflow-group.js +1 -0
- package/custom-elements.json +20 -18
- package/helpers/mathjax.js +17 -28
- package/helpers/prism.js +0 -2
- package/package.json +1 -1
|
@@ -254,7 +254,7 @@ A tag-list allowing the user to see (and remove) the currently applied filters.
|
|
|
254
254
|
display: block;
|
|
255
255
|
max-width: 100%;
|
|
256
256
|
}
|
|
257
|
-
|
|
257
|
+
}
|
|
258
258
|
</style>
|
|
259
259
|
<div class="filter-wrapper">
|
|
260
260
|
<d2l-filter-tags filter-ids="core-filter core-filter-2"></d2l-filter-tags>
|
|
@@ -300,7 +300,78 @@ A tag-list allowing the user to see (and remove) the currently applied filters.
|
|
|
300
300
|
|
|
301
301
|
## Filter Overflow Group [d2l-filter-overflow-group]
|
|
302
302
|
|
|
303
|
-
|
|
303
|
+
The `d2l-filter-overflow-group` is a container for multiple filters that handles overflow on smaller screens. Overflowing filters are displayed in a single filter.
|
|
304
|
+
|
|
305
|
+
<!-- docs: demo live name:d2l-filter-overflow-group align:start display:block autoSize:false size:medium -->
|
|
306
|
+
```html
|
|
307
|
+
<script type="module">
|
|
308
|
+
import '@brightspace-ui/core/components/filter/filter.js';
|
|
309
|
+
import '@brightspace-ui/core/components/filter/filter-dimension-set.js';
|
|
310
|
+
import '@brightspace-ui/core/components/filter/filter-dimension-set-value.js';
|
|
311
|
+
import '@brightspace-ui/core/components/filter/filter-overflow-group.js';
|
|
312
|
+
</script>
|
|
313
|
+
<d2l-filter-overflow-group>
|
|
314
|
+
<d2l-filter>
|
|
315
|
+
<d2l-filter-dimension-set key="skill" text="Skill">
|
|
316
|
+
<d2l-filter-dimension-set-value key="communication" text="Fall"></d2l-filter-dimension-set-value>
|
|
317
|
+
<d2l-filter-dimension-set-value key="leadership" text="Winter"></d2l-filter-dimension-set-value>
|
|
318
|
+
<d2l-filter-dimension-set-value key="management" text="Spring"></d2l-filter-dimension-set-value>
|
|
319
|
+
<d2l-filter-dimension-set-value key="planning" text="Summer"></d2l-filter-dimension-set-value>
|
|
320
|
+
</d2l-filter-dimension-set>
|
|
321
|
+
</d2l-filter>
|
|
322
|
+
<d2l-filter>
|
|
323
|
+
<d2l-filter-dimension-set key="type" text="Type" selection-single>
|
|
324
|
+
<d2l-filter-dimension-set-value key="certificate" text="Certificate"></d2l-filter-dimension-set-value>
|
|
325
|
+
<d2l-filter-dimension-set-value key="degree" text="Degree"></d2l-filter-dimension-set-value>
|
|
326
|
+
<d2l-filter-dimension-set-value key="diploma" text="Diploma"></d2l-filter-dimension-set-value>
|
|
327
|
+
<d2l-filter-dimension-set-value key="course" text="Course"></d2l-filter-dimension-set-value>
|
|
328
|
+
</d2l-filter-dimension-set>
|
|
329
|
+
</d2l-filter>
|
|
330
|
+
<d2l-filter>
|
|
331
|
+
<d2l-filter-dimension-set key="course" text="Course" select-all>
|
|
332
|
+
<d2l-filter-dimension-set-value key="art" text="Art"></d2l-filter-dimension-set-value>
|
|
333
|
+
<d2l-filter-dimension-set-value key="astronomy" text="Astronomy" selected></d2l-filter-dimension-set-value>
|
|
334
|
+
<d2l-filter-dimension-set-value key="biology" text="Biology"></d2l-filter-dimension-set-value>
|
|
335
|
+
<d2l-filter-dimension-set-value key="chemistry" text="Chemistry"></d2l-filter-dimension-set-value>
|
|
336
|
+
</d2l-filter-dimension-set>
|
|
337
|
+
<d2l-filter-dimension-set key="duration" text="Duration">
|
|
338
|
+
<d2l-filter-dimension-set-value key="lessthanthree" text="< 3 months"></d2l-filter-dimension-set-value>
|
|
339
|
+
<d2l-filter-dimension-set-value key="threetosix" text="3-6 months"></d2l-filter-dimension-set-value>
|
|
340
|
+
<d2l-filter-dimension-set-value key="sixtotwelve" text="6-12 months"></d2l-filter-dimension-set-value>
|
|
341
|
+
</d2l-filter-dimension-set>
|
|
342
|
+
</d2l-filter>
|
|
343
|
+
<d2l-filter>
|
|
344
|
+
<d2l-filter-dimension-set key="provider" text="Semester3">
|
|
345
|
+
<d2l-filter-dimension-set-value key="mcmaster" text="McMaster"></d2l-filter-dimension-set-value>
|
|
346
|
+
<d2l-filter-dimension-set-value key="powered" text="PowerED"></d2l-filter-dimension-set-value>
|
|
347
|
+
<d2l-filter-dimension-set-value key="guelph" text="University of Guelph"></d2l-filter-dimension-set-value>
|
|
348
|
+
<d2l-filter-dimension-set-value key="manitoba" text="University of Manitoba"></d2l-filter-dimension-set-value>
|
|
349
|
+
</d2l-filter-dimension-set>
|
|
350
|
+
</d2l-filter>
|
|
351
|
+
<d2l-filter>
|
|
352
|
+
<d2l-filter-dimension-set key="format" text="Format">
|
|
353
|
+
<d2l-filter-dimension-set-value key="selfpaced" text="Self-Paced"></d2l-filter-dimension-set-value>
|
|
354
|
+
<d2l-filter-dimension-set-value key="instructor" text="Instructor Lead" selected></d2l-filter-dimension-set-value>
|
|
355
|
+
</d2l-filter-dimension-set>
|
|
356
|
+
</d2l-filter>
|
|
357
|
+
<d2l-filter>
|
|
358
|
+
<d2l-filter-dimension-set key="language" text="Language" selection-single>
|
|
359
|
+
<d2l-filter-dimension-set-value key="english" text="English"></d2l-filter-dimension-set-value>
|
|
360
|
+
<d2l-filter-dimension-set-value key="french" text="French"></d2l-filter-dimension-set-value>
|
|
361
|
+
<d2l-filter-dimension-set-value key="spanish" text="Spanish"></d2l-filter-dimension-set-value>
|
|
362
|
+
</d2l-filter-dimension-set>
|
|
363
|
+
</d2l-filter>
|
|
364
|
+
</d2l-filter-overflow-group>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
<!-- docs: start hidden content -->
|
|
368
|
+
### Properties
|
|
369
|
+
|
|
370
|
+
| Property | Type | Description |
|
|
371
|
+
|---|---|---|
|
|
372
|
+
| `min-to-show` | Number | The minimum number of elements to always show. Please consult the design team when using this attribute. |
|
|
373
|
+
| `max-to-show` | Number | The maximum number of elements to show |
|
|
374
|
+
<!-- docs: end hidden content -->
|
|
304
375
|
|
|
305
376
|
## Filter Dimension: Date [d2l-filter-dimension-date]
|
|
306
377
|
|
|
@@ -1,26 +1,63 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import './filter.js';
|
|
2
|
+
import { css, html, LitElement } from 'lit';
|
|
3
|
+
import { OVERFLOW_CLASS, OverflowGroupMixin } from '../overflow-group/overflow-group-mixin.js';
|
|
4
|
+
import { RtlMixin } from '../../mixins/rtl-mixin.js';
|
|
5
|
+
|
|
6
|
+
function createFilterItem(node) {
|
|
7
|
+
const dimensionSets = node.querySelectorAll('d2l-filter-dimension-set');
|
|
8
|
+
const clones = Array.from(dimensionSets).map((set) => set.cloneNode(true));
|
|
9
|
+
return clones;
|
|
10
|
+
}
|
|
3
11
|
|
|
4
12
|
/**
|
|
5
13
|
* A component that can be used to display a group of filters that will be put into an overflow filter when they no longer fit on the first line of their container
|
|
6
14
|
* @slot - d2l-filters to be added to the container
|
|
7
15
|
*/
|
|
8
|
-
class FilterOverflowGroup extends OverflowGroupMixin(LitElement) {
|
|
16
|
+
class FilterOverflowGroup extends OverflowGroupMixin(RtlMixin(LitElement)) {
|
|
9
17
|
|
|
10
18
|
static get styles() {
|
|
11
19
|
return [super.styles, css`
|
|
12
20
|
::slotted(d2l-filter) {
|
|
13
21
|
margin-right: 0.3rem;
|
|
14
22
|
}
|
|
23
|
+
:host([dir="rtl"]) ::slotted(d2l-filter) {
|
|
24
|
+
margin-left: 0.3rem;
|
|
25
|
+
margin-right: 0;
|
|
26
|
+
}
|
|
15
27
|
`];
|
|
16
28
|
}
|
|
17
29
|
|
|
30
|
+
firstUpdated(changedProperties) {
|
|
31
|
+
super.firstUpdated(changedProperties);
|
|
32
|
+
|
|
33
|
+
this.addEventListener('d2l-filter-change', this._handleFilterChange);
|
|
34
|
+
}
|
|
35
|
+
|
|
18
36
|
convertToOverflowItem(node) {
|
|
19
37
|
const tagName = node.tagName.toLowerCase();
|
|
20
38
|
if (tagName !== 'd2l-filter') console.warn(`d2l-filter-overflow-group: ${tagName} is invalid in this group. This group should only contain d2l-filter direct child elements.`);
|
|
39
|
+
else return createFilterItem(node);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getOverflowContainer(overflowItems) {
|
|
43
|
+
return html`
|
|
44
|
+
<d2l-filter class="${OVERFLOW_CLASS}" @d2l-filter-change="${this._handleFilterChange}">
|
|
45
|
+
${overflowItems}
|
|
46
|
+
</d2l-filter>
|
|
47
|
+
`;
|
|
21
48
|
}
|
|
22
49
|
|
|
23
|
-
|
|
50
|
+
_handleFilterChange(e) {
|
|
51
|
+
const target = (e.target.classList && e.target.classList.contains(OVERFLOW_CLASS)) ? this : e.target;
|
|
52
|
+
e.detail.dimensions.forEach((dimension) => {
|
|
53
|
+
const filterSet = target.querySelector(`d2l-filter-dimension-set[key=${dimension.dimensionKey}`);
|
|
54
|
+
if (!filterSet) return;
|
|
55
|
+
dimension.changes.forEach((change) => {
|
|
56
|
+
const filterSetValue = filterSet.querySelector(`d2l-filter-dimension-set-value[key=${change.valueKey}]`);
|
|
57
|
+
if (!filterSetValue) return;
|
|
58
|
+
filterSetValue.selected = change.selected;
|
|
59
|
+
});
|
|
60
|
+
});
|
|
24
61
|
}
|
|
25
62
|
|
|
26
63
|
}
|
|
@@ -527,6 +527,131 @@
|
|
|
527
527
|
</template>
|
|
528
528
|
</d2l-demo-snippet>
|
|
529
529
|
|
|
530
|
+
<h2>HTML Block (html prop)</h2>
|
|
531
|
+
|
|
532
|
+
<d2l-demo-snippet>
|
|
533
|
+
<template>
|
|
534
|
+
<d2l-html-block html="<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>x</mi>
|
|
535
|
+
<mo>=</mo>
|
|
536
|
+
<mrow>
|
|
537
|
+
<mfrac>
|
|
538
|
+
<mrow>
|
|
539
|
+
<mo>&#x2212;</mo>
|
|
540
|
+
<mi>b</mi>
|
|
541
|
+
<mo>&#xB1;</mo>
|
|
542
|
+
<msqrt>
|
|
543
|
+
<msup>
|
|
544
|
+
<mi>b</mi>
|
|
545
|
+
<mn>2</mn>
|
|
546
|
+
</msup>
|
|
547
|
+
<mo>&#x2212;</mo>
|
|
548
|
+
<mn>4</mn>
|
|
549
|
+
<mi>a</mi>
|
|
550
|
+
<mi>c</mi>
|
|
551
|
+
</msqrt>
|
|
552
|
+
</mrow>
|
|
553
|
+
<mrow>
|
|
554
|
+
<mn>2</mn>
|
|
555
|
+
<mi>a</mi>
|
|
556
|
+
</mrow>
|
|
557
|
+
</mfrac>
|
|
558
|
+
</mrow>
|
|
559
|
+
<mtext>.</mtext>
|
|
560
|
+
<mspace linebreak="newline"></mspace>
|
|
561
|
+
<msup>
|
|
562
|
+
<mi>e</mi>
|
|
563
|
+
<mrow>
|
|
564
|
+
<mi>i</mi>
|
|
565
|
+
<mi>π<!-- π --></mi>
|
|
566
|
+
</mrow>
|
|
567
|
+
</msup>
|
|
568
|
+
<mo>+</mo>
|
|
569
|
+
<mn>1</mn>
|
|
570
|
+
<mo>=</mo>
|
|
571
|
+
<mn>0</mn>
|
|
572
|
+
</math>
|
|
573
|
+
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
|
|
574
|
+
<msup>
|
|
575
|
+
<mrow>
|
|
576
|
+
<mo>(</mo>
|
|
577
|
+
<mrow>
|
|
578
|
+
<munderover>
|
|
579
|
+
<mo>∑<!-- ∑ --></mo>
|
|
580
|
+
<mrow class="MJX-TeXAtom-ORD">
|
|
581
|
+
<mi>k</mi>
|
|
582
|
+
<mo>=</mo>
|
|
583
|
+
<mn>1</mn>
|
|
584
|
+
</mrow>
|
|
585
|
+
<mi>n</mi>
|
|
586
|
+
</munderover>
|
|
587
|
+
<msub>
|
|
588
|
+
<mi>a</mi>
|
|
589
|
+
<mi>k</mi>
|
|
590
|
+
</msub>
|
|
591
|
+
<msub>
|
|
592
|
+
<mi>b</mi>
|
|
593
|
+
<mi>k</mi>
|
|
594
|
+
</msub>
|
|
595
|
+
</mrow>
|
|
596
|
+
<mo>)</mo>
|
|
597
|
+
</mrow>
|
|
598
|
+
<mrow class="MJX-TeXAtom-ORD">
|
|
599
|
+
<mspace width="negativethinmathspace"></mspace>
|
|
600
|
+
<mspace width="negativethinmathspace"></mspace>
|
|
601
|
+
<mn>2</mn>
|
|
602
|
+
</mrow>
|
|
603
|
+
</msup>
|
|
604
|
+
<mo>≤<!-- ≤ --></mo>
|
|
605
|
+
<mrow>
|
|
606
|
+
<mo>(</mo>
|
|
607
|
+
<mrow>
|
|
608
|
+
<munderover>
|
|
609
|
+
<mo>∑<!-- ∑ --></mo>
|
|
610
|
+
<mrow class="MJX-TeXAtom-ORD">
|
|
611
|
+
<mi>k</mi>
|
|
612
|
+
<mo>=</mo>
|
|
613
|
+
<mn>1</mn>
|
|
614
|
+
</mrow>
|
|
615
|
+
<mi>n</mi>
|
|
616
|
+
</munderover>
|
|
617
|
+
<msubsup>
|
|
618
|
+
<mi>a</mi>
|
|
619
|
+
<mi>k</mi>
|
|
620
|
+
<mn>2</mn>
|
|
621
|
+
</msubsup>
|
|
622
|
+
</mrow>
|
|
623
|
+
<mo>)</mo>
|
|
624
|
+
</mrow>
|
|
625
|
+
<mrow>
|
|
626
|
+
<mo>(</mo>
|
|
627
|
+
<mrow>
|
|
628
|
+
<munderover>
|
|
629
|
+
<mo>∑<!-- ∑ --></mo>
|
|
630
|
+
<mrow class="MJX-TeXAtom-ORD">
|
|
631
|
+
<mi>k</mi>
|
|
632
|
+
<mo>=</mo>
|
|
633
|
+
<mn>1</mn>
|
|
634
|
+
</mrow>
|
|
635
|
+
<mi>n</mi>
|
|
636
|
+
</munderover>
|
|
637
|
+
<msubsup>
|
|
638
|
+
<mi>b</mi>
|
|
639
|
+
<mi>k</mi>
|
|
640
|
+
<mn>2</mn>
|
|
641
|
+
</msubsup>
|
|
642
|
+
</mrow>
|
|
643
|
+
<mo>)</mo>
|
|
644
|
+
</mrow>
|
|
645
|
+
</math>
|
|
646
|
+
<div>$$ {\color{red}x} + {\color{blue}y} = {\color{green}z} $$</div>
|
|
647
|
+
<pre class="d2l-code d2l-code-dark"><code class="language-javascript">function helloGrumpy(name) {
|
|
648
|
+
console.log(`Hi there ${name}.`);
|
|
649
|
+
}
|
|
650
|
+
helloGrumpy('Wizard');</code></pre>">
|
|
651
|
+
</d2l-html-block>
|
|
652
|
+
</template>
|
|
653
|
+
</d2l-demo-snippet>
|
|
654
|
+
|
|
530
655
|
<h2>HTML Block (wrapped)</h2>
|
|
531
656
|
|
|
532
657
|
<d2l-demo-snippet>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import '../colors/colors.js';
|
|
2
2
|
import { codeStyles, HtmlBlockCodeRenderer } from '../../helpers/prism.js';
|
|
3
|
-
import { css, LitElement } from 'lit';
|
|
3
|
+
import { css, html, LitElement } from 'lit';
|
|
4
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
4
5
|
import { HtmlAttributeObserverController } from '../../controllers/attributeObserver/htmlAttributeObserverController.js';
|
|
5
6
|
import { HtmlBlockMathRenderer } from '../../helpers/mathjax.js';
|
|
6
7
|
import { requestInstance } from '../../mixins/provider-mixin.js';
|
|
@@ -138,8 +139,14 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
138
139
|
* @type {Boolean}
|
|
139
140
|
*/
|
|
140
141
|
compact: { type: Boolean },
|
|
142
|
+
/**
|
|
143
|
+
* The HTML to be rendered. Ignored if slotted content is provided.
|
|
144
|
+
* @type {String}
|
|
145
|
+
*/
|
|
146
|
+
html: { type: String },
|
|
141
147
|
/**
|
|
142
148
|
* Whether to display the HTML in inline mode
|
|
149
|
+
* @type {Boolean}
|
|
143
150
|
*/
|
|
144
151
|
inline: { type: Boolean },
|
|
145
152
|
/**
|
|
@@ -161,13 +168,17 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
161
168
|
text-align: left;
|
|
162
169
|
}
|
|
163
170
|
:host([inline]),
|
|
164
|
-
:host([inline])
|
|
171
|
+
:host([inline]) .d2l-html-block-rendered {
|
|
165
172
|
display: inline;
|
|
166
173
|
}
|
|
167
174
|
:host([hidden]),
|
|
168
|
-
:host([no-deferred-rendering])
|
|
175
|
+
:host([no-deferred-rendering]) .d2l-html-block-rendered,
|
|
176
|
+
slot {
|
|
169
177
|
display: none;
|
|
170
178
|
}
|
|
179
|
+
:host([no-deferred-rendering]) slot {
|
|
180
|
+
display: contents;
|
|
181
|
+
}
|
|
171
182
|
:host([dir="rtl"]) {
|
|
172
183
|
text-align: right;
|
|
173
184
|
}
|
|
@@ -177,8 +188,10 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
177
188
|
constructor() {
|
|
178
189
|
super();
|
|
179
190
|
this.compact = false;
|
|
191
|
+
this.html = '';
|
|
180
192
|
this.inline = false;
|
|
181
193
|
this.noDeferredRendering = false;
|
|
194
|
+
this._hasSlottedContent = false;
|
|
182
195
|
|
|
183
196
|
const rendererContextAttributes = getRenderers().reduce((attrs, currentRenderer) => {
|
|
184
197
|
if (currentRenderer.contextAttributes) currentRenderer.contextAttributes.forEach(attr => attrs.push(attr));
|
|
@@ -196,7 +209,10 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
196
209
|
|
|
197
210
|
const slot = this.shadowRoot.querySelector('slot');
|
|
198
211
|
if (slot) {
|
|
199
|
-
slot.assignedNodes({ flatten: true })
|
|
212
|
+
const slottedNodes = slot.assignedNodes({ flatten: true });
|
|
213
|
+
this._hasSlottedContent = this._hasSlottedElements(slottedNodes);
|
|
214
|
+
|
|
215
|
+
slottedNodes.forEach(
|
|
200
216
|
node => this._contentObserver.observe(node, { attributes: true, childList: true, subtree: true })
|
|
201
217
|
);
|
|
202
218
|
}
|
|
@@ -209,52 +225,81 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
209
225
|
|
|
210
226
|
firstUpdated(changedProperties) {
|
|
211
227
|
super.firstUpdated(changedProperties);
|
|
228
|
+
this._updateContextKeys();
|
|
229
|
+
}
|
|
212
230
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
+ '"></div><slot'
|
|
219
|
-
+ `${!this.noDeferredRendering ? ' style="display: none"' : ''}`
|
|
220
|
-
+ '></slot>';
|
|
231
|
+
render() {
|
|
232
|
+
const renderContainerClasses = {
|
|
233
|
+
'd2l-html-block-rendered': true,
|
|
234
|
+
'd2l-html-block-compact': this.compact
|
|
235
|
+
};
|
|
221
236
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
237
|
+
return html`
|
|
238
|
+
<div class="${classMap(renderContainerClasses)}"></div>
|
|
239
|
+
<slot @slotchange="${this._handleSlotChange}"></slot>
|
|
240
|
+
`;
|
|
225
241
|
}
|
|
226
242
|
|
|
227
|
-
updated() {
|
|
228
|
-
super.updated();
|
|
229
|
-
if (this.
|
|
243
|
+
async updated(changedProperties) {
|
|
244
|
+
super.updated(changedProperties);
|
|
245
|
+
if (changedProperties.has('html') && this.html !== undefined && this.html !== null && !this._hasSlottedContent) {
|
|
246
|
+
await this._updateRenderContainer();
|
|
247
|
+
}
|
|
248
|
+
if (this._contextChanged()) {
|
|
249
|
+
if (this._hasSlottedContent) this._render();
|
|
250
|
+
else if (this.html !== undefined && this.html !== null) {
|
|
251
|
+
await this._updateRenderContainer();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
this._updateContextKeys();
|
|
255
|
+
}
|
|
230
256
|
}
|
|
231
257
|
|
|
232
|
-
|
|
233
|
-
if (this.
|
|
234
|
-
|
|
258
|
+
_contextChanged() {
|
|
259
|
+
if (!this._contextObserverController) return false;
|
|
260
|
+
|
|
261
|
+
if (this._contextKeys.size !== this._contextObserverController.values.size) return true;
|
|
262
|
+
for (const [attr, val] of this._contextKeys) {
|
|
235
263
|
if (!this._contextObserverController.values.has(attr)) return true;
|
|
236
264
|
if (this._contextObserverController.values.get(attr) !== val) return true;
|
|
237
265
|
}
|
|
238
266
|
return false;
|
|
239
267
|
}
|
|
240
268
|
|
|
269
|
+
async _handleSlotChange(e) {
|
|
270
|
+
if (!e.target || !this.shadowRoot) return;
|
|
271
|
+
const slot = this.shadowRoot.querySelector('slot');
|
|
272
|
+
const slottedNodes = slot.assignedNodes({ flatten: true });
|
|
273
|
+
|
|
274
|
+
if (!this.html && this._hasSlottedElements(slottedNodes)) {
|
|
275
|
+
this._hasSlottedContent = true;
|
|
276
|
+
await this._render(e.target);
|
|
277
|
+
} else {
|
|
278
|
+
this._hasSlottedContent = false;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
_hasSlottedElements(slottedNodes) {
|
|
283
|
+
if (!slottedNodes || slottedNodes.length === 0) return false;
|
|
284
|
+
if (slottedNodes.filter(node => node.nodeType === Node.ELEMENT_NODE || node.textContent).length === 0) return false;
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
|
|
241
288
|
async _processRenderers(elem) {
|
|
242
289
|
for (const renderer of getRenderers()) {
|
|
243
290
|
if (this._contextObserverController && renderer.contextAttributes) {
|
|
244
291
|
const contextValues = new Map();
|
|
245
292
|
renderer.contextAttributes.forEach(attr => contextValues.set(attr, this._contextObserverController.values.get(attr)));
|
|
246
|
-
|
|
293
|
+
await renderer.render(elem, {
|
|
247
294
|
contextValues: contextValues,
|
|
248
295
|
noDeferredRendering: this.noDeferredRendering
|
|
249
296
|
});
|
|
250
297
|
} else {
|
|
251
|
-
|
|
298
|
+
await renderer.render(elem, {
|
|
252
299
|
noDeferredRendering: this.noDeferredRendering
|
|
253
300
|
});
|
|
254
301
|
}
|
|
255
302
|
}
|
|
256
|
-
|
|
257
|
-
return elem;
|
|
258
303
|
}
|
|
259
304
|
|
|
260
305
|
async _render(slot) {
|
|
@@ -274,20 +319,16 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
274
319
|
}
|
|
275
320
|
|
|
276
321
|
_stamp(slot) {
|
|
277
|
-
const
|
|
278
|
-
if (nodes && nodes.length > 0) {
|
|
279
|
-
|
|
280
|
-
let temp = document.createElement('div');
|
|
281
|
-
temp.style.display = 'none';
|
|
282
|
-
nodes.forEach(node => temp.appendChild(node.cloneNode(true)));
|
|
322
|
+
const renderContainer = this.shadowRoot.querySelector('.d2l-html-block-rendered');
|
|
283
323
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
324
|
+
const stampHTML = async nodes => {
|
|
325
|
+
renderContainer.innerHTML = '';
|
|
326
|
+
if (!nodes || nodes.length === 0) return;
|
|
287
327
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
328
|
+
// Nodes must be cloned into the render container before processing, as
|
|
329
|
+
// some renderers require connected nodes (e.g. MathJax).
|
|
330
|
+
nodes.forEach(node => renderContainer.appendChild(node.cloneNode(true)));
|
|
331
|
+
await this._processRenderers(renderContainer);
|
|
291
332
|
};
|
|
292
333
|
|
|
293
334
|
if (this._contentObserver) this._contentObserver.disconnect();
|
|
@@ -303,6 +344,21 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
303
344
|
stampHTML(slottedNodes);
|
|
304
345
|
}
|
|
305
346
|
|
|
347
|
+
_updateContextKeys() {
|
|
348
|
+
if (!this._contextObserverController) return;
|
|
349
|
+
if (!this._contextKeys) this._contextKeys = new Map();
|
|
350
|
+
|
|
351
|
+
this._contextObserverController.values.forEach((val, attr) => {
|
|
352
|
+
this._contextKeys.set(attr, val);
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async _updateRenderContainer() {
|
|
357
|
+
const renderContainer = this.shadowRoot.querySelector('.d2l-html-block-rendered');
|
|
358
|
+
renderContainer.innerHTML = this.html;
|
|
359
|
+
await this._processRenderers(renderContainer);
|
|
360
|
+
}
|
|
361
|
+
|
|
306
362
|
}
|
|
307
363
|
|
|
308
364
|
customElements.define('d2l-html-block', HtmlBlock);
|
|
@@ -2,6 +2,7 @@ import { css, html, nothing } from 'lit';
|
|
|
2
2
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
|
3
3
|
import { offscreenStyles } from '../offscreen/offscreen.js';
|
|
4
4
|
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
|
5
|
+
import { styleMap } from 'lit/directives/style-map.js';
|
|
5
6
|
|
|
6
7
|
export const OVERFLOW_CLASS = 'd2l-overflow-container';
|
|
7
8
|
export const OVERFLOW_MINI_CLASS = 'd2l-overflow-container-mini';
|
|
@@ -28,8 +29,7 @@ export const OverflowGroupMixin = superclass => class extends LocalizeCoreElemen
|
|
|
28
29
|
static get properties() {
|
|
29
30
|
return {
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
-
* @type {boolean}
|
|
32
|
+
* @ignore
|
|
33
33
|
*/
|
|
34
34
|
autoShow: {
|
|
35
35
|
type: Boolean,
|
|
@@ -95,7 +95,9 @@ export const OverflowGroupMixin = superclass => class extends LocalizeCoreElemen
|
|
|
95
95
|
this._handleResize = this._handleResize.bind(this);
|
|
96
96
|
this._resizeObserver = new ResizeObserver((entries) => requestAnimationFrame(() => this._handleResize(entries)));
|
|
97
97
|
|
|
98
|
+
this._hasResized = false;
|
|
98
99
|
this._isObserving = false;
|
|
100
|
+
this._itemHeight = 0;
|
|
99
101
|
this._mini = this.openerType === OPENER_TYPE.ICON;
|
|
100
102
|
this._overflowContainerHidden = false;
|
|
101
103
|
this._slotItems = [];
|
|
@@ -129,8 +131,13 @@ export const OverflowGroupMixin = superclass => class extends LocalizeCoreElemen
|
|
|
129
131
|
}
|
|
130
132
|
});
|
|
131
133
|
|
|
134
|
+
const containerStyles = {
|
|
135
|
+
minHeight: this.autoShow ? 'none' : `${this._itemHeight}px`,
|
|
136
|
+
maxHeight: this.autoShow ? 'none' : `${this._itemHeight}px`
|
|
137
|
+
};
|
|
138
|
+
|
|
132
139
|
return html`
|
|
133
|
-
<div class="d2l-overflow-group-container">
|
|
140
|
+
<div class="d2l-overflow-group-container" style="${styleMap(containerStyles)}">
|
|
134
141
|
<slot @slotchange="${this._handleSlotChange}"></slot>
|
|
135
142
|
${overflowContainer}
|
|
136
143
|
</div>
|
|
@@ -277,12 +284,15 @@ export const OverflowGroupMixin = superclass => class extends LocalizeCoreElemen
|
|
|
277
284
|
|
|
278
285
|
_getItemLayouts(filteredNodes) {
|
|
279
286
|
const items = filteredNodes.map((node) => {
|
|
287
|
+
node.removeAttribute('data-is-chomped');
|
|
280
288
|
const computedStyles = window.getComputedStyle(node);
|
|
289
|
+
const itemHidden = computedStyles.display === 'none';
|
|
290
|
+
this._itemHeight = !itemHidden ? Math.max(this._itemHeight, Math.ceil(parseFloat(computedStyles.height))) : this._itemHeight;
|
|
281
291
|
|
|
282
292
|
return {
|
|
283
293
|
type: node.tagName.toLowerCase(),
|
|
284
294
|
isChomped: false,
|
|
285
|
-
isHidden:
|
|
295
|
+
isHidden: itemHidden,
|
|
286
296
|
width: Math.ceil(parseFloat(computedStyles.width) || 0)
|
|
287
297
|
+ parseInt(computedStyles.marginRight) || 0
|
|
288
298
|
+ parseInt(computedStyles.marginLeft) || 0,
|
|
@@ -316,20 +326,44 @@ export const OverflowGroupMixin = superclass => class extends LocalizeCoreElemen
|
|
|
316
326
|
if (!mutations || mutations.length === 0) return;
|
|
317
327
|
if (this._updateOverflowItemsRequested) return;
|
|
318
328
|
|
|
329
|
+
let isWidthModifyingMutation = false;
|
|
330
|
+
for (const mutation of mutations) {
|
|
331
|
+
if (mutation.attributeName
|
|
332
|
+
&& (mutation.attributeName === 'selected' || mutation.attributeName === 'text')
|
|
333
|
+
) {
|
|
334
|
+
isWidthModifyingMutation = true;
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
319
339
|
this._updateOverflowItemsRequested = true;
|
|
320
340
|
setTimeout(() => {
|
|
321
|
-
this._overflowItems = this._slotItems.map(node => this.convertToOverflowItem(node));
|
|
341
|
+
this._overflowItems = this._slotItems.map((node) => this.convertToOverflowItem(node));
|
|
342
|
+
|
|
343
|
+
// when certain attributes change the corresponding item width can also change and so we need to re-get the layouts and chomp
|
|
344
|
+
if (isWidthModifyingMutation) {
|
|
345
|
+
this._itemLayouts = this._getItemLayouts(this._slotItems);
|
|
346
|
+
this._chomp();
|
|
347
|
+
}
|
|
322
348
|
this._updateOverflowItemsRequested = false;
|
|
323
349
|
this.requestUpdate();
|
|
324
350
|
}, 0);
|
|
325
351
|
}
|
|
326
352
|
|
|
327
|
-
_handleResize(entries) {
|
|
353
|
+
async _handleResize(entries) {
|
|
354
|
+
await (document.fonts ? document.fonts.ready : Promise.resolve()); // computed widths can be incorrect if we don't wait for fonts to load
|
|
328
355
|
this._availableWidth = Math.ceil(entries[0].contentRect.width);
|
|
329
|
-
|
|
356
|
+
|
|
357
|
+
if (!this._hasResized) {
|
|
358
|
+
this._hasResized = true;
|
|
359
|
+
await this._handleSlotChange();
|
|
360
|
+
} else {
|
|
361
|
+
this._chomp();
|
|
362
|
+
}
|
|
330
363
|
}
|
|
331
364
|
|
|
332
365
|
_handleSlotChange() {
|
|
366
|
+
if (!this._hasResized) return;
|
|
333
367
|
requestAnimationFrame(async() => {
|
|
334
368
|
await this._getItems();
|
|
335
369
|
|
|
@@ -56,6 +56,7 @@ function createMenuItemSeparator() {
|
|
|
56
56
|
* A component that can be used to display a set of buttons, links or menus that will be put into a dropdown menu when they no longer fit on the first line of their container
|
|
57
57
|
* @slot - Buttons, dropdown buttons, links or other items to be added to the container
|
|
58
58
|
* @attr {'default'|'icon'} [opener-type="default"] - Set the opener type to 'icon' for a `...` menu icon instead of `More actions` text
|
|
59
|
+
* @attr {boolean} auto-show - Use predefined classes on slot elements to set min and max buttons to show
|
|
59
60
|
*/
|
|
60
61
|
class OverflowGroup extends OverflowGroupMixin(RtlMixin(LitElement)) {
|
|
61
62
|
|
package/custom-elements.json
CHANGED
|
@@ -3364,12 +3364,6 @@
|
|
|
3364
3364
|
"path": "./components/filter/filter-overflow-group.js",
|
|
3365
3365
|
"description": "A component that can be used to display a group of filters that will be put into an overflow filter when they no longer fit on the first line of their container",
|
|
3366
3366
|
"attributes": [
|
|
3367
|
-
{
|
|
3368
|
-
"name": "auto-show",
|
|
3369
|
-
"description": "Use predefined classes on slot elements to set min and max slotted items to show",
|
|
3370
|
-
"type": "boolean",
|
|
3371
|
-
"default": "false"
|
|
3372
|
-
},
|
|
3373
3367
|
{
|
|
3374
3368
|
"name": "max-to-show",
|
|
3375
3369
|
"description": "maximum amount of slotted items to show",
|
|
@@ -3386,8 +3380,6 @@
|
|
|
3386
3380
|
"properties": [
|
|
3387
3381
|
{
|
|
3388
3382
|
"name": "autoShow",
|
|
3389
|
-
"attribute": "auto-show",
|
|
3390
|
-
"description": "Use predefined classes on slot elements to set min and max slotted items to show",
|
|
3391
3383
|
"type": "boolean",
|
|
3392
3384
|
"default": "false"
|
|
3393
3385
|
},
|
|
@@ -3818,10 +3810,16 @@
|
|
|
3818
3810
|
"type": "Boolean",
|
|
3819
3811
|
"default": "false"
|
|
3820
3812
|
},
|
|
3813
|
+
{
|
|
3814
|
+
"name": "html",
|
|
3815
|
+
"description": "The HTML to be rendered. Ignored if slotted content is provided.",
|
|
3816
|
+
"type": "String",
|
|
3817
|
+
"default": "\"\""
|
|
3818
|
+
},
|
|
3821
3819
|
{
|
|
3822
3820
|
"name": "inline",
|
|
3823
3821
|
"description": "Whether to display the HTML in inline mode",
|
|
3824
|
-
"type": "
|
|
3822
|
+
"type": "Boolean",
|
|
3825
3823
|
"default": "false"
|
|
3826
3824
|
},
|
|
3827
3825
|
{
|
|
@@ -3839,11 +3837,18 @@
|
|
|
3839
3837
|
"type": "Boolean",
|
|
3840
3838
|
"default": "false"
|
|
3841
3839
|
},
|
|
3840
|
+
{
|
|
3841
|
+
"name": "html",
|
|
3842
|
+
"attribute": "html",
|
|
3843
|
+
"description": "The HTML to be rendered. Ignored if slotted content is provided.",
|
|
3844
|
+
"type": "String",
|
|
3845
|
+
"default": "\"\""
|
|
3846
|
+
},
|
|
3842
3847
|
{
|
|
3843
3848
|
"name": "inline",
|
|
3844
3849
|
"attribute": "inline",
|
|
3845
3850
|
"description": "Whether to display the HTML in inline mode",
|
|
3846
|
-
"type": "
|
|
3851
|
+
"type": "Boolean",
|
|
3847
3852
|
"default": "false"
|
|
3848
3853
|
},
|
|
3849
3854
|
{
|
|
@@ -8831,12 +8836,6 @@
|
|
|
8831
8836
|
"type": "'default'|'subtle'",
|
|
8832
8837
|
"default": "\"\\\"default\\\"\""
|
|
8833
8838
|
},
|
|
8834
|
-
{
|
|
8835
|
-
"name": "auto-show",
|
|
8836
|
-
"description": "Use predefined classes on slot elements to set min and max slotted items to show",
|
|
8837
|
-
"type": "boolean",
|
|
8838
|
-
"default": "false"
|
|
8839
|
-
},
|
|
8840
8839
|
{
|
|
8841
8840
|
"name": "max-to-show",
|
|
8842
8841
|
"description": "maximum amount of slotted items to show",
|
|
@@ -8854,6 +8853,11 @@
|
|
|
8854
8853
|
"description": "Set the opener type to 'icon' for a `...` menu icon instead of `More actions` text",
|
|
8855
8854
|
"type": "'default'|'icon'",
|
|
8856
8855
|
"default": "\"default\""
|
|
8856
|
+
},
|
|
8857
|
+
{
|
|
8858
|
+
"name": "auto-show",
|
|
8859
|
+
"description": "Use predefined classes on slot elements to set min and max buttons to show",
|
|
8860
|
+
"type": "boolean"
|
|
8857
8861
|
}
|
|
8858
8862
|
],
|
|
8859
8863
|
"properties": [
|
|
@@ -8866,8 +8870,6 @@
|
|
|
8866
8870
|
},
|
|
8867
8871
|
{
|
|
8868
8872
|
"name": "autoShow",
|
|
8869
|
-
"attribute": "auto-show",
|
|
8870
|
-
"description": "Use predefined classes on slot elements to set min and max slotted items to show",
|
|
8871
8873
|
"type": "boolean",
|
|
8872
8874
|
"default": "false"
|
|
8873
8875
|
},
|
package/helpers/mathjax.js
CHANGED
|
@@ -61,35 +61,18 @@ export class HtmlBlockMathRenderer {
|
|
|
61
61
|
// This work-around should be removed when linebreaks are natively supported.
|
|
62
62
|
// MathJax issue: https://github.com/mathjax/MathJax/issues/2312
|
|
63
63
|
// A duplicate that explains our exact issue: https://github.com/mathjax/MathJax/issues/2495
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (options.noDeferredRendering) {
|
|
69
|
-
elem.querySelectorAll('mspace[linebreak="newline"]').forEach(elm => {
|
|
70
|
-
elm.setAttribute('style', lineBreakStyle);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
await window.MathJax.startup.promise;
|
|
74
|
-
renderingPromise = renderingPromise.then(() => window.MathJax.typesetShadow(elem.getRootNode(), elem));
|
|
75
|
-
await renderingPromise;
|
|
76
|
-
return elem;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const inner = elem.innerHTML.replace(/<mspace linebreak="newline">/gi, `<mspace linebreak="newline" style="${lineBreakStyle}">`);
|
|
80
|
-
|
|
81
|
-
const temp = document.createElement('div');
|
|
82
|
-
temp.style.display = 'none';
|
|
83
|
-
temp.attachShadow({ mode: 'open' });
|
|
84
|
-
temp.shadowRoot.innerHTML = `<div><mjx-doc><mjx-head></mjx-head><mjx-body>${inner}</mjx-body></mjx-doc></div>`;
|
|
64
|
+
elem.querySelectorAll('mspace[linebreak="newline"]').forEach(elm => {
|
|
65
|
+
elm.style.display = 'block';
|
|
66
|
+
elm.style.height = '0.5rem';
|
|
67
|
+
});
|
|
85
68
|
|
|
86
|
-
|
|
69
|
+
// If we're using deferred rendering, we need to create a document structure
|
|
70
|
+
// within the element so MathJax can appropriately process math.
|
|
71
|
+
if (!options.noDeferredRendering) elem.innerHTML = `<mjx-doc><mjx-head></mjx-head><mjx-body>${elem.innerHTML}</mjx-body></mjx-doc>`;
|
|
87
72
|
|
|
88
73
|
await window.MathJax.startup.promise;
|
|
89
|
-
renderingPromise = renderingPromise.then(() => window.MathJax.typesetShadow(
|
|
74
|
+
renderingPromise = renderingPromise.then(() => window.MathJax.typesetShadow(elem.getRootNode(), elem));
|
|
90
75
|
await renderingPromise;
|
|
91
|
-
|
|
92
|
-
return temp.shadowRoot.firstChild;
|
|
93
76
|
}
|
|
94
77
|
|
|
95
78
|
}
|
|
@@ -129,12 +112,18 @@ export function loadMathJax(mathJaxConfig) {
|
|
|
129
112
|
const AbstractHandler = window.MathJax._.core.Handler.AbstractHandler.prototype;
|
|
130
113
|
const startup = window.MathJax.startup;
|
|
131
114
|
|
|
115
|
+
const getFirstChild = doc => {
|
|
116
|
+
const child = doc.firstChild;
|
|
117
|
+
if (!child || child.nodeType === Node.ELEMENT_NODE) return child;
|
|
118
|
+
else return child.nextElementSibling;
|
|
119
|
+
};
|
|
120
|
+
|
|
132
121
|
//
|
|
133
122
|
// Extend HTMLAdaptor to handle shadowDOM as the document
|
|
134
123
|
//
|
|
135
124
|
class ShadowAdaptor extends HTMLAdaptor {
|
|
136
125
|
body(doc) {
|
|
137
|
-
return doc.body || (doc
|
|
126
|
+
return doc.body || (getFirstChild(doc) || {}).lastChild || doc;
|
|
138
127
|
}
|
|
139
128
|
create(kind, ns) {
|
|
140
129
|
const document = (this.document.createElement ? this.document : this.window.document);
|
|
@@ -143,10 +132,10 @@ export function loadMathJax(mathJaxConfig) {
|
|
|
143
132
|
document.createElement(kind));
|
|
144
133
|
}
|
|
145
134
|
head(doc) {
|
|
146
|
-
return doc.head || (doc
|
|
135
|
+
return doc.head || (getFirstChild(doc) || {}).firstChild || doc;
|
|
147
136
|
}
|
|
148
137
|
root(doc) {
|
|
149
|
-
return doc.documentElement || doc
|
|
138
|
+
return doc.documentElement || getFirstChild(doc) || doc;
|
|
150
139
|
}
|
|
151
140
|
text(text) {
|
|
152
141
|
const document = (this.document.createTextNode ? this.document : this.window.document);
|
package/helpers/prism.js
CHANGED
|
@@ -450,8 +450,6 @@ export async function formatCodeElement(elem) {
|
|
|
450
450
|
|
|
451
451
|
if (!elem.dataset.language && languageInfo.key !== 'plain') elem.dataset.language = languageInfo.desc;
|
|
452
452
|
Prism.highlightElement(code);
|
|
453
|
-
|
|
454
|
-
return elem;
|
|
455
453
|
}
|
|
456
454
|
|
|
457
455
|
export class HtmlBlockCodeRenderer {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.42.2",
|
|
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",
|