@brightspace-ui/core 2.188.0 → 2.189.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.
@@ -136,6 +136,12 @@ The `d2l-collapsible-panel` element is a container that provides specific layout
136
136
  | `panel-title` | String | The title of the panel |
137
137
  | `skeleton` | Boolean | Renders the panel title and the expand/collapse icon as skeleton loaders |
138
138
  | `type` | String | The type of collapsible panel |
139
+
140
+ ### Events
141
+ | Event | Description |
142
+ |--|--|
143
+ | `d2l-collapsible-panel-expand` | Dispatched when the panel is expanded |
144
+ | `d2l-collapsible-panel-collapse` | Dispatched when the panel is collapsed |
139
145
  <!-- docs: end hidden content -->
140
146
 
141
147
  ### Panel Types
@@ -1,12 +1,13 @@
1
1
  import '../colors/colors.js';
2
2
  import { codeStyles, createHtmlBlockRenderer as createCodeRenderer } from '../../helpers/prism.js';
3
- import { css, html, LitElement, unsafeCSS } from 'lit';
3
+ 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
7
  import { HtmlAttributeObserverController } from '../../controllers/attributeObserver/htmlAttributeObserverController.js';
8
-
8
+ import { renderEmbeds } from '../../helpers/embeds.js';
9
9
  import { requestInstance } from '../../mixins/provider/provider-mixin.js';
10
+ import { until } from 'lit/directives/until.js';
10
11
 
11
12
  export const htmlBlockContentStyles = css`
12
13
  .d2l-html-block-rendered {
@@ -231,7 +232,9 @@ class HtmlBlock extends LitElement {
231
232
  };
232
233
 
233
234
  return html`
234
- <div class="${classMap(renderContainerClasses)}"></div>
235
+ <div class="${classMap(renderContainerClasses)}">
236
+ ${(this._embedsFeatureEnabled() && !this.noDeferredRendering) ? until(this._processEmbeds(), nothing) : nothing}
237
+ </div>
235
238
  ${this.noDeferredRendering ? html`<slot @slotchange="${this._handleSlotChange}"></slot>` : ''}
