@sneat/components 0.1.3 → 0.1.4

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 (170) hide show
  1. package/esm2022/index.js +15 -0
  2. package/esm2022/index.js.map +1 -0
  3. package/esm2022/lib/app-version/app-version.component.js +16 -0
  4. package/esm2022/lib/app-version/app-version.component.js.map +1 -0
  5. package/esm2022/lib/app-version/build-info.js +5 -0
  6. package/esm2022/lib/app-version/build-info.js.map +1 -0
  7. package/esm2022/lib/app-version/index.js +3 -0
  8. package/esm2022/lib/app-version/index.js.map +1 -0
  9. package/esm2022/lib/card-list/index.js +2 -0
  10. package/esm2022/lib/card-list/index.js.map +1 -0
  11. package/esm2022/lib/card-list/sneat-card-list.component.js +106 -0
  12. package/esm2022/lib/card-list/sneat-card-list.component.js.map +1 -0
  13. package/esm2022/lib/copyright/copyright.component.js +11 -0
  14. package/esm2022/lib/copyright/copyright.component.js.map +1 -0
  15. package/esm2022/lib/copyright/index.js +2 -0
  16. package/esm2022/lib/copyright/index.js.map +1 -0
  17. package/esm2022/lib/country-input/country-input.component.js +59 -0
  18. package/esm2022/lib/country-input/country-input.component.js.map +1 -0
  19. package/esm2022/lib/country-input/index.js +2 -0
  20. package/esm2022/lib/country-input/index.js.map +1 -0
  21. package/esm2022/lib/country-selector/countries-loader.service.js +91 -0
  22. package/esm2022/lib/country-selector/countries-loader.service.js.map +1 -0
  23. package/esm2022/lib/country-selector/countries.js +22 -0
  24. package/esm2022/lib/country-selector/countries.js.map +1 -0
  25. package/esm2022/lib/country-selector/country-selector.component.js +103 -0
  26. package/esm2022/lib/country-selector/country-selector.component.js.map +1 -0
  27. package/esm2022/lib/country-selector/country-selector.service.js +15 -0
  28. package/esm2022/lib/country-selector/country-selector.service.js.map +1 -0
  29. package/esm2022/lib/country-selector/index.js +5 -0
  30. package/esm2022/lib/country-selector/index.js.map +1 -0
  31. package/esm2022/lib/date-input/date-input.component.js +70 -0
  32. package/esm2022/lib/date-input/date-input.component.js.map +1 -0
  33. package/esm2022/lib/date-input/date-modal.component.js +53 -0
  34. package/esm2022/lib/date-input/date-modal.component.js.map +1 -0
  35. package/esm2022/lib/dialog-header/dialog-header.component.js +23 -0
  36. package/esm2022/lib/dialog-header/dialog-header.component.js.map +1 -0
  37. package/esm2022/lib/dialog-header/index.js +2 -0
  38. package/esm2022/lib/dialog-header/index.js.map +1 -0
  39. package/esm2022/lib/error-card/index.js +2 -0
  40. package/esm2022/lib/error-card/index.js.map +1 -0
  41. package/esm2022/lib/error-card/sneat-error-card.component.js +23 -0
  42. package/esm2022/lib/error-card/sneat-error-card.component.js.map +1 -0
  43. package/esm2022/lib/filter-item/filter-item.component.js +37 -0
  44. package/esm2022/lib/filter-item/filter-item.component.js.map +1 -0
  45. package/esm2022/lib/filter-item/index.js +2 -0
  46. package/esm2022/lib/filter-item/index.js.map +1 -0
  47. package/esm2022/lib/pipes/country-emoji.pipe.js +69 -0
  48. package/esm2022/lib/pipes/country-emoji.pipe.js.map +1 -0
  49. package/esm2022/lib/pipes/decimal64p2.pipe.js +47 -0
  50. package/esm2022/lib/pipes/decimal64p2.pipe.js.map +1 -0
  51. package/esm2022/lib/pipes/gender.pipes.js +69 -0
  52. package/esm2022/lib/pipes/gender.pipes.js.map +1 -0
  53. package/esm2022/lib/pipes/index.js +7 -0
  54. package/esm2022/lib/pipes/index.js.map +1 -0
  55. package/esm2022/lib/pipes/long-month-name.pipe.js +41 -0
  56. package/esm2022/lib/pipes/long-month-name.pipe.js.map +1 -0
  57. package/esm2022/lib/pipes/short-month-name.pipe.js +31 -0
  58. package/esm2022/lib/pipes/short-month-name.pipe.js.map +1 -0
  59. package/esm2022/lib/pipes/team-emoji.pipe.js +31 -0
  60. package/esm2022/lib/pipes/team-emoji.pipe.js.map +1 -0
  61. package/esm2022/lib/save-event.js +2 -0
  62. package/esm2022/lib/save-event.js.map +1 -0
  63. package/esm2022/lib/user-country/user-country.component.js +136 -0
  64. package/esm2022/lib/user-country/user-country.component.js.map +1 -0
  65. package/esm2022/lib/virtual-slider/virtual-slider.js +83 -0
  66. package/esm2022/lib/virtual-slider/virtual-slider.js.map +1 -0
  67. package/esm2022/sneat-components.js +5 -0
  68. package/esm2022/sneat-components.js.map +1 -0
  69. package/lib/app-version/app-version.component.d.ts +9 -0
  70. package/lib/app-version/build-info.d.ts +4 -0
  71. package/lib/card-list/sneat-card-list.component.d.ts +43 -0
  72. package/lib/copyright/copyright.component.d.ts +5 -0
  73. package/lib/country-input/country-input.component.d.ts +16 -0
  74. package/lib/country-selector/countries-loader.service.d.ts +43 -0
  75. package/lib/country-selector/countries.d.ts +25 -0
  76. package/lib/country-selector/country-selector.component.d.ts +31 -0
  77. package/lib/country-selector/country-selector.service.d.ts +8 -0
  78. package/lib/date-input/date-input.component.d.ts +21 -0
  79. package/lib/date-input/date-modal.component.d.ts +13 -0
  80. package/lib/dialog-header/dialog-header.component.d.ts +8 -0
  81. package/lib/error-card/sneat-error-card.component.d.ts +8 -0
  82. package/lib/filter-item/filter-item.component.d.ts +13 -0
  83. package/lib/pipes/country-emoji.pipe.d.ts +29 -0
  84. package/lib/pipes/decimal64p2.pipe.d.ts +12 -0
  85. package/lib/pipes/gender.pipes.d.ts +20 -0
  86. package/lib/pipes/long-month-name.pipe.d.ts +7 -0
  87. package/lib/pipes/short-month-name.pipe.d.ts +8 -0
  88. package/lib/pipes/team-emoji.pipe.d.ts +8 -0
  89. package/lib/save-event.d.ts +5 -0
  90. package/lib/user-country/user-country.component.d.ts +24 -0
  91. package/lib/virtual-slider/virtual-slider.d.ts +13 -0
  92. package/package.json +14 -2
  93. package/sneat-components.d.ts +5 -0
  94. package/eslint.config.js +0 -7
  95. package/ng-package.json +0 -10
  96. package/project.json +0 -38
  97. package/src/assets/data/countries.json +0 -1730
  98. package/src/lib/app-version/app-version.component.html +0 -15
  99. package/src/lib/app-version/app-version.component.spec.ts +0 -25
  100. package/src/lib/app-version/app-version.component.ts +0 -17
  101. package/src/lib/app-version/build-info.ts +0 -8
  102. package/src/lib/card-list/sneat-card-list.component.html +0 -108
  103. package/src/lib/card-list/sneat-card-list.component.spec.ts +0 -131
  104. package/src/lib/card-list/sneat-card-list.component.ts +0 -125
  105. package/src/lib/copyright/copyright.component.html +0 -1
  106. package/src/lib/copyright/copyright.component.spec.ts +0 -24
  107. package/src/lib/copyright/copyright.component.ts +0 -7
  108. package/src/lib/country-input/country-input.component.html +0 -33
  109. package/src/lib/country-input/country-input.component.spec.ts +0 -84
  110. package/src/lib/country-input/country-input.component.ts +0 -76
  111. package/src/lib/country-selector/countries-loader.service.spec.ts +0 -149
  112. package/src/lib/country-selector/countries-loader.service.ts +0 -100
  113. package/src/lib/country-selector/countries.ts +0 -42
  114. package/src/lib/country-selector/country-selector.component.html +0 -24
  115. package/src/lib/country-selector/country-selector.component.spec.ts +0 -5
  116. package/src/lib/country-selector/country-selector.component.ts +0 -125
  117. package/src/lib/country-selector/country-selector.service.spec.ts +0 -23
  118. package/src/lib/country-selector/country-selector.service.ts +0 -11
  119. package/src/lib/date-input/date-input.component.html +0 -39
  120. package/src/lib/date-input/date-input.component.spec.ts +0 -179
  121. package/src/lib/date-input/date-input.component.ts +0 -97
  122. package/src/lib/date-input/date-modal.component.html +0 -23
  123. package/src/lib/date-input/date-modal.component.spec.ts +0 -105
  124. package/src/lib/date-input/date-modal.component.ts +0 -67
  125. package/src/lib/dialog-header/dialog-header.component.html +0 -8
  126. package/src/lib/dialog-header/dialog-header.component.spec.ts +0 -67
  127. package/src/lib/dialog-header/dialog-header.component.ts +0 -26
  128. package/src/lib/dismissable.ts +0 -6
  129. package/src/lib/error-card/sneat-error-card.component.html +0 -20
  130. package/src/lib/error-card/sneat-error-card.component.spec.ts +0 -49
  131. package/src/lib/error-card/sneat-error-card.component.ts +0 -28
  132. package/src/lib/filter-item/filter-item.component.html +0 -19
  133. package/src/lib/filter-item/filter-item.component.spec.ts +0 -83
  134. package/src/lib/filter-item/filter-item.component.ts +0 -47
  135. package/src/lib/pipes/country-emoji.pipe.spec.ts +0 -116
  136. package/src/lib/pipes/country-emoji.pipe.ts +0 -67
  137. package/src/lib/pipes/decimal64p2.pipe.spec.ts +0 -61
  138. package/src/lib/pipes/decimal64p2.pipe.ts +0 -35
  139. package/src/lib/pipes/gender.pipes.spec.ts +0 -84
  140. package/src/lib/pipes/gender.pipes.ts +0 -65
  141. package/src/lib/pipes/long-month-name.pipe.spec.ts +0 -36
  142. package/src/lib/pipes/long-month-name.pipe.ts +0 -35
  143. package/src/lib/pipes/short-month-name.pipe.spec.ts +0 -28
  144. package/src/lib/pipes/short-month-name.pipe.ts +0 -26
  145. package/src/lib/pipes/team-emoji.pipe.spec.ts +0 -27
  146. package/src/lib/pipes/team-emoji.pipe.ts +0 -26
  147. package/src/lib/save-event.ts +0 -5
  148. package/src/lib/test-ide-bug.ts +0 -24
  149. package/src/lib/user-country/user-country.component.html +0 -44
  150. package/src/lib/user-country/user-country.component.spec.ts +0 -136
  151. package/src/lib/user-country/user-country.component.ts +0 -172
  152. package/src/lib/virtual-slider/odd-even-virtual-slider.ts +0 -1
  153. package/src/lib/virtual-slider/virtual-slider.ts +0 -130
  154. package/src/lib/webstorm-type-err-demo.component.ts +0 -35
  155. package/src/test-setup.ts +0 -3
  156. package/tsconfig.json +0 -13
  157. package/tsconfig.lib.json +0 -19
  158. package/tsconfig.lib.prod.json +0 -7
  159. package/tsconfig.spec.json +0 -31
  160. package/vite.config.mts +0 -10
  161. /package/{src/index.ts → index.d.ts} +0 -0
  162. /package/{src/lib/app-version/index.ts → lib/app-version/index.d.ts} +0 -0
  163. /package/{src/lib/card-list/index.ts → lib/card-list/index.d.ts} +0 -0
  164. /package/{src/lib/copyright/index.ts → lib/copyright/index.d.ts} +0 -0
  165. /package/{src/lib/country-input/index.ts → lib/country-input/index.d.ts} +0 -0
  166. /package/{src/lib/country-selector/index.ts → lib/country-selector/index.d.ts} +0 -0
  167. /package/{src/lib/dialog-header/index.ts → lib/dialog-header/index.d.ts} +0 -0
  168. /package/{src/lib/error-card/index.ts → lib/error-card/index.d.ts} +0 -0
  169. /package/{src/lib/filter-item/index.ts → lib/filter-item/index.d.ts} +0 -0
  170. /package/{src/lib/pipes/index.ts → lib/pipes/index.d.ts} +0 -0
