@zywave/zui-table 4.0.2-pre.1 → 4.0.2-pre.2
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/dist/base.d.ts +29 -0
- package/dist/base.js +67 -0
- package/dist/base.js.map +1 -0
- package/dist/css/zui-table.fouc.css +1 -1
- package/dist/custom-elements.json +192 -27
- package/dist/zui-table-cell-css.js +1 -1
- package/dist/zui-table-cell-css.js.map +1 -1
- package/dist/zui-table-cell.d.ts +27 -3
- package/dist/zui-table-cell.js +93 -6
- package/dist/zui-table-cell.js.map +1 -1
- package/dist/zui-table-css.js +1 -1
- package/dist/zui-table-css.js.map +1 -1
- package/dist/zui-table-footer.d.ts +6 -4
- package/dist/zui-table-footer.js +6 -4
- package/dist/zui-table-footer.js.map +1 -1
- package/dist/zui-table-row-css.js +1 -1
- package/dist/zui-table-row-css.js.map +1 -1
- package/dist/zui-table-row.d.ts +7 -4
- package/dist/zui-table-row.js +57 -11
- package/dist/zui-table-row.js.map +1 -1
- package/dist/zui-table-topbar-css.js +1 -1
- package/dist/zui-table-topbar-css.js.map +1 -1
- package/dist/zui-table-topbar.d.ts +12 -3
- package/dist/zui-table-topbar.js +105 -5
- package/dist/zui-table-topbar.js.map +1 -1
- package/dist/zui-table.d.ts +7 -5
- package/dist/zui-table.js +24 -10
- package/dist/zui-table.js.map +1 -1
- package/docs/customelement-manifest-element.html +28 -0
- package/{demo/index.html → docs/demo.html} +236 -42
- package/lab.html +347 -60
- package/package.json +9 -4
- package/src/base.ts +79 -0
- package/src/css/zui-table.fouc.scss +90 -17
- package/src/zui-table-cell-css.js +1 -1
- package/src/zui-table-cell.scss +26 -0
- package/src/zui-table-cell.ts +84 -6
- package/src/zui-table-css.js +1 -1
- package/src/zui-table-footer.ts +6 -4
- package/src/zui-table-row-css.js +1 -1
- package/src/zui-table-row.scss +11 -4
- package/src/zui-table-row.ts +51 -11
- package/src/zui-table-topbar-css.js +1 -1
- package/src/zui-table-topbar.scss +77 -9
- package/src/zui-table-topbar.ts +106 -5
- package/src/zui-table.scss +2 -2
- package/src/zui-table.ts +24 -9
- package/test/zui-table.test.ts +146 -4
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
display: flex;
|
|
10
10
|
width: 100%;
|
|
11
11
|
min-height: rem(60);
|
|
12
|
+
flex-wrap: wrap;
|
|
13
|
+
justify-content: space-between;
|
|
12
14
|
align-items: center;
|
|
13
|
-
padding: rem(10) rem(20);
|
|
14
|
-
background-color: var(--zui-gray-25);
|
|
15
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
16
15
|
|
|
17
16
|
@media (min-width: $bp-xs) {
|
|
17
|
+
flex-wrap: nowrap;
|
|
18
|
+
padding: rem(10) rem(20);
|
|
19
|
+
background-color: var(--zui-gray-25);
|
|
18
20
|
box-shadow: none;
|
|
19
21
|
}
|
|
20
22
|
}
|
|
@@ -23,28 +25,94 @@
|
|
|
23
25
|
display: flex;
|
|
24
26
|
flex: 1;
|
|
25
27
|
align-items: center;
|
|
28
|
+
order: 1;
|
|
29
|
+
margin-bottom: rem(20);
|
|
30
|
+
|
|
31
|
+
@media (min-width: $bp-xxs) {
|
|
32
|
+
flex: auto;
|
|
33
|
+
order: 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@media (min-width: $bp-xs) {
|
|
37
|
+
margin-bottom: 0;
|
|
38
|
+
}
|
|
26
39
|
|
|
27
40
|
::slotted(zui-search) {
|
|
28
41
|
--zui-search-border-color: var(--zui-gray-50);
|
|
42
|
+
width: 100%;
|
|
43
|
+
|
|
44
|
+
@media (min-width: $bp-xs) {
|
|
45
|
+
width: auto;
|
|
46
|
+
}
|
|
29
47
|
}
|
|
30
48
|
}
|
|
31
49
|
|
|
32
50
|
.counter {
|
|
51
|
+
display: flex;
|
|
52
|
+
width: 100%;
|
|
33
53
|
flex-shrink: 0;
|
|
54
|
+
justify-content: flex-end;
|
|
55
|
+
order: 2;
|
|
56
|
+
margin-bottom: rem(10);
|
|
34
57
|
margin-left: auto;
|
|
35
58
|
padding-left: rem(10);
|
|
36
59
|
font-size: rem(12);
|
|
37
60
|
color: var(--zui-gray-400);
|
|
61
|
+
|
|
62
|
+
@media (min-width: $bp-xs) {
|
|
63
|
+
width: auto;
|
|
64
|
+
margin-bottom: 0;
|
|
65
|
+
}
|
|
38
66
|
}
|
|
39
67
|
|
|
40
68
|
.action {
|
|
41
|
-
|
|
69
|
+
display: flex;
|
|
70
|
+
width: 100%;
|
|
71
|
+
justify-content: flex-end;
|
|
72
|
+
margin-bottom: rem(20);
|
|
42
73
|
|
|
43
|
-
|
|
44
|
-
|
|
74
|
+
@media (min-width: $bp-xxs) {
|
|
75
|
+
width: auto;
|
|
45
76
|
}
|
|
46
|
-
}
|
|
47
77
|
|
|
48
|
-
|
|
49
|
-
|
|
78
|
+
@media (min-width: $bp-xs) {
|
|
79
|
+
margin-bottom: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
slot[name='action'] {
|
|
83
|
+
display: flex;
|
|
84
|
+
width: 100%;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
|
|
87
|
+
@media (min-width: $bp-xxs) {
|
|
88
|
+
flex-direction: row;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
::slotted(zui-button) {
|
|
93
|
+
width: 100%;
|
|
94
|
+
|
|
95
|
+
@media (min-width: $bp-xxs) {
|
|
96
|
+
width: auto;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
::slotted(zui-button:first-of-type) {
|
|
101
|
+
@media (min-width: $bp-xxs) {
|
|
102
|
+
margin-left: rem(20);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@media (min-width: $bp-xs) {
|
|
106
|
+
margin-left: rem(10);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
::slotted(zui-button:not(:first-of-type)) {
|
|
111
|
+
margin-top: rem(10);
|
|
112
|
+
|
|
113
|
+
@media (min-width: $bp-xxs) {
|
|
114
|
+
margin-top: 0;
|
|
115
|
+
margin-left: rem(10);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
50
118
|
}
|
package/src/zui-table-topbar.ts
CHANGED
|
@@ -1,26 +1,127 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ZuiTableBaseElement } from './base.js';
|
|
2
2
|
import { html } from 'lit';
|
|
3
|
+
import { queryAssignedElements, queryAssignedNodes } from 'lit/decorators.js';
|
|
3
4
|
import { style } from './zui-table-topbar-css.js';
|
|
5
|
+
import { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints';
|
|
6
|
+
import type { ZuiButton } from '@zywave/zui-button/dist/zui-button.js';
|
|
4
7
|
|
|
5
8
|
/**
|
|
9
|
+
* Used to house table related pieces such as a search input or `zui-search`, and other up front information.
|
|
10
|
+
*
|
|
6
11
|
* @element zui-table-topbar
|
|
7
12
|
*
|
|
8
|
-
* @slot -
|
|
13
|
+
* @slot - Unnamed slot, table cell content goes here
|
|
9
14
|
* @slot counter - Total number of results from table goes here
|
|
10
15
|
* @slot action - Action(s) that affect the whole table goes here
|
|
11
16
|
*/
|
|
12
|
-
export class ZuiTableTopbarElement extends
|
|
17
|
+
export class ZuiTableTopbarElement extends ZuiTableBaseElement {
|
|
18
|
+
@queryAssignedElements({ slot: 'action' })
|
|
19
|
+
private _actionSlottedElements: Array<HTMLCollection>;
|
|
20
|
+
|
|
21
|
+
@queryAssignedNodes({ slot: 'counter' })
|
|
22
|
+
private _counterSlottedNodes: Array<HTMLCollection>;
|
|
23
|
+
|
|
24
|
+
@queryAssignedElements({ selector: 'zui-button', slot: 'action' })
|
|
25
|
+
private _actionButtons: Array<ZuiButton>;
|
|
26
|
+
|
|
27
|
+
#mobileBreakpoint: MediaQueryList = window.matchMedia(`only screen and (max-width: ${screenBreakpoints.xsmall})`);
|
|
28
|
+
|
|
29
|
+
#mobileTopbarActionButtonsEvent = (b: MediaQueryListEvent) => {
|
|
30
|
+
b.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();
|
|
31
|
+
};
|
|
32
|
+
|
|
13
33
|
static get styles() {
|
|
14
34
|
return [super.styles, style];
|
|
15
35
|
}
|
|
16
36
|
|
|
37
|
+
connectedCallback() {
|
|
38
|
+
super.connectedCallback();
|
|
39
|
+
|
|
40
|
+
if (this.#mobileBreakpoint.addEventListener) {
|
|
41
|
+
this.#mobileBreakpoint.addEventListener('change', this.#mobileTopbarActionButtonsEvent);
|
|
42
|
+
} else {
|
|
43
|
+
this.#mobileBreakpoint.addListener(this.#mobileTopbarActionButtonsEvent);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
disconnectedCallback() {
|
|
48
|
+
super.disconnectedCallback();
|
|
49
|
+
|
|
50
|
+
if (this.#mobileBreakpoint.addEventListener) {
|
|
51
|
+
this.#mobileBreakpoint.removeEventListener('change', this.#mobileTopbarActionButtonsEvent);
|
|
52
|
+
} else if (this.#mobileBreakpoint.addListener) {
|
|
53
|
+
this.#mobileBreakpoint.removeListener(this.#mobileTopbarActionButtonsEvent);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
firstUpdated() {
|
|
58
|
+
this.#mobileBreakpoint.matches ? this.#addBlockStylingToButtons() : this.#removeBlockStylingFromButtons();
|
|
59
|
+
this.#toggleActionDivDisplay();
|
|
60
|
+
this.#toggleCounterDivDisplay();
|
|
61
|
+
}
|
|
62
|
+
|
|
17
63
|
render() {
|
|
18
64
|
return html`<div class="topbar">
|
|
19
65
|
<div class="content"><slot></slot></div>
|
|
20
|
-
<div class="counter"><slot name="counter"></slot></div>
|
|
21
|
-
<div class="action"
|
|
66
|
+
<div class="counter"><slot name="counter" @slotchange="${this.#toggleCounterDivDisplay}"></slot></div>
|
|
67
|
+
<div class="action"
|
|
68
|
+
><slot
|
|
69
|
+
name="action"
|
|
70
|
+
@slotchange="${this.#toggleActionDivDisplay} ${this.#mobileBreakpoint.matches
|
|
71
|
+
? this.#addBlockStylingToButtons
|
|
72
|
+
: this.#removeBlockStylingFromButtons}"
|
|
73
|
+
></slot
|
|
74
|
+
></div>
|
|
22
75
|
</div>`;
|
|
23
76
|
}
|
|
77
|
+
|
|
78
|
+
#addBlockStylingToButtons() {
|
|
79
|
+
if (this._actionButtons.length > 0) {
|
|
80
|
+
for (const button of this._actionButtons) {
|
|
81
|
+
if (!button.hasAttribute('block')) {
|
|
82
|
+
button.setAttribute('block', '');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.requestUpdate();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#removeBlockStylingFromButtons() {
|
|
91
|
+
if (this._actionButtons.length > 0) {
|
|
92
|
+
for (const button of this._actionButtons) {
|
|
93
|
+
if (button.hasAttribute('block')) {
|
|
94
|
+
button.removeAttribute('block');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.requestUpdate();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
#toggleCounterDivDisplay() {
|
|
103
|
+
const counter: HTMLElement = this.shadowRoot.querySelector('.counter');
|
|
104
|
+
|
|
105
|
+
if (this._counterSlottedNodes.length === 0) {
|
|
106
|
+
counter.style.display = 'none';
|
|
107
|
+
} else if (this._counterSlottedNodes.length > 0 && counter.style.display === 'none') {
|
|
108
|
+
counter.style.removeProperty('display');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.requestUpdate();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#toggleActionDivDisplay() {
|
|
115
|
+
const action: HTMLElement = this.shadowRoot.querySelector('.action');
|
|
116
|
+
|
|
117
|
+
if (this._actionSlottedElements.length === 0) {
|
|
118
|
+
action.style.display = 'none';
|
|
119
|
+
} else if (this._actionSlottedElements.length > 0 && action.style.display === 'none') {
|
|
120
|
+
action.style.removeProperty('display');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.requestUpdate();
|
|
124
|
+
}
|
|
24
125
|
}
|
|
25
126
|
|
|
26
127
|
window.customElements.define('zui-table-topbar', ZuiTableTopbarElement);
|
package/src/zui-table.scss
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
::slotted(zui-table-row:not([header])) {
|
|
33
|
-
border-bottom:
|
|
33
|
+
border-bottom: 2px solid var(--zui-gray-100);
|
|
34
34
|
|
|
35
35
|
@media (min-width: $bp-xs) {
|
|
36
36
|
border-bottom-width: 1px;
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
display: flex;
|
|
46
46
|
width: 100%;
|
|
47
47
|
flex-direction: column;
|
|
48
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
49
48
|
border-collapse: collapse;
|
|
50
49
|
border-spacing: 0;
|
|
51
50
|
|
|
52
51
|
@media (min-width: $bp-xs) {
|
|
53
52
|
background-color: #fff;
|
|
53
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
54
54
|
}
|
|
55
55
|
}
|
package/src/zui-table.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ZuiTableBaseElement, TableElementConnectedEvent } from './base.js';
|
|
2
2
|
import { html } from 'lit';
|
|
3
3
|
import { property, queryAssignedElements } from 'lit/decorators.js';
|
|
4
4
|
import { style } from './zui-table-css.js';
|
|
@@ -7,20 +7,22 @@ import type { ZuiTableRowElement } from './zui-table-row.js';
|
|
|
7
7
|
import type { ZuiTableFooterElement } from './zui-table-footer.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* A standardized responsive table component.
|
|
11
|
+
*
|
|
10
12
|
* @element zui-table
|
|
11
13
|
*
|
|
12
|
-
* @slot -
|
|
14
|
+
* @slot - Unnamed slot, all table content will appear here, such as table rows
|
|
13
15
|
* @slot no-results-message - Customize the no results message that is shown when the `no-results` attribute is set on `<zui-table>`: `<zui-table no-results>`
|
|
14
16
|
* @slot footer - Only for `<zui-table-footer>`. When there is a `<zui-table-footer>` present inside `<zui-table>`, it will be auto-assigned to this slot in order to place it outside of the rendered table for styling purposes.
|
|
15
17
|
*
|
|
16
18
|
* @cssprop [--zui-table-cell-padding=13px 20px] - Override cell padding
|
|
17
|
-
* @cssprop [--zui-table-columns-template=repeat(auto-fit, minmax(0, 1fr))] - Override the table columns template. See
|
|
19
|
+
* @cssprop [--zui-table-columns-template=repeat(auto-fit, minmax(0, 1fr))] - Override the table columns template. See https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns for more information on valid values.
|
|
18
20
|
* @cssprop [--zui-table-summary-background-color=var(--zui-gray-600)] - Override the table summary background color
|
|
19
21
|
* @cssprop [--zui-table-summary-text-color=#fff] - Override the the table summary text color
|
|
20
22
|
* @cssprop [--zui-table-footer-margin=10px] - Override the margin between the table and footer of the table
|
|
21
23
|
*/
|
|
22
24
|
|
|
23
|
-
export class ZuiTableElement extends
|
|
25
|
+
export class ZuiTableElement extends ZuiTableBaseElement {
|
|
24
26
|
/**
|
|
25
27
|
* Set for alternating table row background colors
|
|
26
28
|
*/
|
|
@@ -30,7 +32,7 @@ export class ZuiTableElement extends ZuiBaseElement {
|
|
|
30
32
|
// TODO: add divided prop so all table cells will have 1px border
|
|
31
33
|
|
|
32
34
|
/**
|
|
33
|
-
* Set to show or hide no results message when there are no results; use in conjunction with the assigned slot
|
|
35
|
+
* Set to show or hide no results message when there are no results; use in conjunction with the assigned slot `no-results-message` to include a no results message
|
|
34
36
|
*/
|
|
35
37
|
@property({ type: Boolean, reflect: true, attribute: 'no-results' })
|
|
36
38
|
noResults = false;
|
|
@@ -42,8 +44,8 @@ export class ZuiTableElement extends ZuiBaseElement {
|
|
|
42
44
|
private _footer: Array<ZuiTableFooterElement>;
|
|
43
45
|
|
|
44
46
|
#internals?: ElementInternals;
|
|
45
|
-
|
|
46
47
|
#mobileBreakpoint: MediaQueryList = window.matchMedia(`only screen and (max-width: ${screenBreakpoints.xsmall})`);
|
|
48
|
+
#sortLock = false;
|
|
47
49
|
|
|
48
50
|
#mobileHeadersEvent = (b: MediaQueryListEvent) => {
|
|
49
51
|
b.matches ? this.#addRowHeadersToCells() : this.#removeRowHeadersFromCells();
|
|
@@ -57,6 +59,21 @@ export class ZuiTableElement extends ZuiBaseElement {
|
|
|
57
59
|
super();
|
|
58
60
|
|
|
59
61
|
this.#internals = this.attachInternals?.();
|
|
62
|
+
|
|
63
|
+
ZuiTableBaseElement._globalChannel.addEventListener('connected', (event: TableElementConnectedEvent) => {
|
|
64
|
+
if (this.contains(event.detail.element)) {
|
|
65
|
+
this._associateElement(event.detail.element);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
this._state.channel.addEventListener('sort', (event: CustomEvent) => {
|
|
70
|
+
if (this.#sortLock) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
this.#sortLock = true;
|
|
74
|
+
this.dispatchEvent(new CustomEvent('sort', { detail: event.detail }));
|
|
75
|
+
setTimeout(() => (this.#sortLock = false), 0);
|
|
76
|
+
});
|
|
60
77
|
}
|
|
61
78
|
|
|
62
79
|
connectedCallback() {
|
|
@@ -89,9 +106,7 @@ export class ZuiTableElement extends ZuiBaseElement {
|
|
|
89
106
|
render() {
|
|
90
107
|
return html`<div class="table">
|
|
91
108
|
<slot
|
|
92
|
-
@slotchange="${this.#mobileBreakpoint.matches
|
|
93
|
-
? this.#addRowHeadersToCells()
|
|
94
|
-
: this.#removeRowHeadersFromCells()}"
|
|
109
|
+
@slotchange="${this.#mobileBreakpoint.matches ? this.#addRowHeadersToCells : this.#removeRowHeadersFromCells}"
|
|
95
110
|
></slot>
|
|
96
111
|
${this.noResults ? this.#renderNoResultsView() : ``}</div
|
|
97
112
|
>
|
package/test/zui-table.test.ts
CHANGED
|
@@ -7,12 +7,13 @@ import {
|
|
|
7
7
|
ZuiTableCellElement,
|
|
8
8
|
ZuiTableTopbarElement,
|
|
9
9
|
ZuiTableFooterElement,
|
|
10
|
+
ZuiTableSortDirection,
|
|
10
11
|
} from '@zywave/zui-table';
|
|
11
12
|
import { assert } from '@esm-bundle/chai';
|
|
12
13
|
import { setViewport } from '@web/test-runner-commands';
|
|
13
|
-
import { isMobile } from '../../../../test/src/util/isMobile';
|
|
14
|
-
import { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints';
|
|
15
|
-
import { sleep } from '@zywave/../../test/src/util/helpers';
|
|
14
|
+
import { isMobile } from '../../../../test/src/util/isMobile.js';
|
|
15
|
+
import { screenBreakpoints } from '@zywave/zui-base/dist/utils/breakpoints.js';
|
|
16
|
+
import { sleep } from '@zywave/../../test/src/util/helpers.js';
|
|
16
17
|
|
|
17
18
|
suite('zui-table', () => {
|
|
18
19
|
let table: ZuiTableElement;
|
|
@@ -115,6 +116,28 @@ suite('zui-table', () => {
|
|
|
115
116
|
assert.isTrue(footerSlot, 'Expected zui-table-footer to be assigned to a slot');
|
|
116
117
|
});
|
|
117
118
|
|
|
119
|
+
test('hide counter and action divs in ZuiTableTopbar if empty', async () => {
|
|
120
|
+
const zuiSearch = document.createElement('zui-search');
|
|
121
|
+
topbar.appendChild(zuiSearch);
|
|
122
|
+
|
|
123
|
+
await table.updateComplete;
|
|
124
|
+
|
|
125
|
+
const counter = topbar.shadowRoot!.querySelector('.counter');
|
|
126
|
+
const counterSlot: HTMLSlotElement = counter.querySelector('slot[name="counter"]');
|
|
127
|
+
const counterSlotLength = counterSlot.assignedElements().length;
|
|
128
|
+
const counterComputedDisplayStyle = window.getComputedStyle(counter).getPropertyValue('display');
|
|
129
|
+
|
|
130
|
+
const action = topbar.shadowRoot!.querySelector('.action');
|
|
131
|
+
const actionSlot: HTMLSlotElement = action.querySelector('slot[name="action"]');
|
|
132
|
+
const actionSlotLength = actionSlot.assignedElements().length;
|
|
133
|
+
const actionComputedDisplayStyle = window.getComputedStyle(action).getPropertyValue('display');
|
|
134
|
+
|
|
135
|
+
assert.equal(counterSlotLength, 0, 'Expected counter slot length to be 0 when empty');
|
|
136
|
+
assert.equal(counterComputedDisplayStyle, 'none', 'Expected counter div to be hidden on mobile if empty');
|
|
137
|
+
assert.equal(actionSlotLength, 0, 'Expected action slot length to be 0 when empty');
|
|
138
|
+
assert.equal(actionComputedDisplayStyle, 'none', 'Expected counter div to be hidden on mobile if empty');
|
|
139
|
+
});
|
|
140
|
+
|
|
118
141
|
test('mobile table with headers in cell', async () => {
|
|
119
142
|
const rowHeader = document.createElement('zui-table-row');
|
|
120
143
|
const rowHeaderCell = document.createElement('zui-table-cell');
|
|
@@ -128,7 +151,7 @@ suite('zui-table', () => {
|
|
|
128
151
|
// TODO: Investigate why setting viewport prior to table update completion fails
|
|
129
152
|
await table.updateComplete;
|
|
130
153
|
await sleep(100);
|
|
131
|
-
await setViewport({ width:
|
|
154
|
+
await setViewport({ width: 479, height: 640 });
|
|
132
155
|
|
|
133
156
|
const rowHeaderComputedDisplayStyle = window.getComputedStyle(rowHeader).getPropertyValue('display');
|
|
134
157
|
const rowHeaderText = rowHeaderCell.textContent;
|
|
@@ -146,4 +169,123 @@ suite('zui-table', () => {
|
|
|
146
169
|
`Expected table body cell text (${bodyCellHeaderText}) to have header text (${rowHeaderText}) in it`
|
|
147
170
|
);
|
|
148
171
|
});
|
|
172
|
+
|
|
173
|
+
test('ZuiButtons in the ZuiTableTopbar action slot switches to block style on mobile', async () => {
|
|
174
|
+
const actionButton = document.createElement('zui-button');
|
|
175
|
+
actionButton.innerText = 'Add a new entry';
|
|
176
|
+
actionButton.setAttribute('slot', 'action');
|
|
177
|
+
topbar.appendChild(actionButton);
|
|
178
|
+
|
|
179
|
+
// Order matters here
|
|
180
|
+
// TODO: Investigate why setting viewport prior to table update completion fails
|
|
181
|
+
await table.updateComplete;
|
|
182
|
+
await sleep(100);
|
|
183
|
+
await setViewport({ width: 479, height: 640 });
|
|
184
|
+
|
|
185
|
+
const actionButtonStyle = actionButton.hasAttribute('block');
|
|
186
|
+
|
|
187
|
+
assert.isTrue(isMobile(), `Expected viewport to be <${screenBreakpoints.xsmall}`);
|
|
188
|
+
assert.isTrue(actionButtonStyle);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
suite('sort', () => {
|
|
192
|
+
test('cell can only be sortable when in header row', async () => {
|
|
193
|
+
row.remove();
|
|
194
|
+
|
|
195
|
+
const newRow = document.createElement('zui-table-row');
|
|
196
|
+
const sortableCell = document.createElement('zui-table-cell');
|
|
197
|
+
sortableCell.setAttribute('sortable', '');
|
|
198
|
+
|
|
199
|
+
newRow.appendChild(sortableCell);
|
|
200
|
+
table.append(newRow);
|
|
201
|
+
|
|
202
|
+
await sortableCell.updateComplete;
|
|
203
|
+
|
|
204
|
+
assert.isFalse(sortableCell.sortable);
|
|
205
|
+
|
|
206
|
+
newRow.setAttribute('header', '');
|
|
207
|
+
|
|
208
|
+
await sortableCell.updateComplete;
|
|
209
|
+
assert.isTrue(sortableCell.sortable);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('clicking sortable cell dispatches sort event', async () => {
|
|
213
|
+
let sortEvent: CustomEvent<{ sort: ZuiTableSortDirection; cell: ZuiTableCellElement }> | undefined;
|
|
214
|
+
let dispatchedSortEventsCounter = 0;
|
|
215
|
+
cell.setAttribute('sortable', '');
|
|
216
|
+
row.setAttribute('header', '');
|
|
217
|
+
await cell.updateComplete;
|
|
218
|
+
|
|
219
|
+
table.addEventListener(
|
|
220
|
+
'sort',
|
|
221
|
+
(event: CustomEvent<{ sort: ZuiTableSortDirection; cell: ZuiTableCellElement }>) => {
|
|
222
|
+
sortEvent = event;
|
|
223
|
+
dispatchedSortEventsCounter++;
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
cell.click();
|
|
228
|
+
|
|
229
|
+
assert.exists(sortEvent);
|
|
230
|
+
assert.equal(sortEvent.detail.sort, 'ascending');
|
|
231
|
+
assert.equal(sortEvent.detail.cell, cell);
|
|
232
|
+
|
|
233
|
+
await sleep(100);
|
|
234
|
+
|
|
235
|
+
assert.equal(dispatchedSortEventsCounter, 1);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test('clicking sortable cell changes direction', async () => {
|
|
239
|
+
cell.setAttribute('sortable', '');
|
|
240
|
+
row.setAttribute('header', '');
|
|
241
|
+
await cell.updateComplete;
|
|
242
|
+
|
|
243
|
+
assert.equal(cell.sort, null);
|
|
244
|
+
|
|
245
|
+
cell.click();
|
|
246
|
+
assert.equal(cell.sort, 'ascending');
|
|
247
|
+
|
|
248
|
+
cell.click();
|
|
249
|
+
assert.equal(cell.sort, 'descending');
|
|
250
|
+
|
|
251
|
+
cell.click();
|
|
252
|
+
assert.equal(cell.sort, null);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('clicking sibling sortable cell resets direction', async () => {
|
|
256
|
+
cell.setAttribute('sortable', '');
|
|
257
|
+
cell.setAttribute('sort', 'ascending');
|
|
258
|
+
|
|
259
|
+
const otherCell = document.createElement('zui-table-cell');
|
|
260
|
+
otherCell.setAttribute('sortable', '');
|
|
261
|
+
|
|
262
|
+
row.setAttribute('header', '');
|
|
263
|
+
row.appendChild(otherCell);
|
|
264
|
+
await cell.updateComplete;
|
|
265
|
+
|
|
266
|
+
assert.equal(cell.sort, 'ascending');
|
|
267
|
+
assert.equal(otherCell.sort, null);
|
|
268
|
+
|
|
269
|
+
otherCell.click();
|
|
270
|
+
assert.equal(cell.sort, null);
|
|
271
|
+
assert.equal(otherCell.sort, 'ascending');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test('multiple header cells with directions set are reset except first', async () => {
|
|
275
|
+
cell.setAttribute('sortable', '');
|
|
276
|
+
cell.setAttribute('sort', 'ascending');
|
|
277
|
+
row.setAttribute('header', '');
|
|
278
|
+
|
|
279
|
+
const otherCell = document.createElement('zui-table-cell');
|
|
280
|
+
otherCell.setAttribute('sortable', '');
|
|
281
|
+
otherCell.setAttribute('sort', 'ascending');
|
|
282
|
+
row.appendChild(otherCell);
|
|
283
|
+
|
|
284
|
+
await cell.updateComplete;
|
|
285
|
+
|
|
286
|
+
assert.equal(cell.sort, 'ascending');
|
|
287
|
+
assert.equal(otherCell.sort, null);
|
|
288
|
+
assert.isFalse(otherCell.hasAttribute('sort'));
|
|
289
|
+
});
|
|
290
|
+
});
|
|
149
291
|
});
|