@jjlmoya/utils-hardware 1.11.0 → 1.13.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 (32) hide show
  1. package/package.json +7 -4
  2. package/scripts/postinstall.mjs +27 -0
  3. package/src/entries.ts +23 -0
  4. package/src/tool/batteryHealthEstimator/component.astro +2 -369
  5. package/src/tool/batteryHealthEstimator/entry.ts +30 -0
  6. package/src/tool/batteryHealthEstimator/index.ts +2 -32
  7. package/src/tool/batteryHealthEstimator/lithium-battery-health-calculator.css +275 -0
  8. package/src/tool/deadPixelTest/component.astro +2 -445
  9. package/src/tool/deadPixelTest/dead-pixel-tester.css +400 -0
  10. package/src/tool/deadPixelTest/entry.ts +30 -0
  11. package/src/tool/deadPixelTest/index.ts +2 -32
  12. package/src/tool/gamepadTest/component.astro +2 -973
  13. package/src/tool/gamepadTest/entry.ts +30 -0
  14. package/src/tool/gamepadTest/gamepad-test.css +882 -0
  15. package/src/tool/gamepadTest/index.ts +2 -32
  16. package/src/tool/gamepadVibrationTester/component.astro +2 -404
  17. package/src/tool/gamepadVibrationTester/entry.ts +30 -0
  18. package/src/tool/gamepadVibrationTester/gamepad-vibration-tester.css +280 -0
  19. package/src/tool/gamepadVibrationTester/index.ts +2 -32
  20. package/src/tool/keyboardTest/component.astro +2 -333
  21. package/src/tool/keyboardTest/entry.ts +30 -0
  22. package/src/tool/keyboardTest/index.ts +2 -32
  23. package/src/tool/keyboardTest/keyboard-test.css +283 -0
  24. package/src/tool/mousePollingTest/component.astro +2 -172
  25. package/src/tool/mousePollingTest/entry.ts +30 -0
  26. package/src/tool/mousePollingTest/index.ts +2 -32
  27. package/src/tool/mousePollingTest/mouse-polling-rate-test.css +143 -0
  28. package/src/tool/toneGenerator/component.astro +2 -330
  29. package/src/tool/toneGenerator/entry.ts +30 -0
  30. package/src/tool/toneGenerator/index.ts +2 -32
  31. package/src/tool/toneGenerator/tone-frequency-generator.css +265 -0
  32. package/src/tools.ts +1 -1
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-hardware",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
7
7
  "exports": {
8
8
  ".": "./src/index.ts",
9
- "./data": "./src/data.ts"
9
+ "./data": "./src/data.ts",
10
+ "./entries": "./src/entries.ts"
10
11
  },
11
12
  "files": [
12
- "src"
13
+ "src",
14
+ "scripts"
13
15
  ],
14
16
  "publishConfig": {
15
17
  "access": "public"
@@ -28,7 +30,8 @@
28
30
  "postversion": "git push && git push --tags",
29
31
  "patch": "npm version patch",
30
32
  "minor": "npm version minor",
31
- "major": "npm version major"
33
+ "major": "npm version major",
34
+ "postinstall": "node scripts/postinstall.mjs"
32
35
  },
