@xsmusices/ui 1.44.2 → 1.44.4

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.
@@ -9380,7 +9380,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImpo
9380
9380
  }] }] });
9381
9381
 
9382
9382
  class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
9383
- elementRef = inject(ElementRef);
9384
9383
  modalService = inject(XSModalService);
9385
9384
  searchSubject = new Subject();
9386
9385
  valueChangesSub = new Subscription();
@@ -9393,9 +9392,6 @@ class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
9393
9392
  searching = signal(false, ...(ngDevMode ? [{ debugName: "searching" }] : []));
9394
9393
  showDropdown = signal(false, ...(ngDevMode ? [{ debugName: "showDropdown" }] : []));
9395
9394
  selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : []));
9396
- dropdownTop = 0;
9397
- dropdownLeft = 0;
9398
- dropdownWidth = 0;
9399
9395
  get pickerProps() {
9400
9396
  return this.props;
9401
9397
  }
@@ -9445,21 +9441,10 @@ class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
9445
9441
  this.showDropdown.set(false);
9446
9442
  return;
9447
9443
  }
9448
- this.calculateDropdownPosition();
9449
9444
  this.showDropdown.set(true);
9450
9445
  this.searching.set(true);
9451
9446
  this.searchSubject.next(query);
9452
9447
  }
