@brightspace-ui/core 3.15.0 → 3.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/dropdown/dropdown-content-mixin.js +20 -16
- package/components/dropdown/dropdown-menu.js +1 -1
- package/components/dropdown/dropdown-tabs.js +2 -2
- package/components/html-block/demo/html-block.html +1 -3
- package/components/html-block/html-block.js +23 -52
- package/helpers/mathjax.js +5 -7
- package/package.json +2 -2
- package/tools/mathjax-test-context.js +3 -1
- package/controllers/attributeObserver/htmlAttributeObserverController.js +0 -50
@@ -698,7 +698,9 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
|
|
698
698
|
}
|
699
699
|
}
|
700
700
|
|
701
|
-
async __position(
|
701
|
+
async __position(contentRect, options) {
|
702
|
+
|
703
|
+
options = Object.assign({ updateAboveBelow: true, updateHeight: true }, options);
|
702
704
|
|
703
705
|
const opener = this.__getOpener();
|
704
706
|
if (!opener) {
|
@@ -713,7 +715,7 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
|
|
713
715
|
const header = this.__getContentTop(); // todo: rename
|
714
716
|
const footer = this.__getContentBottom(); // todo: rename
|
715
717
|
|
716
|
-
if (!this.noAutoFit) {
|
718
|
+
if (!this.noAutoFit && options.updateHeight) {
|
717
719
|
this._contentHeight = null;
|
718
720
|
}
|
719
721
|
|
@@ -783,25 +785,27 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
|
|
783
785
|
|
784
786
|
}
|
785
787
|
|
786
|
-
if (
|
788
|
+
if (options.updateAboveBelow) {
|
787
789
|
this.openedAbove = this._getOpenedAbove(spaceAround, spaceAroundScroll, spaceRequired);
|
788
790
|
}
|
789
791
|
|
790
792
|
this._position = this._getPosition(spaceAround, targetRect, contentRect);
|
791
793
|
this._pointerPosition = this._getPointerPosition(targetRect);
|
792
794
|
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
795
|
+
if (options.updateHeight) {
|
796
|
+
// calculate height available to the dropdown contents for overflow because that is the only area capable of scrolling
|
797
|
+
const availableHeight = this.openedAbove ? spaceAround.above : spaceAround.below;
|
798
|
+
if (!this.noAutoFit && availableHeight && availableHeight > 0) {
|
799
|
+
// only apply maximum if it's less than space available and the header/footer alone won't exceed it (content must be visible)
|
800
|
+
this._contentHeight = this.maxHeight !== null
|
801
|
+
&& availableHeight > this.maxHeight
|
802
|
+
&& headerFooterHeight < this.maxHeight
|
803
|
+
? this.maxHeight - headerFooterHeight - 2
|
804
|
+
: availableHeight - headerFooterHeight;
|
805
|
+
|
806
|
+
// ensure the content height has updated when the __toggleScrollStyles event handler runs
|
807
|
+
await this.updateComplete;
|
808
|
+
}
|
805
809
|
}
|
806
810
|
|
807
811
|
/** Dispatched when the dropdown position finishes adjusting */
|
@@ -832,7 +836,7 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
|
|
832
836
|
// throttle repositioning (https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event#scroll_event_throttling)
|
833
837
|
if (!this.__repositioning) {
|
834
838
|
requestAnimationFrame(() => {
|
835
|
-
this.__position(
|
839
|
+
this.__position(undefined, { updateAboveBelow: false, updateHeight: false });
|
836
840
|
this.__repositioning = false;
|
837
841
|
});
|
838
842
|
}
|
@@ -148,7 +148,7 @@ class DropdownMenu extends ThemeMixin(DropdownContentMixin(LitElement)) {
|
|
148
148
|
this.maxHeight = this._maxHeightNonTray;
|
149
149
|
}
|
150
150
|
|
151
|
-
this.__position(
|
151
|
+
this.__position(e.detail, { updateAboveBelow: this._initializingHeight });
|
152
152
|
this._initializingHeight = false;
|
153
153
|
|
154
154
|
const menu = this.__getMenuElement();
|
@@ -46,7 +46,7 @@ class DropdownTabs extends DropdownContentMixin(LitElement) {
|
|
46
46
|
height: e.detail.height + tabListRect.height + 52,
|
47
47
|
width: e.detail.width
|
48
48
|
};
|
49
|
-
this.__position(
|
49
|
+
this.__position(rect, { updateAboveBelow: this._initializingHeight });
|
50
50
|
this._initializingHeight = false;
|
51
51
|
}
|
52
52
|
|
@@ -56,7 +56,7 @@ class DropdownTabs extends DropdownContentMixin(LitElement) {
|
|
56
56
|
}
|
57
57
|
|
58
58
|
_onTabSelected() {
|
59
|
-
this.__position(
|
59
|
+
this.__position();
|
60
60
|
}
|
61
61
|
|
62
62
|
}
|
@@ -5,6 +5,7 @@
|
|
5
5
|
<meta charset="UTF-8">
|
6
6
|
<link rel="stylesheet" href="../../demo/styles.css" type="text/css">
|
7
7
|
<script type="module">
|
8
|
+
import '../../../tools/mathjax-test-context.js';
|
8
9
|
import '../../demo/demo-page.js';
|
9
10
|
import '../html-block.js';
|
10
11
|
|
@@ -46,9 +47,6 @@
|
|
46
47
|
});
|
47
48
|
|
48
49
|
</script>
|
49
|
-
<script type="module">
|
50
|
-
import '../../../tools/mathjax-test-context.js';
|
51
|
-
</script>
|
52
50
|
</head>
|
53
51
|
<body unresolved>
|
54
52
|
|
@@ -4,9 +4,9 @@ import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
|
|
4
4
|
import { classMap } from 'lit/directives/class-map.js';
|
5
5
|
import { createHtmlBlockRenderer as createMathRenderer } from '../../helpers/mathjax.js';
|
6
6
|
import { getFocusPseudoClass } from '../../helpers/focus.js';
|
7
|
-
import { HtmlAttributeObserverController } from '../../controllers/attributeObserver/htmlAttributeObserverController.js';
|
8
7
|
import { renderEmbeds } from '../../helpers/embeds.js';
|
9
8
|
import { requestInstance } from '../../mixins/provider/provider-mixin.js';
|
9
|
+
import { tryGet } from '@brightspace-ui/lms-context-provider/client.js';
|
10
10
|
import { until } from 'lit/directives/until.js';
|
11
11
|
|
12
12
|
export const htmlBlockContentStyles = css`
|
@@ -166,7 +166,8 @@ class HtmlBlock extends LitElement {
|
|
166
166
|
* unless your HTML relies on script executions that may break upon stamping.
|
167
167
|
* @type {Boolean}
|
168
168
|
*/
|
169
|
-
noDeferredRendering: { type: Boolean, attribute: 'no-deferred-rendering' }
|
169
|
+
noDeferredRendering: { type: Boolean, attribute: 'no-deferred-rendering' },
|
170
|
+
_context: { type: Object, state: true }
|
170
171
|
};
|
171
172
|
}
|
172
173
|
|
@@ -201,26 +202,28 @@ class HtmlBlock extends LitElement {
|
|
201
202
|
this.inline = false;
|
202
203
|
this.noDeferredRendering = false;
|
203
204
|
|
204
|
-
this.
|
205
|
-
this.
|
206
|
-
|
207
|
-
});
|
205
|
+
this._context = new Map();
|
206
|
+
this._initialContextResolve = undefined;
|
207
|
+
this._initialContextPromise = new Promise(resolve => this._initialContextResolve = resolve);
|
208
208
|
|
209
209
|
this._renderersProcessedResolve = undefined;
|
210
210
|
this._renderersProcessedPromise = new Promise(resolve => this._renderersProcessedResolve = resolve);
|
211
211
|
|
212
|
-
getRenderers().then(renderers => renderers.reduce((
|
213
|
-
if (currentRenderer.
|
214
|
-
return
|
215
|
-
}, []))
|
216
|
-
|
217
|
-
|
212
|
+
const contextKeysPromise = getRenderers().then(renderers => renderers.reduce((keys, currentRenderer) => {
|
213
|
+
if (currentRenderer.contextKeys) currentRenderer.contextKeys.forEach(key => keys.push(key));
|
214
|
+
return keys;
|
215
|
+
}, []));
|
216
|
+
|
217
|
+
const contextValsPromise = contextKeysPromise.then(contextKeys => {
|
218
|
+
return Promise.allSettled(contextKeys.map(key => {
|
219
|
+
return tryGet(key, undefined, ctx => this._context.set(key, ctx));
|
220
|
+
}));
|
218
221
|
});
|
219
|
-
}
|
220
222
|
|
221
|
-
|
222
|
-
|
223
|
-
|
223
|
+
Promise.all([contextKeysPromise, contextValsPromise]).then(([contextKeys, contextResults]) => {
|
224
|
+
contextKeys.forEach((key, index) => this._context.set(key, contextResults[index].value));
|
225
|
+
this._initialContextResolve();
|
226
|
+
});
|
224
227
|
}
|
225
228
|
|
226
229
|
render() {
|
@@ -248,38 +251,15 @@ class HtmlBlock extends LitElement {
|
|
248
251
|
|
249
252
|
async updated(changedProperties) {
|
250
253
|
super.updated(changedProperties);
|
251
|
-
if (changedProperties.has('html') && this.html !== undefined && this.html !== null && !this.noDeferredRendering) {
|
254
|
+
if ((changedProperties.has('html') || changedProperties.has('_context')) && this.html !== undefined && this.html !== null && !this.noDeferredRendering) {
|
252
255
|
await this._updateRenderContainer();
|
253
256
|
}
|
254
|
-
if (await this._contextChanged()) {
|
255
|
-
if (this.noDeferredRendering) this._renderInline();
|
256
|
-
else if (this.html !== undefined && this.html !== null) {
|
257
|
-
await this._updateRenderContainer();
|
258
|
-
}
|
259
|
-
|
260
|
-
this._updateContextKeys();
|
261
|
-
}
|
262
257
|
}
|
263
258
|
|
264
259
|
async getLoadingComplete() {
|
265
260
|
return this._renderersProcessedPromise;
|
266
261
|
}
|
267
262
|
|
268
|
-
async _contextChanged() {
|
269
|
-
await this._contextObserverControllerInitialized;
|
270
|
-
if (!this._contextKeys) {
|
271
|
-
this._updateContextKeys();
|
272
|
-
return true;
|
273
|
-
}
|
274
|
-
|
275
|
-
if (this._contextKeys.size !== this._contextObserverController.values.size) return true;
|
276
|
-
for (const [attr, val] of this._contextKeys) {
|
277
|
-
if (!this._contextObserverController.values.has(attr)) return true;
|
278
|
-
if (this._contextObserverController.values.get(attr) !== val) return true;
|
279
|
-
}
|
280
|
-
return false;
|
281
|
-
}
|
282
|
-
|
283
263
|
_embedsFeatureEnabled() {
|
284
264
|
return window.D2L?.LP?.Web?.UI?.Flags.Flag('shield-7574-enable-embed-rendering-framework', true);
|
285
265
|
}
|
@@ -296,13 +276,13 @@ class HtmlBlock extends LitElement {
|
|
296
276
|
}
|
297
277
|
|
298
278
|
async _processRenderers(elem) {
|
299
|
-
await this.
|
279
|
+
await this._initialContextPromise;
|
300
280
|
const renderers = await getRenderers();
|
301
281
|
const loadingCompletePromises = [];
|
302
282
|
for (const renderer of renderers) {
|
303
|
-
if (renderer.
|
283
|
+
if (renderer.contextKeys) {
|
304
284
|
const contextValues = new Map();
|
305
|
-
renderer.
|
285
|
+
renderer.contextKeys.forEach(key => contextValues.set(key, this._context.get(key)));
|
306
286
|
await renderer.render(elem, {
|
307
287
|
contextValues: contextValues,
|
308
288
|
noDeferredRendering: this.noDeferredRendering
|
@@ -333,15 +313,6 @@ class HtmlBlock extends LitElement {
|
|
333
313
|
await this._processRenderers(noDeferredRenderingContainer);
|
334
314
|
}
|
335
315
|
|
336
|
-
_updateContextKeys() {
|
337
|
-
if (!this._contextObserverController) return;
|
338
|
-
if (!this._contextKeys) this._contextKeys = new Map();
|
339
|
-
|
340
|
-
this._contextObserverController.values.forEach((val, attr) => {
|
341
|
-
this._contextKeys.set(attr, val);
|
342
|
-
});
|
343
|
-
}
|
344
|
-
|
345
316
|
async _updateRenderContainer() {
|
346
317
|
const renderContainer = this.shadowRoot.querySelector('.d2l-html-block-rendered');
|
347
318
|
if (!this._embedsFeatureEnabled()) renderContainer.innerHTML = this.html;
|
package/helpers/mathjax.js
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
* match what's present in the MathJax-src repo.
|
4
4
|
*/
|
5
5
|
|
6
|
-
const
|
6
|
+
const mathjaxContextKey = 'd2l-mathjax';
|
7
7
|
const mathjaxBaseUrl = 'https://s.brightspace.com/lib/mathjax/3.2.2';
|
8
8
|
|
9
9
|
const mathjaxFontMappings = new Map([
|
@@ -32,16 +32,14 @@ const mathjaxFontMappings = new Map([
|
|
32
32
|
|
33
33
|
class HtmlBlockMathRenderer {
|
34
34
|
|
35
|
-
get
|
36
|
-
return [
|
35
|
+
get contextKeys() {
|
36
|
+
return [mathjaxContextKey];
|
37
37
|
}
|
38
38
|
|
39
39
|
async render(elem, options) {
|
40
40
|
if (!options.contextValues) return elem;
|
41
|
-
const
|
42
|
-
if (
|
43
|
-
|
44
|
-
const context = JSON.parse(contextVal) || {};
|
41
|
+
const context = options.contextValues.get(mathjaxContextKey);
|
42
|
+
if (context === undefined) return elem;
|
45
43
|
|
46
44
|
if (!elem.querySelector('math') && !(context.renderLatex && /\$\$|\\\(|\\\[|\\begin{|\\ref{|\\eqref{/.test(elem.innerHTML))) return elem;
|
47
45
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.16.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",
|
@@ -47,7 +47,6 @@
|
|
47
47
|
"devDependencies": {
|
48
48
|
"@brightspace-ui/stylelint-config": "^1",
|
49
49
|
"@brightspace-ui/testing": "^1",
|
50
|
-
"@open-wc/semantic-dom-diff": "^0.20",
|
51
50
|
"@rollup/plugin-dynamic-import-vars": "^2",
|
52
51
|
"@rollup/plugin-node-resolve": "^15",
|
53
52
|
"@rollup/plugin-replace": "^5",
|
@@ -67,6 +66,7 @@
|
|
67
66
|
},
|
68
67
|
"dependencies": {
|
69
68
|
"@brightspace-ui/intl": "^3",
|
69
|
+
"@brightspace-ui/lms-context-provider": "^1",
|
70
70
|
"@formatjs/intl-pluralrules": "^1",
|
71
71
|
"@open-wc/dedupe-mixin": "^1",
|
72
72
|
"ifrau": "^0.41",
|
@@ -1,6 +1,8 @@
|
|
1
|
+
import { addContext } from '@brightspace-ui/lms-context-provider/test-helpers/test-host.js';
|
2
|
+
|
1
3
|
console.warn('Using mathjax test context, this is intended for demo pages and tests only');
|
2
4
|
|
3
|
-
|
5
|
+
addContext('d2l-mathjax', {
|
4
6
|
outputScale: 1.1,
|
5
7
|
renderLatex: !(window.location.search.indexOf('latex=false') !== -1),
|
6
8
|
enableMML3Support: true
|
@@ -1,50 +0,0 @@
|
|
1
|
-
const controllerCallbacks = new Map();
|
2
|
-
|
3
|
-
const contextObserver = new MutationObserver(mutations => {
|
4
|
-
controllerCallbacks.forEach(callback => callback(
|
5
|
-
mutations.map(mutation => mutation.attributeName)
|
6
|
-
));
|
7
|
-
});
|
8
|
-
|
9
|
-
export class HtmlAttributeObserverController {
|
10
|
-
|
11
|
-
constructor(host, ...attributes) {
|
12
|
-
if (attributes.length === 0) throw new Error(
|
13
|
-
'Can\'t construct controller; must supply at least one observed attribute.'
|
14
|
-
);
|
15
|
-
|
16
|
-
this._host = host;
|
17
|
-
this._attributes = attributes;
|
18
|
-
this.values = new Map();
|
19
|
-
host.addController(this);
|
20
|
-
}
|
21
|
-
|
22
|
-
hostConnected() {
|
23
|
-
this._updateAttributeValues(this._attributes);
|
24
|
-
if (controllerCallbacks.size === 0) contextObserver.observe(document.documentElement, { attributes: true });
|
25
|
-
controllerCallbacks.set(this, this._handleContextChange.bind(this));
|
26
|
-
}
|
27
|
-
|
28
|
-
hostDisconnected() {
|
29
|
-
controllerCallbacks.delete(this);
|
30
|
-
}
|
31
|
-
|
32
|
-
_handleContextChange(attributeNames) {
|
33
|
-
const attributes = attributeNames.filter(attr => this._attributes.includes(attr));
|
34
|
-
if (attributes.length === 0) return;
|
35
|
-
this._updateAttributeValues(attributes);
|
36
|
-
this._host.requestUpdate();
|
37
|
-
}
|
38
|
-
|
39
|
-
_updateAttributeValues(names) {
|
40
|
-
names.forEach(name => {
|
41
|
-
this.values.set(
|
42
|
-
name,
|
43
|
-
document.documentElement.hasAttribute(name)
|
44
|
-
? document.documentElement.getAttribute(name)
|
45
|
-
: undefined
|
46
|
-
);
|
47
|
-
});
|
48
|
-
}
|
49
|
-
|
50
|
-
}
|