@lit-material/data-table 0.0.1
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/LICENSE +21 -0
- package/README.md +133 -0
- package/dist/data-table-cell-styles.d.ts +2 -0
- package/dist/data-table-cell-styles.d.ts.map +1 -0
- package/dist/data-table-cell-styles.js +73 -0
- package/dist/data-table-cell-styles.js.map +1 -0
- package/dist/data-table-cell.d.ts +47 -0
- package/dist/data-table-cell.d.ts.map +1 -0
- package/dist/data-table-cell.js +90 -0
- package/dist/data-table-cell.js.map +1 -0
- package/dist/data-table-row-styles.d.ts +2 -0
- package/dist/data-table-row-styles.d.ts.map +1 -0
- package/dist/data-table-row-styles.js +27 -0
- package/dist/data-table-row-styles.js.map +1 -0
- package/dist/data-table-row.d.ts +28 -0
- package/dist/data-table-row.d.ts.map +1 -0
- package/dist/data-table-row.js +50 -0
- package/dist/data-table-row.js.map +1 -0
- package/dist/data-table-styles.d.ts +2 -0
- package/dist/data-table-styles.d.ts.map +1 -0
- package/dist/data-table-styles.js +18 -0
- package/dist/data-table-styles.js.map +1 -0
- package/dist/data-table.d.ts +60 -0
- package/dist/data-table.d.ts.map +1 -0
- package/dist/data-table.js +164 -0
- package/dist/data-table.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 bohdaq
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# @lit-material/data-table
|
|
2
|
+
|
|
3
|
+
Material Design 3 data table web components built with [Lit](https://lit.dev/). Part of
|
|
4
|
+
[lit-material](https://github.com/bohdaq/lit-material).
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install @lit-material/data-table @lit-material/tokens
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<link rel="stylesheet" href="node_modules/@lit-material/tokens/css/index.css" />
|
|
18
|
+
<script type="module">
|
|
19
|
+
import "@lit-material/data-table";
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<lit-material-data-table id="table">
|
|
23
|
+
<lit-material-data-table-row header>
|
|
24
|
+
<lit-material-data-table-cell header>
|
|
25
|
+
<input type="checkbox" data-select-all aria-label="Select all rows" />
|
|
26
|
+
</lit-material-data-table-cell>
|
|
27
|
+
<lit-material-data-table-cell header sort-key="name">Name</lit-material-data-table-cell>
|
|
28
|
+
<lit-material-data-table-cell header sort-key="age" numeric>Age</lit-material-data-table-cell>
|
|
29
|
+
</lit-material-data-table-row>
|
|
30
|
+
|
|
31
|
+
<lit-material-data-table-row data-row-id="1">
|
|
32
|
+
<lit-material-data-table-cell>
|
|
33
|
+
<input type="checkbox" data-row-select aria-label="Select row: Ada" />
|
|
34
|
+
</lit-material-data-table-cell>
|
|
35
|
+
<lit-material-data-table-cell>Ada</lit-material-data-table-cell>
|
|
36
|
+
<lit-material-data-table-cell numeric>32</lit-material-data-table-cell>
|
|
37
|
+
</lit-material-data-table-row>
|
|
38
|
+
</lit-material-data-table>
|
|
39
|
+
|
|
40
|
+
<script type="module">
|
|
41
|
+
const table = document.querySelector("#table");
|
|
42
|
+
table.addEventListener("sort-change", (e) => console.log(e.detail)); // { sortKey, sortDirection }
|
|
43
|
+
table.addEventListener("selection-change", (e) => console.log(e.detail)); // { selected: string[] }
|
|
44
|
+
</script>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Why not a real `<table>`?
|
|
48
|
+
|
|
49
|
+
An earlier version of this component wrapped a real `<table>`/`<thead>`/`<tbody>`, with sorting
|
|
50
|
+
and selection styled from the outer component's own shadow root. That doesn't work: CSS
|
|
51
|
+
`::slotted()` can only style a *directly* slotted node, never its descendants — so with
|
|
52
|
+
`<thead>`/`<tbody>` as the slotted content, individual `<th>`/`<td>` cells are unreachable from
|
|
53
|
+
the table's stylesheet entirely (the same wall
|
|
54
|
+
[`@lit-material/badge`](https://github.com/bohdaq/lit-material/tree/main/packages/badge)'s README
|
|
55
|
+
describes hitting from a different angle). Splitting the table into
|
|
56
|
+
`lit-material-data-table-row`/`-cell` sub-components — the same shape as
|
|
57
|
+
[`@lit-material/list`](https://github.com/bohdaq/lit-material/tree/main/packages/list)'s
|
|
58
|
+
list/list-item split — gives every visual unit its own shadow root to style, at the cost of using
|
|
59
|
+
`display: table` / `table-row` / `table-cell` instead of the real elements to still get native
|
|
60
|
+
column alignment.
|
|
61
|
+
|
|
62
|
+
## API
|
|
63
|
+
|
|
64
|
+
### `lit-material-data-table`
|
|
65
|
+
|
|
66
|
+
| Property | Attribute | Type | Default |
|
|
67
|
+
| ---------------- | ------------------ | ----------------------------------------- | -------------- |
|
|
68
|
+
| `sortKey` | `sort-key` | `string \| undefined` | `undefined` |
|
|
69
|
+
| `sortDirection` | `sort-direction` | `"none" \| "ascending" \| "descending"` | `"ascending"` |
|
|
70
|
+
|
|
71
|
+
Slot: default (`lit-material-data-table-row` elements).
|
|
72
|
+
|
|
73
|
+
This component owns UI *state* (which column is sorted which way, which rows are checked) and
|
|
74
|
+
*notifies* you of it via events — it never reorders rows or owns your data. Activating a sortable
|
|
75
|
+
header updates `sortKey`/`sortDirection`, syncs the indicator onto the right cell, and fires
|
|
76
|
+
`sort-change`; you re-render rows in the new order (or re-fetch a sorted page) in response. The
|
|
77
|
+
same headless-behavior split
|
|
78
|
+
[`@lit-material/tabs`](https://github.com/bohdaq/lit-material/tree/main/packages/tabs) makes for
|
|
79
|
+
tab panels.
|
|
80
|
+
|
|
81
|
+
Row selection works by event delegation rather than a hard dependency on any specific checkbox
|
|
82
|
+
implementation: put a real `<input type="checkbox">` (or
|
|
83
|
+
[`@lit-material/checkbox`](https://github.com/bohdaq/lit-material/tree/main/packages/checkbox), or
|
|
84
|
+
anything that fires a bubbling `change` event) with a `data-row-select` attribute in a row's cell,
|
|
85
|
+
and one with `data-select-all` in the header row's. Give each selectable row a `data-row-id`
|
|
86
|
+
attribute — `selection-change`'s `detail.selected` is the list of checked rows' `data-row-id`
|
|
87
|
+
values.
|
|
88
|
+
|
|
89
|
+
Fires `sort-change` (`detail: { sortKey, sortDirection }`) and `selection-change`
|
|
90
|
+
(`detail: { selected: string[] }`).
|
|
91
|
+
|
|
92
|
+
### `lit-material-data-table-row`
|
|
93
|
+
|
|
94
|
+
| Property | Attribute | Type | Default |
|
|
95
|
+
| ---------- | ---------- | --------- | ------- |
|
|
96
|
+
| `header` | `header` | `boolean` | `false` |
|
|
97
|
+
| `selected` | `selected` | `boolean` | `false` |
|
|
98
|
+
|
|
99
|
+
Slot: default (`lit-material-data-table-cell` elements). Set `header` on the row made up of
|
|
100
|
+
header cells (typically the first). `selected` is normally managed by the parent table from a
|
|
101
|
+
`data-row-select` checkbox's checked state, not set directly.
|
|
102
|
+
|
|
103
|
+
### `lit-material-data-table-cell`
|
|
104
|
+
|
|
105
|
+
| Property | Attribute | Type | Default |
|
|
106
|
+
| ---------------- | ------------------ | ----------------------------------------- | ------- |
|
|
107
|
+
| `header` | `header` | `boolean` | `false` |
|
|
108
|
+
| `numeric` | `numeric` | `boolean` | `false` |
|
|
109
|
+
| `sortKey` | `sort-key` | `string \| undefined` | `undefined` |
|
|
110
|
+
| `sortDirection` | `sort-direction` | `"none" \| "ascending" \| "descending"` | `"none"` |
|
|
111
|
+
|
|
112
|
+
Slot: default (the cell's content). `numeric` right-aligns content (and applies tabular figures)
|
|
113
|
+
— use it for numeric columns per the MD3 spec. Set `sort-key` on a `header` cell to make it
|
|
114
|
+
sortable: that wraps its content in a real `<button>` (the ARIA APG pattern for sortable column
|
|
115
|
+
headers is an interactive element *inside* the columnheader cell, not the cell itself carrying the
|
|
116
|
+
interaction). `sortDirection` is kept in sync by the parent table, not set directly.
|
|
117
|
+
|
|
118
|
+
## Accessibility
|
|
119
|
+
|
|
120
|
+
Built entirely on ARIA `table`/`row`/`columnheader`/`cell` roles (set automatically — the
|
|
121
|
+
underlying elements aren't real `<table>`/`<tr>`/`<th>`/`<td>`, see above for why) rather than
|
|
122
|
+
requiring you to wire them up. Row-select and select-all checkboxes need their own `aria-label` (a
|
|
123
|
+
bare checkbox has no accessible name of its own) — see the usage example above.
|
|
124
|
+
|
|
125
|
+
## Scope
|
|
126
|
+
|
|
127
|
+
Deliberately out of scope for this first pass: pagination, column resizing, column reordering, row
|
|
128
|
+
virtualization for very large datasets, and multi-column sort. All reasonable follow-ups, not
|
|
129
|
+
silently missing pieces.
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-cell-styles.d.ts","sourceRoot":"","sources":["../src/data-table-cell-styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBAsElB,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: table-cell;
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
padding: 12px 16px;
|
|
7
|
+
vertical-align: middle;
|
|
8
|
+
color: var(--md-sys-color-on-surface, #1c1b1f);
|
|
9
|
+
font-family: var(--md-sys-typescale-body-medium-font, Roboto, system-ui, sans-serif);
|
|
10
|
+
font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);
|
|
11
|
+
text-align: start;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:host([numeric]) {
|
|
15
|
+
text-align: end;
|
|
16
|
+
font-variant-numeric: tabular-nums;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
:host([header]) {
|
|
20
|
+
color: var(--md-sys-color-on-surface-variant, #49454f);
|
|
21
|
+
font-family: var(--md-sys-typescale-label-large-font, Roboto, system-ui, sans-serif);
|
|
22
|
+
font-size: var(--md-sys-typescale-label-large-size, 0.875rem);
|
|
23
|
+
font-weight: var(--md-sys-typescale-label-large-weight, 500);
|
|
24
|
+
white-space: nowrap;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.content {
|
|
28
|
+
display: inline-flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
gap: 4px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:host([numeric]) .content {
|
|
34
|
+
justify-content: flex-end;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Sortable header cells get a real <button> around their content (see the
|
|
38
|
+
component) — an ARIA APG "sortable column header" pattern, rather than
|
|
39
|
+
making the cell's own columnheader role itself the interactive target. */
|
|
40
|
+
.sort-button {
|
|
41
|
+
display: inline-flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: 4px;
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
border: none;
|
|
46
|
+
margin: 0;
|
|
47
|
+
padding: 0;
|
|
48
|
+
background: transparent;
|
|
49
|
+
color: inherit;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
font: inherit;
|
|
52
|
+
-webkit-appearance: none;
|
|
53
|
+
appearance: none;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.sort-button:focus-visible {
|
|
57
|
+
outline: 2px solid var(--md-sys-color-secondary, #625b71);
|
|
58
|
+
outline-offset: 2px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.sort-icon {
|
|
62
|
+
display: inline-block;
|
|
63
|
+
width: 1em;
|
|
64
|
+
font-size: 0.75em;
|
|
65
|
+
opacity: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:host([sort-direction="ascending"]) .sort-icon,
|
|
69
|
+
:host([sort-direction="descending"]) .sort-icon {
|
|
70
|
+
opacity: 1;
|
|
71
|
+
}
|
|
72
|
+
`;
|
|
73
|
+
//# sourceMappingURL=data-table-cell-styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-cell-styles.js","sourceRoot":"","sources":["../src/data-table-cell-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsExB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
export type SortDirection = "none" | "ascending" | "descending";
|
|
3
|
+
/**
|
|
4
|
+
* A single cell inside a `lit-material-data-table-row`.
|
|
5
|
+
*
|
|
6
|
+
* `header` renders it as a column header (`role="columnheader"`, label
|
|
7
|
+
* typography); otherwise it's a plain data cell (`role="cell"`). Set
|
|
8
|
+
* `sort-key` on a header cell to make it sortable — that wraps its content
|
|
9
|
+
* in a real `<button>` (the ARIA APG pattern for sortable column headers is
|
|
10
|
+
* an interactive element *inside* the columnheader cell, not the cell
|
|
11
|
+
* itself carrying the interaction) which requests a sort from the parent
|
|
12
|
+
* table on click; `sort-direction` is then kept in sync by the table, not
|
|
13
|
+
* set directly.
|
|
14
|
+
*
|
|
15
|
+
* `:host` uses `display: table-cell` (not a real `<td>`) so cells still
|
|
16
|
+
* align into columns via the browser's native table layout algorithm
|
|
17
|
+
* without needing an actual `<table>` element — see `lit-material-data-table`
|
|
18
|
+
* for why: CSS `::slotted()` can only style a *directly* slotted node, never
|
|
19
|
+
* its descendants, so a real `<table>` with slotted `<thead>`/`<tbody>`
|
|
20
|
+
* content would leave individual `<td>`/`<th>` cells entirely unstylable
|
|
21
|
+
* from this component's own shadow root.
|
|
22
|
+
*
|
|
23
|
+
* @element lit-material-data-table-cell
|
|
24
|
+
*
|
|
25
|
+
* @slot - The cell's content.
|
|
26
|
+
*
|
|
27
|
+
* @csspart sort-button - The button wrapping content, for sortable header cells.
|
|
28
|
+
* @csspart sort-icon - The ascending/descending indicator.
|
|
29
|
+
*/
|
|
30
|
+
export declare class LitMaterialDataTableCell extends LitElement {
|
|
31
|
+
static styles: import("lit").CSSResult;
|
|
32
|
+
header: boolean;
|
|
33
|
+
numeric: boolean;
|
|
34
|
+
sortKey?: string;
|
|
35
|
+
/** Kept in sync by the parent table — see the class docs. Not meant to be set directly. */
|
|
36
|
+
sortDirection: SortDirection;
|
|
37
|
+
protected willUpdate(changed: Map<string, unknown>): void;
|
|
38
|
+
private get isSortable();
|
|
39
|
+
render(): import("lit").TemplateResult<1>;
|
|
40
|
+
private readonly handleSortClick;
|
|
41
|
+
}
|
|
42
|
+
declare global {
|
|
43
|
+
interface HTMLElementTagNameMap {
|
|
44
|
+
"lit-material-data-table-cell": LitMaterialDataTableCell;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=data-table-cell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-cell.d.ts","sourceRoot":"","sources":["../src/data-table-cell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;AAIvC,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBACa,wBAAyB,SAAQ,UAAU;IACtD,OAAgB,MAAM,0BAAU;IAEY,MAAM,UAAS;IACf,OAAO,UAAS;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACtD,2FAA2F;IACjC,aAAa,EAAE,aAAa,CAAU;cAE7E,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMlE,OAAO,KAAK,UAAU,GAErB;IAEQ,MAAM;IAaf,OAAO,CAAC,QAAQ,CAAC,eAAe,CAQ9B;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,8BAA8B,EAAE,wBAAwB,CAAC;KAC1D;CACF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, LitElement } from "lit";
|
|
8
|
+
import { customElement, property } from "lit/decorators.js";
|
|
9
|
+
import { styles } from "./data-table-cell-styles.js";
|
|
10
|
+
/**
|
|
11
|
+
* A single cell inside a `lit-material-data-table-row`.
|
|
12
|
+
*
|
|
13
|
+
* `header` renders it as a column header (`role="columnheader"`, label
|
|
14
|
+
* typography); otherwise it's a plain data cell (`role="cell"`). Set
|
|
15
|
+
* `sort-key` on a header cell to make it sortable — that wraps its content
|
|
16
|
+
* in a real `<button>` (the ARIA APG pattern for sortable column headers is
|
|
17
|
+
* an interactive element *inside* the columnheader cell, not the cell
|
|
18
|
+
* itself carrying the interaction) which requests a sort from the parent
|
|
19
|
+
* table on click; `sort-direction` is then kept in sync by the table, not
|
|
20
|
+
* set directly.
|
|
21
|
+
*
|
|
22
|
+
* `:host` uses `display: table-cell` (not a real `<td>`) so cells still
|
|
23
|
+
* align into columns via the browser's native table layout algorithm
|
|
24
|
+
* without needing an actual `<table>` element — see `lit-material-data-table`
|
|
25
|
+
* for why: CSS `::slotted()` can only style a *directly* slotted node, never
|
|
26
|
+
* its descendants, so a real `<table>` with slotted `<thead>`/`<tbody>`
|
|
27
|
+
* content would leave individual `<td>`/`<th>` cells entirely unstylable
|
|
28
|
+
* from this component's own shadow root.
|
|
29
|
+
*
|
|
30
|
+
* @element lit-material-data-table-cell
|
|
31
|
+
*
|
|
32
|
+
* @slot - The cell's content.
|
|
33
|
+
*
|
|
34
|
+
* @csspart sort-button - The button wrapping content, for sortable header cells.
|
|
35
|
+
* @csspart sort-icon - The ascending/descending indicator.
|
|
36
|
+
*/
|
|
37
|
+
let LitMaterialDataTableCell = class LitMaterialDataTableCell extends LitElement {
|
|
38
|
+
constructor() {
|
|
39
|
+
super(...arguments);
|
|
40
|
+
this.header = false;
|
|
41
|
+
this.numeric = false;
|
|
42
|
+
/** Kept in sync by the parent table — see the class docs. Not meant to be set directly. */
|
|
43
|
+
this.sortDirection = "none";
|
|
44
|
+
this.handleSortClick = () => {
|
|
45
|
+
this.dispatchEvent(new CustomEvent("sort-request", {
|
|
46
|
+
bubbles: true,
|
|
47
|
+
composed: true,
|
|
48
|
+
detail: { sortKey: this.sortKey },
|
|
49
|
+
}));
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
static { this.styles = styles; }
|
|
53
|
+
willUpdate(changed) {
|
|
54
|
+
if (changed.has("header")) {
|
|
55
|
+
this.setAttribute("role", this.header ? "columnheader" : "cell");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
get isSortable() {
|
|
59
|
+
return this.header && !!this.sortKey;
|
|
60
|
+
}
|
|
61
|
+
render() {
|
|
62
|
+
if (this.isSortable) {
|
|
63
|
+
const icon = this.sortDirection === "descending" ? "▼" : "▲";
|
|
64
|
+
return html `
|
|
65
|
+
<button class="sort-button" part="sort-button" type="button" @click=${this.handleSortClick}>
|
|
66
|
+
<span class="content"><slot></slot></span>
|
|
67
|
+
<span class="sort-icon" part="sort-icon" aria-hidden="true">${icon}</span>
|
|
68
|
+
</button>
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
return html `<span class="content"><slot></slot></span>`;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
__decorate([
|
|
75
|
+
property({ type: Boolean, reflect: true })
|
|
76
|
+
], LitMaterialDataTableCell.prototype, "header", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
property({ type: Boolean, reflect: true })
|
|
79
|
+
], LitMaterialDataTableCell.prototype, "numeric", void 0);
|
|
80
|
+
__decorate([
|
|
81
|
+
property({ attribute: "sort-key" })
|
|
82
|
+
], LitMaterialDataTableCell.prototype, "sortKey", void 0);
|
|
83
|
+
__decorate([
|
|
84
|
+
property({ attribute: "sort-direction", reflect: true })
|
|
85
|
+
], LitMaterialDataTableCell.prototype, "sortDirection", void 0);
|
|
86
|
+
LitMaterialDataTableCell = __decorate([
|
|
87
|
+
customElement("lit-material-data-table-cell")
|
|
88
|
+
], LitMaterialDataTableCell);
|
|
89
|
+
export { LitMaterialDataTableCell };
|
|
90
|
+
//# sourceMappingURL=data-table-cell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-cell.js","sourceRoot":"","sources":["../src/data-table-cell.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEI,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,UAAU;IAAjD;;QAGuC,WAAM,GAAG,KAAK,CAAC;QACf,YAAO,GAAG,KAAK,CAAC;QAE5D,2FAA2F;QACjC,kBAAa,GAAkB,MAAM,CAAC;QAyB/E,oBAAe,GAAG,GAAS,EAAE;YAC5C,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,cAAc,EAAE;gBAC9B,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;aAClC,CAAC,CACH,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;aAxCiB,WAAM,GAAG,MAAM,AAAT,CAAU;IAQb,UAAU,CAAC,OAA6B;QACzD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,IAAY,UAAU;QACpB,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IACvC,CAAC;IAEQ,MAAM;QACb,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAC7D,OAAO,IAAI,CAAA;8EAC6D,IAAI,CAAC,eAAe;;wEAE1B,IAAI;;OAErE,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAA,4CAA4C,CAAC;IAC1D,CAAC;;AA3B2C;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;wDAAgB;AACf;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;yDAAiB;AACvB;IAApC,QAAQ,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;yDAAkB;AAEI;IAAzD,QAAQ,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;+DAAuC;AAPrF,wBAAwB;IADpC,aAAa,CAAC,8BAA8B,CAAC;GACjC,wBAAwB,CAyCpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-row-styles.d.ts","sourceRoot":"","sources":["../src/data-table-row-styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBAwBlB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: table-row;
|
|
5
|
+
border-bottom: 1px solid var(--md-sys-color-outline-variant, #cac4d0);
|
|
6
|
+
transition: background-color 150ms var(--md-sys-motion-easing-standard, cubic-bezier(0.2, 0, 0, 1));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
:host(:last-of-type) {
|
|
10
|
+
border-bottom: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:host(:not([header]):hover) {
|
|
14
|
+
background-color: color-mix(in srgb, var(--md-sys-color-on-surface, #1c1b1f) 4%, transparent);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:host([selected]) {
|
|
18
|
+
background-color: var(--md-sys-color-secondary-container, #e8def8);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@media (prefers-reduced-motion: reduce) {
|
|
22
|
+
:host {
|
|
23
|
+
transition: none;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
//# sourceMappingURL=data-table-row-styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-row-styles.js","sourceRoot":"","sources":["../src/data-table-row-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;CAwBxB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
/**
|
|
3
|
+
* A row inside a `lit-material-data-table` — holds `lit-material-data-table-cell` children.
|
|
4
|
+
*
|
|
5
|
+
* Set `header` on a row made up of header cells (typically the first row);
|
|
6
|
+
* it skips the hover/`selected` styling body rows get. `:host` uses
|
|
7
|
+
* `display: table-row` for the same reason `lit-material-data-table-cell`
|
|
8
|
+
* uses `display: table-cell` — native table column alignment without an
|
|
9
|
+
* actual `<table>` element.
|
|
10
|
+
*
|
|
11
|
+
* @element lit-material-data-table-row
|
|
12
|
+
*
|
|
13
|
+
* @slot - `lit-material-data-table-cell` elements.
|
|
14
|
+
*/
|
|
15
|
+
export declare class LitMaterialDataTableRow extends LitElement {
|
|
16
|
+
static styles: import("lit").CSSResult;
|
|
17
|
+
header: boolean;
|
|
18
|
+
/** Highlights the row — set by the table from a row-select checkbox's checked state, not directly. */
|
|
19
|
+
selected: boolean;
|
|
20
|
+
protected willUpdate(changed: Map<string, unknown>): void;
|
|
21
|
+
render(): import("lit").TemplateResult<1>;
|
|
22
|
+
}
|
|
23
|
+
declare global {
|
|
24
|
+
interface HTMLElementTagNameMap {
|
|
25
|
+
"lit-material-data-table-row": LitMaterialDataTableRow;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=data-table-row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-row.d.ts","sourceRoot":"","sources":["../src/data-table-row.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;AAIvC;;;;;;;;;;;;GAYG;AACH,qBACa,uBAAwB,SAAQ,UAAU;IACrD,OAAgB,MAAM,0BAAU;IAEY,MAAM,UAAS;IAC3D,sGAAsG;IAC1D,QAAQ,UAAS;cAE1C,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMzD,MAAM;CAGhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,6BAA6B,EAAE,uBAAuB,CAAC;KACxD;CACF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, LitElement } from "lit";
|
|
8
|
+
import { customElement, property } from "lit/decorators.js";
|
|
9
|
+
import { styles } from "./data-table-row-styles.js";
|
|
10
|
+
/**
|
|
11
|
+
* A row inside a `lit-material-data-table` — holds `lit-material-data-table-cell` children.
|
|
12
|
+
*
|
|
13
|
+
* Set `header` on a row made up of header cells (typically the first row);
|
|
14
|
+
* it skips the hover/`selected` styling body rows get. `:host` uses
|
|
15
|
+
* `display: table-row` for the same reason `lit-material-data-table-cell`
|
|
16
|
+
* uses `display: table-cell` — native table column alignment without an
|
|
17
|
+
* actual `<table>` element.
|
|
18
|
+
*
|
|
19
|
+
* @element lit-material-data-table-row
|
|
20
|
+
*
|
|
21
|
+
* @slot - `lit-material-data-table-cell` elements.
|
|
22
|
+
*/
|
|
23
|
+
let LitMaterialDataTableRow = class LitMaterialDataTableRow extends LitElement {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
this.header = false;
|
|
27
|
+
/** Highlights the row — set by the table from a row-select checkbox's checked state, not directly. */
|
|
28
|
+
this.selected = false;
|
|
29
|
+
}
|
|
30
|
+
static { this.styles = styles; }
|
|
31
|
+
willUpdate(changed) {
|
|
32
|
+
if (changed.has("header") || !this.hasAttribute("role")) {
|
|
33
|
+
this.setAttribute("role", "row");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
render() {
|
|
37
|
+
return html `<slot></slot>`;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
__decorate([
|
|
41
|
+
property({ type: Boolean, reflect: true })
|
|
42
|
+
], LitMaterialDataTableRow.prototype, "header", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
property({ type: Boolean, reflect: true })
|
|
45
|
+
], LitMaterialDataTableRow.prototype, "selected", void 0);
|
|
46
|
+
LitMaterialDataTableRow = __decorate([
|
|
47
|
+
customElement("lit-material-data-table-row")
|
|
48
|
+
], LitMaterialDataTableRow);
|
|
49
|
+
export { LitMaterialDataTableRow };
|
|
50
|
+
//# sourceMappingURL=data-table-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-row.js","sourceRoot":"","sources":["../src/data-table-row.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEpD;;;;;;;;;;;;GAYG;AAEI,IAAM,uBAAuB,GAA7B,MAAM,uBAAwB,SAAQ,UAAU;IAAhD;;QAGuC,WAAM,GAAG,KAAK,CAAC;QAC3D,sGAAsG;QAC1D,aAAQ,GAAG,KAAK,CAAC;IAW/D,CAAC;aAfiB,WAAM,GAAG,MAAM,AAAT,CAAU;IAMb,UAAU,CAAC,OAA6B;QACzD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA,eAAe,CAAC;IAC7B,CAAC;;AAZ2C;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;uDAAgB;AAEf;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;yDAAkB;AALlD,uBAAuB;IADnC,aAAa,CAAC,6BAA6B,CAAC;GAChC,uBAAuB,CAgBnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-styles.d.ts","sourceRoot":"","sources":["../src/data-table-styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBAelB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
overflow-x: auto;
|
|
7
|
+
border-radius: var(--md-sys-shape-corner-large, 12px);
|
|
8
|
+
border: 1px solid var(--md-sys-color-outline-variant, #cac4d0);
|
|
9
|
+
background-color: var(--md-sys-color-surface, #fffbfe);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.table {
|
|
13
|
+
display: table;
|
|
14
|
+
width: 100%;
|
|
15
|
+
border-collapse: collapse;
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
//# sourceMappingURL=data-table-styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table-styles.js","sourceRoot":"","sources":["../src/data-table-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;CAexB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
import type { SortDirection } from "./data-table-cell.js";
|
|
3
|
+
/**
|
|
4
|
+
* Material Design 3 data table — a container for `lit-material-data-table-row`
|
|
5
|
+
* elements (each holding `lit-material-data-table-cell` elements).
|
|
6
|
+
*
|
|
7
|
+
* This component owns UI *state* (which column is sorted which way, which
|
|
8
|
+
* rows are checked) and *notifies* you of it via events — it doesn't own
|
|
9
|
+
* your data, so it never reorders rows itself. Sort a header cell (one
|
|
10
|
+
* with `sort-key` set) and this table updates `sortKey`/`sortDirection`,
|
|
11
|
+
* syncs the indicator onto the right cell, and fires `sort-change`; you
|
|
12
|
+
* re-render the rows in the new order (or re-fetch a sorted page) in
|
|
13
|
+
* response. The same headless-behavior split
|
|
14
|
+
* [`lit-material-tabs`](https://github.com/bohdaq/lit-material/tree/main/packages/tabs)
|
|
15
|
+
* makes for tab *panels*.
|
|
16
|
+
*
|
|
17
|
+
* Row selection works by event delegation rather than a hard dependency on
|
|
18
|
+
* any specific checkbox implementation: put a real `<input type="checkbox">`
|
|
19
|
+
* (or `lit-material-checkbox`, or anything that fires a bubbling `change`
|
|
20
|
+
* event) with a `data-row-select` attribute in a row's cell, and one with
|
|
21
|
+
* `data-select-all` in the header row's — this table listens for `change`
|
|
22
|
+
* on those, drives "select all" indeterminate state, sets the matching
|
|
23
|
+
* row's `selected`, and fires `selection-change` with the checked rows'
|
|
24
|
+
* closest-`<tr>`-equivalent (`lit-material-data-table-row`) `data-row-id`
|
|
25
|
+
* attribute.
|
|
26
|
+
*
|
|
27
|
+
* @element lit-material-data-table
|
|
28
|
+
*
|
|
29
|
+
* @slot - `lit-material-data-table-row` elements.
|
|
30
|
+
*
|
|
31
|
+
* @csspart table - The table layout container.
|
|
32
|
+
*
|
|
33
|
+
* @fires sort-change - `detail: { sortKey, sortDirection }`, when a sortable header cell is activated.
|
|
34
|
+
* @fires selection-change - `detail: { selected: string[] }` (the checked rows' `data-row-id` values),
|
|
35
|
+
* when a `data-row-select`/`data-select-all` checkbox changes.
|
|
36
|
+
*/
|
|
37
|
+
export declare class LitMaterialDataTable extends LitElement {
|
|
38
|
+
static styles: import("lit").CSSResult;
|
|
39
|
+
sortKey?: string;
|
|
40
|
+
sortDirection: SortDirection;
|
|
41
|
+
constructor();
|
|
42
|
+
protected willUpdate(changed: Map<string, unknown>): void;
|
|
43
|
+
private get headerCells();
|
|
44
|
+
private get rowCheckboxes();
|
|
45
|
+
private get selectAllCheckbox();
|
|
46
|
+
private syncSortIndicators;
|
|
47
|
+
private syncSelectAllState;
|
|
48
|
+
private syncRowSelectedState;
|
|
49
|
+
private dispatchSelectionChange;
|
|
50
|
+
private readonly handleSlotChange;
|
|
51
|
+
private readonly handleSortRequest;
|
|
52
|
+
private readonly handleChange;
|
|
53
|
+
render(): import("lit").TemplateResult<1>;
|
|
54
|
+
}
|
|
55
|
+
declare global {
|
|
56
|
+
interface HTMLElementTagNameMap {
|
|
57
|
+
"lit-material-data-table": LitMaterialDataTable;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=data-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../src/data-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;AAEvC,OAAO,KAAK,EAA4B,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBACa,oBAAqB,SAAQ,UAAU;IAClD,OAAgB,MAAM,0BAAU;IAEK,OAAO,CAAC,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,aAAa,CAAe;;cAQnE,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAalE,OAAO,KAAK,WAAW,GAMtB;IAED,OAAO,KAAK,aAAa,GAGxB;IAED,OAAO,KAAK,iBAAiB,GAG5B;IAED,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,uBAAuB;IAQ/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAI/B;IAEF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAehC;IAEF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAe3B;IAEO,MAAM;CAGhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,yBAAyB,EAAE,oBAAoB,CAAC;KACjD;CACF"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, LitElement } from "lit";
|
|
8
|
+
import { customElement, property } from "lit/decorators.js";
|
|
9
|
+
import { styles } from "./data-table-styles.js";
|
|
10
|
+
/**
|
|
11
|
+
* Material Design 3 data table — a container for `lit-material-data-table-row`
|
|
12
|
+
* elements (each holding `lit-material-data-table-cell` elements).
|
|
13
|
+
*
|
|
14
|
+
* This component owns UI *state* (which column is sorted which way, which
|
|
15
|
+
* rows are checked) and *notifies* you of it via events — it doesn't own
|
|
16
|
+
* your data, so it never reorders rows itself. Sort a header cell (one
|
|
17
|
+
* with `sort-key` set) and this table updates `sortKey`/`sortDirection`,
|
|
18
|
+
* syncs the indicator onto the right cell, and fires `sort-change`; you
|
|
19
|
+
* re-render the rows in the new order (or re-fetch a sorted page) in
|
|
20
|
+
* response. The same headless-behavior split
|
|
21
|
+
* [`lit-material-tabs`](https://github.com/bohdaq/lit-material/tree/main/packages/tabs)
|
|
22
|
+
* makes for tab *panels*.
|
|
23
|
+
*
|
|
24
|
+
* Row selection works by event delegation rather than a hard dependency on
|
|
25
|
+
* any specific checkbox implementation: put a real `<input type="checkbox">`
|
|
26
|
+
* (or `lit-material-checkbox`, or anything that fires a bubbling `change`
|
|
27
|
+
* event) with a `data-row-select` attribute in a row's cell, and one with
|
|
28
|
+
* `data-select-all` in the header row's — this table listens for `change`
|
|
29
|
+
* on those, drives "select all" indeterminate state, sets the matching
|
|
30
|
+
* row's `selected`, and fires `selection-change` with the checked rows'
|
|
31
|
+
* closest-`<tr>`-equivalent (`lit-material-data-table-row`) `data-row-id`
|
|
32
|
+
* attribute.
|
|
33
|
+
*
|
|
34
|
+
* @element lit-material-data-table
|
|
35
|
+
*
|
|
36
|
+
* @slot - `lit-material-data-table-row` elements.
|
|
37
|
+
*
|
|
38
|
+
* @csspart table - The table layout container.
|
|
39
|
+
*
|
|
40
|
+
* @fires sort-change - `detail: { sortKey, sortDirection }`, when a sortable header cell is activated.
|
|
41
|
+
* @fires selection-change - `detail: { selected: string[] }` (the checked rows' `data-row-id` values),
|
|
42
|
+
* when a `data-row-select`/`data-select-all` checkbox changes.
|
|
43
|
+
*/
|
|
44
|
+
let LitMaterialDataTable = class LitMaterialDataTable extends LitElement {
|
|
45
|
+
static { this.styles = styles; }
|
|
46
|
+
constructor() {
|
|
47
|
+
super();
|
|
48
|
+
this.sortDirection = "ascending";
|
|
49
|
+
this.handleSlotChange = () => {
|
|
50
|
+
this.syncSortIndicators();
|
|
51
|
+
this.syncSelectAllState();
|
|
52
|
+
this.syncRowSelectedState();
|
|
53
|
+
};
|
|
54
|
+
this.handleSortRequest = (event) => {
|
|
55
|
+
const key = event.detail.sortKey;
|
|
56
|
+
if (!key)
|
|
57
|
+
return;
|
|
58
|
+
if (this.sortKey === key) {
|
|
59
|
+
this.sortDirection = this.sortDirection === "ascending" ? "descending" : "ascending";
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.sortKey = key;
|
|
63
|
+
this.sortDirection = "ascending";
|
|
64
|
+
}
|
|
65
|
+
this.dispatchEvent(new CustomEvent("sort-change", {
|
|
66
|
+
bubbles: true,
|
|
67
|
+
detail: { sortKey: this.sortKey, sortDirection: this.sortDirection },
|
|
68
|
+
}));
|
|
69
|
+
};
|
|
70
|
+
this.handleChange = (event) => {
|
|
71
|
+
const target = event.composedPath()[0];
|
|
72
|
+
if (!target?.hasAttribute)
|
|
73
|
+
return;
|
|
74
|
+
if (target.hasAttribute("data-select-all")) {
|
|
75
|
+
const checked = target.checked;
|
|
76
|
+
this.rowCheckboxes.forEach((box) => {
|
|
77
|
+
if (!box.disabled)
|
|
78
|
+
box.checked = checked;
|
|
79
|
+
});
|
|
80
|
+
this.syncRowSelectedState();
|
|
81
|
+
this.dispatchSelectionChange();
|
|
82
|
+
}
|
|
83
|
+
else if (target.hasAttribute("data-row-select")) {
|
|
84
|
+
this.syncRowSelectedState();
|
|
85
|
+
this.syncSelectAllState();
|
|
86
|
+
this.dispatchSelectionChange();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
this.addEventListener("sort-request", this.handleSortRequest);
|
|
90
|
+
this.addEventListener("change", this.handleChange);
|
|
91
|
+
}
|
|
92
|
+
willUpdate(changed) {
|
|
93
|
+
// Not connectedCallback(): attribute mutations made there don't make it
|
|
94
|
+
// into SSR's serialized host tag (see lit-material-linear-progress for
|
|
95
|
+
// the full explanation) — willUpdate() runs inside the same
|
|
96
|
+
// synchronous pass that produces SSR's output.
|
|
97
|
+
if (!this.hasAttribute("role")) {
|
|
98
|
+
this.setAttribute("role", "table");
|
|
99
|
+
}
|
|
100
|
+
if (changed.has("sortKey") || changed.has("sortDirection")) {
|
|
101
|
+
this.syncSortIndicators();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
get headerCells() {
|
|
105
|
+
// @lit-labs/ssr's light-DOM shim doesn't implement querySelectorAll on
|
|
106
|
+
// the host during connectedCallback — degrade to no cells rather than
|
|
107
|
+
// throwing (there's no sort/selection state to sync server-side anyway).
|
|
108
|
+
if (typeof this.querySelectorAll !== "function")
|
|
109
|
+
return [];
|
|
110
|
+
return Array.from(this.querySelectorAll("lit-material-data-table-cell[header]"));
|
|
111
|
+
}
|
|
112
|
+
get rowCheckboxes() {
|
|
113
|
+
if (typeof this.querySelectorAll !== "function")
|
|
114
|
+
return [];
|
|
115
|
+
return Array.from(this.querySelectorAll("[data-row-select]"));
|
|
116
|
+
}
|
|
117
|
+
get selectAllCheckbox() {
|
|
118
|
+
if (typeof this.querySelector !== "function")
|
|
119
|
+
return null;
|
|
120
|
+
return this.querySelector("[data-select-all]");
|
|
121
|
+
}
|
|
122
|
+
syncSortIndicators() {
|
|
123
|
+
this.headerCells.forEach((cell) => {
|
|
124
|
+
cell.sortDirection = cell.sortKey === this.sortKey ? this.sortDirection : "none";
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
syncSelectAllState() {
|
|
128
|
+
const selectAll = this.selectAllCheckbox;
|
|
129
|
+
if (!selectAll)
|
|
130
|
+
return;
|
|
131
|
+
const boxes = this.rowCheckboxes;
|
|
132
|
+
const checkedCount = boxes.filter((box) => box.checked).length;
|
|
133
|
+
selectAll.checked = boxes.length > 0 && checkedCount === boxes.length;
|
|
134
|
+
selectAll.indeterminate = checkedCount > 0 && checkedCount < boxes.length;
|
|
135
|
+
}
|
|
136
|
+
syncRowSelectedState() {
|
|
137
|
+
this.rowCheckboxes.forEach((box) => {
|
|
138
|
+
const row = box.closest("lit-material-data-table-row");
|
|
139
|
+
if (row)
|
|
140
|
+
row.selected = box.checked;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
dispatchSelectionChange() {
|
|
144
|
+
const selected = this.rowCheckboxes
|
|
145
|
+
.filter((box) => box.checked)
|
|
146
|
+
.map((box) => box.closest("lit-material-data-table-row")?.getAttribute("data-row-id"))
|
|
147
|
+
.filter((id) => id !== null && id !== undefined);
|
|
148
|
+
this.dispatchEvent(new CustomEvent("selection-change", { bubbles: true, detail: { selected } }));
|
|
149
|
+
}
|
|
150
|
+
render() {
|
|
151
|
+
return html `<div class="table" part="table"><slot @slotchange=${this.handleSlotChange}></slot></div>`;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
__decorate([
|
|
155
|
+
property({ attribute: "sort-key" })
|
|
156
|
+
], LitMaterialDataTable.prototype, "sortKey", void 0);
|
|
157
|
+
__decorate([
|
|
158
|
+
property({ attribute: "sort-direction" })
|
|
159
|
+
], LitMaterialDataTable.prototype, "sortDirection", void 0);
|
|
160
|
+
LitMaterialDataTable = __decorate([
|
|
161
|
+
customElement("lit-material-data-table")
|
|
162
|
+
], LitMaterialDataTable);
|
|
163
|
+
export { LitMaterialDataTable };
|
|
164
|
+
//# sourceMappingURL=data-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.js","sourceRoot":"","sources":["../src/data-table.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { LitMaterialDataTable } from "./data-table.js";
|
|
2
|
+
export { LitMaterialDataTableRow } from "./data-table-row.js";
|
|
3
|
+
export { LitMaterialDataTableCell } from "./data-table-cell.js";
|
|
4
|
+
export type { SortDirection } from "./data-table-cell.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lit-material/data-table",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Material Design 3 data table web components (sortable, selectable).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "bohdaq",
|
|
8
|
+
"email": "bohdaq@gmail.com",
|
|
9
|
+
"url": "https://github.com/bohdaq"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/bohdaq/lit-material#readme",
|
|
12
|
+
"bugs": "https://github.com/bohdaq/lit-material/issues",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+ssh://git@github.com/bohdaq/lit-material.git",
|
|
16
|
+
"directory": "packages/data-table"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"lit",
|
|
20
|
+
"web-components",
|
|
21
|
+
"lit-material",
|
|
22
|
+
"material-design",
|
|
23
|
+
"material-design-3",
|
|
24
|
+
"data-table",
|
|
25
|
+
"table"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"lit": "^3.2.0",
|
|
44
|
+
"@lit-material/tokens": "0.0.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@lit-labs/ssr": "^3.3.1",
|
|
48
|
+
"@open-wc/testing": "^4.0.0",
|
|
49
|
+
"@web/dev-server-esbuild": "^1.0.0",
|
|
50
|
+
"@web/test-runner": "^0.19.0",
|
|
51
|
+
"@web/test-runner-commands": "^0.9.0",
|
|
52
|
+
"@web/test-runner-playwright": "^0.11.0",
|
|
53
|
+
"tsx": "^4.19.0",
|
|
54
|
+
"typescript": "^5.7.0"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsc -p tsconfig.json",
|
|
58
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
59
|
+
"test": "web-test-runner && node --import tsx --test src/*.ssr.test.ts"
|
|
60
|
+
}
|
|
61
|
+
}
|