@aquera/ngx-smart-table 0.0.14-alpha → 0.0.16-alpha
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-select-editor.mjs +121 -191
- package/esm2020/lib/models/workbook-action.interface.mjs +1 -1
- package/esm2020/lib/renderer/components/st-table/st-table.component.mjs +25 -2
- package/esm2020/lib/renderer/components/st-workbook/st-workbook.component.mjs +13 -5
- package/fesm2015/aquera-ngx-smart-table.mjs +159 -198
- package/fesm2015/aquera-ngx-smart-table.mjs.map +1 -1
- package/fesm2020/aquera-ngx-smart-table.mjs +156 -195
- package/fesm2020/aquera-ngx-smart-table.mjs.map +1 -1
- package/lib/editors/nile-select-editor.d.ts +0 -8
- package/lib/models/workbook-action.interface.d.ts +5 -0
- package/lib/renderer/components/st-workbook/st-workbook.component.d.ts +5 -1
- package/package.json +1 -1
|
@@ -3523,6 +3523,72 @@ class NileInputEditor {
|
|
|
3523
3523
|
* Custom editor using NileSelect from @aquera/nile-elements
|
|
3524
3524
|
* This demonstrates how to create dropdown/select editors for ngx-smart-table
|
|
3525
3525
|
*/
|
|
3526
|
+
/**
|
|
3527
|
+
* Inject global styles for nile-select dropdown height limit
|
|
3528
|
+
*/
|
|
3529
|
+
let dropdownStylesInjected = false;
|
|
3530
|
+
function injectDropdownStyles() {
|
|
3531
|
+
if (dropdownStylesInjected)
|
|
3532
|
+
return;
|
|
3533
|
+
dropdownStylesInjected = true;
|
|
3534
|
+
const styleId = 'nile-select-dropdown-styles';
|
|
3535
|
+
if (document.getElementById(styleId))
|
|
3536
|
+
return;
|
|
3537
|
+
const style = document.createElement('style');
|
|
3538
|
+
style.id = styleId;
|
|
3539
|
+
style.textContent = `
|
|
3540
|
+
/* Limit nile-select dropdown height and enable scrolling */
|
|
3541
|
+
.nile-select-portal-append {
|
|
3542
|
+
max-height: 300px !important;
|
|
3543
|
+
}
|
|
3544
|
+
.nile-select-portal-append .select__listbox {
|
|
3545
|
+
min-width: 220px !important;
|
|
3546
|
+
max-height: 260px !important;
|
|
3547
|
+
overflow-y: auto !important;
|
|
3548
|
+
width: auto !important;
|
|
3549
|
+
}
|
|
3550
|
+
.nile-select-portal-append .select__footer {
|
|
3551
|
+
height: 35px !important;
|
|
3552
|
+
}
|
|
3553
|
+
/* Prevent option text truncation - target the options container */
|
|
3554
|
+
.nile-select-portal-append .select__options {
|
|
3555
|
+
width: auto !important;
|
|
3556
|
+
}
|
|
3557
|
+
.nile-select-portal-append nile-option {
|
|
3558
|
+
width: auto !important;
|
|
3559
|
+
max-width: none !important;
|
|
3560
|
+
}
|
|
3561
|
+
.nile-select-portal-append nile-option::part(base) {
|
|
3562
|
+
white-space: nowrap !important;
|
|
3563
|
+
text-overflow: clip !important;
|
|
3564
|
+
overflow: visible !important;
|
|
3565
|
+
max-width: none !important;
|
|
3566
|
+
}
|
|
3567
|
+
/* Fix option text truncation by changing flex direction */
|
|
3568
|
+
.nile-select-portal-append nile-option::part(option_label_container) {
|
|
3569
|
+
flex-direction: row !important;
|
|
3570
|
+
}
|
|
3571
|
+
/* Combobox styling using ::part() selector */
|
|
3572
|
+
nile-select.st-cell-editor::part(combobox) {
|
|
3573
|
+
background-color: var(--nile-colors-white-base, var(--ng-colors-bg-primary)) !important;
|
|
3574
|
+
border: solid 1px transparent !important;
|
|
3575
|
+
margin: 1px 4px !important;
|
|
3576
|
+
}
|
|
3577
|
+
nile-select.st-cell-editor::part(combobox):hover {
|
|
3578
|
+
border: solid 1px transparent !important;
|
|
3579
|
+
}
|
|
3580
|
+
.st-cell-editor::part(combobox) {
|
|
3581
|
+
background-color: var(--nile-colors-white-base, var(--ng-colors-bg-primary)) !important;
|
|
3582
|
+
border: solid 1px transparent !important;
|
|
3583
|
+
margin: 1px 4px !important;
|
|
3584
|
+
}
|
|
3585
|
+
/* Search input full width */
|
|
3586
|
+
.nile-select-portal-append .select__search {
|
|
3587
|
+
width: 100% !important;
|
|
3588
|
+
}
|
|
3589
|
+
`;
|
|
3590
|
+
document.head.appendChild(style);
|
|
3591
|
+
}
|
|
3526
3592
|
/**
|
|
3527
3593
|
* Custom editor that uses NileSelect component
|
|
3528
3594
|
* @template T The value type (string for single selection, string[] for multiple)
|
|
@@ -3533,7 +3599,6 @@ class NileSelectEditor {
|
|
|
3533
3599
|
this.acceptsInitialKeypress = false;
|
|
3534
3600
|
this.eventListeners = [];
|
|
3535
3601
|
this.currentOptions = [];
|
|
3536
|
-
this.isInitializing = false; // Flag to prevent immediate close during initialization
|
|
3537
3602
|
// Handle Observable options
|
|
3538
3603
|
if (isObservable(options.options)) {
|
|
3539
3604
|
this.optionsSubscription = options.options.subscribe(opts => {
|
|
@@ -3552,99 +3617,20 @@ class NileSelectEditor {
|
|
|
3552
3617
|
}
|
|
3553
3618
|
}
|
|
3554
3619
|
}
|
|
3555
|
-
/**
|
|
3556
|
-
* Inject global styles to remove border from nile-select combobox
|
|
3557
|
-
* Uses ::part selector which works across shadow DOM boundaries
|
|
3558
|
-
*/
|
|
3559
|
-
injectBorderlessStyles() {
|
|
3560
|
-
if (NileSelectEditor.stylesInjected)
|
|
3561
|
-
return;
|
|
3562
|
-
const styleId = 'nile-select-borderless-styles';
|
|
3563
|
-
if (document.getElementById(styleId)) {
|
|
3564
|
-
NileSelectEditor.stylesInjected = true;
|
|
3565
|
-
return;
|
|
3566
|
-
}
|
|
3567
|
-
const style = document.createElement('style');
|
|
3568
|
-
style.id = styleId;
|
|
3569
|
-
style.textContent = `
|
|
3570
|
-
.st-cell-editor::part(combobox) {
|
|
3571
|
-
border: none !important;
|
|
3572
|
-
outline: none !important;
|
|
3573
|
-
box-shadow: none !important;
|
|
3574
|
-
min-height: unset !important;
|
|
3575
|
-
height: 100% !important;
|
|
3576
|
-
padding: 0 !important;
|
|
3577
|
-
}
|
|
3578
|
-
.st-cell-editor::part(combobox):hover {
|
|
3579
|
-
border: none !important;
|
|
3580
|
-
outline: none !important;
|
|
3581
|
-
box-shadow: none !important;
|
|
3582
|
-
}
|
|
3583
|
-
.st-cell-editor::part(combobox):focus {
|
|
3584
|
-
border: none !important;
|
|
3585
|
-
outline: none !important;
|
|
3586
|
-
box-shadow: none !important;
|
|
3587
|
-
}
|
|
3588
|
-
// .st-cell-editor::part(tag) {
|
|
3589
|
-
// margin: 1px 2px !important;
|
|
3590
|
-
// border-radius: 3px !important;
|
|
3591
|
-
// background-color: #e2e8f0 !important;
|
|
3592
|
-
// font-size: 12px !important;
|
|
3593
|
-
// height: auto !important;
|
|
3594
|
-
// }
|
|
3595
|
-
// .st-cell-editor::part(tag__base) {
|
|
3596
|
-
// border: none !important;
|
|
3597
|
-
// outline: none !important;
|
|
3598
|
-
// padding: 0 2px !important;
|
|
3599
|
-
// height: auto !important;
|
|
3600
|
-
// }
|
|
3601
|
-
// .st-cell-editor::part(tag__content) {
|
|
3602
|
-
// padding: 0 !important;
|
|
3603
|
-
// }
|
|
3604
|
-
.st-cell-editor::part(tags) {
|
|
3605
|
-
gap: 2px !important;
|
|
3606
|
-
align-items: center !important;
|
|
3607
|
-
}
|
|
3608
|
-
.st-cell-editor::part(tags-count) {
|
|
3609
|
-
margin: 0 !important;
|
|
3610
|
-
}
|
|
3611
|
-
.st-cell-editor::part(footer) {
|
|
3612
|
-
height: 35px !important;
|
|
3613
|
-
min-height: 35px !important;
|
|
3614
|
-
padding: 8px !important;
|
|
3615
|
-
padding-bottom: 30px !important;
|
|
3616
|
-
box-sizing: border-box !important;
|
|
3617
|
-
}
|
|
3618
|
-
.st-cell-editor::part(listbox) {
|
|
3619
|
-
margin-bottom: 0 !important;
|
|
3620
|
-
padding-bottom: 0 !important;
|
|
3621
|
-
}
|
|
3622
|
-
`;
|
|
3623
|
-
document.head.appendChild(style);
|
|
3624
|
-
NileSelectEditor.stylesInjected = true;
|
|
3625
|
-
}
|
|
3626
3620
|
edit(context) {
|
|
3627
3621
|
if (!context.container) {
|
|
3628
3622
|
console.warn('NileSelectEditor requires a container element');
|
|
3629
3623
|
return;
|
|
3630
3624
|
}
|
|
3631
|
-
//
|
|
3632
|
-
|
|
3625
|
+
// Inject dropdown height styles once
|
|
3626
|
+
injectDropdownStyles();
|
|
3633
3627
|
// Create NileSelect custom element using document.createElement
|
|
3634
3628
|
this.select = document.createElement('nile-select');
|
|
3635
3629
|
this.select.className = 'st-cell-editor';
|
|
3636
|
-
// Apply inline styles for proper cell fitting
|
|
3637
|
-
this.select.style.width = '
|
|
3638
|
-
this.select.style.height = '
|
|
3639
|
-
this.select.style.maxHeight = '100%';
|
|
3630
|
+
// Apply inline styles for proper cell fitting
|
|
3631
|
+
this.select.style.width = '100%';
|
|
3632
|
+
this.select.style.height = 'inherit';
|
|
3640
3633
|
this.select.style.boxSizing = 'border-box';
|
|
3641
|
-
this.select.style.margin = '0 2px';
|
|
3642
|
-
this.select.style.overflow = 'hidden';
|
|
3643
|
-
// Inject styles to remove border using ::part selector
|
|
3644
|
-
this.injectBorderlessStyles();
|
|
3645
|
-
// Also try removing outline on host element
|
|
3646
|
-
this.select.style.outline = 'none';
|
|
3647
|
-
this.select.style.border = 'none';
|
|
3648
3634
|
// Set initial value
|
|
3649
3635
|
this.setInitialValue(context.value);
|
|
3650
3636
|
// Apply all configuration options
|
|
@@ -3658,20 +3644,10 @@ class NileSelectEditor {
|
|
|
3658
3644
|
context.container.appendChild(this.select);
|
|
3659
3645
|
// Focus and auto-open after render
|
|
3660
3646
|
setTimeout(() => {
|
|
3661
|
-
var _a;
|
|
3662
|
-
(_a = this.select) === null || _a === void 0 ? void 0 : _a.focus();
|
|
3663
|
-
// Auto-open the dropdown
|
|
3664
3647
|
if (this.select) {
|
|
3648
|
+
this.select.focus();
|
|
3665
3649
|
this.select.open = true;
|
|
3666
3650
|
}
|
|
3667
|
-
// Clear initializing flag after dropdown has opened
|
|
3668
|
-
setTimeout(() => {
|
|
3669
|
-
this.isInitializing = false;
|
|
3670
|
-
// For multi-select, find the portal div for click detection
|
|
3671
|
-
if (this.options.multiple) {
|
|
3672
|
-
this.portalDiv = document.querySelector('.nile-select-portal-append');
|
|
3673
|
-
}
|
|
3674
|
-
}, 100);
|
|
3675
3651
|
}, 0);
|
|
3676
3652
|
}
|
|
3677
3653
|
/**
|
|
@@ -3755,13 +3731,9 @@ class NileSelectEditor {
|
|
|
3755
3731
|
if (this.options.pill) {
|
|
3756
3732
|
this.select.pill = this.options.pill;
|
|
3757
3733
|
}
|
|
3758
|
-
if (this.options.hoist
|
|
3734
|
+
if (this.options.hoist) {
|
|
3759
3735
|
this.select.hoist = this.options.hoist;
|
|
3760
3736
|
}
|
|
3761
|
-
else {
|
|
3762
|
-
// Default hoist to true for all selects to prevent clipping issues in table cells
|
|
3763
|
-
this.select.hoist = true;
|
|
3764
|
-
}
|
|
3765
3737
|
if (this.options.placement) {
|
|
3766
3738
|
this.select.placement = this.options.placement;
|
|
3767
3739
|
}
|
|
@@ -3771,12 +3743,8 @@ class NileSelectEditor {
|
|
|
3771
3743
|
if (this.options.disableLocalSearch) {
|
|
3772
3744
|
this.select.disableLocalSearch = this.options.disableLocalSearch;
|
|
3773
3745
|
}
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
}
|
|
3777
|
-
else {
|
|
3778
|
-
this.select.portal = true; // Default to portal mode for better positioning
|
|
3779
|
-
}
|
|
3746
|
+
// Enable portal mode by default to prevent dropdown clipping in table cells
|
|
3747
|
+
this.select.portal = this.options.portal !== false;
|
|
3780
3748
|
// Prevent width syncing issues in table cells
|
|
3781
3749
|
this.select.noWidthSync = true;
|
|
3782
3750
|
}
|
|
@@ -3836,13 +3804,6 @@ class NileSelectEditor {
|
|
|
3836
3804
|
if (!this.select)
|
|
3837
3805
|
return;
|
|
3838
3806
|
const validateOnSave = this.options.validateOnSave !== false;
|
|
3839
|
-
// Prevent click events from bubbling up to the cell container
|
|
3840
|
-
// This prevents parent handlers from interfering with nile-select's toggle
|
|
3841
|
-
const clickHandler = (e) => {
|
|
3842
|
-
e.stopPropagation();
|
|
3843
|
-
};
|
|
3844
|
-
this.select.addEventListener('click', clickHandler);
|
|
3845
|
-
this.eventListeners.push({ event: 'click', handler: clickHandler });
|
|
3846
3807
|
// Handle keyboard events (keydown is not replaced by custom events)
|
|
3847
3808
|
const keydownHandler = (e) => {
|
|
3848
3809
|
const keyEvent = e;
|
|
@@ -3854,45 +3815,56 @@ class NileSelectEditor {
|
|
|
3854
3815
|
};
|
|
3855
3816
|
this.select.addEventListener('keydown', keydownHandler);
|
|
3856
3817
|
this.eventListeners.push({ event: 'keydown', handler: keydownHandler });
|
|
3857
|
-
// Use nile-change custom event as
|
|
3858
|
-
|
|
3818
|
+
// Use nile-change custom event as save trigger - ONLY for single-select
|
|
3819
|
+
// Multi-select should stay open until user clicks outside
|
|
3820
|
+
if (!this.options.multiple) {
|
|
3821
|
+
const changeHandler = (e) => {
|
|
3822
|
+
var _a, _b;
|
|
3823
|
+
const customEvent = e;
|
|
3824
|
+
if (validateOnSave && !((_a = this.select) === null || _a === void 0 ? void 0 : _a.checkValidity())) {
|
|
3825
|
+
(_b = this.select) === null || _b === void 0 ? void 0 : _b.reportValidity();
|
|
3826
|
+
return;
|
|
3827
|
+
}
|
|
3828
|
+
context.onSave(this.parseValue(customEvent.detail.value));
|
|
3829
|
+
};
|
|
3830
|
+
this.select.addEventListener('nile-change', changeHandler);
|
|
3831
|
+
this.eventListeners.push({ event: 'nile-change', handler: changeHandler });
|
|
3832
|
+
}
|
|
3833
|
+
// Track if save was already triggered (to prevent double save)
|
|
3834
|
+
let saveTriggered = false;
|
|
3835
|
+
// Use mousedown on document to detect clicks outside the select and portal
|
|
3836
|
+
const documentMousedownHandler = (e) => {
|
|
3859
3837
|
var _a, _b;
|
|
3860
|
-
|
|
3861
|
-
if (this.isInitializing) {
|
|
3838
|
+
if (saveTriggered)
|
|
3862
3839
|
return;
|
|
3863
|
-
|
|
3864
|
-
const customEvent = e;
|
|
3865
|
-
if (validateOnSave && !((_a = this.select) === null || _a === void 0 ? void 0 : _a.checkValidity())) {
|
|
3866
|
-
(_b = this.select) === null || _b === void 0 ? void 0 : _b.reportValidity();
|
|
3840
|
+
if (!this.select)
|
|
3867
3841
|
return;
|
|
3868
|
-
|
|
3869
|
-
//
|
|
3870
|
-
|
|
3871
|
-
if (!this.options.multiple) {
|
|
3872
|
-
context.onSave(this.parseValue(customEvent.detail.value));
|
|
3873
|
-
}
|
|
3874
|
-
};
|
|
3875
|
-
this.select.addEventListener('nile-change', changeHandler);
|
|
3876
|
-
this.eventListeners.push({ event: 'nile-change', handler: changeHandler });
|
|
3877
|
-
// Handle blur as secondary save trigger - only for single-select
|
|
3878
|
-
// Multi-select uses hide event instead
|
|
3879
|
-
const blurHandler = (e) => {
|
|
3880
|
-
var _a, _b;
|
|
3881
|
-
// Ignore blur during initialization
|
|
3882
|
-
if (this.isInitializing) {
|
|
3842
|
+
const target = e.target;
|
|
3843
|
+
// Check if click is inside the select element
|
|
3844
|
+
if (this.select.contains(target)) {
|
|
3883
3845
|
return;
|
|
3884
3846
|
}
|
|
3847
|
+
// Check if click is inside any nile-select portal
|
|
3848
|
+
const portals = document.querySelectorAll('.nile-select-portal-append');
|
|
3849
|
+
for (let i = 0; i < portals.length; i++) {
|
|
3850
|
+
if (portals[i].contains(target)) {
|
|
3851
|
+
return;
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
// Click is outside - save and exit
|
|
3855
|
+
saveTriggered = true;
|
|
3885
3856
|
if (validateOnSave && !((_a = this.select) === null || _a === void 0 ? void 0 : _a.checkValidity())) {
|
|
3886
3857
|
(_b = this.select) === null || _b === void 0 ? void 0 : _b.reportValidity();
|
|
3887
3858
|
return;
|
|
3888
3859
|
}
|
|
3889
|
-
|
|
3890
|
-
if (!this.options.multiple) {
|
|
3891
|
-
context.onSave(this.getCurrentValue());
|
|
3892
|
-
}
|
|
3860
|
+
context.onSave(this.getCurrentValue());
|
|
3893
3861
|
};
|
|
3894
|
-
|
|
3895
|
-
|
|
3862
|
+
// Add listener after a short delay to avoid capturing the initial click that opened the editor
|
|
3863
|
+
setTimeout(() => {
|
|
3864
|
+
document.addEventListener('mousedown', documentMousedownHandler, true);
|
|
3865
|
+
}, 50);
|
|
3866
|
+
// Store for cleanup
|
|
3867
|
+
this._documentMousedownHandler = documentMousedownHandler;
|
|
3896
3868
|
// Handle clear button if enabled
|
|
3897
3869
|
if (this.options.clearable) {
|
|
3898
3870
|
const clearHandler = (e) => {
|
|
@@ -3911,44 +3883,6 @@ class NileSelectEditor {
|
|
|
3911
3883
|
this.select.addEventListener('nile-search', searchHandler);
|
|
3912
3884
|
this.eventListeners.push({ event: 'nile-search', handler: searchHandler });
|
|
3913
3885
|
}
|
|
3914
|
-
// For multi-select: detect clicks outside portal and select
|
|
3915
|
-
if (this.options.multiple) {
|
|
3916
|
-
const documentClickHandler = (e) => {
|
|
3917
|
-
var _a, _b, _c, _d;
|
|
3918
|
-
const mouseEvent = e;
|
|
3919
|
-
const target = mouseEvent.target;
|
|
3920
|
-
// Check if portal div exists (might take a moment to render)
|
|
3921
|
-
if (!this.portalDiv) {
|
|
3922
|
-
this.portalDiv = document.querySelector('.nile-select-portal-append');
|
|
3923
|
-
}
|
|
3924
|
-
// Determine if click is inside the select or portal
|
|
3925
|
-
const clickedInsideSelect = (_a = this.select) === null || _a === void 0 ? void 0 : _a.contains(target);
|
|
3926
|
-
const clickedInsidePortal = (_b = this.portalDiv) === null || _b === void 0 ? void 0 : _b.contains(target);
|
|
3927
|
-
// If clicked outside both select and portal, save and close
|
|
3928
|
-
if (!clickedInsideSelect && !clickedInsidePortal) {
|
|
3929
|
-
if (validateOnSave && !((_c = this.select) === null || _c === void 0 ? void 0 : _c.checkValidity())) {
|
|
3930
|
-
(_d = this.select) === null || _d === void 0 ? void 0 : _d.reportValidity();
|
|
3931
|
-
return;
|
|
3932
|
-
}
|
|
3933
|
-
context.onSave(this.getCurrentValue());
|
|
3934
|
-
}
|
|
3935
|
-
// Otherwise, click is inside - do nothing (dropdown stays open)
|
|
3936
|
-
};
|
|
3937
|
-
// Delay adding the document click handler to prevent the initial click
|
|
3938
|
-
// (that opened the editor) from immediately triggering it and closing the dropdown
|
|
3939
|
-
// Use 200ms to ensure the dropdown has fully opened
|
|
3940
|
-
setTimeout(() => {
|
|
3941
|
-
// Only add if select still exists (editor not destroyed)
|
|
3942
|
-
if (this.select) {
|
|
3943
|
-
// Use bubbling phase (false) instead of capture to not interfere with nile-select's toggle
|
|
3944
|
-
document.addEventListener('click', documentClickHandler, false);
|
|
3945
|
-
this.eventListeners.push({
|
|
3946
|
-
event: 'document-click',
|
|
3947
|
-
handler: documentClickHandler
|
|
3948
|
-
});
|
|
3949
|
-
}
|
|
3950
|
-
}, 200);
|
|
3951
|
-
}
|
|
3952
3886
|
}
|
|
3953
3887
|
/**
|
|
3954
3888
|
* Parse value based on selection mode
|
|
@@ -3968,30 +3902,25 @@ class NileSelectEditor {
|
|
|
3968
3902
|
return value;
|
|
3969
3903
|
}
|
|
3970
3904
|
destroy() {
|
|
3971
|
-
// Reset initialization flag
|
|
3972
|
-
this.isInitializing = false;
|
|
3973
3905
|
// Unsubscribe from options Observable
|
|
3974
3906
|
if (this.optionsSubscription) {
|
|
3975
3907
|
this.optionsSubscription.unsubscribe();
|
|
3976
3908
|
this.optionsSubscription = undefined;
|
|
3977
3909
|
}
|
|
3910
|
+
// Remove document mousedown handler if exists
|
|
3911
|
+
if (this._documentMousedownHandler) {
|
|
3912
|
+
document.removeEventListener('mousedown', this._documentMousedownHandler, true);
|
|
3913
|
+
delete this._documentMousedownHandler;
|
|
3914
|
+
}
|
|
3978
3915
|
// Remove all event listeners
|
|
3979
3916
|
if (this.select) {
|
|
3980
3917
|
this.eventListeners.forEach(({ event, handler }) => {
|
|
3981
3918
|
var _a;
|
|
3982
|
-
|
|
3983
|
-
// Remove from document for multi-select click handler (bubbling phase)
|
|
3984
|
-
document.removeEventListener('click', handler, false);
|
|
3985
|
-
}
|
|
3986
|
-
else {
|
|
3987
|
-
// Remove from select element
|
|
3988
|
-
(_a = this.select) === null || _a === void 0 ? void 0 : _a.removeEventListener(event, handler);
|
|
3989
|
-
}
|
|
3919
|
+
(_a = this.select) === null || _a === void 0 ? void 0 : _a.removeEventListener(event, handler);
|
|
3990
3920
|
});
|
|
3991
3921
|
this.eventListeners = [];
|
|
3992
3922
|
this.select.remove();
|
|
3993
3923
|
this.select = undefined;
|
|
3994
|
-
this.portalDiv = undefined; // Clean up portal reference
|
|
3995
3924
|
}
|
|
3996
3925
|
}
|
|
3997
3926
|
focus() {
|
|
@@ -4011,7 +3940,6 @@ class NileSelectEditor {
|
|
|
4011
3940
|
return (Array.isArray(value) ? (value.length > 0 ? value[0] : '') : value);
|
|
4012
3941
|
}
|
|
4013
3942
|
}
|
|
4014
|
-
NileSelectEditor.stylesInjected = false;
|
|
4015
3943
|
|
|
4016
3944
|
/**
|
|
4017
3945
|
* Custom editor using NileAutoComplete from @aquera/nile-elements
|
|
@@ -8755,6 +8683,15 @@ class StTableComponent {
|
|
|
8755
8683
|
// Use setTimeout to ensure DOM has updated
|
|
8756
8684
|
setTimeout(() => {
|
|
8757
8685
|
var _a;
|
|
8686
|
+
// Don't steal focus from editors - if a cell is being edited,
|
|
8687
|
+
// the editor should keep focus
|
|
8688
|
+
const editingPosition = this.getActiveTableState().getEditingPosition();
|
|
8689
|
+
if (editingPosition &&
|
|
8690
|
+
editingPosition.rowIndex === rowIndex &&
|
|
8691
|
+
editingPosition.columnIndex === colIndex) {
|
|
8692
|
+
// Cell is being edited, don't steal focus from the editor
|
|
8693
|
+
return;
|
|
8694
|
+
}
|
|
8758
8695
|
// Use absolute row index for virtual scroll compatibility
|
|
8759
8696
|
const absoluteRowIndex = this.getAbsoluteRowIndex(rowIndex);
|
|
8760
8697
|
// Query within this component's host element to avoid selecting rows from other tables
|
|
@@ -9015,11 +8952,27 @@ class StTableComponent {
|
|
|
9015
8952
|
* Clear focus when clicking outside table
|
|
9016
8953
|
*/
|
|
9017
8954
|
onDocumentClick(event) {
|
|
8955
|
+
var _a;
|
|
9018
8956
|
if (!this.isKeyboardNavigationEnabled())
|
|
9019
8957
|
return;
|
|
9020
8958
|
const target = event.target;
|
|
9021
8959
|
const tableElement = target.closest('.st-table');
|
|
9022
|
-
if (
|
|
8960
|
+
// Also check if click is inside a portal (e.g., nile-select dropdown)
|
|
8961
|
+
// These are rendered outside the table but are part of the editing experience
|
|
8962
|
+
const portalElement = target.closest('.nile-select-portal-append');
|
|
8963
|
+
// Check composedPath for shadow DOM elements (e.g., nile-option, nile-input inside shadow root)
|
|
8964
|
+
const composedPath = ((_a = event.composedPath) === null || _a === void 0 ? void 0 : _a.call(event)) || [];
|
|
8965
|
+
const isInsideNileElement = composedPath.some((el) => {
|
|
8966
|
+
var _a, _b;
|
|
8967
|
+
if (el instanceof HTMLElement) {
|
|
8968
|
+
const tagName = (_a = el.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
8969
|
+
// Check for any nile-* custom elements used in editors
|
|
8970
|
+
return (tagName === null || tagName === void 0 ? void 0 : tagName.startsWith('nile-')) ||
|
|
8971
|
+
((_b = el.classList) === null || _b === void 0 ? void 0 : _b.contains('nile-select-portal-append'));
|
|
8972
|
+
}
|
|
8973
|
+
return false;
|
|
8974
|
+
});
|
|
8975
|
+
if (!tableElement && !portalElement && !isInsideNileElement) {
|
|
9023
8976
|
this.getActiveTableState().clearFocus();
|
|
9024
8977
|
this.getActiveTableState().clearEditingCell();
|
|
9025
8978
|
}
|
|
@@ -9987,9 +9940,13 @@ class StWorkbookComponent {
|
|
|
9987
9940
|
this.workbookActionsOpen = false;
|
|
9988
9941
|
this.workbookActionsPosition = {};
|
|
9989
9942
|
/**
|
|
9990
|
-
* Visible workbook actions (filtered by hidden)
|
|
9943
|
+
* Visible workbook actions for dropdown (filtered by hidden and showInToolbar)
|
|
9991
9944
|
*/
|
|
9992
9945
|
this.visibleWorkbookActions = [];
|
|
9946
|
+
/**
|
|
9947
|
+
* Workbook actions to show directly in toolbar
|
|
9948
|
+
*/
|
|
9949
|
+
this.toolbarWorkbookActions = [];
|
|
9993
9950
|
/**
|
|
9994
9951
|
* Destroy subject for cleanup
|
|
9995
9952
|
*/
|
|
@@ -10230,14 +10187,18 @@ class StWorkbookComponent {
|
|
|
10230
10187
|
updateVisibleWorkbookActions() {
|
|
10231
10188
|
if (!this.config.workbookActions) {
|
|
10232
10189
|
this.visibleWorkbookActions = [];
|
|
10190
|
+
this.toolbarWorkbookActions = [];
|
|
10233
10191
|
return;
|
|
10234
10192
|
}
|
|
10235
|
-
|
|
10193
|
+
const visibleActions = this.config.workbookActions.filter(action => {
|
|
10236
10194
|
if (typeof action.hidden === 'function') {
|
|
10237
10195
|
return !action.hidden();
|
|
10238
10196
|
}
|
|
10239
10197
|
return !action.hidden;
|
|
10240
10198
|
});
|
|
10199
|
+
// Separate toolbar actions from dropdown actions
|
|
10200
|
+
this.toolbarWorkbookActions = visibleActions.filter(action => action.showInToolbar === true);
|
|
10201
|
+
this.visibleWorkbookActions = visibleActions.filter(action => action.showInToolbar !== true);
|
|
10241
10202
|
}
|
|
10242
10203
|
/**
|
|
10243
10204
|
* Check if workbook action is disabled
|
|
@@ -10434,10 +10395,10 @@ class StWorkbookComponent {
|
|
|
10434
10395
|
}
|
|
10435
10396
|
}
|
|
10436
10397
|
StWorkbookComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StWorkbookComponent, deps: [{ token: AutosaveService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
10437
|
-
StWorkbookComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StWorkbookComponent, selector: "st-workbook", inputs: { config: "config", sheetsData: "sheetsData", state: "state" }, outputs: { sheetChanged: "sheetChanged", addSheet: "addSheet", sheetTabAction: "sheetTabAction", workbookAction: "workbookAction", cellChange: "cellChange", cellSave: "cellSave", tableStateChange: "tableStateChange", fullscreenToggle: "fullscreenToggle", requestAddRow: "requestAddRow" }, viewQueries: [{ propertyName: "tableComponent", first: true, predicate: StTableComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen$ | async\">\n <nile-tab-group [activeIndex]=\"activeSheetIndex\">\n \n <!-- Sheet Tabs (one per sheet) -->\n <nile-tab *ngFor=\"let sheet of sheets; let i = index\"\n slot=\"nav\" \n panel=\"shared-panel\"\n [class.active]=\"i === activeSheetIndex\"\n (click)=\"onTabChange(i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n \n <!-- Tab actions dropdown button -->\n <button class=\"tab-actions-button\"\n (click)=\"openTabActions($event, sheet, i)\"\n *ngIf=\"hasTabActions(sheet)\">\n <nile-icon name=\"arrowdown\" size=\"14\"></nile-icon>\n </button>\n </div>\n </nile-tab>\n \n <!-- Toolbar Tab (for workbook controls) -->\n <nile-tab slot=\"nav\" \n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\">\n <!-- Autosave Indicator -->\n <div class=\"autosave-indicator\" *ngIf=\"autosaveEnabled\">\n <nile-icon \n *ngIf=\"!isSaving && lastSaveTime\" \n name=\"save\" \n size=\"14\"\n [title]=\"'Saved at ' + (lastSaveTime | date:'HH:mm:ss')\">\n </nile-icon>\n <nile-icon \n *ngIf=\"isSaving\" \n name=\"loader\" \n size=\"14\"\n title=\"Saving...\">\n </nile-icon>\n </div>\n\n <!-- Workbook Actions Dropdown -->\n <button class=\"workbook-actions-button\"\n *ngIf=\"config.workbookActions && config.workbookActions.length > 0\"\n (click)=\"toggleWorkbookActions($event)\"\n title=\"Workbook Actions\">\n <nile-icon name=\"settings\"></nile-icon>\n </button>\n \n <!-- Add Sheet Button -->\n <button class=\"add-sheet-button\"\n *ngIf=\"canAddSheet\"\n (click)=\"onAddSheet()\"\n title=\"Add Sheet\">\n <nile-icon name=\"plus\"></nile-icon>\n </button>\n \n <!-- Fullscreen Button -->\n <button class=\"fullscreen-button\"\n *ngIf=\"config.display?.allowFullscreen !== false\"\n (click)=\"toggleFullscreen()\"\n [title]=\"(isFullscreen$ | async) ? 'Exit Fullscreen' : 'Fullscreen'\">\n <nile-icon [name]=\"(isFullscreen$ | async) ? 'collapse' : 'expand-06'\"></nile-icon>\n </button>\n </div>\n </nile-tab>\n \n <!-- Single Shared Tab Panel -->\n <nile-tab-panel name=\"shared-panel\">\n <!-- Lazy loading strategy: table is destroyed and recreated with new config/state when sheet changes -->\n <!-- Using ngFor with trackBy to force complete reinitialization when tableComponentKey changes -->\n <ng-container *ngFor=\"let key of [tableComponentKey]; trackBy: trackByKey\">\n <st-table *ngIf=\"currentTableConfig && currentTableState\"\n [attr.data-sheet-key]=\"key\"\n [tableConfig]=\"currentTableConfig\"\n [data$]=\"currentTableData$\"\n [tableState]=\"currentTableState\"\n (cellChange)=\"onCellChange($event)\"\n (cellSave)=\"onCellSave($event)\"\n (stateChange)=\"onTableStateChange($event)\"\n (requestAddRow)=\"onRequestAddRow($event)\">\n </st-table>\n </ng-container>\n </nile-tab-panel>\n \n </nile-tab-group>\n</div>\n\n<!-- Tab Actions Dropdown -->\n<div class=\"tab-actions-dropdown\" \n *ngIf=\"tabActionsOpen\"\n [ngStyle]=\"tabActionsPosition\">\n <div class=\"dropdown-backdrop\" (click)=\"closeTabActions()\"></div>\n <div class=\"dropdown-menu\">\n <nile-menu>\n <nile-menu-item *ngFor=\"let action of selectedSheet?.tabActions\" \n (click)=\"onTabActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" slot=\"prefix\" size=\"14\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </nile-menu>\n </div>\n</div>\n\n<!-- Workbook Actions Dropdown -->\n<div class=\"workbook-actions-dropdown\"\n *ngIf=\"workbookActionsOpen\"\n [ngStyle]=\"workbookActionsPosition\">\n <div class=\"dropdown-backdrop\" (click)=\"closeWorkbookActions()\"></div>\n <div class=\"dropdown-menu\">\n <nile-menu>\n <nile-menu-item *ngFor=\"let action of visibleWorkbookActions\"\n [class.disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" slot=\"prefix\" size=\"14\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </nile-menu>\n </div>\n</div>\n\n<!-- Fullscreen Backdrop -->\n<div class=\"fullscreen-backdrop\" \n *ngIf=\"isFullscreen$ | async\"\n (click)=\"toggleFullscreen()\">\n</div>\n\n", styles: ["@import\"@aquera/nile/lib/styles/variables.css\";:host{display:block;width:100%;height:100%}.workbook-container{display:flex;flex-direction:column;height:100%;background:white;border:1px solid var(--nile-color-neutral-200);border-radius:4px;overflow:hidden}.workbook-container.fullscreen{position:fixed;inset:0;z-index:2000;border:none;border-radius:0}.workbook-container nile-tab-group{height:100%;display:flex;flex-direction:column}.sheet-tab-content{display:flex;align-items:center;gap:8px;padding:0 4px}.sheet-tab-content .sheet-name{font-size:12px;font-weight:500;font-family:var(--nile-font-family-sans-serif);color:#000}.sheet-tab-content .tab-actions-button{width:20px;height:20px;padding:0;background:transparent;border:none;cursor:pointer}.workbook-toolbar-tab{margin-left:auto!important;pointer-events:auto!important;border-left:1px solid var(--nile-color-neutral-200)}.workbook-toolbar-tab .workbook-toolbar-content{display:flex;gap:4px;align-items:center;padding:0 8px}.workbook-toolbar-tab .workbook-toolbar-content .autosave-indicator{display:flex;align-items:center;margin-right:8px;color:var(--nile-color-success-500)}.workbook-toolbar-tab button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;color:var(--nile-color-neutral-600)}.workbook-toolbar-tab button:hover{background-color:var(--nile-color-neutral-100);color:var(--nile-color-neutral-900)}.workbook-toolbar-tab button:active{background-color:var(--nile-color-neutral-200)}.workbook-toolbar-tab button nile-icon{font-size:16px}.tab-actions-dropdown{position:fixed;z-index:1001}.tab-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.tab-actions-dropdown .dropdown-menu{position:relative;min-width:180px;background:white;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.tab-actions-dropdown .dropdown-menu nile-menu{display:block}.workbook-actions-dropdown{position:fixed;z-index:1001}.workbook-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.workbook-actions-dropdown .dropdown-menu{position:relative;min-width:200px;background:white;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.workbook-actions-dropdown .dropdown-menu nile-menu{display:block}.fullscreen-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:1999;cursor:pointer}nile-tab-group::part(nav){background-color:#fafafa}nile-tab-group::part(active-tab-indicator-path){background:none}nile-tab-group::part(active-tab-indicator){border-bottom:none}nile-tab-group::part(tabs){gap:0}nile-tab-group nile-tab{border:1px solid #e0e0e0;border-top-left-radius:6px;border-top-right-radius:6px}nile-tab-group nile-tab::part(base){padding-left:.5rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom-left-radius:0;border-bottom-right-radius:0}nile-tab-group nile-tab.active{background-color:#fff;color:#000}nile-tab-group nile-tab.active .sheet-name{font-weight:600}nile-tab-group nile-tab-panel::part(base){padding:0;max-height:30rem}\n"], components: [{ type: StTableComponent, selector: "st-table", inputs: ["tableConfig", "data", "data$", "tableState", "enableSorting", "enableFiltering", "validateConfig"], outputs: ["stateChange", "dataChange", "cellEdit", "cellSave", "cellCancel", "cellChange", "columnResized", "columnMoved", "configValidationErrors", "columnAdded", "rowAction", "validationStateChange", "requestAddRow"] }], directives: [{ type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], pipes: { "async": i1.AsyncPipe, "date": i1.DatePipe } });
|
|
10398
|
+
StWorkbookComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StWorkbookComponent, selector: "st-workbook", inputs: { config: "config", sheetsData: "sheetsData", state: "state" }, outputs: { sheetChanged: "sheetChanged", addSheet: "addSheet", sheetTabAction: "sheetTabAction", workbookAction: "workbookAction", cellChange: "cellChange", cellSave: "cellSave", tableStateChange: "tableStateChange", fullscreenToggle: "fullscreenToggle", requestAddRow: "requestAddRow" }, viewQueries: [{ propertyName: "tableComponent", first: true, predicate: StTableComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen$ | async\">\n <nile-tab-group [activeIndex]=\"activeSheetIndex\">\n \n <!-- Sheet Tabs (one per sheet) -->\n <nile-tab *ngFor=\"let sheet of sheets; let i = index\"\n slot=\"nav\" \n panel=\"shared-panel\"\n [class.active]=\"i === activeSheetIndex\"\n (click)=\"onTabChange(i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n \n <!-- Tab actions dropdown button -->\n <button class=\"tab-actions-button\"\n (click)=\"openTabActions($event, sheet, i)\"\n *ngIf=\"hasTabActions(sheet)\">\n <nile-icon name=\"arrowdown\" size=\"14\"></nile-icon>\n </button>\n </div>\n </nile-tab>\n \n <!-- Toolbar Tab (for workbook controls) -->\n <nile-tab slot=\"nav\" \n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\">\n <!-- Autosave Indicator -->\n <div class=\"autosave-indicator\" *ngIf=\"autosaveEnabled\">\n <nile-icon \n *ngIf=\"!isSaving && lastSaveTime\" \n name=\"save\" \n size=\"14\"\n [title]=\"'Saved at ' + (lastSaveTime | date:'HH:mm:ss')\">\n </nile-icon>\n <nile-icon \n *ngIf=\"isSaving\" \n name=\"loader\" \n size=\"14\"\n title=\"Saving...\">\n </nile-icon>\n </div>\n\n <!-- Toolbar Workbook Actions (shown as individual buttons) -->\n <button *ngFor=\"let action of toolbarWorkbookActions\"\n class=\"toolbar-action-button\"\n [class.disabled]=\"isActionDisabled(action)\"\n [title]=\"action.label\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" [name]=\"action.icon\"></nile-icon>\n <span *ngIf=\"!action.icon\">{{ action.label }}</span>\n </button>\n\n <!-- Workbook Actions Dropdown -->\n <button class=\"workbook-actions-button\"\n *ngIf=\"visibleWorkbookActions.length > 0\"\n (click)=\"toggleWorkbookActions($event)\"\n title=\"Workbook Actions\">\n <nile-icon name=\"settings\"></nile-icon>\n </button>\n \n <!-- Add Sheet Button -->\n <button class=\"add-sheet-button\"\n *ngIf=\"canAddSheet\"\n (click)=\"onAddSheet()\"\n title=\"Add Sheet\">\n <nile-icon name=\"plus\"></nile-icon>\n </button>\n \n <!-- Fullscreen Button -->\n <button class=\"fullscreen-button\"\n *ngIf=\"config.display?.allowFullscreen !== false\"\n (click)=\"toggleFullscreen()\"\n [title]=\"(isFullscreen$ | async) ? 'Exit Fullscreen' : 'Fullscreen'\">\n <nile-icon [name]=\"(isFullscreen$ | async) ? 'collapse' : 'expand-06'\"></nile-icon>\n </button>\n </div>\n </nile-tab>\n \n <!-- Single Shared Tab Panel -->\n <nile-tab-panel name=\"shared-panel\">\n <!-- Lazy loading strategy: table is destroyed and recreated with new config/state when sheet changes -->\n <!-- Using ngFor with trackBy to force complete reinitialization when tableComponentKey changes -->\n <ng-container *ngFor=\"let key of [tableComponentKey]; trackBy: trackByKey\">\n <st-table *ngIf=\"currentTableConfig && currentTableState\"\n [attr.data-sheet-key]=\"key\"\n [tableConfig]=\"currentTableConfig\"\n [data$]=\"currentTableData$\"\n [tableState]=\"currentTableState\"\n (cellChange)=\"onCellChange($event)\"\n (cellSave)=\"onCellSave($event)\"\n (stateChange)=\"onTableStateChange($event)\"\n (requestAddRow)=\"onRequestAddRow($event)\">\n </st-table>\n </ng-container>\n </nile-tab-panel>\n \n </nile-tab-group>\n</div>\n\n<!-- Tab Actions Dropdown -->\n<div class=\"tab-actions-dropdown\" \n *ngIf=\"tabActionsOpen\"\n [ngStyle]=\"tabActionsPosition\">\n <div class=\"dropdown-backdrop\" (click)=\"closeTabActions()\"></div>\n <div class=\"dropdown-menu\">\n <nile-menu>\n <nile-menu-item *ngFor=\"let action of selectedSheet?.tabActions\" \n (click)=\"onTabActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" slot=\"prefix\" size=\"14\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </nile-menu>\n </div>\n</div>\n\n<!-- Workbook Actions Dropdown -->\n<div class=\"workbook-actions-dropdown\"\n *ngIf=\"workbookActionsOpen\"\n [ngStyle]=\"workbookActionsPosition\">\n <div class=\"dropdown-backdrop\" (click)=\"closeWorkbookActions()\"></div>\n <div class=\"dropdown-menu\">\n <nile-menu>\n <nile-menu-item *ngFor=\"let action of visibleWorkbookActions\"\n [class.disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" slot=\"prefix\" size=\"14\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </nile-menu>\n </div>\n</div>\n\n<!-- Fullscreen Backdrop -->\n<div class=\"fullscreen-backdrop\" \n *ngIf=\"isFullscreen$ | async\"\n (click)=\"toggleFullscreen()\">\n</div>\n\n", styles: ["@import\"@aquera/nile/lib/styles/variables.css\";:host{display:block;width:100%;height:100%}.workbook-container{display:flex;flex-direction:column;height:100%;background:white;border:1px solid var(--nile-color-neutral-200);border-radius:4px;overflow:hidden}.workbook-container.fullscreen{position:fixed;inset:0;z-index:2000;border:none;border-radius:0}.workbook-container nile-tab-group{height:100%;display:flex;flex-direction:column}.sheet-tab-content{display:flex;align-items:center;gap:8px;padding:0 4px}.sheet-tab-content .sheet-name{font-size:12px;font-weight:500;font-family:var(--nile-font-family-sans-serif);color:#000}.sheet-tab-content .tab-actions-button{width:20px;height:20px;padding:0;background:transparent;border:none;cursor:pointer}.workbook-toolbar-tab{margin-left:auto!important;pointer-events:auto!important;border-left:1px solid var(--nile-color-neutral-200)}.workbook-toolbar-tab .workbook-toolbar-content{display:flex;gap:4px;align-items:center;padding:0 8px}.workbook-toolbar-tab .workbook-toolbar-content .autosave-indicator{display:flex;align-items:center;margin-right:8px;color:var(--nile-color-success-500)}.workbook-toolbar-tab button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;color:var(--nile-color-neutral-600)}.workbook-toolbar-tab button:hover{background-color:var(--nile-color-neutral-100);color:var(--nile-color-neutral-900)}.workbook-toolbar-tab button:active{background-color:var(--nile-color-neutral-200)}.workbook-toolbar-tab button nile-icon{font-size:16px}.workbook-toolbar-tab button.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tab-actions-dropdown{position:fixed;z-index:1001}.tab-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.tab-actions-dropdown .dropdown-menu{position:relative;min-width:180px;background:white;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.tab-actions-dropdown .dropdown-menu nile-menu{display:block}.workbook-actions-dropdown{position:fixed;z-index:1001}.workbook-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.workbook-actions-dropdown .dropdown-menu{position:relative;min-width:200px;background:white;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.workbook-actions-dropdown .dropdown-menu nile-menu{display:block}.fullscreen-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:1999;cursor:pointer}nile-tab-group::part(nav){background-color:#fafafa}nile-tab-group::part(active-tab-indicator-path){background:none}nile-tab-group::part(active-tab-indicator){border-bottom:none}nile-tab-group::part(tabs){gap:0}nile-tab-group nile-tab{border:1px solid #e0e0e0;border-top-left-radius:6px;border-top-right-radius:6px}nile-tab-group nile-tab::part(base){padding-left:.5rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom-left-radius:0;border-bottom-right-radius:0}nile-tab-group nile-tab.active{background-color:#fff;color:#000}nile-tab-group nile-tab.active .sheet-name{font-weight:600}nile-tab-group nile-tab-panel::part(base){padding:0;max-height:30rem}\n"], components: [{ type: StTableComponent, selector: "st-table", inputs: ["tableConfig", "data", "data$", "tableState", "enableSorting", "enableFiltering", "validateConfig"], outputs: ["stateChange", "dataChange", "cellEdit", "cellSave", "cellCancel", "cellChange", "columnResized", "columnMoved", "configValidationErrors", "columnAdded", "rowAction", "validationStateChange", "requestAddRow"] }], directives: [{ type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], pipes: { "async": i1.AsyncPipe, "date": i1.DatePipe } });
|
|
10438
10399
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StWorkbookComponent, decorators: [{
|
|
10439
10400
|
type: Component,
|
|
10440
|
-
args: [{ selector: 'st-workbook', template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen$ | async\">\n <nile-tab-group [activeIndex]=\"activeSheetIndex\">\n \n <!-- Sheet Tabs (one per sheet) -->\n <nile-tab *ngFor=\"let sheet of sheets; let i = index\"\n slot=\"nav\" \n panel=\"shared-panel\"\n [class.active]=\"i === activeSheetIndex\"\n (click)=\"onTabChange(i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n \n <!-- Tab actions dropdown button -->\n <button class=\"tab-actions-button\"\n (click)=\"openTabActions($event, sheet, i)\"\n *ngIf=\"hasTabActions(sheet)\">\n <nile-icon name=\"arrowdown\" size=\"14\"></nile-icon>\n </button>\n </div>\n </nile-tab>\n \n <!-- Toolbar Tab (for workbook controls) -->\n <nile-tab slot=\"nav\" \n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\">\n <!-- Autosave Indicator -->\n <div class=\"autosave-indicator\" *ngIf=\"autosaveEnabled\">\n <nile-icon \n *ngIf=\"!isSaving && lastSaveTime\" \n name=\"save\" \n size=\"14\"\n [title]=\"'Saved at ' + (lastSaveTime | date:'HH:mm:ss')\">\n </nile-icon>\n <nile-icon \n *ngIf=\"isSaving\" \n name=\"loader\" \n size=\"14\"\n title=\"Saving...\">\n </nile-icon>\n </div>\n\n <!-- Workbook Actions
|
|
10401
|
+
args: [{ selector: 'st-workbook', template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen$ | async\">\n <nile-tab-group [activeIndex]=\"activeSheetIndex\">\n \n <!-- Sheet Tabs (one per sheet) -->\n <nile-tab *ngFor=\"let sheet of sheets; let i = index\"\n slot=\"nav\" \n panel=\"shared-panel\"\n [class.active]=\"i === activeSheetIndex\"\n (click)=\"onTabChange(i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n \n <!-- Tab actions dropdown button -->\n <button class=\"tab-actions-button\"\n (click)=\"openTabActions($event, sheet, i)\"\n *ngIf=\"hasTabActions(sheet)\">\n <nile-icon name=\"arrowdown\" size=\"14\"></nile-icon>\n </button>\n </div>\n </nile-tab>\n \n <!-- Toolbar Tab (for workbook controls) -->\n <nile-tab slot=\"nav\" \n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\">\n <!-- Autosave Indicator -->\n <div class=\"autosave-indicator\" *ngIf=\"autosaveEnabled\">\n <nile-icon \n *ngIf=\"!isSaving && lastSaveTime\" \n name=\"save\" \n size=\"14\"\n [title]=\"'Saved at ' + (lastSaveTime | date:'HH:mm:ss')\">\n </nile-icon>\n <nile-icon \n *ngIf=\"isSaving\" \n name=\"loader\" \n size=\"14\"\n title=\"Saving...\">\n </nile-icon>\n </div>\n\n <!-- Toolbar Workbook Actions (shown as individual buttons) -->\n <button *ngFor=\"let action of toolbarWorkbookActions\"\n class=\"toolbar-action-button\"\n [class.disabled]=\"isActionDisabled(action)\"\n [title]=\"action.label\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" [name]=\"action.icon\"></nile-icon>\n <span *ngIf=\"!action.icon\">{{ action.label }}</span>\n </button>\n\n <!-- Workbook Actions Dropdown -->\n <button class=\"workbook-actions-button\"\n *ngIf=\"visibleWorkbookActions.length > 0\"\n (click)=\"toggleWorkbookActions($event)\"\n title=\"Workbook Actions\">\n <nile-icon name=\"settings\"></nile-icon>\n </button>\n \n <!-- Add Sheet Button -->\n <button class=\"add-sheet-button\"\n *ngIf=\"canAddSheet\"\n (click)=\"onAddSheet()\"\n title=\"Add Sheet\">\n <nile-icon name=\"plus\"></nile-icon>\n </button>\n \n <!-- Fullscreen Button -->\n <button class=\"fullscreen-button\"\n *ngIf=\"config.display?.allowFullscreen !== false\"\n (click)=\"toggleFullscreen()\"\n [title]=\"(isFullscreen$ | async) ? 'Exit Fullscreen' : 'Fullscreen'\">\n <nile-icon [name]=\"(isFullscreen$ | async) ? 'collapse' : 'expand-06'\"></nile-icon>\n </button>\n </div>\n </nile-tab>\n \n <!-- Single Shared Tab Panel -->\n <nile-tab-panel name=\"shared-panel\">\n <!-- Lazy loading strategy: table is destroyed and recreated with new config/state when sheet changes -->\n <!-- Using ngFor with trackBy to force complete reinitialization when tableComponentKey changes -->\n <ng-container *ngFor=\"let key of [tableComponentKey]; trackBy: trackByKey\">\n <st-table *ngIf=\"currentTableConfig && currentTableState\"\n [attr.data-sheet-key]=\"key\"\n [tableConfig]=\"currentTableConfig\"\n [data$]=\"currentTableData$\"\n [tableState]=\"currentTableState\"\n (cellChange)=\"onCellChange($event)\"\n (cellSave)=\"onCellSave($event)\"\n (stateChange)=\"onTableStateChange($event)\"\n (requestAddRow)=\"onRequestAddRow($event)\">\n </st-table>\n </ng-container>\n </nile-tab-panel>\n \n </nile-tab-group>\n</div>\n\n<!-- Tab Actions Dropdown -->\n<div class=\"tab-actions-dropdown\" \n *ngIf=\"tabActionsOpen\"\n [ngStyle]=\"tabActionsPosition\">\n <div class=\"dropdown-backdrop\" (click)=\"closeTabActions()\"></div>\n <div class=\"dropdown-menu\">\n <nile-menu>\n <nile-menu-item *ngFor=\"let action of selectedSheet?.tabActions\" \n (click)=\"onTabActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" slot=\"prefix\" size=\"14\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </nile-menu>\n </div>\n</div>\n\n<!-- Workbook Actions Dropdown -->\n<div class=\"workbook-actions-dropdown\"\n *ngIf=\"workbookActionsOpen\"\n [ngStyle]=\"workbookActionsPosition\">\n <div class=\"dropdown-backdrop\" (click)=\"closeWorkbookActions()\"></div>\n <div class=\"dropdown-menu\">\n <nile-menu>\n <nile-menu-item *ngFor=\"let action of visibleWorkbookActions\"\n [class.disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n <nile-icon *ngIf=\"action.icon\" slot=\"prefix\" size=\"14\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </nile-menu>\n </div>\n</div>\n\n<!-- Fullscreen Backdrop -->\n<div class=\"fullscreen-backdrop\" \n *ngIf=\"isFullscreen$ | async\"\n (click)=\"toggleFullscreen()\">\n</div>\n\n", styles: ["@import\"@aquera/nile/lib/styles/variables.css\";:host{display:block;width:100%;height:100%}.workbook-container{display:flex;flex-direction:column;height:100%;background:white;border:1px solid var(--nile-color-neutral-200);border-radius:4px;overflow:hidden}.workbook-container.fullscreen{position:fixed;inset:0;z-index:2000;border:none;border-radius:0}.workbook-container nile-tab-group{height:100%;display:flex;flex-direction:column}.sheet-tab-content{display:flex;align-items:center;gap:8px;padding:0 4px}.sheet-tab-content .sheet-name{font-size:12px;font-weight:500;font-family:var(--nile-font-family-sans-serif);color:#000}.sheet-tab-content .tab-actions-button{width:20px;height:20px;padding:0;background:transparent;border:none;cursor:pointer}.workbook-toolbar-tab{margin-left:auto!important;pointer-events:auto!important;border-left:1px solid var(--nile-color-neutral-200)}.workbook-toolbar-tab .workbook-toolbar-content{display:flex;gap:4px;align-items:center;padding:0 8px}.workbook-toolbar-tab .workbook-toolbar-content .autosave-indicator{display:flex;align-items:center;margin-right:8px;color:var(--nile-color-success-500)}.workbook-toolbar-tab button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;color:var(--nile-color-neutral-600)}.workbook-toolbar-tab button:hover{background-color:var(--nile-color-neutral-100);color:var(--nile-color-neutral-900)}.workbook-toolbar-tab button:active{background-color:var(--nile-color-neutral-200)}.workbook-toolbar-tab button nile-icon{font-size:16px}.workbook-toolbar-tab button.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tab-actions-dropdown{position:fixed;z-index:1001}.tab-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.tab-actions-dropdown .dropdown-menu{position:relative;min-width:180px;background:white;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.tab-actions-dropdown .dropdown-menu nile-menu{display:block}.workbook-actions-dropdown{position:fixed;z-index:1001}.workbook-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.workbook-actions-dropdown .dropdown-menu{position:relative;min-width:200px;background:white;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.workbook-actions-dropdown .dropdown-menu nile-menu{display:block}.fullscreen-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:1999;cursor:pointer}nile-tab-group::part(nav){background-color:#fafafa}nile-tab-group::part(active-tab-indicator-path){background:none}nile-tab-group::part(active-tab-indicator){border-bottom:none}nile-tab-group::part(tabs){gap:0}nile-tab-group nile-tab{border:1px solid #e0e0e0;border-top-left-radius:6px;border-top-right-radius:6px}nile-tab-group nile-tab::part(base){padding-left:.5rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom-left-radius:0;border-bottom-right-radius:0}nile-tab-group nile-tab.active{background-color:#fff;color:#000}nile-tab-group nile-tab.active .sheet-name{font-weight:600}nile-tab-group nile-tab-panel::part(base){padding:0;max-height:30rem}\n"] }]
|
|
10441
10402
|
}], ctorParameters: function () { return [{ type: AutosaveService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { config: [{
|
|
10442
10403
|
type: Input
|
|
10443
10404
|
}], sheetsData: [{
|