236
239
  `;
237
240
  }
@@ -270,11 +273,21 @@ class HtmlBlock extends LitElement {
270
273
  return false;
271
274
  }
272
275
 
276
+ _embedsFeatureEnabled() {
277
+ return window.D2L?.LP?.Web?.UI?.Flags.Flag('shield-7574-enable-embed-rendering-framework', true);
278
+ }
279
+
273
280
  async _handleSlotChange(e) {
274
281
  if (!e.target || !this.shadowRoot || !this.noDeferredRendering) return;
275
282
  await this._renderInline(e.target);
276
283
  }
277
284
 
285
+ async _processEmbeds() {
286
+ const htmlFragment = document.createRange().createContextualFragment(this.html);
287
+ await renderEmbeds(htmlFragment);
288
+ return htmlFragment;
289
+ }
290
+
278
291
  async _processRenderers(elem) {
279
292
  await this._contextObserverControllerInitialized;
280
293
  const renderers = await getRenderers();
@@ -324,7 +337,7 @@ class HtmlBlock extends LitElement {
324
337
 
325
338
  async _updateRenderContainer() {
326
339
  const renderContainer = this.shadowRoot.querySelector('.d2l-html-block-rendered');
327
- renderContainer.innerHTML = this.html;
340
+ if (!this._embedsFeatureEnabled()) renderContainer.innerHTML = this.html;
328
341
  await this._processRenderers(renderContainer);
329
342
  }
330
343
 
@@ -0,0 +1,102 @@
1
+ import { html, nothing, render } from 'lit';
2
+ import { ifDefined } from 'lit/directives/if-defined.js';
3
+ import { map } from 'lit/directives/map.js';
4
+ import { tryGetPluginByKey } from './plugins.js';
5
+
6
+ const embedTypeAttributeName = 'data-d2l-embed-type';
7
+
8
+ function tryGetEmbedRendererPlugin(embedType) {
9
+ const embedRendererPlugin = tryGetPluginByKey('d2l-html-embed-renderer', embedType);
10
+ if (!embedRendererPlugin) {
11
+ console.warn(`d2l-html-embed-renderer: Can't find plugin for ${embedType} embed type.`);
12
+ }
13
+
14
+ return embedRendererPlugin;
15
+ }
16
+
17
+ export async function createEmbedViewPlaceholder(embedType, props) {
18
+ const embedRendererPlugin = tryGetEmbedRendererPlugin(embedType);
19
+ if (!embedRendererPlugin) return;
20
+
21
+ const placeholderData = await embedRendererPlugin.getViewPlaceholderData(props);
22
+ const contents = placeholderData.contents
23
+ ? map(Object.entries(placeholderData.contents), ([id, content]) => html`<template data-d2l-embed-template-id=${id}>${content}</template>`)
24
+ : nothing;
25
+
26
+ const properties = placeholderData.properties ? JSON.stringify(placeholderData.properties) : undefined;
27
+
28
+ return placeholderData.inline
29
+ ? html`
30
+ <span data-d2l-embed-type="${embedType}" data-d2l-embed-props="${ifDefined(properties)}" style="${placeholderData.style}">
31
+ ${contents}
32
+ </span>
33
+ ` : html`
34
+ <div data-d2l-embed-type="${embedType}" data-d2l-embed-props="${ifDefined(properties)}" style="${placeholderData.style}">
35
+ ${contents}
36
+ </div>
37
+ `;
38
+ }
39
+
40
+ export async function createEmbedEditorPlaceholder(embedType, props) {
41
+ const embedRendererPlugin = tryGetEmbedRendererPlugin(embedType);
42
+ if (!embedRendererPlugin) return;
43
+
44
+ const placeholderData = await embedRendererPlugin.getEditorPlaceholderData(props);
45
+ const text = placeholderData.text || nothing;
46
+
47
+ const properties = placeholderData.properties ? JSON.stringify(placeholderData.properties) : undefined;
48
+
49
+ return placeholderData.inline
50
+ ? html`
51
+ <span
52
+ contentEditable="${ifDefined(placeholderData.contentEditable)}"
53
+ data-d2l-embed-type="${embedType}"
54
+ data-d2l-embed-props="${ifDefined(properties)}"
55
+ style="${placeholderData.style}">
56
+ ${text}
57
+ </span>
58
+ ` : html`
59
+ <div
60
+ contentEditable="${ifDefined(placeholderData.contentEditable)}"
61
+ data-d2l-embed-type="${embedType}"
62
+ data-d2l-embed-props="${ifDefined(properties)}"
63
+ style="${placeholderData.style}">
64
+ ${text}
65
+ </div>
66
+ `;
67
+ }
68
+
69
+ export async function renderEmbeds(node) {
70
+ const placeholders = [...node.querySelectorAll(`div[${embedTypeAttributeName}], span[${embedTypeAttributeName}]`)];
71
+ if (placeholders.length === 0) return;
72
+
73
+ const processPlaceholder = async placeholder => {
74
+ const embedRendererPlugin = tryGetEmbedRendererPlugin(placeholder.dataset.d2lEmbedType);
75
+ if (!embedRendererPlugin) return;
76
+
77
+ const templates = [...placeholder.querySelectorAll('template[data-d2l-embed-template-id]')];
78
+ const processedTemplates = await Promise.all(templates.map(async template => {
79
+ const templateNode = template.content.cloneNode(true);
80
+ await renderEmbeds(templateNode);
81
+ return html`${templateNode}`;
82
+ }));
83
+
84
+ const processedTemplateContents = templates.reduce((acc, template, index) => {
85
+ acc[template.dataset.d2lEmbedTemplateId] = processedTemplates[index];
86
+ return acc;
87
+ }, {});
88
+
89
+ const props = JSON.parse(placeholder.dataset.d2lEmbedProps);
90
+ return embedRendererPlugin.renderView(processedTemplateContents, props);
91
+ };
92
+
93
+ const embeds = await Promise.all(placeholders.map(processPlaceholder));
94
+ placeholders.forEach((placeholder, index) => {
95
+ if (!embeds[index]) {
96
+ console.warn(`d2l-html-embed-renderer: Can't find valid embed for placeholder with ${placeholder.dataset.d2lEmbedType} embed type`);
97
+ }
98
+
99
+ render(embeds[index], placeholder.parentNode, { renderBefore: placeholder });
100
+ placeholder.remove();
101
+ });
102
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.188.0",
3
+ "version": "2.189.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",