@roxyapi/ui 0.1.2 → 0.1.3
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/README.md +321 -14
- package/THEMING.md +24 -7
- package/dist/cdn/components/biorhythm-chart.js +15 -22
- package/dist/cdn/components/biorhythm-chart.js.map +3 -3
- 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 +6 -6
- package/dist/cdn/components/data.js.map +3 -3
- package/dist/cdn/components/dosha-card.js +13 -13
- package/dist/cdn/components/dosha-card.js.map +2 -2
- package/dist/cdn/components/endpoint-form.js +47 -28
- package/dist/cdn/components/endpoint-form.js.map +3 -3
- package/dist/cdn/components/guna-milan.js +18 -18
- 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 +38 -38
- package/dist/cdn/components/horoscope-card.js.map +3 -3
- 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 +21 -21
- package/dist/cdn/components/moon-phase.js.map +4 -4
- package/dist/cdn/components/natal-chart.js +61 -19
- 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 +3 -3
- package/dist/cdn/components/panchang-table.js +25 -25
- package/dist/cdn/components/panchang-table.js.map +4 -4
- 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/vedic-kundli.js +23 -9
- package/dist/cdn/components/vedic-kundli.js.map +3 -3
- package/dist/cdn/roxy-ui.js +560 -350
- package/dist/cdn/roxy-ui.js.map +4 -4
- 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/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 +6 -0
- package/dist/components/data.d.ts.map +1 -1
- package/dist/components/data.js +9 -1
- package/dist/components/data.js.map +2 -2
- 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 +12 -13
- 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 +66 -8
- package/dist/components/endpoint-form.js.map +2 -2
- 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 +22 -12
- package/dist/components/guna-milan.js.map +3 -3
- package/dist/components/hexagram.d.ts +3 -27
- package/dist/components/hexagram.d.ts.map +1 -1
- package/dist/components/hexagram.js +31 -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 +24 -15
- package/dist/components/horoscope-card.js.map +2 -2
- 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 +3 -11
- 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 +17 -4
- package/dist/components/moon-phase.js.map +3 -3
- package/dist/components/natal-chart.d.ts +7 -43
- package/dist/components/natal-chart.d.ts.map +1 -1
- package/dist/components/natal-chart.js +130 -70
- 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 +54 -28
- package/dist/components/numerology-card.js.map +2 -2
- 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/synastry-chart.d.ts +9 -28
- package/dist/components/synastry-chart.d.ts.map +1 -1
- package/dist/components/synastry-chart.js +178 -38
- 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/vedic-kundli.d.ts +3 -23
- package/dist/components/vedic-kundli.d.ts.map +1 -1
- package/dist/components/vedic-kundli.js +25 -13
- package/dist/components/vedic-kundli.js.map +2 -2
- package/dist/index.cjs +1149 -358
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1149 -358
- package/dist/index.js.map +4 -4
- package/dist/manifest.d.ts +49 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/styles/tokens.css +47 -1
- 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 +15 -0
- package/dist/utils/format.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/biorhythm-chart.ts +39 -84
- package/src/components/compatibility-card.ts +85 -52
- package/src/components/dasha-timeline.ts +55 -73
- package/src/components/data.ts +20 -1
- package/src/components/dosha-card.ts +18 -31
- package/src/components/endpoint-form.ts +79 -11
- package/src/components/guna-milan.ts +16 -34
- package/src/components/hexagram.ts +53 -43
- package/src/components/horoscope-card.ts +51 -39
- package/src/components/kp-planets-table.ts +8 -27
- package/src/components/location-search.ts +45 -20
- package/src/components/moon-phase.ts +28 -25
- package/src/components/natal-chart.ts +129 -84
- package/src/components/numerology-card.ts +87 -79
- package/src/components/panchang-table.ts +40 -78
- package/src/components/synastry-chart.ts +220 -78
- package/src/components/tarot-card.ts +76 -62
- package/src/components/tarot-spread.ts +72 -45
- package/src/components/vedic-kundli.ts +42 -51
- package/src/index.ts +14 -24
- package/src/manifest.ts +366 -0
- package/src/styles/tokens.css +47 -1
- package/src/tokens/index.ts +5 -0
- package/src/types/types.gen.ts +1 -1
- package/src/utils/debounce.ts +23 -4
- package/src/utils/format.ts +57 -0
- package/src/version.ts +2 -0
package/dist/utils/debounce.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Lightweight debounce for input handlers. Used by location search.
|
|
3
|
+
*
|
|
4
|
+
* The returned function exposes a `.cancel()` method so callers can clear a
|
|
5
|
+
* pending invocation when the host element disconnects, preventing the timer
|
|
6
|
+
* from firing on a detached node and mutating reactive state after teardown.
|
|
3
7
|
*/
|
|
4
|
-
export
|
|
8
|
+
export interface Debounced<F extends (...args: never[]) => unknown> {
|
|
9
|
+
(...args: Parameters<F>): void;
|
|
10
|
+
cancel: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function debounce<F extends (...args: never[]) => unknown>(fn: F, wait: number): Debounced<F>;
|
|
5
13
|
//# sourceMappingURL=debounce.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../src/utils/debounce.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../src/utils/debounce.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO;IACjE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EAC/D,EAAE,EAAE,CAAC,EACL,IAAI,EAAE,MAAM,GACV,SAAS,CAAC,CAAC,CAAC,CAgBd"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Display formatters for ISO timestamps and floats coming back from the API.
|
|
3
|
+
* Every helper returns "" for nullish or unparseable input so it falls out of
|
|
4
|
+
* template literals cleanly.
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatTime(input: unknown): string;
|
|
7
|
+
export declare function formatDate(input: unknown): string;
|
|
8
|
+
export declare function formatTimeRange(t: {
|
|
9
|
+
start?: string;
|
|
10
|
+
end?: string;
|
|
11
|
+
} | undefined): string;
|
|
12
|
+
export declare function formatNumber(value: unknown, dp?: number): string;
|
|
13
|
+
export declare function formatPercent(value: unknown, dp?: number): string;
|
|
14
|
+
export declare function formatLongitude(value: unknown): string;
|
|
15
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAYjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAWjD;AAED,wBAAgB,eAAe,CAC9B,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAC7C,MAAM,CAMR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,SAAI,GAAG,MAAM,CAG3D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,SAAI,GAAG,MAAM,CAG5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,eAAe,UAAU,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roxyapi/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Web components for the RoxyAPI catalog. Drop-in charts, tables, cards, forms for astrology, tarot, numerology, biorhythm, I Ching, crystals, dreams, angel numbers, and more. One key, beautiful in 30 minutes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
"types": "./dist/components/*.d.ts",
|
|
17
17
|
"import": "./dist/components/*.js"
|
|
18
18
|
},
|
|
19
|
+
"./types": {
|
|
20
|
+
"types": "./dist/types/index.d.ts"
|
|
21
|
+
},
|
|
19
22
|
"./styles/tokens.css": "./dist/styles/tokens.css",
|
|
20
23
|
"./registry/*": "./dist/registry/*.json"
|
|
21
24
|
},
|
|
@@ -63,6 +66,9 @@
|
|
|
63
66
|
"./dist/components/*.js",
|
|
64
67
|
"./dist/cdn/*.js"
|
|
65
68
|
],
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=18"
|
|
71
|
+
},
|
|
66
72
|
"peerDependencies": {
|
|
67
73
|
"lit": "^3.0.0"
|
|
68
74
|
},
|
|
@@ -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>
|
|
@@ -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;
|
|
@@ -1,36 +1,25 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import type {
|
|
4
|
+
GetCurrentDashaResponse,
|
|
5
|
+
GetMajorDashasResponse,
|
|
6
|
+
GetSubDashasResponse,
|
|
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
|
-
lord?: string;
|
|
10
|
-
planet?: string;
|
|
11
|
-
startDate?: string;
|
|
12
|
-
endDate?: string;
|
|
13
|
-
years?: number;
|
|
14
|
-
durationYears?: number;
|
|
15
|
-
}
|
|
11
|
+
type DashaData =
|
|
12
|
+
| GetCurrentDashaResponse
|
|
13
|
+
| GetMajorDashasResponse
|
|
14
|
+
| GetSubDashasResponse;
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
mahadashas?: DashaPeriod[];
|
|
25
|
-
antardashas?: DashaPeriod[];
|
|
26
|
-
mahadashaLord?: string;
|
|
27
|
-
mahadashaPeriod?: DashaPeriod;
|
|
28
|
-
birthDashaBalance?: { lord?: string; years?: number };
|
|
29
|
-
totalYears?: number;
|
|
30
|
-
remainingInMahadasha?: number;
|
|
31
|
-
remainingInAntardasha?: number;
|
|
32
|
-
remainingInPratyantardasha?: number;
|
|
33
|
-
}
|
|
16
|
+
type DashaPeriod = {
|
|
17
|
+
planet: string;
|
|
18
|
+
startDate: string;
|
|
19
|
+
endDate: string;
|
|
20
|
+
durationYears: number;
|
|
21
|
+
interpretation?: string;
|
|
22
|
+
};
|
|
34
23
|
|
|
35
24
|
/**
|
|
36
25
|
* Dasha timeline. Renders /vedic-astrology/dasha/{current,major,sub/{...}}.
|
|
@@ -132,7 +121,7 @@ export class RoxyDashaTimeline extends LitElement {
|
|
|
132
121
|
|
|
133
122
|
const periods = this.collectPeriods(d);
|
|
134
123
|
const maxYears = periods.length
|
|
135
|
-
? Math.max(...periods.map((p) => p.durationYears
|
|
124
|
+
? Math.max(...periods.map((p) => p.durationYears))
|
|
136
125
|
: 0;
|
|
137
126
|
|
|
138
127
|
return html`<div class="wrap" aria-label="Dasha timeline">
|
|
@@ -147,11 +136,11 @@ export class RoxyDashaTimeline extends LitElement {
|
|
|
147
136
|
}
|
|
148
137
|
</h2>
|
|
149
138
|
${
|
|
150
|
-
|
|
139
|
+
'nakshatraName' in d && d.nakshatraName
|
|
151
140
|
? html`<div class="nakshatra">
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
141
|
+
Moon nakshatra: ${d.nakshatraName}
|
|
142
|
+
${'nakshatraLord' in d && d.nakshatraLord ? html`(lord ${d.nakshatraLord})` : nothing}
|
|
143
|
+
</div>`
|
|
155
144
|
: nothing
|
|
156
145
|
}
|
|
157
146
|
</header>
|
|
@@ -168,68 +157,61 @@ export class RoxyDashaTimeline extends LitElement {
|
|
|
168
157
|
}
|
|
169
158
|
|
|
170
159
|
private renderCurrent(d: DashaData) {
|
|
160
|
+
if (!('mahadasha' in d)) return nothing;
|
|
171
161
|
return html`<div class="current">
|
|
172
162
|
${
|
|
173
|
-
d.mahadasha
|
|
163
|
+
'mahadasha' in d && d.mahadasha
|
|
174
164
|
? html`<div>
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
165
|
+
<span>Mahadasha</span>
|
|
166
|
+
<strong>${d.mahadasha.planet}</strong>
|
|
167
|
+
${
|
|
168
|
+
'remainingInMahadasha' in d && d.remainingInMahadasha
|
|
169
|
+
? html`<small>${formatNumber(d.remainingInMahadasha.years + d.remainingInMahadasha.months / 12, 1)} years left</small>`
|
|
170
|
+
: nothing
|
|
171
|
+
}
|
|
172
|
+
</div>`
|
|
183
173
|
: nothing
|
|
184
174
|
}
|
|
185
175
|
${
|
|
186
|
-
d.antardasha
|
|
176
|
+
'antardasha' in d && d.antardasha
|
|
187
177
|
? html`<div>
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
178
|
+
<span>Antardasha</span>
|
|
179
|
+
<strong>${d.antardasha.planet}</strong>
|
|
180
|
+
${
|
|
181
|
+
'remainingInAntardasha' in d && d.remainingInAntardasha
|
|
182
|
+
? html`<small>${formatNumber(d.remainingInAntardasha.years + d.remainingInAntardasha.months / 12, 1)} years left</small>`
|
|
183
|
+
: nothing
|
|
184
|
+
}
|
|
185
|
+
</div>`
|
|
196
186
|
: nothing
|
|
197
187
|
}
|
|
198
188
|
${
|
|
199
|
-
d.pratyantardasha
|
|
189
|
+
'pratyantardasha' in d && d.pratyantardasha
|
|
200
190
|
? html`<div>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}</
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
? html`<small
|
|
210
|
-
>${d.remainingInPratyantardasha.toFixed(2)} years left</small
|
|
211
|
-
>`
|
|
212
|
-
: nothing
|
|
213
|
-
}
|
|
214
|
-
</div>`
|
|
191
|
+
<span>Pratyantardasha</span>
|
|
192
|
+
<strong>${d.pratyantardasha.planet}</strong>
|
|
193
|
+
${
|
|
194
|
+
'remainingInPratyantardasha' in d && d.remainingInPratyantardasha
|
|
195
|
+
? html`<small>${formatNumber(d.remainingInPratyantardasha.years + d.remainingInPratyantardasha.months / 12, 1)} years left</small>`
|
|
196
|
+
: nothing
|
|
197
|
+
}
|
|
198
|
+
</div>`
|
|
215
199
|
: nothing
|
|
216
200
|
}
|
|
217
201
|
</div>`;
|
|
218
202
|
}
|
|
219
203
|
|
|
220
204
|
private collectPeriods(d: DashaData): DashaPeriod[] {
|
|
221
|
-
if (
|
|
222
|
-
if (
|
|
223
|
-
return
|
|
205
|
+
if ('mahadashas' in d && d.mahadashas?.length) return d.mahadashas;
|
|
206
|
+
if ('antardashas' in d && d.antardashas?.length) return d.antardashas;
|
|
207
|
+
return [];
|
|
224
208
|
}
|
|
225
209
|
|
|
226
210
|
private renderBar(p: DashaPeriod, max: number) {
|
|
227
|
-
const
|
|
228
|
-
p.lord ?? p.mahadashaLord ?? p.antardashaLord ?? p.planet ?? '';
|
|
229
|
-
const years = p.durationYears ?? p.years ?? 0;
|
|
211
|
+
const years = p.durationYears;
|
|
230
212
|
const width = max > 0 ? (years / max) * 100 : 0;
|
|
231
213
|
return html`<div class="bar" role="listitem">
|
|
232
|
-
<span>${
|
|
214
|
+
<span>${p.planet}</span>
|
|
233
215
|
<span class="bar-track"><span style="width: ${width}%"></span></span>
|
|
234
216
|
<span class="dates">
|
|
235
217
|
${p.startDate ? formatYear(p.startDate) : ''}
|