@jjlmoya/utils-home 1.14.0 → 1.16.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/dewPointCalculator/component.astro +0 -232
  5. package/src/tool/dewPointCalculator/dew-point-calculator.css +230 -0
  6. package/src/tool/dewPointCalculator/entry.ts +32 -0
  7. package/src/tool/dewPointCalculator/index.ts +2 -34
  8. package/src/tool/heatingComparator/component.astro +0 -269
  9. package/src/tool/heatingComparator/entry.ts +30 -0
  10. package/src/tool/heatingComparator/heating-consumption-comparator.css +267 -0
  11. package/src/tool/heatingComparator/index.ts +2 -32
  12. package/src/tool/ledSavingCalculator/component.astro +0 -305
  13. package/src/tool/ledSavingCalculator/entry.ts +31 -0
  14. package/src/tool/ledSavingCalculator/index.ts +2 -33
  15. package/src/tool/ledSavingCalculator/led-saving-calculator.css +303 -0
  16. package/src/tool/projectorCalculator/component.astro +0 -359
  17. package/src/tool/projectorCalculator/entry.ts +31 -0
  18. package/src/tool/projectorCalculator/index.ts +2 -33
  19. package/src/tool/projectorCalculator/projector-throw-calculator.css +357 -0
  20. package/src/tool/qrGenerator/component.astro +0 -266
  21. package/src/tool/qrGenerator/entry.ts +30 -0
  22. package/src/tool/qrGenerator/index.ts +2 -32
  23. package/src/tool/qrGenerator/qr-generator.css +264 -0
  24. package/src/tool/solarCalculator/component.astro +0 -298
  25. package/src/tool/solarCalculator/entry.ts +30 -0
  26. package/src/tool/solarCalculator/index.ts +2 -32
  27. package/src/tool/solarCalculator/solar-panel-calculator.css +296 -0
  28. package/src/tool/tariffComparator/component.astro +0 -337
  29. package/src/tool/tariffComparator/electricity-tariff-comparator.css +335 -0
  30. package/src/tool/tariffComparator/entry.ts +31 -0
  31. package/src/tool/tariffComparator/index.ts +2 -33
  32. package/src/tools.ts +1 -1
