@jjlmoya/utils-hardware 1.18.0 → 1.19.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 (38) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +4 -1
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/pagespeed_best_practices.test.ts +198 -0
  7. package/src/tests/tool_validation.test.ts +2 -2
  8. package/src/tool/batteryHealthEstimator/component.astro +3 -3
  9. package/src/tool/gamepadTest/component.astro +4 -3
  10. package/src/tool/gamepadVibrationTester/component.astro +3 -3
  11. package/src/tool/keyboardTest/component.astro +6 -1
  12. package/src/tool/mouseDoubleClickTest/bibliography.astro +14 -0
  13. package/src/tool/mouseDoubleClickTest/bibliography.ts +16 -0
  14. package/src/tool/mouseDoubleClickTest/component.astro +135 -0
  15. package/src/tool/mouseDoubleClickTest/entry.ts +29 -0
  16. package/src/tool/mouseDoubleClickTest/i18n/de.ts +274 -0
  17. package/src/tool/mouseDoubleClickTest/i18n/en.ts +274 -0
  18. package/src/tool/mouseDoubleClickTest/i18n/es.ts +274 -0
  19. package/src/tool/mouseDoubleClickTest/i18n/fr.ts +274 -0
  20. package/src/tool/mouseDoubleClickTest/i18n/id.ts +285 -0
  21. package/src/tool/mouseDoubleClickTest/i18n/it.ts +274 -0
  22. package/src/tool/mouseDoubleClickTest/i18n/ja.ts +274 -0
  23. package/src/tool/mouseDoubleClickTest/i18n/ko.ts +274 -0
  24. package/src/tool/mouseDoubleClickTest/i18n/nl.ts +274 -0
  25. package/src/tool/mouseDoubleClickTest/i18n/pl.ts +274 -0
  26. package/src/tool/mouseDoubleClickTest/i18n/pt.ts +274 -0
  27. package/src/tool/mouseDoubleClickTest/i18n/ru.ts +274 -0
  28. package/src/tool/mouseDoubleClickTest/i18n/sv.ts +274 -0
  29. package/src/tool/mouseDoubleClickTest/i18n/tr.ts +274 -0
  30. package/src/tool/mouseDoubleClickTest/i18n/zh.ts +274 -0
  31. package/src/tool/mouseDoubleClickTest/index.ts +9 -0
  32. package/src/tool/mouseDoubleClickTest/logic.ts +258 -0
  33. package/src/tool/mouseDoubleClickTest/mouse-double-click-test.css +488 -0
  34. package/src/tool/mouseDoubleClickTest/seo.astro +15 -0
  35. package/src/tool/mouseDoubleClickTest/ui.ts +26 -0
  36. package/src/tool/mousePollingTest/logic/RatonManager.ts +6 -6
  37. package/src/tool/toneGenerator/component.astro +7 -7
  38. package/src/tools.ts +2 -2
