@roxyapi/ui 0.1.2 → 0.2.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/AGENTS.md +6 -0
- package/README.md +327 -14
- package/THEMING.md +24 -7
- package/dist/cdn/components/ashtakavarga-grid.js +349 -0
- package/dist/cdn/components/ashtakavarga-grid.js.map +7 -0
- package/dist/cdn/components/biorhythm-chart.js +15 -22
- package/dist/cdn/components/biorhythm-chart.js.map +3 -3
- package/dist/cdn/components/choghadiya-grid.js +239 -0
- package/dist/cdn/components/choghadiya-grid.js.map +7 -0
- package/dist/cdn/components/compatibility-card.js +36 -34
- package/dist/cdn/components/compatibility-card.js.map +4 -4
- package/dist/cdn/components/dasha-timeline.js +35 -39
- package/dist/cdn/components/dasha-timeline.js.map +4 -4
- package/dist/cdn/components/data.js +9 -9
- package/dist/cdn/components/data.js.map +4 -4
- package/dist/cdn/components/divisional-chart.js +279 -0
- package/dist/cdn/components/divisional-chart.js.map +7 -0
- package/dist/cdn/components/dosha-card.js +49 -49
- package/dist/cdn/components/dosha-card.js.map +3 -3
- package/dist/cdn/components/endpoint-form.js +47 -28
- package/dist/cdn/components/endpoint-form.js.map +4 -4
- package/dist/cdn/components/guna-milan.js +66 -24
- package/dist/cdn/components/guna-milan.js.map +4 -4
- package/dist/cdn/components/hexagram.js +26 -26
- package/dist/cdn/components/hexagram.js.map +3 -3
- package/dist/cdn/components/horoscope-card.js +47 -40
- package/dist/cdn/components/horoscope-card.js.map +4 -4
- package/dist/cdn/components/kp-planets-table.js +10 -10
- package/dist/cdn/components/kp-planets-table.js.map +4 -4
- package/dist/cdn/components/location-search.js +6 -6
- package/dist/cdn/components/location-search.js.map +3 -3
- package/dist/cdn/components/moon-phase.js +18 -18
- package/dist/cdn/components/moon-phase.js.map +4 -4
- package/dist/cdn/components/natal-chart.js +240 -24
- package/dist/cdn/components/natal-chart.js.map +4 -4
- package/dist/cdn/components/numerology-card.js +40 -31
- package/dist/cdn/components/numerology-card.js.map +4 -4
- package/dist/cdn/components/panchang-table.js +30 -30
- package/dist/cdn/components/panchang-table.js.map +4 -4
- package/dist/cdn/components/shadbala-table.js +312 -0
- package/dist/cdn/components/shadbala-table.js.map +7 -0
- package/dist/cdn/components/synastry-chart.js +129 -39
- package/dist/cdn/components/synastry-chart.js.map +4 -4
- package/dist/cdn/components/tarot-card.js +49 -20
- package/dist/cdn/components/tarot-card.js.map +3 -3
- package/dist/cdn/components/tarot-spread.js +43 -27
- package/dist/cdn/components/tarot-spread.js.map +3 -3
- package/dist/cdn/components/transits-table.js +391 -0
- package/dist/cdn/components/transits-table.js.map +7 -0
- package/dist/cdn/components/vedic-kundli.js +63 -27
- package/dist/cdn/components/vedic-kundli.js.map +4 -4
- package/dist/cdn/components/yoga-list.js +334 -0
- package/dist/cdn/components/yoga-list.js.map +7 -0
- package/dist/cdn/roxy-ui.js +2104 -544
- package/dist/cdn/roxy-ui.js.map +4 -4
- package/dist/components/ashtakavarga-grid.d.ts +26 -0
- package/dist/components/ashtakavarga-grid.d.ts.map +1 -0
- package/dist/components/ashtakavarga-grid.js +457 -0
- package/dist/components/ashtakavarga-grid.js.map +7 -0
- package/dist/components/biorhythm-chart.d.ts +2 -46
- package/dist/components/biorhythm-chart.d.ts.map +1 -1
- package/dist/components/biorhythm-chart.js +24 -23
- package/dist/components/biorhythm-chart.js.map +2 -2
- package/dist/components/choghadiya-grid.d.ts +19 -0
- package/dist/components/choghadiya-grid.d.ts.map +1 -0
- package/dist/components/choghadiya-grid.js +304 -0
- package/dist/components/choghadiya-grid.js.map +7 -0
- package/dist/components/compatibility-card.d.ts +2 -27
- package/dist/components/compatibility-card.d.ts.map +1 -1
- package/dist/components/compatibility-card.js +50 -29
- package/dist/components/compatibility-card.js.map +3 -3
- package/dist/components/dasha-timeline.d.ts +2 -31
- package/dist/components/dasha-timeline.d.ts.map +1 -1
- package/dist/components/dasha-timeline.js +32 -30
- package/dist/components/dasha-timeline.js.map +3 -3
- package/dist/components/data.d.ts +11 -7
- package/dist/components/data.d.ts.map +1 -1
- package/dist/components/data.js +16 -6
- package/dist/components/data.js.map +3 -3
- package/dist/components/divisional-chart.d.ts +20 -0
- package/dist/components/divisional-chart.d.ts.map +1 -0
- package/dist/components/divisional-chart.js +471 -0
- package/dist/components/divisional-chart.js.map +7 -0
- package/dist/components/dosha-card.d.ts +2 -16
- package/dist/components/dosha-card.d.ts.map +1 -1
- package/dist/components/dosha-card.js +45 -43
- package/dist/components/dosha-card.js.map +2 -2
- package/dist/components/endpoint-form.d.ts +2 -0
- package/dist/components/endpoint-form.d.ts.map +1 -1
- package/dist/components/endpoint-form.js +71 -11
- package/dist/components/endpoint-form.js.map +3 -3
- package/dist/components/guna-milan.d.ts +2 -20
- package/dist/components/guna-milan.d.ts.map +1 -1
- package/dist/components/guna-milan.js +79 -20
- package/dist/components/guna-milan.js.map +4 -4
- package/dist/components/hexagram.d.ts +3 -27
- package/dist/components/hexagram.d.ts.map +1 -1
- package/dist/components/hexagram.js +48 -15
- package/dist/components/hexagram.js.map +2 -2
- package/dist/components/horoscope-card.d.ts +2 -20
- package/dist/components/horoscope-card.d.ts.map +1 -1
- package/dist/components/horoscope-card.js +54 -18
- package/dist/components/horoscope-card.js.map +3 -3
- package/dist/components/kp-planets-table.d.ts +2 -21
- package/dist/components/kp-planets-table.d.ts.map +1 -1
- package/dist/components/kp-planets-table.js +10 -4
- package/dist/components/kp-planets-table.js.map +3 -3
- package/dist/components/location-search.d.ts +5 -14
- package/dist/components/location-search.d.ts.map +1 -1
- package/dist/components/location-search.js +45 -5
- package/dist/components/location-search.js.map +2 -2
- package/dist/components/moon-phase.d.ts +4 -21
- package/dist/components/moon-phase.d.ts.map +1 -1
- package/dist/components/moon-phase.js +34 -4
- package/dist/components/moon-phase.js.map +3 -3
- package/dist/components/natal-chart.d.ts +9 -43
- package/dist/components/natal-chart.d.ts.map +1 -1
- package/dist/components/natal-chart.js +346 -79
- package/dist/components/natal-chart.js.map +3 -3
- package/dist/components/numerology-card.d.ts +5 -37
- package/dist/components/numerology-card.d.ts.map +1 -1
- package/dist/components/numerology-card.js +58 -30
- package/dist/components/numerology-card.js.map +3 -3
- package/dist/components/panchang-table.d.ts +3 -62
- package/dist/components/panchang-table.d.ts.map +1 -1
- package/dist/components/panchang-table.js +62 -32
- package/dist/components/panchang-table.js.map +3 -3
- package/dist/components/shadbala-table.d.ts +18 -0
- package/dist/components/shadbala-table.d.ts.map +1 -0
- package/dist/components/shadbala-table.js +400 -0
- package/dist/components/shadbala-table.js.map +7 -0
- package/dist/components/synastry-chart.d.ts +9 -28
- package/dist/components/synastry-chart.d.ts.map +1 -1
- package/dist/components/synastry-chart.js +201 -56
- package/dist/components/synastry-chart.js.map +3 -3
- package/dist/components/tarot-card.d.ts +5 -29
- package/dist/components/tarot-card.d.ts.map +1 -1
- package/dist/components/tarot-card.js +59 -20
- package/dist/components/tarot-card.js.map +2 -2
- package/dist/components/tarot-spread.d.ts +2 -24
- package/dist/components/tarot-spread.d.ts.map +1 -1
- package/dist/components/tarot-spread.js +39 -13
- package/dist/components/tarot-spread.js.map +2 -2
- package/dist/components/transits-table.d.ts +21 -0
- package/dist/components/transits-table.d.ts.map +1 -0
- package/dist/components/transits-table.js +515 -0
- package/dist/components/transits-table.js.map +7 -0
- package/dist/components/vedic-kundli.d.ts +5 -28
- package/dist/components/vedic-kundli.d.ts.map +1 -1
- package/dist/components/vedic-kundli.js +147 -83
- package/dist/components/vedic-kundli.js.map +3 -3
- package/dist/components/yoga-list.d.ts +29 -0
- package/dist/components/yoga-list.d.ts.map +1 -0
- package/dist/components/yoga-list.js +389 -0
- package/dist/components/yoga-list.js.map +7 -0
- package/dist/index.cjs +3693 -1180
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3709 -1196
- package/dist/index.js.map +4 -4
- package/dist/manifest.d.ts +43 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.json +7 -2
- package/dist/styles/tokens.css +73 -1
- package/dist/tokens/index.d.ts +6 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types.gen.d.ts +27811 -0
- package/dist/types/types.gen.d.ts.map +1 -0
- package/dist/utils/debounce.d.ts +9 -1
- package/dist/utils/debounce.d.ts.map +1 -1
- package/dist/utils/format.d.ts +29 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/kundli-render.d.ts +63 -0
- package/dist/utils/kundli-render.d.ts.map +1 -0
- package/dist/utils/string.d.ts +14 -0
- package/dist/utils/string.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +7 -1
- package/src/components/ashtakavarga-grid.ts +354 -0
- package/src/components/biorhythm-chart.ts +39 -84
- package/src/components/choghadiya-grid.ts +185 -0
- package/src/components/compatibility-card.ts +85 -52
- package/src/components/dasha-timeline.ts +55 -73
- package/src/components/data.ts +28 -16
- package/src/components/divisional-chart.ts +214 -0
- package/src/components/dosha-card.ts +72 -68
- package/src/components/endpoint-form.ts +80 -18
- package/src/components/guna-milan.ts +87 -47
- package/src/components/hexagram.ts +53 -43
- package/src/components/horoscope-card.ts +59 -43
- package/src/components/kp-planets-table.ts +8 -27
- package/src/components/location-search.ts +47 -23
- package/src/components/moon-phase.ts +28 -25
- package/src/components/natal-chart.ts +364 -110
- package/src/components/numerology-card.ts +86 -84
- package/src/components/panchang-table.ts +40 -78
- package/src/components/shadbala-table.ts +286 -0
- package/src/components/synastry-chart.ts +213 -97
- package/src/components/tarot-card.ts +76 -62
- package/src/components/tarot-spread.ts +72 -45
- package/src/components/transits-table.ts +350 -0
- package/src/components/vedic-kundli.ts +59 -173
- package/src/components/yoga-list.ts +328 -0
- package/src/index.ts +18 -26
- package/src/manifest.ts +340 -0
- package/src/styles/tokens.css +73 -1
- package/src/tokens/index.ts +14 -0
- package/src/types/types.gen.ts +3 -3
- package/src/utils/debounce.ts +23 -4
- package/src/utils/format.ts +75 -0
- package/src/utils/kundli-render.ts +197 -0
- package/src/utils/string.ts +23 -0
- package/src/version.ts +2 -0
- package/dist/utils/motion.d.ts +0 -13
- package/dist/utils/motion.d.ts.map +0 -1
- package/src/utils/motion.ts +0 -18
|
@@ -1,28 +1,18 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
import { SIGN_GLYPH } from '../tokens/index.js';
|
|
4
|
+
import type {
|
|
5
|
+
GetDailyHoroscopeResponse,
|
|
6
|
+
GetMonthlyHoroscopeResponse,
|
|
7
|
+
GetWeeklyHoroscopeResponse,
|
|
8
|
+
} from '../types/index.js';
|
|
4
9
|
import { baseStyles } from '../utils/base-styles.js';
|
|
10
|
+
import { capitalize } from '../utils/string.js';
|
|
5
11
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
love?: string;
|
|
11
|
-
career?: string;
|
|
12
|
-
health?: string;
|
|
13
|
-
finance?: string;
|
|
14
|
-
advice?: string;
|
|
15
|
-
luckyNumber?: number | string;
|
|
16
|
-
luckyColor?: string;
|
|
17
|
-
compatibleSigns?: string[];
|
|
18
|
-
moonSign?: string;
|
|
19
|
-
moonPhase?: string;
|
|
20
|
-
energyRating?: number;
|
|
21
|
-
week?: string;
|
|
22
|
-
month?: string;
|
|
23
|
-
luckyDays?: string[];
|
|
24
|
-
luckyNumbers?: number[];
|
|
25
|
-
}
|
|
12
|
+
type HoroscopeData =
|
|
13
|
+
| GetDailyHoroscopeResponse
|
|
14
|
+
| GetWeeklyHoroscopeResponse
|
|
15
|
+
| GetMonthlyHoroscopeResponse;
|
|
26
16
|
|
|
27
17
|
/**
|
|
28
18
|
* Daily, weekly, or monthly horoscope card. Pass `data` from
|
|
@@ -134,6 +124,13 @@ export class RoxyHoroscopeCard extends LitElement {
|
|
|
134
124
|
font-weight: var(--roxy-weight-bold, 600);
|
|
135
125
|
}
|
|
136
126
|
|
|
127
|
+
.compat-wrap {
|
|
128
|
+
width: 100%;
|
|
129
|
+
display: flex;
|
|
130
|
+
align-items: center;
|
|
131
|
+
flex-wrap: wrap;
|
|
132
|
+
gap: var(--roxy-space-xs, 0.25rem);
|
|
133
|
+
}
|
|
137
134
|
.compat {
|
|
138
135
|
display: flex;
|
|
139
136
|
flex-wrap: wrap;
|
|
@@ -163,8 +160,15 @@ export class RoxyHoroscopeCard extends LitElement {
|
|
|
163
160
|
|
|
164
161
|
const sign = d.sign ?? '';
|
|
165
162
|
const glyph = sign ? (SIGN_GLYPH[capitalize(sign)] ?? '') : '';
|
|
166
|
-
const energy =
|
|
167
|
-
|
|
163
|
+
const energy =
|
|
164
|
+
'energyRating' in d && typeof d.energyRating === 'number'
|
|
165
|
+
? d.energyRating
|
|
166
|
+
: null;
|
|
167
|
+
const dateLabel =
|
|
168
|
+
('date' in d && d.date) ||
|
|
169
|
+
('week' in d && d.week) ||
|
|
170
|
+
('month' in d && d.month) ||
|
|
171
|
+
'';
|
|
168
172
|
|
|
169
173
|
return html`<article
|
|
170
174
|
class="card"
|
|
@@ -224,7 +228,7 @@ export class RoxyHoroscopeCard extends LitElement {
|
|
|
224
228
|
: nothing
|
|
225
229
|
}
|
|
226
230
|
${
|
|
227
|
-
d.advice
|
|
231
|
+
'advice' in d && d.advice
|
|
228
232
|
? html`<div class="section">
|
|
229
233
|
<h3>Advice</h3>
|
|
230
234
|
<p>${d.advice}</p>
|
|
@@ -233,57 +237,69 @@ export class RoxyHoroscopeCard extends LitElement {
|
|
|
233
237
|
}
|
|
234
238
|
</div>
|
|
235
239
|
|
|
236
|
-
${
|
|
237
|
-
|
|
238
|
-
|
|
240
|
+
${(() => {
|
|
241
|
+
const luckyNumber =
|
|
242
|
+
'luckyNumber' in d && d.luckyNumber !== undefined
|
|
243
|
+
? d.luckyNumber
|
|
244
|
+
: undefined;
|
|
245
|
+
const luckyColor =
|
|
246
|
+
'luckyColor' in d && d.luckyColor ? d.luckyColor : '';
|
|
247
|
+
const luckyNumbers =
|
|
248
|
+
'luckyNumbers' in d && d.luckyNumbers ? d.luckyNumbers : [];
|
|
249
|
+
const luckyDays = 'luckyDays' in d && d.luckyDays ? d.luckyDays : [];
|
|
250
|
+
const compatibleSigns = d.compatibleSigns ?? [];
|
|
251
|
+
if (
|
|
252
|
+
luckyNumber === undefined &&
|
|
253
|
+
!luckyColor &&
|
|
254
|
+
luckyNumbers.length === 0 &&
|
|
255
|
+
luckyDays.length === 0 &&
|
|
256
|
+
compatibleSigns.length === 0
|
|
257
|
+
)
|
|
258
|
+
return nothing;
|
|
259
|
+
return html`<div class="lucky">
|
|
239
260
|
${
|
|
240
|
-
|
|
241
|
-
? html`<span>Lucky number <strong>${
|
|
261
|
+
luckyNumber !== undefined
|
|
262
|
+
? html`<span>Lucky number <strong>${luckyNumber}</strong></span>`
|
|
242
263
|
: nothing
|
|
243
264
|
}
|
|
244
265
|
${
|
|
245
|
-
|
|
246
|
-
? html`<span>Lucky color <strong>${
|
|
266
|
+
luckyColor
|
|
267
|
+
? html`<span>Lucky color <strong>${luckyColor}</strong></span>`
|
|
247
268
|
: nothing
|
|
248
269
|
}
|
|
249
270
|
${
|
|
250
|
-
|
|
271
|
+
luckyNumbers.length
|
|
251
272
|
? html`<span
|
|
252
273
|
>Lucky numbers
|
|
253
|
-
<strong>${
|
|
274
|
+
<strong>${luckyNumbers.join(', ')}</strong></span
|
|
254
275
|
>`
|
|
255
276
|
: nothing
|
|
256
277
|
}
|
|
257
278
|
${
|
|
258
|
-
|
|
279
|
+
luckyDays.length
|
|
259
280
|
? html`<span
|
|
260
|
-
>Lucky days <strong>${
|
|
281
|
+
>Lucky days <strong>${luckyDays.join(', ')}</strong></span
|
|
261
282
|
>`
|
|
262
283
|
: nothing
|
|
263
284
|
}
|
|
264
285
|
${
|
|
265
|
-
|
|
286
|
+
compatibleSigns.length
|
|
266
287
|
? html`<span class="compat-wrap">
|
|
267
288
|
Best with
|
|
268
289
|
<span class="compat"
|
|
269
|
-
>${
|
|
290
|
+
>${compatibleSigns.map(
|
|
270
291
|
(s) => html`<span>${s}</span>`,
|
|
271
292
|
)}</span
|
|
272
293
|
>
|
|
273
294
|
</span>`
|
|
274
295
|
: nothing
|
|
275
296
|
}
|
|
276
|
-
</div
|
|
277
|
-
|
|
278
|
-
}
|
|
297
|
+
</div>`;
|
|
298
|
+
})()}
|
|
279
299
|
</article>`;
|
|
280
300
|
}
|
|
281
301
|
}
|
|
282
302
|
|
|
283
|
-
function capitalize(s: string): string {
|
|
284
|
-
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
285
|
-
}
|
|
286
|
-
|
|
287
303
|
declare global {
|
|
288
304
|
interface HTMLElementTagNameMap {
|
|
289
305
|
'roxy-horoscope-card': RoxyHoroscopeCard;
|
|
@@ -1,27 +1,8 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import type { KpPlanetsResponse } from '../types/index.js';
|
|
3
4
|
import { baseStyles } from '../utils/base-styles.js';
|
|
4
|
-
|
|
5
|
-
interface KpPlanet {
|
|
6
|
-
planet?: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
sign?: string;
|
|
9
|
-
signLord?: string;
|
|
10
|
-
nakshatra?: string;
|
|
11
|
-
nakshatraLord?: string;
|
|
12
|
-
pada?: number;
|
|
13
|
-
starLord?: string;
|
|
14
|
-
subLord?: string;
|
|
15
|
-
subSubLord?: string;
|
|
16
|
-
kpNumber?: number;
|
|
17
|
-
retrograde?: boolean;
|
|
18
|
-
longitude?: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface KpData {
|
|
22
|
-
ayanamsa?: number | string;
|
|
23
|
-
planets?: KpPlanet[];
|
|
24
|
-
}
|
|
5
|
+
import { formatNumber } from '../utils/format.js';
|
|
25
6
|
|
|
26
7
|
/**
|
|
27
8
|
* KP planets table with sub-lord and sub-sub-lord columns. Renders
|
|
@@ -86,7 +67,7 @@ export class RoxyKpPlanetsTable extends LitElement {
|
|
|
86
67
|
color: var(--roxy-fg, #0a0a0a);
|
|
87
68
|
}
|
|
88
69
|
.retro {
|
|
89
|
-
color: var(--roxy-warning, #
|
|
70
|
+
color: var(--roxy-warning-fg, #9a3412);
|
|
90
71
|
font-size: var(--roxy-text-xs, 0.75rem);
|
|
91
72
|
margin-left: 4px;
|
|
92
73
|
}
|
|
@@ -94,7 +75,7 @@ export class RoxyKpPlanetsTable extends LitElement {
|
|
|
94
75
|
];
|
|
95
76
|
|
|
96
77
|
@property({ attribute: false })
|
|
97
|
-
data:
|
|
78
|
+
data: KpPlanetsResponse | null = null;
|
|
98
79
|
|
|
99
80
|
render() {
|
|
100
81
|
if (!this.data)
|
|
@@ -109,8 +90,8 @@ export class RoxyKpPlanetsTable extends LitElement {
|
|
|
109
90
|
<header class="head">
|
|
110
91
|
<h2 class="title">KP planets</h2>
|
|
111
92
|
${
|
|
112
|
-
this.data.ayanamsa
|
|
113
|
-
? html`<span class="ayanamsa">Ayanamsa: ${this.data.ayanamsa}
|
|
93
|
+
typeof this.data.ayanamsa === 'number'
|
|
94
|
+
? html`<span class="ayanamsa">Ayanamsa: ${formatNumber(this.data.ayanamsa, 2)}°</span>`
|
|
114
95
|
: nothing
|
|
115
96
|
}
|
|
116
97
|
</header>
|
|
@@ -131,13 +112,13 @@ export class RoxyKpPlanetsTable extends LitElement {
|
|
|
131
112
|
${planets.map(
|
|
132
113
|
(p) => html`<tr>
|
|
133
114
|
<td class="planet">
|
|
134
|
-
${p.planet
|
|
115
|
+
${p.planet}
|
|
135
116
|
${p.retrograde ? html`<span class="retro">R</span>` : nothing}
|
|
136
117
|
</td>
|
|
137
118
|
<td>${p.sign ?? ''}</td>
|
|
138
119
|
<td>${p.signLord ?? ''}</td>
|
|
139
120
|
<td>${p.nakshatra ?? ''}</td>
|
|
140
|
-
<td>${p.
|
|
121
|
+
<td>${p.nakshatraLord ?? ''}</td>
|
|
141
122
|
<td>${p.subLord ?? ''}</td>
|
|
142
123
|
<td>${p.subSubLord ?? ''}</td>
|
|
143
124
|
<td>${p.kpNumber ?? ''}</td>
|
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
3
|
+
import type { SearchCitiesResponse } from '../types/index.js';
|
|
3
4
|
import { baseStyles } from '../utils/base-styles.js';
|
|
4
5
|
import { debounce } from '../utils/debounce.js';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
city: string;
|
|
8
|
-
province?: string;
|
|
9
|
-
country: string;
|
|
10
|
-
iso2?: string;
|
|
11
|
-
latitude: number;
|
|
12
|
-
longitude: number;
|
|
13
|
-
timezone: string;
|
|
14
|
-
utcOffset: number;
|
|
15
|
-
population?: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface CitySearchResponse {
|
|
19
|
-
total?: number;
|
|
20
|
-
cities?: CityResult[];
|
|
21
|
-
}
|
|
7
|
+
type CityResult = SearchCitiesResponse['cities'][number];
|
|
22
8
|
|
|
23
9
|
/**
|
|
24
10
|
* Stateful location search input. Calls /location/search and emits
|
|
25
11
|
* `roxy-location-select` CustomEvent with the chosen city. Required for any
|
|
26
12
|
* chart endpoint.
|
|
27
13
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* state with Lit reactive properties and using direct fetch to RoxyAPI.
|
|
14
|
+
* Behavior: 300ms input debounce, click-outside dismiss, keyboard navigation
|
|
15
|
+
* with arrow keys / Enter / Escape, AbortController on stale requests.
|
|
31
16
|
*
|
|
32
17
|
* Attributes:
|
|
33
18
|
* api-key optional. Direct call to roxyapi.com when set.
|
|
@@ -175,6 +160,8 @@ export class RoxyLocationSearch extends LitElement {
|
|
|
175
160
|
private highlight = -1;
|
|
176
161
|
|
|
177
162
|
private clickOutsideHandler?: (e: MouseEvent) => void;
|
|
163
|
+
private abortController?: AbortController;
|
|
164
|
+
private secretKeyWarned = false;
|
|
178
165
|
private debouncedFetch = debounce((q: string) => {
|
|
179
166
|
void this.fetchResults(q);
|
|
180
167
|
}, 300);
|
|
@@ -194,9 +181,41 @@ export class RoxyLocationSearch extends LitElement {
|
|
|
194
181
|
if (this.clickOutsideHandler) {
|
|
195
182
|
document.removeEventListener('mousedown', this.clickOutsideHandler);
|
|
196
183
|
}
|
|
184
|
+
this.debouncedFetch.cancel();
|
|
185
|
+
if (this.abortController) {
|
|
186
|
+
this.abortController.abort();
|
|
187
|
+
this.abortController = undefined;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private warnIfSecretKey() {
|
|
192
|
+
if (this.secretKeyWarned) return;
|
|
193
|
+
if (!this.apiKey) return;
|
|
194
|
+
// Browser-safe publishable keys carry the `pk_` prefix and a server-side
|
|
195
|
+
// origin allowlist. Anything else (a raw secret key, UUID-style token)
|
|
196
|
+
// must not ship to the browser.
|
|
197
|
+
if (this.apiKey.startsWith('pk_')) return;
|
|
198
|
+
this.secretKeyWarned = true;
|
|
199
|
+
const message =
|
|
200
|
+
'Possible secret key in client-side <roxy-location-search>; use a `pk_` publishable key with origin allowlist instead.';
|
|
201
|
+
// eslint-disable-next-line no-console
|
|
202
|
+
console.warn(message);
|
|
203
|
+
this.dispatchEvent(
|
|
204
|
+
new CustomEvent('roxy-validation-error', {
|
|
205
|
+
detail: { reason: 'possible-secret-key', message },
|
|
206
|
+
bubbles: true,
|
|
207
|
+
composed: true,
|
|
208
|
+
}),
|
|
209
|
+
);
|
|
197
210
|
}
|
|
198
211
|
|
|
199
212
|
private async fetchResults(q: string) {
|
|
213
|
+
this.warnIfSecretKey();
|
|
214
|
+
// Abort any in-flight request so a stale response cannot overwrite a
|
|
215
|
+
// fresher one (debounced typing) or land after disconnect.
|
|
216
|
+
if (this.abortController) this.abortController.abort();
|
|
217
|
+
const controller = new AbortController();
|
|
218
|
+
this.abortController = controller;
|
|
200
219
|
this.isLoading = true;
|
|
201
220
|
try {
|
|
202
221
|
const url = new URL(this.endpoint);
|
|
@@ -207,17 +226,22 @@ export class RoxyLocationSearch extends LitElement {
|
|
|
207
226
|
};
|
|
208
227
|
if (this.apiKey) headers['X-API-Key'] = this.apiKey;
|
|
209
228
|
if (this.publishableKey) headers['X-API-Key'] = this.publishableKey;
|
|
210
|
-
const res = await fetch(url, { headers });
|
|
229
|
+
const res = await fetch(url, { headers, signal: controller.signal });
|
|
211
230
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
212
|
-
const json = (await res.json()) as
|
|
231
|
+
const json = (await res.json()) as SearchCitiesResponse;
|
|
232
|
+
if (controller.signal.aborted) return;
|
|
213
233
|
this.results = json.cities ?? [];
|
|
214
234
|
this.isOpen = this.results.length > 0;
|
|
215
235
|
this.highlight = this.results.length > 0 ? 0 : -1;
|
|
216
|
-
} catch (
|
|
236
|
+
} catch (err) {
|
|
237
|
+
if ((err as { name?: string })?.name === 'AbortError') return;
|
|
217
238
|
this.results = [];
|
|
218
239
|
this.isOpen = false;
|
|
219
240
|
} finally {
|
|
220
|
-
this.
|
|
241
|
+
if (this.abortController === controller) {
|
|
242
|
+
this.abortController = undefined;
|
|
243
|
+
}
|
|
244
|
+
if (!controller.signal.aborted) this.isLoading = false;
|
|
221
245
|
}
|
|
222
246
|
}
|
|
223
247
|
|
|
@@ -1,27 +1,21 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
import { MOON_PHASE_EMOJI } from '../tokens/index.js';
|
|
4
|
+
import type {
|
|
5
|
+
GetCurrentMoonPhaseResponse,
|
|
6
|
+
GetMoonCalendarResponse,
|
|
7
|
+
GetUpcomingMoonPhasesResponse,
|
|
8
|
+
} from '../types/index.js';
|
|
4
9
|
import { baseStyles } from '../utils/base-styles.js';
|
|
10
|
+
import { formatNumber } from '../utils/format.js';
|
|
5
11
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
distance?: number;
|
|
14
|
-
meaning?: {
|
|
15
|
-
name?: string;
|
|
16
|
-
symbol?: string;
|
|
17
|
-
description?: string;
|
|
18
|
-
keywords?: string[];
|
|
19
|
-
};
|
|
20
|
-
month?: string;
|
|
21
|
-
year?: number;
|
|
22
|
-
phases?: Array<MoonPhaseData>;
|
|
23
|
-
upcoming?: Array<MoonPhaseData>;
|
|
24
|
-
}
|
|
12
|
+
type MoonPhaseData =
|
|
13
|
+
| GetCurrentMoonPhaseResponse
|
|
14
|
+
| GetUpcomingMoonPhasesResponse
|
|
15
|
+
| GetMoonCalendarResponse;
|
|
16
|
+
type MoonListEntry =
|
|
17
|
+
| GetUpcomingMoonPhasesResponse['phases'][number]
|
|
18
|
+
| GetMoonCalendarResponse['calendar'][number];
|
|
25
19
|
|
|
26
20
|
/**
|
|
27
21
|
* Moon phase card. Renders /astrology/moon-phase/{current,upcoming,calendar/...}.
|
|
@@ -125,22 +119,26 @@ export class RoxyMoonPhase extends LitElement {
|
|
|
125
119
|
const d = this.data;
|
|
126
120
|
if (!d)
|
|
127
121
|
return html`<div class="roxy-empty" role="status">No moon phase data</div>`;
|
|
128
|
-
const list
|
|
122
|
+
const list: MoonListEntry[] =
|
|
123
|
+
'phases' in d ? d.phases : 'calendar' in d ? d.calendar : [];
|
|
129
124
|
if (this.mode !== 'current' && list.length > 0) {
|
|
125
|
+
const month = 'month' in d ? d.month : undefined;
|
|
126
|
+
const year = 'year' in d ? d.year : undefined;
|
|
130
127
|
return html`<article
|
|
131
128
|
class="card"
|
|
132
129
|
aria-label="Moon phase calendar"
|
|
133
130
|
>
|
|
134
|
-
<h2 class="label">${
|
|
131
|
+
<h2 class="label">${month ?? 'Moon phases'} ${year ?? ''}</h2>
|
|
135
132
|
<div class="list" role="list">
|
|
136
133
|
${list.map((phase) => this.renderListItem(phase))}
|
|
137
134
|
</div>
|
|
138
135
|
</article>`;
|
|
139
136
|
}
|
|
137
|
+
if (!('phase' in d)) return nothing;
|
|
140
138
|
return this.renderSingle(d);
|
|
141
139
|
}
|
|
142
140
|
|
|
143
|
-
private renderSingle(d:
|
|
141
|
+
private renderSingle(d: GetCurrentMoonPhaseResponse) {
|
|
144
142
|
const emoji = phaseEmoji(d.phase);
|
|
145
143
|
return html`<article class="card" aria-label="Current moon phase">
|
|
146
144
|
<div class="hero">
|
|
@@ -155,7 +153,7 @@ export class RoxyMoonPhase extends LitElement {
|
|
|
155
153
|
typeof d.illumination === 'number'
|
|
156
154
|
? html`<div>
|
|
157
155
|
<span>Illumination</span>
|
|
158
|
-
<strong>${(d.illumination
|
|
156
|
+
<strong>${formatIllumination(d.illumination)}</strong>
|
|
159
157
|
</div>`
|
|
160
158
|
: nothing
|
|
161
159
|
}
|
|
@@ -163,7 +161,7 @@ export class RoxyMoonPhase extends LitElement {
|
|
|
163
161
|
typeof d.age === 'number'
|
|
164
162
|
? html`<div>
|
|
165
163
|
<span>Age</span>
|
|
166
|
-
<strong>${d.age
|
|
164
|
+
<strong>${formatNumber(d.age, 1)} days</strong>
|
|
167
165
|
</div>`
|
|
168
166
|
: nothing
|
|
169
167
|
}
|
|
@@ -199,7 +197,7 @@ export class RoxyMoonPhase extends LitElement {
|
|
|
199
197
|
</article>`;
|
|
200
198
|
}
|
|
201
199
|
|
|
202
|
-
private renderListItem(p:
|
|
200
|
+
private renderListItem(p: MoonListEntry) {
|
|
203
201
|
const emoji = phaseEmoji(p.phase);
|
|
204
202
|
return html`<div class="list-item" role="listitem">
|
|
205
203
|
<span aria-hidden="true">${emoji}</span>
|
|
@@ -214,6 +212,11 @@ function phaseEmoji(phase: string | undefined): string {
|
|
|
214
212
|
return MOON_PHASE_EMOJI[phase.toLowerCase()] ?? '🌙';
|
|
215
213
|
}
|
|
216
214
|
|
|
215
|
+
function formatIllumination(v: number): string {
|
|
216
|
+
const pct = v <= 1 ? v * 100 : v;
|
|
217
|
+
return `${Math.round(pct)}%`;
|
|
218
|
+
}
|
|
219
|
+
|
|
217
220
|
declare global {
|
|
218
221
|
interface HTMLElementTagNameMap {
|
|
219
222
|
'roxy-moon-phase': RoxyMoonPhase;
|