9453
- calculateDropdownPosition() {
9454
- const host = this.elementRef.nativeElement;
9455
- const input = host.querySelector('input');
9456
- if (!input)
9457
- return;
9458
- const rect = input.getBoundingClientRect();
9459
- this.dropdownTop = rect.bottom + 4;
9460
- this.dropdownLeft = rect.left;
9461
- this.dropdownWidth = rect.width;
9462
- }
9463
9448
  async doSearch(query) {
9464
9449
  const onSearch = this.pickerProps.onSearch;
9465
9450
  if (!onSearch)
@@ -9619,12 +9604,11 @@ class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
9619
9604
  onSearchFocus() {
9620
9605
  if (this.searchQuery().trim() &&
9621
9606
  this.searchResults().length > 0) {
9622
- this.calculateDropdownPosition();
9623
9607
  this.showDropdown.set(true);
9624
9608
  }
9625
9609
  }
9626
9610
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: XSFormlyEntityPickerComponent, deps: [{ token: XSTranslateService }], target: i0.ɵɵFactoryTarget.Component });
9627
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: XSFormlyEntityPickerComponent, isStandalone: true, selector: "xs-formly-entity-picker", usesInheritance: true, ngImport: i0, template: "<div [id]=\"'xs-formly-entity-picker-' + id\" [class]=\"wrapperClass\">\n @if (pickerProps.label) {\n <label class=\"formly-label\">\n {{ translateLabel(pickerProps.label) }}\n @if (infoText) {\n <xs-popover-info [text]=\"infoText\" />\n }\n </label>\n }\n\n <div class=\"flex flex-col gap-4\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"onSearchChange($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur()\"\n [placeholder]=\"searchPlaceholder\"\n class=\"input !pr-11 !py-4 rounded-xl\"\n />\n <xs-icon\n icon=\"magnifying-glass\"\n class=\"absolute right-4 top-1/2 -translate-y-1/2 text-zinc-500 text-sm\"\n ></xs-icon>\n </div>\n\n @if (showDropdown()) {\n <div\n class=\"fixed z-[10002] rounded-xl bg-black shadow-xl max-h-48 overflow-y-auto\"\n [style.top.px]=\"dropdownTop\"\n [style.left.px]=\"dropdownLeft\"\n [style.width.px]=\"dropdownWidth\"\n >\n @if (searching()) {\n <div class=\"flex items-center justify-center py-6 bg-zinc-900/50 rounded-xl\">\n <div class=\"animate-spin size-5 border-2 border-zinc-600 border-t-white rounded-full\"></div>\n </div>\n } @else if (searchResults().length === 0) {\n <xs-empty-state\n [config]=\"getNoResultsConfig()\"\n />\n } @else {\n <div class=\"bg-zinc-900/50 rounded-xl\">\n <div class=\"flex flex-col\">\n @for (item of searchResults(); track item._id) {\n <button\n type=\"button\"\n class=\"flex items-center gap-3 w-full p-3 hover:bg-zinc-800/60 transition text-left\"\n (click)=\"selectResult(item)\"\n >\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n <xs-icon icon=\"plus\" class=\"text-zinc-400 text-xs shrink-0\"></xs-icon>\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (selectedItems().length > 0) {\n <div class=\"flex flex-col gap-2\">\n <p class=\"formly-label pt-1\">\n {{ t('FORM.ENTITY_PICKER.ITEM_COUNT') }} ({{ selectedItems().length }})\n </p>\n @for (item of selectedItems(); track item._id; let i = $index) {\n <div class=\"flex items-center gap-4 px-4 py-3.5 rounded-xl bg-zinc-900/50\">\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-semibold text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n\n <div class=\"flex items-center gap-1 shrink-0\">\n @if (showReorder) {\n <xs-button\n icon=\"chevron-up\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_UP')\"\n [disabled]=\"i === 0\"\n (onClick)=\"moveItem(i, -1)\"\n />\n <xs-button\n icon=\"chevron-down\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_DOWN')\"\n [disabled]=\"i === selectedItems().length - 1\"\n (onClick)=\"moveItem(i, 1)\"\n />\n }\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-8 h-8 rounded-lg bg-red-600 text-white hover:opacity-70 transition shrink-0\"\n (click)=\"removeItem(i)\"\n [attr.aria-label]=\"t('FORM.ENTITY_PICKER.DELETE')\"\n >\n <xs-icon icon=\"trash\" class=\"text-xs\"></xs-icon>\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n @if (errorMessage) {\n <p class=\"text-xs text-red-500 mt-2\">{{ errorMessage }}</p>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: XSIconComponent, selector: "xs-icon", inputs: ["icon", "size", "class"] }, { kind: "component", type: XSImageComponent, selector: "xs-image", inputs: ["config", "viewTransitionName", "src", "alt", "width", "height", "size", "rounded", "objectFit", "clickable", "item", "typeItem", "imageType", "fallbackSrc", "loading", "priority", "customClass", "generateAvatar"], outputs: ["onClick", "onLoad", "onError"] }, { kind: "component", type: XSButtonComponent, selector: "xs-button", inputs: ["id", "label", "type", "icon", "action", "customClass", "variant", "layout", "badgeCount", "isFull", "disabled", "loading", "title", "ariaLabel", "borderRadius", "isGrouped", "groupPosition"], outputs: ["isGroupedChange", "groupPositionChange", "click", "onClick"] }, { kind: "component", type: XSEmptyStateComponent, selector: "xs-empty-state", inputs: ["config", "regionAriaLabel"], outputs: ["actionClick"] }, { kind: "component", type: XSPopoverInfoComponent, selector: "xs-popover-info", inputs: ["text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9611
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.33", type: XSFormlyEntityPickerComponent, isStandalone: true, selector: "xs-formly-entity-picker", usesInheritance: true, ngImport: i0, template: "<div [id]=\"'xs-formly-entity-picker-' + id\" [class]=\"wrapperClass\">\n @if (pickerProps.label) {\n <label class=\"formly-label\">\n {{ translateLabel(pickerProps.label) }}\n @if (infoText) {\n <xs-popover-info [text]=\"infoText\" />\n }\n </label>\n }\n\n <div class=\"flex flex-col gap-4\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"onSearchChange($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur()\"\n [placeholder]=\"searchPlaceholder\"\n class=\"input !pr-11 !py-4 rounded-xl\"\n />\n <xs-icon\n icon=\"magnifying-glass\"\n class=\"absolute right-4 top-1/2 -translate-y-1/2 text-zinc-500 text-sm\"\n ></xs-icon>\n\n @if (showDropdown()) {\n <div\n class=\"absolute left-0 right-0 top-full mt-1 z-[10002] rounded-xl bg-black shadow-xl max-h-48 overflow-y-auto\"\n >\n @if (searching()) {\n <div class=\"flex items-center justify-center py-6 bg-zinc-900/50 rounded-xl\">\n <div class=\"animate-spin size-5 border-2 border-zinc-600 border-t-white rounded-full\"></div>\n </div>\n } @else if (searchResults().length === 0) {\n <xs-empty-state\n [config]=\"getNoResultsConfig()\"\n />\n } @else {\n <div class=\"bg-zinc-900/50 rounded-xl\">\n <div class=\"flex flex-col\">\n @for (item of searchResults(); track item._id) {\n <button\n type=\"button\"\n class=\"flex items-center gap-3 w-full p-3 hover:bg-zinc-800/60 transition text-left\"\n (click)=\"selectResult(item)\"\n >\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n <xs-icon icon=\"plus\" class=\"text-zinc-400 text-xs shrink-0\"></xs-icon>\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n @if (selectedItems().length > 0) {\n <div class=\"flex flex-col gap-2\">\n <p class=\"formly-label pt-1\">\n {{ t('FORM.ENTITY_PICKER.ITEM_COUNT') }} ({{ selectedItems().length }})\n </p>\n @for (item of selectedItems(); track item._id; let i = $index) {\n <div class=\"flex items-center gap-4 px-4 py-3.5 rounded-xl bg-zinc-900/50\">\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-semibold text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n\n <div class=\"flex items-center gap-1 shrink-0\">\n @if (showReorder) {\n <xs-button\n icon=\"chevron-up\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_UP')\"\n [disabled]=\"i === 0\"\n (onClick)=\"moveItem(i, -1)\"\n />\n <xs-button\n icon=\"chevron-down\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_DOWN')\"\n [disabled]=\"i === selectedItems().length - 1\"\n (onClick)=\"moveItem(i, 1)\"\n />\n }\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-8 h-8 rounded-lg bg-red-600 text-white hover:opacity-70 transition shrink-0\"\n (click)=\"removeItem(i)\"\n [attr.aria-label]=\"t('FORM.ENTITY_PICKER.DELETE')\"\n >\n <xs-icon icon=\"trash\" class=\"text-xs\"></xs-icon>\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n @if (errorMessage) {\n <p class=\"text-xs text-red-500 mt-2\">{{ errorMessage }}</p>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: XSIconComponent, selector: "xs-icon", inputs: ["icon", "size", "class"] }, { kind: "component", type: XSImageComponent, selector: "xs-image", inputs: ["config", "viewTransitionName", "src", "alt", "width", "height", "size", "rounded", "objectFit", "clickable", "item", "typeItem", "imageType", "fallbackSrc", "loading", "priority", "customClass", "generateAvatar"], outputs: ["onClick", "onLoad", "onError"] }, { kind: "component", type: XSButtonComponent, selector: "xs-button", inputs: ["id", "label", "type", "icon", "action", "customClass", "variant", "layout", "badgeCount", "isFull", "disabled", "loading", "title", "ariaLabel", "borderRadius", "isGrouped", "groupPosition"], outputs: ["isGroupedChange", "groupPositionChange", "click", "onClick"] }, { kind: "component", type: XSEmptyStateComponent, selector: "xs-empty-state", inputs: ["config", "regionAriaLabel"], outputs: ["actionClick"] }, { kind: "component", type: XSPopoverInfoComponent, selector: "xs-popover-info", inputs: ["text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9628
9612
  }
9629
9613
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: XSFormlyEntityPickerComponent, decorators: [{
9630
9614
  type: Component,
@@ -9636,7 +9620,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImpo
9636
9620
  XSButtonComponent,
9637
9621
  XSEmptyStateComponent,
9638
9622
  XSPopoverInfoComponent,
9639
- ], template: "<div [id]=\"'xs-formly-entity-picker-' + id\" [class]=\"wrapperClass\">\n @if (pickerProps.label) {\n <label class=\"formly-label\">\n {{ translateLabel(pickerProps.label) }}\n @if (infoText) {\n <xs-popover-info [text]=\"infoText\" />\n }\n </label>\n }\n\n <div class=\"flex flex-col gap-4\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"onSearchChange($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur()\"\n [placeholder]=\"searchPlaceholder\"\n class=\"input !pr-11 !py-4 rounded-xl\"\n />\n <xs-icon\n icon=\"magnifying-glass\"\n class=\"absolute right-4 top-1/2 -translate-y-1/2 text-zinc-500 text-sm\"\n ></xs-icon>\n </div>\n\n @if (showDropdown()) {\n <div\n class=\"fixed z-[10002] rounded-xl bg-black shadow-xl max-h-48 overflow-y-auto\"\n [style.top.px]=\"dropdownTop\"\n [style.left.px]=\"dropdownLeft\"\n [style.width.px]=\"dropdownWidth\"\n >\n @if (searching()) {\n <div class=\"flex items-center justify-center py-6 bg-zinc-900/50 rounded-xl\">\n <div class=\"animate-spin size-5 border-2 border-zinc-600 border-t-white rounded-full\"></div>\n </div>\n } @else if (searchResults().length === 0) {\n <xs-empty-state\n [config]=\"getNoResultsConfig()\"\n />\n } @else {\n <div class=\"bg-zinc-900/50 rounded-xl\">\n <div class=\"flex flex-col\">\n @for (item of searchResults(); track item._id) {\n <button\n type=\"button\"\n class=\"flex items-center gap-3 w-full p-3 hover:bg-zinc-800/60 transition text-left\"\n (click)=\"selectResult(item)\"\n >\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n <xs-icon icon=\"plus\" class=\"text-zinc-400 text-xs shrink-0\"></xs-icon>\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (selectedItems().length > 0) {\n <div class=\"flex flex-col gap-2\">\n <p class=\"formly-label pt-1\">\n {{ t('FORM.ENTITY_PICKER.ITEM_COUNT') }} ({{ selectedItems().length }})\n </p>\n @for (item of selectedItems(); track item._id; let i = $index) {\n <div class=\"flex items-center gap-4 px-4 py-3.5 rounded-xl bg-zinc-900/50\">\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-semibold text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n\n <div class=\"flex items-center gap-1 shrink-0\">\n @if (showReorder) {\n <xs-button\n icon=\"chevron-up\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_UP')\"\n [disabled]=\"i === 0\"\n (onClick)=\"moveItem(i, -1)\"\n />\n <xs-button\n icon=\"chevron-down\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_DOWN')\"\n [disabled]=\"i === selectedItems().length - 1\"\n (onClick)=\"moveItem(i, 1)\"\n />\n }\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-8 h-8 rounded-lg bg-red-600 text-white hover:opacity-70 transition shrink-0\"\n (click)=\"removeItem(i)\"\n [attr.aria-label]=\"t('FORM.ENTITY_PICKER.DELETE')\"\n >\n <xs-icon icon=\"trash\" class=\"text-xs\"></xs-icon>\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n @if (errorMessage) {\n <p class=\"text-xs text-red-500 mt-2\">{{ errorMessage }}</p>\n }\n</div>\n" }]
9623
+ ], template: "<div [id]=\"'xs-formly-entity-picker-' + id\" [class]=\"wrapperClass\">\n @if (pickerProps.label) {\n <label class=\"formly-label\">\n {{ translateLabel(pickerProps.label) }}\n @if (infoText) {\n <xs-popover-info [text]=\"infoText\" />\n }\n </label>\n }\n\n <div class=\"flex flex-col gap-4\">\n <div class=\"relative\">\n <input\n type=\"text\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"onSearchChange($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur()\"\n [placeholder]=\"searchPlaceholder\"\n class=\"input !pr-11 !py-4 rounded-xl\"\n />\n <xs-icon\n icon=\"magnifying-glass\"\n class=\"absolute right-4 top-1/2 -translate-y-1/2 text-zinc-500 text-sm\"\n ></xs-icon>\n\n @if (showDropdown()) {\n <div\n class=\"absolute left-0 right-0 top-full mt-1 z-[10002] rounded-xl bg-black shadow-xl max-h-48 overflow-y-auto\"\n >\n @if (searching()) {\n <div class=\"flex items-center justify-center py-6 bg-zinc-900/50 rounded-xl\">\n <div class=\"animate-spin size-5 border-2 border-zinc-600 border-t-white rounded-full\"></div>\n </div>\n } @else if (searchResults().length === 0) {\n <xs-empty-state\n [config]=\"getNoResultsConfig()\"\n />\n } @else {\n <div class=\"bg-zinc-900/50 rounded-xl\">\n <div class=\"flex flex-col\">\n @for (item of searchResults(); track item._id) {\n <button\n type=\"button\"\n class=\"flex items-center gap-3 w-full p-3 hover:bg-zinc-800/60 transition text-left\"\n (click)=\"selectResult(item)\"\n >\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n <xs-icon icon=\"plus\" class=\"text-zinc-400 text-xs shrink-0\"></xs-icon>\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n @if (selectedItems().length > 0) {\n <div class=\"flex flex-col gap-2\">\n <p class=\"formly-label pt-1\">\n {{ t('FORM.ENTITY_PICKER.ITEM_COUNT') }} ({{ selectedItems().length }})\n </p>\n @for (item of selectedItems(); track item._id; let i = $index) {\n <div class=\"flex items-center gap-4 px-4 py-3.5 rounded-xl bg-zinc-900/50\">\n <div class=\"size-9 shrink-0 rounded-lg bg-zinc-800 flex items-center justify-center overflow-hidden\">\n @if (item['image']) {\n <xs-image\n [item]=\"item\"\n [typeItem]=\"typeItem\"\n imageType=\"small\"\n size=\"sm\"\n customClass=\"size-9 object-cover\"\n ></xs-image>\n } @else {\n <xs-icon [icon]=\"iconFallback\" class=\"text-zinc-500 text-xs\"></xs-icon>\n }\n </div>\n\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-semibold text-zinc-200 truncate\">{{ item.name }}</p>\n @if (getSecondaryText(item)) {\n <p class=\"text-xs text-zinc-400 truncate\">{{ getSecondaryText(item) }}</p>\n }\n </div>\n\n <div class=\"flex items-center gap-1 shrink-0\">\n @if (showReorder) {\n <xs-button\n icon=\"chevron-up\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_UP')\"\n [disabled]=\"i === 0\"\n (onClick)=\"moveItem(i, -1)\"\n />\n <xs-button\n icon=\"chevron-down\"\n layout=\"iconOnlyMini\"\n variant=\"primary\"\n [title]=\"t('FORM.ENTITY_PICKER.MOVE_DOWN')\"\n [disabled]=\"i === selectedItems().length - 1\"\n (onClick)=\"moveItem(i, 1)\"\n />\n }\n <button\n type=\"button\"\n class=\"flex items-center justify-center w-8 h-8 rounded-lg bg-red-600 text-white hover:opacity-70 transition shrink-0\"\n (click)=\"removeItem(i)\"\n [attr.aria-label]=\"t('FORM.ENTITY_PICKER.DELETE')\"\n >\n <xs-icon icon=\"trash\" class=\"text-xs\"></xs-icon>\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n @if (errorMessage) {\n <p class=\"text-xs text-red-500 mt-2\">{{ errorMessage }}</p>\n }\n</div>\n" }]
9640
9624
  }], ctorParameters: () => [{ type: XSTranslateService }] });
9641
9625
 
9642
9626
  const iconNameForType = (name) => {