commons-shared-web-ui 0.0.65 → 0.0.66
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.
|
@@ -13249,6 +13249,9 @@ class SmartTableComponent {
|
|
|
13249
13249
|
router;
|
|
13250
13250
|
cdr;
|
|
13251
13251
|
ngZone;
|
|
13252
|
+
static instanceCounter = 0;
|
|
13253
|
+
/** Unique per-instance name for the row-selection radio group (see `isMultiSelect`). */
|
|
13254
|
+
radioGroupName = `st-row-select-${SmartTableComponent.instanceCounter++}`;
|
|
13252
13255
|
config;
|
|
13253
13256
|
/**
|
|
13254
13257
|
* External data mode: pass table rows directly from the parent.
|
|
@@ -13911,6 +13914,10 @@ class SmartTableComponent {
|
|
|
13911
13914
|
});
|
|
13912
13915
|
}
|
|
13913
13916
|
// --- Selection ---
|
|
13917
|
+
/** `false` (via `config.multiSelect`) switches row selection from checkboxes to a radio button per row. */
|
|
13918
|
+
get isMultiSelect() {
|
|
13919
|
+
return this.config?.multiSelect !== false;
|
|
13920
|
+
}
|
|
13914
13921
|
onSelectAll(event) {
|
|
13915
13922
|
const checked = event.target.checked;
|
|
13916
13923
|
this.data.forEach(row => row.selected = checked);
|
|
@@ -13919,6 +13926,12 @@ class SmartTableComponent {
|
|
|
13919
13926
|
onRowSelect(row) {
|
|
13920
13927
|
this.updateSelectedRows();
|
|
13921
13928
|
}
|
|
13929
|
+
/** Single-select mode: the newly picked row replaces the entire selection, including across pages. */
|
|
13930
|
+
onRowSelectSingle(row) {
|
|
13931
|
+
this.data.forEach(r => r.selected = (r === row));
|
|
13932
|
+
this.selectedRows = [row];
|
|
13933
|
+
this.rowSelect.emit(this.selectedRows);
|
|
13934
|
+
}
|
|
13922
13935
|
updateSelectedRows() {
|
|
13923
13936
|
const idField = this.config.rowIdField || 'id';
|
|
13924
13937
|
// 1. Identify rows from the global selection that are NOT on the current page
|
|
@@ -14329,11 +14342,11 @@ class SmartTableComponent {
|
|
|
14329
14342
|
});
|
|
14330
14343
|
}
|
|
14331
14344
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, deps: [{ token: i3.HttpClient }, { token: i1$4.Router }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
14332
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config", tableData: "tableData", totalItemsCount: "totalItemsCount", selectedRows: "selectedRows" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", columnClick: "columnClick", sortChange: "sortChange", pageChange: "pageChange", searchChange: "searchChange", rowSave: "rowSave" }, host: { listeners: { "document:click": "closeDropdown()" } }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of getVisibleActions(config.topBarButtons)\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of getVisibleActions(config.actions, row); let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, getVisibleActions(action.items, row), row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (getVisibleActions(config.actions).length > 0 ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.smart-table-wrapper{font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08))}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f5f5f5);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th{padding:.4rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #e63e30);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}.st-table-container{font-size:13px}}.st-table-container{position:relative}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\n"], dependencies: [{ 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"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: PaginationComponent, selector: "lib-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "pageSizeOptions", "theme", "labels"], outputs: ["pageChange", "itemsPerPageChange"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: i7.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i7.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen", "confirmDisabled", "confirmLoading"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] });
|
|
14345
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config", tableData: "tableData", totalItemsCount: "totalItemsCount", selectedRows: "selectedRows" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", columnClick: "columnClick", sortChange: "sortChange", pageChange: "pageChange", searchChange: "searchChange", rowSave: "rowSave" }, host: { listeners: { "document:click": "closeDropdown()" } }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of getVisibleActions(config.topBarButtons)\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" *ngIf=\"isMultiSelect\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input *ngIf=\"isMultiSelect\" type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n <input *ngIf=\"!isMultiSelect\" type=\"radio\" [name]=\"radioGroupName\" [checked]=\"row.selected\" (change)=\"onRowSelectSingle(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of getVisibleActions(config.actions, row); let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, getVisibleActions(action.items, row), row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (getVisibleActions(config.actions).length > 0 ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.smart-table-wrapper{font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08))}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f5f5f5);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th{padding:.4rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox],input[type=radio]{accent-color:var(--st-checkbox-color, #e63e30);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}.st-table-container{font-size:13px}}.st-table-container{position:relative}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\n"], dependencies: [{ 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"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: PaginationComponent, selector: "lib-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "pageSizeOptions", "theme", "labels"], outputs: ["pageChange", "itemsPerPageChange"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: i7.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i7.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen", "confirmDisabled", "confirmLoading"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] });
|
|
14333
14346
|
}
|
|
14334
14347
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, decorators: [{
|
|
14335
14348
|
type: Component,
|
|
14336
|
-
args: [{ selector: 'lib-smart-table', standalone: false, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of getVisibleActions(config.topBarButtons)\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of getVisibleActions(config.actions, row); let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, getVisibleActions(action.items, row), row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (getVisibleActions(config.actions).length > 0 ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.smart-table-wrapper{font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08))}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f5f5f5);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th{padding:.4rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #e63e30);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}.st-table-container{font-size:13px}}.st-table-container{position:relative}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\n"] }]
|
|
14349
|
+
args: [{ selector: 'lib-smart-table', standalone: false, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of getVisibleActions(config.topBarButtons)\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" *ngIf=\"isMultiSelect\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input *ngIf=\"isMultiSelect\" type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n <input *ngIf=\"!isMultiSelect\" type=\"radio\" [name]=\"radioGroupName\" [checked]=\"row.selected\" (change)=\"onRowSelectSingle(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"getVisibleActions(config.actions).length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of getVisibleActions(config.actions, row); let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, getVisibleActions(action.items, row), row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (getVisibleActions(config.actions).length > 0 ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.smart-table-wrapper{font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08))}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f5f5f5);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th{padding:.4rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr .clickable-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox],input[type=radio]{accent-color:var(--st-checkbox-color, #e63e30);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}.st-table-container{font-size:13px}}.st-table-container{position:relative}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\n"] }]
|
|
14337
14350
|
}], ctorParameters: () => [{ type: i3.HttpClient }, { type: i1$4.Router }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], propDecorators: { config: [{
|
|
14338
14351
|
type: Input
|
|
14339
14352
|
}], tableData: [{
|