nexheal-lib 0.0.2 → 0.0.3

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.
Files changed (62) hide show
  1. package/.editorconfig +17 -0
  2. package/.vscode/extensions.json +4 -0
  3. package/.vscode/launch.json +20 -0
  4. package/.vscode/tasks.json +42 -0
  5. package/README.md +15 -19
  6. package/angular.json +36 -0
  7. package/package.json +47 -23
  8. package/projects/nexheal-lib/README.md +63 -0
  9. package/projects/nexheal-lib/ng-package.json +9 -0
  10. package/projects/nexheal-lib/package.json +12 -0
  11. package/projects/nexheal-lib/src/directives/clickoutside.directive.ts +34 -0
  12. package/projects/nexheal-lib/src/lib/controls/autocomplete-control/autocomplete-control.component.html +52 -0
  13. package/projects/nexheal-lib/src/lib/controls/autocomplete-control/autocomplete-control.component.scss +22 -0
  14. package/projects/nexheal-lib/src/lib/controls/autocomplete-control/autocomplete-control.component.spec.ts +22 -0
  15. package/projects/nexheal-lib/src/lib/controls/autocomplete-control/autocomplete-control.component.ts +367 -0
  16. package/projects/nexheal-lib/src/lib/controls/calendar-control/calendar-control.component.html +152 -0
  17. package/projects/nexheal-lib/src/lib/controls/calendar-control/calendar-control.component.scss +194 -0
  18. package/projects/nexheal-lib/src/lib/controls/calendar-control/calendar-control.component.spec.ts +22 -0
  19. package/projects/nexheal-lib/src/lib/controls/calendar-control/calendar-control.component.ts +759 -0
  20. package/projects/nexheal-lib/src/lib/controls/checkbox-control/checkbox-control.component.html +4 -0
  21. package/projects/nexheal-lib/src/lib/controls/checkbox-control/checkbox-control.component.spec.ts +22 -0
  22. package/projects/nexheal-lib/src/lib/controls/checkbox-control/checkbox-control.component.ts +94 -0
  23. package/projects/nexheal-lib/src/lib/controls/input-control/input-control.component.html +61 -0
  24. package/projects/nexheal-lib/src/lib/controls/input-control/input-control.component.scss +132 -0
  25. package/projects/nexheal-lib/src/lib/controls/input-control/input-control.component.spec.ts +22 -0
  26. package/projects/nexheal-lib/src/lib/controls/input-control/input-control.component.ts +202 -0
  27. package/projects/nexheal-lib/src/lib/controls/multiselect-control/multiselect-control.component.html +72 -0
  28. package/projects/nexheal-lib/src/lib/controls/multiselect-control/multiselect-control.component.scss +90 -0
  29. package/projects/nexheal-lib/src/lib/controls/multiselect-control/multiselect-control.component.spec.ts +22 -0
  30. package/projects/nexheal-lib/src/lib/controls/multiselect-control/multiselect-control.component.ts +482 -0
  31. package/projects/nexheal-lib/src/lib/controls/select-control/select-control.component.html +53 -0
  32. package/projects/nexheal-lib/src/lib/controls/select-control/select-control.component.scss +19 -0
  33. package/projects/nexheal-lib/src/lib/controls/select-control/select-control.component.spec.ts +22 -0
  34. package/projects/nexheal-lib/src/lib/controls/select-control/select-control.component.ts +375 -0
  35. package/projects/nexheal-lib/src/lib/controls/switch-control/switch-control.component.html +4 -0
  36. package/projects/nexheal-lib/src/lib/controls/switch-control/switch-control.component.scss +53 -0
  37. package/projects/nexheal-lib/src/lib/controls/switch-control/switch-control.component.spec.ts +22 -0
  38. package/projects/nexheal-lib/src/lib/controls/switch-control/switch-control.component.ts +93 -0
  39. package/projects/nexheal-lib/src/lib/controls/text-editor/text-editor.component.html +88 -0
  40. package/projects/nexheal-lib/src/lib/controls/text-editor/text-editor.component.scss +122 -0
  41. package/projects/nexheal-lib/src/lib/controls/text-editor/text-editor.component.spec.ts +22 -0
  42. package/projects/nexheal-lib/src/lib/controls/text-editor/text-editor.component.ts +314 -0
  43. package/projects/nexheal-lib/src/lib/controls/textarea-control/textarea-control.component.html +19 -0
  44. package/projects/nexheal-lib/src/lib/controls/textarea-control/textarea-control.component.scss +15 -0
  45. package/projects/nexheal-lib/src/lib/controls/textarea-control/textarea-control.component.spec.ts +22 -0
  46. package/projects/nexheal-lib/src/lib/controls/textarea-control/textarea-control.component.ts +83 -0
  47. package/projects/nexheal-lib/src/public-api.ts +13 -0
  48. package/projects/nexheal-lib/src/styles/nexheal.scss +1 -0
  49. package/projects/nexheal-lib/tsconfig.lib.json +18 -0
  50. package/projects/nexheal-lib/tsconfig.lib.prod.json +11 -0
  51. package/projects/nexheal-lib/tsconfig.spec.json +14 -0
  52. package/tsconfig.json +39 -0
  53. package/fesm2022/nexheal-lib.mjs +0 -2837
  54. package/fesm2022/nexheal-lib.mjs.map +0 -1
  55. package/index.d.ts +0 -498
  56. package/src/styles/fonts/icomoon.eot +0 -0
  57. package/src/styles/fonts/icomoon.svg +0 -46
  58. package/src/styles/fonts/icomoon.ttf +0 -0
  59. package/src/styles/fonts/icomoon.woff +0 -0
  60. package/src/styles/icon.css +0 -133
  61. package/src/styles/nexheal.scss +0 -2
  62. /package/{src → projects/nexheal-lib/src}/styles/_formcontrols.scss +0 -0
