@brightspace-ui/core 3.88.3 → 3.89.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/demo/dropdown-menu.html +7 -0
- package/components/dropdown/demo/dropdown-tabs.html +7 -0
- package/components/dropdown/demo/dropdown.html +7 -2
- package/components/dropdown/dropdown-content.js +32 -15
- package/components/dropdown/dropdown-menu.js +291 -116
- package/components/dropdown/dropdown-opener-mixin.js +21 -6
- package/components/dropdown/dropdown-popover-mixin.js +366 -0
- package/components/dropdown/dropdown-tabs.js +112 -48
- package/components/popover/demo/popover.html +2 -2
- package/components/popover/popover-mixin.js +120 -100
- package/components/tabs/tab-internal.js +3 -12
- package/components/tabs/tab-mixin.js +0 -1
- package/components/tabs/tab.js +0 -1
- package/components/tabs/tabs.js +21 -66
- package/custom-elements.json +17 -36
- package/helpers/flags.js +1 -0
- package/package.json +1 -1
@@ -63,7 +63,7 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
63
63
|
--d2l-popover-default-border-color: var(--d2l-color-mica);
|
64
64
|
--d2l-popover-default-border-radius: 0.3rem;
|
65
65
|
--d2l-popover-default-foreground-color: var(--d2l-color-ferrite);
|
66
|
-
--d2l-popover-default-shadow:
|
66
|
+
--d2l-popover-default-shadow-color: rgba(0, 0, 0, 0.15);
|
67
67
|
background-color: transparent; /* override popover default */
|
68
68
|
border: none; /* override popover */
|
69
69
|
box-sizing: border-box;
|
@@ -75,8 +75,17 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
75
75
|
overflow: visible; /* override popover */
|
76
76
|
padding: 0; /* override popover */
|
77
77
|
position: fixed; /* normalize popover */
|
78
|
+
text-align: start;
|
78
79
|
width: fit-content; /* normalize popover */
|
79
80
|
}
|
81
|
+
:host([theme="dark"]) {
|
82
|
+
--d2l-popover-default-animation-name: d2l-popover-animation-dark;
|
83
|
+
--d2l-popover-default-background-color: #333536; /* tungsten @ 70% */
|
84
|
+
--d2l-popover-default-border-color: var(--d2l-color-tungsten);
|
85
|
+
--d2l-popover-default-foreground-color: var(--d2l-color-sylvite);
|
86
|
+
--d2l-popover-default-shadow-color: rgba(0, 0, 0, 1);
|
87
|
+
opacity: 0.9;
|
88
|
+
}
|
80
89
|
:host([hidden]) {
|
81
90
|
display: none;
|
82
91
|
}
|
@@ -99,8 +108,9 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
99
108
|
background-color: var(--d2l-popover-background-color, var(--d2l-popover-default-background-color));
|
100
109
|
border: 1px solid var(--d2l-popover-border-color, var(--d2l-popover-default-border-color));
|
101
110
|
border-radius: var(--d2l-popover-border-radius, var(--d2l-popover-default-border-radius));
|
102
|
-
box-shadow: var(--d2l-popover-shadow, var(--d2l-popover-default-shadow));
|
111
|
+
box-shadow: 0 2px 12px 0 var(--d2l-popover-shadow-color, var(--d2l-popover-default-shadow-color));
|
103
112
|
box-sizing: border-box;
|
113
|
+
display: flex;
|
104
114
|
max-width: 370px;
|
105
115
|
min-width: 70px;
|
106
116
|
width: 100vw;
|
@@ -109,6 +119,7 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
109
119
|
box-sizing: border-box;
|
110
120
|
display: inline-block;
|
111
121
|
max-width: 100%;
|
122
|
+
min-width: inherit;
|
112
123
|
outline: none;
|
113
124
|
overflow-y: auto;
|
114
125
|
}
|
@@ -142,6 +153,10 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
142
153
|
0% { opacity: 0; transform: translate(0, -10px); }
|
143
154
|
100% { opacity: 1; transform: translate(0, 0); }
|
144
155
|
}
|
156
|
+
@keyframes d2l-popover-animation-dark {
|
157
|
+
0% { opacity: 0; transform: translate(0, -10px); }
|
158
|
+
100% { opacity: 0.9; transform: translate(0, 0); }
|
159
|
+
}
|
145
160
|
@media (prefers-reduced-motion: no-preference) {
|
146
161
|
:host([_opened]) {
|
147
162
|
animation: var(--d2l-popover-animation-name, var(--d2l-popover-default-animation-name)) 300ms ease;
|
@@ -259,6 +274,8 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
259
274
|
|
260
275
|
await this.updateComplete; // wait before applying focus to opener
|
261
276
|
this.#focusOpener();
|
277
|
+
|
278
|
+
/** @ignore */
|
262
279
|
this.dispatchEvent(new CustomEvent('d2l-popover-close', { bubbles: true, composed: true }));
|
263
280
|
|
264
281
|
}
|
@@ -290,7 +307,7 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
290
307
|
this._trapFocus = properties?.trapFocus ?? false;
|
291
308
|
}
|
292
309
|
|
293
|
-
async open(applyFocus = true) {
|
310
|
+
async open(opener, applyFocus = true) {
|
294
311
|
if (this._opened) return;
|
295
312
|
|
296
313
|
const ifrauBackdropService = await tryGetIfrauBackdropService();
|
@@ -306,10 +323,10 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
306
323
|
|
307
324
|
this._previousFocusableAncestor = getPreviousFocusableAncestor(this, false, false);
|
308
325
|
|
309
|
-
this._opener =
|
326
|
+
this._opener = opener;
|
310
327
|
this.#addAutoCloseHandlers();
|
311
328
|
|
312
|
-
await this
|
329
|
+
await this.position();
|
313
330
|
|
314
331
|
this._showBackdrop = this._mobile && this._mobileTrayLocation;
|
315
332
|
if (ifrauBackdropService && this._showBackdrop) {
|
@@ -322,10 +339,99 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
322
339
|
|
323
340
|
this.#addRepositionHandlers();
|
324
341
|
|
342
|
+
/** @ignore */
|
325
343
|
this.dispatchEvent(new CustomEvent('d2l-popover-open', { bubbles: true, composed: true }));
|
326
344
|
|
327
345
|
}
|
328
346
|
|
347
|
+
async position(contentRect, options) {
|
348
|
+
if (!this._opener) return;
|
349
|
+
|
350
|
+
options = Object.assign({ updateLocation: true, updateHeight: true }, options);
|
351
|
+
|
352
|
+
const content = this.#getContentContainer();
|
353
|
+
|
354
|
+
if (!this._noAutoFit && options.updateHeight) {
|
355
|
+
this._contentHeight = null;
|
356
|
+
}
|
357
|
+
|
358
|
+
// don't let popover content horizontally overflow viewport
|
359
|
+
this._width = null;
|
360
|
+
|
361
|
+
await this.updateComplete;
|
362
|
+
|
363
|
+
const adjustPosition = async() => {
|
364
|
+
|
365
|
+
const scrollHeight = document.documentElement.scrollHeight;
|
366
|
+
const openerRect = this._opener.getBoundingClientRect();
|
367
|
+
contentRect = contentRect ?? content.getBoundingClientRect();
|
368
|
+
|
369
|
+
const height = this._minHeight ?? Math.min(this._maxHeight ?? Number.MAX_VALUE, contentRect.height);
|
370
|
+
|
371
|
+
const spaceRequired = {
|
372
|
+
height: height + 10,
|
373
|
+
width: contentRect.width
|
374
|
+
};
|
375
|
+
|
376
|
+
// space in viewport
|
377
|
+
const spaceAround = this.#constrainSpaceAround({
|
378
|
+
// allow for opener offset + outer margin
|
379
|
+
above: openerRect.top - this._offset - this._margin,
|
380
|
+
// allow for opener offset + outer margin
|
381
|
+
below: window.innerHeight - openerRect.bottom - this._offset - this._margin,
|
382
|
+
// allow for outer margin
|
383
|
+
left: openerRect.left - 20,
|
384
|
+
// allow for outer margin
|
385
|
+
right: document.documentElement.clientWidth - openerRect.right - 15
|
386
|
+
}, spaceRequired, openerRect);
|
387
|
+
|
388
|
+
// space in document
|
389
|
+
const spaceAroundScroll = this.#constrainSpaceAround({
|
390
|
+
above: openerRect.top + document.documentElement.scrollTop,
|
391
|
+
below: scrollHeight - openerRect.bottom - document.documentElement.scrollTop
|
392
|
+
}, spaceRequired, openerRect);
|
393
|
+
|
394
|
+
if (options.updateLocation) {
|
395
|
+
this._location = this.#getLocation(spaceAround, spaceAroundScroll, spaceRequired);
|
396
|
+
}
|
397
|
+
|
398
|
+
this._position = this.#getPosition(spaceAround, openerRect, contentRect);
|
399
|
+
if (!this._noPointer) this._pointerPosition = this.#getPointerPosition(openerRect);
|
400
|
+
|
401
|
+
if (options.updateHeight) {
|
402
|
+
|
403
|
+
// calculate height available to the popover contents for overflow because that is the only area capable of scrolling
|
404
|
+
const availableHeight = (this._location === 'block-start') ? spaceAround.above : spaceAround.below;
|
405
|
+
|
406
|
+
if (!this._noAutoFit && availableHeight && availableHeight > 0) {
|
407
|
+
// only apply maximum if it's less than space available and the header/footer alone won't exceed it (content must be visible)
|
408
|
+
this._contentHeight = this._maxHeight !== null && availableHeight > this._maxHeight
|
409
|
+
? this._maxHeight - 2 : availableHeight;
|
410
|
+
|
411
|
+
// ensure the content height has updated when the __toggleScrollStyles event handler runs
|
412
|
+
await this.updateComplete;
|
413
|
+
}
|
414
|
+
|
415
|
+
// todo: handle inline-start and inline-end locations
|
416
|
+
|
417
|
+
}
|
418
|
+
|
419
|
+
/** @ignore */
|
420
|
+
this.dispatchEvent(new CustomEvent('d2l-popover-position', { bubbles: true, composed: true }));
|
421
|
+
|
422
|
+
};
|
423
|
+
|
424
|
+
const scrollWidth = content.scrollWidth;
|
425
|
+
const availableWidth = window.innerWidth - 40;
|
426
|
+
|
427
|
+
this._width = (availableWidth > scrollWidth ? scrollWidth : availableWidth);
|
428
|
+
|
429
|
+
await this.updateComplete;
|
430
|
+
|
431
|
+
await adjustPosition();
|
432
|
+
|
433
|
+
}
|
434
|
+
|
329
435
|
renderPopover(content) {
|
330
436
|
|
331
437
|
const mobileTrayLocation = this._mobile ? this._mobileTrayLocation : null;
|
@@ -392,12 +498,12 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
392
498
|
async resize() {
|
393
499
|
if (!this._opened) return;
|
394
500
|
this._showBackdrop = this._mobile && this._mobileTrayLocation;
|
395
|
-
await this
|
501
|
+
await this.position();
|
396
502
|
}
|
397
503
|
|
398
|
-
toggleOpen(applyFocus = true) {
|
504
|
+
toggleOpen(opener, applyFocus = true) {
|
399
505
|
if (this._opened) return this.close();
|
400
|
-
else return this.open(!this._noAutoFocus && applyFocus);
|
506
|
+
else return this.open(opener, (!this._noAutoFocus && applyFocus));
|
401
507
|
}
|
402
508
|
|
403
509
|
#ifrauContextInfo;
|
@@ -864,7 +970,7 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
864
970
|
#handleFocusTrapEnter() {
|
865
971
|
this.#focusContent(this.#getContentContainer());
|
866
972
|
|
867
|
-
/**
|
973
|
+
/** @ignore */
|
868
974
|
this.dispatchEvent(new CustomEvent('d2l-popover-focus-enter', { detail: { applyFocus: this._applyFocus } }));
|
869
975
|
}
|
870
976
|
|
@@ -872,7 +978,7 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
872
978
|
this._mobile = this.#mediaQueryList.matches;
|
873
979
|
if (this._opened) {
|
874
980
|
this._showBackdrop = this._mobile && this._mobileTrayLocation;
|
875
|
-
await this
|
981
|
+
await this.position();
|
876
982
|
}
|
877
983
|
}
|
878
984
|
|
@@ -880,94 +986,6 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
880
986
|
this.resize();
|
881
987
|
}
|
882
988
|
|
883
|
-
async #position(contentRect, options) {
|
884
|
-
if (!this._opener) return;
|
885
|
-
|
886
|
-
options = Object.assign({ updateLocation: true, updateHeight: true }, options);
|
887
|
-
|
888
|
-
const content = this.#getContentContainer();
|
889
|
-
|
890
|
-
if (!this._noAutoFit && options.updateHeight) {
|
891
|
-
this._contentHeight = null;
|
892
|
-
}
|
893
|
-
|
894
|
-
// don't let popover content horizontally overflow viewport
|
895
|
-
this._width = null;
|
896
|
-
|
897
|
-
await this.updateComplete;
|
898
|
-
|
899
|
-
const adjustPosition = async() => {
|
900
|
-
|
901
|
-
const scrollHeight = document.documentElement.scrollHeight;
|
902
|
-
const openerRect = this._opener.getBoundingClientRect();
|
903
|
-
contentRect = contentRect ?? content.getBoundingClientRect();
|
904
|
-
|
905
|
-
const height = this._minHeight ?? Math.min(this._maxHeight ?? Number.MAX_VALUE, contentRect.height);
|
906
|
-
|
907
|
-
const spaceRequired = {
|
908
|
-
height: height + 10,
|
909
|
-
width: contentRect.width
|
910
|
-
};
|
911
|
-
|
912
|
-
// space in viewport
|
913
|
-
const spaceAround = this.#constrainSpaceAround({
|
914
|
-
// allow for opener offset + outer margin
|
915
|
-
above: openerRect.top - this._offset - this._margin,
|
916
|
-
// allow for opener offset + outer margin
|
917
|
-
below: window.innerHeight - openerRect.bottom - this._offset - this._margin,
|
918
|
-
// allow for outer margin
|
919
|
-
left: openerRect.left - 20,
|
920
|
-
// allow for outer margin
|
921
|
-
right: document.documentElement.clientWidth - openerRect.right - 15
|
922
|
-
}, spaceRequired, openerRect);
|
923
|
-
|
924
|
-
// space in document
|
925
|
-
const spaceAroundScroll = this.#constrainSpaceAround({
|
926
|
-
above: openerRect.top + document.documentElement.scrollTop,
|
927
|
-
below: scrollHeight - openerRect.bottom - document.documentElement.scrollTop
|
928
|
-
}, spaceRequired, openerRect);
|
929
|
-
|
930
|
-
if (options.updateLocation) {
|
931
|
-
this._location = this.#getLocation(spaceAround, spaceAroundScroll, spaceRequired);
|
932
|
-
}
|
933
|
-
|
934
|
-
this._position = this.#getPosition(spaceAround, openerRect, contentRect);
|
935
|
-
if (!this._noPointer) this._pointerPosition = this.#getPointerPosition(openerRect);
|
936
|
-
|
937
|
-
if (options.updateHeight) {
|
938
|
-
|
939
|
-
// calculate height available to the popover contents for overflow because that is the only area capable of scrolling
|
940
|
-
const availableHeight = (this._location === 'block-start') ? spaceAround.above : spaceAround.below;
|
941
|
-
|
942
|
-
if (!this._noAutoFit && availableHeight && availableHeight > 0) {
|
943
|
-
// only apply maximum if it's less than space available and the header/footer alone won't exceed it (content must be visible)
|
944
|
-
this._contentHeight = this._maxHeight !== null && availableHeight > this._maxHeight
|
945
|
-
? this._maxHeight - 2 : availableHeight;
|
946
|
-
|
947
|
-
// ensure the content height has updated when the __toggleScrollStyles event handler runs
|
948
|
-
await this.updateComplete;
|
949
|
-
}
|
950
|
-
|
951
|
-
// todo: handle inline-start and inline-end locations
|
952
|
-
|
953
|
-
}
|
954
|
-
|
955
|
-
/** Dispatched when the popover position finishes adjusting */
|
956
|
-
this.dispatchEvent(new CustomEvent('d2l-popover-position', { bubbles: true, composed: true }));
|
957
|
-
|
958
|
-
};
|
959
|
-
|
960
|
-
const scrollWidth = content.scrollWidth;
|
961
|
-
const availableWidth = window.innerWidth - 40;
|
962
|
-
|
963
|
-
this._width = (availableWidth > scrollWidth ? scrollWidth : availableWidth);
|
964
|
-
|
965
|
-
await this.updateComplete;
|
966
|
-
|
967
|
-
await adjustPosition();
|
968
|
-
|
969
|
-
}
|
970
|
-
|
971
989
|
#removeAutoCloseHandlers() {
|
972
990
|
this.removeEventListener('blur', this.#handleAutoCloseFocusBound, { capture: true });
|
973
991
|
document.body?.removeEventListener('focus', this.#handleAutoCloseFocusBound, { capture: true }); // DE41322: document.body can be null in some scenarios
|
@@ -979,7 +997,9 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
979
997
|
}
|
980
998
|
|
981
999
|
#removeRepositionHandlers() {
|
982
|
-
|
1000
|
+
if (this._opener) {
|
1001
|
+
this._openerIntersectionObserver?.unobserve(this._opener);
|
1002
|
+
}
|
983
1003
|
this._scrollablesObserved?.forEach(node => {
|
984
1004
|
node.removeEventListener('scroll', this.#repositionBound);
|
985
1005
|
});
|
@@ -992,7 +1012,7 @@ export const PopoverMixin = superclass => class extends superclass {
|
|
992
1012
|
// throttle repositioning (https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event#scroll_event_throttling)
|
993
1013
|
if (!this._repositioning) {
|
994
1014
|
requestAnimationFrame(() => {
|
995
|
-
this
|
1015
|
+
this.position(undefined, { updateLocation: false, updateHeight: false });
|
996
1016
|
this._repositioning = false;
|
997
1017
|
});
|
998
1018
|
}
|
@@ -2,7 +2,6 @@ import '../colors/colors.js';
|
|
2
2
|
import { css, html, LitElement, unsafeCSS } from 'lit';
|
3
3
|
import { classMap } from 'lit/directives/class-map.js';
|
4
4
|
import { getFocusPseudoClass } from '../../helpers/focus.js';
|
5
|
-
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
|
6
5
|
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
|
7
6
|
|
8
7
|
const keyCodes = {
|
@@ -10,7 +9,7 @@ const keyCodes = {
|
|
10
9
|
SPACE: 32
|
11
10
|
};
|
12
11
|
|
13
|
-
class Tab extends SkeletonMixin(
|
12
|
+
class Tab extends SkeletonMixin(LitElement) {
|
14
13
|
|
15
14
|
static get properties() {
|
16
15
|
return {
|
@@ -44,11 +43,7 @@ class Tab extends SkeletonMixin(RtlMixin(LitElement)) {
|
|
44
43
|
top: 0.15rem;
|
45
44
|
}
|
46
45
|
:host(:first-child) .d2l-tab-text {
|
47
|
-
margin-
|
48
|
-
}
|
49
|
-
:host([dir="rtl"]:first-child) .d2l-tab-text {
|
50
|
-
margin-left: 0.6rem;
|
51
|
-
margin-right: 0;
|
46
|
+
margin-inline-start: 0;
|
52
47
|
}
|
53
48
|
.d2l-tab-selected-indicator {
|
54
49
|
border-top: 4px solid var(--d2l-color-celestine);
|
@@ -69,13 +64,9 @@ class Tab extends SkeletonMixin(RtlMixin(LitElement)) {
|
|
69
64
|
min-width: 50px;
|
70
65
|
}
|
71
66
|
:host(:first-child) .d2l-tab-selected-indicator {
|
72
|
-
margin-
|
67
|
+
margin-inline-start: 0;
|
73
68
|
width: calc(100% - 0.6rem);
|
74
69
|
}
|
75
|
-
:host([dir="rtl"]:first-child) .d2l-tab-selected-indicator {
|
76
|
-
margin-left: 0.6rem;
|
77
|
-
margin-right: 0;
|
78
|
-
}
|
79
70
|
:host(:${unsafeCSS(getFocusPseudoClass())}) > .d2l-tab-text {
|
80
71
|
border-radius: 0.3rem;
|
81
72
|
box-shadow: 0 0 0 2px var(--d2l-color-celestine);
|
package/components/tabs/tab.js
CHANGED
package/components/tabs/tabs.js
CHANGED
@@ -11,7 +11,6 @@ import { getFocusPseudoClass } from '../../helpers/focus.js';
|
|
11
11
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
12
12
|
import { repeat } from 'lit/directives/repeat.js';
|
13
13
|
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
14
|
-
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
|
15
14
|
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
|
16
15
|
import { styleMap } from 'lit/directives/style-map.js';
|
17
16
|
|
@@ -19,41 +18,13 @@ const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
19
18
|
|
20
19
|
const scrollButtonWidth = 56;
|
21
20
|
|
22
|
-
// remove once IE11 is no longer supported
|
23
|
-
if (!Array.prototype.findIndex) {
|
24
|
-
Object.defineProperty(Array.prototype, 'findIndex', {
|
25
|
-
value: function(predicate) {
|
26
|
-
|
27
|
-
if (this === null) throw new TypeError('"this" is null or not defined');
|
28
|
-
|
29
|
-
const o = Object(this);
|
30
|
-
const len = o.length >>> 0;
|
31
|
-
|
32
|
-
if (typeof predicate !== 'function') throw new TypeError('predicate must be a function');
|
33
|
-
|
34
|
-
const thisArg = arguments[1];
|
35
|
-
let k = 0;
|
36
|
-
|
37
|
-
while (k < len) {
|
38
|
-
const kValue = o[k];
|
39
|
-
if (predicate.call(thisArg, kValue, k, o)) return k;
|
40
|
-
k++;
|
41
|
-
}
|
42
|
-
|
43
|
-
return -1;
|
44
|
-
},
|
45
|
-
configurable: true,
|
46
|
-
writable: true
|
47
|
-
});
|
48
|
-
}
|
49
|
-
|
50
21
|
/**
|
51
22
|
* A component for tabbed content. It supports the "d2l-tab-panel" component for the content, renders tabs responsively, and provides virtual scrolling for large tab lists.
|
52
23
|
* @slot - Contains the tab panels (e.g., "d2l-tab-panel" components)
|
53
24
|
* @slot ext - Additional content (e.g., a button) positioned at right
|
54
25
|
* @fires d2l-tabs-initialized - Dispatched when the component is initialized
|
55
26
|
*/
|
56
|
-
class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(
|
27
|
+
class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))) {
|
57
28
|
|
58
29
|
static get properties() {
|
59
30
|
return {
|
@@ -113,11 +84,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
113
84
|
}
|
114
85
|
.d2l-tabs-container-ext {
|
115
86
|
flex: none;
|
116
|
-
padding-
|
117
|
-
}
|
118
|
-
:host([dir="rtl"]) .d2l-tabs-container-ext {
|
119
|
-
padding-left: 0;
|
120
|
-
padding-right: 4px;
|
87
|
+
padding-inline: 4px 0;
|
121
88
|
}
|
122
89
|
.d2l-tabs-container-list {
|
123
90
|
display: block;
|
@@ -136,27 +103,15 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
136
103
|
z-index: 1;
|
137
104
|
}
|
138
105
|
.d2l-tabs-scroll-previous-container {
|
139
|
-
|
140
|
-
margin-
|
141
|
-
}
|
142
|
-
:host([dir="rtl"]) .d2l-tabs-scroll-previous-container {
|
143
|
-
left: auto;
|
144
|
-
margin-left: 0;
|
145
|
-
margin-right: 4px;
|
146
|
-
right: 0;
|
106
|
+
inset-inline-start: 0;
|
107
|
+
margin-inline: 4px 0;
|
147
108
|
}
|
148
109
|
.d2l-tabs-container[data-allow-scroll-previous] > .d2l-tabs-scroll-previous-container {
|
149
110
|
display: inline-block;
|
150
111
|
}
|
151
112
|
.d2l-tabs-scroll-next-container {
|
152
|
-
|
153
|
-
|
154
|
-
}
|
155
|
-
:host([dir="rtl"]) .d2l-tabs-scroll-next-container {
|
156
|
-
left: 0;
|
157
|
-
margin-left: 4px;
|
158
|
-
margin-right: 0;
|
159
|
-
right: auto;
|
113
|
+
inset-inline-end: 0;
|
114
|
+
margin-inline: 0 4px;
|
160
115
|
}
|
161
116
|
.d2l-tabs-container[data-allow-scroll-next] > .d2l-tabs-scroll-next-container {
|
162
117
|
display: inline-block;
|
@@ -290,7 +245,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
290
245
|
const measures = this._getMeasures();
|
291
246
|
const newTranslationValue = this._calculateScrollPosition(tabInfo, measures);
|
292
247
|
|
293
|
-
if (this
|
248
|
+
if (!this.#isRTL()) {
|
294
249
|
if (newTranslationValue >= 0) return;
|
295
250
|
} else {
|
296
251
|
if (newTranslationValue <= 0) return;
|
@@ -434,8 +389,10 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
434
389
|
const isOverflowingLeft = (selectedTabMeasures.offsetLeft + this._translationValue < 0);
|
435
390
|
const isOverflowingRight = (selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + this._translationValue > measures.tabsContainerRect.width);
|
436
391
|
|
392
|
+
const isRTL = this.#isRTL();
|
393
|
+
|
437
394
|
let getNewTranslationValue;
|
438
|
-
if (
|
395
|
+
if (!isRTL) {
|
439
396
|
getNewTranslationValue = () => {
|
440
397
|
if (selectedTabIndex === 0) {
|
441
398
|
// position selected tab at beginning
|
@@ -471,7 +428,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
471
428
|
let expectedPosition;
|
472
429
|
|
473
430
|
// make sure the new position will not place selected tab behind left scroll button
|
474
|
-
if (
|
431
|
+
if (!isRTL) {
|
475
432
|
expectedPosition = selectedTabMeasures.offsetLeft + newTranslationValue;
|
476
433
|
if (newTranslationValue < 0 && this._isPositionInLeftScrollArea(expectedPosition)) {
|
477
434
|
newTranslationValue = getNewTranslationValue();
|
@@ -483,7 +440,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
483
440
|
}
|
484
441
|
}
|
485
442
|
|
486
|
-
if (
|
443
|
+
if (!isRTL) {
|
487
444
|
// make sure there will not be any empty space between left side of container and first tab
|
488
445
|
if (newTranslationValue > 0) newTranslationValue = 0;
|
489
446
|
} else {
|
@@ -492,7 +449,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
492
449
|
}
|
493
450
|
|
494
451
|
// make sure the new position will not place selected tab behind the right scroll button
|
495
|
-
if (
|
452
|
+
if (!isRTL) {
|
496
453
|
expectedPosition = selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + newTranslationValue;
|
497
454
|
if ((selectedTabIndex < this._tabInfos.length - 1) && this._isPositionInRightScrollArea(expectedPosition, measures)) {
|
498
455
|
newTranslationValue = getNewTranslationValue();
|
@@ -556,13 +513,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
556
513
|
}
|
557
514
|
|
558
515
|
_getTabInfo(id) {
|
559
|
-
|
560
|
-
return this._tabInfos.find((t) => t.id === id);
|
561
|
-
} else {
|
562
|
-
// IE11
|
563
|
-
const index = this._tabInfos.findIndex((t) => t.id === id);
|
564
|
-
return index !== -1 ? this._tabInfos[index] : null;
|
565
|
-
}
|
516
|
+
return this._tabInfos.find((t) => t.id === id);
|
566
517
|
}
|
567
518
|
|
568
519
|
_handleFocusOut(e) {
|
@@ -695,7 +646,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
695
646
|
const lastTabMeasures = measures.tabRects[measures.tabRects.length - 1];
|
696
647
|
let isOverflowingNext;
|
697
648
|
|
698
|
-
if (this
|
649
|
+
if (!this.#isRTL()) {
|
699
650
|
|
700
651
|
newTranslationValue = (this._translationValue - measures.tabsContainerRect.width + scrollButtonWidth);
|
701
652
|
if (newTranslationValue < 0) newTranslationValue += scrollButtonWidth;
|
@@ -738,7 +689,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
738
689
|
let newTranslationValue;
|
739
690
|
let isOverflowingPrevious;
|
740
691
|
|
741
|
-
if (this
|
692
|
+
if (!this.#isRTL()) {
|
742
693
|
|
743
694
|
newTranslationValue = (this._translationValue + measures.tabsContainerRect.width - scrollButtonWidth);
|
744
695
|
isOverflowingPrevious = (newTranslationValue < 0);
|
@@ -921,7 +872,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
921
872
|
return Promise.resolve();
|
922
873
|
}
|
923
874
|
|
924
|
-
if (this
|
875
|
+
if (!this.#isRTL()) {
|
925
876
|
// show/hide scroll buttons
|
926
877
|
this._allowScrollPrevious = (this._translationValue < 0);
|
927
878
|
this._allowScrollNext = (lastTabMeasures.offsetLeft + lastTabMeasures.rect.width + this._translationValue > measures.tabsContainerRect.width);
|
@@ -986,6 +937,10 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(RtlMixin(Lit
|
|
986
937
|
return this.updateComplete;
|
987
938
|
}
|
988
939
|
|
940
|
+
#isRTL() {
|
941
|
+
return document.documentElement.getAttribute('dir') === 'rtl';
|
942
|
+
}
|
943
|
+
|
989
944
|
}
|
990
945
|
|
991
946
|
customElements.define('d2l-tabs', Tabs);
|