@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zywave/zui-table",
|
|
3
|
-
"version": "4.0.2-pre.
|
|
3
|
+
"version": "4.0.2-pre.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"build:clean": "node ../../../scripts/node/remove-build-files.mjs && yarn run build",
|
|
10
10
|
"build:scss": "node ../../../scripts/node/sass.mjs",
|
|
11
11
|
"build:ts": "tsc -p tsconfig.build.json",
|
|
12
|
-
"launch-server:
|
|
12
|
+
"launch-server:cem": "es-dev-server --root-dir ../../../ --app-index packages/components/zui-table/docs/customelement-manifest-element.html --open --node-resolve --watch",
|
|
13
|
+
"launch-server:demo": "es-dev-server --root-dir ../../../ --app-index packages/components/zui-table/docs/demo.html --open --node-resolve --watch",
|
|
13
14
|
"launch-server:lab": "es-dev-server --root-dir ../../../ --app-index packages/components/zui-table/lab.html --open --node-resolve --watch",
|
|
14
15
|
"demo": "npm-run-all build --parallel watcher:start launch-server:demo",
|
|
15
16
|
"watch": "npm-run-all build --parallel watcher:start launch-server:lab",
|
|
@@ -21,7 +22,11 @@
|
|
|
21
22
|
},
|
|
22
23
|
"customElements": "dist/custom-elements.json",
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@zywave/zui-base": "^4.1.20-pre.
|
|
25
|
+
"@zywave/zui-base": "^4.1.20-pre.2",
|
|
26
|
+
"@zywave/zui-icons": "^4.0.26-pre.2"
|
|
25
27
|
},
|
|
26
|
-
"
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@zywave/zui-button": "^4.0.26-pre.2"
|
|
30
|
+
},
|
|
31
|
+
"gitHead": "957ede57ae7125aa5f34137d1dd502260968055b"
|
|
27
32
|
}
|
package/src/base.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ZuiBaseElement } from '@zywave/zui-base';
|
|
2
|
+
import type { ZuiTableElement } from './zui-table';
|
|
3
|
+
import type { ZuiTableCellElement } from './zui-table-cell';
|
|
4
|
+
|
|
5
|
+
class TableState {
|
|
6
|
+
elements: Set<ZuiTableBaseElement> = new Set();
|
|
7
|
+
root: ZuiTableElement;
|
|
8
|
+
sortedCell?: ZuiTableCellElement;
|
|
9
|
+
channel = new EventTarget();
|
|
10
|
+
|
|
11
|
+
constructor(root: ZuiTableElement) {
|
|
12
|
+
this.root = root;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export abstract class ZuiTableBaseElement extends ZuiBaseElement {
|
|
17
|
+
/**
|
|
18
|
+
* This represents a common eventing ecosystem for all ZuiTableBaseElements, regardless of association
|
|
19
|
+
*/
|
|
20
|
+
protected static _globalChannel = new EventTarget();
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Accessor for the associated table state
|
|
24
|
+
*/
|
|
25
|
+
protected get _state() {
|
|
26
|
+
if (this.tagName === 'ZUI-TABLE') {
|
|
27
|
+
return ZuiTableBaseElement.#states.get(this as unknown as ZuiTableElement);
|
|
28
|
+
}
|
|
29
|
+
const table = ZuiTableBaseElement.#tableAssociations.get(this);
|
|
30
|
+
if (table) {
|
|
31
|
+
return ZuiTableBaseElement.#states.get(table);
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static #states = new WeakMap<ZuiTableElement, TableState>();
|
|
37
|
+
static #tableAssociations = new WeakMap<ZuiTableBaseElement, ZuiTableElement>();
|
|
38
|
+
|
|
39
|
+
constructor() {
|
|
40
|
+
super();
|
|
41
|
+
|
|
42
|
+
if (this.tagName === 'ZUI-TABLE') {
|
|
43
|
+
ZuiTableBaseElement.#states.set(
|
|
44
|
+
this as unknown as ZuiTableElement,
|
|
45
|
+
new TableState(this as unknown as ZuiTableElement)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
connectedCallback() {
|
|
51
|
+
super.connectedCallback();
|
|
52
|
+
|
|
53
|
+
if (this.tagName !== 'ZUI-TABLE') {
|
|
54
|
+
ZuiTableBaseElement._globalChannel.dispatchEvent(new CustomEvent('connected', { detail: { element: this } }));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
disconnectedCallback() {
|
|
59
|
+
super.disconnectedCallback();
|
|
60
|
+
|
|
61
|
+
if (this.tagName === 'ZUI-TABLE') {
|
|
62
|
+
ZuiTableBaseElement.#states.delete(this as unknown as ZuiTableElement);
|
|
63
|
+
} else {
|
|
64
|
+
ZuiTableBaseElement.#tableAssociations.delete(this);
|
|
65
|
+
this._state?.elements.delete(this);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
protected _associateElement(element: ZuiTableBaseElement) {
|
|
70
|
+
if (this.tagName !== 'ZUI-TABLE' || element.tagName === 'ZUI-TABLE') {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
ZuiTableBaseElement.#tableAssociations.set(element, this as unknown as ZuiTableElement);
|
|
75
|
+
this._state.elements.add(element);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type TableElementConnectedEvent = CustomEvent<{ element: ZuiTableBaseElement }>;
|
|
@@ -5,20 +5,11 @@ zui-table {
|
|
|
5
5
|
@include undefined-element {
|
|
6
6
|
display: block;
|
|
7
7
|
width: 100%;
|
|
8
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
9
8
|
border-collapse: collapse;
|
|
10
9
|
border-spacing: 0;
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
min-height: rem(60);
|
|
15
|
-
align-items: center;
|
|
16
|
-
padding: rem(10) rem(20);
|
|
17
|
-
background-color: var(--zui-gray-25);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
[slot='footer'] {
|
|
21
|
-
margin-top: rem(10);
|
|
11
|
+
@media (min-width: $bp-xs) {
|
|
12
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
22
13
|
}
|
|
23
14
|
|
|
24
15
|
[slot='no-results-message'] {
|
|
@@ -44,6 +35,12 @@ zui-table[no-results] {
|
|
|
44
35
|
[slot='no-results-message'] {
|
|
45
36
|
display: block;
|
|
46
37
|
padding: rem(12) rem(20);
|
|
38
|
+
background-color: #fff;
|
|
39
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
40
|
+
|
|
41
|
+
@media (min-width: $bp-xs) {
|
|
42
|
+
box-shadow: none;
|
|
43
|
+
}
|
|
47
44
|
}
|
|
48
45
|
}
|
|
49
46
|
}
|
|
@@ -53,24 +50,98 @@ zui-table-topbar {
|
|
|
53
50
|
display: flex;
|
|
54
51
|
width: 100%;
|
|
55
52
|
min-height: rem(60);
|
|
53
|
+
flex-wrap: wrap;
|
|
56
54
|
align-items: center;
|
|
57
|
-
padding: rem(10)
|
|
58
|
-
|
|
55
|
+
// padding-bottom: rem(10);
|
|
56
|
+
|
|
57
|
+
@media (min-width: $bp-xs) {
|
|
58
|
+
flex-wrap: nowrap;
|
|
59
|
+
padding: rem(10) rem(20);
|
|
60
|
+
background-color: var(--zui-gray-25);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
*:not([slot='action']):not([slot='counter']) {
|
|
64
|
+
margin-bottom: rem(20);
|
|
65
|
+
|
|
66
|
+
@media (min-width: $bp-xs) {
|
|
67
|
+
margin-bottom: 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
zui-search {
|
|
72
|
+
--zui-search-border-color: var(--zui-gray-50);
|
|
73
|
+
flex: 1;
|
|
74
|
+
flex-basis: 100%;
|
|
75
|
+
order: 1;
|
|
76
|
+
|
|
77
|
+
@media (min-width: $bp-xxs) {
|
|
78
|
+
flex-basis: auto;
|
|
79
|
+
order: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@media (min-width: $bp-xs) {
|
|
83
|
+
flex: 0;
|
|
84
|
+
margin-right: auto;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
59
87
|
|
|
60
88
|
[slot='counter'] {
|
|
89
|
+
display: flex;
|
|
90
|
+
width: 100%;
|
|
61
91
|
flex-shrink: 0;
|
|
62
|
-
|
|
92
|
+
justify-content: flex-end;
|
|
93
|
+
order: 2;
|
|
94
|
+
margin-bottom: rem(10);
|
|
63
95
|
padding-left: rem(10);
|
|
64
96
|
font-size: rem(12);
|
|
65
97
|
color: var(--zui-gray-400);
|
|
98
|
+
|
|
99
|
+
@media (min-width: $bp-xs) {
|
|
100
|
+
width: auto;
|
|
101
|
+
margin-bottom: 0;
|
|
102
|
+
}
|
|
66
103
|
}
|
|
67
104
|
|
|
68
105
|
[slot='action'] {
|
|
69
|
-
|
|
106
|
+
width: 100%;
|
|
107
|
+
margin-bottom: rem(20);
|
|
70
108
|
|
|
71
|
-
|
|
109
|
+
@media (min-width: $bp-xxs) {
|
|
110
|
+
width: auto;
|
|
72
111
|
margin-left: rem(10);
|
|
73
112
|
}
|
|
113
|
+
|
|
114
|
+
@media (min-width: $bp-xs) {
|
|
115
|
+
margin-bottom: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&:first-of-type {
|
|
119
|
+
margin-bottom: 0;
|
|
120
|
+
|
|
121
|
+
@media (min-width: $bp-xxs) {
|
|
122
|
+
margin-bottom: rem(20);
|
|
123
|
+
margin-left: rem(20);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@media (min-width: $bp-xs) {
|
|
127
|
+
margin-bottom: 0;
|
|
128
|
+
margin-left: rem(10);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
&:last-of-type {
|
|
133
|
+
margin-bottom: rem(20);
|
|
134
|
+
|
|
135
|
+
@media (min-width: $bp-xs) {
|
|
136
|
+
margin-bottom: 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
+ [slot='action'] {
|
|
141
|
+
@media (max-width: $bp-xxs) {
|
|
142
|
+
margin-top: rem(10);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
74
145
|
}
|
|
75
146
|
}
|
|
76
147
|
}
|
|
@@ -81,10 +152,12 @@ zui-table-row {
|
|
|
81
152
|
grid-template-columns: auto;
|
|
82
153
|
padding: rem(10) 0;
|
|
83
154
|
background-color: #fff;
|
|
155
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
84
156
|
|
|
85
157
|
@media (min-width: $bp-xs) {
|
|
86
158
|
display: flex;
|
|
87
159
|
padding: 0;
|
|
160
|
+
box-shadow: none;
|
|
88
161
|
}
|
|
89
162
|
}
|
|
90
163
|
}
|
|
@@ -108,7 +181,7 @@ zui-table-row[header] {
|
|
|
108
181
|
|
|
109
182
|
zui-table-row:not([header]) {
|
|
110
183
|
@include undefined-element {
|
|
111
|
-
border-bottom:
|
|
184
|
+
border-bottom: 2px solid var(--zui-gray-100);
|
|
112
185
|
|
|
113
186
|
@media (min-width: $bp-xs) {
|
|
114
187
|
border-bottom-width: 1px;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
2
|
|
|
3
|
-
export const style = css`:host{contain:none}:host([action]) div{display:flex}@media(min-width: 45em){:host([action]) div{--zui-table-cell-padding: 0.375rem 1.25rem;align-items:center}}:host([action]) ::slotted(zui-button:not(:first-of-type)){margin-left:.625rem}div{padding:var(--zui-table-cell-padding, 0.3125rem 0.9375rem)}@media(min-width: 45em){div{padding:var(--zui-table-cell-padding, 0.8125rem 1.25rem)}}div.header{float:left;width:33.333%;font-weight:600}div.header+div{padding:var(--zui-table-cell-padding, 0.3125rem 0.9375rem 0.3125rem 0)}`;
|
|
3
|
+
export const style = css`:host{--zui-table-cell-sort-active-color: var(--zui-blue);--zui-table-cell-sort-color: var(--zui-gray-300);contain:none;overflow-wrap:break-word}:host([action]) div{display:flex}@media(min-width: 45em){:host([action]) div{--zui-table-cell-padding: 0.375rem 1.25rem;align-items:center}}:host([action]) ::slotted(zui-button:not(:first-of-type)){margin-left:.625rem}:host([sort=ascending]) zui-icon{--zui-icon-sort-ascending-color: var(--zui-table-cell-sort-active-color)}:host([sort=descending]) zui-icon{--zui-icon-sort-descending-color: var(--zui-table-cell-sort-active-color)}div{padding:var(--zui-table-cell-padding, 0.3125rem 0.9375rem)}@media(min-width: 45em){div{padding:var(--zui-table-cell-padding, 0.8125rem 1.25rem)}}div.header{float:left;width:33.333%;font-weight:600}div.header+div{padding:var(--zui-table-cell-padding, 0.3125rem 0.9375rem 0.3125rem 0)}zui-icon{--zui-icon-size: 1.125rem;vertical-align:middle;margin-left:.625rem;fill:var(--zui-table-cell-sort-color)}.is-selectable{cursor:pointer}`;
|
package/src/zui-table-cell.scss
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
@use '@zywave/zui-base-styles/src/variables' as *;
|
|
3
3
|
|
|
4
4
|
:host {
|
|
5
|
+
--zui-table-cell-sort-active-color: var(--zui-blue);
|
|
6
|
+
--zui-table-cell-sort-color: var(--zui-gray-300);
|
|
5
7
|
contain: none;
|
|
8
|
+
overflow-wrap: break-word;
|
|
6
9
|
}
|
|
7
10
|
|
|
8
11
|
:host([action]) {
|
|
@@ -19,6 +22,18 @@
|
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
:host([sort='ascending']) {
|
|
26
|
+
zui-icon {
|
|
27
|
+
--zui-icon-sort-ascending-color: var(--zui-table-cell-sort-active-color);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:host([sort='descending']) {
|
|
32
|
+
zui-icon {
|
|
33
|
+
--zui-icon-sort-descending-color: var(--zui-table-cell-sort-active-color);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
div {
|
|
23
38
|
padding: var(--zui-table-cell-padding, #{rem(5)} #{rem(15)});
|
|
24
39
|
|
|
@@ -36,3 +51,14 @@ div.header {
|
|
|
36
51
|
padding: var(--zui-table-cell-padding, #{rem(5)} #{rem(15)} #{rem(5)} 0);
|
|
37
52
|
}
|
|
38
53
|
}
|
|
54
|
+
|
|
55
|
+
zui-icon {
|
|
56
|
+
--zui-icon-size: #{rem(18)};
|
|
57
|
+
vertical-align: middle;
|
|
58
|
+
margin-left: rem(10);
|
|
59
|
+
fill: var(--zui-table-cell-sort-color);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.is-selectable {
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
}
|
package/src/zui-table-cell.ts
CHANGED
|
@@ -1,33 +1,111 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { html } from 'lit';
|
|
3
|
-
import { property } from 'lit/decorators.js';
|
|
1
|
+
import { ZuiTableBaseElement } from './base.js';
|
|
2
|
+
import { html, nothing } from 'lit';
|
|
3
|
+
import { property, state } from 'lit/decorators.js';
|
|
4
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
4
5
|
import { style } from './zui-table-cell-css.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
8
|
+
* An individual table cell to be passed into a `<zui-table-row>`.
|
|
9
|
+
*
|
|
7
10
|
* @element zui-table-cell
|
|
8
11
|
*
|
|
9
|
-
* @slot -
|
|
12
|
+
* @slot - Unnamed slot, table cell content goes here
|
|
10
13
|
*
|
|
11
14
|
* @cssprop [--zui-table-cell-padding=13px 20px] - Override cell padding
|
|
15
|
+
* @cssprop [--zui-table-cell-sort-color=var(--zui-gray-300)] - ([sortable]): Default color of chevron when `direction` is `null`
|
|
16
|
+
* @cssprop [--zui-table-cell-sort-active-color=var(--zui-blue)] - Highlight color used to indicate the active sort direction
|
|
17
|
+
*
|
|
18
|
+
* @event sort - Event fires when a `sortable` cell is clicked
|
|
12
19
|
*/
|
|
13
|
-
export class ZuiTableCellElement extends
|
|
20
|
+
export class ZuiTableCellElement extends ZuiTableBaseElement {
|
|
14
21
|
/**
|
|
15
22
|
* Set to decrease table cell padding to accommodate action button(s)
|
|
16
23
|
*/
|
|
17
24
|
@property({ type: Boolean, reflect: true })
|
|
18
25
|
action = false;
|
|
19
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Current sort direction of the sortable cell
|
|
29
|
+
* @type {null | "ascending" | "descending"}
|
|
30
|
+
*/
|
|
31
|
+
@property({ type: String, reflect: true })
|
|
32
|
+
get sort(): ZuiTableSortDirection {
|
|
33
|
+
return this.#sort;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set sort(val: ZuiTableSortDirection) {
|
|
37
|
+
const acceptableVals = ['ascending', 'descending', null];
|
|
38
|
+
if (acceptableVals.includes(val)) {
|
|
39
|
+
const oldVal = this.#sort;
|
|
40
|
+
this.#sort = val;
|
|
41
|
+
this.requestUpdate('sort', oldVal);
|
|
42
|
+
this._state?.channel.dispatchEvent(new CustomEvent('sort', { detail: { sort: val, cell: this } }));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* (`zui-table-row[header]`): Whether or not cell header is sortable; another requirement is the parent element, `<zui-table-cell header>` must have `header` attribute or property set
|
|
48
|
+
*/
|
|
49
|
+
@property({ type: Boolean, reflect: true })
|
|
50
|
+
get sortable() {
|
|
51
|
+
return this._isAllowedSort && this.#sortable;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
set sortable(val: boolean) {
|
|
55
|
+
const oldVal = this.#sortable;
|
|
56
|
+
this.#sortable = val;
|
|
57
|
+
this.requestUpdate('sortable', oldVal);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* This private field is needed to persist state between the cell and the header row. DO NOT USE EXTERNALLY
|
|
62
|
+
*/
|
|
63
|
+
@state()
|
|
64
|
+
private _isAllowedSort = false;
|
|
65
|
+
|
|
66
|
+
#sort: ZuiTableSortDirection = null;
|
|
67
|
+
#sortable = false;
|
|
68
|
+
|
|
20
69
|
static get styles() {
|
|
21
70
|
return [super.styles, style];
|
|
22
71
|
}
|
|
23
72
|
|
|
24
73
|
render() {
|
|
25
|
-
|
|
74
|
+
const styles = { 'is-selectable': this.sortable };
|
|
75
|
+
return html`<div @click="${this.#onSortableClick}" class="${classMap(styles)}">
|
|
76
|
+
<slot></slot>
|
|
77
|
+
${this.sortable ? html`<zui-icon icon="zui-sort"></zui-icon>` : nothing}
|
|
78
|
+
</div>`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
click() {
|
|
82
|
+
super.click();
|
|
83
|
+
|
|
84
|
+
this.#onSortableClick();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#onSortableClick() {
|
|
88
|
+
if (this.sortable) {
|
|
89
|
+
switch (this.sort) {
|
|
90
|
+
case 'ascending':
|
|
91
|
+
this.sort = 'descending';
|
|
92
|
+
break;
|
|
93
|
+
case 'descending':
|
|
94
|
+
this.sort = null;
|
|
95
|
+
break;
|
|
96
|
+
case null:
|
|
97
|
+
default:
|
|
98
|
+
this.sort = 'ascending';
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
26
102
|
}
|
|
27
103
|
}
|
|
28
104
|
|
|
29
105
|
window.customElements.define('zui-table-cell', ZuiTableCellElement);
|
|
30
106
|
|
|
107
|
+
export type ZuiTableSortDirection = null | 'ascending' | 'descending';
|
|
108
|
+
|
|
31
109
|
declare global {
|
|
32
110
|
interface HTMLElementTagNameMap {
|
|
33
111
|
'zui-table-cell': ZuiTableCellElement;
|
package/src/zui-table-css.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
2
|
|
|
3
|
-
export const style = css`:host{contain:none;display:block}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:transparent;box-shadow:none}}::slotted(zui-table-row:not([header])){border-bottom:
|
|
3
|
+
export const style = css`:host{contain:none;display:block}:host([banded]) ::slotted(zui-table-row:not([header]):nth-child(even)){background-color:var(--zui-gray-25)}:host([banded]) ::slotted(zui-table-row:not([header])){border:0}:host([no-results]) .no-results{padding:.75rem 1.25rem;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){:host([no-results]) .no-results{background-color:transparent;box-shadow:none}}::slotted(zui-table-row:not([header])){border-bottom:2px solid var(--zui-gray-100)}@media(min-width: 45em){::slotted(zui-table-row:not([header])){border-bottom-width:1px}}::slotted(zui-table-row:not([header]):last-of-type){border-bottom:0}.table{display:flex;width:100%;flex-direction:column;border-collapse:collapse;border-spacing:0}@media(min-width: 45em){.table{background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}}`;
|
package/src/zui-table-footer.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ZuiTableBaseElement } from './base.js';
|
|
2
2
|
import { html } from 'lit';
|
|
3
3
|
import { style } from './zui-table-footer-css.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
+
* Footer table element, should come as the last item passed into a `<zui-table>`.
|
|
7
|
+
*
|
|
6
8
|
* @element zui-table-footer
|
|
7
9
|
*
|
|
8
|
-
* @slot -
|
|
10
|
+
* @slot - Unnamed slot, table footer content goes here
|
|
9
11
|
*
|
|
10
|
-
* @cssprop [--zui-table-footer-margin=10px] - Override the margin between the table and footer of the table
|
|
12
|
+
* @cssprop [--zui-table-footer-margin=0.625rem (10px)] - Override the margin between the table and footer of the table
|
|
11
13
|
*/
|
|
12
|
-
export class ZuiTableFooterElement extends
|
|
14
|
+
export class ZuiTableFooterElement extends ZuiTableBaseElement {
|
|
13
15
|
static get styles() {
|
|
14
16
|
return [super.styles, style];
|
|
15
17
|
}
|
package/src/zui-table-row-css.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
2
|
|
|
3
|
-
export const style = css`:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600
|
|
3
|
+
export const style = css`:host{contain:none}:host(:last-of-type:not([summary])) div,:host([summary]) div{margin-bottom:0}:host([header]){display:none;background-color:#fff;border-bottom:1px solid var(--zui-gray-200)}@media(min-width: 45em){:host([header]){display:block}}:host([header]) div{box-shadow:none}:host([header]) ::slotted(zui-table-cell){--zui-table-cell-padding: 0.53125rem 1.25rem;font-weight:600;user-select:none}div{display:grid;grid-template-columns:auto;margin-bottom:0;padding:.625rem 0;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.29)}@media(min-width: 45em){div{grid-template-columns:var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));padding:0;background-color:transparent;box-shadow:none}}:host([summary]){background-color:var(--zui-table-summary-background-color, var(--zui-gray-600)) !important}:host([summary]) div{margin-bottom:0;background-color:transparent}:host([summary]) ::slotted(zui-table-cell){font-weight:600;color:var(--zui-table-summary-text-color, #fff)}`;
|
package/src/zui-table-row.scss
CHANGED
|
@@ -17,13 +17,18 @@
|
|
|
17
17
|
background-color: #fff;
|
|
18
18
|
border-bottom: 1px solid var(--zui-gray-200);
|
|
19
19
|
|
|
20
|
+
@media (min-width: $bp-xs) {
|
|
21
|
+
display: block;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
div {
|
|
25
|
+
box-shadow: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
20
28
|
::slotted(zui-table-cell) {
|
|
21
29
|
--zui-table-cell-padding: #{rem(8.5)} #{rem(20)};
|
|
22
30
|
font-weight: 600;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@media (min-width: $bp-xs) {
|
|
26
|
-
display: block;
|
|
31
|
+
user-select: none;
|
|
27
32
|
}
|
|
28
33
|
}
|
|
29
34
|
|
|
@@ -33,11 +38,13 @@ div {
|
|
|
33
38
|
margin-bottom: 0;
|
|
34
39
|
padding: rem(10) 0;
|
|
35
40
|
background-color: #fff;
|
|
41
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.29);
|
|
36
42
|
|
|
37
43
|
@media (min-width: $bp-xs) {
|
|
38
44
|
grid-template-columns: var(--zui-table-columns-template, repeat(auto-fit, minmax(0, 1fr)));
|
|
39
45
|
padding: 0;
|
|
40
46
|
background-color: transparent;
|
|
47
|
+
box-shadow: none;
|
|
41
48
|
}
|
|
42
49
|
}
|
|
43
50
|
|
package/src/zui-table-row.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ZuiTableBaseElement } 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-row-css.js';
|
|
5
5
|
import type { ZuiTableCellElement } from './zui-table-cell.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
+
* Pass into `<zui-table>`, `<zui-table-row>` holds a row of `<zui-table-cell>`'s.
|
|
9
|
+
*
|
|
8
10
|
* @element zui-table-row
|
|
9
11
|
*
|
|
10
|
-
* @slot -
|
|
12
|
+
* @slot - Unnamed slot, `<zui-table-cell>`s are declared here
|
|
11
13
|
*
|
|
12
|
-
* @cssprop [--zui-table-columns-template=repeat(auto-fit, minmax(0, 1fr))] - Override the table columns template. See
|
|
14
|
+
* @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.
|
|
13
15
|
* @cssprop [--zui-table-summary-background-color=var(--zui-gray-600)] - Override the table summary background color
|
|
14
16
|
* @cssprop [--zui-table-summary-text-color=#fff] - Override the table summary text color
|
|
15
17
|
*/
|
|
16
|
-
export class ZuiTableRowElement extends
|
|
18
|
+
export class ZuiTableRowElement extends ZuiTableBaseElement {
|
|
17
19
|
/**
|
|
18
20
|
* Declare a table header; typically the first row in `<zui-table>`
|
|
19
21
|
*/
|
|
@@ -29,6 +31,8 @@ export class ZuiTableRowElement extends ZuiBaseElement {
|
|
|
29
31
|
@queryAssignedElements({ selector: 'zui-table-cell' })
|
|
30
32
|
private _slottedCells: Array<ZuiTableCellElement>;
|
|
31
33
|
|
|
34
|
+
#sortLock?: boolean;
|
|
35
|
+
|
|
32
36
|
static get styles() {
|
|
33
37
|
return [super.styles, style];
|
|
34
38
|
}
|
|
@@ -39,27 +43,63 @@ export class ZuiTableRowElement extends ZuiBaseElement {
|
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
firstUpdated() {
|
|
42
|
-
this
|
|
46
|
+
if (this.header) {
|
|
47
|
+
const firstCellWithDirection = this._slottedCells?.find((cell) => cell?.hasAttribute('sort'));
|
|
48
|
+
this._slottedCells.forEach((cell) => {
|
|
49
|
+
if (cell.sort && cell !== firstCellWithDirection) {
|
|
50
|
+
cell.sort = null;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
updated(changedProperties: Map<string | number | symbol, unknown>) {
|
|
57
|
+
super.updated(changedProperties);
|
|
58
|
+
if (changedProperties.has('header')) {
|
|
59
|
+
this.#ensureCellState();
|
|
60
|
+
if (this.header) {
|
|
61
|
+
this._state?.channel.addEventListener('sort', (e: CustomEvent<{ cell: HTMLElement }>) => this.#onTableSort(e));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
43
64
|
}
|
|
44
65
|
|
|
45
66
|
render() {
|
|
46
67
|
return html`<div>
|
|
47
|
-
<slot @slotchange="${this.#
|
|
68
|
+
<slot @slotchange="${this.#ensureCellState()}"></slot>
|
|
48
69
|
</div>`;
|
|
49
70
|
}
|
|
50
71
|
|
|
51
|
-
#
|
|
72
|
+
#onTableSort(event: CustomEvent<{ cell: HTMLElement }>) {
|
|
73
|
+
if (this.#sortLock) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.#sortLock = true;
|
|
77
|
+
this._slottedCells?.forEach((cell) => {
|
|
78
|
+
if (cell !== event.detail.cell) {
|
|
79
|
+
cell.sort = null;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
this.#sortLock = false;
|
|
84
|
+
}, 0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#ensureCellState() {
|
|
52
88
|
if (!this._slottedCells) {
|
|
53
89
|
return;
|
|
54
90
|
}
|
|
55
91
|
|
|
56
92
|
if (this.header) {
|
|
57
|
-
this._slottedCells.
|
|
93
|
+
this._slottedCells.forEach((cell) => {
|
|
94
|
+
cell.setAttribute('role', 'columnheader');
|
|
95
|
+
(cell as any)._isAllowedSort = true;
|
|
96
|
+
});
|
|
58
97
|
} else {
|
|
59
|
-
this._slottedCells.
|
|
98
|
+
this._slottedCells.forEach((cell) => {
|
|
99
|
+
cell.setAttribute('role', 'cell');
|
|
100
|
+
(cell as any)._isAllowedSort = false;
|
|
101
|
+
});
|
|
60
102
|
}
|
|
61
|
-
|
|
62
|
-
this.requestUpdate();
|
|
63
103
|
}
|
|
64
104
|
}
|
|
65
105
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
2
|
|
|
3
|
-
export const style = css`:host{contain:none}.topbar{display:flex;width:100%;min-height:3.75rem;align-items:center;padding:.625rem 1.25rem;background-color:var(--zui-gray-25);box-shadow:
|
|
3
|
+
export const style = css`:host{contain:none}.topbar{display:flex;width:100%;min-height:3.75rem;flex-wrap:wrap;justify-content:space-between;align-items:center}@media(min-width: 45em){.topbar{flex-wrap:nowrap;padding:.625rem 1.25rem;background-color:var(--zui-gray-25);box-shadow:none}}.content{display:flex;flex:1;align-items:center;order:1;margin-bottom:1.25rem}@media(min-width: 30em){.content{flex:auto;order:0}}@media(min-width: 45em){.content{margin-bottom:0}}.content ::slotted(zui-search){--zui-search-border-color: var(--zui-gray-50);width:100%}@media(min-width: 45em){.content ::slotted(zui-search){width:auto}}.counter{display:flex;width:100%;flex-shrink:0;justify-content:flex-end;order:2;margin-bottom:.625rem;margin-left:auto;padding-left:.625rem;font-size:.75rem;color:var(--zui-gray-400)}@media(min-width: 45em){.counter{width:auto;margin-bottom:0}}.action{display:flex;width:100%;justify-content:flex-end;margin-bottom:1.25rem}@media(min-width: 30em){.action{width:auto}}@media(min-width: 45em){.action{margin-bottom:0}}.action slot[name=action]{display:flex;width:100%;flex-direction:column}@media(min-width: 30em){.action slot[name=action]{flex-direction:row}}.action ::slotted(zui-button){width:100%}@media(min-width: 30em){.action ::slotted(zui-button){width:auto}}@media(min-width: 30em){.action ::slotted(zui-button:first-of-type){margin-left:1.25rem}}@media(min-width: 45em){.action ::slotted(zui-button:first-of-type){margin-left:.625rem}}.action ::slotted(zui-button:not(:first-of-type)){margin-top:.625rem}@media(min-width: 30em){.action ::slotted(zui-button:not(:first-of-type)){margin-top:0;margin-left:.625rem}}`;
|