@roxyapi/ui 0.1.1 → 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/AGENTS.md +2 -2
- package/LICENSE +21 -0
- package/README.md +505 -0
- 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 +9 -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
|
@@ -1,34 +1,9 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
3
|
+
import type { GetCardResponse, GetDailyCardResponse } from '../types/index.js';
|
|
3
4
|
import { baseStyles } from '../utils/base-styles.js';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
id?: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
arcana?: 'major' | 'minor' | string;
|
|
9
|
-
number?: number | string;
|
|
10
|
-
position?: string;
|
|
11
|
-
reversed?: boolean;
|
|
12
|
-
keywords?: string[];
|
|
13
|
-
meaning?:
|
|
14
|
-
| string
|
|
15
|
-
| {
|
|
16
|
-
upright?: string;
|
|
17
|
-
reversed?: string;
|
|
18
|
-
spiritual?: string;
|
|
19
|
-
emotional?: string;
|
|
20
|
-
physical?: string;
|
|
21
|
-
};
|
|
22
|
-
imageUrl?: string;
|
|
23
|
-
upright?: { meaning?: string; keywords?: string[] };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface TarotData {
|
|
27
|
-
date?: string;
|
|
28
|
-
seed?: string;
|
|
29
|
-
card?: TarotCard;
|
|
30
|
-
dailyMessage?: string;
|
|
31
|
-
}
|
|
6
|
+
type TarotData = GetCardResponse | GetDailyCardResponse;
|
|
32
7
|
|
|
33
8
|
/**
|
|
34
9
|
* Tarot card. Renders /tarot/cards/{id} or /tarot/daily. Click to flip
|
|
@@ -92,11 +67,6 @@ export class RoxyTarotCard extends LitElement {
|
|
|
92
67
|
letter-spacing: 0.06em;
|
|
93
68
|
margin-bottom: var(--roxy-space-sm, 0.5rem);
|
|
94
69
|
}
|
|
95
|
-
.position {
|
|
96
|
-
color: var(--roxy-info, #0284c7);
|
|
97
|
-
margin-left: var(--roxy-space-xs, 0.25rem);
|
|
98
|
-
text-transform: capitalize;
|
|
99
|
-
}
|
|
100
70
|
|
|
101
71
|
.message {
|
|
102
72
|
color: var(--roxy-fg, #0a0a0a);
|
|
@@ -137,37 +107,28 @@ export class RoxyTarotCard extends LitElement {
|
|
|
137
107
|
];
|
|
138
108
|
|
|
139
109
|
@property({ attribute: false })
|
|
140
|
-
data: TarotData |
|
|
110
|
+
data: TarotData | null = null;
|
|
141
111
|
|
|
142
112
|
@state()
|
|
143
113
|
private flipped = false;
|
|
144
114
|
|
|
145
|
-
private getCard(): TarotCard | null {
|
|
146
|
-
if (!this.data) return null;
|
|
147
|
-
if ('card' in this.data && this.data.card) return this.data.card;
|
|
148
|
-
return this.data as TarotCard;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
115
|
private toggleFlip = () => {
|
|
152
116
|
this.flipped = !this.flipped;
|
|
153
117
|
};
|
|
154
118
|
|
|
155
119
|
render() {
|
|
156
|
-
const
|
|
157
|
-
if (!
|
|
120
|
+
const d = this.data;
|
|
121
|
+
if (!d)
|
|
158
122
|
return html`<div class="roxy-empty" role="status">No tarot data</div>`;
|
|
159
123
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const
|
|
168
|
-
this.data && 'dailyMessage' in this.data
|
|
169
|
-
? this.data.dailyMessage
|
|
170
|
-
: undefined;
|
|
124
|
+
if ('card' in d) return this.renderDailyCard(d);
|
|
125
|
+
return this.renderFullCard(d);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private renderDailyCard(d: GetDailyCardResponse) {
|
|
129
|
+
const card = d.card;
|
|
130
|
+
const isReversed = this.flipped !== Boolean(card.reversed);
|
|
131
|
+
const keywords = card.keywords ?? [];
|
|
171
132
|
|
|
172
133
|
return html`<article class="card" aria-label=${card.name ?? 'Tarot card'}>
|
|
173
134
|
<div class="image-wrap">
|
|
@@ -197,21 +158,74 @@ export class RoxyTarotCard extends LitElement {
|
|
|
197
158
|
<div>
|
|
198
159
|
<div class="meta">
|
|
199
160
|
${card.arcana ? html`${card.arcana} arcana` : nothing}
|
|
200
|
-
${card.number !== undefined && card.number !== null ? html` · ${card.number}` : nothing}
|
|
201
161
|
${isReversed ? html` · reversed` : nothing}
|
|
202
|
-
${
|
|
203
|
-
card.position
|
|
204
|
-
? html`<span class="position">${card.position}</span>`
|
|
205
|
-
: nothing
|
|
206
|
-
}
|
|
207
162
|
</div>
|
|
208
163
|
<h2 class="title">${card.name ?? 'Tarot card'}</h2>
|
|
209
|
-
${dailyMessage ? html`<p class="message">${dailyMessage}</p>` : nothing}
|
|
210
|
-
${meaning ? html`<p>${meaning}</p>` : nothing}
|
|
164
|
+
${d.dailyMessage ? html`<p class="message">${d.dailyMessage}</p>` : nothing}
|
|
165
|
+
${card.meaning ? html`<p>${card.meaning}</p>` : nothing}
|
|
166
|
+
${
|
|
167
|
+
keywords.length > 0
|
|
168
|
+
? html`<div class="chips">
|
|
169
|
+
${keywords.map((k) => html`<span>${k}</span>`)}
|
|
170
|
+
</div>`
|
|
171
|
+
: nothing
|
|
172
|
+
}
|
|
173
|
+
<button
|
|
174
|
+
class="flip"
|
|
175
|
+
type="button"
|
|
176
|
+
@click=${this.toggleFlip}
|
|
177
|
+
aria-pressed=${this.flipped ? 'true' : 'false'}
|
|
178
|
+
>
|
|
179
|
+
Flip card
|
|
180
|
+
</button>
|
|
181
|
+
</div>
|
|
182
|
+
</article>`;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private renderFullCard(d: GetCardResponse) {
|
|
186
|
+
const isReversed = this.flipped;
|
|
187
|
+
const orientedMeaning = isReversed ? d.reversed : d.upright;
|
|
188
|
+
const keywords = isReversed
|
|
189
|
+
? (d.keywords?.reversed ?? [])
|
|
190
|
+
: (d.keywords?.upright ?? []);
|
|
191
|
+
|
|
192
|
+
return html`<article class="card" aria-label=${d.name ?? 'Tarot card'}>
|
|
193
|
+
<div class="image-wrap">
|
|
194
|
+
${
|
|
195
|
+
d.imageUrl
|
|
196
|
+
? html`<img
|
|
197
|
+
class=${`image ${isReversed ? 'reversed' : ''}`}
|
|
198
|
+
src=${d.imageUrl}
|
|
199
|
+
alt=${d.name ?? 'Tarot card'}
|
|
200
|
+
tabindex="0"
|
|
201
|
+
@click=${this.toggleFlip}
|
|
202
|
+
@keydown=${(e: KeyboardEvent) => {
|
|
203
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
204
|
+
e.preventDefault();
|
|
205
|
+
this.toggleFlip();
|
|
206
|
+
}
|
|
207
|
+
}}
|
|
208
|
+
/>`
|
|
209
|
+
: html`<div
|
|
210
|
+
class=${`image ${isReversed ? 'reversed' : ''}`}
|
|
211
|
+
style="aspect-ratio: 0.6; display: flex; align-items: center; justify-content: center; color: var(--roxy-muted)"
|
|
212
|
+
>
|
|
213
|
+
${d.name ?? '?'}
|
|
214
|
+
</div>`
|
|
215
|
+
}
|
|
216
|
+
</div>
|
|
217
|
+
<div>
|
|
218
|
+
<div class="meta">
|
|
219
|
+
${d.arcana ? html`${d.arcana} arcana` : nothing}
|
|
220
|
+
${d.number !== undefined && d.number !== null ? html` · ${d.number}` : nothing}
|
|
221
|
+
${isReversed ? html` · reversed` : nothing}
|
|
222
|
+
</div>
|
|
223
|
+
<h2 class="title">${d.name ?? 'Tarot card'}</h2>
|
|
224
|
+
${orientedMeaning?.description ? html`<p>${orientedMeaning.description}</p>` : nothing}
|
|
211
225
|
${
|
|
212
|
-
|
|
226
|
+
keywords.length > 0
|
|
213
227
|
? html`<div class="chips">
|
|
214
|
-
${
|
|
228
|
+
${keywords.map((k) => html`<span>${k}</span>`)}
|
|
215
229
|
</div>`
|
|
216
230
|
: nothing
|
|
217
231
|
}
|
|
@@ -1,32 +1,22 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import type {
|
|
4
|
+
CastCelticCrossResponse,
|
|
5
|
+
CastLoveSpreadResponse,
|
|
6
|
+
CastReadingResponse,
|
|
7
|
+
CastThreeCardResponse,
|
|
8
|
+
CastYesNoResponse,
|
|
9
|
+
DrawCardsResponse,
|
|
10
|
+
} from '../types/index.js';
|
|
3
11
|
import { baseStyles } from '../utils/base-styles.js';
|
|
4
12
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
imageUrl?: string;
|
|
13
|
-
reversed?: boolean;
|
|
14
|
-
keywords?: string[];
|
|
15
|
-
arcana?: string;
|
|
16
|
-
};
|
|
17
|
-
interpretation?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface TarotSpreadData {
|
|
21
|
-
spread?: string;
|
|
22
|
-
positions?: TarotPosition[];
|
|
23
|
-
cards?: TarotPosition[];
|
|
24
|
-
reading?: string;
|
|
25
|
-
question?: string;
|
|
26
|
-
answer?: 'Yes' | 'No' | 'Maybe' | string;
|
|
27
|
-
strength?: string;
|
|
28
|
-
interpretation?: string;
|
|
29
|
-
}
|
|
13
|
+
type TarotSpreadData =
|
|
14
|
+
| CastThreeCardResponse
|
|
15
|
+
| CastCelticCrossResponse
|
|
16
|
+
| CastLoveSpreadResponse
|
|
17
|
+
| CastYesNoResponse
|
|
18
|
+
| CastReadingResponse
|
|
19
|
+
| DrawCardsResponse;
|
|
30
20
|
|
|
31
21
|
/**
|
|
32
22
|
* Tarot spread card. Renders /tarot/spreads/{three-card,celtic-cross,love},
|
|
@@ -72,15 +62,15 @@ export class RoxyTarotSpread extends LitElement {
|
|
|
72
62
|
}
|
|
73
63
|
.answer.yes {
|
|
74
64
|
background: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);
|
|
75
|
-
color: var(--roxy-success, #
|
|
65
|
+
color: var(--roxy-success-fg, #166534);
|
|
76
66
|
}
|
|
77
67
|
.answer.no {
|
|
78
68
|
background: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);
|
|
79
|
-
color: var(--roxy-danger, #
|
|
69
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
80
70
|
}
|
|
81
71
|
.answer.maybe {
|
|
82
72
|
background: color-mix(in srgb, var(--roxy-warning, #ea580c) 16%, transparent);
|
|
83
|
-
color: var(--roxy-warning, #
|
|
73
|
+
color: var(--roxy-warning-fg, #9a3412);
|
|
84
74
|
}
|
|
85
75
|
|
|
86
76
|
.grid {
|
|
@@ -157,22 +147,41 @@ export class RoxyTarotSpread extends LitElement {
|
|
|
157
147
|
if (!d)
|
|
158
148
|
return html`<div class="roxy-empty" role="status">No tarot spread</div>`;
|
|
159
149
|
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
const
|
|
163
|
-
?
|
|
150
|
+
const isYesNo = 'answer' in d;
|
|
151
|
+
const isDrawn = 'cards' in d && !('spread' in d);
|
|
152
|
+
const positions = isDrawn
|
|
153
|
+
? []
|
|
154
|
+
: 'positions' in d
|
|
155
|
+
? (d.positions ?? [])
|
|
156
|
+
: [];
|
|
157
|
+
const cards = isDrawn && 'cards' in d ? (d as DrawCardsResponse).cards : [];
|
|
158
|
+
const answer = isYesNo ? (d as CastYesNoResponse).answer : undefined;
|
|
159
|
+
const strength = isYesNo ? (d as CastYesNoResponse).strength : undefined;
|
|
160
|
+
const spreadLabel =
|
|
161
|
+
'spread' in d
|
|
162
|
+
? (d as CastThreeCardResponse).spread
|
|
163
|
+
: this.spread.replace(/-/g, ' ');
|
|
164
|
+
const question =
|
|
165
|
+
'question' in d ? (d as CastThreeCardResponse).question : undefined;
|
|
166
|
+
const summary =
|
|
167
|
+
'summary' in d ? (d as CastThreeCardResponse).summary : undefined;
|
|
168
|
+
const yesNoInterp = isYesNo
|
|
169
|
+
? (d as CastYesNoResponse).interpretation
|
|
170
|
+
: undefined;
|
|
171
|
+
const answerClass = answer
|
|
172
|
+
? answer.toLowerCase().replace(/[^a-z]/g, '')
|
|
164
173
|
: '';
|
|
165
174
|
|
|
166
175
|
return html`<article class="wrap" aria-label="Tarot spread">
|
|
167
176
|
<header class="head">
|
|
168
|
-
<h2 class="title">${
|
|
169
|
-
${
|
|
177
|
+
<h2 class="title">${spreadLabel}</h2>
|
|
178
|
+
${question ? html`<span class="question">"${question}"</span>` : nothing}
|
|
170
179
|
</header>
|
|
171
180
|
${
|
|
172
181
|
isYesNo
|
|
173
182
|
? html`<div>
|
|
174
|
-
<span class=${`answer ${answerClass}`}>${
|
|
175
|
-
${
|
|
183
|
+
<span class=${`answer ${answerClass}`}>${answer}</span>
|
|
184
|
+
${strength ? html`<small> · ${strength}</small>` : nothing}
|
|
176
185
|
</div>`
|
|
177
186
|
: nothing
|
|
178
187
|
}
|
|
@@ -181,7 +190,7 @@ export class RoxyTarotSpread extends LitElement {
|
|
|
181
190
|
? html`<div class="grid">
|
|
182
191
|
${positions.map(
|
|
183
192
|
(p) => html`<div class="card">
|
|
184
|
-
<p class="label">${p.
|
|
193
|
+
<p class="label">${p.name ?? ''}</p>
|
|
185
194
|
<div class="image">
|
|
186
195
|
${
|
|
187
196
|
p.card?.imageUrl
|
|
@@ -197,22 +206,40 @@ export class RoxyTarotSpread extends LitElement {
|
|
|
197
206
|
${p.card?.name ?? ''}
|
|
198
207
|
${p.card?.reversed ? html`<small>(reversed)</small>` : nothing}
|
|
199
208
|
</p>
|
|
200
|
-
${
|
|
201
|
-
p.interpretation
|
|
202
|
-
? html`<p class="interp">${p.interpretation}</p>`
|
|
203
|
-
: nothing
|
|
204
|
-
}
|
|
209
|
+
${p.interpretation ? html`<p class="interp">${p.interpretation}</p>` : nothing}
|
|
205
210
|
</div>`,
|
|
206
211
|
)}
|
|
207
212
|
</div>`
|
|
208
213
|
: nothing
|
|
209
214
|
}
|
|
210
|
-
${d.reading ? html`<p class="reading">${d.reading}</p>` : nothing}
|
|
211
215
|
${
|
|
212
|
-
|
|
213
|
-
? html`<
|
|
216
|
+
cards.length > 0
|
|
217
|
+
? html`<div class="grid">
|
|
218
|
+
${cards.map(
|
|
219
|
+
(c) => html`<div class="card">
|
|
220
|
+
<div class="image">
|
|
221
|
+
${
|
|
222
|
+
c.imageUrl
|
|
223
|
+
? html`<img
|
|
224
|
+
src=${c.imageUrl}
|
|
225
|
+
alt=${c.name ?? 'tarot card'}
|
|
226
|
+
class=${c.reversed ? 'reversed' : ''}
|
|
227
|
+
/>`
|
|
228
|
+
: html`${c.name ?? '?'}`
|
|
229
|
+
}
|
|
230
|
+
</div>
|
|
231
|
+
<p class="name">
|
|
232
|
+
${c.name ?? ''}
|
|
233
|
+
${c.reversed ? html`<small>(reversed)</small>` : nothing}
|
|
234
|
+
</p>
|
|
235
|
+
${c.meaning ? html`<p class="interp">${c.meaning}</p>` : nothing}
|
|
236
|
+
</div>`,
|
|
237
|
+
)}
|
|
238
|
+
</div>`
|
|
214
239
|
: nothing
|
|
215
240
|
}
|
|
241
|
+
${summary ? html`<p class="reading">${summary}</p>` : nothing}
|
|
242
|
+
${yesNoInterp ? html`<p class="reading">${yesNoInterp}</p>` : nothing}
|
|
216
243
|
</article>`;
|
|
217
244
|
}
|
|
218
245
|
}
|
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
import { css, html, LitElement, nothing, svg } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
import { PLANET_ABBR, SIGN_ABBR } from '../tokens/index.js';
|
|
4
|
+
import type { BirthChartResponse } from '../types/index.js';
|
|
4
5
|
import { baseStyles } from '../utils/base-styles.js';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
[planet: string]: {
|
|
8
|
-
graha?: string;
|
|
9
|
-
rashi?: string;
|
|
10
|
-
longitude?: number;
|
|
11
|
-
nakshatra?: string;
|
|
12
|
-
isRetrograde?: boolean;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
7
|
+
type RashiBucket = BirthChartResponse['aries'];
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
isRetrograde?: boolean;
|
|
22
|
-
}>;
|
|
23
|
-
}
|
|
9
|
+
// TODO(spec): BirthChartResponse types only `aries` and `meta`, but the API
|
|
10
|
+
// returns all 12 rashi keys (taurus, gemini, ..., pisces) with the same shape
|
|
11
|
+
// as `aries`. Update the OpenAPI schema so the renderer can index by rashi
|
|
12
|
+
// without casts.
|
|
13
|
+
type BirthChartByRashi = BirthChartResponse & Record<string, RashiBucket>;
|
|
24
14
|
|
|
25
15
|
interface KundliHouse {
|
|
26
16
|
house: number;
|
|
@@ -28,19 +18,6 @@ interface KundliHouse {
|
|
|
28
18
|
planets: string[];
|
|
29
19
|
}
|
|
30
20
|
|
|
31
|
-
interface KundliData {
|
|
32
|
-
meta?: KundliMeta;
|
|
33
|
-
houses?: Array<{
|
|
34
|
-
house?: number;
|
|
35
|
-
number?: number;
|
|
36
|
-
sign?: string;
|
|
37
|
-
planets?: string[];
|
|
38
|
-
}>;
|
|
39
|
-
combustion?: unknown[];
|
|
40
|
-
planetaryWar?: unknown[];
|
|
41
|
-
[rashi: string]: unknown;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
21
|
const SOUTH_HOUSE_CENTERS: Record<number, { x: number; y: number }> = {
|
|
45
22
|
1: { x: 150, y: 58 },
|
|
46
23
|
2: { x: 205, y: 52 },
|
|
@@ -145,39 +122,35 @@ export class RoxyVedicKundli extends LitElement {
|
|
|
145
122
|
font-weight: 600;
|
|
146
123
|
font-family: var(--roxy-font-sans);
|
|
147
124
|
}
|
|
125
|
+
.lagna-marker {
|
|
126
|
+
fill: var(--roxy-accent-fg, #b45309);
|
|
127
|
+
font-size: 8px;
|
|
128
|
+
font-weight: 700;
|
|
129
|
+
font-family: var(--roxy-font-sans);
|
|
130
|
+
letter-spacing: 0.05em;
|
|
131
|
+
}
|
|
132
|
+
.lagna-bg {
|
|
133
|
+
fill: color-mix(in srgb, var(--roxy-accent, #f59e0b) 12%, transparent);
|
|
134
|
+
stroke: color-mix(in srgb, var(--roxy-accent, #f59e0b) 45%, transparent);
|
|
135
|
+
stroke-width: 0.8;
|
|
136
|
+
}
|
|
148
137
|
`,
|
|
149
138
|
];
|
|
150
139
|
|
|
151
140
|
@property({ attribute: false })
|
|
152
|
-
data:
|
|
141
|
+
data: BirthChartResponse | null = null;
|
|
153
142
|
|
|
154
143
|
@property({ type: String, reflect: true, attribute: 'chart-style' })
|
|
155
144
|
chartStyle: 'south' | 'north' = 'south';
|
|
156
145
|
|
|
157
146
|
private buildHouses(): KundliHouse[] {
|
|
158
147
|
if (!this.data) return [];
|
|
148
|
+
const data = this.data as BirthChartByRashi;
|
|
159
149
|
const houses: KundliHouse[] = [];
|
|
160
|
-
// Prefer normalized .houses array if present
|
|
161
|
-
if (Array.isArray(this.data.houses)) {
|
|
162
|
-
for (const h of this.data.houses) {
|
|
163
|
-
houses.push({
|
|
164
|
-
house: (h.house ?? h.number ?? houses.length + 1) as number,
|
|
165
|
-
sign: h.sign ?? '',
|
|
166
|
-
planets: h.planets ?? [],
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
if (houses.length > 0) return houses;
|
|
170
|
-
}
|
|
171
|
-
// Otherwise read the rashi buckets and project them as houses 1..12
|
|
172
|
-
// keyed by sign order. Lagna-anchored ordering would require knowing
|
|
173
|
-
// the ascendant rashi; we render rashi buckets directly which is the
|
|
174
|
-
// canonical South Indian layout.
|
|
175
150
|
for (let i = 0; i < 12; i++) {
|
|
176
151
|
const key = RASHI_KEYS[i];
|
|
177
|
-
const bucket =
|
|
178
|
-
const planets = (bucket?.signs ?? [])
|
|
179
|
-
.map((p) => p.planet ?? '')
|
|
180
|
-
.filter(Boolean);
|
|
152
|
+
const bucket = data[key];
|
|
153
|
+
const planets = (bucket?.signs ?? []).map((p) => p.graha).filter(Boolean);
|
|
181
154
|
houses.push({
|
|
182
155
|
house: i + 1,
|
|
183
156
|
sign: RASHI_TO_SIGN[key] ?? '',
|
|
@@ -220,23 +193,41 @@ export class RoxyVedicKundli extends LitElement {
|
|
|
220
193
|
</div>`;
|
|
221
194
|
}
|
|
222
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
|
+
|
|
223
202
|
private renderHouseGroup(h: KundliHouse) {
|
|
224
203
|
const center = SOUTH_HOUSE_CENTERS[h.house];
|
|
225
204
|
const signPos = SOUTH_SIGN_POSITIONS[h.house];
|
|
226
205
|
if (!center || !signPos) return nothing;
|
|
227
206
|
const signAbbr = SIGN_ABBR[h.sign] ?? '';
|
|
228
207
|
const planets = h.planets ?? [];
|
|
208
|
+
const isLagna = this.isLagna(h);
|
|
229
209
|
return svg`
|
|
230
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
|
+
}
|
|
231
216
|
${
|
|
232
217
|
signAbbr
|
|
233
218
|
? svg`<text class="sign-text" x=${signPos.x} y=${signPos.y} text-anchor="middle" dominant-baseline="central">${signAbbr}</text>`
|
|
234
219
|
: nothing
|
|
235
220
|
}
|
|
221
|
+
${
|
|
222
|
+
isLagna
|
|
223
|
+
? svg`<text class="lagna-marker" x=${center.x} y=${center.y - 18} text-anchor="middle" dominant-baseline="central">LAGNA</text>`
|
|
224
|
+
: nothing
|
|
225
|
+
}
|
|
236
226
|
${planets.map((planet, j) => {
|
|
237
227
|
const abbr = PLANET_ABBR[capitalize(planet)] ?? planet.slice(0, 2);
|
|
238
228
|
const lineHeight = 13;
|
|
239
|
-
const
|
|
229
|
+
const baseY = isLagna ? center.y + 8 : center.y;
|
|
230
|
+
const startY = baseY - ((planets.length - 1) * lineHeight) / 2;
|
|
240
231
|
const yPos = startY + j * lineHeight;
|
|
241
232
|
return svg`<text class="planet-text" x=${center.x} y=${yPos} text-anchor="middle" dominant-baseline="central">${abbr}</text>`;
|
|
242
233
|
})}
|
package/src/index.ts
CHANGED
|
@@ -33,29 +33,19 @@ export { RoxyTarotSpread } from './components/tarot-spread.js';
|
|
|
33
33
|
// Vedic
|
|
34
34
|
export { RoxyVedicKundli } from './components/vedic-kundli.js';
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
import { ROXY_COMPONENTS, type RoxyComponentSlug } from './manifest.js';
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'panchang-table',
|
|
47
|
-
'dasha-timeline',
|
|
48
|
-
'dosha-card',
|
|
49
|
-
'guna-milan',
|
|
50
|
-
'kp-planets-table',
|
|
51
|
-
'numerology-card',
|
|
52
|
-
'tarot-card',
|
|
53
|
-
'tarot-spread',
|
|
54
|
-
'biorhythm-chart',
|
|
55
|
-
'hexagram',
|
|
56
|
-
'endpoint-form',
|
|
57
|
-
'location-search',
|
|
58
|
-
'data',
|
|
59
|
-
] as const;
|
|
38
|
+
export {
|
|
39
|
+
ROXY_COMPONENTS,
|
|
40
|
+
type RoxyComponent,
|
|
41
|
+
type RoxyComponentSlug,
|
|
42
|
+
type RoxyComponentTag,
|
|
43
|
+
type RoxyDomain,
|
|
44
|
+
} from './manifest.js';
|
|
45
|
+
export { ROXY_UI_VERSION } from './version.js';
|
|
60
46
|
|
|
61
|
-
|
|
47
|
+
/** Slugs in declaration order. Kept for the auto-mount widgets script and downstream codegen. */
|
|
48
|
+
export const ROXY_UI_COMPONENTS: readonly RoxyComponentSlug[] =
|
|
49
|
+
ROXY_COMPONENTS.map((c) => c.slug) as RoxyComponentSlug[];
|
|
50
|
+
|
|
51
|
+
export type RoxyUIComponentName = RoxyComponentSlug;
|