@timlassiter11/yatl 0.3.22 → 1.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/README.md CHANGED
@@ -1,144 +1,297 @@
1
1
  # YATL
2
+
2
3
  **Yet Another Table Library**
3
4
 
4
- YATL is a lightweight and customizable JavaScript library for creating dynamic, interactive tables. It provides features like sorting, filtering, searching, and virtual scrolling, making it easy to work with large datasets in a performant way.
5
+ YATL is a powerful, feature-rich, and lightweight Web Component data table built with Lit. It handles large datasets with ease using virtual scrolling, offers advanced fuzzy search capabilities, supports state persistence, and works in any framework (React, Vue, Angular, or Vanilla JS).
5
6
 
6
7
  ## Why?!?
7
- I needed a free and simple table library for vanilla JS that was easy to customize and could handle large datasets... so I created YATL. It is designed with performance and simplicity in mind. It has zero dependencies, is incredibly lightweight, and uses a highly efficient virtual scrolling engine to handle massive datasets with ease. If you need a powerful table without the bloat of larger frameworks, YATL is for you.
8
+
9
+ I needed a free and simple table library for vanilla JS that was easy to customize and could handle large datasets... so I created YATL. As the project that I wrote this for grew, so did this library. Now it is a web component built using Lit that is fairly feature rich for simple use cases. There are many other great table libraries out there but if you want something simple to just drop in but with all of the major features already included, YATL might be for you.
8
10
 
9
11
  ## Features
10
- - **Sorting**: Sort table rows by multiple columns (ascending or descending).
11
- - **Filtering**: Filter rows based on multiple criteria or custom filter functions.
12
- - **Searching**: Perform case-insensitive searches across table data with support for tokenization and regular expressions.
13
- - **Virtual Scrolling**: Efficiently render large datasets with virtual scrolling.
14
- - **Customizable Columns**: Define column properties like visibility, formatting, and sorting behavior.
15
- - **Export to CSV**: Export table data to a CSV file.
12
+
13
+ - **Virtual Scrolling**: Render 100,000+ rows smoothly with virtual scrolling.
14
+ - **Smart Search**: Tokenized fuzzy search with relevance scoring and highlighting.
15
+ - **State Persistence**: Automatically save and restore column order, visibility, sort, and widths to LocalStorage.
16
+ - **Highly Customizable**: Slot support, CSS Shadow Parts, and custom cell renderers.
17
+ - **Interactive**: Drag-and-drop column reordering, multi-column sorting (`SHIFT+CLICK`), and resizeable headers.
18
+ - **Export**: Built-in CSV export for visible or all data.
19
+ - **Type Safe**: Generic component with full type hint support.
16
20
 
17
21
  ## Installation
18
22
 
19
23
  The recommend method is to use npm.
24
+
20
25
  ```bash
21
26
  npm install @timlassiter11/yatl
22
27
  ```
23
28
 
