@open-rlb/ng-bootstrap 3.1.4 → 3.1.5

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.
@@ -6686,11 +6686,37 @@ function requiredAutocompleteValue() {
6686
6686
  };
6687
6687
  }
6688
6688
 
6689
- class AutocompleteCountryDialCodeComponent extends AbstractAutocompleteComponent {
6690
- constructor(idService, renderer, control) {
6691
- super(idService, renderer, control);
6689
+ class AutocompleteCountryDialCodeComponent extends AbstractComponent {
6690
+ onDocumentPointerDown(event) {
6691
+ this.handleOutsideEvent(event);
6692
+ }
6693
+ onEscape(event) {
6694
+ if (this.isOpen()) {
6695
+ this.closeDropdown();
6696
+ this.el()?.nativeElement?.blur();
6697
+ }
6698
+ }
6699
+ constructor(idService, hostRef, control) {
6700
+ super(idService, control);
6701
+ this.hostRef = hostRef;
6692
6702
  this.control = control;
6703
+ // State
6704
+ this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
6705
+ this.suggestions = signal([], ...(ngDevMode ? [{ debugName: "suggestions" }] : []));
6706
+ this.hasSuggestions = computed(() => this.suggestions().length > 0, ...(ngDevMode ? [{ debugName: "hasSuggestions" }] : []));
6707
+ // Inputs
6708
+ this.disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
6709
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute });
6710
+ this.placeholder = input('', { ...(ngDevMode ? { debugName: "placeholder" } : {}), alias: 'placeholder' });
6711
+ this.size = input(undefined, ...(ngDevMode ? [{ debugName: "size" }] : []));
6712
+ this.maxHeight = input(200, { ...(ngDevMode ? { debugName: "maxHeight" } : {}), transform: numberAttribute, alias: 'max-height' });
6713
+ this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : {}), transform: booleanAttribute, alias: 'loading' });
6714
+ this.userDefinedId = input('', { ...(ngDevMode ? { debugName: "userDefinedId" } : {}), alias: 'id', transform: (v) => v || '' });
6693
6715
  this.enableFlagIcons = input(true, { ...(ngDevMode ? { debugName: "enableFlagIcons" } : {}), transform: booleanAttribute, alias: 'enable-flag-icons' });
6716
+ // View Children
6717
+ this.el = viewChild('field', ...(ngDevMode ? [{ debugName: "el" }] : []));
6718
+ this.dropdown = viewChild('autocomplete', ...(ngDevMode ? [{ debugName: "dropdown" }] : []));
6719
+ this.selected = output();
6694
6720
  this._countries = [
6695
6721
  {
6696
6722
  text: 'Afghanistan',
@@ -7909,47 +7935,105 @@ class AutocompleteCountryDialCodeComponent extends AbstractAutocompleteComponent
7909
7935
  },
7910
7936
  ];
7911
7937
  }