@@ -0,0 +1,4 @@
1
+ <label class="checkbox-container" [ngClass]="customClass" #checkboxContainer>
2
+ <input type="checkbox" [formControl]="checkboxControl" (focus)="onFocus($event)" (blur)="onBlur()" />
3
+ <span class="checkmark"></span>{{ title }}
4
+ </label>
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { CheckboxControl } from './checkbox-control.component';
3
+
4
+ describe('CheckboxControl', () => {
5
+ let component: CheckboxControl;
6
+ let fixture: ComponentFixture<CheckboxControl>;
7
+
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [CheckboxControl]
11
+ })
12
+ .compileComponents();
13
+
14
+ fixture = TestBed.createComponent(CheckboxControl);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,94 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, Input, Output, EventEmitter, forwardRef, Renderer2, ElementRef, ViewChild } from '@angular/core';
3
+ import { NG_VALUE_ACCESSOR, ControlValueAccessor, ReactiveFormsModule, FormControl, FormsModule } from '@angular/forms';
4
+
5
+ @Component({
6
+ selector: 'checkbox-control',
7
+ standalone: true,
8
+ imports: [
9
+ CommonModule,
10
+ ReactiveFormsModule,
11
+ FormsModule
12
+ ],
13
+ providers: [
14
+ {
15
+ provide: NG_VALUE_ACCESSOR,
16
+ useExisting: forwardRef(() => CheckboxControl),
17
+ multi: true,
18
+ },
19
+ ],
20
+ templateUrl: './checkbox-control.component.html'
21
+ })
22
+ export class CheckboxControl implements ControlValueAccessor {
23
+
24
+ @Input() title!: string;
25
+ @Input() customClass!: string;
26
+ @Input() type: 'boolean' | 'number' | 'string' = 'boolean';
27
+ @Input() set disabled(value: boolean) { this._disabled = value; this.setDisabledState(value); }
28
+ @Output() checkboxChange = new EventEmitter<boolean>();
29
+ @Output() blurEvent = new EventEmitter<void>();
30
+
31
+ @ViewChild('checkboxContainer') checkboxContainer!: ElementRef;
32
+
33
+ private _disabled = false;
34
+ checkboxControl = new FormControl({ value: false, disabled: this._disabled });
35
+ private onChange: any = () => { };
36
+ private onTouched: any = () => { };
37
+
38
+ constructor(
39
+ private _renderer: Renderer2,
40
+ private _elementRef: ElementRef
41
+ ) {
42
+ this.checkboxControl.valueChanges.subscribe(value => {
43
+ const converted = this.convertType(value);
44
+ this.onChange(converted);
45
+ this.onTouched();
46
+ this.checkboxChange.emit(converted);
47
+ });
48
+ }
49
+
50
+ writeValue(value: any): void {
51
+ if (value !== undefined && value !== null) {
52
+ this.checkboxControl.setValue(this.convertType(value), { emitEvent: false });
53
+ }
54
+ }
55
+
56
+ registerOnChange(fn: any): void {
57
+ this.onChange = fn;
58
+ }
59
+ registerOnTouched(fn: any): void {
60
+ this.onTouched = fn;
61
+ }
62
+
63
+ convertType(value: any): any {
64
+ switch (this.type) {
65
+ case 'number':
66
+ return Number(value == 2 ? 0 : value == 0 ? 2 : value);
67
+ case 'string':
68
+ return String(value);
69
+ default:
70
+ return !!value;
71
+ }
72
+ }
73
+
74
+ // events
75
+ onFocus(event: FocusEvent) {
76
+ const targetElement = event.target as Element;
77
+ if (targetElement.matches(':focus-visible')) {
78
+ this.checkboxContainer.nativeElement.classList.add('focused');
79
+ }
80
+ }
81
+ onBlur() {
82
+ this.blurEvent.emit();
83
+ this.checkboxContainer.nativeElement.classList.remove('focused');
84
+ }
85
+ setDisabledState(isDisabled: boolean): void {
86
+ this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
87
+ if (isDisabled) {
88
+ this.checkboxControl.disable();
89
+ } else {
90
+ this.checkboxControl.enable();
91
+ }
92
+ }
93
+
94
+ }
@@ -0,0 +1,61 @@
1
+ <div class="form-group input" [ngClass]="customClass">
2
+ @if (title) {
3
+ <label class="inp-label" [ngClass]="{ 'required': required }">{{ title }}</label>
4
+ }
5
+
6
+ @if (useReactiveForms) {
7
+ <input [type]="getInputType()" class="form-control" [placeholder]="placeholder" [formControl]="inputControl"
8
+ [ngClass]="{ 'is-invalid': error }" (focus)="onFocus()" (blur)="onBlur()" [readonly]="readonly"
9
+ (keypress)="onKeyPress($event)" [attr.autocomplete]="autocomplete || null" />
10
+ } @else {
11
+ <input [type]="getInputType()" class="form-control" [placeholder]="placeholder" [(ngModel)]="ngModel"
12
+ [ngClass]="{ 'is-invalid': error }" (focus)="onFocus()" (blur)="onBlur()" [readonly]="readonly"
13
+ (keypress)="onKeyPress($event)" />
14
+ }
15
+ @if(deFocus){
16
+ <span class="focus-border"></span>
17
+ }
18
+ @if (!inputLoader && showClearButton()) {
19
+ <label class="clear" (click)="resetInput()">
20
+ <i class="he he-close"></i>
21
+ </label>
22
+ }
23
+
24
+ @if (price) {
25
+ <label class="ls-price">
26
+ <i class="he he-rupee"></i>
27
+ </label>
28
+ }
29
+
30
+ @if (type === 'search') {
31
+ <label class="ls-search">
32
+ <i class="he he-search"></i>
33
+ </label>
34
+ }
35
+
36
+ @if (advSearch) {
37
+ <label class="rs-search" (click)="onAdvSearchClick()">
38
+ <i class="he he-search-adv"></i>
39
+ </label>
40
+ }
41
+
42
+ @if (search) {
43
+ <label class="rs-search" (click)="onSearchClick()">
44
+ <i class="he he-search"></i>
45
+ </label>
46
+ }
47
+
48
+ @if (type === 'password' && !disabled) {
49
+ <label class="toggle-eye" (click)="passwordVisible()">
50
+ <i class="he" [ngClass]="showPassword ? 'he-eye-off' : 'he-eye'"></i>
51
+ </label>
52
+ }
53
+
54
+ @if (inputLoader) {
55
+ <label class="loader input-loader"></label>
56
+ }
57
+
58
+ @if (error) {
59
+ <div class="val-msg">{{ errorMessage }}</div>
60
+ }
61
+ </div>
@@ -0,0 +1,132 @@
1
+ .form-group {
2
+ .toggle-eye,
3
+ ::ng-deep .toggle-eye {
4
+ top: 28px;
5
+ right: 10px;
6
+ padding: 5px;
7
+ line-height: 1;
8
+ position: absolute;
9
+ .he {
10
+ font-size: 18px;
11
+ }
12
+ .rb {
13
+ font-size: 17px;
14
+ color: #5f6554;
15
+ }
16
+ }
17
+ &.no-label {
18
+ .toggle-eye {
19
+ top: 9px;
20
+ }
21
+ }
22
+ &.group-sm {
23
+ .toggle-eye {
24
+ top: 5px;
25
+ }
26
+ }
27
+ &.left-input-search {
28
+ .ls-search {
29
+ top: 9px;
30
+ left: 10px;
31
+ position: absolute;
32
+ .he {
33
+ font-size: 1em;
34
+ color: #807a7a;
35
+ font-weight: 600;
36
+ }
37
+ }
38
+ .form-control {
39
+ text-indent: 1.25rem;
40
+ }
41
+ }
42
+ &.right-input-search {
43
+ .rs-search {
44
+ top: 27px;
45
+ right: 7px;
46
+ padding: 5px;
47
+ width: 30px;
48
+ height: 30px;
49
+ display: grid;
50
+ cursor: pointer;
51
+ position: absolute;
52
+ border-radius: 5px;
53
+ place-items: center;
54
+ i {
55
+ font-size: 16px;
56
+ color: #807a7a;
57
+ }
58
+ &:hover {
59
+ background: rgba(255, 127, 93, 0.1);
60
+ i {
61
+ color: #ff7f5d;
62
+ }
63
+ }
64
+ }
65
+ .rs-search + .rs-search {
66
+ right: 37px;
67
+ }
68
+ .clear {
69
+ right: 2.5rem;
70
+ }
71
+ .form-control {
72
+ padding-right: 4rem;
73
+ }
74
+ &.no-label {
75
+ .rs-search {
76
+ top: 7px;
77
+ }
78
+ .clear {
79
+ top: 10px;
80
+ }
81
+ }
82
+ &.group-sm {
83
+ &.no-label {
84
+ .rs-search {
85
+ top: 4px;
86
+ width: 27px;
87
+ height: 27px;
88
+ i {
89
+ font-size: 14px;
90
+ }
91
+ }
92
+ .clear {
93
+ top: 6px;
94
+ right: 2.25rem;
95
+ }
96
+ }
97
+ }
98
+ &.double-search {
99
+ .form-control {
100
+ padding-right: 6rem;
101
+ }
102
+ .clear {
103
+ right: 4.5rem;
104
+ }
105
+ }
106
+ }
107
+ &.price-input {
108
+ .form-control {
109
+ text-indent: 1rem;
110
+ }
111
+ .ls-price {
112
+ top: 21px;
113
+ padding: 8px;
114
+ display: flex;
115
+ color: #2ba599;
116
+ position: absolute;
117
+ align-items: center;
118
+ height: calc(var(--input-height) - 2px);
119
+ i {
120
+ top: 1px;
121
+ color: inherit;
122
+ cursor: default;
123
+ font-size: 12px;
124
+ }
125
+ }
126
+ }
127
+ .clear {
128
+ z-index: 4;
129
+ cursor: pointer;
130
+ background-color: transparent;
131
+ }
132
+ }
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { InputControl } from './input-control.component';
3
+
4
+ describe('InputControl', () => {
5
+ let component: InputControl;
6
+ let fixture: ComponentFixture<InputControl>;
7
+
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [InputControl]
11
+ })
12
+ .compileComponents();
13
+
14
+ fixture = TestBed.createComponent(InputControl);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,202 @@
1
+ import { CommonModule } from "@angular/common";
2
+ import { Component, Input, Output, EventEmitter, forwardRef, OnInit, OnDestroy, inject } from "@angular/core";
3
+ import { NG_VALUE_ACCESSOR, ControlValueAccessor, ReactiveFormsModule, FormControl, FormsModule } from "@angular/forms";
4
+ import { Subscription } from "rxjs";
5
+
6
+ @Component({
7
+ selector: "input-control",
8
+ standalone: true,
9
+ imports: [
10
+ CommonModule,
11
+ ReactiveFormsModule,
12
+ FormsModule
13
+ ],
14
+ providers: [
15
+ {
16
+ provide: NG_VALUE_ACCESSOR,
17
+ useExisting: forwardRef(() => InputControl),
18
+ multi: true,
19
+ },
20
+ ],
21
+ templateUrl: "./input-control.component.html",
22
+ styleUrls: ["./input-control.component.scss"],
23
+ })
24
+ export class InputControl implements ControlValueAccessor, OnInit, OnDestroy {
25
+
26
+ @Input() type: | "text" | "password" | "decimal" | "number" | "email" | "search" = "text";
27
+ @Input() title!: string;
28
+ @Input() placeholder: string = "";
29
+ @Input() customClass!: string;
30
+ @Input() clearVal: boolean = true;
31
+ @Input() required: boolean = false;
32
+ @Input() deFocus: boolean = true;
33
+ @Input() error: boolean = false;
34
+ @Input() errorMessage: string = "";
35
+ @Input() autocomplete: string = '';
36
+ @Input() readonly: boolean = false;
37
+ @Input() search: boolean = false;
38
+ @Input() price: boolean = false;
39
+ @Input() maxlength!: number;
40
+ @Input() ngModel!: string;
41
+ @Input() advSearch: boolean = false;
42
+ @Input() inputLoader: boolean = false;
43
+ @Input() useReactiveForms: boolean = true;
44
+ @Output() blurEvent = new EventEmitter<void>();
45
+ @Output() selectionCleared = new EventEmitter<void>();
46
+ @Output() inputChange = new EventEmitter<string>();
47
+ @Output() ngModelChange: EventEmitter<string> = new EventEmitter<string>();
48
+ @Output() searchClicked: EventEmitter<void> = new EventEmitter<void>();
49
+ @Output() advSearchClicked: EventEmitter<void> = new EventEmitter<void>();
50
+
51
+ private _disabled = false;
52
+ @Input() set disabled(isDisabled: boolean) {
53
+ this._disabled = isDisabled;
54
+ this.setDisabledState(isDisabled);
55
+ }
56
+ get disabled(): boolean {
57
+ return this._disabled;
58
+ }
59
+ private valueChangesSubscription!: Subscription;
60
+ private onChange: any = () => { };
61
+ private onTouched: any = () => { };
62
+
63
+ isFocused: boolean = false;
64
+ showPassword: boolean = false;
65
+ inputControl = new FormControl("");
66
+
67
+ ngOnInit() {
68
+ if (this.useReactiveForms) {
69
+ this.valueChangesSubscription = this.inputControl.valueChanges.subscribe(
70
+ (value) => {
71
+ this.onChange(value);
72
+ this.inputChange.emit(value ?? "");
73
+ }
74
+ );
75
+ }
76
+ }
77
+
78
+ ngOnDestroy(): void {
79
+ if (this.valueChangesSubscription) {
80
+ this.valueChangesSubscription.unsubscribe();
81
+ }
82
+ }
83
+
84
+ // input type
85
+ getInputType() {
86
+ return this.type === "password" && this.showPassword ? "text" : this.type;
87
+ }
88
+
89
+ writeValue(value: any): void {
90
+ if (this.useReactiveForms) {
91
+ if (value !== undefined) {
92
+ this.inputControl.setValue(value, {
93
+ emitEvent: false,
94
+ });
95
+ if (value != '') {
96
+ this.onChange(value);
97
+ }
98
+ }
99
+ if (this.inputControl.disabled !== this.disabled) {
100
+ this.setDisabledState(this.disabled);
101
+ }
102
+ } else {
103
+ this.ngModel = value;
104
+ }
105
+ }
106
+ registerOnChange(fn: any): void {
107
+ this.onChange = fn;
108
+ }
109
+ registerOnTouched(fn: any): void {
110
+ this.onTouched = fn;
111
+ }
112
+
113
+ // events
114
+ onBlur() {
115
+ this.blurEvent.emit();
116
+ setTimeout(() => {
117
+ this.isFocused = false;
118
+ this.onTouched();
119
+ if (!this.useReactiveForms) {
120
+ this.ngModelChange.emit(this.ngModel);
121
+ }
122
+ }, 200);
123
+ }
124
+ onFocus() {
125
+ this.isFocused = true;
126
+ }
127
+ onKeyPress(event: KeyboardEvent) {
128
+ let allowedKeys: string[] = [];
129
+
130
+ switch (this.type) {
131
+ case "number":
132
+ allowedKeys = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
133
+ break;
134
+ case "decimal":
135
+ allowedKeys = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."];
136
+ break;
137
+ default:
138
+ break;
139
+ }
140
+ if (this.search && event.key == "Enter") {
141
+ this.onSearchClick();
142
+ }
143
+ if (
144
+ (this.type == "number" || this.type == "decimal") &&
145
+ !allowedKeys.includes(event.key)
146
+ ) {
147
+ event.preventDefault();
148
+ return;
149
+ }
150
+ if (this.maxlength != null && (this.type == "number" || this.type == "decimal")) {
151
+ const currentValue: string = this.inputControl.value ?? "";
152
+ if (currentValue.length >= this.maxlength) {
153
+ event.preventDefault();
154
+ return;
155
+ }
156
+ }
157
+ }
158
+ setDisabledState(isDisabled: boolean): void {
159
+ this._disabled = isDisabled;
160
+ if (this._disabled && this.useReactiveForms) {
161
+ this.inputControl.disable({
162
+ emitEvent: false,
163
+ });
164
+ } else if (this.useReactiveForms) {
165
+ this.inputControl.enable({
166
+ emitEvent: false,
167
+ });
168
+ }
169
+ }
170
+
171
+ // actions
172
+ passwordVisible() {
173
+ this.showPassword = !this.showPassword;
174
+ }
175
+ onSearchClick(): void {
176
+ this.searchClicked.emit();
177
+ }
178
+ onAdvSearchClick(): void {
179
+ this.advSearchClicked.emit();
180
+ }
181
+
182
+ // clear
183
+ showClearButton() {
184
+ return (
185
+ this.isFocused &&
186
+ this.clearVal &&
187
+ this.inputControl.value &&
188
+ this.type !== "password"
189
+ );
190
+ }
191
+ resetInput() {
192
+ this.selectionCleared.emit();
193
+ if (this.useReactiveForms) {
194
+ this.inputControl.setValue("");
195
+ this.inputControl.markAsPristine({ onlySelf: true });
196
+
197
+ } else {
198
+ this.ngModel = "";
199
+ this.ngModelChange.emit(this.ngModel);
200
+ }
201
+ }
202
+ }
@@ -0,0 +1,72 @@
1
+ <div class="form-group multi-select" [ngClass]="customClass" (clickOutside)="selectListOutsideClick()">
2
+ @if (title) {
3
+ <label class="inp-label" [ngClass]="{ 'required': required }">{{ title }}</label>
4
+ }
5
+
6
+ <input #input type="text" class="form-control" placeholder="{{ placeholder }}" [formControl]="inputControl"
7
+ [ngClass]="{'is-invalid': error}" (blur)="onBlur($event)" (click)="toggleDropdown()" readonly
8
+ [value]="selectedItemList" (keydown)="onKeyDown($event)" [attr.autocomplete]="autocomplete || null" />
9
+
10
+ @if (deFocus) {
11
+ <span class="focus-border"></span>
12
+ }
13
+
14
+ @if (!inputLoader && isDropdownOpen && clearVal && selectedItems.length > 0) {
15
+ <label class="clear" (click)="resetSelection()">
16
+ <i class="he he-close"></i>
17
+ </label>
18
+ }
19
+
20
+ @if (!inputLoader) {
21
+ <label class="arrow">
22
+ <i class="he he-chevron-down"></i>
23
+ </label> }
24
+
25
+ @if (isDropdownOpen) {
26
+ <div #dropdown class="option-list">
27
+ @if (showSearch && filteredOptions.length > 5) {
28
+ <div class="list-filter">
29
+ <div>
30
+ <label class="checkbox-container select-all">
31
+ <input type="checkbox" [checked]="selectAllChecked" (change)="onSelectAllChange($event)" tabindex="-1" />
32
+ <span class="checkmark"></span>
33
+ </label>
34
+ </div>
35
+ <div class="form-group">
36
+ <input type="text" class="form-control" placeholder="Search..." (input)="handleInput($event) "
37
+ (keydown)="onKeyDown($event)" />
38
+ </div>
39
+ <div class="ms-close">
40
+ <button type="button" class="icon-button">
41
+ <a (click)="onCloseDropdown()"><i class="he he-close"></i></a>
42
+ </button>
43
+ </div>
44
+ </div>
45
+ }
46
+
47
+ <div class="list-wrap">
48
+ @for (option of filteredOptions; track option[optionDisplayProperty]; let i = $index) {
49
+ <div class="list-item" (change)="toggleCheckbox(option)" [ngClass]="{ 'highlighted': i === highlightedIndex }">
50
+ <label class="checkbox-container multi-select">
51
+ <input type="checkbox" [checked]="isSelected(option)" tabindex="-1" />
52
+ <span class="checkmark"></span>
53
+ {{ option[optionDisplayProperty] }}
54
+ </label>
55
+ </div>
56
+ }
57
+ </div>
58
+
59
+ @if (filteredOptions.length === 0) {
60
+ <div class="no-results">No results found</div>
61
+ }
62
+ </div>
63
+ }
64
+
65
+ @if (inputLoader) {
66
+ <label class="loader input-loader"></label>
67
+ }
68
+
69
+ @if (error) {
70
+ <div class="val-msg">{{ errorMessage }}</div>
71
+ }
72
+ </div>
@@ -0,0 +1,90 @@
1
+ .form-group {
2
+ &.multi-select {
3
+ .option-list {
4
+ .list-filter {
5
+ gap: 10px;
6
+ display: flex;
7
+ padding: 9px 10px;
8
+ align-items: center;
9
+ border-bottom: 1px solid #efefef;
10
+ .checkbox-container {
11
+ &.select-all {
12
+ top: -10px;
13
+ margin-bottom: 0;
14
+ padding-left: 22px;
15
+ }
16
+ }
17
+ .form-group {
18
+ margin-bottom: 0;
19
+ width: calc(100% - 70px);
20
+ .form-control {
21
+ height: 34px;
22
+ border-radius: 5px;
23
+ background: #ffffff;
24
+ padding: 0.275rem 0.5rem;
25
+ border: 1px solid #cccccc !important;
26
+ &::placeholder {
27
+ font-size: 0.925em;
28
+ }
29
+ }
30
+ }
31
+ .ms-close {
32
+ .icon-button {
33
+ background: #f0f0f0;
34
+ a {
35
+ width: 28px;
36
+ height: 28px;
37
+ display: grid;
38
+ cursor: pointer;
39
+ position: relative;
40
+ border-radius: 5px;
41
+ place-items: center;
42
+ text-decoration: none;
43
+ border: 1px solid #efefef;
44
+ box-shadow: 0 0 3px #ebebeb;
45
+ i {
46
+ font-size: 14px;
47
+ }
48
+ &:hover {
49
+ background: rgba(255, 127, 93, 0.1);
50
+ i {
51
+ color: #ff7f5d;
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ .list-wrap {
59
+ overflow: auto;
60
+ max-height: calc(233px - 53px);
61
+ }
62
+ .list-item {
63
+ padding: 0;
64
+ .checkbox-container {
65
+ &.multi-select {
66
+ width: 100%;
67
+ font-size: 1em;
68
+ margin-bottom: 0;
69
+ font-weight: 400;
70
+ color: #584e4e;
71
+ letter-spacing: 0.015rem;
72
+ padding: 10px 10px 10px 40px;
73
+ .checkmark {
74
+ top: 9px;
75
+ left: 10px;
76
+ }
77
+ }
78
+ }
79
+ }
80
+ .no-results {
81
+ padding: 10px;
82
+ color: #9b9b9b;
83
+ text-align: center;
84
+ }
85
+ }
86
+ .clear {
87
+ right: 30px;
88
+ }
89
+ }
90
+ }