24
29
  Alternatively you can manually download the source files from the [releases](https://github.com/timlassiter11/YATL/releases) section.
25
30
 
26
- ### npm
31
+ ### Lit
27
32
  ```ts
28
- import { DataTable } from "@timlassiter11/yatl";
33
+ import { html, LitElement } from 'lit';
34
+
35
+ import '@timlassiter11/yatl';
36
+
37
+ class MyComponent extends LitElement {
38
+ @state()
39
+ private _tableData: User[] = [];
29
40
 
30
- const datatble = DataTable("#myTable", {
31
- ...
32
- });
41
+ private _tableColums: ColumnOptions<User>[] = [
42
+ {
43
+ field: 'id',
44
+ title: 'ID',
45
+ resizeable: true,
46
+ sortable: true,
47
+ searchable: false,
48
+ },
49
+ {
50
+ field: 'name',
51
+ resizeable: true,
52
+ sortable: true,
53
+ searchable: true,
54
+ tokenize: true,
55
+ },
56
+ {
57
+ field: 'status',
58
+ resizeable: true,
59
+ sortable: true,
60
+ searchable: false,
61
+ }
62
+ ];
33
63
 
64
+ protected override render() {
65
+ return html`<yatl-table
66
+ .columns=${this._columns}
67
+ .data=${this._tableData}
68
+ enable-virtual-scroll
69
+ @dt.row.clicked=${(event) => console.log(event.detail.row)}></yatl-table>`
70
+ }
71
+
72
+ private handleRowClicked = (event) => {
73
+ console.log(event.detail)
74
+ }
75
+ }
34
76
  ```
35
77
 
36
- ### source (ES6)
37
- ```javascript
38
- import { DataTable } from "path/to/data-table.esm.js";
78
+ ### npm
79
+
80
+ ```ts
81
+ import '@timlassiter11/yatl';
82
+
83
+ const table = document.querySelector('yatl-table');
84
+
85
+ table.columns = [
86
+ { field: 'id', title: 'ID', sortable: true, width: 60 },
87
+ { field: 'name', title: 'Name', sortable: true, searchable: true },
88
+ { field: 'role', title: 'Role', sortable: true },
89
+ {
90
+ field: 'status',
91
+ title: 'Status',
92
+ // Custom renderer example
93
+ cellRenderer: value => (value === 'Active' ? '🟢' : '🔴'),
94
+ },
95
+ ];
39
96
 
40
- const dataTable = new DataTable("#myTable", {
41
- ...
42
- });
97
+ table.data = [
98
+ { id: 1, name: 'Alice', role: 'Admin', status: 'Active' },
99
+ { id: 2, name: 'Bob', role: 'User', status: 'Inactive' },
100
+ // ... more data
101
+ ];
43
102
  ```
44
103
 
45
- ### source (UMD)
104
+ ### Vanilla JS
105
+
46
106
  ```html
47
- <script src="path/to/data-table.umd.js"></script>
48
- <script>
49
- const datatble = new yatl.DataTable("#myTable", {
50
- ...
51
- });
52
- </script>
107
+ <!DOCTYPE html>
108
+ <html lang="en">
109
+ <head>
110
+ <meta charset="UTF-8" />
111
+ <title>YATL Demo</title>
112
+ <script src="yatl.min.global.js"></script>
113
+
114
+ <style>
115
+ yatl-table {
116
+ height: 500px;
117
+ display: block;
118
+ border: 1px solid #ddd;
119
+ }
120
+ </style>
121
+ </head>
122
+ <body>
123
+ <yatl-table id="my-table" enable-footer enable-column-reorder></yatl-table>
124
+
125
+ <script>
126
+ const table = document.getElementById('my-table');
127
+
128
+ // Define Columns
129
+ table.columns = [
130
+ { field: 'id', title: 'ID', width: 50 },
131
+ { field: 'firstName', title: 'First Name', sortable: true },
132
+ { field: 'lastName', title: 'Last Name', sortable: true },
133
+ { field: 'email', title: 'Email', width: 200 },
134
+ ];
135
+
136
+ // Load some data
137
+ table.data = Array.from({ length: 1000 }, (_, i) => ({
138
+ id: i + 1,
139
+ firstName: `User ${i}`,
140
+ lastName: `Doe`,
141
+ email: `user${i}@example.com`,
142
+ }));
143
+ </script>
144
+ </body>
145
+ </html>
53
146
  ```
54
147
 
55
148
  ## Styling
56
- Some optional styling is included which adds sorting indicators and sticky headers. To use them simply include the stylesheet.
57
149
 
58
- ### npm
59
- ```ts
60
- import "@timlassiter11/yatl/data-table.css";
150
+ `yatl-table` uses the native Web Component Shadow DOM to encapsulate its styles. This prevents your global CSS from accidentally breaking the table, and prevents the table's styles from leaking out.
151
+
152
+ To customize the table, you use the standard CSS ::part() pseudo-element.
153
+ ### The Basics
154
+
155
+ To style a specific part of the table, select the element and use ::part(name).
156
+
157
+ ```css
158
+ /* Target the main table container */
159
+ yatl-table::part(table) {
160
+ border: 1px solid #e2e8f0;
161
+ border-radius: 8px;
162
+ font-family: 'Inter', sans-serif;
163
+ }
164
+
165
+ /* Target the header row */
166
+ yatl-table::part(header) {
167
+ background-color: #f8fafc;
168
+ font-weight: 700;
169
+ text-transform: uppercase;
170
+ font-size: 0.75rem;
171
+ }
61
172
  ```
62
173
 
63
- ### source
64
- ```html
65
- <link rel="stylesheet" href="path/to/data-table.css">
174
+
175
+ ### Part Reference
176
+
177
+ Here is a list of all exposed parts you can target:
178
+
179
+ | Part Name | Description |
180
+ |-------------------|---------------------------------------------------|
181
+ | table | The main container grid. |
182
+ | header | The container for the header row. |
183
+ | header-cell | Individual header cells. |
184
+ | header-title | The text span inside a header cell. |
185
+ | header-sort-icon | The sorting arrow icon. |
186
+ | header-resizer | The drag handle for resizing columns. |
187
+ | row | The container for a data row. |
188
+ | cell | Targets all cells (both header and body). |
189
+ | body-cell | Targets only data cells (not headers). |
190
+ | footer | The footer container. |
191
+ | message | The empty state / no results message container. |
192
+
193
+ ### Common Recipes
194
+ #### Zebra Striping
195
+ You can use standard pseudo-classes like :nth-child combined with ::part.
196
+
197
+ ```css
198
+ /* Stripe every even row */
199
+ yatl-table::part(row):nth-child(even) {
200
+ background-color: #f9f9f9;
201
+ }
202
+
203
+ /* Add a hover effect to rows */
204
+ yatl-table::part(row):hover {
205
+ background-color: #e0f2fe;
206
+ cursor: pointer;
207
+ }
66
208
  ```
67
209
 
68
- ## Usage
69
- ```javascript
70
- // Initialize the DataTable
71
- const dataTable = new DataTable("#myTable", {
72
- columns: [
73
- { field: "name", title: "First Name", sortable: true, searchable: true },
74
- // Titles will be created from the field name
75
- { field: "age", sortable: true },
76
- { field: "city", searchable: true },
77
- ],
78
- data: [
79
- { name: "Alice", age: 25, city: "New York" },
80
- { name: "Bob", age: 30, city: "Los Angeles" },
81
- { name: "Charlie", age: 35, city: "Chicago" },
82
- ],
83
- });
84
-
85
- // Sort by age in ascending order
86
- dataTable.sort("age", "asc");
87
-
88
- // Filter rows to only people aged 25
89
- dataTable.filter({ age: 25 });
90
-
91
- // Filter rows to only people over 25
92
- dataTable.filter((row) => row.age > 25);
93
-
94
- // Search for Bob
95
- dataTable.search("bob");
96
-
97
- // Export table data to CSV
98
- dataTable.export("my-table-data");
210
+ #### Targeting Specific Columns
211
+ Every cell automatically gets a part name based on its field property in the format cell-{field}.
212
+
213
+ For example, if you have a column defined as `{ field: 'status' }`:
214
+
215
+ ```css
216
+ /* Center the 'status' column and make it bold */
217
+ yatl-table::part(cell-status) {
218
+ justify-content: center; /* Flex alignment */
219
+ font-weight: bold;
220
+ text-align: center;
221
+ }
222
+
223
+ /* Set a specific width or background for the ID column */
224
+ yatl-table::part(cell-id) {
225
+ background-color: #f1f5f9;
226
+ font-family: monospace;
227
+ }
99
228
  ```
100
229
 
101
- ### Virtual Scroll
102
- Virtual scrolling is used to render only the rows that are visible (with some extras before and after). This allows the library to support tables with hundreads of thousands of rows without issue. This is done using some magic (*simple math...*) but requires it's parent enforce a height. To do this you can simply add a height to the table.
230
+ #### Conditional Row Styling
103
231
 
104
- ```html
105
- <body>
106
- <table style="height: 500px;"></table>
107
- </body>
232
+ You can style rows based on their data using the rowParts property in JavaScript combined with CSS.
233
+
234
+ ```js
235
+ const table = document.querySelector('yatl-table');
236
+
237
+ // Return a string (or array of strings) to add to the row's parts
238
+ table.rowParts = (row) => {
239
+ const parts = [];
240
+ if (row.stock < 5) parts.push('low-stock');
241
+ if (row.price > 1000) parts.push('expensive');
242
+ return parts;
243
+ };
244
+ ```
245
+
246
+ ```css
247
+ /* Style rows tagged as 'low-stock' */
248
+ yatl-table::part(low-stock) {
249
+ background-color: #fef2f2; /* Light red */
250
+ border-left: 4px solid #ef4444;
251
+ }
252
+
253
+ /* Style rows tagged as 'expensive' */
254
+ yatl-table::part(expensive) {
255
+ color: #0f172a;
256
+ font-weight: 600;
257
+ }
108
258
  ```
109
259
 
110
- This will result in the following HTML after the table is initialized
260
+ #### Customizing the Footer
261
+ ```css
262
+ yatl-table::part(footer) {
263
+ background-color: #1e293b;
264
+ color: white;
265
+ padding: 1rem;
266
+ }
267
+ ```
268
+
269
+ ### Virtual Scroll
270
+
271
+ Virtual scrolling is used to render only the rows that are visible (with some extras before and after). This allows the library to support tables with hundreads of thousands of rows without issue. This is done using `lit-virtualizer` and requires it's parent enforce a height. To do this you can simply add a height to the table.
272
+
111
273
  ```html
112
274
  <body>
113
- <div class="dt-scroller" style="overflow: auto; height: 500px;">
114
- <table></table>
115
- </div>
275
+ <yatl-table style="height: 500px;"></yatl-table>
116
276
  </body>
117
277
  ```
118
278
 
119
- Most of the time this isn't ideal though and instead we'd like to let the layout work it's magic (*probably also simple math...*). To do this, it's best to wrap the table in an element that can enforce a height.
279
+ Most of the time this isn't ideal though and instead we'd like to let the layout work it's magic. To do this, it's best to wrap the table in an element that can enforce a height.
120
280
 
121
281
  ```html
122
282
  <body style="height: 100vh;">
123
- <div style="display: flex; flex-direction: column; overflow: auto; height: 100%;">
124
- <div>
125
- ... Lot's of cool table controls or filters
126
- </div>
127
- <table></table>
128
- <div>
129
- ... Some boring footer info or something
130
- </div>
131
- </div>
283
+ <div style="display: flex;">
284
+ <div>... Lot's of cool table controls or filters</div>
285
+ <yatl-table style="flex-grow: 1;"></yatl-table>
286
+ <div>... Some boring footer info or something</div>
287
+ </div>
132
288
  </body>
133
289
  ```
134
290
 
135
- Since the `dt-scroller` wrapper listens to scroll and resize events, this allows the table to be responsive and update what is rendered as the layout changes.
136
-
137
291
  ### Docs
138
- Full API docs can be found [here](https://timlassiter11.github.io/YATL/docs/index.html).
139
292
 
140
- # Known Issues
141
- There are some limitations to virtual scrolling. For one, rows need to be a uniform height to accurately calculate the table height. Also, there seems to be a maximum element size that once exceeded, the contents are no longer rendered. I've found this to occur with datasets approaching 1 million rows in Chrome and unfortunately I have no workaround for it. If you have that many rows you definitely need some server side pagination and this is probably not the library for you.
293
+ Full API docs can be found [here](https://timlassiter11.github.io/YATL/docs/index.html).
142
294
 
143
295
  # Examples
144
- Examples can be found in the examples directoy and are also hosted [here](https://timlassiter11.github.io/YATL/index.html) to view live.
296
+
297
+ Examples can be found in the examples directoy and are also hosted [here](https://timlassiter11.github.io/YATL/examples/index.html) to view live.