7912
- getSuggestions(query) {
7913
- this.clearDropdown();
7914
- this.activeIndex.set(-1);
7938
+ update(ev) {
7939
+ if (this.typingTimeout)
7940
+ clearTimeout(this.typingTimeout);
7941
+ this.typingTimeout = setTimeout(() => {
7942
+ if (!this.disabled()) {
7943
+ const t = ev;
7944
+ this.manageSuggestions(t?.value);
7945
+ }
7946
+ }, 200);
7947
+ }
7948
+ onWrite(data) {
7949
+ const field = this.el();
7950
+ if (field && field.nativeElement) {
7951
+ if (typeof data === 'string') {
7952
+ const match = this._countries.find(c => c.value === data);
7953
+ field.nativeElement.value = match ? match.text : data;
7954
+ }
7955
+ else {
7956
+ field.nativeElement.value = data?.text || '';
7957
+ }
7958
+ }
7959
+ }
7960
+ getText(d) {
7961
+ if (!d)
7962
+ return '';
7963
+ if (typeof d === 'string') {
7964
+ const match = this._countries.find(c => c.value === d);
7965
+ return match ? match.text : d;
7966
+ }
7967
+ return d.text;
7968
+ }
7969
+ manageSuggestions(query) {
7970
+ this.suggestions.set([]);
7915
7971
  if (query && query.length > 0) {
7916
7972
  this.openDropdown();
7917
- const suggestions = this.getCountries().filter(o => {
7918
- const _c = o;
7919
- return _c.text.toLowerCase().startsWith(query.toLowerCase());
7920
- });
7921
- this.renderAc(suggestions);
7973
+ const rawSuggestions = this.getCountries().filter(c => c.text.toLowerCase().startsWith(query.toLowerCase()));
7974
+ this.suggestions.set(rawSuggestions);
7922
7975
  }
7923
7976
  else {
7924
7977
  this.closeDropdown();
7925
7978
  }
7926
7979
  }
7927
- getItemText(data) {
7928
- const valueToFind = typeof data === 'object' ? data?.value : data;
7929
- const h = this.getCountries().find(c => {
7930
- if (typeof c === 'object') {
7931
- const _c = c;
7932
- return _c.value === valueToFind;
7933
- }
7934
- return false;
7935
- });
7936
- return typeof h === 'object' ? h.text : typeof data === 'string' ? data : '';
7980
+ selectItem(item, ev) {
7981
+ ev?.stopPropagation();
7982
+ this.selected.emit(item);
7983
+ this.setValue(item);
7984
+ this.closeDropdown();
7985
+ }
7986
+ onEnter(ev) {
7987
+ const t = ev;
7988
+ if (!this.disabled() && t && t.value) {
7989
+ // Try to find exact match by name
7990
+ const match = this._countries.find(c => c.text.toLowerCase() === t.value.toLowerCase());
7991
+ const item = match || { text: t.value, value: t.value };
7992
+ this.setValue(item);
7993
+ this.closeDropdown();
7994
+ }
7995
+ }
7996
+ handleOutsideEvent(event) {
7997
+ if (!this.isOpen())
7998
+ return;
7999
+ const target = event.target;
8000
+ const dropdown = this.dropdown();
8001
+ const path = event.composedPath ? event.composedPath() : [];
8002
+ const clickedInsideHost = this.hostRef?.nativeElement?.contains(target);
8003
+ const clickedInsideDropdown = dropdown?.nativeElement?.contains
8004
+ ? dropdown.nativeElement.contains(target)
8005
+ : false;
8006
+ const clickedInPath = path.length
8007
+ ? path.some(p => p === this.hostRef.nativeElement || (dropdown && p === dropdown.nativeElement))
8008
+ : false;
8009
+ if (!(clickedInsideHost || clickedInsideDropdown || clickedInPath)) {
8010
+ this.closeDropdown();
8011
+ }
8012
+ }
8013
+ openDropdown() {
8014
+ if (this.isOpen())
8015
+ return;
8016
+ this.isOpen.set(true);
8017
+ }
8018
+ closeDropdown() {
8019
+ if (!this.isOpen())
8020
+ return;
8021
+ this.isOpen.set(false);
7937
8022
  }
7938
8023
  getCountries() {
7939
8024
  if (this.enableFlagIcons()) {
7940
- return this._countries.map(country => {
7941
- return {
7942
- ...country,
7943
- iconClass: `fi fi-${country.data.toLowerCase()}`,
7944
- };
7945
- });
8025
+ return this._countries.map(country => ({
8026
+ ...country,
8027
+ // Using 'data' (ISO Code) for flag class
8028
+ iconClass: country.data ? `fi fi-${country.data.toLowerCase()}` : undefined,
8029
+ }));
7946
8030
  }
7947
8031
  else {
7948
8032
  return this._countries;
7949
8033
  }
7950
8034
  }
7951
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteCountryDialCodeComponent, deps: [{ token: UniqueIdService }, { token: i0.Renderer2 }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
7952
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteCountryDialCodeComponent, isStandalone: false, selector: "rlb-autocomplete-country-dial-code", inputs: { enableFlagIcons: { classPropertyName: "enableFlagIcons", publicName: "enable-flag-icons", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
8035
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteCountryDialCodeComponent, deps: [{ token: UniqueIdService }, { token: i0.ElementRef }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
8036
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteCountryDialCodeComponent, isStandalone: false, selector: "rlb-autocomplete-country-dial-code", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "max-height", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, userDefinedId: { classPropertyName: "userDefinedId", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, enableFlagIcons: { classPropertyName: "enableFlagIcons", publicName: "enable-flag-icons", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", selected: "selected" }, host: { listeners: { "document:pointerdown": "onDocumentPointerDown($event)", "document:keydown.escape": "onEscape($event)" } }, viewQueries: [{ propertyName: "el", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "dropdown", first: true, predicate: ["autocomplete"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
7953
8037
  <ng-content select="[before]"></ng-content>
7954
8038
  <div class="input-group has-validation position-relative">
7955
8039
  <input
@@ -7957,7 +8041,8 @@ class AutocompleteCountryDialCodeComponent extends AbstractAutocompleteComponent
7957
8041
  [id]="id"
7958
8042
  class="form-control"
7959
8043
  type="text"
7960
- [attr.autocomplete]="'off'"
8044
+ [value]="getText(value)"
8045
+ autocomplete="off"
7961
8046
  [attr.disabled]="disabled() ? true : undefined"
7962
8047
  [attr.readonly]="readonly() ? true : undefined"
7963
8048
  [attr.placeholder]="placeholder()"
@@ -7969,23 +8054,47 @@ class AutocompleteCountryDialCodeComponent extends AbstractAutocompleteComponent
7969
8054
  'is-valid': control?.touched && control?.valid,
7970
8055
  }"
7971
8056
  (input)="update($event.target)"
8057
+ (keyup.enter)="onEnter($event.target)"
7972
8058
  />
7973
8059
  @if (errors() && showError()) {
7974
8060
  <rlb-input-validation [errors]="errors()" />
7975
8061
  }
7976
- <div
7977
- #autocomplete
7978
- [id]="id + '-ac'"
7979
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
7980
- aria-labelledby="dropdownMenu"
7981
- [style.max-height.px]="maxHeight()"
7982
- style="z-index: 1000; top: 100%;"
7983
- ></div>
8062
+
8063
+ <!-- Dropdown Logic -->
8064
+ @if (isOpen()) {
8065
+ <div
8066
+ #autocomplete
8067
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
8068
+ [style.max-height.px]="maxHeight()"
8069
+ style="z-index: 1000; top: 100%;"
8070
+ >
8071
+ @if (!hasSuggestions()) {
8072
+ <a class="dropdown-item disabled text-center">No suggestions</a>
8073
+ } @else {
8074
+ @for (item of suggestions(); track item.value) {
8075
+ <a
8076
+ class="dropdown-item"
8077
+ (click)="selectItem(item, $event)"
8078
+ style="cursor: pointer"
8079
+ >
8080
+ @if (item.iconClass) {
8081
+ <i
8082
+ [class]="item.iconClass"
8083
+ class="me-2"
8084
+ ></i>
8085
+ }
8086
+ <!-- Display Country Name and Dial Code -->
8087
+ {{ item.text }} ({{ item.value }})
8088
+ </a>
8089
+ }
8090
+ }
8091
+ </div>
8092
+ }
7984
8093
  </div>
7985
- @if (loading() || acLoading()) {
8094
+ @if (loading()) {
7986
8095
  <rlb-progress
7987
8096
  [height]="2"
7988
- [infinite]="loading() || acLoading()"
8097
+ [infinite]="loading()"
7989
8098
  color="primary"
7990
8099
  class="w-100"
7991
8100
  />
@@ -8005,7 +8114,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8005
8114
  [id]="id"
8006
8115
  class="form-control"
8007
8116
  type="text"
8008
- [attr.autocomplete]="'off'"
8117
+ [value]="getText(value)"
8118
+ autocomplete="off"
8009
8119
  [attr.disabled]="disabled() ? true : undefined"
8010
8120
  [attr.readonly]="readonly() ? true : undefined"
8011
8121
  [attr.placeholder]="placeholder()"
@@ -8017,23 +8127,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8017
8127
  'is-valid': control?.touched && control?.valid,
8018
8128
  }"
8019
8129
  (input)="update($event.target)"
8130
+ (keyup.enter)="onEnter($event.target)"
8020
8131
  />
8021
8132
  @if (errors() && showError()) {
8022
8133
  <rlb-input-validation [errors]="errors()" />
8023
8134
  }
8024
- <div
8025
- #autocomplete
8026
- [id]="id + '-ac'"
8027
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
8028
- aria-labelledby="dropdownMenu"
8029
- [style.max-height.px]="maxHeight()"
8030
- style="z-index: 1000; top: 100%;"
8031
- ></div>
8135
+
8136
+ <!-- Dropdown Logic -->
8137
+ @if (isOpen()) {
8138
+ <div
8139
+ #autocomplete
8140
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
8141
+ [style.max-height.px]="maxHeight()"
8142
+ style="z-index: 1000; top: 100%;"
8143
+ >
8144
+ @if (!hasSuggestions()) {
8145
+ <a class="dropdown-item disabled text-center">No suggestions</a>
8146
+ } @else {
8147
+ @for (item of suggestions(); track item.value) {
8148
+ <a
8149
+ class="dropdown-item"
8150
+ (click)="selectItem(item, $event)"
8151
+ style="cursor: pointer"
8152
+ >
8153
+ @if (item.iconClass) {
8154
+ <i
8155
+ [class]="item.iconClass"
8156
+ class="me-2"
8157
+ ></i>
8158
+ }
8159
+ <!-- Display Country Name and Dial Code -->
8160
+ {{ item.text }} ({{ item.value }})
8161
+ </a>
8162
+ }
8163
+ }
8164
+ </div>
8165
+ }
8032
8166
  </div>
8033
- @if (loading() || acLoading()) {
8167
+ @if (loading()) {
8034
8168
  <rlb-progress
8035
8169
  [height]="2"
8036
- [infinite]="loading() || acLoading()"
8170
+ [infinite]="loading()"
8037
8171
  color="primary"
8038
8172
  class="w-100"
8039
8173
  />
@@ -8042,20 +8176,50 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8042
8176
  `,
8043
8177
  standalone: false,
8044
8178
  }]
8045
- }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.Renderer2 }, { type: i2$2.NgControl, decorators: [{
8179
+ }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.ElementRef }, { type: i2$2.NgControl, decorators: [{
8046
8180
  type: Self
8047
8181
  }, {
8048
8182
  type: Optional
8049
- }] }], propDecorators: { enableFlagIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-flag-icons", required: false }] }] } });
8183
+ }] }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "max-height", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], userDefinedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], enableFlagIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-flag-icons", required: false }] }], el: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], dropdown: [{ type: i0.ViewChild, args: ['autocomplete', { isSignal: true }] }], selected: [{ type: i0.Output, args: ["selected"] }], onDocumentPointerDown: [{
8184
+ type: HostListener,
8185
+ args: ['document:pointerdown', ['$event']]
8186
+ }], onEscape: [{
8187
+ type: HostListener,
8188
+ args: ['document:keydown.escape', ['$event']]
8189
+ }] } });
8050
8190
 
8051
- class AutocompleteCountryComponent extends AbstractAutocompleteComponent {
8052
- constructor(idService, renderer, control) {
8053
- super(idService, renderer, control);
8191
+ class AutocompleteCountryComponent extends AbstractComponent {
8192
+ onDocumentPointerDown(event) {
8193
+ this.handleOutsideEvent(event);
8194
+ }
8195
+ onEscape(event) {
8196
+ if (this.isOpen()) {
8197
+ this.closeDropdown();
8198
+ this.el()?.nativeElement?.blur();
8199
+ }
8200
+ }
8201
+ constructor(idService, hostRef, control) {
8202
+ super(idService, control);
8203
+ this.hostRef = hostRef;
8054
8204
  this.control = control;
8055
- this.enableFlagIcons = input(false, { ...(ngDevMode ? { debugName: "enableFlagIcons" } : {}), transform: booleanAttribute,
8056
- alias: 'enable-flag-icons' });
8057
- this.enableValidation = input(false, { ...(ngDevMode ? { debugName: "enableValidation" } : {}), transform: booleanAttribute,
8058
- alias: 'enable-validation' });
8205
+ // State
8206
+ this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
8207
+ this.suggestions = signal([], ...(ngDevMode ? [{ debugName: "suggestions" }] : []));
8208
+ this.hasSuggestions = computed(() => this.suggestions().length > 0, ...(ngDevMode ? [{ debugName: "hasSuggestions" }] : []));
8209
+ // Inputs
8210
+ this.disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
8211
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute });
8212
+ this.placeholder = input('', { ...(ngDevMode ? { debugName: "placeholder" } : {}), alias: 'placeholder' });
8213
+ this.size = input(undefined, ...(ngDevMode ? [{ debugName: "size" }] : []));
8214
+ this.maxHeight = input(200, { ...(ngDevMode ? { debugName: "maxHeight" } : {}), transform: numberAttribute, alias: 'max-height' });
8215
+ this.userDefinedId = input('', { ...(ngDevMode ? { debugName: "userDefinedId" } : {}), alias: 'id', transform: (v) => v || '' });
8216
+ // Specific inputs for Country
8217
+ this.enableFlagIcons = input(false, { ...(ngDevMode ? { debugName: "enableFlagIcons" } : {}), transform: booleanAttribute, alias: 'enable-flag-icons' });
8218
+ this.enableValidation = input(false, { ...(ngDevMode ? { debugName: "enableValidation" } : {}), transform: booleanAttribute, alias: 'enable-validation' });
8219
+ // View Children
8220
+ this.el = viewChild('field', ...(ngDevMode ? [{ debugName: "el" }] : []));
8221
+ this.dropdown = viewChild('autocomplete', ...(ngDevMode ? [{ debugName: "dropdown" }] : []));
8222
+ this.selected = output();
8059
8223
  this._countries = [
8060
8224
  { text: 'Afghanistan', value: 'AF' },
8061
8225
  { text: 'Albania', value: 'AL' },
@@ -8257,51 +8421,106 @@ class AutocompleteCountryComponent extends AbstractAutocompleteComponent {
8257
8421
  { text: 'Zimbabwe', value: 'ZW' },
8258
8422
  ];
8259
8423
  }
8260
- getSuggestions(query) {
8261
- this.clearDropdown();
8262
- this.activeIndex.set(-1);
8424
+ update(ev) {
8425
+ if (this.typingTimeout)
8426
+ clearTimeout(this.typingTimeout);
8427
+ this.typingTimeout = setTimeout(() => {
8428
+ if (!this.disabled()) {
8429
+ const t = ev;
8430
+ this.manageSuggestions(t?.value);
8431
+ }
8432
+ }, 200);
8433
+ }
8434
+ onWrite(data) {
8435
+ const field = this.el();
8436
+ if (field && field.nativeElement) {
8437
+ if (typeof data === 'string') {
8438
+ // Try to find the full object to display correct text
8439
+ const match = this._countries.find(c => c.value === data || c.text === data);
8440
+ field.nativeElement.value = match ? match.text : data;
8441
+ }
8442
+ else {
8443
+ field.nativeElement.value = data?.text || '';
8444
+ }
8445
+ }
8446
+ }
8447
+ getText(d) {
8448
+ if (d == null)
8449
+ return '';
8450
+ if (typeof d === 'string') {
8451
+ const match = this._countries.find(c => c.value === d);
8452
+ return match ? match.text : d;
8453
+ }
8454
+ return d?.text;
8455
+ }
8456
+ manageSuggestions(query) {
8457
+ this.suggestions.set([]);
8263
8458
  if (query && query.length > 0) {
8264
8459
  this.openDropdown();
8265
- const suggestions = this.getCountries().filter((o) => {
8266
- const _c = o;
8267
- return _c.text.toLowerCase().startsWith(query.toLowerCase());
8268
- });
8269
- this.renderAc(suggestions);
8460
+ const rawSuggestions = this.getCountries().filter(c => c.text.toLowerCase().startsWith(query.toLowerCase()));
8461
+ this.suggestions.set(rawSuggestions);
8270
8462
  }
8271
8463
  else {
8272
8464
  this.closeDropdown();
8273
8465
  }
8274
8466
  }
8275
- getItemText(data) {
8276
- const valueToFind = typeof data === 'object' ? data?.value : data;
8277
- const h = this.getCountries().find((c) => {
8278
- if (typeof c === 'object') {
8279
- const _c = c;
8280
- return _c.value === valueToFind;
8281
- }
8282
- return false;
8283
- });
8284
- return typeof h === 'object'
8285
- ? h.text
8286
- : typeof data === 'string'
8287
- ? data
8288
- : '';
8467
+ selectItem(item, ev) {
8468
+ ev?.stopPropagation();
8469
+ this.selected.emit(item);
8470
+ this.setValue(item);
8471
+ this.closeDropdown();
8289
8472
  }
8473
+ onEnter(ev) {
8474
+ const t = ev;
8475
+ if (!this.disabled() && t && t.value) {
8476
+ // Try to find exact match
8477
+ const match = this._countries.find(c => c.text.toLowerCase() === t.value.toLowerCase());
8478
+ const item = match || { text: t.value, value: t.value };
8479
+ this.setValue(item);
8480
+ this.closeDropdown();
8481
+ }
8482
+ }
8483
+ handleOutsideEvent(event) {
8484
+ if (!this.isOpen())
8485
+ return;
8486
+ const target = event.target;
8487
+ const dropdown = this.dropdown();
8488
+ const path = event.composedPath ? event.composedPath() : [];
8489
+ const clickedInsideHost = this.hostRef?.nativeElement?.contains(target);
8490
+ const clickedInsideDropdown = dropdown?.nativeElement?.contains
8491
+ ? dropdown.nativeElement.contains(target)
8492
+ : false;
8493
+ const clickedInPath = path.length
8494
+ ? path.some(p => p === this.hostRef.nativeElement || (dropdown && p === dropdown.nativeElement))
8495
+ : false;
8496
+ if (!(clickedInsideHost || clickedInsideDropdown || clickedInPath)) {
8497
+ this.closeDropdown();
8498
+ }
8499
+ }
8500
+ openDropdown() {
8501
+ if (this.isOpen())
8502
+ return;
8503
+ this.isOpen.set(true);
8504
+ }
8505
+ closeDropdown() {
8506
+ if (!this.isOpen())
8507
+ return;
8508
+ this.isOpen.set(false);
8509
+ }
8510
+ // Data Logic
8290
8511
  getCountries() {
8291
8512
  if (this.enableFlagIcons()) {
8292
- return this._countries.map((country) => {
8293
- return {
8294
- ...country,
8295
- iconClass: `fi fi-${country.value.toLowerCase()}`,
8296
- };
8297
- });
8513
+ return this._countries.map(country => ({
8514
+ ...country,
8515
+ iconClass: `fi fi-${country.value.toLowerCase()}`,
8516
+ }));
8298
8517
  }
8299
8518
  else {
8300
8519
  return this._countries;
8301
8520
  }
8302
8521
  }
8303
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteCountryComponent, deps: [{ token: UniqueIdService }, { token: i0.Renderer2 }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
8304
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteCountryComponent, isStandalone: false, selector: "rlb-autocomplete-country", inputs: { enableFlagIcons: { classPropertyName: "enableFlagIcons", publicName: "enable-flag-icons", isSignal: true, isRequired: false, transformFunction: null }, enableValidation: { classPropertyName: "enableValidation", publicName: "enable-validation", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
8522
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteCountryComponent, deps: [{ token: UniqueIdService }, { token: i0.ElementRef }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
8523
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteCountryComponent, isStandalone: false, selector: "rlb-autocomplete-country", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "max-height", isSignal: true, isRequired: false, transformFunction: null }, userDefinedId: { classPropertyName: "userDefinedId", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, enableFlagIcons: { classPropertyName: "enableFlagIcons", publicName: "enable-flag-icons", isSignal: true, isRequired: false, transformFunction: null }, enableValidation: { classPropertyName: "enableValidation", publicName: "enable-validation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", selected: "selected" }, host: { listeners: { "document:pointerdown": "onDocumentPointerDown($event)", "document:keydown.escape": "onEscape($event)" } }, viewQueries: [{ propertyName: "el", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "dropdown", first: true, predicate: ["autocomplete"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
8305
8524
  <ng-content select="[before]"></ng-content>
8306
8525
  <div class="input-group has-validation position-relative">
8307
8526
  <input
@@ -8309,7 +8528,8 @@ class AutocompleteCountryComponent extends AbstractAutocompleteComponent {
8309
8528
  [id]="id"
8310
8529
  class="form-control"
8311
8530
  type="text"
8312
- [attr.autocomplete]="'off'"
8531
+ [value]="getText(value)"
8532
+ autocomplete="off"
8313
8533
  [attr.disabled]="disabled() ? true : undefined"
8314
8534
  [attr.readonly]="readonly() ? true : undefined"
8315
8535
  [attr.placeholder]="placeholder()"
@@ -8317,34 +8537,46 @@ class AutocompleteCountryComponent extends AbstractAutocompleteComponent {
8317
8537
  [class.form-control-sm]="size() === 'small'"
8318
8538
  (blur)="touch()"
8319
8539
  [ngClass]="{
8320
- 'is-invalid':
8321
- control?.touched && control?.invalid && enableValidation(),
8540
+ 'is-invalid': control?.touched && control?.invalid && enableValidation(),
8322
8541
  'is-valid': control?.touched && control?.valid && enableValidation(),
8323
8542
  }"
8324
8543
  (input)="update($event.target)"
8544
+ (keyup.enter)="onEnter($event.target)"
8325
8545
  />
8326
- @if (errors() && showError()) {
8327
- <rlb-input-validation [errors]="errors()" />
8546
+
8547
+ <!-- Dropdown Logic -->
8548
+ @if (isOpen()) {
8549
+ <div
8550
+ #autocomplete
8551
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
8552
+ [style.max-height.px]="maxHeight()"
8553
+ style="z-index: 1000; top: 100%;"
8554
+ >
8555
+ @if (!hasSuggestions()) {
8556
+ <a class="dropdown-item disabled text-center">No suggestions</a>
8557
+ } @else {
8558
+ @for (item of suggestions(); track item.value) {
8559
+ <a
8560
+ class="dropdown-item"
8561
+ (click)="selectItem(item, $event)"
8562
+ style="cursor: pointer"
8563
+ >
8564
+ <!-- Flag Icon Support -->
8565
+ @if (item.iconClass) {
8566
+ <i
8567
+ [class]="item.iconClass"
8568
+ class="me-2"
8569
+ ></i>
8570
+ }
8571
+ {{ item.text }}
8572
+ </a>
8573
+ }
8574
+ }
8575
+ </div>
8328
8576
  }
8329
- <div
8330
- #autocomplete
8331
- [id]="id + '-ac'"
8332
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
8333
- aria-labelledby="dropdownMenu"
8334
- [style.max-height.px]="maxHeight()"
8335
- style="z-index: 1000; top: 100%;"
8336
- ></div>
8337
8577
  </div>
8338
- @if (loading() || acLoading()) {
8339
- <rlb-progress
8340
- [height]="2"
8341
- [infinite]="loading() || acLoading()"
8342
- color="primary"
8343
- class="w-100"
8344
- />
8345
- }
8346
8578
  <ng-content select="[after]"></ng-content>
8347
- `, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: InputValidationComponent, selector: "rlb-input-validation", inputs: ["errors"], outputs: ["errorsChange"] }, { kind: "component", type: ProgressComponent, selector: "rlb-progress", inputs: ["max", "min", "value", "height", "animated", "striped", "infinite", "aria-label", "showValue", "color", "text-color"] }] }); }
8579
+ `, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
8348
8580
  }
8349
8581
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteCountryComponent, decorators: [{
8350
8582
  type: Component,
@@ -8358,7 +8590,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8358
8590
  [id]="id"
8359
8591
  class="form-control"
8360
8592
  type="text"
8361
- [attr.autocomplete]="'off'"
8593
+ [value]="getText(value)"
8594
+ autocomplete="off"
8362
8595
  [attr.disabled]="disabled() ? true : undefined"
8363
8596
  [attr.readonly]="readonly() ? true : undefined"
8364
8597
  [attr.placeholder]="placeholder()"
@@ -8366,75 +8599,172 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8366
8599
  [class.form-control-sm]="size() === 'small'"
8367
8600
  (blur)="touch()"
8368
8601
  [ngClass]="{
8369
- 'is-invalid':
8370
- control?.touched && control?.invalid && enableValidation(),
8602
+ 'is-invalid': control?.touched && control?.invalid && enableValidation(),
8371
8603
  'is-valid': control?.touched && control?.valid && enableValidation(),
8372
8604
  }"
8373
8605
  (input)="update($event.target)"
8606
+ (keyup.enter)="onEnter($event.target)"
8374
8607
  />
8375
- @if (errors() && showError()) {
8376
- <rlb-input-validation [errors]="errors()" />
8608
+
8609
+ <!-- Dropdown Logic -->
8610
+ @if (isOpen()) {
8611
+ <div
8612
+ #autocomplete
8613
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
8614
+ [style.max-height.px]="maxHeight()"
8615
+ style="z-index: 1000; top: 100%;"
8616
+ >
8617
+ @if (!hasSuggestions()) {
8618
+ <a class="dropdown-item disabled text-center">No suggestions</a>
8619
+ } @else {
8620
+ @for (item of suggestions(); track item.value) {
8621
+ <a
8622
+ class="dropdown-item"
8623
+ (click)="selectItem(item, $event)"
8624
+ style="cursor: pointer"
8625
+ >
8626
+ <!-- Flag Icon Support -->
8627
+ @if (item.iconClass) {
8628
+ <i
8629
+ [class]="item.iconClass"
8630
+ class="me-2"
8631
+ ></i>
8632
+ }
8633
+ {{ item.text }}
8634
+ </a>
8635
+ }
8636
+ }
8637
+ </div>
8377
8638
  }
8378
- <div
8379
- #autocomplete
8380
- [id]="id + '-ac'"
8381
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
8382
- aria-labelledby="dropdownMenu"
8383
- [style.max-height.px]="maxHeight()"
8384
- style="z-index: 1000; top: 100%;"
8385
- ></div>
8386
8639
  </div>
8387
- @if (loading() || acLoading()) {
8388
- <rlb-progress
8389
- [height]="2"
8390
- [infinite]="loading() || acLoading()"
8391
- color="primary"
8392
- class="w-100"
8393
- />
8394
- }
8395
8640
  <ng-content select="[after]"></ng-content>
8396
8641
  `,
8397
8642
  standalone: false,
8398
8643
  }]
8399
- }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.Renderer2 }, { type: i2$2.NgControl, decorators: [{
8644
+ }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.ElementRef }, { type: i2$2.NgControl, decorators: [{
8400
8645
  type: Self
8401
8646
  }, {
8402
8647
  type: Optional
8403
- }] }], propDecorators: { enableFlagIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-flag-icons", required: false }] }], enableValidation: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-validation", required: false }] }] } });
8648
+ }] }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "max-height", required: false }] }], userDefinedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], enableFlagIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-flag-icons", required: false }] }], enableValidation: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-validation", required: false }] }], el: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], dropdown: [{ type: i0.ViewChild, args: ['autocomplete', { isSignal: true }] }], selected: [{ type: i0.Output, args: ["selected"] }], onDocumentPointerDown: [{
8649
+ type: HostListener,
8650
+ args: ['document:pointerdown', ['$event']]
8651
+ }], onEscape: [{
8652
+ type: HostListener,
8653
+ args: ['document:keydown.escape', ['$event']]
8654
+ }] } });
8404
8655
 
