@masterteam/components 0.0.166 → 0.0.168

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.
@@ -3,13 +3,21 @@ import { input, signal, computed, inject, effect, HostBinding, ViewChild, Change
3
3
  import * as i2 from 'primeng/inputtext';
4
4
  import { InputTextModule } from 'primeng/inputtext';
5
5
  import * as i1 from '@angular/forms';
6
- import { Validators, NgControl, FormsModule } from '@angular/forms';
6
+ import { NgControl, FormsModule } from '@angular/forms';
7
7
  import { Tooltip } from '@masterteam/components/tooltip';
8
8
  import { FieldValidation } from '@masterteam/components/field-validation';
9
9
  import { isInvalid } from '@masterteam/components';
10
10
  import { Icon } from '@masterteam/icons';
11
11
  import { TranslocoService } from '@jsverse/transloco';
12
12
 
13
+ const requiredNoWhitespace = (control) => {
14
+ const value = control.value;
15
+ if (value === null || value === undefined)
16
+ return { required: true };
17
+ if (typeof value === 'string' && value.trim() === '')
18
+ return { required: true };
19
+ return null;
20
+ };
13
21
  // TODO: text stuck when reset
14
22
  class TextField {
15
23
  inputText;
@@ -27,7 +35,7 @@ class TextField {
27
35
  iconPosition = input('start', ...(ngDevMode ? [{ debugName: "iconPosition" }] : /* istanbul ignore next */ []));
28
36
  // readonly externalControl = input<any>(null);
29
37
  styleClass;
30
- requiredValidator = Validators.required;
38
+ requiredValidator = requiredNoWhitespace;
31
39
  value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
32
40
  disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
33
41
  passwordVisible = signal(false, ...(ngDevMode ? [{ debugName: "passwordVisible" }] : /* istanbul ignore next */ []));
@@ -63,7 +71,7 @@ class TextField {
63
71
  }
64
72
  effect(() => {
65
73
  if (this.ngControl?.control && this.required()) {
66
- this.ngControl.control.addValidators(Validators.required);
74
+ this.ngControl.control.addValidators(this.requiredValidator);
67
75
  this.ngControl.control.updateValueAndValidity();
68
76
  }
69
77
  });
@@ -1 +1 @@
1
- {"version":3,"file":"masterteam-components-text-field.mjs","sources":["../../../../packages/masterteam/components/text-field/text-field.ts","../../../../packages/masterteam/components/text-field/text-field.html","../../../../packages/masterteam/components/text-field/masterteam-components-text-field.ts"],"sourcesContent":["import {\r\n Component,\r\n HostBinding,\r\n SimpleChanges,\r\n ViewChild,\r\n signal,\r\n input,\r\n OnInit,\r\n OnChanges,\r\n inject,\r\n ChangeDetectionStrategy,\r\n effect,\r\n computed,\r\n} from '@angular/core';\r\nimport { InputTextModule } from 'primeng/inputtext';\r\nimport {\r\n ControlValueAccessor,\r\n FormsModule,\r\n NgControl,\r\n Validators,\r\n} from '@angular/forms';\r\n// import { KeyFilterModule, KeyFilterPattern } from 'primeng/keyfilter';\r\nimport { Tooltip } from '@masterteam/components/tooltip';\r\nimport { FieldValidation } from '@masterteam/components/field-validation';\r\nimport { isInvalid } from '@masterteam/components';\r\nimport { Icon, MTIcon } from '@masterteam/icons';\r\nimport { TranslocoService } from '@jsverse/transloco';\r\n\r\n// TODO: text stuck when reset\r\n@Component({\r\n selector: 'mt-text-field',\r\n standalone: true,\r\n imports: [\r\n FormsModule,\r\n InputTextModule,\r\n // INFO: if we need this filter uncomment the import, and next line and add this to the template input\r\n //[pKeyFilter]=\"\r\n // pKeyFilter()\r\n // ? pKeyFilter() === 'alphanum'\r\n // ? alphaNum\r\n // : pKeyFilter()\r\n // : null\r\n // \"\r\n // KeyFilterModule,\r\n Tooltip,\r\n FieldValidation,\r\n Icon,\r\n ],\r\n templateUrl: './text-field.html',\r\n styleUrls: ['./text-field.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'grid gap-1',\r\n },\r\n})\r\nexport class TextField implements ControlValueAccessor, OnInit, OnChanges {\r\n @ViewChild('inputText', { static: true })\r\n inputText: HTMLInputElement;\r\n\r\n readonly field = input<boolean>(true);\r\n readonly hint = input<string>();\r\n readonly label = input<string>();\r\n readonly placeholder = input<string>();\r\n readonly class = input<string>('');\r\n readonly type = input<string>('text');\r\n readonly readonly = input<boolean>(false);\r\n readonly pInputs = input<Partial<HTMLInputElement>>();\r\n // readonly pKeyFilter = input<KeyFilterPattern | RegExp>();\r\n readonly required = input<boolean>(false);\r\n readonly icon = input<MTIcon>();\r\n readonly iconPosition = input<'start' | 'end'>('start');\r\n // readonly externalControl = input<any>(null);\r\n\r\n @HostBinding('class') styleClass: string;\r\n\r\n requiredValidator = Validators.required;\r\n value = signal<string | null>(null);\r\n disabled = signal<boolean>(false);\r\n passwordVisible = signal<boolean>(false);\r\n isPasswordField = computed(() => this.type() === 'password');\r\n inputType = computed(() =>\r\n this.isPasswordField() && this.passwordVisible() ? 'text' : this.type(),\r\n );\r\n hasStartIcon = computed(\r\n () => Boolean(this.icon()) && this.iconPosition() === 'start',\r\n );\r\n hasEndIcon = computed(\r\n () =>\r\n this.isPasswordField() ||\r\n (Boolean(this.icon()) && this.iconPosition() === 'end'),\r\n );\r\n hasHint = computed(() => Boolean(this.hint()));\r\n hasEndActions = computed(() => this.hasEndIcon() || this.hasHint());\r\n hasTwoEndActions = computed(() => this.hasEndIcon() && this.hasHint());\r\n passwordToggleIcon = computed<MTIcon>(() =>\r\n this.passwordVisible() ? 'general.eye-off' : 'general.eye',\r\n );\r\n private readonly transloco = inject(TranslocoService);\r\n passwordToggleLabel = computed(() =>\r\n this.passwordVisible()\r\n ? this.transloco.translate('components.textField.hidePassword')\r\n : this.transloco.translate('components.textField.showPassword'),\r\n );\r\n\r\n alphaNum: RegExp = /[\\u0621-\\u064A\\u0660-\\u0669a-z0-9\\s]/i;\r\n\r\n onTouched: () => void = () => {};\r\n onModelChange: (value: any) => void = () => {};\r\n\r\n public ngControl: NgControl | null = null;\r\n\r\n isInvalid = isInvalid;\r\n\r\n constructor() {\r\n try {\r\n // Try to inject NgControl if available\r\n this.ngControl = inject(NgControl, { self: true, optional: true });\r\n if (this.ngControl) {\r\n this.ngControl.valueAccessor = this;\r\n }\r\n } catch (_e) {\r\n // If injection fails, ngControl will remain null\r\n this.ngControl = null;\r\n }\r\n effect(() => {\r\n if (this.ngControl?.control && this.required()) {\r\n this.ngControl.control.addValidators(Validators.required);\r\n this.ngControl.control.updateValueAndValidity();\r\n }\r\n });\r\n }\r\n\r\n ngOnInit() {\r\n this.styleClass = this.class();\r\n // if (this.externalControl()) {\r\n // debugger\r\n // this.ngControl = this.externalControl();\r\n // }\r\n\r\n if (this.pInputs()) {\r\n this.applyInputsToInputText();\r\n }\r\n }\r\n\r\n applyInputsToInputText() {\r\n Object.assign(this.inputText, this.pInputs());\r\n }\r\n\r\n onValueChange(value: any) {\r\n this.value.set(value);\r\n\r\n const control = this.ngControl?.control;\r\n if (control) {\r\n control.setValue(value);\r\n control.markAsDirty();\r\n control.markAsTouched();\r\n control.updateValueAndValidity({ emitEvent: false });\r\n return;\r\n }\r\n\r\n this.onModelChange(value);\r\n this.onTouched();\r\n }\r\n\r\n togglePasswordVisibility() {\r\n if (this.disabled() || this.readonly()) {\r\n return;\r\n }\r\n\r\n this.passwordVisible.update((visible) => !visible);\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n if (changes['pInputs']) {\r\n this.applyInputsToInputText();\r\n }\r\n }\r\n\r\n writeValue(value: string) {\r\n this.value.set(value);\r\n }\r\n\r\n registerOnChange(fn: any) {\r\n this.onModelChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any) {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(disabled: boolean) {\r\n this.disabled.set(disabled);\r\n }\r\n}\r\n","@if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >{{ label() }}</label\r\n >\r\n}\r\n\r\n<div\r\n class=\"mt-text-field__input\"\r\n [class.mt-text-field__input--start-icon]=\"hasStartIcon()\"\r\n [class.mt-text-field__input--end-action]=\"hasEndActions()\"\r\n [class.mt-text-field__input--two-end-actions]=\"hasTwoEndActions()\"\r\n>\r\n @if (icon() && iconPosition() === \"start\") {\r\n <span class=\"mt-text-field__icon mt-text-field__icon--start\">\r\n <mt-icon [icon]=\"icon()\" />\r\n </span>\r\n }\r\n\r\n <input\r\n #inputText=\"\"\r\n pInputText=\"\"\r\n [ngModel]=\"value()\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [type]=\"inputType()\"\r\n [id]=\"ngControl?.name || label()\"\r\n [invalid]=\"isInvalid(ngControl?.control)\"\r\n (blur)=\"onTouched()\"\r\n placeholder=\"{{ placeholder() ?? label() ?? '' }}\"\r\n class=\"w-full\"\r\n />\r\n\r\n @if (isPasswordField()) {\r\n <button\r\n type=\"button\"\r\n class=\"mt-text-field__action\"\r\n [class.mt-text-field__action--before-hint]=\"hasHint()\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [attr.aria-label]=\"passwordToggleLabel()\"\r\n [mtTooltip]=\"passwordToggleLabel()\"\r\n tooltipPosition=\"top\"\r\n (click)=\"togglePasswordVisibility()\"\r\n >\r\n <mt-icon [icon]=\"passwordToggleIcon()\" />\r\n </button>\r\n } @else if (icon() && iconPosition() === \"end\") {\r\n <span\r\n class=\"mt-text-field__icon mt-text-field__icon--end\"\r\n [class.mt-text-field__icon--before-hint]=\"hasHint()\"\r\n >\r\n <mt-icon [icon]=\"icon()\" />\r\n </span>\r\n }\r\n\r\n @if (hint()) {\r\n <span\r\n class=\"mt-text-field__icon mt-text-field__icon--end\"\r\n [mtTooltip]=\"hint()\"\r\n tooltipPosition=\"top\"\r\n >\r\n <mt-icon icon=\"general.info-circle\" />\r\n </span>\r\n }\r\n</div>\r\n\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"masterteam-components-text-field.mjs","sources":["../../../../packages/masterteam/components/text-field/text-field.ts","../../../../packages/masterteam/components/text-field/text-field.html","../../../../packages/masterteam/components/text-field/masterteam-components-text-field.ts"],"sourcesContent":["import {\r\n Component,\r\n HostBinding,\r\n SimpleChanges,\r\n ViewChild,\r\n signal,\r\n input,\r\n OnInit,\r\n OnChanges,\r\n inject,\r\n ChangeDetectionStrategy,\r\n effect,\r\n computed,\r\n} from '@angular/core';\r\nimport { InputTextModule } from 'primeng/inputtext';\r\nimport {\r\n AbstractControl,\r\n ControlValueAccessor,\r\n FormsModule,\r\n NgControl,\r\n ValidationErrors,\r\n ValidatorFn,\r\n} from '@angular/forms';\r\n// import { KeyFilterModule, KeyFilterPattern } from 'primeng/keyfilter';\r\nimport { Tooltip } from '@masterteam/components/tooltip';\r\nimport { FieldValidation } from '@masterteam/components/field-validation';\r\nimport { isInvalid } from '@masterteam/components';\r\nimport { Icon, MTIcon } from '@masterteam/icons';\r\nimport { TranslocoService } from '@jsverse/transloco';\r\n\r\nconst requiredNoWhitespace: ValidatorFn = (\r\n control: AbstractControl,\r\n): ValidationErrors | null => {\r\n const value = control.value;\r\n if (value === null || value === undefined) return { required: true };\r\n if (typeof value === 'string' && value.trim() === '')\r\n return { required: true };\r\n return null;\r\n};\r\n\r\n// TODO: text stuck when reset\r\n@Component({\r\n selector: 'mt-text-field',\r\n standalone: true,\r\n imports: [\r\n FormsModule,\r\n InputTextModule,\r\n // INFO: if we need this filter uncomment the import, and next line and add this to the template input\r\n //[pKeyFilter]=\"\r\n // pKeyFilter()\r\n // ? pKeyFilter() === 'alphanum'\r\n // ? alphaNum\r\n // : pKeyFilter()\r\n // : null\r\n // \"\r\n // KeyFilterModule,\r\n Tooltip,\r\n FieldValidation,\r\n Icon,\r\n ],\r\n templateUrl: './text-field.html',\r\n styleUrls: ['./text-field.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'grid gap-1',\r\n },\r\n})\r\nexport class TextField implements ControlValueAccessor, OnInit, OnChanges {\r\n @ViewChild('inputText', { static: true })\r\n inputText: HTMLInputElement;\r\n\r\n readonly field = input<boolean>(true);\r\n readonly hint = input<string>();\r\n readonly label = input<string>();\r\n readonly placeholder = input<string>();\r\n readonly class = input<string>('');\r\n readonly type = input<string>('text');\r\n readonly readonly = input<boolean>(false);\r\n readonly pInputs = input<Partial<HTMLInputElement>>();\r\n // readonly pKeyFilter = input<KeyFilterPattern | RegExp>();\r\n readonly required = input<boolean>(false);\r\n readonly icon = input<MTIcon>();\r\n readonly iconPosition = input<'start' | 'end'>('start');\r\n // readonly externalControl = input<any>(null);\r\n\r\n @HostBinding('class') styleClass: string;\r\n\r\n requiredValidator: ValidatorFn = requiredNoWhitespace;\r\n value = signal<string | null>(null);\r\n disabled = signal<boolean>(false);\r\n passwordVisible = signal<boolean>(false);\r\n isPasswordField = computed(() => this.type() === 'password');\r\n inputType = computed(() =>\r\n this.isPasswordField() && this.passwordVisible() ? 'text' : this.type(),\r\n );\r\n hasStartIcon = computed(\r\n () => Boolean(this.icon()) && this.iconPosition() === 'start',\r\n );\r\n hasEndIcon = computed(\r\n () =>\r\n this.isPasswordField() ||\r\n (Boolean(this.icon()) && this.iconPosition() === 'end'),\r\n );\r\n hasHint = computed(() => Boolean(this.hint()));\r\n hasEndActions = computed(() => this.hasEndIcon() || this.hasHint());\r\n hasTwoEndActions = computed(() => this.hasEndIcon() && this.hasHint());\r\n passwordToggleIcon = computed<MTIcon>(() =>\r\n this.passwordVisible() ? 'general.eye-off' : 'general.eye',\r\n );\r\n private readonly transloco = inject(TranslocoService);\r\n passwordToggleLabel = computed(() =>\r\n this.passwordVisible()\r\n ? this.transloco.translate('components.textField.hidePassword')\r\n : this.transloco.translate('components.textField.showPassword'),\r\n );\r\n\r\n alphaNum: RegExp = /[\\u0621-\\u064A\\u0660-\\u0669a-z0-9\\s]/i;\r\n\r\n onTouched: () => void = () => {};\r\n onModelChange: (value: any) => void = () => {};\r\n\r\n public ngControl: NgControl | null = null;\r\n\r\n isInvalid = isInvalid;\r\n\r\n constructor() {\r\n try {\r\n // Try to inject NgControl if available\r\n this.ngControl = inject(NgControl, { self: true, optional: true });\r\n if (this.ngControl) {\r\n this.ngControl.valueAccessor = this;\r\n }\r\n } catch (_e) {\r\n // If injection fails, ngControl will remain null\r\n this.ngControl = null;\r\n }\r\n effect(() => {\r\n if (this.ngControl?.control && this.required()) {\r\n this.ngControl.control.addValidators(this.requiredValidator);\r\n this.ngControl.control.updateValueAndValidity();\r\n }\r\n });\r\n }\r\n\r\n ngOnInit() {\r\n this.styleClass = this.class();\r\n // if (this.externalControl()) {\r\n // debugger\r\n // this.ngControl = this.externalControl();\r\n // }\r\n\r\n if (this.pInputs()) {\r\n this.applyInputsToInputText();\r\n }\r\n }\r\n\r\n applyInputsToInputText() {\r\n Object.assign(this.inputText, this.pInputs());\r\n }\r\n\r\n onValueChange(value: any) {\r\n this.value.set(value);\r\n\r\n const control = this.ngControl?.control;\r\n if (control) {\r\n control.setValue(value);\r\n control.markAsDirty();\r\n control.markAsTouched();\r\n control.updateValueAndValidity({ emitEvent: false });\r\n return;\r\n }\r\n\r\n this.onModelChange(value);\r\n this.onTouched();\r\n }\r\n\r\n togglePasswordVisibility() {\r\n if (this.disabled() || this.readonly()) {\r\n return;\r\n }\r\n\r\n this.passwordVisible.update((visible) => !visible);\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n if (changes['pInputs']) {\r\n this.applyInputsToInputText();\r\n }\r\n }\r\n\r\n writeValue(value: string) {\r\n this.value.set(value);\r\n }\r\n\r\n registerOnChange(fn: any) {\r\n this.onModelChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any) {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(disabled: boolean) {\r\n this.disabled.set(disabled);\r\n }\r\n}\r\n","@if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >{{ label() }}</label\r\n >\r\n}\r\n\r\n<div\r\n class=\"mt-text-field__input\"\r\n [class.mt-text-field__input--start-icon]=\"hasStartIcon()\"\r\n [class.mt-text-field__input--end-action]=\"hasEndActions()\"\r\n [class.mt-text-field__input--two-end-actions]=\"hasTwoEndActions()\"\r\n>\r\n @if (icon() && iconPosition() === \"start\") {\r\n <span class=\"mt-text-field__icon mt-text-field__icon--start\">\r\n <mt-icon [icon]=\"icon()\" />\r\n </span>\r\n }\r\n\r\n <input\r\n #inputText=\"\"\r\n pInputText=\"\"\r\n [ngModel]=\"value()\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [type]=\"inputType()\"\r\n [id]=\"ngControl?.name || label()\"\r\n [invalid]=\"isInvalid(ngControl?.control)\"\r\n (blur)=\"onTouched()\"\r\n placeholder=\"{{ placeholder() ?? label() ?? '' }}\"\r\n class=\"w-full\"\r\n />\r\n\r\n @if (isPasswordField()) {\r\n <button\r\n type=\"button\"\r\n class=\"mt-text-field__action\"\r\n [class.mt-text-field__action--before-hint]=\"hasHint()\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [attr.aria-label]=\"passwordToggleLabel()\"\r\n [mtTooltip]=\"passwordToggleLabel()\"\r\n tooltipPosition=\"top\"\r\n (click)=\"togglePasswordVisibility()\"\r\n >\r\n <mt-icon [icon]=\"passwordToggleIcon()\" />\r\n </button>\r\n } @else if (icon() && iconPosition() === \"end\") {\r\n <span\r\n class=\"mt-text-field__icon mt-text-field__icon--end\"\r\n [class.mt-text-field__icon--before-hint]=\"hasHint()\"\r\n >\r\n <mt-icon [icon]=\"icon()\" />\r\n </span>\r\n }\r\n\r\n @if (hint()) {\r\n <span\r\n class=\"mt-text-field__icon mt-text-field__icon--end\"\r\n [mtTooltip]=\"hint()\"\r\n tooltipPosition=\"top\"\r\n >\r\n <mt-icon icon=\"general.info-circle\" />\r\n </span>\r\n }\r\n</div>\r\n\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -12,7 +12,7 @@ import { Tooltip } from '@masterteam/components/tooltip';
12
12
  import { FieldValidation } from '@masterteam/components/field-validation';
13
13
  import { isInvalid } from '@masterteam/components';
14
14
  import { Icon } from '@masterteam/icons';
15
- import { Subject, distinctUntilChanged, tap, switchMap, of, finalize, catchError } from 'rxjs';
15
+ import { Subject, debounceTime, tap, switchMap, of, finalize, catchError } from 'rxjs';
16
16
  import { HttpClient, HttpParams } from '@angular/common/http';
17
17
  import { Avatar } from '@masterteam/components/avatar';
18
18
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -63,11 +63,10 @@ class UserSearchField {
63
63
  this.styleClass = this.class();
64
64
  }
65
65
  search(event) {
66
- this.loading.set(true);
67
66
  this.searchTerms.next(event.query);
68
67
  }
69
68
  onFocus() {
70
- if (this.filteredUsers().length > 0 && this.autocomplete()) {
69
+ if (this.filteredUsers().length > 0) {
71
70
  this.autocomplete()?.show();
72
71
  }
73
72
  }
@@ -78,17 +77,20 @@ class UserSearchField {
78
77
  const updated = [...current, selectedUser];
79
78
  this.value.set(updated);
80
79
  this.onModelChange(updated);
80
+ const remaining = this.filteredUsers().filter((u) => u.id !== selectedUser.id);
81
+ this.filteredUsers.set(remaining);
82
+ if (remaining.length > 0) {
83
+ queueMicrotask(() => this.autocomplete()?.show());
84
+ }
81
85
  }
82
86
  else {
83
87
  this.value.set(selectedUser);
84
88
  this.onModelChange(selectedUser);
89
+ this.filteredUsers.set([]);
90
+ this.autocomplete()?.hide();
85
91
  }
86
92
  this.onTouched();
87
93
  this.loading.set(false);
88
- this.filteredUsers.set([]);
89
- if (!this.isMultiple() && this.autocomplete()) {
90
- this.autocomplete()?.hide();
91
- }
92
94
  }
93
95
  onUnselect(event) {
94
96
  const removedUser = event.value;
@@ -123,13 +125,14 @@ class UserSearchField {
123
125
  }
124
126
  getUsers() {
125
127
  this.searchTerms
126
- .pipe(takeUntilDestroyed(), distinctUntilChanged(), tap(() => this.loading.set(true)), switchMap((term) => {
127
- if (!term) {
128
+ .pipe(takeUntilDestroyed(), debounceTime(250), tap(() => this.loading.set(true)), switchMap((term) => {
129
+ const trimmed = term?.trim();
130
+ if (!trimmed) {
128
131
  this.filteredUsers.set([]);
129
132
  this.loading.set(false);
130
- return of([]);
133
+ return of({ [this.dataKey()]: [] });
131
134
  }
132
- const params = new HttpParams().set(this.paramName(), term);
135
+ const params = new HttpParams().set(this.paramName(), trimmed);
133
136
  return this.http
134
137
  .get(this.apiUrl(), {
135
138
  params,
@@ -137,13 +140,19 @@ class UserSearchField {
137
140
  })
138
141
  .pipe(finalize(() => this.loading.set(false)), catchError((err) => {
139
142
  console.error('API search failed:', err);
140
- this.filteredUsers.set([]);
141
143
  return of({ [this.dataKey()]: [] });
142
144
  }));
143
145
  }))
144
146
  .subscribe({
145
- next: (users) => {
146
- this.filteredUsers.set((users[this.dataKey()] ?? []));
147
+ next: (response) => {
148
+ const users = (response?.[this.dataKey()] ?? []);
149
+ if (this.isMultiple()) {
150
+ const selectedIds = new Set((this.value() ?? []).map((u) => u.id));
151
+ this.filteredUsers.set(users.filter((u) => !selectedIds.has(u.id)));
152
+ }
153
+ else {
154
+ this.filteredUsers.set(users);
155
+ }
147
156
  },
148
157
  });
149
158
  }
@@ -1 +1 @@
1
- {"version":3,"file":"masterteam-components-user-search-field.mjs","sources":["../../../../packages/masterteam/components/user-search-field/user-search-field.ts","../../../../packages/masterteam/components/user-search-field/user-search-field.html","../../../../packages/masterteam/components/user-search-field/masterteam-components-user-search-field.ts"],"sourcesContent":["import {\r\n Component,\r\n HostBinding,\r\n signal,\r\n input,\r\n OnInit,\r\n inject,\r\n ChangeDetectionStrategy,\r\n effect,\r\n viewChild,\r\n} from '@angular/core';\r\nimport {\r\n ControlValueAccessor,\r\n FormsModule,\r\n NgControl,\r\n Validators,\r\n} from '@angular/forms';\r\nimport { AutoComplete, AutoCompleteModule } from 'primeng/autocomplete';\r\nimport { InputGroupModule } from 'primeng/inputgroup';\r\nimport { InputGroupAddonModule } from 'primeng/inputgroupaddon';\r\nimport { Tooltip } from '@masterteam/components/tooltip';\r\nimport { FieldValidation } from '@masterteam/components/field-validation';\r\nimport { isInvalid } from '@masterteam/components';\r\nimport { Icon } from '@masterteam/icons';\r\nimport {\r\n Subject,\r\n distinctUntilChanged,\r\n switchMap,\r\n tap,\r\n of,\r\n finalize,\r\n catchError,\r\n} from 'rxjs';\r\nimport { HttpClient, HttpContext, HttpParams } from '@angular/common/http';\r\nimport { Avatar } from '@masterteam/components/avatar';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport { TranslocoService, TranslocoPipe } from '@jsverse/transloco';\r\n\r\nexport interface User {\r\n isExternal: boolean;\r\n id: string;\r\n displayName: string;\r\n userName: string;\r\n photo: string;\r\n}\r\n\r\n@Component({\r\n selector: 'mt-user-search-field',\r\n standalone: true,\r\n imports: [\r\n FormsModule,\r\n AutoCompleteModule,\r\n Tooltip,\r\n InputGroupModule,\r\n InputGroupAddonModule,\r\n FieldValidation,\r\n Icon,\r\n Avatar,\r\n TranslocoPipe,\r\n ],\r\n templateUrl: './user-search-field.html',\r\n styleUrls: ['./user-search-field.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'grid gap-1',\r\n },\r\n})\r\nexport class UserSearchField implements ControlValueAccessor, OnInit {\r\n readonly hint = input<string>();\r\n readonly label = input<string>();\r\n readonly placeholder = input<string>();\r\n readonly class = input<string>('');\r\n readonly readonly = input<boolean>(false);\r\n readonly required = input<boolean>(false);\r\n readonly isMultiple = input<boolean>(false);\r\n readonly apiUrl = input.required<string>();\r\n readonly dataKey = input<string>('data');\r\n readonly paramName = input<string>('query');\r\n readonly context = input<HttpContext | undefined>(undefined);\r\n\r\n @HostBinding('class') styleClass: string;\r\n\r\n requiredValidator = Validators.required;\r\n value = signal<User | User[] | null>(null);\r\n disabled = signal<boolean>(false);\r\n loading = signal<boolean>(false);\r\n\r\n readonly size = input<'small' | 'large' | undefined>();\r\n\r\n filteredUsers = signal<User[]>([]);\r\n private searchTerms = new Subject<string>();\r\n\r\n private readonly translocoService = inject(TranslocoService);\r\n\r\n readonly autocomplete = viewChild<AutoComplete>('autocomplete');\r\n\r\n onTouched: () => void = () => {};\r\n onModelChange: (value: any) => void = () => {};\r\n\r\n public ngControl: NgControl | null = null;\r\n private http = inject(HttpClient);\r\n\r\n isInvalid = isInvalid;\r\n\r\n constructor() {\r\n this.ngControl = inject(NgControl, { self: true, optional: true });\r\n if (this.ngControl) {\r\n this.ngControl.valueAccessor = this;\r\n }\r\n effect(() => {\r\n if (this.ngControl?.control && this.required()) {\r\n this.ngControl.control.addValidators(Validators.required);\r\n this.ngControl.control.updateValueAndValidity();\r\n }\r\n });\r\n this.getUsers();\r\n }\r\n\r\n ngOnInit() {\r\n this.styleClass = this.class();\r\n }\r\n\r\n search(event: { query: string }) {\r\n this.loading.set(true);\r\n this.searchTerms.next(event.query);\r\n }\r\n\r\n onFocus() {\r\n if (this.filteredUsers().length > 0 && this.autocomplete()) {\r\n this.autocomplete()?.show();\r\n }\r\n }\r\n\r\n onSelect(event: { originalEvent: Event; value: User }) {\r\n const selectedUser = event.value;\r\n if (this.isMultiple()) {\r\n const current = (this.value() as User[]) || [];\r\n const updated = [...current, selectedUser];\r\n this.value.set(updated);\r\n this.onModelChange(updated);\r\n } else {\r\n this.value.set(selectedUser);\r\n this.onModelChange(selectedUser);\r\n }\r\n this.onTouched();\r\n this.loading.set(false);\r\n this.filteredUsers.set([]);\r\n if (!this.isMultiple() && this.autocomplete()) {\r\n this.autocomplete()?.hide();\r\n }\r\n }\r\n\r\n onUnselect(event: { originalEvent: Event; value: User }) {\r\n const removedUser = event.value;\r\n const current = (this.value() as User[]) || [];\r\n const updated = current.filter((u) => u.id !== removedUser.id);\r\n this.value.set(updated);\r\n this.onModelChange(updated);\r\n this.onTouched();\r\n }\r\n\r\n onClear() {\r\n this.value.set(this.isMultiple() ? [] : null);\r\n this.onModelChange(this.isMultiple() ? [] : null);\r\n this.filteredUsers.set([]);\r\n this.loading.set(false);\r\n }\r\n\r\n writeValue(value: User | User[] | null): void {\r\n if (this.isMultiple()) {\r\n this.value.set(Array.isArray(value) ? value : value ? [value] : []);\r\n } else {\r\n this.value.set(Array.isArray(value) ? (value[0] ?? null) : value);\r\n }\r\n }\r\n\r\n registerOnChange(fn: (value: User | null) => void) {\r\n this.onModelChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any) {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(disabled: boolean) {\r\n this.disabled.set(disabled);\r\n }\r\n\r\n getUsers() {\r\n this.searchTerms\r\n .pipe(\r\n takeUntilDestroyed(),\r\n distinctUntilChanged(),\r\n tap(() => this.loading.set(true)),\r\n switchMap((term: string) => {\r\n if (!term) {\r\n this.filteredUsers.set([]);\r\n this.loading.set(false);\r\n return of([]);\r\n }\r\n const params = new HttpParams().set(this.paramName(), term);\r\n return this.http\r\n .get<any>(this.apiUrl(), {\r\n params,\r\n context: this.context(),\r\n })\r\n .pipe(\r\n finalize(() => this.loading.set(false)),\r\n catchError((err) => {\r\n console.error('API search failed:', err);\r\n this.filteredUsers.set([]);\r\n return of({ [this.dataKey()]: [] });\r\n }),\r\n );\r\n }),\r\n )\r\n .subscribe({\r\n next: (users) => {\r\n this.filteredUsers.set((users[this.dataKey()] ?? []) as User[]);\r\n },\r\n });\r\n }\r\n}\r\n","@if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >\r\n {{ label() }}\r\n </label>\r\n}\r\n<div class=\"relative\">\r\n <p-inputgroup>\r\n <p-autoComplete\r\n #autocomplete=\"\"\r\n [suggestions]=\"filteredUsers()\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"onSelect($event)\"\r\n (onUnselect)=\"onUnselect($event)\"\r\n (onClear)=\"onClear()\"\r\n (onFocus)=\"onFocus()\"\r\n (onBlur)=\"onTouched()\"\r\n [ngModel]=\"isMultiple() ? value() : value()?.['displayName']\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [id]=\"ngControl?.name || label()\"\r\n [invalid]=\"isInvalid(ngControl?.control)\"\r\n [placeholder]=\"'components.userSearchField.search' | transloco\"\r\n [multiple]=\"isMultiple()\"\r\n [optionLabel]=\"'displayName'\"\r\n class=\"w-full\"\r\n appendTo=\"body\"\r\n styleClass=\"w-full\"\r\n [dropdown]=\"false\"\r\n [size]=\"size()\"\r\n >\r\n <ng-template let-user pTemplate=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <mt-avatar size=\"small\" icon=\"user.user-01\" />\r\n <div class=\"flex align-items-center gap-3\">\r\n <span class=\"font-medium\">{{ user.displayName }}</span>\r\n <medium class=\"text-gray-500\">{{ \"@\" + user.userName }}</medium>\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- <ng-template let-user #pTemplate=\"selecteditem\">\r\n <div class=\"flex items-center gap-2\">\r\n <mt-avatar size=\"small\" icon=\"user.user-01\" />\r\n <div class=\"flex align-items-center gap-3\">\r\n <span class=\"font-medium\">{{ user.displayName }}</span>\r\n <medium class=\"text-gray-500\">{{ \"@\" + user.userName }}</medium>\r\n </div>\r\n </div>\r\n </ng-template> -->\r\n </p-autoComplete>\r\n @if (hint()) {\r\n <p-inputgroup-addon [mtTooltip]=\"hint()\" tooltipPosition=\"top\">\r\n <mt-icon icon=\"general.help-circle\" />\r\n </p-inputgroup-addon>\r\n } @else {\r\n <p-inputgroup-addon tooltipPosition=\"top\">\r\n <mt-icon icon=\"user.user-03\" />\r\n </p-inputgroup-addon>\r\n }\r\n </p-inputgroup>\r\n\r\n @if (loading()) {\r\n <mt-icon\r\n icon=\"general.loading-01\"\r\n class=\"animate-spin absolute right-3 bg-white top-1/2 -translate-y-1/2\"\r\n />\r\n }\r\n</div>\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;MAmEa,eAAe,CAAA;IACjB,IAAI,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAU;IACtB,KAAK,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAU;IACvB,WAAW,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,aAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAU;AAC7B,IAAA,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC;AACzB,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,+EAAC;AAChC,IAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,+EAAC;AAChC,IAAA,UAAU,GAAG,KAAK,CAAU,KAAK,iFAAC;AAClC,IAAA,MAAM,GAAG,KAAK,CAAC,QAAQ,4EAAU;AACjC,IAAA,OAAO,GAAG,KAAK,CAAS,MAAM,8EAAC;AAC/B,IAAA,SAAS,GAAG,KAAK,CAAS,OAAO,gFAAC;AAClC,IAAA,OAAO,GAAG,KAAK,CAA0B,SAAS,8EAAC;AAEtC,IAAA,UAAU;AAEhC,IAAA,iBAAiB,GAAG,UAAU,CAAC,QAAQ;AACvC,IAAA,KAAK,GAAG,MAAM,CAAuB,IAAI,4EAAC;AAC1C,IAAA,QAAQ,GAAG,MAAM,CAAU,KAAK,+EAAC;AACjC,IAAA,OAAO,GAAG,MAAM,CAAU,KAAK,8EAAC;IAEvB,IAAI,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAiC;AAEtD,IAAA,aAAa,GAAG,MAAM,CAAS,EAAE,oFAAC;AAC1B,IAAA,WAAW,GAAG,IAAI,OAAO,EAAU;AAE1B,IAAA,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAEnD,IAAA,YAAY,GAAG,SAAS,CAAe,cAAc,mFAAC;AAE/D,IAAA,SAAS,GAAe,MAAK,EAAE,CAAC;AAChC,IAAA,aAAa,GAAyB,MAAK,EAAE,CAAC;IAEvC,SAAS,GAAqB,IAAI;AACjC,IAAA,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;IAEjC,SAAS,GAAG,SAAS;AAErB,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAClE,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI;QACrC;QACA,MAAM,CAAC,MAAK;YACV,IAAI,IAAI,CAAC,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;gBAC9C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC;AACzD,gBAAA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,sBAAsB,EAAE;YACjD;AACF,QAAA,CAAC,CAAC;QACF,IAAI,CAAC,QAAQ,EAAE;IACjB;IAEA,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,EAAE;IAChC;AAEA,IAAA,MAAM,CAAC,KAAwB,EAAA;AAC7B,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IACpC;IAEA,OAAO,GAAA;AACL,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;AAC1D,YAAA,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE;QAC7B;IACF;AAEA,IAAA,QAAQ,CAAC,KAA4C,EAAA;AACnD,QAAA,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK;AAChC,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;YACrB,MAAM,OAAO,GAAI,IAAI,CAAC,KAAK,EAAa,IAAI,EAAE;YAC9C,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,EAAE,YAAY,CAAC;AAC1C,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACvB,YAAA,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QAC7B;aAAO;AACL,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC;AAC5B,YAAA,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC;QAClC;QACA,IAAI,CAAC,SAAS,EAAE;AAChB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACvB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE;AAC7C,YAAA,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE;QAC7B;IACF;AAEA,IAAA,UAAU,CAAC,KAA4C,EAAA;AACrD,QAAA,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK;QAC/B,MAAM,OAAO,GAAI,IAAI,CAAC,KAAK,EAAa,IAAI,EAAE;AAC9C,QAAA,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,EAAE,CAAC;AAC9D,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACvB,QAAA,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,SAAS,EAAE;IAClB;IAEA,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAC7C,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACjD,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1B,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;IACzB;AAEA,IAAA,UAAU,CAAC,KAA2B,EAAA;AACpC,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;AACrB,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACrE;aAAO;YACL,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,CAAC;QACnE;IACF;AAEA,IAAA,gBAAgB,CAAC,EAAgC,EAAA;AAC/C,QAAA,IAAI,CAAC,aAAa,GAAG,EAAE;IACzB;AAEA,IAAA,iBAAiB,CAAC,EAAO,EAAA;AACvB,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACrB;AAEA,IAAA,gBAAgB,CAAC,QAAiB,EAAA;AAChC,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC7B;IAEA,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC;aACF,IAAI,CACH,kBAAkB,EAAE,EACpB,oBAAoB,EAAE,EACtB,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EACjC,SAAS,CAAC,CAAC,IAAY,KAAI;YACzB,IAAI,CAAC,IAAI,EAAE;AACT,gBAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1B,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACvB,gBAAA,OAAO,EAAE,CAAC,EAAE,CAAC;YACf;AACA,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC;YAC3D,OAAO,IAAI,CAAC;AACT,iBAAA,GAAG,CAAM,IAAI,CAAC,MAAM,EAAE,EAAE;gBACvB,MAAM;AACN,gBAAA,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;aACxB;iBACA,IAAI,CACH,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EACvC,UAAU,CAAC,CAAC,GAAG,KAAI;AACjB,gBAAA,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,GAAG,CAAC;AACxC,gBAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1B,gBAAA,OAAO,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;YACrC,CAAC,CAAC,CACH;AACL,QAAA,CAAC,CAAC;AAEH,aAAA,SAAS,CAAC;AACT,YAAA,IAAI,EAAE,CAAC,KAAK,KAAI;AACd,gBAAA,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAY;YACjE,CAAC;AACF,SAAA,CAAC;IACN;uGA1JW,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAe,qxDCnE5B,wmFAuEA,EAAA,MAAA,EAAA,CAAA,qGAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDrBI,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACX,kBAAkB,y2CAClB,OAAO,EAAA,QAAA,EAAA,aAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACP,gBAAgB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,UAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,MAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAChB,qBAAqB,oKACrB,eAAe,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACf,IAAI,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACJ,MAAM,sLACN,aAAa,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FASJ,eAAe,EAAA,UAAA,EAAA,CAAA;kBArB3B,SAAS;+BACE,sBAAsB,EAAA,UAAA,EACpB,IAAI,EAAA,OAAA,EACP;wBACP,WAAW;wBACX,kBAAkB;wBAClB,OAAO;wBACP,gBAAgB;wBAChB,qBAAqB;wBACrB,eAAe;wBACf,IAAI;wBACJ,MAAM;wBACN,aAAa;qBACd,EAAA,eAAA,EAGgB,uBAAuB,CAAC,MAAM,EAAA,IAAA,EACzC;AACJ,wBAAA,KAAK,EAAE,YAAY;AACpB,qBAAA,EAAA,QAAA,EAAA,wmFAAA,EAAA,MAAA,EAAA,CAAA,qGAAA,CAAA,EAAA;;sBAeA,WAAW;uBAAC,OAAO;oJAc4B,cAAc,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AE9FhE;;AAEG;;;;"}
1
+ {"version":3,"file":"masterteam-components-user-search-field.mjs","sources":["../../../../packages/masterteam/components/user-search-field/user-search-field.ts","../../../../packages/masterteam/components/user-search-field/user-search-field.html","../../../../packages/masterteam/components/user-search-field/masterteam-components-user-search-field.ts"],"sourcesContent":["import {\r\n Component,\r\n HostBinding,\r\n signal,\r\n input,\r\n OnInit,\r\n inject,\r\n ChangeDetectionStrategy,\r\n effect,\r\n viewChild,\r\n} from '@angular/core';\r\nimport {\r\n ControlValueAccessor,\r\n FormsModule,\r\n NgControl,\r\n Validators,\r\n} from '@angular/forms';\r\nimport { AutoComplete, AutoCompleteModule } from 'primeng/autocomplete';\r\nimport { InputGroupModule } from 'primeng/inputgroup';\r\nimport { InputGroupAddonModule } from 'primeng/inputgroupaddon';\r\nimport { Tooltip } from '@masterteam/components/tooltip';\r\nimport { FieldValidation } from '@masterteam/components/field-validation';\r\nimport { isInvalid } from '@masterteam/components';\r\nimport { Icon } from '@masterteam/icons';\r\nimport {\r\n Subject,\r\n debounceTime,\r\n switchMap,\r\n tap,\r\n of,\r\n finalize,\r\n catchError,\r\n} from 'rxjs';\r\nimport { HttpClient, HttpContext, HttpParams } from '@angular/common/http';\r\nimport { Avatar } from '@masterteam/components/avatar';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport { TranslocoService, TranslocoPipe } from '@jsverse/transloco';\r\n\r\nexport interface User {\r\n isExternal: boolean;\r\n id: string;\r\n displayName: string;\r\n userName: string;\r\n photo: string;\r\n}\r\n\r\n@Component({\r\n selector: 'mt-user-search-field',\r\n standalone: true,\r\n imports: [\r\n FormsModule,\r\n AutoCompleteModule,\r\n Tooltip,\r\n InputGroupModule,\r\n InputGroupAddonModule,\r\n FieldValidation,\r\n Icon,\r\n Avatar,\r\n TranslocoPipe,\r\n ],\r\n templateUrl: './user-search-field.html',\r\n styleUrls: ['./user-search-field.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'grid gap-1',\r\n },\r\n})\r\nexport class UserSearchField implements ControlValueAccessor, OnInit {\r\n readonly hint = input<string>();\r\n readonly label = input<string>();\r\n readonly placeholder = input<string>();\r\n readonly class = input<string>('');\r\n readonly readonly = input<boolean>(false);\r\n readonly required = input<boolean>(false);\r\n readonly isMultiple = input<boolean>(false);\r\n readonly apiUrl = input.required<string>();\r\n readonly dataKey = input<string>('data');\r\n readonly paramName = input<string>('query');\r\n readonly context = input<HttpContext | undefined>(undefined);\r\n\r\n @HostBinding('class') styleClass: string;\r\n\r\n requiredValidator = Validators.required;\r\n value = signal<User | User[] | null>(null);\r\n disabled = signal<boolean>(false);\r\n loading = signal<boolean>(false);\r\n\r\n readonly size = input<'small' | 'large' | undefined>();\r\n\r\n filteredUsers = signal<User[]>([]);\r\n private searchTerms = new Subject<string>();\r\n\r\n private readonly translocoService = inject(TranslocoService);\r\n\r\n readonly autocomplete = viewChild<AutoComplete>('autocomplete');\r\n\r\n onTouched: () => void = () => {};\r\n onModelChange: (value: any) => void = () => {};\r\n\r\n public ngControl: NgControl | null = null;\r\n private http = inject(HttpClient);\r\n\r\n isInvalid = isInvalid;\r\n\r\n constructor() {\r\n this.ngControl = inject(NgControl, { self: true, optional: true });\r\n if (this.ngControl) {\r\n this.ngControl.valueAccessor = this;\r\n }\r\n effect(() => {\r\n if (this.ngControl?.control && this.required()) {\r\n this.ngControl.control.addValidators(Validators.required);\r\n this.ngControl.control.updateValueAndValidity();\r\n }\r\n });\r\n this.getUsers();\r\n }\r\n\r\n ngOnInit() {\r\n this.styleClass = this.class();\r\n }\r\n\r\n search(event: { query: string }) {\r\n this.searchTerms.next(event.query);\r\n }\r\n\r\n onFocus() {\r\n if (this.filteredUsers().length > 0) {\r\n this.autocomplete()?.show();\r\n }\r\n }\r\n\r\n onSelect(event: { originalEvent: Event; value: User }) {\r\n const selectedUser = event.value;\r\n if (this.isMultiple()) {\r\n const current = (this.value() as User[]) || [];\r\n const updated = [...current, selectedUser];\r\n this.value.set(updated);\r\n this.onModelChange(updated);\r\n const remaining = this.filteredUsers().filter(\r\n (u) => u.id !== selectedUser.id,\r\n );\r\n this.filteredUsers.set(remaining);\r\n if (remaining.length > 0) {\r\n queueMicrotask(() => this.autocomplete()?.show());\r\n }\r\n } else {\r\n this.value.set(selectedUser);\r\n this.onModelChange(selectedUser);\r\n this.filteredUsers.set([]);\r\n this.autocomplete()?.hide();\r\n }\r\n this.onTouched();\r\n this.loading.set(false);\r\n }\r\n\r\n onUnselect(event: { originalEvent: Event; value: User }) {\r\n const removedUser = event.value;\r\n const current = (this.value() as User[]) || [];\r\n const updated = current.filter((u) => u.id !== removedUser.id);\r\n this.value.set(updated);\r\n this.onModelChange(updated);\r\n this.onTouched();\r\n }\r\n\r\n onClear() {\r\n this.value.set(this.isMultiple() ? [] : null);\r\n this.onModelChange(this.isMultiple() ? [] : null);\r\n this.filteredUsers.set([]);\r\n this.loading.set(false);\r\n }\r\n\r\n writeValue(value: User | User[] | null): void {\r\n if (this.isMultiple()) {\r\n this.value.set(Array.isArray(value) ? value : value ? [value] : []);\r\n } else {\r\n this.value.set(Array.isArray(value) ? (value[0] ?? null) : value);\r\n }\r\n }\r\n\r\n registerOnChange(fn: (value: User | null) => void) {\r\n this.onModelChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any) {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(disabled: boolean) {\r\n this.disabled.set(disabled);\r\n }\r\n\r\n getUsers() {\r\n this.searchTerms\r\n .pipe(\r\n takeUntilDestroyed(),\r\n debounceTime(250),\r\n tap(() => this.loading.set(true)),\r\n switchMap((term: string) => {\r\n const trimmed = term?.trim();\r\n if (!trimmed) {\r\n this.filteredUsers.set([]);\r\n this.loading.set(false);\r\n return of({ [this.dataKey()]: [] } as Record<string, User[]>);\r\n }\r\n const params = new HttpParams().set(this.paramName(), trimmed);\r\n return this.http\r\n .get<Record<string, User[]>>(this.apiUrl(), {\r\n params,\r\n context: this.context(),\r\n })\r\n .pipe(\r\n finalize(() => this.loading.set(false)),\r\n catchError((err) => {\r\n console.error('API search failed:', err);\r\n return of({ [this.dataKey()]: [] } as Record<string, User[]>);\r\n }),\r\n );\r\n }),\r\n )\r\n .subscribe({\r\n next: (response) => {\r\n const users = (response?.[this.dataKey()] ?? []) as User[];\r\n if (this.isMultiple()) {\r\n const selectedIds = new Set(\r\n ((this.value() as User[]) ?? []).map((u) => u.id),\r\n );\r\n this.filteredUsers.set(users.filter((u) => !selectedIds.has(u.id)));\r\n } else {\r\n this.filteredUsers.set(users);\r\n }\r\n },\r\n });\r\n }\r\n}\r\n","@if (label()) {\r\n <label\r\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\r\n [for]=\"ngControl?.name || label()\"\r\n >\r\n {{ label() }}\r\n </label>\r\n}\r\n<div class=\"relative\">\r\n <p-inputgroup>\r\n <p-autoComplete\r\n #autocomplete=\"\"\r\n [suggestions]=\"filteredUsers()\"\r\n (completeMethod)=\"search($event)\"\r\n (onSelect)=\"onSelect($event)\"\r\n (onUnselect)=\"onUnselect($event)\"\r\n (onClear)=\"onClear()\"\r\n (onFocus)=\"onFocus()\"\r\n (onBlur)=\"onTouched()\"\r\n [ngModel]=\"isMultiple() ? value() : value()?.['displayName']\"\r\n [disabled]=\"disabled() || readonly()\"\r\n [id]=\"ngControl?.name || label()\"\r\n [invalid]=\"isInvalid(ngControl?.control)\"\r\n [placeholder]=\"'components.userSearchField.search' | transloco\"\r\n [multiple]=\"isMultiple()\"\r\n [optionLabel]=\"'displayName'\"\r\n class=\"w-full\"\r\n appendTo=\"body\"\r\n styleClass=\"w-full\"\r\n [dropdown]=\"false\"\r\n [size]=\"size()\"\r\n >\r\n <ng-template let-user pTemplate=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <mt-avatar size=\"small\" icon=\"user.user-01\" />\r\n <div class=\"flex align-items-center gap-3\">\r\n <span class=\"font-medium\">{{ user.displayName }}</span>\r\n <medium class=\"text-gray-500\">{{ \"@\" + user.userName }}</medium>\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- <ng-template let-user #pTemplate=\"selecteditem\">\r\n <div class=\"flex items-center gap-2\">\r\n <mt-avatar size=\"small\" icon=\"user.user-01\" />\r\n <div class=\"flex align-items-center gap-3\">\r\n <span class=\"font-medium\">{{ user.displayName }}</span>\r\n <medium class=\"text-gray-500\">{{ \"@\" + user.userName }}</medium>\r\n </div>\r\n </div>\r\n </ng-template> -->\r\n </p-autoComplete>\r\n @if (hint()) {\r\n <p-inputgroup-addon [mtTooltip]=\"hint()\" tooltipPosition=\"top\">\r\n <mt-icon icon=\"general.help-circle\" />\r\n </p-inputgroup-addon>\r\n } @else {\r\n <p-inputgroup-addon tooltipPosition=\"top\">\r\n <mt-icon icon=\"user.user-03\" />\r\n </p-inputgroup-addon>\r\n }\r\n </p-inputgroup>\r\n\r\n @if (loading()) {\r\n <mt-icon\r\n icon=\"general.loading-01\"\r\n class=\"animate-spin absolute right-3 bg-white top-1/2 -translate-y-1/2\"\r\n />\r\n }\r\n</div>\r\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masterteam/components",
3
- "version": "0.0.166",
3
+ "version": "0.0.168",
4
4
  "publishConfig": {
5
5
  "directory": "../../../dist/masterteam/components",
6
6
  "linkDirectory": true,
@@ -192,6 +192,7 @@ declare class EntityField {
192
192
  readonly hideLabel: _angular_core.Signal<boolean>;
193
193
  readonly labelPosition: _angular_core.Signal<_masterteam_components_entities.EntityLabelPosition>;
194
194
  readonly labelContainerClass: _angular_core.Signal<string>;
195
+ readonly contentContainerClass: _angular_core.Signal<string>;
195
196
  readonly containerClass: _angular_core.Signal<string>;
196
197
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EntityField, never>;
197
198
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityField, "mt-entity-field", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelIconName": { "alias": "labelIconName"; "required": false; "isSignal": true; }; "configuration": { "alias": "configuration"; "required": false; "isSignal": true; }; "gap": { "alias": "gap"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
@@ -1,16 +1,24 @@
1
1
  import { DrawerService, DynamicDrawerConfigInterface } from '@masterteam/components/dynamic-drawer';
2
- import { DialogService, DynamicDialogConfig } from '@masterteam/components/dialog';
2
+ import { DialogService, DynamicDialogConfig, DynamicDialogRef } from '@masterteam/components/dialog';
3
3
  import * as i0 from '@angular/core';
4
4
 
5
5
  declare class ModalService {
6
6
  readonly drawerService: DrawerService;
7
7
  readonly dialogService: DialogService;
8
8
  private dir;
9
+ private readonly openRefs;
9
10
  footerClass: string;
10
11
  contentClass: string;
11
12
  modalConfig: any;
12
- openModal(component: any, modalType: 'drawer' | 'dialog', config: DynamicDialogConfig | DynamicDrawerConfigInterface): any;
13
+ openModal(component: any, modalType: 'drawer' | 'dialog', config: DynamicDialogConfig | DynamicDrawerConfigInterface): DynamicDialogRef<any>;
14
+ /**
15
+ * Closes every modal/drawer opened through this service.
16
+ * Useful on session expiry, forced logout, or any global reset
17
+ * where leftover popups would confuse the user.
18
+ */
19
+ closeAll(): void;
13
20
  handelStartEndPosition(position: string | undefined): string;
21
+ private trackRef;
14
22
  static ɵfac: i0.ɵɵFactoryDeclaration<ModalService, never>;
15
23
  static ɵprov: i0.ɵɵInjectableDeclaration<ModalService>;
16
24
  }
@@ -31,6 +31,13 @@ interface FilterConfig {
31
31
  type: 'text' | 'select' | 'userSelect' | 'date' | 'boolean' | 'user' | 'numberRange';
32
32
  label?: string;
33
33
  options?: FilterOption[];
34
+ /**
35
+ * Controls multi-select behaviour for `select` / `userSelect` filters.
36
+ * Defaults to `true` — opt out with `multiple: false` for a single-select.
37
+ * The stored filter value is an array; rows match if the cell value matches
38
+ * *any* selected entry.
39
+ */
40
+ multiple?: boolean;
34
41
  [key: string]: unknown;
35
42
  }
36
43
  /**
@@ -362,6 +369,12 @@ declare class TableValueResolver {
362
369
  private static readonly UNSORTABLE_ENTITY_VIEW_TYPES;
363
370
  private static readonly EXPORTABLE_ENTITY_VIEW_TYPES;
364
371
  private static readonly FILTERABLE_ENTITY_VIEW_TYPES;
372
+ /**
373
+ * Sentinel `key` value that resolves to the whole row instead of a property
374
+ * path. Use it when a cell renderer (e.g. `type: 'user'`) needs the full
375
+ * record, not a single field — `key: '{{record}}'` in the column def.
376
+ */
377
+ static readonly RECORD_KEY = "{{record}}";
365
378
  static getProperty(obj: unknown, key: string): unknown;
366
379
  /**
367
380
  * Recursively scans `value` for any string field that contains `searchTerm`.
@@ -446,16 +459,6 @@ declare class TableFilter implements ControlValueAccessor {
446
459
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableFilter, "mt-table-filter", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; }, { "filterApplied": "filterApplied"; "filterReset": "filterReset"; }, never, never, true, never>;
447
460
  }
448
461
 
449
- /**
450
- * Renders a single filter control for one `ColumnDef`, dispatching on
451
- * `column.filterConfig.type` (`text` | `select` | `date` | `boolean` | `user`
452
- * | `numberRange`).
453
- *
454
- * Two-way binds the filter value via `value` / `valueChange`. Shared by both
455
- * filter UX modes (popover + per-column) so field rendering lives in one place.
456
- * Add a new filter type by adding a `@case` in the template and extending
457
- * `FilterConfig['type']`.
458
- */
459
462
  declare class TableFilterField {
460
463
  readonly column: _angular_core.InputSignal<ColumnDef>;
461
464
  readonly value: _angular_core.ModelSignal<any>;
@@ -464,7 +467,14 @@ declare class TableFilterField {
464
467
  label: string;
465
468
  value: boolean;
466
469
  }[]>;
470
+ protected readonly multiValue: _angular_core.Signal<readonly unknown[]>;
471
+ protected readonly filterOptions: _angular_core.Signal<readonly unknown[]>;
467
472
  protected getFilterType(): string;
473
+ /**
474
+ * `select` / `userSelect` filters default to multi-select unless the caller
475
+ * opts out with `filterConfig.multiple: false`.
476
+ */
477
+ protected isMultiple(): boolean;
468
478
  protected getScalarValue(): any;
469
479
  protected getDateRangeValue(part: 'from' | 'to'): Date | null;
470
480
  protected getNumberRangeValue(part: 'from' | 'to'): number | null;
@@ -1,6 +1,6 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { OnInit, OnChanges, SimpleChanges } from '@angular/core';
3
- import { ControlValueAccessor, Validators, NgControl } from '@angular/forms';
3
+ import { ControlValueAccessor, ValidatorFn, NgControl } from '@angular/forms';
4
4
  import { isInvalid } from '@masterteam/components';
5
5
  import { MTIcon } from '@masterteam/icons';
6
6
 
@@ -18,7 +18,7 @@ declare class TextField implements ControlValueAccessor, OnInit, OnChanges {
18
18
  readonly icon: _angular_core.InputSignal<MTIcon | undefined>;
19
19
  readonly iconPosition: _angular_core.InputSignal<"start" | "end">;
20
20
  styleClass: string;
21
- requiredValidator: typeof Validators.required;
21
+ requiredValidator: ValidatorFn;
22
22
  value: _angular_core.WritableSignal<string | null>;
23
23
  disabled: _angular_core.WritableSignal<boolean>;
24
24
  passwordVisible: _angular_core.WritableSignal<boolean>;