@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,351 @@
1
+ .sail-area-calculator {
2
+ --sa-primary: #003b73;
3
+ --sa-primary-light: #0055a4;
4
+ --sa-secondary: #ef4135;
5
+ --sa-radius: 16px;
6
+ --n-bg: #fff;
7
+ --n-bg-muted: #f1f5f9;
8
+ --n-text: #0f172a;
9
+ --n-text-muted: #475569;
10
+ --n-text-dim: #64748b;
11
+ --n-border: #e2e8f0;
12
+ --n-shadow: rgba(0, 0, 0, 0.05);
13
+ --n-primary: #3b82f6;
14
+ --n-primary-on: #fff;
15
+ --n-accent: #6366f1;
16
+ --n-cyan: #0891b2;
17
+ --n-success: #10b981;
18
+ --n-warning: #f59e0b;
19
+ --n-error: #f43f5e;
20
+
21
+ padding: 1rem;
22
+ max-width: 1200px;
23
+ margin: 0 auto;
24
+ }
25
+
26
+ :global(.theme-dark) .sail-area-calculator {
27
+ --n-bg: #0f172a;
28
+ --n-bg-muted: #1e293b;
29
+ --n-text: #f8fafc;
30
+ --n-text-muted: #94a3b8;
31
+ --n-text-dim: #64748b;
32
+ --n-border: #334155;
33
+ --n-shadow: rgba(0, 0, 0, 0.3);
34
+ --n-primary: #60a5fa;
35
+ --n-primary-on: #fff;
36
+ --n-accent: #818cf8;
37
+ --n-cyan: #22d3ee;
38
+ --n-success: #34d399;
39
+ --n-warning: #fbbf24;
40
+ --n-error: #fb7185;
41
+ }
42
+
43
+ .sa-calculator-wrapper {
44
+ background: var(--n-bg);
45
+ border: 1px solid var(--n-border);
46
+ border-radius: var(--sa-radius);
47
+ padding: 1.5rem;
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 2rem;
51
+ }
52
+
53
+ .sa-main-controls {
54
+ display: flex;
55
+ flex-direction: column;
56
+ gap: 1.5rem;
57
+ }
58
+
59
+ .sa-section-group h3 {
60
+ font-size: 0.75rem;
61
+ text-transform: uppercase;
62
+ letter-spacing: 0.1em;
63
+ color: var(--n-text-muted);
64
+ margin-bottom: 1rem;
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 0.5rem;
68
+ opacity: 0.8;
69
+ border-bottom: 1px solid var(--n-border);
70
+ padding-bottom: 0.4rem;
71
+ }
72
+
73
+ .sa-compact-grid {
74
+ display: grid;
75
+ grid-template-columns: repeat(2, 1fr);
76
+ gap: 1rem;
77
+ }
78
+
79
+ .sa-input-row {
80
+ display: flex;
81
+ flex-direction: column;
82
+ gap: 0.4rem;
83
+ }
84
+
85
+ .sa-input-row label {
86
+ font-size: 0.7rem;
87
+ font-weight: 700;
88
+ color: var(--n-text-muted);
89
+ }
90
+
91
+ .sa-elegant-input {
92
+ background: var(--n-bg-muted);
93
+ border: 1.5px solid var(--n-border);
94
+ border-radius: 10px;
95
+ padding: 0.7rem 0.9rem;
96
+ font-size: 0.95rem;
97
+ color: var(--n-text);
98
+ font-weight: 600;
99
+ width: 100%;
100
+ }
101
+
102
+ .sa-elegant-input:focus {
103
+ border-color: var(--sa-primary-light);
104
+ outline: none;
105
+ }
106
+
107
+ .sa-input-with-unit {
108
+ position: relative;
109
+ display: flex;
110
+ align-items: center;
111
+ }
112
+
113
+ .sa-unit-tag {
114
+ position: absolute;
115
+ right: 10px;
116
+ font-size: 0.65rem;
117
+ font-weight: 900;
118
+ color: var(--n-text-muted);
119
+ background: var(--n-bg);
120
+ border: 1px solid var(--n-border);
121
+ padding: 2px 6px;
122
+ border-radius: 4px;
123
+ }
124
+
125
+ .sa-unit-tag select {
126
+ color: var(--n-text-muted);
127
+ }
128
+
129
+ .sa-sidebar-results {
130
+ background: var(--n-bg-muted);
131
+ padding: 1.5rem;
132
+ border-radius: var(--sa-radius);
133
+ border: 1px solid var(--n-border);
134
+ text-align: center;
135
+ }
136
+
137
+ .sad-value-large {
138
+ font-size: 3.5rem;
139
+ font-weight: 950;
140
+ letter-spacing: -0.04em;
141
+ color: var(--sa-primary);
142
+ line-height: 1;
143
+ }
144
+
145
+ :global(.theme-dark) .sail-area-calculator .sad-value-large {
146
+ color: var(--n-accent);
147
+ }
148
+
149
+ .sad-label {
150
+ font-size: 0.75rem;
151
+ font-weight: 850;
152
+ color: var(--n-text-muted);
153
+ text-transform: uppercase;
154
+ letter-spacing: 0.15em;
155
+ }
156
+
157
+ .sa-gauge-track {
158
+ height: 4px;
159
+ background: var(--n-border);
160
+ border-radius: 2px;
161
+ margin: 1.5rem 0;
162
+ position: relative;
163
+ }
164
+
165
+ .sa-gauge-indicator {
166
+ position: absolute;
167
+ top: 50%;
168
+ width: 14px;
169
+ height: 14px;
170
+ background: var(--sa-secondary);
171
+ border: 3px solid var(--n-bg-muted);
172
+ border-radius: 50%;
173
+ transform: translate(-50%, -50%);
174
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
175
+ transition: left 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
176
+ }
177
+
178
+ .sa-verdict-box {
179
+ background: var(--n-bg);
180
+ padding: 1rem;
181
+ border-radius: 12px;
182
+ border: 1px solid var(--n-border);
183
+ }
184
+
185
+ .sa-verdict-box h4 {
186
+ font-size: 0.95rem;
187
+ margin-bottom: 0.4rem;
188
+ color: var(--n-text);
189
+ }
190
+
191
+ .sa-verdict-box p {
192
+ font-size: 0.8rem;
193
+ line-height: 1.5;
194
+ color: var(--n-text-muted);
195
+ }
196
+
197
+ .sa-stats-summary {
198
+ display: grid;
199
+ grid-template-columns: 1fr 1fr;
200
+ gap: 1rem;
201
+ margin-top: 1.5rem;
202
+ padding-top: 1.5rem;
203
+ border-top: 1px dashed var(--n-border);
204
+ }
205
+
206
+ .sa-stat-item span {
207
+ font-size: 0.75rem;
208
+ color: var(--n-text-muted);
209
+ display: block;
210
+ }
211
+
212
+ .sa-stat-item span:last-child {
213
+ font-size: 1.2rem;
214
+ font-weight: 900;
215
+ color: var(--n-text);
216
+ }
217
+
218
+ .sa-export-btn-premium {
219
+ width: 100%;
220
+ margin-top: 1.5rem;
221
+ padding: 1rem;
222
+ background: var(--sa-primary);
223
+ color: var(--n-primary-on);
224
+ border: none;
225
+ border-radius: 10px;
226
+ font-size: 0.75rem;
227
+ font-weight: 800;
228
+ letter-spacing: 0.05em;
229
+ cursor: pointer;
230
+ display: flex;
231
+ align-items: center;
232
+ justify-content: center;
233
+ gap: 0.5rem;
234
+ }
235
+
236
+ .sa-slider-box {
237
+ background: var(--n-bg-muted);
238
+ padding: 1.5rem;
239
+ border-radius: 12px;
240
+ border: 1px solid var(--n-border);
241
+ }
242
+
243
+ .sa-slider-header {
244
+ display: flex;
245
+ justify-content: space-between;
246
+ align-items: center;
247
+ margin-bottom: 1.5rem;
248
+ }
249
+
250
+ .sa-slider-header label {
251
+ font-size: 0.85rem;
252
+ font-weight: 800;
253
+ color: var(--n-text);
254
+ }
255
+
256
+ .sa-percentage-badge {
257
+ background: var(--sa-primary);
258
+ color: var(--n-primary-on);
259
+ padding: 4px 10px;
260
+ border-radius: 20px;
261
+ font-size: 0.8rem;
262
+ font-weight: 900;
263
+ }
264
+
265
+ .sa-slider-wrapper {
266
+ padding: 0 5px;
267
+ }
268
+
269
+ .sa-modern-slider {
270
+ appearance: none;
271
+ width: 100%;
272
+ height: 6px;
273
+ background: var(--n-border);
274
+ border-radius: 10px;
275
+ outline: none;
276
+ margin: 1rem 0;
277
+ }
278
+
279
+ .sa-modern-slider::-webkit-slider-thumb {
280
+ appearance: none;
281
+ width: 24px;
282
+ height: 24px;
283
+ background: var(--sa-primary);
284
+ border: 4px solid var(--n-bg-muted);
285
+ border-radius: 50%;
286
+ cursor: pointer;
287
+ box-shadow: 0 2px 10px rgba(0, 59, 115, 0.2);
288
+ transition: transform 0.2s;
289
+ }
290
+
291
+ .sa-modern-slider::-webkit-slider-thumb:hover {
292
+ transform: scale(1.1);
293
+ }
294
+
295
+ .sa-modern-slider::-moz-range-thumb {
296
+ width: 24px;
297
+ height: 24px;
298
+ background: var(--sa-primary);
299
+ border: 4px solid var(--n-bg-muted);
300
+ border-radius: 50%;
301
+ cursor: pointer;
302
+ }
303
+
304
+ .sa-modern-slider::-moz-range-track {
305
+ height: 6px;
306
+ background: var(--n-border);
307
+ border-radius: 10px;
308
+ }
309
+
310
+ .sa-slider-ticks {
311
+ display: flex;
312
+ justify-content: space-between;
313
+ margin-top: 0.5rem;
314
+ }
315
+
316
+ .sa-slider-ticks span {
317
+ font-size: 0.65rem;
318
+ font-weight: 700;
319
+ color: var(--n-text-muted);
320
+ }
321
+
322
+ @media (min-width: 1024px) {
323
+ .sail-area-calculator {
324
+ padding: 2rem;
325
+ }
326
+
327
+ .sa-calculator-wrapper {
328
+ display: grid;
329
+ grid-template-columns: 1fr 400px;
330
+ gap: 3rem;
331
+ padding: 2.5rem;
332
+ }
333
+
334
+ .sa-compact-grid {
335
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
336
+ }
337
+
338
+ .sa-main-controls {
339
+ gap: 2.5rem;
340
+ }
341
+
342
+ .sa-sidebar-results {
343
+ position: sticky;
344
+ top: 2rem;
345
+ padding: 2.5rem;
346
+ }
347
+
348
+ .sad-value-large {
349
+ font-size: 5.5rem;
350
+ }
351
+ }
@@ -123,244 +123,3 @@ const bd = JSON.parse(ui.beaufortDataJson) as { force: number; name: string; sea
123
123
  sync('val-kn', savedKn);
124
124
  </script>
125
125
 
126
- <style>
127
- .speed-converter {
128
- --n-bg: #fff;
129
- --n-bg-muted: #f1f5f9;
130
- --n-text: #0f172a;
131
- --n-text-muted: #475569;
132
- --n-text-dim: #64748b;
133
- --n-border: #e2e8f0;
134
- --n-shadow: rgba(0, 0, 0, 0.05);
135
- --n-primary: #3b82f6;
136
- --n-primary-on: #fff;
137
- --n-accent: #6366f1;
138
- --n-cyan: #0891b2;
139
- --n-success: #10b981;
140
- --n-warning: #f59e0b;
141
- --n-error: #f43f5e;
142
-
143
- max-width: 900px;
144
- margin: 0 auto;
145
- display: flex;
146
- flex-direction: column;
147
- gap: 2rem;
148
- }
149
-
150
- :global(.theme-dark) .speed-converter {
151
- --n-bg: #0f172a;
152
- --n-bg-muted: #1e293b;
153
- --n-text: #f8fafc;
154
- --n-text-muted: #94a3b8;
155
- --n-text-dim: #64748b;
156
- --n-border: #334155;
157
- --n-shadow: rgba(0, 0, 0, 0.3);
158
- --n-primary: #60a5fa;
159
- --n-primary-on: #fff;
160
- --n-accent: #818cf8;
161
- --n-cyan: #22d3ee;
162
- --n-success: #34d399;
163
- --n-warning: #fbbf24;
164
- --n-error: #fb7185;
165
- }
166
-
167
- .sc-input-grid {
168
- display: grid;
169
- grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
170
- gap: 1rem;
171
- background: var(--n-bg);
172
- border: 1px solid var(--n-border);
173
- border-radius: 1.5rem;
174
- padding: 2rem;
175
- }
176
-
177
- .sc-input-group {
178
- display: flex;
179
- flex-direction: column;
180
- gap: 0.5rem;
181
- }
182
-
183
- .sc-input-group label {
184
- font-size: 0.8rem;
185
- font-weight: 600;
186
- color: var(--n-text-muted);
187
- text-transform: uppercase;
188
- }
189
-
190
- .sc-input-wrapper {
191
- background: var(--n-bg-muted);
192
- border: 2px solid var(--n-border);
193
- border-radius: 0.8rem;
194
- padding: 0.8rem 1rem;
195
- transition: border-color 0.2s;
196
- }
197
-
198
- .sc-input-wrapper:focus-within {
199
- border-color: var(--n-cyan);
200
- }
201
-
202
- .sc-input-wrapper input {
203
- background: transparent;
204
- border: none;
205
- outline: none;
206
- color: var(--n-text);
207
- font-size: 1.5rem;
208
- font-weight: 800;
209
- width: 100%;
210
- }
211
-
212
- .sc-input-wrapper input::-webkit-outer-spin-button,
213
- .sc-input-wrapper input::-webkit-inner-spin-button {
214
- appearance: none;
215
- }
216
-
217
- .sc-beaufort-summary {
218
- background: var(--n-primary);
219
- color: var(--n-primary-on);
220
- border-radius: 1.5rem;
221
- padding: 2rem;
222
- display: grid;
223
- grid-template-columns: auto 1fr;
224
- gap: 1rem 2rem;
225
- align-items: center;
226
- }
227
-
228
- .sc-force-circle {
229
- width: 80px;
230
- height: 80px;
231
- border-radius: 50%;
232
- background: rgba(255, 255, 255, 0.15);
233
- display: flex;
234
- align-items: center;
235
- justify-content: center;
236
- font-size: 2.5rem;
237
- font-weight: 800;
238
- color: var(--n-primary-on);
239
- flex-shrink: 0;
240
- }
241
-
242
- .sc-force-text-box {
243
- display: flex;
244
- flex-direction: column;
245
- gap: 0.3rem;
246
- }
247
-
248
- .sc-force-name {
249
- margin: 0;
250
- font-size: 1.4rem;
251
- font-weight: 800;
252
- color: var(--n-primary-on);
253
- }
254
-
255
- .sc-force-detail {
256
- margin: 0;
257
- opacity: 0.8;
258
- font-size: 0.9rem;
259
- color: var(--n-primary-on);
260
- }
261
-
262
- .sc-sea-state-box {
263
- grid-column: 1 / -1;
264
- background: rgba(255, 255, 255, 0.1);
265
- border-radius: 1rem;
266
- padding: 1rem 1.5rem;
267
- }
268
-
269
- .sc-sea-text .label {
270
- font-size: 0.7rem;
271
- text-transform: uppercase;
272
- opacity: 0.7;
273
- color: var(--n-primary-on);
274
- font-weight: 700;
275
- }
276
-
277
- .sc-sea-text p {
278
- margin: 0.2rem 0 0;
279
- font-weight: 600;
280
- color: var(--n-primary-on);
281
- }
282
-
283
- .sc-table-container {
284
- background: var(--n-bg);
285
- border: 1px solid var(--n-border);
286
- border-radius: 1.5rem;
287
- overflow: hidden;
288
- }
289
-
290
- .sc-table-container h3 {
291
- padding: 1.5rem;
292
- margin: 0;
293
- font-size: 1rem;
294
- color: var(--n-text-muted);
295
- border-bottom: 1px solid var(--n-border);
296
- font-weight: 700;
297
- }
298
-
299
- .sc-scroll-area {
300
- overflow-x: auto;
301
- }
302
-
303
- .sc-beaufort-table {
304
- width: 100%;
305
- border-collapse: collapse;
306
- }
307
-
308
- .sc-beaufort-table th {
309
- text-align: left;
310
- padding: 0.8rem 1rem;
311
- font-size: 0.75rem;
312
- color: var(--n-text-muted);
313
- text-transform: uppercase;
314
- border-bottom: 2px solid var(--n-border);
315
- }
316
-
317
- .sc-beaufort-table td {
318
- padding: 0.8rem 1rem;
319
- font-size: 0.9rem;
320
- color: var(--n-text-muted);
321
- border-bottom: 1px solid var(--n-border);
322
- }
323
-
324
- .sc-clickable-row {
325
- cursor: pointer;
326
- transition: background 0.15s;
327
- }
328
-
329
- .sc-clickable-row:hover {
330
- background: var(--n-bg-muted);
331
- }
332
-
333
- .sc-clickable-row.active {
334
- background: var(--n-primary);
335
- }
336
-
337
- .sc-clickable-row.active td {
338
- color: var(--n-primary-on);
339
- }
340
-
341
- .sc-force-tag {
342
- background: var(--n-bg-muted);
343
- padding: 0.2rem 0.5rem;
344
- border-radius: 0.4rem;
345
- font-weight: 700;
346
- font-size: 0.85rem;
347
- color: var(--n-text);
348
- }
349
-
350
- .sc-clickable-row.active .sc-force-tag {
351
- background: rgba(255, 255, 255, 0.2);
352
- color: var(--n-primary-on);
353
- }
354
-
355
- @media (max-width: 640px) {
356
- .sc-beaufort-summary {
357
- grid-template-columns: 1fr;
358
- }
359
-
360
- .sc-force-circle {
361
- width: 60px;
362
- height: 60px;
363
- font-size: 2rem;
364
- }
365
- }
366
- </style>
@@ -0,0 +1,46 @@
1
+ import type { NauticalToolEntry, ToolLocaleContent } from '../../types';
2
+
3
+ export interface SpeedConverterUI {
4
+ [key: string]: string;
5
+ knLabel: string;
6
+ kmhLabel: string;
7
+ msLabel: string;
8
+ mphLabel: string;
9
+ beaufortTitle: string;
10
+ forceLabel: string;
11
+ descriptionLabel: string;
12
+ knotsLabel: string;
13
+ effectLabel: string;
14
+ seaStateLabel: string;
15
+ windEffectLabel: string;
16
+ faqTitle: string;
17
+ bibliographyTitle: string;
18
+ beaufortDataJson: string;
19
+ }
20
+
21
+ export type SpeedConverterLocaleContent = ToolLocaleContent<SpeedConverterUI>;
22
+
23
+ export const speedConverter: NauticalToolEntry<SpeedConverterUI> = {
24
+ id: 'speed-converter',
25
+ icons: {
26
+ bg: 'mdi:speedometer',
27
+ fg: 'mdi:weather-windy',
28
+ },
29
+ i18n: {
30
+ es: () => import('./i18n/es').then((m) => m.content),
31
+ en: () => import('./i18n/en').then((m) => m.content),
32
+ fr: () => import('./i18n/fr').then((m) => m.content),
33
+ de: () => import('./i18n/de').then((m) => m.content),
34
+ id: () => import('./i18n/id').then((m) => m.content),
35
+ it: () => import('./i18n/it').then((m) => m.content),
36
+ ja: () => import('./i18n/ja').then((m) => m.content),
37
+ ko: () => import('./i18n/ko').then((m) => m.content),
38
+ nl: () => import('./i18n/nl').then((m) => m.content),
39
+ pl: () => import('./i18n/pl').then((m) => m.content),
40
+ pt: () => import('./i18n/pt').then((m) => m.content),
41
+ ru: () => import('./i18n/ru').then((m) => m.content),
42
+ sv: () => import('./i18n/sv').then((m) => m.content),
43
+ tr: () => import('./i18n/tr').then((m) => m.content),
44
+ zh: () => import('./i18n/zh').then((m) => m.content),
45
+ },
46
+ };
@@ -1,51 +1,5 @@
1
- import type { NauticalToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
-
3
- export interface SpeedConverterUI {
4
- [key: string]: string;
5
- knLabel: string;
6
- kmhLabel: string;
7
- msLabel: string;
8
- mphLabel: string;
9
- beaufortTitle: string;
10
- forceLabel: string;
11
- descriptionLabel: string;
12
- knotsLabel: string;
13
- effectLabel: string;
14
- seaStateLabel: string;
15
- windEffectLabel: string;
16
- faqTitle: string;
17
- bibliographyTitle: string;
18
- beaufortDataJson: string;
19
- }
20
-
21
- export type SpeedConverterLocaleContent = ToolLocaleContent<SpeedConverterUI>;
22
-
23
- export const speedConverter: NauticalToolEntry<SpeedConverterUI> = {
24
- id: 'speed-converter',
25
- icons: {
26
- bg: 'mdi:speedometer',
27
- fg: 'mdi:weather-windy',
28
- },
29
- i18n: {
30
- es: () => import('./i18n/es').then((m) => m.content),
31
- en: () => import('./i18n/en').then((m) => m.content),
32
- fr: () => import('./i18n/fr').then((m) => m.content),
33
- de: () => import('./i18n/de').then((m) => m.content),
34
- id: () => import('./i18n/id').then((m) => m.content),
35
- it: () => import('./i18n/it').then((m) => m.content),
36
- ja: () => import('./i18n/ja').then((m) => m.content),
37
- ko: () => import('./i18n/ko').then((m) => m.content),
38
- nl: () => import('./i18n/nl').then((m) => m.content),
39
- pl: () => import('./i18n/pl').then((m) => m.content),
40
- pt: () => import('./i18n/pt').then((m) => m.content),
41
- ru: () => import('./i18n/ru').then((m) => m.content),
42
- sv: () => import('./i18n/sv').then((m) => m.content),
43
- tr: () => import('./i18n/tr').then((m) => m.content),
44
- zh: () => import('./i18n/zh').then((m) => m.content),
45
- },
46
- };
47
-
48
-
1
+ import { speedConverter } from './entry';
2
+ export * from './entry';
49
3
  export const SPEED_CONVERTER_TOOL: ToolDefinition = {
50
4
  entry: speedConverter,
51
5
  Component: () => import('./component.astro'),