33
36
  "lint-staged": {
34
37
  "*.{ts,tsx,astro}": [
@@ -0,0 +1,27 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, readdirSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const libDir = dirname(fileURLToPath(import.meta.url));
6
+ const toolsDir = join(libDir, '../src/tool');
7
+
8
+ const inNodeModules = libDir.includes('node_modules');
9
+ if (!inNodeModules) process.exit(0);
10
+
11
+ const projectRoot = join(libDir, '../../../..');
12
+ const categoryKey = JSON.parse(readFileSync(join(libDir, '../package.json'), 'utf8')).name.replace('@jjlmoya/utils-', '');
13
+ const destDir = join(projectRoot, `public/styles/lib/${categoryKey}`);
14
+
15
+ mkdirSync(destDir, { recursive: true });
16
+
17
+ const tools = readdirSync(toolsDir, { withFileTypes: true }).filter(d => d.isDirectory());
18
+ for (const tool of tools) {
19
+ const toolDir = join(toolsDir, tool.name);
20
+ let files;
21
+ try { files = readdirSync(toolDir).filter(f => f.endsWith('.css')); }
22
+ catch { continue; }
23
+ for (const file of files) {
24
+ writeFileSync(join(destDir, file), readFileSync(join(toolDir, file)));
25
+ console.log(`[@jjlmoya/utils-${categoryKey}] copied ${file}`);
26
+ }
27
+ }
package/src/entries.ts ADDED
@@ -0,0 +1,23 @@
1
+ export { estimadorSaludBateria } from './tool/batteryHealthEstimator/entry';
2
+ export type { EstimadorSaludBateriaLocaleContent } from './tool/batteryHealthEstimator/entry';
3
+ export { pixelesPantalla } from './tool/deadPixelTest/entry';
4
+ export type { PixelesPantallaLocaleContent } from './tool/deadPixelTest/entry';
5
+ export { testMando } from './tool/gamepadTest/entry';
6
+ export type { TestMandoLocaleContent } from './tool/gamepadTest/entry';
7
+ export { probadorVibracionMando } from './tool/gamepadVibrationTester/entry';
8
+ export type { ProbadorVibracionMandoLocaleContent } from './tool/gamepadVibrationTester/entry';
9
+ export { testTeclado } from './tool/keyboardTest/entry';
10
+ export type { TestTecladoLocaleContent } from './tool/keyboardTest/entry';
11
+ export { testRaton } from './tool/mousePollingTest/entry';
12
+ export type { TestRatonLocaleContent } from './tool/mousePollingTest/entry';
13
+ export { toneGenerator } from './tool/toneGenerator/entry';
14
+ export type { ToneGeneratorLocaleContent } from './tool/toneGenerator/entry';
15
+ export { hardwareCategory } from './category';
16
+ import { estimadorSaludBateria } from './tool/batteryHealthEstimator/entry';
17
+ import { pixelesPantalla } from './tool/deadPixelTest/entry';
18
+ import { testMando } from './tool/gamepadTest/entry';
19
+ import { probadorVibracionMando } from './tool/gamepadVibrationTester/entry';
20
+ import { testTeclado } from './tool/keyboardTest/entry';
21
+ import { testRaton } from './tool/mousePollingTest/entry';
22
+ import { toneGenerator } from './tool/toneGenerator/entry';
23
+ export const ALL_ENTRIES = [estimadorSaludBateria, pixelesPantalla, testMando, probadorVibracionMando, testTeclado, testRaton, toneGenerator];
@@ -24,97 +24,7 @@ const S = JSON.stringify({
24
24
 
25
25
  <div id="bh-root" class="bh-wrapper" data-s={S}>
26
26
 
27
- <style is:global>
28
- .bh-wrapper {
29
- --bh-accent: #10b981;
30
- --bh-warn: #f59e0b;
31
- --bh-danger: #f43f5e;
32
- --bh-blue: #3b82f6;
33
- --bh-surface: #fff;
34
- --bh-surface-alt: #f8fafc;
35
- --bh-surface-dark: #020617;
36
- --bh-border: #e2e8f0;
37
- --bh-text: #0f172a;
38
- --bh-text-muted: #64748b;
39
- --bh-text-faint: #94a3b8;
40
- }
41
-
42
- .theme-dark .bh-wrapper {
43
- --bh-surface: #09090b;
44
- --bh-surface-alt: #18181b;
45
- --bh-border: #27272a;
46
- --bh-text: #fafafa;
47
- --bh-text-muted: #a1a1aa;
48
- --bh-text-faint: #52525b;
49
- }
50
-
51
- .bh-status-card[data-status="excelente"] {
52
- background: rgba(16, 185, 129, 0.08);
53
- border-color: rgba(16, 185, 129, 0.2);
54
- color: #065f46;
55
- }
56
-
57
- .theme-dark .bh-status-card[data-status="excelente"] {
58
- color: #34d399;
59
- }
60
-
61
- .bh-status-card[data-status="bueno"] {
62
- background: rgba(59, 130, 246, 0.08);
63
- border-color: rgba(59, 130, 246, 0.2);
64
- color: #1e40af;
65
- }
66
-
67
- .theme-dark .bh-status-card[data-status="bueno"] {
68
- color: #93c5fd;
69
- }
70
-
71
- .bh-status-card[data-status="regular"] {
72
- background: rgba(245, 158, 11, 0.08);
73
- border-color: rgba(245, 158, 11, 0.2);
74
- color: #92400e;
75
- }
76
-
77
- .theme-dark .bh-status-card[data-status="regular"] {
78
- color: #fcd34d;
79
- }
80
-
81
- .bh-status-card[data-status="critico"] {
82
- background: rgba(244, 63, 94, 0.08);
83
- border-color: rgba(244, 63, 94, 0.2);
84
- color: #9f1239;
85
- }
86
-
87
- .theme-dark .bh-status-card[data-status="critico"] {
88
- color: #fda4af;
89
- }
90
-
91
- .bh-rec {
92
- display: flex;
93
- gap: 0.5rem;
94
- align-items: flex-start;
95
- opacity: 0.85;
96
- }
97
-
98
- .bh-rec-dot {
99
- flex-shrink: 0;
100
- width: 0.25rem;
101
- height: 0.25rem;
102
- border-radius: 9999px;
103
- background: currentcolor;
104
- margin-top: 0.5rem;
105
- }
106
-
107
- .bh-rec p {
108
- margin: 0;
109
- font-size: 0.75rem;
110
- line-height: 1.5;
111
- }
112
-
113
- body.is-widget .bh-wrapper {
114
- padding: 0;
115
- }
116
- </style>
117
-
27
+
118
28
  <div class="bh-grid">
119
29
 
120
30
  <div class="bh-left">
@@ -204,284 +114,7 @@ const S = JSON.stringify({
204
114
 
205
115
  </div>
206
116
 
207
- <style>
208
- .bh-wrapper {
209
- width: 100%;
210
- color: var(--bh-text);
211
- }
212
-
213
- .bh-grid {
214
- display: grid;
215
- grid-template-columns: 1fr 2fr;
216
- gap: 2rem;
217
- align-items: start;
218
- }
219
-
220
- @media (max-width: 768px) {
221
- .bh-grid {
222
- grid-template-columns: 1fr;
223
- }
224
- }
225
-
226
- .bh-left {
227
- display: flex;
228
- flex-direction: column;
229
- gap: 1.25rem;
230
- }
231
-
232
- .bh-params-panel {
233
- background: var(--bh-surface);
234
- border: 1px solid var(--bh-border);
235
- border-radius: 1.5rem;
236
- padding: 2rem;
237
- }
238
-
239
- .bh-params-title {
240
- display: flex;
241
- align-items: center;
242
- gap: 0.5rem;
243
- font-size: 1rem;
244
- font-weight: 800;
245
- margin: 0 0 2rem;
246
- }
247
-
248
- .bh-params-icon {
249
- width: 1.25rem;
250
- height: 1.25rem;
251
- color: var(--bh-accent);
252
- }
253
-
254
- .bh-sliders {
255
- display: flex;
256
- flex-direction: column;
257
- gap: 2rem;
258
- }
259
-
260
- .bh-slider-group {
261
- display: flex;
262
- flex-direction: column;
263
- gap: 0.75rem;
264
- }
265
-
266
- .bh-slider-header {
267
- display: flex;
268
- justify-content: space-between;
269
- align-items: center;
270
- }
271
-
272
- .bh-slider-label {
273
- font-size: 0.7rem;
274
- font-weight: 800;
275
- text-transform: uppercase;
276
- letter-spacing: 0.1em;
277
- color: var(--bh-text-muted);
278
- }
279
-
280
- .bh-slider-val {
281
- font-size: 0.875rem;
282
- font-weight: 700;
283
- color: var(--bh-accent);
284
- }
285
-
286
- .bh-slider {
287
- -webkit-appearance: none;
288
- appearance: none;
289
- width: 100%;
290
- height: 6px;
291
- background: var(--bh-border);
292
- border-radius: 3px;
293
- outline: none;
294
- accent-color: var(--bh-accent);
295
- }
296
-
297
- .bh-slider::-webkit-slider-thumb {
298
- -webkit-appearance: none;
299
- appearance: none;
300
- width: 18px;
301
- height: 18px;
302
- background: var(--bh-accent);
303
- border-radius: 50%;
304
- cursor: pointer;
305
- border: 4px solid var(--bh-surface);
306
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
307
- }
308
-
309
- .bh-slider-hint {
310
- font-size: 0.625rem;
311
- color: var(--bh-text-faint);
312
- font-style: italic;
313
- margin: 0;
314
- }
315
-
316
- .bh-status-card {
317
- padding: 1.25rem;
318
- border-radius: 1rem;
319
- border: 1px solid var(--bh-border);
320
- display: flex;
321
- flex-direction: column;
322
- gap: 0.75rem;
323
- transition: background 400ms, border-color 400ms, color 400ms;
324
- }
325
-
326
- .bh-status-text {
327
- font-size: 0.8rem;
328
- font-weight: 800;
329
- text-transform: uppercase;
330
- letter-spacing: 0.05em;
331
- }
332
-
333
- .bh-recs {
334
- display: flex;
335
- flex-direction: column;
336
- gap: 0.5rem;
337
- }
338
-
339
- .bh-right {
340
- display: flex;
341
- flex-direction: column;
342
- gap: 1.5rem;
343
- }
344
-
345
- .bh-ring-wrap {
346
- background: var(--bh-surface);
347
- border: 1px solid var(--bh-border);
348
- border-radius: 1.5rem;
349
- padding: 2rem;
350
- display: flex;
351
- align-items: center;
352
- justify-content: center;
353
- min-height: 340px;
354
- position: relative;
355
- overflow: hidden;
356
- }
357
-
358
- .bh-ring-glow {
359
- position: absolute;
360
- inset: 0;
361
- background: radial-gradient(circle at 50% 50%, rgba(16, 185, 129, 0.05), transparent);
362
- pointer-events: none;
363
- }
364
-
365
- .bh-ring-container {
366
- position: relative;
367
- width: 220px;
368
- height: 220px;
369
- }
370
-
371
- .bh-ring-svg {
372
- width: 100%;
373
- height: 100%;
374
- transform: rotate(-90deg);
375
- }
376
-
377
- .bh-ring-track {
378
- color: var(--bh-border);
379
- stroke: currentcolor;
380
- }
381
-
382
- .bh-ring-progress {
383
- color: var(--bh-accent);
384
- stroke: currentcolor;
385
- transition: stroke-dashoffset 1s ease-out, stroke 500ms ease;
386
- }
387
-
388
- .bh-ring-overlay {
389
- position: absolute;
390
- inset: 0;
391
- display: flex;
392
- flex-direction: column;
393
- align-items: center;
394
- justify-content: center;
395
- text-align: center;
396
- }
397
-
398
- .bh-ring-label {
399
- font-size: 0.6rem;
400
- font-weight: 900;
401
- text-transform: uppercase;
402
- letter-spacing: 0.2em;
403
- color: var(--bh-text-faint);
404
- margin-bottom: 0.25rem;
405
- }
406
-
407
- .bh-ring-value {
408
- display: flex;
409
- align-items: flex-end;
410
- gap: 0.25rem;
411
- line-height: 1;
412
- }
413
-
414
- #bh-soh {
415
- font-size: 4rem;
416
- font-weight: 900;
417
- color: var(--bh-text);
418
- }
419
-
420
- .bh-ring-pct {
421
- font-size: 1.5rem;
422
- font-weight: 900;
423
- color: var(--bh-text-muted);
424
- margin-bottom: 0.25rem;
425
- }
426
-
427
- .bh-ring-years {
428
- margin-top: 1rem;
429
- padding: 0.375rem 1rem;
430
- border-radius: 9999px;
431
- background: var(--bh-surface-alt);
432
- border: 1px solid var(--bh-border);
433
- font-size: 0.65rem;
434
- font-weight: 900;
435
- text-transform: uppercase;
436
- letter-spacing: 0.1em;
437
- color: var(--bh-text-muted);
438
- }
439
-
440
- .bh-indicators {
441
- display: grid;
442
- grid-template-columns: repeat(3, 1fr);
443
- gap: 0.75rem;
444
- }
445
-
446
- .bh-indicator {
447
- background: var(--bh-surface);
448
- border: 1px solid var(--bh-border);
449
- border-radius: 1rem;
450
- padding: 1rem;
451
- }
452
-
453
- .bh-indicator-title {
454
- display: block;
455
- font-size: 0.6rem;
456
- font-weight: 900;
457
- text-transform: uppercase;
458
- letter-spacing: 0.1em;
459
- color: var(--bh-text-faint);
460
- margin-bottom: 0.5rem;
461
- }
462
-
463
- .bh-indicator-row {
464
- display: flex;
465
- align-items: center;
466
- gap: 0.5rem;
467
- }
468
-
469
- .bh-dot {
470
- width: 0.75rem;
471
- height: 0.75rem;
472
- border-radius: 9999px;
473
- background: var(--bh-accent);
474
- flex-shrink: 0;
475
- transition: background 300ms;
476
- }
477
-
478
- .bh-indicator-label {
479
- font-size: 0.8rem;
480
- font-weight: 700;
481
- color: var(--bh-text);
482
- }
483
- </style>
484
-
117
+
485
118
  <script>
486
119
  const root = document.getElementById('bh-root');
487
120
  const S: Record<string, string> = JSON.parse(root?.dataset?.s ?? '{}');
@@ -0,0 +1,30 @@
1
+ import type { HardwareToolEntry, ToolLocaleContent } from '../../types';
2
+
3
+
4
+ import type { EstimadorSaludBateriaUI } from './ui';
5
+ export type EstimadorSaludBateriaLocaleContent = ToolLocaleContent<EstimadorSaludBateriaUI>;
6
+
7
+ export const estimadorSaludBateria: HardwareToolEntry<EstimadorSaludBateriaUI> = {
8
+ id: 'estimador-salud-bateria',
9
+ icons: {
10
+ bg: 'mdi:battery-heart-variant',
11
+ fg: 'mdi:battery-charging-high',
12
+ },
13
+ i18n: {
14
+ de: () => import('./i18n/de').then((m) => m.content),
15
+ en: () => import('./i18n/en').then((m) => m.content),
16
+ es: () => import('./i18n/es').then((m) => m.content),
17
+ fr: () => import('./i18n/fr').then((m) => m.content),
18
+ id: () => import('./i18n/id').then((m) => m.content),
19
+ it: () => import('./i18n/it').then((m) => m.content),
20
+ ja: () => import('./i18n/ja').then((m) => m.content),
21
+ ko: () => import('./i18n/ko').then((m) => m.content),
22
+ nl: () => import('./i18n/nl').then((m) => m.content),
23
+ pl: () => import('./i18n/pl').then((m) => m.content),
24
+ pt: () => import('./i18n/pt').then((m) => m.content),
25
+ ru: () => import('./i18n/ru').then((m) => m.content),
26
+ sv: () => import('./i18n/sv').then((m) => m.content),
27
+ tr: () => import('./i18n/tr').then((m) => m.content),
28
+ zh: () => import('./i18n/zh').then((m) => m.content),
29
+ },
30
+ };
@@ -1,35 +1,5 @@
1
- import type { HardwareToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
-
3
-
4
- import type { EstimadorSaludBateriaUI } from './ui';
5
- export type EstimadorSaludBateriaLocaleContent = ToolLocaleContent<EstimadorSaludBateriaUI>;
6
-
7
- export const estimadorSaludBateria: HardwareToolEntry<EstimadorSaludBateriaUI> = {
8
- id: 'estimador-salud-bateria',
9
- icons: {
10
- bg: 'mdi:battery-heart-variant',
11
- fg: 'mdi:battery-charging-high',
12
- },
13
- i18n: {
14
- de: () => import('./i18n/de').then((m) => m.content),
15
- en: () => import('./i18n/en').then((m) => m.content),
16
- es: () => import('./i18n/es').then((m) => m.content),
17
- fr: () => import('./i18n/fr').then((m) => m.content),
18
- id: () => import('./i18n/id').then((m) => m.content),
19
- it: () => import('./i18n/it').then((m) => m.content),
20
- ja: () => import('./i18n/ja').then((m) => m.content),
21
- ko: () => import('./i18n/ko').then((m) => m.content),
22
- nl: () => import('./i18n/nl').then((m) => m.content),
23
- pl: () => import('./i18n/pl').then((m) => m.content),
24
- pt: () => import('./i18n/pt').then((m) => m.content),
25
- ru: () => import('./i18n/ru').then((m) => m.content),
26
- sv: () => import('./i18n/sv').then((m) => m.content),
27
- tr: () => import('./i18n/tr').then((m) => m.content),
28
- zh: () => import('./i18n/zh').then((m) => m.content),
29
- },
30
- };
31
-
32
-
1
+ import { estimadorSaludBateria } from './entry';
2
+ export * from './entry';
33
3
  export const ESTIMADOR_SALUD_BATERIA_TOOL: ToolDefinition = {
34
4
  entry: estimadorSaludBateria,
35
5
  Component: () => import('./component.astro'),