ngx-opalbytes-components 1.18.0 → 1.20.0

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 (78) hide show
  1. package/README.md +103 -0
  2. package/cli/cao-comp.cjs +186 -0
  3. package/fesm2022/ngx-opalbytes-components.mjs +331 -76
  4. package/fesm2022/ngx-opalbytes-components.mjs.map +1 -1
  5. package/package.json +4 -1
  6. package/src/lib/shared/components/autocomplete/autocomplete.component.html +126 -0
  7. package/src/lib/shared/components/autocomplete/autocomplete.component.scss +150 -0
  8. package/src/lib/shared/components/autocomplete/autocomplete.component.ts +552 -0
  9. package/src/lib/shared/components/base-button/base-button.component.html +33 -0
  10. package/src/lib/shared/components/base-button/base-button.component.scss +14 -0
  11. package/src/lib/shared/components/base-button/base-button.component.spec.ts +64 -0
  12. package/src/lib/shared/components/base-button/base-button.component.ts +48 -0
  13. package/src/lib/shared/components/base-icon/base-icon.css +0 -0
  14. package/src/lib/shared/components/base-icon/base-icon.html +11 -0
  15. package/src/lib/shared/components/base-icon/base-icon.spec.ts +23 -0
  16. package/src/lib/shared/components/base-icon/base-icon.ts +18 -0
  17. package/src/lib/shared/components/base-input/base-input.css +193 -0
  18. package/src/lib/shared/components/base-input/base-input.html +43 -0
  19. package/src/lib/shared/components/base-input/base-input.spec.ts +146 -0
  20. package/src/lib/shared/components/base-input/base-input.ts +133 -0
  21. package/src/lib/shared/components/base-time-range/base-time-range.css +27 -0
  22. package/src/lib/shared/components/base-time-range/base-time-range.html +23 -0
  23. package/src/lib/shared/components/base-time-range/base-time-range.spec.ts +27 -0
  24. package/src/lib/shared/components/base-time-range/base-time-range.ts +61 -0
  25. package/src/lib/shared/components/base-toggle/base-toggle.component.html +28 -0
  26. package/src/lib/shared/components/base-toggle/base-toggle.component.scss +45 -0
  27. package/src/lib/shared/components/base-toggle/base-toggle.component.spec.ts +22 -0
  28. package/src/lib/shared/components/base-toggle/base-toggle.component.ts +138 -0
  29. package/src/lib/shared/components/card/card.component.css +264 -0
  30. package/src/lib/shared/components/card/card.component.html +103 -0
  31. package/src/lib/shared/components/card/card.component.ts +63 -0
  32. package/src/lib/shared/components/date-picker/date-picker.html +82 -0
  33. package/src/lib/shared/components/date-picker/date-picker.scss +8 -0
  34. package/src/lib/shared/components/date-picker/date-picker.spec.ts +23 -0
  35. package/src/lib/shared/components/date-picker/date-picker.ts +165 -0
  36. package/src/lib/shared/components/drop-down/drop-down.css +61 -0
  37. package/src/lib/shared/components/drop-down/drop-down.html +96 -0
  38. package/src/lib/shared/components/drop-down/drop-down.spec.ts +335 -0
  39. package/src/lib/shared/components/drop-down/drop-down.ts +335 -0
  40. package/src/lib/shared/components/footer/footer.css +29 -0
  41. package/src/lib/shared/components/footer/footer.html +10 -0
  42. package/src/lib/shared/components/footer/footer.spec.ts +22 -0
  43. package/src/lib/shared/components/footer/footer.ts +15 -0
  44. package/src/lib/shared/components/index.ts +19 -0
  45. package/src/lib/shared/components/kpi/kpi.css +0 -0
  46. package/src/lib/shared/components/kpi/kpi.html +11 -0
  47. package/src/lib/shared/components/kpi/kpi.spec.ts +38 -0
  48. package/src/lib/shared/components/kpi/kpi.ts +25 -0
  49. package/src/lib/shared/components/links-button/links-button.css +70 -0
  50. package/src/lib/shared/components/links-button/links-button.html +23 -0
  51. package/src/lib/shared/components/links-button/links-button.spec.ts +139 -0
  52. package/src/lib/shared/components/links-button/links-button.ts +45 -0
  53. package/src/lib/shared/components/paginator/paginator.css +0 -0
  54. package/src/lib/shared/components/paginator/paginator.html +10 -0
  55. package/src/lib/shared/components/paginator/paginator.spec.ts +23 -0
  56. package/src/lib/shared/components/paginator/paginator.ts +25 -0
  57. package/src/lib/shared/components/stepper/step/step.css +8 -0
  58. package/src/lib/shared/components/stepper/step/step.html +1 -0
  59. package/src/lib/shared/components/stepper/step/step.spec.ts +131 -0
  60. package/src/lib/shared/components/stepper/step/step.ts +14 -0
  61. package/src/lib/shared/components/stepper/stepper.css +17 -0
  62. package/src/lib/shared/components/stepper/stepper.html +11 -0
  63. package/src/lib/shared/components/stepper/stepper.spec.ts +238 -0
  64. package/src/lib/shared/components/stepper/stepper.ts +57 -0
  65. package/src/lib/shared/components/tab-group/tab-group.component.html +84 -0
  66. package/src/lib/shared/components/tab-group/tab-group.component.scss +151 -0
  67. package/src/lib/shared/components/tab-group/tab-group.spec.ts +22 -0
  68. package/src/lib/shared/components/tab-group/tab-group.ts +218 -0
  69. package/src/lib/shared/components/tab-panel/tab-content.directive.ts +7 -0
  70. package/src/lib/shared/components/tab-panel/tab-label.directive.ts +7 -0
  71. package/src/lib/shared/components/tab-panel/tab-panel.css +0 -0
  72. package/src/lib/shared/components/tab-panel/tab-panel.spec.ts +22 -0
  73. package/src/lib/shared/components/tab-panel/tab-panel.ts +31 -0
  74. package/src/lib/shared/components/time-picker/time-picker.css +84 -0
  75. package/src/lib/shared/components/time-picker/time-picker.html +21 -0
  76. package/src/lib/shared/components/time-picker/time-picker.spec.ts +23 -0
  77. package/src/lib/shared/components/time-picker/time-picker.ts +90 -0
  78. package/types/ngx-opalbytes-components.d.ts +70 -13
@@ -0,0 +1,11 @@
1
+ @if (imgSource) {
2
+ @if (isLucideIcon) {
3
+ <div class="icon">
4
+ <svg [lucideIcon]="imgSource" [style.color]="iconColor" [strokeWidth]="strokeWidthIcon" [size]="size"></svg>
5
+ </div>
6
+ } @else {
7
+ <div class="icon">
8
+ <img alt="ícone de início" [src]="imgSource" />
9
+ </div>
10
+ }
11
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { CaoBaseIcon } from './base-icon';
4
+
5
+ describe('CaoBaseIcon', () => {
6
+ let component: CaoBaseIcon;
7
+ let fixture: ComponentFixture<CaoBaseIcon>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [CaoBaseIcon]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(CaoBaseIcon);
16
+ component = fixture.componentInstance;
17
+ await fixture.whenStable();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,18 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, Input } from '@angular/core';
3
+
4
+ import { LucideDynamicIcon } from '@lucide/angular';
5
+
6
+ @Component({
7
+ selector: 'cao-base-icon',
8
+ imports: [CommonModule, LucideDynamicIcon],
9
+ templateUrl: './base-icon.html',
10
+ styleUrl: './base-icon.css',
11
+ })
12
+ export class CaoBaseIcon {
13
+ @Input() imgSource = ""
14
+ @Input() isLucideIcon = true
15
+ @Input() strokeWidthIcon = 1
16
+ @Input() iconColor = ""
17
+ @Input() size = 32
18
+ }
@@ -0,0 +1,193 @@
1
+ .form-field {
2
+ display: flex;
3
+ flex-direction: column;
4
+ width: 100%;
5
+ height: 100%;
6
+ }
7
+
8
+ label {
9
+ font-size: 12px;
10
+ color: var(--primary);
11
+ font-weight: 700;
12
+ text-transform: uppercase;
13
+ white-space: nowrap;
14
+ }
15
+
16
+ .input-wrapper {
17
+ position: relative;
18
+ width: 100%;
19
+ height: 100%;
20
+ }
21
+
22
+ .input-wrapper input,
23
+ .input-wrapper textarea {
24
+ width: 100%;
25
+ height: 100%;
26
+ border: none;
27
+ background-color: var(--input-background);
28
+ border-radius: 8px;
29
+ padding: 14px 10px;
30
+ color: var(--text-color-input);
31
+ text-overflow: ellipsis;
32
+ white-space: nowrap;
33
+ overflow: hidden;
34
+ }
35
+
36
+ .input-wrapper input::placeholder,
37
+ .input-wrapper textarea::placeholder {
38
+ color: var(--input-text);
39
+ }
40
+
41
+ .input-wrapper input:focus,
42
+ .input-wrapper textarea:focus {
43
+ outline: none;
44
+ box-shadow: none;
45
+ }
46
+
47
+ .input-wrapper.has-leading-icon input {
48
+ padding-left: 33px;
49
+ }
50
+
51
+ .input-wrapper.has-trailing-icon input {
52
+ padding-right: 30px;
53
+ }
54
+
55
+ .input-wrapper img {
56
+ width: 100%;
57
+ height: auto;
58
+ }
59
+
60
+ .input-wrapper .icon {
61
+ position: absolute;
62
+ top: 50%;
63
+ transform: translateY(-50%);
64
+ width: 15px;
65
+ height: 15px;
66
+ pointer-events: none;
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ }
71
+
72
+ .input-wrapper.has-leading-icon .icon:first-of-type {
73
+ left: 8px;
74
+ }
75
+
76
+ .input-wrapper.has-trailing-icon .icon:last-of-type {
77
+ right: 8px;
78
+ }
79
+
80
+ .input-wrapper .search-icon-border {
81
+ position: absolute;
82
+ top: 50%;
83
+ right: 14px;
84
+ transform: translateY(-50%);
85
+ border-left: 1px solid var(--line-color);
86
+ padding-left: 8px;
87
+ height: 24px;
88
+ display: flex;
89
+ align-items: center;
90
+ }
91
+
92
+ .input-wrapper .search-icon {
93
+ width: 16px;
94
+ height: 24px;
95
+ cursor: pointer;
96
+ transition: filter 0.2s;
97
+ }
98
+
99
+ .input-wrapper .search-icon:hover {
100
+ filter: invert(62%) sepia(92%) saturate(747%) hue-rotate(142deg) brightness(97%) contrast(101%);
101
+ }
102
+
103
+ [type="date"] {
104
+ height: 43px;
105
+ padding: 14px 0 14px 12px !important;
106
+ }
107
+
108
+
109
+ [type="date"].invalid::-webkit-calendar-picker-indicator {
110
+ border-left: 1px solid var(--error);
111
+ }
112
+
113
+ [type="date"].valid::-webkit-calendar-picker-indicator {
114
+ border-left: 1px solid var(--success);
115
+ }
116
+
117
+ .input-date-disabled {
118
+ background: url("/assets/images/svg/icon-date-border.svg") no-repeat right 12px center;
119
+ background-size: 30px;
120
+ border: none;
121
+ border-radius: 8px;
122
+ background-color: var(--input-background);
123
+ padding: 12px 40px 12px 16px;
124
+ width: 100%;
125
+ color: var(--input-text);
126
+ }
127
+
128
+ .input-date-disabled::placeholder {
129
+ color: var(--input-text);
130
+ }
131
+
132
+ .input-secondary {
133
+ width: 100%;
134
+ border: 1px solid var(--data-bg) !important;
135
+ background-color: var(--white) !important;
136
+ }
137
+
138
+ .input-secondary.invalid {
139
+ border: 1px solid var(--error) !important;
140
+ }
141
+
142
+ .input-secondary.valid {
143
+ border: 1px solid var(--success) !important;
144
+ }
145
+
146
+ .input-wrapper .invalid {
147
+ border: 1px solid var(--error);
148
+ }
149
+
150
+ .input-wrapper .valid {
151
+ border: 1px solid var(--success);
152
+ }
153
+
154
+ .input-border-primary {
155
+ border: 1px solid var(--primary) !important;
156
+ background-color: var(--white) !important;
157
+ }
158
+
159
+ .input-border-primary.invalid {
160
+ border: 1px solid var(--error) !important;
161
+ }
162
+
163
+ .input-border-primary.valid {
164
+ border: 1px solid var(--success) !important;
165
+ }
166
+
167
+ /* stylelint-disable selector-pseudo-element-no-unknown */
168
+ ::ng-deep .custom-arrow-tooltip {
169
+ background-color: var(--color-tooltip);
170
+ color: var(--white);
171
+ padding: 0 4px;
172
+ border-radius: 6px;
173
+ font-size: 12px;
174
+ position: relative;
175
+ text-align: center;
176
+ max-width: 260px;
177
+ box-shadow: 0 2px 10px rgb(0 0 0 / 30%);
178
+ }
179
+
180
+ ::ng-deep .input-component .cdk-overlay-pane .custom-arrow-tooltip::after {
181
+ content: "";
182
+ position: absolute;
183
+ top: -6px;
184
+ rotate: 180deg;
185
+ right: 50%;
186
+ transform: translateX(-50%);
187
+ width: 0;
188
+ height: 0;
189
+ border-left: 8px solid transparent;
190
+ border-right: 8px solid transparent;
191
+ border-top: 8px solid var(--color-tooltip);
192
+ }
193
+ /* stylelint-enable selector-pseudo-element-no-unknown */
@@ -0,0 +1,43 @@
1
+ <div class="form-field input-component" [class.search-mode]="searchMode">
2
+ <div class="input-wrapper" [class.has-leading-icon]="_leadingIcon" [class.has-trailing-icon]="_trailingIcon"
3
+ [class.focused]="isFocused">
4
+ @if (_leadingIcon) { @if (isLucideIcon) {
5
+ <div class="icon">
6
+ <svg [lucideIcon]="_leadingIcon" [style.color]="iconColor"></svg>
7
+ </div>
8
+ } @else {
9
+ <div class="icon">
10
+ <img alt="ícone de início" [src]="_leadingIcon"/>
11
+ </div>
12
+ } } @switch (type) {
13
+ @case ('textarea') {
14
+ <textarea matTooltip="{{ tooltip }}" matTooltipPosition="above" matTooltipClass="custom-arrow-tooltip" [attr.data-cy]="dataCy"
15
+ [placeholder]="placeholder" [disabled]="isDisabled" [ngClass]="[
16
+ inputClass,
17
+ control?.touched && control?.invalid ? 'invalid' : '',
18
+ control?.touched && control?.valid && control?.value ? 'valid' : ''
19
+ ]" [attr.maxlength]="maxLength"
20
+ [rows]="textareaRows" [mask]="mask" [allowNegativeNumbers]="allowNegativeNumbers" [thousandSeparator]="thousandSeparator" [decimalMarker]="decimalMarker" [separatorLimit]="separatorLimit"
21
+ [(ngModel)]="value" (input)="onInput($event)"
22
+ (focus)="onFocus()" (blur)="onBlur()"></textarea>
23
+ }
24
+ @default {
25
+ <input matTooltip="{{ tooltip }}" matTooltipPosition="below" matTooltipClass="custom-arrow-tooltip" [attr.data-cy]="dataCy" [type]="type"
26
+ [placeholder]="placeholder" [disabled]="isDisabled" [ngClass]="[
27
+ inputClass,
28
+ control?.touched && control?.invalid ? 'invalid' : '',
29
+ control?.touched && control?.valid && control?.value ? 'valid' : ''
30
+ ]" [attr.maxlength]="maxLength"
31
+ [mask]="mask" [allowNegativeNumbers]="allowNegativeNumbers" [thousandSeparator]="thousandSeparator" [decimalMarker]="decimalMarker" [separatorLimit]="separatorLimit" [(ngModel)]="value" (input)="onInput($event)"
32
+ (change)="onInputChange($event)" (focus)="onFocus()" (blur)="onBlur()" />
33
+ } } @if (_trailingIcon) { @if (isLucideIcon) {
34
+ <div class="icon">
35
+ <svg [lucideIcon]="_trailingIcon" [style.color]="iconColor"></svg>
36
+ </div>
37
+ } @else {
38
+ <div class="icon">
39
+ <img alt="ícone de fim" [src]="_trailingIcon" />
40
+ </div>
41
+ } }
42
+ </div>
43
+ </div>
@@ -0,0 +1,146 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ import { ComponentFixture, TestBed } from "@angular/core/testing";
3
+ import { FormsModule } from "@angular/forms";
4
+ import { CaoBaseInput } from "./base-input";
5
+ import { EventEmitter } from '@angular/core';
6
+
7
+ describe("CaoBaseInputComponent", () => {
8
+ let component: CaoBaseInput;
9
+ let fixture: ComponentFixture<CaoBaseInput>;
10
+
11
+ beforeEach(async () => {
12
+ await TestBed.configureTestingModule({
13
+ imports: [FormsModule, CaoBaseInput],
14
+ }).compileComponents();
15
+
16
+ fixture = TestBed.createComponent(CaoBaseInput);
17
+ component = fixture.componentInstance;
18
+ fixture.detectChanges();
19
+ });
20
+
21
+ it("deve ser criado", () => {
22
+ expect(component).toBeTruthy();
23
+ });
24
+
25
+ it("deve ter type e placeholder padrão definidos como 'text' e ''", () => {
26
+ expect(component.type).toBe("text");
27
+ expect(component.placeholder).toBe("");
28
+ });
29
+
30
+ it("deve aplicar o placeholder corretamente", () => {
31
+ component.placeholder = "Digite aqui";
32
+ fixture.detectChanges();
33
+ const input = fixture.nativeElement.querySelector("input");
34
+ expect(input.placeholder).toBe("Digite aqui");
35
+ });
36
+
37
+ it("deve aplicar o tipo de input corretamente", () => {
38
+ component.type = "password";
39
+ fixture.detectChanges();
40
+ const input = fixture.nativeElement.querySelector("input");
41
+ expect(input.type).toBe("password");
42
+ });
43
+
44
+ it("deve aplicar o maxlength corretamente", () => {
45
+ component.maxLength = 5;
46
+ fixture.detectChanges();
47
+ const input = fixture.nativeElement.querySelector("input");
48
+ expect(input.getAttribute("maxlength")).toBe("5");
49
+ });
50
+
51
+ it("deve escrever o valor corretamente", () => {
52
+ component.writeValue("valor inicial");
53
+ expect(component.value).toBe("valor inicial");
54
+ });
55
+
56
+ it("deve lidar com valores nulos ou indefinidos no writeValue", () => {
57
+ component.writeValue(null);
58
+ expect(component.value).toBe("");
59
+ component.writeValue(undefined);
60
+ expect(component.value).toBe("");
61
+ });
62
+
63
+ it("deve registrar função onChange corretamente", () => {
64
+ const mockFn = vi.fn();
65
+ component.registerOnChange(mockFn);
66
+ component.onChange("teste");
67
+ expect(mockFn).toHaveBeenCalledWith("teste");
68
+ });
69
+
70
+ it("deve registrar função onTouched corretamente", () => {
71
+ const mockFn = vi.fn();
72
+ component.registerOnTouched(mockFn);
73
+ component.onTouched();
74
+ expect(mockFn).toHaveBeenCalledWith();
75
+ });
76
+
77
+ it("deve desabilitar o input quando setDisabledState(true) é chamado", () => {
78
+ component.setDisabledState(true);
79
+ fixture.detectChanges();
80
+ expect(component.isDisabled).toBeTruthy();
81
+ });
82
+
83
+ it("deve atualizar o valor quando o input é alterado", () => {
84
+ const input = fixture.nativeElement.querySelector("input");
85
+ input.value = "novo valor";
86
+ input.dispatchEvent(new Event("input"));
87
+ fixture.detectChanges();
88
+ expect(component.value).toBe("novo valor");
89
+ });
90
+
91
+ it("deve emitir o evento valueChange quando o valor é alterado", () => {
92
+ const emitSpy = vi.spyOn(component.valueChange as EventEmitter<string>, 'emit');
93
+ const input = fixture.nativeElement.querySelector("input");
94
+ input.value = "valor teste";
95
+ input.dispatchEvent(new Event("input"));
96
+ fixture.detectChanges();
97
+ expect(emitSpy).toHaveBeenCalledWith("valor teste");
98
+ });
99
+
100
+ it("deve emitir evento searchClick ao chamar onSearchClick", () => {
101
+ const emitSpy = vi.spyOn(component.searchClick as EventEmitter<void>, 'emit');
102
+ component.onSearchClick();
103
+ expect(emitSpy).toHaveBeenCalledWith();
104
+ });
105
+
106
+ it("deve chamar onTouched quando o input perde o foco", () => {
107
+ const mockTouchedFn = vi.fn();
108
+ component.registerOnTouched(mockTouchedFn);
109
+ fixture.detectChanges();
110
+
111
+ const input = fixture.nativeElement.querySelector("input");
112
+ input.dispatchEvent(new Event("blur"));
113
+
114
+ expect(mockTouchedFn).toHaveBeenCalledWith();
115
+ });
116
+
117
+ it("deve ativar isFocused ao focar", () => {
118
+ const input = fixture.nativeElement.querySelector("input");
119
+ input.dispatchEvent(new Event("focus"));
120
+ expect(component.isFocused).toBeTruthy();
121
+ });
122
+
123
+ it("deve desativar isFocused ao desfocar", () => {
124
+ const input = fixture.nativeElement.querySelector("input");
125
+ input.dispatchEvent(new Event("focus"));
126
+ input.dispatchEvent(new Event("blur"));
127
+ expect(component.isFocused).toBeFalsy();
128
+ });
129
+
130
+ it("deve retornar o valor de controlName via controlNameValue", () => {
131
+ component.controlName = "cpf";
132
+ expect(component.controlNameValue).toBe("cpf");
133
+ });
134
+
135
+ it("deve aplicar ícone do material se isLucideIcon for true", () => {
136
+ component.isLucideIcon = true;
137
+ component.leadingIcon = "home";
138
+ expect(component._leadingIcon).toBe("home");
139
+ });
140
+
141
+ it("deve manter a máscara definida corretamente", () => {
142
+ component.mask = "000.000.000-00";
143
+ fixture.detectChanges();
144
+ expect(component.mask).toBe("000.000.000-00");
145
+ });
146
+ });
@@ -0,0 +1,133 @@
1
+ import { CommonModule } from "@angular/common";
2
+ import { Component, EventEmitter, Input, Output } from "@angular/core";
3
+ import { AbstractControl, ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from "@angular/forms";
4
+ import { MatTooltipModule } from "@angular/material/tooltip";
5
+
6
+ import { LucideDynamicIcon } from "@lucide/angular";
7
+ import { NgxMaskDirective, provideNgxMask } from "ngx-mask";
8
+
9
+ export type CaoTypeInputs = 'text' | 'textarea' | 'number' | 'password' | 'date'
10
+
11
+ @Component({
12
+ standalone: true,
13
+ selector: "cao-input",
14
+ templateUrl: "./base-input.html",
15
+ styleUrls: ["./base-input.css"],
16
+ imports: [CommonModule, FormsModule, NgxMaskDirective, MatTooltipModule, LucideDynamicIcon],
17
+ providers: [
18
+ {
19
+ provide: NG_VALUE_ACCESSOR,
20
+ useExisting: CaoBaseInput,
21
+ multi: true,
22
+ },
23
+ provideNgxMask(),
24
+ ],
25
+ })
26
+ export class CaoBaseInput implements ControlValueAccessor {
27
+ @Input() type: CaoTypeInputs = "text" ;
28
+ @Input() placeholder = "";
29
+ @Input() inputClass = "";
30
+ @Input() value: string | number | boolean | Date = "";
31
+ @Input() errorMessage = "";
32
+ @Input() isDisabled = false;
33
+ @Input() maxLength?: number;
34
+ @Input() searchMode = false;
35
+ @Input() showBorder = false;
36
+ @Input() isLucideIcon = false;
37
+ @Input() iconColor = "";
38
+ @Input() mask?: string;
39
+ @Input() control?: AbstractControl | null;
40
+ @Input() tooltip = "";
41
+ @Input() dataCy?: string = "";
42
+ @Input() textareaRows?: string = "";
43
+
44
+ @Input() decimalMarker: "." | "," | [".", ","] = ",";
45
+ @Input() thousandSeparator = ".";
46
+ @Input() allowNegativeNumbers = false;
47
+ @Input() separatorLimit = "";
48
+
49
+ @Input() set leadingIcon(value: string) {
50
+ this._leadingIcon = value;
51
+ this.icon = true;
52
+ }
53
+
54
+ @Input() set trailingIcon(value: string) {
55
+ this._trailingIcon = value;
56
+ this.icon = true;
57
+ }
58
+
59
+ @Output() readonly valueChange = new EventEmitter<string>();
60
+ @Output() readonly searchClick = new EventEmitter<void>();
61
+ @Output() readonly inputChange = new EventEmitter<string>();
62
+
63
+ isFocused = false;
64
+ icon = false;
65
+ _leadingIcon?: string;
66
+ _trailingIcon?: string;
67
+
68
+ onChange: any = () => { };
69
+ onTouched: any = () => { };
70
+
71
+ get hasError() {
72
+ return !!this.errorMessage;
73
+ }
74
+
75
+ @Input() controlName = "";
76
+
77
+ get controlNameValue(): string {
78
+ return this.controlName;
79
+ }
80
+
81
+ onInput(event: Event) {
82
+ const newValue = (event.target as HTMLInputElement).value;
83
+ this.value = newValue;
84
+ this.onChange(newValue);
85
+ this.valueChange.emit(newValue);
86
+ }
87
+
88
+ onInputChange(event: Event) {
89
+ const newValue = (event.target as HTMLInputElement).value;
90
+ this.value = newValue;
91
+ this.inputChange.emit(newValue);
92
+ }
93
+
94
+ onFocus() {
95
+ this.isFocused = true;
96
+ this.onTouched();
97
+ }
98
+
99
+ onBlur() {
100
+ this.isFocused = false;
101
+ this.onTouched();
102
+
103
+ if (this.control?.touched && this.control?.valid && this.control?.value) {
104
+ setTimeout(() => {
105
+ const active = document.activeElement as HTMLElement;
106
+ const current = document.querySelector(`[formcontrolname="${this.controlNameValue}"]`);
107
+ if (!current || !active || !current.contains(active)) {
108
+ this.control?.markAsUntouched();
109
+ }
110
+ });
111
+ }
112
+ }
113
+
114
+ onSearchClick() {
115
+ this.searchClick.emit();
116
+ }
117
+
118
+ writeValue(value: string | null | undefined): void {
119
+ this.value = value || "";
120
+ }
121
+
122
+ registerOnChange(fn: any): void {
123
+ this.onChange = fn;
124
+ }
125
+
126
+ registerOnTouched(fn: any): void {
127
+ this.onTouched = fn;
128
+ }
129
+
130
+ setDisabledState(isDisabled: boolean): void {
131
+ this.isDisabled = isDisabled;
132
+ }
133
+ }
@@ -0,0 +1,27 @@
1
+ .input-data-field {
2
+ height: 44px;
3
+ border-radius: 8px;
4
+ font-size: 12px;
5
+ font-weight: 600;
6
+ }
7
+
8
+ .input-data-field.mat-mdc-text-field-wrapper {
9
+ height: 100% !important;
10
+ }
11
+
12
+ .input-data-field.mat-mdc-form-field-flex {
13
+ height: 100% !important;
14
+ }
15
+
16
+ .input-data-field.mat-mdc-form-field-infix {
17
+ height: 100%;
18
+ padding: 10px 0 !important;
19
+ }
20
+
21
+ .input-data-field.mat-mdc-notch-piece {
22
+ border: none;
23
+ }
24
+
25
+ .input-data-field.mat-date-range-input-container {
26
+ font-size: 12px;
27
+ }
@@ -0,0 +1,23 @@
1
+ <label class="label-dropw-down" [for]="controlName">{{ label }}</label>
2
+ <mat-form-field class="input-data-field" subscriptSizing="dynamic" appearance="outline">
3
+ <mat-date-range-input [rangePicker]="picker" [max]="maxDate"
4
+ [attr.dataCy]="this.dataCy"
5
+ >
6
+ <input
7
+ #startDateInput
8
+ matStartDate
9
+ placeholder="DATA INÍCIO"
10
+ [tabIndex]="1"
11
+ [value]="startDate"
12
+ (dateInput)="onSelectStartDate($event)" />
13
+ <input
14
+ #endDateInput
15
+ matEndDate
16
+ placeholder="DATA FIM"
17
+ [tabIndex]="2"
18
+ [value]="finalDate"
19
+ (dateInput)="onInputMaxDate($event)" />
20
+ </mat-date-range-input>
21
+ <mat-datepicker-toggle matIconSuffix [for]="picker" />
22
+ <mat-date-range-picker #picker />
23
+ </mat-form-field>
@@ -0,0 +1,27 @@
1
+ import { provideNativeDateAdapter } from '@angular/material/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+
4
+ import { BaseTimeRange } from './base-time-range';
5
+
6
+ describe('BaseTimeRange', () => {
7
+ let component: BaseTimeRange;
8
+ let fixture: ComponentFixture<BaseTimeRange>;
9
+
10
+ beforeEach(async () => {
11
+ await TestBed.configureTestingModule({
12
+ imports: [BaseTimeRange],
13
+ providers: [
14
+ provideNativeDateAdapter()
15
+ ]
16
+ })
17
+ .compileComponents();
18
+
19
+ fixture = TestBed.createComponent(BaseTimeRange);
20
+ component = fixture.componentInstance;
21
+ await fixture.whenStable();
22
+ });
23
+
24
+ it('should create', () => {
25
+ expect(component).toBeTruthy();
26
+ });
27
+ });