@roxyapi/ui 0.1.3 → 0.2.1
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 +9 -3
- package/dist/cdn/components/ashtakavarga-grid.js +349 -0
- package/dist/cdn/components/ashtakavarga-grid.js.map +7 -0
- 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 +6 -6
- package/dist/cdn/components/compatibility-card.js.map +1 -1
- package/dist/cdn/components/dasha-timeline.js +4 -4
- package/dist/cdn/components/dasha-timeline.js.map +1 -1
- 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 +39 -39
- package/dist/cdn/components/dosha-card.js.map +3 -3
- package/dist/cdn/components/endpoint-form.js +8 -8
- package/dist/cdn/components/endpoint-form.js.map +4 -4
- package/dist/cdn/components/guna-milan.js +64 -22
- package/dist/cdn/components/guna-milan.js.map +3 -3
- package/dist/cdn/components/hexagram.js +9 -9
- package/dist/cdn/components/hexagram.js.map +3 -3
- package/dist/cdn/components/horoscope-card.js +28 -21
- package/dist/cdn/components/horoscope-card.js.map +4 -4
- package/dist/cdn/components/kp-planets-table.js +4 -4
- package/dist/cdn/components/kp-planets-table.js.map +1 -1
- package/dist/cdn/components/location-search.js.map +2 -2
- package/dist/cdn/components/moon-phase.js +13 -13
- package/dist/cdn/components/moon-phase.js.map +3 -3
- package/dist/cdn/components/natal-chart.js +196 -22
- package/dist/cdn/components/natal-chart.js.map +4 -4
- package/dist/cdn/components/numerology-card.js +6 -6
- package/dist/cdn/components/numerology-card.js.map +4 -4
- package/dist/cdn/components/panchang-table.js +9 -9
- package/dist/cdn/components/panchang-table.js.map +1 -1
- 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 +21 -21
- package/dist/cdn/components/synastry-chart.js.map +4 -4
- package/dist/cdn/components/transits-table.js +396 -0
- package/dist/cdn/components/transits-table.js.map +7 -0
- package/dist/cdn/components/vedic-kundli.js +51 -29
- 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 +1877 -522
- 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/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.js.map +1 -1
- package/dist/components/dasha-timeline.js.map +1 -1
- package/dist/components/data.d.ts +5 -7
- package/dist/components/data.d.ts.map +1 -1
- package/dist/components/data.js +7 -5
- 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.map +1 -1
- package/dist/components/dosha-card.js +33 -30
- package/dist/components/dosha-card.js.map +2 -2
- package/dist/components/endpoint-form.d.ts.map +1 -1
- package/dist/components/endpoint-form.js +5 -3
- package/dist/components/endpoint-form.js.map +3 -3
- package/dist/components/guna-milan.d.ts.map +1 -1
- package/dist/components/guna-milan.js +61 -12
- package/dist/components/guna-milan.js.map +3 -3
- package/dist/components/hexagram.js +17 -0
- package/dist/components/hexagram.js.map +2 -2
- package/dist/components/horoscope-card.d.ts.map +1 -1
- package/dist/components/horoscope-card.js +30 -3
- package/dist/components/horoscope-card.js.map +3 -3
- package/dist/components/kp-planets-table.js.map +1 -1
- package/dist/components/location-search.d.ts +2 -3
- package/dist/components/location-search.d.ts.map +1 -1
- package/dist/components/location-search.js.map +2 -2
- package/dist/components/moon-phase.js +17 -0
- package/dist/components/moon-phase.js.map +2 -2
- package/dist/components/natal-chart.d.ts +2 -0
- package/dist/components/natal-chart.d.ts.map +1 -1
- package/dist/components/natal-chart.js +243 -36
- package/dist/components/natal-chart.js.map +3 -3
- package/dist/components/numerology-card.d.ts.map +1 -1
- package/dist/components/numerology-card.js +5 -3
- package/dist/components/numerology-card.js.map +3 -3
- package/dist/components/panchang-table.js.map +1 -1
- 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.map +1 -1
- package/dist/components/synastry-chart.js +34 -29
- package/dist/components/synastry-chart.js.map +3 -3
- 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 +520 -0
- package/dist/components/transits-table.js.map +7 -0
- package/dist/components/vedic-kundli.d.ts +3 -6
- package/dist/components/vedic-kundli.d.ts.map +1 -1
- package/dist/components/vedic-kundli.js +132 -80
- 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 +2707 -980
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2714 -987
- package/dist/index.js.map +4 -4
- package/dist/manifest.d.ts +4 -10
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.json +7 -2
- package/dist/styles/tokens.css +26 -0
- package/dist/tokens/index.d.ts +6 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/types/types.gen.d.ts +2 -2
- package/dist/utils/format.d.ts +15 -1
- package/dist/utils/format.d.ts.map +1 -1
- 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 +1 -1
- package/package.json +1 -1
- package/src/components/ashtakavarga-grid.ts +354 -0
- package/src/components/choghadiya-grid.ts +185 -0
- package/src/components/data.ts +8 -15
- package/src/components/divisional-chart.ts +214 -0
- package/src/components/dosha-card.ts +53 -36
- package/src/components/endpoint-form.ts +1 -7
- package/src/components/guna-milan.ts +74 -16
- package/src/components/horoscope-card.ts +8 -4
- package/src/components/location-search.ts +2 -3
- package/src/components/natal-chart.ts +251 -42
- package/src/components/numerology-card.ts +1 -7
- package/src/components/shadbala-table.ts +286 -0
- package/src/components/synastry-chart.ts +13 -39
- package/src/components/transits-table.ts +358 -0
- package/src/components/vedic-kundli.ts +38 -143
- package/src/components/yoga-list.ts +328 -0
- package/src/index.ts +8 -6
- package/src/manifest.ts +74 -100
- package/src/styles/tokens.css +26 -0
- package/src/tokens/index.ts +9 -0
- package/src/types/types.gen.ts +2 -2
- package/src/utils/format.ts +21 -3
- package/src/utils/kundli-render.ts +197 -0
- package/src/utils/string.ts +23 -0
- package/src/version.ts +1 -1
- package/dist/utils/motion.d.ts +0 -13
- package/dist/utils/motion.d.ts.map +0 -1
- package/src/utils/motion.ts +0 -18
|
@@ -33,6 +33,14 @@ export class RoxyGunaMilan extends LitElement {
|
|
|
33
33
|
gap: var(--roxy-space-md, 1rem);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
.score-header {
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: 1rem;
|
|
40
|
+
}
|
|
41
|
+
.score-info {
|
|
42
|
+
flex: 1;
|
|
43
|
+
}
|
|
36
44
|
.score-bar {
|
|
37
45
|
display: grid;
|
|
38
46
|
grid-template-columns: 1fr auto;
|
|
@@ -54,6 +62,26 @@ export class RoxyGunaMilan extends LitElement {
|
|
|
54
62
|
font-size: var(--roxy-text-sm, 0.875rem);
|
|
55
63
|
color: var(--roxy-secondary, #475569);
|
|
56
64
|
}
|
|
65
|
+
.score-ring {
|
|
66
|
+
width: 120px;
|
|
67
|
+
height: 120px;
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
}
|
|
70
|
+
.score-ring svg {
|
|
71
|
+
width: 100%;
|
|
72
|
+
height: 100%;
|
|
73
|
+
}
|
|
74
|
+
.score-ring .ring-text {
|
|
75
|
+
font-size: 22px;
|
|
76
|
+
font-weight: 700;
|
|
77
|
+
fill: var(--roxy-fg, #0a0a0a);
|
|
78
|
+
font-family: var(--roxy-font-sans);
|
|
79
|
+
}
|
|
80
|
+
.score-ring .ring-max {
|
|
81
|
+
font-size: 10px;
|
|
82
|
+
fill: var(--roxy-muted, #71717a);
|
|
83
|
+
font-family: var(--roxy-font-sans);
|
|
84
|
+
}
|
|
57
85
|
|
|
58
86
|
table {
|
|
59
87
|
width: 100%;
|
|
@@ -130,24 +158,54 @@ export class RoxyGunaMilan extends LitElement {
|
|
|
130
158
|
(b) => b?.category !== undefined,
|
|
131
159
|
);
|
|
132
160
|
|
|
161
|
+
const score = d.total ?? 0;
|
|
162
|
+
const max = d.maxScore ?? 36;
|
|
163
|
+
const pct = (score / max) * 100;
|
|
164
|
+
const trackColor =
|
|
165
|
+
'color-mix(in srgb, var(--roxy-border) 50%, transparent)';
|
|
166
|
+
const fillColor =
|
|
167
|
+
pct >= 70
|
|
168
|
+
? 'var(--roxy-success)'
|
|
169
|
+
: pct >= 50
|
|
170
|
+
? 'var(--roxy-warning)'
|
|
171
|
+
: 'var(--roxy-danger)';
|
|
172
|
+
// SVG circle with r=45: circumference = 2 * pi * 45 = 282.74
|
|
173
|
+
// dasharray segments = pct * 2.827, (100 - pct) * 2.827
|
|
174
|
+
const dashFill = pct * 2.827;
|
|
175
|
+
const dashGap = (100 - pct) * 2.827;
|
|
176
|
+
|
|
133
177
|
return html`<article class="card" aria-label="Guna Milan score">
|
|
134
|
-
<div class="score-
|
|
135
|
-
<div>
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
178
|
+
<div class="score-header">
|
|
179
|
+
<div class="score-info">
|
|
180
|
+
<div class="score-bar">
|
|
181
|
+
<div>
|
|
182
|
+
<span class="total">${formatNumber(d.total, 1)}</span>
|
|
183
|
+
<span class="over"> / ${d.maxScore}</span>
|
|
184
|
+
${
|
|
185
|
+
typeof d.percentage === 'number'
|
|
186
|
+
? html`<small style="margin-left: 0.5rem; color: var(--roxy-muted)">
|
|
187
|
+
${formatPercent(d.percentage, 1)}
|
|
188
|
+
</small>`
|
|
189
|
+
: nothing
|
|
190
|
+
}
|
|
191
|
+
</div>
|
|
192
|
+
${
|
|
193
|
+
d.recommendation
|
|
194
|
+
? html`<span class="recommendation">${d.recommendation}</span>`
|
|
195
|
+
: nothing
|
|
196
|
+
}
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
<div class="score-ring" role="meter" aria-label="Guna milan score" aria-valuemin="0" aria-valuemax="36" aria-valuenow="${score}">
|
|
200
|
+
<svg viewBox="0 0 100 100" aria-hidden="true">
|
|
201
|
+
<circle class="ring-track" cx="50" cy="50" r="45" fill="none" stroke="${trackColor}" stroke-width="8"/>
|
|
202
|
+
<circle class="ring-fill" cx="50" cy="50" r="45" fill="none" stroke="${fillColor}" stroke-width="8"
|
|
203
|
+
stroke-dasharray="${dashFill},${dashGap}" stroke-linecap="round"
|
|
204
|
+
transform="rotate(-90 50 50)"/>
|
|
205
|
+
<text x="50" y="50" text-anchor="middle" dominant-baseline="central" class="ring-text">${score}</text>
|
|
206
|
+
<text x="50" y="64" text-anchor="middle" dominant-baseline="central" class="ring-max">/${max}</text>
|
|
207
|
+
</svg>
|
|
145
208
|
</div>
|
|
146
|
-
${
|
|
147
|
-
d.recommendation
|
|
148
|
-
? html`<span class="recommendation">${d.recommendation}</span>`
|
|
149
|
-
: nothing
|
|
150
|
-
}
|
|
151
209
|
</div>
|
|
152
210
|
|
|
153
211
|
${
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
GetWeeklyHoroscopeResponse,
|
|
8
8
|
} from '../types/index.js';
|
|
9
9
|
import { baseStyles } from '../utils/base-styles.js';
|
|
10
|
+
import { capitalize } from '../utils/string.js';
|
|
10
11
|
|
|
11
12
|
type HoroscopeData =
|
|
12
13
|
| GetDailyHoroscopeResponse
|
|
@@ -123,6 +124,13 @@ export class RoxyHoroscopeCard extends LitElement {
|
|
|
123
124
|
font-weight: var(--roxy-weight-bold, 600);
|
|
124
125
|
}
|
|
125
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
|
+
}
|
|
126
134
|
.compat {
|
|
127
135
|
display: flex;
|
|
128
136
|
flex-wrap: wrap;
|
|
@@ -292,10 +300,6 @@ export class RoxyHoroscopeCard extends LitElement {
|
|
|
292
300
|
}
|
|
293
301
|
}
|
|
294
302
|
|
|
295
|
-
function capitalize(s: string): string {
|
|
296
|
-
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
297
|
-
}
|
|
298
|
-
|
|
299
303
|
declare global {
|
|
300
304
|
interface HTMLElementTagNameMap {
|
|
301
305
|
'roxy-horoscope-card': RoxyHoroscopeCard;
|
|
@@ -11,9 +11,8 @@ type CityResult = SearchCitiesResponse['cities'][number];
|
|
|
11
11
|
* `roxy-location-select` CustomEvent with the chosen city. Required for any
|
|
12
12
|
* chart endpoint.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* 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.
|
|
17
16
|
*
|
|
18
17
|
* Attributes:
|
|
19
18
|
* api-key optional. Direct call to roxyapi.com when set.
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing, svg } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
-
import { PLANET_GLYPH, SIGN_GLYPH } from '../tokens/index.js';
|
|
3
|
+
import { PLANET_GLYPH, SIGN_GLYPH, SIGNS_ORDER } from '../tokens/index.js';
|
|
4
4
|
import type { NatalChartResponse } from '../types/index.js';
|
|
5
5
|
import { baseStyles } from '../utils/base-styles.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { polarToCartesian } from '../utils/degree.js';
|
|
7
|
+
import {
|
|
8
|
+
ASPECT_CLASS,
|
|
9
|
+
formatNumber,
|
|
10
|
+
normalizeAspect,
|
|
11
|
+
} from '../utils/format.js';
|
|
12
|
+
import { capitalize } from '../utils/string.js';
|
|
8
13
|
|
|
9
14
|
type PlanetEntry = NatalChartResponse['planets'][number];
|
|
10
15
|
type AspectEntry = NatalChartResponse['aspects'][number];
|
|
11
16
|
|
|
12
|
-
const SIZE =
|
|
17
|
+
const SIZE = 420;
|
|
13
18
|
const CENTER = SIZE / 2;
|
|
14
|
-
const OUTER_R =
|
|
15
|
-
const SIGN_R =
|
|
16
|
-
const HOUSE_R =
|
|
17
|
-
const PLANET_R =
|
|
18
|
-
const ANGLE_TICK_R =
|
|
19
|
-
const ANGLE_LABEL_R =
|
|
19
|
+
const OUTER_R = 164;
|
|
20
|
+
const SIGN_R = 146;
|
|
21
|
+
const HOUSE_R = 120;
|
|
22
|
+
const PLANET_R = 96;
|
|
23
|
+
const ANGLE_TICK_R = 178;
|
|
24
|
+
const ANGLE_LABEL_R = 196;
|
|
20
25
|
|
|
21
26
|
/**
|
|
22
27
|
* Western natal chart wheel. Renders the 12 zodiac signs, 12 houses, planet
|
|
@@ -125,6 +130,136 @@ export class RoxyNatalChart extends LitElement {
|
|
|
125
130
|
margin-right: 4px;
|
|
126
131
|
vertical-align: middle;
|
|
127
132
|
}
|
|
133
|
+
|
|
134
|
+
.details {
|
|
135
|
+
margin-top: var(--roxy-space-md, 1rem);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.pill-row {
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-wrap: wrap;
|
|
141
|
+
gap: var(--roxy-space-xs, 0.25rem);
|
|
142
|
+
margin-bottom: var(--roxy-space-xs, 0.25rem);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.pill {
|
|
146
|
+
padding: 2px 8px;
|
|
147
|
+
border-radius: var(--roxy-radius-sm, 4px);
|
|
148
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
149
|
+
background: color-mix(in srgb, var(--roxy-fg, #0f172a) 8%, transparent);
|
|
150
|
+
color: var(--roxy-fg, #0f172a);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.pill--success {
|
|
154
|
+
background: color-mix(in srgb, var(--roxy-success, #16a34a) 15%, transparent);
|
|
155
|
+
color: var(--roxy-success, #16a34a);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.pill--danger {
|
|
159
|
+
background: color-mix(in srgb, var(--roxy-danger, #dc2626) 15%, transparent);
|
|
160
|
+
color: var(--roxy-danger, #dc2626);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.pill--muted {
|
|
164
|
+
background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent);
|
|
165
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.summary {
|
|
169
|
+
color: var(--roxy-fg, #0f172a);
|
|
170
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
171
|
+
margin: var(--roxy-space-md, 1rem) 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.dist-grid {
|
|
175
|
+
display: grid;
|
|
176
|
+
grid-template-columns: 1fr 1fr;
|
|
177
|
+
gap: var(--roxy-space-md, 1rem);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@container (max-width: 639px) {
|
|
181
|
+
.dist-grid {
|
|
182
|
+
grid-template-columns: 1fr;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.dist-section h3 {
|
|
187
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
188
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
189
|
+
color: var(--roxy-muted, #71717a);
|
|
190
|
+
margin: 0 0 var(--roxy-space-xs, 0.25rem);
|
|
191
|
+
text-transform: uppercase;
|
|
192
|
+
letter-spacing: 0.05em;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.dist-row {
|
|
196
|
+
display: grid;
|
|
197
|
+
grid-template-columns: 4rem 1fr 1.5rem;
|
|
198
|
+
align-items: center;
|
|
199
|
+
gap: var(--roxy-space-xs, 0.25rem);
|
|
200
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
201
|
+
color: var(--roxy-fg, #0f172a);
|
|
202
|
+
margin-bottom: 4px;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.dist-bar {
|
|
206
|
+
background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 20%, transparent);
|
|
207
|
+
height: 6px;
|
|
208
|
+
border-radius: 3px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.dist-bar > span {
|
|
212
|
+
display: block;
|
|
213
|
+
height: 100%;
|
|
214
|
+
background: var(--roxy-accent, #f59e0b);
|
|
215
|
+
border-radius: 3px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.interpretations {
|
|
219
|
+
margin-top: var(--roxy-space-md, 1rem);
|
|
220
|
+
}
|
|
221
|
+
.interpretations h3 {
|
|
222
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
223
|
+
font-weight: 600;
|
|
224
|
+
color: var(--roxy-muted, #71717a);
|
|
225
|
+
text-transform: uppercase;
|
|
226
|
+
letter-spacing: 0.06em;
|
|
227
|
+
margin: 0 0 var(--roxy-space-sm, 0.5rem);
|
|
228
|
+
}
|
|
229
|
+
.interp-card {
|
|
230
|
+
border: 1px solid var(--roxy-border, #e4e4e7);
|
|
231
|
+
border-radius: var(--roxy-radius-md, 8px);
|
|
232
|
+
padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
|
|
233
|
+
margin-bottom: var(--roxy-space-xs, 0.25rem);
|
|
234
|
+
}
|
|
235
|
+
.interp-card summary {
|
|
236
|
+
cursor: pointer;
|
|
237
|
+
font-weight: 500;
|
|
238
|
+
color: var(--roxy-fg, #0f172a);
|
|
239
|
+
}
|
|
240
|
+
.interp-card summary small {
|
|
241
|
+
color: var(--roxy-muted, #71717a);
|
|
242
|
+
margin-left: 0.5em;
|
|
243
|
+
font-weight: 400;
|
|
244
|
+
}
|
|
245
|
+
.interp-body {
|
|
246
|
+
margin-top: var(--roxy-space-xs, 0.25rem);
|
|
247
|
+
color: var(--roxy-fg, #0f172a);
|
|
248
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
249
|
+
}
|
|
250
|
+
.interp-keywords {
|
|
251
|
+
display: flex;
|
|
252
|
+
flex-wrap: wrap;
|
|
253
|
+
gap: 0.25rem;
|
|
254
|
+
margin-top: 0.5rem;
|
|
255
|
+
}
|
|
256
|
+
.interp-keywords .kw {
|
|
257
|
+
padding: 1px 8px;
|
|
258
|
+
border-radius: 9999px;
|
|
259
|
+
background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 14%, transparent);
|
|
260
|
+
color: var(--roxy-accent-fg, #b45309);
|
|
261
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
262
|
+
}
|
|
128
263
|
`,
|
|
129
264
|
];
|
|
130
265
|
|
|
@@ -211,6 +346,8 @@ export class RoxyNatalChart extends LitElement {
|
|
|
211
346
|
<span><span class="legend-swatch" style="background: var(--roxy-success)"></span>harmonious</span>
|
|
212
347
|
<span><span class="legend-swatch" style="background: var(--roxy-danger)"></span>challenging</span>
|
|
213
348
|
</div>
|
|
349
|
+
${this.renderDetails()}
|
|
350
|
+
${this.renderInterpretations()}
|
|
214
351
|
</div>`;
|
|
215
352
|
}
|
|
216
353
|
|
|
@@ -245,21 +382,7 @@ export class RoxyNatalChart extends LitElement {
|
|
|
245
382
|
}
|
|
246
383
|
|
|
247
384
|
private renderSigns() {
|
|
248
|
-
|
|
249
|
-
'Aries',
|
|
250
|
-
'Taurus',
|
|
251
|
-
'Gemini',
|
|
252
|
-
'Cancer',
|
|
253
|
-
'Leo',
|
|
254
|
-
'Virgo',
|
|
255
|
-
'Libra',
|
|
256
|
-
'Scorpio',
|
|
257
|
-
'Sagittarius',
|
|
258
|
-
'Capricorn',
|
|
259
|
-
'Aquarius',
|
|
260
|
-
'Pisces',
|
|
261
|
-
];
|
|
262
|
-
return order.map((sign, i) => {
|
|
385
|
+
return SIGNS_ORDER.map((sign, i) => {
|
|
263
386
|
const angle = this.toAngle(i * 30 + 15);
|
|
264
387
|
const pos = polarToCartesian(CENTER, CENTER, SIGN_R, angle);
|
|
265
388
|
return svg`<text class="sign-glyph" x=${pos.x} y=${pos.y} text-anchor="middle" dominant-baseline="central">${SIGN_GLYPH[sign]}</text>`;
|
|
@@ -288,6 +411,109 @@ export class RoxyNatalChart extends LitElement {
|
|
|
288
411
|
});
|
|
289
412
|
}
|
|
290
413
|
|
|
414
|
+
private renderDetails() {
|
|
415
|
+
const summary = this.data?.summary;
|
|
416
|
+
const ai = this.data?.aspectsInterpretation;
|
|
417
|
+
if (!summary && !ai) return nothing;
|
|
418
|
+
|
|
419
|
+
const retrogrades = summary?.retrogradePlanets ?? [];
|
|
420
|
+
const elementDist = summary?.elementDistribution ?? {};
|
|
421
|
+
const modalityDist = summary?.modalityDistribution ?? {};
|
|
422
|
+
const elementMax = Math.max(1, ...Object.values(elementDist));
|
|
423
|
+
const modalityMax = Math.max(1, ...Object.values(modalityDist));
|
|
424
|
+
|
|
425
|
+
return html`<div class="details">
|
|
426
|
+
${
|
|
427
|
+
summary?.dominantElement || summary?.dominantModality
|
|
428
|
+
? html`<div class="pill-row">
|
|
429
|
+
${summary.dominantElement ? html`<span class="pill">Dominant element: ${summary.dominantElement}</span>` : nothing}
|
|
430
|
+
${summary.dominantModality ? html`<span class="pill">Dominant modality: ${summary.dominantModality}</span>` : nothing}
|
|
431
|
+
</div>`
|
|
432
|
+
: nothing
|
|
433
|
+
}
|
|
434
|
+
${
|
|
435
|
+
ai
|
|
436
|
+
? html`<div class="pill-row">
|
|
437
|
+
<span class="pill pill--success">Harmonious ${ai.harmonious}</span>
|
|
438
|
+
<span class="pill pill--danger">Challenging ${ai.challenging}</span>
|
|
439
|
+
<span class="pill pill--muted">Neutral ${ai.neutral}</span>
|
|
440
|
+
</div>`
|
|
441
|
+
: nothing
|
|
442
|
+
}
|
|
443
|
+
${
|
|
444
|
+
retrogrades.length > 0
|
|
445
|
+
? html`<div class="pill-row">
|
|
446
|
+
${retrogrades.map((p) => {
|
|
447
|
+
const glyph = PLANET_GLYPH[p] ?? p.slice(0, 2);
|
|
448
|
+
return html`<span class="pill pill--muted">${glyph} ${p} R</span>`;
|
|
449
|
+
})}
|
|
450
|
+
</div>`
|
|
451
|
+
: nothing
|
|
452
|
+
}
|
|
453
|
+
${ai?.summary ? html`<p class="summary">${ai.summary}</p>` : nothing}
|
|
454
|
+
${
|
|
455
|
+
Object.keys(elementDist).length > 0 ||
|
|
456
|
+
Object.keys(modalityDist).length > 0
|
|
457
|
+
? html`<div class="dist-grid">
|
|
458
|
+
${
|
|
459
|
+
Object.keys(elementDist).length > 0
|
|
460
|
+
? html`<div class="dist-section">
|
|
461
|
+
<h3>Elements</h3>
|
|
462
|
+
${Object.entries(elementDist).map(
|
|
463
|
+
([label, count]) => html`<div class="dist-row">
|
|
464
|
+
<span>${label}</span>
|
|
465
|
+
<div class="dist-bar"><span style="width: ${Math.round((count / elementMax) * 100)}%"></span></div>
|
|
466
|
+
<span>${count}</span>
|
|
467
|
+
</div>`,
|
|
468
|
+
)}
|
|
469
|
+
</div>`
|
|
470
|
+
: nothing
|
|
471
|
+
}
|
|
472
|
+
${
|
|
473
|
+
Object.keys(modalityDist).length > 0
|
|
474
|
+
? html`<div class="dist-section">
|
|
475
|
+
<h3>Modalities</h3>
|
|
476
|
+
${Object.entries(modalityDist).map(
|
|
477
|
+
([label, count]) => html`<div class="dist-row">
|
|
478
|
+
<span>${label}</span>
|
|
479
|
+
<div class="dist-bar"><span style="width: ${Math.round((count / modalityMax) * 100)}%"></span></div>
|
|
480
|
+
<span>${count}</span>
|
|
481
|
+
</div>`,
|
|
482
|
+
)}
|
|
483
|
+
</div>`
|
|
484
|
+
: nothing
|
|
485
|
+
}
|
|
486
|
+
</div>`
|
|
487
|
+
: nothing
|
|
488
|
+
}
|
|
489
|
+
</div>`;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
private renderInterpretations() {
|
|
493
|
+
const planets = this.getPlanets().filter((p) => p.interpretation);
|
|
494
|
+
if (planets.length === 0) return nothing;
|
|
495
|
+
return html`<section class="interpretations">
|
|
496
|
+
<h3>Planet readings</h3>
|
|
497
|
+
${planets.map((p) => {
|
|
498
|
+
const interp = p.interpretation!;
|
|
499
|
+
const glyph = PLANET_GLYPH[capitalize(p.name)] ?? '';
|
|
500
|
+
const deg = formatNumber(p.degree ?? 0, 1);
|
|
501
|
+
return html`<details class="interp-card">
|
|
502
|
+
<summary>${glyph} ${p.name} <small>${p.sign ?? ''} ${deg}</small></summary>
|
|
503
|
+
<div class="interp-body">
|
|
504
|
+
${interp.summary ? html`<p class="interp-summary">${interp.summary}</p>` : nothing}
|
|
505
|
+
${interp.detailed ? html`<p class="interp-detail">${interp.detailed}</p>` : nothing}
|
|
506
|
+
${
|
|
507
|
+
interp.keywords?.length
|
|
508
|
+
? html`<div class="interp-keywords">${interp.keywords.map((k) => html`<span class="kw">${k}</span>`)}</div>`
|
|
509
|
+
: nothing
|
|
510
|
+
}
|
|
511
|
+
</div>
|
|
512
|
+
</details>`;
|
|
513
|
+
})}
|
|
514
|
+
</section>`;
|
|
515
|
+
}
|
|
516
|
+
|
|
291
517
|
private renderAspects(planets: PlanetEntry[], aspects: AspectEntry[]) {
|
|
292
518
|
const planetMap = new Map<string, number>();
|
|
293
519
|
for (const p of planets) {
|
|
@@ -319,23 +545,6 @@ export class RoxyNatalChart extends LitElement {
|
|
|
319
545
|
}
|
|
320
546
|
}
|
|
321
547
|
|
|
322
|
-
function capitalize(s: string): string {
|
|
323
|
-
if (!s) return '';
|
|
324
|
-
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const ASPECT_CLASS: Record<string, string> = {
|
|
328
|
-
conjunction: 'aspect-conjunction',
|
|
329
|
-
sextile: 'aspect-sextile',
|
|
330
|
-
square: 'aspect-square',
|
|
331
|
-
trine: 'aspect-trine',
|
|
332
|
-
opposition: 'aspect-opposition',
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
function normalizeAspect(a: AspectEntry): string {
|
|
336
|
-
return (a.type ?? '').toLowerCase().replace(/_/g, '-');
|
|
337
|
-
}
|
|
338
|
-
|
|
339
548
|
declare global {
|
|
340
549
|
interface HTMLElementTagNameMap {
|
|
341
550
|
'roxy-natal-chart': RoxyNatalChart;
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
GenerateNumerologyChartResponse,
|
|
8
8
|
} from '../types/index.js';
|
|
9
9
|
import { baseStyles } from '../utils/base-styles.js';
|
|
10
|
+
import { humanize } from '../utils/string.js';
|
|
10
11
|
|
|
11
12
|
type NumerologyData =
|
|
12
13
|
| CalculateLifePathResponse
|
|
@@ -237,13 +238,6 @@ function karmicDebtText(value: KarmicDebtMeaning | undefined): string {
|
|
|
237
238
|
.join(' ');
|
|
238
239
|
}
|
|
239
240
|
|
|
240
|
-
function humanize(s: string): string {
|
|
241
|
-
return s
|
|
242
|
-
.replace(/[_-]+/g, ' ')
|
|
243
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
244
|
-
.replace(/^\w/, (c) => c.toUpperCase());
|
|
245
|
-
}
|
|
246
|
-
|
|
247
241
|
declare global {
|
|
248
242
|
interface HTMLElementTagNameMap {
|
|
249
243
|
'roxy-numerology-card': RoxyNumerologyCard;
|