@brightspace-ui/core 3.4.0 → 3.5.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.
@@ -1,4 +1,5 @@
|
|
1
1
|
import '../table-col-sort-button.js';
|
2
|
+
import '../table-col-sort-button-item.js';
|
2
3
|
import '../table-controls.js';
|
3
4
|
import '../../button/button-icon.js';
|
4
5
|
import '../../dropdown/dropdown-button-subtle.js';
|
@@ -24,13 +25,13 @@ const columns = ['Population', 'Size', 'Elevation'];
|
|
24
25
|
const thText = ['Additional', 'Placeholder', 'Header', 'Row'];
|
25
26
|
|
26
27
|
const data = () => [
|
27
|
-
{ name: 'Ottawa, Canada', city: 'Ottawa', country: 'Canada',
|
28
|
-
{ name: 'Toronto, Canada', city: 'Toronto', country: 'Canada',
|
29
|
-
{ name: 'Sydney, Australia', city: 'Sydney', country: 'Australia',
|
30
|
-
{ name: 'Cairo, Egypt', city: 'Cairo', country: 'Egypt',
|
31
|
-
{ name: 'Moscow, Russia', city: 'Moscow', country: 'Russia',
|
32
|
-
{ name: 'London, England', city: 'London', country: 'England',
|
33
|
-
{ name: 'Tokyo, Japan', city: 'Tokyo', country: 'Japan',
|
28
|
+
{ name: 'Ottawa, Canada', data: { 'city': 'Ottawa', 'country': 'Canada', 'population': 994837, 'size': 2790, 'elevation': 70 }, selected: true },
|
29
|
+
{ name: 'Toronto, Canada', data: { 'city': 'Toronto', 'country': 'Canada', 'population': 2930000, 'size': 630, 'elevation': 76 }, selected: true },
|
30
|
+
{ name: 'Sydney, Australia', data: { 'city': 'Sydney', 'country': 'Australia', 'population': 5312000, 'size': 12368, 'elevation': 3 }, selected: false },
|
31
|
+
{ name: 'Cairo, Egypt', data: { 'city': 'Cairo', 'country': 'Egypt', 'population': 9540000, 'size': 3085, 'elevation': 23 }, selected: false },
|
32
|
+
{ name: 'Moscow, Russia', data: { 'city': 'Moscow', 'country': 'Russia', 'population': 12712305, 'size': 2511, 'elevation': 124 }, selected: false },
|
33
|
+
{ name: 'London, England', data: { 'city': 'London', 'country': 'England', 'population': 8982000, 'size': 1572, 'elevation': 11 }, selected: false },
|
34
|
+
{ name: 'Tokyo, Japan', data: { 'city': 'Tokyo', 'country': 'Japan', 'population': 13960000, 'size': 2194, 'elevation': 40 }, selected: false }
|
34
35
|
];
|
35
36
|
|
36
37
|
const formatter = new Intl.NumberFormat('en-US');
|
@@ -100,7 +101,7 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
100
101
|
<thead>
|
101
102
|
<tr>
|
102
103
|
<th scope="col" sticky><d2l-selection-select-all></d2l-selection-select-all></th>
|
103
|
-
${this._renderDoubleSortButton('
|
104
|
+
${this._renderDoubleSortButton('Location')}
|
104
105
|
${columns.map(columnHeading => this._renderSortButton(columnHeading))}
|
105
106
|
</tr>
|
106
107
|
</thead>
|
@@ -145,7 +146,7 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
145
146
|
_handlePagerLoadMore(e) {
|
146
147
|
const startIndex = this._data.length + 1;
|
147
148
|
for (let i = 0; i < e.target.pageSize; i++) {
|
148
|
-
this._data.push({ name: `Country ${startIndex + i}`, data: { 'population': 26320000, 'size': 6340, 'elevation': 4 }, selected: false });
|
149
|
+
this._data.push({ name: `City ${startIndex + i}, Country ${startIndex + i}`, data: { 'city': `City ${startIndex + i}`, 'country': `Country ${startIndex + i}`, 'population': 26320000, 'size': 6340, 'elevation': 4 }, selected: false });
|
149
150
|
}
|
150
151
|
this.requestUpdate();
|
151
152
|
e.detail.complete();
|
@@ -156,38 +157,40 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
156
157
|
const desc = e.target.hasAttribute('desc');
|
157
158
|
this._sortDesc = field === this._sortField ? !desc : false; // if sorting on same field then reverse, otherwise sort ascending
|
158
159
|
this._sortField = field;
|
160
|
+
this._handleSortData();
|
161
|
+
}
|
162
|
+
|
163
|
+
_handleSortComplex(e) {
|
164
|
+
this._sortField = e.target?.getAttribute('data-field');
|
165
|
+
this._sortDesc = e.target?.hasAttribute('data-desc');
|
166
|
+
this._handleSortData();
|
167
|
+
}
|
159
168
|
|
169
|
+
_handleSortData() {
|
160
170
|
this._data = this._data.sort((a, b) => {
|
161
|
-
if (this.
|
162
|
-
if (this.
|
163
|
-
|
164
|
-
if (a[this._sortField] < b[this._sortField]) return 1;
|
165
|
-
} else {
|
166
|
-
if (a[this._sortField] < b[this._sortField]) return -1;
|
167
|
-
if (a[this._sortField] > b[this._sortField]) return 1;
|
168
|
-
}
|
171
|
+
if (this._sortDesc) {
|
172
|
+
if (a.data[this._sortField] > b.data[this._sortField]) return -1;
|
173
|
+
if (a.data[this._sortField] < b.data[this._sortField]) return 1;
|
169
174
|
} else {
|
170
|
-
if (this.
|
171
|
-
|
172
|
-
}
|
173
|
-
return a.data[this._sortField] - b.data[this._sortField];
|
175
|
+
if (a.data[this._sortField] < b.data[this._sortField]) return -1;
|
176
|
+
if (a.data[this._sortField] > b.data[this._sortField]) return 1;
|
174
177
|
}
|
178
|
+
return 0;
|
175
179
|
});
|
176
180
|
}
|
177
181
|
|
178
|
-
_renderDoubleSortButton(
|
182
|
+
_renderDoubleSortButton(name) {
|
183
|
+
const noSort = this._sortField?.toLowerCase() !== 'city' && this._sortField?.toLowerCase() !== 'country';
|
179
184
|
return html`
|
180
185
|
<th scope="col">
|
181
186
|
<d2l-table-col-sort-button
|
182
|
-
@click="${this._handleSort}"
|
183
|
-
source-type="words"
|
184
|
-
?desc="${this._sortDesc}"
|
185
|
-
?nosort="${this._sortField !== item1.toLowerCase()}">${item1}</d2l-table-col-sort-button>
|
186
|
-
<d2l-table-col-sort-button
|
187
|
-
@click="${this._handleSort}"
|
188
|
-
source-type="words"
|
189
187
|
?desc="${this._sortDesc}"
|
190
|
-
?nosort="${
|
188
|
+
?nosort="${noSort}">${name}
|
189
|
+
<d2l-table-col-sort-button-item slot="items" text="City, A to Z" data-field="city" @d2l-table-col-sort-button-item-change="${this._handleSortComplex}" value="1"></d2l-table-col-sort-button-item>
|
190
|
+
<d2l-table-col-sort-button-item slot="items" text="City, Z to A" data-field="city" data-desc @d2l-table-col-sort-button-item-change="${this._handleSortComplex}" value="2"></d2l-table-col-sort-button-item>
|
191
|
+
<d2l-table-col-sort-button-item slot="items" text="Country, A to Z" data-field="country" @d2l-table-col-sort-button-item-change="${this._handleSortComplex}" value="3"></d2l-table-col-sort-button-item>
|
192
|
+
<d2l-table-col-sort-button-item slot="items" text="Country, Z to A" data-field="country" data-desc @d2l-table-col-sort-button-item-change="${this._handleSortComplex}" value="4"></d2l-table-col-sort-button-item>
|
193
|
+
</d2l-table-col-sort-button>
|
191
194
|
</th>
|
192
195
|
`;
|
193
196
|
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import '../icons/icon.js';
|
2
|
+
import { html, LitElement } from 'lit';
|
3
|
+
import { MenuItemRadioMixin } from '../menu/menu-item-radio-mixin.js';
|
4
|
+
import { menuItemSelectableStyles } from '../menu/menu-item-selectable-styles.js';
|
5
|
+
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* A radio menu item to be used within the d2l-table-col-sort-button component for a multi-faceted sort.
|
9
|
+
*/
|
10
|
+
class TableColSortButtonItem extends RtlMixin(MenuItemRadioMixin(LitElement)) {
|
11
|
+
|
12
|
+
static get styles() {
|
13
|
+
return menuItemSelectableStyles;
|
14
|
+
}
|
15
|
+
|
16
|
+
firstUpdated() {
|
17
|
+
super.firstUpdated();
|
18
|
+
this.addEventListener('d2l-menu-item-change', this._onChangeOption);
|
19
|
+
}
|
20
|
+
|
21
|
+
render() {
|
22
|
+
return html`
|
23
|
+
<d2l-icon icon="tier1:check"></d2l-icon>
|
24
|
+
<div class="d2l-menu-item-text">${this.text}</div>
|
25
|
+
`;
|
26
|
+
}
|
27
|
+
|
28
|
+
_onChangeOption() {
|
29
|
+
/** Dispatched when the selected multi-faceted sort option changes */
|
30
|
+
this.dispatchEvent(new CustomEvent('d2l-table-col-sort-button-item-change', { bubbles: true, composed: true }));
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
customElements.define('d2l-table-col-sort-button-item', TableColSortButtonItem);
|
@@ -1,6 +1,10 @@
|
|
1
1
|
import '../colors/colors.js';
|
2
|
+
import '../dropdown/dropdown.js';
|
3
|
+
import '../dropdown/dropdown-menu.js';
|
2
4
|
import '../icons/icon.js';
|
5
|
+
import '../menu/menu.js';
|
3
6
|
import { css, html, LitElement, unsafeCSS } from 'lit';
|
7
|
+
import { classMap } from 'lit/directives/class-map.js';
|
4
8
|
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
|
5
9
|
import { getFocusPseudoClass } from '../../helpers/focus.js';
|
6
10
|
import { getUniqueId } from '../../helpers/uniqueId.js';
|
@@ -46,7 +50,9 @@ export class TableColSortButton extends LocalizeCoreElement(FocusMixin(LitElemen
|
|
46
50
|
sourceType: {
|
47
51
|
attribute: 'source-type',
|
48
52
|
type: String
|
49
|
-
}
|
53
|
+
},
|
54
|
+
_hasDropdownItems: { state: true },
|
55
|
+
_selectedMenuItemText: { state: true }
|
50
56
|
};
|
51
57
|
}
|
52
58
|
|
@@ -60,6 +66,9 @@ export class TableColSortButton extends LocalizeCoreElement(FocusMixin(LitElemen
|
|
60
66
|
:host([nosort]) {
|
61
67
|
--d2l-table-col-sort-button-additional-padding-inline-end: calc(0.6rem + 18px);
|
62
68
|
}
|
69
|
+
:host > :first-child {
|
70
|
+
width: var(--d2l-table-col-sort-button-width);
|
71
|
+
}
|
63
72
|
:host([nosort][position="center"]) {
|
64
73
|
--d2l-table-col-sort-button-additional-padding-inline-end: calc(0.5 * (0.6rem + 18px) + var(--d2l-table-cell-col-sort-button-size-offset, 4px));
|
65
74
|
--d2l-table-col-sort-button-additional-padding-inline-start: calc(0.5 * (0.6rem + 18px) - var(--d2l-table-cell-col-sort-button-size-offset, 4px));
|
@@ -91,8 +100,9 @@ export class TableColSortButton extends LocalizeCoreElement(FocusMixin(LitElemen
|
|
91
100
|
padding: calc(var(--d2l-table-cell-padding) - var(--d2l-table-cell-col-sort-button-size-offset, 4px));
|
92
101
|
padding-inline-end: calc(var(--d2l-table-cell-padding) - var(--d2l-table-cell-col-sort-button-size-offset, 4px) + var(--d2l-table-col-sort-button-additional-padding-inline-end));
|
93
102
|
padding-inline-start: calc(var(--d2l-table-cell-padding) - var(--d2l-table-cell-col-sort-button-size-offset, 4px) + var(--d2l-table-col-sort-button-additional-padding-inline-start));
|
103
|
+
text-align: start;
|
94
104
|
text-decoration: none;
|
95
|
-
width:
|
105
|
+
width: 100%;
|
96
106
|
}
|
97
107
|
button::-moz-focus-inner {
|
98
108
|
border: 0;
|
@@ -111,6 +121,12 @@ export class TableColSortButton extends LocalizeCoreElement(FocusMixin(LitElemen
|
|
111
121
|
d2l-icon {
|
112
122
|
margin-inline-start: 0.6rem;
|
113
123
|
}
|
124
|
+
::slotted(*[slot="items"]) {
|
125
|
+
display: none;
|
126
|
+
}
|
127
|
+
::slotted(d2l-table-col-sort-button-item[slot="items"]) {
|
128
|
+
display: flex;
|
129
|
+
}
|
114
130
|
`;
|
115
131
|
}
|
116
132
|
|
@@ -122,31 +138,75 @@ export class TableColSortButton extends LocalizeCoreElement(FocusMixin(LitElemen
|
|
122
138
|
this.sourceType = 'unknown';
|
123
139
|
|
124
140
|
this._describedById = getUniqueId();
|
141
|
+
this._hasDropdownItems = false;
|
125
142
|
}
|
126
143
|
|
127
144
|
static get focusElementSelector() {
|
128
145
|
return 'button';
|
129
146
|
}
|
130
147
|
|
148
|
+
firstUpdated(changedProperties) {
|
149
|
+
super.firstUpdated(changedProperties);
|
150
|
+
|
151
|
+
const selectedItem = this.querySelector('[selected]');
|
152
|
+
if (selectedItem && !this.nosort) this._selectedMenuItemText = selectedItem.text;
|
153
|
+
}
|
154
|
+
|
131
155
|
render() {
|
132
156
|
const buttonDescription = this.nosort ? this.localize('components.table-col-sort-button.addSortOrder') : this.localize('components.table-col-sort-button.changeSortOrder');
|
133
157
|
const buttonTitle = this.nosort
|
134
158
|
? undefined
|
135
159
|
: this.localize('components.table-col-sort-button.title', {
|
136
|
-
sourceType: this.sourceType,
|
137
|
-
direction: this.desc ? 'desc' : undefined
|
160
|
+
sourceType: this._hasDropdownItems && this._selectedMenuItemText ? 'value' : this.sourceType,
|
161
|
+
direction: this.desc ? 'desc' : undefined,
|
162
|
+
selectedMenuItemText: this._selectedMenuItemText
|
138
163
|
});
|
139
164
|
|
140
165
|
const iconView = !this.nosort ?
|
141
166
|
html`<d2l-icon icon="${this.desc ? 'tier1:arrow-toggle-down' : 'tier1:arrow-toggle-up'}"></d2l-icon>` :
|
142
167
|
null;
|
143
168
|
|
144
|
-
|
169
|
+
const button = html`<button
|
145
170
|
aria-describedby="${this._describedById}"
|
171
|
+
class="${classMap({ 'd2l-dropdown-opener': this._hasDropdownItems })}"
|
146
172
|
title="${ifDefined(buttonTitle)}"
|
147
173
|
type="button">
|
148
174
|
<slot></slot>${iconView}
|
149
175
|
</button><span id="${this._describedById}" hidden>${buttonDescription}</span>`;
|
176
|
+
if (this._hasDropdownItems) {
|
177
|
+
return html`<d2l-dropdown>
|
178
|
+
${button}
|
179
|
+
<d2l-dropdown-menu no-pointer align="start" vertical-offset="0">
|
180
|
+
<d2l-menu @d2l-table-col-sort-button-item-change="${this._handleTablColSortButtonItemChange}">
|
181
|
+
<slot name="items" @slotchange="${this._handleSlotChange}"></slot>
|
182
|
+
</d2l-menu>
|
183
|
+
</d2l-dropdown-menu>
|
184
|
+
</d2l-dropdown>`;
|
185
|
+
} else {
|
186
|
+
return html`${button}<slot name="items" @slotchange="${this._handleSlotChange}"></slot>`;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
updated(changedProperties) {
|
191
|
+
super.updated(changedProperties);
|
192
|
+
|
193
|
+
// de-select any selected dropdown menu item
|
194
|
+
if (changedProperties.has('nosort') && this.nosort && this._hasDropdownItems) {
|
195
|
+
const selectedItem = this.querySelector('[selected]');
|
196
|
+
if (selectedItem) selectedItem.selected = false;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
_handleSlotChange(e) {
|
201
|
+
const items = e.target?.assignedNodes({ flatten: true }).filter((node) => node.nodeType === Node.ELEMENT_NODE);
|
202
|
+
const filteredItems = items.filter((item) => {
|
203
|
+
return item.tagName === 'D2L-TABLE-COL-SORT-BUTTON-ITEM';
|
204
|
+
});
|
205
|
+
this._hasDropdownItems = filteredItems.length > 0;
|
206
|
+
}
|
207
|
+
|
208
|
+
_handleTablColSortButtonItemChange(e) {
|
209
|
+
this._selectedMenuItemText = e.target?.text;
|
150
210
|
}
|
151
211
|
|
152
212
|
}
|
package/custom-elements.json
CHANGED
@@ -12020,6 +12020,92 @@
|
|
12020
12020
|
}
|
12021
12021
|
]
|
12022
12022
|
},
|
12023
|
+
{
|
12024
|
+
"name": "d2l-table-col-sort-button-item",
|
12025
|
+
"path": "./components/table/table-col-sort-button-item.js",
|
12026
|
+
"description": "A radio menu item to be used within the d2l-table-col-sort-button component for a multi-faceted sort.",
|
12027
|
+
"attributes": [
|
12028
|
+
{
|
12029
|
+
"name": "value",
|
12030
|
+
"description": "REQUIRED: The selectable item's value",
|
12031
|
+
"type": "string"
|
12032
|
+
},
|
12033
|
+
{
|
12034
|
+
"name": "selected",
|
12035
|
+
"description": "This will set the item to be selected by default",
|
12036
|
+
"type": "boolean",
|
12037
|
+
"default": "false"
|
12038
|
+
},
|
12039
|
+
{
|
12040
|
+
"name": "text",
|
12041
|
+
"description": "REQUIRED: Text displayed by the menu item",
|
12042
|
+
"type": "string"
|
12043
|
+
},
|
12044
|
+
{
|
12045
|
+
"name": "description",
|
12046
|
+
"description": "Provide a description for the menu item that will be used by screen readers",
|
12047
|
+
"type": "string"
|
12048
|
+
},
|
12049
|
+
{
|
12050
|
+
"name": "disabled",
|
12051
|
+
"description": "Disables the menu item",
|
12052
|
+
"type": "boolean",
|
12053
|
+
"default": "false"
|
12054
|
+
}
|
12055
|
+
],
|
12056
|
+
"properties": [
|
12057
|
+
{
|
12058
|
+
"name": "value",
|
12059
|
+
"attribute": "value",
|
12060
|
+
"description": "REQUIRED: The selectable item's value",
|
12061
|
+
"type": "string"
|
12062
|
+
},
|
12063
|
+
{
|
12064
|
+
"name": "selected",
|
12065
|
+
"attribute": "selected",
|
12066
|
+
"description": "This will set the item to be selected by default",
|
12067
|
+
"type": "boolean",
|
12068
|
+
"default": "false"
|
12069
|
+
},
|
12070
|
+
{
|
12071
|
+
"name": "text",
|
12072
|
+
"attribute": "text",
|
12073
|
+
"description": "REQUIRED: Text displayed by the menu item",
|
12074
|
+
"type": "string"
|
12075
|
+
},
|
12076
|
+
{
|
12077
|
+
"name": "description",
|
12078
|
+
"attribute": "description",
|
12079
|
+
"description": "Provide a description for the menu item that will be used by screen readers",
|
12080
|
+
"type": "string"
|
12081
|
+
},
|
12082
|
+
{
|
12083
|
+
"name": "disabled",
|
12084
|
+
"attribute": "disabled",
|
12085
|
+
"description": "Disables the menu item",
|
12086
|
+
"type": "boolean",
|
12087
|
+
"default": "false"
|
12088
|
+
}
|
12089
|
+
],
|
12090
|
+
"events": [
|
12091
|
+
{
|
12092
|
+
"name": "d2l-table-col-sort-button-item-change",
|
12093
|
+
"description": "Dispatched when the selected multi-faceted sort option changes"
|
12094
|
+
},
|
12095
|
+
{
|
12096
|
+
"name": "d2l-menu-item-change",
|
12097
|
+
"description": "Dispatched when the selected menu item changes"
|
12098
|
+
},
|
12099
|
+
{
|
12100
|
+
"name": "d2l-menu-item-select",
|
12101
|
+
"description": "Dispatched when the menu item is selected"
|
12102
|
+
},
|
12103
|
+
{
|
12104
|
+
"name": "d2l-menu-item-visibility-change",
|
12105
|
+
"description": "Dispatched when the visibility of the menu item changes"
|
12106
|
+
}
|
12107
|
+
]
|
12108
|
+
},
|
12023
12109
|
{
|
12024
12110
|
"name": "d2l-table-col-sort-button",
|
12025
12111
|
"path": "./components/table/table-col-sort-button.js",
|
package/lang/en.js
CHANGED
@@ -107,7 +107,7 @@ export default {
|
|
107
107
|
"components.switch.conditions": "Conditions must be met",
|
108
108
|
"components.table-col-sort-button.addSortOrder": "Select to add sort order",
|
109
109
|
"components.table-col-sort-button.changeSortOrder": "Select to change sort order",
|
110
|
-
"components.table-col-sort-button.title": "{sourceType, select, dates {{direction, select, desc {Sorted new to old} other {Sorted old to new}}} numbers {{direction, select, desc {Sorted high to low} other {Sorted low to high}}} words {{direction, select, desc {Sorted Z to A} other {Sorted A to Z}}} other {{direction, select, desc {Sorted descending} other {Sorted ascending}}}}",
|
110
|
+
"components.table-col-sort-button.title": "{sourceType, select, dates {{direction, select, desc {Sorted new to old} other {Sorted old to new}}} numbers {{direction, select, desc {Sorted high to low} other {Sorted low to high}}} words {{direction, select, desc {Sorted Z to A} other {Sorted A to Z}}} value {Sorted {selectedMenuItemText}} other {{direction, select, desc {Sorted descending} other {Sorted ascending}}}}",
|
111
111
|
"components.table-controls.label": "Actions for table",
|
112
112
|
"components.tabs.next": "Scroll Forward",
|
113
113
|
"components.tabs.previous": "Scroll Backward",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.5.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",
|