@aquera/ngx-smart-table 0.0.16-alpha → 0.0.17-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.
@@ -3678,6 +3678,7 @@ class NileSelectEditor {
3678
3678
  this.acceptsInitialKeypress = false;
3679
3679
  this.eventListeners = [];
3680
3680
  this.currentOptions = [];
3681
+ this.trackedValues = []; // Track selected values for virtual scroll
3681
3682
  // Handle Observable options
3682
3683
  if (isObservable(options.options)) {
3683
3684
  this.optionsSubscription = options.options.subscribe(opts => {
@@ -3721,13 +3722,15 @@ class NileSelectEditor {
3721
3722
  // Clear container and append select
3722
3723
  context.container.innerHTML = '';
3723
3724
  context.container.appendChild(this.select);
3724
- // Focus and auto-open after render
3725
+ // Focus the select after render
3725
3726
  setTimeout(() => {
3726
- if (this.select) {
3727
- this.select.focus();
3728
- this.select.open = true;
3727
+ try {
3728
+ this.select?.focus();
3729
3729
  }
3730
- }, 0);
3730
+ catch (e) {
3731
+ // Ignore errors
3732
+ }
3733
+ }, 50);
3731
3734
  }
3732
3735
  /**
3733
3736
  * Set the initial value for the select
@@ -3739,17 +3742,21 @@ class NileSelectEditor {
3739
3742
  // Handle multiple selection - value should be array
3740
3743
  if (Array.isArray(value)) {
3741
3744
  this.select.value = value;
3745
+ this.trackedValues = [...value]; // Initialize tracked values
3742
3746
  }
3743
3747
  else if (value) {
3744
3748
  this.select.value = [String(value)];
3749
+ this.trackedValues = [String(value)];
3745
3750
  }
3746
3751
  else {
3747
3752
  this.select.value = [];
3753
+ this.trackedValues = [];
3748
3754
  }
3749
3755
  }
3750
3756
  else {
3751
3757
  // Handle single selection
3752
3758
  this.select.value = value ? String(value) : '';
3759
+ this.trackedValues = value ? [String(value)] : [];
3753
3760
  }
3754
3761
  }
3755
3762
  /**
@@ -3833,12 +3840,17 @@ class NileSelectEditor {
3833
3840
  updateOptions() {
3834
3841
  if (!this.select)
3835
3842
  return;
3836
- // Clear existing options
3837
- while (this.select.firstChild) {
3838
- this.select.removeChild(this.select.firstChild);
3843
+ // For virtual scroll mode, just update the data property (no DOM children to clear)
3844
+ if (this.options.enableVirtualScroll) {
3845
+ this.createAndAppendOptions(this.currentOptions);
3846
+ }
3847
+ else {
3848
+ // Standard mode: clear existing nile-option elements first
3849
+ while (this.select.firstChild) {
3850
+ this.select.removeChild(this.select.firstChild);
3851
+ }
3852
+ this.createAndAppendOptions(this.currentOptions);
3839
3853
  }
3840
- // Re-append with new options
3841
- this.createAndAppendOptions(this.currentOptions);
3842
3854
  // Trigger update on the web component
3843
3855
  if (this.select.requestUpdate) {
3844
3856
  this.select.requestUpdate();
@@ -3846,11 +3858,22 @@ class NileSelectEditor {
3846
3858
  }
3847
3859
  /**
3848
3860
  * Create NileOption elements and append them to the select
3861
+ * When enableVirtualScroll is true, uses data property instead of DOM elements
3862
+ * @see https://nile.aqueralabs.com/select-virtual?theme=enterprise
3849
3863
  * @param options - The options to render
3850
3864
  */
3851
3865
  createAndAppendOptions(options) {
3852
3866
  if (!this.select)
3853
3867
  return;
3868
+ // Virtual scroll mode: use data property instead of DOM elements
3869
+ if (this.options.enableVirtualScroll) {
3870
+ const virtualData = options.map(opt => typeof opt === 'string'
3871
+ ? { value: opt, label: opt }
3872
+ : { value: opt.value, label: opt.label, disabled: opt.disabled });
3873
+ this.select.data = virtualData;
3874
+ return;
3875
+ }
3876
+ // Standard mode: create nile-option elements
3854
3877
  options.forEach(opt => {
3855
3878
  const nileOption = document.createElement('nile-option');
3856
3879
  // Auto-detect format: string or SelectOption object
@@ -3899,15 +3922,37 @@ class NileSelectEditor {
3899
3922
  if (!this.options.multiple) {
3900
3923
  const changeHandler = (e) => {
3901
3924
  const customEvent = e;
3902
- if (validateOnSave && !this.select?.checkValidity()) {
3903
- this.select?.reportValidity();
3904
- return;
3925
+ try {
3926
+ if (validateOnSave && this.select && !this.select.checkValidity()) {
3927
+ this.select.reportValidity();
3928
+ return;
3929
+ }
3930
+ }
3931
+ catch (err) {
3932
+ // Ignore validation errors - nile-select internals may not be ready
3905
3933
  }
3906
3934
  context.onSave(this.parseValue(customEvent.detail.value));
3907
3935
  };
3908
3936
  this.select.addEventListener('nile-change', changeHandler);
3909
3937
  this.eventListeners.push({ event: 'nile-change', handler: changeHandler });
3910
3938
  }
3939
+ // For multi-select, track value changes (needed for virtual scroll where value property doesn't update)
3940
+ if (this.options.multiple) {
3941
+ const trackValueHandler = (e) => {
3942
+ const customEvent = e;
3943
+ const newValue = customEvent.detail?.value;
3944
+ if (newValue !== undefined) {
3945
+ if (Array.isArray(newValue)) {
3946
+ this.trackedValues = [...newValue];
3947
+ }
3948
+ else {
3949
+ this.trackedValues = newValue ? [newValue] : [];
3950
+ }
3951
+ }
3952
+ };
3953
+ this.select.addEventListener('nile-change', trackValueHandler);
3954
+ this.eventListeners.push({ event: 'nile-change', handler: trackValueHandler });
3955
+ }
3911
3956
  // Track if save was already triggered (to prevent double save)
3912
3957
  let saveTriggered = false;
3913
3958
  // Use mousedown on document to detect clicks outside the select and portal
@@ -3916,23 +3961,47 @@ class NileSelectEditor {
3916
3961
  return;
3917
3962
  if (!this.select)
3918
3963
  return;
3919
- const target = e.target;
3920
- // Check if click is inside the select element
3921
- if (this.select.contains(target)) {
3922
- return;
3964
+ // Use composedPath to traverse shadow DOM boundaries
3965
+ const path = e.composedPath();
3966
+ // Check if click is inside the select element or any nile-select related elements
3967
+ for (const element of path) {
3968
+ if (!(element instanceof HTMLElement))
3969
+ continue;
3970
+ // Check if it's our select element
3971
+ if (element === this.select) {
3972
+ return;
3973
+ }
3974
+ // Check for nile-select portals (various class names)
3975
+ if (element.classList?.contains('nile-select-portal-append') ||
3976
+ element.classList?.contains('select__listbox') ||
3977
+ element.classList?.contains('select__options') ||
3978
+ element.tagName?.toLowerCase() === 'nile-option' ||
3979
+ element.tagName?.toLowerCase() === 'nile-select') {
3980
+ return;
3981
+ }
3982
+ // Check for any element with nile-select in its class
3983
+ if (element.className && typeof element.className === 'string' &&
3984
+ element.className.includes('nile-select')) {
3985
+ return;
3986
+ }
3923
3987
  }
3924
- // Check if click is inside any nile-select portal
3925
- const portals = document.querySelectorAll('.nile-select-portal-append');
3988
+ // Also check portal containers directly
3989
+ const portals = document.querySelectorAll('.nile-select-portal-append, [class*="select__listbox"]');
3926
3990
  for (let i = 0; i < portals.length; i++) {
3927
- if (portals[i].contains(target)) {
3991
+ if (portals[i].contains(e.target)) {
3928
3992
  return;
3929
3993
  }
3930
3994
  }
3931
3995
  // Click is outside - save and exit
3932
3996
  saveTriggered = true;
3933
- if (validateOnSave && !this.select?.checkValidity()) {
3934
- this.select?.reportValidity();
3935
- return;
3997
+ try {
3998
+ if (validateOnSave && this.select && !this.select.checkValidity()) {
3999
+ this.select.reportValidity();
4000
+ return;
4001
+ }
4002
+ }
4003
+ catch (err) {
4004
+ // Ignore validation errors - nile-select internals may not be ready
3936
4005
  }
3937
4006
  context.onSave(this.getCurrentValue());
3938
4007
  };
@@ -4000,19 +4069,29 @@ class NileSelectEditor {
4000
4069
  }
4001
4070
  }
4002
4071
  focus() {
4003
- this.select?.focus();
4072
+ try {
4073
+ this.select?.focus();
4074
+ }
4075
+ catch (e) {
4076
+ // Ignore focus errors - nile-select internals may not be ready
4077
+ }
4004
4078
  }
4005
4079
  getCurrentValue() {
4006
4080
  if (!this.select) {
4007
4081
  return (this.options.multiple ? [] : '');
4008
4082
  }
4009
- const value = this.select.value;
4010
- // Handle multiple selection
4083
+ // For multi-select, prefer tracked values (more reliable for virtual scroll)
4011
4084
  if (this.options.multiple) {
4012
- return (Array.isArray(value) ? value : [value]);
4085
+ // Use tracked values if available, otherwise try component value
4086
+ let values = this.trackedValues.length > 0 ? this.trackedValues : this.select.value;
4087
+ if (Array.isArray(values)) {
4088
+ return values.filter((v) => v !== undefined && v !== null && v !== '');
4089
+ }
4090
+ return (values ? [values] : []);
4013
4091
  }
4014
- // Handle single selection
4015
- return (Array.isArray(value) ? (value.length > 0 ? value[0] : '') : value);
4092
+ // For single-select, use tracked values or component value
4093
+ let value = this.trackedValues.length > 0 ? this.trackedValues[0] : this.select.value;
4094
+ return (Array.isArray(value) ? (value.length > 0 ? value[0] : '') : (value || ''));
4016
4095
  }
4017
4096
  }
4018
4097