@seniorsistemas/angular-components 19.9.3 → 19.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/autocomplete/README.md +4 -0
- package/autocomplete/lib/autocomplete/autocomplete.component.d.ts +7 -1
- package/autocomplete/lib/autocomplete/components/autocomplete-chip/autocomplete-chip.component.d.ts +3 -1
- package/checkbox/lib/checkbox/checkbox.component.d.ts +1 -6
- package/checkbox-list/lib/checkbox-list/checkbox-list.component.d.ts +8 -0
- package/content-generator/lib/content-generator/content-generator.component.d.ts +2 -2
- package/country-phone-picker/lib/country-phone-picker/country-phone-picker.component.d.ts +2 -0
- package/drawer/README.md +9 -2
- package/drawer/lib/drawer/drawer.component.d.ts +12 -1
- package/editor/lib/editor/editor.component.d.ts +1 -1
- package/esm2022/autocomplete/lib/autocomplete/autocomplete.component.mjs +10 -4
- package/esm2022/autocomplete/lib/autocomplete/components/autocomplete-chip/autocomplete-chip.component.mjs +5 -3
- package/esm2022/button/lib/button/button.component.mjs +3 -3
- package/esm2022/checkbox/lib/checkbox/checkbox.component.mjs +3 -9
- package/esm2022/checkbox-list/lib/checkbox-list/checkbox-list.component.mjs +17 -5
- package/esm2022/content-generator/lib/content-generator/content-generator.component.mjs +9 -8
- package/esm2022/country-phone-picker/lib/country-phone-picker/country-phone-picker.component.mjs +18 -3
- package/esm2022/drawer/lib/drawer/drawer.component.mjs +33 -11
- package/esm2022/drawer/lib/drawer/drawer.module.mjs +2 -2
- package/esm2022/dynamic-form/dynamic-form/components/lookup/lookup.component.mjs +3 -3
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/bignumber/bignumber-field.component.mjs +3 -3
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/boolean/boolean-switch-field/boolean-switch-field.component.mjs +3 -3
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/checkbox/checkbox-field.component.mjs +4 -3
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/currency/currency-field.component.mjs +3 -3
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/number/number-field.component.mjs +3 -3
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/password/password-field.component.mjs +3 -3
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/select/select-field.component.mjs +2 -2
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/text/text-field.component.mjs +3 -3
- package/esm2022/editor/lib/editor/editor.component.mjs +8 -8
- package/esm2022/file-picker/lib/file-picker/file-picker.component.mjs +4 -4
- package/esm2022/global-search/lib/global-search/components/dropdown/global-search-dropdown-item.component.mjs +4 -4
- package/esm2022/global-search/lib/global-search/global-search.module.mjs +2 -2
- package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-number/inline-edit-number.component.mjs +3 -3
- package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-text/inline-edit-text.component.mjs +2 -3
- package/esm2022/insights/lib/insights/components/insights-card/insights-card.component.mjs +21 -3
- package/esm2022/insights/lib/insights/components/insights-sidebar/insights-sidebar.component.mjs +14 -3
- package/esm2022/insights/lib/insights/insights.component.mjs +15 -4
- package/esm2022/paginator/lib/models/paginator.models.mjs +1 -1
- package/esm2022/paginator/lib/paginator/paginator.component.mjs +19 -13
- package/esm2022/profile-picture-picker/lib/profile-picture-picker/profile-picture-picker.component.mjs +19 -8
- package/esm2022/profile-picture-picker/lib/profile-picture-picker/profile-picture-picker.module.mjs +3 -4
- package/esm2022/rating-scale/lib/rating-scale/models/rating-scale-node.mjs +1 -1
- package/esm2022/rating-scale/lib/rating-scale/rating-scale.component.mjs +23 -3
- package/esm2022/select/lib/select/components/select-option/select-option.component.mjs +5 -3
- package/esm2022/select/lib/select/select.component.mjs +6 -4
- package/esm2022/side-sheet/lib/side-sheet/side-sheet.component.mjs +6 -5
- package/esm2022/slider/lib/slider/slider.component.mjs +3 -3
- package/esm2022/speech-recognition/lib/speech-recognition/speech-recognition/speech-recognition.component.mjs +58 -8
- package/esm2022/split-button/lib/split-button/split-button.component.mjs +11 -3
- package/esm2022/star-rating/star-rating/star-rating.component.mjs +3 -3
- package/esm2022/table/lib/table/table-column/table-columns.component.mjs +1 -1
- package/esm2022/table-header/lib/table-header/table-header-checkbox.component.mjs +14 -21
- package/esm2022/text-area/lib/text-area/text-area.component.mjs +3 -3
- package/esm2022/token-list/lib/token-list/token-list.component.mjs +7 -3
- package/esm2022/tooltip/lib/tooltip/tooltip.directive.mjs +3 -2
- package/esm2022/utils/lib/utils/utils.mjs +49 -3
- package/fesm2022/seniorsistemas-angular-components-autocomplete.mjs +13 -5
- package/fesm2022/seniorsistemas-angular-components-autocomplete.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-button.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-button.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-checkbox-list.mjs +16 -4
- package/fesm2022/seniorsistemas-angular-components-checkbox-list.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-checkbox.mjs +2 -8
- package/fesm2022/seniorsistemas-angular-components-checkbox.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-content-generator.mjs +8 -6
- package/fesm2022/seniorsistemas-angular-components-content-generator.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-country-phone-picker.mjs +17 -2
- package/fesm2022/seniorsistemas-angular-components-country-phone-picker.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-drawer.mjs +32 -9
- package/fesm2022/seniorsistemas-angular-components-drawer.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +17 -17
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-editor.mjs +7 -7
- package/fesm2022/seniorsistemas-angular-components-editor.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-file-picker.mjs +3 -3
- package/fesm2022/seniorsistemas-angular-components-file-picker.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-global-search.mjs +3 -3
- package/fesm2022/seniorsistemas-angular-components-global-search.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs +3 -4
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-insights.mjs +47 -7
- package/fesm2022/seniorsistemas-angular-components-insights.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-paginator.mjs +18 -12
- package/fesm2022/seniorsistemas-angular-components-paginator.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs +20 -9
- package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-rating-scale.mjs +22 -2
- package/fesm2022/seniorsistemas-angular-components-rating-scale.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-select.mjs +9 -5
- package/fesm2022/seniorsistemas-angular-components-select.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-side-sheet.mjs +5 -4
- package/fesm2022/seniorsistemas-angular-components-side-sheet.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-slider.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-slider.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-speech-recognition.mjs +57 -7
- package/fesm2022/seniorsistemas-angular-components-speech-recognition.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-split-button.mjs +10 -2
- package/fesm2022/seniorsistemas-angular-components-split-button.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-star-rating.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-star-rating.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-table-header.mjs +13 -20
- package/fesm2022/seniorsistemas-angular-components-table-header.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-table.mjs +1 -1
- package/fesm2022/seniorsistemas-angular-components-table.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-text-area.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-text-area.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-token-list.mjs +6 -2
- package/fesm2022/seniorsistemas-angular-components-token-list.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-tooltip.mjs +2 -1
- package/fesm2022/seniorsistemas-angular-components-tooltip.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-utils.mjs +49 -3
- package/fesm2022/seniorsistemas-angular-components-utils.mjs.map +1 -1
- package/global-search/lib/global-search/global-search.module.d.ts +1 -1
- package/insights/README.md +12 -0
- package/insights/lib/insights/components/insights-card/insights-card.component.d.ts +22 -1
- package/insights/lib/insights/components/insights-sidebar/insights-sidebar.component.d.ts +9 -1
- package/insights/lib/insights/insights.component.d.ts +9 -1
- package/package.json +1 -3
- package/paginator/lib/models/paginator.models.d.ts +1 -0
- package/paginator/lib/paginator/paginator.component.d.ts +3 -1
- package/profile-picture-picker/lib/profile-picture-picker/profile-picture-picker.component.d.ts +3 -1
- package/rating-scale/README.md +38 -13
- package/rating-scale/lib/rating-scale/models/rating-scale-node.d.ts +8 -0
- package/rating-scale/lib/rating-scale/rating-scale.component.d.ts +4 -1
- package/select/README.md +2 -0
- package/select/lib/select/components/select-option/select-option.component.d.ts +3 -1
- package/select/lib/select/select.component.d.ts +3 -1
- package/side-sheet/README.md +4 -4
- package/side-sheet/lib/side-sheet/side-sheet.component.d.ts +1 -0
- package/speech-recognition/README.md +1 -0
- package/speech-recognition/lib/speech-recognition/speech-recognition/speech-recognition.component.d.ts +4 -1
- package/split-button/README.md +2 -0
- package/split-button/lib/split-button/split-button.component.d.ts +5 -1
- package/table-header/lib/table-header/table-header-checkbox.component.d.ts +1 -4
- package/token-list/lib/token-list/token-list.component.d.ts +3 -1
- package/utils/lib/utils/utils.d.ts +21 -0
|
@@ -2,10 +2,9 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { inject, EventEmitter, forwardRef, ElementRef, Component, Input, ViewChild, Output, HostListener, NgModule } from '@angular/core';
|
|
3
3
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
4
|
import { TranslateService, TranslatePipe } from '@ngx-translate/core';
|
|
5
|
-
import { ConfirmationService } from 'primeng/api';
|
|
6
5
|
import { isNullOrUndefined } from '@seniorsistemas/angular-components/utils';
|
|
7
6
|
import { ImageCropperService } from '@seniorsistemas/angular-components/image-cropper';
|
|
8
|
-
import {
|
|
7
|
+
import { ConfirmDialogService } from '@seniorsistemas/angular-components/confirm-dialog';
|
|
9
8
|
import { ThumbnailComponent } from '@seniorsistemas/angular-components/thumbnail';
|
|
10
9
|
import { ButtonComponent } from '@seniorsistemas/angular-components/button';
|
|
11
10
|
|
|
@@ -30,7 +29,7 @@ import { ButtonComponent } from '@seniorsistemas/angular-components/button';
|
|
|
30
29
|
*/
|
|
31
30
|
class ProfilePicturePickerComponent {
|
|
32
31
|
imageCropperService = inject(ImageCropperService);
|
|
33
|
-
|
|
32
|
+
confirmDialogService = inject(ConfirmDialogService);
|
|
34
33
|
translateService = inject(TranslateService);
|
|
35
34
|
/**
|
|
36
35
|
* @description Título simples exibido quando nenhuma imagem está selecionada.
|
|
@@ -123,6 +122,7 @@ class ProfilePicturePickerComponent {
|
|
|
123
122
|
get imageBase64() {
|
|
124
123
|
return typeof this.image === 'string' ? this.image : (this.image?.base64 ?? '');
|
|
125
124
|
}
|
|
125
|
+
disabled = false;
|
|
126
126
|
_onChange;
|
|
127
127
|
_onTouched;
|
|
128
128
|
writeValue(value) {
|
|
@@ -134,6 +134,9 @@ class ProfilePicturePickerComponent {
|
|
|
134
134
|
registerOnTouched(onTouched) {
|
|
135
135
|
this._onTouched = onTouched;
|
|
136
136
|
}
|
|
137
|
+
setDisabledState(isDisabled) {
|
|
138
|
+
this.disabled = isDisabled;
|
|
139
|
+
}
|
|
137
140
|
ngOnInit() {
|
|
138
141
|
this._normalizeSuportedExtensions();
|
|
139
142
|
}
|
|
@@ -148,6 +151,9 @@ class ProfilePicturePickerComponent {
|
|
|
148
151
|
onDrop(event) {
|
|
149
152
|
event.preventDefault();
|
|
150
153
|
event.stopPropagation();
|
|
154
|
+
if (this.disabled) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
151
157
|
this._onTouched?.();
|
|
152
158
|
const files = [];
|
|
153
159
|
const dataTransferFiles = event.dataTransfer?.files;
|
|
@@ -176,13 +182,19 @@ class ProfilePicturePickerComponent {
|
|
|
176
182
|
}
|
|
177
183
|
}
|
|
178
184
|
selectPhoto() {
|
|
185
|
+
if (this.disabled) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
179
188
|
const fileInputElement = this.fileInput?.nativeElement;
|
|
180
189
|
fileInputElement.value = '';
|
|
181
190
|
fileInputElement.click();
|
|
182
191
|
this._onTouched?.();
|
|
183
192
|
}
|
|
184
193
|
removePhoto() {
|
|
185
|
-
this.
|
|
194
|
+
if (this.disabled) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
this.confirmDialogService.confirm({
|
|
186
198
|
message: this.confirmationTexts?.removalMessage ??
|
|
187
199
|
this.translateService.instant('platform.angular_components.confirmation_remove_image'),
|
|
188
200
|
acceptLabel: this.confirmationTexts?.removalAcceptLabel ??
|
|
@@ -191,7 +203,6 @@ class ProfilePicturePickerComponent {
|
|
|
191
203
|
this.translateService.instant('platform.angular_components.cancel'),
|
|
192
204
|
header: this.confirmationTexts?.removalHeader ??
|
|
193
205
|
this.translateService.instant('platform.angular_components.remove_image'),
|
|
194
|
-
rejectButtonStyleClass: 'ui-button-secondary',
|
|
195
206
|
accept: () => {
|
|
196
207
|
const fileInputElement = this.fileInput?.nativeElement;
|
|
197
208
|
fileInputElement.value = '';
|
|
@@ -285,7 +296,7 @@ class ProfilePicturePickerComponent {
|
|
|
285
296
|
useExisting: forwardRef(() => ProfilePicturePickerComponent),
|
|
286
297
|
multi: true,
|
|
287
298
|
},
|
|
288
|
-
], viewQueries: [{ propertyName: "uploadPicture", first: true, predicate: ["uploadPicture"], descendants: true }, { propertyName: "info", first: true, predicate: ["info"], descendants: true }, { propertyName: "thumbnail", first: true, predicate: ["thumbnail"], descendants: true, read: ElementRef }, { propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, read: ElementRef }], ngImport: i0, template: "<
|
|
299
|
+
], viewQueries: [{ propertyName: "uploadPicture", first: true, predicate: ["uploadPicture"], descendants: true }, { propertyName: "info", first: true, predicate: ["info"], descendants: true }, { propertyName: "thumbnail", first: true, predicate: ["thumbnail"], descendants: true, read: ElementRef }, { propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, read: ElementRef }], ngImport: i0, template: "<input\n #fileInput\n [accept]=\"accept\"\n [disabled]=\"disabled\"\n class=\"file-input\"\n type=\"file\"\n (change)=\"photoSelected($event)\"\n/>\n<div\n #uploadPicture\n class=\"upload-picture\"\n [class.upload-picture--disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n>\n <s-thumbnail\n #thumbnail\n iconClass=\"far fa-user\"\n [imageSource]=\"imageBase64\"\n [hasAction]=\"!image\"\n (click)=\"selectPhoto()\"\n >\n </s-thumbnail>\n <div\n #info\n class=\"info\"\n >\n @if (image) {\n <div class=\"buttons\">\n <s-button\n [label]=\"changeButtonLabel || 'platform.angular_components.change_photo' | translate\"\n priority=\"primary\"\n [disabled]=\"disabled\"\n (clicked)=\"selectPhoto()\"\n >\n </s-button>\n <s-button\n [label]=\"removeButtonLabel || 'platform.angular_components.remove' | translate\"\n priority=\"secondary\"\n [disabled]=\"disabled\"\n (clicked)=\"removePhoto()\"\n >\n </s-button>\n </div>\n } @else {\n <p class=\"title\">\n {{ simpleTitle || 'platform.angular_components.drag_your_photo_or' | translate }}\n <span\n class=\"action-title\"\n (click)=\"selectPhoto()\"\n >\n {{ actionTitle || 'platform.angular_components.select_a_file' | translate }}\n </span>\n </p>\n }\n <p class=\"subtitle\">{{ subtitle }}</p>\n </div>\n</div>\n", styles: [".file-input{display:none}.upload-picture{display:flex;flex-wrap:wrap}.upload-picture--disabled{opacity:.5;pointer-events:none}.upload-picture .info{display:flex;flex-direction:column;padding:12px 20px;align-items:flex-start}.upload-picture .info .title{font-family:Open Sans,sans-serif;font-weight:700;font-size:.875rem;line-height:150%;color:#333}.upload-picture .info .title .action-title{cursor:pointer;color:#428bca}.upload-picture .info .buttons{display:flex;gap:8px}.upload-picture .info .buttons s-button{margin:0}.upload-picture .info .subtitle{padding:6px 0;font-family:Open Sans,sans-serif;font-weight:400;font-size:.75rem;line-height:150%;color:#697882;text-align:center}.upload-picture--small .info{align-items:center}.upload-picture--small .info .title,.upload-picture--small .info .subtitle{text-align:center}.upload-picture--small .info .buttons{justify-content:center;flex-wrap:wrap}\n"], dependencies: [{ kind: "component", type: ThumbnailComponent, selector: "s-thumbnail", inputs: ["id", "size", "imageSource", "imageFallback", "imageAlt", "iconClass", "hasAction", "actionIconClass", "isTile", "isBrand"] }, { kind: "component", type: ButtonComponent, selector: "s-button", inputs: ["id", "label", "tooltip", "tooltipPosition", "iconClass", "rightIconClass", "caret", "styleClass", "baseZIndex", "disabled", "auxiliary", "type", "priority", "menuOptions", "size", "slide", "animation", "badge", "iconColor", "menuAriaLabel", "ariaLabel"], outputs: ["clicked"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
289
300
|
}
|
|
290
301
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProfilePicturePickerComponent, decorators: [{
|
|
291
302
|
type: Component,
|
|
@@ -295,7 +306,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
295
306
|
useExisting: forwardRef(() => ProfilePicturePickerComponent),
|
|
296
307
|
multi: true,
|
|
297
308
|
},
|
|
298
|
-
], standalone: true, imports: [
|
|
309
|
+
], standalone: true, imports: [ThumbnailComponent, ButtonComponent, TranslatePipe], template: "<input\n #fileInput\n [accept]=\"accept\"\n [disabled]=\"disabled\"\n class=\"file-input\"\n type=\"file\"\n (change)=\"photoSelected($event)\"\n/>\n<div\n #uploadPicture\n class=\"upload-picture\"\n [class.upload-picture--disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n>\n <s-thumbnail\n #thumbnail\n iconClass=\"far fa-user\"\n [imageSource]=\"imageBase64\"\n [hasAction]=\"!image\"\n (click)=\"selectPhoto()\"\n >\n </s-thumbnail>\n <div\n #info\n class=\"info\"\n >\n @if (image) {\n <div class=\"buttons\">\n <s-button\n [label]=\"changeButtonLabel || 'platform.angular_components.change_photo' | translate\"\n priority=\"primary\"\n [disabled]=\"disabled\"\n (clicked)=\"selectPhoto()\"\n >\n </s-button>\n <s-button\n [label]=\"removeButtonLabel || 'platform.angular_components.remove' | translate\"\n priority=\"secondary\"\n [disabled]=\"disabled\"\n (clicked)=\"removePhoto()\"\n >\n </s-button>\n </div>\n } @else {\n <p class=\"title\">\n {{ simpleTitle || 'platform.angular_components.drag_your_photo_or' | translate }}\n <span\n class=\"action-title\"\n (click)=\"selectPhoto()\"\n >\n {{ actionTitle || 'platform.angular_components.select_a_file' | translate }}\n </span>\n </p>\n }\n <p class=\"subtitle\">{{ subtitle }}</p>\n </div>\n</div>\n", styles: [".file-input{display:none}.upload-picture{display:flex;flex-wrap:wrap}.upload-picture--disabled{opacity:.5;pointer-events:none}.upload-picture .info{display:flex;flex-direction:column;padding:12px 20px;align-items:flex-start}.upload-picture .info .title{font-family:Open Sans,sans-serif;font-weight:700;font-size:.875rem;line-height:150%;color:#333}.upload-picture .info .title .action-title{cursor:pointer;color:#428bca}.upload-picture .info .buttons{display:flex;gap:8px}.upload-picture .info .buttons s-button{margin:0}.upload-picture .info .subtitle{padding:6px 0;font-family:Open Sans,sans-serif;font-weight:400;font-size:.75rem;line-height:150%;color:#697882;text-align:center}.upload-picture--small .info{align-items:center}.upload-picture--small .info .title,.upload-picture--small .info .subtitle{text-align:center}.upload-picture--small .info .buttons{justify-content:center;flex-wrap:wrap}\n"] }]
|
|
299
310
|
}], propDecorators: { simpleTitle: [{
|
|
300
311
|
type: Input
|
|
301
312
|
}], actionTitle: [{
|
|
@@ -358,14 +369,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
358
369
|
class ProfilePicturePickerModule {
|
|
359
370
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProfilePicturePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
360
371
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: ProfilePicturePickerModule, imports: [ProfilePicturePickerComponent], exports: [ProfilePicturePickerComponent] });
|
|
361
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProfilePicturePickerModule, providers: [ImageCropperService
|
|
372
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProfilePicturePickerModule, providers: [ImageCropperService], imports: [ProfilePicturePickerComponent] });
|
|
362
373
|
}
|
|
363
374
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProfilePicturePickerModule, decorators: [{
|
|
364
375
|
type: NgModule,
|
|
365
376
|
args: [{
|
|
366
377
|
imports: [ProfilePicturePickerComponent],
|
|
367
378
|
exports: [ProfilePicturePickerComponent],
|
|
368
|
-
providers: [ImageCropperService
|
|
379
|
+
providers: [ImageCropperService],
|
|
369
380
|
}]
|
|
370
381
|
}] });
|
|
371
382
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seniorsistemas-angular-components-profile-picture-picker.mjs","sources":["../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/profile-picture-picker.component.ts","../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/profile-picture-picker.component.html","../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/profile-picture-picker.module.ts","../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/validators/validators.ts","../../projects/angular-components/profile-picture-picker/src/seniorsistemas-angular-components-profile-picture-picker.ts"],"sourcesContent":["import {\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n forwardRef,\r\n HostListener,\r\n Input,\r\n OnInit,\r\n Output,\r\n ViewChild,\r\n inject,\r\n} from '@angular/core';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\nimport { TranslateService, TranslatePipe } from '@ngx-translate/core';\r\nimport { ConfirmationService } from 'primeng/api';\r\nimport { ConfirmationTexts, CropperLabelsConfig, FileValidationErrors, ProfilePicturePickerData } from './models/index';\r\nimport { isNullOrUndefined } from '@seniorsistemas/angular-components/utils';\r\nimport { ImageCropperService } from '@seniorsistemas/angular-components/image-cropper';\r\nimport { ConfirmDialog } from 'primeng/confirmdialog';\r\nimport { ThumbnailComponent } from '@seniorsistemas/angular-components/thumbnail';\r\nimport { ButtonComponent } from '@seniorsistemas/angular-components/button';\r\n\r\n/**\r\n * @description Componente para seleção, edição e remoção de foto de perfil do usuário.\r\n * Permite ao usuário fazer upload de uma imagem, recortá-la com o {@link ImageCropperService}\r\n * e confirmar ou remover a foto atual. Implementa {@link ControlValueAccessor} para uso\r\n * em formulários reativos e template-driven do Angular.\r\n *\r\n * @example\r\n * ```html\r\n * <s-profile-picture-picker\r\n * formControlName=\"avatar\"\r\n * subtitle=\"Formatos aceitos: JPG e PNG\"\r\n * [maxFileSize]=\"2097152\"\r\n * accept=\"image/jpeg,image/png\"\r\n * (imageChange)=\"onImageChange($event)\"\r\n * (removedImage)=\"onImageRemoved()\" />\r\n * ```\r\n *\r\n * @category Inputs\r\n */\r\n@Component({\r\n selector: 's-profile-picture-picker',\r\n templateUrl: 'profile-picture-picker.component.html',\r\n styleUrls: ['profile-picture-picker.component.scss'],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => ProfilePicturePickerComponent),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n imports: [ConfirmDialog, ThumbnailComponent, ButtonComponent, TranslatePipe],\r\n})\r\nexport class ProfilePicturePickerComponent implements OnInit, ControlValueAccessor {\r\n private readonly imageCropperService = inject(ImageCropperService);\r\n private readonly confirmationService = inject(ConfirmationService);\r\n private readonly translateService = inject(TranslateService);\r\n\r\n /**\r\n * @description Título simples exibido quando nenhuma imagem está selecionada.\r\n */\r\n @Input()\r\n public simpleTitle!: string;\r\n\r\n /**\r\n * @description Título de ação exibido como label principal do botão de upload.\r\n */\r\n @Input()\r\n public actionTitle!: string;\r\n\r\n /**\r\n * @description Legenda exibida abaixo do título, descrevendo formatos suportados\r\n * ou outras orientações para o usuário. Campo obrigatório.\r\n */\r\n @Input({ required: true })\r\n public subtitle!: string;\r\n\r\n /**\r\n * @description Proporção (aspect ratio) do recorte da imagem.\r\n * Por exemplo, `1` para quadrado, `16/9` para widescreen.\r\n *\r\n * @default 1\r\n */\r\n @Input()\r\n public aspectRatio = 1;\r\n\r\n /**\r\n * @description Configurações de rótulos exibidos no componente de recorte de imagem (cropper).\r\n * Permite sobrescrever os textos padrão dos botões e instruções do cropper.\r\n */\r\n @Input()\r\n public cropperLabelsConfig?: CropperLabelsConfig;\r\n\r\n /**\r\n * @description Texto do botão de remoção da foto atual.\r\n * Se não informado, utiliza o label padrão de remoção.\r\n */\r\n @Input()\r\n public removeButtonLabel?: string;\r\n\r\n /**\r\n * @description Texto do botão de troca da foto atual.\r\n * Se não informado, utiliza o label padrão de alteração.\r\n */\r\n @Input()\r\n public changeButtonLabel?: string;\r\n\r\n /**\r\n * @description Textos personalizados exibidos no diálogo de confirmação\r\n * ao remover ou substituir a foto. Permite sobrescrever título, mensagem e botões.\r\n */\r\n @Input()\r\n public confirmationTexts?: ConfirmationTexts;\r\n\r\n /**\r\n * @description Tamanho máximo permitido para o arquivo de imagem, em bytes.\r\n * Quando o arquivo excede esse limite, o output `invalidFile` é emitido.\r\n */\r\n @Input()\r\n public maxFileSize?: number;\r\n\r\n /**\r\n * @description Tipos MIME aceitos pelo input de arquivo.\r\n * Exemplo: `\"image/jpeg,image/png\"`.\r\n */\r\n @Input()\r\n public accept?: string;\r\n\r\n /**\r\n * @description Lista de extensões de arquivo aceitas para validação.\r\n * Exemplo: `['.jpg', '.jpeg', '.png']`.\r\n *\r\n * @default []\r\n */\r\n @Input()\r\n public supportedExtensions: string[] = [];\r\n\r\n /**\r\n * @description Imagem atual do componente. Pode ser uma string base64, um objeto\r\n * {@link ProfilePicturePickerData} com metadados, ou `null` para sem imagem.\r\n *\r\n * @default null\r\n */\r\n @Input()\r\n public image: string | ProfilePicturePickerData | null = null;\r\n\r\n @ViewChild('uploadPicture')\r\n public uploadPicture: ElementRef | null = null;\r\n\r\n @ViewChild('info')\r\n public info: ElementRef | null = null;\r\n\r\n @ViewChild('thumbnail', { read: ElementRef })\r\n public thumbnail: ElementRef | null = null;\r\n\r\n @ViewChild('fileInput', { read: ElementRef })\r\n public fileInput: ElementRef | null = null;\r\n\r\n /**\r\n * @deprecated Use `imageChange` em vez deste output.\r\n * @description Emitido ao selecionar ou recortar uma nova imagem. Emite a string base64 da imagem.\r\n */\r\n @Output()\r\n public changedImage: EventEmitter<string> = new EventEmitter();\r\n\r\n /**\r\n * @description Emitido ao selecionar, recortar ou alterar a imagem.\r\n * Emite a string base64 ou um objeto {@link ProfilePicturePickerData} com os dados da imagem.\r\n */\r\n @Output()\r\n public imageChange = new EventEmitter<string | ProfilePicturePickerData>();\r\n\r\n /**\r\n * @description Emitido quando o usuário confirma a remoção da foto atual.\r\n */\r\n @Output()\r\n public removedImage = new EventEmitter();\r\n\r\n /**\r\n * @description Emitido quando o arquivo selecionado não passa na validação.\r\n * Emite um objeto {@link FileValidationErrors} descrevendo os erros encontrados\r\n * (ex.: tamanho excedido, extensão inválida).\r\n */\r\n @Output()\r\n public invalidFile: EventEmitter<FileValidationErrors> = new EventEmitter();\r\n\r\n public get imageBase64(): string {\r\n return typeof this.image === 'string' ? this.image : (this.image?.base64 ?? '');\r\n }\r\n\r\n private _onChange?: (value: string | ProfilePicturePickerData) => void;\r\n private _onTouched?: () => void;\r\n\r\n public writeValue(value: string | ProfilePicturePickerData): void {\r\n this.image = value;\r\n }\r\n\r\n public registerOnChange(onChange: (value: string | ProfilePicturePickerData) => void): void {\r\n this._onChange = onChange;\r\n }\r\n\r\n public registerOnTouched(onTouched: () => void): void {\r\n this._onTouched = onTouched;\r\n }\r\n\r\n public ngOnInit(): void {\r\n this._normalizeSuportedExtensions();\r\n }\r\n\r\n @HostListener('dragover', ['$event'])\r\n public onDragOver(event: DragEvent) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n\r\n @HostListener('dragleave', ['$event'])\r\n public onDragLeave(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n\r\n @HostListener('drop', ['$event'])\r\n public onDrop(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n this._onTouched?.();\r\n\r\n const files: File[] = [];\r\n const dataTransferFiles = event.dataTransfer?.files;\r\n\r\n if (!isNullOrUndefined(dataTransferFiles)) {\r\n for (let i = 0; i < dataTransferFiles?.length; i++) {\r\n const item = dataTransferFiles.item(i);\r\n if (!isNullOrUndefined(item)) {\r\n files.push(item);\r\n }\r\n }\r\n }\r\n\r\n this._showImageCropper(files);\r\n }\r\n\r\n // Verificando o redimensionamento para ajustar o design para ficar responsivo.\r\n @HostListener('window:resize')\r\n public onResize(): void {\r\n if (this.uploadPicture && this.info && this.thumbnail) {\r\n const uploadPictureWidth = this._getWidthElement(this.uploadPicture);\r\n const infoWidth = this._getWidthElement(this.info);\r\n const thumbnailWidth = this._getWidthElement(this.thumbnail);\r\n\r\n if (thumbnailWidth + infoWidth > uploadPictureWidth) {\r\n this.uploadPicture.nativeElement.classList.add('upload-picture--small');\r\n } else {\r\n this.uploadPicture.nativeElement.classList.remove('upload-picture--small');\r\n }\r\n }\r\n }\r\n\r\n public selectPhoto(): void {\r\n const fileInputElement = this.fileInput?.nativeElement;\r\n fileInputElement.value = '';\r\n fileInputElement.click();\r\n\r\n this._onTouched?.();\r\n }\r\n\r\n public removePhoto(): void {\r\n this.confirmationService.confirm({\r\n message:\r\n this.confirmationTexts?.removalMessage ??\r\n this.translateService.instant('platform.angular_components.confirmation_remove_image'),\r\n acceptLabel:\r\n this.confirmationTexts?.removalAcceptLabel ??\r\n this.translateService.instant('platform.angular_components.remove'),\r\n rejectLabel:\r\n this.confirmationTexts?.removalRejectLabel ??\r\n this.translateService.instant('platform.angular_components.cancel'),\r\n header:\r\n this.confirmationTexts?.removalHeader ??\r\n this.translateService.instant('platform.angular_components.remove_image'),\r\n rejectButtonStyleClass: 'ui-button-secondary',\r\n accept: () => {\r\n const fileInputElement = this.fileInput?.nativeElement;\r\n fileInputElement.value = '';\r\n this.image = null;\r\n this.removedImage.emit();\r\n },\r\n });\r\n }\r\n\r\n public photoSelected(event: any): void {\r\n this._showImageCropper(event.srcElement.files);\r\n }\r\n\r\n private _showImageCropper(files: File[]): void {\r\n if (!this._validateData(files)) {\r\n return;\r\n }\r\n\r\n const file = files[0];\r\n\r\n const fileReader = new FileReader();\r\n fileReader.readAsDataURL(file);\r\n fileReader.onloadend = (fileEvent: any) => {\r\n this.imageCropperService.show({\r\n imageSource: fileEvent.target.result,\r\n croppedImage: (image) => {\r\n this.changedImage.emit(image);\r\n\r\n const data: ProfilePicturePickerData = { source: file, base64: image };\r\n\r\n // Se o tipo do image for string eu preciso atualizar e mandar para o imageChange uma string.\r\n // Se for ProfilePicturePickerData eu preciso mandar o data completo.\r\n if (typeof this.image === 'string') {\r\n this.image = image;\r\n this.imageChange.emit(image);\r\n } else {\r\n this.image = data;\r\n this.imageChange.emit(data);\r\n }\r\n\r\n this._onChange?.(this.image);\r\n },\r\n changeImage: () => this.selectPhoto(),\r\n allowSelectAnother: false,\r\n aspectRatio: this.aspectRatio,\r\n ...this.cropperLabelsConfig,\r\n });\r\n };\r\n }\r\n\r\n private _normalizeSuportedExtensions(): void {\r\n this.supportedExtensions = this.supportedExtensions?.map((extension) =>\r\n extension.replace('.', '').toLocaleLowerCase(),\r\n );\r\n }\r\n\r\n private _validateData(files: File[]): boolean {\r\n if (!files.length) {\r\n return false;\r\n }\r\n\r\n if (files.length > 1) {\r\n this.invalidFile.emit({ file: null, validation: 'maxFileLimit' });\r\n return false;\r\n }\r\n\r\n const file = files[0];\r\n\r\n if (!file.type.includes('image')) {\r\n this.invalidFile.emit({ file, validation: 'typeInvalid' });\r\n return false;\r\n }\r\n\r\n if (!this._validateFileExtension(file)) {\r\n this.invalidFile.emit({ file, validation: 'unsupportedExtension' });\r\n return false;\r\n }\r\n\r\n if (!this._validateFileSize(file)) {\r\n this.invalidFile.emit({ file, validation: 'maxFileSize' });\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private _validateFileExtension(file: File): boolean {\r\n if (this.supportedExtensions?.length) {\r\n const extension = file.name.split('.').pop()?.toLowerCase() ?? '';\r\n return this.supportedExtensions.includes(extension);\r\n }\r\n return true;\r\n }\r\n\r\n private _validateFileSize(file: File): boolean {\r\n if (this.maxFileSize) {\r\n return file.size <= this.maxFileSize;\r\n }\r\n return true;\r\n }\r\n\r\n private _getWidthElement(element: ElementRef): number {\r\n const { left, right } = element.nativeElement.getBoundingClientRect();\r\n return right - left;\r\n }\r\n}\r\n","<p-confirmDialog></p-confirmDialog>\n\n<input\n #fileInput\n [accept]=\"accept\"\n class=\"file-input\"\n type=\"file\"\n (change)=\"photoSelected($event)\"\n/>\n<div\n #uploadPicture\n class=\"upload-picture\"\n>\n <s-thumbnail\n #thumbnail\n iconClass=\"far fa-user\"\n [imageSource]=\"imageBase64\"\n [hasAction]=\"!image\"\n (click)=\"selectPhoto()\"\n >\n </s-thumbnail>\n <div\n #info\n class=\"info\"\n >\n @if (image) {\n <div class=\"buttons\">\n <s-button\n [label]=\"changeButtonLabel || 'platform.angular_components.change_photo' | translate\"\n priority=\"primary\"\n (clicked)=\"selectPhoto()\"\n >\n </s-button>\n <s-button\n [label]=\"removeButtonLabel || 'platform.angular_components.remove' | translate\"\n priority=\"secondary\"\n (clicked)=\"removePhoto()\"\n >\n </s-button>\n </div>\n } @else {\n <p class=\"title\">\n {{ simpleTitle || 'platform.angular_components.drag_your_photo_or' | translate }}\n <span\n class=\"action-title\"\n (click)=\"selectPhoto()\"\n >\n {{ actionTitle || 'platform.angular_components.select_a_file' | translate }}\n </span>\n </p>\n }\n <p class=\"subtitle\">{{ subtitle }}</p>\n </div>\n</div>\n","import { NgModule } from '@angular/core';\r\n\r\nimport { ConfirmationService } from 'primeng/api';\r\n\r\nimport { ProfilePicturePickerComponent } from './profile-picture-picker.component';\r\nimport { ImageCropperService } from '@seniorsistemas/angular-components/image-cropper';\r\n\r\n@NgModule({\r\n imports: [ProfilePicturePickerComponent],\r\n exports: [ProfilePicturePickerComponent],\r\n providers: [ImageCropperService, ConfirmationService],\r\n})\r\nexport class ProfilePicturePickerModule {}\r\n","import { AbstractControl, ValidatorFn } from \"@angular/forms\";\n\nconst maxFileSize = (size: number): ValidatorFn => {\n return (control: AbstractControl) => {\n if (control.value?.source?.size > size) {\n return {\n maxFileSize: true,\n };\n }\n\n return null;\n };\n};\n\nconst fileExtension = (extensions: string[]) => {\n return (control: AbstractControl) => {\n if (extensions.length) {\n const extension = control.value?.source?.name?.split(\".\").pop().toLowerCase();\n if (extension?.includes(extension)) {\n return {\n fileExtension: true,\n };\n }\n }\n return null;\n };\n};\n\nexport const Validators = {\n maxFileSize,\n fileExtension,\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"seniorsistemas-angular-components-profile-picture-picker.mjs","sources":["../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/profile-picture-picker.component.ts","../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/profile-picture-picker.component.html","../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/profile-picture-picker.module.ts","../../projects/angular-components/profile-picture-picker/src/lib/profile-picture-picker/validators/validators.ts","../../projects/angular-components/profile-picture-picker/src/seniorsistemas-angular-components-profile-picture-picker.ts"],"sourcesContent":["import {\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n forwardRef,\r\n HostListener,\r\n Input,\r\n OnInit,\r\n Output,\r\n ViewChild,\r\n inject,\r\n} from '@angular/core';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\nimport { TranslateService, TranslatePipe } from '@ngx-translate/core';\r\nimport { ConfirmationTexts, CropperLabelsConfig, FileValidationErrors, ProfilePicturePickerData } from './models/index';\r\nimport { isNullOrUndefined } from '@seniorsistemas/angular-components/utils';\r\nimport { ImageCropperService } from '@seniorsistemas/angular-components/image-cropper';\r\nimport { ConfirmDialogService } from '@seniorsistemas/angular-components/confirm-dialog';\r\nimport { ThumbnailComponent } from '@seniorsistemas/angular-components/thumbnail';\r\nimport { ButtonComponent } from '@seniorsistemas/angular-components/button';\r\n\r\n/**\r\n * @description Componente para seleção, edição e remoção de foto de perfil do usuário.\r\n * Permite ao usuário fazer upload de uma imagem, recortá-la com o {@link ImageCropperService}\r\n * e confirmar ou remover a foto atual. Implementa {@link ControlValueAccessor} para uso\r\n * em formulários reativos e template-driven do Angular.\r\n *\r\n * @example\r\n * ```html\r\n * <s-profile-picture-picker\r\n * formControlName=\"avatar\"\r\n * subtitle=\"Formatos aceitos: JPG e PNG\"\r\n * [maxFileSize]=\"2097152\"\r\n * accept=\"image/jpeg,image/png\"\r\n * (imageChange)=\"onImageChange($event)\"\r\n * (removedImage)=\"onImageRemoved()\" />\r\n * ```\r\n *\r\n * @category Inputs\r\n */\r\n@Component({\r\n selector: 's-profile-picture-picker',\r\n templateUrl: 'profile-picture-picker.component.html',\r\n styleUrls: ['profile-picture-picker.component.scss'],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => ProfilePicturePickerComponent),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n imports: [ThumbnailComponent, ButtonComponent, TranslatePipe],\r\n})\r\nexport class ProfilePicturePickerComponent implements OnInit, ControlValueAccessor {\r\n private readonly imageCropperService = inject(ImageCropperService);\r\n private readonly confirmDialogService = inject(ConfirmDialogService);\r\n private readonly translateService = inject(TranslateService);\r\n\r\n /**\r\n * @description Título simples exibido quando nenhuma imagem está selecionada.\r\n */\r\n @Input()\r\n public simpleTitle!: string;\r\n\r\n /**\r\n * @description Título de ação exibido como label principal do botão de upload.\r\n */\r\n @Input()\r\n public actionTitle!: string;\r\n\r\n /**\r\n * @description Legenda exibida abaixo do título, descrevendo formatos suportados\r\n * ou outras orientações para o usuário. Campo obrigatório.\r\n */\r\n @Input({ required: true })\r\n public subtitle!: string;\r\n\r\n /**\r\n * @description Proporção (aspect ratio) do recorte da imagem.\r\n * Por exemplo, `1` para quadrado, `16/9` para widescreen.\r\n *\r\n * @default 1\r\n */\r\n @Input()\r\n public aspectRatio = 1;\r\n\r\n /**\r\n * @description Configurações de rótulos exibidos no componente de recorte de imagem (cropper).\r\n * Permite sobrescrever os textos padrão dos botões e instruções do cropper.\r\n */\r\n @Input()\r\n public cropperLabelsConfig?: CropperLabelsConfig;\r\n\r\n /**\r\n * @description Texto do botão de remoção da foto atual.\r\n * Se não informado, utiliza o label padrão de remoção.\r\n */\r\n @Input()\r\n public removeButtonLabel?: string;\r\n\r\n /**\r\n * @description Texto do botão de troca da foto atual.\r\n * Se não informado, utiliza o label padrão de alteração.\r\n */\r\n @Input()\r\n public changeButtonLabel?: string;\r\n\r\n /**\r\n * @description Textos personalizados exibidos no diálogo de confirmação\r\n * ao remover ou substituir a foto. Permite sobrescrever título, mensagem e botões.\r\n */\r\n @Input()\r\n public confirmationTexts?: ConfirmationTexts;\r\n\r\n /**\r\n * @description Tamanho máximo permitido para o arquivo de imagem, em bytes.\r\n * Quando o arquivo excede esse limite, o output `invalidFile` é emitido.\r\n */\r\n @Input()\r\n public maxFileSize?: number;\r\n\r\n /**\r\n * @description Tipos MIME aceitos pelo input de arquivo.\r\n * Exemplo: `\"image/jpeg,image/png\"`.\r\n */\r\n @Input()\r\n public accept?: string;\r\n\r\n /**\r\n * @description Lista de extensões de arquivo aceitas para validação.\r\n * Exemplo: `['.jpg', '.jpeg', '.png']`.\r\n *\r\n * @default []\r\n */\r\n @Input()\r\n public supportedExtensions: string[] = [];\r\n\r\n /**\r\n * @description Imagem atual do componente. Pode ser uma string base64, um objeto\r\n * {@link ProfilePicturePickerData} com metadados, ou `null` para sem imagem.\r\n *\r\n * @default null\r\n */\r\n @Input()\r\n public image: string | ProfilePicturePickerData | null = null;\r\n\r\n @ViewChild('uploadPicture')\r\n public uploadPicture: ElementRef | null = null;\r\n\r\n @ViewChild('info')\r\n public info: ElementRef | null = null;\r\n\r\n @ViewChild('thumbnail', { read: ElementRef })\r\n public thumbnail: ElementRef | null = null;\r\n\r\n @ViewChild('fileInput', { read: ElementRef })\r\n public fileInput: ElementRef | null = null;\r\n\r\n /**\r\n * @deprecated Use `imageChange` em vez deste output.\r\n * @description Emitido ao selecionar ou recortar uma nova imagem. Emite a string base64 da imagem.\r\n */\r\n @Output()\r\n public changedImage: EventEmitter<string> = new EventEmitter();\r\n\r\n /**\r\n * @description Emitido ao selecionar, recortar ou alterar a imagem.\r\n * Emite a string base64 ou um objeto {@link ProfilePicturePickerData} com os dados da imagem.\r\n */\r\n @Output()\r\n public imageChange = new EventEmitter<string | ProfilePicturePickerData>();\r\n\r\n /**\r\n * @description Emitido quando o usuário confirma a remoção da foto atual.\r\n */\r\n @Output()\r\n public removedImage = new EventEmitter();\r\n\r\n /**\r\n * @description Emitido quando o arquivo selecionado não passa na validação.\r\n * Emite um objeto {@link FileValidationErrors} descrevendo os erros encontrados\r\n * (ex.: tamanho excedido, extensão inválida).\r\n */\r\n @Output()\r\n public invalidFile: EventEmitter<FileValidationErrors> = new EventEmitter();\r\n\r\n public get imageBase64(): string {\r\n return typeof this.image === 'string' ? this.image : (this.image?.base64 ?? '');\r\n }\r\n\r\n public disabled = false;\r\n\r\n private _onChange?: (value: string | ProfilePicturePickerData) => void;\r\n private _onTouched?: () => void;\r\n\r\n public writeValue(value: string | ProfilePicturePickerData): void {\r\n this.image = value;\r\n }\r\n\r\n public registerOnChange(onChange: (value: string | ProfilePicturePickerData) => void): void {\r\n this._onChange = onChange;\r\n }\r\n\r\n public registerOnTouched(onTouched: () => void): void {\r\n this._onTouched = onTouched;\r\n }\r\n\r\n public setDisabledState(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n }\r\n\r\n public ngOnInit(): void {\r\n this._normalizeSuportedExtensions();\r\n }\r\n\r\n @HostListener('dragover', ['$event'])\r\n public onDragOver(event: DragEvent) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n\r\n @HostListener('dragleave', ['$event'])\r\n public onDragLeave(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n\r\n @HostListener('drop', ['$event'])\r\n public onDrop(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n if (this.disabled) {\r\n return;\r\n }\r\n\r\n this._onTouched?.();\r\n\r\n const files: File[] = [];\r\n const dataTransferFiles = event.dataTransfer?.files;\r\n\r\n if (!isNullOrUndefined(dataTransferFiles)) {\r\n for (let i = 0; i < dataTransferFiles?.length; i++) {\r\n const item = dataTransferFiles.item(i);\r\n if (!isNullOrUndefined(item)) {\r\n files.push(item);\r\n }\r\n }\r\n }\r\n\r\n this._showImageCropper(files);\r\n }\r\n\r\n // Verificando o redimensionamento para ajustar o design para ficar responsivo.\r\n @HostListener('window:resize')\r\n public onResize(): void {\r\n if (this.uploadPicture && this.info && this.thumbnail) {\r\n const uploadPictureWidth = this._getWidthElement(this.uploadPicture);\r\n const infoWidth = this._getWidthElement(this.info);\r\n const thumbnailWidth = this._getWidthElement(this.thumbnail);\r\n\r\n if (thumbnailWidth + infoWidth > uploadPictureWidth) {\r\n this.uploadPicture.nativeElement.classList.add('upload-picture--small');\r\n } else {\r\n this.uploadPicture.nativeElement.classList.remove('upload-picture--small');\r\n }\r\n }\r\n }\r\n\r\n public selectPhoto(): void {\r\n if (this.disabled) {\r\n return;\r\n }\r\n\r\n const fileInputElement = this.fileInput?.nativeElement;\r\n fileInputElement.value = '';\r\n fileInputElement.click();\r\n\r\n this._onTouched?.();\r\n }\r\n\r\n public removePhoto(): void {\r\n if (this.disabled) {\r\n return;\r\n }\r\n\r\n this.confirmDialogService.confirm({\r\n message:\r\n this.confirmationTexts?.removalMessage ??\r\n this.translateService.instant('platform.angular_components.confirmation_remove_image'),\r\n acceptLabel:\r\n this.confirmationTexts?.removalAcceptLabel ??\r\n this.translateService.instant('platform.angular_components.remove'),\r\n rejectLabel:\r\n this.confirmationTexts?.removalRejectLabel ??\r\n this.translateService.instant('platform.angular_components.cancel'),\r\n header:\r\n this.confirmationTexts?.removalHeader ??\r\n this.translateService.instant('platform.angular_components.remove_image'),\r\n accept: () => {\r\n const fileInputElement = this.fileInput?.nativeElement;\r\n fileInputElement.value = '';\r\n this.image = null;\r\n this.removedImage.emit();\r\n },\r\n });\r\n }\r\n\r\n public photoSelected(event: any): void {\r\n this._showImageCropper(event.srcElement.files);\r\n }\r\n\r\n private _showImageCropper(files: File[]): void {\r\n if (!this._validateData(files)) {\r\n return;\r\n }\r\n\r\n const file = files[0];\r\n\r\n const fileReader = new FileReader();\r\n fileReader.readAsDataURL(file);\r\n fileReader.onloadend = (fileEvent: any) => {\r\n this.imageCropperService.show({\r\n imageSource: fileEvent.target.result,\r\n croppedImage: (image) => {\r\n this.changedImage.emit(image);\r\n\r\n const data: ProfilePicturePickerData = { source: file, base64: image };\r\n\r\n // Se o tipo do image for string eu preciso atualizar e mandar para o imageChange uma string.\r\n // Se for ProfilePicturePickerData eu preciso mandar o data completo.\r\n if (typeof this.image === 'string') {\r\n this.image = image;\r\n this.imageChange.emit(image);\r\n } else {\r\n this.image = data;\r\n this.imageChange.emit(data);\r\n }\r\n\r\n this._onChange?.(this.image);\r\n },\r\n changeImage: () => this.selectPhoto(),\r\n allowSelectAnother: false,\r\n aspectRatio: this.aspectRatio,\r\n ...this.cropperLabelsConfig,\r\n });\r\n };\r\n }\r\n\r\n private _normalizeSuportedExtensions(): void {\r\n this.supportedExtensions = this.supportedExtensions?.map((extension) =>\r\n extension.replace('.', '').toLocaleLowerCase(),\r\n );\r\n }\r\n\r\n private _validateData(files: File[]): boolean {\r\n if (!files.length) {\r\n return false;\r\n }\r\n\r\n if (files.length > 1) {\r\n this.invalidFile.emit({ file: null, validation: 'maxFileLimit' });\r\n return false;\r\n }\r\n\r\n const file = files[0];\r\n\r\n if (!file.type.includes('image')) {\r\n this.invalidFile.emit({ file, validation: 'typeInvalid' });\r\n return false;\r\n }\r\n\r\n if (!this._validateFileExtension(file)) {\r\n this.invalidFile.emit({ file, validation: 'unsupportedExtension' });\r\n return false;\r\n }\r\n\r\n if (!this._validateFileSize(file)) {\r\n this.invalidFile.emit({ file, validation: 'maxFileSize' });\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private _validateFileExtension(file: File): boolean {\r\n if (this.supportedExtensions?.length) {\r\n const extension = file.name.split('.').pop()?.toLowerCase() ?? '';\r\n return this.supportedExtensions.includes(extension);\r\n }\r\n return true;\r\n }\r\n\r\n private _validateFileSize(file: File): boolean {\r\n if (this.maxFileSize) {\r\n return file.size <= this.maxFileSize;\r\n }\r\n return true;\r\n }\r\n\r\n private _getWidthElement(element: ElementRef): number {\r\n const { left, right } = element.nativeElement.getBoundingClientRect();\r\n return right - left;\r\n }\r\n}\r\n","<input\n #fileInput\n [accept]=\"accept\"\n [disabled]=\"disabled\"\n class=\"file-input\"\n type=\"file\"\n (change)=\"photoSelected($event)\"\n/>\n<div\n #uploadPicture\n class=\"upload-picture\"\n [class.upload-picture--disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n>\n <s-thumbnail\n #thumbnail\n iconClass=\"far fa-user\"\n [imageSource]=\"imageBase64\"\n [hasAction]=\"!image\"\n (click)=\"selectPhoto()\"\n >\n </s-thumbnail>\n <div\n #info\n class=\"info\"\n >\n @if (image) {\n <div class=\"buttons\">\n <s-button\n [label]=\"changeButtonLabel || 'platform.angular_components.change_photo' | translate\"\n priority=\"primary\"\n [disabled]=\"disabled\"\n (clicked)=\"selectPhoto()\"\n >\n </s-button>\n <s-button\n [label]=\"removeButtonLabel || 'platform.angular_components.remove' | translate\"\n priority=\"secondary\"\n [disabled]=\"disabled\"\n (clicked)=\"removePhoto()\"\n >\n </s-button>\n </div>\n } @else {\n <p class=\"title\">\n {{ simpleTitle || 'platform.angular_components.drag_your_photo_or' | translate }}\n <span\n class=\"action-title\"\n (click)=\"selectPhoto()\"\n >\n {{ actionTitle || 'platform.angular_components.select_a_file' | translate }}\n </span>\n </p>\n }\n <p class=\"subtitle\">{{ subtitle }}</p>\n </div>\n</div>\n","import { NgModule } from '@angular/core';\r\n\r\nimport { ProfilePicturePickerComponent } from './profile-picture-picker.component';\r\nimport { ImageCropperService } from '@seniorsistemas/angular-components/image-cropper';\r\n\r\n@NgModule({\r\n imports: [ProfilePicturePickerComponent],\r\n exports: [ProfilePicturePickerComponent],\r\n providers: [ImageCropperService],\r\n})\r\nexport class ProfilePicturePickerModule {}\r\n","import { AbstractControl, ValidatorFn } from \"@angular/forms\";\n\nconst maxFileSize = (size: number): ValidatorFn => {\n return (control: AbstractControl) => {\n if (control.value?.source?.size > size) {\n return {\n maxFileSize: true,\n };\n }\n\n return null;\n };\n};\n\nconst fileExtension = (extensions: string[]) => {\n return (control: AbstractControl) => {\n if (extensions.length) {\n const extension = control.value?.source?.name?.split(\".\").pop().toLowerCase();\n if (extension?.includes(extension)) {\n return {\n fileExtension: true,\n };\n }\n }\n return null;\n };\n};\n\nexport const Validators = {\n maxFileSize,\n fileExtension,\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,26 @@ class RatingScaleComponent {
|
|
|
39
39
|
value;
|
|
40
40
|
_onChange;
|
|
41
41
|
_onTouched;
|
|
42
|
+
ngOnChanges(changes) {
|
|
43
|
+
if (changes['nodes']) {
|
|
44
|
+
this.nodes?.forEach((node) => {
|
|
45
|
+
const hasSelectedIcon = !!node.selectedIcon;
|
|
46
|
+
const hasUnselectedIcon = !!node.unselectedIcon;
|
|
47
|
+
if (hasSelectedIcon !== hasUnselectedIcon) {
|
|
48
|
+
console.warn(`s-rating-scale: o nó "${node.id}" informou apenas um de "selectedIcon"/"unselectedIcon" — os dois devem ser informados juntos. Nenhum ícone será exibido para esse nó até que ambos sejam informados.`);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
getNodeIconClass(node) {
|
|
54
|
+
if (node.selectedIcon && node.unselectedIcon) {
|
|
55
|
+
return this.value?.id === node.id ? node.selectedIcon : node.unselectedIcon;
|
|
56
|
+
}
|
|
57
|
+
if (node.selectedIcon || node.unselectedIcon) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return node.icon ? `fas ${node.icon}` : undefined;
|
|
61
|
+
}
|
|
42
62
|
writeValue(value) {
|
|
43
63
|
if (!this.disabled) {
|
|
44
64
|
this.value = value;
|
|
@@ -63,7 +83,7 @@ class RatingScaleComponent {
|
|
|
63
83
|
useExisting: forwardRef(() => RatingScaleComponent),
|
|
64
84
|
multi: true,
|
|
65
85
|
},
|
|
66
|
-
], ngImport: i0, template: "<div\n class=\"flex flex-col\"\n [class.opacity-50]=\"disabled\">\n <div class=\"flex\">\n @for (node of nodes; track node.id) {\n <button\n class=\"flex flex-grow items-center justify-center rounded-xbig border border-secondary bg-grayscale-0 p-2 mx-0.5 first:ml-0 last:mr-0\"\n [class.bg-hippie-blue-100]=\"value?.id === node.id && !disabled\"\n [class.border-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.text-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.cursor-pointer]=\"!disabled\"\n [class.hover:bg-grayscale-20]=\"!disabled\"\n [class.focus:border-2]=\"!disabled\"\n [class.focus:outline-none]=\"!disabled\"\n tabindex=\"0\"\n (click)=\"onSelect(node)\">\n @
|
|
86
|
+
], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"flex flex-col\"\n [class.opacity-50]=\"disabled\">\n <div class=\"flex\">\n @for (node of nodes; track node.id) {\n <button\n class=\"flex flex-grow items-center justify-center rounded-xbig border border-secondary bg-grayscale-0 p-2 mx-0.5 first:ml-0 last:mr-0\"\n [class.bg-hippie-blue-100]=\"value?.id === node.id && !disabled\"\n [class.border-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.text-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.cursor-pointer]=\"!disabled\"\n [class.hover:bg-grayscale-20]=\"!disabled\"\n [class.focus:border-2]=\"!disabled\"\n [class.focus:outline-none]=\"!disabled\"\n tabindex=\"0\"\n (click)=\"onSelect(node)\">\n @let nodeIconClass = getNodeIconClass(node);\n @if (nodeIconClass) {\n <span\n class=\"m-1.5 text-base text-grayscale-60\"\n [ngClass]=\"nodeIconClass\">\n </span>\n }\n @if (node.title) {\n <span class=\"m-1.5 text-sm font-normal leading-[150%] text-grayscale-90\">{{ node.title }}</span>\n }\n </button>\n }\n </div>\n <div class=\"flex justify-between py-3\">\n <span class=\"font-open-sans text-sm font-normal leading-[150%] text-[#080808]\">{{ startLabel }}</span>\n <span class=\"font-open-sans text-sm font-normal leading-[150%] text-[#080808]\">{{ endLabel }}</span>\n </div>\n</div>", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
67
87
|
}
|
|
68
88
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RatingScaleComponent, decorators: [{
|
|
69
89
|
type: Component,
|
|
@@ -73,7 +93,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
73
93
|
useExisting: forwardRef(() => RatingScaleComponent),
|
|
74
94
|
multi: true,
|
|
75
95
|
},
|
|
76
|
-
], standalone: true, imports: [NgClass], template: "<div\n class=\"flex flex-col\"\n [class.opacity-50]=\"disabled\">\n <div class=\"flex\">\n @for (node of nodes; track node.id) {\n <button\n class=\"flex flex-grow items-center justify-center rounded-xbig border border-secondary bg-grayscale-0 p-2 mx-0.5 first:ml-0 last:mr-0\"\n [class.bg-hippie-blue-100]=\"value?.id === node.id && !disabled\"\n [class.border-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.text-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.cursor-pointer]=\"!disabled\"\n [class.hover:bg-grayscale-20]=\"!disabled\"\n [class.focus:border-2]=\"!disabled\"\n [class.focus:outline-none]=\"!disabled\"\n tabindex=\"0\"\n (click)=\"onSelect(node)\">\n @
|
|
96
|
+
], standalone: true, imports: [NgClass], template: "<div\n class=\"flex flex-col\"\n [class.opacity-50]=\"disabled\">\n <div class=\"flex\">\n @for (node of nodes; track node.id) {\n <button\n class=\"flex flex-grow items-center justify-center rounded-xbig border border-secondary bg-grayscale-0 p-2 mx-0.5 first:ml-0 last:mr-0\"\n [class.bg-hippie-blue-100]=\"value?.id === node.id && !disabled\"\n [class.border-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.text-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.cursor-pointer]=\"!disabled\"\n [class.hover:bg-grayscale-20]=\"!disabled\"\n [class.focus:border-2]=\"!disabled\"\n [class.focus:outline-none]=\"!disabled\"\n tabindex=\"0\"\n (click)=\"onSelect(node)\">\n @let nodeIconClass = getNodeIconClass(node);\n @if (nodeIconClass) {\n <span\n class=\"m-1.5 text-base text-grayscale-60\"\n [ngClass]=\"nodeIconClass\">\n </span>\n }\n @if (node.title) {\n <span class=\"m-1.5 text-sm font-normal leading-[150%] text-grayscale-90\">{{ node.title }}</span>\n }\n </button>\n }\n </div>\n <div class=\"flex justify-between py-3\">\n <span class=\"font-open-sans text-sm font-normal leading-[150%] text-[#080808]\">{{ startLabel }}</span>\n <span class=\"font-open-sans text-sm font-normal leading-[150%] text-[#080808]\">{{ endLabel }}</span>\n </div>\n</div>" }]
|
|
77
97
|
}], propDecorators: { nodes: [{
|
|
78
98
|
type: Input,
|
|
79
99
|
args: [{ required: true }]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seniorsistemas-angular-components-rating-scale.mjs","sources":["../../projects/angular-components/rating-scale/src/lib/rating-scale/rating-scale.component.ts","../../projects/angular-components/rating-scale/src/lib/rating-scale/rating-scale.component.html","../../projects/angular-components/rating-scale/src/lib/rating-scale/rating-scale.module.ts","../../projects/angular-components/rating-scale/src/seniorsistemas-angular-components-rating-scale.ts"],"sourcesContent":["import { NgClass } from '@angular/common';\r\nimport { Component, Input, forwardRef } from '@angular/core';\r\n\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { RatingScaleNode } from './models/rating-scale-node';\r\n\r\n/**\r\n * @description Componente de escala de avaliação que permite ao usuário selecionar um nó de uma escala visual.\r\n * Implementa `ControlValueAccessor` para integração com Reactive Forms e Template-Driven Forms.\r\n * Ideal para pesquisas de satisfação (NPS, CSAT) e questionários de feedback.\r\n *\r\n * @example\r\n * ```html\r\n * <s-rating-scale\r\n * [nodes]=\"ratingNodes\"\r\n * startLabel=\"Péssimo\"\r\n * endLabel=\"Ótimo\"\r\n * [(ngModel)]=\"rating\"\r\n * />\r\n * ```\r\n *\r\n * @category Feedback\r\n */\r\n@Component({\r\n selector: 's-rating-scale',\r\n templateUrl: './rating-scale.component.html',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => RatingScaleComponent),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n imports: [NgClass],\r\n})\r\nexport class RatingScaleComponent implements ControlValueAccessor {\r\n /**\r\n * @description Lista de nós que compõem a escala de avaliação. Campo obrigatório.\r\n * Cada `RatingScaleNode` define o valor, rótulo e cor do item na escala.\r\n */\r\n @Input({ required: true })\r\n public nodes!: RatingScaleNode[];\r\n\r\n /** @description Rótulo exibido no início (extremidade esquerda) da escala. */\r\n @Input()\r\n public startLabel?: string;\r\n\r\n /** @description Rótulo exibido no final (extremidade direita) da escala. */\r\n @Input()\r\n public endLabel?: string;\r\n\r\n /**\r\n * @description Quando `true`, a escala fica desabilitada e o usuário não pode selecionar nenhum nó.\r\n *\r\n * @default false\r\n */\r\n @Input()\r\n public disabled = false;\r\n\r\n public value?: RatingScaleNode;\r\n private _onChange?: (value: RatingScaleNode) => void;\r\n private _onTouched?: (value: RatingScaleNode) => void;\r\n\r\n public writeValue(value: RatingScaleNode): void {\r\n if (!this.disabled) {\r\n this.value = value;\r\n }\r\n }\r\n public registerOnChange(onChange: (value: RatingScaleNode) => void): void {\r\n this._onChange = onChange;\r\n }\r\n public registerOnTouched(onTouched: (value: RatingScaleNode) => void): void {\r\n this._onTouched = onTouched;\r\n }\r\n\r\n public onSelect(rating: RatingScaleNode) {\r\n this.value = rating;\r\n if (this._onChange) {\r\n this._onChange(this.value);\r\n }\r\n }\r\n}\r\n","<div\n class=\"flex flex-col\"\n [class.opacity-50]=\"disabled\">\n <div class=\"flex\">\n @for (node of nodes; track node.id) {\n <button\n class=\"flex flex-grow items-center justify-center rounded-xbig border border-secondary bg-grayscale-0 p-2 mx-0.5 first:ml-0 last:mr-0\"\n [class.bg-hippie-blue-100]=\"value?.id === node.id && !disabled\"\n [class.border-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.text-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.cursor-pointer]=\"!disabled\"\n [class.hover:bg-grayscale-20]=\"!disabled\"\n [class.focus:border-2]=\"!disabled\"\n [class.focus:outline-none]=\"!disabled\"\n tabindex=\"0\"\n (click)=\"onSelect(node)\">\n @
|
|
1
|
+
{"version":3,"file":"seniorsistemas-angular-components-rating-scale.mjs","sources":["../../projects/angular-components/rating-scale/src/lib/rating-scale/rating-scale.component.ts","../../projects/angular-components/rating-scale/src/lib/rating-scale/rating-scale.component.html","../../projects/angular-components/rating-scale/src/lib/rating-scale/rating-scale.module.ts","../../projects/angular-components/rating-scale/src/seniorsistemas-angular-components-rating-scale.ts"],"sourcesContent":["import { NgClass } from '@angular/common';\r\nimport { Component, Input, OnChanges, SimpleChanges, forwardRef } from '@angular/core';\r\n\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { RatingScaleNode } from './models/rating-scale-node';\r\n\r\n/**\r\n * @description Componente de escala de avaliação que permite ao usuário selecionar um nó de uma escala visual.\r\n * Implementa `ControlValueAccessor` para integração com Reactive Forms e Template-Driven Forms.\r\n * Ideal para pesquisas de satisfação (NPS, CSAT) e questionários de feedback.\r\n *\r\n * @example\r\n * ```html\r\n * <s-rating-scale\r\n * [nodes]=\"ratingNodes\"\r\n * startLabel=\"Péssimo\"\r\n * endLabel=\"Ótimo\"\r\n * [(ngModel)]=\"rating\"\r\n * />\r\n * ```\r\n *\r\n * @category Feedback\r\n */\r\n@Component({\r\n selector: 's-rating-scale',\r\n templateUrl: './rating-scale.component.html',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => RatingScaleComponent),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n imports: [NgClass],\r\n})\r\nexport class RatingScaleComponent implements ControlValueAccessor, OnChanges {\r\n /**\r\n * @description Lista de nós que compõem a escala de avaliação. Campo obrigatório.\r\n * Cada `RatingScaleNode` define o valor, rótulo e cor do item na escala.\r\n */\r\n @Input({ required: true })\r\n public nodes!: RatingScaleNode[];\r\n\r\n /** @description Rótulo exibido no início (extremidade esquerda) da escala. */\r\n @Input()\r\n public startLabel?: string;\r\n\r\n /** @description Rótulo exibido no final (extremidade direita) da escala. */\r\n @Input()\r\n public endLabel?: string;\r\n\r\n /**\r\n * @description Quando `true`, a escala fica desabilitada e o usuário não pode selecionar nenhum nó.\r\n *\r\n * @default false\r\n */\r\n @Input()\r\n public disabled = false;\r\n\r\n public value?: RatingScaleNode;\r\n private _onChange?: (value: RatingScaleNode) => void;\r\n private _onTouched?: (value: RatingScaleNode) => void;\r\n\r\n public ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['nodes']) {\r\n this.nodes?.forEach((node) => {\r\n const hasSelectedIcon = !!node.selectedIcon;\r\n const hasUnselectedIcon = !!node.unselectedIcon;\r\n if (hasSelectedIcon !== hasUnselectedIcon) {\r\n console.warn(\r\n `s-rating-scale: o nó \"${node.id}\" informou apenas um de \"selectedIcon\"/\"unselectedIcon\" — os dois devem ser informados juntos. Nenhum ícone será exibido para esse nó até que ambos sejam informados.`,\r\n );\r\n }\r\n });\r\n }\r\n }\r\n\r\n public getNodeIconClass(node: RatingScaleNode): string | undefined {\r\n if (node.selectedIcon && node.unselectedIcon) {\r\n return this.value?.id === node.id ? node.selectedIcon : node.unselectedIcon;\r\n }\r\n if (node.selectedIcon || node.unselectedIcon) {\r\n return undefined;\r\n }\r\n return node.icon ? `fas ${node.icon}` : undefined;\r\n }\r\n\r\n public writeValue(value: RatingScaleNode): void {\r\n if (!this.disabled) {\r\n this.value = value;\r\n }\r\n }\r\n public registerOnChange(onChange: (value: RatingScaleNode) => void): void {\r\n this._onChange = onChange;\r\n }\r\n public registerOnTouched(onTouched: (value: RatingScaleNode) => void): void {\r\n this._onTouched = onTouched;\r\n }\r\n\r\n public onSelect(rating: RatingScaleNode) {\r\n this.value = rating;\r\n if (this._onChange) {\r\n this._onChange(this.value);\r\n }\r\n }\r\n}\r\n","<div\n class=\"flex flex-col\"\n [class.opacity-50]=\"disabled\">\n <div class=\"flex\">\n @for (node of nodes; track node.id) {\n <button\n class=\"flex flex-grow items-center justify-center rounded-xbig border border-secondary bg-grayscale-0 p-2 mx-0.5 first:ml-0 last:mr-0\"\n [class.bg-hippie-blue-100]=\"value?.id === node.id && !disabled\"\n [class.border-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.text-criticality-blue]=\"value?.id === node.id && !disabled\"\n [class.cursor-pointer]=\"!disabled\"\n [class.hover:bg-grayscale-20]=\"!disabled\"\n [class.focus:border-2]=\"!disabled\"\n [class.focus:outline-none]=\"!disabled\"\n tabindex=\"0\"\n (click)=\"onSelect(node)\">\n @let nodeIconClass = getNodeIconClass(node);\n @if (nodeIconClass) {\n <span\n class=\"m-1.5 text-base text-grayscale-60\"\n [ngClass]=\"nodeIconClass\">\n </span>\n }\n @if (node.title) {\n <span class=\"m-1.5 text-sm font-normal leading-[150%] text-grayscale-90\">{{ node.title }}</span>\n }\n </button>\n }\n </div>\n <div class=\"flex justify-between py-3\">\n <span class=\"font-open-sans text-sm font-normal leading-[150%] text-[#080808]\">{{ startLabel }}</span>\n <span class=\"font-open-sans text-sm font-normal leading-[150%] text-[#080808]\">{{ endLabel }}</span>\n </div>\n</div>","import { NgModule } from '@angular/core';\r\n\r\nimport { RatingScaleComponent } from './rating-scale.component';\r\n\r\n@NgModule({\r\n imports: [RatingScaleComponent],\r\n exports: [RatingScaleComponent],\r\n})\r\nexport class RatingScaleModule {}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,8 @@ class SelectOptionComponent {
|
|
|
21
21
|
isGrouper = input.required();
|
|
22
22
|
isFocused = input.required();
|
|
23
23
|
isSelected = model.required();
|
|
24
|
+
/** @description Classe do ícone de checkmark exibido quando a opção está selecionada. @default 'far fa-check' */
|
|
25
|
+
checkIconClass = input('far fa-check');
|
|
24
26
|
selected = output();
|
|
25
27
|
onClick() {
|
|
26
28
|
if (this.isGrouper()) {
|
|
@@ -29,11 +31,11 @@ class SelectOptionComponent {
|
|
|
29
31
|
this.selected.emit();
|
|
30
32
|
}
|
|
31
33
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
32
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectOptionComponent, isStandalone: true, selector: "s-select-option", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: true, transformFunction: null }, isGrouper: { classPropertyName: "isGrouper", publicName: "isGrouper", isSignal: true, isRequired: true, transformFunction: null }, isFocused: { classPropertyName: "isFocused", publicName: "isFocused", isSignal: true, isRequired: true, transformFunction: null }, isSelected: { classPropertyName: "isSelected", publicName: "isSelected", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { isSelected: "isSelectedChange", selected: "selected" }, ngImport: i0, template: "<div\n [attr.id]=\"id()\"\n [attr.role]=\"isGrouper() ? 'presentation' : 'option'\"\n [attr.aria-selected]=\"isGrouper() ? null : isSelected()\"\n class=\"flex select-none items-center gap-3 px-3 py-2\"\n [class.hover:bg-grayscale-10]=\"!isGrouper()\"\n [class.bg-grayscale-10]=\"!isGrouper() && isFocused()\"\n (click)=\"onClick()\"\n (keydown.enter)=\"onClick()\"\n (keydown.space)=\"onClick(); $event.preventDefault()\"\n>\n @if (!isGrouper() && checkmark() && !multiple() && isSelected()) {\n <i\n class=\"
|
|
34
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectOptionComponent, isStandalone: true, selector: "s-select-option", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: true, transformFunction: null }, isGrouper: { classPropertyName: "isGrouper", publicName: "isGrouper", isSignal: true, isRequired: true, transformFunction: null }, isFocused: { classPropertyName: "isFocused", publicName: "isFocused", isSignal: true, isRequired: true, transformFunction: null }, isSelected: { classPropertyName: "isSelected", publicName: "isSelected", isSignal: true, isRequired: true, transformFunction: null }, checkIconClass: { classPropertyName: "checkIconClass", publicName: "checkIconClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isSelected: "isSelectedChange", selected: "selected" }, ngImport: i0, template: "<div\n [attr.id]=\"id()\"\n [attr.role]=\"isGrouper() ? 'presentation' : 'option'\"\n [attr.aria-selected]=\"isGrouper() ? null : isSelected()\"\n class=\"flex select-none items-center gap-3 px-3 py-2\"\n [class.hover:bg-grayscale-10]=\"!isGrouper()\"\n [class.bg-grayscale-10]=\"!isGrouper() && isFocused()\"\n (click)=\"onClick()\"\n (keydown.enter)=\"onClick()\"\n (keydown.space)=\"onClick(); $event.preventDefault()\"\n>\n @if (!isGrouper() && checkmark() && !multiple() && isSelected()) {\n <i\n class=\"text-grayscale-60\"\n [class]=\"checkIconClass()\"\n aria-hidden=\"true\"\n ></i>\n }\n\n @if (!isGrouper() && multiple()) {\n <s-checkbox [checked]=\"isSelected()\"></s-checkbox>\n }\n <span\n [class]=\"isSelected() ? 'text-[#428BCA]' : 'text-grayscale-90'\"\n [class.font-bold]=\"isGrouper()\"\n >\n {{ label() }}\n </span>\n</div>\n\n", dependencies: [{ kind: "component", type: CheckboxComponent, selector: "s-checkbox", inputs: ["disabled", "checked", "indeterminate", "label", "ariaLabel", "ariaLabelledBy"], outputs: ["disabledChange", "checkedChange"] }] });
|
|
33
35
|
}
|
|
34
36
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectOptionComponent, decorators: [{
|
|
35
37
|
type: Component,
|
|
36
|
-
args: [{ selector: 's-select-option', standalone: true, imports: [CheckboxComponent], template: "<div\n [attr.id]=\"id()\"\n [attr.role]=\"isGrouper() ? 'presentation' : 'option'\"\n [attr.aria-selected]=\"isGrouper() ? null : isSelected()\"\n class=\"flex select-none items-center gap-3 px-3 py-2\"\n [class.hover:bg-grayscale-10]=\"!isGrouper()\"\n [class.bg-grayscale-10]=\"!isGrouper() && isFocused()\"\n (click)=\"onClick()\"\n (keydown.enter)=\"onClick()\"\n (keydown.space)=\"onClick(); $event.preventDefault()\"\n>\n @if (!isGrouper() && checkmark() && !multiple() && isSelected()) {\n <i\n class=\"
|
|
38
|
+
args: [{ selector: 's-select-option', standalone: true, imports: [CheckboxComponent], template: "<div\n [attr.id]=\"id()\"\n [attr.role]=\"isGrouper() ? 'presentation' : 'option'\"\n [attr.aria-selected]=\"isGrouper() ? null : isSelected()\"\n class=\"flex select-none items-center gap-3 px-3 py-2\"\n [class.hover:bg-grayscale-10]=\"!isGrouper()\"\n [class.bg-grayscale-10]=\"!isGrouper() && isFocused()\"\n (click)=\"onClick()\"\n (keydown.enter)=\"onClick()\"\n (keydown.space)=\"onClick(); $event.preventDefault()\"\n>\n @if (!isGrouper() && checkmark() && !multiple() && isSelected()) {\n <i\n class=\"text-grayscale-60\"\n [class]=\"checkIconClass()\"\n aria-hidden=\"true\"\n ></i>\n }\n\n @if (!isGrouper() && multiple()) {\n <s-checkbox [checked]=\"isSelected()\"></s-checkbox>\n }\n <span\n [class]=\"isSelected() ? 'text-[#428BCA]' : 'text-grayscale-90'\"\n [class.font-bold]=\"isGrouper()\"\n >\n {{ label() }}\n </span>\n</div>\n\n" }]
|
|
37
39
|
}] });
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -73,6 +75,8 @@ class SelectComponent {
|
|
|
73
75
|
filter = input(false);
|
|
74
76
|
/** @description Exibe um ícone de checkmark ao lado da opção selecionada. @default false */
|
|
75
77
|
checkmark = input(false);
|
|
78
|
+
/** @description Classe do ícone de checkmark exibido quando `checkmark` está ativo. @default 'far fa-check' */
|
|
79
|
+
checkIconClass = input('far fa-check');
|
|
76
80
|
/** @description Chave(s) do objeto usada(s) para filtragem textual. Quando não informado, usa `optionLabel`. */
|
|
77
81
|
filterBy = input();
|
|
78
82
|
/** @description Habilita agrupamento de opções. As opções devem conter itens filhos conforme a estrutura de grupo suportada. @default false */
|
|
@@ -862,13 +866,13 @@ class SelectComponent {
|
|
|
862
866
|
}
|
|
863
867
|
}
|
|
864
868
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
865
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectComponent, isStandalone: true, selector: "s-select", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", showOptions: "showOptionsChange" }, host: { listeners: { "window:resize": "onWindowResize($event)" } }, providers: [
|
|
869
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SelectComponent, isStandalone: true, selector: "s-select", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, checkmark: { classPropertyName: "checkmark", publicName: "checkmark", isSignal: true, isRequired: false, transformFunction: null }, checkIconClass: { classPropertyName: "checkIconClass", publicName: "checkIconClass", isSignal: true, isRequired: false, transformFunction: null }, filterBy: { classPropertyName: "filterBy", publicName: "filterBy", isSignal: true, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showOptions: { classPropertyName: "showOptions", publicName: "showOptions", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", showOptions: "showOptionsChange" }, host: { listeners: { "window:resize": "onWindowResize($event)" } }, providers: [
|
|
866
870
|
{
|
|
867
871
|
provide: NG_VALUE_ACCESSOR,
|
|
868
872
|
useExisting: forwardRef(() => SelectComponent),
|
|
869
873
|
multi: true,
|
|
870
874
|
},
|
|
871
|
-
], viewQueries: [{ propertyName: "_containerDiv", first: true, predicate: ["containerDiv"], descendants: true, isSignal: true }, { propertyName: "_filterInput", first: true, predicate: ["filterInput"], descendants: true, isSignal: true }, { propertyName: "_selectAllCheckbox", first: true, predicate: ["selectAllCheckbox"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #containerDiv\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n [class.pointer-events-none]=\"disabled()\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.bg-grayscale-5]=\"disabled()\"\n [class.pointer-events-auto]=\"!disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n [class.bg-grayscale-0]=\"!disabled()\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"showOptions()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-owns]=\"showOptions() ? componentId + '-listbox' : null\"\n [attr.aria-activedescendant]=\"showOptions() ? focusedOptionId() : null\"\n role=\"combobox\"\n [id]=\"componentId + '-combobox'\"\n (click)=\"onContainerDivClick()\"\n (keydown)=\"onKeyDown($event)\"\n tabindex=\"0\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"resolvedAriaLabelledBy() || null\"\n>\n <span\n class=\"flex flex-grow select-none px-3 py-[7px]\"\n [class.text-grayscale-90]=\"!disabled() && !isClean()\"\n [class.text-grayscale-60]=\"!disabled() && isClean()\"\n [class.text-grayscale-30]=\"disabled()\"\n >\n {{ print() || placeholder() }}\n </span>\n\n @if (!disabled() && showClear() && !isClean()) {\n <button\n class=\"mx-3\"\n (click)=\"clear($event)\"\n [attr.aria-label]=\"'platform.angular_components.aria_clear_selection' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n\n <div\n class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n >\n <i\n class=\"fas\"\n aria-hidden=\"true\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.fa-caret-down]=\"!showOptions()\"\n [class.fa-caret-up]=\"showOptions()\"\n ></i>\n </div>\n</div>\n\n<ng-template\n #dropdownTemplate\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"showOptions()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n (backdropClick)=\"showOptions.set(false)\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (detach)=\"showOptions.set(false)\"\n>\n <div\n [id]=\"componentId + '-listbox'\"\n class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n (click)=\"$event.stopPropagation()\"\n [style.width.px]=\"containerDiv.offsetWidth\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n [@visibilityChanged]\n role=\"listbox\"\n >\n @if (filter()) {\n <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n @if (multiple()) {\n <s-checkbox\n #selectAllCheckbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"selectAllIsIndeterminate()\"\n (checkedChange)=\"toggleSelectAll()\"\n ></s-checkbox>\n }\n\n <div class=\"relative flex h-[35px] grow\">\n <form\n class=\"flex w-full grow\"\n [formGroup]=\"filterForm\"\n >\n <input\n #filterInput\n class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n type=\"text\"\n formControlName=\"filter\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onFilterKeyDown($event)\"\n [attr.aria-label]=\"'platform.angular_components.filter_options' | translate\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-activedescendant]=\"focusedOptionId()\"\n autocomplete=\"off\"\n />\n </form>\n <i\n class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"\n aria-hidden=\"true\"\n ></i>\n </div>\n <button\n (click)=\"clearFilter()\"\n [attr.aria-label]=\"'platform.angular_components.clear_filter' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n\n <!-- Virtual scroll -->\n @if (virtualScroll() && filteredOptions().length > 10) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"virtualScrollItemSize()\"\n class=\"h-52 overflow-auto\"\n >\n <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Normal list -->\n @if (!virtualScroll() || filteredOptions().length <= 10) {\n <ul class=\"max-h-52 overflow-auto\">\n @for (option of filteredOptions(); track option.id) {\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n }\n </ul>\n }\n\n @if (filteredOptions().length === 0) {\n <span class=\"m-3 text-grayscale-60\">\n {{ emptyMessage() ?? 'platform.angular_components.no_records_found' | translate }}\n </span>\n }\n </div>\n</ng-template>\n\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: SelectOptionComponent, selector: "s-select-option", inputs: ["id", "label", "multiple", "checkmark", "isGrouper", "isFocused", "isSelected"], outputs: ["isSelectedChange", "selected"] }, { kind: "component", type: CheckboxComponent, selector: "s-checkbox", inputs: ["disabled", "checked", "indeterminate", "label", "ariaLabel", "ariaLabelledBy"], outputs: ["disabledChange", "checkedChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i4.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i4.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }], animations: [
|
|
875
|
+
], viewQueries: [{ propertyName: "_containerDiv", first: true, predicate: ["containerDiv"], descendants: true, isSignal: true }, { propertyName: "_filterInput", first: true, predicate: ["filterInput"], descendants: true, isSignal: true }, { propertyName: "_selectAllCheckbox", first: true, predicate: ["selectAllCheckbox"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #containerDiv\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n [class.pointer-events-none]=\"disabled()\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.bg-grayscale-5]=\"disabled()\"\n [class.pointer-events-auto]=\"!disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n [class.bg-grayscale-0]=\"!disabled()\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"showOptions()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-owns]=\"showOptions() ? componentId + '-listbox' : null\"\n [attr.aria-activedescendant]=\"showOptions() ? focusedOptionId() : null\"\n role=\"combobox\"\n [id]=\"componentId + '-combobox'\"\n (click)=\"onContainerDivClick()\"\n (keydown)=\"onKeyDown($event)\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"resolvedAriaLabelledBy() || null\"\n>\n <span\n class=\"flex flex-grow select-none px-3 py-[7px]\"\n [class.text-grayscale-90]=\"!disabled() && !isClean()\"\n [class.text-grayscale-60]=\"!disabled() && isClean()\"\n [class.text-grayscale-30]=\"disabled()\"\n >\n {{ print() || placeholder() }}\n </span>\n\n @if (!disabled() && showClear() && !isClean()) {\n <button\n class=\"mx-3\"\n (click)=\"clear($event)\"\n [attr.aria-label]=\"'platform.angular_components.aria_clear_selection' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n\n <div\n class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n >\n <i\n class=\"fas\"\n aria-hidden=\"true\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.fa-caret-down]=\"!showOptions()\"\n [class.fa-caret-up]=\"showOptions()\"\n ></i>\n </div>\n</div>\n\n<ng-template\n #dropdownTemplate\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"showOptions()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n (backdropClick)=\"showOptions.set(false)\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (detach)=\"showOptions.set(false)\"\n>\n <div\n [id]=\"componentId + '-listbox'\"\n class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n (click)=\"$event.stopPropagation()\"\n [style.width.px]=\"containerDiv.offsetWidth\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n [@visibilityChanged]\n role=\"listbox\"\n >\n @if (filter()) {\n <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n @if (multiple()) {\n <s-checkbox\n #selectAllCheckbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"selectAllIsIndeterminate()\"\n (checkedChange)=\"toggleSelectAll()\"\n ></s-checkbox>\n }\n\n <div class=\"relative flex h-[35px] grow\">\n <form\n class=\"flex w-full grow\"\n [formGroup]=\"filterForm\"\n >\n <input\n #filterInput\n class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n type=\"text\"\n formControlName=\"filter\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onFilterKeyDown($event)\"\n [attr.aria-label]=\"'platform.angular_components.filter_options' | translate\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-activedescendant]=\"focusedOptionId()\"\n autocomplete=\"off\"\n />\n </form>\n <i\n class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"\n aria-hidden=\"true\"\n ></i>\n </div>\n <button\n (click)=\"clearFilter()\"\n [attr.aria-label]=\"'platform.angular_components.clear_filter' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n\n <!-- Virtual scroll -->\n @if (virtualScroll() && filteredOptions().length > 10) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"virtualScrollItemSize()\"\n class=\"h-52 overflow-auto\"\n >\n <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [checkIconClass]=\"checkIconClass()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Normal list -->\n @if (!virtualScroll() || filteredOptions().length <= 10) {\n <ul class=\"max-h-52 overflow-auto\">\n @for (option of filteredOptions(); track option.id) {\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [checkIconClass]=\"checkIconClass()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n }\n </ul>\n }\n\n @if (filteredOptions().length === 0) {\n <span class=\"m-3 text-grayscale-60\">\n {{ emptyMessage() ?? 'platform.angular_components.no_records_found' | translate }}\n </span>\n }\n </div>\n</ng-template>\n\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: SelectOptionComponent, selector: "s-select-option", inputs: ["id", "label", "multiple", "checkmark", "isGrouper", "isFocused", "isSelected", "checkIconClass"], outputs: ["isSelectedChange", "selected"] }, { kind: "component", type: CheckboxComponent, selector: "s-checkbox", inputs: ["disabled", "checked", "indeterminate", "label", "ariaLabel", "ariaLabelledBy"], outputs: ["disabledChange", "checkedChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i4.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i4.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }], animations: [
|
|
872
876
|
trigger('visibilityChanged', [
|
|
873
877
|
state('void', style({ opacity: 0, transform: 'scale(0.95)' })),
|
|
874
878
|
transition(':enter', [
|
|
@@ -907,7 +911,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
907
911
|
animate('500ms cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 0, transform: 'scale(0.95)' })),
|
|
908
912
|
]),
|
|
909
913
|
]),
|
|
910
|
-
], template: "<div\n #containerDiv\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n [class.pointer-events-none]=\"disabled()\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.bg-grayscale-5]=\"disabled()\"\n [class.pointer-events-auto]=\"!disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n [class.bg-grayscale-0]=\"!disabled()\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"showOptions()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-owns]=\"showOptions() ? componentId + '-listbox' : null\"\n [attr.aria-activedescendant]=\"showOptions() ? focusedOptionId() : null\"\n role=\"combobox\"\n [id]=\"componentId + '-combobox'\"\n (click)=\"onContainerDivClick()\"\n (keydown)=\"onKeyDown($event)\"\n tabindex=\"0\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"resolvedAriaLabelledBy() || null\"\n>\n <span\n class=\"flex flex-grow select-none px-3 py-[7px]\"\n [class.text-grayscale-90]=\"!disabled() && !isClean()\"\n [class.text-grayscale-60]=\"!disabled() && isClean()\"\n [class.text-grayscale-30]=\"disabled()\"\n >\n {{ print() || placeholder() }}\n </span>\n\n @if (!disabled() && showClear() && !isClean()) {\n <button\n class=\"mx-3\"\n (click)=\"clear($event)\"\n [attr.aria-label]=\"'platform.angular_components.aria_clear_selection' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n\n <div\n class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n >\n <i\n class=\"fas\"\n aria-hidden=\"true\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.fa-caret-down]=\"!showOptions()\"\n [class.fa-caret-up]=\"showOptions()\"\n ></i>\n </div>\n</div>\n\n<ng-template\n #dropdownTemplate\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"showOptions()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n (backdropClick)=\"showOptions.set(false)\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (detach)=\"showOptions.set(false)\"\n>\n <div\n [id]=\"componentId + '-listbox'\"\n class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n (click)=\"$event.stopPropagation()\"\n [style.width.px]=\"containerDiv.offsetWidth\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n [@visibilityChanged]\n role=\"listbox\"\n >\n @if (filter()) {\n <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n @if (multiple()) {\n <s-checkbox\n #selectAllCheckbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"selectAllIsIndeterminate()\"\n (checkedChange)=\"toggleSelectAll()\"\n ></s-checkbox>\n }\n\n <div class=\"relative flex h-[35px] grow\">\n <form\n class=\"flex w-full grow\"\n [formGroup]=\"filterForm\"\n >\n <input\n #filterInput\n class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n type=\"text\"\n formControlName=\"filter\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onFilterKeyDown($event)\"\n [attr.aria-label]=\"'platform.angular_components.filter_options' | translate\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-activedescendant]=\"focusedOptionId()\"\n autocomplete=\"off\"\n />\n </form>\n <i\n class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"\n aria-hidden=\"true\"\n ></i>\n </div>\n <button\n (click)=\"clearFilter()\"\n [attr.aria-label]=\"'platform.angular_components.clear_filter' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n\n <!-- Virtual scroll -->\n @if (virtualScroll() && filteredOptions().length > 10) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"virtualScrollItemSize()\"\n class=\"h-52 overflow-auto\"\n >\n <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Normal list -->\n @if (!virtualScroll() || filteredOptions().length <= 10) {\n <ul class=\"max-h-52 overflow-auto\">\n @for (option of filteredOptions(); track option.id) {\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n }\n </ul>\n }\n\n @if (filteredOptions().length === 0) {\n <span class=\"m-3 text-grayscale-60\">\n {{ emptyMessage() ?? 'platform.angular_components.no_records_found' | translate }}\n </span>\n }\n </div>\n</ng-template>\n\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"] }]
|
|
914
|
+
], template: "<div\n #containerDiv\n cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n class=\"select-container group flex h-[35px] w-full overflow-hidden rounded-[3px] border outline-1 outline-primary focus:outline\"\n [class.pointer-events-none]=\"disabled()\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.bg-grayscale-5]=\"disabled()\"\n [class.pointer-events-auto]=\"!disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n [class.bg-grayscale-0]=\"!disabled()\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-expanded]=\"showOptions()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-owns]=\"showOptions() ? componentId + '-listbox' : null\"\n [attr.aria-activedescendant]=\"showOptions() ? focusedOptionId() : null\"\n role=\"combobox\"\n [id]=\"componentId + '-combobox'\"\n (click)=\"onContainerDivClick()\"\n (keydown)=\"onKeyDown($event)\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"resolvedAriaLabelledBy() || null\"\n>\n <span\n class=\"flex flex-grow select-none px-3 py-[7px]\"\n [class.text-grayscale-90]=\"!disabled() && !isClean()\"\n [class.text-grayscale-60]=\"!disabled() && isClean()\"\n [class.text-grayscale-30]=\"disabled()\"\n >\n {{ print() || placeholder() }}\n </span>\n\n @if (!disabled() && showClear() && !isClean()) {\n <button\n class=\"mx-3\"\n (click)=\"clear($event)\"\n [attr.aria-label]=\"'platform.angular_components.aria_clear_selection' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n\n <div\n class=\"dropdown-container flex items-center border-l px-3 group-hover:bg-grayscale-10 group-focus:border-primary\"\n [class.border-grayscale-20]=\"disabled()\"\n [class.border-grayscale-30]=\"!disabled()\"\n >\n <i\n class=\"fas\"\n aria-hidden=\"true\"\n [class.text-grayscale-30]=\"disabled()\"\n [class.text-grayscale-90]=\"!disabled()\"\n [class.fa-caret-down]=\"!showOptions()\"\n [class.fa-caret-up]=\"showOptions()\"\n ></i>\n </div>\n</div>\n\n<ng-template\n #dropdownTemplate\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"showOptions()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n (backdropClick)=\"showOptions.set(false)\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (detach)=\"showOptions.set(false)\"\n>\n <div\n [id]=\"componentId + '-listbox'\"\n class=\"dropdown-body-class z-[1000] rounded-[3px] bg-grayscale-0 py-1 shadow-md\"\n (click)=\"$event.stopPropagation()\"\n [style.width.px]=\"containerDiv.offsetWidth\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n [@visibilityChanged]\n role=\"listbox\"\n >\n @if (filter()) {\n <div class=\"flex w-full items-center gap-3 px-3 py-1.5\">\n @if (multiple()) {\n <s-checkbox\n #selectAllCheckbox\n [checked]=\"allSelected()\"\n [indeterminate]=\"selectAllIsIndeterminate()\"\n (checkedChange)=\"toggleSelectAll()\"\n ></s-checkbox>\n }\n\n <div class=\"relative flex h-[35px] grow\">\n <form\n class=\"flex w-full grow\"\n [formGroup]=\"filterForm\"\n >\n <input\n #filterInput\n class=\"w-full grow rounded-[3px] border border-grayscale-30 pl-2.5 pr-7 outline-1 outline-primary\"\n type=\"text\"\n formControlName=\"filter\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"onFilterKeyDown($event)\"\n [attr.aria-label]=\"'platform.angular_components.filter_options' | translate\"\n [attr.aria-controls]=\"componentId + '-listbox'\"\n [attr.aria-activedescendant]=\"focusedOptionId()\"\n autocomplete=\"off\"\n />\n </form>\n <i\n class=\"fas fa-search absolute right-2.5 top-2.5 text-grayscale-90\"\n aria-hidden=\"true\"\n ></i>\n </div>\n <button\n (click)=\"clearFilter()\"\n [attr.aria-label]=\"'platform.angular_components.clear_filter' | translate\"\n >\n <i\n class=\"fas fa-times flex items-center\"\n aria-hidden=\"true\"\n ></i>\n </button>\n </div>\n }\n\n <!-- Virtual scroll -->\n @if (virtualScroll() && filteredOptions().length > 10) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"virtualScrollItemSize()\"\n class=\"h-52 overflow-auto\"\n >\n <ng-container *cdkVirtualFor=\"let option of filteredOptions(); trackBy: trackById\">\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [checkIconClass]=\"checkIconClass()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n }\n\n <!-- Normal list -->\n @if (!virtualScroll() || filteredOptions().length <= 10) {\n <ul class=\"max-h-52 overflow-auto\">\n @for (option of filteredOptions(); track option.id) {\n <s-select-option\n [id]=\"option.id\"\n [label]=\"getOptionLabel(option.data)\"\n [multiple]=\"multiple()\"\n [checkmark]=\"checkmark()\"\n [checkIconClass]=\"checkIconClass()\"\n [isSelected]=\"isOptionSelected(option)\"\n (selected)=\"selectItem(option)\"\n [isGrouper]=\"option.grouper ?? false\"\n [isFocused]=\"option.data === focusedItem()\"\n ></s-select-option>\n }\n </ul>\n }\n\n @if (filteredOptions().length === 0) {\n <span class=\"m-3 text-grayscale-60\">\n {{ emptyMessage() ?? 'platform.angular_components.no_records_found' | translate }}\n </span>\n }\n </div>\n</ng-template>\n\n", styles: [":host.ng-dirty.ng-invalid{.dropdown-container,.select-container{border-color:#c13018;outline:none}}\n"] }]
|
|
911
915
|
}], ctorParameters: () => [] });
|
|
912
916
|
|
|
913
917
|
/**
|