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,238 @@
1
+ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
2
+ import { ComponentFixture, TestBed } from "@angular/core/testing";
3
+ import { StepperComponent } from "./stepper";
4
+ import { StepComponent } from "./step/step";
5
+ import { Component, QueryList, EventEmitter } from "@angular/core";
6
+ import { By } from "@angular/platform-browser";
7
+
8
+ describe("StepperComponent", () => {
9
+ let component: StepperComponent;
10
+ let fixture: ComponentFixture<StepperComponent>;
11
+
12
+ @Component({
13
+ selector: "cao-step",
14
+ template: "<div></div>",
15
+ standalone: true,
16
+ })
17
+ class MockStepComponent {
18
+ isActive = false;
19
+ }
20
+
21
+ beforeEach(async () => {
22
+ await TestBed.configureTestingModule({
23
+ imports: [StepperComponent, MockStepComponent],
24
+ })
25
+ .overrideComponent(StepperComponent, {
26
+ remove: { imports: [StepComponent] },
27
+ add: { imports: [MockStepComponent] },
28
+ })
29
+ .compileComponents();
30
+
31
+ fixture = TestBed.createComponent(StepperComponent);
32
+ component = fixture.componentInstance;
33
+ });
34
+
35
+ afterEach(() => {
36
+ vi.clearAllMocks();
37
+ });
38
+
39
+ it("deve criar o componente", () => {
40
+ expect(component).toBeTruthy();
41
+ });
42
+
43
+ describe("ngAfterContentInit", () => {
44
+ it("deve ativar o primeiro passo e definir lengthStep quando há passos", () => {
45
+ const step1 = new MockStepComponent();
46
+ const step2 = new MockStepComponent();
47
+ component.steps = new QueryList<StepComponent>();
48
+ component.steps.reset([step1 as StepComponent, step2 as StepComponent]);
49
+
50
+ component.ngAfterContentInit();
51
+
52
+ expect(component.steps.toArray()[0].isActive).toBe(true);
53
+ expect(component.lengthStep).toBe(2);
54
+ });
55
+
56
+ it("não deve fazer nada quando não há passos", () => {
57
+ component.steps = new QueryList<StepComponent>();
58
+ component.steps.reset([]);
59
+ const originalLength = component.lengthStep;
60
+
61
+ component.ngAfterContentInit();
62
+
63
+ expect(component.lengthStep).toBe(originalLength);
64
+ });
65
+ });
66
+
67
+ describe("nextStep", () => {
68
+ it("deve avançar para o próximo passo quando não estiver no último", () => {
69
+ const steps = [
70
+ { isActive: true } as StepComponent,
71
+ { isActive: false } as StepComponent,
72
+ { isActive: false } as StepComponent,
73
+ ];
74
+ component.steps = new QueryList<StepComponent>();
75
+ component.steps.reset(steps);
76
+ component.activeStepIndex = 0;
77
+
78
+ const emitSpy = vi.spyOn(component.maxReachedEvent as EventEmitter<null>, 'emit');
79
+
80
+ component.nextStep();
81
+
82
+ expect(component.activeStepIndex).toBe(1);
83
+ expect(steps[1].isActive).toBe(true);
84
+ expect(emitSpy).not.toHaveBeenCalled();
85
+ });
86
+
87
+ it("deve emitir maxReachedEvent quando estiver no último passo", () => {
88
+ const steps = [
89
+ { isActive: true } as StepComponent,
90
+ { isActive: true } as StepComponent
91
+ ];
92
+ component.steps = new QueryList<StepComponent>();
93
+ component.steps.reset(steps);
94
+ component.activeStepIndex = 1;
95
+
96
+ const emitSpy = vi.spyOn(component.maxReachedEvent as EventEmitter<null>, 'emit');
97
+
98
+ component.nextStep();
99
+
100
+ expect(emitSpy).toHaveBeenCalledWith(null);
101
+ expect(component.activeStepIndex).toBe(1);
102
+ });
103
+
104
+ it("não deve fazer nada quando não há passos", () => {
105
+ component.steps = new QueryList<StepComponent>();
106
+ component.steps.reset([]);
107
+ const originalIndex = component.activeStepIndex;
108
+
109
+ const emitSpy = vi.spyOn(component.maxReachedEvent as EventEmitter<null>, 'emit');
110
+
111
+ component.nextStep();
112
+
113
+ expect(component.activeStepIndex).toBe(originalIndex);
114
+ expect(emitSpy).not.toHaveBeenCalled();
115
+ });
116
+ });
117
+
118
+ describe("prevStep", () => {
119
+ it("deve voltar para o passo anterior quando não estiver no primeiro", () => {
120
+ const steps = [
121
+ { isActive: true } as StepComponent,
122
+ { isActive: true } as StepComponent,
123
+ { isActive: false } as StepComponent,
124
+ ];
125
+ component.steps = new QueryList<StepComponent>();
126
+ component.steps.reset(steps);
127
+ component.activeStepIndex = 1;
128
+
129
+ component.prevStep();
130
+
131
+ expect(component.activeStepIndex).toBe(0);
132
+ expect(steps[1].isActive).toBe(false);
133
+ expect(steps[0].isActive).toBe(true);
134
+ });
135
+
136
+ it("não deve fazer nada quando estiver no primeiro passo", () => {
137
+ const steps = [
138
+ { isActive: true } as StepComponent,
139
+ { isActive: false } as StepComponent
140
+ ];
141
+ component.steps = new QueryList<StepComponent>();
142
+ component.steps.reset(steps);
143
+ component.activeStepIndex = 0;
144
+
145
+ component.prevStep();
146
+
147
+ expect(component.activeStepIndex).toBe(0);
148
+ expect(steps[0].isActive).toBe(true);
149
+ });
150
+
151
+ it("não deve fazer nada quando não há passos", () => {
152
+ component.steps = new QueryList<StepComponent>();
153
+ component.steps.reset([]);
154
+ const originalIndex = component.activeStepIndex;
155
+
156
+ component.prevStep();
157
+
158
+ expect(component.activeStepIndex).toBe(originalIndex);
159
+ });
160
+ });
161
+
162
+ describe("resetStepper", () => {
163
+ it("deve redefinir para o primeiro passo e desativar todos os outros", () => {
164
+ const steps = [
165
+ { isActive: false } as StepComponent,
166
+ { isActive: true } as StepComponent,
167
+ { isActive: true } as StepComponent,
168
+ ];
169
+ component.steps = new QueryList<StepComponent>();
170
+ component.steps.reset(steps);
171
+ component.activeStepIndex = 2;
172
+
173
+ const forEachSpy = vi.spyOn(component.steps, "forEach");
174
+
175
+ component.resetStepper();
176
+
177
+ expect(component.activeStepIndex).toBe(0);
178
+ expect(forEachSpy).toHaveBeenCalled();
179
+ expect(steps[0].isActive).toBe(true);
180
+ expect(steps[1].isActive).toBe(false);
181
+ expect(steps[2].isActive).toBe(false);
182
+ });
183
+
184
+ it("não deve ativar nenhum passo quando não há passos", () => {
185
+ component.steps = new QueryList<StepComponent>();
186
+ component.steps.reset([]);
187
+ component.activeStepIndex = 2;
188
+
189
+ const forEachSpy = vi.spyOn(component.steps, "forEach");
190
+
191
+ component.resetStepper();
192
+
193
+ expect(component.activeStepIndex).toBe(0);
194
+ expect(forEachSpy).toHaveBeenCalled();
195
+ });
196
+ });
197
+
198
+ describe("Testes com Template", () => {
199
+ it("deve exibir o título do stepper quando fornecido", () => {
200
+ component.title = "Meu Stepper";
201
+ fixture.detectChanges();
202
+
203
+ const titleElement = fixture.debugElement.query(By.css(".stepper-title"));
204
+ expect(titleElement).toBeTruthy();
205
+ expect(titleElement.nativeElement.textContent).toContain("Meu Stepper");
206
+ });
207
+ });
208
+
209
+ // Testes adicionais para melhor cobertura
210
+ describe("Outros comportamentos", () => {
211
+ it("deve permitir navegação entre múltiplos passos", async() => {
212
+ const steps = [
213
+ { isActive: false } as StepComponent,
214
+ { isActive: false } as StepComponent,
215
+ { isActive: false } as StepComponent,
216
+ ];
217
+ component.steps = new QueryList<StepComponent>();
218
+ component.steps.reset(steps);
219
+
220
+ component.ngAfterContentInit();
221
+ expect(component.activeStepIndex).toBe(0);
222
+ expect(steps[0].isActive).toBe(true);
223
+
224
+ component.nextStep();
225
+
226
+ expect(component.activeStepIndex).toBe(1);
227
+ expect(component.steps.get(0)?.isActive).toBe(true);
228
+
229
+ component.nextStep();
230
+ expect(component.activeStepIndex).toBe(2);
231
+ expect(component.steps.get(2)?.isActive).toBe(true);
232
+
233
+ component.prevStep();
234
+ expect(component.activeStepIndex).toBe(1);
235
+ expect(component.steps.get(1)?.isActive).toBe(true);
236
+ });
237
+ });
238
+ });
@@ -0,0 +1,57 @@
1
+ import { AfterContentInit, EventEmitter, Output , ContentChildren, Input, QueryList , Component } from "@angular/core";
2
+
3
+
4
+ import { StepComponent } from "./step/step";
5
+
6
+ @Component({
7
+ selector: "cao-stepper",
8
+ standalone: true,
9
+ templateUrl: "./stepper.html",
10
+ styleUrl: "./stepper.css",
11
+ })
12
+ export class StepperComponent implements AfterContentInit {
13
+ constructor() {}
14
+ @ContentChildren(StepComponent) steps!: QueryList<StepComponent>;
15
+ @Input() title!: string;
16
+ activeStepIndex = 0;
17
+ lengthStep = 0;
18
+ showLine = true;
19
+
20
+ @Output() readonly maxReachedEvent: EventEmitter<null> = new EventEmitter<null>();
21
+
22
+ ngAfterContentInit(): void {
23
+ if (this.steps.length > 0) {
24
+ this.steps.toArray()[0].isActive = true;
25
+ this.lengthStep = this.steps.length;
26
+ }
27
+ }
28
+
29
+ nextStep() {
30
+ if (this.steps.length > 0) {
31
+ if (this.activeStepIndex < this.steps.length - 1) {
32
+ this.activeStepIndex++;
33
+ this.steps.toArray()[this.activeStepIndex].isActive = true;
34
+ } else {
35
+ this.maxReachedEvent.emit(null);
36
+ }
37
+ }
38
+ }
39
+
40
+ prevStep() {
41
+ if (this.steps.length > 0) {
42
+ if (this.activeStepIndex > 0) {
43
+ this.steps.toArray()[this.activeStepIndex].isActive = false;
44
+ this.activeStepIndex--;
45
+ this.steps.toArray()[this.activeStepIndex].isActive = true;
46
+ }
47
+ }
48
+ }
49
+
50
+ resetStepper() {
51
+ this.activeStepIndex = 0;
52
+ this.steps.forEach((step) => (step.isActive = false));
53
+ if (this.steps.length > 0) {
54
+ this.steps.toArray()[0].isActive = true;
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,84 @@
1
+ <div
2
+ #header
3
+ [class]="'cao-tab-header cao-tab-header--align-' + labelAlign"
4
+ >
5
+ <div class="cao-tab-label-list" role="tablist">
6
+ @for (tab of tabList; track $index; let i = $index) {
7
+ <button
8
+ #tabBtn
9
+ role="tab"
10
+ type="button"
11
+ class="cao-tab-label"
12
+ [class.cao-tab-label--active]="isActive(i)"
13
+ [class.cao-tab-label--disabled]="tab.isDisabled"
14
+ [attr.aria-selected]="isActive(i)"
15
+ [attr.aria-disabled]="tab.isDisabled || null"
16
+ [attr.tabindex]="isActive(i) ? 0 : -1"
17
+ [attr.id]="'cao-tab-label-' + i"
18
+ [attr.aria-controls]="'cao-tab-content-' + i"
19
+ (click)="onTabClick(i)"
20
+ (keydown)="onKeydown($event, i)"
21
+ (focus)="onFocus(i)"
22
+ >
23
+ @if (tab.leadingIcon) {
24
+ <span class="leading-icon">
25
+ @if (tab.isLucideIcon) {
26
+ <svg [lucideIcon]="tab.leadingIcon" [style.color]="isActive(i) ? iconColorActive : iconColorInactive" [strokeWidth]="strokeWidthIcon"></svg>
27
+ } @else {
28
+ <img alt="icon" [src]="tab.leadingIcon" />
29
+ }
30
+ </span>
31
+ }
32
+
33
+ @if (tab.labelTemplate) {
34
+ <ng-container [ngTemplateOutlet]="tab.labelTemplate" />
35
+ } @else {
36
+ <span class="cao-tab-labeltext">{{ tab.label }}</span>
37
+ }
38
+
39
+ @if (tab.trailingIcon) {
40
+ <span class="trailing-icon">
41
+ @if (tab.isLucideIcon) {
42
+ <svg [lucideIcon]="tab.trailingIcon" [style.color]="isActive(i) ? iconColorActive : iconColorInactive" [strokeWidth]="strokeWidthIcon"></svg>
43
+ } @else {
44
+ <img alt="icon" [src]="tab.trailingIcon" />
45
+ }
46
+ </span>
47
+ }
48
+ </button>
49
+ }
50
+ </div>
51
+
52
+ <!-- Ink bar animado -->
53
+ <div class="cao-tab-ink-bar-track">
54
+ <div #inkBar class="cao-tab-ink-bar"></div>
55
+ </div>
56
+ </div>
57
+
58
+ <!-- ═══ Tab Bodies ════════════════════════════════════════════════════════ -->
59
+ <div
60
+ class="cao-tab-body-wrapper"
61
+ [class.cao-tab-body-wrapper--dynamic]="dynamicHeight"
62
+ >
63
+ @for (tab of tabList; track $index; let i = $index) {
64
+ <div
65
+ role="tabpanel"
66
+ class="cao-tab-body"
67
+ [class.cao-tab-body--active]="isActive(i)"
68
+ [attr.id]="'cao-tab-content-' + i"
69
+ [attr.aria-labelledby]="'cao-tab-label-' + i"
70
+ [attr.aria-hidden]="!isActive(i)"
71
+ [style.--cao-tab-anim-duration]="animationDuration"
72
+ >
73
+ <div class="cao-tab-bodycontent">
74
+ @if (tab.lazyContent) {
75
+ @if (isActive(i) || wasActivated(i)) {
76
+ <ng-container [ngTemplateOutlet]="tab.lazyContent" />
77
+ }
78
+ } @else {
79
+ <ng-container [ngTemplateOutlet]="tab.content" />
80
+ }
81
+ </div>
82
+ </div>
83
+ }
84
+ </div>
@@ -0,0 +1,151 @@
1
+ :host {
2
+ --cao-tab-font-family: inherit;
3
+ --cao-tab-font-size: 0.875rem;
4
+ --cao-tab-font-weight: 500;
5
+ --cao-tab-label-height: 48px;
6
+ --cao-tab-Label-px: 16px;
7
+ --cao-tab-Label-gap: 6px;
8
+
9
+ --cao-tab-color-text: #6b7280;
10
+ --cao-tab-color-active: #4f46e5;
11
+ --cao-tab-color-hover-bg: #f3f4f6;
12
+ --cao-tab-color-disabled: #d1d5db;
13
+ --cao-tab-color-ink-bar: #4f46e5;
14
+ --cao-tab-color-header-border: #e5e7eb;
15
+
16
+ --cao-tab-color-header-border: #e5e7eb;
17
+
18
+ --cao-tab-ink-bar-height: 2px;
19
+ --cao-tab-content-pt: 20px;
20
+ --cao-tab-radius: 4px;
21
+
22
+ display: flex;
23
+ flex-direction: column;
24
+ width: 100%;
25
+ }
26
+
27
+ .cao-tab-header {
28
+ position: relative;
29
+ border-bottom: 1px solid var(--cao-tab-color-header-border);
30
+ overflow-x: auto;
31
+ scrollbar-width: none;
32
+ }
33
+ .cao-tab-header::-webkit-scrollbar { display: none; }
34
+
35
+ .cao-tab-label-list {
36
+ display: flex;
37
+ align-items: center;
38
+ min-width: max-content;
39
+ }
40
+
41
+ .cao-tab-header--align-center .cao-tab-label-list { justify-content: center; }
42
+ .cao-tab-header--align-end .cao-tab-label-list { justify-content: flex-end; }
43
+ .cao-tab-header--align-start .cao-tab-label-list { justify-content: flex-start; }
44
+
45
+ .cao-tab-label {
46
+ width: 100%;
47
+ display: inline-flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ align-items: center;
51
+ gap: var(--cao-tab-label-gap);
52
+ height: var(--cao-tab-label-height);
53
+ padding: 0 var(--cao-tab-label-px);
54
+
55
+ font-family: var(--cao-tab-font-family);
56
+ font-size: var(--cao-tab-font-size);
57
+ font-weight: var(--cao-tab-font-weight);
58
+ color: var(--cao-tab-color-text);
59
+ white-space: nowrap;
60
+
61
+ background: transparent;
62
+ border: none;
63
+ border-radius: var(--cao-tab-radius) var(--cao-tab-radius) 0 0;
64
+ cursor: pointer;
65
+ user-select: none;
66
+ transition: color 180ms ease, background-color 180ms ease;
67
+
68
+ outline: none;
69
+ }
70
+
71
+ .cao-tab-label:focus-visible {
72
+ outline: 2px solid var(--cao-tab-color-active);
73
+ outline-offset: -2px;
74
+ }
75
+
76
+ .cao-tab-label:hover:not(.cao-tab-label--disabled) {
77
+ background-color: var(--cao-tab-color-hover-bg);
78
+ color: var(--cao-tab-color-active);
79
+ }
80
+
81
+ .cao-tab-label--active {
82
+ color: var(--cao-tab-color-active);
83
+ }
84
+
85
+ .cao-tab-label--disabled {
86
+ color: var(--cao-tab-color-disabled);
87
+ cursor: not-allowed;
88
+ pointer-events: none;
89
+ }
90
+
91
+ .cao-tab-label__icon {
92
+ flex-shrink: 0;
93
+ color: inherit;
94
+ transition: color 180ms ease;
95
+ }
96
+
97
+ .cao-tab-ink-bar-track {
98
+ position: absolute;
99
+ bottom: 0;
100
+ left: 0;
101
+ right: 0;
102
+ height: var(--cao-tab-ink-bar-height);
103
+ pointer-events: none;
104
+ }
105
+
106
+ .cao-tab-ink-bar {
107
+ position: absolute;
108
+ bottom: 0;
109
+ left: 0;
110
+ height: 100%;
111
+ background-color: var(--cao-tab-color-ink-bar);
112
+ border-radius: 2px 2px 0 0;
113
+ transition-property: transform, width;
114
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
115
+ transition-duration: 300ms; /* sobrescrito por JS */
116
+ }
117
+
118
+ .cao-tab-body-wrapper {
119
+ position: relative;
120
+ overflow: hidden;
121
+ }
122
+
123
+ .cao-tab-body-wrapper--dynamic {
124
+ height: auto;
125
+ }
126
+
127
+ .cao-tab-body {
128
+ position: absolute;
129
+ top: 0;
130
+ left: 0;
131
+ width: 100%;
132
+ visibility: hidden;
133
+ opacity: 0;
134
+ pointer-events: none;
135
+ transform: translateX(24px);
136
+ transition:
137
+ opacity var(--cao-tab-anim-duration, 300ms) cubic-bezier(0.4, 0, 0.2, 1),
138
+ transform var(--cao-tab-anim-duration, 300ms) cubic-bezier(0.4, 0, 0.2, 1);
139
+ }
140
+
141
+ .cao-tab-body--active {
142
+ position: relative;
143
+ visibility: visible;
144
+ opacity: 1;
145
+ pointer-events: auto;
146
+ transform: translateX(0);
147
+ }
148
+
149
+ .cao-tab-body__content {
150
+ padding-top: var(--cao-tab-content-pt);
151
+ }
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from "@angular/core/testing";
2
+
3
+ import { CaoTabGroup } from "./tab-group";
4
+
5
+ describe("TabGroup", () => {
6
+ let component: CaoTabGroup;
7
+ let fixture: ComponentFixture<CaoTabGroup>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [CaoTabGroup],
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(CaoTabGroup);
15
+ component = fixture.componentInstance;
16
+ await fixture.whenStable();
17
+ });
18
+
19
+ it("should create", () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });