@duskmoon-dev/el-table 0.4.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.
@@ -0,0 +1,904 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
6
+ var __toCommonJS = (from) => {
7
+ var entry = __moduleCache.get(from), desc;
8
+ if (entry)
9
+ return entry;
10
+ entry = __defProp({}, "__esModule", { value: true });
11
+ if (from && typeof from === "object" || typeof from === "function")
12
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
+ get: () => from[key],
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ }));
16
+ __moduleCache.set(from, entry);
17
+ return entry;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+
29
+ // src/index.ts
30
+ var exports_src = {};
31
+ __export(exports_src, {
32
+ registerTableColumn: () => registerTableColumn,
33
+ registerTable: () => registerTable,
34
+ register: () => register,
35
+ ElDmTableColumn: () => ElDmTableColumn,
36
+ ElDmTable: () => ElDmTable
37
+ });
38
+ module.exports = __toCommonJS(exports_src);
39
+
40
+ // src/el-dm-table.ts
41
+ var import_el_core2 = require("@duskmoon-dev/el-core");
42
+
43
+ // src/el-dm-table-column.ts
44
+ var import_el_core = require("@duskmoon-dev/el-core");
45
+
46
+ class ElDmTableColumn extends import_el_core.BaseElement {
47
+ static properties = {
48
+ key: { type: String, reflect: true },
49
+ label: { type: String, reflect: true },
50
+ sortable: { type: Boolean, reflect: true },
51
+ width: { type: String, reflect: true },
52
+ align: { type: String, reflect: true, default: "left" },
53
+ hidden: { type: Boolean, reflect: true }
54
+ };
55
+ connectedCallback() {
56
+ super.connectedCallback();
57
+ this._notifyParent();
58
+ }
59
+ disconnectedCallback() {
60
+ super.disconnectedCallback();
61
+ this._notifyParent();
62
+ }
63
+ _notifyParent() {
64
+ this.dispatchEvent(new CustomEvent("table-column-change", {
65
+ bubbles: true,
66
+ composed: true
67
+ }));
68
+ }
69
+ toColumnDef() {
70
+ return {
71
+ key: this.key,
72
+ label: this.label || this.key || "",
73
+ sortable: this.sortable || false,
74
+ width: this.width,
75
+ align: this.align || "left",
76
+ hidden: this.hidden || false
77
+ };
78
+ }
79
+ render() {
80
+ return `<slot></slot>`;
81
+ }
82
+ }
83
+ function registerTableColumn() {
84
+ if (!customElements.get("el-dm-table-column")) {
85
+ customElements.define("el-dm-table-column", ElDmTableColumn);
86
+ }
87
+ }
88
+
89
+ // src/el-dm-table.ts
90
+ var ICONS = {
91
+ sortAsc: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="M11 4h4"/><path d="M11 8h7"/><path d="M11 12h10"/></svg>`,
92
+ sortDesc: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 8 4-4 4 4"/><path d="M7 4v16"/><path d="M11 12h4"/><path d="M11 16h7"/><path d="M11 20h10"/></svg>`,
93
+ sort: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="m21 8-4-4-4 4"/><path d="M17 4v16"/></svg>`,
94
+ chevronLeft: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>`,
95
+ chevronRight: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>`,
96
+ chevronFirst: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m17 18-6-6 6-6"/><path d="M7 6v12"/></svg>`,
97
+ chevronLast: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 18 6-6-6-6"/><path d="M17 6v12"/></svg>`
98
+ };
99
+ var styles = import_el_core2.css`
100
+ :host {
101
+ display: block;
102
+ font-family: inherit;
103
+ }
104
+
105
+ :host([hidden]) {
106
+ display: none !important;
107
+ }
108
+
109
+ /* Main wrapper */
110
+ .table-wrapper {
111
+ display: flex;
112
+ flex-direction: column;
113
+ gap: 0.75rem;
114
+ }
115
+
116
+ /* Header/Footer action slots */
117
+ .table-header-actions,
118
+ .table-footer-actions {
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 0.5rem;
122
+ }
123
+
124
+ .table-header-actions:empty,
125
+ .table-footer-actions:empty {
126
+ display: none;
127
+ }
128
+
129
+ /* Container for scrolling */
130
+ .table-container {
131
+ overflow-x: auto;
132
+ border: 1px solid var(--dm-color-outline, #e0e0e0);
133
+ border-radius: var(--dm-radius-md, 0.5rem);
134
+ }
135
+
136
+ /* Sticky header variant */
137
+ :host([sticky-header]) .table-container {
138
+ max-height: var(--table-max-height, 400px);
139
+ overflow-y: auto;
140
+ }
141
+
142
+ :host([sticky-header]) .table thead {
143
+ position: sticky;
144
+ top: 0;
145
+ z-index: 1;
146
+ }
147
+
148
+ /* Base table */
149
+ .table {
150
+ width: 100%;
151
+ border-collapse: collapse;
152
+ font-size: 0.875rem;
153
+ background-color: var(--dm-color-surface, #ffffff);
154
+ }
155
+
156
+ /* Header styles */
157
+ .table-th {
158
+ padding: 0.75rem 1rem;
159
+ text-align: left;
160
+ font-weight: 600;
161
+ color: var(--dm-color-on-surface, #1a1a1a);
162
+ background-color: var(--dm-color-surface-variant, #f5f5f5);
163
+ border-bottom: 2px solid var(--dm-color-outline, #e0e0e0);
164
+ white-space: nowrap;
165
+ }
166
+
167
+ .table-th.sortable {
168
+ cursor: pointer;
169
+ user-select: none;
170
+ }
171
+
172
+ .table-th.sortable:hover {
173
+ background-color: var(--dm-color-surface-container, #ebebeb);
174
+ }
175
+
176
+ .table-th.sortable:focus-visible {
177
+ outline: 2px solid var(--dm-color-primary, #6366f1);
178
+ outline-offset: -2px;
179
+ }
180
+
181
+ .table-th.sorted {
182
+ color: var(--dm-color-primary, #6366f1);
183
+ }
184
+
185
+ .th-content {
186
+ display: flex;
187
+ align-items: center;
188
+ gap: 0.5rem;
189
+ }
190
+
191
+ .sort-icon {
192
+ display: flex;
193
+ width: 1rem;
194
+ height: 1rem;
195
+ opacity: 0.5;
196
+ flex-shrink: 0;
197
+ }
198
+
199
+ .table-th.sorted .sort-icon {
200
+ opacity: 1;
201
+ }
202
+
203
+ /* Cell styles */
204
+ .table-td {
205
+ padding: 0.75rem 1rem;
206
+ border-bottom: 1px solid var(--dm-color-outline-variant, #e8e8e8);
207
+ color: var(--dm-color-on-surface, #1a1a1a);
208
+ }
209
+
210
+ /* Row styles */
211
+ .table-row {
212
+ transition: background-color 150ms ease;
213
+ }
214
+
215
+ :host([hoverable]) .table-row:hover {
216
+ background-color: var(--dm-color-surface-variant, #f5f5f5);
217
+ }
218
+
219
+ .table-row.selected {
220
+ background-color: var(--dm-color-primary-container, #e8e8ff);
221
+ }
222
+
223
+ :host([hoverable]) .table-row.selected:hover {
224
+ background-color: color-mix(
225
+ in srgb,
226
+ var(--dm-color-primary-container, #e8e8ff) 90%,
227
+ var(--dm-color-primary, #6366f1)
228
+ );
229
+ }
230
+
231
+ /* Selection column */
232
+ .select-cell {
233
+ width: 48px;
234
+ text-align: center;
235
+ padding: 0.5rem;
236
+ }
237
+
238
+ .select-cell input {
239
+ cursor: pointer;
240
+ width: 18px;
241
+ height: 18px;
242
+ accent-color: var(--dm-color-primary, #6366f1);
243
+ }
244
+
245
+ /* Striped variant */
246
+ :host([striped]) .table tbody tr:nth-child(even) {
247
+ background-color: var(--dm-color-surface-variant, #fafafa);
248
+ }
249
+
250
+ :host([striped]) .table tbody tr.selected:nth-child(even) {
251
+ background-color: var(--dm-color-primary-container, #e8e8ff);
252
+ }
253
+
254
+ /* Bordered variant */
255
+ :host([bordered]) .table-td,
256
+ :host([bordered]) .table-th {
257
+ border: 1px solid var(--dm-color-outline, #e0e0e0);
258
+ }
259
+
260
+ /* Compact variant */
261
+ :host([compact]) .table-th,
262
+ :host([compact]) .table-td {
263
+ padding: 0.5rem 0.75rem;
264
+ font-size: 0.8125rem;
265
+ }
266
+
267
+ :host([compact]) .select-cell {
268
+ padding: 0.375rem 0.5rem;
269
+ }
270
+
271
+ /* Loading state */
272
+ .loading-row td {
273
+ padding: 3rem;
274
+ text-align: center;
275
+ color: var(--dm-color-on-surface-variant, #666);
276
+ }
277
+
278
+ .loading-spinner {
279
+ display: inline-block;
280
+ width: 24px;
281
+ height: 24px;
282
+ border: 2px solid var(--dm-color-outline, #e0e0e0);
283
+ border-top-color: var(--dm-color-primary, #6366f1);
284
+ border-radius: 50%;
285
+ animation: spin 0.8s linear infinite;
286
+ }
287
+
288
+ @keyframes spin {
289
+ to {
290
+ transform: rotate(360deg);
291
+ }
292
+ }
293
+
294
+ /* Empty state */
295
+ .empty-row td {
296
+ padding: 3rem;
297
+ text-align: center;
298
+ color: var(--dm-color-on-surface-variant, #666);
299
+ }
300
+
301
+ /* Pagination styles */
302
+ .table-pagination {
303
+ display: flex;
304
+ align-items: center;
305
+ justify-content: space-between;
306
+ flex-wrap: wrap;
307
+ gap: 1rem;
308
+ padding: 0.75rem 1rem;
309
+ border: 1px solid var(--dm-color-outline, #e0e0e0);
310
+ border-top: none;
311
+ border-radius: 0 0 var(--dm-radius-md, 0.5rem) var(--dm-radius-md, 0.5rem);
312
+ background-color: var(--dm-color-surface-variant, #f5f5f5);
313
+ font-size: 0.875rem;
314
+ }
315
+
316
+ .pagination-info {
317
+ color: var(--dm-color-on-surface-variant, #666);
318
+ }
319
+
320
+ .pagination-controls {
321
+ display: flex;
322
+ align-items: center;
323
+ gap: 1rem;
324
+ }
325
+
326
+ .pagination-nav {
327
+ display: flex;
328
+ align-items: center;
329
+ gap: 0.25rem;
330
+ }
331
+
332
+ .pagination-btn {
333
+ display: inline-flex;
334
+ align-items: center;
335
+ justify-content: center;
336
+ width: 32px;
337
+ height: 32px;
338
+ border: 1px solid var(--dm-color-outline, #e0e0e0);
339
+ border-radius: var(--dm-radius-sm, 0.25rem);
340
+ background: var(--dm-color-surface, #ffffff);
341
+ cursor: pointer;
342
+ transition: all 150ms ease;
343
+ color: var(--dm-color-on-surface, #1a1a1a);
344
+ }
345
+
346
+ .pagination-btn:hover:not(:disabled) {
347
+ background: var(--dm-color-surface-container, #ebebeb);
348
+ }
349
+
350
+ .pagination-btn:focus-visible {
351
+ outline: 2px solid var(--dm-color-primary, #6366f1);
352
+ outline-offset: 2px;
353
+ }
354
+
355
+ .pagination-btn:disabled {
356
+ opacity: 0.5;
357
+ cursor: not-allowed;
358
+ }
359
+
360
+ .pagination-current {
361
+ padding: 0 0.75rem;
362
+ color: var(--dm-color-on-surface, #1a1a1a);
363
+ min-width: 100px;
364
+ text-align: center;
365
+ }
366
+
367
+ .page-size-select {
368
+ padding: 0.375rem 0.75rem;
369
+ border: 1px solid var(--dm-color-outline, #e0e0e0);
370
+ border-radius: var(--dm-radius-sm, 0.25rem);
371
+ background: var(--dm-color-surface, #ffffff);
372
+ font-size: 0.875rem;
373
+ cursor: pointer;
374
+ }
375
+
376
+ .page-size-select:focus-visible {
377
+ outline: 2px solid var(--dm-color-primary, #6366f1);
378
+ outline-offset: 2px;
379
+ }
380
+
381
+ /* Clickable rows */
382
+ :host([selection-mode='single']) .table-row,
383
+ :host([selection-mode='multiple']) .table-row {
384
+ cursor: pointer;
385
+ }
386
+ `;
387
+
388
+ class ElDmTable extends import_el_core2.BaseElement {
389
+ static properties = {
390
+ columns: { type: Array, attribute: false },
391
+ data: { type: Array, attribute: false },
392
+ sortColumn: { type: String, reflect: true, attribute: "sort-column" },
393
+ sortDirection: {
394
+ type: String,
395
+ reflect: true,
396
+ attribute: "sort-direction",
397
+ default: "asc"
398
+ },
399
+ paginated: { type: Boolean, reflect: true },
400
+ page: { type: Number, reflect: true, default: 1 },
401
+ pageSize: { type: Number, reflect: true, attribute: "page-size", default: 10 },
402
+ pageSizeOptions: { type: Array, attribute: false },
403
+ selectionMode: {
404
+ type: String,
405
+ reflect: true,
406
+ attribute: "selection-mode",
407
+ default: "none"
408
+ },
409
+ selectedIds: { type: Array, attribute: false },
410
+ striped: { type: Boolean, reflect: true },
411
+ bordered: { type: Boolean, reflect: true },
412
+ hoverable: { type: Boolean, reflect: true, default: true },
413
+ compact: { type: Boolean, reflect: true },
414
+ stickyHeader: { type: Boolean, reflect: true, attribute: "sticky-header" },
415
+ loading: { type: Boolean, reflect: true },
416
+ emptyMessage: {
417
+ type: String,
418
+ reflect: true,
419
+ attribute: "empty-message",
420
+ default: "No data available"
421
+ }
422
+ };
423
+ _internalSelectedIds = new Set;
424
+ constructor() {
425
+ super();
426
+ this.attachStyles(styles);
427
+ this.columns = [];
428
+ this.data = [];
429
+ this.selectedIds = [];
430
+ this.pageSizeOptions = [5, 10, 25, 50];
431
+ }
432
+ connectedCallback() {
433
+ super.connectedCallback();
434
+ this.addEventListener("table-column-change", this._handleColumnChange);
435
+ }
436
+ disconnectedCallback() {
437
+ super.disconnectedCallback();
438
+ this.removeEventListener("table-column-change", this._handleColumnChange);
439
+ }
440
+ update() {
441
+ super.update();
442
+ this._attachEventListeners();
443
+ }
444
+ _handleColumnChange = () => {
445
+ this.update();
446
+ };
447
+ _attachEventListeners() {
448
+ this.shadowRoot?.querySelectorAll(".table-th.sortable").forEach((th) => {
449
+ th.addEventListener("click", this._handleHeaderClick);
450
+ th.addEventListener("keydown", this._handleHeaderKeydown);
451
+ });
452
+ this.shadowRoot?.querySelectorAll(".table-row").forEach((row) => {
453
+ row.addEventListener("click", this._handleRowClick);
454
+ });
455
+ this.shadowRoot?.querySelectorAll(".row-select").forEach((input) => {
456
+ input.addEventListener("change", this._handleRowSelectChange);
457
+ });
458
+ const selectAll = this.shadowRoot?.querySelector(".select-all");
459
+ selectAll?.addEventListener("change", this._handleSelectAllChange);
460
+ this.shadowRoot?.querySelectorAll(".pagination-btn").forEach((btn) => {
461
+ btn.addEventListener("click", this._handlePaginationClick);
462
+ });
463
+ const pageSizeSelect = this.shadowRoot?.querySelector(".page-size-select");
464
+ pageSizeSelect?.addEventListener("change", this._handlePageSizeChange);
465
+ }
466
+ _handleHeaderClick = (e) => {
467
+ const th = e.currentTarget.closest("[data-column]");
468
+ const column = th?.getAttribute("data-column");
469
+ if (column) {
470
+ this.sort(column);
471
+ }
472
+ };
473
+ _handleHeaderKeydown = (e) => {
474
+ const keyEvent = e;
475
+ if (keyEvent.key === "Enter" || keyEvent.key === " ") {
476
+ keyEvent.preventDefault();
477
+ this._handleHeaderClick(e);
478
+ }
479
+ };
480
+ sort(column, direction) {
481
+ if (direction) {
482
+ this.sortColumn = column;
483
+ this.sortDirection = direction;
484
+ } else if (this.sortColumn === column) {
485
+ this.sortDirection = this.sortDirection === "asc" ? "desc" : "asc";
486
+ } else {
487
+ this.sortColumn = column;
488
+ this.sortDirection = "asc";
489
+ }
490
+ this.emit("sort", {
491
+ column: this.sortColumn,
492
+ direction: this.sortDirection
493
+ });
494
+ }
495
+ _sortData(data) {
496
+ if (!this.sortColumn)
497
+ return data;
498
+ return [...data].sort((a, b) => {
499
+ const aVal = a[this.sortColumn];
500
+ const bVal = b[this.sortColumn];
501
+ let comparison = 0;
502
+ if (aVal === null || aVal === undefined)
503
+ comparison = 1;
504
+ else if (bVal === null || bVal === undefined)
505
+ comparison = -1;
506
+ else if (typeof aVal === "string" && typeof bVal === "string") {
507
+ comparison = aVal.localeCompare(bVal);
508
+ } else if (typeof aVal === "number" && typeof bVal === "number") {
509
+ comparison = aVal - bVal;
510
+ } else {
511
+ comparison = String(aVal).localeCompare(String(bVal));
512
+ }
513
+ return this.sortDirection === "desc" ? -comparison : comparison;
514
+ });
515
+ }
516
+ _handlePaginationClick = (e) => {
517
+ const btn = e.currentTarget;
518
+ const action = btn.getAttribute("data-action");
519
+ switch (action) {
520
+ case "first":
521
+ this.goToPage(1);
522
+ break;
523
+ case "prev":
524
+ this.goToPage(this.page - 1);
525
+ break;
526
+ case "next":
527
+ this.goToPage(this.page + 1);
528
+ break;
529
+ case "last":
530
+ this.goToPage(this._getTotalPages());
531
+ break;
532
+ }
533
+ };
534
+ _handlePageSizeChange = (e) => {
535
+ const select = e.target;
536
+ const newPageSize = parseInt(select.value, 10);
537
+ this.pageSize = newPageSize;
538
+ this.page = 1;
539
+ this.emit("page-change", {
540
+ page: this.page,
541
+ pageSize: this.pageSize
542
+ });
543
+ };
544
+ goToPage(page) {
545
+ const totalPages = this._getTotalPages();
546
+ const newPage = Math.max(1, Math.min(page, totalPages));
547
+ if (newPage !== this.page) {
548
+ this.page = newPage;
549
+ this.emit("page-change", {
550
+ page: this.page,
551
+ pageSize: this.pageSize
552
+ });
553
+ }
554
+ }
555
+ _getTotalPages() {
556
+ return Math.max(1, Math.ceil(this.data.length / this.pageSize));
557
+ }
558
+ _paginateData(data) {
559
+ if (!this.paginated)
560
+ return data;
561
+ const start = (this.page - 1) * this.pageSize;
562
+ const end = start + this.pageSize;
563
+ return data.slice(start, end);
564
+ }
565
+ _getStartRow() {
566
+ if (this.data.length === 0)
567
+ return 0;
568
+ return (this.page - 1) * this.pageSize + 1;
569
+ }
570
+ _getEndRow() {
571
+ return Math.min(this.page * this.pageSize, this.data.length);
572
+ }
573
+ _handleRowClick = (e) => {
574
+ const row = e.target.closest(".table-row");
575
+ if (!row)
576
+ return;
577
+ if (e.target.closest(".select-cell"))
578
+ return;
579
+ const rowId = row.getAttribute("data-row-id");
580
+ const rowIndex = parseInt(row.getAttribute("data-row-index") || "0", 10);
581
+ if (rowId !== null) {
582
+ const id = this._parseId(rowId);
583
+ const rowData = this.data.find((r) => r.id === id);
584
+ if (rowData) {
585
+ this.emit("row-click", {
586
+ row: rowData,
587
+ rowIndex
588
+ });
589
+ if (this.selectionMode !== "none") {
590
+ this.toggleRowSelection(id);
591
+ }
592
+ }
593
+ }
594
+ };
595
+ _handleRowSelectChange = (e) => {
596
+ const input = e.target;
597
+ const rowId = input.getAttribute("data-row-id");
598
+ if (rowId !== null) {
599
+ const id = this._parseId(rowId);
600
+ if (input.checked) {
601
+ this.selectRow(id);
602
+ } else {
603
+ this.deselectRow(id);
604
+ }
605
+ }
606
+ };
607
+ _handleSelectAllChange = (e) => {
608
+ const input = e.target;
609
+ if (input.checked) {
610
+ this.selectAll();
611
+ } else {
612
+ this.deselectAll();
613
+ }
614
+ };
615
+ _parseId(idStr) {
616
+ const num = Number(idStr);
617
+ return isNaN(num) ? idStr : num;
618
+ }
619
+ selectRow(id) {
620
+ if (this.selectionMode === "single") {
621
+ this._internalSelectedIds.clear();
622
+ }
623
+ this._internalSelectedIds.add(id);
624
+ this._emitSelectionChange();
625
+ }
626
+ deselectRow(id) {
627
+ this._internalSelectedIds.delete(id);
628
+ this._emitSelectionChange();
629
+ }
630
+ toggleRowSelection(id) {
631
+ if (this._internalSelectedIds.has(id)) {
632
+ this.deselectRow(id);
633
+ } else {
634
+ this.selectRow(id);
635
+ }
636
+ }
637
+ selectAll() {
638
+ const visibleData = this._getProcessedData();
639
+ visibleData.forEach((row) => this._internalSelectedIds.add(row.id));
640
+ this._emitSelectionChange();
641
+ }
642
+ deselectAll() {
643
+ this._internalSelectedIds.clear();
644
+ this._emitSelectionChange();
645
+ }
646
+ getSelectedRows() {
647
+ return this.data.filter((row) => this._internalSelectedIds.has(row.id));
648
+ }
649
+ _emitSelectionChange() {
650
+ this.selectedIds = Array.from(this._internalSelectedIds);
651
+ this.emit("select", {
652
+ selectedIds: this.selectedIds,
653
+ selectedRows: this.getSelectedRows()
654
+ });
655
+ this.update();
656
+ }
657
+ _isRowSelected(row) {
658
+ return this._internalSelectedIds.has(row.id);
659
+ }
660
+ _isAllSelected() {
661
+ const visibleData = this._getProcessedData();
662
+ if (visibleData.length === 0)
663
+ return false;
664
+ return visibleData.every((row) => this._internalSelectedIds.has(row.id));
665
+ }
666
+ _isSomeSelected() {
667
+ const visibleData = this._getProcessedData();
668
+ return visibleData.some((row) => this._internalSelectedIds.has(row.id)) && !this._isAllSelected();
669
+ }
670
+ _getEffectiveColumns() {
671
+ if (this.columns && this.columns.length > 0) {
672
+ return this.columns.filter((col) => !col.hidden);
673
+ }
674
+ const columnElements = this.querySelectorAll("el-dm-table-column");
675
+ const cols = [];
676
+ columnElements.forEach((el) => {
677
+ if (el instanceof ElDmTableColumn) {
678
+ const colDef = el.toColumnDef();
679
+ if (!colDef.hidden) {
680
+ cols.push(colDef);
681
+ }
682
+ }
683
+ });
684
+ return cols;
685
+ }
686
+ _getProcessedData() {
687
+ let result = [...this.data || []];
688
+ result = this._sortData(result);
689
+ result = this._paginateData(result);
690
+ return result;
691
+ }
692
+ getVisibleData() {
693
+ return this._getProcessedData();
694
+ }
695
+ refresh() {
696
+ this.update();
697
+ }
698
+ _formatCellValue(value) {
699
+ if (value === null || value === undefined)
700
+ return "";
701
+ if (typeof value === "boolean")
702
+ return value ? "Yes" : "No";
703
+ if (value instanceof Date)
704
+ return value.toLocaleDateString();
705
+ return String(value);
706
+ }
707
+ _renderHeaderCell(column) {
708
+ const sortable = column.sortable;
709
+ const isSorted = this.sortColumn === column.key;
710
+ const sortIcon = isSorted ? this.sortDirection === "asc" ? ICONS.sortAsc : ICONS.sortDesc : ICONS.sort;
711
+ return `
712
+ <th
713
+ class="table-th ${sortable ? "sortable" : ""} ${isSorted ? "sorted" : ""}"
714
+ part="th"
715
+ data-column="${column.key}"
716
+ style="text-align: ${column.align || "left"}; ${column.width ? `width: ${column.width};` : ""}"
717
+ scope="col"
718
+ ${sortable ? `role="columnheader" aria-sort="${isSorted ? this.sortDirection === "asc" ? "ascending" : "descending" : "none"}" tabindex="0"` : ""}
719
+ >
720
+ <span class="th-content">
721
+ <span>${column.label}</span>
722
+ ${sortable ? `<span class="sort-icon">${sortIcon}</span>` : ""}
723
+ </span>
724
+ </th>
725
+ `;
726
+ }
727
+ _renderSelectAllCell() {
728
+ if (this.selectionMode !== "multiple") {
729
+ return '<th class="table-th select-cell" part="th"></th>';
730
+ }
731
+ const isAllSelected = this._isAllSelected();
732
+ const isSomeSelected = this._isSomeSelected();
733
+ return `
734
+ <th class="table-th select-cell" part="th">
735
+ <input
736
+ type="checkbox"
737
+ class="select-all"
738
+ ${isAllSelected ? "checked" : ""}
739
+ ${isSomeSelected ? 'data-indeterminate="true"' : ""}
740
+ aria-label="Select all rows"
741
+ />
742
+ </th>
743
+ `;
744
+ }
745
+ _renderSelectCell(row) {
746
+ const isSelected = this._isRowSelected(row);
747
+ const inputType = this.selectionMode === "single" ? "radio" : "checkbox";
748
+ return `
749
+ <td class="table-td select-cell" part="td">
750
+ <input
751
+ type="${inputType}"
752
+ class="row-select"
753
+ name="table-selection"
754
+ data-row-id="${row.id}"
755
+ ${isSelected ? "checked" : ""}
756
+ aria-label="Select row"
757
+ />
758
+ </td>
759
+ `;
760
+ }
761
+ _renderDataRow(row, index, columns) {
762
+ const isSelected = this._isRowSelected(row);
763
+ const showSelectionColumn = this.selectionMode !== "none";
764
+ return `
765
+ <tr
766
+ class="table-row ${isSelected ? "selected" : ""}"
767
+ part="row"
768
+ data-row-id="${row.id}"
769
+ data-row-index="${index}"
770
+ ${isSelected ? 'aria-selected="true"' : ""}
771
+ >
772
+ ${showSelectionColumn ? this._renderSelectCell(row) : ""}
773
+ ${columns.map((col) => `
774
+ <td
775
+ class="table-td"
776
+ part="td"
777
+ style="text-align: ${col.align || "left"};"
778
+ >
779
+ ${this._formatCellValue(row[col.key])}
780
+ </td>
781
+ `).join("")}
782
+ </tr>
783
+ `;
784
+ }
785
+ _renderLoadingRow(colCount) {
786
+ const totalCols = this.selectionMode !== "none" ? colCount + 1 : colCount;
787
+ return `
788
+ <tr class="loading-row">
789
+ <td colspan="${totalCols}">
790
+ <div class="loading-spinner"></div>
791
+ <div>Loading...</div>
792
+ </td>
793
+ </tr>
794
+ `;
795
+ }
796
+ _renderEmptyRow(colCount) {
797
+ const totalCols = this.selectionMode !== "none" ? colCount + 1 : colCount;
798
+ return `
799
+ <tr class="empty-row">
800
+ <td colspan="${totalCols}">
801
+ <slot name="empty">${this.emptyMessage}</slot>
802
+ </td>
803
+ </tr>
804
+ `;
805
+ }
806
+ _renderPagination() {
807
+ const totalPages = this._getTotalPages();
808
+ const showPageSizeSelect = this.pageSizeOptions && this.pageSizeOptions.length > 0;
809
+ return `
810
+ <div class="table-pagination" part="pagination">
811
+ <div class="pagination-info">
812
+ Showing ${this._getStartRow()} to ${this._getEndRow()} of ${this.data.length} entries
813
+ </div>
814
+ <div class="pagination-controls">
815
+ ${showPageSizeSelect ? `
816
+ <select class="page-size-select" aria-label="Rows per page">
817
+ ${this.pageSizeOptions.map((size) => `
818
+ <option value="${size}" ${size === this.pageSize ? "selected" : ""}>
819
+ ${size} / page
820
+ </option>
821
+ `).join("")}
822
+ </select>
823
+ ` : ""}
824
+ <div class="pagination-nav">
825
+ <button
826
+ class="pagination-btn"
827
+ data-action="first"
828
+ ${this.page <= 1 ? "disabled" : ""}
829
+ aria-label="First page"
830
+ >${ICONS.chevronFirst}</button>
831
+ <button
832
+ class="pagination-btn"
833
+ data-action="prev"
834
+ ${this.page <= 1 ? "disabled" : ""}
835
+ aria-label="Previous page"
836
+ >${ICONS.chevronLeft}</button>
837
+ <span class="pagination-current">
838
+ Page ${this.page} of ${totalPages}
839
+ </span>
840
+ <button
841
+ class="pagination-btn"
842
+ data-action="next"
843
+ ${this.page >= totalPages ? "disabled" : ""}
844
+ aria-label="Next page"
845
+ >${ICONS.chevronRight}</button>
846
+ <button
847
+ class="pagination-btn"
848
+ data-action="last"
849
+ ${this.page >= totalPages ? "disabled" : ""}
850
+ aria-label="Last page"
851
+ >${ICONS.chevronLast}</button>
852
+ </div>
853
+ </div>
854
+ </div>
855
+ `;
856
+ }
857
+ render() {
858
+ const columns = this._getEffectiveColumns();
859
+ const processedData = this._getProcessedData();
860
+ const showSelectionColumn = this.selectionMode !== "none";
861
+ return `
862
+ <div class="table-wrapper" part="wrapper">
863
+ <div class="table-header-actions" part="header-actions">
864
+ <slot name="header-actions"></slot>
865
+ </div>
866
+
867
+ <div class="table-container" part="container">
868
+ <table class="table" part="table" role="grid" aria-busy="${this.loading}">
869
+ <thead part="thead">
870
+ <tr part="header-row">
871
+ ${showSelectionColumn ? this._renderSelectAllCell() : ""}
872
+ ${columns.map((col) => this._renderHeaderCell(col)).join("")}
873
+ </tr>
874
+ </thead>
875
+ <tbody part="tbody">
876
+ ${this.loading ? this._renderLoadingRow(columns.length) : ""}
877
+ ${!this.loading && processedData.length === 0 ? this._renderEmptyRow(columns.length) : ""}
878
+ ${!this.loading ? processedData.map((row, idx) => this._renderDataRow(row, idx, columns)).join("") : ""}
879
+ </tbody>
880
+ </table>
881
+ </div>
882
+
883
+ ${this.paginated ? this._renderPagination() : ""}
884
+
885
+ <div class="table-footer-actions" part="footer-actions">
886
+ <slot name="footer-actions"></slot>
887
+ </div>
888
+ </div>
889
+ `;
890
+ }
891
+ }
892
+ function registerTable() {
893
+ if (!customElements.get("el-dm-table")) {
894
+ customElements.define("el-dm-table", ElDmTable);
895
+ }
896
+ }
897
+ // src/index.ts
898
+ function register() {
899
+ registerTable();
900
+ registerTableColumn();
901
+ }
902
+
903
+ //# debugId=35759F8857AE354464756E2164756E21
904
+ //# sourceMappingURL=index.js.map