@@ -1,179 +0,0 @@
1
- import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
- import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
3
- import { PopoverController } from '@ionic/angular/standalone';
4
- import { DateInputComponent } from './date-input.component';
5
-
6
- describe('DateInputComponent', () => {
7
- let component: DateInputComponent;
8
- let fixture: ComponentFixture<DateInputComponent>;
9
- let popoverController: {
10
- create: ReturnType<typeof vi.fn>;
11
- };
12
-
13
- beforeEach(waitForAsync(async () => {
14
- popoverController = {
15
- create: vi.fn(),
16
- };
17
-
18
- await TestBed.configureTestingModule({
19
- imports: [DateInputComponent],
20
- providers: [
21
- { provide: PopoverController, useValue: popoverController },
22
- ],
23
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
24
- })
25
- .overrideComponent(DateInputComponent, {
26
- set: {
27
- imports: [],
28
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
29
- providers: [],
30
- template: '',
31
- },
32
- })
33
- .compileComponents();
34
- fixture = TestBed.createComponent(DateInputComponent);
35
- component = fixture.componentInstance;
36
- fixture.componentRef.setInput('$label', 'Test Label');
37
- fixture.componentRef.setInput('$value', '2024-01-01');
38
- }));
39
-
40
- it('should create', () => {
41
- expect(component).toBeTruthy();
42
- });
43
-
44
- it('should initialize with undefined newValue', () => {
45
- expect(component.$newValue()).toBeUndefined();
46
- });
47
-
48
- it('should compute noValueText with default when noValueLabel is not set', () => {
49
- expect(component['$noValueText']()).toBe('(not set)');
50
- });
51
-
52
- it('should compute noValueText with custom label when provided', () => {
53
- fixture.componentRef.setInput('$noValueLabel', 'Custom Label');
54
- expect(component['$noValueText']()).toBe('Custom Label');
55
- });
56
-
57
- it('should compute displayValue from value when not updating', () => {
58
- fixture.componentRef.setInput('$updating', false);
59
- expect(component.$displayValue()).toBe('2024-01-01');
60
- });
61
-
62
- it('should compute displayValue from newValue when updating', () => {
63
- component.$newValue.set('2024-12-31');
64
- fixture.componentRef.setInput('$updating', true);
65
- expect(component.$displayValue()).toBe('2024-12-31');
66
- });
67
-
68
- it('should update newValue when onValueChanged is called', () => {
69
- const mockEvent = {
70
- detail: { value: '2024-06-15' },
71
- } as CustomEvent;
72
-
73
- component['onValueChanged'](mockEvent);
74
-
75
- expect(component.$newValue()).toBe('2024-06-15');
76
- });
77
-
78
- it('should emit valueChange when save is called', () => {
79
- const emitSpy = vi.fn();
80
- component.valueChange.subscribe(emitSpy);
81
- component.$newValue.set('2024-03-20');
82
-
83
- const mockEvent = {
84
- preventDefault: vi.fn(),
85
- stopPropagation: vi.fn(),
86
- } as unknown as Event;
87
-
88
- component['save'](mockEvent);
89
-
90
- expect(mockEvent.preventDefault).toHaveBeenCalled();
91
- expect(mockEvent.stopPropagation).toHaveBeenCalled();
92
- expect(emitSpy).toHaveBeenCalledWith('2024-03-20');
93
- });
94
-
95
- it('should open date picker and handle date selection', async () => {
96
- const mockPopover = {
97
- onDidDismiss: vi.fn().mockResolvedValue({
98
- data: '2024-09-01',
99
- }),
100
- present: vi.fn().mockResolvedValue(undefined),
101
- };
102
-
103
- popoverController.create.mockResolvedValue(mockPopover);
104
-
105
- const emitSpy = vi.fn();
106
- component.valueChange.subscribe(emitSpy);
107
-
108
- const mockEvent = {
109
- stopPropagation: vi.fn(),
110
- preventDefault: vi.fn(),
111
- } as unknown as Event;
112
-
113
- await component['openDatePicker'](mockEvent);
114
-
115
- expect(mockEvent.stopPropagation).toHaveBeenCalled();
116
- expect(mockEvent.preventDefault).toHaveBeenCalled();
117
- expect(popoverController.create).toHaveBeenCalledWith({
118
- reference: 'trigger',
119
- event: mockEvent,
120
- side: 'bottom',
121
- alignment: 'center',
122
- component: expect.anything(),
123
- componentProps: {
124
- title: 'Test Label',
125
- max: undefined,
126
- },
127
- });
128
- expect(mockPopover.present).toHaveBeenCalled();
129
- expect(component.$newValue()).toBe('2024-09-01');
130
- expect(emitSpy).toHaveBeenCalledWith('2024-09-01');
131
- });
132
-
133
- it('should handle empty date selection in date picker', async () => {
134
- const mockPopover = {
135
- onDidDismiss: vi.fn().mockResolvedValue({
136
- data: '',
137
- }),
138
- present: vi.fn().mockResolvedValue(undefined),
139
- };
140
-
141
- popoverController.create.mockResolvedValue(mockPopover);
142
-
143
- const emitSpy = vi.fn();
144
- component.valueChange.subscribe(emitSpy);
145
-
146
- const mockEvent = {
147
- stopPropagation: vi.fn(),
148
- preventDefault: vi.fn(),
149
- } as unknown as Event;
150
-
151
- await component['openDatePicker'](mockEvent);
152
-
153
- expect(component.$newValue()).toBe('');
154
- expect(emitSpy).toHaveBeenCalledWith('');
155
- });
156
-
157
- it('should not emit when date picker is cancelled', async () => {
158
- const mockPopover = {
159
- onDidDismiss: vi.fn().mockResolvedValue({
160
- data: undefined,
161
- }),
162
- present: vi.fn().mockResolvedValue(undefined),
163
- };
164
-
165
- popoverController.create.mockResolvedValue(mockPopover);
166
-
167
- const emitSpy = vi.fn();
168
- component.valueChange.subscribe(emitSpy);
169
-
170
- const mockEvent = {
171
- stopPropagation: vi.fn(),
172
- preventDefault: vi.fn(),
173
- } as unknown as Event;
174
-
175
- await component['openDatePicker'](mockEvent);
176
-
177
- expect(emitSpy).not.toHaveBeenCalled();
178
- });
179
- });
@@ -1,97 +0,0 @@
1
- import {
2
- Component,
3
- computed,
4
- inject,
5
- input,
6
- Output,
7
- EventEmitter,
8
- signal,
9
- } from '@angular/core';
10
- import {
11
- IonInput,
12
- IonLabel,
13
- IonButton,
14
- IonButtons,
15
- IonItem,
16
- PopoverController,
17
- IonIcon,
18
- IonSpinner,
19
- } from '@ionic/angular/standalone';
20
- import { DateModalComponent } from './date-modal.component';
21
-
22
- @Component({
23
- selector: 'sneat-date-input',
24
- templateUrl: 'date-input.component.html',
25
- imports: [
26
- IonItem,
27
- IonInput,
28
- IonLabel,
29
- IonButtons,
30
- IonButton,
31
- IonIcon,
32
- IonSpinner,
33
- ],
34
- providers: [PopoverController],
35
- })
36
- export class DateInputComponent {
37
- public readonly $label = input.required<string>();
38
- public readonly $value = input.required<string | undefined>();
39
- public readonly $max = input<string>();
40
-
41
- public readonly $newValue = signal<string | undefined>(undefined);
42
-
43
- public readonly $displayValue = computed(() =>
44
- this.$updating() ? this.$newValue() : this.$value(),
45
- );
46
-
47
- public readonly $updating = input<boolean>();
48
-
49
- @Output() public valueChange = new EventEmitter<string | undefined>();
50
-
51
- public readonly $noValueLabel = input<string>();
52
-
53
- protected readonly $noValueText = computed(
54
- () => this.$noValueLabel() || '(not set)',
55
- );
56
-
57
- protected readonly $noValueButtonColor = input<string>();
58
-
59
- protected readonly popoverCtrl = inject(PopoverController);
60
-
61
- protected onValueChanged(event: CustomEvent): void {
62
- const newValue = event.detail.value as string;
63
- // console.log('onValueChanged', newValue);
64
- this.$newValue.set(newValue);
65
- }
66
-
67
- protected save(event: Event): void {
68
- event.preventDefault();
69
- event.stopPropagation();
70
- this.valueChange.emit(this.$newValue());
71
- }
72
-
73
- protected async openDatePicker(event: Event): Promise<void> {
74
- event.stopPropagation();
75
- event.preventDefault();
76
- const popover = await this.popoverCtrl.create({
77
- reference: 'trigger',
78
- event,
79
- side: 'bottom',
80
- alignment: 'center',
81
- component: DateModalComponent,
82
- componentProps: {
83
- title: this.$label(),
84
- max: this.$max(),
85
- },
86
- });
87
- popover.onDidDismiss().then((eventDetail) => {
88
- // console.log(`Selected "${this.$label()}":`, eventDetail.data);
89
- const value = eventDetail.data as string | undefined;
90
- if (value !== undefined) {
91
- this.$newValue.set(value || '');
92
- this.valueChange.emit(eventDetail.data as string | undefined);
93
- }
94
- });
95
- await popover.present();
96
- }
97
- }
@@ -1,23 +0,0 @@
1
- <ion-header>
2
- <ion-toolbar>
3
- <ion-title>{{ title }}</ion-title>
4
- <ion-buttons slot="end">
5
- <ion-button
6
- (click)="dismiss()"
7
- [disabled]="!$date()"
8
- [color]="$date() ? 'primary' : undefined"
9
- [fill]="$date() ? 'solid' : undefined"
10
- >
11
- <ion-label>Set</ion-label>
12
- </ion-button>
13
- </ion-buttons>
14
- </ion-toolbar>
15
- </ion-header>
16
- <ion-content>
17
- <ion-datetime
18
- [value]="$date()"
19
- [max]="max"
20
- (ionChange)="onDateChanged($event)"
21
- presentation="date"
22
- />
23
- </ion-content>
@@ -1,105 +0,0 @@
1
- import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
- import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
3
- import { PopoverController } from '@ionic/angular/standalone';
4
- import { ErrorLogger } from '@sneat/core';
5
- import { ClassName } from '@sneat/ui';
6
- import { DateModalComponent } from './date-modal.component';
7
-
8
- describe('DateModalComponent', () => {
9
- let component: DateModalComponent;
10
- let fixture: ComponentFixture<DateModalComponent>;
11
- let popoverController: { dismiss: ReturnType<typeof vi.fn> };
12
- let errorLogger: { logError: ReturnType<typeof vi.fn>; logErrorHandler: ReturnType<typeof vi.fn> };
13
-
14
- beforeEach(waitForAsync(async () => {
15
- popoverController = {
16
- dismiss: vi.fn().mockResolvedValue(true),
17
- };
18
-
19
- errorLogger = {
20
- logError: vi.fn(),
21
- logErrorHandler: vi.fn().mockReturnValue(() => undefined),
22
- };
23
-
24
- await TestBed.configureTestingModule({
25
- imports: [DateModalComponent],
26
- providers: [
27
- { provide: ClassName, useValue: 'TestComponent' },
28
- { provide: ErrorLogger, useValue: errorLogger },
29
- { provide: PopoverController, useValue: popoverController },
30
- ],
31
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
32
- })
33
- .overrideComponent(DateModalComponent, {
34
- set: { imports: [], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: '' },
35
- })
36
- .compileComponents();
37
- fixture = TestBed.createComponent(DateModalComponent);
38
- component = fixture.componentInstance;
39
- }));
40
-
41
- it('should create', () => {
42
- expect(component).toBeTruthy();
43
- });
44
-
45
- it('should initialize with undefined date', () => {
46
- expect(component['$date']()).toBeUndefined();
47
- });
48
-
49
- it('should set date when onDateChanged is called with valid date', () => {
50
- const mockEvent = {
51
- detail: { value: '2024-03-15T10:30:00.000Z' },
52
- } as CustomEvent;
53
-
54
- component['onDateChanged'](mockEvent);
55
-
56
- expect(component['$date']()).toBe('2024-03-15');
57
- });
58
-
59
- it('should handle date change with already formatted date', () => {
60
- const mockEvent = {
61
- detail: { value: '2024-12-25' },
62
- } as CustomEvent;
63
-
64
- component['onDateChanged'](mockEvent);
65
-
66
- expect(component['$date']()).toBe('2024-12-25');
67
- });
68
-
69
- it('should set null when onDateChanged receives empty value', () => {
70
- const mockEvent = {
71
- detail: { value: null },
72
- } as CustomEvent;
73
-
74
- component['onDateChanged'](mockEvent);
75
-
76
- expect(component['$date']()).toBeNull();
77
- });
78
-
79
- it('should dismiss popover with current date', () => {
80
- component['$date'].set('2024-06-10');
81
-
82
- component['dismiss']();
83
-
84
- expect(popoverController.dismiss).toHaveBeenCalledWith('2024-06-10');
85
- });
86
-
87
- it('should dismiss popover with undefined date', () => {
88
- component['dismiss']();
89
-
90
- expect(popoverController.dismiss).toHaveBeenCalledWith(undefined);
91
- });
92
-
93
- it('should handle dismiss error', async () => {
94
- const mockError = new Error('Dismiss failed');
95
- popoverController.dismiss = vi.fn().mockRejectedValue(mockError);
96
- const errorHandler = vi.fn();
97
- errorLogger.logErrorHandler = vi.fn().mockReturnValue(errorHandler);
98
-
99
- component['dismiss']();
100
-
101
- await new Promise((resolve) => setTimeout(resolve, 0));
102
-
103
- expect(errorLogger.logErrorHandler).toHaveBeenCalledWith('failed to dismiss date modal');
104
- });
105
- });
@@ -1,67 +0,0 @@
1
- import {
2
- Component,
3
- inject,
4
- Input,
5
- signal,
6
- ChangeDetectionStrategy,
7
- } from '@angular/core';
8
- import {
9
- IonButton,
10
- IonButtons,
11
- IonContent,
12
- IonDatetime,
13
- IonHeader,
14
- IonLabel,
15
- IonTitle,
16
- IonToolbar,
17
- PopoverController,
18
- } from '@ionic/angular/standalone';
19
- import { ClassName, SneatBaseComponent } from '@sneat/ui';
20
-
21
- @Component({
22
- imports: [
23
- IonDatetime,
24
- IonHeader,
25
- IonToolbar,
26
- IonTitle,
27
- IonContent,
28
- IonButton,
29
- IonButtons,
30
- IonLabel,
31
- ],
32
- providers: [
33
- {
34
- provide: ClassName,
35
- useValue: 'DateModalComponent',
36
- },
37
- ],
38
- changeDetection: ChangeDetectionStrategy.OnPush,
39
- selector: 'sneat-contact-dob-modal',
40
- templateUrl: 'date-modal.component.html',
41
- })
42
- export class DateModalComponent extends SneatBaseComponent {
43
- @Input() title?: string;
44
- @Input() max?: string;
45
-
46
- public constructor() {
47
- super();
48
- }
49
-
50
- private popoverCtrl = inject(PopoverController);
51
-
52
- protected readonly $date = signal<string | undefined>(undefined);
53
-
54
- protected onDateChanged(event: CustomEvent): void {
55
- let { value } = event.detail;
56
- if (value) {
57
- value = (value as string).slice(0, 10);
58
- }
59
- this.$date.set(value);
60
- }
61
-
62
- protected dismiss(): void {
63
- this.popoverCtrl
64
- .dismiss(this.$date())
65
- .catch(this.errorLogger.logErrorHandler('failed to dismiss date modal'));
66
- }
67
- }
@@ -1,8 +0,0 @@
1
- <ion-item color="primary" class="sneat-tiny-end-padding">
2
- <ion-label>{{ dialogTitle }}</ion-label>
3
- <ion-buttons slot="end">
4
- <ion-button (click)="close($event)">
5
- <ion-icon name="close-outline" />
6
- </ion-button>
7
- </ion-buttons>
8
- </ion-item>
@@ -1,67 +0,0 @@
1
- import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
- import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
3
- import { ModalController } from '@ionic/angular/standalone';
4
- import { DialogHeaderComponent } from './dialog-header.component';
5
-
6
- describe('DialogHeaderComponent', () => {
7
- let component: DialogHeaderComponent;
8
- let fixture: ComponentFixture<DialogHeaderComponent>;
9
- let modalController: { dismiss: ReturnType<typeof vi.fn> };
10
-
11
- beforeEach(waitForAsync(async () => {
12
- modalController = {
13
- dismiss: vi.fn().mockResolvedValue(true),
14
- };
15
-
16
- await TestBed.configureTestingModule({
17
- imports: [DialogHeaderComponent],
18
- providers: [{ provide: ModalController, useValue: modalController }],
19
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
20
- })
21
- .overrideComponent(DialogHeaderComponent, {
22
- set: { imports: [], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: '' },
23
- })
24
- .compileComponents();
25
- fixture = TestBed.createComponent(DialogHeaderComponent);
26
- component = fixture.componentInstance;
27
- }));
28
-
29
- it('should create', () => {
30
- expect(component).toBeTruthy();
31
- });
32
-
33
- it('should initialize with default dialogTitle', () => {
34
- expect(component.dialogTitle).toBe('Dialog');
35
- });
36
-
37
- it('should call modalController.dismiss when close is called', () => {
38
- const mockEvent = {
39
- stopPropagation: vi.fn(),
40
- preventDefault: vi.fn(),
41
- } as unknown as Event;
42
-
43
- component.close(mockEvent);
44
-
45
- expect(mockEvent.stopPropagation).toHaveBeenCalled();
46
- expect(mockEvent.preventDefault).toHaveBeenCalled();
47
- expect(modalController.dismiss).toHaveBeenCalled();
48
- });
49
-
50
- it('should handle dismiss error gracefully', async () => {
51
- const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
52
- modalController.dismiss = vi.fn().mockRejectedValue(new Error('Dismiss failed'));
53
-
54
- const mockEvent = {
55
- stopPropagation: vi.fn(),
56
- preventDefault: vi.fn(),
57
- } as unknown as Event;
58
-
59
- component.close(mockEvent);
60
-
61
- // Wait for promise to reject
62
- await new Promise((resolve) => setTimeout(resolve, 0));
63
-
64
- expect(consoleErrorSpy).toHaveBeenCalledWith(expect.any(Error));
65
- consoleErrorSpy.mockRestore();
66
- });
67
- });
@@ -1,26 +0,0 @@
1
- import { Component, Input, inject } from '@angular/core';
2
- import {
3
- ModalController,
4
- IonButton,
5
- IonButtons,
6
- IonIcon,
7
- IonItem,
8
- IonLabel,
9
- } from '@ionic/angular/standalone';
10
-
11
- @Component({
12
- selector: 'sneat-dialog-header',
13
- templateUrl: './dialog-header.component.html',
14
- imports: [IonItem, IonLabel, IonButtons, IonButton, IonIcon],
15
- })
16
- export class DialogHeaderComponent {
17
- private readonly modalController = inject(ModalController);
18
-
19
- @Input() dialogTitle = 'Dialog';
20
-
21
- close(event: Event): void {
22
- event.stopPropagation();
23
- event.preventDefault();
24
- this.modalController.dismiss().catch(console.error);
25
- }
26
- }
@@ -1,6 +0,0 @@
1
- export interface IDismissable {
2
- /**
3
- * When `id` is not provided, it dismisses the top overlay.
4
- */
5
- dismiss(data?: unknown, role?: string, id?: string): Promise<boolean>;
6
- }
@@ -1,20 +0,0 @@
1
- <ion-card>
2
- <ion-card-header>
3
- <ion-card-title color="danger">Error</ion-card-title>
4
- </ion-card-header>
5
- <ion-card-content>
6
- @if (error?.message) {
7
- <p>
8
- {{ error?.message }}
9
- </p>
10
- }
11
- <ion-item>
12
- <ion-textarea
13
- readonly="true"
14
- [value]="error | json"
15
- autoGrow="true"
16
- color="medium"
17
- />
18
- </ion-item>
19
- </ion-card-content>
20
- </ion-card>
@@ -1,49 +0,0 @@
1
- import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2
- import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
- import { SneatErrorCardComponent } from './sneat-error-card.component';
4
-
5
- describe('SneatErrorCardComponent', () => {
6
- let component: SneatErrorCardComponent;
7
- let fixture: ComponentFixture<SneatErrorCardComponent>;
8
-
9
- beforeEach(waitForAsync(async () => {
10
- await TestBed.configureTestingModule({
11
- imports: [SneatErrorCardComponent],
12
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
13
- })
14
- .overrideComponent(SneatErrorCardComponent, {
15
- set: {
16
- imports: [],
17
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
18
- template: '',
19
- },
20
- })
21
- .compileComponents();
22
-
23
- fixture = TestBed.createComponent(SneatErrorCardComponent);
24
- component = fixture.componentInstance;
25
- }));
26
-
27
- it('should create', () => {
28
- expect(component).toBeTruthy();
29
- });
30
-
31
- it('should accept error with message', () => {
32
- const error = { message: 'Test error message' };
33
- component.error = error;
34
- expect(component.error).toBe(error);
35
- expect(component.error.message).toBe('Test error message');
36
- });
37
-
38
- it('should accept error without message', () => {
39
- const error = {};
40
- component.error = error;
41
- expect(component.error).toBe(error);
42
- expect(component.error.message).toBeUndefined();
43
- });
44
-
45
- it('should handle undefined error', () => {
46
- component.error = undefined;
47
- expect(component.error).toBeUndefined();
48
- });
49
- });
@@ -1,28 +0,0 @@
1
- import { JsonPipe } from '@angular/common';
2
- import { Component, Input } from '@angular/core';
3
- import {
4
- IonCard,
5
- IonCardContent,
6
- IonCardHeader,
7
- IonCardTitle,
8
- IonItem,
9
- IonTextarea,
10
- } from '@ionic/angular/standalone';
11
-
12
- @Component({
13
- selector: 'sneat-datatug-error-card',
14
- templateUrl: './sneat-error-card.component.html',
15
- imports: [
16
- IonCard,
17
- IonCardHeader,
18
- IonCardTitle,
19
- IonCardContent,
20
- IonItem,
21
- IonTextarea,
22
- JsonPipe,
23
- ],
24
- })
25
- export class SneatErrorCardComponent {
26
- @Input()
27
- error?: { message?: string };
28
- }