@sneat/ui 0.26.0 → 0.26.2
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/esm2022/lib/components/sneat-base-modal.component.js +4 -4
- package/esm2022/lib/components/sneat-base-modal.component.js.map +1 -1
- package/esm2022/lib/components/sneat-base.component.js +3 -3
- package/esm2022/lib/focus.js.map +1 -1
- package/esm2022/lib/selector/multi-selector/multi-selector.component.js +13 -15
- package/esm2022/lib/selector/multi-selector/multi-selector.component.js.map +1 -1
- package/esm2022/lib/selector/multi-selector/multi-selector.service.js +1 -1
- package/esm2022/lib/selector/multi-selector/multi-selector.service.js.map +1 -1
- package/esm2022/lib/selector/select-from-list/select-from-list.component.js +50 -43
- package/esm2022/lib/selector/select-from-list/select-from-list.component.js.map +1 -1
- package/esm2022/lib/selector/selector-base.component.js +12 -11
- package/esm2022/lib/selector/selector-base.component.js.map +1 -1
- package/esm2022/lib/selector/selector-base.service.js +1 -1
- package/esm2022/lib/selector/selector-base.service.js.map +1 -1
- package/lib/components/sneat-base.component.d.ts +1 -1
- package/lib/focus.d.ts +1 -1
- package/lib/selector/multi-selector/multi-selector.component.d.ts +3 -3
- package/lib/selector/multi-selector/multi-selector.service.d.ts +1 -1
- package/lib/selector/select-from-list/select-from-list.component.d.ts +13 -13
- package/lib/selector/selector-base.component.d.ts +3 -3
- package/package.json +6 -5
- package/tsconfig.lib.prod.tsbuildinfo +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { inject, Injectable } from '@angular/core';
|
|
2
2
|
import { SneatBaseComponent } from './sneat-base.component';
|
|
3
|
-
import { ModalController } from '@ionic/angular
|
|
3
|
+
import { ModalController } from '@ionic/angular';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
export class SneatBaseModalComponent extends SneatBaseComponent {
|
|
6
6
|
constructor() {
|
|
@@ -15,10 +15,10 @@ export class SneatBaseModalComponent extends SneatBaseComponent {
|
|
|
15
15
|
.dismiss(data, role, id)
|
|
16
16
|
.catch(this.errorLogger.logErrorHandler(`Failed to close modal ${this.className}`));
|
|
17
17
|
}
|
|
18
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
19
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
18
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SneatBaseModalComponent, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
19
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SneatBaseModalComponent }); }
|
|
20
20
|
}
|
|
21
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
21
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SneatBaseModalComponent, decorators: [{
|
|
22
22
|
type: Injectable
|
|
23
23
|
}] });
|
|
24
24
|
//# sourceMappingURL=sneat-base-modal.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sneat-base-modal.component.js","sourceRoot":"","sources":["../../../../../../libs/ui/src/lib/components/sneat-base-modal.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sneat-base-modal.component.js","sourceRoot":"","sources":["../../../../../../libs/ui/src/lib/components/sneat-base-modal.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;;AAGjD,MAAM,OAAgB,uBAAwB,SAAQ,kBAAkB;IADxE;;QAEmB,oBAAe,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;KAe5D;IAbW,KAAK;QACb,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAES,YAAY,CAAC,IAAc,EAAE,IAAa,EAAE,EAAW;QAC/D,IAAI,CAAC,eAAe;aACjB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;aACvB,KAAK,CACJ,IAAI,CAAC,WAAW,CAAC,eAAe,CAC9B,yBAAyB,IAAI,CAAC,SAAS,EAAE,CAC1C,CACF,CAAC;IACN,CAAC;8GAfmB,uBAAuB;kHAAvB,uBAAuB;;2FAAvB,uBAAuB;kBAD5C,UAAU","sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { SneatBaseComponent } from './sneat-base.component';\nimport { ModalController } from '@ionic/angular';\n\n@Injectable()\nexport abstract class SneatBaseModalComponent extends SneatBaseComponent {\n private readonly modalController = inject(ModalController);\n\n protected close(): void {\n this.dismissModal();\n }\n\n protected dismissModal(data?: unknown, role?: string, id?: string): void {\n this.modalController\n .dismiss(data, role, id)\n .catch(\n this.errorLogger.logErrorHandler(\n `Failed to close modal ${this.className}`,\n ),\n );\n }\n}\n"]}
|
|
@@ -49,10 +49,10 @@ export class SneatBaseComponent {
|
|
|
49
49
|
this.log(`${this.className}.SneatBaseComponent.unsubscribe(reason: ${reason})`);
|
|
50
50
|
this.subs.unsubscribe();
|
|
51
51
|
}
|
|
52
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
53
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
52
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SneatBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
53
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SneatBaseComponent }); }
|
|
54
54
|
}
|
|
55
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
55
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SneatBaseComponent, decorators: [{
|
|
56
56
|
type: Injectable
|
|
57
57
|
}], ctorParameters: () => [] });
|
|
58
58
|
//# sourceMappingURL=sneat-base.component.js.map
|
package/esm2022/lib/focus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"focus.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/focus.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,qBAAqB,CAAC,WAAyB;IAC7D,OAAO,CAAC,KAA8B,EAAE,KAAK,GAAG,GAAG,EAAQ,EAAE;QAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QACD,UAAU,CAAC,GAAG,EAAE;YACd,qBAAqB,CAAC,GAAG,EAAE;gBACzB,qHAAqH;gBACrH,KAAK;qBACF,QAAQ,EAAE;qBACV,KAAK,CAAC,WAAW,CAAC,eAAe,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACxE,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { IonInput, IonTextarea } from '@ionic/angular
|
|
1
|
+
{"version":3,"file":"focus.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/focus.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,qBAAqB,CAAC,WAAyB;IAC7D,OAAO,CAAC,KAA8B,EAAE,KAAK,GAAG,GAAG,EAAQ,EAAE;QAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACtD,OAAO;QACT,CAAC;QACD,UAAU,CAAC,GAAG,EAAE;YACd,qBAAqB,CAAC,GAAG,EAAE;gBACzB,qHAAqH;gBACrH,KAAK;qBACF,QAAQ,EAAE;qBACV,KAAK,CAAC,WAAW,CAAC,eAAe,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACxE,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { IonInput, IonTextarea } from '@ionic/angular';\nimport { IErrorLogger } from '@sneat/core';\n\nexport function createSetFocusToInput(errorLogger: IErrorLogger) {\n return (input?: IonInput | IonTextarea, delay = 100): void => {\n if (!input) {\n console.error('can not set focus to undefined input');\n return;\n }\n setTimeout(() => {\n requestAnimationFrame(() => {\n // input.getInputElement().then(el => el.focus()).catch(errorLogger.logErrorHandler('failed to set focus to input'));\n input\n .setFocus()\n .catch(errorLogger.logErrorHandler('failed to set focus to input'));\n });\n }, delay);\n };\n}\n"]}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, Output, } from '@angular/core';
|
|
2
|
-
import { IonButton, IonButtons, IonCard, IonIcon, IonItem, IonItemDivider, IonLabel, IonList, ModalController, } from '@ionic/angular
|
|
1
|
+
import { Component, EventEmitter, Input, Output, ChangeDetectionStrategy, input } from '@angular/core';
|
|
2
|
+
import { IonButton, IonButtons, IonCard, IonIcon, IonItem, IonItemDivider, IonLabel, IonList, ModalController, } from '@ionic/angular';
|
|
3
3
|
import { ClassName } from '../../components';
|
|
4
4
|
import { OverlayController, SelectorBaseComponent, } from '../selector-base.component';
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
6
|
export class MultiSelectorComponent extends SelectorBaseComponent {
|
|
7
7
|
constructor() {
|
|
8
8
|
super(...arguments);
|
|
9
|
-
this.title = 'Select'
|
|
10
|
-
|
|
9
|
+
this.title = input('Select', /* @ts-ignore */
|
|
10
|
+
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
11
|
+
this.canRemove = input(false, /* @ts-ignore */
|
|
12
|
+
...(ngDevMode ? [{ debugName: "canRemove" }] : /* istanbul ignore next */ []));
|
|
11
13
|
this.removeItems = new EventEmitter();
|
|
12
14
|
this.addItems = new EventEmitter();
|
|
13
15
|
}
|
|
@@ -21,8 +23,8 @@ export class MultiSelectorComponent extends SelectorBaseComponent {
|
|
|
21
23
|
this.selectedItems = this.selectedItems?.filter((i) => i.id !== item.id);
|
|
22
24
|
this.removeItems.emit([{ event, item }]);
|
|
23
25
|
}
|
|
24
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
25
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
26
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: MultiSelectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
27
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: MultiSelectorComponent, isStandalone: true, selector: "sneat-multi-selector", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, canRemove: { classPropertyName: "canRemove", publicName: "canRemove", isSignal: true, isRequired: false, transformFunction: null }, allItems: { classPropertyName: "allItems", publicName: "allItems", isSignal: false, isRequired: false, transformFunction: null }, selectedIDs: { classPropertyName: "selectedIDs", publicName: "selectedIDs", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { removeItems: "removeItems", addItems: "addItems" }, providers: [
|
|
26
28
|
{
|
|
27
29
|
provide: ClassName,
|
|
28
30
|
useValue: 'MultiSelectorComponent',
|
|
@@ -31,9 +33,9 @@ export class MultiSelectorComponent extends SelectorBaseComponent {
|
|
|
31
33
|
provide: OverlayController,
|
|
32
34
|
useClass: ModalController,
|
|
33
35
|
},
|
|
34
|
-
], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ion-card>\n <ion-item-divider color=\"light\">\n <ion-label color=\"medium\">{{ title }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\">\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n\n <ion-list>\n @for (item of selectedItems; track item.id) {\n <ion-item>\n <ion-label>{{ item.title }}</ion-label>\n @if (canRemove) {\n <ion-buttons slot=\"end\">\n <ion-button title=\"Remove\" (click)=\"removeItem($event, item)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n </ion-list>\n</ion-card>\n", dependencies: [{ kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonItemDivider, selector: "ion-item-divider", inputs: ["color", "mode", "sticky"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }] }); }
|
|
36
|
+
], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ion-card>\n <ion-item-divider color=\"light\">\n <ion-label color=\"medium\">{{ title() }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\">\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n\n <ion-list>\n @for (item of selectedItems; track item.id) {\n <ion-item>\n <ion-label>{{ item.title }}</ion-label>\n @if (canRemove()) {\n <ion-buttons slot=\"end\">\n <ion-button title=\"Remove\" (click)=\"removeItem($event, item)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n </ion-list>\n</ion-card>\n", dependencies: [{ kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonItemDivider, selector: "ion-item-divider", inputs: ["color", "mode", "sticky"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"], outputs: ["ionFocus", "ionBlur"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
35
37
|
}
|
|
36
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
38
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: MultiSelectorComponent, decorators: [{
|
|
37
39
|
type: Component,
|
|
38
40
|
args: [{ selector: 'sneat-multi-selector', imports: [
|
|
39
41
|
IonCard,
|
|
@@ -44,7 +46,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
44
46
|
IonItem,
|
|
45
47
|
IonIcon,
|
|
46
48
|
IonList,
|
|
47
|
-
], providers: [
|
|
49
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
48
50
|
{
|
|
49
51
|
provide: ClassName,
|
|
50
52
|
useValue: 'MultiSelectorComponent',
|
|
@@ -53,12 +55,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
53
55
|
provide: OverlayController,
|
|
54
56
|
useClass: ModalController,
|
|
55
57
|
},
|
|
56
|
-
], template: "<ion-card>\n <ion-item-divider color=\"light\">\n <ion-label color=\"medium\">{{ title }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\">\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n\n <ion-list>\n @for (item of selectedItems; track item.id) {\n <ion-item>\n <ion-label>{{ item.title }}</ion-label>\n @if (canRemove) {\n <ion-buttons slot=\"end\">\n <ion-button title=\"Remove\" (click)=\"removeItem($event, item)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n </ion-list>\n</ion-card>\n" }]
|
|
57
|
-
}], propDecorators: { title: [{
|
|
58
|
-
type: Input
|
|
59
|
-
}], canRemove: [{
|
|
60
|
-
type: Input
|
|
61
|
-
}], allItems: [{
|
|
58
|
+
], template: "<ion-card>\n <ion-item-divider color=\"light\">\n <ion-label color=\"medium\">{{ title() }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\">\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n\n <ion-list>\n @for (item of selectedItems; track item.id) {\n <ion-item>\n <ion-label>{{ item.title }}</ion-label>\n @if (canRemove()) {\n <ion-buttons slot=\"end\">\n <ion-button title=\"Remove\" (click)=\"removeItem($event, item)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n </ion-list>\n</ion-card>\n" }]
|
|
59
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], canRemove: [{ type: i0.Input, args: [{ isSignal: true, alias: "canRemove", required: false }] }], allItems: [{
|
|
62
60
|
type: Input
|
|
63
61
|
}], selectedIDs: [{
|
|
64
62
|
type: Input
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-selector.component.js","sourceRoot":"","sources":["../../../../../../../libs/ui/src/lib/selector/multi-selector/multi-selector.component.ts","../../../../../../../libs/ui/src/lib/selector/multi-selector/multi-selector.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,EAEL,MAAM,
|
|
1
|
+
{"version":3,"file":"multi-selector.component.js","sourceRoot":"","sources":["../../../../../../../libs/ui/src/lib/selector/multi-selector/multi-selector.component.ts","../../../../../../../libs/ui/src/lib/selector/multi-selector/multi-selector.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,EAEL,MAAM,EAEN,uBAAuB,EACvB,KAAK,EACN,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,SAAS,EACT,UAAU,EACV,OAAO,EACP,OAAO,EACP,OAAO,EACP,cAAc,EACd,QAAQ,EACR,OAAO,EACP,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACL,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;;AA2BpC,MAAM,OAAO,sBACX,SAAQ,qBAAwB;IA1BlC;;QA6BW,UAAK,GAAG,KAAK,CAAC,QAAQ;kFAAC,CAAC;QAExB,cAAS,GAAG,KAAK,CAAC,KAAK;sFAAC,CAAC;QAQf,gBAAW,GAAG,IAAI,YAAY,EAAsB,CAAC;QACrD,aAAQ,GAAG,IAAI,YAAY,EAAsB,CAAC;KAiBtE;IAbC,WAAW,CAAC,OAAsB;QAChC,IAAI,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAClD,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CACpC,CAAC;QACJ,CAAC;IACH,CAAC;IAES,UAAU,CAAC,KAAY,EAAE,IAAiB;QAClD,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;8GA/BU,sBAAsB;kGAAtB,sBAAsB,upBAXtB;YACT;gBACE,OAAO,EAAE,SAAS;gBAClB,QAAQ,EAAE,wBAAwB;aACnC;YACD;gBACE,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,eAAe;aAC1B;SACF,sECnDH,qwBA0BA,4CDMI,OAAO,yLACP,cAAc,kGACd,QAAQ,6FACR,UAAU,8EACV,SAAS,sRACT,OAAO,0NACP,OAAO,2JACP,OAAO;;2FAcE,sBAAsB;kBAzBlC,SAAS;+BACE,sBAAsB,WAEvB;wBACP,OAAO;wBACP,cAAc;wBACd,QAAQ;wBACR,UAAU;wBACV,SAAS;wBACT,OAAO;wBACP,OAAO;wBACP,OAAO;qBACR,mBACgB,uBAAuB,CAAC,MAAM,aACpC;wBACT;4BACE,OAAO,EAAE,SAAS;4BAClB,QAAQ,EAAE,wBAAwB;yBACnC;wBACD;4BACE,OAAO,EAAE,iBAAiB;4BAC1B,QAAQ,EAAE,eAAe;yBAC1B;qBACF;;sBAWA,KAAK;;sBAGL,KAAK;;sBAEL,MAAM;;sBACN,MAAM","sourcesContent":["import {\n Component,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n SimpleChanges,\n ChangeDetectionStrategy,\n input\n} from '@angular/core';\nimport {\n IonButton,\n IonButtons,\n IonCard,\n IonIcon,\n IonItem,\n IonItemDivider,\n IonLabel,\n IonList,\n ModalController,\n} from '@ionic/angular';\nimport { ClassName } from '../../components';\nimport { ISelectItem, ISelectItemEvent } from '../selector-interfaces';\nimport {\n OverlayController,\n SelectorBaseComponent,\n} from '../selector-base.component';\n\n@Component({\n selector: 'sneat-multi-selector',\n templateUrl: './multi-selector.component.html',\n imports: [\n IonCard,\n IonItemDivider,\n IonLabel,\n IonButtons,\n IonButton,\n IonItem,\n IonIcon,\n IonList,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: ClassName,\n useValue: 'MultiSelectorComponent',\n },\n {\n provide: OverlayController,\n useClass: ModalController,\n },\n ],\n})\nexport class MultiSelectorComponent<T = ISelectItem>\n extends SelectorBaseComponent<T>\n implements OnChanges\n{\n readonly title = input('Select');\n\n readonly canRemove = input(false);\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() public allItems?: ISelectItem[];\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() public selectedIDs?: readonly string[];\n\n @Output() readonly removeItems = new EventEmitter<ISelectItemEvent[]>();\n @Output() readonly addItems = new EventEmitter<ISelectItemEvent[]>();\n\n protected selectedItems?: ISelectItem[];\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['allItems']) {\n this.selectedItems = this.allItems?.filter((item) =>\n this.selectedIDs?.includes(item.id),\n );\n }\n }\n\n protected removeItem(event: Event, item: ISelectItem): void {\n event.stopPropagation();\n this.selectedItems = this.selectedItems?.filter((i) => i.id !== item.id);\n this.removeItems.emit([{ event, item }]);\n }\n}\n","<ion-card>\n <ion-item-divider color=\"light\">\n <ion-label color=\"medium\">{{ title() }}</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\">\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n\n <ion-list>\n @for (item of selectedItems; track item.id) {\n <ion-item>\n <ion-label>{{ item.title }}</ion-label>\n @if (canRemove()) {\n <ion-buttons slot=\"end\">\n <ion-button title=\"Remove\" (click)=\"removeItem($event, item)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n </ion-list>\n</ion-card>\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate, __metadata, __param } from "tslib";
|
|
2
2
|
import { Inject } from '@angular/core';
|
|
3
|
-
import { ModalController } from '@ionic/angular
|
|
3
|
+
import { ModalController } from '@ionic/angular';
|
|
4
4
|
import { ErrorLogger } from '@sneat/core';
|
|
5
5
|
import { MultiSelectorComponent } from './multi-selector.component';
|
|
6
6
|
let MultiSelectorService = class MultiSelectorService {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-selector.service.js","sourceRoot":"","sources":["../../../../../../../libs/ui/src/lib/selector/multi-selector/multi-selector.service.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,eAAe,EAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"multi-selector.service.js","sourceRoot":"","sources":["../../../../../../../libs/ui/src/lib/selector/multi-selector/multi-selector.service.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,eAAe,EAAgB,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,IAAa,oBAAoB,GAAjC,MAAa,oBAAoB;IAC/B,YACwC,WAAyB,EAC9C,eAAgC;QADX,gBAAW,GAAX,WAAW,CAAc;QAC9C,oBAAe,GAAf,eAAe,CAAiB;IAChD,CAAC;IAEJ,cAAc,CACZ,KAAoB,EACpB,aAA4B;QAE5B,MAAM,MAAM,GAAG,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC5D,MAAM,YAAY,GAAiB;gBACjC,SAAS,EAAE,sBAAsB;gBACjC,cAAc,EAAE;oBACd,KAAK;oBACL,aAAa;iBACd;gBACD,aAAa,EAAE,IAAI;aACpB,CAAC;YACF,IAAI,CAAC,eAAe;iBACjB,MAAM,CAAC,YAAY,CAAC;iBACpB,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;gBACd,KAAK;qBACF,YAAY,EAAE;qBACd,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC;qBACrD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;oBACb,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,EAAE,gCAAgC,CAAC,CAAC;oBACjE,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC,CAAC,CAAC;gBACL,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;oBAC5B,MAAM,CAAC,GAAG,CAAC,CAAC;oBACZ,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;gBACvD,CAAC,CAAC,CAAC;YACL,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACb,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;gBACzD,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AA1CY,oBAAoB;IAE5B,WAAA,MAAM,CAAC,WAAW,CAAC,CAAA;6CACc,eAAe;GAHxC,oBAAoB,CA0ChC","sourcesContent":["import { Inject } from '@angular/core';\nimport { ModalController, ModalOptions } from '@ionic/angular';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport { ISelectItem } from '../selector-interfaces';\nimport { MultiSelectorComponent } from './multi-selector.component';\n\nexport class MultiSelectorService {\n constructor(\n @Inject(ErrorLogger) private readonly errorLogger: IErrorLogger,\n private readonly modalController: ModalController,\n ) {}\n\n selectMultiple(\n items: ISelectItem[],\n selectedItems: ISelectItem[],\n ): Promise<ISelectItem[]> {\n const result = new Promise<ISelectItem[]>((resolve, reject) => {\n const modalOptions: ModalOptions = {\n component: MultiSelectorComponent,\n componentProps: {\n items,\n selectedItems,\n },\n keyboardClose: true,\n };\n this.modalController\n .create(modalOptions)\n .then((modal) => {\n modal\n .onDidDismiss()\n .then((res) => resolve(res.data?.selectedItems || []))\n .catch((err) => {\n this.errorLogger.logError(err, 'Failed to handle modal dismiss');\n reject(err);\n });\n modal.present().catch((err) => {\n reject(err);\n this.errorLogger.logError('Failed to present modal');\n });\n })\n .catch((err) => {\n this.errorLogger.logError(err, 'Failed to create modal');\n reject(err);\n });\n });\n\n return result;\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, computed, EventEmitter, forwardRef, input, Input, Output, signal, ViewChild, inject, } from '@angular/core';
|
|
2
2
|
import { FormsModule, NG_VALUE_ACCESSOR, } from '@angular/forms';
|
|
3
3
|
import { RouterModule } from '@angular/router';
|
|
4
|
-
import { IonButton, IonButtons, IonCheckbox, IonIcon, IonInput, IonItem, IonItemDivider, IonItemGroup, IonLabel, IonList, IonRadio, IonRadioGroup, IonSelect, IonSelectOption, IonSpinner, } from '@ionic/angular
|
|
4
|
+
import { IonButton, IonButtons, IonCheckbox, IonIcon, IonInput, IonItem, IonItemDivider, IonItemGroup, IonLabel, IonList, IonRadio, IonRadioGroup, IonSelect, IonSelectOption, IonSpinner, } from '@ionic/angular';
|
|
5
5
|
import { ErrorLogger } from '@sneat/core';
|
|
6
6
|
import { NEVER, Observable, Subject, takeUntil } from 'rxjs';
|
|
7
7
|
import * as i0 from "@angular/core";
|
|
@@ -9,28 +9,57 @@ import * as i1 from "@angular/forms";
|
|
|
9
9
|
export class SelectFromListComponent {
|
|
10
10
|
constructor() {
|
|
11
11
|
this.errorLogger = inject(ErrorLogger);
|
|
12
|
+
// TODO: Skipped for migration because:
|
|
13
|
+
// Your application code writes to the input. This prevents migration.
|
|
12
14
|
this.value = '';
|
|
13
15
|
this.valueChange = new EventEmitter();
|
|
14
|
-
this.filterLabel = 'Find'
|
|
15
|
-
|
|
16
|
+
this.filterLabel = input('Find', /* @ts-ignore */
|
|
17
|
+
...(ngDevMode ? [{ debugName: "filterLabel" }] : /* istanbul ignore next */ []));
|
|
18
|
+
this.label = input('Please choose', /* @ts-ignore */
|
|
19
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
20
|
+
this.listLabel = input(/* @ts-ignore */
|
|
21
|
+
...(ngDevMode ? [undefined, { debugName: "listLabel" }] : /* istanbul ignore next */ []));
|
|
22
|
+
this.listLabelColor = input(/* @ts-ignore */
|
|
23
|
+
...(ngDevMode ? [undefined, { debugName: "listLabelColor" }] : /* istanbul ignore next */ []));
|
|
24
|
+
this.isFilterable = input(/* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [undefined, { debugName: "isFilterable" }] : /* istanbul ignore next */ []));
|
|
26
|
+
this.isLoading = input(/* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [undefined, { debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
28
|
+
// TODO: Skipped for migration because:
|
|
29
|
+
// Your application code writes to the input. This prevents migration.
|
|
16
30
|
this.items$ = NEVER;
|
|
17
|
-
this.$items = signal(undefined,
|
|
18
|
-
|
|
19
|
-
this.
|
|
31
|
+
this.$items = signal(undefined, /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "$items" }] : /* istanbul ignore next */ []));
|
|
33
|
+
this.lastItemLines = input(/* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [undefined, { debugName: "lastItemLines" }] : /* istanbul ignore next */ []));
|
|
35
|
+
this.justify = input(/* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [undefined, { debugName: "justify" }] : /* istanbul ignore next */ []));
|
|
37
|
+
this.other = input('none', /* @ts-ignore */
|
|
38
|
+
...(ngDevMode ? [{ debugName: "other" }] : /* istanbul ignore next */ []));
|
|
39
|
+
this.canAdd = input(false, /* @ts-ignore */
|
|
40
|
+
...(ngDevMode ? [{ debugName: "canAdd" }] : /* istanbul ignore next */ []));
|
|
20
41
|
this.filterChanged = new EventEmitter();
|
|
42
|
+
// TODO: Skipped for migration because:
|
|
43
|
+
// Your application code writes to the input. This prevents migration.
|
|
21
44
|
this.selectMode = 'single';
|
|
22
|
-
this.isReadonly = false
|
|
23
|
-
|
|
45
|
+
this.isReadonly = input(false, /* @ts-ignore */
|
|
46
|
+
...(ngDevMode ? [{ debugName: "isReadonly" }] : /* istanbul ignore next */ []));
|
|
47
|
+
this.$isProcessing = input(/* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [undefined, { debugName: "$isProcessing" }] : /* istanbul ignore next */ []));
|
|
24
49
|
// @Input() ngModel?: string;
|
|
25
50
|
// @Output() readonly ngModelChange = new EventEmitter<string>();
|
|
26
51
|
this.destroyed = new Subject();
|
|
27
|
-
this.$displayItems = signal(undefined,
|
|
52
|
+
this.$displayItems = signal(undefined, /* @ts-ignore */
|
|
53
|
+
...(ngDevMode ? [{ debugName: "$displayItems" }] : /* istanbul ignore next */ []));
|
|
28
54
|
this.$hiddenCount = computed(() => {
|
|
29
55
|
return (this.$items()?.length || 0) - (this.$displayItems()?.length || 0);
|
|
30
|
-
},
|
|
56
|
+
}, /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "$hiddenCount" }] : /* istanbul ignore next */ []));
|
|
31
58
|
this.isDisabled = false;
|
|
32
|
-
this.$filter = signal('',
|
|
33
|
-
|
|
59
|
+
this.$filter = signal('', /* @ts-ignore */
|
|
60
|
+
...(ngDevMode ? [{ debugName: "$filter" }] : /* istanbul ignore next */ []));
|
|
61
|
+
this.$selectedItem = signal(undefined, /* @ts-ignore */
|
|
62
|
+
...(ngDevMode ? [{ debugName: "$selectedItem" }] : /* istanbul ignore next */ []));
|
|
34
63
|
this.onChange = (id) => {
|
|
35
64
|
this.value = id;
|
|
36
65
|
if (this.$selectedItem()?.id !== id) {
|
|
@@ -145,16 +174,16 @@ export class SelectFromListComponent {
|
|
|
145
174
|
ngOnDestroy() {
|
|
146
175
|
this.destroyed.next();
|
|
147
176
|
}
|
|
148
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
149
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
177
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SelectFromListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
178
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SelectFromListComponent, isStandalone: true, selector: "sneat-select-from-list", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, filterLabel: { classPropertyName: "filterLabel", publicName: "filterLabel", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, listLabel: { classPropertyName: "listLabel", publicName: "listLabel", isSignal: true, isRequired: false, transformFunction: null }, listLabelColor: { classPropertyName: "listLabelColor", publicName: "listLabelColor", isSignal: true, isRequired: false, transformFunction: null }, isFilterable: { classPropertyName: "isFilterable", publicName: "isFilterable", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: false, isRequired: false, transformFunction: null }, items$: { classPropertyName: "items$", publicName: "items$", isSignal: false, isRequired: false, transformFunction: null }, lastItemLines: { classPropertyName: "lastItemLines", publicName: "lastItemLines", isSignal: true, isRequired: false, transformFunction: null }, labelPlacement: { classPropertyName: "labelPlacement", publicName: "labelPlacement", isSignal: false, isRequired: false, transformFunction: null }, justify: { classPropertyName: "justify", publicName: "justify", isSignal: true, isRequired: false, transformFunction: null }, other: { classPropertyName: "other", publicName: "other", isSignal: true, isRequired: false, transformFunction: null }, canAdd: { classPropertyName: "canAdd", publicName: "canAdd", isSignal: true, isRequired: false, transformFunction: null }, filterItem: { classPropertyName: "filterItem", publicName: "filterItem", isSignal: false, isRequired: false, transformFunction: null }, selectMode: { classPropertyName: "selectMode", publicName: "selectMode", isSignal: false, isRequired: false, transformFunction: null }, isReadonly: { classPropertyName: "isReadonly", publicName: "isReadonly", isSignal: true, isRequired: false, transformFunction: null }, $isProcessing: { classPropertyName: "$isProcessing", publicName: "$isProcessing", isSignal: true, isRequired: false, transformFunction: null }, sortBy: { classPropertyName: "sortBy", publicName: "sortBy", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", filterChanged: "filterChanged" }, providers: [
|
|
150
179
|
{
|
|
151
180
|
provide: NG_VALUE_ACCESSOR,
|
|
152
181
|
useExisting: forwardRef(() => SelectFromListComponent),
|
|
153
182
|
multi: true,
|
|
154
183
|
},
|
|
155
|
-
], viewQueries: [{ propertyName: "addInput", first: true, predicate: IonInput, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }, { propertyName: "selectInput", first: true, predicate: ["selectInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (value) {\n <ion-item\n [lines]=\"lastItemLines\"\n [class]=\"{ 'sneat-tiny-end-padding': !isReadonly }\"\n >\n @if ($selectedItem()?.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"$selectedItem()?.iconName\"\n [color]=\"\n $selectedItem()?.iconColor || $selectedItem()?.labelColor || 'medium'\n \"\n />\n }\n <ion-select\n #selectInput\n interface=\"popover\"\n [label]=\"label\"\n [(ngModel)]=\"value\"\n (ionChange)=\"onSelectChanged()\"\n [disabled]=\"isReadonly || !!$isProcessing()\"\n >\n @for (item of items; track item.id) {\n <ion-select-option [value]=\"item.id\">\n {{ item.emoji }}\n @if (item.shortTitle) {\n {{ item.shortTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-select-option>\n }\n <!--\t\t<ion-select-option value=\"other\">OTHER</ion-select-option>-->\n </ion-select>\n @if ($isProcessing()) {\n <ion-spinner name=\"lines-small\" color=\"medium\" slot=\"end\" />\n } @else if (!isReadonly) {\n <ion-buttons slot=\"end\" class=\"ion-no-margin\">\n <ion-button color=\"medium\" title=\"Deselect\" (click)=\"deselect()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n} @else {\n @if (isFilterable) {\n <ion-item class=\"sneat-tiny-end-padding\">\n <ion-input\n #filterInput\n color=\"medium\"\n placeholder=\"filter\"\n [label]=\"filterLabel\"\n [value]=\"$filter()\"\n (ionChange)=\"onFilterChanged($event, 'ionChange')\"\n (ionInput)=\"onFilterChanged($event, 'ionInput')\"\n />\n @if ($filter()) {\n <ion-buttons slot=\"end\">\n @if (canAdd && $hiddenCount()) {\n <ion-button\n title=\"Use this\"\n color=\"primary\"\n (click)=\"onAdd($event)\"\n >\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n <ion-button (click)=\"clearFilter()\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n\n @if (items && !items.length) {\n <ion-item-divider>\n <ion-label>No items yet.</ion-label>\n </ion-item-divider>\n }\n\n @if (labelPlacement) {\n <ion-radio-group [(ngModel)]=\"value\" (ionChange)=\"onRadioChanged($event)\">\n <ion-list class=\"ion-no-padding\" lines=\"full\">\n @if (listLabel === \"divider\") {\n <ion-item [color]=\"listLabelColor\">\n <ion-label>{{ label }}</ion-label>\n </ion-item>\n }\n @for (item of $displayItems(); track item.id) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : 'full'\"\n (click)=\"select(item)\"\n tappable=\"true\"\n >\n @switch (selectMode) {\n @case (\"multiple\") {\n <ion-checkbox\n slot=\"start\"\n [value]=\"item.id\"\n [checked]=\"false\"\n [disabled]=\"isDisabled\"\n (ionChange)=\"onCheckboxChange($event, item)\"\n />\n <ion-label>\n <!-- TODO: duplicate code with the next case -->\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-label>\n }\n @case (\"single\") {\n <ion-radio\n [value]=\"item.id\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"\n justify ||\n (!labelPlacement || labelPlacement === 'start'\n ? 'space-between'\n : 'start')\n \"\n >\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-radio>\n }\n }\n </ion-item>\n @if (item.description1) {\n <ion-item-divider>\n <ion-label>\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item-divider>\n }\n }\n </ion-list>\n </ion-radio-group>\n } @else {\n <ion-item-group>\n @for (item of $displayItems(); track item.id; let last = $last) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : last ? lastItemLines : 'full'\"\n button\n (click)=\"select(item)\"\n >\n @if (item.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"item.iconName\"\n [color]=\"item.iconColor || item.labelColor || 'medium'\"\n />\n }\n @if (!labelPlacement) {\n <ion-label [color]=\"item.labelColor\">\n <span class=\"ion-margin-end\">{{ item.emoji }}</span>\n {{ item.title }}\n </ion-label>\n }\n </ion-item>\n @if (item.description1) {\n <ion-item [lines]=\"last ? lastItemLines : 'full'\">\n <ion-label color=\"medium\">\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item>\n }\n }\n </ion-item-group>\n }\n @if ($hiddenCount(); as hiddenCount) {\n <ion-item-divider>\n <ion-label color=\"medium\"\n >{{ hiddenCount }} out of {{ items?.length }} items are hidden by filter\n </ion-label>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"clearFilter()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Clear filter</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: RouterModule }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItemDivider, selector: "ion-item-divider", inputs: ["color", "mode", "sticky"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonItemGroup, selector: "ion-item-group" }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
184
|
+
], viewQueries: [{ propertyName: "addInput", first: true, predicate: IonInput, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }, { propertyName: "selectInput", first: true, predicate: ["selectInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (value) {\n <ion-item\n [lines]=\"lastItemLines()\"\n [class]=\"{ 'sneat-tiny-end-padding': !isReadonly() }\"\n >\n @if ($selectedItem()?.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"$safeNavigationMigration($selectedItem()?.iconName)\"\n [color]=\"\n $selectedItem()?.iconColor || $selectedItem()?.labelColor || 'medium'\n \"\n />\n }\n <ion-select\n #selectInput\n interface=\"popover\"\n [label]=\"label()\"\n [(ngModel)]=\"value\"\n (ionChange)=\"onSelectChanged()\"\n [disabled]=\"isReadonly() || !!$isProcessing()\"\n >\n @for (item of items; track item.id) {\n <ion-select-option [value]=\"item.id\">\n {{ item.emoji }}\n @if (item.shortTitle) {\n {{ item.shortTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-select-option>\n }\n <!--\t\t<ion-select-option value=\"other\">OTHER</ion-select-option>-->\n </ion-select>\n @if ($isProcessing()) {\n <ion-spinner name=\"lines-small\" color=\"medium\" slot=\"end\" />\n } @else if (!isReadonly()) {\n <ion-buttons slot=\"end\" class=\"ion-no-margin\">\n <ion-button color=\"medium\" title=\"Deselect\" (click)=\"deselect()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n} @else {\n @if (isFilterable()) {\n <ion-item class=\"sneat-tiny-end-padding\">\n <ion-input\n #filterInput\n color=\"medium\"\n placeholder=\"filter\"\n [label]=\"filterLabel()\"\n [value]=\"$filter()\"\n (ionChange)=\"onFilterChanged($event, 'ionChange')\"\n (ionInput)=\"onFilterChanged($event, 'ionInput')\"\n />\n @if ($filter()) {\n <ion-buttons slot=\"end\">\n @if (canAdd() && $hiddenCount()) {\n <ion-button\n title=\"Use this\"\n color=\"primary\"\n (click)=\"onAdd($event)\"\n >\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n <ion-button (click)=\"clearFilter()\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n\n @if (items && !items.length) {\n <ion-item-divider>\n <ion-label>No items yet.</ion-label>\n </ion-item-divider>\n }\n\n @if (labelPlacement) {\n <ion-radio-group [(ngModel)]=\"value\" (ionChange)=\"onRadioChanged($event)\">\n <ion-list class=\"ion-no-padding\" lines=\"full\">\n @if (listLabel() === \"divider\") {\n <ion-item [color]=\"listLabelColor()\">\n <ion-label>{{ label() }}</ion-label>\n </ion-item>\n }\n @for (item of $displayItems(); track item.id) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : 'full'\"\n (click)=\"select(item)\"\n tappable=\"true\"\n >\n @switch (selectMode) {\n @case (\"multiple\") {\n <ion-checkbox\n slot=\"start\"\n [value]=\"item.id\"\n [checked]=\"false\"\n [disabled]=\"isDisabled\"\n (ionChange)=\"onCheckboxChange($event, item)\"\n />\n <ion-label>\n <!-- TODO: duplicate code with the next case -->\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-label>\n }\n @case (\"single\") {\n <ion-radio\n [value]=\"item.id\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"\n justify() ||\n (!labelPlacement || labelPlacement === 'start'\n ? 'space-between'\n : 'start')\n \"\n >\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-radio>\n }\n }\n </ion-item>\n @if (item.description1) {\n <ion-item-divider>\n <ion-label>\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item-divider>\n }\n }\n </ion-list>\n </ion-radio-group>\n } @else {\n <ion-item-group>\n @for (item of $displayItems(); track item.id; let last = $last) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : last ? lastItemLines() : 'full'\"\n button\n (click)=\"select(item)\"\n >\n @if (item.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"item.iconName\"\n [color]=\"item.iconColor || item.labelColor || 'medium'\"\n />\n }\n @if (!labelPlacement) {\n <ion-label [color]=\"item.labelColor\">\n <span class=\"ion-margin-end\">{{ item.emoji }}</span>\n {{ item.title }}\n </ion-label>\n }\n </ion-item>\n @if (item.description1) {\n <ion-item [lines]=\"last ? lastItemLines() : 'full'\">\n <ion-label color=\"medium\">\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item>\n }\n }\n </ion-item-group>\n }\n @if ($hiddenCount(); as hiddenCount) {\n <ion-item-divider>\n <ion-label color=\"medium\"\n >{{ hiddenCount }} out of {{ items?.length }} items are hidden by filter\n </ion-label>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"clearFilter()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Clear filter</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n }\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: RouterModule }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["description", "disabled", "justify", "labelPlacement", "mode", "value"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"], outputs: ["ionFocus", "ionBlur"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItemDivider, selector: "ion-item-divider", inputs: ["color", "mode", "sticky"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"], outputs: ["ionFocus", "ionBlur"] }, { kind: "component", type: IonItemGroup, selector: "ion-item-group" }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
156
185
|
}
|
|
157
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
186
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SelectFromListComponent, decorators: [{
|
|
158
187
|
type: Component,
|
|
159
188
|
args: [{ providers: [
|
|
160
189
|
{
|
|
@@ -180,46 +209,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
180
209
|
IonRadio,
|
|
181
210
|
IonItemGroup,
|
|
182
211
|
IonSpinner,
|
|
183
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sneat-select-from-list', template: "@if (value) {\n <ion-item\n [lines]=\"lastItemLines\"\n [class]=\"{ 'sneat-tiny-end-padding': !isReadonly }\"\n >\n @if ($selectedItem()?.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"$selectedItem()?.iconName\"\n [color]=\"\n $selectedItem()?.iconColor || $selectedItem()?.labelColor || 'medium'\n \"\n />\n }\n <ion-select\n #selectInput\n interface=\"popover\"\n [label]=\"label\"\n [(ngModel)]=\"value\"\n (ionChange)=\"onSelectChanged()\"\n [disabled]=\"isReadonly || !!$isProcessing()\"\n >\n @for (item of items; track item.id) {\n <ion-select-option [value]=\"item.id\">\n {{ item.emoji }}\n @if (item.shortTitle) {\n {{ item.shortTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-select-option>\n }\n <!--\t\t<ion-select-option value=\"other\">OTHER</ion-select-option>-->\n </ion-select>\n @if ($isProcessing()) {\n <ion-spinner name=\"lines-small\" color=\"medium\" slot=\"end\" />\n } @else if (!isReadonly) {\n <ion-buttons slot=\"end\" class=\"ion-no-margin\">\n <ion-button color=\"medium\" title=\"Deselect\" (click)=\"deselect()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n} @else {\n @if (isFilterable) {\n <ion-item class=\"sneat-tiny-end-padding\">\n <ion-input\n #filterInput\n color=\"medium\"\n placeholder=\"filter\"\n [label]=\"filterLabel\"\n [value]=\"$filter()\"\n (ionChange)=\"onFilterChanged($event, 'ionChange')\"\n (ionInput)=\"onFilterChanged($event, 'ionInput')\"\n />\n @if ($filter()) {\n <ion-buttons slot=\"end\">\n @if (canAdd && $hiddenCount()) {\n <ion-button\n title=\"Use this\"\n color=\"primary\"\n (click)=\"onAdd($event)\"\n >\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n <ion-button (click)=\"clearFilter()\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n\n @if (items && !items.length) {\n <ion-item-divider>\n <ion-label>No items yet.</ion-label>\n </ion-item-divider>\n }\n\n @if (labelPlacement) {\n <ion-radio-group [(ngModel)]=\"value\" (ionChange)=\"onRadioChanged($event)\">\n <ion-list class=\"ion-no-padding\" lines=\"full\">\n @if (listLabel === \"divider\") {\n <ion-item [color]=\"listLabelColor\">\n <ion-label>{{ label }}</ion-label>\n </ion-item>\n }\n @for (item of $displayItems(); track item.id) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : 'full'\"\n (click)=\"select(item)\"\n tappable=\"true\"\n >\n @switch (selectMode) {\n @case (\"multiple\") {\n <ion-checkbox\n slot=\"start\"\n [value]=\"item.id\"\n [checked]=\"false\"\n [disabled]=\"isDisabled\"\n (ionChange)=\"onCheckboxChange($event, item)\"\n />\n <ion-label>\n <!-- TODO: duplicate code with the next case -->\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-label>\n }\n @case (\"single\") {\n <ion-radio\n [value]=\"item.id\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"\n justify ||\n (!labelPlacement || labelPlacement === 'start'\n ? 'space-between'\n : 'start')\n \"\n >\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-radio>\n }\n }\n </ion-item>\n @if (item.description1) {\n <ion-item-divider>\n <ion-label>\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item-divider>\n }\n }\n </ion-list>\n </ion-radio-group>\n } @else {\n <ion-item-group>\n @for (item of $displayItems(); track item.id; let last = $last) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : last ? lastItemLines : 'full'\"\n button\n (click)=\"select(item)\"\n >\n @if (item.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"item.iconName\"\n [color]=\"item.iconColor || item.labelColor || 'medium'\"\n />\n }\n @if (!labelPlacement) {\n <ion-label [color]=\"item.labelColor\">\n <span class=\"ion-margin-end\">{{ item.emoji }}</span>\n {{ item.title }}\n </ion-label>\n }\n </ion-item>\n @if (item.description1) {\n <ion-item [lines]=\"last ? lastItemLines : 'full'\">\n <ion-label color=\"medium\">\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item>\n }\n }\n </ion-item-group>\n }\n @if ($hiddenCount(); as hiddenCount) {\n <ion-item-divider>\n <ion-label color=\"medium\"\n >{{ hiddenCount }} out of {{ items?.length }} items are hidden by filter\n </ion-label>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"clearFilter()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Clear filter</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n }\n}\n" }]
|
|
212
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'sneat-select-from-list', template: "@if (value) {\n <ion-item\n [lines]=\"lastItemLines()\"\n [class]=\"{ 'sneat-tiny-end-padding': !isReadonly() }\"\n >\n @if ($selectedItem()?.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"$safeNavigationMigration($selectedItem()?.iconName)\"\n [color]=\"\n $selectedItem()?.iconColor || $selectedItem()?.labelColor || 'medium'\n \"\n />\n }\n <ion-select\n #selectInput\n interface=\"popover\"\n [label]=\"label()\"\n [(ngModel)]=\"value\"\n (ionChange)=\"onSelectChanged()\"\n [disabled]=\"isReadonly() || !!$isProcessing()\"\n >\n @for (item of items; track item.id) {\n <ion-select-option [value]=\"item.id\">\n {{ item.emoji }}\n @if (item.shortTitle) {\n {{ item.shortTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-select-option>\n }\n <!--\t\t<ion-select-option value=\"other\">OTHER</ion-select-option>-->\n </ion-select>\n @if ($isProcessing()) {\n <ion-spinner name=\"lines-small\" color=\"medium\" slot=\"end\" />\n } @else if (!isReadonly()) {\n <ion-buttons slot=\"end\" class=\"ion-no-margin\">\n <ion-button color=\"medium\" title=\"Deselect\" (click)=\"deselect()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n} @else {\n @if (isFilterable()) {\n <ion-item class=\"sneat-tiny-end-padding\">\n <ion-input\n #filterInput\n color=\"medium\"\n placeholder=\"filter\"\n [label]=\"filterLabel()\"\n [value]=\"$filter()\"\n (ionChange)=\"onFilterChanged($event, 'ionChange')\"\n (ionInput)=\"onFilterChanged($event, 'ionInput')\"\n />\n @if ($filter()) {\n <ion-buttons slot=\"end\">\n @if (canAdd() && $hiddenCount()) {\n <ion-button\n title=\"Use this\"\n color=\"primary\"\n (click)=\"onAdd($event)\"\n >\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n <ion-button (click)=\"clearFilter()\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n\n @if (items && !items.length) {\n <ion-item-divider>\n <ion-label>No items yet.</ion-label>\n </ion-item-divider>\n }\n\n @if (labelPlacement) {\n <ion-radio-group [(ngModel)]=\"value\" (ionChange)=\"onRadioChanged($event)\">\n <ion-list class=\"ion-no-padding\" lines=\"full\">\n @if (listLabel() === \"divider\") {\n <ion-item [color]=\"listLabelColor()\">\n <ion-label>{{ label() }}</ion-label>\n </ion-item>\n }\n @for (item of $displayItems(); track item.id) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : 'full'\"\n (click)=\"select(item)\"\n tappable=\"true\"\n >\n @switch (selectMode) {\n @case (\"multiple\") {\n <ion-checkbox\n slot=\"start\"\n [value]=\"item.id\"\n [checked]=\"false\"\n [disabled]=\"isDisabled\"\n (ionChange)=\"onCheckboxChange($event, item)\"\n />\n <ion-label>\n <!-- TODO: duplicate code with the next case -->\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-label>\n }\n @case (\"single\") {\n <ion-radio\n [value]=\"item.id\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"\n justify() ||\n (!labelPlacement || labelPlacement === 'start'\n ? 'space-between'\n : 'start')\n \"\n >\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-radio>\n }\n }\n </ion-item>\n @if (item.description1) {\n <ion-item-divider>\n <ion-label>\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item-divider>\n }\n }\n </ion-list>\n </ion-radio-group>\n } @else {\n <ion-item-group>\n @for (item of $displayItems(); track item.id; let last = $last) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : last ? lastItemLines() : 'full'\"\n button\n (click)=\"select(item)\"\n >\n @if (item.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"item.iconName\"\n [color]=\"item.iconColor || item.labelColor || 'medium'\"\n />\n }\n @if (!labelPlacement) {\n <ion-label [color]=\"item.labelColor\">\n <span class=\"ion-margin-end\">{{ item.emoji }}</span>\n {{ item.title }}\n </ion-label>\n }\n </ion-item>\n @if (item.description1) {\n <ion-item [lines]=\"last ? lastItemLines() : 'full'\">\n <ion-label color=\"medium\">\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item>\n }\n }\n </ion-item-group>\n }\n @if ($hiddenCount(); as hiddenCount) {\n <ion-item-divider>\n <ion-label color=\"medium\"\n >{{ hiddenCount }} out of {{ items?.length }} items are hidden by filter\n </ion-label>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"clearFilter()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Clear filter</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n }\n}\n" }]
|
|
184
213
|
}], propDecorators: { value: [{
|
|
185
214
|
type: Input
|
|
186
215
|
}], valueChange: [{
|
|
187
216
|
type: Output
|
|
188
|
-
}], filterLabel: [{
|
|
189
|
-
type: Input
|
|
190
|
-
}], label: [{
|
|
191
|
-
type: Input
|
|
192
|
-
}], listLabel: [{
|
|
193
|
-
type: Input
|
|
194
|
-
}], listLabelColor: [{
|
|
195
|
-
type: Input
|
|
196
|
-
}], isFilterable: [{
|
|
197
|
-
type: Input
|
|
198
|
-
}], isLoading: [{
|
|
199
|
-
type: Input
|
|
200
|
-
}], items: [{
|
|
217
|
+
}], filterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLabel", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], listLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "listLabel", required: false }] }], listLabelColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "listLabelColor", required: false }] }], isFilterable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFilterable", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], items: [{
|
|
201
218
|
type: Input
|
|
202
219
|
}], items$: [{
|
|
203
220
|
type: Input
|
|
204
|
-
}], lastItemLines: [{
|
|
221
|
+
}], lastItemLines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastItemLines", required: false }] }], labelPlacement: [{
|
|
205
222
|
type: Input
|
|
206
|
-
}],
|
|
207
|
-
type: Input
|
|
208
|
-
}], justify: [{
|
|
209
|
-
type: Input
|
|
210
|
-
}], other: [{
|
|
211
|
-
type: Input
|
|
212
|
-
}], canAdd: [{
|
|
213
|
-
type: Input
|
|
214
|
-
}], filterItem: [{
|
|
223
|
+
}], justify: [{ type: i0.Input, args: [{ isSignal: true, alias: "justify", required: false }] }], other: [{ type: i0.Input, args: [{ isSignal: true, alias: "other", required: false }] }], canAdd: [{ type: i0.Input, args: [{ isSignal: true, alias: "canAdd", required: false }] }], filterItem: [{
|
|
215
224
|
type: Input
|
|
216
225
|
}], filterChanged: [{
|
|
217
226
|
type: Output
|
|
218
227
|
}], selectMode: [{
|
|
219
228
|
type: Input
|
|
220
|
-
}], isReadonly: [{
|
|
221
|
-
type: Input
|
|
222
|
-
}], $isProcessing: [{ type: i0.Input, args: [{ isSignal: true, alias: "$isProcessing", required: false }] }], sortBy: [{
|
|
229
|
+
}], isReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "isReadonly", required: false }] }], $isProcessing: [{ type: i0.Input, args: [{ isSignal: true, alias: "$isProcessing", required: false }] }], sortBy: [{
|
|
223
230
|
type: Input
|
|
224
231
|
}], addInput: [{
|
|
225
232
|
type: ViewChild,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select-from-list.component.js","sourceRoot":"","sources":["../../../../../../../libs/ui/src/lib/selector/select-from-list/select-from-list.component.ts","../../../../../../../libs/ui/src/lib/selector/select-from-list/select-from-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n EventEmitter,\n forwardRef,\n input,\n Input,\n OnChanges,\n OnDestroy,\n Output,\n signal,\n SimpleChanges,\n ViewChild,\n inject,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormsModule,\n NG_VALUE_ACCESSOR,\n} from '@angular/forms';\nimport { RouterModule } from '@angular/router';\nimport {\n IonButton,\n IonButtons,\n IonCheckbox,\n IonIcon,\n IonInput,\n IonItem,\n IonItemDivider,\n IonItemGroup,\n IonLabel,\n IonList,\n IonRadio,\n IonRadioGroup,\n IonSelect,\n IonSelectOption,\n IonSpinner,\n} from '@ionic/angular/standalone';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport { NEVER, Observable, Subject, takeUntil } from 'rxjs';\nimport { ISelectItem } from '../selector-interfaces';\n\n@Component({\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SelectFromListComponent),\n multi: true,\n },\n ],\n imports: [\n FormsModule,\n RouterModule,\n IonItem,\n IonIcon,\n IonSelect,\n IonSelectOption,\n IonButtons,\n IonButton,\n IonInput,\n IonItemDivider,\n IonRadioGroup,\n IonList,\n IonLabel,\n IonCheckbox,\n IonRadio,\n IonItemGroup,\n IonSpinner,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'sneat-select-from-list',\n templateUrl: './select-from-list.component.html',\n})\nexport class SelectFromListComponent\n implements ControlValueAccessor, OnChanges, OnDestroy\n{\n private readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n\n @Input() value: string | undefined = '';\n @Output() readonly valueChange = new EventEmitter<string>();\n\n @Input() filterLabel = 'Find';\n @Input() label = 'Please choose';\n @Input() listLabel?: 'divider';\n @Input() listLabelColor?:\n | 'light'\n | 'medium'\n | 'primary'\n | 'secondary'\n | 'tertiary';\n @Input() isFilterable?: boolean;\n @Input() isLoading?: boolean;\n @Input() items?: readonly ISelectItem[];\n @Input() items$: Observable<ISelectItem[]> = NEVER;\n\n private $items = signal<undefined | readonly ISelectItem[]>(undefined);\n\n @Input() lastItemLines?: 'none' | 'inset' | 'full';\n @Input() labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';\n @Input() justify?: 'start' | 'end' | 'space-between';\n @Input() other: 'top' | 'bottom' | 'none' = 'none';\n @Input() canAdd = false;\n @Input() filterItem?: (item: ISelectItem, filter: string) => boolean;\n\n @Output() readonly filterChanged = new EventEmitter<string>();\n\n @Input() selectMode: 'single' | 'multiple' = 'single';\n\n @Input() isReadonly = false;\n\n public $isProcessing = input<boolean>();\n\n @Input() sortBy?: 'title' | 'id';\n\n // @Input() ngModel?: string;\n // @Output() readonly ngModelChange = new EventEmitter<string>();\n\n private destroyed = new Subject<void>();\n\n @ViewChild(IonInput, { static: false }) addInput?: IonInput;\n @ViewChild('filterInput', { static: false }) filterInput?: IonInput;\n @ViewChild('selectInput', { static: false }) selectInput?: IonSelect;\n\n protected readonly $displayItems = signal<undefined | readonly ISelectItem[]>(\n undefined,\n );\n\n protected readonly $hiddenCount = computed(() => {\n return (this.$items()?.length || 0) - (this.$displayItems()?.length || 0);\n });\n\n protected isDisabled = false;\n\n protected readonly $filter = signal('');\n\n public focus(): void {\n setTimeout(() => {\n this.filterInput\n ?.setFocus()\n .catch(\n this.errorLogger.logErrorHandler(\n 'Failed to set focus to filter input',\n ),\n );\n }, 100);\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['items']) {\n this.$items.set(this.items);\n this.applyFilter();\n }\n if (changes['items$'] && this.items$) {\n this.items$?.pipe(takeUntil(this.destroyed)).subscribe((items) => {\n this.$items.set(items);\n this.applyFilter();\n });\n }\n }\n\n private applyFilter(): void {\n const f = this.$filter().trim().toLowerCase();\n // console.log('SelectFromListComponent.applyFilter', f);\n const items = this.$items();\n let displayItems = f\n ? items?.filter(\n (v) =>\n v.title.toLowerCase().includes(f) ||\n v.longTitle?.toLowerCase().includes(f) ||\n (this.filterItem && this.filterItem(v, f)),\n )\n : items;\n if (displayItems && this.sortBy) {\n switch (this.sortBy) {\n case 'title':\n displayItems = [...displayItems].toSorted((a, b) =>\n a.title.localeCompare(b.title),\n );\n break;\n case 'id':\n displayItems = [...displayItems].toSorted((a, b) =>\n a.id.localeCompare(b.id),\n );\n break;\n }\n }\n this.$displayItems.set(displayItems);\n }\n\n protected select(item: ISelectItem): void {\n switch (this.selectMode) {\n case 'multiple':\n return;\n case 'single':\n this.$selectedItem.set(item);\n this.onChange(item.id);\n if (this.$filter()) {\n this.clearFilter();\n }\n }\n }\n\n protected readonly $selectedItem = signal<ISelectItem | undefined>(undefined);\n\n protected onRadioChanged(event: Event): void {\n if (this.selectMode !== 'single') {\n return;\n }\n const value = (event as CustomEvent).detail['value'] as string;\n this.value = value;\n this.onChange(value);\n this.clearFilter();\n }\n\n protected onSelectChanged(): void {\n // this.value = (event as CustomEvent).detail['value'] as string;\n this.onChange(this.value || '');\n }\n\n protected onChange = (id: string) => {\n this.value = id;\n if (this.$selectedItem()?.id !== id) {\n const selectedItem = this.items?.find((item) => item.id === id);\n this.$selectedItem.set(selectedItem);\n }\n this.valueChange.emit(this.value);\n };\n\n onTouched: () => void = () => void 0;\n\n registerOnChange(fn: (v: unknown) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.isDisabled = isDisabled;\n }\n\n writeValue(obj: unknown): void {\n this.value = obj as string;\n }\n\n protected onFilterChanged(\n event: CustomEvent,\n source: 'ionChange' | 'ionInput',\n ): void {\n void source;\n this.$filter.set(event.detail.value || '');\n this.applyFilter();\n this.filterChanged.emit(this.$filter());\n }\n\n protected clearFilter(): void {\n this.$filter.set('');\n this.filterChanged.emit(this.$filter());\n this.applyFilter();\n }\n\n protected deselect(): void {\n this.value = '';\n this.onChange(this.value);\n }\n\n protected onAdd(event: Event): void {\n event.preventDefault();\n this.value = this.$filter();\n this.onChange(this.value);\n }\n\n protected onCheckboxChange(event: CustomEvent, item: ISelectItem): void {\n void event;\n void item;\n }\n\n ngOnDestroy(): void {\n this.destroyed.next();\n }\n}\n","@if (value) {\n <ion-item\n [lines]=\"lastItemLines\"\n [class]=\"{ 'sneat-tiny-end-padding': !isReadonly }\"\n >\n @if ($selectedItem()?.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"$selectedItem()?.iconName\"\n [color]=\"\n $selectedItem()?.iconColor || $selectedItem()?.labelColor || 'medium'\n \"\n />\n }\n <ion-select\n #selectInput\n interface=\"popover\"\n [label]=\"label\"\n [(ngModel)]=\"value\"\n (ionChange)=\"onSelectChanged()\"\n [disabled]=\"isReadonly || !!$isProcessing()\"\n >\n @for (item of items; track item.id) {\n <ion-select-option [value]=\"item.id\">\n {{ item.emoji }}\n @if (item.shortTitle) {\n {{ item.shortTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-select-option>\n }\n <!--\t\t<ion-select-option value=\"other\">OTHER</ion-select-option>-->\n </ion-select>\n @if ($isProcessing()) {\n <ion-spinner name=\"lines-small\" color=\"medium\" slot=\"end\" />\n } @else if (!isReadonly) {\n <ion-buttons slot=\"end\" class=\"ion-no-margin\">\n <ion-button color=\"medium\" title=\"Deselect\" (click)=\"deselect()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n} @else {\n @if (isFilterable) {\n <ion-item class=\"sneat-tiny-end-padding\">\n <ion-input\n #filterInput\n color=\"medium\"\n placeholder=\"filter\"\n [label]=\"filterLabel\"\n [value]=\"$filter()\"\n (ionChange)=\"onFilterChanged($event, 'ionChange')\"\n (ionInput)=\"onFilterChanged($event, 'ionInput')\"\n />\n @if ($filter()) {\n <ion-buttons slot=\"end\">\n @if (canAdd && $hiddenCount()) {\n <ion-button\n title=\"Use this\"\n color=\"primary\"\n (click)=\"onAdd($event)\"\n >\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n <ion-button (click)=\"clearFilter()\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n\n @if (items && !items.length) {\n <ion-item-divider>\n <ion-label>No items yet.</ion-label>\n </ion-item-divider>\n }\n\n @if (labelPlacement) {\n <ion-radio-group [(ngModel)]=\"value\" (ionChange)=\"onRadioChanged($event)\">\n <ion-list class=\"ion-no-padding\" lines=\"full\">\n @if (listLabel === \"divider\") {\n <ion-item [color]=\"listLabelColor\">\n <ion-label>{{ label }}</ion-label>\n </ion-item>\n }\n @for (item of $displayItems(); track item.id) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : 'full'\"\n (click)=\"select(item)\"\n tappable=\"true\"\n >\n @switch (selectMode) {\n @case (\"multiple\") {\n <ion-checkbox\n slot=\"start\"\n [value]=\"item.id\"\n [checked]=\"false\"\n [disabled]=\"isDisabled\"\n (ionChange)=\"onCheckboxChange($event, item)\"\n />\n <ion-label>\n <!-- TODO: duplicate code with the next case -->\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-label>\n }\n @case (\"single\") {\n <ion-radio\n [value]=\"item.id\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"\n justify ||\n (!labelPlacement || labelPlacement === 'start'\n ? 'space-between'\n : 'start')\n \"\n >\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-radio>\n }\n }\n </ion-item>\n @if (item.description1) {\n <ion-item-divider>\n <ion-label>\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item-divider>\n }\n }\n </ion-list>\n </ion-radio-group>\n } @else {\n <ion-item-group>\n @for (item of $displayItems(); track item.id; let last = $last) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : last ? lastItemLines : 'full'\"\n button\n (click)=\"select(item)\"\n >\n @if (item.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"item.iconName\"\n [color]=\"item.iconColor || item.labelColor || 'medium'\"\n />\n }\n @if (!labelPlacement) {\n <ion-label [color]=\"item.labelColor\">\n <span class=\"ion-margin-end\">{{ item.emoji }}</span>\n {{ item.title }}\n </ion-label>\n }\n </ion-item>\n @if (item.description1) {\n <ion-item [lines]=\"last ? lastItemLines : 'full'\">\n <ion-label color=\"medium\">\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item>\n }\n }\n </ion-item-group>\n }\n @if ($hiddenCount(); as hiddenCount) {\n <ion-item-divider>\n <ion-label color=\"medium\"\n >{{ hiddenCount }} out of {{ items?.length }} items are hidden by filter\n </ion-label>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"clearFilter()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Clear filter</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"select-from-list.component.js","sourceRoot":"","sources":["../../../../../../../libs/ui/src/lib/selector/select-from-list/select-from-list.component.ts","../../../../../../../libs/ui/src/lib/selector/select-from-list/select-from-list.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n EventEmitter,\n forwardRef,\n input,\n Input,\n OnChanges,\n OnDestroy,\n Output,\n signal,\n SimpleChanges,\n ViewChild,\n inject,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormsModule,\n NG_VALUE_ACCESSOR,\n} from '@angular/forms';\nimport { RouterModule } from '@angular/router';\nimport {\n IonButton,\n IonButtons,\n IonCheckbox,\n IonIcon,\n IonInput,\n IonItem,\n IonItemDivider,\n IonItemGroup,\n IonLabel,\n IonList,\n IonRadio,\n IonRadioGroup,\n IonSelect,\n IonSelectOption,\n IonSpinner,\n} from '@ionic/angular';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport { NEVER, Observable, Subject, takeUntil } from 'rxjs';\nimport { ISelectItem } from '../selector-interfaces';\n\n@Component({\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SelectFromListComponent),\n multi: true,\n },\n ],\n imports: [\n FormsModule,\n RouterModule,\n IonItem,\n IonIcon,\n IonSelect,\n IonSelectOption,\n IonButtons,\n IonButton,\n IonInput,\n IonItemDivider,\n IonRadioGroup,\n IonList,\n IonLabel,\n IonCheckbox,\n IonRadio,\n IonItemGroup,\n IonSpinner,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'sneat-select-from-list',\n templateUrl: './select-from-list.component.html',\n})\nexport class SelectFromListComponent\n implements ControlValueAccessor, OnChanges, OnDestroy\n{\n private readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() value: string | undefined = '';\n @Output() readonly valueChange = new EventEmitter<string>();\n\n readonly filterLabel = input('Find');\n readonly label = input('Please choose');\n readonly listLabel = input<'divider'>();\n readonly listLabelColor = input<'light' | 'medium' | 'primary' | 'secondary' | 'tertiary'>();\n readonly isFilterable = input<boolean>();\n readonly isLoading = input<boolean>();\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() items?: readonly ISelectItem[];\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() items$: Observable<ISelectItem[]> = NEVER;\n\n private $items = signal<undefined | readonly ISelectItem[]>(undefined);\n\n readonly lastItemLines = input<'none' | 'inset' | 'full'>();\n // TODO: Skipped for migration because:\n // This input is used in a control flow expression (e.g. `@if` or `*ngIf`)\n // and migrating would break narrowing currently.\n @Input() labelPlacement?: 'start' | 'end' | 'fixed' | 'stacked';\n readonly justify = input<'start' | 'end' | 'space-between'>();\n readonly other = input<'top' | 'bottom' | 'none'>('none');\n readonly canAdd = input(false);\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() filterItem?: (item: ISelectItem, filter: string) => boolean;\n\n @Output() readonly filterChanged = new EventEmitter<string>();\n\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() selectMode: 'single' | 'multiple' = 'single';\n\n readonly isReadonly = input(false);\n\n public $isProcessing = input<boolean>();\n\n // TODO: Skipped for migration because:\n // Your application code writes to the input. This prevents migration.\n @Input() sortBy?: 'title' | 'id';\n\n // @Input() ngModel?: string;\n // @Output() readonly ngModelChange = new EventEmitter<string>();\n\n private destroyed = new Subject<void>();\n\n @ViewChild(IonInput, { static: false }) addInput?: IonInput;\n @ViewChild('filterInput', { static: false }) filterInput?: IonInput;\n @ViewChild('selectInput', { static: false }) selectInput?: IonSelect;\n\n protected readonly $displayItems = signal<undefined | readonly ISelectItem[]>(\n undefined,\n );\n\n protected readonly $hiddenCount = computed(() => {\n return (this.$items()?.length || 0) - (this.$displayItems()?.length || 0);\n });\n\n protected isDisabled = false;\n\n protected readonly $filter = signal('');\n\n public focus(): void {\n setTimeout(() => {\n this.filterInput\n ?.setFocus()\n .catch(\n this.errorLogger.logErrorHandler(\n 'Failed to set focus to filter input',\n ),\n );\n }, 100);\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['items']) {\n this.$items.set(this.items);\n this.applyFilter();\n }\n if (changes['items$'] && this.items$) {\n this.items$?.pipe(takeUntil(this.destroyed)).subscribe((items) => {\n this.$items.set(items);\n this.applyFilter();\n });\n }\n }\n\n private applyFilter(): void {\n const f = this.$filter().trim().toLowerCase();\n // console.log('SelectFromListComponent.applyFilter', f);\n const items = this.$items();\n let displayItems = f\n ? items?.filter(\n (v) =>\n v.title.toLowerCase().includes(f) ||\n v.longTitle?.toLowerCase().includes(f) ||\n (this.filterItem && this.filterItem(v, f)),\n )\n : items;\n if (displayItems && this.sortBy) {\n switch (this.sortBy) {\n case 'title':\n displayItems = [...displayItems].toSorted((a, b) =>\n a.title.localeCompare(b.title),\n );\n break;\n case 'id':\n displayItems = [...displayItems].toSorted((a, b) =>\n a.id.localeCompare(b.id),\n );\n break;\n }\n }\n this.$displayItems.set(displayItems);\n }\n\n protected select(item: ISelectItem): void {\n switch (this.selectMode) {\n case 'multiple':\n return;\n case 'single':\n this.$selectedItem.set(item);\n this.onChange(item.id);\n if (this.$filter()) {\n this.clearFilter();\n }\n }\n }\n\n protected readonly $selectedItem = signal<ISelectItem | undefined>(undefined);\n\n protected onRadioChanged(event: Event): void {\n if (this.selectMode !== 'single') {\n return;\n }\n const value = (event as CustomEvent).detail['value'] as string;\n this.value = value;\n this.onChange(value);\n this.clearFilter();\n }\n\n protected onSelectChanged(): void {\n // this.value = (event as CustomEvent).detail['value'] as string;\n this.onChange(this.value || '');\n }\n\n protected onChange = (id: string) => {\n this.value = id;\n if (this.$selectedItem()?.id !== id) {\n const selectedItem = this.items?.find((item) => item.id === id);\n this.$selectedItem.set(selectedItem);\n }\n this.valueChange.emit(this.value);\n };\n\n onTouched: () => void = () => void 0;\n\n registerOnChange(fn: (v: unknown) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.isDisabled = isDisabled;\n }\n\n writeValue(obj: unknown): void {\n this.value = obj as string;\n }\n\n protected onFilterChanged(\n event: CustomEvent,\n source: 'ionChange' | 'ionInput',\n ): void {\n void source;\n this.$filter.set(event.detail.value || '');\n this.applyFilter();\n this.filterChanged.emit(this.$filter());\n }\n\n protected clearFilter(): void {\n this.$filter.set('');\n this.filterChanged.emit(this.$filter());\n this.applyFilter();\n }\n\n protected deselect(): void {\n this.value = '';\n this.onChange(this.value);\n }\n\n protected onAdd(event: Event): void {\n event.preventDefault();\n this.value = this.$filter();\n this.onChange(this.value);\n }\n\n protected onCheckboxChange(event: CustomEvent, item: ISelectItem): void {\n void event;\n void item;\n }\n\n ngOnDestroy(): void {\n this.destroyed.next();\n }\n}\n","@if (value) {\n <ion-item\n [lines]=\"lastItemLines()\"\n [class]=\"{ 'sneat-tiny-end-padding': !isReadonly() }\"\n >\n @if ($selectedItem()?.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"$safeNavigationMigration($selectedItem()?.iconName)\"\n [color]=\"\n $selectedItem()?.iconColor || $selectedItem()?.labelColor || 'medium'\n \"\n />\n }\n <ion-select\n #selectInput\n interface=\"popover\"\n [label]=\"label()\"\n [(ngModel)]=\"value\"\n (ionChange)=\"onSelectChanged()\"\n [disabled]=\"isReadonly() || !!$isProcessing()\"\n >\n @for (item of items; track item.id) {\n <ion-select-option [value]=\"item.id\">\n {{ item.emoji }}\n @if (item.shortTitle) {\n {{ item.shortTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-select-option>\n }\n <!--\t\t<ion-select-option value=\"other\">OTHER</ion-select-option>-->\n </ion-select>\n @if ($isProcessing()) {\n <ion-spinner name=\"lines-small\" color=\"medium\" slot=\"end\" />\n } @else if (!isReadonly()) {\n <ion-buttons slot=\"end\" class=\"ion-no-margin\">\n <ion-button color=\"medium\" title=\"Deselect\" (click)=\"deselect()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n} @else {\n @if (isFilterable()) {\n <ion-item class=\"sneat-tiny-end-padding\">\n <ion-input\n #filterInput\n color=\"medium\"\n placeholder=\"filter\"\n [label]=\"filterLabel()\"\n [value]=\"$filter()\"\n (ionChange)=\"onFilterChanged($event, 'ionChange')\"\n (ionInput)=\"onFilterChanged($event, 'ionInput')\"\n />\n @if ($filter()) {\n <ion-buttons slot=\"end\">\n @if (canAdd() && $hiddenCount()) {\n <ion-button\n title=\"Use this\"\n color=\"primary\"\n (click)=\"onAdd($event)\"\n >\n <ion-icon name=\"add-outline\" />\n <ion-label>Add</ion-label>\n </ion-button>\n }\n <ion-button (click)=\"clearFilter()\" title=\"Clear filter\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n }\n\n @if (items && !items.length) {\n <ion-item-divider>\n <ion-label>No items yet.</ion-label>\n </ion-item-divider>\n }\n\n @if (labelPlacement) {\n <ion-radio-group [(ngModel)]=\"value\" (ionChange)=\"onRadioChanged($event)\">\n <ion-list class=\"ion-no-padding\" lines=\"full\">\n @if (listLabel() === \"divider\") {\n <ion-item [color]=\"listLabelColor()\">\n <ion-label>{{ label() }}</ion-label>\n </ion-item>\n }\n @for (item of $displayItems(); track item.id) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : 'full'\"\n (click)=\"select(item)\"\n tappable=\"true\"\n >\n @switch (selectMode) {\n @case (\"multiple\") {\n <ion-checkbox\n slot=\"start\"\n [value]=\"item.id\"\n [checked]=\"false\"\n [disabled]=\"isDisabled\"\n (ionChange)=\"onCheckboxChange($event, item)\"\n />\n <ion-label>\n <!-- TODO: duplicate code with the next case -->\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-label>\n }\n @case (\"single\") {\n <ion-radio\n [value]=\"item.id\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"\n justify() ||\n (!labelPlacement || labelPlacement === 'start'\n ? 'space-between'\n : 'start')\n \"\n >\n {{ item.emoji }}\n @if (item.shortTitle) {\n @if (item.longTitle) {\n {{ item.longTitle }} - {{ item.shortTitle }}\n } @else {\n {{ item.title }} - {{ item.shortTitle }}\n }\n } @else if (item.longTitle) {\n {{ item.longTitle }}\n } @else {\n {{ item.title }}\n }\n </ion-radio>\n }\n }\n </ion-item>\n @if (item.description1) {\n <ion-item-divider>\n <ion-label>\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item-divider>\n }\n }\n </ion-list>\n </ion-radio-group>\n } @else {\n <ion-item-group>\n @for (item of $displayItems(); track item.id; let last = $last) {\n <ion-item\n [lines]=\"item.description1 ? 'inset' : last ? lastItemLines() : 'full'\"\n button\n (click)=\"select(item)\"\n >\n @if (item.iconName) {\n <ion-icon\n slot=\"start\"\n [name]=\"item.iconName\"\n [color]=\"item.iconColor || item.labelColor || 'medium'\"\n />\n }\n @if (!labelPlacement) {\n <ion-label [color]=\"item.labelColor\">\n <span class=\"ion-margin-end\">{{ item.emoji }}</span>\n {{ item.title }}\n </ion-label>\n }\n </ion-item>\n @if (item.description1) {\n <ion-item [lines]=\"last ? lastItemLines() : 'full'\">\n <ion-label color=\"medium\">\n {{ item.description1 }}\n @if (item.description2) {\n <i>{{ item.description2 }}</i>\n }\n </ion-label>\n </ion-item>\n }\n }\n </ion-item-group>\n }\n @if ($hiddenCount(); as hiddenCount) {\n <ion-item-divider>\n <ion-label color=\"medium\"\n >{{ hiddenCount }} out of {{ items?.length }} items are hidden by filter\n </ion-label>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"clearFilter()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Clear filter</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n }\n}\n"]}
|