@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
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import { PLANET_GLYPH, SIGN_GLYPH } from '../tokens/index.js';
|
|
4
|
+
import type { TransitsResponse } from '../types/index.js';
|
|
5
|
+
import { baseStyles } from '../utils/base-styles.js';
|
|
6
|
+
import { formatDate, formatNumber, formatTime } from '../utils/format.js';
|
|
7
|
+
import { capitalize } from '../utils/string.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Transit positions and aspect table. Pass `data` from /astrology/transits.
|
|
11
|
+
* When natalChart is included in the request, `data.transitAspects` and
|
|
12
|
+
* `data.summary` are present and rendered automatically.
|
|
13
|
+
*/
|
|
14
|
+
@customElement('roxy-transits-table')
|
|
15
|
+
export class RoxyTransitsTable extends LitElement {
|
|
16
|
+
static styles = [
|
|
17
|
+
baseStyles,
|
|
18
|
+
css`
|
|
19
|
+
.wrap {
|
|
20
|
+
display: grid;
|
|
21
|
+
gap: var(--roxy-space-md, 1rem);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.head {
|
|
25
|
+
display: flex;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
align-items: baseline;
|
|
28
|
+
gap: var(--roxy-space-md, 1rem);
|
|
29
|
+
flex-wrap: wrap;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.title {
|
|
33
|
+
font-size: var(--roxy-text-lg, 1.125rem);
|
|
34
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
35
|
+
margin: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.subtitle {
|
|
39
|
+
color: var(--roxy-muted, #71717a);
|
|
40
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
41
|
+
margin: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.summary-pills {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-wrap: wrap;
|
|
47
|
+
gap: var(--roxy-space-sm, 0.5rem);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.pill {
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
gap: 4px;
|
|
54
|
+
padding: 2px var(--roxy-space-sm, 0.5rem);
|
|
55
|
+
border-radius: var(--roxy-radius-full, 9999px);
|
|
56
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
57
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
58
|
+
border: 1px solid currentColor;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.pill--muted {
|
|
62
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
63
|
+
background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.pill--success {
|
|
67
|
+
color: var(--roxy-success-fg, #166534);
|
|
68
|
+
background: color-mix(in srgb, var(--roxy-success, #16a34a) 10%, transparent);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.pill--danger {
|
|
72
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
73
|
+
background: color-mix(in srgb, var(--roxy-danger, #dc2626) 10%, transparent);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
table {
|
|
77
|
+
width: 100%;
|
|
78
|
+
border-collapse: collapse;
|
|
79
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
th,
|
|
83
|
+
td {
|
|
84
|
+
padding: var(--roxy-space-sm, 0.5rem);
|
|
85
|
+
border-bottom: 1px solid var(--roxy-border, #e4e4e7);
|
|
86
|
+
text-align: left;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
th {
|
|
90
|
+
color: var(--roxy-muted, #71717a);
|
|
91
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
92
|
+
text-transform: uppercase;
|
|
93
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
94
|
+
letter-spacing: 0.06em;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.section-label {
|
|
98
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
99
|
+
color: var(--roxy-muted, #71717a);
|
|
100
|
+
text-transform: uppercase;
|
|
101
|
+
letter-spacing: 0.06em;
|
|
102
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
103
|
+
margin: 0 0 var(--roxy-space-xs, 0.25rem) 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.glyph {
|
|
107
|
+
font-size: 1.1em;
|
|
108
|
+
margin-right: 2px;
|
|
109
|
+
line-height: 1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.planet-cell {
|
|
113
|
+
display: flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
gap: 4px;
|
|
116
|
+
white-space: nowrap;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.retro-badge {
|
|
120
|
+
display: inline-block;
|
|
121
|
+
font-size: 0.7em;
|
|
122
|
+
padding: 1px 4px;
|
|
123
|
+
border-radius: var(--roxy-radius-sm, 4px);
|
|
124
|
+
background: color-mix(in srgb, var(--roxy-warning, #ea580c) 12%, transparent);
|
|
125
|
+
color: var(--roxy-warning-fg, #9a3412);
|
|
126
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
127
|
+
margin-left: 2px;
|
|
128
|
+
vertical-align: middle;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.speed {
|
|
132
|
+
font-variant-numeric: tabular-nums;
|
|
133
|
+
color: var(--roxy-muted, #71717a);
|
|
134
|
+
white-space: nowrap;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.speed-arrow {
|
|
138
|
+
font-size: 0.85em;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
td.num {
|
|
142
|
+
font-variant-numeric: tabular-nums;
|
|
143
|
+
color: var(--roxy-muted, #71717a);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.nature-harmonious {
|
|
147
|
+
color: var(--roxy-success-fg, #166534);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.nature-challenging {
|
|
151
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.nature-neutral {
|
|
155
|
+
color: var(--roxy-muted, #71717a);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.arrow-cell {
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
gap: 4px;
|
|
162
|
+
white-space: nowrap;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.interp-row td {
|
|
166
|
+
padding-top: 0;
|
|
167
|
+
padding-bottom: var(--roxy-space-sm, 0.5rem);
|
|
168
|
+
border-bottom: 1px solid var(--roxy-border, #e4e4e7);
|
|
169
|
+
color: var(--roxy-secondary, #475569);
|
|
170
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
171
|
+
line-height: 1.45;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.aspect-row td {
|
|
175
|
+
border-bottom: none;
|
|
176
|
+
padding-bottom: 4px;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.aspect-row.no-interp td {
|
|
180
|
+
border-bottom: 1px solid var(--roxy-border, #e4e4e7);
|
|
181
|
+
padding-bottom: var(--roxy-space-sm, 0.5rem);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.overflow-scroll {
|
|
185
|
+
overflow-x: auto;
|
|
186
|
+
-webkit-overflow-scrolling: touch;
|
|
187
|
+
}
|
|
188
|
+
`,
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
@property({ attribute: false })
|
|
192
|
+
data: TransitsResponse | null = null;
|
|
193
|
+
|
|
194
|
+
render() {
|
|
195
|
+
if (!this.data?.transitPlanets?.length) {
|
|
196
|
+
return html`<div class="roxy-empty" role="status">No transits data</div>`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const {
|
|
200
|
+
transitDate,
|
|
201
|
+
transitTime,
|
|
202
|
+
transitPlanets,
|
|
203
|
+
transitAspects,
|
|
204
|
+
summary,
|
|
205
|
+
} = this.data;
|
|
206
|
+
|
|
207
|
+
const dateStr = [formatDate(transitDate), formatTime(transitTime)]
|
|
208
|
+
.filter(Boolean)
|
|
209
|
+
.join(' ');
|
|
210
|
+
|
|
211
|
+
return html`<div class="wrap" aria-label="Transit positions table">
|
|
212
|
+
<div class="head">
|
|
213
|
+
<h2 class="title">Transits</h2>
|
|
214
|
+
${dateStr ? html`<p class="subtitle">${dateStr}</p>` : nothing}
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
${summary ? this.renderSummaryPills(summary) : nothing}
|
|
218
|
+
|
|
219
|
+
<div>
|
|
220
|
+
<p class="section-label">Planet positions</p>
|
|
221
|
+
<div class="overflow-scroll">
|
|
222
|
+
${this.renderPlanetsTable(transitPlanets)}
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
${
|
|
227
|
+
transitAspects?.length
|
|
228
|
+
? html`<div>
|
|
229
|
+
<p class="section-label">Transit aspects</p>
|
|
230
|
+
<div class="overflow-scroll">
|
|
231
|
+
${this.renderAspectsTable(transitAspects)}
|
|
232
|
+
</div>
|
|
233
|
+
</div>`
|
|
234
|
+
: nothing
|
|
235
|
+
}
|
|
236
|
+
</div>`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private renderSummaryPills(
|
|
240
|
+
summary: NonNullable<TransitsResponse['summary']>,
|
|
241
|
+
) {
|
|
242
|
+
return html`<div class="summary-pills" role="region" aria-label="Aspect summary">
|
|
243
|
+
<span class="pill pill--muted">
|
|
244
|
+
Total: ${summary.totalAspects}
|
|
245
|
+
</span>
|
|
246
|
+
<span class="pill pill--success">
|
|
247
|
+
Harmonious: ${summary.harmonious}
|
|
248
|
+
</span>
|
|
249
|
+
<span class="pill pill--danger">
|
|
250
|
+
Challenging: ${summary.challenging}
|
|
251
|
+
</span>
|
|
252
|
+
<span class="pill pill--muted">
|
|
253
|
+
Neutral: ${summary.neutral}
|
|
254
|
+
</span>
|
|
255
|
+
</div>`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private renderPlanetsTable(planets: TransitsResponse['transitPlanets']) {
|
|
259
|
+
return html`<table class="planets-table">
|
|
260
|
+
<thead>
|
|
261
|
+
<tr>
|
|
262
|
+
<th scope="col">Planet</th>
|
|
263
|
+
<th scope="col">Sign</th>
|
|
264
|
+
<th scope="col">Degree</th>
|
|
265
|
+
<th scope="col">Speed</th>
|
|
266
|
+
</tr>
|
|
267
|
+
</thead>
|
|
268
|
+
<tbody>
|
|
269
|
+
${planets.map((p) => {
|
|
270
|
+
const pGlyph = PLANET_GLYPH[capitalize(p.name)] ?? '';
|
|
271
|
+
const sGlyph = SIGN_GLYPH[capitalize(p.sign)] ?? '';
|
|
272
|
+
const speedArrow = p.speed >= 0 ? '↑' : '↓';
|
|
273
|
+
return html`<tr>
|
|
274
|
+
<td>
|
|
275
|
+
<div class="planet-cell">
|
|
276
|
+
<span class="glyph" aria-hidden="true">${pGlyph}</span>
|
|
277
|
+
${p.name}
|
|
278
|
+
${
|
|
279
|
+
p.isRetrograde
|
|
280
|
+
? html`<span class="retro-badge" aria-label="retrograde">R</span>`
|
|
281
|
+
: nothing
|
|
282
|
+
}
|
|
283
|
+
</div>
|
|
284
|
+
</td>
|
|
285
|
+
<td>
|
|
286
|
+
<div class="planet-cell">
|
|
287
|
+
<span class="glyph" aria-hidden="true">${sGlyph}</span>
|
|
288
|
+
${p.sign}
|
|
289
|
+
</div>
|
|
290
|
+
</td>
|
|
291
|
+
<td class="num">${formatNumber(p.degree, 2)}</td>
|
|
292
|
+
<td class="speed">
|
|
293
|
+
<span class="speed-arrow" aria-hidden="true">${speedArrow}</span>
|
|
294
|
+
${formatNumber(Math.abs(p.speed), 4)}
|
|
295
|
+
</td>
|
|
296
|
+
</tr>`;
|
|
297
|
+
})}
|
|
298
|
+
</tbody>
|
|
299
|
+
</table>`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private renderAspectsTable(
|
|
303
|
+
aspects: NonNullable<TransitsResponse['transitAspects']>,
|
|
304
|
+
) {
|
|
305
|
+
return html`<table class="aspects-table">
|
|
306
|
+
<thead>
|
|
307
|
+
<tr>
|
|
308
|
+
<th scope="col">Transit Planet</th>
|
|
309
|
+
<th scope="col">Natal Planet</th>
|
|
310
|
+
<th scope="col">Type</th>
|
|
311
|
+
<th scope="col">Orb</th>
|
|
312
|
+
<th scope="col">Status</th>
|
|
313
|
+
<th scope="col">Strength</th>
|
|
314
|
+
</tr>
|
|
315
|
+
</thead>
|
|
316
|
+
<tbody>
|
|
317
|
+
${aspects.map((a) => {
|
|
318
|
+
const tGlyph = PLANET_GLYPH[capitalize(a.transitPlanet)] ?? '';
|
|
319
|
+
const nGlyph = PLANET_GLYPH[capitalize(a.natalPlanet)] ?? '';
|
|
320
|
+
const natureClass = `nature-${(a.nature ?? '').toLowerCase()}`;
|
|
321
|
+
const summary = a.interpretation?.summary ?? '';
|
|
322
|
+
const rowClass = summary ? 'aspect-row' : 'aspect-row no-interp';
|
|
323
|
+
return html`<tr class=${rowClass}>
|
|
324
|
+
<td>
|
|
325
|
+
<div class="arrow-cell">
|
|
326
|
+
<span class="glyph" aria-hidden="true">${tGlyph}</span>
|
|
327
|
+
${a.transitPlanet}
|
|
328
|
+
</div>
|
|
329
|
+
</td>
|
|
330
|
+
<td>
|
|
331
|
+
<div class="arrow-cell">
|
|
332
|
+
<span class="glyph" aria-hidden="true">${nGlyph}</span>
|
|
333
|
+
${a.natalPlanet}
|
|
334
|
+
</div>
|
|
335
|
+
</td>
|
|
336
|
+
<td class=${natureClass}>${(a.type ?? '').toLowerCase()}</td>
|
|
337
|
+
<td class="num">${formatNumber(a.orb, 2)}</td>
|
|
338
|
+
<td>${a.isApplying ? 'Applying' : 'Separating'}</td>
|
|
339
|
+
<td class="num">${formatNumber(a.strength, 1)}</td>
|
|
340
|
+
</tr>
|
|
341
|
+
${
|
|
342
|
+
summary
|
|
343
|
+
? html`<tr class="interp-row">
|
|
344
|
+
<td colspan="6">${summary}</td>
|
|
345
|
+
</tr>`
|
|
346
|
+
: nothing
|
|
347
|
+
}`;
|
|
348
|
+
})}
|
|
349
|
+
</tbody>
|
|
350
|
+
</table>`;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
declare global {
|
|
355
|
+
interface HTMLElementTagNameMap {
|
|
356
|
+
'roxy-transits-table': RoxyTransitsTable;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
@@ -1,90 +1,30 @@
|
|
|
1
|
-
import { css, html, LitElement
|
|
1
|
+
import { css, html, LitElement } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
-
import {
|
|
3
|
+
import { RASHI_KEYS } from '../tokens/index.js';
|
|
4
4
|
import type { BirthChartResponse } from '../types/index.js';
|
|
5
5
|
import { baseStyles } from '../utils/base-styles.js';
|
|
6
|
+
import type { HouseDef } from '../utils/kundli-render.js';
|
|
7
|
+
import {
|
|
8
|
+
RASHI_TO_SIGN,
|
|
9
|
+
renderNorthFrame,
|
|
10
|
+
renderNorthHouseGroup,
|
|
11
|
+
renderSouthFrame,
|
|
12
|
+
renderSouthHouseGroup,
|
|
13
|
+
} from '../utils/kundli-render.js';
|
|
6
14
|
|
|
7
15
|
type RashiBucket = BirthChartResponse['aries'];
|
|
8
16
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// without casts.
|
|
17
|
+
// The /vedic-astrology/birth-chart response carries all 12 rashi keys
|
|
18
|
+
// (aries, taurus, ..., pisces), each shaped like the spec-typed `aries`
|
|
19
|
+
// bucket. This local alias indexes by rashi name without per-call casts.
|
|
13
20
|
type BirthChartByRashi = BirthChartResponse & Record<string, RashiBucket>;
|
|
14
21
|
|
|
15
|
-
interface KundliHouse {
|
|
16
|
-
house: number;
|
|
17
|
-
sign: string;
|
|
18
|
-
planets: string[];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const SOUTH_HOUSE_CENTERS: Record<number, { x: number; y: number }> = {
|
|
22
|
-
1: { x: 150, y: 58 },
|
|
23
|
-
2: { x: 205, y: 52 },
|
|
24
|
-
3: { x: 253, y: 112 },
|
|
25
|
-
4: { x: 243, y: 150 },
|
|
26
|
-
5: { x: 253, y: 188 },
|
|
27
|
-
6: { x: 205, y: 248 },
|
|
28
|
-
7: { x: 150, y: 242 },
|
|
29
|
-
8: { x: 95, y: 248 },
|
|
30
|
-
9: { x: 47, y: 188 },
|
|
31
|
-
10: { x: 57, y: 150 },
|
|
32
|
-
11: { x: 47, y: 112 },
|
|
33
|
-
12: { x: 95, y: 52 },
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const SOUTH_SIGN_POSITIONS: Record<number, { x: number; y: number }> = {
|
|
37
|
-
1: { x: 150, y: 35 },
|
|
38
|
-
2: { x: 222, y: 40 },
|
|
39
|
-
3: { x: 265, y: 100 },
|
|
40
|
-
4: { x: 265, y: 150 },
|
|
41
|
-
5: { x: 265, y: 200 },
|
|
42
|
-
6: { x: 222, y: 260 },
|
|
43
|
-
7: { x: 150, y: 265 },
|
|
44
|
-
8: { x: 78, y: 260 },
|
|
45
|
-
9: { x: 35, y: 200 },
|
|
46
|
-
10: { x: 35, y: 150 },
|
|
47
|
-
11: { x: 35, y: 100 },
|
|
48
|
-
12: { x: 78, y: 40 },
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const RASHI_KEYS = [
|
|
52
|
-
'aries',
|
|
53
|
-
'taurus',
|
|
54
|
-
'gemini',
|
|
55
|
-
'cancer',
|
|
56
|
-
'leo',
|
|
57
|
-
'virgo',
|
|
58
|
-
'libra',
|
|
59
|
-
'scorpio',
|
|
60
|
-
'sagittarius',
|
|
61
|
-
'capricorn',
|
|
62
|
-
'aquarius',
|
|
63
|
-
'pisces',
|
|
64
|
-
] as const;
|
|
65
|
-
|
|
66
|
-
const RASHI_TO_SIGN: Record<string, string> = {
|
|
67
|
-
aries: 'Aries',
|
|
68
|
-
taurus: 'Taurus',
|
|
69
|
-
gemini: 'Gemini',
|
|
70
|
-
cancer: 'Cancer',
|
|
71
|
-
leo: 'Leo',
|
|
72
|
-
virgo: 'Virgo',
|
|
73
|
-
libra: 'Libra',
|
|
74
|
-
scorpio: 'Scorpio',
|
|
75
|
-
sagittarius: 'Sagittarius',
|
|
76
|
-
capricorn: 'Capricorn',
|
|
77
|
-
aquarius: 'Aquarius',
|
|
78
|
-
pisces: 'Pisces',
|
|
79
|
-
};
|
|
80
|
-
|
|
81
22
|
/**
|
|
82
23
|
* Vedic kundli (D1 Rashi chart). South Indian style by default. Pass `data`
|
|
83
|
-
* from /vedic-astrology/birth-chart. North Indian style via
|
|
24
|
+
* from /vedic-astrology/birth-chart. North Indian style via chartStyle="north".
|
|
84
25
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* DOM color-probing hook in favor of CSS custom properties on :host.
|
|
26
|
+
* Theming flows through CSS custom properties on :host, so the chart adopts
|
|
27
|
+
* the host page palette without runtime color probing.
|
|
88
28
|
*/
|
|
89
29
|
@customElement('roxy-vedic-kundli')
|
|
90
30
|
export class RoxyVedicKundli extends LitElement {
|
|
@@ -122,6 +62,12 @@ export class RoxyVedicKundli extends LitElement {
|
|
|
122
62
|
font-weight: 600;
|
|
123
63
|
font-family: var(--roxy-font-sans);
|
|
124
64
|
}
|
|
65
|
+
.house-num {
|
|
66
|
+
fill: var(--roxy-muted, #71717a);
|
|
67
|
+
font-size: 9px;
|
|
68
|
+
font-weight: 400;
|
|
69
|
+
font-family: var(--roxy-font-sans);
|
|
70
|
+
}
|
|
125
71
|
.lagna-marker {
|
|
126
72
|
fill: var(--roxy-accent-fg, #b45309);
|
|
127
73
|
font-size: 8px;
|
|
@@ -143,18 +89,23 @@ export class RoxyVedicKundli extends LitElement {
|
|
|
143
89
|
@property({ type: String, reflect: true, attribute: 'chart-style' })
|
|
144
90
|
chartStyle: 'south' | 'north' = 'south';
|
|
145
91
|
|
|
146
|
-
private buildHouses():
|
|
92
|
+
private buildHouses(): HouseDef[] {
|
|
147
93
|
if (!this.data) return [];
|
|
148
94
|
const data = this.data as BirthChartByRashi;
|
|
149
|
-
const
|
|
95
|
+
const lagnaSign = this.data?.meta?.Lagna?.rashi ?? '';
|
|
96
|
+
const houses: HouseDef[] = [];
|
|
150
97
|
for (let i = 0; i < 12; i++) {
|
|
151
98
|
const key = RASHI_KEYS[i];
|
|
152
99
|
const bucket = data[key];
|
|
153
100
|
const planets = (bucket?.signs ?? []).map((p) => p.graha).filter(Boolean);
|
|
101
|
+
const sign = RASHI_TO_SIGN[key] ?? '';
|
|
154
102
|
houses.push({
|
|
155
|
-
|
|
156
|
-
sign
|
|
103
|
+
number: i + 1,
|
|
104
|
+
sign,
|
|
157
105
|
planets,
|
|
106
|
+
isLagna: lagnaSign
|
|
107
|
+
? lagnaSign.toLowerCase() === sign.toLowerCase()
|
|
108
|
+
: false,
|
|
158
109
|
});
|
|
159
110
|
}
|
|
160
111
|
return houses;
|
|
@@ -164,6 +115,7 @@ export class RoxyVedicKundli extends LitElement {
|
|
|
164
115
|
if (!this.data)
|
|
165
116
|
return html`<div class="roxy-empty" role="status">No kundli data</div>`;
|
|
166
117
|
const houses = this.buildHouses();
|
|
118
|
+
const isNorth = this.chartStyle === 'north';
|
|
167
119
|
|
|
168
120
|
return html`<div class="wrap">
|
|
169
121
|
<h2 class="title">Vedic kundli</h2>
|
|
@@ -173,74 +125,17 @@ export class RoxyVedicKundli extends LitElement {
|
|
|
173
125
|
aria-label="Vedic birth chart with twelve sign houses"
|
|
174
126
|
>
|
|
175
127
|
<title>Vedic kundli</title>
|
|
176
|
-
|
|
177
|
-
<polygon
|
|
178
|
-
class="line"
|
|
179
|
-
points="220,80 220,220 80,220 80,80"
|
|
180
|
-
stroke-width="1"
|
|
181
|
-
fill="none"
|
|
182
|
-
/>
|
|
183
|
-
<line class="line" x1="150" y1="10" x2="80" y2="80" stroke-width="1" />
|
|
184
|
-
<line class="line" x1="150" y1="10" x2="220" y2="80" stroke-width="1" />
|
|
185
|
-
<line class="line" x1="290" y1="150" x2="220" y2="80" stroke-width="1" />
|
|
186
|
-
<line class="line" x1="290" y1="150" x2="220" y2="220" stroke-width="1" />
|
|
187
|
-
<line class="line" x1="150" y1="290" x2="220" y2="220" stroke-width="1" />
|
|
188
|
-
<line class="line" x1="150" y1="290" x2="80" y2="220" stroke-width="1" />
|
|
189
|
-
<line class="line" x1="10" y1="150" x2="80" y2="220" stroke-width="1" />
|
|
190
|
-
<line class="line" x1="10" y1="150" x2="80" y2="80" stroke-width="1" />
|
|
191
|
-
${houses.map((h) => this.renderHouseGroup(h))}
|
|
192
|
-
</svg>
|
|
193
|
-
</div>`;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
private isLagna(h: KundliHouse): boolean {
|
|
197
|
-
const ascSign = this.data?.meta?.Lagna?.rashi;
|
|
198
|
-
if (!ascSign) return false;
|
|
199
|
-
return ascSign.toLowerCase() === h.sign.toLowerCase();
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private renderHouseGroup(h: KundliHouse) {
|
|
203
|
-
const center = SOUTH_HOUSE_CENTERS[h.house];
|
|
204
|
-
const signPos = SOUTH_SIGN_POSITIONS[h.house];
|
|
205
|
-
if (!center || !signPos) return nothing;
|
|
206
|
-
const signAbbr = SIGN_ABBR[h.sign] ?? '';
|
|
207
|
-
const planets = h.planets ?? [];
|
|
208
|
-
const isLagna = this.isLagna(h);
|
|
209
|
-
return svg`
|
|
210
|
-
<g>
|
|
211
|
-
${
|
|
212
|
-
isLagna
|
|
213
|
-
? svg`<rect class="lagna-bg" x=${center.x - 30} y=${center.y - 28} width="60" height="56" rx="6" />`
|
|
214
|
-
: nothing
|
|
215
|
-
}
|
|
128
|
+
${isNorth ? renderNorthFrame() : renderSouthFrame()}
|
|
216
129
|
${
|
|
217
|
-
|
|
218
|
-
?
|
|
219
|
-
:
|
|
130
|
+
isNorth
|
|
131
|
+
? houses.map((h) => renderNorthHouseGroup(h))
|
|
132
|
+
: houses.map((h) => renderSouthHouseGroup(h))
|
|
220
133
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
? svg`<text class="lagna-marker" x=${center.x} y=${center.y - 18} text-anchor="middle" dominant-baseline="central">LAGNA</text>`
|
|
224
|
-
: nothing
|
|
225
|
-
}
|
|
226
|
-
${planets.map((planet, j) => {
|
|
227
|
-
const abbr = PLANET_ABBR[capitalize(planet)] ?? planet.slice(0, 2);
|
|
228
|
-
const lineHeight = 13;
|
|
229
|
-
const baseY = isLagna ? center.y + 8 : center.y;
|
|
230
|
-
const startY = baseY - ((planets.length - 1) * lineHeight) / 2;
|
|
231
|
-
const yPos = startY + j * lineHeight;
|
|
232
|
-
return svg`<text class="planet-text" x=${center.x} y=${yPos} text-anchor="middle" dominant-baseline="central">${abbr}</text>`;
|
|
233
|
-
})}
|
|
234
|
-
</g>
|
|
235
|
-
`;
|
|
134
|
+
</svg>
|
|
135
|
+
</div>`;
|
|
236
136
|
}
|
|
237
137
|
}
|
|
238
138
|
|
|
239
|
-
function capitalize(s: string): string {
|
|
240
|
-
if (!s) return '';
|
|
241
|
-
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
242
|
-
}
|
|
243
|
-
|
|
244
139
|
declare global {
|
|
245
140
|
interface HTMLElementTagNameMap {
|
|
246
141
|
'roxy-vedic-kundli': RoxyVedicKundli;
|