8405
- class AutocompleteTimezonesComponent extends AbstractAutocompleteComponent {
8406
- constructor(idService, renderer, control) {
8407
- super(idService, renderer, control);
8656
+ class AutocompleteTimezonesComponent extends AbstractComponent {
8657
+ onDocumentPointerDown(event) {
8658
+ this.handleOutsideEvent(event);
8659
+ }
8660
+ onEscape(event) {
8661
+ if (this.isOpen()) {
8662
+ this.closeDropdown();
8663
+ this.el()?.nativeElement?.blur();
8664
+ }
8665
+ }
8666
+ constructor(idService, hostRef, control) {
8667
+ super(idService, control);
8668
+ this.hostRef = hostRef;
8408
8669
  this.control = control;
8409
- this.enableFlagIcons = input(false, { ...(ngDevMode ? { debugName: "enableFlagIcons" } : {}), transform: booleanAttribute,
8410
- alias: 'enable-flag-icons' });
8670
+ // State
8671
+ this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
8672
+ this.suggestions = signal([], ...(ngDevMode ? [{ debugName: "suggestions" }] : []));
8673
+ this.hasSuggestions = computed(() => this.suggestions().length > 0, ...(ngDevMode ? [{ debugName: "hasSuggestions" }] : []));
8674
+ // Inputs
8675
+ this.disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
8676
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute });
8677
+ this.placeholder = input('', { ...(ngDevMode ? { debugName: "placeholder" } : {}), alias: 'placeholder' });
8678
+ this.size = input(undefined, ...(ngDevMode ? [{ debugName: "size" }] : []));
8679
+ this.maxHeight = input(200, { ...(ngDevMode ? { debugName: "maxHeight" } : {}), transform: numberAttribute, alias: 'max-height' });
8680
+ this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : {}), transform: booleanAttribute, alias: 'loading' });
8681
+ this.userDefinedId = input('', { ...(ngDevMode ? { debugName: "userDefinedId" } : {}), alias: 'id', transform: (v) => v || '' });
8682
+ this.enableFlagIcons = input(false, { ...(ngDevMode ? { debugName: "enableFlagIcons" } : {}), transform: booleanAttribute, alias: 'enable-flag-icons' });
8683
+ // View Children
8684
+ this.el = viewChild('field', ...(ngDevMode ? [{ debugName: "el" }] : []));
8685
+ this.dropdown = viewChild('autocomplete', ...(ngDevMode ? [{ debugName: "dropdown" }] : []));
8686
+ this.selected = output();
8411
8687
  }
