@jjlmoya/utils-astronomy 1.4.0 → 1.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-astronomy",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -8,6 +8,7 @@ interface Props {
8
8
  }
9
9
 
10
10
  const { ui } = Astro.props;
11
+ const bortleData = ui.bortleData;
11
12
  ---
12
13
 
13
14
  <div class="bortle-wrapper" id="bortle-simulator">
@@ -80,8 +81,14 @@ const { ui } = Astro.props;
80
81
  </div>
81
82
  </div>
82
83
 
84
+ <script define:vars={{ ui, bortleData }} is:inline>
85
+ window.__bortleUI = ui;
86
+ window.__bortleData = bortleData;
87
+ </script>
88
+
83
89
  <script>
84
- import { getBortleData } from './logic';
90
+ const uiData = window.__bortleUI || {};
91
+ const bortleDataMap = window.__bortleData || {};
85
92
 
86
93
  const elements = {
87
94
  stars: document.getElementById('layer-stars'),
@@ -162,9 +169,9 @@ const { ui } = Astro.props;
162
169
  }
163
170
 
164
171
  if (elements.slider) {
165
- function updateText(level: number, data: ReturnType<typeof getBortleData>) {
172
+ function updateText(level: number, data: BortleLevel) {
166
173
  if (elements.title) elements.title.innerText = data.title;
167
- if (elements.classLabel) elements.classLabel.innerText = `CLASE ${level}`;
174
+ if (elements.classLabel) elements.classLabel.innerText = `${uiData.classPrefix} ${level}`;
168
175
  if (elements.nelm) elements.nelm.innerText = `NELM ${data.nelm.toFixed(1)}`;
169
176
  if (elements.desc) elements.desc.innerText = data.description;
170
177
  if (elements.descMobile) elements.descMobile.innerText = data.description;
@@ -194,7 +201,7 @@ const { ui } = Astro.props;
194
201
 
195
202
  function updateAll(val: number) {
196
203
  const level = Math.floor(val);
197
- const data = getBortleData(level);
204
+ const data = bortleDataMap[level.toString()];
198
205
  updateText(level, data);
199
206
  updateThumb(val);
200
207
  updateLayers(level, data.skyBrightness);
@@ -11,6 +11,18 @@ const ui: BortleVisualizerUI = {
11
11
  classLabel: 'Bortle Class',
12
12
  nelmLabel: 'NELM',
13
13
  sqmLabel: 'SQM',
14
+ classPrefix: 'CLASS',
15
+ bortleData: {
16
+ 1: { title: 'Excellent Dark Sky', description: 'Astronomer\'s paradise. Milky Way casts shadows. Zodiacal light visible and colorful. M33 naked-eye visible.', nelm: 8.0, sqm: '21.99 - 22.0', starsVisible: true, milkyWayVisible: true, cloudsLit: false, skyBrightness: 0.0 },
17
+ 2: { title: 'Truly Dark', description: 'Really dark sites. Milky Way is highly structured. Clouds only visible as black holes in the sky.', nelm: 7.5, sqm: '21.89 - 21.99', starsVisible: true, milkyWayVisible: true, cloudsLit: false, skyBrightness: 0.1 },
18
+ 3: { title: 'Rural Sky', description: 'Complex Milky Way. Some light pollution on horizon. Clouds lit near horizon but dark overhead.', nelm: 7.0, sqm: '21.69 - 21.89', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.2 },
19
+ 4: { title: 'Rural/Suburban', description: 'Milky Way loses detail but visible. Light domes on horizon. Clouds lit from below.', nelm: 6.5, sqm: '20.49 - 21.69', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.35 },
20
+ 5: { title: 'Suburban Sky', description: 'Milky Way very faint or invisible near horizon. Zodiacal light rarely visible. Sky appears grayish.', nelm: 6.0, sqm: '19.50 - 20.49', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.5 },
21
+ 6: { title: 'Bright Suburban', description: 'Milky Way invisible. Sky is bright gray. Clouds very bright. M31 barely visible.', nelm: 5.5, sqm: '18.94 - 19.50', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.65 },
22
+ 7: { title: 'Suburban/Urban', description: 'Sky grayish-white. Strong light sources in all directions. Only brightest stars visible.', nelm: 5.0, sqm: '18.38 - 18.94', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.8 },
23
+ 8: { title: 'Urban Sky', description: 'Sky is grayish-white or orange. Can read newspaper headlines. Only major constellations visible.', nelm: 4.5, sqm: '< 18.38', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.9 },
24
+ 9: { title: 'City Center', description: 'Sky bright as twilight. Moon visible but constellations not. Only planets and Moon visible.', nelm: 4.0, sqm: '< 18.00', starsVisible: false, milkyWayVisible: false, cloudsLit: true, skyBrightness: 1.0 },
25
+ },
14
26
  };
15
27
 
16
28
  const faq: BortleVisualizerLocaleContent['faq'] = [
@@ -138,6 +150,7 @@ const appSchema: WithContext<SoftwareApplication> = {
138
150
  inLanguage: 'en',
139
151
  };
140
152
 
153
+
141
154
  export const content: BortleVisualizerLocaleContent = {
142
155
  slug,
143
156
  title,
@@ -149,5 +162,6 @@ export const content: BortleVisualizerLocaleContent = {
149
162
  bibliography,
150
163
  bibliographyTitle: 'Bibliographic References',
151
164
  howTo,
165
+ bortleData: ui.bortleData,
152
166
  schemas: [faqSchema as any, howToSchema as any, appSchema],
153
167
  };
@@ -11,6 +11,18 @@ const ui: BortleVisualizerUI = {
11
11
  classLabel: 'Clase Bortle',
12
12
  nelmLabel: 'NELM',
13
13
  sqmLabel: 'SQM',
14
+ classPrefix: 'CLASE',
15
+ bortleData: {
16
+ 1: { title: 'Cielo Oscuro Excelente', description: 'El nirvana astronómico. La Vía Láctea proyecta sombras. La luz zodiacal es visible y colorida. M33 es visible a simple vista.', nelm: 8.0, sqm: '21.99 - 22.0', starsVisible: true, milkyWayVisible: true, cloudsLit: false, skyBrightness: 0.0 },
17
+ 2: { title: 'Cielo Oscuro Típico', description: 'Sitios realmente oscuros. La Vía Láctea es muy estructurada. Nubes solo visibles como agujeros negros en el cielo.', nelm: 7.5, sqm: '21.89 - 21.99', starsVisible: true, milkyWayVisible: true, cloudsLit: false, skyBrightness: 0.1 },
18
+ 3: { title: 'Cielo Rural', description: 'Vía Láctea compleja. Alguna contaminación lumínica en el horizonte. Las nubes están iluminadas cerca del horizonte pero oscuras arriba.', nelm: 7.0, sqm: '21.69 - 21.89', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.2 },
19
+ 4: { title: 'Transición Rural/Suburbana', description: 'La Vía Láctea pierde detalle pero se ve. Domos de luz en el horizonte. Las nubes están iluminadas por abajo.', nelm: 6.5, sqm: '20.49 - 21.69', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.35 },
20
+ 5: { title: 'Cielo Suburbano', description: 'La Vía Láctea es muy débil o invisible cerca del horizonte. Luz zodiacal rara vez visible. El cielo se ve grisáceo, no negro.', nelm: 6.0, sqm: '19.50 - 20.49', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.5 },
21
+ 6: { title: 'Cielo Suburbano Brillante', description: 'Vía Láctea invisible. El cielo es gris brillante. Nubes muy brillantes. M31 (Andrómeda) apenas visible.', nelm: 5.5, sqm: '18.94 - 19.50', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.65 },
22
+ 7: { title: 'Transición Suburbana/Urbana', description: 'Fondo del cielo gris claro. Fuentes de luz fuertes en todas direcciones. Solo las estrellas más brillantes son visibles.', nelm: 5.0, sqm: '18.38 - 18.94', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.8 },
23
+ 8: { title: 'Cielo Urbano', description: 'El cielo es gris blanquecino o naranja. Se pueden leer titulares de periódico. Solo se ven constelaciones principales.', nelm: 4.5, sqm: '< 18.38', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.9 },
24
+ 9: { title: 'Cielo Urbano Interior', description: 'El cielo es muy brillante, incluso en el cenit. Solo se ven la Luna, planetas y un puñado de estrellas brillantes.', nelm: 4.0, sqm: '< 18.00', starsVisible: false, milkyWayVisible: false, cloudsLit: true, skyBrightness: 1.0 },
25
+ },
14
26
  };
15
27
 
16
28
  const faq: BortleVisualizerLocaleContent['faq'] = [
@@ -146,6 +158,7 @@ const appSchema: WithContext<SoftwareApplication> = {
146
158
  inLanguage: 'es',
147
159
  };
148
160
 
161
+
149
162
  export const content: BortleVisualizerLocaleContent = {
150
163
  slug,
151
164
  title,
@@ -157,5 +170,6 @@ export const content: BortleVisualizerLocaleContent = {
157
170
  bibliography,
158
171
  bibliographyTitle: 'Referencias Bibliográficas',
159
172
  howTo,
173
+ bortleData: ui.bortleData,
160
174
  schemas: [faqSchema as any, howToSchema as any, appSchema],
161
175
  };
@@ -11,6 +11,18 @@ const ui: BortleVisualizerUI = {
11
11
  classLabel: 'Classe Bortle',
12
12
  nelmLabel: 'NELM',
13
13
  sqmLabel: 'SQM',
14
+ classPrefix: 'CLASSE',
15
+ bortleData: {
16
+ 1: { title: 'Ciel Noir Excellent', description: 'Paradis de l\'astronome. Voie lactée projette des ombres. Lumière zodiacale visible et colorée. M33 visible à l\'œil nu.', nelm: 8.0, sqm: '21.99 - 22.0', starsVisible: true, milkyWayVisible: true, cloudsLit: false, skyBrightness: 0.0 },
17
+ 2: { title: 'Ciel Vraiment Sombre', description: 'Sites véritablement sombres. Voie lactée très structurée. Nuages visibles uniquement comme des trous noirs dans le ciel.', nelm: 7.5, sqm: '21.89 - 21.99', starsVisible: true, milkyWayVisible: true, cloudsLit: false, skyBrightness: 0.1 },
18
+ 3: { title: 'Ciel Rural', description: 'Voie lactée complexe. Pollution lumineuse à l\'horizon. Nuages éclairés près de l\'horizon mais sombres au-dessus.', nelm: 7.0, sqm: '21.69 - 21.89', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.2 },
19
+ 4: { title: 'Rural/Suburbain', description: 'Voie lactée perd en détail mais visible. Dômes de lumière à l\'horizon. Nuages éclairés d\'en bas.', nelm: 6.5, sqm: '20.49 - 21.69', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.35 },
20
+ 5: { title: 'Ciel Suburbain', description: 'Voie lactée très faible ou invisible près de l\'horizon. Lumière zodiacale rarement visible. Ciel grisâtre.', nelm: 6.0, sqm: '19.50 - 20.49', starsVisible: true, milkyWayVisible: true, cloudsLit: true, skyBrightness: 0.5 },
21
+ 6: { title: 'Suburbain Brillant', description: 'Voie lactée invisible. Ciel gris clair. Nuages très brillants. M31 à peine visible.', nelm: 5.5, sqm: '18.94 - 19.50', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.65 },
22
+ 7: { title: 'Suburbain/Urbain', description: 'Ciel gris clair. Sources lumineuses fortes dans toutes les directions. Seules les plus brillantes étoiles visibles.', nelm: 5.0, sqm: '18.38 - 18.94', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.8 },
23
+ 8: { title: 'Ciel Urbain', description: 'Ciel gris-blanc ou orange. Peut lire les gros titres des journaux. Seules les principales constellations visibles.', nelm: 4.5, sqm: '< 18.38', starsVisible: true, milkyWayVisible: false, cloudsLit: true, skyBrightness: 0.9 },
24
+ 9: { title: 'Centre-Ville', description: 'Ciel lumineux comme le crépuscule. Lune visible mais constellations non. Seulement planètes et Lune visibles.', nelm: 4.0, sqm: '< 18.00', starsVisible: false, milkyWayVisible: false, cloudsLit: true, skyBrightness: 1.0 },
25
+ },
14
26
  };
15
27
 
16
28
  const faq: BortleVisualizerLocaleContent['faq'] = [
@@ -149,5 +161,6 @@ export const content: BortleVisualizerLocaleContent = {
149
161
  bibliography,
150
162
  bibliographyTitle: 'Références Bibliographiques',
151
163
  howTo,
164
+ bortleData: ui.bortleData,
152
165
  schemas: [faqSchema as any, howToSchema as any, appSchema],
153
166
  };
@@ -4,15 +4,31 @@ import BortleVisualizerSEO from './seo.astro';
4
4
  import BortleVisualizerBibliography from './bibliography.astro';
5
5
 
6
6
  export interface BortleVisualizerUI {
7
- [key: string]: string;
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ [key: string]: any;
8
9
  toolTitle: string;
9
10
  sliderLabel: string;
10
11
  classLabel: string;
11
12
  nelmLabel: string;
12
13
  sqmLabel: string;
14
+ classPrefix: string;
15
+ bortleData: Record<number, BortleLevel>;
13
16
  }
14
17
 
15
- export type BortleVisualizerLocaleContent = ToolLocaleContent<BortleVisualizerUI>;
18
+ export interface BortleLevel {
19
+ title: string;
20
+ description: string;
21
+ nelm: number;
22
+ sqm: string;
23
+ starsVisible: boolean;
24
+ milkyWayVisible: boolean;
25
+ cloudsLit: boolean;
26
+ skyBrightness: number;
27
+ }
28
+
29
+ export interface BortleVisualizerLocaleContent extends ToolLocaleContent<BortleVisualizerUI> {
30
+ bortleData: Record<number, BortleLevel>;
31
+ }
16
32
 
17
33
  import { content as es } from './i18n/es';
18
34
  import { content as en } from './i18n/en';
@@ -35,7 +35,7 @@ const { ui } = Astro.props;
35
35
  <p id="modal-type" class="modal-type">Type</p>
36
36
  </div>
37
37
  </div>
38
- <button id="close-modal" class="modal-close" aria-label="Cerrar">
38
+ <button id="close-modal" class="modal-close" aria-label={ui.closeLabel}>
39
39
  <Icon name="mdi:close" />
40
40
  </button>
41
41
  </div>
@@ -128,14 +128,20 @@ const { ui } = Astro.props;
128
128
  </div>
129
129
  </div>
130
130
 
131
+ <script define:vars={{ ui }} is:inline>
132
+ window.__deepSpaceUI = ui;
133
+ </script>
134
+
131
135
  <script>
136
+ import type { DeepSpaceObject } from "./index";
132
137
  import {
133
- DEEP_SPACE_OBJECTS,
134
138
  calculateLimitingMagnitude,
135
139
  apertureSliderToMm,
136
140
  } from "./logic";
137
141
 
138
142
  const container = document.getElementById("scope-container");
143
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
144
+ const uiData = (window as any).__deepSpaceUI || {};
139
145
  const canvas = document.getElementById("sky-canvas") as HTMLCanvasElement;
140
146
  const ctx = canvas?.getContext("2d");
141
147
  const objectsLayer = document.getElementById("objects-layer");
@@ -168,7 +174,8 @@ const { ui } = Astro.props;
168
174
  function initObjectsDOM() {
169
175
  if (!objectsLayer) return;
170
176
  objectsLayer.innerHTML = "";
171
- DEEP_SPACE_OBJECTS.forEach((obj, idx) => {
177
+ const objects = uiData.deepSpaceObjects || [];
178
+ objects.forEach((obj: DeepSpaceObject, idx: number) => {
172
179
  const el = document.createElement("div");
173
180
  el.id = `obj-${idx}`;
174
181
  el.className = "scope-object";
@@ -194,13 +201,13 @@ const { ui } = Astro.props;
194
201
  const modalContent = document.getElementById("modal-content");
195
202
  const closeModalBtn = document.getElementById("close-modal");
196
203
 
197
- function openModal(obj: (typeof DEEP_SPACE_OBJECTS)[0]) {
204
+ function openModal(obj: DeepSpaceObject) {
198
205
  if (!modal || !modalContent) return;
199
206
  document.getElementById("modal-title")!.innerText = obj.name;
200
207
  document.getElementById("modal-type")!.innerText = obj.type;
201
208
  document.getElementById("modal-mag")!.innerText = obj.mag.toString();
202
- document.getElementById("modal-az")!.innerText = `Azimuth: ${obj.az}°`;
203
- document.getElementById("modal-alt")!.innerText = `Altitud: ${obj.alt}°`;
209
+ document.getElementById("modal-az")!.innerText = `${uiData.azimuthLabel}: ${obj.az}°`;
210
+ document.getElementById("modal-alt")!.innerText = `${uiData.altitudeLabel}: ${obj.alt}°`;
204
211
  const iconEl = document.getElementById("modal-icon");
205
212
  if (iconEl) {
206
213
  iconEl.innerHTML = `<span class="iconify" data-icon="${obj.icon}" style="font-size:2.5rem;color:${obj.color}"></span>`;
@@ -209,7 +216,7 @@ const { ui } = Astro.props;
209
216
  if (descEl) {
210
217
  descEl.innerText =
211
218
  obj.desc ||
212
- `Un objeto fascinante del espacio profundo. Magnitud ${obj.mag}.`;
219
+ `${uiData.defaultObjDesc} ${obj.mag}.`;
213
220
  }
214
221
  modal.classList.remove("modal-hidden");
215
222
  modalContent.classList.remove("modal-scale-out");
@@ -235,10 +242,10 @@ const { ui } = Astro.props;
235
242
 
236
243
  function updateDisplays(limit: number, apertureMM: number, bortle: number) {
237
244
  document.getElementById("aperture-display")!.innerText = `${apertureMM}mm`;
238
- document.getElementById("bortle-display")!.innerText = `Clase ${bortle}`;
245
+ document.getElementById("bortle-display")!.innerText = `${uiData.bortleClassPrefix} ${bortle}`;
239
246
  if (limitMagDisplay) limitMagDisplay.innerText = limit.toFixed(1);
240
247
  if (azimuthDisplay)
241
- azimuthDisplay.innerText = `AZ: ${Math.round(panAngle)}°`;
248
+ azimuthDisplay.innerText = `${uiData.azimuthLabel}: ${Math.round(panAngle)}°`;
242
249
  if (pollutionLayer) {
243
250
  const opacity = (bortle - 1) * 0.08;
244
251
  pollutionLayer.style.backgroundColor = `rgba(217, 119, 6, ${opacity})`;
@@ -266,7 +273,7 @@ const { ui } = Astro.props;
266
273
 
267
274
  function updateObjectElement(
268
275
  el: HTMLElement,
269
- obj: (typeof DEEP_SPACE_OBJECTS)[0],
276
+ obj: DeepSpaceObject,
270
277
  limit: number,
271
278
  ) {
272
279
  const delta = getShortestDelta(obj.az, panAngle);
@@ -282,7 +289,8 @@ const { ui } = Astro.props;
282
289
  }
283
290
 
284
291
  function renderObjects(limit: number) {
285
- DEEP_SPACE_OBJECTS.forEach((obj, idx) => {
292
+ const objects = uiData.deepSpaceObjects || [];
293
+ objects.forEach((obj: DeepSpaceObject, idx: number) => {
286
294
  const el = document.getElementById(`obj-${idx}`);
287
295
  if (!el) return;
288
296
  if (obj.mag > limit) {
@@ -481,7 +489,7 @@ const { ui } = Astro.props;
481
489
  }
482
490
  }
483
491
 
484
- .scope-object {
492
+ :global(.scope-object) {
485
493
  position: absolute;
486
494
  transform: translate(-50%, -50%);
487
495
  display: flex;
@@ -494,23 +502,23 @@ const { ui } = Astro.props;
494
502
  cursor: pointer;
495
503
  }
496
504
 
497
- .scope-object:hover .scope-obj-icon {
505
+ :global(.scope-object:hover) :global(.scope-obj-icon) {
498
506
  transform: scale(1.25);
499
507
  }
500
508
 
501
- .scope-obj-icon {
509
+ :global(.scope-obj-icon) {
502
510
  font-size: 2rem;
503
511
  transition: transform 0.3s ease;
504
512
  filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.4));
505
513
  }
506
514
 
507
515
  @media (min-width: 768px) {
508
- .scope-obj-icon {
516
+ :global(.scope-obj-icon) {
509
517
  font-size: 3rem;
510
518
  }
511
519
  }
512
520
 
513
- .scope-obj-label {
521
+ :global(.scope-obj-label) {
514
522
  margin-top: 0.5rem;
515
523
  display: flex;
516
524
  flex-direction: column;
@@ -519,7 +527,7 @@ const { ui } = Astro.props;
519
527
  transition: opacity 0.3s ease;
520
528
  }
521
529
 
522
- .scope-obj-name {
530
+ :global(.scope-obj-name) {
523
531
  font-size: 0.625rem;
524
532
  font-weight: 700;
525
533
  color: var(--on-dark);
@@ -531,7 +539,7 @@ const { ui } = Astro.props;
531
539
  white-space: nowrap;
532
540
  }
533
541
 
534
- .scope-obj-mag {
542
+ :global(.scope-obj-mag) {
535
543
  font-size: 0.5rem;
536
544
  color: rgba(148, 163, 184, 0.8);
537
545
  background: rgba(0, 0, 0, 0.8);
@@ -18,6 +18,27 @@ const ui: DeepSpaceScopeUI = {
18
18
  deepSpaceLabel: 'Deep Space',
19
19
  magnitudeLabel: 'Magnitude',
20
20
  coordinatesLabel: 'Coordinates',
21
+ closeLabel: 'Close',
22
+ altitudeLabel: 'Altitude',
23
+ defaultObjDesc: 'A fascinating deep space object. Magnitude',
24
+ bortleClassPrefix: 'Class',
25
+ deepSpaceObjects: [
26
+ { name: 'Venus', type: 'Planet', mag: -4.5, az: 270, alt: 30, icon: 'mdi:circle', color: '#fef08a', desc: 'The brightest planet in the night sky. Visible in broad daylight.' },
27
+ { name: 'Jupiter', type: 'Planet', mag: -2.5, az: 180, alt: 40, icon: 'mdi:circle', color: '#fef9c3', desc: 'The giant of the solar system. Its four Galilean moons can be seen with binoculars.' },
28
+ { name: 'Saturn', type: 'Planet', mag: 0.8, az: 220, alt: 35, icon: 'mdi:circle', color: '#fefce8', desc: 'Its rings are visible with a 60mm telescope at 50x magnification.' },
29
+ { name: 'Mars', type: 'Planet', mag: 1.5, az: 150, alt: 25, icon: 'mdi:circle', color: '#f87171', desc: 'The Red Planet. Varies from magnitude -2.9 at opposition to +1.8 at conjunction.' },
30
+ { name: 'Sirius', type: 'Star', mag: -1.46, az: 145, alt: 50, icon: 'mdi:star-four-points', color: '#bfdbfe', desc: 'The brightest star in the night sky. Located just 8.6 light-years away.' },
31
+ { name: 'Canopus', type: 'Star', mag: -0.74, az: 200, alt: 20, icon: 'mdi:star-four-points', color: '#fef9c3', desc: 'The second brightest star, used for navigation in the Southern Hemisphere.' },
32
+ { name: 'Arcturus', type: 'Star', mag: -0.05, az: 60, alt: 55, icon: 'mdi:star-four-points', color: '#fdba74', desc: 'Orange giant in the Boötes constellation. 36 light-years from Earth.' },
33
+ { name: 'Vega', type: 'Star', mag: 0.03, az: 40, alt: 70, icon: 'mdi:star-four-points', color: '#dbeafe', desc: 'Vertex of the Summer Triangle. The reference star for magnitude 0.' },
34
+ { name: 'M42 Orion', type: 'Nebula', mag: 4.0, az: 140, alt: 45, icon: 'mdi:creation', color: '#a5b4fc', desc: 'The Great Orion Nebula, 1344 light-years away. A nursery for young stars.' },
35
+ { name: 'M45 Pleiades', type: 'Cluster', mag: 1.6, az: 100, alt: 60, icon: 'mdi:creation', color: '#93c5fd', desc: 'The Seven Sisters. At 444 light-years, the most famous open cluster in the sky.' },
36
+ { name: 'M31 Andromeda', type: 'Galaxy', mag: 3.4, az: 30, alt: 50, icon: 'mdi:creation', color: '#d8b4fe', desc: 'The largest neighboring galaxy. 2.5 million light-years away, visible to the naked eye in dark skies.' },
37
+ { name: 'M13 Hercules', type: 'Cluster', mag: 5.8, az: 80, alt: 65, icon: 'mdi:creation', color: '#fde047', desc: 'The Great Globular Cluster in Hercules. Contains 300,000 stars 25,100 light-years away.' },
38
+ { name: 'M57 Ring', type: 'Nebula', mag: 8.8, az: 50, alt: 58, icon: 'mdi:creation', color: '#67e8f9', desc: 'Planetary nebula in Lyra. Ring of gas ejected by a white dwarf.' },
39
+ { name: 'M81 Bode', type: 'Galaxy', mag: 6.9, az: 340, alt: 55, icon: 'mdi:creation', color: '#c4b5fd', desc: 'Spiral galaxy in Ursa Major. Interacting gravitationally with M82.' },
40
+ { name: 'Pluto', type: 'Dwarf Planet', mag: 14.3, az: 195, alt: 22, icon: 'mdi:circle-small', color: '#cbd5e1', desc: 'The most famous dwarf planet. Requires a 250mm or larger telescope and dark skies.' },
41
+ ],
21
42
  };
22
43
 
23
44
  const faq: DeepSpaceScopeLocaleContent['faq'] = [
@@ -18,6 +18,27 @@ const ui: DeepSpaceScopeUI = {
18
18
  deepSpaceLabel: 'Espacio Profundo',
19
19
  magnitudeLabel: 'Magnitud',
20
20
  coordinatesLabel: 'Coordenadas',
21
+ closeLabel: 'Cerrar',
22
+ altitudeLabel: 'Altitud',
23
+ defaultObjDesc: 'Un objeto del espacio profundo. Magnitud',
24
+ bortleClassPrefix: 'Clase',
25
+ deepSpaceObjects: [
26
+ { name: 'Venus', type: 'Planeta', mag: -4.5, az: 270, alt: 30, icon: 'mdi:circle', color: '#fef08a', desc: 'El planeta más brillante del cielo nocturno. Visible a plena luz del día.' },
27
+ { name: 'Júpiter', type: 'Planeta', mag: -2.5, az: 180, alt: 40, icon: 'mdi:circle', color: '#fef9c3', desc: 'El gigante del sistema solar. Con binoculares se pueden ver sus cuatro lunas galileanas.' },
28
+ { name: 'Saturno', type: 'Planeta', mag: 0.8, az: 220, alt: 35, icon: 'mdi:circle', color: '#fefce8', desc: 'Sus anillos son visibles con un telescopio de 60mm a 50 aumentos.' },
29
+ { name: 'Marte', type: 'Planeta', mag: 1.5, az: 150, alt: 25, icon: 'mdi:circle', color: '#f87171', desc: 'El planeta rojo. Varía de magnitud -2.9 en oposición a +1.8 en conjunción.' },
30
+ { name: 'Sirio', type: 'Estrella', mag: -1.46, az: 145, alt: 50, icon: 'mdi:star-four-points', color: '#bfdbfe', desc: 'La estrella más brillante del cielo nocturno. Está a solo 8.6 años-luz.' },
31
+ { name: 'Canopus', type: 'Estrella', mag: -0.74, az: 200, alt: 20, icon: 'mdi:star-four-points', color: '#fef9c3', desc: 'La segunda estrella más brillante, usada para navegar en el hemisferio sur.' },
32
+ { name: 'Arcturus', type: 'Estrella', mag: -0.05, az: 60, alt: 55, icon: 'mdi:star-four-points', color: '#fdba74', desc: 'Gigante naranja en la constelación del Boyero. A 36 años-luz de la Tierra.' },
33
+ { name: 'Vega', type: 'Estrella', mag: 0.03, az: 40, alt: 70, icon: 'mdi:star-four-points', color: '#dbeafe', desc: 'Vértice del Triángulo de Verano. La estrella de referencia para magnitud 0.' },
34
+ { name: 'M42 Orión', type: 'Nebulosa', mag: 4.0, az: 140, alt: 45, icon: 'mdi:creation', color: '#a5b4fc', desc: 'La gran nebulosa de Orión, a 1344 años-luz. Vivero de estrellas jóvenes.' },
35
+ { name: 'M45 Pléyades', type: 'Cúmulo', mag: 1.6, az: 100, alt: 60, icon: 'mdi:creation', color: '#93c5fd', desc: 'Las Siete Hermanas. A 444 años-luz, el cúmulo abierto más famoso del cielo.' },
36
+ { name: 'M31 Andrómeda', type: 'Galaxia', mag: 3.4, az: 30, alt: 50, icon: 'mdi:creation', color: '#d8b4fe', desc: 'La galaxia vecina más grande. A 2.5 millones de años-luz, visible a simple vista en cielos oscuros.' },
37
+ { name: 'M13 Hércules', type: 'Cúmulo', mag: 5.8, az: 80, alt: 65, icon: 'mdi:creation', color: '#fde047', desc: 'El gran cúmulo globular de Hércules. Contiene 300.000 estrellas a 25.100 años-luz.' },
38
+ { name: 'M57 Anillo', type: 'Nebulosa', mag: 8.8, az: 50, alt: 58, icon: 'mdi:creation', color: '#67e8f9', desc: 'Nebulosa planetaria en Lyra. Anillo de gas expulsado por una enana blanca.' },
39
+ { name: 'M81 Bode', type: 'Galaxia', mag: 6.9, az: 340, alt: 55, icon: 'mdi:creation', color: '#c4b5fd', desc: 'Galaxia espiral en la Osa Mayor. Interactuando gravitatoriamente con M82.' },
40
+ { name: 'Plutón', type: 'Planeta Enano', mag: 14.3, az: 195, alt: 22, icon: 'mdi:circle-small', color: '#cbd5e1', desc: 'El planeta enano más famoso. Requiere un telescopio de 250mm o más y cielos oscuros.' },
41
+ ],
21
42
  };
22
43
 
23
44
  const faq: DeepSpaceScopeLocaleContent['faq'] = [
@@ -18,6 +18,27 @@ const ui: DeepSpaceScopeUI = {
18
18
  deepSpaceLabel: 'Espace Profond',
19
19
  magnitudeLabel: 'Magnitude',
20
20
  coordinatesLabel: 'Coordonnées',
21
+ closeLabel: 'Fermer',
22
+ altitudeLabel: 'Altitude',
23
+ defaultObjDesc: 'Un objet fascinant de l\'espace profond. Magnitude',
24
+ bortleClassPrefix: 'Classe',
25
+ deepSpaceObjects: [
26
+ { name: 'Vénus', type: 'Planète', mag: -4.5, az: 270, alt: 30, icon: 'mdi:circle', color: '#fef08a', desc: 'La planète la plus brillante du ciel nocturne. Visible en plein jour.' },
27
+ { name: 'Jupiter', type: 'Planète', mag: -2.5, az: 180, alt: 40, icon: 'mdi:circle', color: '#fef9c3', desc: 'Le géant du système solaire. Ses quatre lunes galiléennes sont visibles avec des jumelles.' },
28
+ { name: 'Saturne', type: 'Planète', mag: 0.8, az: 220, alt: 35, icon: 'mdi:circle', color: '#fefce8', desc: 'Ses anneaux sont visibles avec un télescope de 60mm à un grossissement de 50x.' },
29
+ { name: 'Mars', type: 'Planète', mag: 1.5, az: 150, alt: 25, icon: 'mdi:circle', color: '#f87171', desc: 'La planète rouge. Varie de la magnitude -2.9 en opposition à +1.8 en conjonction.' },
30
+ { name: 'Sirius', type: 'Étoile', mag: -1.46, az: 145, alt: 50, icon: 'mdi:star-four-points', color: '#bfdbfe', desc: 'L\'étoile la plus brillante du ciel nocturne. Située à seulement 8,6 années-lumière.' },
31
+ { name: 'Canope', type: 'Étoile', mag: -0.74, az: 200, alt: 20, icon: 'mdi:star-four-points', color: '#fef9c3', desc: 'La deuxième étoile la plus brillante, utilisée pour la navigation dans l\'hémisphère sud.' },
32
+ { name: 'Arcturus', type: 'Étoile', mag: -0.05, az: 60, alt: 55, icon: 'mdi:star-four-points', color: '#fdba74', desc: 'Géante orange dans la constellation du Bouvier. À 36 années-lumière de la Terre.' },
33
+ { name: 'Véga', type: 'Étoile', mag: 0.03, az: 40, alt: 70, icon: 'mdi:star-four-points', color: '#dbeafe', desc: 'Sommet du Triangle d\'Été. L\'étoile de référence pour la magnitude 0.' },
34
+ { name: 'M42 Orion', type: 'Nébuleuse', mag: 4.0, az: 140, alt: 45, icon: 'mdi:creation', color: '#a5b4fc', desc: 'La grande nébuleuse d\'Orion, à 1344 années-lumière. Une pouponnière d\'étoiles jeunes.' },
35
+ { name: 'M45 Pléiades', type: 'Amas', mag: 1.6, az: 100, alt: 60, icon: 'mdi:creation', color: '#93c5fd', desc: 'Les Sept Sœurs. À 444 années-lumière, l\'amas ouvert le plus célèbre du ciel.' },
36
+ { name: 'M31 Andromède', type: 'Galaxie', mag: 3.4, az: 30, alt: 50, icon: 'mdi:creation', color: '#d8b4fe', desc: 'La plus grande galaxie voisine. À 2,5 millions d\'années-lumière, visible à l\'œil nu sous un ciel sombre.' },
37
+ { name: 'M13 Hercule', type: 'Amas', mag: 5.8, az: 80, alt: 65, icon: 'mdi:creation', color: '#fde047', desc: 'Le grand amas globulaire d\'Hercule. Contiene 300 000 étoiles à 25 100 années-lumière.' },
38
+ { name: 'M57 Anneau', type: 'Nébuleuse', mag: 8.8, az: 50, alt: 58, icon: 'mdi:creation', color: '#67e8f9', desc: 'Nébuleuse planétaire dans la Lyre. Anneau de gaz expulsé par une naine blanche.' },
39
+ { name: 'M81 Bode', type: 'Galaxie', mag: 6.9, az: 340, alt: 55, icon: 'mdi:creation', color: '#c4b5fd', desc: 'Galaxie spirale dans la Grande Ourse. Interagissant gravitationnellement avec M82.' },
40
+ { name: 'Pluton', type: 'Planète naine', mag: 14.3, az: 195, alt: 22, icon: 'mdi:circle-small', color: '#cbd5e1', desc: 'La planète naine la plus célèbre. Nécessite un télescope de 250mm ou plus et un ciel sombre.' },
41
+ ],
21
42
  };
22
43
 
23
44
  const faq: DeepSpaceScopeLocaleContent['faq'] = [
@@ -3,8 +3,19 @@ import DeepSpaceScopeComponent from './component.astro';
3
3
  import DeepSpaceScopeSEO from './seo.astro';
4
4
  import DeepSpaceScopeBibliography from './bibliography.astro';
5
5
 
6
+ export interface DeepSpaceObject {
7
+ name: string;
8
+ type: string;
9
+ mag: number;
10
+ az: number;
11
+ alt: number;
12
+ color: string;
13
+ icon: string;
14
+ }
15
+
6
16
  export interface DeepSpaceScopeUI {
7
- [key: string]: string;
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ [key: string]: any;
8
19
  toolTitle: string;
9
20
  apertureLabel: string;
10
21
  bortleLabel: string;
@@ -17,6 +28,11 @@ export interface DeepSpaceScopeUI {
17
28
  deepSpaceLabel: string;
18
29
  magnitudeLabel: string;
19
30
  coordinatesLabel: string;
31
+ closeLabel: string;
32
+ altitudeLabel: string;
33
+ defaultObjDesc: string;
34
+ bortleClassPrefix: string;
35
+ deepSpaceObjects: DeepSpaceObject[];
20
36
  }
21
37
 
22
38
  export type DeepSpaceScopeLocaleContent = ToolLocaleContent<DeepSpaceScopeUI>;
@@ -22,20 +22,4 @@ export function apertureSliderToMm(sliderValue: number): number {
22
22
  return Math.round(50 + (sliderValue / 100) * 350);
23
23
  }
24
24
 
25
- export const DEEP_SPACE_OBJECTS: DeepSpaceObject[] = [
26
- { name: 'Venus', type: 'Planeta', mag: -4.5, az: 270, alt: 30, icon: 'mdi:circle', color: '#fef08a', desc: 'El planeta más brillante del cielo nocturno. Visible a plena luz del día.' },
27
- { name: 'Júpiter', type: 'Planeta', mag: -2.5, az: 180, alt: 40, icon: 'mdi:circle', color: '#fef9c3', desc: 'El gigante del sistema solar. Con binoculares se pueden ver sus cuatro lunas galileanas.' },
28
- { name: 'Saturno', type: 'Planeta', mag: 0.8, az: 220, alt: 35, icon: 'mdi:circle', color: '#fefce8', desc: 'Sus anillos son visibles con un telescopio de 60mm a 50 aumentos.' },
29
- { name: 'Marte', type: 'Planeta', mag: 1.5, az: 150, alt: 25, icon: 'mdi:circle', color: '#f87171', desc: 'El planeta rojo. Varía de magnitud -2.9 en oposición a +1.8 en conjunción.' },
30
- { name: 'Sirio', type: 'Estrella', mag: -1.46, az: 145, alt: 50, icon: 'mdi:star-four-points', color: '#bfdbfe', desc: 'La estrella más brillante del cielo nocturno. Está a solo 8.6 años-luz.' },
31
- { name: 'Canopus', type: 'Estrella', mag: -0.74, az: 200, alt: 20, icon: 'mdi:star-four-points', color: '#fef9c3', desc: 'La segunda estrella más brillante, usada para navegar en el hemisferio sur.' },
32
- { name: 'Arcturus', type: 'Estrella', mag: -0.05, az: 60, alt: 55, icon: 'mdi:star-four-points', color: '#fdba74', desc: 'Gigante naranja en la constelación del Boyero. A 36 años-luz de la Tierra.' },
33
- { name: 'Vega', type: 'Estrella', mag: 0.03, az: 40, alt: 70, icon: 'mdi:star-four-points', color: '#dbeafe', desc: 'Vértice del Triángulo de Verano. La estrella de referencia para magnitud 0.' },
34
- { name: 'M42 Orión', type: 'Nebulosa', mag: 4.0, az: 140, alt: 45, icon: 'mdi:creation', color: '#a5b4fc', desc: 'La gran nebulosa de Orión, a 1344 años-luz. Vivero de estrellas jóvenes.' },
35
- { name: 'M45 Pléyades', type: 'Cúmulo', mag: 1.6, az: 100, alt: 60, icon: 'mdi:creation', color: '#93c5fd', desc: 'Las Siete Hermanas. A 444 años-luz, el cúmulo abierto más famoso del cielo.' },
36
- { name: 'M31 Andrómeda', type: 'Galaxia', mag: 3.4, az: 30, alt: 50, icon: 'mdi:creation', color: '#d8b4fe', desc: 'La galaxia vecina más grande. A 2.5 millones de años-luz, visible a simple vista en cielos oscuros.' },
37
- { name: 'M13 Hércules', type: 'Cúmulo', mag: 5.8, az: 80, alt: 65, icon: 'mdi:creation', color: '#fde047', desc: 'El gran cúmulo globular de Hércules. Contiene 300.000 estrellas a 25.100 años-luz.' },
38
- { name: 'M57 Anillo', type: 'Nebulosa', mag: 8.8, az: 50, alt: 58, icon: 'mdi:creation', color: '#67e8f9', desc: 'Nebulosa planetaria en Lyra. Anillo de gas expulsado por una enana blanca.' },
39
- { name: 'M81 Bode', type: 'Galaxia', mag: 6.9, az: 340, alt: 55, icon: 'mdi:creation', color: '#c4b5fd', desc: 'Galaxia espiral en la Osa Mayor. Interactuando gravitatoriamente con M82.' },
40
- { name: 'Plutón', type: 'Planeta Enano', mag: 14.3, az: 195, alt: 22, icon: 'mdi:circle-small', color: '#cbd5e1', desc: 'El planeta enano más famoso. Requiere un telescopio de 250mm o más y cielos oscuros.' },
41
- ];
25
+ export const DEEP_SPACE_OBJECTS: DeepSpaceObject[] = [];
@@ -105,10 +105,16 @@ const { ui } = Astro.props;
105
105
  </div>
106
106
  </div>
107
107
 
108
+ <script define:vars={{ ui }} is:inline>
109
+ window.__starCalcUI = ui;
110
+ </script>
111
+
108
112
  <script>
109
113
  import { calculateExposureTime } from './logic';
110
114
  import type { SensorCropFactor } from './logic';
111
115
 
116
+ const uiData = window.__starCalcUI;
117
+
112
118
  class StarCalculatorApp {
113
119
  mode = 'classic';
114
120
  focalLengthInput: HTMLInputElement;
@@ -228,12 +234,12 @@ const { ui } = Astro.props;
228
234
  this.starPreview.style.width = `${trailLength + 4}px`;
229
235
  this.starPreview.style.borderRadius = '2px';
230
236
  this.starPreview.classList.add('is-trail');
231
- if (info) info.textContent = 'Trazo de estrella visible';
237
+ if (info) info.textContent = uiData.trailStars;
232
238
  } else {
233
239
  this.starPreview.style.width = '4px';
234
240
  this.starPreview.style.borderRadius = '50%';
235
241
  this.starPreview.classList.remove('is-trail');
236
- if (info) info.textContent = 'Estrellas como puntos';
242
+ if (info) info.textContent = uiData.pointStars;
237
243
  }
238
244
  }
239
245
  }
@@ -1,16 +1,17 @@
1
1
  ---
2
2
  import type { TelescopeResolutionUI } from './index';
3
- import type { KnownLocale } from '../../types';
4
-
5
3
  interface Props {
6
4
  ui: TelescopeResolutionUI;
7
- locale?: KnownLocale;
8
5
  }
9
6
 
10
7
  const { ui } = Astro.props;
11
8
  ---
12
9
 
13
- <div class="tscope-wrapper">
10
+ <script define:vars={{ ui }} is:inline>
11
+ window.__telescopeUI = ui;
12
+ </script>
13
+
14
+ <div class="tscope-wrapper" id="tscope-root">
14
15
  <div class="tscope-grid">
15
16
  <div class="tscope-controls">
16
17
  <div class="tscope-control-group">
@@ -40,12 +41,7 @@ const { ui } = Astro.props;
40
41
  <div class="tscope-select-wrapper">
41
42
  <select id="preset-selector" class="tscope-select">
42
43
  <option value="">{ui.presetsPlaceholder}</option>
43
- <option value="70">70mm (Refractor - Iniciación)</option>
44
- <option value="114">114mm (4.5") Newtonian</option>
45
- <option value="150">150mm (6") Dobson</option>
46
- <option value="200">200mm (8") Dobson</option>
47
- <option value="254">254mm (10") Dobson</option>
48
- <option value="304">304mm (12") Profesional</option>
44
+ {ui.presets.map((preset: { value: string; label: string }) => <option value={preset.value}>{preset.label}</option>)}
49
45
  </select>
50
46
  <svg class="tscope-select-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
51
47
  <polyline points="6 9 12 15 18 9"></polyline>
@@ -70,6 +66,11 @@ const { ui } = Astro.props;
70
66
  </div>
71
67
  </div>
72
68
 
69
+ <div class="tscope-seeing-alert" id="seeing-alert">
70
+ <span id="seeing-alert-prefix">{ui.seeingAlertPrefix}</span>
71
+ <span id="seeing-alert-suffix">{ui.seeingAlertSuffix}</span>
72
+ </div>
73
+
73
74
  <div class="tscope-comp-grid">
74
75
  <div class="tscope-comp-card">
75
76
  <h4 class="tscope-comp-title">{ui.rayleighLabel}</h4>
@@ -81,10 +82,6 @@ const { ui } = Astro.props;
81
82
  </div>
82
83
  </div>
83
84
 
84
- <div id="seeing-alert" class="tscope-seeing-alert">
85
- {ui.seeingAlertPrefix} (1.0") {ui.seeingAlertSuffix} (0.77").
86
- </div>
87
-
88
85
  <div class="tscope-visualization">
89
86
  <label class="tscope-vis-label">{ui.simLabel}</label>
90
87
  <div class="tscope-sim-container">
@@ -102,6 +99,17 @@ const { ui } = Astro.props;
102
99
  <script>
103
100
  import { calculateResolution, inchesToMm, mmToInches } from './logic';
104
101
 
102
+ const seeingAlertPrefix = document.getElementById('seeing-alert-prefix');
103
+ const seeingValueDisplay = document.getElementById('seeing-value');
104
+
105
+ function updateSeeingAlert() {
106
+ if (seeingAlertPrefix && seeingValueDisplay) {
107
+ const seeingVal = seeingValueDisplay.textContent;
108
+ const originalPrefix = seeingAlertPrefix.textContent || '';
109
+ seeingAlertPrefix.textContent = `${originalPrefix} (${seeingVal}")`;
110
+ }
111
+ }
112
+
105
113
  class ResolutionApp {
106
114
  apertureInput: HTMLInputElement;
107
115
  unitSelector: HTMLSelectElement;
@@ -111,10 +119,9 @@ const { ui } = Astro.props;
111
119
  rayleighDisplay: HTMLElement;
112
120
  maxMagDisplay: HTMLElement;
113
121
  seeingDisplay: HTMLElement;
114
- seeingAlert: HTMLElement;
115
122
  star1: HTMLElement;
116
123
  star2: HTMLElement;
117
- stepBtns: NodeListOf<HTMLButtonElement>;
124
+ stepBtns: NodeListOf<HTMLButtonElement> | undefined;
118
125
 
119
126
  constructor() {
120
127
  this.apertureInput = document.getElementById('aperture-input') as HTMLInputElement;
@@ -125,7 +132,6 @@ const { ui } = Astro.props;
125
132
  this.rayleighDisplay = document.getElementById('rayleigh-result') as HTMLElement;
126
133
  this.maxMagDisplay = document.getElementById('max-mag-result') as HTMLElement;
127
134
  this.seeingDisplay = document.getElementById('seeing-value') as HTMLElement;
128
- this.seeingAlert = document.getElementById('seeing-alert') as HTMLElement;
129
135
  this.star1 = document.getElementById('star-1') as HTMLElement;
130
136
  this.star2 = document.getElementById('star-2') as HTMLElement;
131
137
  this.stepBtns = document.querySelectorAll('.tscope-step-btn');
@@ -171,6 +177,7 @@ const { ui } = Astro.props;
171
177
  });
172
178
  this.seeingInput.addEventListener('input', () => {
173
179
  this.seeingDisplay.textContent = this.seeingInput.value;
180
+ updateSeeingAlert();
174
181
  this.calculate();
175
182
  });
176
183
  this.calculate();
@@ -188,13 +195,6 @@ const { ui } = Astro.props;
188
195
  this.rayleighDisplay.textContent = result.rayleigh.toFixed(2);
189
196
  this.maxMagDisplay.textContent = Math.round(result.maxMagnification).toString();
190
197
 
191
- if (result.seeingLimited) {
192
- this.seeingAlert.classList.add('visible');
193
- this.seeingAlert.textContent = `Atmosfera limitada: El seeing de hoy (${seeing}") impedirá que veas el potencial de tu telescopio (${result.dawes.toFixed(2)}").`;
194
- } else {
195
- this.seeingAlert.classList.remove('visible');
196
- }
197
-
198
198
  this.updateSimulation(result.dawes);
199
199
  }
200
200
 
@@ -217,6 +217,7 @@ const { ui } = Astro.props;
217
217
  }
218
218
 
219
219
  new ResolutionApp();
220
+ updateSeeingAlert();
220
221
  </script>
221
222
 
222
223
  <style>
@@ -463,11 +464,10 @@ const { ui } = Astro.props;
463
464
  font-size: 0.85rem;
464
465
  color: var(--text-muted);
465
466
  line-height: 1.6;
466
- display: none;
467
+ display: block;
467
468
  }
468
469
 
469
470
  .tscope-seeing-alert.visible {
470
- display: block;
471
471
  animation: tscope-slide-in 0.4s ease-out;
472
472
  }
473
473
 
@@ -18,10 +18,18 @@ const ui: TelescopeResolutionUI = {
18
18
  arcsecUnit: 'arcseconds',
19
19
  rayleighLabel: 'Rayleigh Limit',
20
20
  maxMagLabel: 'Max. Useful Magnification',
21
- seeingAlertPrefix: 'Atmosphere limited: Today\'s seeing',
22
- seeingAlertSuffix: 'will prevent you from seeing your telescope\'s full potential',
21
+ seeingAlertPrefix: "Atmosphere limited: Today's seeing",
22
+ seeingAlertSuffix: "will prevent you from seeing your telescope's full potential",
23
23
  simLabel: 'Simulation: Binary Stars',
24
24
  simExplanation: 'Dawes separates point stars; Rayleigh defines planetary details.',
25
+ presets: [
26
+ { value: '70', label: '70mm (Beginner Refractor)' },
27
+ { value: '114', label: '114mm (4.5") Newtonian' },
28
+ { value: '150', label: '150mm (6") Dobsonian' },
29
+ { value: '200', label: '200mm (8") Dobsonian' },
30
+ { value: '254', label: '254mm (10") Dobsonian' },
31
+ { value: '304', label: '304mm (12") Professional' },
32
+ ],
25
33
  };
26
34
 
27
35
  const faq: TelescopeResolutionLocaleContent['faq'] = [
@@ -22,6 +22,14 @@ const ui: TelescopeResolutionUI = {
22
22
  seeingAlertSuffix: 'impedirá que veas el potencial de tu telescopio',
23
23
  simLabel: 'Simulación: Estrellas Binarias',
24
24
  simExplanation: 'Dawes separa estrellas puntuales; Rayleigh define detalles planetarios.',
25
+ presets: [
26
+ { value: '70', label: '70mm (Refractor - Iniciación)' },
27
+ { value: '114', label: '114mm (4.5") Newtonian' },
28
+ { value: '150', label: '150mm (6") Dobson' },
29
+ { value: '200', label: '200mm (8") Dobson' },
30
+ { value: '254', label: '254mm (10") Dobson' },
31
+ { value: '304', label: '304mm (12") Profesional' },
32
+ ],
25
33
  };
26
34
 
27
35
  const faq: TelescopeResolutionLocaleContent['faq'] = [
@@ -18,10 +18,18 @@ const ui: TelescopeResolutionUI = {
18
18
  arcsecUnit: 'arcsecondes',
19
19
  rayleighLabel: 'Limite de Rayleigh',
20
20
  maxMagLabel: 'Grossissement Max. Utile',
21
- seeingAlertPrefix: 'Atmosphère limitée: Le seeing d\'aujourd\'hui',
21
+ seeingAlertPrefix: "Atmosphère limitée: Le seeing d'aujourd'hui",
22
22
  seeingAlertSuffix: 'vous empêchera de voir le potentiel complet de votre télescope',
23
23
  simLabel: 'Simulation: Étoiles Binaires',
24
24
  simExplanation: 'Dawes sépare les étoiles ponctuelles; Rayleigh définit les détails planétaires.',
25
+ presets: [
26
+ { value: '70', label: '70mm (Réfracteur - Débutant)' },
27
+ { value: '114', label: '114mm (4,5") Newtonien' },
28
+ { value: '150', label: '150mm (6") Dobsonien' },
29
+ { value: '200', label: '200mm (8") Dobsonien' },
30
+ { value: '254', label: '254mm (10") Dobsonien' },
31
+ { value: '304', label: '304mm (12") Professionnel' },
32
+ ],
25
33
  };
26
34
 
27
35
  const faq: TelescopeResolutionLocaleContent['faq'] = [
@@ -4,7 +4,7 @@ import TelescopeResolutionSEO from './seo.astro';
4
4
  import TelescopeResolutionBibliography from './bibliography.astro';
5
5
 
6
6
  export interface TelescopeResolutionUI {
7
- [key: string]: string;
7
+ [key: string]: string | Array<{ value: string; label: string }>;
8
8
  toolTitle: string;
9
9
  apertureLabel: string;
10
10
  unitLabel: string;
@@ -21,6 +21,7 @@ export interface TelescopeResolutionUI {
21
21
  seeingAlertSuffix: string;
22
22
  simLabel: string;
23
23
  simExplanation: string;
24
+ presets: Array<{ value: string; label: string }>;
24
25
  }
25
26
 
26
27
  export type TelescopeResolutionLocaleContent = ToolLocaleContent<TelescopeResolutionUI>;
package/src/types.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { SEOSection } from '@jjlmoya/utils-shared';
2
- import type { WithContext, Thing } from 'schema-dts';
3
2
 
4
3
  export type { SEOSection };
5
4
 
@@ -23,7 +22,8 @@ export interface HowToStep {
23
22
  text: string;
24
23
  }
25
24
 
26
- export interface ToolLocaleContent<TUI extends Record<string, string> = Record<string, string>> {
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ export interface ToolLocaleContent<TUI extends Record<string, any> = Record<string, any>> {
27
27
  slug: string;
28
28
  title: string;
29
29
  description: string;
@@ -34,7 +34,8 @@ export interface ToolLocaleContent<TUI extends Record<string, string> = Record<s
34
34
  bibliography: BibliographyEntry[];
35
35
  bibliographyTitle: string;
36
36
  howTo: HowToStep[];
37
- schemas: WithContext<Thing>[];
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ schemas: any[];
38
39
  }
39
40
 
40
41
  export interface CategoryLocaleContent {
@@ -48,7 +49,8 @@ export type LocaleLoader<T> = () => Promise<T>;
48
49
 
49
50
  export type LocaleMap<T> = Partial<Record<KnownLocale, LocaleLoader<T>>>;
50
51
 
51
- export interface AstronomyToolEntry<TUI extends Record<string, string> = Record<string, string>> {
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ export interface AstronomyToolEntry<TUI extends Record<string, any> = Record<string, any>> {
52
54
  id: string;
53
55
  icons: {
54
56
  bg: string;