@dragonworks/ngx-dashboard-widgets 20.0.6 → 20.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/dragonworks-ngx-dashboard-widgets.mjs +2251 -0
- package/fesm2022/dragonworks-ngx-dashboard-widgets.mjs.map +1 -0
- package/index.d.ts +532 -0
- package/package.json +42 -31
- package/ng-package.json +0 -7
- package/src/lib/arrow-widget/arrow-state-dialog.component.ts +0 -187
- package/src/lib/arrow-widget/arrow-widget.component.html +0 -9
- package/src/lib/arrow-widget/arrow-widget.component.scss +0 -52
- package/src/lib/arrow-widget/arrow-widget.component.ts +0 -78
- package/src/lib/arrow-widget/arrow-widget.metadata.ts +0 -3
- package/src/lib/clock-widget/analog-clock/analog-clock.component.html +0 -66
- package/src/lib/clock-widget/analog-clock/analog-clock.component.scss +0 -103
- package/src/lib/clock-widget/analog-clock/analog-clock.component.ts +0 -120
- package/src/lib/clock-widget/clock-state-dialog.component.ts +0 -170
- package/src/lib/clock-widget/clock-widget.component.html +0 -16
- package/src/lib/clock-widget/clock-widget.component.scss +0 -160
- package/src/lib/clock-widget/clock-widget.component.ts +0 -87
- package/src/lib/clock-widget/clock-widget.metadata.ts +0 -42
- package/src/lib/clock-widget/digital-clock/__tests__/digital-clock.component.spec.ts +0 -276
- package/src/lib/clock-widget/digital-clock/digital-clock.component.html +0 -1
- package/src/lib/clock-widget/digital-clock/digital-clock.component.scss +0 -43
- package/src/lib/clock-widget/digital-clock/digital-clock.component.ts +0 -105
- package/src/lib/directives/__tests__/responsive-text.directive.spec.ts +0 -906
- package/src/lib/directives/responsive-text.directive.ts +0 -334
- package/src/lib/label-widget/__tests__/label-widget.component.spec.ts +0 -539
- package/src/lib/label-widget/label-state-dialog.component.ts +0 -385
- package/src/lib/label-widget/label-widget.component.html +0 -21
- package/src/lib/label-widget/label-widget.component.scss +0 -112
- package/src/lib/label-widget/label-widget.component.ts +0 -96
- package/src/lib/label-widget/label-widget.metadata.ts +0 -3
- package/src/public-api.ts +0 -7
- package/tsconfig.lib.json +0 -15
- package/tsconfig.lib.prod.json +0 -11
- package/tsconfig.spec.json +0 -14
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
-
import { DigitalClockComponent } from '../digital-clock.component';
|
|
3
|
-
|
|
4
|
-
describe('DigitalClockComponent', () => {
|
|
5
|
-
let component: DigitalClockComponent;
|
|
6
|
-
let fixture: ComponentFixture<DigitalClockComponent>;
|
|
7
|
-
|
|
8
|
-
beforeEach(async () => {
|
|
9
|
-
await TestBed.configureTestingModule({
|
|
10
|
-
imports: [DigitalClockComponent]
|
|
11
|
-
})
|
|
12
|
-
.compileComponents();
|
|
13
|
-
|
|
14
|
-
fixture = TestBed.createComponent(DigitalClockComponent);
|
|
15
|
-
component = fixture.componentInstance;
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
// Ensure proper cleanup after each test
|
|
20
|
-
fixture.destroy();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should create', () => {
|
|
24
|
-
expect(component).toBeTruthy();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('Component Initialization', () => {
|
|
28
|
-
it('should display current time immediately after initialization', () => {
|
|
29
|
-
fixture.detectChanges();
|
|
30
|
-
|
|
31
|
-
const timeElement = fixture.nativeElement.querySelector('.digital-time');
|
|
32
|
-
expect(timeElement?.textContent?.trim()).toBeTruthy();
|
|
33
|
-
expect(timeElement?.textContent?.trim()).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should display current time within reasonable bounds', () => {
|
|
37
|
-
fixture.detectChanges();
|
|
38
|
-
|
|
39
|
-
const timeElement = fixture.nativeElement.querySelector('.digital-time');
|
|
40
|
-
const displayedTime = timeElement?.textContent?.trim();
|
|
41
|
-
|
|
42
|
-
expect(displayedTime).toBeTruthy();
|
|
43
|
-
expect(displayedTime).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
44
|
-
|
|
45
|
-
// The displayed time should be within reasonable bounds of current time
|
|
46
|
-
const displayedHour = parseInt(displayedTime!.substring(0, 2));
|
|
47
|
-
const currentHour = new Date().getHours();
|
|
48
|
-
expect(Math.abs(displayedHour - currentHour)).toBeLessThanOrEqual(1);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe('User Configuration Options', () => {
|
|
53
|
-
it('should display time in 24h format without seconds when configured', () => {
|
|
54
|
-
fixture.componentRef.setInput('timeFormat', '24h');
|
|
55
|
-
fixture.componentRef.setInput('showSeconds', false);
|
|
56
|
-
fixture.detectChanges();
|
|
57
|
-
|
|
58
|
-
const formattedTime = component.formattedTime();
|
|
59
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2}$/);
|
|
60
|
-
expect(formattedTime).not.toContain('AM');
|
|
61
|
-
expect(formattedTime).not.toContain('PM');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should display time in 24h format with seconds when configured', () => {
|
|
65
|
-
fixture.componentRef.setInput('timeFormat', '24h');
|
|
66
|
-
fixture.componentRef.setInput('showSeconds', true);
|
|
67
|
-
fixture.detectChanges();
|
|
68
|
-
|
|
69
|
-
const formattedTime = component.formattedTime();
|
|
70
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
71
|
-
expect(formattedTime).not.toContain('AM');
|
|
72
|
-
expect(formattedTime).not.toContain('PM');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should display time in 12h format without seconds when configured', () => {
|
|
76
|
-
fixture.componentRef.setInput('timeFormat', '12h');
|
|
77
|
-
fixture.componentRef.setInput('showSeconds', false);
|
|
78
|
-
fixture.detectChanges();
|
|
79
|
-
|
|
80
|
-
const formattedTime = component.formattedTime();
|
|
81
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2} (AM|PM)$/);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should display time in 12h format with seconds when configured', () => {
|
|
85
|
-
fixture.componentRef.setInput('timeFormat', '12h');
|
|
86
|
-
fixture.componentRef.setInput('showSeconds', true);
|
|
87
|
-
fixture.detectChanges();
|
|
88
|
-
|
|
89
|
-
const formattedTime = component.formattedTime();
|
|
90
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2}:\d{2} (AM|PM)$/);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('should update display format when switching between 24h and 12h', () => {
|
|
94
|
-
// Start with 24h format
|
|
95
|
-
fixture.componentRef.setInput('timeFormat', '24h');
|
|
96
|
-
fixture.componentRef.setInput('showSeconds', false);
|
|
97
|
-
fixture.detectChanges();
|
|
98
|
-
|
|
99
|
-
const time24h = component.formattedTime();
|
|
100
|
-
expect(time24h).toMatch(/^\d{2}:\d{2}$/);
|
|
101
|
-
|
|
102
|
-
// Switch to 12h format
|
|
103
|
-
fixture.componentRef.setInput('timeFormat', '12h');
|
|
104
|
-
fixture.detectChanges();
|
|
105
|
-
|
|
106
|
-
const time12h = component.formattedTime();
|
|
107
|
-
expect(time12h).toMatch(/^\d{2}:\d{2} (AM|PM)$/);
|
|
108
|
-
|
|
109
|
-
// Times should be different formats
|
|
110
|
-
expect(time24h).not.toBe(time12h);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should update display when toggling seconds visibility', () => {
|
|
114
|
-
fixture.componentRef.setInput('timeFormat', '24h');
|
|
115
|
-
fixture.componentRef.setInput('showSeconds', false);
|
|
116
|
-
fixture.detectChanges();
|
|
117
|
-
|
|
118
|
-
const timeWithoutSeconds = component.formattedTime();
|
|
119
|
-
expect(timeWithoutSeconds).toMatch(/^\d{2}:\d{2}$/);
|
|
120
|
-
|
|
121
|
-
// Enable seconds
|
|
122
|
-
fixture.componentRef.setInput('showSeconds', true);
|
|
123
|
-
fixture.detectChanges();
|
|
124
|
-
|
|
125
|
-
const timeWithSeconds = component.formattedTime();
|
|
126
|
-
expect(timeWithSeconds).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
127
|
-
|
|
128
|
-
// Should be different lengths
|
|
129
|
-
expect(timeWithSeconds.length).toBeGreaterThan(timeWithoutSeconds.length);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe('Template Integration', () => {
|
|
134
|
-
it('should display formatted time in template element', () => {
|
|
135
|
-
fixture.componentRef.setInput('timeFormat', '24h');
|
|
136
|
-
fixture.componentRef.setInput('showSeconds', true);
|
|
137
|
-
fixture.detectChanges();
|
|
138
|
-
|
|
139
|
-
const timeElement = fixture.nativeElement.querySelector('.digital-time');
|
|
140
|
-
const templateTime = timeElement?.textContent?.trim();
|
|
141
|
-
const componentTime = component.formattedTime();
|
|
142
|
-
|
|
143
|
-
expect(templateTime).toBe(componentTime);
|
|
144
|
-
expect(templateTime).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should update template when time format changes', () => {
|
|
148
|
-
fixture.componentRef.setInput('timeFormat', '24h');
|
|
149
|
-
fixture.componentRef.setInput('showSeconds', false);
|
|
150
|
-
fixture.detectChanges();
|
|
151
|
-
|
|
152
|
-
let timeElement = fixture.nativeElement.querySelector('.digital-time');
|
|
153
|
-
let templateTime = timeElement?.textContent?.trim();
|
|
154
|
-
expect(templateTime).toMatch(/^\d{2}:\d{2}$/);
|
|
155
|
-
|
|
156
|
-
// Change to 12h format
|
|
157
|
-
fixture.componentRef.setInput('timeFormat', '12h');
|
|
158
|
-
fixture.detectChanges();
|
|
159
|
-
|
|
160
|
-
timeElement = fixture.nativeElement.querySelector('.digital-time');
|
|
161
|
-
templateTime = timeElement?.textContent?.trim();
|
|
162
|
-
expect(templateTime).toMatch(/^\d{2}:\d{2} (AM|PM)$/);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('should reflect input changes in host element classes', () => {
|
|
166
|
-
fixture.componentRef.setInput('hasBackground', true);
|
|
167
|
-
fixture.componentRef.setInput('timeFormat', '12h');
|
|
168
|
-
fixture.componentRef.setInput('showSeconds', true);
|
|
169
|
-
fixture.detectChanges();
|
|
170
|
-
|
|
171
|
-
const hostElement = fixture.nativeElement;
|
|
172
|
-
expect(hostElement.classList.contains('has-background')).toBe(true);
|
|
173
|
-
expect(hostElement.classList.contains('show-pm')).toBe(true);
|
|
174
|
-
expect(hostElement.classList.contains('show-seconds')).toBe(true);
|
|
175
|
-
expect(hostElement.classList.contains('clock-widget')).toBe(true);
|
|
176
|
-
expect(hostElement.classList.contains('digital')).toBe(true);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('should update host classes when inputs change', () => {
|
|
180
|
-
fixture.componentRef.setInput('hasBackground', false);
|
|
181
|
-
fixture.componentRef.setInput('timeFormat', '24h');
|
|
182
|
-
fixture.componentRef.setInput('showSeconds', false);
|
|
183
|
-
fixture.detectChanges();
|
|
184
|
-
|
|
185
|
-
const hostElement = fixture.nativeElement;
|
|
186
|
-
expect(hostElement.classList.contains('has-background')).toBe(false);
|
|
187
|
-
expect(hostElement.classList.contains('show-pm')).toBe(false);
|
|
188
|
-
expect(hostElement.classList.contains('show-seconds')).toBe(false);
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
describe('Input Validation', () => {
|
|
193
|
-
it('should handle rapid input changes without errors', () => {
|
|
194
|
-
fixture.detectChanges();
|
|
195
|
-
|
|
196
|
-
// Rapidly change inputs multiple times
|
|
197
|
-
for (let i = 0; i < 10; i++) {
|
|
198
|
-
fixture.componentRef.setInput('timeFormat', i % 2 === 0 ? '24h' : '12h');
|
|
199
|
-
fixture.componentRef.setInput('showSeconds', i % 2 === 0);
|
|
200
|
-
fixture.componentRef.setInput('hasBackground', i % 3 === 0);
|
|
201
|
-
fixture.detectChanges();
|
|
202
|
-
|
|
203
|
-
// Should still display valid time format
|
|
204
|
-
const formattedTime = component.formattedTime();
|
|
205
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2}(:\d{2})?( (AM|PM))?$/);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('should maintain consistent formatting patterns', () => {
|
|
210
|
-
fixture.detectChanges();
|
|
211
|
-
|
|
212
|
-
// Test all combinations of inputs
|
|
213
|
-
const timeFormats: Array<'12h' | '24h'> = ['12h', '24h'];
|
|
214
|
-
const showSecondsOptions = [true, false];
|
|
215
|
-
const hasBackgroundOptions = [true, false];
|
|
216
|
-
|
|
217
|
-
timeFormats.forEach(timeFormat => {
|
|
218
|
-
showSecondsOptions.forEach(showSeconds => {
|
|
219
|
-
hasBackgroundOptions.forEach(hasBackground => {
|
|
220
|
-
fixture.componentRef.setInput('timeFormat', timeFormat);
|
|
221
|
-
fixture.componentRef.setInput('showSeconds', showSeconds);
|
|
222
|
-
fixture.componentRef.setInput('hasBackground', hasBackground);
|
|
223
|
-
fixture.detectChanges();
|
|
224
|
-
|
|
225
|
-
const formattedTime = component.formattedTime();
|
|
226
|
-
|
|
227
|
-
if (timeFormat === '24h') {
|
|
228
|
-
if (showSeconds) {
|
|
229
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
230
|
-
} else {
|
|
231
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2}$/);
|
|
232
|
-
}
|
|
233
|
-
expect(formattedTime).not.toContain('AM');
|
|
234
|
-
expect(formattedTime).not.toContain('PM');
|
|
235
|
-
} else {
|
|
236
|
-
if (showSeconds) {
|
|
237
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2}:\d{2} (AM|PM)$/);
|
|
238
|
-
} else {
|
|
239
|
-
expect(formattedTime).toMatch(/^\d{2}:\d{2} (AM|PM)$/);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
describe('Component Lifecycle', () => {
|
|
249
|
-
it('should handle component destruction cleanly', () => {
|
|
250
|
-
fixture.detectChanges();
|
|
251
|
-
|
|
252
|
-
// Destroy should not throw errors
|
|
253
|
-
expect(() => {
|
|
254
|
-
fixture.destroy();
|
|
255
|
-
}).not.toThrow();
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it('should provide consistent output across multiple initialization cycles', () => {
|
|
259
|
-
// Initialize and get initial time format
|
|
260
|
-
fixture.detectChanges();
|
|
261
|
-
const firstTime = component.formattedTime();
|
|
262
|
-
|
|
263
|
-
// Destroy and recreate
|
|
264
|
-
fixture.destroy();
|
|
265
|
-
fixture = TestBed.createComponent(DigitalClockComponent);
|
|
266
|
-
component = fixture.componentInstance;
|
|
267
|
-
fixture.detectChanges();
|
|
268
|
-
|
|
269
|
-
const secondTime = component.formattedTime();
|
|
270
|
-
|
|
271
|
-
// Both should be valid time formats (though potentially different times)
|
|
272
|
-
expect(firstTime).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
273
|
-
expect(secondTime).toMatch(/^\d{2}:\d{2}:\d{2}$/);
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<div responsiveText class="digital-time">{{ formattedTime() }}</div>
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// Digital Clock Component Styles
|
|
2
|
-
|
|
3
|
-
:host {
|
|
4
|
-
// Base widget styles
|
|
5
|
-
display: flex;
|
|
6
|
-
align-items: center;
|
|
7
|
-
justify-content: center;
|
|
8
|
-
height: 100%;
|
|
9
|
-
width: 100%;
|
|
10
|
-
box-sizing: border-box;
|
|
11
|
-
transition: background-color var(--mat-sys-motion-duration-medium2)
|
|
12
|
-
var(--mat-sys-motion-easing-standard);
|
|
13
|
-
|
|
14
|
-
// Clock widget padding and colors
|
|
15
|
-
padding: var(--mat-sys-spacing-4);
|
|
16
|
-
color: var(--mat-sys-on-surface-variant, #6c757d);
|
|
17
|
-
|
|
18
|
-
&.has-background {
|
|
19
|
-
background-color: var(--mat-sys-surface-container-high);
|
|
20
|
-
border-radius: 4px;
|
|
21
|
-
color: var(--mat-sys-on-surface, #1f1f1f);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
&:hover {
|
|
25
|
-
opacity: 0.8;
|
|
26
|
-
color: var(--mat-sys-primary, #6750a4);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Digital time display
|
|
31
|
-
.digital-time {
|
|
32
|
-
// Default: when NO PM is shown (regardless of seconds)
|
|
33
|
-
font-size: clamp(8px, min(20cqw, 50cqh), 200px);
|
|
34
|
-
font-family: monospace;
|
|
35
|
-
font-weight: 500;
|
|
36
|
-
letter-spacing: 0.05em;
|
|
37
|
-
transition: color 0.2s ease;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Smaller font when showing both PM AND seconds
|
|
41
|
-
:host.show-pm.show-seconds .digital-time {
|
|
42
|
-
font-size: clamp(8px, min(15cqw, 50cqh), 200px);
|
|
43
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
inject,
|
|
4
|
-
signal,
|
|
5
|
-
computed,
|
|
6
|
-
DestroyRef,
|
|
7
|
-
input,
|
|
8
|
-
ChangeDetectionStrategy,
|
|
9
|
-
} from '@angular/core';
|
|
10
|
-
|
|
11
|
-
export interface DigitalClockConfig {
|
|
12
|
-
timeFormat: '12h' | '24h';
|
|
13
|
-
showSeconds: boolean;
|
|
14
|
-
hasBackground: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
@Component({
|
|
18
|
-
selector: 'ngx-digital-clock',
|
|
19
|
-
standalone: true,
|
|
20
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
21
|
-
templateUrl: './digital-clock.component.html',
|
|
22
|
-
styleUrl: './digital-clock.component.scss',
|
|
23
|
-
host: {
|
|
24
|
-
'[class.has-background]': 'hasBackground()',
|
|
25
|
-
'[class.show-pm]': 'timeFormat() === "12h"',
|
|
26
|
-
'[class.show-seconds]': 'showSeconds()',
|
|
27
|
-
class: 'clock-widget digital',
|
|
28
|
-
},
|
|
29
|
-
})
|
|
30
|
-
export class DigitalClockComponent {
|
|
31
|
-
readonly #destroyRef = inject(DestroyRef);
|
|
32
|
-
|
|
33
|
-
// Inputs
|
|
34
|
-
timeFormat = input<'12h' | '24h'>('24h');
|
|
35
|
-
showSeconds = input<boolean>(true);
|
|
36
|
-
hasBackground = input<boolean>(false);
|
|
37
|
-
|
|
38
|
-
// Time tracking
|
|
39
|
-
currentTime = signal(new Date());
|
|
40
|
-
|
|
41
|
-
formattedTime = computed(() => {
|
|
42
|
-
const time = this.currentTime();
|
|
43
|
-
const format = this.timeFormat();
|
|
44
|
-
const showSecs = this.showSeconds();
|
|
45
|
-
return this.#formatTime(time, format, showSecs);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
#intervalId: number | null = null;
|
|
49
|
-
|
|
50
|
-
#formatTime(time: Date, format: '12h' | '24h', showSecs: boolean): string {
|
|
51
|
-
let hours = time.getHours();
|
|
52
|
-
const minutes = time.getMinutes();
|
|
53
|
-
const seconds = time.getSeconds();
|
|
54
|
-
|
|
55
|
-
// Pad with leading zeros
|
|
56
|
-
const mm = minutes.toString().padStart(2, '0');
|
|
57
|
-
const ss = seconds.toString().padStart(2, '0');
|
|
58
|
-
|
|
59
|
-
if (format === '12h') {
|
|
60
|
-
// 12-hour format with AM/PM
|
|
61
|
-
const ampm = hours >= 12 ? 'PM' : 'AM';
|
|
62
|
-
hours = hours % 12;
|
|
63
|
-
if (hours === 0) hours = 12; // Convert 0 to 12 for 12 AM/PM
|
|
64
|
-
|
|
65
|
-
const hh = hours.toString().padStart(2, '0');
|
|
66
|
-
return showSecs ? `${hh}:${mm}:${ss} ${ampm}` : `${hh}:${mm} ${ampm}`;
|
|
67
|
-
} else {
|
|
68
|
-
// 24-hour format
|
|
69
|
-
const hh = hours.toString().padStart(2, '0');
|
|
70
|
-
return showSecs ? `${hh}:${mm}:${ss}` : `${hh}:${mm}`;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
constructor() {
|
|
75
|
-
// Set up time update timer
|
|
76
|
-
this.#startTimer();
|
|
77
|
-
|
|
78
|
-
// Clean up timer on component destruction
|
|
79
|
-
this.#destroyRef.onDestroy(() => {
|
|
80
|
-
this.#stopTimer();
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
#startTimer(): void {
|
|
85
|
-
// Sync to the next second boundary for smooth start
|
|
86
|
-
const now = new Date();
|
|
87
|
-
const msUntilNextSecond = 1000 - now.getMilliseconds();
|
|
88
|
-
|
|
89
|
-
setTimeout(() => {
|
|
90
|
-
this.currentTime.set(new Date());
|
|
91
|
-
|
|
92
|
-
// Start the regular 1-second interval
|
|
93
|
-
this.#intervalId = window.setInterval(() => {
|
|
94
|
-
this.currentTime.set(new Date());
|
|
95
|
-
}, 1000);
|
|
96
|
-
}, msUntilNextSecond);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
#stopTimer(): void {
|
|
100
|
-
if (this.#intervalId !== null) {
|
|
101
|
-
clearInterval(this.#intervalId);
|
|
102
|
-
this.#intervalId = null;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|