@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/README.md +243 -90
- package/dist/index.d.mts +632 -0
- package/dist/index.d.ts +632 -0
- package/dist/index.js +1903 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1868 -0
- package/dist/index.mjs.map +1 -0
- package/dist/yatl.min.global.js +455 -0
- package/dist/yatl.min.global.js.map +1 -0
- package/package.json +32 -21
- package/dist/data-table.css +0 -2
- package/dist/data-table.css.map +0 -1
- package/dist/data-table.d.mts +0 -626
- package/dist/data-table.d.ts +0 -626
- package/dist/data-table.global.js +0 -4
- package/dist/data-table.global.js.map +0 -1
- package/dist/data-table.js +0 -4
- package/dist/data-table.js.map +0 -1
- package/dist/data-table.mjs +0 -4
- package/dist/data-table.mjs.map +0 -1
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
|