@roxyapi/ui 0.1.3 → 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 +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 +391 -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 +1872 -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 +515 -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 +2693 -971
- 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 +2712 -990
- 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 +350 -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,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
|
+
}
|
package/src/components/data.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing, type TemplateResult } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
import { baseStyles } from '../utils/base-styles.js';
|
|
4
|
+
import { humanize } from '../utils/string.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Generic fallback renderer. Accepts ANY OpenAPI response shape and renders
|
|
7
|
-
* via field-name heuristics so future spec additions render reasonably
|
|
8
|
-
* hand-wired components.
|
|
7
|
+
* Generic fallback renderer. Accepts ANY OpenAPI response shape and renders
|
|
8
|
+
* it via field-name heuristics so future spec additions render reasonably
|
|
9
|
+
* without hand-wired components.
|
|
9
10
|
*
|
|
10
11
|
* Heuristic order:
|
|
11
12
|
* 1. Primitive (string, number, boolean) -> single line.
|
|
@@ -14,9 +15,8 @@ import { baseStyles } from '../utils/base-styles.js';
|
|
|
14
15
|
* 4. Object with title-like field -> card with key/value rows.
|
|
15
16
|
* 5. Otherwise -> definition list of all keys.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* instead of this fallback.
|
|
18
|
+
* When a schema declares an `x-roxy-ui` hint, a future dispatcher can opt
|
|
19
|
+
* into a hand-tuned component instead of this fallback.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
type Json = string | number | boolean | null | Json[] | { [key: string]: Json };
|
|
@@ -196,7 +196,7 @@ export class RoxyData extends LitElement {
|
|
|
196
196
|
return html`<table class="roxy-table" role="table">
|
|
197
197
|
<thead>
|
|
198
198
|
<tr>
|
|
199
|
-
${keys.map((k) => html`<th>${
|
|
199
|
+
${keys.map((k) => html`<th>${humanize(k)}</th>`)}
|
|
200
200
|
</tr>
|
|
201
201
|
</thead>
|
|
202
202
|
<tbody>
|
|
@@ -246,7 +246,7 @@ export class RoxyData extends LitElement {
|
|
|
246
246
|
? html`<dl class="roxy-rows">
|
|
247
247
|
${rows.map(
|
|
248
248
|
([k, v]) => html`
|
|
249
|
-
<dt>${
|
|
249
|
+
<dt>${humanize(k)}</dt>
|
|
250
250
|
<dd>${this.renderField(v)}</dd>
|
|
251
251
|
`,
|
|
252
252
|
)}
|
|
@@ -290,13 +290,6 @@ export class RoxyData extends LitElement {
|
|
|
290
290
|
}
|
|
291
291
|
return Array.from(seen);
|
|
292
292
|
}
|
|
293
|
-
|
|
294
|
-
private humanize(key: string): string {
|
|
295
|
-
return key
|
|
296
|
-
.replace(/[_-]+/g, ' ')
|
|
297
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
298
|
-
.replace(/^\w/, (c) => c.toUpperCase());
|
|
299
|
-
}
|
|
300
293
|
}
|
|
301
294
|
|
|
302
295
|
declare global {
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import { PLANET_GLYPH, RASHI_KEYS } from '../tokens/index.js';
|
|
4
|
+
import type { DivisionalChartResponse } from '../types/index.js';
|
|
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';
|
|
14
|
+
|
|
15
|
+
type RashiBucket = {
|
|
16
|
+
rashi?: string;
|
|
17
|
+
signs?: Array<{ graha: string; isRetrograde?: boolean }>;
|
|
18
|
+
};
|
|
19
|
+
type ChartByRashi = { [key: string]: RashiBucket | unknown };
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Divisional chart renderer (D2-D60). Accepts a DivisionalChartResponse and
|
|
23
|
+
* renders the same south/north kundli wheel as the birth chart, plus division
|
|
24
|
+
* metadata and Vargottama planet pills.
|
|
25
|
+
*/
|
|
26
|
+
@customElement('roxy-divisional-chart')
|
|
27
|
+
export class RoxyDivisionalChart extends LitElement {
|
|
28
|
+
static styles = [
|
|
29
|
+
baseStyles,
|
|
30
|
+
css`
|
|
31
|
+
.wrap {
|
|
32
|
+
display: grid;
|
|
33
|
+
gap: var(--roxy-space-md, 1rem);
|
|
34
|
+
}
|
|
35
|
+
.header {
|
|
36
|
+
display: grid;
|
|
37
|
+
gap: var(--roxy-space-xs, 0.25rem);
|
|
38
|
+
}
|
|
39
|
+
.title {
|
|
40
|
+
font-size: var(--roxy-text-lg, 1.125rem);
|
|
41
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
42
|
+
margin: 0;
|
|
43
|
+
}
|
|
44
|
+
.division-meta {
|
|
45
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
46
|
+
color: var(--roxy-muted, #71717a);
|
|
47
|
+
margin: 0;
|
|
48
|
+
}
|
|
49
|
+
.significance {
|
|
50
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
51
|
+
color: var(--roxy-muted, #71717a);
|
|
52
|
+
border-left: 2px solid var(--roxy-border, #e4e4e7);
|
|
53
|
+
padding-left: var(--roxy-space-sm, 0.5rem);
|
|
54
|
+
margin: 0;
|
|
55
|
+
}
|
|
56
|
+
svg {
|
|
57
|
+
display: block;
|
|
58
|
+
width: 100%;
|
|
59
|
+
max-width: 360px;
|
|
60
|
+
margin: 0 auto;
|
|
61
|
+
}
|
|
62
|
+
.line {
|
|
63
|
+
fill: transparent;
|
|
64
|
+
stroke: var(--roxy-border, #e4e4e7);
|
|
65
|
+
}
|
|
66
|
+
.sign-text {
|
|
67
|
+
fill: var(--roxy-muted, #71717a);
|
|
68
|
+
font-size: 9px;
|
|
69
|
+
font-weight: 500;
|
|
70
|
+
font-family: var(--roxy-font-sans);
|
|
71
|
+
}
|
|
72
|
+
.planet-text {
|
|
73
|
+
fill: var(--roxy-fg, #0a0a0a);
|
|
74
|
+
font-size: 11px;
|
|
75
|
+
font-weight: 600;
|
|
76
|
+
font-family: var(--roxy-font-sans);
|
|
77
|
+
}
|
|
78
|
+
.house-num {
|
|
79
|
+
fill: var(--roxy-muted, #71717a);
|
|
80
|
+
font-size: 9px;
|
|
81
|
+
font-weight: 400;
|
|
82
|
+
font-family: var(--roxy-font-sans);
|
|
83
|
+
}
|
|
84
|
+
.lagna-marker {
|
|
85
|
+
fill: var(--roxy-accent-fg, #b45309);
|
|
86
|
+
font-size: 8px;
|
|
87
|
+
font-weight: 700;
|
|
88
|
+
font-family: var(--roxy-font-sans);
|
|
89
|
+
letter-spacing: 0.05em;
|
|
90
|
+
}
|
|
91
|
+
.lagna-bg {
|
|
92
|
+
fill: color-mix(in srgb, var(--roxy-accent, #f59e0b) 12%, transparent);
|
|
93
|
+
stroke: color-mix(in srgb, var(--roxy-accent, #f59e0b) 45%, transparent);
|
|
94
|
+
stroke-width: 0.8;
|
|
95
|
+
}
|
|
96
|
+
.vargottama-row {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-wrap: wrap;
|
|
99
|
+
gap: var(--roxy-space-xs, 0.25rem);
|
|
100
|
+
align-items: center;
|
|
101
|
+
}
|
|
102
|
+
.vargottama-label {
|
|
103
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
104
|
+
color: var(--roxy-muted, #71717a);
|
|
105
|
+
font-weight: 500;
|
|
106
|
+
margin-right: var(--roxy-space-xs, 0.25rem);
|
|
107
|
+
}
|
|
108
|
+
.vargottama-pill {
|
|
109
|
+
display: inline-flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
gap: 0.2em;
|
|
112
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
113
|
+
font-weight: 600;
|
|
114
|
+
padding: 0.15em 0.6em;
|
|
115
|
+
border-radius: 999px;
|
|
116
|
+
background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 22%, transparent);
|
|
117
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
118
|
+
border: 1px solid color-mix(in srgb, var(--roxy-accent, #f59e0b) 45%, transparent);
|
|
119
|
+
}
|
|
120
|
+
`,
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
@property({ attribute: false })
|
|
124
|
+
data: DivisionalChartResponse | null = null;
|
|
125
|
+
|
|
126
|
+
@property({ type: String, reflect: true, attribute: 'chart-style' })
|
|
127
|
+
chartStyle: 'south' | 'north' = 'south';
|
|
128
|
+
|
|
129
|
+
private buildHouses(): HouseDef[] {
|
|
130
|
+
if (!this.data) return [];
|
|
131
|
+
const chart = this.data.chart as ChartByRashi;
|
|
132
|
+
const meta =
|
|
133
|
+
(this.data.chart as { meta?: Record<string, { rashi?: string }> }).meta ??
|
|
134
|
+
{};
|
|
135
|
+
const lagnaSign = meta.Lagna?.rashi ?? '';
|
|
136
|
+
const houses: HouseDef[] = [];
|
|
137
|
+
for (let i = 0; i < 12; i++) {
|
|
138
|
+
const key = RASHI_KEYS[i];
|
|
139
|
+
const bucket = chart[key] as RashiBucket | undefined;
|
|
140
|
+
const planets = (bucket?.signs ?? []).map((p) => p.graha).filter(Boolean);
|
|
141
|
+
const sign = RASHI_TO_SIGN[key] ?? '';
|
|
142
|
+
houses.push({
|
|
143
|
+
number: i + 1,
|
|
144
|
+
sign,
|
|
145
|
+
planets,
|
|
146
|
+
isLagna: lagnaSign
|
|
147
|
+
? lagnaSign.toLowerCase() === sign.toLowerCase()
|
|
148
|
+
: false,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return houses;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
render() {
|
|
155
|
+
if (!this.data)
|
|
156
|
+
return html`<div class="roxy-empty" role="status">No divisional chart data</div>`;
|
|
157
|
+
|
|
158
|
+
const { division, vargottama } = this.data;
|
|
159
|
+
const houses = this.buildHouses();
|
|
160
|
+
const isNorth = this.chartStyle === 'north';
|
|
161
|
+
|
|
162
|
+
return html`<div class="wrap">
|
|
163
|
+
<div class="header">
|
|
164
|
+
<h2 class="title">
|
|
165
|
+
D${division.number} ${division.name}
|
|
166
|
+
${
|
|
167
|
+
division.sanskritName && division.sanskritName !== division.name
|
|
168
|
+
? html`<span class="division-meta"> · ${division.sanskritName}</span>`
|
|
169
|
+
: nothing
|
|
170
|
+
}
|
|
171
|
+
</h2>
|
|
172
|
+
${
|
|
173
|
+
division.significance
|
|
174
|
+
? html`<p class="significance">${division.significance}</p>`
|
|
175
|
+
: nothing
|
|
176
|
+
}
|
|
177
|
+
</div>
|
|
178
|
+
|
|
179
|
+
<svg
|
|
180
|
+
viewBox="0 0 300 300"
|
|
181
|
+
role="img"
|
|
182
|
+
aria-label="D${division.number} ${division.name} divisional chart with twelve sign houses"
|
|
183
|
+
>
|
|
184
|
+
<title>D${division.number} ${division.name}</title>
|
|
185
|
+
${isNorth ? renderNorthFrame() : renderSouthFrame()}
|
|
186
|
+
${
|
|
187
|
+
isNorth
|
|
188
|
+
? houses.map((h) => renderNorthHouseGroup(h))
|
|
189
|
+
: houses.map((h) => renderSouthHouseGroup(h))
|
|
190
|
+
}
|
|
191
|
+
</svg>
|
|
192
|
+
|
|
193
|
+
${
|
|
194
|
+
vargottama && vargottama.length > 0
|
|
195
|
+
? html`<div class="vargottama-row" role="list" aria-label="Vargottama planets">
|
|
196
|
+
<span class="vargottama-label">Vargottama:</span>
|
|
197
|
+
${vargottama.map(
|
|
198
|
+
(planet) =>
|
|
199
|
+
html`<span class="vargottama-pill" role="listitem">
|
|
200
|
+
${PLANET_GLYPH[planet] ?? ''} ${planet}
|
|
201
|
+
</span>`,
|
|
202
|
+
)}
|
|
203
|
+
</div>`
|
|
204
|
+
: nothing
|
|
205
|
+
}
|
|
206
|
+
</div>`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
declare global {
|
|
211
|
+
interface HTMLElementTagNameMap {
|
|
212
|
+
'roxy-divisional-chart': RoxyDivisionalChart;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -65,25 +65,24 @@ export class RoxyDoshaCard extends LitElement {
|
|
|
65
65
|
background: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);
|
|
66
66
|
color: var(--roxy-danger-fg, #991b1b);
|
|
67
67
|
}
|
|
68
|
-
.severity {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
background: var(--roxy-danger, #dc2626);
|
|
68
|
+
.severity-bar {
|
|
69
|
+
position: relative;
|
|
70
|
+
width: 100%;
|
|
71
|
+
height: 8px;
|
|
72
|
+
background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 30%, transparent);
|
|
73
|
+
border-radius: 4px;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
}
|
|
76
|
+
.severity-fill {
|
|
77
|
+
display: block;
|
|
78
|
+
height: 100%;
|
|
79
|
+
transition: width var(--roxy-motion-duration, 200ms) ease-out;
|
|
80
|
+
border-radius: 4px;
|
|
81
|
+
}
|
|
82
|
+
@media (prefers-reduced-motion: reduce) {
|
|
83
|
+
.severity-fill {
|
|
84
|
+
transition: none;
|
|
85
|
+
}
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
.description {
|
|
@@ -128,7 +127,24 @@ export class RoxyDoshaCard extends LitElement {
|
|
|
128
127
|
|
|
129
128
|
const present = !!d.present;
|
|
130
129
|
const label = DOSHA_LABELS[this.type] ?? this.type;
|
|
131
|
-
const
|
|
130
|
+
const sevLower = (d.severity ?? '').toLowerCase();
|
|
131
|
+
const tier =
|
|
132
|
+
sevLower === 'severe'
|
|
133
|
+
? 3
|
|
134
|
+
: sevLower === 'moderate'
|
|
135
|
+
? 2
|
|
136
|
+
: sevLower === 'mild'
|
|
137
|
+
? 1
|
|
138
|
+
: 0;
|
|
139
|
+
const pct = tier * 33;
|
|
140
|
+
const barColor =
|
|
141
|
+
tier === 3
|
|
142
|
+
? 'var(--roxy-danger)'
|
|
143
|
+
: tier === 2
|
|
144
|
+
? 'var(--roxy-warning)'
|
|
145
|
+
: tier === 1
|
|
146
|
+
? 'var(--roxy-success)'
|
|
147
|
+
: 'transparent';
|
|
132
148
|
|
|
133
149
|
return html`<article
|
|
134
150
|
class="card"
|
|
@@ -136,23 +152,24 @@ export class RoxyDoshaCard extends LitElement {
|
|
|
136
152
|
>
|
|
137
153
|
<header class="head">
|
|
138
154
|
<h2 class="title">${label}</h2>
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
</span>
|
|
143
|
-
${
|
|
144
|
-
d.severity
|
|
145
|
-
? html`<span
|
|
146
|
-
class=${`severity ${sevClass}`}
|
|
147
|
-
role="img"
|
|
148
|
-
aria-label=${`Severity ${d.severity}`}
|
|
149
|
-
>
|
|
150
|
-
<span></span><span></span><span></span>
|
|
151
|
-
</span>`
|
|
152
|
-
: nothing
|
|
153
|
-
}
|
|
154
|
-
</div>
|
|
155
|
+
<span class=${`badge ${present ? 'present' : 'absent'}`}>
|
|
156
|
+
${present ? 'Present' : 'Absent'}
|
|
157
|
+
</span>
|
|
155
158
|
</header>
|
|
159
|
+
${
|
|
160
|
+
d.severity
|
|
161
|
+
? html`<div
|
|
162
|
+
class="severity-bar"
|
|
163
|
+
role="meter"
|
|
164
|
+
aria-valuemin="0"
|
|
165
|
+
aria-valuemax="3"
|
|
166
|
+
aria-valuenow="${tier}"
|
|
167
|
+
aria-label="Severity ${d.severity}"
|
|
168
|
+
>
|
|
169
|
+
<span class="severity-fill" style="width: ${pct}%; background: ${barColor};"></span>
|
|
170
|
+
</div>`
|
|
171
|
+
: nothing
|
|
172
|
+
}
|
|
156
173
|
${d.description ? html`<p class="description">${d.description}</p>` : nothing}
|
|
157
174
|
${this.renderEffects(d)}
|
|
158
175
|
${
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
3
3
|
import { baseStyles } from '../utils/base-styles.js';
|
|
4
|
+
import { humanize } from '../utils/string.js';
|
|
4
5
|
|
|
5
6
|
interface OpenApiSchemaRef {
|
|
6
7
|
$ref?: string;
|
|
@@ -487,13 +488,6 @@ export class RoxyEndpointForm extends LitElement {
|
|
|
487
488
|
}
|
|
488
489
|
}
|
|
489
490
|
|
|
490
|
-
function humanize(s: string): string {
|
|
491
|
-
return s
|
|
492
|
-
.replace(/[_-]+/g, ' ')
|
|
493
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
494
|
-
.replace(/^\w/, (c) => c.toUpperCase());
|
|
495
|
-
}
|
|
496
|
-
|
|
497
491
|
declare global {
|
|
498
492
|
interface HTMLElementTagNameMap {
|
|
499
493
|
'roxy-endpoint-form': RoxyEndpointForm;
|