@jjlmoya/utils-nautical 1.12.0 → 1.14.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.
@@ -0,0 +1,239 @@
1
+ .speed-converter {
2
+ --n-bg: #fff;
3
+ --n-bg-muted: #f1f5f9;
4
+ --n-text: #0f172a;
5
+ --n-text-muted: #475569;
6
+ --n-text-dim: #64748b;
7
+ --n-border: #e2e8f0;
8
+ --n-shadow: rgba(0, 0, 0, 0.05);
9
+ --n-primary: #3b82f6;
10
+ --n-primary-on: #fff;
11
+ --n-accent: #6366f1;
12
+ --n-cyan: #0891b2;
13
+ --n-success: #10b981;
14
+ --n-warning: #f59e0b;
15
+ --n-error: #f43f5e;
16
+
17
+ max-width: 900px;
18
+ margin: 0 auto;
19
+ display: flex;
20
+ flex-direction: column;
21
+ gap: 2rem;
22
+ }
23
+
24
+ :global(.theme-dark) .speed-converter {
25
+ --n-bg: #0f172a;
26
+ --n-bg-muted: #1e293b;
27
+ --n-text: #f8fafc;
28
+ --n-text-muted: #94a3b8;
29
+ --n-text-dim: #64748b;
30
+ --n-border: #334155;
31
+ --n-shadow: rgba(0, 0, 0, 0.3);
32
+ --n-primary: #60a5fa;
33
+ --n-primary-on: #fff;
34
+ --n-accent: #818cf8;
35
+ --n-cyan: #22d3ee;
36
+ --n-success: #34d399;
37
+ --n-warning: #fbbf24;
38
+ --n-error: #fb7185;
39
+ }
40
+
41
+ .sc-input-grid {
42
+ display: grid;
43
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
44
+ gap: 1rem;
45
+ background: var(--n-bg);
46
+ border: 1px solid var(--n-border);
47
+ border-radius: 1.5rem;
48
+ padding: 2rem;
49
+ }
50
+
51
+ .sc-input-group {
52
+ display: flex;
53
+ flex-direction: column;
54
+ gap: 0.5rem;
55
+ }
56
+
57
+ .sc-input-group label {
58
+ font-size: 0.8rem;
59
+ font-weight: 600;
60
+ color: var(--n-text-muted);
61
+ text-transform: uppercase;
62
+ }
63
+
64
+ .sc-input-wrapper {
65
+ background: var(--n-bg-muted);
66
+ border: 2px solid var(--n-border);
67
+ border-radius: 0.8rem;
68
+ padding: 0.8rem 1rem;
69
+ transition: border-color 0.2s;
70
+ }
71
+
72
+ .sc-input-wrapper:focus-within {
73
+ border-color: var(--n-cyan);
74
+ }
75
+
76
+ .sc-input-wrapper input {
77
+ background: transparent;
78
+ border: none;
79
+ outline: none;
80
+ color: var(--n-text);
81
+ font-size: 1.5rem;
82
+ font-weight: 800;
83
+ width: 100%;
84
+ }
85
+
86
+ .sc-input-wrapper input::-webkit-outer-spin-button,
87
+ .sc-input-wrapper input::-webkit-inner-spin-button {
88
+ appearance: none;
89
+ }
90
+
91
+ .sc-beaufort-summary {
92
+ background: var(--n-primary);
93
+ color: var(--n-primary-on);
94
+ border-radius: 1.5rem;
95
+ padding: 2rem;
96
+ display: grid;
97
+ grid-template-columns: auto 1fr;
98
+ gap: 1rem 2rem;
99
+ align-items: center;
100
+ }
101
+
102
+ .sc-force-circle {
103
+ width: 80px;
104
+ height: 80px;
105
+ border-radius: 50%;
106
+ background: rgba(255, 255, 255, 0.15);
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: center;
110
+ font-size: 2.5rem;
111
+ font-weight: 800;
112
+ color: var(--n-primary-on);
113
+ flex-shrink: 0;
114
+ }
115
+
116
+ .sc-force-text-box {
117
+ display: flex;
118
+ flex-direction: column;
119
+ gap: 0.3rem;
120
+ }
121
+
122
+ .sc-force-name {
123
+ margin: 0;
124
+ font-size: 1.4rem;
125
+ font-weight: 800;
126
+ color: var(--n-primary-on);
127
+ }
128
+
129
+ .sc-force-detail {
130
+ margin: 0;
131
+ opacity: 0.8;
132
+ font-size: 0.9rem;
133
+ color: var(--n-primary-on);
134
+ }
135
+
136
+ .sc-sea-state-box {
137
+ grid-column: 1 / -1;
138
+ background: rgba(255, 255, 255, 0.1);
139
+ border-radius: 1rem;
140
+ padding: 1rem 1.5rem;
141
+ }
142
+
143
+ .sc-sea-text .label {
144
+ font-size: 0.7rem;
145
+ text-transform: uppercase;
146
+ opacity: 0.7;
147
+ color: var(--n-primary-on);
148
+ font-weight: 700;
149
+ }
150
+
151
+ .sc-sea-text p {
152
+ margin: 0.2rem 0 0;
153
+ font-weight: 600;
154
+ color: var(--n-primary-on);
155
+ }
156
+
157
+ .sc-table-container {
158
+ background: var(--n-bg);
159
+ border: 1px solid var(--n-border);
160
+ border-radius: 1.5rem;
161
+ overflow: hidden;
162
+ }
163
+
164
+ .sc-table-container h3 {
165
+ padding: 1.5rem;
166
+ margin: 0;
167
+ font-size: 1rem;
168
+ color: var(--n-text-muted);
169
+ border-bottom: 1px solid var(--n-border);
170
+ font-weight: 700;
171
+ }
172
+
173
+ .sc-scroll-area {
174
+ overflow-x: auto;
175
+ }
176
+
177
+ .sc-beaufort-table {
178
+ width: 100%;
179
+ border-collapse: collapse;
180
+ }
181
+
182
+ .sc-beaufort-table th {
183
+ text-align: left;
184
+ padding: 0.8rem 1rem;
185
+ font-size: 0.75rem;
186
+ color: var(--n-text-muted);
187
+ text-transform: uppercase;
188
+ border-bottom: 2px solid var(--n-border);
189
+ }
190
+
191
+ .sc-beaufort-table td {
192
+ padding: 0.8rem 1rem;
193
+ font-size: 0.9rem;
194
+ color: var(--n-text-muted);
195
+ border-bottom: 1px solid var(--n-border);
196
+ }
197
+
198
+ .sc-clickable-row {
199
+ cursor: pointer;
200
+ transition: background 0.15s;
201
+ }
202
+
203
+ .sc-clickable-row:hover {
204
+ background: var(--n-bg-muted);
205
+ }
206
+
207
+ .sc-clickable-row.active {
208
+ background: var(--n-primary);
209
+ }
210
+
211
+ .sc-clickable-row.active td {
212
+ color: var(--n-primary-on);
213
+ }
214
+
215
+ .sc-force-tag {
216
+ background: var(--n-bg-muted);
217
+ padding: 0.2rem 0.5rem;
218
+ border-radius: 0.4rem;
219
+ font-weight: 700;
220
+ font-size: 0.85rem;
221
+ color: var(--n-text);
222
+ }
223
+
224
+ .sc-clickable-row.active .sc-force-tag {
225
+ background: rgba(255, 255, 255, 0.2);
226
+ color: var(--n-primary-on);
227
+ }
228
+
229
+ @media (max-width: 640px) {
230
+ .sc-beaufort-summary {
231
+ grid-template-columns: 1fr;
232
+ }
233
+
234
+ .sc-force-circle {
235
+ width: 60px;
236
+ height: 60px;
237
+ font-size: 2rem;
238
+ }
239
+ }
@@ -312,315 +312,3 @@ const { ui } = Astro.props;
312
312
  new TideCalculator();
