nexheal-lib 0.0.46 → 0.0.49

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.
@@ -2791,10 +2791,13 @@ class PaginatedAutocompleteControl {
2791
2791
  paginationType = 'scroll';
2792
2792
  pageSize = 10;
2793
2793
  searchDebounce = 300;
2794
+ /** Re-fetch page 1 every time the dropdown opens, instead of reusing cached results */
2795
+ refreshOnOpen = false;
2794
2796
  /** Total record count for the current search, from the API response */
2795
2797
  totalCount = 0;
2796
2798
  _disabled = false;
2797
2799
  _pendingPage = 1;
2800
+ lastLoadedSearch = null;
2798
2801
  /** Items of the page just loaded. Page 1 replaces the list, later pages append. */
2799
2802
  _displayedOptions = [];
2800
2803
  set options(value) {
@@ -2811,6 +2814,8 @@ class PaginatedAutocompleteControl {
2811
2814
  ];
2812
2815
  }
2813
2816
  this.isPageLoading = false;
2817
+ this.loadErrorMessage = null;
2818
+ this.failedPage = null;
2814
2819
  this.processValueBuffer();
2815
2820
  if (this.isDropdownOpen) {
2816
2821
  if (this._pendingPage <= 1) {
@@ -2847,6 +2852,8 @@ class PaginatedAutocompleteControl {
2847
2852
  valueBuffer = null;
2848
2853
  popperInstance;
2849
2854
  preventClearOnBlur = false;
2855
+ searchInput$ = new Subject();
2856
+ cancelPendingSearch = false;
2850
2857
  onChange = () => { };
2851
2858
  onTouched = () => { };
2852
2859
  inputElement;
@@ -2855,6 +2862,8 @@ class PaginatedAutocompleteControl {
2855
2862
  isDropdownOpen = false;
2856
2863
  hasFocus = false;
2857
2864
  isPageLoading = false;
2865
+ loadErrorMessage = null;
2866
+ failedPage = null;
2858
2867
  selectedItems;
2859
2868
  highlightedIndex = null;
2860
2869
  currentPage = 1;
@@ -2864,12 +2873,17 @@ class PaginatedAutocompleteControl {
2864
2873
  constructor() { }
2865
2874
  ngOnInit() {
2866
2875
  this.inputControl.markAsPristine();
2867
- this.subscription.add(this.inputControl.valueChanges
2868
- .pipe(debounceTime(this.searchDebounce), distinctUntilChanged())
2876
+ // Search is driven by real keystrokes (the DOM input event), never by
2877
+ // programmatic setValue — this avoids selection/debounce races entirely.
2878
+ this.subscription.add(this.searchInput$
2879
+ .pipe(debounceTime(this.searchDebounce))
2869
2880
  .subscribe((value) => {
2881
+ // A selection happened after this keystroke — drop the search
2882
+ if (this.cancelPendingSearch)
2883
+ return;
2870
2884
  if (this.readonly || !this.hasFocus)
2871
2885
  return;
2872
- this.loadPage(1, value || "");
2886
+ this.loadPage(1, value);
2873
2887
  }));
2874
2888
  }
2875
2889
  ngAfterViewInit() {
@@ -2883,6 +2897,7 @@ class PaginatedAutocompleteControl {
2883
2897
  }
2884
2898
  // CVA
2885
2899
  writeValue(value) {
2900
+ this.cancelPendingSearch = true;
2886
2901
  if (value == null) {
2887
2902
  this.valueBuffer = null;
2888
2903
  this.selectedItems = null;
@@ -2926,6 +2941,9 @@ class PaginatedAutocompleteControl {
2926
2941
  loadPage(page, search) {
2927
2942
  this.currentPage = page;
2928
2943
  this._pendingPage = page;
2944
+ this.lastLoadedSearch = search;
2945
+ this.loadErrorMessage = null;
2946
+ this.failedPage = null;
2929
2947
  this.isPageLoading = true;
2930
2948
  if (page === 1) {
2931
2949
  this.openDropdown();
@@ -2953,6 +2971,22 @@ class PaginatedAutocompleteControl {
2953
2971
  event.stopPropagation();
2954
2972
  this.loadNextPage();
2955
2973
  }
2974
+ /** Call from the parent's API error handler to unblock paging and show a
2975
+ * Retry row in the dropdown. e.g. error: () => ctrl.pageLoadFailed() */
2976
+ pageLoadFailed(message = "Couldn't load results") {
2977
+ this.isPageLoading = false;
2978
+ this.loadErrorMessage = message;
2979
+ this.failedPage = this._pendingPage;
2980
+ if (this._pendingPage > 1) {
2981
+ // Roll back so a retry re-requests the failed page, not the one after it
2982
+ this.currentPage = this._pendingPage - 1;
2983
+ }
2984
+ }
2985
+ retryLoad(event) {
2986
+ event.stopPropagation();
2987
+ const page = this.failedPage ?? 1;
2988
+ this.loadPage(page, this.lastLoadedSearch || "");
2989
+ }
2956
2990
  openDropdown() {
2957
2991
  if (this.isDropdownOpen)
2958
2992
  return;
@@ -2964,6 +2998,7 @@ class PaginatedAutocompleteControl {
2964
2998
  }
2965
2999
  // selection
2966
3000
  selectSuggestion(suggestion) {
3001
+ this.cancelPendingSearch = true;
2967
3002
  this.inputControl.setValue(suggestion[this.optionDisplayProperty], {
2968
3003
  emitEvent: false,
2969
3004
  });
@@ -2977,22 +3012,61 @@ class PaginatedAutocompleteControl {
2977
3012
  }
2978
3013
  }
2979
3014
  // events
3015
+ onUserType(event) {
3016
+ if (this.readonly)
3017
+ return;
3018
+ // A real keystroke re-arms searching after any selection cancelled it
3019
+ this.cancelPendingSearch = false;
3020
+ this.searchInput$.next(event.target.value || "");
3021
+ }
2980
3022
  onFocus() {
2981
3023
  this.hasFocus = true;
2982
3024
  if (this.readonly || this.isDropdownOpen)
2983
3025
  return;
2984
- this.loadPage(1, this.inputControl.value || "");
3026
+ this.openWithSearch();
2985
3027
  }
2986
3028
  onInputClick() {
2987
3029
  if (this.readonly || this.isDropdownOpen)
2988
3030
  return;
2989
3031
  if (this.hasFocus) {
2990
- this.loadPage(1, this.inputControl.value || "");
3032
+ this.openWithSearch();
2991
3033
  }
2992
3034
  }
3035
+ /** Text to search with when the dropdown opens: if the input just holds the
3036
+ * selected item's display text, open with the full list instead. */
3037
+ openSearchTerm() {
3038
+ const value = this.inputControl.value || "";
3039
+ if (this.selectedItems &&
3040
+ value === this.selectedItems[this.optionDisplayProperty]) {
3041
+ return "";
3042
+ }
3043
+ return value;
3044
+ }
3045
+ openWithSearch() {
3046
+ const term = this.openSearchTerm();
3047
+ // Reuse cached results when reopening with the same search term
3048
+ if (!this.refreshOnOpen &&
3049
+ this.lastLoadedSearch === term &&
3050
+ this._displayedOptions.length > 0) {
3051
+ this.openDropdown();
3052
+ const idx = this.selectedItems
3053
+ ? this._displayedOptions.findIndex((o) => o.id === this.selectedItems.id)
3054
+ : -1;
3055
+ this.highlightedIndex =
3056
+ idx >= 0 ? idx : this._displayedOptions.length > 0 ? 0 : null;
3057
+ return;
3058
+ }
3059
+ this.loadPage(1, term);
3060
+ }
2993
3061
  onBlur() {
2994
3062
  this.blurEvent.emit();
2995
3063
  this.onTouched();
3064
+ // mousedown fires before blur — if no dropdown interaction flagged itself,
3065
+ // the user clicked outside: close immediately instead of waiting 300ms.
3066
+ if (!this.preventClearOnBlur) {
3067
+ this.isDropdownOpen = false;
3068
+ this.isPageLoading = false;
3069
+ }
2996
3070
  // Delay so option / load-more mousedown and click can occur first.
2997
3071
  setTimeout(() => {
2998
3072
  if (this.preventClearOnBlur) {
@@ -3086,6 +3160,19 @@ class PaginatedAutocompleteControl {
3086
3160
  fallbackPlacements: ["top-start", "bottom-start"],
3087
3161
  },
3088
3162
  },
3163
+ // Make the dropdown exactly as wide as the input
3164
+ {
3165
+ name: "sameWidth",
3166
+ enabled: true,
3167
+ phase: "beforeWrite",
3168
+ requires: ["computeStyles"],
3169
+ fn: ({ state }) => {
3170
+ state.styles["popper"].width = `${state.rects.reference.width}px`;
3171
+ },
3172
+ effect: ({ state }) => {
3173
+ state.elements.popper.style.width = `${state.elements.reference.offsetWidth}px`;
3174
+ },
3175
+ },
3089
3176
  ],
3090
3177
  });
3091
3178
  }
@@ -3100,6 +3187,7 @@ class PaginatedAutocompleteControl {
3100
3187
  }
3101
3188
  // clear
3102
3189
  resetInput() {
3190
+ this.cancelPendingSearch = true;
3103
3191
  this.inputControl.setValue("", { emitEvent: false });
3104
3192
  this.selectedItems = null;
3105
3193
  this.valueBuffer = null;
@@ -3110,13 +3198,13 @@ class PaginatedAutocompleteControl {
3110
3198
  }
3111
3199
  }
3112
3200
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PaginatedAutocompleteControl, deps: [], target: i0.ɵɵFactoryTarget.Component });
3113
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: PaginatedAutocompleteControl, isStandalone: true, selector: "paginated-autocomplete-control", inputs: { title: "title", required: "required", placeholder: "placeholder", customClass: "customClass", clearVal: "clearVal", error: "error", errorMessage: "errorMessage", autocomplete: "autocomplete", inputLoader: "inputLoader", readonly: "readonly", optionDisplayProperty: "optionDisplayProperty", paginationType: "paginationType", pageSize: "pageSize", searchDebounce: "searchDebounce", totalCount: "totalCount", options: "options", disabled: "disabled" }, outputs: { pageChange: "pageChange", optionSelected: "optionSelected", selectionCleared: "selectionCleared", blurEvent: "blurEvent", optionPatched: "optionPatched" }, providers: [
3201
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: PaginatedAutocompleteControl, isStandalone: true, selector: "paginated-autocomplete-control", inputs: { title: "title", required: "required", placeholder: "placeholder", customClass: "customClass", clearVal: "clearVal", error: "error", errorMessage: "errorMessage", autocomplete: "autocomplete", inputLoader: "inputLoader", readonly: "readonly", optionDisplayProperty: "optionDisplayProperty", paginationType: "paginationType", pageSize: "pageSize", searchDebounce: "searchDebounce", refreshOnOpen: "refreshOnOpen", totalCount: "totalCount", options: "options", disabled: "disabled" }, outputs: { pageChange: "pageChange", optionSelected: "optionSelected", selectionCleared: "selectionCleared", blurEvent: "blurEvent", optionPatched: "optionPatched" }, providers: [
3114
3202
  {
3115
3203
  provide: NG_VALUE_ACCESSOR,
3116
3204
  useExisting: PaginatedAutocompleteControl,
3117
3205
  multi: true,
3118
3206
  },
3119
- ], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }, { propertyName: "dropdownElement", first: true, predicate: ["dropdownElement"], descendants: true }], ngImport: i0, template: "<div class=\"form-group auto-complete paginated-autocomplete\" [ngClass]=\"customClass\" [class.readonly]=\"readonly\">\n @if (title) {\n <label class=\"inp-label\" [ngClass]=\"{ 'required': required }\">{{ title }}</label>\n }\n\n <input #inputElement type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [formControl]=\"inputControl\"\n (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" (focus)=\"onFocus()\" (click)=\"onInputClick()\"\n [ngClass]=\"{'is-invalid': error}\" [attr.autocomplete]=\"autocomplete || null\" [readonly]=\"readonly\" />\n\n <span class=\"focus-border\"></span>\n\n @if (!inputLoader && inputControl.value && clearVal && hasFocus) {\n <label class=\"clear\" (mousedown)=\"onOptionMouseDown()\" (click)=\"resetInput()\">\n <i class=\"he he-close\"></i>\n </label>\n }\n\n @if (isDropdownOpen) {\n <div #dropdownElement class=\"option-list\" (scroll)=\"onListScroll($event)\">\n @if (options.length === 0 && !isPageLoading) {\n <div class=\"no-results\">\n <div>No results found</div>\n </div>\n } @else {\n @for (suggestion of options; track suggestion.id; let i = $index) {\n <div class=\"list-item\" [ngClass]=\"{\n 'active': suggestion === selectedItems,\n 'highlighted': highlightedIndex === i\n }\" (mousedown)=\"onOptionMouseDown()\" (click)=\"selectSuggestion(suggestion)\" (mouseover)=\"onMouseOver(i)\">\n {{ suggestion[optionDisplayProperty] }}\n </div>\n }\n\n @if (isPageLoading) {\n <div class=\"list-loading\">Loading...</div>\n }\n\n @if (paginationType === 'click' && hasMore && !isPageLoading) {\n <div class=\"load-more\" (mousedown)=\"onOptionMouseDown()\" (click)=\"onLoadMoreClick($event)\">\n Load more ({{ options.length }} of {{ totalCount }})\n </div>\n }\n }\n </div>\n }\n\n @if (inputLoader) {\n <label class=\"loader input-loader\"></label>\n }\n\n @if (error) {\n <div class=\"val-msg\">{{ errorMessage }}</div>\n }\n</div>\n", styles: [".form-group.paginated-autocomplete .form-control{padding-right:unset}.form-group.paginated-autocomplete .clear{right:7px}.form-group.paginated-autocomplete .option-list{max-height:220px;overflow-y:auto}.form-group.paginated-autocomplete .option-list .no-results{padding:10px;color:#9b9b9b;text-align:center}.form-group.paginated-autocomplete .option-list .list-loading{padding:8px 10px;color:#9b9b9b;text-align:center;font-size:12px}.form-group.paginated-autocomplete .option-list .load-more{padding:8px 10px;text-align:center;cursor:pointer;color:#0d6efd;font-size:13px;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}.form-group.paginated-autocomplete .option-list .load-more:hover{background-color:#f5f5f5}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
3207
+ ], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }, { propertyName: "dropdownElement", first: true, predicate: ["dropdownElement"], descendants: true }], ngImport: i0, template: "<div class=\"form-group auto-complete paginated-autocomplete\" [ngClass]=\"customClass\" [class.readonly]=\"readonly\">\n @if (title) {\n <label class=\"inp-label\" [ngClass]=\"{ 'required': required }\">{{ title }}</label>\n }\n\n <input #inputElement type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [formControl]=\"inputControl\"\n (input)=\"onUserType($event)\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" (focus)=\"onFocus()\" (click)=\"onInputClick()\"\n [ngClass]=\"{'is-invalid': error}\" [attr.autocomplete]=\"autocomplete || null\" [readonly]=\"readonly\" />\n\n <span class=\"focus-border\"></span>\n\n @if (!inputLoader && inputControl.value && clearVal && hasFocus) {\n <label class=\"clear\" (mousedown)=\"onOptionMouseDown()\" (click)=\"resetInput()\">\n <i class=\"he he-close\"></i>\n </label>\n }\n\n @if (isDropdownOpen) {\n <div #dropdownElement class=\"option-list\" (mousedown)=\"onOptionMouseDown()\" (scroll)=\"onListScroll($event)\">\n @if (options.length === 0 && !isPageLoading && !loadErrorMessage) {\n <div class=\"no-results\">\n <div>No results found</div>\n </div>\n } @else {\n @for (suggestion of options; track suggestion.id; let i = $index) {\n <div class=\"list-item\" [ngClass]=\"{\n 'active': suggestion === selectedItems,\n 'highlighted': highlightedIndex === i\n }\" (click)=\"selectSuggestion(suggestion)\" (mouseover)=\"onMouseOver(i)\">\n {{ suggestion[optionDisplayProperty] }}\n </div>\n }\n\n @if (isPageLoading) {\n <div class=\"list-loading\">Loading...</div>\n }\n\n @if (loadErrorMessage) {\n <div class=\"load-error\" (click)=\"retryLoad($event)\">\n {{ loadErrorMessage }} \u00B7 <span class=\"retry\">Retry</span>\n </div>\n }\n\n @if (paginationType === 'click' && hasMore && !isPageLoading && !loadErrorMessage) {\n <div class=\"load-more\" (click)=\"onLoadMoreClick($event)\">\n Load more ({{ options.length }} of {{ totalCount }})\n </div>\n }\n\n @if (totalCount > 0 && options.length > 0 && !loadErrorMessage && !(paginationType === 'click' && hasMore)) {\n <div class=\"list-footer\">\n {{ options.length }} of {{ totalCount }}\n @if (hasMore && paginationType === 'scroll') {\n <span> \u00B7 scroll for more</span>\n }\n </div>\n }\n }\n </div>\n }\n\n @if (inputLoader) {\n <label class=\"loader input-loader\"></label>\n }\n\n @if (error) {\n <div class=\"val-msg\">{{ errorMessage }}</div>\n }\n</div>\n", styles: [".form-group.paginated-autocomplete .form-control{padding-right:unset}.form-group.paginated-autocomplete .clear{right:7px}.form-group.paginated-autocomplete .option-list{max-height:220px;overflow-y:auto}.form-group.paginated-autocomplete .option-list .no-results{padding:10px;color:#9b9b9b;text-align:center}.form-group.paginated-autocomplete .option-list .list-loading{padding:8px 10px;color:#9b9b9b;text-align:center;font-size:12px}.form-group.paginated-autocomplete .option-list .load-more{padding:8px 10px;text-align:center;cursor:pointer;color:#0d6efd;font-size:13px;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}.form-group.paginated-autocomplete .option-list .load-more:hover{background-color:#f5f5f5}.form-group.paginated-autocomplete .option-list .load-error{padding:8px 10px;text-align:center;font-size:12px;color:#dc3545;cursor:pointer;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}.form-group.paginated-autocomplete .option-list .load-error .retry{color:#0d6efd;text-decoration:underline}.form-group.paginated-autocomplete .option-list .load-error:hover{background-color:#f5f5f5}.form-group.paginated-autocomplete .option-list .list-footer{position:sticky;bottom:0;padding:4px 10px;text-align:center;font-size:11px;color:#9b9b9b;background-color:#fff;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
3120
3208
  }
3121
3209
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PaginatedAutocompleteControl, decorators: [{
3122
3210
  type: Component,
@@ -3126,7 +3214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
3126
3214
  useExisting: PaginatedAutocompleteControl,
3127
3215
  multi: true,
3128
3216
  },
3129
- ], template: "<div class=\"form-group auto-complete paginated-autocomplete\" [ngClass]=\"customClass\" [class.readonly]=\"readonly\">\n @if (title) {\n <label class=\"inp-label\" [ngClass]=\"{ 'required': required }\">{{ title }}</label>\n }\n\n <input #inputElement type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [formControl]=\"inputControl\"\n (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" (focus)=\"onFocus()\" (click)=\"onInputClick()\"\n [ngClass]=\"{'is-invalid': error}\" [attr.autocomplete]=\"autocomplete || null\" [readonly]=\"readonly\" />\n\n <span class=\"focus-border\"></span>\n\n @if (!inputLoader && inputControl.value && clearVal && hasFocus) {\n <label class=\"clear\" (mousedown)=\"onOptionMouseDown()\" (click)=\"resetInput()\">\n <i class=\"he he-close\"></i>\n </label>\n }\n\n @if (isDropdownOpen) {\n <div #dropdownElement class=\"option-list\" (scroll)=\"onListScroll($event)\">\n @if (options.length === 0 && !isPageLoading) {\n <div class=\"no-results\">\n <div>No results found</div>\n </div>\n } @else {\n @for (suggestion of options; track suggestion.id; let i = $index) {\n <div class=\"list-item\" [ngClass]=\"{\n 'active': suggestion === selectedItems,\n 'highlighted': highlightedIndex === i\n }\" (mousedown)=\"onOptionMouseDown()\" (click)=\"selectSuggestion(suggestion)\" (mouseover)=\"onMouseOver(i)\">\n {{ suggestion[optionDisplayProperty] }}\n </div>\n }\n\n @if (isPageLoading) {\n <div class=\"list-loading\">Loading...</div>\n }\n\n @if (paginationType === 'click' && hasMore && !isPageLoading) {\n <div class=\"load-more\" (mousedown)=\"onOptionMouseDown()\" (click)=\"onLoadMoreClick($event)\">\n Load more ({{ options.length }} of {{ totalCount }})\n </div>\n }\n }\n </div>\n }\n\n @if (inputLoader) {\n <label class=\"loader input-loader\"></label>\n }\n\n @if (error) {\n <div class=\"val-msg\">{{ errorMessage }}</div>\n }\n</div>\n", styles: [".form-group.paginated-autocomplete .form-control{padding-right:unset}.form-group.paginated-autocomplete .clear{right:7px}.form-group.paginated-autocomplete .option-list{max-height:220px;overflow-y:auto}.form-group.paginated-autocomplete .option-list .no-results{padding:10px;color:#9b9b9b;text-align:center}.form-group.paginated-autocomplete .option-list .list-loading{padding:8px 10px;color:#9b9b9b;text-align:center;font-size:12px}.form-group.paginated-autocomplete .option-list .load-more{padding:8px 10px;text-align:center;cursor:pointer;color:#0d6efd;font-size:13px;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}.form-group.paginated-autocomplete .option-list .load-more:hover{background-color:#f5f5f5}\n"] }]
3217
+ ], template: "<div class=\"form-group auto-complete paginated-autocomplete\" [ngClass]=\"customClass\" [class.readonly]=\"readonly\">\n @if (title) {\n <label class=\"inp-label\" [ngClass]=\"{ 'required': required }\">{{ title }}</label>\n }\n\n <input #inputElement type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [formControl]=\"inputControl\"\n (input)=\"onUserType($event)\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" (focus)=\"onFocus()\" (click)=\"onInputClick()\"\n [ngClass]=\"{'is-invalid': error}\" [attr.autocomplete]=\"autocomplete || null\" [readonly]=\"readonly\" />\n\n <span class=\"focus-border\"></span>\n\n @if (!inputLoader && inputControl.value && clearVal && hasFocus) {\n <label class=\"clear\" (mousedown)=\"onOptionMouseDown()\" (click)=\"resetInput()\">\n <i class=\"he he-close\"></i>\n </label>\n }\n\n @if (isDropdownOpen) {\n <div #dropdownElement class=\"option-list\" (mousedown)=\"onOptionMouseDown()\" (scroll)=\"onListScroll($event)\">\n @if (options.length === 0 && !isPageLoading && !loadErrorMessage) {\n <div class=\"no-results\">\n <div>No results found</div>\n </div>\n } @else {\n @for (suggestion of options; track suggestion.id; let i = $index) {\n <div class=\"list-item\" [ngClass]=\"{\n 'active': suggestion === selectedItems,\n 'highlighted': highlightedIndex === i\n }\" (click)=\"selectSuggestion(suggestion)\" (mouseover)=\"onMouseOver(i)\">\n {{ suggestion[optionDisplayProperty] }}\n </div>\n }\n\n @if (isPageLoading) {\n <div class=\"list-loading\">Loading...</div>\n }\n\n @if (loadErrorMessage) {\n <div class=\"load-error\" (click)=\"retryLoad($event)\">\n {{ loadErrorMessage }} \u00B7 <span class=\"retry\">Retry</span>\n </div>\n }\n\n @if (paginationType === 'click' && hasMore && !isPageLoading && !loadErrorMessage) {\n <div class=\"load-more\" (click)=\"onLoadMoreClick($event)\">\n Load more ({{ options.length }} of {{ totalCount }})\n </div>\n }\n\n @if (totalCount > 0 && options.length > 0 && !loadErrorMessage && !(paginationType === 'click' && hasMore)) {\n <div class=\"list-footer\">\n {{ options.length }} of {{ totalCount }}\n @if (hasMore && paginationType === 'scroll') {\n <span> \u00B7 scroll for more</span>\n }\n </div>\n }\n }\n </div>\n }\n\n @if (inputLoader) {\n <label class=\"loader input-loader\"></label>\n }\n\n @if (error) {\n <div class=\"val-msg\">{{ errorMessage }}</div>\n }\n</div>\n", styles: [".form-group.paginated-autocomplete .form-control{padding-right:unset}.form-group.paginated-autocomplete .clear{right:7px}.form-group.paginated-autocomplete .option-list{max-height:220px;overflow-y:auto}.form-group.paginated-autocomplete .option-list .no-results{padding:10px;color:#9b9b9b;text-align:center}.form-group.paginated-autocomplete .option-list .list-loading{padding:8px 10px;color:#9b9b9b;text-align:center;font-size:12px}.form-group.paginated-autocomplete .option-list .load-more{padding:8px 10px;text-align:center;cursor:pointer;color:#0d6efd;font-size:13px;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}.form-group.paginated-autocomplete .option-list .load-more:hover{background-color:#f5f5f5}.form-group.paginated-autocomplete .option-list .load-error{padding:8px 10px;text-align:center;font-size:12px;color:#dc3545;cursor:pointer;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}.form-group.paginated-autocomplete .option-list .load-error .retry{color:#0d6efd;text-decoration:underline}.form-group.paginated-autocomplete .option-list .load-error:hover{background-color:#f5f5f5}.form-group.paginated-autocomplete .option-list .list-footer{position:sticky;bottom:0;padding:4px 10px;text-align:center;font-size:11px;color:#9b9b9b;background-color:#fff;border-top:1px solid #eee;-webkit-user-select:none;user-select:none}\n"] }]
3130
3218
  }], ctorParameters: () => [], propDecorators: { title: [{
3131
3219
  type: Input
3132
3220
  }], required: [{
@@ -3155,6 +3243,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
3155
3243
  type: Input
3156
3244
  }], searchDebounce: [{
3157
3245
  type: Input
3246
+ }], refreshOnOpen: [{
3247
+ type: Input
3158
3248
  }], totalCount: [{
3159
3249
  type: Input
3160
3250
  }], options: [{