@timlassiter11/yatl 0.3.22 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1903 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __decorateClass = (decorators, target, key, kind) => {
20
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
21
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
22
+ if (decorator = decorators[i])
23
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
24
+ if (kind && result) __defProp(target, key, result);
25
+ return result;
26
+ };
27
+
28
+ // src/index.ts
29
+ var src_exports = {};
30
+ __export(src_exports, {
31
+ YatlChangeEvent: () => YatlChangeEvent,
32
+ YatlColumnReorderEvent: () => YatlColumnReorderEvent,
33
+ YatlColumnResizeEvent: () => YatlColumnResizeEvent,
34
+ YatlColumnToggleEvent: () => YatlColumnToggleEvent,
35
+ YatlEvent: () => YatlEvent,
36
+ YatlRowClickEvent: () => YatlRowClickEvent,
37
+ YatlSearchEvent: () => YatlSearchEvent,
38
+ YatlSortEvent: () => YatlSortEvent,
39
+ YatlTable: () => YatlTable,
40
+ createRegexTokenizer: () => createRegexTokenizer,
41
+ findColumn: () => findColumn,
42
+ whitespaceTokenizer: () => whitespaceTokenizer
43
+ });
44
+ module.exports = __toCommonJS(src_exports);
45
+
46
+ // src/events.ts
47
+ var YatlEvent = class extends CustomEvent {
48
+ constructor(name, detail, options = {}) {
49
+ super(name, {
50
+ bubbles: true,
51
+ composed: true,
52
+ cancelable: false,
53
+ ...options,
54
+ detail
55
+ });
56
+ }
57
+ };
58
+ var _YatlRowClickEvent = class _YatlRowClickEvent extends YatlEvent {
59
+ constructor(row, index, field, originalEvent) {
60
+ super(_YatlRowClickEvent.EVENT_NAME, {
61
+ row,
62
+ index,
63
+ field,
64
+ originalEvent
65
+ });
66
+ }
67
+ };
68
+ _YatlRowClickEvent.EVENT_NAME = "yatl-row-click";
69
+ var YatlRowClickEvent = _YatlRowClickEvent;
70
+ var _YatlChangeEvent = class _YatlChangeEvent extends YatlEvent {
71
+ constructor(data) {
72
+ super(_YatlChangeEvent.EVENT_NAME, { data });
73
+ }
74
+ };
75
+ _YatlChangeEvent.EVENT_NAME = "yatl-change";
76
+ var YatlChangeEvent = _YatlChangeEvent;
77
+ var _YatlSortEvent = class _YatlSortEvent extends YatlEvent {
78
+ constructor(field, order) {
79
+ super(
80
+ _YatlSortEvent.EVENT_NAME,
81
+ {
82
+ field,
83
+ order
84
+ },
85
+ {
86
+ cancelable: true
87
+ }
88
+ );
89
+ }
90
+ };
91
+ _YatlSortEvent.EVENT_NAME = "yatl-sort";
92
+ var YatlSortEvent = _YatlSortEvent;
93
+ var _YatlColumnToggleEvent = class _YatlColumnToggleEvent extends YatlEvent {
94
+ constructor(field, visible) {
95
+ super(
96
+ _YatlColumnToggleEvent.EVENT_NAME,
97
+ {
98
+ field,
99
+ visible
100
+ },
101
+ {
102
+ cancelable: true
103
+ }
104
+ );
105
+ }
106
+ };
107
+ _YatlColumnToggleEvent.EVENT_NAME = "yatl-column-toggle";
108
+ var YatlColumnToggleEvent = _YatlColumnToggleEvent;
109
+ var _YatlColumnResizeEvent = class _YatlColumnResizeEvent extends YatlEvent {
110
+ constructor(field, width) {
111
+ super(_YatlColumnResizeEvent.EVENT_NAME, {
112
+ field,
113
+ width
114
+ });
115
+ }
116
+ };
117
+ _YatlColumnResizeEvent.EVENT_NAME = "yatl-column-resize";
118
+ var YatlColumnResizeEvent = _YatlColumnResizeEvent;
119
+ var _YatlColumnReorderEvent = class _YatlColumnReorderEvent extends YatlEvent {
120
+ constructor(draggedColumn, droppedColumn, order) {
121
+ super(
122
+ _YatlColumnReorderEvent.EVENT_NAME,
123
+ {
124
+ draggedColumn,
125
+ droppedColumn,
126
+ order
127
+ },
128
+ {
129
+ cancelable: true
130
+ }
131
+ );
132
+ }
133
+ };
134
+ _YatlColumnReorderEvent.EVENT_NAME = "yatl-column-reorder";
135
+ var YatlColumnReorderEvent = _YatlColumnReorderEvent;
136
+ var _YatlSearchEvent = class _YatlSearchEvent extends YatlEvent {
137
+ constructor(query2) {
138
+ super(_YatlSearchEvent.EVENT_NAME, { query: query2 });
139
+ }
140
+ };
141
+ _YatlSearchEvent.EVENT_NAME = "yatl-search";
142
+ var YatlSearchEvent = _YatlSearchEvent;
143
+
144
+ // src/utils.ts
145
+ var import_lit = require("lit");
146
+ var toHumanReadable = (str) => {
147
+ return str.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (char) => char.toUpperCase());
148
+ };
149
+ var createRegexTokenizer = (exp = "\\S+") => {
150
+ const regex = new RegExp(`"[^"]*"|${exp}`, "g");
151
+ return (value) => {
152
+ const matches = value.match(regex) || [];
153
+ return matches.map((token) => {
154
+ token = token.toLocaleLowerCase().trim();
155
+ if (token.startsWith('"') && token.endsWith('"')) {
156
+ return { value: token.slice(1, -1), quoted: true };
157
+ }
158
+ return { value: token, quoted: false };
159
+ });
160
+ };
161
+ };
162
+ var whitespaceTokenizer = createRegexTokenizer();
163
+ function isValidKey(key, obj) {
164
+ return key in obj;
165
+ }
166
+ function getNestedValue(obj, path) {
167
+ const keys = path.split(".");
168
+ let current = obj;
169
+ for (const key of keys) {
170
+ if (current && isValidKey(key, current)) {
171
+ current = current[key];
172
+ } else {
173
+ return void 0;
174
+ }
175
+ }
176
+ return current;
177
+ }
178
+ function findColumn(field, columns) {
179
+ return columns.find((c) => c.field === field);
180
+ }
181
+ function highlightText(text, ranges) {
182
+ if (!text || !ranges || ranges.length === 0) {
183
+ return text;
184
+ }
185
+ const sortedRanges = [...ranges].sort((a, b) => a[0] - b[0]);
186
+ const mergedRanges = [];
187
+ let currentRange = sortedRanges[0];
188
+ for (let i = 1; i < sortedRanges.length; i++) {
189
+ const nextRange = sortedRanges[i];
190
+ if (nextRange[0] < currentRange[1]) {
191
+ currentRange[1] = Math.max(currentRange[1], nextRange[1]);
192
+ } else {
193
+ mergedRanges.push(currentRange);
194
+ currentRange = nextRange;
195
+ }
196
+ }
197
+ mergedRanges.push(currentRange);
198
+ const result = [];
199
+ let lastIndex = 0;
200
+ for (const [start, end] of mergedRanges) {
201
+ const safeStart = Math.max(0, Math.min(start, text.length));
202
+ const safeEnd = Math.max(0, Math.min(end, text.length));
203
+ if (safeStart > lastIndex) {
204
+ result.push(text.slice(lastIndex, safeStart));
205
+ }
206
+ result.push(
207
+ import_lit.html`<mark class="highlight">${text.slice(safeStart, safeEnd)}</mark>`
208
+ );
209
+ lastIndex = safeEnd;
210
+ }
211
+ if (lastIndex < text.length) {
212
+ result.push(text.slice(lastIndex));
213
+ }
214
+ return import_lit.html`${result}`;
215
+ }
216
+ function widthsToGridTemplates(widths, defaultWidth = "1fr") {
217
+ return widths.map((width) => width ? `${width}px` : defaultWidth);
218
+ }
219
+ function didSortStateChange(newState, oldState) {
220
+ if (!oldState) {
221
+ return true;
222
+ }
223
+ const allKeys = /* @__PURE__ */ new Set([
224
+ ...oldState.map((s) => s.field),
225
+ ...newState.map((s) => s.field)
226
+ ]);
227
+ for (const key of allKeys) {
228
+ const oldSort = findColumn(key, oldState)?.sortState;
229
+ const newSort = findColumn(key, newState)?.sortState;
230
+ if (oldSort?.order !== newSort?.order || oldSort?.priority !== newSort?.priority) {
231
+ return true;
232
+ }
233
+ }
234
+ return false;
235
+ }
236
+ function isCompareable(value) {
237
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value instanceof Date;
238
+ }
239
+
240
+ // src/yatl-table.ts
241
+ var import_lit3 = require("lit");
242
+ var import_decorators = require("lit/decorators.js");
243
+ var import_class_map = require("lit/directives/class-map.js");
244
+ var import_if_defined = require("lit/directives/if-defined.js");
245
+ var import_repeat = require("lit/directives/repeat.js");
246
+ var import_style_map = require("lit/directives/style-map.js");
247
+ var import_virtualizer = require("@lit-labs/virtualizer");
248
+
249
+ // src/yatl-table.styles.ts
250
+ var import_lit2 = require("lit");
251
+ var yatl_table_styles_default = import_lit2.css`
252
+ /* Style declarations */
253
+ :host {
254
+ /* Typography */
255
+ --yatl-font-family: var(
256
+ --yatl-table-font,
257
+ -apple-system,
258
+ BlinkMacSystemFont,
259
+ 'Segoe UI',
260
+ Roboto,
261
+ Helvetica,
262
+ Arial,
263
+ sans-serif,
264
+ 'Apple Color Emoji',
265
+ 'Segoe UI Emoji'
266
+ );
267
+ --yatl-font-size: var(--yatl-table-font-size, 0.875rem);
268
+ --yatl-line-height: var(--yatl-table-line-height, 1.25rem);
269
+
270
+ /* Spacing */
271
+ --yatl-cell-padding: var(--yatl-table-cell-padding, 10px 16px);
272
+ --yatl-header-padding: var(--yatl-table-header-padding, 12px 16px);
273
+
274
+ /* Colors */
275
+ --yatl-bg: var(--yatl-table-bg, #ffffff);
276
+ --yatl-text: var(--yatl-table-text, #0f172a);
277
+ --yatl-text-muted: var(--yatl-table-text-muted, #64748b);
278
+ --yatl-border-color: var(--yatl-table-border-color, #e2e8f0);
279
+
280
+ --yatl-header-bg: var(--yatl-table-header-bg, #f8fafc);
281
+ --yatl-header-text: var(--yatl-table-header-text, #475569);
282
+
283
+ --yatl-row-hover-bg: var(--yatl-table-row-hover-bg, #f1f5f9);
284
+ --yatl-row-selected-bg: var(--yatl-table-row-selected-bg, #e0f2fe);
285
+
286
+ /* Resize grab handle width */
287
+ --yatl-resizer-width: 10px;
288
+ /* z-index for the header */
289
+ --header-z-index: 2;
290
+ /* Drop target background color */
291
+ --header-drop-color: rgba(255, 255, 255, 0.1);
292
+
293
+ font-family: var(--yatl-font-family);
294
+ font-size: var(--yatl-font-size);
295
+ color: var(--yatl-text);
296
+ }
297
+
298
+ :host(.dark) {
299
+ --yatl-table-bg: #1e293b;
300
+ --yatl-table-text: #f1f5f9;
301
+ --yatl-table-text-muted: #94a3b8;
302
+ --yatl-table-border-color: #334155;
303
+
304
+ --yatl-table-header-bg: #0f172a;
305
+ --yatl-table-header-text: #cbd5e1;
306
+
307
+ --yatl-table-row-hover-bg: #334155;
308
+ --yatl-table-row-selected-bg: #1e3a8a;
309
+ }
310
+
311
+ @media (prefers-color-scheme: dark) {
312
+ :host {
313
+ --yatl-bg: var(--yatl-table-bg, #1e293b);
314
+ --yatl-text: var(--yatl-table-text, #f1f5f9);
315
+ --yatl-text-muted: var(--yatl-table-text-muted, #94a3b8);
316
+ --yatl-border-color: var(--yatl-table-border-color, #334155);
317
+
318
+ --yatl-header-bg: var(--yatl-table-header-bg, #0f172a);
319
+ --yatl-header-text: var(--yatl-table-header-text, #cbd5e1);
320
+
321
+ --yatl-row-hover-bg: var(--yatl-table-row-hover-bg, #334155);
322
+ --yatl-row-selected-bg: var(--yatl-table-row-selected-bg, #1e3a8a);
323
+ }
324
+ }
325
+
326
+ :host {
327
+ font-family: system-ui, sans-serif;
328
+ }
329
+
330
+ .table {
331
+ background-color: var(--yatl-bg);
332
+ border: 1px solid var(--yatl-border-color);
333
+ border-radius: 6px;
334
+ }
335
+
336
+ .header.row {
337
+ background-color: var(--yatl-header-bg);
338
+ border-bottom: 1px solid var(--yatl-border-color);
339
+ font-weight: 600;
340
+ color: var(--yatl-header-text);
341
+ }
342
+
343
+ .row {
344
+ background-color: var(--yatl-bg);
345
+ border-bottom: 1px solid var(--yatl-border-color);
346
+ transition: background-color 50ms;
347
+ position: relative;
348
+ }
349
+
350
+ .row:last-child {
351
+ border-bottom: none;
352
+ }
353
+
354
+ .header .cell::after,
355
+ .row:not(.header)::after {
356
+ content: '';
357
+ position: absolute;
358
+ inset: 0;
359
+ pointer-events: none;
360
+ background-color: transparent;
361
+ transition: background-color 50ms;
362
+ z-index: 1;
363
+ }
364
+
365
+ .header .cell:hover::after,
366
+ .row:not(.header):hover::after {
367
+ background-color: rgba(0, 0, 0, 0.2);
368
+ }
369
+
370
+ .cell {
371
+ align-items: center;
372
+ padding: var(--yatl-cell-padding);
373
+ }
374
+
375
+ .header .cell {
376
+ padding: var(--yatl-header-padding);
377
+ }
378
+
379
+ .footer {
380
+ padding: 8px 12px;
381
+ background-color: var(--yatl-header-bg);
382
+ border-top: 1px solid var(--yatl-border-color);
383
+ color: var(--yatl-text-muted);
384
+ font-size: 0.8em;
385
+ }
386
+
387
+ .resizer::after {
388
+ height: 60%;
389
+ width: 1px;
390
+ background-color: color-mix(in srgb, currentColor 30%, transparent);
391
+ transition: background-color 0.2s;
392
+ }
393
+
394
+ .resizer:hover::after {
395
+ background-color: currentColor;
396
+ width: 2px;
397
+ }
398
+
399
+ .drop-indicator {
400
+ background: rgba(0, 0, 0, 0.4);
401
+ }
402
+
403
+ .message {
404
+ font-size: large;
405
+ }
406
+
407
+ /* Layout stuff
408
+ * Most of this is functional and needed
409
+ * for the table to work properly.
410
+ * Modify with caution!
411
+ */
412
+ :host {
413
+ display: block;
414
+ height: 100%;
415
+ width: 100%;
416
+ }
417
+
418
+ .table {
419
+ display: flex;
420
+ flex-direction: column;
421
+ height: 100%;
422
+ width: 100%;
423
+ min-height: 0;
424
+ overflow: auto;
425
+ box-sizing: border-box;
426
+ }
427
+
428
+ .header {
429
+ z-index: var(--header-z-index);
430
+ flex-shrink: 0;
431
+ position: sticky;
432
+ top: 0;
433
+ }
434
+
435
+ .header-content {
436
+ position: relative;
437
+ width: 100%;
438
+ display: flex;
439
+ flex-direction: row;
440
+ align-items: baseline;
441
+ gap: 0.5rem;
442
+ }
443
+
444
+ .sort-icon {
445
+ position: relative;
446
+ width: 1ch;
447
+ align-self: stretch;
448
+ padding: 0;
449
+ overflow: hidden;
450
+ flex-shrink: 0;
451
+ }
452
+
453
+ .sort-icon::after {
454
+ content: '';
455
+ position: absolute;
456
+ }
457
+
458
+ .sort-icon.descending::after {
459
+ content: '\\2191';
460
+ }
461
+
462
+ .sort-icon.ascending::after {
463
+ content: '\\2193';
464
+ }
465
+
466
+ .resizer {
467
+ position: absolute;
468
+ top: 0;
469
+ bottom: 0;
470
+ right: 0;
471
+ width: var(--yatl-resizer-width);
472
+ cursor: col-resize;
473
+ display: flex;
474
+ justify-content: center;
475
+ align-items: center;
476
+ }
477
+
478
+ .resizer::after {
479
+ content: '';
480
+ display: block;
481
+ }
482
+
483
+ .drop-indicator {
484
+ display: none;
485
+ position: absolute;
486
+ top: 0;
487
+ left: 0;
488
+ right: 0;
489
+ bottom: 0;
490
+ pointer-events: none;
491
+ z-index: calc(var(--header-z-index) + 1);
492
+ }
493
+
494
+ .drop-indicator.active {
495
+ display: block;
496
+ }
497
+
498
+ .sortable {
499
+ cursor: pointer;
500
+ }
501
+
502
+ /* Footer */
503
+ .footer {
504
+ display: flex;
505
+ align-items: center;
506
+ justify-content: space-between;
507
+ flex-shrink: 0;
508
+
509
+ position: sticky;
510
+ bottom: 0;
511
+ z-index: var(--header-z-index);
512
+ }
513
+
514
+ /* Generic table parts */
515
+ .row {
516
+ display: grid;
517
+ grid-template-columns: var(--grid-template);
518
+ min-width: 100%;
519
+ width: fit-content;
520
+ }
521
+
522
+ .cell {
523
+ white-space: nowrap;
524
+ overflow: hidden;
525
+ text-overflow: ellipsis;
526
+ position: relative;
527
+ display: flex;
528
+ align-items: center;
529
+ }
530
+
531
+ .message {
532
+ width: 100%;
533
+ height: 100%;
534
+ text-align: center;
535
+ pointer-events: none;
536
+ display: flex;
537
+ align-items: center;
538
+ justify-content: center;
539
+ }
540
+
541
+ .truncate {
542
+ display: block;
543
+ white-space: nowrap;
544
+ overflow: hidden;
545
+ text-overflow: ellipsis;
546
+ }
547
+ `;
548
+
549
+ // src/yatl-table.ts
550
+ var STATE_SAVE_DEBOUNCE = 1e3;
551
+ var DEFAULT_STORAGE_OPTIONS = {
552
+ storage: "local",
553
+ saveColumnSortOrders: true,
554
+ saveColumnVisibility: true,
555
+ saveColumnWidths: true,
556
+ saveColumnOrder: true
557
+ };
558
+ var SAVE_TRIGGERS = /* @__PURE__ */ new Set([
559
+ "searchQuery",
560
+ "filters",
561
+ // Covers column order
562
+ "columns",
563
+ // Covers sort, visibility, and width
564
+ "columnStates",
565
+ "storageOptions"
566
+ ]);
567
+ var MATCH_WEIGHTS = {
568
+ EXACT: 100,
569
+ PREFIX: 50,
570
+ SUBSTRING: 10
571
+ };
572
+ var YatlTable = class extends import_lit3.LitElement {
573
+ constructor() {
574
+ super(...arguments);
575
+ // #region --- State Data ---
576
+ // Property data
577
+ this._enableSearchTokenization = false;
578
+ this._enableSearchScoring = false;
579
+ this._columns = [];
580
+ this._columnStates = [];
581
+ this._storageOptions = null;
582
+ this._data = [];
583
+ this._searchQuery = "";
584
+ this._searchIncludedFields = [];
585
+ this._searchTokenizer = whitespaceTokenizer;
586
+ this._filters = null;
587
+ this._filteredData = [];
588
+ // Flag if we have already restored the state or not.
589
+ this.hasRestoredState = false;
590
+ // save state debounce timer
591
+ this.saveTimer = 0;
592
+ // Flags set when something changes that
593
+ // requires the filter or sort logic to re-run.
594
+ this.filterDirty = false;
595
+ this.sortDirty = false;
596
+ // The last time the data was updated.
597
+ // For displaying in the footer only.
598
+ this.dataLastUpdate = null;
599
+ // Maps rows to their metadata
600
+ this.rowMetadata = /* @__PURE__ */ new WeakMap();
601
+ // List of tokens created from the current query
602
+ this.queryTokens = null;
603
+ // Column resize state
604
+ this.resizeState = null;
605
+ // Column drag & drop state
606
+ this.dragColumn = null;
607
+ this.enableVirtualScroll = false;
608
+ this.enableSearchHighlight = true;
609
+ this.enableColumnReorder = true;
610
+ this.enableFooter = false;
611
+ this.nullValuePlaceholder = "-";
612
+ this.emptyMessage = "No records to display";
613
+ this.noResultsMessage = "No matching records found";
614
+ this.rowParts = null;
615
+ // #endregion
616
+ // #region --- Event Handlers ---
617
+ this.handleHeaderClicked = (event, column) => {
618
+ const target = event.target;
619
+ if (!column.sortable || target.classList.contains("resizer")) {
620
+ return;
621
+ }
622
+ const multiSort = event.shiftKey;
623
+ const state2 = findColumn(column.field, this._columnStates);
624
+ if (!state2?.sortState) {
625
+ this.sort(column.field, "asc", !multiSort);
626
+ } else if (state2.sortState.order === "asc") {
627
+ this.sort(column.field, "desc", !multiSort);
628
+ } else if (state2.sortState.order) {
629
+ this.sort(column.field, null, !multiSort);
630
+ }
631
+ };
632
+ this.handleCellClick = (event, row, field) => {
633
+ if (window.getSelection()?.toString()) return;
634
+ const rowIndex = this.rowMetadata.get(row).index;
635
+ this.dispatchEvent(new YatlRowClickEvent(row, rowIndex, field, event));
636
+ };
637
+ this.handleResizeMouseMove = (event) => {
638
+ if (!this.resizeState?.active) return;
639
+ requestAnimationFrame(() => {
640
+ if (!this.resizeState?.active) return;
641
+ const deltaX = event.pageX - this.resizeState.startX;
642
+ const newWidth = Math.max(50, this.resizeState.startWidth + deltaX);
643
+ this.resizeState.currentWidths[this.resizeState.columnIndex] = `${newWidth}px`;
644
+ this.tableElement.style.setProperty(
645
+ "--grid-template",
646
+ this.resizeState.currentWidths.join(" ")
647
+ );
648
+ });
649
+ };
650
+ this.handleResizeMouseUp = (_event) => {
651
+ window.removeEventListener("mousemove", this.handleResizeMouseMove);
652
+ window.removeEventListener("mouseup", this.handleResizeMouseUp);
653
+ document.body.style.cursor = "";
654
+ if (this.resizeState?.active) {
655
+ const finalWidth = parseFloat(
656
+ this.resizeState.currentWidths[this.resizeState.columnIndex]
657
+ );
658
+ const columnStates = this.columnStates;
659
+ const state2 = findColumn(this.resizeState.columnField, columnStates);
660
+ state2.width = finalWidth;
661
+ this.columnStates = columnStates;
662
+ this.dispatchEvent(new YatlColumnResizeEvent(state2.field, state2.width));
663
+ }
664
+ this.resizeState = null;
665
+ };
666
+ this.handleDragColumnStart = (event, field) => {
667
+ const target = event.target;
668
+ console.log("Starting drag event");
669
+ console.log(target);
670
+ if (target?.classList.contains("resizer")) {
671
+ event.preventDefault();
672
+ return;
673
+ }
674
+ if (event.dataTransfer) {
675
+ event.dataTransfer.effectAllowed = "move";
676
+ event.dataTransfer.setData("text/plain", field);
677
+ this.dragColumn = field;
678
+ }
679
+ };
680
+ this.handleDragColumnEnter = (event) => {
681
+ const cell = event.currentTarget;
682
+ cell.querySelector(".drop-indicator")?.classList.add("active");
683
+ };
684
+ this.handleDragColumnLeave = (event) => {
685
+ const cell = event.currentTarget;
686
+ const enteringElement = event.relatedTarget;
687
+ if (cell.contains(enteringElement)) {
688
+ return;
689
+ }
690
+ cell.querySelector(".drop-indicator")?.classList.remove("active");
691
+ };
692
+ this.handleDragColumnOver = (event) => {
693
+ event.preventDefault();
694
+ if (event.dataTransfer) {
695
+ event.dataTransfer.dropEffect = "move";
696
+ }
697
+ };
698
+ this.handleDragColumnDrop = (event, field) => {
699
+ if (!this.dragColumn || this.dragColumn === field) {
700
+ return;
701
+ }
702
+ event.preventDefault();
703
+ event.stopPropagation();
704
+ const columns = [...this.columns];
705
+ const dragIndex = columns.findIndex((col) => col.field === this.dragColumn);
706
+ const dropIndex = columns.findIndex((col) => col.field === field);
707
+ if (dragIndex > -1 && dropIndex > -1) {
708
+ const [draggedColumn] = columns.splice(dragIndex, 1);
709
+ const droppedColumn = findColumn(field, this.columns);
710
+ if (!droppedColumn) return;
711
+ columns.splice(dropIndex, 0, draggedColumn);
712
+ const newColumnOrder = columns.map((col) => col.field);
713
+ const reorderEvent = new YatlColumnReorderEvent(
714
+ draggedColumn.field,
715
+ droppedColumn.field,
716
+ newColumnOrder
717
+ );
718
+ if (!this.dispatchEvent(reorderEvent)) {
719
+ return;
720
+ }
721
+ this.setColumnOrder(newColumnOrder);
722
+ }
723
+ };
724
+ this.handleDragColumnEnd = () => {
725
+ this.dragColumn = null;
726
+ this.tableElement.querySelectorAll(".drop-indicator.active").forEach((element) => element.classList.remove("active"));
727
+ };
728
+ }
729
+ get enableSearchTokenization() {
730
+ return this._enableSearchTokenization;
731
+ }
732
+ set enableSearchTokenization(enable) {
733
+ if (this._enableSearchTokenization === enable) {
734
+ return;
735
+ }
736
+ const oldValue = this._enableSearchTokenization;
737
+ this._enableSearchTokenization = enable;
738
+ this.updateInternalQuery();
739
+ this.filterDirty = true;
740
+ this.requestUpdate("enableSearchTokenization", oldValue);
741
+ }
742
+ get enableSearchScoring() {
743
+ return this._enableSearchScoring;
744
+ }
745
+ set enableSearchScoring(enable) {
746
+ if (this._enableSearchScoring === enable) {
747
+ return;
748
+ }
749
+ const oldValue = this._enableSearchScoring;
750
+ this._enableSearchScoring = enable;
751
+ this.filterDirty = true;
752
+ this.requestUpdate("enableSearchScoring", oldValue);
753
+ }
754
+ get columns() {
755
+ return this._columns;
756
+ }
757
+ set columns(columns) {
758
+ if (this._columns === columns) {
759
+ return;
760
+ }
761
+ const oldValue = this._columns;
762
+ this._columns = columns;
763
+ this.createColumnStates();
764
+ this.filterDirty = true;
765
+ this.requestUpdate("columns", oldValue);
766
+ }
767
+ get columnStates() {
768
+ return this._columnStates.map((state2) => ({
769
+ ...state2,
770
+ sortState: state2.sortState ? { ...state2.sortState } : void 0
771
+ }));
772
+ }
773
+ set columnStates(states) {
774
+ if (this._columnStates === states) {
775
+ return;
776
+ }
777
+ const oldValue = this._columnStates;
778
+ this._columnStates = states;
779
+ if (didSortStateChange(this._columnStates, oldValue)) {
780
+ this.sortDirty = true;
781
+ }
782
+ this.requestUpdate("columnStates", oldValue);
783
+ }
784
+ get searchQuery() {
785
+ return this._searchQuery;
786
+ }
787
+ set searchQuery(query2) {
788
+ if (this._searchQuery === query2) {
789
+ return;
790
+ }
791
+ const oldValue = this._searchQuery;
792
+ this._searchQuery = query2;
793
+ this.updateInternalQuery();
794
+ this.filterDirty = true;
795
+ this.requestUpdate("searchQuery", oldValue);
796
+ }
797
+ get searchIncludedFields() {
798
+ return this._searchIncludedFields;
799
+ }
800
+ set searchIncludedFields(fields) {
801
+ if (this._searchIncludedFields === fields) {
802
+ return;
803
+ }
804
+ const oldValue = this._searchIncludedFields;
805
+ this._searchIncludedFields = fields;
806
+ this.filterDirty = true;
807
+ this.requestUpdate("searchIncludedFields", oldValue);
808
+ }
809
+ get searchTokenizer() {
810
+ return this._searchTokenizer;
811
+ }
812
+ set searchTokenizer(tokenizer) {
813
+ if (this._searchTokenizer === tokenizer) {
814
+ return;
815
+ }
816
+ const oldValue = this._searchTokenizer;
817
+ this._searchTokenizer = tokenizer;
818
+ this.filterDirty = true;
819
+ this.requestUpdate("searchTokenizer", oldValue);
820
+ }
821
+ get filters() {
822
+ return this._filters;
823
+ }
824
+ set filters(filters) {
825
+ if (this._filters === filters) {
826
+ return;
827
+ }
828
+ const oldValue = this._filters;
829
+ this._filters = filters;
830
+ this.filterDirty = true;
831
+ this.requestUpdate("filters", oldValue);
832
+ }
833
+ get storageOptions() {
834
+ return this._storageOptions;
835
+ }
836
+ set storageOptions(options) {
837
+ if (this._storageOptions === options) {
838
+ return;
839
+ }
840
+ const oldValue = this._storageOptions;
841
+ this._storageOptions = options;
842
+ if (!this.hasRestoredState) {
843
+ this.loadStateFromStorage();
844
+ }
845
+ this.requestUpdate("storageOptions", oldValue);
846
+ }
847
+ get data() {
848
+ return this._data;
849
+ }
850
+ set data(value) {
851
+ const oldValue = this._data;
852
+ this._data = value;
853
+ this.dataLastUpdate = /* @__PURE__ */ new Date();
854
+ this.createMetadata();
855
+ this.filterDirty = true;
856
+ this.requestUpdate("data", oldValue);
857
+ }
858
+ get filteredData() {
859
+ if (this.filterDirty) {
860
+ this.filterRows();
861
+ } else if (this.sortDirty) {
862
+ this.sortRows();
863
+ }
864
+ this.filterDirty = false;
865
+ this.sortDirty = false;
866
+ return [...this._filteredData];
867
+ }
868
+ // #endregion
869
+ // #region --- Public Methods ---
870
+ /**
871
+ * Gets a copy of the current state of the table.
872
+ */
873
+ getState() {
874
+ const states = this.columnStates;
875
+ return {
876
+ searchQuery: this.searchQuery,
877
+ filters: this.filters,
878
+ columnOrder: this.columns.map((column) => column.field),
879
+ columns: this.columns.map((column) => {
880
+ const columnState = findColumn(column.field, states);
881
+ return {
882
+ field: column.field,
883
+ visible: columnState?.visible ?? true,
884
+ sortState: columnState?.sortState,
885
+ width: columnState?.width
886
+ };
887
+ })
888
+ };
889
+ }
890
+ /**
891
+ * Restores the table to the provided state.
892
+ * @param state - The state to restore the table to.
893
+ */
894
+ restoreState(state2) {
895
+ if ("searchQuery" in state2 && state2.searchQuery !== void 0) {
896
+ this.searchQuery = state2.searchQuery;
897
+ }
898
+ if ("filters" in state2 && state2.filters !== void 0) {
899
+ this.filters = state2.filters;
900
+ }
901
+ if ("columnOrder" in state2 && state2.columnOrder !== void 0) {
902
+ this.setColumnOrder(state2.columnOrder);
903
+ }
904
+ if ("columns" in state2 && state2.columns !== void 0) {
905
+ const newColumnStates = [];
906
+ for (const newState of state2.columns) {
907
+ const currentState = findColumn(newState.field, this._columnStates) ?? {
908
+ field: newState.field,
909
+ visible: true
910
+ };
911
+ newColumnStates.push(currentState);
912
+ if (!newState) {
913
+ continue;
914
+ }
915
+ if ("visible" in newState && newState.visible !== void 0) {
916
+ currentState.visible = newState.visible;
917
+ }
918
+ if ("sortState" in newState && newState.sortState !== void 0) {
919
+ currentState.sortState = newState.sortState;
920
+ }
921
+ if ("width" in newState && newState.width !== void 0) {
922
+ currentState.width = newState.width;
923
+ }
924
+ }
925
+ this.columnStates = newColumnStates;
926
+ }
927
+ }
928
+ /**
929
+ * Sorts the table by a specified column and order.
930
+ * If `order` is `null`, the sort on this column is removed.
931
+ * @param field - The field name of the column to sort by.
932
+ * @param order - The sort order: 'asc', 'desc', or `null` to remove sorting for this column.
933
+ * @param clear - Clear all other sorting
934
+ */
935
+ sort(field, order, clear = true) {
936
+ const columnStates = this.columnStates;
937
+ const state2 = findColumn(field, columnStates);
938
+ if (!state2) {
939
+ throw new Error(`Cannot get options for non-existent column "${field}"`);
940
+ }
941
+ if (order === state2.sortState?.order) {
942
+ return;
943
+ }
944
+ if (!this.dispatchEvent(new YatlSortEvent(field, order))) {
945
+ return;
946
+ }
947
+ if (order && !state2.sortState) {
948
+ const priorities = columnStates.map((col) => col.sortState?.priority).filter((priority2) => priority2 !== void 0);
949
+ const maxPriority = this.columns.length + 1;
950
+ const priority = Math.min(maxPriority, ...priorities) - 1;
951
+ state2.sortState = { order, priority };
952
+ } else if (order && state2.sortState) {
953
+ state2.sortState.order = order;
954
+ } else {
955
+ state2.sortState = null;
956
+ }
957
+ if (clear) {
958
+ for (const state3 of columnStates) {
959
+ if (state3.field !== field) {
960
+ state3.sortState = null;
961
+ }
962
+ }
963
+ }
964
+ this.columnStates = columnStates;
965
+ }
966
+ /**
967
+ * Sets the visibility of a specified column.
968
+ * @param field - The field name of the column.
969
+ * @param visible - `true` to show the column, `false` to hide it.
970
+ */
971
+ setColumnVisibility(field, visible) {
972
+ const columnStates = this.columnStates;
973
+ const state2 = findColumn(field, columnStates);
974
+ if (!state2) {
975
+ throw new Error(`Cannot get options for non-existent column "${field}"`);
976
+ }
977
+ if (state2.visible === visible) {
978
+ return;
979
+ }
980
+ if (!this.dispatchEvent(new YatlColumnToggleEvent(field, visible))) {
981
+ return;
982
+ }
983
+ state2.visible = visible;
984
+ this.columnStates = columnStates;
985
+ }
986
+ /**
987
+ * Toggles the visibility of hte specified column
988
+ * @param field - The field name of the column to toggle.
989
+ */
990
+ toggleColumnVisibility(field) {
991
+ const state2 = findColumn(field, this._columnStates);
992
+ this.setColumnVisibility(field, !state2);
993
+ }
994
+ /**
995
+ * Shows the specified column
996
+ * @param field - The field name of the column to show.
997
+ */
998
+ showColumn(field) {
999
+ this.setColumnVisibility(field, true);
1000
+ }
1001
+ /**
1002
+ * Hides the specified column
1003
+ * @param field - The field name of the column to hide.
1004
+ */
1005
+ hideColumn(field) {
1006
+ this.setColumnVisibility(field, false);
1007
+ }
1008
+ /**
1009
+ * Export the current visible table data to a CSV file.
1010
+ * @param filename - The name of the file to save.
1011
+ * @param all - If `true`, exports all original data (ignoring filters). If `false` (default), exports only the currently visible (filtered and sorted) rows.
1012
+ */
1013
+ export(filename, all = false) {
1014
+ const data = all ? this.data : this.filteredData;
1015
+ const rows = [...data.values()];
1016
+ const columnData = this.columnData;
1017
+ const csvHeaders = columnData.filter((col) => all || col.state?.visible).map((col) => `"${col.options.title}"`).join(",");
1018
+ const csvRows = rows.map((row) => {
1019
+ const list = [];
1020
+ for (const col of columnData) {
1021
+ let value = getNestedValue(row, col.field);
1022
+ if (all || col.state.visible) {
1023
+ if (typeof col.options.valueFormatter === "function") {
1024
+ value = col.options.valueFormatter(value, row);
1025
+ }
1026
+ value = String(value).replace('"', '""');
1027
+ list.push(`"${value}"`);
1028
+ }
1029
+ }
1030
+ return list.join(",");
1031
+ }).join("\n");
1032
+ const csvContent = csvHeaders + "\n" + csvRows;
1033
+ const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8," });
1034
+ const a = document.createElement("a");
1035
+ a.style.display = "none";
1036
+ a.href = URL.createObjectURL(blob);
1037
+ a.download = `${filename}.csv`;
1038
+ document.body.append(a);
1039
+ a.click();
1040
+ a.remove();
1041
+ }
1042
+ scrollToRow(row) {
1043
+ const index = this.data.findIndex((v) => v === row);
1044
+ if (typeof index === "number") {
1045
+ return this.scrollToOriginalIndex(index);
1046
+ } else {
1047
+ throw new Error("Row not in table");
1048
+ }
1049
+ }
1050
+ /**
1051
+ * Scrolls the table to bring the row at the specified original index into view.
1052
+ * @param index - The original index of the row (from the initial dataset).
1053
+ */
1054
+ scrollToOriginalIndex(index) {
1055
+ const rowData = this.data[index];
1056
+ if (rowData) {
1057
+ const filteredIndex = this.filteredData.indexOf(rowData);
1058
+ if (filteredIndex >= 0) {
1059
+ return this.scrollToFilteredIndex(filteredIndex);
1060
+ } else {
1061
+ throw new Error("Cannot scroll to filtered out row");
1062
+ }
1063
+ } else {
1064
+ throw new RangeError(`Row index ${index} out of range`);
1065
+ }
1066
+ }
1067
+ async scrollToFilteredIndex(index) {
1068
+ const rowData = this.filteredData[index];
1069
+ if (!rowData) {
1070
+ throw new RangeError(`Row index ${index} out of range`);
1071
+ }
1072
+ await this.updateComplete;
1073
+ if (this.virtualizer) {
1074
+ this.virtualizer.element(index)?.scrollIntoView({
1075
+ block: "start",
1076
+ behavior: "instant"
1077
+ });
1078
+ } else {
1079
+ const row = this.tableElement.querySelector(
1080
+ `.row[data-filtered-index="${index}"]`
1081
+ );
1082
+ row?.scrollIntoView({
1083
+ block: "start",
1084
+ behavior: "smooth"
1085
+ });
1086
+ }
1087
+ }
1088
+ async scrollToPx(px) {
1089
+ await this.updateComplete;
1090
+ if (this.virtualizer) {
1091
+ this.virtualizer.scrollTop = px;
1092
+ } else {
1093
+ this.tableElement.scrollTop = px;
1094
+ }
1095
+ }
1096
+ /**
1097
+ * Sets the display order of the columns in the table.
1098
+ *
1099
+ * @param fields - An array of field names representing the new order of columns. Columns not included in the array will be placed at the end.
1100
+ * @throws {TypeError} If `fields` is not an array.
1101
+ */
1102
+ setColumnOrder(fields) {
1103
+ const newColumns = [];
1104
+ for (const field of fields) {
1105
+ const col = findColumn(field, this.columns);
1106
+ if (col) {
1107
+ newColumns.push(col);
1108
+ }
1109
+ }
1110
+ for (const col of this.columns) {
1111
+ if (!findColumn(col.field, newColumns)) {
1112
+ newColumns.push(col);
1113
+ }
1114
+ }
1115
+ this.columns = [...newColumns];
1116
+ }
1117
+ /**
1118
+ * Finds the first row
1119
+ * @param field
1120
+ * @param value
1121
+ * @returns
1122
+ */
1123
+ findRow(field, value) {
1124
+ return this.data.find((row) => {
1125
+ const rowValue = getNestedValue(row, field);
1126
+ return rowValue === value;
1127
+ });
1128
+ }
1129
+ /**
1130
+ * Finds the original index of the first row where the specified field matches the given value.
1131
+ * This searches through the original, unfiltered dataset.
1132
+ * @param field - The field name within the row data to search.
1133
+ * @param value - The value to match against the field's content.
1134
+ * @returns The original index of the found row, or -1 if no match is found.
1135
+ * @example
1136
+ * ```ts
1137
+ * const index = dataTable.indexOf('id', 12345);
1138
+ * if (index >= 0) {
1139
+ * dataTable.updateRow({description: "Updated description"}, index);
1140
+ * }
1141
+ * ```
1142
+ */
1143
+ findRowIndex(field, value) {
1144
+ const row = this.findRow(field, value);
1145
+ if (row) {
1146
+ return this.rowMetadata.get(row).index;
1147
+ }
1148
+ return -1;
1149
+ }
1150
+ /**
1151
+ * Updates the data of a row at a specific original index.
1152
+ * @param index - The original index of the row to update.
1153
+ * @param data - An object containing the new data to assign to the row. Existing fields will be updated, and new fields will be added.
1154
+ *
1155
+ * @example
1156
+ * ```ts
1157
+ * const index = dataTable.indexOf('id', 12345);
1158
+ * if (index >= 0) {
1159
+ * dataTable.updateRow(index, {description: "Updated description"});
1160
+ * }
1161
+ * ```
1162
+ */
1163
+ updateRow(index, data) {
1164
+ const current_row = this.data[index];
1165
+ if (current_row) {
1166
+ Object.assign(current_row, data);
1167
+ this.requestUpdate("data");
1168
+ }
1169
+ }
1170
+ /**
1171
+ * Deletes a row at a specific original index from the table.
1172
+ * @param index - The original index of the row to delete.
1173
+ */
1174
+ deleteRow(index) {
1175
+ this.data = this.data.toSpliced(index, 1);
1176
+ }
1177
+ // #endregion
1178
+ // #region --- Render Methods ---
1179
+ renderColumnSortIcon(column, state2) {
1180
+ return column.sortable ? import_lit3.html`<div
1181
+ part="header-sort-icon"
1182
+ class=${(0, import_class_map.classMap)({
1183
+ "sort-icon": true,
1184
+ ascending: state2.sortState?.order === "asc",
1185
+ descending: state2.sortState?.order === "desc"
1186
+ })}
1187
+ ></div>` : import_lit3.nothing;
1188
+ }
1189
+ renderColumnResizer(column, _state) {
1190
+ return column.resizable ? import_lit3.html`<div
1191
+ part="header-resizer"
1192
+ class="resizer"
1193
+ @click=${(event) => event.stopPropagation()}
1194
+ @mousedown=${(event) => this.handleResizeMouseDown(event, column.field)}
1195
+ ></div>` : import_lit3.nothing;
1196
+ }
1197
+ renderHeaderCell(column) {
1198
+ const state2 = findColumn(column.field, this._columnStates);
1199
+ if (state2.visible == false) {
1200
+ return import_lit3.nothing;
1201
+ }
1202
+ return import_lit3.html`
1203
+ <div
1204
+ part="cell header-cell"
1205
+ class=${(0, import_class_map.classMap)({
1206
+ cell: true,
1207
+ sortable: column.sortable ?? false
1208
+ })}
1209
+ draggable=${(0, import_if_defined.ifDefined)(this.enableColumnReorder ? true : void 0)}
1210
+ data-field=${column.field}
1211
+ @dragstart=${(event) => this.handleDragColumnStart(event, column.field)}
1212
+ @dragenter=${this.handleDragColumnEnter}
1213
+ @dragleave=${this.handleDragColumnLeave}
1214
+ @dragover=${this.handleDragColumnOver}
1215
+ @drop=${(event) => this.handleDragColumnDrop(event, column.field)}
1216
+ @dragend=${this.handleDragColumnEnd}
1217
+ @click=${(event) => this.handleHeaderClicked(event, column)}
1218
+ >
1219
+ <div class="header-content">
1220
+ <span class="header-title truncate" part="header-title">
1221
+ ${column.title ?? toHumanReadable(column.field)}
1222
+ </span>
1223
+ ${this.renderColumnSortIcon(column, state2)}
1224
+ </div>
1225
+ ${this.renderColumnResizer(column, state2)}
1226
+ <div part="drop-indicator" class="drop-indicator"></div>
1227
+ </div>
1228
+ `;
1229
+ }
1230
+ renderHeader() {
1231
+ return import_lit3.html`
1232
+ <div part="header" class="header row">
1233
+ ${this.columns.map((column) => this.renderHeaderCell(column))}
1234
+ </div>
1235
+ `;
1236
+ }
1237
+ renderCellContents(value, column, row) {
1238
+ if (column.cellRenderer) {
1239
+ return column.cellRenderer(value, column.field, row);
1240
+ }
1241
+ if (value == null) {
1242
+ return this.nullValuePlaceholder;
1243
+ }
1244
+ const indices = this.rowMetadata.get(row).highlightIndices;
1245
+ return this.enableSearchHighlight && indices ? highlightText(String(value), indices[column.field]) : value;
1246
+ }
1247
+ renderCell(column, row) {
1248
+ const state2 = findColumn(column.field, this._columnStates);
1249
+ if (state2?.visible == false) {
1250
+ return import_lit3.nothing;
1251
+ }
1252
+ let value = getNestedValue(row, column.field);
1253
+ let userParts = column.cellParts?.call(this, value, column.field, row);
1254
+ if (Array.isArray(userParts)) {
1255
+ userParts = userParts.join(" ");
1256
+ }
1257
+ if (typeof column.valueFormatter === "function") {
1258
+ value = column.valueFormatter(value, row);
1259
+ }
1260
+ return import_lit3.html`
1261
+ <div
1262
+ part="cell body-cell cell-${column.field} ${userParts}"
1263
+ data-field=${column.field}
1264
+ class="cell"
1265
+ title=${(0, import_if_defined.ifDefined)(value ? String(value) : void 0)}
1266
+ @click=${(event) => this.handleCellClick(event, row, column.field)}
1267
+ >
1268
+ <span class="truncate">
1269
+ ${this.renderCellContents(value, column, row)}
1270
+ </span>
1271
+ </div>
1272
+ `;
1273
+ }
1274
+ renderRow(row, index) {
1275
+ const metadata = this.rowMetadata.get(row);
1276
+ let userParts = this.rowParts?.(row) ?? "";
1277
+ if (Array.isArray(userParts)) {
1278
+ userParts = userParts.join(" ");
1279
+ }
1280
+ return import_lit3.html`
1281
+ <div
1282
+ part=${"row " + userParts}
1283
+ class="row"
1284
+ data-index=${metadata.index}
1285
+ data-filtered-index=${index}
1286
+ >
1287
+ ${this.columns.map((column) => this.renderCell(column, row))}
1288
+ </div>
1289
+ `;
1290
+ }
1291
+ renderBody() {
1292
+ if (this.columnWidths.length === 0) {
1293
+ return import_lit3.html`
1294
+ <div part="message" class="message">No visible columns.</div>
1295
+ `;
1296
+ }
1297
+ if (this.data.length === 0) {
1298
+ return import_lit3.html`<div part="message" class="message">
1299
+ ${this.emptyMessage}
1300
+ </div>`;
1301
+ }
1302
+ if (this.filteredData.length === 0) {
1303
+ return import_lit3.html`<div part="message" class="message">
1304
+ ${this.noResultsMessage}
1305
+ </div>`;
1306
+ }
1307
+ if (this.enableVirtualScroll) {
1308
+ return import_lit3.html`
1309
+ <lit-virtualizer
1310
+ .items=${this.filteredData}
1311
+ .renderItem=${(item, index) => this.renderRow(item, index)}
1312
+ ></lit-virtualizer>
1313
+ `;
1314
+ }
1315
+ return import_lit3.html`
1316
+ ${(0, import_repeat.repeat)(
1317
+ this.filteredData,
1318
+ (item) => this.rowMetadata.get(item).index,
1319
+ (item, index) => this.renderRow(item, index)
1320
+ )}
1321
+ `;
1322
+ }
1323
+ renderFooter() {
1324
+ if (!this.enableFooter) {
1325
+ return import_lit3.nothing;
1326
+ }
1327
+ const total = this.data.length;
1328
+ const filtered = this.filteredData.length;
1329
+ const fmt = new Intl.NumberFormat(void 0);
1330
+ const totalStr = fmt.format(total);
1331
+ const filteredStr = fmt.format(filtered);
1332
+ const rowCountText = total !== filtered ? `Showing ${filteredStr} of ${totalStr} records` : `Total records: ${totalStr}`;
1333
+ const formatter = Intl.DateTimeFormat(void 0, {
1334
+ dateStyle: "short",
1335
+ timeStyle: "short"
1336
+ });
1337
+ const lastUpdateText = this.dataLastUpdate ? formatter.format(this.dataLastUpdate) : "Never";
1338
+ return import_lit3.html`
1339
+ <div part="footer" class="footer">
1340
+ <slot name="footer">
1341
+ <span part="row-count">${rowCountText}</span>
1342
+ <span part="timestamp">${lastUpdateText}</span>
1343
+ </slot>
1344
+ </div>
1345
+ `;
1346
+ }
1347
+ render() {
1348
+ const gridTemplate = widthsToGridTemplates(this.columnWidths).join(" ");
1349
+ return import_lit3.html`
1350
+ <div
1351
+ part="table"
1352
+ class="table"
1353
+ style=${(0, import_style_map.styleMap)({ "--grid-template": gridTemplate })}
1354
+ >
1355
+ ${this.renderHeader()} ${this.renderBody()} ${this.renderFooter()}
1356
+ </div>
1357
+ `;
1358
+ }
1359
+ // #endregion
1360
+ // #region --- Lifecycle Methods ---
1361
+ updated(changedProperties) {
1362
+ super.updated(changedProperties);
1363
+ if (!this.storageOptions?.key) return;
1364
+ const shouldSave = Array.from(changedProperties.keys()).some(
1365
+ (prop) => SAVE_TRIGGERS.has(prop)
1366
+ );
1367
+ if (shouldSave) {
1368
+ this.scheduleSave();
1369
+ }
1370
+ }
1371
+ disconnectedCallback() {
1372
+ super.disconnectedCallback();
1373
+ window.addEventListener("mousemove", this.handleResizeMouseMove);
1374
+ window.addEventListener("mouseup", this.handleResizeMouseUp);
1375
+ }
1376
+ // #endregion
1377
+ // #region --- Filter Methods ---
1378
+ /**
1379
+ * Calculates a relevance score for a given query against a target string.
1380
+ *
1381
+ * This function implements a tiered matching strategy:
1382
+ * 1. **Exact Match**: The query exactly matches the target. This yields the highest score.
1383
+ * 2. **Prefix Match**: The target starts with the query. This is the next most relevant.
1384
+ * 3. **Substring Match**: The target contains the query somewhere. This is the least relevant.
1385
+ *
1386
+ * The final score is weighted and adjusted by the length difference between the query and the target
1387
+ * to ensure that more specific matches (e.g., "apple" vs "application" for the query "apple") rank higher.
1388
+ *
1389
+ * @param query The search term (e.g., "app").
1390
+ * @param target The string to be searched (e.g., "Apple" or "Application").
1391
+ * @returns A numerical score representing the relevance of the match. Higher is better. Returns 0 if no match is found.
1392
+ */
1393
+ calculateSearchScore(query2, target) {
1394
+ const results = { score: 0, ranges: [] };
1395
+ if (!query2 || !target) {
1396
+ return results;
1397
+ }
1398
+ let baseScore = 0;
1399
+ let matchTypeWeight = 0;
1400
+ if (target === query2) {
1401
+ matchTypeWeight = MATCH_WEIGHTS.EXACT;
1402
+ baseScore = query2.length;
1403
+ results.ranges.push([0, target.length]);
1404
+ } else if (target.startsWith(query2)) {
1405
+ matchTypeWeight = MATCH_WEIGHTS.PREFIX;
1406
+ baseScore = query2.length;
1407
+ results.ranges.push([0, query2.length]);
1408
+ } else {
1409
+ const index = target.indexOf(query2);
1410
+ if (index !== -1) {
1411
+ matchTypeWeight = MATCH_WEIGHTS.SUBSTRING;
1412
+ baseScore = query2.length;
1413
+ let cursor = index;
1414
+ while (cursor !== -1) {
1415
+ results.ranges.push([cursor, cursor + query2.length]);
1416
+ cursor = target.indexOf(query2, cursor + 1);
1417
+ }
1418
+ } else {
1419
+ return results;
1420
+ }
1421
+ }
1422
+ const lengthDifference = target.length - query2.length;
1423
+ const specificityBonus = 1 / (1 + lengthDifference);
1424
+ results.score = baseScore * matchTypeWeight * specificityBonus;
1425
+ return results;
1426
+ }
1427
+ searchField(query2, value, tokens) {
1428
+ const result = { score: 0, ranges: [] };
1429
+ const addRangesFromValue = (searchTerm) => {
1430
+ let idx = value.indexOf(searchTerm);
1431
+ while (idx !== -1) {
1432
+ result.ranges.push([idx, idx + searchTerm.length]);
1433
+ idx = value.indexOf(searchTerm, idx + 1);
1434
+ }
1435
+ };
1436
+ if (query2.quoted || !tokens) {
1437
+ if (!this.enableSearchScoring) {
1438
+ if (value.includes(query2.value)) {
1439
+ result.score = 1;
1440
+ addRangesFromValue(query2.value);
1441
+ }
1442
+ } else {
1443
+ const calculation = this.calculateSearchScore(query2.value, value);
1444
+ result.score = calculation.score;
1445
+ result.ranges = calculation.ranges;
1446
+ }
1447
+ return result;
1448
+ }
1449
+ if (!this.enableSearchScoring) {
1450
+ const isMatch = tokens.some((token) => token.includes(query2.value));
1451
+ if (isMatch) {
1452
+ result.score = 1;
1453
+ addRangesFromValue(query2.value);
1454
+ }
1455
+ return result;
1456
+ }
1457
+ for (const token of tokens) {
1458
+ const calculation = this.calculateSearchScore(query2.value, token);
1459
+ if (calculation.score > 0) {
1460
+ result.score += calculation.score;
1461
+ addRangesFromValue(query2.value);
1462
+ }
1463
+ }
1464
+ return result;
1465
+ }
1466
+ filterField(value, filter, filterFunction = null) {
1467
+ if (Array.isArray(filter)) {
1468
+ if (filter.length === 0) {
1469
+ return true;
1470
+ }
1471
+ return filter.some(
1472
+ (element) => this.filterField(value, element, filterFunction)
1473
+ );
1474
+ }
1475
+ if (Array.isArray(value)) {
1476
+ if (value.length === 0) {
1477
+ return false;
1478
+ }
1479
+ return value.some(
1480
+ (element) => this.filterField(element, filter, filterFunction)
1481
+ );
1482
+ }
1483
+ if (typeof filterFunction === "function") {
1484
+ return filterFunction(value, filter);
1485
+ }
1486
+ if (filter instanceof RegExp) {
1487
+ return filter.test(String(value));
1488
+ }
1489
+ return filter === value;
1490
+ }
1491
+ filterRow(row, index) {
1492
+ if (!this.filters) {
1493
+ return true;
1494
+ }
1495
+ if (typeof this.filters === "function") {
1496
+ return this.filters(row, index);
1497
+ }
1498
+ for (const field in this.filters) {
1499
+ const filter = getNestedValue(this.filters, field);
1500
+ const value = getNestedValue(row, field);
1501
+ if (typeof filter === "function") {
1502
+ if (!filter(value)) {
1503
+ return false;
1504
+ }
1505
+ } else {
1506
+ const col = findColumn(field, this.columns);
1507
+ const filterCallback = col ? col.filter : void 0;
1508
+ if (!this.filterField(value, filter, filterCallback)) {
1509
+ return false;
1510
+ }
1511
+ }
1512
+ }
1513
+ return true;
1514
+ }
1515
+ filterRows() {
1516
+ const searchableFields = [...this.columnData.values()].filter((col) => col.options.searchable).map((c) => c.field);
1517
+ const fields = [...searchableFields, ...this.searchIncludedFields];
1518
+ this._filteredData = this.data.filter((row, index) => {
1519
+ const metadata = this.rowMetadata.get(row);
1520
+ metadata.searchScore = 0;
1521
+ metadata.highlightIndices = {};
1522
+ if (!this.filterRow(row, index)) {
1523
+ return false;
1524
+ }
1525
+ if (!this.queryTokens) {
1526
+ return true;
1527
+ }
1528
+ for (const field of fields) {
1529
+ const originalValue = getNestedValue(row, field);
1530
+ const compareValue = metadata.searchValues[field];
1531
+ const columnTokens = metadata.searchTokens[field];
1532
+ if (typeof originalValue !== "string" || typeof compareValue !== "string") {
1533
+ continue;
1534
+ }
1535
+ const fieldResults = { score: 0, ranges: [] };
1536
+ for (const token of this.queryTokens) {
1537
+ const results = this.searchField(token, compareValue, columnTokens);
1538
+ fieldResults.score += results.score;
1539
+ fieldResults.ranges.push(...results.ranges);
1540
+ }
1541
+ if (fieldResults.score > 0) {
1542
+ metadata.searchScore += fieldResults.score;
1543
+ metadata.highlightIndices[field] = fieldResults.ranges;
1544
+ }
1545
+ }
1546
+ return metadata.searchScore > 0;
1547
+ });
1548
+ this.filterDirty = false;
1549
+ this.sortRows();
1550
+ this.dispatchEvent(new YatlChangeEvent(this.data));
1551
+ }
1552
+ // #endregion
1553
+ // #region --- Sort Methods ---
1554
+ compareRows(a, b, field) {
1555
+ let aValue, bValue;
1556
+ const columnData = findColumn(field, this.columnData);
1557
+ if (!columnData.state.sortState) {
1558
+ return 0;
1559
+ }
1560
+ const aMetadata = this.rowMetadata.get(a);
1561
+ const bMetadata = this.rowMetadata.get(b);
1562
+ if (columnData.state.sortState?.order === "asc") {
1563
+ aValue = aMetadata.sortValues[columnData.field];
1564
+ bValue = bMetadata.sortValues[columnData.field];
1565
+ } else {
1566
+ aValue = bMetadata.sortValues[columnData.field];
1567
+ bValue = aMetadata.sortValues[columnData.field];
1568
+ }
1569
+ if (typeof columnData.options.sorter === "function") {
1570
+ const ret = columnData.options.sorter(aValue, bValue);
1571
+ if (ret !== 0) return ret;
1572
+ }
1573
+ const aIsNull = aValue == null;
1574
+ const bIsNull = bValue == null;
1575
+ if (aIsNull && !bIsNull) return -1;
1576
+ if (bIsNull && !aIsNull) return 1;
1577
+ if (aValue < bValue) return -1;
1578
+ if (aValue > bValue) return 1;
1579
+ return 0;
1580
+ }
1581
+ sortRows() {
1582
+ if (this.filterDirty) {
1583
+ this.filterRows();
1584
+ return;
1585
+ }
1586
+ const sortedColumns = this.columnData.filter((col) => col.state.visible && col.state.sortState).sort(
1587
+ (a, b) => b.state.sortState.priority - a.state.sortState.priority
1588
+ );
1589
+ this._filteredData = this._filteredData.toSorted((a, b) => {
1590
+ const aMetadata = this.rowMetadata.get(a);
1591
+ const bMetadata = this.rowMetadata.get(b);
1592
+ if (this.enableSearchScoring && this.queryTokens) {
1593
+ const aValue = aMetadata.searchScore || 0;
1594
+ const bValue = bMetadata.searchScore || 0;
1595
+ if (aValue > bValue) return -1;
1596
+ if (aValue < bValue) return 1;
1597
+ }
1598
+ for (const col of sortedColumns) {
1599
+ const comp = this.compareRows(a, b, col.field);
1600
+ if (comp !== 0) {
1601
+ return comp;
1602
+ }
1603
+ }
1604
+ return aMetadata.index - bMetadata.index;
1605
+ });
1606
+ this.sortDirty = false;
1607
+ }
1608
+ // #endregion
1609
+ // #region --- State Methods ---
1610
+ createColumnStates() {
1611
+ this.columnStates = this.columns.map((column) => {
1612
+ const previousState = findColumn(column.field, this._columnStates);
1613
+ return {
1614
+ field: column.field,
1615
+ visible: previousState?.visible ?? true,
1616
+ sortState: previousState?.sortState,
1617
+ width: previousState?.width
1618
+ };
1619
+ });
1620
+ }
1621
+ createMetadata() {
1622
+ this.rowMetadata = /* @__PURE__ */ new WeakMap();
1623
+ let index = 0;
1624
+ for (const row of this.data) {
1625
+ const metadata = {
1626
+ index: index++,
1627
+ searchTokens: {},
1628
+ searchValues: {},
1629
+ sortValues: {}
1630
+ };
1631
+ this.rowMetadata.set(row, metadata);
1632
+ for (const column of this.columns) {
1633
+ const value = getNestedValue(row, column.field);
1634
+ if (typeof column.sortValue === "function") {
1635
+ metadata.sortValues[column.field] = column.sortValue(value);
1636
+ } else if (typeof value === "string") {
1637
+ metadata.sortValues[column.field] = value.toLocaleLowerCase();
1638
+ } else if (isCompareable(value)) {
1639
+ metadata.sortValues[column.field] = value;
1640
+ } else {
1641
+ metadata.sortValues[column.field] = String(value);
1642
+ }
1643
+ if (typeof value === "string") {
1644
+ metadata.searchValues[column.field] = value.toLocaleLowerCase();
1645
+ }
1646
+ if (column.searchable && column.tokenize && value) {
1647
+ const tokenizer = column.searchTokenizer ?? this.searchTokenizer;
1648
+ metadata.searchTokens[column.field] = tokenizer(String(value)).map(
1649
+ (token) => token.value
1650
+ );
1651
+ }
1652
+ }
1653
+ for (const field of this.searchIncludedFields) {
1654
+ const value = getNestedValue(row, field);
1655
+ if (typeof value === "string") {
1656
+ metadata.searchValues[field] = value.toLocaleLowerCase();
1657
+ }
1658
+ }
1659
+ }
1660
+ }
1661
+ updateInternalQuery() {
1662
+ if (this.searchQuery.length === 0) {
1663
+ this.queryTokens = null;
1664
+ return;
1665
+ }
1666
+ this.queryTokens = [
1667
+ { value: this.searchQuery.toLocaleLowerCase(), quoted: true }
1668
+ ];
1669
+ if (this.enableSearchTokenization) {
1670
+ this.queryTokens.push(...this.searchTokenizer(this.searchQuery));
1671
+ }
1672
+ }
1673
+ // #endregion
1674
+ // #region --- Utilities ---
1675
+ get columnData() {
1676
+ return this.columns.map((column) => ({
1677
+ field: column.field,
1678
+ options: column,
1679
+ state: findColumn(column.field, this._columnStates) ?? {
1680
+ field: column.field,
1681
+ visible: true
1682
+ }
1683
+ }));
1684
+ }
1685
+ get columnWidths() {
1686
+ return this.columns.map((col) => findColumn(col.field, this._columnStates)).filter((state2) => state2 ? state2.visible : true).map((state2) => state2?.width ?? null);
1687
+ }
1688
+ scheduleSave() {
1689
+ window.clearTimeout(this.saveTimer);
1690
+ this.saveTimer = window.setTimeout(() => {
1691
+ this.saveStateToStorage();
1692
+ }, STATE_SAVE_DEBOUNCE);
1693
+ }
1694
+ // #endregion
1695
+ // #region --- Storage Methods ---
1696
+ saveStateToStorage() {
1697
+ if (!this.storageOptions) {
1698
+ return;
1699
+ }
1700
+ const options = { ...DEFAULT_STORAGE_OPTIONS, ...this.storageOptions };
1701
+ const savedTableState = {
1702
+ columns: []
1703
+ };
1704
+ const tableState = this.getState();
1705
+ if (options.saveColumnOrder) {
1706
+ savedTableState.columnOrder = tableState.columnOrder;
1707
+ }
1708
+ for (const columnState of tableState.columns) {
1709
+ const savedColumnState = {
1710
+ field: columnState.field
1711
+ };
1712
+ if (options.saveColumnSortOrders) {
1713
+ savedColumnState.sortState = columnState.sortState;
1714
+ }
1715
+ if (options.saveColumnVisibility) {
1716
+ savedColumnState.visible = columnState.visible;
1717
+ }
1718
+ if (options.saveColumnWidths) {
1719
+ savedColumnState.width = columnState.width;
1720
+ }
1721
+ savedTableState.columns?.push(savedColumnState);
1722
+ }
1723
+ const storage = options.storage === "session" ? sessionStorage : localStorage;
1724
+ try {
1725
+ storage.setItem(options.key, JSON.stringify(savedTableState));
1726
+ } catch (error) {
1727
+ console.warn("Failed to save table state", error);
1728
+ }
1729
+ }
1730
+ loadStateFromStorage() {
1731
+ if (!this.storageOptions) {
1732
+ return;
1733
+ }
1734
+ const options = { ...DEFAULT_STORAGE_OPTIONS, ...this.storageOptions };
1735
+ const json = localStorage.getItem(options.key);
1736
+ if (!json) {
1737
+ return;
1738
+ }
1739
+ try {
1740
+ const savedTableState = JSON.parse(json);
1741
+ const tableStateToRestore = {};
1742
+ if (options.saveColumnOrder) {
1743
+ tableStateToRestore.columnOrder = savedTableState.columnOrder;
1744
+ }
1745
+ if (savedTableState.columns) {
1746
+ tableStateToRestore.columns = [];
1747
+ for (const savedColumnState of savedTableState.columns) {
1748
+ const columnStateToRestore = {
1749
+ field: savedColumnState.field
1750
+ };
1751
+ if (options.saveColumnVisibility) {
1752
+ columnStateToRestore.visible = savedColumnState.visible;
1753
+ }
1754
+ if (options.saveColumnWidths) {
1755
+ columnStateToRestore.width = savedColumnState.width;
1756
+ }
1757
+ if (options.saveColumnSortOrders) {
1758
+ columnStateToRestore.sortState = savedColumnState.sortState;
1759
+ }
1760
+ tableStateToRestore.columns.push(columnStateToRestore);
1761
+ }
1762
+ }
1763
+ this.restoreState(tableStateToRestore);
1764
+ this.hasRestoredState = true;
1765
+ } catch (error) {
1766
+ console.error("Failed to restore DataTable state:", error);
1767
+ }
1768
+ }
1769
+ handleResizeMouseDown(event, field) {
1770
+ event.preventDefault();
1771
+ event.stopPropagation();
1772
+ const target = event.target;
1773
+ const header = target.closest(".cell");
1774
+ if (!header) {
1775
+ return;
1776
+ }
1777
+ const columnIndex = this.columns.findIndex((col) => col.field === field);
1778
+ if (columnIndex < 0) {
1779
+ return;
1780
+ }
1781
+ this.tableElement.querySelectorAll(".header .cell").forEach((element) => {
1782
+ const field2 = element.dataset.field;
1783
+ if (field2) {
1784
+ const state2 = findColumn(field2, this._columnStates);
1785
+ if (state2) {
1786
+ state2.width = element.getBoundingClientRect().width;
1787
+ }
1788
+ }
1789
+ });
1790
+ this.resizeState = {
1791
+ active: true,
1792
+ startX: event.pageX,
1793
+ startWidth: header.getBoundingClientRect().width,
1794
+ columnIndex,
1795
+ columnField: field,
1796
+ currentWidths: widthsToGridTemplates(this.columnWidths)
1797
+ };
1798
+ this.tableElement.style.setProperty(
1799
+ "--grid-template",
1800
+ this.resizeState.currentWidths.join(" ")
1801
+ );
1802
+ window.addEventListener("mousemove", this.handleResizeMouseMove);
1803
+ window.addEventListener("mouseup", this.handleResizeMouseUp);
1804
+ document.body.style.cursor = "col-resize";
1805
+ }
1806
+ addEventListener(type, listener, options) {
1807
+ super.addEventListener(
1808
+ type,
1809
+ listener,
1810
+ options
1811
+ );
1812
+ }
1813
+ removeEventListener(type, listener, options) {
1814
+ super.removeEventListener(type, listener, options);
1815
+ }
1816
+ dispatchEvent(event) {
1817
+ return super.dispatchEvent(event);
1818
+ }
1819
+ // #endregion
1820
+ };
1821
+ YatlTable.styles = [yatl_table_styles_default];
1822
+ __decorateClass([
1823
+ (0, import_decorators.query)(".table")
1824
+ ], YatlTable.prototype, "tableElement", 2);
1825
+ __decorateClass([
1826
+ (0, import_decorators.query)("lit-virtualizer")
1827
+ ], YatlTable.prototype, "virtualizer", 2);
1828
+ __decorateClass([
1829
+ (0, import_decorators.state)()
1830
+ ], YatlTable.prototype, "_filteredData", 2);
1831
+ __decorateClass([
1832
+ (0, import_decorators.property)({ type: Boolean, attribute: "enable-virtual-scroll" })
1833
+ ], YatlTable.prototype, "enableVirtualScroll", 2);
1834
+ __decorateClass([
1835
+ (0, import_decorators.property)({ type: Boolean, attribute: "enable-search-highlight" })
1836
+ ], YatlTable.prototype, "enableSearchHighlight", 2);
1837
+ __decorateClass([
1838
+ (0, import_decorators.property)({ type: Boolean, attribute: "enable-search-tokenization" })
1839
+ ], YatlTable.prototype, "enableSearchTokenization", 1);
1840
+ __decorateClass([
1841
+ (0, import_decorators.property)({ type: Boolean, attribute: "enable-search-scoring" })
1842
+ ], YatlTable.prototype, "enableSearchScoring", 1);
1843
+ __decorateClass([
1844
+ (0, import_decorators.property)({ type: Boolean, attribute: "enable-column-reorder" })
1845
+ ], YatlTable.prototype, "enableColumnReorder", 2);
1846
+ __decorateClass([
1847
+ (0, import_decorators.property)({ type: Boolean, attribute: "enable-footer" })
1848
+ ], YatlTable.prototype, "enableFooter", 2);
1849
+ __decorateClass([
1850
+ (0, import_decorators.property)({ type: String, attribute: "null-value-placeholder" })
1851
+ ], YatlTable.prototype, "nullValuePlaceholder", 2);
1852
+ __decorateClass([
1853
+ (0, import_decorators.property)({ type: String, attribute: "empty-message" })
1854
+ ], YatlTable.prototype, "emptyMessage", 2);
1855
+ __decorateClass([
1856
+ (0, import_decorators.property)({ type: String, attribute: "no-results-message" })
1857
+ ], YatlTable.prototype, "noResultsMessage", 2);
1858
+ __decorateClass([
1859
+ (0, import_decorators.property)({ attribute: false })
1860
+ ], YatlTable.prototype, "columns", 1);
1861
+ __decorateClass([
1862
+ (0, import_decorators.property)({ attribute: false })
1863
+ ], YatlTable.prototype, "columnStates", 1);
1864
+ __decorateClass([
1865
+ (0, import_decorators.property)({ type: String, attribute: "search-query" })
1866
+ ], YatlTable.prototype, "searchQuery", 1);
1867
+ __decorateClass([
1868
+ (0, import_decorators.property)({ type: Array, attribute: "search-included-fields" })
1869
+ ], YatlTable.prototype, "searchIncludedFields", 1);
1870
+ __decorateClass([
1871
+ (0, import_decorators.property)({ attribute: false })
1872
+ ], YatlTable.prototype, "searchTokenizer", 1);
1873
+ __decorateClass([
1874
+ (0, import_decorators.property)({ attribute: false })
1875
+ ], YatlTable.prototype, "filters", 1);
1876
+ __decorateClass([
1877
+ (0, import_decorators.property)({ attribute: false })
1878
+ ], YatlTable.prototype, "rowParts", 2);
1879
+ __decorateClass([
1880
+ (0, import_decorators.property)({ type: Object, attribute: "storage-options" })
1881
+ ], YatlTable.prototype, "storageOptions", 1);
1882
+ __decorateClass([
1883
+ (0, import_decorators.property)({ attribute: false })
1884
+ ], YatlTable.prototype, "data", 1);
1885
+ YatlTable = __decorateClass([
1886
+ (0, import_decorators.customElement)("yatl-table")
1887
+ ], YatlTable);
1888
+ // Annotate the CommonJS export names for ESM import in node:
1889
+ 0 && (module.exports = {
1890
+ YatlChangeEvent,
1891
+ YatlColumnReorderEvent,
1892
+ YatlColumnResizeEvent,
1893
+ YatlColumnToggleEvent,
1894
+ YatlEvent,
1895
+ YatlRowClickEvent,
1896
+ YatlSearchEvent,
1897
+ YatlSortEvent,
1898
+ YatlTable,
1899
+ createRegexTokenizer,
1900
+ findColumn,
1901
+ whitespaceTokenizer
1902
+ });
1903
+ //# sourceMappingURL=index.js.map