ng-dynamic-datatable 0.0.11 → 0.0.12

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.
@@ -3,6 +3,305 @@ import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
4
  import { EventEmitter, Output, Input, Component } from '@angular/core';
5
5
 
6
+ const VALID_TRIGGERS = {
7
+ hover: 'hover',
8
+ click: 'click'
9
+ };
10
+ const VALID_POSITIONS = {
11
+ top: 'top',
12
+ bottom: 'bottom',
13
+ left: 'left',
14
+ right: 'right'
15
+ };
16
+ class TooltipManager {
17
+ registry = new WeakMap();
18
+ root;
19
+ documentRef;
20
+ activeTarget = null;
21
+ activeTooltipEl = null;
22
+ offset = 10;
23
+ viewportPadding = 8;
24
+ onMouseOverBound = (event) => this.onMouseOver(event);
25
+ onMouseOutBound = (event) => this.onMouseOut(event);
26
+ onFocusInBound = (event) => this.onFocusIn(event);
27
+ onFocusOutBound = (event) => this.onFocusOut(event);
28
+ onClickBound = (event) => this.onClick(event);
29
+ onDocumentClickBound = (event) => this.onDocumentClick(event);
30
+ onDocumentKeydownBound = (event) => this.onDocumentKeydown(event);
31
+ onWindowResizeBound = () => this.reposition();
32
+ onWindowScrollBound = () => this.reposition();
33
+ constructor(root, documentRef = document) {
34
+ this.root = root;
35
+ this.documentRef = documentRef;
36
+ }
37
+ init() {
38
+ this.root.addEventListener('mouseover', this.onMouseOverBound);
39
+ this.root.addEventListener('mouseout', this.onMouseOutBound);
40
+ this.root.addEventListener('focusin', this.onFocusInBound);
41
+ this.root.addEventListener('focusout', this.onFocusOutBound);
42
+ this.root.addEventListener('click', this.onClickBound);
43
+ this.documentRef.addEventListener('click', this.onDocumentClickBound, true);
44
+ this.documentRef.addEventListener('keydown', this.onDocumentKeydownBound);
45
+ window.addEventListener('resize', this.onWindowResizeBound);
46
+ window.addEventListener('scroll', this.onWindowScrollBound, true);
47
+ }
48
+ destroy() {
49
+ this.hide(true);
50
+ this.root.removeEventListener('mouseover', this.onMouseOverBound);
51
+ this.root.removeEventListener('mouseout', this.onMouseOutBound);
52
+ this.root.removeEventListener('focusin', this.onFocusInBound);
53
+ this.root.removeEventListener('focusout', this.onFocusOutBound);
54
+ this.root.removeEventListener('click', this.onClickBound);
55
+ this.documentRef.removeEventListener('click', this.onDocumentClickBound, true);
56
+ this.documentRef.removeEventListener('keydown', this.onDocumentKeydownBound);
57
+ window.removeEventListener('resize', this.onWindowResizeBound);
58
+ window.removeEventListener('scroll', this.onWindowScrollBound, true);
59
+ }
60
+ register(element, config) {
61
+ this.registry.set(element, { config });
62
+ }
63
+ onMouseOver(event) {
64
+ const target = this.getTooltipTarget(event.target);
65
+ if (!target) {
66
+ return;
67
+ }
68
+ if (this.getTrigger(target) !== 'hover') {
69
+ return;
70
+ }
71
+ this.show(target);
72
+ }
73
+ onMouseOut(event) {
74
+ const target = this.getTooltipTarget(event.target);
75
+ if (!target || this.getTrigger(target) !== 'hover') {
76
+ return;
77
+ }
78
+ const next = event.relatedTarget;
79
+ if (next && (target.contains(next) || (this.activeTooltipEl?.contains(next) ?? false))) {
80
+ return;
81
+ }
82
+ this.hide();
83
+ }
84
+ onFocusIn(event) {
85
+ const target = this.getTooltipTarget(event.target);
86
+ if (!target) {
87
+ return;
88
+ }
89
+ this.show(target);
90
+ }
91
+ onFocusOut(event) {
92
+ const target = this.getTooltipTarget(event.target);
93
+ if (!target) {
94
+ return;
95
+ }
96
+ const next = event.relatedTarget;
97
+ if (next && (target.contains(next) || (this.activeTooltipEl?.contains(next) ?? false))) {
98
+ return;
99
+ }
100
+ this.hide();
101
+ }
102
+ onClick(event) {
103
+ const target = this.getTooltipTarget(event.target);
104
+ if (!target) {
105
+ return;
106
+ }
107
+ if (this.getTrigger(target) !== 'click') {
108
+ return;
109
+ }
110
+ event.preventDefault();
111
+ event.stopPropagation();
112
+ if (this.activeTarget === target && this.activeTooltipEl) {
113
+ this.hide();
114
+ return;
115
+ }
116
+ this.show(target);
117
+ }
118
+ onDocumentClick(event) {
119
+ if (!this.activeTarget || !this.activeTooltipEl) {
120
+ return;
121
+ }
122
+ if (this.getTrigger(this.activeTarget) !== 'click') {
123
+ return;
124
+ }
125
+ const node = event.target;
126
+ const insideTarget = !!(node && this.activeTarget.contains(node));
127
+ const insideTooltip = !!(node && this.activeTooltipEl.contains(node));
128
+ if (!insideTarget && !insideTooltip) {
129
+ this.hide();
130
+ }
131
+ }
132
+ onDocumentKeydown(event) {
133
+ if (event.key === 'Escape') {
134
+ this.hide();
135
+ }
136
+ }
137
+ getTooltipTarget(input) {
138
+ if (!(input instanceof Element)) {
139
+ return null;
140
+ }
141
+ const target = input.closest('[data-tooltip]');
142
+ if (!target) {
143
+ return null;
144
+ }
145
+ if (!this.root.contains(target)) {
146
+ return null;
147
+ }
148
+ return target;
149
+ }
150
+ getEntry(target) {
151
+ return this.registry.get(target);
152
+ }
153
+ getTrigger(target) {
154
+ const value = this.getEntry(target)?.config.trigger ?? target.dataset['tooltipTrigger'] ?? 'hover';
155
+ const normalized = String(value).toLowerCase();
156
+ return VALID_TRIGGERS[normalized] ?? 'hover';
157
+ }
158
+ getPosition(target) {
159
+ const value = this.getEntry(target)?.config.position ?? target.dataset['tooltipPosition'] ?? 'bottom';
160
+ const normalized = String(value).toLowerCase();
161
+ return VALID_POSITIONS[normalized] ?? 'bottom';
162
+ }
163
+ getContent(target) {
164
+ const entry = this.getEntry(target);
165
+ const html = entry?.config.html ?? target.dataset['tooltipHtml'] ?? '';
166
+ const text = entry?.config.content ?? target.dataset['tooltip'] ?? '';
167
+ const icon = entry?.config.icon ?? target.dataset['tooltipIcon'] ?? '';
168
+ const allowHtmlAttr = target.dataset['tooltipAllowHtml'];
169
+ const allowHtml = entry?.config.allowHtml ?? (allowHtmlAttr === 'true');
170
+ const noArrowAttr = target.dataset['tooltipNoArrow'];
171
+ const noArrow = entry?.config.noArrow ?? (noArrowAttr === 'true');
172
+ const offsetRaw = entry?.config.offset ?? target.dataset['tooltipOffset'];
173
+ const offset = Number.isFinite(Number(offsetRaw)) ? Number(offsetRaw) : this.offset;
174
+ return { icon, text, html, allowHtml, noArrow, offset };
175
+ }
176
+ show(target) {
177
+ const payload = this.getContent(target);
178
+ const content = payload.allowHtml && payload.html ? payload.html : payload.text;
179
+ if (!content) {
180
+ this.hide();
181
+ return;
182
+ }
183
+ this.hide(true);
184
+ const tooltip = this.documentRef.createElement('div');
185
+ tooltip.className = 'ndt-tooltip';
186
+ tooltip.setAttribute('role', 'tooltip');
187
+ tooltip.setAttribute('data-placement', this.getPosition(target));
188
+ if (payload.noArrow) {
189
+ tooltip.setAttribute('data-no-arrow', 'true');
190
+ }
191
+ const contentWrap = this.documentRef.createElement('div');
192
+ contentWrap.className = 'ndt-tooltip__content';
193
+ if (payload.icon) {
194
+ const iconEl = this.documentRef.createElement('span');
195
+ iconEl.className = `ndt-tooltip__icon ${payload.icon}`;
196
+ iconEl.setAttribute('aria-hidden', 'true');
197
+ contentWrap.appendChild(iconEl);
198
+ }
199
+ const textEl = this.documentRef.createElement('span');
200
+ textEl.className = 'ndt-tooltip__text';
201
+ if (payload.allowHtml && payload.html) {
202
+ textEl.innerHTML = payload.html;
203
+ }
204
+ else {
205
+ textEl.textContent = payload.text;
206
+ }
207
+ contentWrap.appendChild(textEl);
208
+ tooltip.appendChild(contentWrap);
209
+ this.documentRef.body.appendChild(tooltip);
210
+ this.activeTarget = target;
211
+ this.activeTooltipEl = tooltip;
212
+ this.positionTooltip(target, tooltip, this.getPosition(target), payload.offset);
213
+ requestAnimationFrame(() => {
214
+ if (this.activeTooltipEl === tooltip) {
215
+ tooltip.classList.add('ndt-tooltip--show');
216
+ }
217
+ });
218
+ }
219
+ hide(immediate = false) {
220
+ if (!this.activeTooltipEl) {
221
+ this.activeTarget = null;
222
+ return;
223
+ }
224
+ const tooltip = this.activeTooltipEl;
225
+ this.activeTooltipEl = null;
226
+ this.activeTarget = null;
227
+ if (immediate) {
228
+ if (tooltip.parentNode) {
229
+ tooltip.parentNode.removeChild(tooltip);
230
+ }
231
+ return;
232
+ }
233
+ tooltip.classList.remove('ndt-tooltip--show');
234
+ window.setTimeout(() => {
235
+ if (tooltip.parentNode) {
236
+ tooltip.parentNode.removeChild(tooltip);
237
+ }
238
+ }, 180);
239
+ }
240
+ reposition() {
241
+ if (!this.activeTarget || !this.activeTooltipEl) {
242
+ return;
243
+ }
244
+ const payload = this.getContent(this.activeTarget);
245
+ this.positionTooltip(this.activeTarget, this.activeTooltipEl, this.getPosition(this.activeTarget), payload.offset);
246
+ }
247
+ positionTooltip(target, tooltip, preferred, offset) {
248
+ const rect = target.getBoundingClientRect();
249
+ const tipRect = tooltip.getBoundingClientRect();
250
+ const vw = window.innerWidth;
251
+ const vh = window.innerHeight;
252
+ const placement = this.pickPlacement(preferred, rect, tipRect, vw, vh, offset);
253
+ const coords = this.computeCoords(placement, rect, tipRect, offset);
254
+ const minX = this.viewportPadding;
255
+ const maxX = vw - tipRect.width - this.viewportPadding;
256
+ const minY = this.viewportPadding;
257
+ const maxY = vh - tipRect.height - this.viewportPadding;
258
+ const left = Math.min(Math.max(coords.left, minX), Math.max(minX, maxX));
259
+ const top = Math.min(Math.max(coords.top, minY), Math.max(minY, maxY));
260
+ tooltip.style.left = `${Math.round(left)}px`;
261
+ tooltip.style.top = `${Math.round(top)}px`;
262
+ tooltip.setAttribute('data-placement', placement);
263
+ }
264
+ pickPlacement(preferred, rect, tipRect, vw, vh, offset) {
265
+ const fits = {
266
+ top: rect.top - offset - tipRect.height >= this.viewportPadding,
267
+ bottom: rect.bottom + offset + tipRect.height <= vh - this.viewportPadding,
268
+ left: rect.left - offset - tipRect.width >= this.viewportPadding,
269
+ right: rect.right + offset + tipRect.width <= vw - this.viewportPadding
270
+ };
271
+ const order = [preferred, 'bottom', 'top', 'right', 'left'];
272
+ for (const candidate of order) {
273
+ if (fits[candidate]) {
274
+ return candidate;
275
+ }
276
+ }
277
+ return preferred;
278
+ }
279
+ computeCoords(placement, rect, tipRect, offset) {
280
+ switch (placement) {
281
+ case 'top':
282
+ return {
283
+ top: rect.top - tipRect.height - offset,
284
+ left: rect.left + (rect.width - tipRect.width) / 2
285
+ };
286
+ case 'bottom':
287
+ return {
288
+ top: rect.bottom + offset,
289
+ left: rect.left + (rect.width - tipRect.width) / 2
290
+ };
291
+ case 'left':
292
+ return {
293
+ top: rect.top + (rect.height - tipRect.height) / 2,
294
+ left: rect.left - tipRect.width - offset
295
+ };
296
+ default:
297
+ return {
298
+ top: rect.top + (rect.height - tipRect.height) / 2,
299
+ left: rect.right + offset
300
+ };
301
+ }
302
+ }
303
+ }
304
+
6
305
  const DEFAULT_CONFIG = {
7
306
  title: 'Dynamic DataTable',
8
307
  features: {
@@ -22,6 +321,7 @@ const DEFAULT_CONFIG = {
22
321
  }
23
322
  };
24
323
  class DynamicDatatableComponent {
324
+ hostRef;
25
325
  config = {};
26
326
  columns = [];
27
327
  data = [];
@@ -50,6 +350,21 @@ class DynamicDatatableComponent {
50
350
  sortState = { key: null, direction: 'asc' };
51
351
  selectedRows = new Set();
52
352
  isExportMenuOpen = false;
353
+ tooltipManager = null;
354
+ constructor(hostRef) {
355
+ this.hostRef = hostRef;
356
+ }
357
+ ngAfterViewInit() {
358
+ if (typeof document === 'undefined') {
359
+ return;
360
+ }
361
+ this.tooltipManager = new TooltipManager(this.hostRef.nativeElement, document);
362
+ this.tooltipManager.init();
363
+ }
364
+ ngOnDestroy() {
365
+ this.tooltipManager?.destroy();
366
+ this.tooltipManager = null;
367
+ }
53
368
  ngOnChanges(_changes) {
54
369
  this.refresh();
55
370
  }
@@ -226,6 +541,25 @@ class DynamicDatatableComponent {
226
541
  }
227
542
  return 'auto';
228
543
  }
544
+ getColumnTooltip(column) {
545
+ const label = String(column.label || 'Column');
546
+ if (this.isFeatureOn('sorting') && column.sortable) {
547
+ const key = String(column.key);
548
+ if (this.sortState.key === key) {
549
+ const direction = this.sortState.direction === 'asc' ? 'ascending' : 'descending';
550
+ return `${label} (sorted ${direction})`;
551
+ }
552
+ return `${label} (click to sort)`;
553
+ }
554
+ return label;
555
+ }
556
+ getCellTooltip(row, column) {
557
+ const value = this.getCellTextValue(row, column).trim();
558
+ if (!value) {
559
+ return String(column.label || 'Cell');
560
+ }
561
+ return value;
562
+ }
229
563
  getColumnCount() {
230
564
  let count = this.mergedColumns.length;
231
565
  if (this.isFeatureOn('checkboxSelection')) {
@@ -436,13 +770,13 @@ class DynamicDatatableComponent {
436
770
  closeMenus() {
437
771
  this.isExportMenuOpen = false;
438
772
  }
439
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: DynamicDatatableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
440
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: DynamicDatatableComponent, isStandalone: true, selector: "lib-dynamic-datatable", inputs: { config: "config", columns: "columns", data: "data" }, outputs: { actionSelected: "actionSelected", selectionChange: "selectionChange", sortChange: "sortChange", pageChange: "pageChange", exportTriggered: "exportTriggered" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"ndt-card\" (click)=\"closeMenus()\">\r\n <div class=\"ndt-header\">\r\n <h3 class=\"ndt-title\">{{ mergedConfig.title }}</h3>\r\n </div>\r\n\r\n <div class=\"ndt-toolbar\">\r\n <div class=\"ndt-left-tools\">\r\n <ng-container *ngIf=\"isFeatureOn('export')\">\r\n <div class=\"ndt-dropdown\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"ndt-btn ndt-export-btn\" type=\"button\" (click)=\"toggleExportMenu($event)\">\r\n <i class=\"bi bi-download\"></i>\r\n <span>Export</span>\r\n <i class=\"bi bi-chevron-down ndt-chevron\"></i>\r\n </button>\r\n\r\n <ul class=\"ndt-dropdown-menu\" *ngIf=\"isExportMenuOpen\">\r\n <li *ngIf=\"isExportFormatEnabled('csv')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" (click)=\"exportCSV()\">\r\n <i class=\"bi bi-filetype-csv\"></i>\r\n <span>CSV</span>\r\n </button>\r\n </li>\r\n <li *ngIf=\"isExportFormatEnabled('excel')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" (click)=\"exportExcel()\">\r\n <i class=\"bi bi-file-earmark-spreadsheet\"></i>\r\n <span>Excel (.xls)</span>\r\n </button>\r\n </li>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n\r\n <label class=\"ndt-inline-label\" *ngIf=\"isFeatureOn('rowsPerPage') && isFeatureOn('pagination')\">\r\n Rows per page:\r\n <select [value]=\"rowsPerPage\" (change)=\"onRowsPerPageChange($event)\">\r\n <option *ngFor=\"let option of mergedConfig.rowsPerPageOptions || []\" [value]=\"option\">{{ option }}</option>\r\n </select>\r\n </label>\r\n </div>\r\n\r\n <div class=\"ndt-right-tools\" *ngIf=\"isFeatureOn('searching')\">\r\n <input\r\n type=\"search\"\r\n placeholder=\"Search records\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearchInput($event)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"ndt-table-wrap\">\r\n <table class=\"ndt-table\">\r\n <colgroup>\r\n <col *ngIf=\"isFeatureOn('checkboxSelection')\" style=\"width: 44px\" />\r\n <col *ngFor=\"let column of mergedColumns\" [style.width]=\"toColumnWidth(column.width)\" />\r\n <col *ngIf=\"isFeatureOn('actions')\" style=\"width: 78px\" />\r\n </colgroup>\r\n\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"isCurrentPageFullySelected()\"\r\n (change)=\"toggleSelectAllCurrentPage($event)\"\r\n />\r\n </th>\r\n <th\r\n *ngFor=\"let column of mergedColumns\"\r\n [class.ndt-sortable]=\"isFeatureOn('sorting') && !!column.sortable\"\r\n (click)=\"toggleSort(column)\"\r\n >\r\n <span class=\"ndt-th-content\">\r\n <span class=\"ndt-th-label\">{{ column.label }}</span>\r\n <i\r\n *ngIf=\"isFeatureOn('sorting') && column.sortable\"\r\n [ngClass]=\"[\r\n 'ndt-sort-indicator',\r\n getSortIconClass(column.key.toString()),\r\n isSortColumn(column.key.toString()) ? 'active' : ''\r\n ]\"\r\n ></i>\r\n </span>\r\n </th>\r\n <th *ngIf=\"isFeatureOn('actions')\">Actions</th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr *ngIf=\"!pagedRows.length\">\r\n <td [attr.colspan]=\"getColumnCount()\" class=\"ndt-empty\">No records found.</td>\r\n </tr>\r\n\r\n <tr *ngFor=\"let row of pagedRows\" [class.ndt-selected]=\"isRowSelected(row.id)\">\r\n <td *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"isRowSelected(row.id)\"\r\n (change)=\"toggleRowSelection(row, $event)\"\r\n />\r\n </td>\r\n\r\n <td *ngFor=\"let column of mergedColumns\" [innerHTML]=\"getRenderedCell(row.data, column)\"></td>\r\n\r\n <td *ngIf=\"isFeatureOn('actions')\" class=\"ndt-actions-cell\">\r\n <div class=\"ndt-action-icons\" (click)=\"$event.stopPropagation()\">\r\n <button\r\n *ngFor=\"let action of mergedConfig.actions || []; let i = index\"\r\n type=\"button\"\r\n class=\"ndt-actions-btn\"\r\n [class.ndt-danger]=\"!!action.danger\"\r\n [attr.title]=\"action.label\"\r\n [attr.aria-label]=\"action.label\"\r\n (click)=\"onActionItemClick(i, row, $event)\"\r\n >\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\"></i>\r\n <span *ngIf=\"!action.icon\" class=\"ndt-action-fallback\">{{ action.label.charAt(0) }}</span>\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div class=\"ndt-footer\">\r\n <div>\r\n {{ selectedRows.size }} selected\r\n </div>\r\n\r\n <div>\r\n Showing {{ getStartEntry() }} to {{ getEndEntry() }} of {{ filteredRows.length }} entries\r\n </div>\r\n\r\n <ul class=\"ndt-pagination\" *ngIf=\"isFeatureOn('pagination') && totalPages > 1\">\r\n <li [class.disabled]=\"currentPage <= 1\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage <= 1\">Prev</button>\r\n </li>\r\n <li *ngFor=\"let page of getPaginationPages()\" [class.active]=\"page === currentPage\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(page)\">{{ page }}</button>\r\n </li>\r\n <li [class.disabled]=\"currentPage >= totalPages\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage >= totalPages\">Next</button>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;--ndt-primary: #4f46e5;--ndt-primary-dark: #4338ca;--ndt-primary-soft: #eef2ff;--ndt-border: #dbe4ff;--ndt-text: #1f2a44;--ndt-muted: #6d7895}.ndt-card{border:1px solid var(--ndt-border);border-radius:20px;padding:10px;background:#ffffffe6;backdrop-filter:blur(3px);box-shadow:0 20px 45px #2d489124;overflow:hidden;color:var(--ndt-text);font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ndt-header,.ndt-toolbar,.ndt-footer{padding:1.05rem 1.35rem}.ndt-header{background:linear-gradient(180deg,#fff,#fafcff);border-bottom:1px solid #eaf0ff}.ndt-title{margin:0;font-size:1.2rem;color:#1b2550}.ndt-toolbar{display:flex;justify-content:space-between;gap:.75rem;flex-wrap:wrap;align-items:center}.ndt-left-tools,.ndt-right-tools{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}.ndt-btn,.ndt-toolbar select,.ndt-toolbar input{border:1px solid #d5def8;background:#fff;color:#445381;border-radius:10px;padding:.36rem .62rem;font-size:.85rem}.ndt-btn:hover{border-color:var(--ndt-primary);background:#4f46e512;color:var(--ndt-primary)}.ndt-toolbar input{min-width:260px}.ndt-toolbar input:focus,.ndt-toolbar select:focus{outline:none;border-color:#4f46e58c;box-shadow:0 0 0 .2rem #4f46e51f}.ndt-inline-label{display:inline-flex;align-items:center;gap:.4rem;color:var(--ndt-muted);font-size:.85rem}.ndt-table-wrap{margin:0 1.35rem;overflow-x:auto;overflow-y:visible;border:1px solid #e5ecff;border-radius:14px;background:#fff}.ndt-table{width:100%;min-width:920px;border-collapse:collapse;table-layout:fixed}.ndt-table th,.ndt-table td{padding:.8rem .72rem;text-align:left;border-bottom:1px solid #edf2ff;vertical-align:middle}.ndt-table th{color:#4a577f;font-size:.85rem;text-transform:uppercase;letter-spacing:.03em;background:#f7faff;border-bottom:1px solid #e6edff}.ndt-th-content{display:flex;align-items:center;justify-content:space-between;gap:.4rem}.ndt-th-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ndt-sortable{cursor:pointer}.ndt-sort-indicator{font-size:.82rem;color:#8a98c2;min-width:16px;text-align:center}.ndt-sort-indicator.active{color:var(--ndt-primary)}.ndt-table tbody tr:hover{background:#f5f8ff}.ndt-selected{background:#ebf1ff}.ndt-actions-cell{text-align:center;position:relative}.ndt-action-icons{display:inline-flex;align-items:center;justify-content:center;gap:.35rem}.ndt-dropdown{position:relative;display:inline-block}.ndt-export-btn{display:inline-flex;align-items:center;gap:.42rem}.ndt-chevron{font-size:.72rem;margin-left:.12rem}.ndt-actions-btn{border:1px solid #d2dcfb;background:#f7f9ff;color:#33446e;border-radius:10px;width:34px;height:30px;padding:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.ndt-actions-btn:hover{border-color:var(--ndt-primary);color:var(--ndt-primary);background:#eef3ff}.ndt-dots{font-size:1rem;line-height:1}.ndt-action-fallback{font-size:.72rem;font-weight:700;line-height:1}.ndt-actions-btn.ndt-danger{color:#dc3545;border-color:#f1c2c7;background:#fff5f6}.ndt-actions-btn.ndt-danger:hover{color:#bb2d3b;border-color:#dc3545;background:#ffe6e9}.ndt-dropdown-menu{position:absolute;left:0;top:calc(100% + .35rem);list-style:none;margin:0;padding:.35rem 0;min-width:120px;border:1px solid #dbe4ff;border-radius:12px;background:#fff;box-shadow:0 12px 24px #2d489124;z-index:20}.ndt-dropdown-item{width:100%;border:0;background:#fff;color:#33446e;display:flex;align-items:center;gap:.45rem;text-align:left;padding:.42rem .72rem;font-size:.84rem;cursor:pointer}.ndt-dropdown-item i{font-size:.9rem;width:14px}.ndt-dropdown-item:hover{background:#f5f8ff;color:var(--ndt-primary)}.ndt-dropdown-item.ndt-danger{color:#dc3545}.ndt-dropdown-item.ndt-danger:hover{background:#fff1f3}.ndt-empty{text-align:center;color:var(--ndt-muted)}.ndt-footer{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap;color:#52628a;font-size:.88rem}.ndt-pagination{display:flex;list-style:none;margin:0;padding:0;align-items:center;gap:.35rem}.ndt-pagination li{display:inline-flex}.ndt-page-link{border:1px solid #d5def8;background:#fff;color:var(--ndt-primary);border-radius:8px;min-width:34px;height:30px;padding:0 .6rem;font-size:.82rem;display:inline-flex;align-items:center;justify-content:center}.ndt-page-link:hover{border-color:var(--ndt-primary);background:#4f46e512}.ndt-pagination li.active .ndt-page-link{background:var(--ndt-primary);border-color:var(--ndt-primary);color:#fff}.ndt-pagination li.disabled .ndt-page-link{opacity:.55;cursor:not-allowed}@media(max-width:900px){.ndt-toolbar,.ndt-footer{flex-direction:column;align-items:flex-start}.ndt-toolbar input{min-width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
773
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: DynamicDatatableComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
774
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: DynamicDatatableComponent, isStandalone: true, selector: "lib-dynamic-datatable", inputs: { config: "config", columns: "columns", data: "data" }, outputs: { actionSelected: "actionSelected", selectionChange: "selectionChange", sortChange: "sortChange", pageChange: "pageChange", exportTriggered: "exportTriggered" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"ndt-card\" (click)=\"closeMenus()\">\r\n <div class=\"ndt-header\">\r\n <h3 class=\"ndt-title\" [attr.data-tooltip]=\"mergedConfig.title\">{{ mergedConfig.title }}</h3>\r\n </div>\r\n\r\n <div class=\"ndt-toolbar\">\r\n <div class=\"ndt-left-tools\">\r\n <ng-container *ngIf=\"isFeatureOn('export')\">\r\n <div class=\"ndt-dropdown\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"ndt-btn ndt-export-btn\" type=\"button\" data-tooltip=\"Export data\" data-tooltip-position=\"bottom\" (click)=\"toggleExportMenu($event)\">\r\n <i class=\"bi bi-download\"></i>\r\n <span>Export</span>\r\n <i class=\"bi bi-chevron-down ndt-chevron\"></i>\r\n </button>\r\n\r\n <ul class=\"ndt-dropdown-menu\" *ngIf=\"isExportMenuOpen\">\r\n <li *ngIf=\"isExportFormatEnabled('csv')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" data-tooltip=\"Download CSV\" data-tooltip-position=\"right\" (click)=\"exportCSV()\">\r\n <i class=\"bi bi-filetype-csv\"></i>\r\n <span>CSV</span>\r\n </button>\r\n </li>\r\n <li *ngIf=\"isExportFormatEnabled('excel')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" data-tooltip=\"Download Excel\" data-tooltip-position=\"right\" (click)=\"exportExcel()\">\r\n <i class=\"bi bi-file-earmark-spreadsheet\"></i>\r\n <span>Excel (.xls)</span>\r\n </button>\r\n </li>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n\r\n <label class=\"ndt-inline-label\" *ngIf=\"isFeatureOn('rowsPerPage') && isFeatureOn('pagination')\">\r\n Rows per page:\r\n <select data-tooltip=\"Rows per page\" [value]=\"rowsPerPage\" (change)=\"onRowsPerPageChange($event)\">\r\n <option *ngFor=\"let option of mergedConfig.rowsPerPageOptions || []\" [value]=\"option\" [attr.data-tooltip]=\"'Show ' + option + ' rows per page'\">{{ option }}</option>\r\n </select>\r\n </label>\r\n </div>\r\n\r\n <div class=\"ndt-right-tools\" *ngIf=\"isFeatureOn('searching')\">\r\n <input\r\n type=\"search\"\r\n placeholder=\"Search records\"\r\n data-tooltip=\"Search records\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearchInput($event)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"ndt-table-wrap\">\r\n <table class=\"ndt-table\">\r\n <colgroup>\r\n <col *ngIf=\"isFeatureOn('checkboxSelection')\" style=\"width: 44px\" />\r\n <col *ngFor=\"let column of mergedColumns\" [style.width]=\"toColumnWidth(column.width)\" />\r\n <col *ngIf=\"isFeatureOn('actions')\" style=\"width: 78px\" />\r\n </colgroup>\r\n\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n data-tooltip=\"Select all rows on current page\"\r\n [checked]=\"isCurrentPageFullySelected()\"\r\n (change)=\"toggleSelectAllCurrentPage($event)\"\r\n />\r\n </th>\r\n <th\r\n *ngFor=\"let column of mergedColumns\"\r\n [class.ndt-sortable]=\"isFeatureOn('sorting') && !!column.sortable\"\r\n [attr.data-tooltip]=\"getColumnTooltip(column)\"\r\n data-tooltip-position=\"top\"\r\n (click)=\"toggleSort(column)\"\r\n >\r\n <span class=\"ndt-th-content\">\r\n <span class=\"ndt-th-label\">{{ column.label }}</span>\r\n <i\r\n *ngIf=\"isFeatureOn('sorting') && column.sortable\"\r\n [ngClass]=\"[\r\n 'ndt-sort-indicator',\r\n getSortIconClass(column.key.toString()),\r\n isSortColumn(column.key.toString()) ? 'active' : ''\r\n ]\"\r\n [attr.data-tooltip]=\"getColumnTooltip(column)\"\r\n data-tooltip-position=\"top\"\r\n ></i>\r\n </span>\r\n </th>\r\n <th *ngIf=\"isFeatureOn('actions')\" data-tooltip=\"Available row actions\" data-tooltip-position=\"top\">Actions</th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr *ngIf=\"!pagedRows.length\">\r\n <td [attr.colspan]=\"getColumnCount()\" class=\"ndt-empty\" data-tooltip=\"No records found\">No records found.</td>\r\n </tr>\r\n\r\n <tr *ngFor=\"let row of pagedRows\" [class.ndt-selected]=\"isRowSelected(row.id)\">\r\n <td *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [attr.data-tooltip]=\"'Select row ' + row.id\"\r\n [checked]=\"isRowSelected(row.id)\"\r\n (change)=\"toggleRowSelection(row, $event)\"\r\n />\r\n </td>\r\n\r\n <td\r\n *ngFor=\"let column of mergedColumns\"\r\n [attr.data-tooltip]=\"getCellTooltip(row.data, column)\"\r\n data-tooltip-position=\"bottom\"\r\n [innerHTML]=\"getRenderedCell(row.data, column)\">\r\n </td>\r\n\r\n <td *ngIf=\"isFeatureOn('actions')\" class=\"ndt-actions-cell\">\r\n <div class=\"ndt-action-icons\" (click)=\"$event.stopPropagation()\">\r\n <button\r\n *ngFor=\"let action of mergedConfig.actions || []; let i = index\"\r\n type=\"button\"\r\n class=\"ndt-actions-btn\"\r\n [class.ndt-danger]=\"!!action.danger\"\r\n [attr.data-tooltip]=\"action.label\"\r\n data-tooltip-position=\"top\"\r\n [attr.aria-label]=\"action.label\"\r\n (click)=\"onActionItemClick(i, row, $event)\"\r\n >\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\"></i>\r\n <span *ngIf=\"!action.icon\" class=\"ndt-action-fallback\">{{ action.label.charAt(0) }}</span>\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div class=\"ndt-footer\">\r\n <div [attr.data-tooltip]=\"selectedRows.size + ' rows selected'\">\r\n {{ selectedRows.size }} selected\r\n </div>\r\n\r\n <div [attr.data-tooltip]=\"'Showing ' + getStartEntry() + ' to ' + getEndEntry() + ' of ' + filteredRows.length + ' entries'\">\r\n Showing {{ getStartEntry() }} to {{ getEndEntry() }} of {{ filteredRows.length }} entries\r\n </div>\r\n\r\n <ul class=\"ndt-pagination\" *ngIf=\"isFeatureOn('pagination') && totalPages > 1\">\r\n <li [class.disabled]=\"currentPage <= 1\">\r\n <button type=\"button\" class=\"ndt-page-link\" data-tooltip=\"Go to previous page\" data-tooltip-position=\"top\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage <= 1\">Prev</button>\r\n </li>\r\n <li *ngFor=\"let page of getPaginationPages()\" [class.active]=\"page === currentPage\">\r\n <button type=\"button\" class=\"ndt-page-link\" [attr.data-tooltip]=\"'Go to page ' + page\" data-tooltip-position=\"top\" (click)=\"goToPage(page)\">{{ page }}</button>\r\n </li>\r\n <li [class.disabled]=\"currentPage >= totalPages\">\r\n <button type=\"button\" class=\"ndt-page-link\" data-tooltip=\"Go to next page\" data-tooltip-position=\"top\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage >= totalPages\">Next</button>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{--ndt-tooltip-bg: #111a32;--ndt-tooltip-color: #ffffff;--ndt-tooltip-shadow: 0 12px 24px rgba(16, 24, 40, .28);--ndt-tooltip-radius: 10px;--ndt-tooltip-padding-y: .4rem;--ndt-tooltip-padding-x: .55rem;--ndt-tooltip-font-size: .78rem;--ndt-tooltip-arrow-size: 7px;--ndt-tooltip-z-index: 1100}[data-tooltip]{cursor:help}.ndt-tooltip{position:fixed;top:0;left:0;z-index:var(--ndt-tooltip-z-index);max-width:min(260px,calc(100vw - 16px));border-radius:var(--ndt-tooltip-radius);background:var(--ndt-tooltip-bg);color:var(--ndt-tooltip-color);box-shadow:var(--ndt-tooltip-shadow);font-size:var(--ndt-tooltip-font-size);line-height:1.3;padding:var(--ndt-tooltip-padding-y) var(--ndt-tooltip-padding-x);opacity:0;transform:translate3d(0,4px,0) scale(.98);transition:opacity .14s ease,transform .18s ease;pointer-events:auto}.ndt-tooltip.ndt-tooltip--show{opacity:1;transform:translateZ(0) scale(1)}.ndt-tooltip__content{display:inline-flex;align-items:center;gap:.42rem;max-width:100%}.ndt-tooltip__icon{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;font-size:.78rem;flex:0 0 auto}.ndt-tooltip__text{word-break:break-word}.ndt-tooltip:before{content:\"\";position:absolute;width:0;height:0;border-style:solid}.ndt-tooltip[data-placement=bottom]:before{top:calc(-1 * var(--ndt-tooltip-arrow-size));left:calc(50% - var(--ndt-tooltip-arrow-size));border-width:0 var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size);border-color:transparent transparent var(--ndt-tooltip-bg) transparent}.ndt-tooltip[data-placement=top]:before{bottom:calc(-1 * var(--ndt-tooltip-arrow-size));left:calc(50% - var(--ndt-tooltip-arrow-size));border-width:var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) 0 var(--ndt-tooltip-arrow-size);border-color:var(--ndt-tooltip-bg) transparent transparent transparent}.ndt-tooltip[data-placement=left]:before{top:calc(50% - var(--ndt-tooltip-arrow-size));right:calc(-1 * var(--ndt-tooltip-arrow-size));border-width:var(--ndt-tooltip-arrow-size) 0 var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size);border-color:transparent transparent transparent var(--ndt-tooltip-bg)}.ndt-tooltip[data-placement=right]:before{top:calc(50% - var(--ndt-tooltip-arrow-size));left:calc(-1 * var(--ndt-tooltip-arrow-size));border-width:var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) 0;border-color:transparent var(--ndt-tooltip-bg) transparent transparent}.ndt-tooltip[data-no-arrow=true]:before{display:none}@media(max-width:576px){.ndt-tooltip{font-size:.75rem;max-width:min(220px,calc(100vw - 12px))}}:host{display:block;--ndt-primary: #4f46e5;--ndt-primary-dark: #4338ca;--ndt-primary-soft: #eef2ff;--ndt-border: #dbe4ff;--ndt-text: #1f2a44;--ndt-muted: #6d7895}.ndt-card{border:1px solid var(--ndt-border);border-radius:20px;padding:10px;background:#ffffffe6;backdrop-filter:blur(3px);box-shadow:0 20px 45px #2d489124;overflow:hidden;color:var(--ndt-text);font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ndt-header,.ndt-toolbar,.ndt-footer{padding:1.05rem 1.35rem}.ndt-header{background:linear-gradient(180deg,#fff,#fafcff);border-bottom:1px solid #eaf0ff}.ndt-title{margin:0;font-size:1.2rem;color:#1b2550}.ndt-toolbar{display:flex;justify-content:space-between;gap:.75rem;flex-wrap:wrap;align-items:center}.ndt-left-tools,.ndt-right-tools{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}.ndt-btn,.ndt-toolbar select,.ndt-toolbar input{border:1px solid #d5def8;background:#fff;color:#445381;border-radius:10px;padding:.36rem .62rem;font-size:.85rem}.ndt-btn:hover{border-color:var(--ndt-primary);background:#4f46e512;color:var(--ndt-primary)}.ndt-toolbar input{min-width:260px}.ndt-toolbar input:focus,.ndt-toolbar select:focus{outline:none;border-color:#4f46e58c;box-shadow:0 0 0 .2rem #4f46e51f}.ndt-inline-label{display:inline-flex;align-items:center;gap:.4rem;color:var(--ndt-muted);font-size:.85rem}.ndt-table-wrap{margin:0 1.35rem;overflow-x:auto;overflow-y:visible;border:1px solid #e5ecff;border-radius:14px;background:#fff}.ndt-table{width:100%;min-width:920px;border-collapse:collapse;table-layout:fixed}.ndt-table th,.ndt-table td{padding:.8rem .72rem;text-align:left;border-bottom:1px solid #edf2ff;vertical-align:middle}.ndt-table th{color:#4a577f;font-size:.85rem;text-transform:uppercase;letter-spacing:.03em;background:#f7faff;border-bottom:1px solid #e6edff}.ndt-th-content{display:flex;align-items:center;justify-content:space-between;gap:.4rem}.ndt-th-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ndt-sortable{cursor:pointer}.ndt-sort-indicator{font-size:.82rem;color:#8a98c2;min-width:16px;text-align:center}.ndt-sort-indicator.active{color:var(--ndt-primary)}.ndt-table tbody tr:hover{background:#f5f8ff}.ndt-selected{background:#ebf1ff}.ndt-actions-cell{text-align:center;position:relative}.ndt-action-icons{display:inline-flex;align-items:center;justify-content:center;gap:.35rem}.ndt-dropdown{position:relative;display:inline-block}.ndt-export-btn{display:inline-flex;align-items:center;gap:.42rem}.ndt-chevron{font-size:.72rem;margin-left:.12rem}.ndt-actions-btn{border:1px solid #d2dcfb;background:#f7f9ff;color:#33446e;border-radius:10px;width:34px;height:30px;padding:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.ndt-actions-btn:hover{border-color:var(--ndt-primary);color:var(--ndt-primary);background:#eef3ff}.ndt-dots{font-size:1rem;line-height:1}.ndt-action-fallback{font-size:.72rem;font-weight:700;line-height:1}.ndt-actions-btn.ndt-danger{color:#dc3545;border-color:#f1c2c7;background:#fff5f6}.ndt-actions-btn.ndt-danger:hover{color:#bb2d3b;border-color:#dc3545;background:#ffe6e9}.ndt-dropdown-menu{position:absolute;left:0;top:calc(100% + .35rem);list-style:none;margin:0;padding:.35rem 0;min-width:120px;border:1px solid #dbe4ff;border-radius:12px;background:#fff;box-shadow:0 12px 24px #2d489124;z-index:20}.ndt-dropdown-item{width:100%;border:0;background:#fff;color:#33446e;display:flex;align-items:center;gap:.45rem;text-align:left;padding:.42rem .72rem;font-size:.84rem;cursor:pointer}.ndt-dropdown-item i{font-size:.9rem;width:14px}.ndt-dropdown-item:hover{background:#f5f8ff;color:var(--ndt-primary)}.ndt-dropdown-item.ndt-danger{color:#dc3545}.ndt-dropdown-item.ndt-danger:hover{background:#fff1f3}.ndt-empty{text-align:center;color:var(--ndt-muted)}.ndt-footer{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap;color:#52628a;font-size:.88rem}.ndt-pagination{display:flex;list-style:none;margin:0;padding:0;align-items:center;gap:.35rem}.ndt-pagination li{display:inline-flex}.ndt-page-link{border:1px solid #d5def8;background:#fff;color:var(--ndt-primary);border-radius:8px;min-width:34px;height:30px;padding:0 .6rem;font-size:.82rem;display:inline-flex;align-items:center;justify-content:center}.ndt-page-link:hover{border-color:var(--ndt-primary);background:#4f46e512}.ndt-pagination li.active .ndt-page-link{background:var(--ndt-primary);border-color:var(--ndt-primary);color:#fff}.ndt-pagination li.disabled .ndt-page-link{opacity:.55;cursor:not-allowed}@media(max-width:900px){.ndt-toolbar,.ndt-footer{flex-direction:column;align-items:flex-start}.ndt-toolbar input{min-width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
441
775
  }
442
776
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: DynamicDatatableComponent, decorators: [{
443
777
  type: Component,
444
- args: [{ selector: 'lib-dynamic-datatable', standalone: true, imports: [CommonModule], template: "<div class=\"ndt-card\" (click)=\"closeMenus()\">\r\n <div class=\"ndt-header\">\r\n <h3 class=\"ndt-title\">{{ mergedConfig.title }}</h3>\r\n </div>\r\n\r\n <div class=\"ndt-toolbar\">\r\n <div class=\"ndt-left-tools\">\r\n <ng-container *ngIf=\"isFeatureOn('export')\">\r\n <div class=\"ndt-dropdown\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"ndt-btn ndt-export-btn\" type=\"button\" (click)=\"toggleExportMenu($event)\">\r\n <i class=\"bi bi-download\"></i>\r\n <span>Export</span>\r\n <i class=\"bi bi-chevron-down ndt-chevron\"></i>\r\n </button>\r\n\r\n <ul class=\"ndt-dropdown-menu\" *ngIf=\"isExportMenuOpen\">\r\n <li *ngIf=\"isExportFormatEnabled('csv')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" (click)=\"exportCSV()\">\r\n <i class=\"bi bi-filetype-csv\"></i>\r\n <span>CSV</span>\r\n </button>\r\n </li>\r\n <li *ngIf=\"isExportFormatEnabled('excel')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" (click)=\"exportExcel()\">\r\n <i class=\"bi bi-file-earmark-spreadsheet\"></i>\r\n <span>Excel (.xls)</span>\r\n </button>\r\n </li>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n\r\n <label class=\"ndt-inline-label\" *ngIf=\"isFeatureOn('rowsPerPage') && isFeatureOn('pagination')\">\r\n Rows per page:\r\n <select [value]=\"rowsPerPage\" (change)=\"onRowsPerPageChange($event)\">\r\n <option *ngFor=\"let option of mergedConfig.rowsPerPageOptions || []\" [value]=\"option\">{{ option }}</option>\r\n </select>\r\n </label>\r\n </div>\r\n\r\n <div class=\"ndt-right-tools\" *ngIf=\"isFeatureOn('searching')\">\r\n <input\r\n type=\"search\"\r\n placeholder=\"Search records\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearchInput($event)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"ndt-table-wrap\">\r\n <table class=\"ndt-table\">\r\n <colgroup>\r\n <col *ngIf=\"isFeatureOn('checkboxSelection')\" style=\"width: 44px\" />\r\n <col *ngFor=\"let column of mergedColumns\" [style.width]=\"toColumnWidth(column.width)\" />\r\n <col *ngIf=\"isFeatureOn('actions')\" style=\"width: 78px\" />\r\n </colgroup>\r\n\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"isCurrentPageFullySelected()\"\r\n (change)=\"toggleSelectAllCurrentPage($event)\"\r\n />\r\n </th>\r\n <th\r\n *ngFor=\"let column of mergedColumns\"\r\n [class.ndt-sortable]=\"isFeatureOn('sorting') && !!column.sortable\"\r\n (click)=\"toggleSort(column)\"\r\n >\r\n <span class=\"ndt-th-content\">\r\n <span class=\"ndt-th-label\">{{ column.label }}</span>\r\n <i\r\n *ngIf=\"isFeatureOn('sorting') && column.sortable\"\r\n [ngClass]=\"[\r\n 'ndt-sort-indicator',\r\n getSortIconClass(column.key.toString()),\r\n isSortColumn(column.key.toString()) ? 'active' : ''\r\n ]\"\r\n ></i>\r\n </span>\r\n </th>\r\n <th *ngIf=\"isFeatureOn('actions')\">Actions</th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr *ngIf=\"!pagedRows.length\">\r\n <td [attr.colspan]=\"getColumnCount()\" class=\"ndt-empty\">No records found.</td>\r\n </tr>\r\n\r\n <tr *ngFor=\"let row of pagedRows\" [class.ndt-selected]=\"isRowSelected(row.id)\">\r\n <td *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"isRowSelected(row.id)\"\r\n (change)=\"toggleRowSelection(row, $event)\"\r\n />\r\n </td>\r\n\r\n <td *ngFor=\"let column of mergedColumns\" [innerHTML]=\"getRenderedCell(row.data, column)\"></td>\r\n\r\n <td *ngIf=\"isFeatureOn('actions')\" class=\"ndt-actions-cell\">\r\n <div class=\"ndt-action-icons\" (click)=\"$event.stopPropagation()\">\r\n <button\r\n *ngFor=\"let action of mergedConfig.actions || []; let i = index\"\r\n type=\"button\"\r\n class=\"ndt-actions-btn\"\r\n [class.ndt-danger]=\"!!action.danger\"\r\n [attr.title]=\"action.label\"\r\n [attr.aria-label]=\"action.label\"\r\n (click)=\"onActionItemClick(i, row, $event)\"\r\n >\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\"></i>\r\n <span *ngIf=\"!action.icon\" class=\"ndt-action-fallback\">{{ action.label.charAt(0) }}</span>\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div class=\"ndt-footer\">\r\n <div>\r\n {{ selectedRows.size }} selected\r\n </div>\r\n\r\n <div>\r\n Showing {{ getStartEntry() }} to {{ getEndEntry() }} of {{ filteredRows.length }} entries\r\n </div>\r\n\r\n <ul class=\"ndt-pagination\" *ngIf=\"isFeatureOn('pagination') && totalPages > 1\">\r\n <li [class.disabled]=\"currentPage <= 1\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage <= 1\">Prev</button>\r\n </li>\r\n <li *ngFor=\"let page of getPaginationPages()\" [class.active]=\"page === currentPage\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(page)\">{{ page }}</button>\r\n </li>\r\n <li [class.disabled]=\"currentPage >= totalPages\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage >= totalPages\">Next</button>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;--ndt-primary: #4f46e5;--ndt-primary-dark: #4338ca;--ndt-primary-soft: #eef2ff;--ndt-border: #dbe4ff;--ndt-text: #1f2a44;--ndt-muted: #6d7895}.ndt-card{border:1px solid var(--ndt-border);border-radius:20px;padding:10px;background:#ffffffe6;backdrop-filter:blur(3px);box-shadow:0 20px 45px #2d489124;overflow:hidden;color:var(--ndt-text);font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ndt-header,.ndt-toolbar,.ndt-footer{padding:1.05rem 1.35rem}.ndt-header{background:linear-gradient(180deg,#fff,#fafcff);border-bottom:1px solid #eaf0ff}.ndt-title{margin:0;font-size:1.2rem;color:#1b2550}.ndt-toolbar{display:flex;justify-content:space-between;gap:.75rem;flex-wrap:wrap;align-items:center}.ndt-left-tools,.ndt-right-tools{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}.ndt-btn,.ndt-toolbar select,.ndt-toolbar input{border:1px solid #d5def8;background:#fff;color:#445381;border-radius:10px;padding:.36rem .62rem;font-size:.85rem}.ndt-btn:hover{border-color:var(--ndt-primary);background:#4f46e512;color:var(--ndt-primary)}.ndt-toolbar input{min-width:260px}.ndt-toolbar input:focus,.ndt-toolbar select:focus{outline:none;border-color:#4f46e58c;box-shadow:0 0 0 .2rem #4f46e51f}.ndt-inline-label{display:inline-flex;align-items:center;gap:.4rem;color:var(--ndt-muted);font-size:.85rem}.ndt-table-wrap{margin:0 1.35rem;overflow-x:auto;overflow-y:visible;border:1px solid #e5ecff;border-radius:14px;background:#fff}.ndt-table{width:100%;min-width:920px;border-collapse:collapse;table-layout:fixed}.ndt-table th,.ndt-table td{padding:.8rem .72rem;text-align:left;border-bottom:1px solid #edf2ff;vertical-align:middle}.ndt-table th{color:#4a577f;font-size:.85rem;text-transform:uppercase;letter-spacing:.03em;background:#f7faff;border-bottom:1px solid #e6edff}.ndt-th-content{display:flex;align-items:center;justify-content:space-between;gap:.4rem}.ndt-th-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ndt-sortable{cursor:pointer}.ndt-sort-indicator{font-size:.82rem;color:#8a98c2;min-width:16px;text-align:center}.ndt-sort-indicator.active{color:var(--ndt-primary)}.ndt-table tbody tr:hover{background:#f5f8ff}.ndt-selected{background:#ebf1ff}.ndt-actions-cell{text-align:center;position:relative}.ndt-action-icons{display:inline-flex;align-items:center;justify-content:center;gap:.35rem}.ndt-dropdown{position:relative;display:inline-block}.ndt-export-btn{display:inline-flex;align-items:center;gap:.42rem}.ndt-chevron{font-size:.72rem;margin-left:.12rem}.ndt-actions-btn{border:1px solid #d2dcfb;background:#f7f9ff;color:#33446e;border-radius:10px;width:34px;height:30px;padding:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.ndt-actions-btn:hover{border-color:var(--ndt-primary);color:var(--ndt-primary);background:#eef3ff}.ndt-dots{font-size:1rem;line-height:1}.ndt-action-fallback{font-size:.72rem;font-weight:700;line-height:1}.ndt-actions-btn.ndt-danger{color:#dc3545;border-color:#f1c2c7;background:#fff5f6}.ndt-actions-btn.ndt-danger:hover{color:#bb2d3b;border-color:#dc3545;background:#ffe6e9}.ndt-dropdown-menu{position:absolute;left:0;top:calc(100% + .35rem);list-style:none;margin:0;padding:.35rem 0;min-width:120px;border:1px solid #dbe4ff;border-radius:12px;background:#fff;box-shadow:0 12px 24px #2d489124;z-index:20}.ndt-dropdown-item{width:100%;border:0;background:#fff;color:#33446e;display:flex;align-items:center;gap:.45rem;text-align:left;padding:.42rem .72rem;font-size:.84rem;cursor:pointer}.ndt-dropdown-item i{font-size:.9rem;width:14px}.ndt-dropdown-item:hover{background:#f5f8ff;color:var(--ndt-primary)}.ndt-dropdown-item.ndt-danger{color:#dc3545}.ndt-dropdown-item.ndt-danger:hover{background:#fff1f3}.ndt-empty{text-align:center;color:var(--ndt-muted)}.ndt-footer{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap;color:#52628a;font-size:.88rem}.ndt-pagination{display:flex;list-style:none;margin:0;padding:0;align-items:center;gap:.35rem}.ndt-pagination li{display:inline-flex}.ndt-page-link{border:1px solid #d5def8;background:#fff;color:var(--ndt-primary);border-radius:8px;min-width:34px;height:30px;padding:0 .6rem;font-size:.82rem;display:inline-flex;align-items:center;justify-content:center}.ndt-page-link:hover{border-color:var(--ndt-primary);background:#4f46e512}.ndt-pagination li.active .ndt-page-link{background:var(--ndt-primary);border-color:var(--ndt-primary);color:#fff}.ndt-pagination li.disabled .ndt-page-link{opacity:.55;cursor:not-allowed}@media(max-width:900px){.ndt-toolbar,.ndt-footer{flex-direction:column;align-items:flex-start}.ndt-toolbar input{min-width:100%}}\n"] }]
445
- }], propDecorators: { config: [{
778
+ args: [{ selector: 'lib-dynamic-datatable', standalone: true, imports: [CommonModule], template: "<div class=\"ndt-card\" (click)=\"closeMenus()\">\r\n <div class=\"ndt-header\">\r\n <h3 class=\"ndt-title\" [attr.data-tooltip]=\"mergedConfig.title\">{{ mergedConfig.title }}</h3>\r\n </div>\r\n\r\n <div class=\"ndt-toolbar\">\r\n <div class=\"ndt-left-tools\">\r\n <ng-container *ngIf=\"isFeatureOn('export')\">\r\n <div class=\"ndt-dropdown\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"ndt-btn ndt-export-btn\" type=\"button\" data-tooltip=\"Export data\" data-tooltip-position=\"bottom\" (click)=\"toggleExportMenu($event)\">\r\n <i class=\"bi bi-download\"></i>\r\n <span>Export</span>\r\n <i class=\"bi bi-chevron-down ndt-chevron\"></i>\r\n </button>\r\n\r\n <ul class=\"ndt-dropdown-menu\" *ngIf=\"isExportMenuOpen\">\r\n <li *ngIf=\"isExportFormatEnabled('csv')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" data-tooltip=\"Download CSV\" data-tooltip-position=\"right\" (click)=\"exportCSV()\">\r\n <i class=\"bi bi-filetype-csv\"></i>\r\n <span>CSV</span>\r\n </button>\r\n </li>\r\n <li *ngIf=\"isExportFormatEnabled('excel')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" data-tooltip=\"Download Excel\" data-tooltip-position=\"right\" (click)=\"exportExcel()\">\r\n <i class=\"bi bi-file-earmark-spreadsheet\"></i>\r\n <span>Excel (.xls)</span>\r\n </button>\r\n </li>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n\r\n <label class=\"ndt-inline-label\" *ngIf=\"isFeatureOn('rowsPerPage') && isFeatureOn('pagination')\">\r\n Rows per page:\r\n <select data-tooltip=\"Rows per page\" [value]=\"rowsPerPage\" (change)=\"onRowsPerPageChange($event)\">\r\n <option *ngFor=\"let option of mergedConfig.rowsPerPageOptions || []\" [value]=\"option\" [attr.data-tooltip]=\"'Show ' + option + ' rows per page'\">{{ option }}</option>\r\n </select>\r\n </label>\r\n </div>\r\n\r\n <div class=\"ndt-right-tools\" *ngIf=\"isFeatureOn('searching')\">\r\n <input\r\n type=\"search\"\r\n placeholder=\"Search records\"\r\n data-tooltip=\"Search records\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearchInput($event)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"ndt-table-wrap\">\r\n <table class=\"ndt-table\">\r\n <colgroup>\r\n <col *ngIf=\"isFeatureOn('checkboxSelection')\" style=\"width: 44px\" />\r\n <col *ngFor=\"let column of mergedColumns\" [style.width]=\"toColumnWidth(column.width)\" />\r\n <col *ngIf=\"isFeatureOn('actions')\" style=\"width: 78px\" />\r\n </colgroup>\r\n\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n data-tooltip=\"Select all rows on current page\"\r\n [checked]=\"isCurrentPageFullySelected()\"\r\n (change)=\"toggleSelectAllCurrentPage($event)\"\r\n />\r\n </th>\r\n <th\r\n *ngFor=\"let column of mergedColumns\"\r\n [class.ndt-sortable]=\"isFeatureOn('sorting') && !!column.sortable\"\r\n [attr.data-tooltip]=\"getColumnTooltip(column)\"\r\n data-tooltip-position=\"top\"\r\n (click)=\"toggleSort(column)\"\r\n >\r\n <span class=\"ndt-th-content\">\r\n <span class=\"ndt-th-label\">{{ column.label }}</span>\r\n <i\r\n *ngIf=\"isFeatureOn('sorting') && column.sortable\"\r\n [ngClass]=\"[\r\n 'ndt-sort-indicator',\r\n getSortIconClass(column.key.toString()),\r\n isSortColumn(column.key.toString()) ? 'active' : ''\r\n ]\"\r\n [attr.data-tooltip]=\"getColumnTooltip(column)\"\r\n data-tooltip-position=\"top\"\r\n ></i>\r\n </span>\r\n </th>\r\n <th *ngIf=\"isFeatureOn('actions')\" data-tooltip=\"Available row actions\" data-tooltip-position=\"top\">Actions</th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr *ngIf=\"!pagedRows.length\">\r\n <td [attr.colspan]=\"getColumnCount()\" class=\"ndt-empty\" data-tooltip=\"No records found\">No records found.</td>\r\n </tr>\r\n\r\n <tr *ngFor=\"let row of pagedRows\" [class.ndt-selected]=\"isRowSelected(row.id)\">\r\n <td *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [attr.data-tooltip]=\"'Select row ' + row.id\"\r\n [checked]=\"isRowSelected(row.id)\"\r\n (change)=\"toggleRowSelection(row, $event)\"\r\n />\r\n </td>\r\n\r\n <td\r\n *ngFor=\"let column of mergedColumns\"\r\n [attr.data-tooltip]=\"getCellTooltip(row.data, column)\"\r\n data-tooltip-position=\"bottom\"\r\n [innerHTML]=\"getRenderedCell(row.data, column)\">\r\n </td>\r\n\r\n <td *ngIf=\"isFeatureOn('actions')\" class=\"ndt-actions-cell\">\r\n <div class=\"ndt-action-icons\" (click)=\"$event.stopPropagation()\">\r\n <button\r\n *ngFor=\"let action of mergedConfig.actions || []; let i = index\"\r\n type=\"button\"\r\n class=\"ndt-actions-btn\"\r\n [class.ndt-danger]=\"!!action.danger\"\r\n [attr.data-tooltip]=\"action.label\"\r\n data-tooltip-position=\"top\"\r\n [attr.aria-label]=\"action.label\"\r\n (click)=\"onActionItemClick(i, row, $event)\"\r\n >\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\"></i>\r\n <span *ngIf=\"!action.icon\" class=\"ndt-action-fallback\">{{ action.label.charAt(0) }}</span>\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div class=\"ndt-footer\">\r\n <div [attr.data-tooltip]=\"selectedRows.size + ' rows selected'\">\r\n {{ selectedRows.size }} selected\r\n </div>\r\n\r\n <div [attr.data-tooltip]=\"'Showing ' + getStartEntry() + ' to ' + getEndEntry() + ' of ' + filteredRows.length + ' entries'\">\r\n Showing {{ getStartEntry() }} to {{ getEndEntry() }} of {{ filteredRows.length }} entries\r\n </div>\r\n\r\n <ul class=\"ndt-pagination\" *ngIf=\"isFeatureOn('pagination') && totalPages > 1\">\r\n <li [class.disabled]=\"currentPage <= 1\">\r\n <button type=\"button\" class=\"ndt-page-link\" data-tooltip=\"Go to previous page\" data-tooltip-position=\"top\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage <= 1\">Prev</button>\r\n </li>\r\n <li *ngFor=\"let page of getPaginationPages()\" [class.active]=\"page === currentPage\">\r\n <button type=\"button\" class=\"ndt-page-link\" [attr.data-tooltip]=\"'Go to page ' + page\" data-tooltip-position=\"top\" (click)=\"goToPage(page)\">{{ page }}</button>\r\n </li>\r\n <li [class.disabled]=\"currentPage >= totalPages\">\r\n <button type=\"button\" class=\"ndt-page-link\" data-tooltip=\"Go to next page\" data-tooltip-position=\"top\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage >= totalPages\">Next</button>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{--ndt-tooltip-bg: #111a32;--ndt-tooltip-color: #ffffff;--ndt-tooltip-shadow: 0 12px 24px rgba(16, 24, 40, .28);--ndt-tooltip-radius: 10px;--ndt-tooltip-padding-y: .4rem;--ndt-tooltip-padding-x: .55rem;--ndt-tooltip-font-size: .78rem;--ndt-tooltip-arrow-size: 7px;--ndt-tooltip-z-index: 1100}[data-tooltip]{cursor:help}.ndt-tooltip{position:fixed;top:0;left:0;z-index:var(--ndt-tooltip-z-index);max-width:min(260px,calc(100vw - 16px));border-radius:var(--ndt-tooltip-radius);background:var(--ndt-tooltip-bg);color:var(--ndt-tooltip-color);box-shadow:var(--ndt-tooltip-shadow);font-size:var(--ndt-tooltip-font-size);line-height:1.3;padding:var(--ndt-tooltip-padding-y) var(--ndt-tooltip-padding-x);opacity:0;transform:translate3d(0,4px,0) scale(.98);transition:opacity .14s ease,transform .18s ease;pointer-events:auto}.ndt-tooltip.ndt-tooltip--show{opacity:1;transform:translateZ(0) scale(1)}.ndt-tooltip__content{display:inline-flex;align-items:center;gap:.42rem;max-width:100%}.ndt-tooltip__icon{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;font-size:.78rem;flex:0 0 auto}.ndt-tooltip__text{word-break:break-word}.ndt-tooltip:before{content:\"\";position:absolute;width:0;height:0;border-style:solid}.ndt-tooltip[data-placement=bottom]:before{top:calc(-1 * var(--ndt-tooltip-arrow-size));left:calc(50% - var(--ndt-tooltip-arrow-size));border-width:0 var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size);border-color:transparent transparent var(--ndt-tooltip-bg) transparent}.ndt-tooltip[data-placement=top]:before{bottom:calc(-1 * var(--ndt-tooltip-arrow-size));left:calc(50% - var(--ndt-tooltip-arrow-size));border-width:var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) 0 var(--ndt-tooltip-arrow-size);border-color:var(--ndt-tooltip-bg) transparent transparent transparent}.ndt-tooltip[data-placement=left]:before{top:calc(50% - var(--ndt-tooltip-arrow-size));right:calc(-1 * var(--ndt-tooltip-arrow-size));border-width:var(--ndt-tooltip-arrow-size) 0 var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size);border-color:transparent transparent transparent var(--ndt-tooltip-bg)}.ndt-tooltip[data-placement=right]:before{top:calc(50% - var(--ndt-tooltip-arrow-size));left:calc(-1 * var(--ndt-tooltip-arrow-size));border-width:var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) var(--ndt-tooltip-arrow-size) 0;border-color:transparent var(--ndt-tooltip-bg) transparent transparent}.ndt-tooltip[data-no-arrow=true]:before{display:none}@media(max-width:576px){.ndt-tooltip{font-size:.75rem;max-width:min(220px,calc(100vw - 12px))}}:host{display:block;--ndt-primary: #4f46e5;--ndt-primary-dark: #4338ca;--ndt-primary-soft: #eef2ff;--ndt-border: #dbe4ff;--ndt-text: #1f2a44;--ndt-muted: #6d7895}.ndt-card{border:1px solid var(--ndt-border);border-radius:20px;padding:10px;background:#ffffffe6;backdrop-filter:blur(3px);box-shadow:0 20px 45px #2d489124;overflow:hidden;color:var(--ndt-text);font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif}.ndt-header,.ndt-toolbar,.ndt-footer{padding:1.05rem 1.35rem}.ndt-header{background:linear-gradient(180deg,#fff,#fafcff);border-bottom:1px solid #eaf0ff}.ndt-title{margin:0;font-size:1.2rem;color:#1b2550}.ndt-toolbar{display:flex;justify-content:space-between;gap:.75rem;flex-wrap:wrap;align-items:center}.ndt-left-tools,.ndt-right-tools{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}.ndt-btn,.ndt-toolbar select,.ndt-toolbar input{border:1px solid #d5def8;background:#fff;color:#445381;border-radius:10px;padding:.36rem .62rem;font-size:.85rem}.ndt-btn:hover{border-color:var(--ndt-primary);background:#4f46e512;color:var(--ndt-primary)}.ndt-toolbar input{min-width:260px}.ndt-toolbar input:focus,.ndt-toolbar select:focus{outline:none;border-color:#4f46e58c;box-shadow:0 0 0 .2rem #4f46e51f}.ndt-inline-label{display:inline-flex;align-items:center;gap:.4rem;color:var(--ndt-muted);font-size:.85rem}.ndt-table-wrap{margin:0 1.35rem;overflow-x:auto;overflow-y:visible;border:1px solid #e5ecff;border-radius:14px;background:#fff}.ndt-table{width:100%;min-width:920px;border-collapse:collapse;table-layout:fixed}.ndt-table th,.ndt-table td{padding:.8rem .72rem;text-align:left;border-bottom:1px solid #edf2ff;vertical-align:middle}.ndt-table th{color:#4a577f;font-size:.85rem;text-transform:uppercase;letter-spacing:.03em;background:#f7faff;border-bottom:1px solid #e6edff}.ndt-th-content{display:flex;align-items:center;justify-content:space-between;gap:.4rem}.ndt-th-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ndt-sortable{cursor:pointer}.ndt-sort-indicator{font-size:.82rem;color:#8a98c2;min-width:16px;text-align:center}.ndt-sort-indicator.active{color:var(--ndt-primary)}.ndt-table tbody tr:hover{background:#f5f8ff}.ndt-selected{background:#ebf1ff}.ndt-actions-cell{text-align:center;position:relative}.ndt-action-icons{display:inline-flex;align-items:center;justify-content:center;gap:.35rem}.ndt-dropdown{position:relative;display:inline-block}.ndt-export-btn{display:inline-flex;align-items:center;gap:.42rem}.ndt-chevron{font-size:.72rem;margin-left:.12rem}.ndt-actions-btn{border:1px solid #d2dcfb;background:#f7f9ff;color:#33446e;border-radius:10px;width:34px;height:30px;padding:0;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.ndt-actions-btn:hover{border-color:var(--ndt-primary);color:var(--ndt-primary);background:#eef3ff}.ndt-dots{font-size:1rem;line-height:1}.ndt-action-fallback{font-size:.72rem;font-weight:700;line-height:1}.ndt-actions-btn.ndt-danger{color:#dc3545;border-color:#f1c2c7;background:#fff5f6}.ndt-actions-btn.ndt-danger:hover{color:#bb2d3b;border-color:#dc3545;background:#ffe6e9}.ndt-dropdown-menu{position:absolute;left:0;top:calc(100% + .35rem);list-style:none;margin:0;padding:.35rem 0;min-width:120px;border:1px solid #dbe4ff;border-radius:12px;background:#fff;box-shadow:0 12px 24px #2d489124;z-index:20}.ndt-dropdown-item{width:100%;border:0;background:#fff;color:#33446e;display:flex;align-items:center;gap:.45rem;text-align:left;padding:.42rem .72rem;font-size:.84rem;cursor:pointer}.ndt-dropdown-item i{font-size:.9rem;width:14px}.ndt-dropdown-item:hover{background:#f5f8ff;color:var(--ndt-primary)}.ndt-dropdown-item.ndt-danger{color:#dc3545}.ndt-dropdown-item.ndt-danger:hover{background:#fff1f3}.ndt-empty{text-align:center;color:var(--ndt-muted)}.ndt-footer{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex-wrap:wrap;color:#52628a;font-size:.88rem}.ndt-pagination{display:flex;list-style:none;margin:0;padding:0;align-items:center;gap:.35rem}.ndt-pagination li{display:inline-flex}.ndt-page-link{border:1px solid #d5def8;background:#fff;color:var(--ndt-primary);border-radius:8px;min-width:34px;height:30px;padding:0 .6rem;font-size:.82rem;display:inline-flex;align-items:center;justify-content:center}.ndt-page-link:hover{border-color:var(--ndt-primary);background:#4f46e512}.ndt-pagination li.active .ndt-page-link{background:var(--ndt-primary);border-color:var(--ndt-primary);color:#fff}.ndt-pagination li.disabled .ndt-page-link{opacity:.55;cursor:not-allowed}@media(max-width:900px){.ndt-toolbar,.ndt-footer{flex-direction:column;align-items:flex-start}.ndt-toolbar input{min-width:100%}}\n"] }]
779
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { config: [{
446
780
  type: Input
447
781
  }], columns: [{
448
782
  type: Input
@@ -1 +1 @@
1
- {"version":3,"file":"ng-dynamic-datatable.mjs","sources":["../../../projects/dynamic-datatable/src/lib/dynamic-datatable.component.ts","../../../projects/dynamic-datatable/src/lib/dynamic-datatable.component.html","../../../projects/dynamic-datatable/src/public-api.ts","../../../projects/dynamic-datatable/src/ng-dynamic-datatable.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';\r\nimport {\r\n DataTableAction,\r\n DataTableActionEvent,\r\n DataTableColumn,\r\n DataTableExportEvent,\r\n DynamicDataTableConfig\r\n} from './models';\r\nimport { InternalSortState } from './dynamic-datatable.types';\r\n\r\ntype RowData = Record<string, unknown>;\r\n\r\ninterface InternalRow<T extends RowData = RowData> {\r\n id: string;\r\n data: T;\r\n}\r\n\r\nconst DEFAULT_CONFIG: Required<Pick<DynamicDataTableConfig, 'title' | 'rowsPerPageOptions' | 'defaultRowsPerPage'>> & {\r\n features: Required<NonNullable<DynamicDataTableConfig['features']>>;\r\n exportOptions: Required<NonNullable<DynamicDataTableConfig['exportOptions']>>;\r\n} = {\r\n title: 'Dynamic DataTable',\r\n features: {\r\n export: true,\r\n sorting: true,\r\n searching: true,\r\n pagination: true,\r\n rowsPerPage: true,\r\n actions: true,\r\n checkboxSelection: true\r\n },\r\n rowsPerPageOptions: [5, 10, 25, 50],\r\n defaultRowsPerPage: 10,\r\n exportOptions: {\r\n fileName: 'datatable-export',\r\n formats: ['csv', 'excel']\r\n }\r\n};\r\n\r\n@Component({\r\n selector: 'lib-dynamic-datatable',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './dynamic-datatable.component.html',\r\n styleUrl: './dynamic-datatable.component.scss'\r\n})\r\nexport class DynamicDatatableComponent implements OnChanges {\r\n @Input() config: DynamicDataTableConfig = {};\r\n @Input() columns: DataTableColumn<RowData>[] = [];\r\n @Input() data: RowData[] = [];\r\n\r\n @Output() readonly actionSelected = new EventEmitter<DataTableActionEvent<RowData>>();\r\n @Output() readonly selectionChange = new EventEmitter<RowData[]>();\r\n @Output() readonly sortChange = new EventEmitter<InternalSortState>();\r\n @Output() readonly pageChange = new EventEmitter<number>();\r\n @Output() readonly exportTriggered = new EventEmitter<DataTableExportEvent<RowData>>();\r\n\r\n mergedConfig: DynamicDataTableConfig<RowData> = {\r\n title: DEFAULT_CONFIG.title,\r\n features: { ...DEFAULT_CONFIG.features },\r\n rowsPerPageOptions: [...DEFAULT_CONFIG.rowsPerPageOptions],\r\n defaultRowsPerPage: DEFAULT_CONFIG.defaultRowsPerPage,\r\n exportOptions: { ...DEFAULT_CONFIG.exportOptions },\r\n columns: [],\r\n actions: []\r\n };\r\n\r\n mergedColumns: DataTableColumn<RowData>[] = [];\r\n\r\n private allRows: InternalRow<RowData>[] = [];\r\n filteredRows: InternalRow<RowData>[] = [];\r\n pagedRows: InternalRow<RowData>[] = [];\r\n\r\n searchTerm = '';\r\n currentPage = 1;\r\n rowsPerPage = DEFAULT_CONFIG.defaultRowsPerPage;\r\n totalPages = 1;\r\n sortState: InternalSortState = { key: null, direction: 'asc' };\r\n selectedRows = new Set<string>();\r\n isExportMenuOpen = false;\r\n\r\n ngOnChanges(_changes: SimpleChanges): void {\r\n this.refresh();\r\n }\r\n\r\n refresh(): void {\r\n this.applyConfig();\r\n this.normalizeRows();\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n updateData(newData: RowData[]): void {\r\n this.data = Array.isArray(newData) ? [...newData] : [];\r\n this.refresh();\r\n }\r\n\r\n updateConfig(newConfig: DynamicDataTableConfig<RowData>): void {\r\n this.config = { ...this.config, ...newConfig };\r\n this.refresh();\r\n }\r\n\r\n getSelectedRows(): RowData[] {\r\n return this.allRows.filter((row) => this.selectedRows.has(row.id)).map((row) => row.data);\r\n }\r\n\r\n clearSelection(): void {\r\n this.selectedRows.clear();\r\n this.selectionChange.emit([]);\r\n }\r\n\r\n isFeatureOn(feature: keyof NonNullable<DynamicDataTableConfig['features']>): boolean {\r\n return Boolean(this.mergedConfig.features?.[feature]);\r\n }\r\n\r\n isExportFormatEnabled(format: 'csv' | 'excel'): boolean {\r\n const formats = this.mergedConfig.exportOptions?.formats ?? [];\r\n return formats.includes(format);\r\n }\r\n\r\n onSearchInput(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n this.searchTerm = (input.value || '').trim().toLowerCase();\r\n this.currentPage = 1;\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n onRowsPerPageChange(event: Event): void {\r\n const select = event.target as HTMLSelectElement;\r\n const value = Number(select.value);\r\n this.rowsPerPage = Number.isFinite(value) && value > 0 ? value : this.getInitialRowsPerPage();\r\n this.currentPage = 1;\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n toggleSort(column: DataTableColumn<RowData>): void {\r\n if (!this.isFeatureOn('sorting') || !column.sortable) {\r\n return;\r\n }\r\n\r\n const key = String(column.key);\r\n if (this.sortState.key === key) {\r\n this.sortState.direction = this.sortState.direction === 'asc' ? 'desc' : 'asc';\r\n } else {\r\n this.sortState = { key, direction: 'asc' };\r\n }\r\n\r\n this.currentPage = 1;\r\n this.sortChange.emit({ ...this.sortState });\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n getSortIconClass(columnKey: string): string {\r\n if (this.sortState.key !== columnKey) {\r\n return 'bi bi-arrow-down-up';\r\n }\r\n\r\n return this.sortState.direction === 'asc' ? 'bi bi-sort-down' : 'bi bi-sort-up';\r\n }\r\n\r\n isSortColumn(columnKey: string): boolean {\r\n return this.sortState.key === columnKey;\r\n }\r\n\r\n goToPage(page: number): void {\r\n if (!this.isFeatureOn('pagination')) {\r\n return;\r\n }\r\n\r\n const bounded = Math.min(Math.max(page, 1), this.totalPages);\r\n if (bounded === this.currentPage) {\r\n return;\r\n }\r\n\r\n this.currentPage = bounded;\r\n this.pageChange.emit(this.currentPage);\r\n this.updatePagedRowsOnly();\r\n }\r\n\r\n getPaginationPages(): number[] {\r\n return Array.from({ length: this.totalPages }, (_, idx) => idx + 1);\r\n }\r\n\r\n isRowSelected(rowId: string): boolean {\r\n return this.selectedRows.has(rowId);\r\n }\r\n\r\n toggleRowSelection(row: InternalRow<RowData>, event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n if (input.checked) {\r\n this.selectedRows.add(row.id);\r\n } else {\r\n this.selectedRows.delete(row.id);\r\n }\r\n\r\n this.emitSelection();\r\n }\r\n\r\n toggleSelectAllCurrentPage(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n this.pagedRows.forEach((row) => {\r\n if (input.checked) {\r\n this.selectedRows.add(row.id);\r\n } else {\r\n this.selectedRows.delete(row.id);\r\n }\r\n });\r\n\r\n this.emitSelection();\r\n }\r\n\r\n isCurrentPageFullySelected(): boolean {\r\n if (!this.pagedRows.length) {\r\n return false;\r\n }\r\n\r\n return this.pagedRows.every((row) => this.selectedRows.has(row.id));\r\n }\r\n\r\n toggleExportMenu(event: Event): void {\r\n event.stopPropagation();\r\n this.isExportMenuOpen = !this.isExportMenuOpen;\r\n }\r\n\r\n onActionItemClick(actionIndex: number, row: InternalRow<RowData>, event: Event): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n if (!Number.isInteger(actionIndex) || actionIndex < 0) {\r\n return;\r\n }\r\n\r\n const action = this.mergedConfig.actions?.[actionIndex];\r\n if (!action) {\r\n return;\r\n }\r\n\r\n const rowIndex = this.filteredRows.findIndex((item) => item.id === row.id);\r\n this.actionSelected.emit({ action, row: row.data, rowIndex });\r\n }\r\n\r\n exportCSV(): void {\r\n this.isExportMenuOpen = false;\r\n const rows = this.getRowsForExport();\r\n this.exportTriggered.emit({ format: 'csv', rows });\r\n\r\n const headers = this.mergedColumns.map((column) => this.escapeCsv(column.label));\r\n const lines = rows.map((row) => {\r\n return this.mergedColumns\r\n .map((column) => this.escapeCsv(this.getCellTextValue(row, column)))\r\n .join(',');\r\n });\r\n\r\n const csv = [headers.join(','), ...lines].join('\\n');\r\n this.downloadFile(csv, `${this.getExportFileName()}.csv`, 'text/csv;charset=utf-8;');\r\n }\r\n\r\n exportExcel(): void {\r\n this.isExportMenuOpen = false;\r\n const rows = this.getRowsForExport();\r\n this.exportTriggered.emit({ format: 'excel', rows });\r\n\r\n const headerCells = this.mergedColumns.map((column) => `<th>${this.escapeHtml(column.label)}</th>`).join('');\r\n const bodyRows = rows\r\n .map((row) => {\r\n const cells = this.mergedColumns\r\n .map((column) => `<td>${this.escapeHtml(this.getCellTextValue(row, column))}</td>`)\r\n .join('');\r\n return `<tr>${cells}</tr>`;\r\n })\r\n .join('');\r\n\r\n const html = `<html><head><meta charset=\"UTF-8\"></head><body><table border=\"1\"><thead><tr>${headerCells}</tr></thead><tbody>${bodyRows}</tbody></table></body></html>`;\r\n this.downloadFile(html, `${this.getExportFileName()}.xls`, 'application/vnd.ms-excel;charset=utf-8;');\r\n }\r\n\r\n getRenderedCell(row: RowData, column: DataTableColumn<RowData>): string {\r\n if (typeof column.render === 'function') {\r\n return column.render(row);\r\n }\r\n\r\n const key = String(column.key);\r\n const value = row[key];\r\n return this.escapeHtml(value == null ? '' : String(value));\r\n }\r\n\r\n toColumnWidth(width: string | number | undefined): string {\r\n if (typeof width === 'number') {\r\n return `${width}px`;\r\n }\r\n\r\n if (typeof width === 'string' && width.trim()) {\r\n return width.trim();\r\n }\r\n\r\n return 'auto';\r\n }\r\n\r\n getColumnCount(): number {\r\n let count = this.mergedColumns.length;\r\n if (this.isFeatureOn('checkboxSelection')) {\r\n count += 1;\r\n }\r\n if (this.isFeatureOn('actions')) {\r\n count += 1;\r\n }\r\n return count;\r\n }\r\n\r\n getStartEntry(): number {\r\n if (!this.filteredRows.length) {\r\n return 0;\r\n }\r\n\r\n if (!this.isFeatureOn('pagination')) {\r\n return 1;\r\n }\r\n\r\n return (this.currentPage - 1) * this.rowsPerPage + 1;\r\n }\r\n\r\n getEndEntry(): number {\r\n if (!this.filteredRows.length) {\r\n return 0;\r\n }\r\n\r\n if (!this.isFeatureOn('pagination')) {\r\n return this.filteredRows.length;\r\n }\r\n\r\n return Math.min(this.currentPage * this.rowsPerPage, this.filteredRows.length);\r\n }\r\n\r\n private applyConfig(): void {\r\n const features = {\r\n ...DEFAULT_CONFIG.features,\r\n ...(this.config.features ?? {})\r\n };\r\n\r\n const exportOptions = {\r\n ...DEFAULT_CONFIG.exportOptions,\r\n ...(this.config.exportOptions ?? {})\r\n };\r\n\r\n const rowsPerPageOptions = (this.config.rowsPerPageOptions ?? DEFAULT_CONFIG.rowsPerPageOptions).filter(\r\n (item) => Number.isFinite(item) && item > 0\r\n );\r\n\r\n this.mergedConfig = {\r\n title: this.config.title ?? DEFAULT_CONFIG.title,\r\n features,\r\n rowsPerPageOptions: rowsPerPageOptions.length ? rowsPerPageOptions : [...DEFAULT_CONFIG.rowsPerPageOptions],\r\n defaultRowsPerPage: this.config.defaultRowsPerPage ?? DEFAULT_CONFIG.defaultRowsPerPage,\r\n exportOptions,\r\n actions: [...(this.config.actions ?? [])],\r\n columns: []\r\n };\r\n\r\n this.mergedColumns = [...(this.columns.length ? this.columns : (this.config.columns ?? []))];\r\n this.rowsPerPage = this.getInitialRowsPerPage();\r\n }\r\n\r\n private normalizeRows(): void {\r\n this.allRows = (Array.isArray(this.data) ? this.data : []).map((row, index) => {\r\n const rowId = row['id'];\r\n const id = rowId == null ? `row-${index + 1}` : String(rowId);\r\n return { id, data: row };\r\n });\r\n\r\n const validIds = new Set(this.allRows.map((row) => row.id));\r\n for (const selectedId of Array.from(this.selectedRows)) {\r\n if (!validIds.has(selectedId)) {\r\n this.selectedRows.delete(selectedId);\r\n }\r\n }\r\n }\r\n\r\n private applyFiltersSortAndPagination(): void {\r\n if (!this.isFeatureOn('searching') || !this.searchTerm) {\r\n this.filteredRows = [...this.allRows];\r\n } else {\r\n this.filteredRows = this.allRows.filter((row) => {\r\n const searchSpace = this.mergedColumns\r\n .map((column) => this.getCellTextValue(row.data, column).toLowerCase())\r\n .join(' ');\r\n return searchSpace.includes(this.searchTerm);\r\n });\r\n }\r\n\r\n if (this.isFeatureOn('sorting') && this.sortState.key) {\r\n const column = this.mergedColumns.find((item) => String(item.key) === this.sortState.key);\r\n if (column?.sortable) {\r\n this.filteredRows.sort((a, b) => {\r\n const aVal = this.getCellTextValue(a.data, column);\r\n const bVal = this.getCellTextValue(b.data, column);\r\n const compare = this.compareValues(aVal, bVal);\r\n return this.sortState.direction === 'asc' ? compare : -compare;\r\n });\r\n }\r\n }\r\n\r\n this.totalPages = this.isFeatureOn('pagination')\r\n ? Math.max(1, Math.ceil(this.filteredRows.length / this.rowsPerPage))\r\n : 1;\r\n\r\n if (this.currentPage > this.totalPages) {\r\n this.currentPage = this.totalPages;\r\n }\r\n\r\n this.updatePagedRowsOnly();\r\n this.emitSelection();\r\n }\r\n\r\n private updatePagedRowsOnly(): void {\r\n if (!this.isFeatureOn('pagination')) {\r\n this.pagedRows = [...this.filteredRows];\r\n return;\r\n }\r\n\r\n const start = (this.currentPage - 1) * this.rowsPerPage;\r\n this.pagedRows = this.filteredRows.slice(start, start + this.rowsPerPage);\r\n }\r\n\r\n private getCellTextValue(row: RowData, column: DataTableColumn<RowData>): string {\r\n const key = String(column.key);\r\n if (row[key] != null) {\r\n return String(row[key]);\r\n }\r\n\r\n const rendered = this.getRenderedCell(row, column);\r\n return this.stripHtml(rendered);\r\n }\r\n\r\n private compareValues(a: string, b: string): number {\r\n const aText = a.trim();\r\n const bText = b.trim();\r\n\r\n const aNum = this.parseStrictNumber(aText);\r\n const bNum = this.parseStrictNumber(bText);\r\n if (aNum !== null && bNum !== null) {\r\n return aNum - bNum;\r\n }\r\n\r\n const aDate = this.parseDateValue(aText);\r\n const bDate = this.parseDateValue(bText);\r\n if (aDate !== null && bDate !== null) {\r\n return aDate - bDate;\r\n }\r\n\r\n return aText.localeCompare(bText, undefined, { numeric: true, sensitivity: 'base' });\r\n }\r\n\r\n private parseStrictNumber(value: string): number | null {\r\n const normalized = value.replace(/[$,\\s]/g, '');\r\n if (!/^[-+]?\\d*\\.?\\d+$/.test(normalized)) {\r\n return null;\r\n }\r\n\r\n const numberValue = Number(normalized);\r\n return Number.isNaN(numberValue) ? null : numberValue;\r\n }\r\n\r\n private parseDateValue(value: string): number | null {\r\n const usDate = value.match(/^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{4})$/);\r\n if (usDate) {\r\n const month = Number(usDate[1]);\r\n const day = Number(usDate[2]);\r\n const year = Number(usDate[3]);\r\n const utc = Date.UTC(year, month - 1, day);\r\n return Number.isNaN(utc) ? null : utc;\r\n }\r\n\r\n const isoDate = value.match(/^(\\d{4})-(\\d{1,2})-(\\d{1,2})$/);\r\n if (isoDate) {\r\n const year = Number(isoDate[1]);\r\n const month = Number(isoDate[2]);\r\n const day = Number(isoDate[3]);\r\n const utc = Date.UTC(year, month - 1, day);\r\n return Number.isNaN(utc) ? null : utc;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private getRowsForExport(): RowData[] {\r\n const selected = this.getSelectedRows();\r\n if (selected.length) {\r\n return selected;\r\n }\r\n\r\n return this.filteredRows.map((item) => item.data);\r\n }\r\n\r\n private getExportFileName(): string {\r\n return this.mergedConfig.exportOptions?.fileName || 'datatable-export';\r\n }\r\n\r\n private downloadFile(content: string, fileName: string, mimeType: string): void {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n const blob = new Blob([content], { type: mimeType });\r\n const url = URL.createObjectURL(blob);\r\n const anchor = document.createElement('a');\r\n anchor.href = url;\r\n anchor.download = fileName;\r\n document.body.appendChild(anchor);\r\n anchor.click();\r\n document.body.removeChild(anchor);\r\n URL.revokeObjectURL(url);\r\n }\r\n\r\n private escapeCsv(value: string): string {\r\n if (/[\",\\n]/.test(value)) {\r\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n\r\n return value;\r\n }\r\n\r\n private stripHtml(input: string): string {\r\n if (typeof document === 'undefined') {\r\n return input;\r\n }\r\n\r\n const temp = document.createElement('div');\r\n temp.innerHTML = input;\r\n return temp.textContent || temp.innerText || '';\r\n }\r\n\r\n private escapeHtml(value: string): string {\r\n return String(value)\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#039;');\r\n }\r\n\r\n private getInitialRowsPerPage(): number {\r\n const options = this.mergedConfig.rowsPerPageOptions ?? DEFAULT_CONFIG.rowsPerPageOptions;\r\n const preferred = Number(this.mergedConfig.defaultRowsPerPage ?? DEFAULT_CONFIG.defaultRowsPerPage);\r\n return options.includes(preferred) ? preferred : options[0] ?? DEFAULT_CONFIG.defaultRowsPerPage;\r\n }\r\n\r\n private emitSelection(): void {\r\n this.selectionChange.emit(this.getSelectedRows());\r\n }\r\n\r\n closeMenus(): void {\r\n this.isExportMenuOpen = false;\r\n }\r\n\r\n}\r\n","<div class=\"ndt-card\" (click)=\"closeMenus()\">\r\n <div class=\"ndt-header\">\r\n <h3 class=\"ndt-title\">{{ mergedConfig.title }}</h3>\r\n </div>\r\n\r\n <div class=\"ndt-toolbar\">\r\n <div class=\"ndt-left-tools\">\r\n <ng-container *ngIf=\"isFeatureOn('export')\">\r\n <div class=\"ndt-dropdown\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"ndt-btn ndt-export-btn\" type=\"button\" (click)=\"toggleExportMenu($event)\">\r\n <i class=\"bi bi-download\"></i>\r\n <span>Export</span>\r\n <i class=\"bi bi-chevron-down ndt-chevron\"></i>\r\n </button>\r\n\r\n <ul class=\"ndt-dropdown-menu\" *ngIf=\"isExportMenuOpen\">\r\n <li *ngIf=\"isExportFormatEnabled('csv')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" (click)=\"exportCSV()\">\r\n <i class=\"bi bi-filetype-csv\"></i>\r\n <span>CSV</span>\r\n </button>\r\n </li>\r\n <li *ngIf=\"isExportFormatEnabled('excel')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" (click)=\"exportExcel()\">\r\n <i class=\"bi bi-file-earmark-spreadsheet\"></i>\r\n <span>Excel (.xls)</span>\r\n </button>\r\n </li>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n\r\n <label class=\"ndt-inline-label\" *ngIf=\"isFeatureOn('rowsPerPage') && isFeatureOn('pagination')\">\r\n Rows per page:\r\n <select [value]=\"rowsPerPage\" (change)=\"onRowsPerPageChange($event)\">\r\n <option *ngFor=\"let option of mergedConfig.rowsPerPageOptions || []\" [value]=\"option\">{{ option }}</option>\r\n </select>\r\n </label>\r\n </div>\r\n\r\n <div class=\"ndt-right-tools\" *ngIf=\"isFeatureOn('searching')\">\r\n <input\r\n type=\"search\"\r\n placeholder=\"Search records\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearchInput($event)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"ndt-table-wrap\">\r\n <table class=\"ndt-table\">\r\n <colgroup>\r\n <col *ngIf=\"isFeatureOn('checkboxSelection')\" style=\"width: 44px\" />\r\n <col *ngFor=\"let column of mergedColumns\" [style.width]=\"toColumnWidth(column.width)\" />\r\n <col *ngIf=\"isFeatureOn('actions')\" style=\"width: 78px\" />\r\n </colgroup>\r\n\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"isCurrentPageFullySelected()\"\r\n (change)=\"toggleSelectAllCurrentPage($event)\"\r\n />\r\n </th>\r\n <th\r\n *ngFor=\"let column of mergedColumns\"\r\n [class.ndt-sortable]=\"isFeatureOn('sorting') && !!column.sortable\"\r\n (click)=\"toggleSort(column)\"\r\n >\r\n <span class=\"ndt-th-content\">\r\n <span class=\"ndt-th-label\">{{ column.label }}</span>\r\n <i\r\n *ngIf=\"isFeatureOn('sorting') && column.sortable\"\r\n [ngClass]=\"[\r\n 'ndt-sort-indicator',\r\n getSortIconClass(column.key.toString()),\r\n isSortColumn(column.key.toString()) ? 'active' : ''\r\n ]\"\r\n ></i>\r\n </span>\r\n </th>\r\n <th *ngIf=\"isFeatureOn('actions')\">Actions</th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr *ngIf=\"!pagedRows.length\">\r\n <td [attr.colspan]=\"getColumnCount()\" class=\"ndt-empty\">No records found.</td>\r\n </tr>\r\n\r\n <tr *ngFor=\"let row of pagedRows\" [class.ndt-selected]=\"isRowSelected(row.id)\">\r\n <td *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"isRowSelected(row.id)\"\r\n (change)=\"toggleRowSelection(row, $event)\"\r\n />\r\n </td>\r\n\r\n <td *ngFor=\"let column of mergedColumns\" [innerHTML]=\"getRenderedCell(row.data, column)\"></td>\r\n\r\n <td *ngIf=\"isFeatureOn('actions')\" class=\"ndt-actions-cell\">\r\n <div class=\"ndt-action-icons\" (click)=\"$event.stopPropagation()\">\r\n <button\r\n *ngFor=\"let action of mergedConfig.actions || []; let i = index\"\r\n type=\"button\"\r\n class=\"ndt-actions-btn\"\r\n [class.ndt-danger]=\"!!action.danger\"\r\n [attr.title]=\"action.label\"\r\n [attr.aria-label]=\"action.label\"\r\n (click)=\"onActionItemClick(i, row, $event)\"\r\n >\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\"></i>\r\n <span *ngIf=\"!action.icon\" class=\"ndt-action-fallback\">{{ action.label.charAt(0) }}</span>\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div class=\"ndt-footer\">\r\n <div>\r\n {{ selectedRows.size }} selected\r\n </div>\r\n\r\n <div>\r\n Showing {{ getStartEntry() }} to {{ getEndEntry() }} of {{ filteredRows.length }} entries\r\n </div>\r\n\r\n <ul class=\"ndt-pagination\" *ngIf=\"isFeatureOn('pagination') && totalPages > 1\">\r\n <li [class.disabled]=\"currentPage <= 1\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage <= 1\">Prev</button>\r\n </li>\r\n <li *ngFor=\"let page of getPaginationPages()\" [class.active]=\"page === currentPage\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(page)\">{{ page }}</button>\r\n </li>\r\n <li [class.disabled]=\"currentPage >= totalPages\">\r\n <button type=\"button\" class=\"ndt-page-link\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage >= totalPages\">Next</button>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n","/*\r\n * Public API Surface of dynamic-datatable\r\n */\r\n\r\nexport * from './lib/dynamic-datatable.component';\r\nexport * from './lib/models';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-dynamic-datatable.mjs","sources":["../../../projects/dynamic-datatable/src/lib/tooltip-manager.ts","../../../projects/dynamic-datatable/src/lib/dynamic-datatable.component.ts","../../../projects/dynamic-datatable/src/lib/dynamic-datatable.component.html","../../../projects/dynamic-datatable/src/public-api.ts","../../../projects/dynamic-datatable/src/ng-dynamic-datatable.ts"],"sourcesContent":["type TooltipTrigger = 'hover' | 'click';\r\ntype TooltipPosition = 'top' | 'bottom' | 'left' | 'right';\r\n\r\ninterface TooltipConfig {\r\n content?: string;\r\n html?: string;\r\n icon?: string;\r\n trigger?: TooltipTrigger;\r\n position?: TooltipPosition;\r\n noArrow?: boolean;\r\n allowHtml?: boolean;\r\n offset?: number;\r\n}\r\n\r\ninterface TooltipEntry {\r\n config: TooltipConfig;\r\n}\r\n\r\nconst VALID_TRIGGERS: Record<string, TooltipTrigger> = {\r\n hover: 'hover',\r\n click: 'click'\r\n};\r\n\r\nconst VALID_POSITIONS: Record<string, TooltipPosition> = {\r\n top: 'top',\r\n bottom: 'bottom',\r\n left: 'left',\r\n right: 'right'\r\n};\r\n\r\nexport class TooltipManager {\r\n private readonly registry = new WeakMap<HTMLElement, TooltipEntry>();\r\n private readonly root: HTMLElement;\r\n private readonly documentRef: Document;\r\n\r\n private activeTarget: HTMLElement | null = null;\r\n private activeTooltipEl: HTMLElement | null = null;\r\n\r\n private readonly offset = 10;\r\n private readonly viewportPadding = 8;\r\n\r\n private readonly onMouseOverBound = (event: Event) => this.onMouseOver(event);\r\n private readonly onMouseOutBound = (event: Event) => this.onMouseOut(event);\r\n private readonly onFocusInBound = (event: Event) => this.onFocusIn(event);\r\n private readonly onFocusOutBound = (event: Event) => this.onFocusOut(event);\r\n private readonly onClickBound = (event: Event) => this.onClick(event);\r\n private readonly onDocumentClickBound = (event: Event) => this.onDocumentClick(event);\r\n private readonly onDocumentKeydownBound = (event: KeyboardEvent) => this.onDocumentKeydown(event);\r\n private readonly onWindowResizeBound = () => this.reposition();\r\n private readonly onWindowScrollBound = () => this.reposition();\r\n\r\n constructor(root: HTMLElement, documentRef: Document = document) {\r\n this.root = root;\r\n this.documentRef = documentRef;\r\n }\r\n\r\n init(): void {\r\n this.root.addEventListener('mouseover', this.onMouseOverBound);\r\n this.root.addEventListener('mouseout', this.onMouseOutBound);\r\n this.root.addEventListener('focusin', this.onFocusInBound);\r\n this.root.addEventListener('focusout', this.onFocusOutBound);\r\n this.root.addEventListener('click', this.onClickBound);\r\n\r\n this.documentRef.addEventListener('click', this.onDocumentClickBound, true);\r\n this.documentRef.addEventListener('keydown', this.onDocumentKeydownBound);\r\n\r\n window.addEventListener('resize', this.onWindowResizeBound);\r\n window.addEventListener('scroll', this.onWindowScrollBound, true);\r\n }\r\n\r\n destroy(): void {\r\n this.hide(true);\r\n\r\n this.root.removeEventListener('mouseover', this.onMouseOverBound);\r\n this.root.removeEventListener('mouseout', this.onMouseOutBound);\r\n this.root.removeEventListener('focusin', this.onFocusInBound);\r\n this.root.removeEventListener('focusout', this.onFocusOutBound);\r\n this.root.removeEventListener('click', this.onClickBound);\r\n\r\n this.documentRef.removeEventListener('click', this.onDocumentClickBound, true);\r\n this.documentRef.removeEventListener('keydown', this.onDocumentKeydownBound);\r\n\r\n window.removeEventListener('resize', this.onWindowResizeBound);\r\n window.removeEventListener('scroll', this.onWindowScrollBound, true);\r\n }\r\n\r\n register(element: HTMLElement, config: TooltipConfig): void {\r\n this.registry.set(element, { config });\r\n }\r\n\r\n private onMouseOver(event: Event): void {\r\n const target = this.getTooltipTarget(event.target);\r\n if (!target) {\r\n return;\r\n }\r\n\r\n if (this.getTrigger(target) !== 'hover') {\r\n return;\r\n }\r\n\r\n this.show(target);\r\n }\r\n\r\n private onMouseOut(event: Event): void {\r\n const target = this.getTooltipTarget(event.target);\r\n if (!target || this.getTrigger(target) !== 'hover') {\r\n return;\r\n }\r\n\r\n const next = (event as MouseEvent).relatedTarget as Node | null;\r\n if (next && (target.contains(next) || (this.activeTooltipEl?.contains(next) ?? false))) {\r\n return;\r\n }\r\n\r\n this.hide();\r\n }\r\n\r\n private onFocusIn(event: Event): void {\r\n const target = this.getTooltipTarget(event.target);\r\n if (!target) {\r\n return;\r\n }\r\n\r\n this.show(target);\r\n }\r\n\r\n private onFocusOut(event: Event): void {\r\n const target = this.getTooltipTarget(event.target);\r\n if (!target) {\r\n return;\r\n }\r\n\r\n const next = (event as FocusEvent).relatedTarget as Node | null;\r\n if (next && (target.contains(next) || (this.activeTooltipEl?.contains(next) ?? false))) {\r\n return;\r\n }\r\n\r\n this.hide();\r\n }\r\n\r\n private onClick(event: Event): void {\r\n const target = this.getTooltipTarget(event.target);\r\n if (!target) {\r\n return;\r\n }\r\n\r\n if (this.getTrigger(target) !== 'click') {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n if (this.activeTarget === target && this.activeTooltipEl) {\r\n this.hide();\r\n return;\r\n }\r\n\r\n this.show(target);\r\n }\r\n\r\n private onDocumentClick(event: Event): void {\r\n if (!this.activeTarget || !this.activeTooltipEl) {\r\n return;\r\n }\r\n\r\n if (this.getTrigger(this.activeTarget) !== 'click') {\r\n return;\r\n }\r\n\r\n const node = event.target as Node | null;\r\n const insideTarget = !!(node && this.activeTarget.contains(node));\r\n const insideTooltip = !!(node && this.activeTooltipEl.contains(node));\r\n\r\n if (!insideTarget && !insideTooltip) {\r\n this.hide();\r\n }\r\n }\r\n\r\n private onDocumentKeydown(event: KeyboardEvent): void {\r\n if (event.key === 'Escape') {\r\n this.hide();\r\n }\r\n }\r\n\r\n private getTooltipTarget(input: EventTarget | null): HTMLElement | null {\r\n if (!(input instanceof Element)) {\r\n return null;\r\n }\r\n\r\n const target = input.closest('[data-tooltip]') as HTMLElement | null;\r\n if (!target) {\r\n return null;\r\n }\r\n\r\n if (!this.root.contains(target)) {\r\n return null;\r\n }\r\n\r\n return target;\r\n }\r\n\r\n private getEntry(target: HTMLElement): TooltipEntry | undefined {\r\n return this.registry.get(target);\r\n }\r\n\r\n private getTrigger(target: HTMLElement): TooltipTrigger {\r\n const value = this.getEntry(target)?.config.trigger ?? target.dataset['tooltipTrigger'] ?? 'hover';\r\n const normalized = String(value).toLowerCase();\r\n return VALID_TRIGGERS[normalized] ?? 'hover';\r\n }\r\n\r\n private getPosition(target: HTMLElement): TooltipPosition {\r\n const value = this.getEntry(target)?.config.position ?? target.dataset['tooltipPosition'] ?? 'bottom';\r\n const normalized = String(value).toLowerCase();\r\n return VALID_POSITIONS[normalized] ?? 'bottom';\r\n }\r\n\r\n private getContent(target: HTMLElement): { icon: string; text: string; html: string; allowHtml: boolean; noArrow: boolean; offset: number } {\r\n const entry = this.getEntry(target);\r\n\r\n const html = entry?.config.html ?? target.dataset['tooltipHtml'] ?? '';\r\n const text = entry?.config.content ?? target.dataset['tooltip'] ?? '';\r\n const icon = entry?.config.icon ?? target.dataset['tooltipIcon'] ?? '';\r\n\r\n const allowHtmlAttr = target.dataset['tooltipAllowHtml'];\r\n const allowHtml = entry?.config.allowHtml ?? (allowHtmlAttr === 'true');\r\n\r\n const noArrowAttr = target.dataset['tooltipNoArrow'];\r\n const noArrow = entry?.config.noArrow ?? (noArrowAttr === 'true');\r\n\r\n const offsetRaw = entry?.config.offset ?? target.dataset['tooltipOffset'];\r\n const offset = Number.isFinite(Number(offsetRaw)) ? Number(offsetRaw) : this.offset;\r\n\r\n return { icon, text, html, allowHtml, noArrow, offset };\r\n }\r\n\r\n private show(target: HTMLElement): void {\r\n const payload = this.getContent(target);\r\n const content = payload.allowHtml && payload.html ? payload.html : payload.text;\r\n\r\n if (!content) {\r\n this.hide();\r\n return;\r\n }\r\n\r\n this.hide(true);\r\n\r\n const tooltip = this.documentRef.createElement('div');\r\n tooltip.className = 'ndt-tooltip';\r\n tooltip.setAttribute('role', 'tooltip');\r\n tooltip.setAttribute('data-placement', this.getPosition(target));\r\n if (payload.noArrow) {\r\n tooltip.setAttribute('data-no-arrow', 'true');\r\n }\r\n\r\n const contentWrap = this.documentRef.createElement('div');\r\n contentWrap.className = 'ndt-tooltip__content';\r\n\r\n if (payload.icon) {\r\n const iconEl = this.documentRef.createElement('span');\r\n iconEl.className = `ndt-tooltip__icon ${payload.icon}`;\r\n iconEl.setAttribute('aria-hidden', 'true');\r\n contentWrap.appendChild(iconEl);\r\n }\r\n\r\n const textEl = this.documentRef.createElement('span');\r\n textEl.className = 'ndt-tooltip__text';\r\n if (payload.allowHtml && payload.html) {\r\n textEl.innerHTML = payload.html;\r\n } else {\r\n textEl.textContent = payload.text;\r\n }\r\n\r\n contentWrap.appendChild(textEl);\r\n tooltip.appendChild(contentWrap);\r\n\r\n this.documentRef.body.appendChild(tooltip);\r\n\r\n this.activeTarget = target;\r\n this.activeTooltipEl = tooltip;\r\n\r\n this.positionTooltip(target, tooltip, this.getPosition(target), payload.offset);\r\n\r\n requestAnimationFrame(() => {\r\n if (this.activeTooltipEl === tooltip) {\r\n tooltip.classList.add('ndt-tooltip--show');\r\n }\r\n });\r\n }\r\n\r\n private hide(immediate = false): void {\r\n if (!this.activeTooltipEl) {\r\n this.activeTarget = null;\r\n return;\r\n }\r\n\r\n const tooltip = this.activeTooltipEl;\r\n this.activeTooltipEl = null;\r\n this.activeTarget = null;\r\n\r\n if (immediate) {\r\n if (tooltip.parentNode) {\r\n tooltip.parentNode.removeChild(tooltip);\r\n }\r\n return;\r\n }\r\n\r\n tooltip.classList.remove('ndt-tooltip--show');\r\n window.setTimeout(() => {\r\n if (tooltip.parentNode) {\r\n tooltip.parentNode.removeChild(tooltip);\r\n }\r\n }, 180);\r\n }\r\n\r\n private reposition(): void {\r\n if (!this.activeTarget || !this.activeTooltipEl) {\r\n return;\r\n }\r\n\r\n const payload = this.getContent(this.activeTarget);\r\n this.positionTooltip(this.activeTarget, this.activeTooltipEl, this.getPosition(this.activeTarget), payload.offset);\r\n }\r\n\r\n private positionTooltip(target: HTMLElement, tooltip: HTMLElement, preferred: TooltipPosition, offset: number): void {\r\n const rect = target.getBoundingClientRect();\r\n const tipRect = tooltip.getBoundingClientRect();\r\n\r\n const vw = window.innerWidth;\r\n const vh = window.innerHeight;\r\n\r\n const placement = this.pickPlacement(preferred, rect, tipRect, vw, vh, offset);\r\n const coords = this.computeCoords(placement, rect, tipRect, offset);\r\n\r\n const minX = this.viewportPadding;\r\n const maxX = vw - tipRect.width - this.viewportPadding;\r\n const minY = this.viewportPadding;\r\n const maxY = vh - tipRect.height - this.viewportPadding;\r\n\r\n const left = Math.min(Math.max(coords.left, minX), Math.max(minX, maxX));\r\n const top = Math.min(Math.max(coords.top, minY), Math.max(minY, maxY));\r\n\r\n tooltip.style.left = `${Math.round(left)}px`;\r\n tooltip.style.top = `${Math.round(top)}px`;\r\n tooltip.setAttribute('data-placement', placement);\r\n }\r\n\r\n private pickPlacement(\r\n preferred: TooltipPosition,\r\n rect: DOMRect,\r\n tipRect: DOMRect,\r\n vw: number,\r\n vh: number,\r\n offset: number\r\n ): TooltipPosition {\r\n const fits: Record<TooltipPosition, boolean> = {\r\n top: rect.top - offset - tipRect.height >= this.viewportPadding,\r\n bottom: rect.bottom + offset + tipRect.height <= vh - this.viewportPadding,\r\n left: rect.left - offset - tipRect.width >= this.viewportPadding,\r\n right: rect.right + offset + tipRect.width <= vw - this.viewportPadding\r\n };\r\n\r\n const order: TooltipPosition[] = [preferred, 'bottom', 'top', 'right', 'left'];\r\n for (const candidate of order) {\r\n if (fits[candidate]) {\r\n return candidate;\r\n }\r\n }\r\n\r\n return preferred;\r\n }\r\n\r\n private computeCoords(\r\n placement: TooltipPosition,\r\n rect: DOMRect,\r\n tipRect: DOMRect,\r\n offset: number\r\n ): { top: number; left: number } {\r\n switch (placement) {\r\n case 'top':\r\n return {\r\n top: rect.top - tipRect.height - offset,\r\n left: rect.left + (rect.width - tipRect.width) / 2\r\n };\r\n case 'bottom':\r\n return {\r\n top: rect.bottom + offset,\r\n left: rect.left + (rect.width - tipRect.width) / 2\r\n };\r\n case 'left':\r\n return {\r\n top: rect.top + (rect.height - tipRect.height) / 2,\r\n left: rect.left - tipRect.width - offset\r\n };\r\n default:\r\n return {\r\n top: rect.top + (rect.height - tipRect.height) / 2,\r\n left: rect.right + offset\r\n };\r\n }\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChanges } from '@angular/core';\r\nimport {\r\n DataTableAction,\r\n DataTableActionEvent,\r\n DataTableColumn,\r\n DataTableExportEvent,\r\n DynamicDataTableConfig\r\n} from './models';\r\nimport { InternalSortState } from './dynamic-datatable.types';\r\nimport { TooltipManager } from './tooltip-manager';\r\n\r\ntype RowData = Record<string, unknown>;\r\n\r\ninterface InternalRow<T extends RowData = RowData> {\r\n id: string;\r\n data: T;\r\n}\r\n\r\nconst DEFAULT_CONFIG: Required<Pick<DynamicDataTableConfig, 'title' | 'rowsPerPageOptions' | 'defaultRowsPerPage'>> & {\r\n features: Required<NonNullable<DynamicDataTableConfig['features']>>;\r\n exportOptions: Required<NonNullable<DynamicDataTableConfig['exportOptions']>>;\r\n} = {\r\n title: 'Dynamic DataTable',\r\n features: {\r\n export: true,\r\n sorting: true,\r\n searching: true,\r\n pagination: true,\r\n rowsPerPage: true,\r\n actions: true,\r\n checkboxSelection: true\r\n },\r\n rowsPerPageOptions: [5, 10, 25, 50],\r\n defaultRowsPerPage: 10,\r\n exportOptions: {\r\n fileName: 'datatable-export',\r\n formats: ['csv', 'excel']\r\n }\r\n};\r\n\r\n@Component({\r\n selector: 'lib-dynamic-datatable',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './dynamic-datatable.component.html',\r\n styleUrl: './dynamic-datatable.component.scss'\r\n})\r\nexport class DynamicDatatableComponent implements OnChanges, AfterViewInit, OnDestroy {\r\n @Input() config: DynamicDataTableConfig = {};\r\n @Input() columns: DataTableColumn<RowData>[] = [];\r\n @Input() data: RowData[] = [];\r\n\r\n @Output() readonly actionSelected = new EventEmitter<DataTableActionEvent<RowData>>();\r\n @Output() readonly selectionChange = new EventEmitter<RowData[]>();\r\n @Output() readonly sortChange = new EventEmitter<InternalSortState>();\r\n @Output() readonly pageChange = new EventEmitter<number>();\r\n @Output() readonly exportTriggered = new EventEmitter<DataTableExportEvent<RowData>>();\r\n\r\n mergedConfig: DynamicDataTableConfig<RowData> = {\r\n title: DEFAULT_CONFIG.title,\r\n features: { ...DEFAULT_CONFIG.features },\r\n rowsPerPageOptions: [...DEFAULT_CONFIG.rowsPerPageOptions],\r\n defaultRowsPerPage: DEFAULT_CONFIG.defaultRowsPerPage,\r\n exportOptions: { ...DEFAULT_CONFIG.exportOptions },\r\n columns: [],\r\n actions: []\r\n };\r\n\r\n mergedColumns: DataTableColumn<RowData>[] = [];\r\n\r\n private allRows: InternalRow<RowData>[] = [];\r\n filteredRows: InternalRow<RowData>[] = [];\r\n pagedRows: InternalRow<RowData>[] = [];\r\n\r\n searchTerm = '';\r\n currentPage = 1;\r\n rowsPerPage = DEFAULT_CONFIG.defaultRowsPerPage;\r\n totalPages = 1;\r\n sortState: InternalSortState = { key: null, direction: 'asc' };\r\n selectedRows = new Set<string>();\r\n isExportMenuOpen = false;\r\n private tooltipManager: TooltipManager | null = null;\r\n\r\n constructor(private readonly hostRef: ElementRef<HTMLElement>) {}\r\n\r\n ngAfterViewInit(): void {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n this.tooltipManager = new TooltipManager(this.hostRef.nativeElement, document);\r\n this.tooltipManager.init();\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.tooltipManager?.destroy();\r\n this.tooltipManager = null;\r\n }\r\n\r\n ngOnChanges(_changes: SimpleChanges): void {\r\n this.refresh();\r\n }\r\n\r\n refresh(): void {\r\n this.applyConfig();\r\n this.normalizeRows();\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n updateData(newData: RowData[]): void {\r\n this.data = Array.isArray(newData) ? [...newData] : [];\r\n this.refresh();\r\n }\r\n\r\n updateConfig(newConfig: DynamicDataTableConfig<RowData>): void {\r\n this.config = { ...this.config, ...newConfig };\r\n this.refresh();\r\n }\r\n\r\n getSelectedRows(): RowData[] {\r\n return this.allRows.filter((row) => this.selectedRows.has(row.id)).map((row) => row.data);\r\n }\r\n\r\n clearSelection(): void {\r\n this.selectedRows.clear();\r\n this.selectionChange.emit([]);\r\n }\r\n\r\n isFeatureOn(feature: keyof NonNullable<DynamicDataTableConfig['features']>): boolean {\r\n return Boolean(this.mergedConfig.features?.[feature]);\r\n }\r\n\r\n isExportFormatEnabled(format: 'csv' | 'excel'): boolean {\r\n const formats = this.mergedConfig.exportOptions?.formats ?? [];\r\n return formats.includes(format);\r\n }\r\n\r\n onSearchInput(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n this.searchTerm = (input.value || '').trim().toLowerCase();\r\n this.currentPage = 1;\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n onRowsPerPageChange(event: Event): void {\r\n const select = event.target as HTMLSelectElement;\r\n const value = Number(select.value);\r\n this.rowsPerPage = Number.isFinite(value) && value > 0 ? value : this.getInitialRowsPerPage();\r\n this.currentPage = 1;\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n toggleSort(column: DataTableColumn<RowData>): void {\r\n if (!this.isFeatureOn('sorting') || !column.sortable) {\r\n return;\r\n }\r\n\r\n const key = String(column.key);\r\n if (this.sortState.key === key) {\r\n this.sortState.direction = this.sortState.direction === 'asc' ? 'desc' : 'asc';\r\n } else {\r\n this.sortState = { key, direction: 'asc' };\r\n }\r\n\r\n this.currentPage = 1;\r\n this.sortChange.emit({ ...this.sortState });\r\n this.applyFiltersSortAndPagination();\r\n }\r\n\r\n getSortIconClass(columnKey: string): string {\r\n if (this.sortState.key !== columnKey) {\r\n return 'bi bi-arrow-down-up';\r\n }\r\n\r\n return this.sortState.direction === 'asc' ? 'bi bi-sort-down' : 'bi bi-sort-up';\r\n }\r\n\r\n isSortColumn(columnKey: string): boolean {\r\n return this.sortState.key === columnKey;\r\n }\r\n\r\n goToPage(page: number): void {\r\n if (!this.isFeatureOn('pagination')) {\r\n return;\r\n }\r\n\r\n const bounded = Math.min(Math.max(page, 1), this.totalPages);\r\n if (bounded === this.currentPage) {\r\n return;\r\n }\r\n\r\n this.currentPage = bounded;\r\n this.pageChange.emit(this.currentPage);\r\n this.updatePagedRowsOnly();\r\n }\r\n\r\n getPaginationPages(): number[] {\r\n return Array.from({ length: this.totalPages }, (_, idx) => idx + 1);\r\n }\r\n\r\n isRowSelected(rowId: string): boolean {\r\n return this.selectedRows.has(rowId);\r\n }\r\n\r\n toggleRowSelection(row: InternalRow<RowData>, event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n if (input.checked) {\r\n this.selectedRows.add(row.id);\r\n } else {\r\n this.selectedRows.delete(row.id);\r\n }\r\n\r\n this.emitSelection();\r\n }\r\n\r\n toggleSelectAllCurrentPage(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n this.pagedRows.forEach((row) => {\r\n if (input.checked) {\r\n this.selectedRows.add(row.id);\r\n } else {\r\n this.selectedRows.delete(row.id);\r\n }\r\n });\r\n\r\n this.emitSelection();\r\n }\r\n\r\n isCurrentPageFullySelected(): boolean {\r\n if (!this.pagedRows.length) {\r\n return false;\r\n }\r\n\r\n return this.pagedRows.every((row) => this.selectedRows.has(row.id));\r\n }\r\n\r\n toggleExportMenu(event: Event): void {\r\n event.stopPropagation();\r\n this.isExportMenuOpen = !this.isExportMenuOpen;\r\n }\r\n\r\n onActionItemClick(actionIndex: number, row: InternalRow<RowData>, event: Event): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n if (!Number.isInteger(actionIndex) || actionIndex < 0) {\r\n return;\r\n }\r\n\r\n const action = this.mergedConfig.actions?.[actionIndex];\r\n if (!action) {\r\n return;\r\n }\r\n\r\n const rowIndex = this.filteredRows.findIndex((item) => item.id === row.id);\r\n this.actionSelected.emit({ action, row: row.data, rowIndex });\r\n }\r\n\r\n exportCSV(): void {\r\n this.isExportMenuOpen = false;\r\n const rows = this.getRowsForExport();\r\n this.exportTriggered.emit({ format: 'csv', rows });\r\n\r\n const headers = this.mergedColumns.map((column) => this.escapeCsv(column.label));\r\n const lines = rows.map((row) => {\r\n return this.mergedColumns\r\n .map((column) => this.escapeCsv(this.getCellTextValue(row, column)))\r\n .join(',');\r\n });\r\n\r\n const csv = [headers.join(','), ...lines].join('\\n');\r\n this.downloadFile(csv, `${this.getExportFileName()}.csv`, 'text/csv;charset=utf-8;');\r\n }\r\n\r\n exportExcel(): void {\r\n this.isExportMenuOpen = false;\r\n const rows = this.getRowsForExport();\r\n this.exportTriggered.emit({ format: 'excel', rows });\r\n\r\n const headerCells = this.mergedColumns.map((column) => `<th>${this.escapeHtml(column.label)}</th>`).join('');\r\n const bodyRows = rows\r\n .map((row) => {\r\n const cells = this.mergedColumns\r\n .map((column) => `<td>${this.escapeHtml(this.getCellTextValue(row, column))}</td>`)\r\n .join('');\r\n return `<tr>${cells}</tr>`;\r\n })\r\n .join('');\r\n\r\n const html = `<html><head><meta charset=\"UTF-8\"></head><body><table border=\"1\"><thead><tr>${headerCells}</tr></thead><tbody>${bodyRows}</tbody></table></body></html>`;\r\n this.downloadFile(html, `${this.getExportFileName()}.xls`, 'application/vnd.ms-excel;charset=utf-8;');\r\n }\r\n\r\n getRenderedCell(row: RowData, column: DataTableColumn<RowData>): string {\r\n if (typeof column.render === 'function') {\r\n return column.render(row);\r\n }\r\n\r\n const key = String(column.key);\r\n const value = row[key];\r\n return this.escapeHtml(value == null ? '' : String(value));\r\n }\r\n\r\n toColumnWidth(width: string | number | undefined): string {\r\n if (typeof width === 'number') {\r\n return `${width}px`;\r\n }\r\n\r\n if (typeof width === 'string' && width.trim()) {\r\n return width.trim();\r\n }\r\n\r\n return 'auto';\r\n }\r\n\r\n getColumnTooltip(column: DataTableColumn<RowData>): string {\r\n const label = String(column.label || 'Column');\r\n if (this.isFeatureOn('sorting') && column.sortable) {\r\n const key = String(column.key);\r\n if (this.sortState.key === key) {\r\n const direction = this.sortState.direction === 'asc' ? 'ascending' : 'descending';\r\n return `${label} (sorted ${direction})`;\r\n }\r\n return `${label} (click to sort)`;\r\n }\r\n return label;\r\n }\r\n\r\n getCellTooltip(row: RowData, column: DataTableColumn<RowData>): string {\r\n const value = this.getCellTextValue(row, column).trim();\r\n if (!value) {\r\n return String(column.label || 'Cell');\r\n }\r\n return value;\r\n }\r\n\r\n getColumnCount(): number {\r\n let count = this.mergedColumns.length;\r\n if (this.isFeatureOn('checkboxSelection')) {\r\n count += 1;\r\n }\r\n if (this.isFeatureOn('actions')) {\r\n count += 1;\r\n }\r\n return count;\r\n }\r\n\r\n getStartEntry(): number {\r\n if (!this.filteredRows.length) {\r\n return 0;\r\n }\r\n\r\n if (!this.isFeatureOn('pagination')) {\r\n return 1;\r\n }\r\n\r\n return (this.currentPage - 1) * this.rowsPerPage + 1;\r\n }\r\n\r\n getEndEntry(): number {\r\n if (!this.filteredRows.length) {\r\n return 0;\r\n }\r\n\r\n if (!this.isFeatureOn('pagination')) {\r\n return this.filteredRows.length;\r\n }\r\n\r\n return Math.min(this.currentPage * this.rowsPerPage, this.filteredRows.length);\r\n }\r\n\r\n private applyConfig(): void {\r\n const features = {\r\n ...DEFAULT_CONFIG.features,\r\n ...(this.config.features ?? {})\r\n };\r\n\r\n const exportOptions = {\r\n ...DEFAULT_CONFIG.exportOptions,\r\n ...(this.config.exportOptions ?? {})\r\n };\r\n\r\n const rowsPerPageOptions = (this.config.rowsPerPageOptions ?? DEFAULT_CONFIG.rowsPerPageOptions).filter(\r\n (item) => Number.isFinite(item) && item > 0\r\n );\r\n\r\n this.mergedConfig = {\r\n title: this.config.title ?? DEFAULT_CONFIG.title,\r\n features,\r\n rowsPerPageOptions: rowsPerPageOptions.length ? rowsPerPageOptions : [...DEFAULT_CONFIG.rowsPerPageOptions],\r\n defaultRowsPerPage: this.config.defaultRowsPerPage ?? DEFAULT_CONFIG.defaultRowsPerPage,\r\n exportOptions,\r\n actions: [...(this.config.actions ?? [])],\r\n columns: []\r\n };\r\n\r\n this.mergedColumns = [...(this.columns.length ? this.columns : (this.config.columns ?? []))];\r\n this.rowsPerPage = this.getInitialRowsPerPage();\r\n }\r\n\r\n private normalizeRows(): void {\r\n this.allRows = (Array.isArray(this.data) ? this.data : []).map((row, index) => {\r\n const rowId = row['id'];\r\n const id = rowId == null ? `row-${index + 1}` : String(rowId);\r\n return { id, data: row };\r\n });\r\n\r\n const validIds = new Set(this.allRows.map((row) => row.id));\r\n for (const selectedId of Array.from(this.selectedRows)) {\r\n if (!validIds.has(selectedId)) {\r\n this.selectedRows.delete(selectedId);\r\n }\r\n }\r\n }\r\n\r\n private applyFiltersSortAndPagination(): void {\r\n if (!this.isFeatureOn('searching') || !this.searchTerm) {\r\n this.filteredRows = [...this.allRows];\r\n } else {\r\n this.filteredRows = this.allRows.filter((row) => {\r\n const searchSpace = this.mergedColumns\r\n .map((column) => this.getCellTextValue(row.data, column).toLowerCase())\r\n .join(' ');\r\n return searchSpace.includes(this.searchTerm);\r\n });\r\n }\r\n\r\n if (this.isFeatureOn('sorting') && this.sortState.key) {\r\n const column = this.mergedColumns.find((item) => String(item.key) === this.sortState.key);\r\n if (column?.sortable) {\r\n this.filteredRows.sort((a, b) => {\r\n const aVal = this.getCellTextValue(a.data, column);\r\n const bVal = this.getCellTextValue(b.data, column);\r\n const compare = this.compareValues(aVal, bVal);\r\n return this.sortState.direction === 'asc' ? compare : -compare;\r\n });\r\n }\r\n }\r\n\r\n this.totalPages = this.isFeatureOn('pagination')\r\n ? Math.max(1, Math.ceil(this.filteredRows.length / this.rowsPerPage))\r\n : 1;\r\n\r\n if (this.currentPage > this.totalPages) {\r\n this.currentPage = this.totalPages;\r\n }\r\n\r\n this.updatePagedRowsOnly();\r\n this.emitSelection();\r\n }\r\n\r\n private updatePagedRowsOnly(): void {\r\n if (!this.isFeatureOn('pagination')) {\r\n this.pagedRows = [...this.filteredRows];\r\n return;\r\n }\r\n\r\n const start = (this.currentPage - 1) * this.rowsPerPage;\r\n this.pagedRows = this.filteredRows.slice(start, start + this.rowsPerPage);\r\n }\r\n\r\n private getCellTextValue(row: RowData, column: DataTableColumn<RowData>): string {\r\n const key = String(column.key);\r\n if (row[key] != null) {\r\n return String(row[key]);\r\n }\r\n\r\n const rendered = this.getRenderedCell(row, column);\r\n return this.stripHtml(rendered);\r\n }\r\n\r\n private compareValues(a: string, b: string): number {\r\n const aText = a.trim();\r\n const bText = b.trim();\r\n\r\n const aNum = this.parseStrictNumber(aText);\r\n const bNum = this.parseStrictNumber(bText);\r\n if (aNum !== null && bNum !== null) {\r\n return aNum - bNum;\r\n }\r\n\r\n const aDate = this.parseDateValue(aText);\r\n const bDate = this.parseDateValue(bText);\r\n if (aDate !== null && bDate !== null) {\r\n return aDate - bDate;\r\n }\r\n\r\n return aText.localeCompare(bText, undefined, { numeric: true, sensitivity: 'base' });\r\n }\r\n\r\n private parseStrictNumber(value: string): number | null {\r\n const normalized = value.replace(/[$,\\s]/g, '');\r\n if (!/^[-+]?\\d*\\.?\\d+$/.test(normalized)) {\r\n return null;\r\n }\r\n\r\n const numberValue = Number(normalized);\r\n return Number.isNaN(numberValue) ? null : numberValue;\r\n }\r\n\r\n private parseDateValue(value: string): number | null {\r\n const usDate = value.match(/^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{4})$/);\r\n if (usDate) {\r\n const month = Number(usDate[1]);\r\n const day = Number(usDate[2]);\r\n const year = Number(usDate[3]);\r\n const utc = Date.UTC(year, month - 1, day);\r\n return Number.isNaN(utc) ? null : utc;\r\n }\r\n\r\n const isoDate = value.match(/^(\\d{4})-(\\d{1,2})-(\\d{1,2})$/);\r\n if (isoDate) {\r\n const year = Number(isoDate[1]);\r\n const month = Number(isoDate[2]);\r\n const day = Number(isoDate[3]);\r\n const utc = Date.UTC(year, month - 1, day);\r\n return Number.isNaN(utc) ? null : utc;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private getRowsForExport(): RowData[] {\r\n const selected = this.getSelectedRows();\r\n if (selected.length) {\r\n return selected;\r\n }\r\n\r\n return this.filteredRows.map((item) => item.data);\r\n }\r\n\r\n private getExportFileName(): string {\r\n return this.mergedConfig.exportOptions?.fileName || 'datatable-export';\r\n }\r\n\r\n private downloadFile(content: string, fileName: string, mimeType: string): void {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n const blob = new Blob([content], { type: mimeType });\r\n const url = URL.createObjectURL(blob);\r\n const anchor = document.createElement('a');\r\n anchor.href = url;\r\n anchor.download = fileName;\r\n document.body.appendChild(anchor);\r\n anchor.click();\r\n document.body.removeChild(anchor);\r\n URL.revokeObjectURL(url);\r\n }\r\n\r\n private escapeCsv(value: string): string {\r\n if (/[\",\\n]/.test(value)) {\r\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n\r\n return value;\r\n }\r\n\r\n private stripHtml(input: string): string {\r\n if (typeof document === 'undefined') {\r\n return input;\r\n }\r\n\r\n const temp = document.createElement('div');\r\n temp.innerHTML = input;\r\n return temp.textContent || temp.innerText || '';\r\n }\r\n\r\n private escapeHtml(value: string): string {\r\n return String(value)\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#039;');\r\n }\r\n\r\n private getInitialRowsPerPage(): number {\r\n const options = this.mergedConfig.rowsPerPageOptions ?? DEFAULT_CONFIG.rowsPerPageOptions;\r\n const preferred = Number(this.mergedConfig.defaultRowsPerPage ?? DEFAULT_CONFIG.defaultRowsPerPage);\r\n return options.includes(preferred) ? preferred : options[0] ?? DEFAULT_CONFIG.defaultRowsPerPage;\r\n }\r\n\r\n private emitSelection(): void {\r\n this.selectionChange.emit(this.getSelectedRows());\r\n }\r\n\r\n closeMenus(): void {\r\n this.isExportMenuOpen = false;\r\n }\r\n\r\n}\r\n","<div class=\"ndt-card\" (click)=\"closeMenus()\">\r\n <div class=\"ndt-header\">\r\n <h3 class=\"ndt-title\" [attr.data-tooltip]=\"mergedConfig.title\">{{ mergedConfig.title }}</h3>\r\n </div>\r\n\r\n <div class=\"ndt-toolbar\">\r\n <div class=\"ndt-left-tools\">\r\n <ng-container *ngIf=\"isFeatureOn('export')\">\r\n <div class=\"ndt-dropdown\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"ndt-btn ndt-export-btn\" type=\"button\" data-tooltip=\"Export data\" data-tooltip-position=\"bottom\" (click)=\"toggleExportMenu($event)\">\r\n <i class=\"bi bi-download\"></i>\r\n <span>Export</span>\r\n <i class=\"bi bi-chevron-down ndt-chevron\"></i>\r\n </button>\r\n\r\n <ul class=\"ndt-dropdown-menu\" *ngIf=\"isExportMenuOpen\">\r\n <li *ngIf=\"isExportFormatEnabled('csv')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" data-tooltip=\"Download CSV\" data-tooltip-position=\"right\" (click)=\"exportCSV()\">\r\n <i class=\"bi bi-filetype-csv\"></i>\r\n <span>CSV</span>\r\n </button>\r\n </li>\r\n <li *ngIf=\"isExportFormatEnabled('excel')\">\r\n <button type=\"button\" class=\"ndt-dropdown-item\" data-tooltip=\"Download Excel\" data-tooltip-position=\"right\" (click)=\"exportExcel()\">\r\n <i class=\"bi bi-file-earmark-spreadsheet\"></i>\r\n <span>Excel (.xls)</span>\r\n </button>\r\n </li>\r\n </ul>\r\n </div>\r\n </ng-container>\r\n\r\n <label class=\"ndt-inline-label\" *ngIf=\"isFeatureOn('rowsPerPage') && isFeatureOn('pagination')\">\r\n Rows per page:\r\n <select data-tooltip=\"Rows per page\" [value]=\"rowsPerPage\" (change)=\"onRowsPerPageChange($event)\">\r\n <option *ngFor=\"let option of mergedConfig.rowsPerPageOptions || []\" [value]=\"option\" [attr.data-tooltip]=\"'Show ' + option + ' rows per page'\">{{ option }}</option>\r\n </select>\r\n </label>\r\n </div>\r\n\r\n <div class=\"ndt-right-tools\" *ngIf=\"isFeatureOn('searching')\">\r\n <input\r\n type=\"search\"\r\n placeholder=\"Search records\"\r\n data-tooltip=\"Search records\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearchInput($event)\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div class=\"ndt-table-wrap\">\r\n <table class=\"ndt-table\">\r\n <colgroup>\r\n <col *ngIf=\"isFeatureOn('checkboxSelection')\" style=\"width: 44px\" />\r\n <col *ngFor=\"let column of mergedColumns\" [style.width]=\"toColumnWidth(column.width)\" />\r\n <col *ngIf=\"isFeatureOn('actions')\" style=\"width: 78px\" />\r\n </colgroup>\r\n\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n data-tooltip=\"Select all rows on current page\"\r\n [checked]=\"isCurrentPageFullySelected()\"\r\n (change)=\"toggleSelectAllCurrentPage($event)\"\r\n />\r\n </th>\r\n <th\r\n *ngFor=\"let column of mergedColumns\"\r\n [class.ndt-sortable]=\"isFeatureOn('sorting') && !!column.sortable\"\r\n [attr.data-tooltip]=\"getColumnTooltip(column)\"\r\n data-tooltip-position=\"top\"\r\n (click)=\"toggleSort(column)\"\r\n >\r\n <span class=\"ndt-th-content\">\r\n <span class=\"ndt-th-label\">{{ column.label }}</span>\r\n <i\r\n *ngIf=\"isFeatureOn('sorting') && column.sortable\"\r\n [ngClass]=\"[\r\n 'ndt-sort-indicator',\r\n getSortIconClass(column.key.toString()),\r\n isSortColumn(column.key.toString()) ? 'active' : ''\r\n ]\"\r\n [attr.data-tooltip]=\"getColumnTooltip(column)\"\r\n data-tooltip-position=\"top\"\r\n ></i>\r\n </span>\r\n </th>\r\n <th *ngIf=\"isFeatureOn('actions')\" data-tooltip=\"Available row actions\" data-tooltip-position=\"top\">Actions</th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr *ngIf=\"!pagedRows.length\">\r\n <td [attr.colspan]=\"getColumnCount()\" class=\"ndt-empty\" data-tooltip=\"No records found\">No records found.</td>\r\n </tr>\r\n\r\n <tr *ngFor=\"let row of pagedRows\" [class.ndt-selected]=\"isRowSelected(row.id)\">\r\n <td *ngIf=\"isFeatureOn('checkboxSelection')\">\r\n <input\r\n type=\"checkbox\"\r\n [attr.data-tooltip]=\"'Select row ' + row.id\"\r\n [checked]=\"isRowSelected(row.id)\"\r\n (change)=\"toggleRowSelection(row, $event)\"\r\n />\r\n </td>\r\n\r\n <td\r\n *ngFor=\"let column of mergedColumns\"\r\n [attr.data-tooltip]=\"getCellTooltip(row.data, column)\"\r\n data-tooltip-position=\"bottom\"\r\n [innerHTML]=\"getRenderedCell(row.data, column)\">\r\n </td>\r\n\r\n <td *ngIf=\"isFeatureOn('actions')\" class=\"ndt-actions-cell\">\r\n <div class=\"ndt-action-icons\" (click)=\"$event.stopPropagation()\">\r\n <button\r\n *ngFor=\"let action of mergedConfig.actions || []; let i = index\"\r\n type=\"button\"\r\n class=\"ndt-actions-btn\"\r\n [class.ndt-danger]=\"!!action.danger\"\r\n [attr.data-tooltip]=\"action.label\"\r\n data-tooltip-position=\"top\"\r\n [attr.aria-label]=\"action.label\"\r\n (click)=\"onActionItemClick(i, row, $event)\"\r\n >\r\n <i *ngIf=\"action.icon\" [class]=\"action.icon\"></i>\r\n <span *ngIf=\"!action.icon\" class=\"ndt-action-fallback\">{{ action.label.charAt(0) }}</span>\r\n </button>\r\n </div>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div class=\"ndt-footer\">\r\n <div [attr.data-tooltip]=\"selectedRows.size + ' rows selected'\">\r\n {{ selectedRows.size }} selected\r\n </div>\r\n\r\n <div [attr.data-tooltip]=\"'Showing ' + getStartEntry() + ' to ' + getEndEntry() + ' of ' + filteredRows.length + ' entries'\">\r\n Showing {{ getStartEntry() }} to {{ getEndEntry() }} of {{ filteredRows.length }} entries\r\n </div>\r\n\r\n <ul class=\"ndt-pagination\" *ngIf=\"isFeatureOn('pagination') && totalPages > 1\">\r\n <li [class.disabled]=\"currentPage <= 1\">\r\n <button type=\"button\" class=\"ndt-page-link\" data-tooltip=\"Go to previous page\" data-tooltip-position=\"top\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage <= 1\">Prev</button>\r\n </li>\r\n <li *ngFor=\"let page of getPaginationPages()\" [class.active]=\"page === currentPage\">\r\n <button type=\"button\" class=\"ndt-page-link\" [attr.data-tooltip]=\"'Go to page ' + page\" data-tooltip-position=\"top\" (click)=\"goToPage(page)\">{{ page }}</button>\r\n </li>\r\n <li [class.disabled]=\"currentPage >= totalPages\">\r\n <button type=\"button\" class=\"ndt-page-link\" data-tooltip=\"Go to next page\" data-tooltip-position=\"top\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage >= totalPages\">Next</button>\r\n </li>\r\n </ul>\r\n </div>\r\n</div>\r\n","/*\r\n * Public API Surface of dynamic-datatable\r\n */\r\n\r\nexport * from './lib/dynamic-datatable.component';\r\nexport * from './lib/models';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
1
+ import { AfterViewInit, ElementRef, EventEmitter, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
2
  import { DataTableActionEvent, DataTableColumn, DataTableExportEvent, DynamicDataTableConfig } from './models';
3
3
  import { InternalSortState } from './dynamic-datatable.types';
4
4
  import * as i0 from "@angular/core";
@@ -7,7 +7,8 @@ interface InternalRow<T extends RowData = RowData> {
7
7
  id: string;
8
8
  data: T;
9
9
  }
10
- export declare class DynamicDatatableComponent implements OnChanges {
10
+ export declare class DynamicDatatableComponent implements OnChanges, AfterViewInit, OnDestroy {
11
+ private readonly hostRef;
11
12
  config: DynamicDataTableConfig;
12
13
  columns: DataTableColumn<RowData>[];
13
14
  data: RowData[];
@@ -28,6 +29,10 @@ export declare class DynamicDatatableComponent implements OnChanges {
28
29
  sortState: InternalSortState;
29
30
  selectedRows: Set<string>;
30
31
  isExportMenuOpen: boolean;
32
+ private tooltipManager;
33
+ constructor(hostRef: ElementRef<HTMLElement>);
34
+ ngAfterViewInit(): void;
35
+ ngOnDestroy(): void;
31
36
  ngOnChanges(_changes: SimpleChanges): void;
32
37
  refresh(): void;
33
38
  updateData(newData: RowData[]): void;
@@ -53,6 +58,8 @@ export declare class DynamicDatatableComponent implements OnChanges {
53
58
  exportExcel(): void;
54
59
  getRenderedCell(row: RowData, column: DataTableColumn<RowData>): string;
55
60
  toColumnWidth(width: string | number | undefined): string;
61
+ getColumnTooltip(column: DataTableColumn<RowData>): string;
62
+ getCellTooltip(row: RowData, column: DataTableColumn<RowData>): string;
56
63
  getColumnCount(): number;
57
64
  getStartEntry(): number;
58
65
  getEndEntry(): number;
@@ -0,0 +1,53 @@
1
+ type TooltipTrigger = 'hover' | 'click';
2
+ type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
3
+ interface TooltipConfig {
4
+ content?: string;
5
+ html?: string;
6
+ icon?: string;
7
+ trigger?: TooltipTrigger;
8
+ position?: TooltipPosition;
9
+ noArrow?: boolean;
10
+ allowHtml?: boolean;
11
+ offset?: number;
12
+ }
13
+ export declare class TooltipManager {
14
+ private readonly registry;
15
+ private readonly root;
16
+ private readonly documentRef;
17
+ private activeTarget;
18
+ private activeTooltipEl;
19
+ private readonly offset;
20
+ private readonly viewportPadding;
21
+ private readonly onMouseOverBound;
22
+ private readonly onMouseOutBound;
23
+ private readonly onFocusInBound;
24
+ private readonly onFocusOutBound;
25
+ private readonly onClickBound;
26
+ private readonly onDocumentClickBound;
27
+ private readonly onDocumentKeydownBound;
28
+ private readonly onWindowResizeBound;
29
+ private readonly onWindowScrollBound;
30
+ constructor(root: HTMLElement, documentRef?: Document);
31
+ init(): void;
32
+ destroy(): void;
33
+ register(element: HTMLElement, config: TooltipConfig): void;
34
+ private onMouseOver;
35
+ private onMouseOut;
36
+ private onFocusIn;
37
+ private onFocusOut;
38
+ private onClick;
39
+ private onDocumentClick;
40
+ private onDocumentKeydown;
41
+ private getTooltipTarget;
42
+ private getEntry;
43
+ private getTrigger;
44
+ private getPosition;
45
+ private getContent;
46
+ private show;
47
+ private hide;
48
+ private reposition;
49
+ private positionTooltip;
50
+ private pickPlacement;
51
+ private computeCoords;
52
+ }
53
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ng-dynamic-datatable",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Config-driven Angular DataTable library with sorting, searching, pagination, selection, and export.",
5
5
  "keywords": [
6
6
  "angular",