8412
- getSuggestions(query) {
8413
- this.clearDropdown();
8414
- this.activeIndex.set(-1);
8688
+ update(ev) {
8689
+ if (this.typingTimeout)
8690
+ clearTimeout(this.typingTimeout);
8691
+ this.typingTimeout = setTimeout(() => {
8692
+ if (!this.disabled()) {
8693
+ const t = ev;
8694
+ this.manageSuggestions(t?.value);
8695
+ }
8696
+ }, 200);
8697
+ }
8698
+ onWrite(data) {
8699
+ const field = this.el();
8700
+ if (field && field.nativeElement) {
8701
+ // Timezones are simple strings, so we just set the value
8702
+ field.nativeElement.value = data || '';
8703
+ }
8704
+ }
8705
+ manageSuggestions(query) {
8706
+ this.suggestions.set([]);
8415
8707
  if (query && query.length > 0) {
8416
8708
  this.openDropdown();
8417
8709
  const timezones = DateTz.timezones();
8418
- const suggestions = timezones.filter((o) => {
8419
- return o.toLowerCase().includes(query.toLowerCase());
8420
- });
8421
- this.renderAc(suggestions);
8710
+ const filtered = timezones.filter(tz => tz.toLowerCase().includes(query.toLowerCase()));
8711
+ // Map string[] to AutocompleteItem[] for the template
8712
+ this.suggestions.set(filtered.map(tz => ({
8713
+ text: tz,
8714
+ value: tz,
8715
+ })));
8422
8716
  }
8423
8717
  else {
8424
8718
  this.closeDropdown();
8425
8719
  }
8426
8720
  }
8427
- getItemText(data) {
8428
- if (typeof data === 'object' && data !== null && 'text' in data) {
8429
- return data.text || '';
8721
+ selectItem(item, ev) {
8722
+ ev?.stopPropagation();
8723
+ const val = item.value;
8724
+ this.selected.emit(val);
8725
+ this.setValue(val);
8726
+ this.closeDropdown();
8727
+ const field = this.el();
8728
+ if (field?.nativeElement) {
8729
+ field.nativeElement.value = val;
8430
8730
  }
8431
- else if (typeof data === 'string') {
8432
- return data;
8731
+ }
8732
+ onEnter(ev) {
8733
+ const t = ev;
8734
+ if (!this.disabled() && t && t.value) {
8735
+ this.setValue(t.value);
8736
+ this.closeDropdown();
8433
8737
  }
8434
- return '';
8435
8738
  }
8436
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteTimezonesComponent, deps: [{ token: UniqueIdService }, { token: i0.Renderer2 }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
8437
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteTimezonesComponent, isStandalone: false, selector: "rlb-autocomplete-timezones", inputs: { enableFlagIcons: { classPropertyName: "enableFlagIcons", publicName: "enable-flag-icons", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
8739
+ handleOutsideEvent(event) {
8740
+ if (!this.isOpen())
8741
+ return;
8742
+ const target = event.target;
8743
+ const dropdown = this.dropdown();
8744
+ const path = event.composedPath ? event.composedPath() : [];
8745
+ const clickedInsideHost = this.hostRef?.nativeElement?.contains(target);
8746
+ const clickedInsideDropdown = dropdown?.nativeElement?.contains
8747
+ ? dropdown.nativeElement.contains(target)
8748
+ : false;
8749
+ const clickedInPath = path.length
8750
+ ? path.some(p => p === this.hostRef.nativeElement || (dropdown && p === dropdown.nativeElement))
8751
+ : false;
8752
+ if (!(clickedInsideHost || clickedInsideDropdown || clickedInPath)) {
8753
+ this.closeDropdown();
8754
+ }
8755
+ }
8756
+ openDropdown() {
8757
+ if (this.isOpen())
8758
+ return;
8759
+ this.isOpen.set(true);
8760
+ }
8761
+ closeDropdown() {
8762
+ if (!this.isOpen())
8763
+ return;
8764
+ this.isOpen.set(false);
8765
+ }
8766
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteTimezonesComponent, deps: [{ token: UniqueIdService }, { token: i0.ElementRef }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
8767
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteTimezonesComponent, isStandalone: false, selector: "rlb-autocomplete-timezones", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "max-height", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, userDefinedId: { classPropertyName: "userDefinedId", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, enableFlagIcons: { classPropertyName: "enableFlagIcons", publicName: "enable-flag-icons", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", selected: "selected" }, host: { listeners: { "document:pointerdown": "onDocumentPointerDown($event)", "document:keydown.escape": "onEscape($event)" } }, viewQueries: [{ propertyName: "el", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "dropdown", first: true, predicate: ["autocomplete"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
8438
8768
  <ng-content select="[before]"></ng-content>
8439
8769
  <div class="input-group has-validation position-relative">
8440
8770
  <input
@@ -8442,10 +8772,11 @@ class AutocompleteTimezonesComponent extends AbstractAutocompleteComponent {
8442
8772
  [id]="id"
8443
8773
  class="form-control"
8444
8774
  type="text"
8775
+ [value]="value || ''"
8776
+ autocomplete="off"
8445
8777
  [attr.disabled]="disabled() ? true : undefined"
8446
8778
  [attr.readonly]="readonly() ? true : undefined"
8447
8779
  [attr.placeholder]="placeholder()"
8448
- [attr.autocomplete]="'off'"
8449
8780
  [class.form-control-lg]="size() === 'large'"
8450
8781
  [class.form-control-sm]="size() === 'small'"
8451
8782
  (blur)="touch()"
@@ -8454,23 +8785,46 @@ class AutocompleteTimezonesComponent extends AbstractAutocompleteComponent {
8454
8785
  'is-valid': control?.touched && control?.valid,
8455
8786
  }"
8456
8787
  (input)="update($event.target)"
8788
+ (keyup.enter)="onEnter($event.target)"
8457
8789
  />
8458
8790
  @if (errors() && showError()) {
8459
8791
  <rlb-input-validation [errors]="errors()" />
8460
8792
  }
8461
- <div
8462
- #autocomplete
8463
- [id]="id + '-ac'"
8464
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
8465
- aria-labelledby="dropdownMenu"
8466
- [style.max-height.px]="maxHeight()"
8467
- style="z-index: 1000; top: 100%;"
8468
- ></div>
8793
+
8794
+ <!-- Dropdown Logic -->
8795
+ @if (isOpen()) {
8796
+ <div
8797
+ #autocomplete
8798
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
8799
+ [style.max-height.px]="maxHeight()"
8800
+ style="z-index: 1000; top: 100%;"
8801
+ >
8802
+ @if (!hasSuggestions()) {
8803
+ <a class="dropdown-item disabled text-center">No suggestions</a>
8804
+ } @else {
8805
+ @for (item of suggestions(); track item.value) {
8806
+ <a
8807
+ class="dropdown-item"
8808
+ (click)="selectItem(item, $event)"
8809
+ style="cursor: pointer"
8810
+ >
8811
+ @if (item.iconClass) {
8812
+ <i
8813
+ [class]="item.iconClass"
8814
+ class="me-2"
8815
+ ></i>
8816
+ }
8817
+ {{ item.text }}
8818
+ </a>
8819
+ }
8820
+ }
8821
+ </div>
8822
+ }
8469
8823
  </div>
8470
- @if (loading() || acLoading()) {
8824
+ @if (loading()) {
8471
8825
  <rlb-progress
8472
8826
  [height]="2"
8473
- [infinite]="loading() || acLoading()"
8827
+ [infinite]="loading()"
8474
8828
  color="primary"
8475
8829
  class="w-100"
8476
8830
  />
@@ -8490,10 +8844,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8490
8844
  [id]="id"
8491
8845
  class="form-control"
8492
8846
  type="text"
8847
+ [value]="value || ''"
8848
+ autocomplete="off"
8493
8849
  [attr.disabled]="disabled() ? true : undefined"
8494
8850
  [attr.readonly]="readonly() ? true : undefined"
8495
8851
  [attr.placeholder]="placeholder()"
8496
- [attr.autocomplete]="'off'"
8497
8852
  [class.form-control-lg]="size() === 'large'"
8498
8853
  [class.form-control-sm]="size() === 'small'"
8499
8854
  (blur)="touch()"
@@ -8502,23 +8857,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8502
8857
  'is-valid': control?.touched && control?.valid,
8503
8858
  }"
8504
8859
  (input)="update($event.target)"
8860
+ (keyup.enter)="onEnter($event.target)"
8505
8861
  />
8506
8862
  @if (errors() && showError()) {
8507
8863
  <rlb-input-validation [errors]="errors()" />
8508
8864
  }
8509
- <div
8510
- #autocomplete
8511
- [id]="id + '-ac'"
8512
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
8513
- aria-labelledby="dropdownMenu"
8514
- [style.max-height.px]="maxHeight()"
8515
- style="z-index: 1000; top: 100%;"
8516
- ></div>
8865
+
8866
+ <!-- Dropdown Logic -->
8867
+ @if (isOpen()) {
8868
+ <div
8869
+ #autocomplete
8870
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
8871
+ [style.max-height.px]="maxHeight()"
8872
+ style="z-index: 1000; top: 100%;"
8873
+ >
8874
+ @if (!hasSuggestions()) {
8875
+ <a class="dropdown-item disabled text-center">No suggestions</a>
8876
+ } @else {
8877
+ @for (item of suggestions(); track item.value) {
8878
+ <a
8879
+ class="dropdown-item"
8880
+ (click)="selectItem(item, $event)"
8881
+ style="cursor: pointer"
8882
+ >
8883
+ @if (item.iconClass) {
8884
+ <i
8885
+ [class]="item.iconClass"
8886
+ class="me-2"
8887
+ ></i>
8888
+ }
8889
+ {{ item.text }}
8890
+ </a>
8891
+ }
8892
+ }
8893
+ </div>
8894
+ }
8517
8895
  </div>
8518
- @if (loading() || acLoading()) {
8896
+ @if (loading()) {
8519
8897
  <rlb-progress
8520
8898
  [height]="2"
8521
- [infinite]="loading() || acLoading()"
8899
+ [infinite]="loading()"
8522
8900
  color="primary"
8523
8901
  class="w-100"
8524
8902
  />
@@ -8527,11 +8905,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8527
8905
  `,
8528
8906
  standalone: false,
8529
8907
  }]
8530
- }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.Renderer2 }, { type: i2$2.NgControl, decorators: [{
8908
+ }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.ElementRef }, { type: i2$2.NgControl, decorators: [{
8531
8909
  type: Self
8532
8910
  }, {
8533
8911
  type: Optional
8534
- }] }], propDecorators: { enableFlagIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-flag-icons", required: false }] }] } });
8912
+ }] }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "max-height", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], userDefinedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], enableFlagIcons: [{ type: i0.Input, args: [{ isSignal: true, alias: "enable-flag-icons", required: false }] }], el: [{ type: i0.ViewChild, args: ['field', { isSignal: true }] }], dropdown: [{ type: i0.ViewChild, args: ['autocomplete', { isSignal: true }] }], selected: [{ type: i0.Output, args: ["selected"] }], onDocumentPointerDown: [{
8913
+ type: HostListener,
8914
+ args: ['document:pointerdown', ['$event']]
8915
+ }], onEscape: [{
8916
+ type: HostListener,
8917
+ args: ['document:keydown.escape', ['$event']]
8918
+ }] } });
8535
8919
 
8536
8920
  class AutocompleteComponent extends AbstractComponent {
8537
8921
  onDocumentPointerDown(event) {
@@ -8543,19 +8927,22 @@ class AutocompleteComponent extends AbstractComponent {
8543
8927
  this.el()?.nativeElement?.blur();
8544
8928
  }
8545
8929
  }
8546
- constructor(idService, renderer, hostRef, control) {
8930
+ constructor(idService, hostRef, control) {
8547
8931
  super(idService, control);
8548
- this.renderer = renderer;
8549
8932
  this.hostRef = hostRef;
8550
8933
  this.control = control;
8551
8934
  this.acLoading = signal(false, ...(ngDevMode ? [{ debugName: "acLoading" }] : []));
8935
+ // State
8552
8936
  this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
8937
+ this.suggestions = signal([], ...(ngDevMode ? [{ debugName: "suggestions" }] : []));
8938
+ this.hasSuggestions = computed(() => this.suggestions().length > 0, ...(ngDevMode ? [{ debugName: "hasSuggestions" }] : []));
8939
+ // Inputs
8553
8940
  this.disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
8554
8941
  this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute, alias: 'readonly' });
8555
8942
  this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : {}), transform: booleanAttribute, alias: 'loading' });
8556
8943
  this.maxHeight = input(200, { ...(ngDevMode ? { debugName: "maxHeight" } : {}), transform: numberAttribute, alias: 'max-height' });
8557
8944
  this.placeholder = input('', { ...(ngDevMode ? { debugName: "placeholder" } : {}), alias: 'placeholder' });
8558
- this.autocomplete = input(() => { return []; }, { ...(ngDevMode ? { debugName: "autocomplete" } : {}), alias: 'autocomplete' });
8945
+ this.autocomplete = input(() => [], { ...(ngDevMode ? { debugName: "autocomplete" } : {}), alias: 'autocomplete' });
8559
8946
  this.type = input('text', { ...(ngDevMode ? { debugName: "type" } : {}), alias: 'type' });
8560
8947
  this.size = input(undefined, ...(ngDevMode ? [{ debugName: "size" }] : []));
8561
8948
  this.charsToSearch = input(3, { ...(ngDevMode ? { debugName: "charsToSearch" } : {}), alias: 'chars-to-search', transform: numberAttribute });
@@ -8585,83 +8972,63 @@ class AutocompleteComponent extends AbstractComponent {
8585
8972
  field.nativeElement.value = data;
8586
8973
  }
8587
8974
  else {
8588
- field.nativeElement.value = data?.text;
8975
+ field.nativeElement.value = data?.text || '';
8589
8976
  }
8590
8977
  }
8591
8978
  }
8592
8979
  manageSuggestions(data) {
8593
- this.clearDropdown();
8980
+ // 1. Reset suggestions but keep dropdown state logic clean
8981
+ this.suggestions.set([]);
8594
8982
  if (data && data.length >= this.charsToSearch()) {
8595
8983
  this.openDropdown();
8596
- const suggestions = this.autocomplete()(data);
8597
- if (suggestions instanceof Promise) {
8598
- this.acLoading.set(true);
8599
- suggestions.then(s => this.renderAc(s)).finally(() => (this.acLoading.set(false)));
8600
- }
8601
- else if (suggestions instanceof Observable) {
8602
- this.acLoading.set(true);
8603
- lastValueFrom(suggestions).then(s => this.renderAc(s)).finally(() => (this.acLoading.set(false)));
8984
+ try {
8985
+ const result = this.autocomplete()(data);
8986
+ if (result instanceof Promise) {
8987
+ this.acLoading.set(true);
8988
+ result
8989
+ .then(s => this.handleResults(s))
8990
+ .catch(() => this.handleResults([]))
8991
+ .finally(() => this.acLoading.set(false));
8992
+ }
8993
+ else if (result instanceof Observable) {
8994
+ this.acLoading.set(true);
8995
+ lastValueFrom(result)
8996
+ .then(s => this.handleResults(s))
8997
+ .catch(() => this.handleResults([]))
8998
+ .finally(() => this.acLoading.set(false));
8999
+ }
9000
+ else {
9001
+ this.handleResults(result);
9002
+ }
8604
9003
  }
8605
- else {
8606
- this.renderAc(suggestions);
9004
+ catch (e) {
9005
+ console.error('Error executing autocomplete function:', e);
9006
+ this.closeDropdown();
8607
9007
  }
8608
9008
  }
8609
9009
  else {
8610
9010
  this.closeDropdown();
8611
9011
  }
8612
9012
  }
8613
- renderAc(suggestions) {
8614
- const dropdown = this.dropdown();
8615
- if (!dropdown)
8616
- return;
8617
- this.clearDropdown();
8618
- if (!suggestions || suggestions.length === 0) {
8619
- const el = this.renderer.createElement('a');
8620
- this.renderer.addClass(el, 'dropdown-item');
8621
- this.renderer.addClass(el, 'disabled');
8622
- this.renderer.addClass(el, 'text-center');
8623
- this.renderer.setAttribute(el, 'disabled', 'true');
8624
- this.renderer.appendChild(el, this.renderer.createText('No suggestions'));
8625
- this.renderer.appendChild(dropdown.nativeElement, el);
8626
- return;
8627
- }
8628
- for (const suggestion of suggestions) {
8629
- const itemData = typeof suggestion === 'string'
8630
- ? { text: suggestion, value: suggestion }
8631
- : suggestion;
8632
- const el = this.renderer.createElement('a');
8633
- this.renderer.addClass(el, 'dropdown-item');
8634
- if (itemData.iconClass) {
8635
- const icon = this.renderer.createElement('i');
8636
- const classes = itemData.iconClass.split(/\s+/);
8637
- for (const cls of classes) {
8638
- if (cls) {
8639
- this.renderer.addClass(icon, cls);
8640
- }
8641
- }
8642
- this.renderer.addClass(icon, 'me-2');
8643
- this.renderer.appendChild(el, icon);
8644
- }
8645
- this.renderer.appendChild(el, this.renderer.createText(itemData.text));
8646
- this.renderer.listen(el, 'click', (ev) => {
8647
- this.selected.emit(itemData);
8648
- this.setValue(itemData);
8649
- this.closeDropdown();
8650
- ev.stopPropagation();
8651
- });
8652
- this.renderer.appendChild(dropdown.nativeElement, el);
8653
- }
9013
+ handleResults(raw) {
9014
+ const normalize = raw.map(r => (typeof r === 'string' ? { text: r, value: r } : r));
9015
+ this.suggestions.set(normalize);
9016
+ }
9017
+ selectItem(item, ev) {
9018
+ ev?.stopPropagation();
9019
+ this.selected.emit(item);
9020
+ this.setValue(item);
9021
+ this.closeDropdown();
8654
9022
  }
8655
9023
  onEnter(ev) {
8656
9024
  const t = ev;
8657
- const dropdown = this.dropdown();
8658
- if (!this.disabled() && t && t.value && dropdown) {
9025
+ if (!this.disabled() && t && t.value) {
8659
9026
  const item = {
8660
9027
  text: t.value,
8661
- value: t.value
9028
+ value: t.value,
8662
9029
  };
8663
9030
  this.setValue(item);
8664
- this.renderer.setStyle(dropdown.nativeElement, 'display', 'none');
9031
+ this.closeDropdown();
8665
9032
  }
8666
9033
  }
8667
9034
  getText(d) {
@@ -8670,86 +9037,94 @@ class AutocompleteComponent extends AbstractComponent {
8670
9037
  return typeof d === 'string' ? d : d?.text;
8671
9038
  }
8672
9039
  handleOutsideEvent(event) {
9040
+ if (!this.isOpen())
9041
+ return;
8673
9042
  const target = event.target;
8674
9043
  const dropdown = this.dropdown();
8675
9044
  const path = event.composedPath ? event.composedPath() : [];
8676
9045
  const clickedInsideHost = this.hostRef?.nativeElement?.contains(target);
8677
- const clickedInsideDropdown = dropdown?.nativeElement?.contains ? dropdown.nativeElement.contains(target) : false;
8678
- const clickedInPath = path.length ? path.some(p => p === this.hostRef.nativeElement || (dropdown && p === dropdown.nativeElement)) : false;
9046
+ const clickedInsideDropdown = dropdown?.nativeElement?.contains
9047
+ ? dropdown.nativeElement.contains(target)
9048
+ : false;
9049
+ // Check path for Shadow DOM support
9050
+ const clickedInPath = path.length
9051
+ ? path.some(p => p === this.hostRef.nativeElement || (dropdown && p === dropdown.nativeElement))
9052
+ : false;
8679
9053
  if (!(clickedInsideHost || clickedInsideDropdown || clickedInPath)) {
8680
9054
  this.closeDropdown();
8681
9055
  }
8682
9056
  }
8683
9057
  openDropdown() {
8684
- const dropdown = this.dropdown();
8685
- if (!dropdown || this.isOpen())
9058
+ if (this.isOpen())
8686
9059
  return;
8687
- this.renderer.setStyle(dropdown.nativeElement, 'display', 'block');
8688
9060
  this.isOpen.set(true);
8689
9061
  }
8690
9062
  closeDropdown() {
8691
- const dropdown = this.dropdown();
8692
- if (!dropdown || !this.isOpen())
9063
+ if (!this.isOpen())
8693
9064
  return;
8694
- this.renderer.setStyle(dropdown.nativeElement, 'display', 'none');
8695
9065
  this.isOpen.set(false);
8696
- this.clearDropdown();
8697
9066
  this.acLoading.set(false);
8698
9067
  }
8699
- clearDropdown() {
8700
- const dropdown = this.dropdown();
8701
- if (!dropdown)
8702
- return;
8703
- while (dropdown.nativeElement.firstChild) {
8704
- dropdown.nativeElement.removeChild(dropdown.nativeElement.lastChild);
8705
- }
8706
- }
8707
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteComponent, deps: [{ token: UniqueIdService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
8708
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteComponent, isStandalone: false, selector: "rlb-autocomplete", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "max-height", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, charsToSearch: { classPropertyName: "charsToSearch", publicName: "chars-to-search", isSignal: true, isRequired: false, transformFunction: null }, menuMaxWidth: { classPropertyName: "menuMaxWidth", publicName: "menu-max-width", isSignal: true, isRequired: false, transformFunction: null }, userDefinedId: { classPropertyName: "userDefinedId", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, enableValidation: { classPropertyName: "enableValidation", publicName: "enable-validation", isSignal: true, isRequired: false, transformFunction: null }, inputAutocomplete: { classPropertyName: "inputAutocomplete", publicName: "inputAutocomplete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", selected: "selected" }, host: { listeners: { "document:pointerdown": "onDocumentPointerDown($event)", "document:keydown.escape": "onEscape($event)" }, styleAttribute: "position: relative;" }, viewQueries: [{ propertyName: "el", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "dropdown", first: true, predicate: ["autocomplete"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
9068
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteComponent, deps: [{ token: UniqueIdService }, { token: i0.ElementRef }, { token: i2$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
9069
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: AutocompleteComponent, isStandalone: false, selector: "rlb-autocomplete", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "max-height", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, charsToSearch: { classPropertyName: "charsToSearch", publicName: "chars-to-search", isSignal: true, isRequired: false, transformFunction: null }, menuMaxWidth: { classPropertyName: "menuMaxWidth", publicName: "menu-max-width", isSignal: true, isRequired: false, transformFunction: null }, userDefinedId: { classPropertyName: "userDefinedId", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, enableValidation: { classPropertyName: "enableValidation", publicName: "enable-validation", isSignal: true, isRequired: false, transformFunction: null }, inputAutocomplete: { classPropertyName: "inputAutocomplete", publicName: "inputAutocomplete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", selected: "selected" }, host: { listeners: { "document:pointerdown": "onDocumentPointerDown($event)", "document:keydown.escape": "onEscape($event)" } }, viewQueries: [{ propertyName: "el", first: true, predicate: ["field"], descendants: true, isSignal: true }, { propertyName: "dropdown", first: true, predicate: ["autocomplete"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
8709
9070
  <ng-content select="[before]"></ng-content>
8710
- <div class="input-group has-validation">
9071
+ <div class="input-group has-validation position-relative">
8711
9072
  <input
8712
9073
  #field
8713
- [id]="id"
8714
9074
  class="form-control"
9075
+ [value]="getText(value)"
9076
+ (input)="update($event.target)"
9077
+ (keyup.enter)="onEnter($event.target)"
9078
+ (blur)="touch()"
9079
+ [id]="id"
8715
9080
  [type]="type()"
8716
- [attr.autocomplete]="inputAutocomplete()"
8717
9081
  [attr.disabled]="disabled() ? true : undefined"
9082
+ [class.is-invalid]="control?.touched && control?.invalid && enableValidation()"
9083
+ [attr.autocomplete]="inputAutocomplete()"
8718
9084
  [attr.readonly]="readonly() ? true : undefined"
8719
9085
  [attr.placeholder]="placeholder()"
8720
9086
  [class.form-control-lg]="size() === 'large'"
8721
9087
  [class.form-control-sm]="size() === 'small'"
8722
- [value]="getText(value)"
8723
- (blur)="touch()"
8724
- [ngClass]="{
8725
- 'is-invalid': control?.touched && control?.invalid && enableValidation(),
8726
- 'is-valid': control?.touched && control?.valid && enableValidation()
9088
+ [ngClass]="{
9089
+ 'is-invalid': control?.touched && control?.invalid && enableValidation(),
9090
+ 'is-valid': control?.touched && control?.valid && enableValidation(),
8727
9091
  }"
8728
- (input)="update($event.target)"
8729
- (keyup.enter)="onEnter($event.target)"
8730
- />
8731
- @if (errors() && showError() && enableValidation()) {
8732
- <rlb-input-validation [errors]="errors()"/>
8733
- }
8734
- </div>
8735
- @if (loading() || acLoading()) {
8736
- <rlb-progress
8737
- [height]="2"
8738
- [infinite]="loading() || acLoading()"
8739
- color="primary"
8740
- class="w-100"
8741
- />
9092
+ />
9093
+
9094
+ @if (isOpen()) {
9095
+ <div
9096
+ #autocomplete
9097
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
9098
+ [style.max-height.px]="maxHeight()"
9099
+ [style.max-width.px]="menuMaxWidth()"
9100
+ style="z-index: 1000; top: 100%;"
9101
+ >
9102
+ @if (acLoading()) {
9103
+ <div class="dropdown-item disabled text-center">Loading...</div>
9104
+ } @else if (!hasSuggestions()) {
9105
+ <a class="dropdown-item disabled text-center">No suggestions</a>
9106
+ } @else {
9107
+ @for (item of suggestions(); track item.value) {
9108
+ <a
9109
+ class="dropdown-item"
9110
+ (click)="selectItem(item, $event)"
9111
+ style="cursor: pointer"
9112
+ >
9113
+ @if (item.iconClass) {
9114
+ <i
9115
+ [class]="item.iconClass"
9116
+ class="me-2"
9117
+ ></i>
9118
+ }
9119
+ {{ item.text }}
9120
+ </a>
9121
+ }
9122
+ }
9123
+ </div>
8742
9124
  }
8743
- <ng-content select="[after]"></ng-content>
8744
- <div
8745
- #autocomplete
8746
- [id]="id+'-ac'"
8747
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
8748
- aria-labelledby="dropdownMenu"
8749
- [style.max-height.px]="maxHeight()"
8750
- [style.width]="'fit-content !important'"
8751
- [style.max-width.px]="menuMaxWidth()"></div>
8752
- `, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: InputValidationComponent, selector: "rlb-input-validation", inputs: ["errors"], outputs: ["errorsChange"] }, { kind: "component", type: ProgressComponent, selector: "rlb-progress", inputs: ["max", "min", "value", "height", "animated", "striped", "infinite", "aria-label", "showValue", "color", "text-color"] }] }); }
9125
+ </div>
9126
+ <ng-content select="[after]"></ng-content>
9127
+ `, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
8753
9128
  }
8754
9129
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: AutocompleteComponent, decorators: [{
8755
9130
  type: Component,
@@ -8757,55 +9132,66 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
8757
9132
  selector: 'rlb-autocomplete',
8758
9133
  template: `
8759
9134
  <ng-content select="[before]"></ng-content>
8760
- <div class="input-group has-validation">
9135
+ <div class="input-group has-validation position-relative">
8761
9136
  <input
8762
9137
  #field
8763
- [id]="id"
8764
9138
  class="form-control"
9139
+ [value]="getText(value)"
9140
+ (input)="update($event.target)"
9141
+ (keyup.enter)="onEnter($event.target)"
9142
+ (blur)="touch()"
9143
+ [id]="id"
8765
9144
  [type]="type()"
8766
- [attr.autocomplete]="inputAutocomplete()"
8767
9145
  [attr.disabled]="disabled() ? true : undefined"
9146
+ [class.is-invalid]="control?.touched && control?.invalid && enableValidation()"
9147
+ [attr.autocomplete]="inputAutocomplete()"
8768
9148
  [attr.readonly]="readonly() ? true : undefined"
8769
9149
  [attr.placeholder]="placeholder()"
8770
9150
  [class.form-control-lg]="size() === 'large'"
8771
9151
  [class.form-control-sm]="size() === 'small'"
8772
- [value]="getText(value)"
8773
- (blur)="touch()"
8774
- [ngClass]="{
8775
- 'is-invalid': control?.touched && control?.invalid && enableValidation(),
8776
- 'is-valid': control?.touched && control?.valid && enableValidation()
9152
+ [ngClass]="{
9153
+ 'is-invalid': control?.touched && control?.invalid && enableValidation(),
9154
+ 'is-valid': control?.touched && control?.valid && enableValidation(),
8777
9155
  }"
8778
- (input)="update($event.target)"
8779
- (keyup.enter)="onEnter($event.target)"
8780
- />
8781
- @if (errors() && showError() && enableValidation()) {
8782
- <rlb-input-validation [errors]="errors()"/>
8783
- }
8784
- </div>
8785
- @if (loading() || acLoading()) {
8786
- <rlb-progress
8787
- [height]="2"
8788
- [infinite]="loading() || acLoading()"
8789
- color="primary"
8790
- class="w-100"
8791
- />
9156
+ />
9157
+
9158
+ @if (isOpen()) {
9159
+ <div
9160
+ #autocomplete
9161
+ class="dropdown-menu show w-100 position-absolute overflow-y-auto"
9162
+ [style.max-height.px]="maxHeight()"
9163
+ [style.max-width.px]="menuMaxWidth()"
9164
+ style="z-index: 1000; top: 100%;"
9165
+ >
9166
+ @if (acLoading()) {
9167
+ <div class="dropdown-item disabled text-center">Loading...</div>
9168
+ } @else if (!hasSuggestions()) {
9169
+ <a class="dropdown-item disabled text-center">No suggestions</a>
9170
+ } @else {
9171
+ @for (item of suggestions(); track item.value) {
9172
+ <a
9173
+ class="dropdown-item"
9174
+ (click)="selectItem(item, $event)"
9175
+ style="cursor: pointer"
9176
+ >
9177
+ @if (item.iconClass) {
9178
+ <i
9179
+ [class]="item.iconClass"
9180
+ class="me-2"
9181
+ ></i>
9182
+ }
9183
+ {{ item.text }}
9184
+ </a>
9185
+ }
9186
+ }
9187
+ </div>
8792
9188
  }
8793
- <ng-content select="[after]"></ng-content>
8794
- <div
8795
- #autocomplete
8796
- [id]="id+'-ac'"
8797
- class="dropdown-menu overflow-y-auto w-100 position-absolute"
8798
- aria-labelledby="dropdownMenu"
8799
- [style.max-height.px]="maxHeight()"
8800
- [style.width]="'fit-content !important'"
8801
- [style.max-width.px]="menuMaxWidth()"></div>
8802
- `,
9189
+ </div>
9190
+ <ng-content select="[after]"></ng-content>
9191
+ `,
8803
9192
  standalone: false,
8804
- host: {
8805
- style: 'position: relative;',
8806
- }
8807
9193
  }]
8808
- }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i2$2.NgControl, decorators: [{
9194
+ }], ctorParameters: () => [{ type: UniqueIdService }, { type: i0.ElementRef }, { type: i2$2.NgControl, decorators: [{
8809
9195
  type: Self
8810
9196
  }, {
8811
9197
  type: Optional