@xsmusices/ui 1.44.2 → 1.44.6
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.
- package/fesm2022/xsmusices-ui.mjs +18 -22
- package/fesm2022/xsmusices-ui.mjs.map +1 -1
- package/index.d.ts +10 -15
- package/package.json +1 -1
|
@@ -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
|
}
|
|
@@ -9416,17 +9412,23 @@ class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
|
|
|
9416
9412
|
ngOnDestroy() {
|
|
9417
9413
|
super.ngOnDestroy();
|
|
9418
9414
|
this.valueChangesSub.unsubscribe();
|
|
9415
|
+
this.searchSubject.complete();
|
|
9419
9416
|
}
|
|
9420
9417
|
syncSelectedItems() {
|
|
9421
9418
|
const value = this.control.value;
|
|
9422
9419
|
const items = Array.isArray(value)
|
|
9423
|
-
? [...value].sort((a, b) => a['position']
|
|
9424
|
-
|
|
9420
|
+
? [...value].sort((a, b) => (typeof a['position'] === 'number'
|
|
9421
|
+
? a['position']
|
|
9422
|
+
: 0) -
|
|
9423
|
+
(typeof b['position'] === 'number'
|
|
9424
|
+
? b['position']
|
|
9425
|
+
: 0))
|
|
9425
9426
|
: [];
|
|
9426
9427
|
this.selectedItems.set(items);
|
|
9427
9428
|
}
|
|
9428
9429
|
updateControl(items) {
|
|
9429
|
-
const sorted = [...items].sort((a, b) => a['position']
|
|
9430
|
+
const sorted = [...items].sort((a, b) => (typeof a['position'] === 'number' ? a['position'] : 0) -
|
|
9431
|
+
(typeof b['position'] === 'number' ? b['position'] : 0));
|
|
9430
9432
|
this.selectedItems.set(sorted);
|
|
9431
9433
|
this.control.setValue(sorted);
|
|
9432
9434
|
this.control.markAsDirty();
|
|
@@ -9445,21 +9447,10 @@ class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
|
|
|
9445
9447
|
this.showDropdown.set(false);
|
|
9446
9448
|
return;
|
|
9447
9449
|
}
|
|
9448
|
-
this.calculateDropdownPosition();
|
|
9449
9450
|
this.showDropdown.set(true);
|
|
9450
9451
|
this.searching.set(true);
|
|
9451
9452
|
this.searchSubject.next(query);
|
|
9452
9453
|
}
|
|
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
9454
|
async doSearch(query) {
|
|
9464
9455
|
const onSearch = this.pickerProps.onSearch;
|
|
9465
9456
|
if (!onSearch)
|
|
@@ -9504,7 +9495,13 @@ class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
|
|
|
9504
9495
|
return;
|
|
9505
9496
|
const onConfirm = this.pickerProps.onConfirmRemove;
|
|
9506
9497
|
if (onConfirm) {
|
|
9507
|
-
|
|
9498
|
+
let allow = false;
|
|
9499
|
+
try {
|
|
9500
|
+
allow = await onConfirm(item);
|
|
9501
|
+
}
|
|
9502
|
+
catch {
|
|
9503
|
+
allow = false;
|
|
9504
|
+
}
|
|
9508
9505
|
if (!allow)
|
|
9509
9506
|
return;
|
|
9510
9507
|
}
|
|
@@ -9619,12 +9616,11 @@ class XSFormlyEntityPickerComponent extends XSFormlyBaseComponent {
|
|
|
9619
9616
|
onSearchFocus() {
|
|
9620
9617
|
if (this.searchQuery().trim() &&
|
|
9621
9618
|
this.searchResults().length > 0) {
|
|
9622
|
-
this.calculateDropdownPosition();
|
|
9623
9619
|
this.showDropdown.set(true);
|
|
9624
9620
|
}
|
|
9625
9621
|
}
|
|
9626
9622
|
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
|
|
9623
|
+
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
9624
|
}
|
|
9629
9625
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImport: i0, type: XSFormlyEntityPickerComponent, decorators: [{
|
|
9630
9626
|
type: Component,
|
|
@@ -9636,7 +9632,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.33", ngImpo
|
|
|
9636
9632
|
XSButtonComponent,
|
|
9637
9633
|
XSEmptyStateComponent,
|
|
9638
9634
|
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
|
|
9635
|
+
], 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
9636
|
}], ctorParameters: () => [{ type: XSTranslateService }] });
|
|
9641
9637
|
|
|
9642
9638
|
const iconNameForType = (name) => {
|