@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,310 @@
1
+ .tide-calculator {
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
+ display: flex;
18
+ flex-direction: column;
19
+ gap: 1.5rem;
20
+ max-width: 1000px;
21
+ margin: 0 auto;
22
+ }
23
+
24
+ :global(.theme-dark) .tide-calculator {
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
+ .tc-main-card {
42
+ background: var(--n-bg);
43
+ border: 1px solid var(--n-border);
44
+ border-radius: 2rem;
45
+ display: grid;
46
+ grid-template-columns: 320px 1fr;
47
+ overflow: hidden;
48
+ box-shadow: 0 20px 40px var(--n-shadow);
49
+ }
50
+
51
+ @media (max-width: 850px) {
52
+ .tc-main-card {
53
+ grid-template-columns: 1fr;
54
+ }
55
+ }
56
+
57
+ .tc-calc-sidebar {
58
+ background: var(--n-primary);
59
+ color: var(--n-primary-on);
60
+ padding: 2rem;
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: 2rem;
64
+ }
65
+
66
+ .tc-sidebar-header {
67
+ display: flex;
68
+ justify-content: space-between;
69
+ align-items: center;
70
+ }
71
+
72
+ .tc-sidebar-header h3 {
73
+ font-size: 1.1rem;
74
+ margin: 0;
75
+ font-weight: 700;
76
+ text-transform: uppercase;
77
+ letter-spacing: 0.05em;
78
+ opacity: 0.9;
79
+ }
80
+
81
+ :global(#invert-btn) {
82
+ background: rgba(255, 255, 255, 0.1);
83
+ border: none;
84
+ color: var(--n-primary-on);
85
+ width: 36px;
86
+ height: 36px;
87
+ border-radius: 50%;
88
+ cursor: pointer;
89
+ display: flex;
90
+ align-items: center;
91
+ justify-content: center;
92
+ transition: background 0.2s;
93
+ }
94
+
95
+ :global(#invert-btn:hover) {
96
+ background: rgba(255, 255, 255, 0.2);
97
+ }
98
+
99
+ .tc-input-set {
100
+ display: flex;
101
+ flex-direction: column;
102
+ gap: 1.5rem;
103
+ }
104
+
105
+ .tc-input-block {
106
+ display: flex;
107
+ flex-direction: column;
108
+ gap: 0.5rem;
109
+ }
110
+
111
+ .tc-input-block label {
112
+ font-size: 0.85rem;
113
+ font-weight: 700;
114
+ color: var(--n-primary-on);
115
+ opacity: 0.85;
116
+ }
117
+
118
+ .tc-input-block .row {
119
+ display: flex;
120
+ gap: 0.5rem;
121
+ }
122
+
123
+ .tide-calculator input[type='time'],
124
+ .tide-calculator input[type='number'] {
125
+ background: rgba(255, 255, 255, 0.1);
126
+ border: 1px solid rgba(255, 255, 255, 0.2);
127
+ border-radius: 0.8rem;
128
+ padding: 0.8rem;
129
+ color: var(--n-primary-on);
130
+ font-size: 1rem;
131
+ outline: none;
132
+ }
133
+
134
+ .tc-unit-input {
135
+ position: relative;
136
+ display: flex;
137
+ align-items: center;
138
+ }
139
+
140
+ .tc-unit-input input {
141
+ width: 80px;
142
+ padding-right: 25px;
143
+ }
144
+
145
+ .tc-unit-input span {
146
+ position: absolute;
147
+ right: 10px;
148
+ font-size: 0.8rem;
149
+ opacity: 0.5;
150
+ }
151
+
152
+ .tc-featured label {
153
+ color: var(--n-primary-on);
154
+ opacity: 1;
155
+ font-size: 0.95rem;
156
+ }
157
+
158
+ .tide-calculator input[type='time'].large-time {
159
+ background: var(--n-primary-on);
160
+ color: var(--n-primary);
161
+ font-size: 1.8rem;
162
+ font-weight: 800;
163
+ text-align: center;
164
+ }
165
+
166
+ .tc-calc-content {
167
+ padding: 2.5rem;
168
+ display: flex;
169
+ flex-direction: column;
170
+ gap: 2rem;
171
+ background: var(--n-bg-muted);
172
+ }
173
+
174
+ .tc-top-row {
175
+ display: flex;
176
+ justify-content: space-between;
177
+ align-items: flex-start;
178
+ }
179
+
180
+ .tc-result-display {
181
+ display: flex;
182
+ flex-direction: column;
183
+ }
184
+
185
+ .tc-result-display .label {
186
+ font-size: 0.85rem;
187
+ font-weight: 600;
188
+ color: var(--n-text-muted);
189
+ text-transform: uppercase;
190
+ letter-spacing: 0.05em;
191
+ }
192
+
193
+ .tc-value-box {
194
+ display: flex;
195
+ align-items: baseline;
196
+ gap: 0.5rem;
197
+ margin: 0.5rem 0;
198
+ }
199
+
200
+ :global(#target-value) {
201
+ font-size: 4rem;
202
+ font-weight: 800;
203
+ color: var(--n-accent);
204
+ line-height: 1;
205
+ }
206
+
207
+ .tc-value-box small {
208
+ font-size: 1.2rem;
209
+ font-weight: 600;
210
+ color: var(--n-text-dim);
211
+ }
212
+
213
+ .tc-status-indicator {
214
+ padding: 0.4rem 1rem;
215
+ border-radius: 2rem;
216
+ font-size: 0.85rem;
217
+ font-weight: 700;
218
+ display: inline-block;
219
+ width: fit-content;
220
+ background: var(--n-bg-muted);
221
+ color: var(--n-text-dim);
222
+ }
223
+
224
+ .tc-status-indicator.up {
225
+ background: color-mix(in srgb, var(--n-success), transparent 80%);
226
+ color: var(--n-success);
227
+ }
228
+
229
+ .tc-status-indicator.down {
230
+ background: color-mix(in srgb, var(--n-error), transparent 80%);
231
+ color: var(--n-error);
232
+ }
233
+
234
+ .tc-summary-info {
235
+ display: flex;
236
+ gap: 1.5rem;
237
+ }
238
+
239
+ .tc-stat {
240
+ display: flex;
241
+ flex-direction: column;
242
+ text-align: right;
243
+ }
244
+
245
+ .tc-s-label {
246
+ font-size: 0.75rem;
247
+ font-weight: 600;
248
+ color: var(--n-text-muted);
249
+ text-transform: uppercase;
250
+ }
251
+
252
+ .tc-stat span:last-child {
253
+ font-size: 1.1rem;
254
+ font-weight: 700;
255
+ color: var(--n-text);
256
+ }
257
+
258
+ .tc-chart-area {
259
+ background: var(--n-bg);
260
+ border: 1px solid var(--n-border);
261
+ border-radius: 1.5rem;
262
+ padding: 1.5rem;
263
+ height: 250px;
264
+ position: relative;
265
+ }
266
+
267
+ .tc-table-card {
268
+ background: var(--n-bg);
269
+ border: 1px solid var(--n-border);
270
+ border-radius: 1.5rem;
271
+ padding: 1.5rem;
272
+ }
273
+
274
+ .tc-table-card h4 {
275
+ margin: 0 0 1rem;
276
+ font-size: 1rem;
277
+ color: var(--n-text-muted);
278
+ }
279
+
280
+ .tc-table-wrapper {
281
+ overflow-x: auto;
282
+ }
283
+
284
+ .tide-calculator table {
285
+ width: 100%;
286
+ border-collapse: collapse;
287
+ }
288
+
289
+ .tide-calculator th {
290
+ text-align: left;
291
+ padding: 1rem;
292
+ font-size: 0.8rem;
293
+ color: var(--n-text-muted);
294
+ text-transform: uppercase;
295
+ border-bottom: 2px solid var(--n-bg-muted);
296
+ }
297
+
298
+ .tide-calculator td {
299
+ padding: 1rem;
300
+ font-size: 0.95rem;
301
+ color: var(--n-text-muted);
302
+ border-bottom: 1px solid var(--n-bg-muted);
303
+ }
304
+
305
+ @media (max-width: 640px) {
306
+ .tc-top-row {
307
+ flex-direction: column;
308
+ gap: 1.5rem;
309
+ }
310
+ }
@@ -238,323 +238,3 @@ const { ui } = Astro.props;
238
238
  new UnderKeelCalculator();
239
239
  </script>
240
240
 
241
- <style>
242
- .under-keel-calculator {
243
- --n-bg: #fff;
244
- --n-bg-muted: #f1f5f9;
245
- --n-text: #0f172a;
246
- --n-text-muted: #475569;
247
- --n-text-dim: #64748b;
248
- --n-border: #e2e8f0;
249
- --n-shadow: rgba(0, 0, 0, 0.05);
250
- --n-primary: #3b82f6;
251
- --n-primary-on: #fff;
252
- --n-accent: #6366f1;
253
- --n-cyan: #0891b2;
254
- --n-success: #10b981;
255
- --n-warning: #f59e0b;
256
- --n-error: #f43f5e;
257
- --ukc-label-size: 0.75rem;
258
- --ukc-label-weight: 800;
259
- --ukc-label-spacing: 0.06em;
260
-
261
- display: flex;
262
- flex-direction: column;
263
- gap: 1.5rem;
264
- max-width: 1000px;
265
- margin: 0 auto;
266
- }
267
-
268
- :global(.theme-dark) .under-keel-calculator {
269
- --n-bg: #0f172a;
270
- --n-bg-muted: #1e293b;
271
- --n-text: #f8fafc;
272
- --n-text-muted: #94a3b8;
273
- --n-text-dim: #64748b;
274
- --n-border: #334155;
275
- --n-shadow: rgba(0, 0, 0, 0.3);
276
- --n-primary: #60a5fa;
277
- --n-primary-on: #fff;
278
- --n-accent: #818cf8;
279
- --n-cyan: #22d3ee;
280
- --n-success: #34d399;
281
- --n-warning: #fbbf24;
282
- --n-error: #fb7185;
283
- }
284
-
285
- .ukc-main-card {
286
- background: var(--n-bg);
287
- border: 1px solid var(--n-border);
288
- border-radius: 2rem;
289
- display: grid;
290
- grid-template-columns: 320px 1fr;
291
- overflow: hidden;
292
- box-shadow: 0 20px 40px var(--n-shadow);
293
- }
294
-
295
- @media (max-width: 850px) {
296
- .ukc-main-card {
297
- grid-template-columns: 1fr;
298
- }
299
- }
300
-
301
- .ukc-calc-sidebar {
302
- background: var(--n-primary);
303
- color: var(--n-primary-on);
304
- padding: 2rem;
305
- display: flex;
306
- flex-direction: column;
307
- gap: 2rem;
308
- }
309
-
310
- .ukc-sidebar-header h3 {
311
- font-size: 1.1rem;
312
- margin: 0;
313
- font-weight: 700;
314
- text-transform: uppercase;
315
- letter-spacing: 0.05em;
316
- opacity: 0.9;
317
- }
318
-
319
- .ukc-input-set {
320
- display: flex;
321
- flex-direction: column;
322
- gap: 1.2rem;
323
- }
324
-
325
- .ukc-input-block {
326
- display: flex;
327
- flex-direction: column;
328
- gap: 0.4rem;
329
- }
330
-
331
- .ukc-input-block label {
332
- font-size: var(--ukc-label-size);
333
- font-weight: var(--ukc-label-weight);
334
- color: var(--n-primary-on);
335
- opacity: 0.9;
336
- text-transform: uppercase;
337
- letter-spacing: var(--ukc-label-spacing);
338
- }
339
-
340
- .ukc-unit-input {
341
- position: relative;
342
- display: flex;
343
- align-items: center;
344
- }
345
-
346
- .ukc-unit-input input {
347
- width: 100%;
348
- background: rgba(255, 255, 255, 0.1);
349
- border: 1px solid rgba(255, 255, 255, 0.2);
350
- border-radius: 0.8rem;
351
- padding: 0.7rem 2.5rem 0.7rem 1rem;
352
- color: var(--n-primary-on);
353
- font-size: 1rem;
354
- outline: none;
355
- }
356
-
357
- .ukc-unit-input span {
358
- position: absolute;
359
- right: 12px;
360
- font-size: 0.85rem;
361
- font-weight: 700;
362
- opacity: 0.6;
363
- }
364
-
365
- .ukc-hr-divider {
366
- height: 1px;
367
- background: rgba(255, 255, 255, 0.1);
368
- margin: 0.5rem 0;
369
- }
370
-
371
- .ukc-row {
372
- display: flex;
373
- gap: 0.5rem;
374
- }
375
-
376
- .under-keel-calculator input[type='time'],
377
- .under-keel-calculator input[type='number'] {
378
- background: rgba(255, 255, 255, 0.1);
379
- border: 1px solid rgba(255, 255, 255, 0.2);
380
- border-radius: 0.8rem;
381
- padding: 0.7rem;
382
- color: var(--n-primary-on);
383
- font-size: 1rem;
384
- outline: none;
385
- }
386
-
387
- .ukc-mini-num {
388
- width: 80px;
389
- }
390
-
391
- .ukc-calc-content {
392
- padding: 2.5rem;
393
- display: flex;
394
- flex-direction: column;
395
- gap: 2rem;
396
- background: var(--n-bg-muted);
397
- }
398
-
399
- .ukc-top-row {
400
- display: flex;
401
- justify-content: space-between;
402
- align-items: flex-start;
403
- }
404
-
405
- .ukc-result-display {
406
- display: flex;
407
- flex-direction: column;
408
- gap: 0.5rem;
409
- }
410
-
411
- .ukc-result-display .label {
412
- font-size: 0.85rem;
413
- font-weight: 600;
414
- color: var(--n-text-muted);
415
- text-transform: uppercase;
416
- letter-spacing: 0.05em;
417
- }
418
-
419
- .ukc-time-range {
420
- display: flex;
421
- align-items: center;
422
- gap: 1.5rem;
423
- font-size: 3.5rem;
424
- font-weight: 800;
425
- color: var(--n-text);
426
- line-height: 1;
427
- }
428
-
429
- .ukc-arrow-sep {
430
- color: var(--n-cyan);
431
- opacity: 0.4;
432
- }
433
-
434
- .ukc-status-indicator {
435
- padding: 0.4rem 1.2rem;
436
- border-radius: 2rem;
437
- font-size: 0.9rem;
438
- font-weight: 700;
439
- width: fit-content;
440
- background: var(--n-bg-muted);
441
- color: var(--n-text-dim);
442
- }
443
-
444
- .ukc-status-indicator.success {
445
- background: color-mix(in srgb, var(--n-success), transparent 80%);
446
- color: var(--n-success);
447
- }
448
-
449
- .ukc-status-indicator.warning {
450
- background: color-mix(in srgb, var(--n-warning), transparent 80%);
451
- color: var(--n-warning);
452
- }
453
-
454
- .ukc-status-indicator.danger {
455
- background: color-mix(in srgb, var(--n-error), transparent 80%);
456
- color: var(--n-error);
457
- }
458
-
459
- .ukc-data-group {
460
- display: flex;
461
- flex-direction: column;
462
- gap: 0.8rem;
463
- }
464
-
465
- .ukc-stat-pill {
466
- background: var(--n-bg);
467
- padding: 0.5rem 1rem;
468
- border-radius: 0.8rem;
469
- border: 1px solid var(--n-border);
470
- display: flex;
471
- justify-content: space-between;
472
- gap: 2rem;
473
- font-size: 0.9rem;
474
- }
475
-
476
- .ukc-stat-pill span {
477
- color: var(--n-text-muted);
478
- font-weight: 500;
479
- }
480
-
481
- .ukc-stat-pill strong {
482
- color: var(--n-text);
483
- font-weight: 700;
484
- }
485
-
486
- .ukc-visual-container {
487
- background: var(--n-bg);
488
- border: 1px solid var(--n-border);
489
- border-radius: 1.5rem;
490
- padding: 2rem;
491
- height: 300px;
492
- display: flex;
493
- justify-content: center;
494
- position: relative;
495
- }
496
-
497
- .ukc-ocean-frame {
498
- width: 200px;
499
- height: 100%;
500
- background: var(--n-bg-muted);
501
- border: 4px solid var(--n-border);
502
- border-radius: 1rem;
503
- position: relative;
504
- overflow: hidden;
505
- }
506
-
507
- .ukc-water-volume {
508
- position: absolute;
509
- bottom: 0;
510
- width: 100%;
511
- background: linear-gradient(to top, var(--n-primary), var(--n-cyan));
512
- opacity: 0.6;
513
- transition: height 0.6s ease;
514
- }
515
-
516
- .ukc-surface-line {
517
- position: absolute;
518
- top: 0;
519
- width: 100%;
520
- height: 3px;
521
- background: var(--n-cyan);
522
- }
523
-
524
- .ukc-ship-silhouette {
525
- position: absolute;
526
- left: 20px;
527
- right: 20px;
528
- height: 30px;
529
- color: var(--n-text);
530
- z-index: 10;
531
- transition: bottom 0.6s ease;
532
- }
533
-
534
- .ukc-sand-bottom {
535
- position: absolute;
536
- bottom: 0;
537
- width: 100%;
538
- height: 40px;
539
- background: color-mix(in srgb, var(--n-warning), transparent 40%);
540
- display: flex;
541
- align-items: center;
542
- justify-content: center;
543
- font-size: 0.7rem;
544
- font-weight: 800;
545
- color: var(--n-text);
546
- letter-spacing: 0.2em;
547
- z-index: 5;
548
- }
549
-
550
- @media (max-width: 640px) {
551
- .ukc-time-range {
552
- font-size: 2.2rem;
553
- }
554
-
555
- .ukc-top-row {
556
- flex-direction: column;
557
- gap: 2rem;
558
- }
559
- }
560
- </style>
@@ -0,0 +1,49 @@
1
+ import type { NauticalToolEntry, ToolLocaleContent } from '../../types';
2
+
3
+ export interface UnderKeelUI {
4
+ [key: string]: string;
5
+ parametersLabel: string;
6
+ boatDraftLabel: string;
7
+ chartDepthLabel: string;
8
+ safetyMarginLabel: string;
9
+ highTideLabel: string;
10
+ lowTideLabel: string;
11
+ metersLabel: string;
12
+ passWindowLabel: string;
13
+ neededLabel: string;
14
+ tideRequiredLabel: string;
15
+ statusNeverLabel: string;
16
+ statusAlwaysLabel: string;
17
+ statusFromLabel: string;
18
+ statusUntilLabel: string;
19
+ bottomLabel: string;
20
+ faqTitle: string;
21
+ bibliographyTitle: string;
22
+ }
23
+
24
+ export type UnderKeelLocaleContent = ToolLocaleContent<UnderKeelUI>;
25
+
26
+ export const underKeel: NauticalToolEntry<UnderKeelUI> = {
27
+ id: 'under-keel',
28
+ icons: {
29
+ bg: 'mdi:ferry',
30
+ fg: 'mdi:anchor',
31
+ },
32
+ i18n: {
33
+ es: () => import('./i18n/es').then((m) => m.content),
34
+ en: () => import('./i18n/en').then((m) => m.content),
35
+ fr: () => import('./i18n/fr').then((m) => m.content),
36
+ de: () => import('./i18n/de').then((m) => m.content),
37
+ id: () => import('./i18n/id').then((m) => m.content),
38
+ it: () => import('./i18n/it').then((m) => m.content),
39
+ ja: () => import('./i18n/ja').then((m) => m.content),
40
+ ko: () => import('./i18n/ko').then((m) => m.content),
41
+ nl: () => import('./i18n/nl').then((m) => m.content),
42
+ pl: () => import('./i18n/pl').then((m) => m.content),
43
+ pt: () => import('./i18n/pt').then((m) => m.content),
44
+ ru: () => import('./i18n/ru').then((m) => m.content),
45
+ sv: () => import('./i18n/sv').then((m) => m.content),
46
+ tr: () => import('./i18n/tr').then((m) => m.content),
47
+ zh: () => import('./i18n/zh').then((m) => m.content),
48
+ },
49
+ };