@brightspace-ui/core 2.75.3 → 2.75.5
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/demo/demo-passthrough-mixin.js +25 -0
- package/components/table/README.md +10 -18
- package/components/table/demo/table-test.js +5 -24
- package/components/table/table-header.js +10 -0
- package/custom-elements.json +53 -11
- package/package.json +1 -1
- package/templates/primary-secondary/primary-secondary.js +160 -77
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a Lit component that mirrors properties of another, and passes its properties through to
|
|
5
|
+
* a specific rendered element.
|
|
6
|
+
*
|
|
7
|
+
* @param superclass The Lit class to mirror (will copy all its properties).
|
|
8
|
+
* @param { String } target The element name or other selector string of the element to pass properties to.
|
|
9
|
+
*/
|
|
10
|
+
export const DemoPassthroughMixin = (superclass, target) => class extends LitElement {
|
|
11
|
+
static get properties() {
|
|
12
|
+
return Object.fromEntries(superclass.elementProperties);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
firstUpdated() {
|
|
16
|
+
this.target = this.shadowRoot.querySelector(target);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
updated(changedProperties) {
|
|
20
|
+
const propertyDefinitions = superclass.elementProperties;
|
|
21
|
+
changedProperties.forEach((_value, key) => {
|
|
22
|
+
if (propertyDefinitions.get(key)?.attribute !== false) this.target[key] = this[key];
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -29,7 +29,7 @@ Tables are used to display tabular data in rows and columns. They can allow user
|
|
|
29
29
|
## Responsive Behavior
|
|
30
30
|
If the browser window is too narrow to display the table’s contents, a scroll button appears. This alerts users to overflowing content and provides a way for users to scroll horizontally. The scroll button sticks to the top of the screen so that it's available as long as the table is in the viewport.
|
|
31
31
|
|
|
32
|
-
<!-- docs: demo
|
|
32
|
+
<!-- docs: demo size:large -->
|
|
33
33
|
```html
|
|
34
34
|
<script type="module">
|
|
35
35
|
import '@brightspace-ui/core/components/table/demo/table-test.js';
|
|
@@ -45,7 +45,7 @@ If the viewport is very narrow — for example, on a mobile device — it may be
|
|
|
45
45
|
|
|
46
46
|
The `d2l-table-wrapper` element can be combined with table styles to apply default/light styling, row selection styles, overflow scrolling and sticky headers to native `<table>` elements within your Lit components.
|
|
47
47
|
|
|
48
|
-
<!-- docs: demo live name:d2l-
|
|
48
|
+
<!-- docs: demo live name:d2l-table-wrapper display:block -->
|
|
49
49
|
```html
|
|
50
50
|
<script type="module">
|
|
51
51
|
import { html, LitElement } from 'lit';
|
|
@@ -63,15 +63,7 @@ The `d2l-table-wrapper` element can be combined with table styles to apply defau
|
|
|
63
63
|
{ name: 'Japan', fruit: { 'apples': 8534, 'oranges': 1325, 'bananas': 78382756 }, selected: false }
|
|
64
64
|
];
|
|
65
65
|
|
|
66
|
-
class
|
|
67
|
-
|
|
68
|
-
static get properties() {
|
|
69
|
-
return {
|
|
70
|
-
noColumnBorder: { attribute: 'no-column-border', type: Boolean },
|
|
71
|
-
type: { type: String },
|
|
72
|
-
stickyHeaders: { attribute: 'sticky-headers', type: Boolean }
|
|
73
|
-
};
|
|
74
|
-
}
|
|
66
|
+
class SampleTable extends LitElement {
|
|
75
67
|
|
|
76
68
|
static get styles() {
|
|
77
69
|
return tableStyles;
|
|
@@ -81,7 +73,7 @@ The `d2l-table-wrapper` element can be combined with table styles to apply defau
|
|
|
81
73
|
const type = this.type === 'light' ? 'light' : 'default';
|
|
82
74
|
|
|
83
75
|
return html`
|
|
84
|
-
<d2l-table-wrapper
|
|
76
|
+
<d2l-table-wrapper>
|
|
85
77
|
<table class="d2l-table">
|
|
86
78
|
<thead>
|
|
87
79
|
<tr>
|
|
@@ -103,9 +95,9 @@ The `d2l-table-wrapper` element can be combined with table styles to apply defau
|
|
|
103
95
|
}
|
|
104
96
|
|
|
105
97
|
}
|
|
106
|
-
customElements.define('d2l-
|
|
98
|
+
customElements.define('d2l-sample-table', SampleTable);
|
|
107
99
|
</script>
|
|
108
|
-
<d2l-
|
|
100
|
+
<d2l-sample-table></d2l-sample-table>
|
|
109
101
|
```
|
|
110
102
|
|
|
111
103
|
<!-- docs: start hidden content -->
|
|
@@ -304,7 +296,7 @@ If your table supports row selection, apply the `selected` attribute to `<tr>` r
|
|
|
304
296
|
|
|
305
297
|
The `d2l-table-header` component can be placed in the `d2l-table-wrapper`'s `header` slot to provide a selection summary, a slot for `d2l-selection-action`s, and overflow-group behaviour.
|
|
306
298
|
|
|
307
|
-
<!-- docs: demo live name:d2l-table-header -->
|
|
299
|
+
<!-- docs: demo live name:d2l-table-header display:block -->
|
|
308
300
|
```html
|
|
309
301
|
<script type="module">
|
|
310
302
|
import '@brightspace-ui/core/components/selection/selection-action.js';
|
|
@@ -314,7 +306,7 @@ The `d2l-table-header` component can be placed in the `d2l-table-wrapper`'s `hea
|
|
|
314
306
|
import { html, LitElement } from 'lit';
|
|
315
307
|
import { tableStyles } from '@brightspace-ui/core/components/table/table-wrapper.js';
|
|
316
308
|
|
|
317
|
-
class
|
|
309
|
+
class SampleTableWithHeader extends LitElement {
|
|
318
310
|
|
|
319
311
|
static get properties() {
|
|
320
312
|
return {
|
|
@@ -369,9 +361,9 @@ The `d2l-table-header` component can be placed in the `d2l-table-wrapper`'s `hea
|
|
|
369
361
|
}
|
|
370
362
|
|
|
371
363
|
}
|
|
372
|
-
customElements.define('d2l-
|
|
364
|
+
customElements.define('d2l-sample-table-with-header', SampleTableWithHeader);
|
|
373
365
|
</script>
|
|
374
|
-
<d2l-
|
|
366
|
+
<d2l-sample-table-with-header></d2l-sample-table-with-header>
|
|
375
367
|
```
|
|
376
368
|
|
|
377
369
|
<!-- docs: start hidden content -->
|
|
@@ -9,9 +9,10 @@ import '../../selection/selection-action-dropdown.js';
|
|
|
9
9
|
import '../../selection/selection-action-menu-item.js';
|
|
10
10
|
import '../../selection/selection-input.js';
|
|
11
11
|
|
|
12
|
-
import { css, html
|
|
12
|
+
import { css, html } from 'lit';
|
|
13
|
+
import { tableStyles, TableWrapper } from '../table-wrapper.js';
|
|
14
|
+
import { DemoPassthroughMixin } from '../../demo/demo-passthrough-mixin.js';
|
|
13
15
|
import { RtlMixin } from '../../../mixins/rtl-mixin.js';
|
|
14
|
-
import { tableStyles } from '../table-wrapper.js';
|
|
15
16
|
|
|
16
17
|
const fruits = ['Apples', 'Oranges', 'Bananas'];
|
|
17
18
|
|
|
@@ -27,25 +28,10 @@ const data = () => [
|
|
|
27
28
|
|
|
28
29
|
const formatter = new Intl.NumberFormat('en-US');
|
|
29
30
|
|
|
30
|
-
class TestTable extends RtlMixin(
|
|
31
|
+
class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-wrapper')) {
|
|
31
32
|
|
|
32
33
|
static get properties() {
|
|
33
34
|
return {
|
|
34
|
-
/**
|
|
35
|
-
* Hides the column borders on "default" table type
|
|
36
|
-
* @type {boolean}
|
|
37
|
-
*/
|
|
38
|
-
noColumnBorder: { attribute: 'no-column-border', type: Boolean },
|
|
39
|
-
/**
|
|
40
|
-
* Type of table style to apply
|
|
41
|
-
* @type {'default'|'light'}
|
|
42
|
-
*/
|
|
43
|
-
type: { type: String },
|
|
44
|
-
/**
|
|
45
|
-
* Whether header row is sticky
|
|
46
|
-
* @type {boolean}
|
|
47
|
-
*/
|
|
48
|
-
stickyHeaders: { attribute: 'sticky-headers', type: Boolean },
|
|
49
35
|
_data: { state: true },
|
|
50
36
|
_sortField: { attribute: false, type: String },
|
|
51
37
|
_sortDesc: { attribute: false, type: Boolean }
|
|
@@ -62,15 +48,10 @@ class TestTable extends RtlMixin(LitElement) {
|
|
|
62
48
|
|
|
63
49
|
constructor() {
|
|
64
50
|
super();
|
|
65
|
-
this.noColumnBorder = false;
|
|
66
|
-
this.sortDesc = false;
|
|
67
|
-
this.stickyHeaders = false;
|
|
68
|
-
this.type = 'default';
|
|
69
51
|
this._data = data();
|
|
70
52
|
}
|
|
71
53
|
|
|
72
54
|
render() {
|
|
73
|
-
const type = this.type === 'light' ? 'light' : 'default';
|
|
74
55
|
const sorted = this._data.sort((a, b) => {
|
|
75
56
|
if (this._sortDesc) {
|
|
76
57
|
return b.fruit[this._sortField] - a.fruit[this._sortField];
|
|
@@ -78,7 +59,7 @@ class TestTable extends RtlMixin(LitElement) {
|
|
|
78
59
|
return a.fruit[this._sortField] - b.fruit[this._sortField];
|
|
79
60
|
});
|
|
80
61
|
return html`
|
|
81
|
-
<d2l-table-wrapper
|
|
62
|
+
<d2l-table-wrapper>
|
|
82
63
|
<d2l-table-header slot="header" no-sticky>
|
|
83
64
|
<d2l-selection-action icon="tier1:plus-default" text="Add" @d2l-selection-action-click="${this._handleAddItem}"></d2l-selection-action>
|
|
84
65
|
<d2l-selection-action-dropdown text="Move To" requires-selection>
|
|
@@ -7,6 +7,16 @@ import { SelectionHeader } from '../selection/selection-header.js';
|
|
|
7
7
|
* A header for table components containing a selection summary and selection actions.
|
|
8
8
|
*/
|
|
9
9
|
class TableHeader extends SelectionHeader {
|
|
10
|
+
static get properties() {
|
|
11
|
+
return {
|
|
12
|
+
/**
|
|
13
|
+
* Whether to render the selection summary
|
|
14
|
+
* @type {boolean}
|
|
15
|
+
*/
|
|
16
|
+
noSelection: { type: Boolean, attribute: 'no-selection' }
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
10
20
|
_renderSelection() {
|
|
11
21
|
return html`
|
|
12
22
|
<d2l-selection-summary
|
package/custom-elements.json
CHANGED
|
@@ -10601,15 +10601,32 @@
|
|
|
10601
10601
|
},
|
|
10602
10602
|
{
|
|
10603
10603
|
"name": "sticky-headers",
|
|
10604
|
-
"description": "Whether header row is sticky",
|
|
10604
|
+
"description": "Whether the header row is sticky. Useful for long tables to \"stick\" the header row in place as the user scrolls.",
|
|
10605
10605
|
"type": "boolean",
|
|
10606
10606
|
"default": "false"
|
|
10607
10607
|
},
|
|
10608
10608
|
{
|
|
10609
10609
|
"name": "type",
|
|
10610
|
-
"description": "Type of table style to apply",
|
|
10610
|
+
"description": "Type of table style to apply. The \"light\" style has fewer borders and tighter padding.",
|
|
10611
10611
|
"type": "'default'|'light'",
|
|
10612
10612
|
"default": "\"default\""
|
|
10613
|
+
},
|
|
10614
|
+
{
|
|
10615
|
+
"name": "selection-count-override",
|
|
10616
|
+
"description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
|
|
10617
|
+
"type": "number"
|
|
10618
|
+
},
|
|
10619
|
+
{
|
|
10620
|
+
"name": "item-count",
|
|
10621
|
+
"description": "Total number of items. Required when selecting all pages is allowed.",
|
|
10622
|
+
"type": "number",
|
|
10623
|
+
"default": "0"
|
|
10624
|
+
},
|
|
10625
|
+
{
|
|
10626
|
+
"name": "selection-single",
|
|
10627
|
+
"description": "Whether to render with single selection behaviour. If `selection-single` is specified, the nested `d2l-selection-input` elements will render radios instead of checkboxes, and the selection component will maintain a single selected item.",
|
|
10628
|
+
"type": "boolean",
|
|
10629
|
+
"default": "false"
|
|
10613
10630
|
}
|
|
10614
10631
|
],
|
|
10615
10632
|
"properties": [
|
|
@@ -10620,24 +10637,49 @@
|
|
|
10620
10637
|
"type": "boolean",
|
|
10621
10638
|
"default": "false"
|
|
10622
10639
|
},
|
|
10623
|
-
{
|
|
10624
|
-
"name": "sortDesc",
|
|
10625
|
-
"type": "boolean",
|
|
10626
|
-
"default": "false"
|
|
10627
|
-
},
|
|
10628
10640
|
{
|
|
10629
10641
|
"name": "stickyHeaders",
|
|
10630
10642
|
"attribute": "sticky-headers",
|
|
10631
|
-
"description": "Whether header row is sticky",
|
|
10643
|
+
"description": "Whether the header row is sticky. Useful for long tables to \"stick\" the header row in place as the user scrolls.",
|
|
10632
10644
|
"type": "boolean",
|
|
10633
10645
|
"default": "false"
|
|
10634
10646
|
},
|
|
10635
10647
|
{
|
|
10636
10648
|
"name": "type",
|
|
10637
10649
|
"attribute": "type",
|
|
10638
|
-
"description": "Type of table style to apply",
|
|
10650
|
+
"description": "Type of table style to apply. The \"light\" style has fewer borders and tighter padding.",
|
|
10639
10651
|
"type": "'default'|'light'",
|
|
10640
10652
|
"default": "\"default\""
|
|
10653
|
+
},
|
|
10654
|
+
{
|
|
10655
|
+
"name": "selectionCountOverride",
|
|
10656
|
+
"attribute": "selection-count-override",
|
|
10657
|
+
"description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
|
|
10658
|
+
"type": "number"
|
|
10659
|
+
},
|
|
10660
|
+
{
|
|
10661
|
+
"name": "itemCount",
|
|
10662
|
+
"attribute": "item-count",
|
|
10663
|
+
"description": "Total number of items. Required when selecting all pages is allowed.",
|
|
10664
|
+
"type": "number",
|
|
10665
|
+
"default": "0"
|
|
10666
|
+
},
|
|
10667
|
+
{
|
|
10668
|
+
"name": "selectionSingle",
|
|
10669
|
+
"attribute": "selection-single",
|
|
10670
|
+
"description": "Whether to render with single selection behaviour. If `selection-single` is specified, the nested `d2l-selection-input` elements will render radios instead of checkboxes, and the selection component will maintain a single selected item.",
|
|
10671
|
+
"type": "boolean",
|
|
10672
|
+
"default": "false"
|
|
10673
|
+
}
|
|
10674
|
+
],
|
|
10675
|
+
"slots": [
|
|
10676
|
+
{
|
|
10677
|
+
"name": "",
|
|
10678
|
+
"description": "Content to wrap"
|
|
10679
|
+
},
|
|
10680
|
+
{
|
|
10681
|
+
"name": "header",
|
|
10682
|
+
"description": "Slot for `d2l-table-header` to be rendered above the table"
|
|
10641
10683
|
}
|
|
10642
10684
|
]
|
|
10643
10685
|
},
|
|
@@ -10689,7 +10731,7 @@
|
|
|
10689
10731
|
"attributes": [
|
|
10690
10732
|
{
|
|
10691
10733
|
"name": "no-selection",
|
|
10692
|
-
"description": "Whether to render
|
|
10734
|
+
"description": "Whether to render the selection summary",
|
|
10693
10735
|
"type": "boolean",
|
|
10694
10736
|
"default": "false"
|
|
10695
10737
|
},
|
|
@@ -10715,7 +10757,7 @@
|
|
|
10715
10757
|
{
|
|
10716
10758
|
"name": "noSelection",
|
|
10717
10759
|
"attribute": "no-selection",
|
|
10718
|
-
"description": "Whether to render
|
|
10760
|
+
"description": "Whether to render the selection summary",
|
|
10719
10761
|
"type": "boolean",
|
|
10720
10762
|
"default": "false"
|
|
10721
10763
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.75.
|
|
3
|
+
"version": "2.75.5",
|
|
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",
|
|
@@ -46,16 +46,22 @@ class Resizer {
|
|
|
46
46
|
constructor() {
|
|
47
47
|
this.contentRect = null;
|
|
48
48
|
this.contentBounds = null;
|
|
49
|
+
this.isCollapsed = false;
|
|
49
50
|
this.isMobile = false;
|
|
50
|
-
this.panelSize = 0;
|
|
51
51
|
this.isRtl = false;
|
|
52
|
+
this.panelSize = 0;
|
|
52
53
|
this.secondaryFirst = false;
|
|
54
|
+
this._wasCollapsed = false;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
clampHeight(height) {
|
|
56
58
|
return clamp(height, this.contentBounds.minHeight, this.contentBounds.maxHeight);
|
|
57
59
|
}
|
|
58
60
|
|
|
61
|
+
clampMaxHeight(height) {
|
|
62
|
+
return Math.min(height, this.contentBounds.maxHeight);
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
clampWidth(width) {
|
|
60
66
|
return clamp(width, this.contentBounds.minWidth, this.contentBounds.maxWidth);
|
|
61
67
|
}
|
|
@@ -155,17 +161,18 @@ class DesktopMouseResizer extends Resizer {
|
|
|
155
161
|
this._onMouseDown = this._onMouseDown.bind(this);
|
|
156
162
|
this._onTouchMove = this._onTouchMove.bind(this);
|
|
157
163
|
this._onMouseMove = this._onMouseMove.bind(this);
|
|
158
|
-
this.
|
|
164
|
+
this._onMouseUp = this._onMouseUp.bind(this);
|
|
165
|
+
this._onTouchEnd = this._onTouchEnd.bind(this);
|
|
159
166
|
this._target = null;
|
|
160
167
|
}
|
|
161
168
|
|
|
162
169
|
connect(target) {
|
|
163
170
|
target.addEventListener('touchstart', this._onTouchStart);
|
|
164
171
|
target.addEventListener('touchmove', this._onTouchMove);
|
|
165
|
-
target.addEventListener('touchend', this.
|
|
172
|
+
target.addEventListener('touchend', this._onTouchEnd);
|
|
166
173
|
target.addEventListener('mousedown', this._onMouseDown);
|
|
167
174
|
window.addEventListener('mousemove', this._onMouseMove);
|
|
168
|
-
window.addEventListener('mouseup', this.
|
|
175
|
+
window.addEventListener('mouseup', this._onMouseUp);
|
|
169
176
|
this._target = target;
|
|
170
177
|
}
|
|
171
178
|
|
|
@@ -173,14 +180,18 @@ class DesktopMouseResizer extends Resizer {
|
|
|
173
180
|
if (this._target) {
|
|
174
181
|
this._target.removeEventListener('touchstart', this._onTouchStart);
|
|
175
182
|
this._target.removeEventListener('touchmove', this._onTouchMove);
|
|
176
|
-
this._target.removeEventListener('touchend', this.
|
|
183
|
+
this._target.removeEventListener('touchend', this._onTouchEnd);
|
|
177
184
|
this._target.removeEventListener('mousedown', this._onMouseDown);
|
|
178
185
|
}
|
|
179
186
|
window.removeEventListener('mousemove', this._onMouseMove);
|
|
180
|
-
window.removeEventListener('mouseup', this.
|
|
187
|
+
window.removeEventListener('mouseup', this._onMouseUp);
|
|
181
188
|
this._target = null;
|
|
182
189
|
}
|
|
183
190
|
|
|
191
|
+
_clampMaxWidth(width) {
|
|
192
|
+
return Math.min(width, this.contentBounds.maxWidth);
|
|
193
|
+
}
|
|
194
|
+
|
|
184
195
|
_computeContentX(clientX) {
|
|
185
196
|
const x = clientX - this.contentRect.left;
|
|
186
197
|
// The direction of the container is flipped if exactly one of isRtl and secondaryFirst is true
|
|
@@ -190,6 +201,7 @@ class DesktopMouseResizer extends Resizer {
|
|
|
190
201
|
_onMouseDown(e) {
|
|
191
202
|
if (!this.isMobile) {
|
|
192
203
|
e.preventDefault();
|
|
204
|
+
this._wasCollapsed = this.isCollapsed;
|
|
193
205
|
this._resizeStart(e.clientX);
|
|
194
206
|
}
|
|
195
207
|
}
|
|
@@ -201,11 +213,19 @@ class DesktopMouseResizer extends Resizer {
|
|
|
201
213
|
this._resize(e.clientX);
|
|
202
214
|
}
|
|
203
215
|
|
|
204
|
-
|
|
205
|
-
if (this._isResizing) {
|
|
206
|
-
|
|
207
|
-
this.dispatchResizeEnd();
|
|
216
|
+
_onMouseUp(e) {
|
|
217
|
+
if (!this._isResizing) {
|
|
218
|
+
return;
|
|
208
219
|
}
|
|
220
|
+
this._resizeEnd(e.clientX);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
_onTouchEnd(e) {
|
|
224
|
+
if (!this._isResizing) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const touch = e.changedTouches[0].clientX;
|
|
228
|
+
this._resizeEnd(touch);
|
|
209
229
|
}
|
|
210
230
|
|
|
211
231
|
_onTouchMove(e) {
|
|
@@ -215,27 +235,39 @@ class DesktopMouseResizer extends Resizer {
|
|
|
215
235
|
const touch = e.touches[0];
|
|
216
236
|
this._resize(touch.clientX);
|
|
217
237
|
}
|
|
218
|
-
|
|
219
238
|
_onTouchStart(e) {
|
|
220
239
|
if (!this.isMobile) {
|
|
221
|
-
e.preventDefault();
|
|
240
|
+
if (e.cancelable) e.preventDefault();
|
|
241
|
+
this._wasCollapsed = this.isCollapsed;
|
|
222
242
|
const touch = e.touches[0];
|
|
223
243
|
this._resizeStart(touch.clientX);
|
|
224
244
|
}
|
|
225
245
|
}
|
|
226
|
-
|
|
227
246
|
_resize(clientX) {
|
|
228
|
-
let actualSecondaryWidth;
|
|
229
247
|
const x = this._computeContentX(clientX);
|
|
230
|
-
const
|
|
248
|
+
const secondaryWidth = x + this._offset;
|
|
249
|
+
this.dispatchResize(this._clampMaxWidth(secondaryWidth), false);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
_resizeEnd(clientX) {
|
|
253
|
+
if (!this._isResizing) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const expandedCollapseThreshold = this.contentBounds.minWidth * 0.75;
|
|
257
|
+
const collapsedCollapseThreshold = this.contentBounds.minWidth * 0.1;
|
|
258
|
+
const x = this._computeContentX(clientX);
|
|
231
259
|
const desiredSecondaryWidth = x + this._offset;
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
260
|
+
if (
|
|
261
|
+
(this._wasCollapsed && desiredSecondaryWidth < collapsedCollapseThreshold)
|
|
262
|
+
|| (!this._wasCollapsed && desiredSecondaryWidth < expandedCollapseThreshold)
|
|
263
|
+
) {
|
|
264
|
+
this.dispatchResize(0, true);
|
|
265
|
+
}
|
|
266
|
+
else if (desiredSecondaryWidth < this.contentBounds.minWidth) {
|
|
267
|
+
this.dispatchResize(this.contentBounds.minWidth, true);
|
|
236
268
|
}
|
|
237
|
-
|
|
238
|
-
this.
|
|
269
|
+
this._isResizing = false;
|
|
270
|
+
this.dispatchResizeEnd();
|
|
239
271
|
}
|
|
240
272
|
|
|
241
273
|
_resizeStart(clientX) {
|
|
@@ -326,6 +358,7 @@ class MobileMouseResizer extends Resizer {
|
|
|
326
358
|
|
|
327
359
|
_onMouseDown(e) {
|
|
328
360
|
if (this.isMobile) {
|
|
361
|
+
this._wasCollapsed = this.isCollapsed;
|
|
329
362
|
this.dispatchResizeStart();
|
|
330
363
|
e.preventDefault();
|
|
331
364
|
const y = e.clientY - this.contentRect.top;
|
|
@@ -340,24 +373,29 @@ class MobileMouseResizer extends Resizer {
|
|
|
340
373
|
return;
|
|
341
374
|
}
|
|
342
375
|
const y = e.clientY - this.contentRect.top;
|
|
376
|
+
const secondaryHeight = this.clampMaxHeight(this.contentRect.height - y + this._offset);
|
|
377
|
+
this.dispatchResize(secondaryHeight, false);
|
|
378
|
+
}
|
|
343
379
|
|
|
344
|
-
|
|
345
|
-
|
|
380
|
+
_onMouseUp(e) {
|
|
381
|
+
if (!this._isResizing) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const expandedCollapseThreshold = this.contentBounds.minHeight * 0.75;
|
|
385
|
+
const collapsedCollapseThreshold = this.contentBounds.minHeight * 0.1;
|
|
386
|
+
const y = e.clientY - this.contentRect.top;
|
|
346
387
|
const desiredSecondaryHeight = this.contentRect.height - y + this._offset;
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
388
|
+
if (
|
|
389
|
+
(this._wasCollapsed && desiredSecondaryHeight < collapsedCollapseThreshold)
|
|
390
|
+
|| (!this._wasCollapsed && desiredSecondaryHeight < expandedCollapseThreshold)
|
|
391
|
+
) {
|
|
392
|
+
if (desiredSecondaryHeight > 0) this.dispatchResize(0, true);
|
|
351
393
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
_onMouseUp() {
|
|
357
|
-
if (this._isResizing) {
|
|
358
|
-
this._isResizing = false;
|
|
359
|
-
this.dispatchResizeEnd();
|
|
394
|
+
else if (desiredSecondaryHeight < this.contentBounds.minHeight) {
|
|
395
|
+
this.dispatchResize(this.contentBounds.minHeight, true);
|
|
360
396
|
}
|
|
397
|
+
this._isResizing = false;
|
|
398
|
+
this.dispatchResizeEnd();
|
|
361
399
|
}
|
|
362
400
|
|
|
363
401
|
}
|
|
@@ -365,52 +403,72 @@ class MobileMouseResizer extends Resizer {
|
|
|
365
403
|
class MobileTouchResizer extends Resizer {
|
|
366
404
|
constructor() {
|
|
367
405
|
super();
|
|
406
|
+
this.isExpanded = false;
|
|
407
|
+
this._wasExpanded = false;
|
|
368
408
|
this._onResizeStart = this._onResizeStart.bind(this);
|
|
369
409
|
this._onTouchMove = this._onTouchMove.bind(this);
|
|
370
410
|
this._onResizeEnd = this._onResizeEnd.bind(this);
|
|
371
|
-
this.
|
|
411
|
+
this._targetDivider = null;
|
|
412
|
+
this._targetSecondary = null;
|
|
372
413
|
}
|
|
373
414
|
|
|
374
|
-
connect(
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
this.
|
|
415
|
+
connect(targetDivider, targetSecondary) {
|
|
416
|
+
targetDivider.addEventListener('touchstart', this._onResizeStart);
|
|
417
|
+
targetDivider.addEventListener('touchmove', this._onTouchMove);
|
|
418
|
+
targetDivider.addEventListener('touchend', this._onResizeEnd);
|
|
419
|
+
this._targetDivider = targetDivider;
|
|
420
|
+
|
|
421
|
+
targetSecondary.addEventListener('touchstart', this._onResizeStart);
|
|
422
|
+
targetSecondary.addEventListener('touchmove', this._onTouchMove);
|
|
423
|
+
targetSecondary.addEventListener('touchend', this._onResizeEnd);
|
|
424
|
+
this._targetSecondary = targetSecondary;
|
|
379
425
|
}
|
|
380
426
|
|
|
381
427
|
disconnect() {
|
|
382
|
-
if (this.
|
|
383
|
-
this.
|
|
384
|
-
this.
|
|
385
|
-
this.
|
|
428
|
+
if (this._targetDivider) {
|
|
429
|
+
this._targetDivider.removeEventListener('touchstart', this._onResizeStart);
|
|
430
|
+
this._targetDivider.removeEventListener('touchmove', this._onTouchMove);
|
|
431
|
+
this._targetDivider.removeEventListener('touchend', this._onResizeEnd);
|
|
386
432
|
}
|
|
387
|
-
this.
|
|
388
|
-
}
|
|
433
|
+
this._targetDivider = null;
|
|
389
434
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
return 0;
|
|
435
|
+
if (this._targetSecondary) {
|
|
436
|
+
this._targetSecondary.removeEventListener('touchstart', this._onResizeStart);
|
|
437
|
+
this._targetSecondary.removeEventListener('touchmove', this._onTouchMove);
|
|
438
|
+
this._targetSecondary.removeEventListener('touchend', this._onResizeEnd);
|
|
395
439
|
}
|
|
396
|
-
|
|
440
|
+
this._targetSecondary = null;
|
|
397
441
|
}
|
|
398
442
|
|
|
399
443
|
_onResizeEnd() {
|
|
400
|
-
if (this._isResizing) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
444
|
+
if (!this._isResizing) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
let secondaryHeight;
|
|
448
|
+
const expandedShrinkThreshold = this.contentBounds.minHeight + (this.contentBounds.maxHeight - this.contentBounds.minHeight) * 0.9;
|
|
449
|
+
const expandThreshold = this.contentBounds.minHeight + (this.contentBounds.maxHeight - this.contentBounds.minHeight) * 0.1;
|
|
450
|
+
const collapseThreshold = this.contentBounds.minHeight * 0.9;
|
|
451
|
+
const collapsedExpandThreshold = this.contentBounds.minHeight * 0.1;
|
|
452
|
+
if (
|
|
453
|
+
(!this._wasCollapsed && this.panelSize < collapseThreshold)
|
|
454
|
+
|| (this._wasCollapsed && this.panelSize < collapsedExpandThreshold)
|
|
455
|
+
) {
|
|
456
|
+
secondaryHeight = 0;
|
|
457
|
+
}
|
|
458
|
+
else if (
|
|
459
|
+
(this._wasExpanded && this.panelSize < expandedShrinkThreshold)
|
|
460
|
+
|| (this._wasCollapsed && this.panelSize < expandThreshold)
|
|
461
|
+
|| (!this._wasExpanded && !this._wasCollapsed && this.panelSize < expandThreshold && this.panelSize > collapseThreshold)
|
|
462
|
+
) {
|
|
463
|
+
secondaryHeight = this.contentBounds.minHeight;
|
|
413
464
|
}
|
|
465
|
+
else {
|
|
466
|
+
secondaryHeight = this.contentBounds.maxHeight;
|
|
467
|
+
}
|
|
468
|
+
this.dispatchResize(secondaryHeight, true);
|
|
469
|
+
|
|
470
|
+
this._isResizing = false;
|
|
471
|
+
this.dispatchResizeEnd();
|
|
414
472
|
}
|
|
415
473
|
|
|
416
474
|
_onResizeStart(e) {
|
|
@@ -421,6 +479,8 @@ class MobileTouchResizer extends Resizer {
|
|
|
421
479
|
this._isResizing = true;
|
|
422
480
|
this._touches = [];
|
|
423
481
|
this._trackTouch(touch);
|
|
482
|
+
this._wasCollapsed = this.isCollapsed;
|
|
483
|
+
this._wasExpanded = this.isExpanded;
|
|
424
484
|
}
|
|
425
485
|
}
|
|
426
486
|
|
|
@@ -431,18 +491,19 @@ class MobileTouchResizer extends Resizer {
|
|
|
431
491
|
const touch = e.touches[0];
|
|
432
492
|
const curTouch = touch.screenY;
|
|
433
493
|
const delta = curTouch - this._prevTouch;
|
|
434
|
-
const
|
|
494
|
+
const isScrollingDivider = this._targetDivider.contains(e.target);
|
|
495
|
+
const curScroll = this._targetSecondary.scrollTop;
|
|
435
496
|
this._trackTouch(touch);
|
|
436
497
|
|
|
437
498
|
let isScrollable;
|
|
438
499
|
let secondaryHeight = this.panelSize;
|
|
439
500
|
if (delta > 0) {
|
|
440
|
-
if (curScroll === 0) {
|
|
441
|
-
secondaryHeight = this.
|
|
501
|
+
if (isScrollingDivider || curScroll === 0) {
|
|
502
|
+
secondaryHeight = this.clampMaxHeight(this.panelSize - delta);
|
|
442
503
|
}
|
|
443
504
|
isScrollable = curScroll > 0;
|
|
444
505
|
} else if (delta < 0) {
|
|
445
|
-
secondaryHeight = this.
|
|
506
|
+
secondaryHeight = this.clampMaxHeight(this.panelSize - delta);
|
|
446
507
|
isScrollable = secondaryHeight === this.contentBounds.maxHeight;
|
|
447
508
|
}
|
|
448
509
|
if (!isScrollable && e.cancelable) {
|
|
@@ -594,7 +655,15 @@ class TemplatePrimarySecondary extends FocusVisiblePolyfillMixin(RtlMixin(Locali
|
|
|
594
655
|
background-color: var(--d2l-color-gypsum);
|
|
595
656
|
}
|
|
596
657
|
:host([resizable]) [data-is-collapsed] aside {
|
|
597
|
-
|
|
658
|
+
visibility: hidden;
|
|
659
|
+
}
|
|
660
|
+
:host([resizable]:not([dir="rtl"]):not([secondary-first])) aside,
|
|
661
|
+
:host([resizable][dir="rtl"][secondary-first]) aside {
|
|
662
|
+
float: left;
|
|
663
|
+
}
|
|
664
|
+
:host([resizable][dir="rtl"]:not([secondary-first])) aside,
|
|
665
|
+
:host([resizable]:not([dir="rtl"])[secondary-first]) aside {
|
|
666
|
+
float: right;
|
|
598
667
|
}
|
|
599
668
|
.d2l-template-primary-secondary-divider {
|
|
600
669
|
background-color: var(--d2l-color-mica);
|
|
@@ -672,10 +741,12 @@ class TemplatePrimarySecondary extends FocusVisiblePolyfillMixin(RtlMixin(Locali
|
|
|
672
741
|
.d2l-template-primary-secondary-divider.focus-visible .d2l-template-primary-secondary-divider-handle-left {
|
|
673
742
|
display: block;
|
|
674
743
|
}
|
|
675
|
-
:host(:not([dir="rtl"])) [data-is-expanded] .d2l-template-primary-secondary-divider-handle-left
|
|
744
|
+
:host(:not([dir="rtl"]):not([secondary-first])) [data-is-expanded] .d2l-template-primary-secondary-divider-handle-left,
|
|
745
|
+
:host([dir="rtl"][secondary-first]) [data-is-expanded] .d2l-template-primary-secondary-divider-handle-left {
|
|
676
746
|
display: none;
|
|
677
747
|
}
|
|
678
|
-
:host([dir="rtl"]) [data-is-expanded] .d2l-template-primary-secondary-divider-handle-right
|
|
748
|
+
:host(:not([dir="rtl"])[secondary-first]) [data-is-expanded] .d2l-template-primary-secondary-divider-handle-right,
|
|
749
|
+
:host([dir="rtl"]:not([secondary-first])) [data-is-expanded] .d2l-template-primary-secondary-divider-handle-right {
|
|
679
750
|
display: none;
|
|
680
751
|
}
|
|
681
752
|
d2l-icon {
|
|
@@ -974,7 +1045,7 @@ class TemplatePrimarySecondary extends FocusVisiblePolyfillMixin(RtlMixin(Locali
|
|
|
974
1045
|
</d2l-icon-custom>
|
|
975
1046
|
</div>
|
|
976
1047
|
<div class="d2l-template-primary-secondary-divider-handle-mobile">
|
|
977
|
-
|
|
1048
|
+
<d2l-icon icon=${size === 0 ? 'tier1:chevron-up' : 'tier1:chevron-down'}></d2l-icon>
|
|
978
1049
|
</div>
|
|
979
1050
|
</div>
|
|
980
1051
|
</div>
|
|
@@ -989,6 +1060,14 @@ class TemplatePrimarySecondary extends FocusVisiblePolyfillMixin(RtlMixin(Locali
|
|
|
989
1060
|
|
|
990
1061
|
updated(changedProperties) {
|
|
991
1062
|
super.updated(changedProperties);
|
|
1063
|
+
if (changedProperties.has('_isCollapsed')) {
|
|
1064
|
+
this._desktopMouseResizer.isCollapsed = this._isCollapsed;
|
|
1065
|
+
this._mobileMouseResizer.isCollapsed = this._isCollapsed;
|
|
1066
|
+
this._mobileTouchResizer.isCollapsed = this._isCollapsed;
|
|
1067
|
+
}
|
|
1068
|
+
if (changedProperties.has('_isExpanded')) {
|
|
1069
|
+
this._mobileTouchResizer.isExpanded = this._isExpanded;
|
|
1070
|
+
}
|
|
992
1071
|
if (changedProperties.has('_size')) {
|
|
993
1072
|
if (this.storageKey) {
|
|
994
1073
|
const key = computeSizeKey(this.storageKey);
|
|
@@ -1003,16 +1082,20 @@ class TemplatePrimarySecondary extends FocusVisiblePolyfillMixin(RtlMixin(Locali
|
|
|
1003
1082
|
this._desktopKeyboardResizer.secondaryFirst = this.secondaryFirst;
|
|
1004
1083
|
this._desktopMouseResizer.secondaryFirst = this.secondaryFirst;
|
|
1005
1084
|
}
|
|
1006
|
-
if (!this.
|
|
1007
|
-
this._secondary = this.shadowRoot.querySelector('aside');
|
|
1085
|
+
if (!this._divider) {
|
|
1008
1086
|
this._divider = this.shadowRoot.querySelector('.d2l-template-primary-secondary-divider');
|
|
1009
1087
|
}
|
|
1088
|
+
if (changedProperties.has('_isMobile') && this._isMobile) {
|
|
1089
|
+
this._secondary = this.shadowRoot.querySelector('aside');
|
|
1090
|
+
if (this._divider.isConnected && this._secondary.isConnected) {
|
|
1091
|
+
this._mobileTouchResizer.connect(this._divider, this._secondary);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1010
1094
|
if (this._divider.isConnected && !this._hasConnectedResizers) {
|
|
1011
1095
|
this._desktopKeyboardResizer.connect(this._divider);
|
|
1012
1096
|
this._desktopMouseResizer.connect(this._divider);
|
|
1013
1097
|
this._mobileKeyboardResizer.connect(this._divider);
|
|
1014
1098
|
this._mobileMouseResizer.connect(this._divider);
|
|
1015
|
-
this._mobileTouchResizer.connect(this._secondary);
|
|
1016
1099
|
this._hasConnectedResizers = true;
|
|
1017
1100
|
}
|
|
1018
1101
|
}
|