@@ -0,0 +1,488 @@
1
+ .mdct-root {
2
+ --mdct-ink: #111827;
3
+ --mdct-muted: #667085;
4
+ --mdct-panel: #f8fafc;
5
+ --mdct-line: rgba(102, 112, 133, 0.18);
6
+ --mdct-line-strong: rgba(102, 112, 133, 0.32);
7
+ --mdct-blue: #2f86ff;
8
+ --mdct-green: #00a878;
9
+ --mdct-red: #e83f64;
10
+ --mdct-violet: #7c5cff;
11
+ --mdct-mouse: #d9e0ea;
12
+ --mdct-mouse-hi: #f2f5f9;
13
+ --mdct-button-bg: rgba(17, 24, 39, 0.035);
14
+ --mdct-button-border: rgba(17, 24, 39, 0.09);
15
+ --mdct-grid: rgba(47, 134, 255, 0.065);
16
+ --mdct-target-text: rgba(17, 24, 39, 0.64);
17
+ --mdct-chip-bg: rgba(17, 24, 39, 0.025);
18
+ --mdct-card-highlight: rgba(255, 255, 255, 0.8);
19
+ --mdct-shadow: rgba(16, 24, 40, 0.18);
20
+
21
+ width: 100%;
22
+ color: var(--mdct-ink);
23
+ }
24
+
25
+ .mdct-root *,
26
+ .mdct-root *::before,
27
+ .mdct-root *::after {
28
+ box-sizing: border-box;
29
+ }
30
+
31
+ .mdct-card {
32
+ width: min(100%, 62rem);
33
+ margin: 0 auto;
34
+ padding: 1.35rem;
35
+ border: 1px solid var(--mdct-line);
36
+ border-radius: 1.25rem;
37
+ background: var(--mdct-panel);
38
+ box-shadow: 0 24px 70px -42px var(--mdct-shadow), inset 0 1px 0 var(--mdct-card-highlight);
39
+ overflow: hidden;
40
+ }
41
+
42
+ .mdct-stage {
43
+ display: grid;
44
+ grid-template-columns: 1fr;
45
+ gap: 1.25rem;
46
+ }
47
+
48
+ .mdct-target {
49
+ min-height: 22rem;
50
+ border: 0;
51
+ background:
52
+ radial-gradient(circle at 50% 44%, rgba(47, 134, 255, 0.09), transparent 12rem),
53
+ linear-gradient(var(--mdct-grid) 1px, transparent 1px),
54
+ linear-gradient(90deg, var(--mdct-grid) 1px, transparent 1px);
55
+ background-size: auto, 4rem 4rem, 4rem 4rem;
56
+ color: #fff;
57
+ cursor: crosshair;
58
+ display: grid;
59
+ align-content: center;
60
+ justify-items: center;
61
+ position: relative;
62
+ overflow: hidden;
63
+ touch-action: none;
64
+ }
65
+
66
+ .mdct-target[data-flash='clean'] {
67
+ background:
68
+ radial-gradient(circle at 50% 44%, rgba(20, 214, 155, 0.16), transparent 12rem),
69
+ linear-gradient(var(--mdct-grid) 1px, transparent 1px),
70
+ linear-gradient(90deg, var(--mdct-grid) 1px, transparent 1px);
71
+ background-size: auto, 4rem 4rem, 4rem 4rem;
72
+ }
73
+
74
+ .mdct-target[data-flash='warning'] {
75
+ background:
76
+ radial-gradient(circle at 50% 44%, rgba(255, 63, 109, 0.18), transparent 12rem),
77
+ linear-gradient(var(--mdct-grid) 1px, transparent 1px),
78
+ linear-gradient(90deg, var(--mdct-grid) 1px, transparent 1px);
79
+ background-size: auto, 4rem 4rem, 4rem 4rem;
80
+ }
81
+
82
+ .mdct-mouse {
83
+ width: min(72vw, 22rem);
84
+ aspect-ratio: 0.78;
85
+ position: relative;
86
+ display: block;
87
+ border-radius: 48% 48% 42% 42% / 31% 31% 56% 56%;
88
+ background:
89
+ linear-gradient(90deg, transparent calc(50% - 1px), rgba(17, 24, 39, 0.1) calc(50% - 1px), rgba(17, 24, 39, 0.1) calc(50% + 1px), transparent calc(50% + 1px)),
90
+ linear-gradient(145deg, var(--mdct-mouse-hi), var(--mdct-mouse));
91
+ box-shadow:
92
+ 0 2rem 4rem rgba(16, 24, 40, 0.14),
93
+ inset 0 1px 0 rgba(255, 255, 255, 0.72),
94
+ inset 0 -3rem 4rem rgba(102, 112, 133, 0.12);
95
+ }
96
+
97
+ .mdct-cable {
98
+ position: absolute;
99
+ left: 50%;
100
+ bottom: 99%;
101
+ width: 0.2rem;
102
+ height: 4.2rem;
103
+ background: linear-gradient(transparent, rgba(102, 112, 133, 0.28));
104
+ transform: translateX(-50%);
105
+ }
106
+
107
+ .mdct-button {
108
+ position: absolute;
109
+ display: grid;
110
+ place-items: center;
111
+ border: 1px solid var(--mdct-button-border);
112
+ background: var(--mdct-button-bg);
113
+ color: var(--mdct-muted);
114
+ transition: background 140ms ease, border-color 140ms ease, color 140ms ease, transform 140ms ease;
115
+ }
116
+
117
+ .mdct-button::before {
118
+ content: attr(data-label);
119
+ font-size: 0.62rem;
120
+ font-weight: 900;
121
+ text-transform: uppercase;
122
+ }
123
+
124
+ .mdct-button::after {
125
+ content: attr(data-count);
126
+ position: absolute;
127
+ right: 0.55rem;
128
+ bottom: 0.45rem;
129
+ color: var(--mdct-blue);
130
+ font-size: 0.82rem;
131
+ font-weight: 950;
132
+ }
133
+
134
+ .mdct-button[data-count='0']::after {
135
+ color: rgba(102, 112, 133, 0.32);
136
+ }
137
+
138
+ .mdct-button[data-flash='clean'] {
139
+ background: rgba(20, 214, 155, 0.18);
140
+ border-color: rgba(20, 214, 155, 0.42);
141
+ color: var(--mdct-green);
142
+ }
143
+
144
+ .mdct-button[data-flash='warning'],
145
+ .mdct-button[data-state='warning'] {
146
+ background: rgba(255, 63, 109, 0.16);
147
+ border-color: rgba(255, 63, 109, 0.42);
148
+ color: var(--mdct-red);
149
+ }
150
+
151
+ .mdct-left,
152
+ .mdct-right {
153
+ top: 1rem;
154
+ width: calc(50% - 0.75rem);
155
+ height: 34%;
156
+ }
157
+
158
+ .mdct-left {
159
+ left: 0.75rem;
160
+ border-radius: 7rem 0.8rem 0.7rem 1.4rem;
161
+ }
162
+
163
+ .mdct-right {
164
+ right: 0.75rem;
165
+ border-radius: 0.8rem 7rem 1.4rem 0.7rem;
166
+ }
167
+
168
+ .mdct-middle {
169
+ left: 50%;
170
+ top: 1.35rem;
171
+ width: 1.1rem;
172
+ height: 4.1rem;
173
+ border-radius: 999rem;
174
+ background: linear-gradient(var(--mdct-blue), var(--mdct-violet));
175
+ border-color: rgba(47, 134, 255, 0.45);
176
+ box-shadow: 0 0 1.3rem rgba(47, 134, 255, 0.28);
177
+ transform: translateX(-50%);
178
+ z-index: 2;
179
+ }
180
+
181
+ .mdct-middle::before {
182
+ writing-mode: vertical-rl;
183
+ font-size: 0.48rem;
184
+ color: white;
185
+ }
186
+
187
+ .mdct-middle::after {
188
+ right: 50%;
189
+ bottom: -1.35rem;
190
+ transform: translateX(50%);
191
+ }
192
+
193
+ .mdct-back,
194
+ .mdct-forward {
195
+ left: -0.42rem;
196
+ width: 3.2rem;
197
+ height: 2.35rem;
198
+ border-radius: 999rem;
199
+ background: rgba(47, 134, 255, 0.08);
200
+ }
201
+
202
+ .mdct-back {
203
+ top: 39%;
204
+ }
205
+
206
+ .mdct-forward {
207
+ top: 51%;
208
+ }
209
+
210
+ .mdct-palm {
211
+ position: absolute;
212
+ left: 18%;
213
+ right: 18%;
214
+ bottom: 13%;
215
+ height: 38%;
216
+ border-radius: 50%;
217
+ border: 1px solid rgba(102, 112, 133, 0.13);
218
+ background: radial-gradient(circle at 50% 10%, rgba(255, 255, 255, 0.28), transparent 62%);
219
+ }
220
+
221
+ .mdct-target-copy {
222
+ display: grid;
223
+ gap: 0.35rem;
224
+ margin-top: 1.1rem;
225
+ text-align: center;
226
+ }
227
+
228
+ .mdct-target-kicker {
229
+ display: inline-flex;
230
+ align-items: center;
231
+ justify-content: center;
232
+ gap: 0.4rem;
233
+ color: var(--mdct-muted);
234
+ font-size: 0.68rem;
235
+ font-weight: 900;
236
+ text-transform: uppercase;
237
+ }
238
+
239
+ .mdct-target-icon {
240
+ width: 0.95rem;
241
+ height: 0.95rem;
242
+ }
243
+
244
+ .mdct-target strong {
245
+ color: var(--mdct-ink);
246
+ font-size: 0.9rem;
247
+ font-weight: 950;
248
+ }
249
+
250
+ .mdct-target small {
251
+ color: var(--mdct-target-text);
252
+ font-size: 0.75rem;
253
+ font-weight: 800;
254
+ }
255
+
256
+ .mdct-dashboard {
257
+ display: grid;
258
+ align-content: start;
259
+ gap: 1rem;
260
+ min-width: 0;
261
+ }
262
+
263
+ .mdct-readout,
264
+ .mdct-metrics,
265
+ .mdct-threshold,
266
+ .mdct-speed-row {
267
+ padding-bottom: 1rem;
268
+ border-bottom: 1px solid var(--mdct-line);
269
+ }
270
+
271
+ .mdct-readout {
272
+ display: grid;
273
+ gap: 0.2rem;
274
+ }
275
+
276
+ .mdct-readout span,
277
+ .mdct-threshold span,
278
+ .mdct-speed-row span,
279
+ .mdct-log-head span,
280
+ .mdct-metric span {
281
+ color: var(--mdct-muted);
282
+ font-size: 0.72rem;
283
+ font-weight: 900;
284
+ text-transform: uppercase;
285
+ }
286
+
287
+ .mdct-readout strong {
288
+ color: var(--mdct-violet);
289
+ font-size: clamp(2.4rem, 6vw, 3.2rem);
290
+ font-weight: 950;
291
+ line-height: 0.95;
292
+ }
293
+
294
+ .mdct-readout small {
295
+ color: var(--mdct-green);
296
+ font-size: 0.78rem;
297
+ font-weight: 800;
298
+ }
299
+
300
+ .mdct-readout small[data-state='warning'] {
301
+ color: var(--mdct-red);
302
+ }
303
+
304
+ .mdct-metrics,
305
+ .mdct-speed-row {
306
+ display: grid;
307
+ grid-template-columns: repeat(2, minmax(0, 1fr));
308
+ gap: 1rem;
309
+ }
310
+
311
+ .mdct-metric,
312
+ .mdct-speed-row div {
313
+ display: grid;
314
+ gap: 0.45rem;
315
+ }
316
+
317
+ .mdct-metric strong {
318
+ font-size: 1.35rem;
319
+ line-height: 1;
320
+ }
321
+
322
+ .mdct-metric-total strong,
323
+ .mdct-threshold b {
324
+ color: var(--mdct-blue);
325
+ }
326
+
327
+ .mdct-metric-alert strong {
328
+ color: var(--mdct-red);
329
+ }
330
+
331
+ .mdct-threshold {
332
+ display: grid;
333
+ grid-template-columns: 1fr auto;
334
+ gap: 0.65rem;
335
+ align-items: center;
336
+ }
337
+
338
+ .mdct-threshold input {
339
+ grid-column: 1 / -1;
340
+ width: 100%;
341
+ accent-color: var(--mdct-blue);
342
+ }
343
+
344
+ .mdct-threshold b {
345
+ font-size: 0.82rem;
346
+ }
347
+
348
+ .mdct-speed-row strong {
349
+ color: var(--mdct-ink);
350
+ font-size: 1rem;
351
+ }
352
+
353
+ .mdct-log-head {
354
+ display: flex;
355
+ align-items: center;
356
+ justify-content: space-between;
357
+ gap: 0.5rem;
358
+ }
359
+
360
+ .mdct-reset {
361
+ border: 1px solid var(--mdct-line-strong);
362
+ border-radius: 0.45rem;
363
+ padding: 0.52rem 1rem;
364
+ background: transparent;
365
+ color: var(--mdct-muted);
366
+ font-size: 0.78rem;
367
+ font-weight: 900;
368
+ cursor: pointer;
369
+ }
370
+
371
+ .mdct-reset:hover {
372
+ border-color: var(--mdct-blue);
373
+ color: var(--mdct-blue);
374
+ }
375
+
376
+ .mdct-log {
377
+ list-style: none;
378
+ margin: 0;
379
+ padding: 0;
380
+ display: flex;
381
+ flex-wrap: wrap;
382
+ gap: 0.45rem;
383
+ }
384
+
385
+ .mdct-log-item,
386
+ .mdct-empty {
387
+ display: inline-flex;
388
+ align-items: center;
389
+ gap: 0.42rem;
390
+ min-height: 1.85rem;
391
+ padding: 0.35rem 0.55rem;
392
+ border: 1px solid var(--mdct-line);
393
+ border-radius: 999rem;
394
+ background: var(--mdct-chip-bg);
395
+ font-size: 0.72rem;
396
+ font-weight: 900;
397
+ }
398
+
399
+ .mdct-log-item.clean b {
400
+ color: var(--mdct-green);
401
+ }
402
+
403
+ .mdct-log-item.suspect b {
404
+ color: var(--mdct-red);
405
+ }
406
+
407
+ .mdct-log-item span,
408
+ .mdct-log-item em,
409
+ .mdct-empty {
410
+ color: var(--mdct-muted);
411
+ }
412
+
413
+ .mdct-log-item em {
414
+ font-style: normal;
415
+ opacity: 0.76;
416
+ }
417
+
418
+ @media (min-width: 780px) {
419
+ .mdct-card {
420
+ padding: 1.4rem;
421
+ }
422
+
423
+ .mdct-stage {
424
+ grid-template-columns: minmax(0, 1.45fr) minmax(18rem, 0.72fr);
425
+ align-items: stretch;
426
+ }
427
+
428
+ .mdct-target {
429
+ min-height: 27rem;
430
+ }
431
+ }
432
+
433
+ @media (max-width: 520px) {
434
+ .mdct-card {
435
+ padding: 1rem;
436
+ }
437
+
438
+ .mdct-target {
439
+ min-height: 22rem;
440
+ }
441
+
442
+ .mdct-mouse {
443
+ width: min(78vw, 18rem);
444
+ }
445
+ }
446
+
447
+ body.is-widget .mdct-card {
448
+ width: 100%;
449
+ }
450
+
451
+ .theme-dark .mdct-root {
452
+ --mdct-ink: #f5f7fb;
453
+ --mdct-muted: #8f97a8;
454
+ --mdct-panel: #11151c;
455
+ --mdct-line: rgba(145, 154, 174, 0.2);
456
+ --mdct-line-strong: rgba(145, 154, 174, 0.34);
457
+ --mdct-green: #14d69b;
458
+ --mdct-red: #ff3f6d;
459
+ --mdct-violet: #9c7bff;
460
+ --mdct-mouse: #1a202b;
461
+ --mdct-mouse-hi: #252c39;
462
+ --mdct-button-bg: rgba(255, 255, 255, 0.045);
463
+ --mdct-button-border: rgba(255, 255, 255, 0.08);
464
+ --mdct-grid: rgba(47, 134, 255, 0.035);
465
+ --mdct-target-text: rgba(245, 247, 251, 0.68);
466
+ --mdct-chip-bg: rgba(255, 255, 255, 0.025);
467
+ --mdct-card-highlight: rgba(255, 255, 255, 0.035);
468
+ --mdct-shadow: rgba(0, 0, 0, 0.5);
469
+ }
470
+
471
+ .theme-dark .mdct-mouse {
472
+ background:
473
+ linear-gradient(90deg, transparent calc(50% - 1px), rgba(255, 255, 255, 0.12) calc(50% - 1px), rgba(255, 255, 255, 0.12) calc(50% + 1px), transparent calc(50% + 1px)),
474
+ linear-gradient(145deg, var(--mdct-mouse-hi), var(--mdct-mouse));
475
+ box-shadow:
476
+ 0 2rem 4rem rgba(0, 0, 0, 0.32),
477
+ inset 0 1px 0 rgba(255, 255, 255, 0.11),
478
+ inset 0 -3rem 4rem rgba(0, 0, 0, 0.24);
479
+ }
480
+
481
+ .theme-dark .mdct-cable {
482
+ background: linear-gradient(transparent, rgba(143, 151, 168, 0.32));
483
+ }
484
+
485
+ .theme-dark .mdct-palm {
486
+ border-color: rgba(143, 151, 168, 0.11);
487
+ background: radial-gradient(circle at 50% 10%, rgba(255, 255, 255, 0.04), transparent 62%);
488
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { mouseDoubleClickTest } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'en' } = Astro.props;
11
+ const content = await mouseDoubleClickTest.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,26 @@
1
+ export interface MouseDoubleClickTestUI extends Record<string, string> {
2
+ badge: string;
3
+ clickTarget: string;
4
+ clickTargetHint: string;
5
+ totalClicks: string;
6
+ suspiciousClicks: string;
7
+ fastestGap: string;
8
+ healthScore: string;
9
+ thresholdLabel: string;
10
+ thresholdUnit: string;
11
+ cleanEvent: string;
12
+ suspiciousEvent: string;
13
+ reset: string;
14
+ statusIdle: string;
15
+ statusClean: string;
16
+ statusWarning: string;
17
+ lastGap: string;
18
+ logTitle: string;
19
+ emptyLog: string;
20
+ leftButton: string;
21
+ middleButton: string;
22
+ rightButton: string;
23
+ backButton: string;
24
+ forwardButton: string;
25
+ otherButton: string;
26
+ }
@@ -83,19 +83,19 @@ export class RatonManager {
83
83
  }
