@brightspace-ui/core 2.6.2 → 2.7.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.
@@ -67,6 +67,7 @@ To use `d2l-html-block` within another Lit component, use the [unsafeHTML](https
67
67
  ```
68
68
 
69
69
  ### Rendering MathML and LaTeX
70
+
70
71
  Examples are provided to display how user-authored math can be embedded within your webpage.
71
72
 
72
73
  **MathML:**
@@ -99,25 +100,13 @@ Examples are provided to display how user-authored math can be embedded within y
99
100
  </d2l-html-block>
100
101
  ```
101
102
 
102
- **LaTeX:** Rendering LaTeX requires the `us125413-mathjax-render-latex` feature flag to be enabled.
103
+ **LaTeX:** Rendering LaTeX requires the `mathjax` context to be set correctly. For testing and/or demo pages you can do the following.
103
104
 
104
105
  <!-- docs: demo code -->
105
106
  ```html
106
107
  <script type="module">
107
108
  import '@brightspace-ui/core/components/html-block/html-block.js';
108
-
109
- window.D2L = {};
110
- D2L.LP = {};
111
- D2L.LP.Web = {};
112
- D2L.LP.Web.UI = {};
113
- D2L.LP.Web.UI.Flags = {
114
- Flag: (feature, defaultValue) => {
115
- if (feature === 'us125413-mathjax-render-latex') return true;
116
- else return defaultValue;
117
- }
118
- };
119
- <!-- docs: start hidden content -->
120
- document.getElementsByTagName('html')[0].dataset.mathjaxContext = JSON.stringify({ renderLatex: true });<!-- docs: end hidden content -->
109
+ import '@brightspace-ui/core/tools/mathjax-test-context.js';
121
110
  </script>
122
111
  <d2l-html-block>
123
112
  <div class="latex-container">
@@ -125,3 +114,27 @@ Examples are provided to display how user-authored math can be embedded within y
125
114
  </div>
126
115
  </d2l-html-block>
127
116
  ```
117
+
118
+ ### Add Context Automatically to Demos and Tests
119
+
120
+ You can automatically set-up the `mathjax` context for demo pages and unit tests when using `@web/dev-server` and `@web/test-runner` by adding the following plugin to your configuration.
121
+
122
+ ```javascript
123
+ export default {
124
+ ...
125
+ plugins: [{
126
+ name: 'setup-mathjax-context',
127
+ transform(context) {
128
+ if (context.response.is('html')) {
129
+ const newBody = context.body.replace(
130
+ /<head>/,
131
+ '<head><script src="/node_modules/@brightspace-ui/core/tools/mathjax-test-context.js"></script>'
132
+ );
133
+
134
+ return { body: newBody };
135
+ }
136
+ }
137
+ }],
138
+ ...
139
+ }
140
+ ```
@@ -7,6 +7,7 @@
7
7
  <script type="module">
8
8
  import '../../demo/demo-page.js';
9
9
  import '../html-block.js';
10
+
10
11
  import { provideInstance } from '../../../mixins/provider-mixin.js';
11
12
 
12
13
  class DemoReplacementRenderer {
@@ -41,8 +42,8 @@
41
42
  provideInstance(document, 'html-block-renderers', [ new DemoReplacementRenderer() ]);
42
43
 
43
44
  </script>
44
- <script>
45
- document.getElementsByTagName('html')[0].dataset.mathjaxContext = JSON.stringify({ outputScale: 1.1, renderLatex: window.location.search.indexOf('latex=true') !== -1 });
45
+ <script type="module">
46
+ import '../../../tools/mathjax-test-context.js';
46
47
  </script>
47
48
  </head>
48
49
  <body unresolved>
@@ -74,7 +74,9 @@ export const ListItemMixin = superclass => class extends LocalizeCoreElement(Lis
74
74
  _dropdownOpen: { type: Boolean, attribute: '_dropdown-open', reflect: true },
75
75
  _fullscreenWithin: { type: Boolean, attribute: '_fullscreen-within', reflect: true },
76
76
  _hovering: { type: Boolean, reflect: true },
77
+ _hoveringPrimaryAction: { type: Boolean, attribute: '_hovering-primary-action', reflect: true },
77
78
  _focusing: { type: Boolean, reflect: true },
79
+ _focusingPrimaryAction: { type: Boolean, attribute: '_focusing-primary-action', reflect: true },
78
80
  _highlight: { type: Boolean, reflect: true },
79
81
  _highlighting: { type: Boolean, reflect: true },
80
82
  _tooltipShowing: { type: Boolean, attribute: '_tooltip-showing', reflect: true }
@@ -163,8 +165,8 @@ export const ListItemMixin = superclass => class extends LocalizeCoreElement(Lis
163
165
  .d2l-list-item-content ::slotted(*) {
164
166
  margin-top: 0.05rem;
165
167
  }
166
- :host([_hovering]) .d2l-list-item-content,
167
- :host([_focusing]) .d2l-list-item-content {
168
+ :host([_hovering-primary-action]) .d2l-list-item-content,
169
+ :host([_focusing-primary-action]) .d2l-list-item-content {
168
170
  --d2l-list-item-content-text-color: var(--d2l-color-celestine);
169
171
  --d2l-list-item-content-text-decoration: underline;
170
172
  }
@@ -511,11 +513,19 @@ export const ListItemMixin = superclass => class extends LocalizeCoreElement(Lis
511
513
  hasDisplayedKeyboardTooltip = true;
512
514
  }
513
515
 
516
+ _onFocusInPrimaryAction() {
517
+ this._focusingPrimaryAction = true;
518
+ }
519
+
514
520
  _onFocusOut() {
515
521
  this._focusing = false;
516
522
  this._displayKeyboardTooltip = false;
517
523
  }
518
524
 
525
+ _onFocusOutPrimaryAction() {
526
+ this._focusingPrimaryAction = false;
527
+ }
528
+
519
529
  _onFullscreenWithin(e) {
520
530
  if (e.detail.state) this._fullscreenWithinCount += 1;
521
531
  else this._fullscreenWithinCount -= 1;
@@ -527,6 +537,7 @@ export const ListItemMixin = superclass => class extends LocalizeCoreElement(Lis
527
537
  }
528
538
 
529
539
  _onMouseEnterPrimaryAction() {
540
+ this._hoveringPrimaryAction = true;
530
541
  this._hovering = true;
531
542
  }
532
543
 
@@ -535,6 +546,7 @@ export const ListItemMixin = superclass => class extends LocalizeCoreElement(Lis
535
546
  }
536
547
 
537
548
  _onMouseLeavePrimaryAction() {
549
+ this._hoveringPrimaryAction = false;
538
550
  this._hovering = false;
539
551
  }
540
552
 
@@ -572,6 +584,8 @@ export const ListItemMixin = superclass => class extends LocalizeCoreElement(Lis
572
584
  </div>` : nothing }
573
585
  ${primaryAction ? html`
574
586
  <div slot="content-action"
587
+ @focusin="${this._onFocusInPrimaryAction}"
588
+ @focusout="${this._onFocusOutPrimaryAction}"
575
589
  @mouseenter="${this._onMouseEnterPrimaryAction}"
576
590
  @mouseleave="${this._onMouseLeavePrimaryAction}">
577
591
  ${primaryAction}
@@ -101,6 +101,7 @@ The `d2l-tooltip` component is used to display additional information when users
101
101
  | `disable-focus-lock` | Boolean, default: `false` | Disables focus lock so that the tooltip will automatically close when no longer hovered even if it still has focus |
102
102
  | `force-show` | Boolean, default: `false` | Force the tooltip to stay open as long as it remains `true` |
103
103
  | `for-type` | String, default: `descriptor` | Accessibility type for the tooltip to specify whether it is the primary label for the target or a secondary descriptor. Valid values are: `label` and `descriptor`. |
104
+ | `show-truncated-only` | Boolean, default: `false` | Only show the tooltip if we detect the target element is truncated |
104
105
  | `position` | String | Optionally force the tooltip to open in a certain direction. Valid values are: `top`, `bottom`, `left` and `right`. If no position is provided, the tooltip will open in the first position that has enough space for it in the order: bottom, top, right, left. |
105
106
 
106
107
  ### Events
@@ -32,6 +32,26 @@
32
32
  padding: 20px;
33
33
  width: 200px;
34
34
  }
35
+
36
+ .truncated {
37
+ border: 1px solid #cdd5dc;
38
+ border-radius: 6px;
39
+ height: 200px;
40
+ padding: 20px;
41
+ width: 200px;
42
+ }
43
+
44
+ .truncated d2l-button {
45
+ margin-bottom: 20px;
46
+ max-width: 100%;
47
+ }
48
+
49
+ .truncated d2l-button span {
50
+ display: block;
51
+ overflow: hidden;
52
+ text-overflow: ellipsis;
53
+ white-space: nowrap;
54
+ }
35
55
  </style>
36
56
  </head>
37
57
 
@@ -114,6 +134,22 @@
114
134
  </template>
115
135
  </d2l-demo-snippet>
116
136
 
137
+ <h2>Tooltip (only show if truncating)</h2>
138
+ <d2l-demo-snippet>
139
+ <template>
140
+ <div class="truncated">
141
+ <d2l-button id="tooltip-short"><span>Short Tooltip</span></d2l-button>
142
+ <d2l-tooltip for="tooltip-short" show-truncated-only>
143
+ This tooltip will not show.
144
+ </d2l-tooltip>
145
+ <d2l-button id="tooltip-long"><span>Very Very Very Very Long Tooltip</span></d2l-button>
146
+ <d2l-tooltip for="tooltip-long" show-truncated-only>
147
+ Very Very Very Very Long Tooltip - this tooltip will show because the text is truncating.
148
+ </d2l-tooltip>
149
+ </div>
150
+ </template>
151
+ </d2l-demo-snippet>
152
+
117
153
  </d2l-demo-page>
118
154
 
119
155
  </body>
@@ -148,6 +148,11 @@ class Tooltip extends RtlMixin(LitElement) {
148
148
  * @type {number}
149
149
  */
150
150
  offset: { type: Number }, /* tooltipOffset */
151
+ /**
152
+ * ADVANCED: Only show the tooltip if we detect the target element is truncated
153
+ * @type {boolean}
154
+ */
155
+ showTruncatedOnly: { type: Boolean, attribute: 'show-truncated-only' },
151
156
  /**
152
157
  * ADVANCED: Force the tooltip to open in a certain direction. If no position is provided, the tooltip will open in the first position that has enough space for it in the order: bottom, top, right, left.
153
158
  * @type {'top'|'bottom'|'left'|'right'}
@@ -390,11 +395,13 @@ class Tooltip extends RtlMixin(LitElement) {
390
395
  this.forceShow = false;
391
396
  this.forType = 'descriptor';
392
397
  this.offset = pointerRotatedOverhang + pointerGap;
398
+ this.showTruncatedOnly = false;
393
399
  this.state = 'info';
394
400
 
395
401
  this._dismissibleId = null;
396
402
  this._isFocusing = false;
397
403
  this._isHovering = false;
404
+ this._resizeRunSinceTruncationCheck = false;
398
405
  this._viewportMargin = defaultViewportMargin;
399
406
  }
400
407
 
@@ -749,7 +756,12 @@ class Tooltip extends RtlMixin(LitElement) {
749
756
  }
750
757
  }
751
758
 
752
- _onTargetFocus() {
759
+ async _onTargetFocus() {
760
+ if (this.showTruncatedOnly) {
761
+ await this._updateTruncating();
762
+ if (!this._truncating) return;
763
+ }
764
+
753
765
  if (this.disableFocusLock) {
754
766
  this.showing = true;
755
767
  } else {
@@ -759,7 +771,12 @@ class Tooltip extends RtlMixin(LitElement) {
759
771
  }
760
772
 
761
773
  _onTargetMouseEnter() {
762
- this._hoverTimeout = setTimeout(() => {
774
+ this._hoverTimeout = setTimeout(async() => {
775
+ if (this.showTruncatedOnly) {
776
+ await this._updateTruncating();
777
+ if (!this._truncating) return;
778
+ }
779
+
763
780
  resetDelayTimeout();
764
781
  this._isHovering = true;
765
782
  this._updateShowing();
@@ -773,6 +790,7 @@ class Tooltip extends RtlMixin(LitElement) {
773
790
  }
774
791
 
775
792
  _onTargetResize() {
793
+ this._resizeRunSinceTruncationCheck = true;
776
794
  if (!this.showing) {
777
795
  return;
778
796
  }
@@ -863,5 +881,41 @@ class Tooltip extends RtlMixin(LitElement) {
863
881
  }
864
882
  this._addListeners();
865
883
  }
884
+
885
+ /**
886
+ * This solution appends a clone of the target to the target in order to retain target styles.
887
+ * A possible consequence of this is unexpected behaviours for web components that have slots.
888
+ * If this becomes an issue, it would also likely be possible to append the clone to document.body
889
+ * and get the expected styles through getComputedStyle.
890
+ */
891
+ async _updateTruncating() {
892
+ // if no resize has happened since truncation was previously calculated the result will not have changed
893
+ if (!this._resizeRunSinceTruncationCheck || !this.showTruncatedOnly) return;
894
+
895
+ const target = this._target;
896
+ const cloneContainer = document.createElement('div');
897
+ cloneContainer.style.position = 'absolute';
898
+ cloneContainer.style.overflow = 'hidden';
899
+ cloneContainer.style.whiteSpace = 'nowrap';
900
+ cloneContainer.style.width = '1px';
901
+
902
+ if (this.getAttribute('dir') === 'rtl') {
903
+ cloneContainer.style.right = '-10000px';
904
+ } else {
905
+ cloneContainer.style.left = '-10000px';
906
+ }
907
+
908
+ const clone = target.cloneNode(true);
909
+ clone.removeAttribute('id');
910
+ clone.style.maxWidth = 'none';
911
+
912
+ cloneContainer.appendChild(clone);
913
+ target.appendChild(cloneContainer);
914
+ await this.updateComplete;
915
+
916
+ this._truncating = clone.scrollWidth > target.offsetWidth;
917
+ this._resizeRunSinceTruncationCheck = false;
918
+ target.removeChild(cloneContainer);
919
+ }
866
920
  }
867
921
  customElements.define('d2l-tooltip', Tooltip);
@@ -9919,6 +9919,12 @@
9919
9919
  "description": "Adjust the size of the gap between the tooltip and its target",
9920
9920
  "type": "number"
9921
9921
  },
9922
+ {
9923
+ "name": "show-truncated-only",
9924
+ "description": "ADVANCED: Only show the tooltip if we detect the target element is truncated",
9925
+ "type": "boolean",
9926
+ "default": "false"
9927
+ },
9922
9928
  {
9923
9929
  "name": "state",
9924
9930
  "description": "The style of the tooltip based on the type of information it displays",
@@ -9996,6 +10002,13 @@
9996
10002
  "description": "Adjust the size of the gap between the tooltip and its target",
9997
10003
  "type": "number"
9998
10004
  },
10005
+ {
10006
+ "name": "showTruncatedOnly",
10007
+ "attribute": "show-truncated-only",
10008
+ "description": "ADVANCED: Only show the tooltip if we detect the target element is truncated",
10009
+ "type": "boolean",
10010
+ "default": "false"
10011
+ },
9999
10012
  {
10000
10013
  "name": "state",
10001
10014
  "attribute": "state",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.6.2",
3
+ "version": "2.7.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",
@@ -1,4 +1,8 @@
1
- document.documentElement.dataset.mathjaxContext = JSON.stringify({
1
+ console.warn('Using mathjax test context, this is intended for demo pages and tests only');
2
+
3
+ const disabled = window.location.search.indexOf('latex=false') !== -1;
4
+
5
+ document.getElementsByTagName('html')[0].dataset.mathjaxContext = JSON.stringify({
2
6
  outputScale: 1.1,
3
- renderLatex: true
7
+ renderLatex: !disabled
4
8
  });