@@ -0,0 +1,264 @@
1
+ .qr-wrapper {
2
+ --qr-p: #3b82f6;
3
+
4
+ width: 100%;
5
+ padding: 1rem 0;
6
+ }
7
+
8
+ .qr-card {
9
+ background: var(--bg-surface);
10
+ width: calc(100% - 24px);
11
+ max-width: 900px;
12
+ margin: 0 auto;
13
+ border-radius: 24px;
14
+ overflow: hidden;
15
+ display: flex;
16
+ flex-direction: column;
17
+ border: 1px solid var(--border-color);
18
+ color: var(--text-main);
19
+ }
20
+
21
+ @media (min-width: 768px) {
22
+ .qr-card {
23
+ flex-direction: row;
24
+ min-height: 520px;
25
+ }
26
+ }
27
+
28
+ .qr-left {
29
+ flex: 1;
30
+ padding: 32px;
31
+ border-bottom: 1px solid var(--border-color);
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: 24px;
35
+ }
36
+
37
+ @media (min-width: 768px) {
38
+ .qr-left {
39
+ border-bottom: none;
40
+ border-right: 1px solid var(--border-color);
41
+ }
42
+ }
43
+
44
+ .qr-right {
45
+ flex: 0 0 auto;
46
+ width: 100%;
47
+ background: var(--bg-muted);
48
+ padding: 40px 32px;
49
+ display: flex;
50
+ flex-direction: column;
51
+ align-items: center;
52
+ justify-content: center;
53
+ gap: 24px;
54
+ position: relative;
55
+ }
56
+
57
+ @media (min-width: 768px) {
58
+ .qr-right {
59
+ width: 340px;
60
+ }
61
+ }
62
+
63
+ .tab-bar {
64
+ display: flex;
65
+ background: var(--bg-muted);
66
+ padding: 4px;
67
+ border-radius: 14px;
68
+ gap: 2px;
69
+ }
70
+
71
+ .tab-btn {
72
+ flex: 1;
73
+ padding: 10px;
74
+ border: none;
75
+ background: transparent;
76
+ border-radius: 10px;
77
+ font-size: 11px;
78
+ font-weight: 800;
79
+ text-transform: uppercase;
80
+ letter-spacing: 0.12em;
81
+ color: var(--text-muted);
82
+ cursor: pointer;
83
+ transition: all 0.2s;
84
+ }
85
+
86
+ .tab-btn.active {
87
+ background: var(--bg-surface);
88
+ color: var(--text-main);
89
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
90
+ }
91
+
92
+ .qr-form {
93
+ display: flex;
94
+ flex-direction: column;
95
+ gap: 16px;
96
+ }
97
+
98
+ .qr-form.hidden {
99
+ display: none;
100
+ }
101
+
102
+ .field-group {
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: 6px;
106
+ }
107
+
108
+ .field-label {
109
+ font-size: 12px;
110
+ font-weight: 700;
111
+ color: var(--text-muted);
112
+ }
113
+
114
+ .field-input {
115
+ width: 100%;
116
+ padding: 10px 14px;
117
+ background: var(--bg-muted);
118
+ border: 1px solid var(--border-color);
119
+ border-radius: 10px;
120
+ font-size: 14px;
121
+ font-weight: 500;
122
+ color: var(--text-main);
123
+ transition: border-color 0.2s, box-shadow 0.2s;
124
+ box-sizing: border-box;
125
+ }
126
+
127
+ .field-input:focus {
128
+ outline: none;
129
+ border-color: var(--qr-p);
130
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
131
+ }
132
+
133
+ .input-row {
134
+ position: relative;
135
+ }
136
+
137
+ .input-row .field-input {
138
+ padding-right: 44px;
139
+ }
140
+
141
+ .eye-btn {
142
+ position: absolute;
143
+ right: 10px;
144
+ top: 50%;
145
+ transform: translateY(-50%);
146
+ background: none;
147
+ border: none;
148
+ cursor: pointer;
149
+ color: var(--text-muted);
150
+ padding: 4px;
151
+ display: flex;
152
+ }
153
+
154
+ .eye-btn svg {
155
+ width: 18px;
156
+ height: 18px;
157
+ }
158
+
159
+ .two-col {
160
+ display: grid;
161
+ grid-template-columns: 1fr 1fr;
162
+ gap: 12px;
163
+ }
164
+
165
+ .check-group {
166
+ justify-content: flex-end;
167
+ padding-bottom: 2px;
168
+ }
169
+
170
+ .check-label {
171
+ display: flex;
172
+ align-items: center;
173
+ gap: 8px;
174
+ cursor: pointer;
175
+ font-size: 13px;
176
+ color: var(--text-muted);
177
+ padding-top: 22px;
178
+ }
179
+
180
+ .check-input {
181
+ width: 16px;
182
+ height: 16px;
183
+ accent-color: var(--qr-p);
184
+ }
185
+
186
+ .qr-preview-area {
187
+ position: relative;
188
+ width: 100%;
189
+ max-width: 260px;
190
+ }
191
+
192
+ .canvas-glow {
193
+ position: relative;
194
+ }
195
+
196
+ .canvas-glow::before {
197
+ content: "";
198
+ position: absolute;
199
+ inset: -4px;
200
+ background: linear-gradient(135deg, #3b82f6, #06b6d4);
201
+ border-radius: 20px;
202
+ filter: blur(12px);
203
+ opacity: 0.3;
204
+ transition: opacity 0.3s;
205
+ }
206
+
207
+ .canvas-glow:hover::before {
208
+ opacity: 0.55;
209
+ }
210
+
211
+ .canvas-box {
212
+ position: relative;
213
+ background: var(--bg-surface);
214
+ border: 1px solid var(--border-color);
215
+ border-radius: 16px;
216
+ padding: 16px;
217
+ display: flex;
218
+ align-items: center;
219
+ justify-content: center;
220
+ }
221
+
222
+ .canvas-box canvas {
223
+ width: 100%;
224
+ height: auto;
225
+ }
226
+
227
+ .download-btn {
228
+ display: flex;
229
+ align-items: center;
230
+ gap: 8px;
231
+ padding: 12px 24px;
232
+ background: var(--qr-p);
233
+ color: #fff;
234
+ border: none;
235
+ border-radius: 12px;
236
+ font-size: 13px;
237
+ font-weight: 700;
238
+ cursor: pointer;
239
+ transition: all 0.2s;
240
+ box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
241
+ }
242
+
243
+ .download-btn:hover {
244
+ filter: brightness(1.1);
245
+ box-shadow: 0 6px 16px rgba(59, 130, 246, 0.4);
246
+ transform: translateY(-1px);
247
+ }
248
+
249
+ .download-btn svg {
250
+ width: 18px;
251
+ height: 18px;
252
+ }
253
+
254
+ .privacy-msg {
255
+ font-size: 12px;
256
+ color: var(--text-muted);
257
+ text-align: center;
258
+ max-width: 220px;
259
+ line-height: 1.5;
260
+ }
261
+
262
+ .theme-dark .canvas-box {
263
+ background: #020617;
264
+ }
@@ -232,301 +232,3 @@ const initial = calculateTilt(40.41);
232
232
  init();
233
233
  </script>
234
234
 
235
- <style>
236
- .solar-wrapper {
237
- --solar-p: #f97316;
238
- --solar-winter: #3b82f6;
239
- --solar-summer: #eab308;
240
-
241
- width: 100%;
242
- padding: 1rem 0;
243
- }
244
-
245
- .solar-card {
246
- background: var(--bg-surface);
247
- width: calc(100% - 24px);
248
- max-width: 960px;
249
- margin: 0 auto;
250
- border-radius: 24px;
251
- overflow: hidden;
252
- display: flex;
253
- flex-direction: column;
254
- border: 1px solid var(--border-color);
255
- color: var(--text-main);
256
- }
257
-
258
- @media (min-width: 768px) {
259
- .solar-card {
260
- flex-direction: row;
261
- min-height: 560px;
262
- }
263
- }
264
-
265
- .solar-left {
266
- flex: 0 0 auto;
267
- width: 100%;
268
- padding: 32px;
269
- border-bottom: 1px solid var(--border-color);
270
- display: flex;
271
- flex-direction: column;
272
- gap: 24px;
273
- }
274
-
275
- @media (min-width: 768px) {
276
- .solar-left {
277
- width: 340px;
278
- border-bottom: none;
279
- border-right: 1px solid var(--border-color);
280
- }
281
- }
282
-
283
- .solar-right {
284
- flex: 1;
285
- background: #020617;
286
- position: relative;
287
- overflow: hidden;
288
- display: flex;
289
- align-items: center;
290
- justify-content: center;
291
- min-height: 380px;
292
- }
293
-
294
- .viz-dots {
295
- position: absolute;
296
- inset: 0;
297
- opacity: 0.15;
298
- pointer-events: none;
299
- background-image: radial-gradient(#fff 1px, transparent 1px);
300
- background-size: 24px 24px;
301
- }
302
-
303
- .viz-svg {
304
- width: 100%;
305
- height: 100%;
306
- position: relative;
307
- z-index: 1;
308
- padding: 1rem;
309
- }
310
-
311
- .sun-pulse {
312
- animation: pulse 2s ease-in-out infinite;
313
- }
314
-
315
- @keyframes pulse {
316
- 0%, 100% { opacity: 0.2; }
317
- 50% { opacity: 0.5; }
318
- }
319
-
320
- .field-group {
321
- display: flex;
322
- flex-direction: column;
323
- gap: 8px;
324
- }
325
-
326
- .field-label {
327
- font-size: 11px;
328
- font-weight: 700;
329
- color: var(--text-muted);
330
- text-transform: uppercase;
331
- letter-spacing: 0.1em;
332
- }
333
-
334
- .lat-row {
335
- position: relative;
336
- }
337
-
338
- .lat-input {
339
- width: 100%;
340
- font-size: 2.5rem;
341
- font-weight: 900;
342
- color: var(--text-main);
343
- background: transparent;
344
- border: none;
345
- border-bottom: 2px solid var(--border-color);
346
- padding: 4px 2.5rem 4px 0;
347
- outline: none;
348
- transition: border-color 0.2s;
349
- box-sizing: border-box;
350
- }
351
-
352
- .lat-input:focus {
353
- border-color: var(--solar-p);
354
- }
355
-
356
- .deg-unit {
357
- position: absolute;
358
- right: 8px;
359
- bottom: 8px;
360
- font-size: 1.5rem;
361
- color: var(--text-muted);
362
- font-weight: 300;
363
- }
364
-
365
- .locate-btn {
366
- display: inline-flex;
367
- align-items: center;
368
- gap: 6px;
369
- background: none;
370
- border: none;
371
- color: var(--solar-p);
372
- font-size: 0.8125rem;
373
- font-weight: 700;
374
- cursor: pointer;
375
- padding: 0;
376
- transition: opacity 0.2s;
377
- }
378
-
379
- .locate-btn:hover {
380
- opacity: 0.75;
381
- }
382
-
383
- .locate-btn.loading {
384
- opacity: 0.5;
385
- pointer-events: none;
386
- }
387
-
388
- .locate-btn svg {
389
- width: 16px;
390
- height: 16px;
391
- }
392
-
393
- .optimal-card {
394
- background: var(--bg-muted);
395
- border-radius: 16px;
396
- padding: 20px;
397
- border: 1px solid var(--border-color);
398
- position: relative;
399
- overflow: hidden;
400
- }
401
-
402
- .optimal-card::after {
403
- content: '';
404
- position: absolute;
405
- top: 0;
406
- right: 0;
407
- width: 80px;
408
- height: 80px;
409
- background: radial-gradient(circle at top right, rgba(249, 115, 22, 0.2), transparent);
410
- border-radius: 0 0 0 80px;
411
- }
412
-
413
- .optimal-label {
414
- font-size: 0.8125rem;
415
- color: var(--text-muted);
416
- font-weight: 500;
417
- margin: 0 0 4px;
418
- }
419
-
420
- .optimal-value-row {
421
- display: flex;
422
- align-items: baseline;
423
- gap: 4px;
424
- }
425
-
426
- .optimal-value {
427
- font-size: 3.5rem;
428
- font-weight: 900;
429
- color: var(--text-main);
430
- line-height: 1;
431
- }
432
-
433
- .optimal-deg {
434
- font-size: 1.5rem;
435
- font-weight: 700;
436
- color: var(--solar-p);
437
- }
438
-
439
- .efficiency-tag {
440
- display: flex;
441
- align-items: center;
442
- gap: 4px;
443
- font-size: 0.75rem;
444
- color: #16a34a;
445
- font-weight: 600;
446
- margin: 8px 0 0;
447
- }
448
-
449
- .efficiency-tag svg {
450
- width: 12px;
451
- height: 12px;
452
- }
453
-
454
- .season-grid {
455
- display: grid;
456
- grid-template-columns: 1fr 1fr;
457
- gap: 12px;
458
- }
459
-
460
- .season-card {
461
- border-radius: 12px;
462
- padding: 14px;
463
- border: 1px solid transparent;
464
- }
465
-
466
- .season-card.winter {
467
- background: rgba(59, 130, 246, 0.08);
468
- border-color: rgba(59, 130, 246, 0.2);
469
- }
470
-
471
- .season-card.summer {
472
- background: rgba(234, 179, 8, 0.08);
473
- border-color: rgba(234, 179, 8, 0.2);
474
- }
475
-
476
- .season-header {
477
- display: flex;
478
- align-items: center;
479
- gap: 6px;
480
- margin-bottom: 8px;
481
- }
482
-
483
- .season-header svg {
484
- width: 14px;
485
- height: 14px;
486
- flex-shrink: 0;
487
- }
488
-
489
- .season-card.winter .season-header svg {
490
- color: var(--solar-winter);
491
- }
492
-
493
- .season-card.summer .season-header svg {
494
- color: var(--solar-summer);
495
- }
496
-
497
- .season-name {
498
- font-size: 0.6875rem;
499
- font-weight: 800;
500
- text-transform: uppercase;
501
- letter-spacing: 0.08em;
502
- }
503
-
504
- .season-card.winter .season-name {
505
- color: var(--solar-winter);
506
- }
507
-
508
- .season-card.summer .season-name {
509
- color: var(--solar-summer);
510
- }
511
-
512
- .season-value {
513
- font-size: 1.5rem;
514
- font-weight: 700;
515
- color: var(--text-main);
516
- margin: 0;
517
- }
518
-
519
- .hemi-badge {
520
- display: inline-block;
521
- padding: 6px 14px;
522
- background: var(--bg-muted);
523
- border: 1px solid var(--border-color);
524
- border-radius: 8px;
525
- font-size: 0.6875rem;
526
- font-weight: 700;
527
- color: var(--text-muted);
528
- text-transform: uppercase;
529
- letter-spacing: 0.08em;
530
- align-self: flex-start;
531
- }
532
- </style>
@@ -0,0 +1,30 @@
1
+ import type { HomeToolEntry, ToolLocaleContent } from '../../types';
2
+
3
+ import type { SolarCalculatorUI } from './ui';
4
+
5
+ export type SolarCalculatorLocaleContent = ToolLocaleContent<SolarCalculatorUI>;
6
+
7
+ export const solarCalculator: HomeToolEntry<SolarCalculatorUI> = {
8
+ id: 'solar-calculator',
9
+ icons: {
10
+ bg: 'mdi:solar-panel-large',
11
+ fg: 'mdi:angle-acute',
12
+ },
13
+ i18n: {
14
+ de: async () => (await import('./i18n/de')).content,
15
+ en: async () => (await import('./i18n/en')).content,
16
+ es: async () => (await import('./i18n/es')).content,
17
+ fr: async () => (await import('./i18n/fr')).content,
18
+ id: async () => (await import('./i18n/id')).content,
19
+ it: async () => (await import('./i18n/it')).content,
20
+ ja: async () => (await import('./i18n/ja')).content,
21
+ ko: async () => (await import('./i18n/ko')).content,
22
+ nl: async () => (await import('./i18n/nl')).content,
23
+ pl: async () => (await import('./i18n/pl')).content,
24
+ pt: async () => (await import('./i18n/pt')).content,
25
+ ru: async () => (await import('./i18n/ru')).content,
26
+ sv: async () => (await import('./i18n/sv')).content,
27
+ tr: async () => (await import('./i18n/tr')).content,
28
+ zh: async () => (await import('./i18n/zh')).content,
29
+ },
30
+ };
@@ -1,35 +1,5 @@
1
- import type { HomeToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
-
3
- import type { SolarCalculatorUI } from './ui';
4
-
5
- export type SolarCalculatorLocaleContent = ToolLocaleContent<SolarCalculatorUI>;
6
-
7
- export const solarCalculator: HomeToolEntry<SolarCalculatorUI> = {
8
- id: 'solar-calculator',
9
- icons: {
10
- bg: 'mdi:solar-panel-large',
11
- fg: 'mdi:angle-acute',
12
- },
13
- i18n: {
14
- de: async () => (await import('./i18n/de')).content,
15
- en: async () => (await import('./i18n/en')).content,
16
- es: async () => (await import('./i18n/es')).content,
17
- fr: async () => (await import('./i18n/fr')).content,
18
- id: async () => (await import('./i18n/id')).content,
19
- it: async () => (await import('./i18n/it')).content,
20
- ja: async () => (await import('./i18n/ja')).content,
21
- ko: async () => (await import('./i18n/ko')).content,
22
- nl: async () => (await import('./i18n/nl')).content,
23
- pl: async () => (await import('./i18n/pl')).content,
24
- pt: async () => (await import('./i18n/pt')).content,
25
- ru: async () => (await import('./i18n/ru')).content,
26
- sv: async () => (await import('./i18n/sv')).content,
27
- tr: async () => (await import('./i18n/tr')).content,
28
- zh: async () => (await import('./i18n/zh')).content,
29
- },
30
- };
31
-
32
-
1
+ import { solarCalculator } from './entry';
2
+ export * from './entry';
33
3
  export const SOLAR_CALCULATOR_TOOL: ToolDefinition = {
34
4
  entry: solarCalculator,
35
5
  Component: () => import('./component.astro'),