@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,58 +1,16 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing, svg } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import type {
|
|
4
|
+
GetCriticalDaysResponse,
|
|
5
|
+
GetDailyBiorhythmResponse,
|
|
6
|
+
GetForecastResponse,
|
|
7
|
+
} from '../types/index.js';
|
|
3
8
|
import { baseStyles } from '../utils/base-styles.js';
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
cycles?: Record<string, number>;
|
|
10
|
-
energyRating?: number;
|
|
11
|
-
overallPhase?: string;
|
|
12
|
-
interpretation?: string;
|
|
13
|
-
advice?: string;
|
|
14
|
-
criticalAlerts?: string[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface BiorhythmDay {
|
|
18
|
-
date?: string;
|
|
19
|
-
cycles?: Record<string, number>;
|
|
20
|
-
energyRating?: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface BiorhythmForecast {
|
|
24
|
-
birthDate?: string;
|
|
25
|
-
startDate?: string;
|
|
26
|
-
endDate?: string;
|
|
27
|
-
totalDays?: number;
|
|
28
|
-
summary?: {
|
|
29
|
-
bestDay?: string;
|
|
30
|
-
worstDay?: string;
|
|
31
|
-
criticalDayCount?: number;
|
|
32
|
-
averageEnergy?: number;
|
|
33
|
-
periodAdvice?: string;
|
|
34
|
-
};
|
|
35
|
-
days?: BiorhythmDay[];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface CriticalDay {
|
|
39
|
-
date?: string;
|
|
40
|
-
cycle?: string;
|
|
41
|
-
period?: string;
|
|
42
|
-
direction?: string;
|
|
43
|
-
severity?: string;
|
|
44
|
-
advisory?: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface CriticalDays {
|
|
48
|
-
birthDate?: string;
|
|
49
|
-
startDate?: string;
|
|
50
|
-
endDate?: string;
|
|
51
|
-
totalCriticalDays?: number;
|
|
52
|
-
criticalDays?: CriticalDay[];
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
type BiorhythmData = DailyBiorhythm & BiorhythmForecast & CriticalDays;
|
|
10
|
+
type BiorhythmData =
|
|
11
|
+
| GetDailyBiorhythmResponse
|
|
12
|
+
| GetForecastResponse
|
|
13
|
+
| GetCriticalDaysResponse;
|
|
56
14
|
|
|
57
15
|
const CYCLE_COLOR: Record<string, string> = {
|
|
58
16
|
physical: '#dc2626',
|
|
@@ -164,18 +122,22 @@ export class RoxyBiorhythmChart extends LitElement {
|
|
|
164
122
|
if (!d)
|
|
165
123
|
return html`<div class="roxy-empty" role="status">No biorhythm data</div>`;
|
|
166
124
|
|
|
167
|
-
if (this.mode === 'critical-days' && d
|
|
168
|
-
return this.renderCritical(d);
|
|
125
|
+
if (this.mode === 'critical-days' && 'criticalDays' in d) {
|
|
126
|
+
return this.renderCritical(d as GetCriticalDaysResponse);
|
|
169
127
|
}
|
|
170
|
-
if (this.mode === 'forecast' && d
|
|
171
|
-
return this.renderForecast(d);
|
|
128
|
+
if (this.mode === 'forecast' && 'days' in d) {
|
|
129
|
+
return this.renderForecast(d as GetForecastResponse);
|
|
172
130
|
}
|
|
173
|
-
return this.renderDaily(d);
|
|
131
|
+
return this.renderDaily(d as GetDailyBiorhythmResponse);
|
|
174
132
|
}
|
|
175
133
|
|
|
176
|
-
private renderDaily(d:
|
|
177
|
-
const
|
|
178
|
-
const entries = Object.entries(
|
|
134
|
+
private renderDaily(d: GetDailyBiorhythmResponse) {
|
|
135
|
+
const raw = d.quickRead ?? {};
|
|
136
|
+
const entries = Object.entries(raw).map(([cycle, value]) => {
|
|
137
|
+
const v = typeof value === 'number' ? value : 0;
|
|
138
|
+
const normalized = Math.abs(v) > 1 ? v / 100 : v;
|
|
139
|
+
return [cycle, normalized] as const;
|
|
140
|
+
});
|
|
179
141
|
return html`<section class="wrap" aria-label="Daily biorhythm">
|
|
180
142
|
<header class="head">
|
|
181
143
|
<h2 class="title">Biorhythm</h2>
|
|
@@ -186,8 +148,7 @@ export class RoxyBiorhythmChart extends LitElement {
|
|
|
186
148
|
}
|
|
187
149
|
</header>
|
|
188
150
|
<div class="bars" role="list">
|
|
189
|
-
${entries.map(([cycle,
|
|
190
|
-
const v = typeof value === 'number' ? value : 0;
|
|
151
|
+
${entries.map(([cycle, v]) => {
|
|
191
152
|
const pct = ((v + 1) / 2) * 100; // -1..1 -> 0..100
|
|
192
153
|
const color = CYCLE_COLOR[cycle] ?? 'var(--roxy-accent, #f59e0b)';
|
|
193
154
|
return html`<div class="bar" role="listitem">
|
|
@@ -198,36 +159,32 @@ export class RoxyBiorhythmChart extends LitElement {
|
|
|
198
159
|
style="width: ${pct}%; background: ${color}"
|
|
199
160
|
></span>
|
|
200
161
|
</span>
|
|
201
|
-
<span class="value">${(v * 100)
|
|
162
|
+
<span class="value">${Math.round(v * 100)}%</span>
|
|
202
163
|
</div>`;
|
|
203
164
|
})}
|
|
204
165
|
</div>
|
|
205
|
-
${d.
|
|
166
|
+
${d.dailyMessage ? html`<p class="advice">${d.dailyMessage}</p>` : nothing}
|
|
206
167
|
${d.advice ? html`<p class="advice">${d.advice}</p>` : nothing}
|
|
207
|
-
${
|
|
208
|
-
d.criticalAlerts?.length
|
|
209
|
-
? html`<div>
|
|
210
|
-
${d.criticalAlerts.map((a) => html`<p class="alert">${a}</p>`)}
|
|
211
|
-
</div>`
|
|
212
|
-
: nothing
|
|
213
|
-
}
|
|
214
168
|
</section>`;
|
|
215
169
|
}
|
|
216
170
|
|
|
217
|
-
private renderForecast(d:
|
|
171
|
+
private renderForecast(d: GetForecastResponse) {
|
|
218
172
|
const days = d.days ?? [];
|
|
219
173
|
if (days.length === 0)
|
|
220
174
|
return html`<div class="roxy-empty" role="status">No forecast</div>`;
|
|
221
175
|
const w = 600;
|
|
222
176
|
const h = 160;
|
|
223
177
|
const xStep = w / Math.max(days.length - 1, 1);
|
|
224
|
-
const
|
|
178
|
+
const cycleKeys = [
|
|
179
|
+
'physical',
|
|
180
|
+
'emotional',
|
|
181
|
+
'intellectual',
|
|
182
|
+
'intuitive',
|
|
183
|
+
] as const;
|
|
225
184
|
return html`<section class="wrap" aria-label="Biorhythm forecast">
|
|
226
185
|
<header class="head">
|
|
227
186
|
<h2 class="title">Forecast</h2>
|
|
228
|
-
<span class="energy"
|
|
229
|
-
>${d.startDate ?? ''} - ${d.endDate ?? ''}</span
|
|
230
|
-
>
|
|
187
|
+
<span class="energy">${d.startDate} - ${d.endDate}</span>
|
|
231
188
|
</header>
|
|
232
189
|
<svg
|
|
233
190
|
viewBox="0 0 ${w} ${h}"
|
|
@@ -243,12 +200,12 @@ export class RoxyBiorhythmChart extends LitElement {
|
|
|
243
200
|
stroke="var(--roxy-border, #e4e4e7)"
|
|
244
201
|
stroke-width="1"
|
|
245
202
|
/>
|
|
246
|
-
${
|
|
203
|
+
${cycleKeys.map((cycle) => {
|
|
247
204
|
const points = days
|
|
248
205
|
.map((day, i) => {
|
|
249
|
-
const v = day
|
|
206
|
+
const v = day[cycle] ?? 0;
|
|
250
207
|
const x = i * xStep;
|
|
251
|
-
const y = h / 2 - v * (h / 2 - 8);
|
|
208
|
+
const y = h / 2 - (v / 100) * (h / 2 - 8);
|
|
252
209
|
return `${x.toFixed(2)},${y.toFixed(2)}`;
|
|
253
210
|
})
|
|
254
211
|
.join(' ');
|
|
@@ -264,18 +221,16 @@ export class RoxyBiorhythmChart extends LitElement {
|
|
|
264
221
|
</section>`;
|
|
265
222
|
}
|
|
266
223
|
|
|
267
|
-
private renderCritical(d:
|
|
224
|
+
private renderCritical(d: GetCriticalDaysResponse) {
|
|
268
225
|
return html`<section class="wrap" aria-label="Critical days">
|
|
269
226
|
<header class="head">
|
|
270
227
|
<h2 class="title">Critical days</h2>
|
|
271
|
-
<span class="energy"
|
|
272
|
-
>${d.totalCriticalDays ?? d.criticalDays?.length ?? 0} total</span
|
|
273
|
-
>
|
|
228
|
+
<span class="energy">${d.totalCriticalDays} total</span>
|
|
274
229
|
</header>
|
|
275
230
|
<div>
|
|
276
|
-
${
|
|
231
|
+
${d.criticalDays.map(
|
|
277
232
|
(day) => html`<span class="crit"
|
|
278
|
-
>${day.date} · ${day.cycle
|
|
233
|
+
>${day.date} · ${day.cycle} ${day.severity}</span
|
|
279
234
|
>`,
|
|
280
235
|
)}
|
|
281
236
|
</div>
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import { PLANET_GLYPH } from '../tokens/index.js';
|
|
4
|
+
import type { GetChoghadiyaResponse } from '../types/index.js';
|
|
5
|
+
import { baseStyles } from '../utils/base-styles.js';
|
|
6
|
+
import { capitalize } from '../utils/string.js';
|
|
7
|
+
|
|
8
|
+
type ChoghadiyaPeriod = GetChoghadiyaResponse['dayChoghadiya'][number];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Format an ISO 8601 datetime string to a short local time (HH:MM).
|
|
12
|
+
* Falls back to the raw string when parsing fails.
|
|
13
|
+
*/
|
|
14
|
+
function fmtTime(iso: string): string {
|
|
15
|
+
try {
|
|
16
|
+
const d = new Date(iso);
|
|
17
|
+
if (Number.isNaN(d.getTime())) return iso;
|
|
18
|
+
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
19
|
+
} catch {
|
|
20
|
+
return iso;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Choghadiya muhurta grid. Accepts a GetChoghadiyaResponse and renders
|
|
26
|
+
* 8 daytime and 8 nighttime muhurta tiles in a two-column responsive layout.
|
|
27
|
+
* Good periods are highlighted in green, Bad periods in red.
|
|
28
|
+
*/
|
|
29
|
+
@customElement('roxy-choghadiya-grid')
|
|
30
|
+
export class RoxyChoghadiyaGrid extends LitElement {
|
|
31
|
+
static styles = [
|
|
32
|
+
baseStyles,
|
|
33
|
+
css`
|
|
34
|
+
.wrap {
|
|
35
|
+
display: grid;
|
|
36
|
+
gap: var(--roxy-space-md, 1rem);
|
|
37
|
+
}
|
|
38
|
+
.header {
|
|
39
|
+
display: grid;
|
|
40
|
+
gap: var(--roxy-space-xs, 0.25rem);
|
|
41
|
+
}
|
|
42
|
+
.title {
|
|
43
|
+
font-size: var(--roxy-text-lg, 1.125rem);
|
|
44
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
45
|
+
margin: 0;
|
|
46
|
+
}
|
|
47
|
+
.subtitle {
|
|
48
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
49
|
+
color: var(--roxy-muted, #71717a);
|
|
50
|
+
margin: 0;
|
|
51
|
+
}
|
|
52
|
+
.cho-grid {
|
|
53
|
+
display: grid;
|
|
54
|
+
grid-template-columns: 1fr;
|
|
55
|
+
gap: var(--roxy-space-md, 1rem);
|
|
56
|
+
}
|
|
57
|
+
@media (min-width: 720px) {
|
|
58
|
+
.cho-grid {
|
|
59
|
+
grid-template-columns: 1fr 1fr;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
.period-col {
|
|
63
|
+
display: grid;
|
|
64
|
+
gap: var(--roxy-space-xs, 0.25rem);
|
|
65
|
+
}
|
|
66
|
+
.period-heading {
|
|
67
|
+
font-size: var(--roxy-text-base, 1rem);
|
|
68
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
69
|
+
margin: 0 0 var(--roxy-space-xs, 0.25rem);
|
|
70
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
71
|
+
}
|
|
72
|
+
.cho-tile {
|
|
73
|
+
display: grid;
|
|
74
|
+
grid-template-columns: 1fr auto;
|
|
75
|
+
align-items: center;
|
|
76
|
+
gap: 0.25em 0.75em;
|
|
77
|
+
padding: 0.55em 0.85em;
|
|
78
|
+
border: 1px solid var(--roxy-border, #e4e4e7);
|
|
79
|
+
border-radius: var(--roxy-radius-md, 8px);
|
|
80
|
+
}
|
|
81
|
+
.cho-tile.good {
|
|
82
|
+
background: color-mix(in srgb, var(--roxy-success, #22c55e) 18%, transparent);
|
|
83
|
+
border-color: color-mix(in srgb, var(--roxy-success, #22c55e) 45%, transparent);
|
|
84
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
85
|
+
}
|
|
86
|
+
.cho-tile.bad {
|
|
87
|
+
background: color-mix(in srgb, var(--roxy-danger, #ef4444) 18%, transparent);
|
|
88
|
+
border-color: color-mix(in srgb, var(--roxy-danger, #ef4444) 45%, transparent);
|
|
89
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
90
|
+
}
|
|
91
|
+
.cho-tile.neutral {
|
|
92
|
+
background: transparent;
|
|
93
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
94
|
+
}
|
|
95
|
+
.tile-name {
|
|
96
|
+
font-size: var(--roxy-text-base, 1rem);
|
|
97
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
98
|
+
grid-column: 1;
|
|
99
|
+
}
|
|
100
|
+
.tile-time {
|
|
101
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
102
|
+
opacity: 0.8;
|
|
103
|
+
white-space: nowrap;
|
|
104
|
+
grid-column: 2;
|
|
105
|
+
grid-row: 1 / 3;
|
|
106
|
+
text-align: right;
|
|
107
|
+
align-self: center;
|
|
108
|
+
}
|
|
109
|
+
.tile-lord {
|
|
110
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
111
|
+
opacity: 0.85;
|
|
112
|
+
grid-column: 1;
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
gap: 0.25em;
|
|
116
|
+
}
|
|
117
|
+
`,
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
@property({ attribute: false })
|
|
121
|
+
data: GetChoghadiyaResponse | null = null;
|
|
122
|
+
|
|
123
|
+
private renderTile(period: ChoghadiyaPeriod) {
|
|
124
|
+
const effectClass =
|
|
125
|
+
period.effect === 'Good'
|
|
126
|
+
? 'good'
|
|
127
|
+
: period.effect === 'Bad'
|
|
128
|
+
? 'bad'
|
|
129
|
+
: 'neutral';
|
|
130
|
+
const lordGlyph = PLANET_GLYPH[capitalize(period.lord)] ?? '';
|
|
131
|
+
const timeRange = `${fmtTime(period.start)} - ${fmtTime(period.end)}`;
|
|
132
|
+
return html`<div class="cho-tile ${effectClass}" role="listitem">
|
|
133
|
+
<span class="tile-name">${period.name}</span>
|
|
134
|
+
<span class="tile-time" aria-label="Time range">${timeRange}</span>
|
|
135
|
+
<span class="tile-lord">
|
|
136
|
+
${lordGlyph ? html`<span aria-hidden="true">${lordGlyph}</span>` : nothing}
|
|
137
|
+
${period.lord}
|
|
138
|
+
</span>
|
|
139
|
+
</div>`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
render() {
|
|
143
|
+
if (!this.data)
|
|
144
|
+
return html`<div class="roxy-empty" role="status">No choghadiya data</div>`;
|
|
145
|
+
|
|
146
|
+
const { date, dayChoghadiya, nightChoghadiya } = this.data;
|
|
147
|
+
|
|
148
|
+
return html`<div class="wrap">
|
|
149
|
+
<div class="header">
|
|
150
|
+
<h2 class="title">Choghadiya</h2>
|
|
151
|
+
${date ? html`<p class="subtitle">${date}</p>` : nothing}
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div class="cho-grid">
|
|
155
|
+
<section class="period-col" aria-label="Day muhurta periods">
|
|
156
|
+
<h3 class="period-heading">Day</h3>
|
|
157
|
+
<div role="list" aria-label="Daytime choghadiya">
|
|
158
|
+
${
|
|
159
|
+
dayChoghadiya && dayChoghadiya.length > 0
|
|
160
|
+
? dayChoghadiya.map((p) => this.renderTile(p))
|
|
161
|
+
: html`<p class="roxy-empty" role="status">No daytime periods</p>`
|
|
162
|
+
}
|
|
163
|
+
</div>
|
|
164
|
+
</section>
|
|
165
|
+
|
|
166
|
+
<section class="period-col" aria-label="Night muhurta periods">
|
|
167
|
+
<h3 class="period-heading">Night</h3>
|
|
168
|
+
<div role="list" aria-label="Nighttime choghadiya">
|
|
169
|
+
${
|
|
170
|
+
nightChoghadiya && nightChoghadiya.length > 0
|
|
171
|
+
? nightChoghadiya.map((p) => this.renderTile(p))
|
|
172
|
+
: html`<p class="roxy-empty" role="status">No nighttime periods</p>`
|
|
173
|
+
}
|
|
174
|
+
</div>
|
|
175
|
+
</section>
|
|
176
|
+
</div>
|
|
177
|
+
</div>`;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
declare global {
|
|
182
|
+
interface HTMLElementTagNameMap {
|
|
183
|
+
'roxy-choghadiya-grid': RoxyChoghadiyaGrid;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -1,26 +1,17 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import type {
|
|
4
|
+
CalculateBioCompatibilityResponse,
|
|
5
|
+
CalculateCompatibilityResponse,
|
|
6
|
+
CalculateNumCompatibilityResponse,
|
|
7
|
+
} from '../types/index.js';
|
|
3
8
|
import { baseStyles } from '../utils/base-styles.js';
|
|
9
|
+
import { formatNumber } from '../utils/format.js';
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
relationshipArchetype?: string;
|
|
10
|
-
advice?: string;
|
|
11
|
-
summary?: string;
|
|
12
|
-
categoryScores?: Record<string, number>;
|
|
13
|
-
categoryBreakdown?: Record<string, number>;
|
|
14
|
-
emotional?: number;
|
|
15
|
-
communication?: number;
|
|
16
|
-
romance?: number;
|
|
17
|
-
strengths?: string[];
|
|
18
|
-
challenges?: string[];
|
|
19
|
-
keyAspects?: string[];
|
|
20
|
-
elementBalance?: Record<string, number>;
|
|
21
|
-
person1?: { name?: string; sign?: string; lifePath?: number };
|
|
22
|
-
person2?: { name?: string; sign?: string; lifePath?: number };
|
|
23
|
-
}
|
|
11
|
+
type CompatibilityData =
|
|
12
|
+
| CalculateCompatibilityResponse
|
|
13
|
+
| CalculateNumCompatibilityResponse
|
|
14
|
+
| CalculateBioCompatibilityResponse;
|
|
24
15
|
|
|
25
16
|
/**
|
|
26
17
|
* Cross-domain compatibility card. Renders /astrology/compatibility-score,
|
|
@@ -94,7 +85,7 @@ export class RoxyCompatibilityCard extends LitElement {
|
|
|
94
85
|
}
|
|
95
86
|
|
|
96
87
|
.archetype {
|
|
97
|
-
color: var(--roxy-
|
|
88
|
+
color: var(--roxy-accent-fg, #b45309);
|
|
98
89
|
font-weight: var(--roxy-weight-bold, 600);
|
|
99
90
|
}
|
|
100
91
|
|
|
@@ -126,23 +117,49 @@ export class RoxyCompatibilityCard extends LitElement {
|
|
|
126
117
|
private getBreakdown(): Record<string, number> {
|
|
127
118
|
const d = this.data;
|
|
128
119
|
if (!d) return {};
|
|
129
|
-
if (d
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return inferred;
|
|
120
|
+
if ('categories' in d && d.categories) {
|
|
121
|
+
const out: Record<string, number> = {};
|
|
122
|
+
for (const [k, v] of Object.entries(d.categories)) {
|
|
123
|
+
if (typeof v === 'number' && Number.isFinite(v)) out[k] = v;
|
|
124
|
+
}
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
return {};
|
|
138
128
|
}
|
|
139
129
|
|
|
140
130
|
render() {
|
|
141
131
|
const d = this.data;
|
|
142
132
|
if (!d)
|
|
143
133
|
return html`<div class="roxy-empty" role="status">No compatibility data</div>`;
|
|
144
|
-
|
|
134
|
+
|
|
135
|
+
const score = d.overallScore;
|
|
145
136
|
const breakdown = this.getBreakdown();
|
|
137
|
+
const rating =
|
|
138
|
+
'rating' in d
|
|
139
|
+
? (d as CalculateNumCompatibilityResponse).rating
|
|
140
|
+
: undefined;
|
|
141
|
+
const archetype =
|
|
142
|
+
'archetype' in d
|
|
143
|
+
? (d as CalculateCompatibilityResponse).archetype
|
|
144
|
+
: undefined;
|
|
145
|
+
const advice =
|
|
146
|
+
'advice' in d
|
|
147
|
+
? (d as CalculateNumCompatibilityResponse).advice
|
|
148
|
+
: undefined;
|
|
149
|
+
const summary =
|
|
150
|
+
'summary' in d
|
|
151
|
+
? (d as CalculateCompatibilityResponse).summary
|
|
152
|
+
: undefined;
|
|
153
|
+
const interpretation =
|
|
154
|
+
'interpretation' in d
|
|
155
|
+
? (d as CalculateCompatibilityResponse).interpretation
|
|
156
|
+
: undefined;
|
|
157
|
+
const strengths = 'strengths' in d ? d.strengths : undefined;
|
|
158
|
+
const challenges = 'challenges' in d ? d.challenges : undefined;
|
|
159
|
+
const keyAspects =
|
|
160
|
+
'keyAspects' in d
|
|
161
|
+
? (d as CalculateCompatibilityResponse).keyAspects
|
|
162
|
+
: undefined;
|
|
146
163
|
|
|
147
164
|
return html`<article
|
|
148
165
|
class="card"
|
|
@@ -153,10 +170,10 @@ export class RoxyCompatibilityCard extends LitElement {
|
|
|
153
170
|
<div>
|
|
154
171
|
${
|
|
155
172
|
typeof score === 'number'
|
|
156
|
-
? html`<div class="score">${score}</div>`
|
|
173
|
+
? html`<div class="score">${formatNumber(score, 0)}</div>`
|
|
157
174
|
: nothing
|
|
158
175
|
}
|
|
159
|
-
${
|
|
176
|
+
${rating ? html`<div class="rating">${rating}</div>` : nothing}
|
|
160
177
|
</div>
|
|
161
178
|
</div>
|
|
162
179
|
|
|
@@ -169,50 +186,42 @@ export class RoxyCompatibilityCard extends LitElement {
|
|
|
169
186
|
<span class="bar"
|
|
170
187
|
><span style="width: ${Math.max(0, Math.min(100, v))}%"></span
|
|
171
188
|
></span>
|
|
172
|
-
<span>${v}</span>
|
|
189
|
+
<span>${formatNumber(v, 0)}</span>
|
|
173
190
|
</div>`,
|
|
174
191
|
)}
|
|
175
192
|
</div>`
|
|
176
193
|
: nothing
|
|
177
194
|
}
|
|
178
195
|
${
|
|
179
|
-
|
|
196
|
+
archetype
|
|
180
197
|
? html`<p>
|
|
181
|
-
<span class="archetype">${
|
|
198
|
+
<span class="archetype">${archetype.label}</span>
|
|
199
|
+
${archetype.description ? html` · ${archetype.description}` : nothing}
|
|
182
200
|
</p>`
|
|
183
201
|
: nothing
|
|
184
202
|
}
|
|
185
|
-
${
|
|
186
|
-
${
|
|
203
|
+
${summary ? html`<p>${summary}</p>` : nothing}
|
|
204
|
+
${interpretation && !summary ? html`<p>${interpretation}</p>` : nothing}
|
|
205
|
+
${advice ? html`<p>${advice}</p>` : nothing}
|
|
187
206
|
${
|
|
188
|
-
(
|
|
207
|
+
(strengths?.length ?? 0) > 0 || (challenges?.length ?? 0) > 0
|
|
189
208
|
? html`<div class="lists">
|
|
190
209
|
${
|
|
191
|
-
|
|
210
|
+
strengths?.length
|
|
192
211
|
? html`<div>
|
|
193
212
|
<h3>Strengths</h3>
|
|
194
213
|
<ul>
|
|
195
|
-
${
|
|
214
|
+
${strengths.map((s) => html`<li>${s}</li>`)}
|
|
196
215
|
</ul>
|
|
197
216
|
</div>`
|
|
198
217
|
: nothing
|
|
199
218
|
}
|
|
200
219
|
${
|
|
201
|
-
|
|
220
|
+
challenges?.length
|
|
202
221
|
? html`<div>
|
|
203
222
|
<h3>Challenges</h3>
|
|
204
223
|
<ul>
|
|
205
|
-
${
|
|
206
|
-
</ul>
|
|
207
|
-
</div>`
|
|
208
|
-
: nothing
|
|
209
|
-
}
|
|
210
|
-
${
|
|
211
|
-
d.keyAspects?.length
|
|
212
|
-
? html`<div>
|
|
213
|
-
<h3>Key aspects</h3>
|
|
214
|
-
<ul>
|
|
215
|
-
${d.keyAspects.map((s) => html`<li>${s}</li>`)}
|
|
224
|
+
${challenges.map((s) => html`<li>${s}</li>`)}
|
|
216
225
|
</ul>
|
|
217
226
|
</div>`
|
|
218
227
|
: nothing
|
|
@@ -220,10 +229,34 @@ export class RoxyCompatibilityCard extends LitElement {
|
|
|
220
229
|
</div>`
|
|
221
230
|
: nothing
|
|
222
231
|
}
|
|
232
|
+
${
|
|
233
|
+
keyAspects?.length
|
|
234
|
+
? html`<div>
|
|
235
|
+
<h3 style="margin: 0 0 0.25rem; font-size: var(--roxy-text-xs); color: var(--roxy-muted); text-transform: uppercase; letter-spacing: 0.06em;">Key aspects</h3>
|
|
236
|
+
<ul style="margin: 0; padding-left: 1rem; font-size: var(--roxy-text-sm);">
|
|
237
|
+
${keyAspects.slice(0, 6).map((a) => html`<li>${formatAspect(a)}</li>`)}
|
|
238
|
+
</ul>
|
|
239
|
+
</div>`
|
|
240
|
+
: nothing
|
|
241
|
+
}
|
|
223
242
|
</article>`;
|
|
224
243
|
}
|
|
225
244
|
}
|
|
226
245
|
|
|
246
|
+
type KeyAspect = CalculateCompatibilityResponse extends {
|
|
247
|
+
keyAspects: Array<infer T>;
|
|
248
|
+
}
|
|
249
|
+
? T
|
|
250
|
+
: never;
|
|
251
|
+
|
|
252
|
+
function formatAspect(a: KeyAspect): string {
|
|
253
|
+
const aspect = a.type.toLowerCase().replace(/_/g, '-');
|
|
254
|
+
const orb =
|
|
255
|
+
typeof a.orb === 'number' ? ` (orb ${formatNumber(a.orb, 1)}°)` : '';
|
|
256
|
+
const head = [a.planet1, aspect, a.planet2].filter(Boolean).join(' ');
|
|
257
|
+
return a.description ? `${head}${orb} · ${a.description}` : `${head}${orb}`;
|
|
258
|
+
}
|
|
259
|
+
|
|
227
260
|
declare global {
|
|
228
261
|
interface HTMLElementTagNameMap {
|
|
229
262
|
'roxy-compatibility-card': RoxyCompatibilityCard;
|