313
313
  </script>
314
314
 
315
- <style>
316
- .tide-calculator {
317
- --n-bg: #fff;
318
- --n-bg-muted: #f1f5f9;
319
- --n-text: #0f172a;
320
- --n-text-muted: #475569;
321
- --n-text-dim: #64748b;
322
- --n-border: #e2e8f0;
323
- --n-shadow: rgba(0, 0, 0, 0.05);
324
- --n-primary: #3b82f6;
325
- --n-primary-on: #fff;
326
- --n-accent: #6366f1;
327
- --n-cyan: #0891b2;
328
- --n-success: #10b981;
329
- --n-warning: #f59e0b;
330
- --n-error: #f43f5e;
331
-
332
- display: flex;
333
- flex-direction: column;
334
- gap: 1.5rem;
335
- max-width: 1000px;
336
- margin: 0 auto;
337
- }
338
-
339
- :global(.theme-dark) .tide-calculator {
340
- --n-bg: #0f172a;
341
- --n-bg-muted: #1e293b;
342
- --n-text: #f8fafc;
343
- --n-text-muted: #94a3b8;
344
- --n-text-dim: #64748b;
345
- --n-border: #334155;
346
- --n-shadow: rgba(0, 0, 0, 0.3);
347
- --n-primary: #60a5fa;
348
- --n-primary-on: #fff;
349
- --n-accent: #818cf8;
350
- --n-cyan: #22d3ee;
351
- --n-success: #34d399;
352
- --n-warning: #fbbf24;
353
- --n-error: #fb7185;
354
- }
355
-
356
- .tc-main-card {
357
- background: var(--n-bg);
358
- border: 1px solid var(--n-border);
359
- border-radius: 2rem;
360
- display: grid;
361
- grid-template-columns: 320px 1fr;
362
- overflow: hidden;
363
- box-shadow: 0 20px 40px var(--n-shadow);
364
- }
365
-
366
- @media (max-width: 850px) {
367
- .tc-main-card {
368
- grid-template-columns: 1fr;
369
- }
370
- }
371
-
372
- .tc-calc-sidebar {
373
- background: var(--n-primary);
374
- color: var(--n-primary-on);
375
- padding: 2rem;
376
- display: flex;
377
- flex-direction: column;
378
- gap: 2rem;
379
- }
380
-
381
- .tc-sidebar-header {
382
- display: flex;
383
- justify-content: space-between;
384
- align-items: center;
385
- }
386
-
387
- .tc-sidebar-header h3 {
388
- font-size: 1.1rem;
389
- margin: 0;
390
- font-weight: 700;
391
- text-transform: uppercase;
392
- letter-spacing: 0.05em;
393
- opacity: 0.9;
394
- }
395
-
396
- :global(#invert-btn) {
397
- background: rgba(255, 255, 255, 0.1);
398
- border: none;
399
- color: var(--n-primary-on);
400
- width: 36px;
401
- height: 36px;
402
- border-radius: 50%;
403
- cursor: pointer;
404
- display: flex;
405
- align-items: center;
406
- justify-content: center;
407
- transition: background 0.2s;
408
- }
409
-
410
- :global(#invert-btn:hover) {
411
- background: rgba(255, 255, 255, 0.2);
412
- }
413
-
414
- .tc-input-set {
415
- display: flex;
416
- flex-direction: column;
417
- gap: 1.5rem;
418
- }
419
-
420
- .tc-input-block {
421
- display: flex;
422
- flex-direction: column;
423
- gap: 0.5rem;
424
- }
425
-
426
- .tc-input-block label {
427
- font-size: 0.85rem;
428
- font-weight: 700;
429
- color: var(--n-primary-on);
430
- opacity: 0.85;
431
- }
432
-
433
- .tc-input-block .row {
434
- display: flex;
435
- gap: 0.5rem;
436
- }
437
-
438
- .tide-calculator input[type='time'],
439
- .tide-calculator input[type='number'] {
440
- background: rgba(255, 255, 255, 0.1);
441
- border: 1px solid rgba(255, 255, 255, 0.2);
442
- border-radius: 0.8rem;
443
- padding: 0.8rem;
444
- color: var(--n-primary-on);
445
- font-size: 1rem;
446
- outline: none;
447
- }
448
-
449
- .tc-unit-input {
450
- position: relative;
451
- display: flex;
452
- align-items: center;
453
- }
454
-
455
- .tc-unit-input input {
456
- width: 80px;
457
- padding-right: 25px;
458
- }
459
-
460
- .tc-unit-input span {
461
- position: absolute;
462
- right: 10px;
463
- font-size: 0.8rem;
464
- opacity: 0.5;
465
- }
466
-
467
- .tc-featured label {
468
- color: var(--n-primary-on);
469
- opacity: 1;
470
- font-size: 0.95rem;
471
- }
472
-
473
- .tide-calculator input[type='time'].large-time {
474
- background: var(--n-primary-on);
475
- color: var(--n-primary);
476
- font-size: 1.8rem;
477
- font-weight: 800;
478
- text-align: center;
479
- }
480
-
481
- .tc-calc-content {
482
- padding: 2.5rem;
483
- display: flex;
484
- flex-direction: column;
485
- gap: 2rem;
486
- background: var(--n-bg-muted);
487
- }
488
-
489
- .tc-top-row {
490
- display: flex;
491
- justify-content: space-between;
492
- align-items: flex-start;
493
- }
494
-
495
- .tc-result-display {
496
- display: flex;
497
- flex-direction: column;
498
- }
499
-
500
- .tc-result-display .label {
501
- font-size: 0.85rem;
502
- font-weight: 600;
503
- color: var(--n-text-muted);
504
- text-transform: uppercase;
505
- letter-spacing: 0.05em;
506
- }
507
-
508
- .tc-value-box {
509
- display: flex;
510
- align-items: baseline;
511
- gap: 0.5rem;
512
- margin: 0.5rem 0;
513
- }
514
-
515
- :global(#target-value) {
516
- font-size: 4rem;
517
- font-weight: 800;
518
- color: var(--n-accent);
519
- line-height: 1;
520
- }
521
-
522
- .tc-value-box small {
523
- font-size: 1.2rem;
524
- font-weight: 600;
525
- color: var(--n-text-dim);
526
- }
527
-
528
- .tc-status-indicator {
529
- padding: 0.4rem 1rem;
530
- border-radius: 2rem;
531
- font-size: 0.85rem;
532
- font-weight: 700;
533
- display: inline-block;
534
- width: fit-content;
535
- background: var(--n-bg-muted);
536
- color: var(--n-text-dim);
537
- }
538
-
539
- .tc-status-indicator.up {
540
- background: color-mix(in srgb, var(--n-success), transparent 80%);
541
- color: var(--n-success);
542
- }
543
-
544
- .tc-status-indicator.down {
545
- background: color-mix(in srgb, var(--n-error), transparent 80%);
546
- color: var(--n-error);
547
- }
548
-
549
- .tc-summary-info {
550
- display: flex;
551
- gap: 1.5rem;
552
- }
553
-
554
- .tc-stat {
555
- display: flex;
556
- flex-direction: column;
557
- text-align: right;
558
- }
559
-
560
- .tc-s-label {
561
- font-size: 0.75rem;
562
- font-weight: 600;
563
- color: var(--n-text-muted);
564
- text-transform: uppercase;
565
- }
566
-
567
- .tc-stat span:last-child {
568
- font-size: 1.1rem;
569
- font-weight: 700;
570
- color: var(--n-text);
571
- }
572
-
573
- .tc-chart-area {
574
- background: var(--n-bg);
575
- border: 1px solid var(--n-border);
576
- border-radius: 1.5rem;
577
- padding: 1.5rem;
578
- height: 250px;
579
- position: relative;
580
- }
581
-
582
- .tc-table-card {
583
- background: var(--n-bg);
584
- border: 1px solid var(--n-border);
585
- border-radius: 1.5rem;
586
- padding: 1.5rem;
587
- }
588
-
589
- .tc-table-card h4 {
590
- margin: 0 0 1rem;
591
- font-size: 1rem;
592
- color: var(--n-text-muted);
593
- }
594
-
595
- .tc-table-wrapper {
596
- overflow-x: auto;
597
- }
598
-
599
- .tide-calculator table {
600
- width: 100%;
601
- border-collapse: collapse;
602
- }
603
-
604
- .tide-calculator th {
605
- text-align: left;
606
- padding: 1rem;
607
- font-size: 0.8rem;
608
- color: var(--n-text-muted);
609
- text-transform: uppercase;
610
- border-bottom: 2px solid var(--n-bg-muted);
611
- }
612
-
613
- .tide-calculator td {
614
- padding: 1rem;
615
- font-size: 0.95rem;
616
- color: var(--n-text-muted);
617
- border-bottom: 1px solid var(--n-bg-muted);
618
- }
619
-
620
- @media (max-width: 640px) {
621
- .tc-top-row {
622
- flex-direction: column;
623
- gap: 1.5rem;
624
- }
625
- }
626
- </style>
@@ -0,0 +1,50 @@
1
+ import type { NauticalToolEntry, ToolLocaleContent } from '../../types';
2
+
3
+ export interface TideCalculatorUI {
4
+ [key: string]: string;
5
+ parametersLabel: string;
6
+ highTideLabel: string;
7
+ lowTideLabel: string;
8
+ targetTimeLabel: string;
9
+ estimatedHeightLabel: string;
10
+ metersLabel: string;
11
+ amplitudeLabel: string;
12
+ durationLabel: string;
13
+ tableBreakdownLabel: string;
14
+ tableHourLabel: string;
15
+ tableStateLabel: string;
16
+ tableStartLabel: string;
17
+ tableEndLabel: string;
18
+ statusUpLabel: string;
19
+ statusDownLabel: string;
20
+ statusOutOfRange: string;
21
+ faqTitle: string;
22
+ bibliographyTitle: string;
23
+ }
24
+
25
+ export type TideCalculatorLocaleContent = ToolLocaleContent<TideCalculatorUI>;
26
+
27
+ export const tideCalculator: NauticalToolEntry<TideCalculatorUI> = {
28
+ id: 'tide-calculator',
29
+ icons: {
30
+ bg: 'mdi:waves',
31
+ fg: 'mdi:sailing',
32
+ },
33
+ i18n: {
34
+ es: () => import('./i18n/es').then((m) => m.content),
35
+ en: () => import('./i18n/en').then((m) => m.content),
36
+ fr: () => import('./i18n/fr').then((m) => m.content),
37
+ de: () => import('./i18n/de').then((m) => m.content),
38
+ id: () => import('./i18n/id').then((m) => m.content),
39
+ it: () => import('./i18n/it').then((m) => m.content),
40
+ ja: () => import('./i18n/ja').then((m) => m.content),
41
+ ko: () => import('./i18n/ko').then((m) => m.content),
42
+ nl: () => import('./i18n/nl').then((m) => m.content),
43
+ pl: () => import('./i18n/pl').then((m) => m.content),
44
+ pt: () => import('./i18n/pt').then((m) => m.content),
45
+ ru: () => import('./i18n/ru').then((m) => m.content),
46
+ sv: () => import('./i18n/sv').then((m) => m.content),
47
+ tr: () => import('./i18n/tr').then((m) => m.content),
48
+ zh: () => import('./i18n/zh').then((m) => m.content),
49
+ },
50
+ };
@@ -1,55 +1,5 @@
1
- import type { NauticalToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
-
3
- export interface TideCalculatorUI {
4
- [key: string]: string;
5
- parametersLabel: string;
6
- highTideLabel: string;
7
- lowTideLabel: string;
8
- targetTimeLabel: string;
9
- estimatedHeightLabel: string;
10
- metersLabel: string;
11
- amplitudeLabel: string;
12
- durationLabel: string;
13
- tableBreakdownLabel: string;
14
- tableHourLabel: string;
15
- tableStateLabel: string;
16
- tableStartLabel: string;
17
- tableEndLabel: string;
18
- statusUpLabel: string;
19
- statusDownLabel: string;
20
- statusOutOfRange: string;
21
- faqTitle: string;
22
- bibliographyTitle: string;
23
- }
24
-
25
- export type TideCalculatorLocaleContent = ToolLocaleContent<TideCalculatorUI>;
26
-
27
- export const tideCalculator: NauticalToolEntry<TideCalculatorUI> = {
28
- id: 'tide-calculator',
29
- icons: {
30
- bg: 'mdi:waves',
31
- fg: 'mdi:sailing',
32
- },
33
- i18n: {
34
- es: () => import('./i18n/es').then((m) => m.content),
35
- en: () => import('./i18n/en').then((m) => m.content),
36
- fr: () => import('./i18n/fr').then((m) => m.content),
37
- de: () => import('./i18n/de').then((m) => m.content),
38
- id: () => import('./i18n/id').then((m) => m.content),
39
- it: () => import('./i18n/it').then((m) => m.content),
40
- ja: () => import('./i18n/ja').then((m) => m.content),
41
- ko: () => import('./i18n/ko').then((m) => m.content),
42
- nl: () => import('./i18n/nl').then((m) => m.content),
43
- pl: () => import('./i18n/pl').then((m) => m.content),
44
- pt: () => import('./i18n/pt').then((m) => m.content),
45
- ru: () => import('./i18n/ru').then((m) => m.content),
46
- sv: () => import('./i18n/sv').then((m) => m.content),
47
- tr: () => import('./i18n/tr').then((m) => m.content),
48
- zh: () => import('./i18n/zh').then((m) => m.content),
49
- },
50
- };
51
-
52
-
1
+ import { tideCalculator } from './entry';
2
+ export * from './entry';
53
3
  export const TIDE_CALCULATOR_TOOL: ToolDefinition = {
54
4
  entry: tideCalculator,
55
5
  Component: () => import('./component.astro'),