@aquera/ngx-smart-table 0.0.17-patch-0.6 → 0.0.17-patch-0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/editors/nile-chip-editor.mjs +5 -2
- package/esm2020/lib/editors/nile-select-editor.mjs +119 -6
- package/esm2020/lib/renderer/components/st-cell/st-cell.component.mjs +9 -3
- package/esm2020/lib/renderer/components/st-column-menu/st-column-menu.component.mjs +36 -17
- package/esm2020/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.mjs +34 -27
- package/esm2020/lib/renderer/components/st-table/st-table.component.mjs +5 -5
- package/fesm2015/aquera-ngx-smart-table.mjs +212 -58
- package/fesm2015/aquera-ngx-smart-table.mjs.map +1 -1
- package/fesm2020/aquera-ngx-smart-table.mjs +201 -53
- package/fesm2020/aquera-ngx-smart-table.mjs.map +1 -1
- package/lib/editors/nile-chip-editor.d.ts +1 -0
- package/lib/editors/nile-select-editor.d.ts +11 -0
- package/lib/renderer/components/st-column-menu/st-column-menu.component.d.ts +4 -2
- package/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.d.ts +4 -2
- package/lib/renderer/components/st-table/st-table.component.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BehaviorSubject, Subject, isObservable, fromEvent, merge } from 'rxjs';
|
|
2
2
|
import { distinctUntilChanged, map, throttleTime, takeUntil, tap, debounceTime } from 'rxjs/operators';
|
|
3
|
+
import { __awaiter } from 'tslib';
|
|
3
4
|
import * as i0 from '@angular/core';
|
|
4
5
|
import { EventEmitter, ElementRef, Component, Input, Output, ViewChild, HostListener, Injectable, ChangeDetectionStrategy, Directive, NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
5
6
|
import * as i1 from '@angular/common';
|
|
@@ -7,7 +8,6 @@ import { CommonModule } from '@angular/common';
|
|
|
7
8
|
import Ajv from 'ajv';
|
|
8
9
|
import * as i1$1 from '@angular/forms';
|
|
9
10
|
import { Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
10
|
-
import { __awaiter } from 'tslib';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Base type definitions for cell configuration model
|
|
@@ -3678,10 +3678,6 @@ class NileInputEditor {
|
|
|
3678
3678
|
}
|
|
3679
3679
|
}
|
|
3680
3680
|
|
|
3681
|
-
/**
|
|
3682
|
-
* Custom editor using NileSelect from @aquera/nile-elements
|
|
3683
|
-
* This demonstrates how to create dropdown/select editors for ngx-smart-table
|
|
3684
|
-
*/
|
|
3685
3681
|
/**
|
|
3686
3682
|
* Inject global styles for nile-select dropdown height limit
|
|
3687
3683
|
*/
|
|
@@ -3814,16 +3810,137 @@ class NileSelectEditor {
|
|
|
3814
3810
|
// Clear container and append select
|
|
3815
3811
|
context.container.innerHTML = '';
|
|
3816
3812
|
context.container.appendChild(this.select);
|
|
3817
|
-
// Focus
|
|
3813
|
+
// Focus after mount; open dropdown only once nile-popup exists (avoids null this.popup in nile-select)
|
|
3814
|
+
const openOnEdit = this.options.openDropdownOnEdit !== false;
|
|
3818
3815
|
setTimeout(() => {
|
|
3819
|
-
|
|
3816
|
+
void this.activateSelectAfterMount(openOnEdit);
|
|
3817
|
+
}, 50);
|
|
3818
|
+
}
|
|
3819
|
+
activateSelectAfterMount(openOnEdit) {
|
|
3820
|
+
var _a;
|
|
3821
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3820
3822
|
try {
|
|
3821
3823
|
(_a = this.select) === null || _a === void 0 ? void 0 : _a.focus();
|
|
3822
3824
|
}
|
|
3823
|
-
catch (
|
|
3824
|
-
//
|
|
3825
|
+
catch (_b) {
|
|
3826
|
+
// ignore
|
|
3825
3827
|
}
|
|
3826
|
-
|
|
3828
|
+
if (!openOnEdit || !this.select || this.options.disabled) {
|
|
3829
|
+
return;
|
|
3830
|
+
}
|
|
3831
|
+
yield this.openNileSelectDropdownSafely();
|
|
3832
|
+
});
|
|
3833
|
+
}
|
|
3834
|
+
/** Lit @query('nile-popup') / .select — must exist before handleOpenChange touches this.popup.popup */
|
|
3835
|
+
isNileSelectPopupMounted(select) {
|
|
3836
|
+
var _a;
|
|
3837
|
+
return !!((_a = select.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('nile-popup'));
|
|
3838
|
+
}
|
|
3839
|
+
invokeShowHandlingPromise(host) {
|
|
3840
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3841
|
+
if (typeof host.show !== 'function') {
|
|
3842
|
+
return;
|
|
3843
|
+
}
|
|
3844
|
+
try {
|
|
3845
|
+
const out = host.show();
|
|
3846
|
+
if (out != null && typeof out.then === 'function') {
|
|
3847
|
+
yield out.catch(() => undefined);
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
catch (_a) {
|
|
3851
|
+
// sync throw from show()
|
|
3852
|
+
}
|
|
3853
|
+
});
|
|
3854
|
+
}
|
|
3855
|
+
openNileSelectDropdownSafely() {
|
|
3856
|
+
var _a, _b, _c, _d;
|
|
3857
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3858
|
+
const select = this.select;
|
|
3859
|
+
if (!select) {
|
|
3860
|
+
return;
|
|
3861
|
+
}
|
|
3862
|
+
try {
|
|
3863
|
+
yield customElements.whenDefined('nile-select');
|
|
3864
|
+
}
|
|
3865
|
+
catch (_e) {
|
|
3866
|
+
// ignore
|
|
3867
|
+
}
|
|
3868
|
+
if (this.options.enableVirtualScroll) {
|
|
3869
|
+
try {
|
|
3870
|
+
yield customElements.whenDefined('nile-virtual-select');
|
|
3871
|
+
}
|
|
3872
|
+
catch (_f) {
|
|
3873
|
+
// ignore — not registered in all environments
|
|
3874
|
+
}
|
|
3875
|
+
// Same idea as nile-popup: inner host may not exist until Lit finishes a pass (or several).
|
|
3876
|
+
const maxVirtualWaitPasses = 50;
|
|
3877
|
+
for (let i = 0; i < maxVirtualWaitPasses; i++) {
|
|
3878
|
+
const vs = (_a = select.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('nile-virtual-select');
|
|
3879
|
+
if (vs) {
|
|
3880
|
+
yield this.invokeShowHandlingPromise(vs);
|
|
3881
|
+
return;
|
|
3882
|
+
}
|
|
3883
|
+
const lit = select;
|
|
3884
|
+
if ((_b = lit.updateComplete) === null || _b === void 0 ? void 0 : _b.then) {
|
|
3885
|
+
try {
|
|
3886
|
+
yield lit.updateComplete;
|
|
3887
|
+
}
|
|
3888
|
+
catch (_g) {
|
|
3889
|
+
// ignore
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
yield new Promise(resolve => requestAnimationFrame(() => resolve()));
|
|
3893
|
+
}
|
|
3894
|
+
return;
|
|
3895
|
+
}
|
|
3896
|
+
const maxWaitPasses = 50;
|
|
3897
|
+
for (let i = 0; i < maxWaitPasses; i++) {
|
|
3898
|
+
if (this.isNileSelectPopupMounted(select)) {
|
|
3899
|
+
break;
|
|
3900
|
+
}
|
|
3901
|
+
const lit = select;
|
|
3902
|
+
if ((_c = lit.updateComplete) === null || _c === void 0 ? void 0 : _c.then) {
|
|
3903
|
+
try {
|
|
3904
|
+
yield lit.updateComplete;
|
|
3905
|
+
}
|
|
3906
|
+
catch (_h) {
|
|
3907
|
+
// ignore
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
yield new Promise(resolve => requestAnimationFrame(() => resolve()));
|
|
3911
|
+
}
|
|
3912
|
+
if (!this.isNileSelectPopupMounted(select)) {
|
|
3913
|
+
return;
|
|
3914
|
+
}
|
|
3915
|
+
const host = select;
|
|
3916
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
3917
|
+
if (!this.isNileSelectPopupMounted(select)) {
|
|
3918
|
+
return;
|
|
3919
|
+
}
|
|
3920
|
+
try {
|
|
3921
|
+
if (typeof host.show === 'function') {
|
|
3922
|
+
yield this.invokeShowHandlingPromise(host);
|
|
3923
|
+
}
|
|
3924
|
+
else {
|
|
3925
|
+
host.open = true;
|
|
3926
|
+
}
|
|
3927
|
+
return;
|
|
3928
|
+
}
|
|
3929
|
+
catch (_j) {
|
|
3930
|
+
// ignore
|
|
3931
|
+
}
|
|
3932
|
+
yield new Promise(resolve => setTimeout(resolve, 40));
|
|
3933
|
+
const lit = select;
|
|
3934
|
+
if ((_d = lit.updateComplete) === null || _d === void 0 ? void 0 : _d.then) {
|
|
3935
|
+
try {
|
|
3936
|
+
yield lit.updateComplete;
|
|
3937
|
+
}
|
|
3938
|
+
catch (_k) {
|
|
3939
|
+
// ignore
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
}
|
|
3943
|
+
});
|
|
3827
3944
|
}
|
|
3828
3945
|
/**
|
|
3829
3946
|
* Set the initial value for the select
|
|
@@ -4898,6 +5015,7 @@ class NileChipEditor {
|
|
|
4898
5015
|
this.acceptsInitialKeypress = false;
|
|
4899
5016
|
this.eventListeners = [];
|
|
4900
5017
|
this.trackedValues = [];
|
|
5018
|
+
this.hasChangeOccurred = false;
|
|
4901
5019
|
}
|
|
4902
5020
|
edit(context) {
|
|
4903
5021
|
var _a, _b;
|
|
@@ -5054,6 +5172,7 @@ class NileChipEditor {
|
|
|
5054
5172
|
const detail = e.detail;
|
|
5055
5173
|
const newValue = Array.isArray(detail === null || detail === void 0 ? void 0 : detail.value) ? [...detail.value] : (((_a = this.chip) === null || _a === void 0 ? void 0 : _a.value) ? [...this.chip.value] : []);
|
|
5056
5174
|
this.trackedValues = newValue;
|
|
5175
|
+
this.hasChangeOccurred = true;
|
|
5057
5176
|
context.onChange(newValue);
|
|
5058
5177
|
});
|
|
5059
5178
|
// Keyboard handling on the chip element
|
|
@@ -5123,6 +5242,7 @@ class NileChipEditor {
|
|
|
5123
5242
|
this.chip = undefined;
|
|
5124
5243
|
this.cellContainer = undefined;
|
|
5125
5244
|
this.trackedValues = [];
|
|
5245
|
+
this.hasChangeOccurred = false;
|
|
5126
5246
|
}
|
|
5127
5247
|
focus() {
|
|
5128
5248
|
var _a;
|
|
@@ -5132,7 +5252,7 @@ class NileChipEditor {
|
|
|
5132
5252
|
catch ( /* ignore */_b) { /* ignore */ }
|
|
5133
5253
|
}
|
|
5134
5254
|
getCurrentValue() {
|
|
5135
|
-
if (this.
|
|
5255
|
+
if (this.hasChangeOccurred) {
|
|
5136
5256
|
return [...this.trackedValues];
|
|
5137
5257
|
}
|
|
5138
5258
|
if (!this.chip)
|
|
@@ -6330,8 +6450,14 @@ class StCellComponent {
|
|
|
6330
6450
|
}
|
|
6331
6451
|
}
|
|
6332
6452
|
onCellClick() {
|
|
6333
|
-
//
|
|
6334
|
-
//
|
|
6453
|
+
// First click: parent <td> focuses this cell (bubbles after this handler).
|
|
6454
|
+
// Second click while already focused: enter edit (spreadsheet-style).
|
|
6455
|
+
if (this.isEditable &&
|
|
6456
|
+
!this.cellLoading &&
|
|
6457
|
+
!this.cell.isEditing() &&
|
|
6458
|
+
this.cell.isFocused()) {
|
|
6459
|
+
this.startEdit();
|
|
6460
|
+
}
|
|
6335
6461
|
}
|
|
6336
6462
|
onCellDoubleClick() {
|
|
6337
6463
|
// Double-click starts editing regardless of EditMode (Excel-like behavior)
|
|
@@ -8056,7 +8182,7 @@ class StColumnMenuDropdownComponent {
|
|
|
8056
8182
|
*/
|
|
8057
8183
|
this.isOpen = false;
|
|
8058
8184
|
/**
|
|
8059
|
-
* Position of the dropdown (x, y coordinates)
|
|
8185
|
+
* Position of the dropdown (x, y coordinates, triggerTop for flip positioning)
|
|
8060
8186
|
*/
|
|
8061
8187
|
this.position = { x: 0, y: 0 };
|
|
8062
8188
|
/**
|
|
@@ -8170,25 +8296,42 @@ class StColumnMenuDropdownComponent {
|
|
|
8170
8296
|
this.dropdownStyle = {};
|
|
8171
8297
|
return;
|
|
8172
8298
|
}
|
|
8173
|
-
const viewportWidth = window.innerWidth;
|
|
8174
|
-
const viewportHeight = window.innerHeight;
|
|
8175
|
-
const dropdownWidth = 280; // Approximate dropdown width
|
|
8176
|
-
const dropdownHeight = 300; // Approximate max dropdown height
|
|
8177
8299
|
let { x, y } = this.position;
|
|
8178
|
-
//
|
|
8179
|
-
if (x + dropdownWidth > viewportWidth) {
|
|
8180
|
-
x = Math.max(10, viewportWidth - dropdownWidth - 10);
|
|
8181
|
-
}
|
|
8182
|
-
// Adjust vertical position if dropdown would overflow
|
|
8183
|
-
if (y + dropdownHeight > viewportHeight) {
|
|
8184
|
-
y = Math.max(10, viewportHeight - dropdownHeight - 10);
|
|
8185
|
-
}
|
|
8300
|
+
// Render at initial position first
|
|
8186
8301
|
this.dropdownStyle = {
|
|
8187
8302
|
position: 'fixed',
|
|
8188
8303
|
left: `${x}px`,
|
|
8189
8304
|
top: `${y}px`,
|
|
8190
|
-
'z-index': 9999
|
|
8305
|
+
'z-index': 9999,
|
|
8306
|
+
visibility: 'hidden'
|
|
8191
8307
|
};
|
|
8308
|
+
// After rendering, measure actual size and adjust if needed
|
|
8309
|
+
requestAnimationFrame(() => {
|
|
8310
|
+
var _a, _b;
|
|
8311
|
+
const viewportWidth = window.innerWidth;
|
|
8312
|
+
const viewportHeight = window.innerHeight;
|
|
8313
|
+
const el = (_a = this.dropdownPanel) === null || _a === void 0 ? void 0 : _a.nativeElement;
|
|
8314
|
+
const dropdownWidth = (el === null || el === void 0 ? void 0 : el.offsetWidth) || 280;
|
|
8315
|
+
const dropdownHeight = (el === null || el === void 0 ? void 0 : el.offsetHeight) || 200;
|
|
8316
|
+
// Adjust horizontal position if dropdown would overflow
|
|
8317
|
+
if (x + dropdownWidth > viewportWidth) {
|
|
8318
|
+
x = Math.max(10, viewportWidth - dropdownWidth - 10);
|
|
8319
|
+
}
|
|
8320
|
+
// Adjust vertical position — flip above the trigger if it overflows bottom
|
|
8321
|
+
if (y + dropdownHeight > viewportHeight) {
|
|
8322
|
+
const triggerTop = (_b = this.position.triggerTop) !== null && _b !== void 0 ? _b : this.position.y;
|
|
8323
|
+
y = triggerTop - dropdownHeight - 4;
|
|
8324
|
+
}
|
|
8325
|
+
// Clamp to viewport edges
|
|
8326
|
+
x = Math.max(10, x);
|
|
8327
|
+
y = Math.max(10, y);
|
|
8328
|
+
this.dropdownStyle = {
|
|
8329
|
+
position: 'fixed',
|
|
8330
|
+
left: `${x}px`,
|
|
8331
|
+
top: `${y}px`,
|
|
8332
|
+
'z-index': 9999
|
|
8333
|
+
};
|
|
8334
|
+
});
|
|
8192
8335
|
}
|
|
8193
8336
|
/**
|
|
8194
8337
|
* Check if an action is disabled
|
|
@@ -8256,10 +8399,10 @@ class StColumnMenuDropdownComponent {
|
|
|
8256
8399
|
}
|
|
8257
8400
|
}
|
|
8258
8401
|
StColumnMenuDropdownComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StColumnMenuDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8259
|
-
StColumnMenuDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StColumnMenuDropdownComponent, selector: "st-column-menu-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "click": "onBackdropClick($event)" } }, viewQueries: [{ propertyName: "filterPopup", first: true, predicate: ["filterPopup"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"], components: [{ type: StColumnFilterComponent, selector: "st-column-filter", inputs: ["column", "tableState", "columnIndex", "isFirstColumn", "isLastColumn", "isOpen", "filterContext"], outputs: ["closed", "filterApplied", "filterCleared"] }], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
8402
|
+
StColumnMenuDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StColumnMenuDropdownComponent, selector: "st-column-menu-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "click": "onBackdropClick($event)" } }, viewQueries: [{ propertyName: "filterPopup", first: true, predicate: ["filterPopup"], descendants: true }, { propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"], components: [{ type: StColumnFilterComponent, selector: "st-column-filter", inputs: ["column", "tableState", "columnIndex", "isFirstColumn", "isLastColumn", "isOpen", "filterContext"], outputs: ["closed", "filterApplied", "filterCleared"] }], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
8260
8403
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StColumnMenuDropdownComponent, decorators: [{
|
|
8261
8404
|
type: Component,
|
|
8262
|
-
args: [{ selector: 'st-column-menu-dropdown', template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"] }]
|
|
8405
|
+
args: [{ selector: 'st-column-menu-dropdown', template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"] }]
|
|
8263
8406
|
}], propDecorators: { isOpen: [{
|
|
8264
8407
|
type: Input
|
|
8265
8408
|
}], position: [{
|
|
@@ -8273,6 +8416,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
8273
8416
|
}], filterPopup: [{
|
|
8274
8417
|
type: ViewChild,
|
|
8275
8418
|
args: ['filterPopup']
|
|
8419
|
+
}], dropdownPanel: [{
|
|
8420
|
+
type: ViewChild,
|
|
8421
|
+
args: ['dropdownPanel']
|
|
8276
8422
|
}], onBackdropClick: [{
|
|
8277
8423
|
type: HostListener,
|
|
8278
8424
|
args: ['click', ['$event']]
|
|
@@ -8285,7 +8431,7 @@ class StRowActionsDropdownComponent {
|
|
|
8285
8431
|
*/
|
|
8286
8432
|
this.isOpen = false;
|
|
8287
8433
|
/**
|
|
8288
|
-
* Position of the dropdown (x, y coordinates)
|
|
8434
|
+
* Position of the dropdown (x, y coordinates, triggerTop for flip positioning)
|
|
8289
8435
|
*/
|
|
8290
8436
|
this.position = { x: 0, y: 0 };
|
|
8291
8437
|
/**
|
|
@@ -8340,35 +8486,40 @@ class StRowActionsDropdownComponent {
|
|
|
8340
8486
|
this.dropdownStyle = {};
|
|
8341
8487
|
return;
|
|
8342
8488
|
}
|
|
8343
|
-
const DROPDOWN_WIDTH = 200; // Approximate width
|
|
8344
|
-
const DROPDOWN_HEIGHT = this.visibleActions.length * 40 + 16; // Approximate height
|
|
8345
|
-
const viewportWidth = window.innerWidth;
|
|
8346
|
-
const viewportHeight = window.innerHeight;
|
|
8347
8489
|
let left = this.position.x;
|
|
8348
8490
|
let top = this.position.y;
|
|
8349
|
-
//
|
|
8350
|
-
if (left + DROPDOWN_WIDTH > viewportWidth) {
|
|
8351
|
-
left = viewportWidth - DROPDOWN_WIDTH - 10;
|
|
8352
|
-
}
|
|
8353
|
-
// Check if dropdown would overflow bottom edge
|
|
8354
|
-
if (top + DROPDOWN_HEIGHT > viewportHeight) {
|
|
8355
|
-
// Position above the trigger
|
|
8356
|
-
top = this.position.y - DROPDOWN_HEIGHT;
|
|
8357
|
-
}
|
|
8358
|
-
// Ensure dropdown doesn't go off-screen on the left
|
|
8359
|
-
if (left < 10) {
|
|
8360
|
-
left = 10;
|
|
8361
|
-
}
|
|
8362
|
-
// Ensure dropdown doesn't go off-screen on the top
|
|
8363
|
-
if (top < 10) {
|
|
8364
|
-
top = 10;
|
|
8365
|
-
}
|
|
8491
|
+
// Render at initial position first (hidden until measured)
|
|
8366
8492
|
this.dropdownStyle = {
|
|
8367
8493
|
position: 'fixed',
|
|
8368
8494
|
left: `${left}px`,
|
|
8369
8495
|
top: `${top}px`,
|
|
8370
|
-
zIndex: TableZIndex.ROW_ACTIONS_DROPDOWN
|
|
8496
|
+
zIndex: TableZIndex.ROW_ACTIONS_DROPDOWN,
|
|
8497
|
+
visibility: 'hidden'
|
|
8371
8498
|
};
|
|
8499
|
+
// After rendering, measure actual size and adjust position directly on the DOM
|
|
8500
|
+
// (OnPush change detection won't pick up property changes inside requestAnimationFrame)
|
|
8501
|
+
requestAnimationFrame(() => {
|
|
8502
|
+
var _a, _b;
|
|
8503
|
+
const el = (_a = this.dropdownPanel) === null || _a === void 0 ? void 0 : _a.nativeElement;
|
|
8504
|
+
if (!el)
|
|
8505
|
+
return;
|
|
8506
|
+
const viewportWidth = window.innerWidth;
|
|
8507
|
+
const viewportHeight = window.innerHeight;
|
|
8508
|
+
const dropdownWidth = el.offsetWidth || 200;
|
|
8509
|
+
const dropdownHeight = el.offsetHeight || (this.visibleActions.length * 40 + 16);
|
|
8510
|
+
if (left + dropdownWidth > viewportWidth) {
|
|
8511
|
+
left = viewportWidth - dropdownWidth - 10;
|
|
8512
|
+
}
|
|
8513
|
+
if (top + dropdownHeight > viewportHeight) {
|
|
8514
|
+
const triggerTop = (_b = this.position.triggerTop) !== null && _b !== void 0 ? _b : this.position.y;
|
|
8515
|
+
top = triggerTop - dropdownHeight - 4;
|
|
8516
|
+
}
|
|
8517
|
+
left = Math.max(10, left);
|
|
8518
|
+
top = Math.max(10, top);
|
|
8519
|
+
el.style.left = `${left}px`;
|
|
8520
|
+
el.style.top = `${top}px`;
|
|
8521
|
+
el.style.visibility = 'visible';
|
|
8522
|
+
});
|
|
8372
8523
|
}
|
|
8373
8524
|
/**
|
|
8374
8525
|
* Handle action click
|
|
@@ -8422,10 +8573,10 @@ class StRowActionsDropdownComponent {
|
|
|
8422
8573
|
}
|
|
8423
8574
|
}
|
|
8424
8575
|
StRowActionsDropdownComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StRowActionsDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8425
|
-
StRowActionsDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StRowActionsDropdownComponent, selector: "st-row-actions-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\"
|
|
8576
|
+
StRowActionsDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StRowActionsDropdownComponent, selector: "st-row-actions-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)" } }, viewQueries: [{ propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\">\n <ng-container *ngFor=\"let action of visibleActions\">\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n <nile-icon *ngIf=\"action.icon\" size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </ng-container>\n \n <nile-menu-item *ngIf=\"visibleActions.length === 0\">No actions available</nile-menu-item>\n </nile-menu>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:transparent;pointer-events:auto;z-index:9998}.dropdown-menu{position:fixed;background-color:#fff;box-shadow:0 5px 15px #0000004d,0 0 0 1px #0000001a;overflow:hidden;pointer-events:auto;z-index:9999}.action-icon{display:flex;align-items:center;justify-content:center;font-size:16px;width:20px;flex-shrink:0}.action-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-empty{padding:16px;text-align:center;color:#a0aec0;font-size:14px;font-style:italic}nile-menu{height:fit-content}\n"], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8426
8577
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StRowActionsDropdownComponent, decorators: [{
|
|
8427
8578
|
type: Component,
|
|
8428
|
-
args: [{ selector: 'st-row-actions-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\"
|
|
8579
|
+
args: [{ selector: 'st-row-actions-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\">\n <ng-container *ngFor=\"let action of visibleActions\">\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n <nile-icon *ngIf=\"action.icon\" size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </ng-container>\n \n <nile-menu-item *ngIf=\"visibleActions.length === 0\">No actions available</nile-menu-item>\n </nile-menu>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:transparent;pointer-events:auto;z-index:9998}.dropdown-menu{position:fixed;background-color:#fff;box-shadow:0 5px 15px #0000004d,0 0 0 1px #0000001a;overflow:hidden;pointer-events:auto;z-index:9999}.action-icon{display:flex;align-items:center;justify-content:center;font-size:16px;width:20px;flex-shrink:0}.action-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-empty{padding:16px;text-align:center;color:#a0aec0;font-size:14px;font-style:italic}nile-menu{height:fit-content}\n"] }]
|
|
8429
8580
|
}], propDecorators: { isOpen: [{
|
|
8430
8581
|
type: Input
|
|
8431
8582
|
}], position: [{
|
|
@@ -8436,6 +8587,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
8436
8587
|
type: Output
|
|
8437
8588
|
}], closed: [{
|
|
8438
8589
|
type: Output
|
|
8590
|
+
}], dropdownPanel: [{
|
|
8591
|
+
type: ViewChild,
|
|
8592
|
+
args: ['dropdownPanel']
|
|
8439
8593
|
}], onEscapeKey: [{
|
|
8440
8594
|
type: HostListener,
|
|
8441
8595
|
args: ['document:keydown.escape', ['$event']]
|
|
@@ -9730,10 +9884,10 @@ class StTableComponent {
|
|
|
9730
9884
|
event.stopPropagation();
|
|
9731
9885
|
const target = event.currentTarget;
|
|
9732
9886
|
const rect = target.getBoundingClientRect();
|
|
9733
|
-
// Calculate position (below the button by default)
|
|
9734
9887
|
const position = {
|
|
9735
9888
|
x: rect.left,
|
|
9736
|
-
y: rect.bottom + 4
|
|
9889
|
+
y: rect.bottom + 4,
|
|
9890
|
+
triggerTop: rect.top
|
|
9737
9891
|
};
|
|
9738
9892
|
// Create context
|
|
9739
9893
|
const context = {
|
|
@@ -9795,10 +9949,10 @@ class StTableComponent {
|
|
|
9795
9949
|
event.stopPropagation();
|
|
9796
9950
|
const target = event.currentTarget;
|
|
9797
9951
|
const rect = target.getBoundingClientRect();
|
|
9798
|
-
// Calculate position (below the button by default)
|
|
9799
9952
|
const position = {
|
|
9800
9953
|
x: rect.left,
|
|
9801
|
-
y: rect.bottom + 4
|
|
9954
|
+
y: rect.bottom + 4,
|
|
9955
|
+
triggerTop: rect.top
|
|
9802
9956
|
};
|
|
9803
9957
|
// Create context
|
|
9804
9958
|
const context = {
|