84
84
 
85
85
  private updateUI(hz: number, avg: number): void {
86
- const { max, avg: avgEl, placeholder } = this.el;
86
+ const { max, avg: avgEl, placeholder, area } = this.el;
87
+ const rect = area?.getBoundingClientRect();
87
88
  if (max) max.textContent = Math.round(this.maxHz).toString();
88
89
  if (avgEl) avgEl.textContent = Math.round(avg).toString();
89
90
  if (placeholder) placeholder.style.opacity = '0';
90
- this.updateFollower(hz);
91
+ this.updateFollower(hz, rect);
91
92
  this.updateGraph();
92
93
  }
93
94
 
94
- private updateFollower(hz: number): void {
95
- const { follower, area } = this.el;
96
- if (!follower || !this.lastMouseEvent || !area) return;
95
+ private updateFollower(hz: number, rect: DOMRect | undefined): void {
96
+ const { follower } = this.el;
97
+ if (!follower || !this.lastMouseEvent || !rect) return;
97
98
  follower.textContent = `${Math.round(hz)} Hz`;
98
- const rect = area.getBoundingClientRect();
99
99
  const x: number = this.lastMouseEvent.clientX - rect.left + 15;
100
100
  const y: number = this.lastMouseEvent.clientY - rect.top + 15;
101
101
  follower.style.transform = `translate(${x}px, ${y}px)`;
@@ -39,7 +39,7 @@ const S = JSON.stringify({ bp: t.btnPlay, bs: t.btnStop });
39
39
 
40
40
  <div class="tg-section">
41
41
  <div class="tg-section-header">
42
- <label class="tg-label">{t.freqLabel}</label>
42
+ <label class="tg-label" for="tg-freq">{t.freqLabel}</label>
43
43
  <div class="tg-presets">
44
44
  <button class="tg-preset" data-val="60">{t.preset60}</button>
45
45
  <button class="tg-preset" data-val="440">{t.preset440}</button>
@@ -73,7 +73,7 @@ const S = JSON.stringify({ bp: t.btnPlay, bs: t.btnStop });
73
73
  </div>
74
74
 
75
75
  <div class="tg-section">
76
- <label class="tg-label">{t.volLabel}</label>
76
+ <label class="tg-label" for="tg-vol">{t.volLabel}</label>
77
77
  <div class="tg-vol-row">
78
78
  <Icon name="mdi:volume-high" class="tg-vol-icon" />
79
79
  <input type="range" id="tg-vol" class="tg-slider tg-vol-slider" min="0" max="1" value="0.5" step="0.01" />
@@ -131,11 +131,6 @@ const S = JSON.stringify({ bp: t.btnPlay, bs: t.btnStop });
131
131
  return true;
132
132
  }
133
133
 
134
- function updateUI(playing: boolean): void {
135
- if (toggleBtn) toggleBtn.dataset.playing = playing ? 'true' : 'false';
136
- if (btnText) btnText.textContent = playing ? BS : BP;
137
- }
138
-
139
134
  function resizeCanvas(): void {
140
135
  if (!canvas) return;
141
136
  const parent = canvas.parentElement;
@@ -145,6 +140,11 @@ const S = JSON.stringify({ bp: t.btnPlay, bs: t.btnStop });
145
140
  if (canvas.height !== rect.height) canvas.height = rect.height;
146
141
  }
147
142
 
143
+ function updateUI(playing: boolean): void {
144
+ if (toggleBtn) toggleBtn.dataset.playing = playing ? 'true' : 'false';
145
+ if (btnText) btnText.textContent = playing ? BS : BP;
146
+ }
147
+
148
148
  function drawWave(w: number, h: number, data: Uint8Array): void {
149
149
  if (!canvasCtx) return;
150
150
  canvasCtx.fillStyle = 'rgb(0,0,0)';
package/src/tools.ts CHANGED
@@ -9,6 +9,6 @@ import { ESTIMADOR_SALUD_BATERIA_TOOL } from './tool/batteryHealthEstimator/inde
9
9
  import { TONE_GENERATOR_TOOL } from './tool/toneGenerator/index';
10
10
  import { REFRESH_RATE_DETECTOR_TOOL } from './tool/refreshRateDetector/index';
11
11
  import { SPECTRUM_CANVAS_TOOL } from './tool/colorAccuracyTest/index';
12
+ import { MOUSE_DOUBLE_CLICK_TEST_TOOL } from './tool/mouseDoubleClickTest/index';
12
13
 
13
- export const ALL_TOOLS: ToolDefinition[] = [PIXELES_PANTALLA_TOOL, TEST_TECLADO_TOOL, TEST_MANDO_TOOL, PROBADOR_VIBRACION_MANDO_TOOL, TEST_RATON_TOOL, ESTIMADOR_SALUD_BATERIA_TOOL, TONE_GENERATOR_TOOL, REFRESH_RATE_DETECTOR_TOOL, SPECTRUM_CANVAS_TOOL];
14
-
14
+ export const ALL_TOOLS: ToolDefinition[] = [PIXELES_PANTALLA_TOOL, TEST_TECLADO_TOOL, TEST_MANDO_TOOL, PROBADOR_VIBRACION_MANDO_TOOL, TEST_RATON_TOOL, MOUSE_DOUBLE_CLICK_TEST_TOOL, ESTIMADOR_SALUD_BATERIA_TOOL, TONE_GENERATOR_TOOL, REFRESH_RATE_DETECTOR_TOOL, SPECTRUM_CANVAS_TOOL];