@roxyapi/ui 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +321 -14
- package/THEMING.md +24 -7
- package/dist/cdn/components/biorhythm-chart.js +15 -22
- package/dist/cdn/components/biorhythm-chart.js.map +3 -3
- package/dist/cdn/components/compatibility-card.js +36 -34
- package/dist/cdn/components/compatibility-card.js.map +4 -4
- package/dist/cdn/components/dasha-timeline.js +35 -39
- package/dist/cdn/components/dasha-timeline.js.map +4 -4
- package/dist/cdn/components/data.js +6 -6
- package/dist/cdn/components/data.js.map +3 -3
- package/dist/cdn/components/dosha-card.js +13 -13
- package/dist/cdn/components/dosha-card.js.map +2 -2
- package/dist/cdn/components/endpoint-form.js +47 -28
- package/dist/cdn/components/endpoint-form.js.map +3 -3
- package/dist/cdn/components/guna-milan.js +18 -18
- package/dist/cdn/components/guna-milan.js.map +4 -4
- package/dist/cdn/components/hexagram.js +26 -26
- package/dist/cdn/components/hexagram.js.map +3 -3
- package/dist/cdn/components/horoscope-card.js +38 -38
- package/dist/cdn/components/horoscope-card.js.map +3 -3
- package/dist/cdn/components/kp-planets-table.js +10 -10
- package/dist/cdn/components/kp-planets-table.js.map +4 -4
- package/dist/cdn/components/location-search.js +6 -6
- package/dist/cdn/components/location-search.js.map +3 -3
- package/dist/cdn/components/moon-phase.js +21 -21
- package/dist/cdn/components/moon-phase.js.map +4 -4
- package/dist/cdn/components/natal-chart.js +61 -19
- package/dist/cdn/components/natal-chart.js.map +4 -4
- package/dist/cdn/components/numerology-card.js +40 -31
- package/dist/cdn/components/numerology-card.js.map +3 -3
- package/dist/cdn/components/panchang-table.js +25 -25
- package/dist/cdn/components/panchang-table.js.map +4 -4
- package/dist/cdn/components/synastry-chart.js +129 -39
- package/dist/cdn/components/synastry-chart.js.map +4 -4
- package/dist/cdn/components/tarot-card.js +49 -20
- package/dist/cdn/components/tarot-card.js.map +3 -3
- package/dist/cdn/components/tarot-spread.js +43 -27
- package/dist/cdn/components/tarot-spread.js.map +3 -3
- package/dist/cdn/components/vedic-kundli.js +23 -9
- package/dist/cdn/components/vedic-kundli.js.map +3 -3
- package/dist/cdn/roxy-ui.js +560 -350
- package/dist/cdn/roxy-ui.js.map +4 -4
- package/dist/components/biorhythm-chart.d.ts +2 -46
- package/dist/components/biorhythm-chart.d.ts.map +1 -1
- package/dist/components/biorhythm-chart.js +24 -23
- package/dist/components/biorhythm-chart.js.map +2 -2
- package/dist/components/compatibility-card.d.ts +2 -27
- package/dist/components/compatibility-card.d.ts.map +1 -1
- package/dist/components/compatibility-card.js +50 -29
- package/dist/components/compatibility-card.js.map +3 -3
- package/dist/components/dasha-timeline.d.ts +2 -31
- package/dist/components/dasha-timeline.d.ts.map +1 -1
- package/dist/components/dasha-timeline.js +32 -30
- package/dist/components/dasha-timeline.js.map +3 -3
- package/dist/components/data.d.ts +6 -0
- package/dist/components/data.d.ts.map +1 -1
- package/dist/components/data.js +9 -1
- package/dist/components/data.js.map +2 -2
- package/dist/components/dosha-card.d.ts +2 -16
- package/dist/components/dosha-card.d.ts.map +1 -1
- package/dist/components/dosha-card.js +12 -13
- package/dist/components/dosha-card.js.map +2 -2
- package/dist/components/endpoint-form.d.ts +2 -0
- package/dist/components/endpoint-form.d.ts.map +1 -1
- package/dist/components/endpoint-form.js +66 -8
- package/dist/components/endpoint-form.js.map +2 -2
- package/dist/components/guna-milan.d.ts +2 -20
- package/dist/components/guna-milan.d.ts.map +1 -1
- package/dist/components/guna-milan.js +22 -12
- package/dist/components/guna-milan.js.map +3 -3
- package/dist/components/hexagram.d.ts +3 -27
- package/dist/components/hexagram.d.ts.map +1 -1
- package/dist/components/hexagram.js +31 -15
- package/dist/components/hexagram.js.map +2 -2
- package/dist/components/horoscope-card.d.ts +2 -20
- package/dist/components/horoscope-card.d.ts.map +1 -1
- package/dist/components/horoscope-card.js +24 -15
- package/dist/components/horoscope-card.js.map +2 -2
- package/dist/components/kp-planets-table.d.ts +2 -21
- package/dist/components/kp-planets-table.d.ts.map +1 -1
- package/dist/components/kp-planets-table.js +10 -4
- package/dist/components/kp-planets-table.js.map +3 -3
- package/dist/components/location-search.d.ts +3 -11
- package/dist/components/location-search.d.ts.map +1 -1
- package/dist/components/location-search.js +45 -5
- package/dist/components/location-search.js.map +2 -2
- package/dist/components/moon-phase.d.ts +4 -21
- package/dist/components/moon-phase.d.ts.map +1 -1
- package/dist/components/moon-phase.js +17 -4
- package/dist/components/moon-phase.js.map +3 -3
- package/dist/components/natal-chart.d.ts +7 -43
- package/dist/components/natal-chart.d.ts.map +1 -1
- package/dist/components/natal-chart.js +130 -70
- package/dist/components/natal-chart.js.map +3 -3
- package/dist/components/numerology-card.d.ts +5 -37
- package/dist/components/numerology-card.d.ts.map +1 -1
- package/dist/components/numerology-card.js +54 -28
- package/dist/components/numerology-card.js.map +2 -2
- package/dist/components/panchang-table.d.ts +3 -62
- package/dist/components/panchang-table.d.ts.map +1 -1
- package/dist/components/panchang-table.js +62 -32
- package/dist/components/panchang-table.js.map +3 -3
- package/dist/components/synastry-chart.d.ts +9 -28
- package/dist/components/synastry-chart.d.ts.map +1 -1
- package/dist/components/synastry-chart.js +178 -38
- package/dist/components/synastry-chart.js.map +3 -3
- package/dist/components/tarot-card.d.ts +5 -29
- package/dist/components/tarot-card.d.ts.map +1 -1
- package/dist/components/tarot-card.js +59 -20
- package/dist/components/tarot-card.js.map +2 -2
- package/dist/components/tarot-spread.d.ts +2 -24
- package/dist/components/tarot-spread.d.ts.map +1 -1
- package/dist/components/tarot-spread.js +39 -13
- package/dist/components/tarot-spread.js.map +2 -2
- package/dist/components/vedic-kundli.d.ts +3 -23
- package/dist/components/vedic-kundli.d.ts.map +1 -1
- package/dist/components/vedic-kundli.js +25 -13
- package/dist/components/vedic-kundli.js.map +2 -2
- package/dist/index.cjs +1149 -358
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1149 -358
- package/dist/index.js.map +4 -4
- package/dist/manifest.d.ts +49 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/styles/tokens.css +47 -1
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types.gen.d.ts +27811 -0
- package/dist/types/types.gen.d.ts.map +1 -0
- package/dist/utils/debounce.d.ts +9 -1
- package/dist/utils/debounce.d.ts.map +1 -1
- package/dist/utils/format.d.ts +15 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +7 -1
- package/src/components/biorhythm-chart.ts +39 -84
- package/src/components/compatibility-card.ts +85 -52
- package/src/components/dasha-timeline.ts +55 -73
- package/src/components/data.ts +20 -1
- package/src/components/dosha-card.ts +18 -31
- package/src/components/endpoint-form.ts +79 -11
- package/src/components/guna-milan.ts +16 -34
- package/src/components/hexagram.ts +53 -43
- package/src/components/horoscope-card.ts +51 -39
- package/src/components/kp-planets-table.ts +8 -27
- package/src/components/location-search.ts +45 -20
- package/src/components/moon-phase.ts +28 -25
- package/src/components/natal-chart.ts +129 -84
- package/src/components/numerology-card.ts +87 -79
- package/src/components/panchang-table.ts +40 -78
- package/src/components/synastry-chart.ts +220 -78
- package/src/components/tarot-card.ts +76 -62
- package/src/components/tarot-spread.ts +72 -45
- package/src/components/vedic-kundli.ts +42 -51
- package/src/index.ts +14 -24
- package/src/manifest.ts +366 -0
- package/src/styles/tokens.css +47 -1
- package/src/tokens/index.ts +5 -0
- package/src/types/types.gen.ts +1 -1
- package/src/utils/debounce.ts +23 -4
- package/src/utils/format.ts +57 -0
- package/src/version.ts +2 -0
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
28
28
|
// packages/ui/src/index.ts
|
|
29
29
|
var src_exports = {};
|
|
30
30
|
__export(src_exports, {
|
|
31
|
+
ROXY_COMPONENTS: () => ROXY_COMPONENTS,
|
|
31
32
|
ROXY_UI_COMPONENTS: () => ROXY_UI_COMPONENTS,
|
|
32
33
|
ROXY_UI_VERSION: () => ROXY_UI_VERSION,
|
|
33
34
|
RoxyBiorhythmChart: () => RoxyBiorhythmChart,
|
|
@@ -165,25 +166,28 @@ var RoxyBiorhythmChart = class extends import_lit2.LitElement {
|
|
|
165
166
|
const d = this.data;
|
|
166
167
|
if (!d)
|
|
167
168
|
return import_lit2.html`<div class="roxy-empty" role="status">No biorhythm data</div>`;
|
|
168
|
-
if (this.mode === "critical-days" && d
|
|
169
|
+
if (this.mode === "critical-days" && "criticalDays" in d) {
|
|
169
170
|
return this.renderCritical(d);
|
|
170
171
|
}
|
|
171
|
-
if (this.mode === "forecast" && d
|
|
172
|
+
if (this.mode === "forecast" && "days" in d) {
|
|
172
173
|
return this.renderForecast(d);
|
|
173
174
|
}
|
|
174
175
|
return this.renderDaily(d);
|
|
175
176
|
}
|
|
176
177
|
renderDaily(d) {
|
|
177
|
-
const
|
|
178
|
-
const entries = Object.entries(
|
|
178
|
+
const raw = d.quickRead ?? {};
|
|
179
|
+
const entries = Object.entries(raw).map(([cycle, value]) => {
|
|
180
|
+
const v = typeof value === "number" ? value : 0;
|
|
181
|
+
const normalized = Math.abs(v) > 1 ? v / 100 : v;
|
|
182
|
+
return [cycle, normalized];
|
|
183
|
+
});
|
|
179
184
|
return import_lit2.html`<section class="wrap" aria-label="Daily biorhythm">
|
|
180
185
|
<header class="head">
|
|
181
186
|
<h2 class="title">Biorhythm</h2>
|
|
182
187
|
${typeof d.energyRating === "number" ? import_lit2.html`<span class="energy">Energy ${d.energyRating}/10</span>` : import_lit2.nothing}
|
|
183
188
|
</header>
|
|
184
189
|
<div class="bars" role="list">
|
|
185
|
-
${entries.map(([cycle,
|
|
186
|
-
const v = typeof value === "number" ? value : 0;
|
|
190
|
+
${entries.map(([cycle, v]) => {
|
|
187
191
|
const pct = (v + 1) / 2 * 100;
|
|
188
192
|
const color = CYCLE_COLOR[cycle] ?? "var(--roxy-accent, #f59e0b)";
|
|
189
193
|
return import_lit2.html`<div class="bar" role="listitem">
|
|
@@ -194,15 +198,12 @@ var RoxyBiorhythmChart = class extends import_lit2.LitElement {
|
|
|
194
198
|
style="width: ${pct}%; background: ${color}"
|
|
195
199
|
></span>
|
|
196
200
|
</span>
|
|
197
|
-
<span class="value">${(v * 100)
|
|
201
|
+
<span class="value">${Math.round(v * 100)}%</span>
|
|
198
202
|
</div>`;
|
|
199
203
|
})}
|
|
200
204
|
</div>
|
|
201
|
-
${d.
|
|
205
|
+
${d.dailyMessage ? import_lit2.html`<p class="advice">${d.dailyMessage}</p>` : import_lit2.nothing}
|
|
202
206
|
${d.advice ? import_lit2.html`<p class="advice">${d.advice}</p>` : import_lit2.nothing}
|
|
203
|
-
${d.criticalAlerts?.length ? import_lit2.html`<div>
|
|
204
|
-
${d.criticalAlerts.map((a) => import_lit2.html`<p class="alert">${a}</p>`)}
|
|
205
|
-
</div>` : import_lit2.nothing}
|
|
206
207
|
</section>`;
|
|
207
208
|
}
|
|
208
209
|
renderForecast(d) {
|
|
@@ -212,13 +213,16 @@ var RoxyBiorhythmChart = class extends import_lit2.LitElement {
|
|
|
212
213
|
const w = 600;
|
|
213
214
|
const h = 160;
|
|
214
215
|
const xStep = w / Math.max(days.length - 1, 1);
|
|
215
|
-
const
|
|
216
|
+
const cycleKeys = [
|
|
217
|
+
"physical",
|
|
218
|
+
"emotional",
|
|
219
|
+
"intellectual",
|
|
220
|
+
"intuitive"
|
|
221
|
+
];
|
|
216
222
|
return import_lit2.html`<section class="wrap" aria-label="Biorhythm forecast">
|
|
217
223
|
<header class="head">
|
|
218
224
|
<h2 class="title">Forecast</h2>
|
|
219
|
-
<span class="energy"
|
|
220
|
-
>${d.startDate ?? ""} - ${d.endDate ?? ""}</span
|
|
221
|
-
>
|
|
225
|
+
<span class="energy">${d.startDate} - ${d.endDate}</span>
|
|
222
226
|
</header>
|
|
223
227
|
<svg
|
|
224
228
|
viewBox="0 0 ${w} ${h}"
|
|
@@ -234,11 +238,11 @@ var RoxyBiorhythmChart = class extends import_lit2.LitElement {
|
|
|
234
238
|
stroke="var(--roxy-border, #e4e4e7)"
|
|
235
239
|
stroke-width="1"
|
|
236
240
|
/>
|
|
237
|
-
${
|
|
241
|
+
${cycleKeys.map((cycle) => {
|
|
238
242
|
const points = days.map((day, i) => {
|
|
239
|
-
const v = day
|
|
243
|
+
const v = day[cycle] ?? 0;
|
|
240
244
|
const x = i * xStep;
|
|
241
|
-
const y = h / 2 - v * (h / 2 - 8);
|
|
245
|
+
const y = h / 2 - v / 100 * (h / 2 - 8);
|
|
242
246
|
return `${x.toFixed(2)},${y.toFixed(2)}`;
|
|
243
247
|
}).join(" ");
|
|
244
248
|
const color = CYCLE_COLOR[cycle] ?? "#475569";
|
|
@@ -252,14 +256,12 @@ var RoxyBiorhythmChart = class extends import_lit2.LitElement {
|
|
|
252
256
|
return import_lit2.html`<section class="wrap" aria-label="Critical days">
|
|
253
257
|
<header class="head">
|
|
254
258
|
<h2 class="title">Critical days</h2>
|
|
255
|
-
<span class="energy"
|
|
256
|
-
>${d.totalCriticalDays ?? d.criticalDays?.length ?? 0} total</span
|
|
257
|
-
>
|
|
259
|
+
<span class="energy">${d.totalCriticalDays} total</span>
|
|
258
260
|
</header>
|
|
259
261
|
<div>
|
|
260
|
-
${
|
|
262
|
+
${d.criticalDays.map(
|
|
261
263
|
(day) => import_lit2.html`<span class="crit"
|
|
262
|
-
>${day.date} · ${day.cycle
|
|
264
|
+
>${day.date} · ${day.cycle} ${day.severity}</span
|
|
263
265
|
>`
|
|
264
266
|
)}
|
|
265
267
|
</div>
|
|
@@ -359,6 +361,50 @@ RoxyBiorhythmChart = __decorateClass([
|
|
|
359
361
|
// packages/ui/src/components/compatibility-card.ts
|
|
360
362
|
var import_lit3 = require("lit");
|
|
361
363
|
var import_decorators2 = require("lit/decorators.js");
|
|
364
|
+
|
|
365
|
+
// packages/ui/src/utils/format.ts
|
|
366
|
+
function formatTime(input) {
|
|
367
|
+
if (typeof input !== "string" || input.length === 0) return "";
|
|
368
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(input)) return "";
|
|
369
|
+
const bareTime = /^\d{2}:\d{2}(:\d{2})?$/.test(input);
|
|
370
|
+
const iso = bareTime ? `1970-01-01T${input}` : input;
|
|
371
|
+
const d = new Date(iso);
|
|
372
|
+
if (Number.isNaN(d.getTime())) return input;
|
|
373
|
+
return d.toLocaleTimeString(void 0, {
|
|
374
|
+
hour: "numeric",
|
|
375
|
+
minute: "2-digit",
|
|
376
|
+
hour12: true
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
function formatDate(input) {
|
|
380
|
+
if (typeof input !== "string" || input.length === 0) return "";
|
|
381
|
+
const d = new Date(
|
|
382
|
+
/^\d{4}-\d{2}-\d{2}$/.test(input) ? `${input}T00:00:00` : input
|
|
383
|
+
);
|
|
384
|
+
if (Number.isNaN(d.getTime())) return input;
|
|
385
|
+
return d.toLocaleDateString(void 0, {
|
|
386
|
+
month: "short",
|
|
387
|
+
day: "numeric",
|
|
388
|
+
year: "numeric"
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function formatTimeRange(t) {
|
|
392
|
+
if (!t) return "";
|
|
393
|
+
const start = formatTime(t.start);
|
|
394
|
+
const end = formatTime(t.end);
|
|
395
|
+
if (start && end) return `${start} - ${end}`;
|
|
396
|
+
return start || end || "";
|
|
397
|
+
}
|
|
398
|
+
function formatNumber(value, dp = 1) {
|
|
399
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return "";
|
|
400
|
+
return value.toFixed(dp).replace(/\.?0+$/, "");
|
|
401
|
+
}
|
|
402
|
+
function formatPercent(value, dp = 1) {
|
|
403
|
+
const n = formatNumber(value, dp);
|
|
404
|
+
return n ? `${n}%` : "";
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// packages/ui/src/components/compatibility-card.ts
|
|
362
408
|
var RoxyCompatibilityCard = class extends import_lit3.LitElement {
|
|
363
409
|
constructor() {
|
|
364
410
|
super(...arguments);
|
|
@@ -368,22 +414,29 @@ var RoxyCompatibilityCard = class extends import_lit3.LitElement {
|
|
|
368
414
|
getBreakdown() {
|
|
369
415
|
const d = this.data;
|
|
370
416
|
if (!d) return {};
|
|
371
|
-
if (d
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
return inferred;
|
|
417
|
+
if ("categories" in d && d.categories) {
|
|
418
|
+
const out = {};
|
|
419
|
+
for (const [k, v] of Object.entries(d.categories)) {
|
|
420
|
+
if (typeof v === "number" && Number.isFinite(v)) out[k] = v;
|
|
421
|
+
}
|
|
422
|
+
return out;
|
|
423
|
+
}
|
|
424
|
+
return {};
|
|
380
425
|
}
|
|
381
426
|
render() {
|
|
382
427
|
const d = this.data;
|
|
383
428
|
if (!d)
|
|
384
429
|
return import_lit3.html`<div class="roxy-empty" role="status">No compatibility data</div>`;
|
|
385
|
-
const score = d.overallScore
|
|
430
|
+
const score = d.overallScore;
|
|
386
431
|
const breakdown = this.getBreakdown();
|
|
432
|
+
const rating = "rating" in d ? d.rating : void 0;
|
|
433
|
+
const archetype = "archetype" in d ? d.archetype : void 0;
|
|
434
|
+
const advice = "advice" in d ? d.advice : void 0;
|
|
435
|
+
const summary = "summary" in d ? d.summary : void 0;
|
|
436
|
+
const interpretation = "interpretation" in d ? d.interpretation : void 0;
|
|
437
|
+
const strengths = "strengths" in d ? d.strengths : void 0;
|
|
438
|
+
const challenges = "challenges" in d ? d.challenges : void 0;
|
|
439
|
+
const keyAspects = "keyAspects" in d ? d.keyAspects : void 0;
|
|
387
440
|
return import_lit3.html`<article
|
|
388
441
|
class="card"
|
|
389
442
|
aria-label=${`Compatibility (${this.mode})`}
|
|
@@ -391,8 +444,8 @@ var RoxyCompatibilityCard = class extends import_lit3.LitElement {
|
|
|
391
444
|
<div class="head">
|
|
392
445
|
<h2>${this.mode} compatibility</h2>
|
|
393
446
|
<div>
|
|
394
|
-
${typeof score === "number" ? import_lit3.html`<div class="score">${score}</div>` : import_lit3.nothing}
|
|
395
|
-
${
|
|
447
|
+
${typeof score === "number" ? import_lit3.html`<div class="score">${formatNumber(score, 0)}</div>` : import_lit3.nothing}
|
|
448
|
+
${rating ? import_lit3.html`<div class="rating">${rating}</div>` : import_lit3.nothing}
|
|
396
449
|
</div>
|
|
397
450
|
</div>
|
|
398
451
|
|
|
@@ -403,35 +456,37 @@ var RoxyCompatibilityCard = class extends import_lit3.LitElement {
|
|
|
403
456
|
<span class="bar"
|
|
404
457
|
><span style="width: ${Math.max(0, Math.min(100, v))}%"></span
|
|
405
458
|
></span>
|
|
406
|
-
<span>${v}</span>
|
|
459
|
+
<span>${formatNumber(v, 0)}</span>
|
|
407
460
|
</div>`
|
|
408
461
|
)}
|
|
409
462
|
</div>` : import_lit3.nothing}
|
|
410
|
-
${
|
|
411
|
-
<span class="archetype">${
|
|
463
|
+
${archetype ? import_lit3.html`<p>
|
|
464
|
+
<span class="archetype">${archetype.label}</span>
|
|
465
|
+
${archetype.description ? import_lit3.html` · ${archetype.description}` : import_lit3.nothing}
|
|
412
466
|
</p>` : import_lit3.nothing}
|
|
413
|
-
${
|
|
414
|
-
${
|
|
415
|
-
${
|
|
416
|
-
|
|
467
|
+
${summary ? import_lit3.html`<p>${summary}</p>` : import_lit3.nothing}
|
|
468
|
+
${interpretation && !summary ? import_lit3.html`<p>${interpretation}</p>` : import_lit3.nothing}
|
|
469
|
+
${advice ? import_lit3.html`<p>${advice}</p>` : import_lit3.nothing}
|
|
470
|
+
${(strengths?.length ?? 0) > 0 || (challenges?.length ?? 0) > 0 ? import_lit3.html`<div class="lists">
|
|
471
|
+
${strengths?.length ? import_lit3.html`<div>
|
|
417
472
|
<h3>Strengths</h3>
|
|
418
473
|
<ul>
|
|
419
|
-
${
|
|
474
|
+
${strengths.map((s) => import_lit3.html`<li>${s}</li>`)}
|
|
420
475
|
</ul>
|
|
421
476
|
</div>` : import_lit3.nothing}
|
|
422
|
-
${
|
|
477
|
+
${challenges?.length ? import_lit3.html`<div>
|
|
423
478
|
<h3>Challenges</h3>
|
|
424
479
|
<ul>
|
|
425
|
-
${
|
|
426
|
-
</ul>
|
|
427
|
-
</div>` : import_lit3.nothing}
|
|
428
|
-
${d.keyAspects?.length ? import_lit3.html`<div>
|
|
429
|
-
<h3>Key aspects</h3>
|
|
430
|
-
<ul>
|
|
431
|
-
${d.keyAspects.map((s) => import_lit3.html`<li>${s}</li>`)}
|
|
480
|
+
${challenges.map((s) => import_lit3.html`<li>${s}</li>`)}
|
|
432
481
|
</ul>
|
|
433
482
|
</div>` : import_lit3.nothing}
|
|
434
483
|
</div>` : import_lit3.nothing}
|
|
484
|
+
${keyAspects?.length ? import_lit3.html`<div>
|
|
485
|
+
<h3 style="margin: 0 0 0.25rem; font-size: var(--roxy-text-xs); color: var(--roxy-muted); text-transform: uppercase; letter-spacing: 0.06em;">Key aspects</h3>
|
|
486
|
+
<ul style="margin: 0; padding-left: 1rem; font-size: var(--roxy-text-sm);">
|
|
487
|
+
${keyAspects.slice(0, 6).map((a) => import_lit3.html`<li>${formatAspect(a)}</li>`)}
|
|
488
|
+
</ul>
|
|
489
|
+
</div>` : import_lit3.nothing}
|
|
435
490
|
</article>`;
|
|
436
491
|
}
|
|
437
492
|
};
|
|
@@ -501,7 +556,7 @@ RoxyCompatibilityCard.styles = [
|
|
|
501
556
|
}
|
|
502
557
|
|
|
503
558
|
.archetype {
|
|
504
|
-
color: var(--roxy-
|
|
559
|
+
color: var(--roxy-accent-fg, #b45309);
|
|
505
560
|
font-weight: var(--roxy-weight-bold, 600);
|
|
506
561
|
}
|
|
507
562
|
|
|
@@ -532,6 +587,12 @@ __decorateClass([
|
|
|
532
587
|
RoxyCompatibilityCard = __decorateClass([
|
|
533
588
|
(0, import_decorators2.customElement)("roxy-compatibility-card")
|
|
534
589
|
], RoxyCompatibilityCard);
|
|
590
|
+
function formatAspect(a) {
|
|
591
|
+
const aspect = a.type.toLowerCase().replace(/_/g, "-");
|
|
592
|
+
const orb = typeof a.orb === "number" ? ` (orb ${formatNumber(a.orb, 1)}\xB0)` : "";
|
|
593
|
+
const head = [a.planet1, aspect, a.planet2].filter(Boolean).join(" ");
|
|
594
|
+
return a.description ? `${head}${orb} \xB7 ${a.description}` : `${head}${orb}`;
|
|
595
|
+
}
|
|
535
596
|
|
|
536
597
|
// packages/ui/src/components/dasha-timeline.ts
|
|
537
598
|
var import_lit4 = require("lit");
|
|
@@ -547,16 +608,16 @@ var RoxyDashaTimeline = class extends import_lit4.LitElement {
|
|
|
547
608
|
if (!d)
|
|
548
609
|
return import_lit4.html`<div class="roxy-empty" role="status">No dasha data</div>`;
|
|
549
610
|
const periods = this.collectPeriods(d);
|
|
550
|
-
const maxYears = periods.length ? Math.max(...periods.map((p) => p.durationYears
|
|
611
|
+
const maxYears = periods.length ? Math.max(...periods.map((p) => p.durationYears)) : 0;
|
|
551
612
|
return import_lit4.html`<div class="wrap" aria-label="Dasha timeline">
|
|
552
613
|
<header class="head">
|
|
553
614
|
<h2 class="title">
|
|
554
615
|
${this.period === "major" ? "Vimshottari Mahadasha" : this.period === "sub" ? "Antardasha" : "Active dashas"}
|
|
555
616
|
</h2>
|
|
556
|
-
${
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
617
|
+
${"nakshatraName" in d && d.nakshatraName ? import_lit4.html`<div class="nakshatra">
|
|
618
|
+
Moon nakshatra: ${d.nakshatraName}
|
|
619
|
+
${"nakshatraLord" in d && d.nakshatraLord ? import_lit4.html`(lord ${d.nakshatraLord})` : import_lit4.nothing}
|
|
620
|
+
</div>` : import_lit4.nothing}
|
|
560
621
|
</header>
|
|
561
622
|
|
|
562
623
|
${this.period === "current" ? this.renderCurrent(d) : import_lit4.nothing}
|
|
@@ -566,39 +627,35 @@ var RoxyDashaTimeline = class extends import_lit4.LitElement {
|
|
|
566
627
|
</div>`;
|
|
567
628
|
}
|
|
568
629
|
renderCurrent(d) {
|
|
630
|
+
if (!("mahadasha" in d)) return import_lit4.nothing;
|
|
569
631
|
return import_lit4.html`<div class="current">
|
|
570
|
-
${d.mahadasha ? import_lit4.html`<div>
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
${d.antardasha ? import_lit4.html`<div>
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
${d.pratyantardasha ? import_lit4.html`<div>
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
${typeof d.remainingInPratyantardasha === "number" ? import_lit4.html`<small
|
|
586
|
-
>${d.remainingInPratyantardasha.toFixed(2)} years left</small
|
|
587
|
-
>` : import_lit4.nothing}
|
|
588
|
-
</div>` : import_lit4.nothing}
|
|
632
|
+
${"mahadasha" in d && d.mahadasha ? import_lit4.html`<div>
|
|
633
|
+
<span>Mahadasha</span>
|
|
634
|
+
<strong>${d.mahadasha.planet}</strong>
|
|
635
|
+
${"remainingInMahadasha" in d && d.remainingInMahadasha ? import_lit4.html`<small>${formatNumber(d.remainingInMahadasha.years + d.remainingInMahadasha.months / 12, 1)} years left</small>` : import_lit4.nothing}
|
|
636
|
+
</div>` : import_lit4.nothing}
|
|
637
|
+
${"antardasha" in d && d.antardasha ? import_lit4.html`<div>
|
|
638
|
+
<span>Antardasha</span>
|
|
639
|
+
<strong>${d.antardasha.planet}</strong>
|
|
640
|
+
${"remainingInAntardasha" in d && d.remainingInAntardasha ? import_lit4.html`<small>${formatNumber(d.remainingInAntardasha.years + d.remainingInAntardasha.months / 12, 1)} years left</small>` : import_lit4.nothing}
|
|
641
|
+
</div>` : import_lit4.nothing}
|
|
642
|
+
${"pratyantardasha" in d && d.pratyantardasha ? import_lit4.html`<div>
|
|
643
|
+
<span>Pratyantardasha</span>
|
|
644
|
+
<strong>${d.pratyantardasha.planet}</strong>
|
|
645
|
+
${"remainingInPratyantardasha" in d && d.remainingInPratyantardasha ? import_lit4.html`<small>${formatNumber(d.remainingInPratyantardasha.years + d.remainingInPratyantardasha.months / 12, 1)} years left</small>` : import_lit4.nothing}
|
|
646
|
+
</div>` : import_lit4.nothing}
|
|
589
647
|
</div>`;
|
|
590
648
|
}
|
|
591
649
|
collectPeriods(d) {
|
|
592
|
-
if (
|
|
593
|
-
if (
|
|
594
|
-
return
|
|
650
|
+
if ("mahadashas" in d && d.mahadashas?.length) return d.mahadashas;
|
|
651
|
+
if ("antardashas" in d && d.antardashas?.length) return d.antardashas;
|
|
652
|
+
return [];
|
|
595
653
|
}
|
|
596
654
|
renderBar(p, max) {
|
|
597
|
-
const
|
|
598
|
-
const years = p.durationYears ?? p.years ?? 0;
|
|
655
|
+
const years = p.durationYears;
|
|
599
656
|
const width = max > 0 ? years / max * 100 : 0;
|
|
600
657
|
return import_lit4.html`<div class="bar" role="listitem">
|
|
601
|
-
<span>${
|
|
658
|
+
<span>${p.planet}</span>
|
|
602
659
|
<span class="bar-track"><span style="width: ${width}%"></span></span>
|
|
603
660
|
<span class="dates">
|
|
604
661
|
${p.startDate ? formatYear(p.startDate) : ""}
|
|
@@ -706,15 +763,20 @@ var import_decorators4 = require("lit/decorators.js");
|
|
|
706
763
|
var TITLE_KEYS = ["title", "name", "label", "heading", "overview", "summary"];
|
|
707
764
|
var IMAGE_KEYS = ["imageUrl", "image", "icon", "symbol"];
|
|
708
765
|
var SKIP_KEYS = ["imageUrl", "image"];
|
|
766
|
+
var MAX_DEPTH = 6;
|
|
709
767
|
var RoxyData = class extends import_lit5.LitElement {
|
|
710
768
|
constructor() {
|
|
711
769
|
super(...arguments);
|
|
712
770
|
this.data = null;
|
|
771
|
+
this.depth = 0;
|
|
713
772
|
}
|
|
714
773
|
render() {
|
|
715
774
|
if (this.data == null) {
|
|
716
775
|
return import_lit5.html`<div class="roxy-empty" role="status">No data</div>`;
|
|
717
776
|
}
|
|
777
|
+
if (this.depth >= MAX_DEPTH) {
|
|
778
|
+
return import_lit5.html`<div class="roxy-empty" role="status">…</div>`;
|
|
779
|
+
}
|
|
718
780
|
return import_lit5.html`<div
|
|
719
781
|
class="roxy-card"
|
|
720
782
|
aria-label="Generic data display"
|
|
@@ -811,7 +873,7 @@ var RoxyData = class extends import_lit5.LitElement {
|
|
|
811
873
|
</ul>`;
|
|
812
874
|
}
|
|
813
875
|
}
|
|
814
|
-
return import_lit5.html`<roxy-data .data=${value}></roxy-data>`;
|
|
876
|
+
return import_lit5.html`<roxy-data .data=${value} .depth=${this.depth + 1}></roxy-data>`;
|
|
815
877
|
}
|
|
816
878
|
formatPrimitive(value) {
|
|
817
879
|
if (value === null || value === void 0) return "";
|
|
@@ -933,6 +995,9 @@ RoxyData.styles = [
|
|
|
933
995
|
__decorateClass([
|
|
934
996
|
(0, import_decorators4.property)({ attribute: false })
|
|
935
997
|
], RoxyData.prototype, "data", 2);
|
|
998
|
+
__decorateClass([
|
|
999
|
+
(0, import_decorators4.property)({ attribute: false })
|
|
1000
|
+
], RoxyData.prototype, "depth", 2);
|
|
936
1001
|
RoxyData = __decorateClass([
|
|
937
1002
|
(0, import_decorators4.customElement)("roxy-data")
|
|
938
1003
|
], RoxyData);
|
|
@@ -978,25 +1043,24 @@ var RoxyDoshaCard = class extends import_lit6.LitElement {
|
|
|
978
1043
|
</div>
|
|
979
1044
|
</header>
|
|
980
1045
|
${d.description ? import_lit6.html`<p class="description">${d.description}</p>` : import_lit6.nothing}
|
|
981
|
-
${this.renderEffects(d
|
|
1046
|
+
${this.renderEffects(d)}
|
|
982
1047
|
${d.remedies && d.remedies.length > 0 ? import_lit6.html`<div>
|
|
983
1048
|
<h3>Remedies</h3>
|
|
984
1049
|
<ul>
|
|
985
1050
|
${d.remedies.map((r) => import_lit6.html`<li>${r}</li>`)}
|
|
986
1051
|
</ul>
|
|
987
1052
|
</div>` : import_lit6.nothing}
|
|
988
|
-
${d.exceptions && d.exceptions.length > 0 ? import_lit6.html`<div>
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1053
|
+
${"exceptions" in d && d.exceptions && d.exceptions.length > 0 ? import_lit6.html`<div>
|
|
1054
|
+
<h3>Exceptions</h3>
|
|
1055
|
+
<ul>
|
|
1056
|
+
${d.exceptions.map((r) => import_lit6.html`<li>${r}</li>`)}
|
|
1057
|
+
</ul>
|
|
1058
|
+
</div>` : import_lit6.nothing}
|
|
994
1059
|
</article>`;
|
|
995
1060
|
}
|
|
996
|
-
renderEffects(
|
|
997
|
-
if (!
|
|
998
|
-
|
|
999
|
-
const entries = Object.entries(e).filter(
|
|
1061
|
+
renderEffects(d) {
|
|
1062
|
+
if (!d.effects) return import_lit6.nothing;
|
|
1063
|
+
const entries = Object.entries(d.effects).filter(
|
|
1000
1064
|
([, v]) => typeof v === "string" && v.length > 0
|
|
1001
1065
|
);
|
|
1002
1066
|
if (entries.length === 0) return import_lit6.nothing;
|
|
@@ -1048,11 +1112,11 @@ RoxyDoshaCard.styles = [
|
|
|
1048
1112
|
}
|
|
1049
1113
|
.badge.absent {
|
|
1050
1114
|
background: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);
|
|
1051
|
-
color: var(--roxy-success, #
|
|
1115
|
+
color: var(--roxy-success-fg, #166534);
|
|
1052
1116
|
}
|
|
1053
1117
|
.badge.present {
|
|
1054
1118
|
background: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);
|
|
1055
|
-
color: var(--roxy-danger, #
|
|
1119
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
1056
1120
|
}
|
|
1057
1121
|
.severity {
|
|
1058
1122
|
display: flex;
|
|
@@ -1116,6 +1180,21 @@ RoxyDoshaCard = __decorateClass([
|
|
|
1116
1180
|
// packages/ui/src/components/endpoint-form.ts
|
|
1117
1181
|
var import_lit7 = require("lit");
|
|
1118
1182
|
var import_decorators6 = require("lit/decorators.js");
|
|
1183
|
+
var specCache = /* @__PURE__ */ new Map();
|
|
1184
|
+
async function loadSpec(url) {
|
|
1185
|
+
let pending = specCache.get(url);
|
|
1186
|
+
if (!pending) {
|
|
1187
|
+
pending = fetch(url).then(async (res) => {
|
|
1188
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1189
|
+
return await res.json();
|
|
1190
|
+
}).catch((err) => {
|
|
1191
|
+
specCache.delete(url);
|
|
1192
|
+
throw err;
|
|
1193
|
+
});
|
|
1194
|
+
specCache.set(url, pending);
|
|
1195
|
+
}
|
|
1196
|
+
return pending;
|
|
1197
|
+
}
|
|
1119
1198
|
var RoxyEndpointForm = class extends import_lit7.LitElement {
|
|
1120
1199
|
constructor() {
|
|
1121
1200
|
super(...arguments);
|
|
@@ -1127,6 +1206,12 @@ var RoxyEndpointForm = class extends import_lit7.LitElement {
|
|
|
1127
1206
|
this.values = {};
|
|
1128
1207
|
this.hasLocation = false;
|
|
1129
1208
|
this.loaded = false;
|
|
1209
|
+
this.specError = null;
|
|
1210
|
+
this.retryLoadSchema = () => {
|
|
1211
|
+
this.loaded = false;
|
|
1212
|
+
this.specError = null;
|
|
1213
|
+
void this.loadSchema();
|
|
1214
|
+
};
|
|
1130
1215
|
this.onLocation = (e) => {
|
|
1131
1216
|
const detail = e.detail;
|
|
1132
1217
|
if (detail) {
|
|
@@ -1167,13 +1252,16 @@ var RoxyEndpointForm = class extends import_lit7.LitElement {
|
|
|
1167
1252
|
void this.loadSchema();
|
|
1168
1253
|
}
|
|
1169
1254
|
async loadSchema() {
|
|
1255
|
+
this.specError = null;
|
|
1170
1256
|
try {
|
|
1171
|
-
const
|
|
1172
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1173
|
-
const spec = await res.json();
|
|
1257
|
+
const spec = await loadSpec(this.specUrl);
|
|
1174
1258
|
const path = `/${this.endpoint.replace(/^\//, "")}`;
|
|
1175
1259
|
const op = spec.paths?.[path]?.[this.method.toLowerCase()];
|
|
1176
|
-
if (!op)
|
|
1260
|
+
if (!op) {
|
|
1261
|
+
throw new Error(
|
|
1262
|
+
`Endpoint ${this.method} ${path} not found in OpenAPI spec`
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1177
1265
|
const schemas = spec.components?.schemas ?? {};
|
|
1178
1266
|
const fields = [];
|
|
1179
1267
|
let bodySchema;
|
|
@@ -1218,8 +1306,17 @@ var RoxyEndpointForm = class extends import_lit7.LitElement {
|
|
|
1218
1306
|
}
|
|
1219
1307
|
this.values = init;
|
|
1220
1308
|
this.loaded = true;
|
|
1221
|
-
} catch (
|
|
1309
|
+
} catch (err) {
|
|
1310
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1311
|
+
this.specError = message;
|
|
1222
1312
|
this.loaded = true;
|
|
1313
|
+
this.dispatchEvent(
|
|
1314
|
+
new CustomEvent("roxy-spec-error", {
|
|
1315
|
+
detail: { url: this.specUrl, message },
|
|
1316
|
+
bubbles: true,
|
|
1317
|
+
composed: true
|
|
1318
|
+
})
|
|
1319
|
+
);
|
|
1223
1320
|
}
|
|
1224
1321
|
}
|
|
1225
1322
|
resolve(schema, all) {
|
|
@@ -1245,6 +1342,12 @@ var RoxyEndpointForm = class extends import_lit7.LitElement {
|
|
|
1245
1342
|
if (!this.loaded) {
|
|
1246
1343
|
return import_lit7.html`<form><div class="roxy-skeleton" style="height: 8rem"></div></form>`;
|
|
1247
1344
|
}
|
|
1345
|
+
if (this.specError) {
|
|
1346
|
+
return import_lit7.html`<div class="spec-error" role="alert">
|
|
1347
|
+
Schema load failed: ${this.specError}
|
|
1348
|
+
<button type="button" class="submit" @click=${this.retryLoadSchema}>Retry</button>
|
|
1349
|
+
</div>`;
|
|
1350
|
+
}
|
|
1248
1351
|
const renderField = (f) => {
|
|
1249
1352
|
if (this.hasLocation && (f.name === "latitude" || f.name === "longitude" || f.name === "timezone")) {
|
|
1250
1353
|
return import_lit7.nothing;
|
|
@@ -1342,22 +1445,27 @@ RoxyEndpointForm.styles = [
|
|
|
1342
1445
|
.fields {
|
|
1343
1446
|
display: grid;
|
|
1344
1447
|
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
|
1448
|
+
align-items: start;
|
|
1345
1449
|
gap: var(--roxy-space-md, 1rem);
|
|
1346
1450
|
}
|
|
1347
1451
|
.field {
|
|
1348
|
-
display:
|
|
1452
|
+
display: flex;
|
|
1453
|
+
flex-direction: column;
|
|
1349
1454
|
gap: var(--roxy-space-xs, 0.25rem);
|
|
1455
|
+
min-width: 0;
|
|
1350
1456
|
}
|
|
1351
1457
|
label {
|
|
1352
1458
|
font-size: var(--roxy-text-sm, 0.875rem);
|
|
1353
1459
|
color: var(--roxy-secondary, #475569);
|
|
1354
1460
|
}
|
|
1355
1461
|
label .req {
|
|
1356
|
-
color: var(--roxy-danger, #
|
|
1462
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
1357
1463
|
margin-left: 4px;
|
|
1358
1464
|
}
|
|
1359
1465
|
input,
|
|
1360
1466
|
select {
|
|
1467
|
+
width: 100%;
|
|
1468
|
+
box-sizing: border-box;
|
|
1361
1469
|
padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
|
|
1362
1470
|
font-size: var(--roxy-text-base, 1rem);
|
|
1363
1471
|
font-family: inherit;
|
|
@@ -1392,7 +1500,7 @@ RoxyEndpointForm.styles = [
|
|
|
1392
1500
|
button.submit {
|
|
1393
1501
|
justify-self: start;
|
|
1394
1502
|
background: var(--roxy-accent-fg, #b45309);
|
|
1395
|
-
color: #fff;
|
|
1503
|
+
color: var(--roxy-bg, #fff);
|
|
1396
1504
|
border: 0;
|
|
1397
1505
|
border-radius: var(--roxy-radius-md, 8px);
|
|
1398
1506
|
padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-lg, 1.5rem);
|
|
@@ -1410,6 +1518,17 @@ RoxyEndpointForm.styles = [
|
|
|
1410
1518
|
outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
|
|
1411
1519
|
outline-offset: 2px;
|
|
1412
1520
|
}
|
|
1521
|
+
.spec-error {
|
|
1522
|
+
display: grid;
|
|
1523
|
+
gap: var(--roxy-space-md, 1rem);
|
|
1524
|
+
justify-items: start;
|
|
1525
|
+
background: var(--roxy-bg, #fff);
|
|
1526
|
+
border: 1px solid var(--roxy-danger, #dc2626);
|
|
1527
|
+
border-radius: var(--roxy-radius-md, 8px);
|
|
1528
|
+
padding: var(--roxy-space-lg, 1.5rem);
|
|
1529
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
1530
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
1531
|
+
}
|
|
1413
1532
|
`
|
|
1414
1533
|
];
|
|
1415
1534
|
__decorateClass([
|
|
@@ -1436,6 +1555,9 @@ __decorateClass([
|
|
|
1436
1555
|
__decorateClass([
|
|
1437
1556
|
(0, import_decorators6.state)()
|
|
1438
1557
|
], RoxyEndpointForm.prototype, "loaded", 2);
|
|
1558
|
+
__decorateClass([
|
|
1559
|
+
(0, import_decorators6.state)()
|
|
1560
|
+
], RoxyEndpointForm.prototype, "specError", 2);
|
|
1439
1561
|
RoxyEndpointForm = __decorateClass([
|
|
1440
1562
|
(0, import_decorators6.customElement)("roxy-endpoint-form")
|
|
1441
1563
|
], RoxyEndpointForm);
|
|
@@ -1455,18 +1577,16 @@ var RoxyGunaMilan = class extends import_lit8.LitElement {
|
|
|
1455
1577
|
const d = this.data;
|
|
1456
1578
|
if (!d)
|
|
1457
1579
|
return import_lit8.html`<div class="roxy-empty" role="status">No Guna Milan data</div>`;
|
|
1458
|
-
const total = d.total ?? d.totalScore ?? 0;
|
|
1459
|
-
const max = d.maxScore ?? 36;
|
|
1460
1580
|
const breakdown = (d.breakdown ?? []).filter(
|
|
1461
|
-
(b) => b
|
|
1581
|
+
(b) => b?.category !== void 0
|
|
1462
1582
|
);
|
|
1463
1583
|
return import_lit8.html`<article class="card" aria-label="Guna Milan score">
|
|
1464
1584
|
<div class="score-bar">
|
|
1465
1585
|
<div>
|
|
1466
|
-
<span class="total">${total}</span>
|
|
1467
|
-
<span class="over"> / ${
|
|
1586
|
+
<span class="total">${formatNumber(d.total, 1)}</span>
|
|
1587
|
+
<span class="over"> / ${d.maxScore}</span>
|
|
1468
1588
|
${typeof d.percentage === "number" ? import_lit8.html`<small style="margin-left: 0.5rem; color: var(--roxy-muted)">
|
|
1469
|
-
${d.percentage}
|
|
1589
|
+
${formatPercent(d.percentage, 1)}
|
|
1470
1590
|
</small>` : import_lit8.nothing}
|
|
1471
1591
|
</div>
|
|
1472
1592
|
${d.recommendation ? import_lit8.html`<span class="recommendation">${d.recommendation}</span>` : import_lit8.nothing}
|
|
@@ -1483,23 +1603,25 @@ var RoxyGunaMilan = class extends import_lit8.LitElement {
|
|
|
1483
1603
|
<tbody>
|
|
1484
1604
|
${breakdown.map((b) => {
|
|
1485
1605
|
const score = b.score ?? 0;
|
|
1486
|
-
const maxScore = b.
|
|
1606
|
+
const maxScore = b.maxScore ?? defaultMax(b.category);
|
|
1487
1607
|
const pct = maxScore ? score / maxScore * 100 : 0;
|
|
1488
1608
|
return import_lit8.html`<tr>
|
|
1489
|
-
<td>${b.
|
|
1609
|
+
<td>${b.category}</td>
|
|
1490
1610
|
<td class="bar-cell">
|
|
1491
1611
|
<div class="mini-bar">
|
|
1492
1612
|
<span style="width: ${pct}%"></span>
|
|
1493
1613
|
</div>
|
|
1494
1614
|
</td>
|
|
1495
|
-
<td class="score">${score} / ${maxScore}</td>
|
|
1615
|
+
<td class="score">${formatNumber(score, 1)} / ${maxScore}</td>
|
|
1496
1616
|
</tr>`;
|
|
1497
1617
|
})}
|
|
1498
1618
|
</tbody>
|
|
1499
1619
|
</table>` : import_lit8.nothing}
|
|
1500
1620
|
${(d.doshas?.length ?? 0) > 0 || (d.doshaCancellations?.length ?? 0) > 0 ? import_lit8.html`<div class="tags">
|
|
1501
1621
|
${d.doshas?.map((x) => import_lit8.html`<span class="dosha">${x}</span>`)}
|
|
1502
|
-
${d.doshaCancellations?.map(
|
|
1622
|
+
${d.doshaCancellations?.map(
|
|
1623
|
+
(x) => import_lit8.html`<span class="cancel" title=${x.reason}>${x.dosha} cancelled</span>`
|
|
1624
|
+
)}
|
|
1503
1625
|
</div>` : import_lit8.nothing}
|
|
1504
1626
|
</article>`;
|
|
1505
1627
|
}
|
|
@@ -1593,11 +1715,11 @@ RoxyGunaMilan.styles = [
|
|
|
1593
1715
|
}
|
|
1594
1716
|
.tags .dosha {
|
|
1595
1717
|
background: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);
|
|
1596
|
-
color: var(--roxy-danger, #
|
|
1718
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
1597
1719
|
}
|
|
1598
1720
|
.tags .cancel {
|
|
1599
1721
|
background: color-mix(in srgb, var(--roxy-success, #16a34a) 18%, transparent);
|
|
1600
|
-
color: var(--roxy-success, #
|
|
1722
|
+
color: var(--roxy-success-fg, #166534);
|
|
1601
1723
|
}
|
|
1602
1724
|
`
|
|
1603
1725
|
];
|
|
@@ -1653,7 +1775,12 @@ var PLANET_GLYPH = {
|
|
|
1653
1775
|
Ascendant: "Asc",
|
|
1654
1776
|
Lagna: "La",
|
|
1655
1777
|
NorthNode: "\u260A",
|
|
1656
|
-
SouthNode: "\u260B"
|
|
1778
|
+
SouthNode: "\u260B",
|
|
1779
|
+
"North node": "\u260A",
|
|
1780
|
+
"South node": "\u260B",
|
|
1781
|
+
Chiron: "\u26B7",
|
|
1782
|
+
Lilith: "\u26B8",
|
|
1783
|
+
"Black moon lilith": "\u26B8"
|
|
1657
1784
|
};
|
|
1658
1785
|
var PLANET_ABBR = {
|
|
1659
1786
|
Sun: "Su",
|
|
@@ -1735,23 +1862,40 @@ var RoxyHexagram = class extends import_lit9.LitElement {
|
|
|
1735
1862
|
this.data = null;
|
|
1736
1863
|
this.mode = "lookup";
|
|
1737
1864
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
if (
|
|
1865
|
+
resolveHexagram() {
|
|
1866
|
+
const d = this.data;
|
|
1867
|
+
if (!d) return null;
|
|
1868
|
+
if ("hexagram" in d && d.hexagram) {
|
|
1869
|
+
if ("lines" in d) {
|
|
1870
|
+
const cast = d;
|
|
1871
|
+
return {
|
|
1872
|
+
hex: cast.hexagram,
|
|
1873
|
+
lines: cast.lines,
|
|
1874
|
+
changingLinePositions: cast.changingLinePositions,
|
|
1875
|
+
resultingHexagram: cast.resultingHexagram
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
const daily = d;
|
|
1741
1879
|
return {
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
changingLinePositions: this.data.changingLinePositions
|
|
1880
|
+
hex: daily.hexagram,
|
|
1881
|
+
dailyMessage: daily.dailyMessage
|
|
1745
1882
|
};
|
|
1746
1883
|
}
|
|
1747
|
-
return
|
|
1884
|
+
return { hex: d };
|
|
1748
1885
|
}
|
|
1749
1886
|
render() {
|
|
1750
|
-
const
|
|
1751
|
-
if (!
|
|
1887
|
+
const resolved = this.resolveHexagram();
|
|
1888
|
+
if (!resolved)
|
|
1752
1889
|
return import_lit9.html`<div class="roxy-empty" role="status">No hexagram data</div>`;
|
|
1753
|
-
const
|
|
1754
|
-
|
|
1890
|
+
const {
|
|
1891
|
+
hex: h,
|
|
1892
|
+
lines: castLines,
|
|
1893
|
+
changingLinePositions,
|
|
1894
|
+
dailyMessage,
|
|
1895
|
+
resultingHexagram
|
|
1896
|
+
} = resolved;
|
|
1897
|
+
const lines = castLines ?? this.derivedLines(h);
|
|
1898
|
+
const changing = new Set(changingLinePositions ?? []);
|
|
1755
1899
|
return import_lit9.html`<article class="card" aria-label="I Ching hexagram">
|
|
1756
1900
|
<div class="glyphs">
|
|
1757
1901
|
${h.symbol ? import_lit9.html`<div class="symbol">${h.symbol}</div>` : import_lit9.nothing}
|
|
@@ -1791,19 +1935,18 @@ var RoxyHexagram = class extends import_lit9.LitElement {
|
|
|
1791
1935
|
</div>
|
|
1792
1936
|
${h.judgment ? import_lit9.html`<p class="judgment">${h.judgment}</p>` : import_lit9.nothing}
|
|
1793
1937
|
${h.image ? import_lit9.html`<p class="image">${h.image}</p>` : import_lit9.nothing}
|
|
1794
|
-
${
|
|
1938
|
+
${dailyMessage ? import_lit9.html`<p class="message">${dailyMessage}</p>` : import_lit9.nothing}
|
|
1795
1939
|
${h.interpretation?.general ? import_lit9.html`<p>${h.interpretation.general}</p>` : import_lit9.nothing}
|
|
1796
1940
|
${changing.size > 0 ? import_lit9.html`<div class="changing">
|
|
1797
1941
|
Changing lines: ${Array.from(changing).sort((a, b) => a - b).join(", ")}.
|
|
1798
|
-
${
|
|
1799
|
-
${
|
|
1942
|
+
${resultingHexagram?.english ? import_lit9.html` Becomes hexagram ${resultingHexagram.number}
|
|
1943
|
+
${resultingHexagram.english}.` : import_lit9.nothing}
|
|
1800
1944
|
</div>` : import_lit9.nothing}
|
|
1801
1945
|
</div>
|
|
1802
1946
|
</article>`;
|
|
1803
1947
|
}
|
|
1804
1948
|
/** When the API only ships symbol+number with no line array, render six solid yang. */
|
|
1805
1949
|
derivedLines(h) {
|
|
1806
|
-
if (!h.symbol) return Array.from({ length: 6 }, () => 7);
|
|
1807
1950
|
const cp = h.symbol.codePointAt(0) ?? 0;
|
|
1808
1951
|
if (cp >= 19904 && cp <= 19967) {
|
|
1809
1952
|
const offset = cp - 19904;
|
|
@@ -1953,8 +2096,8 @@ var RoxyHoroscopeCard = class extends import_lit10.LitElement {
|
|
|
1953
2096
|
return import_lit10.html`<div class="roxy-empty" role="status">No horoscope data</div>`;
|
|
1954
2097
|
const sign = d.sign ?? "";
|
|
1955
2098
|
const glyph = sign ? SIGN_GLYPH[capitalize(sign)] ?? "" : "";
|
|
1956
|
-
const energy = typeof d.energyRating === "number" ? d.energyRating : null;
|
|
1957
|
-
const dateLabel = d.date
|
|
2099
|
+
const energy = "energyRating" in d && typeof d.energyRating === "number" ? d.energyRating : null;
|
|
2100
|
+
const dateLabel = "date" in d && d.date || "week" in d && d.week || "month" in d && d.month || "";
|
|
1958
2101
|
return import_lit10.html`<article
|
|
1959
2102
|
class="card"
|
|
1960
2103
|
aria-label=${`${this.period} horoscope for ${sign}`}
|
|
@@ -1992,31 +2135,40 @@ var RoxyHoroscopeCard = class extends import_lit10.LitElement {
|
|
|
1992
2135
|
<h3>Finance</h3>
|
|
1993
2136
|
<p>${d.finance}</p>
|
|
1994
2137
|
</div>` : import_lit10.nothing}
|
|
1995
|
-
${d.advice ? import_lit10.html`<div class="section">
|
|
2138
|
+
${"advice" in d && d.advice ? import_lit10.html`<div class="section">
|
|
1996
2139
|
<h3>Advice</h3>
|
|
1997
2140
|
<p>${d.advice}</p>
|
|
1998
2141
|
</div>` : import_lit10.nothing}
|
|
1999
2142
|
</div>
|
|
2000
2143
|
|
|
2001
|
-
${
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2144
|
+
${(() => {
|
|
2145
|
+
const luckyNumber = "luckyNumber" in d && d.luckyNumber !== void 0 ? d.luckyNumber : void 0;
|
|
2146
|
+
const luckyColor = "luckyColor" in d && d.luckyColor ? d.luckyColor : "";
|
|
2147
|
+
const luckyNumbers = "luckyNumbers" in d && d.luckyNumbers ? d.luckyNumbers : [];
|
|
2148
|
+
const luckyDays = "luckyDays" in d && d.luckyDays ? d.luckyDays : [];
|
|
2149
|
+
const compatibleSigns = d.compatibleSigns ?? [];
|
|
2150
|
+
if (luckyNumber === void 0 && !luckyColor && luckyNumbers.length === 0 && luckyDays.length === 0 && compatibleSigns.length === 0)
|
|
2151
|
+
return import_lit10.nothing;
|
|
2152
|
+
return import_lit10.html`<div class="lucky">
|
|
2153
|
+
${luckyNumber !== void 0 ? import_lit10.html`<span>Lucky number <strong>${luckyNumber}</strong></span>` : import_lit10.nothing}
|
|
2154
|
+
${luckyColor ? import_lit10.html`<span>Lucky color <strong>${luckyColor}</strong></span>` : import_lit10.nothing}
|
|
2155
|
+
${luckyNumbers.length ? import_lit10.html`<span
|
|
2005
2156
|
>Lucky numbers
|
|
2006
|
-
<strong>${
|
|
2157
|
+
<strong>${luckyNumbers.join(", ")}</strong></span
|
|
2007
2158
|
>` : import_lit10.nothing}
|
|
2008
|
-
${
|
|
2009
|
-
>Lucky days <strong>${
|
|
2159
|
+
${luckyDays.length ? import_lit10.html`<span
|
|
2160
|
+
>Lucky days <strong>${luckyDays.join(", ")}</strong></span
|
|
2010
2161
|
>` : import_lit10.nothing}
|
|
2011
|
-
${
|
|
2162
|
+
${compatibleSigns.length ? import_lit10.html`<span class="compat-wrap">
|
|
2012
2163
|
Best with
|
|
2013
2164
|
<span class="compat"
|
|
2014
|
-
>${
|
|
2015
|
-
|
|
2016
|
-
|
|
2165
|
+
>${compatibleSigns.map(
|
|
2166
|
+
(s) => import_lit10.html`<span>${s}</span>`
|
|
2167
|
+
)}</span
|
|
2017
2168
|
>
|
|
2018
2169
|
</span>` : import_lit10.nothing}
|
|
2019
|
-
</div
|
|
2170
|
+
</div>`;
|
|
2171
|
+
})()}
|
|
2020
2172
|
</article>`;
|
|
2021
2173
|
}
|
|
2022
2174
|
};
|
|
@@ -2171,7 +2323,7 @@ var RoxyKpPlanetsTable = class extends import_lit11.LitElement {
|
|
|
2171
2323
|
>
|
|
2172
2324
|
<header class="head">
|
|
2173
2325
|
<h2 class="title">KP planets</h2>
|
|
2174
|
-
${this.data.ayanamsa ? import_lit11.html`<span class="ayanamsa">Ayanamsa: ${this.data.ayanamsa}
|
|
2326
|
+
${typeof this.data.ayanamsa === "number" ? import_lit11.html`<span class="ayanamsa">Ayanamsa: ${formatNumber(this.data.ayanamsa, 2)}°</span>` : import_lit11.nothing}
|
|
2175
2327
|
</header>
|
|
2176
2328
|
<table role="table">
|
|
2177
2329
|
<thead>
|
|
@@ -2190,13 +2342,13 @@ var RoxyKpPlanetsTable = class extends import_lit11.LitElement {
|
|
|
2190
2342
|
${planets.map(
|
|
2191
2343
|
(p) => import_lit11.html`<tr>
|
|
2192
2344
|
<td class="planet">
|
|
2193
|
-
${p.planet
|
|
2345
|
+
${p.planet}
|
|
2194
2346
|
${p.retrograde ? import_lit11.html`<span class="retro">R</span>` : import_lit11.nothing}
|
|
2195
2347
|
</td>
|
|
2196
2348
|
<td>${p.sign ?? ""}</td>
|
|
2197
2349
|
<td>${p.signLord ?? ""}</td>
|
|
2198
2350
|
<td>${p.nakshatra ?? ""}</td>
|
|
2199
|
-
<td>${p.
|
|
2351
|
+
<td>${p.nakshatraLord ?? ""}</td>
|
|
2200
2352
|
<td>${p.subLord ?? ""}</td>
|
|
2201
2353
|
<td>${p.subSubLord ?? ""}</td>
|
|
2202
2354
|
<td>${p.kpNumber ?? ""}</td>
|
|
@@ -2264,7 +2416,7 @@ RoxyKpPlanetsTable.styles = [
|
|
|
2264
2416
|
color: var(--roxy-fg, #0a0a0a);
|
|
2265
2417
|
}
|
|
2266
2418
|
.retro {
|
|
2267
|
-
color: var(--roxy-warning, #
|
|
2419
|
+
color: var(--roxy-warning-fg, #9a3412);
|
|
2268
2420
|
font-size: var(--roxy-text-xs, 0.75rem);
|
|
2269
2421
|
margin-left: 4px;
|
|
2270
2422
|
}
|
|
@@ -2284,10 +2436,20 @@ var import_decorators11 = require("lit/decorators.js");
|
|
|
2284
2436
|
// packages/ui/src/utils/debounce.ts
|
|
2285
2437
|
function debounce(fn, wait) {
|
|
2286
2438
|
let timer;
|
|
2287
|
-
|
|
2439
|
+
const debounced = ((...args) => {
|
|
2288
2440
|
if (timer) clearTimeout(timer);
|
|
2289
|
-
timer = setTimeout(() =>
|
|
2441
|
+
timer = setTimeout(() => {
|
|
2442
|
+
timer = void 0;
|
|
2443
|
+
fn(...args);
|
|
2444
|
+
}, wait);
|
|
2290
2445
|
});
|
|
2446
|
+
debounced.cancel = () => {
|
|
2447
|
+
if (timer) {
|
|
2448
|
+
clearTimeout(timer);
|
|
2449
|
+
timer = void 0;
|
|
2450
|
+
}
|
|
2451
|
+
};
|
|
2452
|
+
return debounced;
|
|
2291
2453
|
}
|
|
2292
2454
|
|
|
2293
2455
|
// packages/ui/src/components/location-search.ts
|
|
@@ -2302,6 +2464,7 @@ var RoxyLocationSearch = class extends import_lit12.LitElement {
|
|
|
2302
2464
|
this.isOpen = false;
|
|
2303
2465
|
this.isLoading = false;
|
|
2304
2466
|
this.highlight = -1;
|
|
2467
|
+
this.secretKeyWarned = false;
|
|
2305
2468
|
this.debouncedFetch = debounce((q) => {
|
|
2306
2469
|
void this.fetchResults(q);
|
|
2307
2470
|
}, 300);
|
|
@@ -2353,8 +2516,32 @@ var RoxyLocationSearch = class extends import_lit12.LitElement {
|
|
|
2353
2516
|
if (this.clickOutsideHandler) {
|
|
2354
2517
|
document.removeEventListener("mousedown", this.clickOutsideHandler);
|
|
2355
2518
|
}
|
|
2519
|
+
this.debouncedFetch.cancel();
|
|
2520
|
+
if (this.abortController) {
|
|
2521
|
+
this.abortController.abort();
|
|
2522
|
+
this.abortController = void 0;
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
warnIfSecretKey() {
|
|
2526
|
+
if (this.secretKeyWarned) return;
|
|
2527
|
+
if (!this.apiKey) return;
|
|
2528
|
+
if (this.apiKey.startsWith("pk_")) return;
|
|
2529
|
+
this.secretKeyWarned = true;
|
|
2530
|
+
const message = "Possible secret key in client-side <roxy-location-search>; use a `pk_` publishable key with origin allowlist instead.";
|
|
2531
|
+
console.warn(message);
|
|
2532
|
+
this.dispatchEvent(
|
|
2533
|
+
new CustomEvent("roxy-validation-error", {
|
|
2534
|
+
detail: { reason: "possible-secret-key", message },
|
|
2535
|
+
bubbles: true,
|
|
2536
|
+
composed: true
|
|
2537
|
+
})
|
|
2538
|
+
);
|
|
2356
2539
|
}
|
|
2357
2540
|
async fetchResults(q) {
|
|
2541
|
+
this.warnIfSecretKey();
|
|
2542
|
+
if (this.abortController) this.abortController.abort();
|
|
2543
|
+
const controller = new AbortController();
|
|
2544
|
+
this.abortController = controller;
|
|
2358
2545
|
this.isLoading = true;
|
|
2359
2546
|
try {
|
|
2360
2547
|
const url = new URL(this.endpoint);
|
|
@@ -2365,17 +2552,22 @@ var RoxyLocationSearch = class extends import_lit12.LitElement {
|
|
|
2365
2552
|
};
|
|
2366
2553
|
if (this.apiKey) headers["X-API-Key"] = this.apiKey;
|
|
2367
2554
|
if (this.publishableKey) headers["X-API-Key"] = this.publishableKey;
|
|
2368
|
-
const res = await fetch(url, { headers });
|
|
2555
|
+
const res = await fetch(url, { headers, signal: controller.signal });
|
|
2369
2556
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
2370
2557
|
const json = await res.json();
|
|
2558
|
+
if (controller.signal.aborted) return;
|
|
2371
2559
|
this.results = json.cities ?? [];
|
|
2372
2560
|
this.isOpen = this.results.length > 0;
|
|
2373
2561
|
this.highlight = this.results.length > 0 ? 0 : -1;
|
|
2374
|
-
} catch (
|
|
2562
|
+
} catch (err) {
|
|
2563
|
+
if (err?.name === "AbortError") return;
|
|
2375
2564
|
this.results = [];
|
|
2376
2565
|
this.isOpen = false;
|
|
2377
2566
|
} finally {
|
|
2378
|
-
this.
|
|
2567
|
+
if (this.abortController === controller) {
|
|
2568
|
+
this.abortController = void 0;
|
|
2569
|
+
}
|
|
2570
|
+
if (!controller.signal.aborted) this.isLoading = false;
|
|
2379
2571
|
}
|
|
2380
2572
|
}
|
|
2381
2573
|
select(city) {
|
|
@@ -2591,18 +2783,21 @@ var RoxyMoonPhase = class extends import_lit13.LitElement {
|
|
|
2591
2783
|
const d = this.data;
|
|
2592
2784
|
if (!d)
|
|
2593
2785
|
return import_lit13.html`<div class="roxy-empty" role="status">No moon phase data</div>`;
|
|
2594
|
-
const list = d.phases
|
|
2786
|
+
const list = "phases" in d ? d.phases : "calendar" in d ? d.calendar : [];
|
|
2595
2787
|
if (this.mode !== "current" && list.length > 0) {
|
|
2788
|
+
const month = "month" in d ? d.month : void 0;
|
|
2789
|
+
const year = "year" in d ? d.year : void 0;
|
|
2596
2790
|
return import_lit13.html`<article
|
|
2597
2791
|
class="card"
|
|
2598
2792
|
aria-label="Moon phase calendar"
|
|
2599
2793
|
>
|
|
2600
|
-
<h2 class="label">${
|
|
2794
|
+
<h2 class="label">${month ?? "Moon phases"} ${year ?? ""}</h2>
|
|
2601
2795
|
<div class="list" role="list">
|
|
2602
2796
|
${list.map((phase) => this.renderListItem(phase))}
|
|
2603
2797
|
</div>
|
|
2604
2798
|
</article>`;
|
|
2605
2799
|
}
|
|
2800
|
+
if (!("phase" in d)) return import_lit13.nothing;
|
|
2606
2801
|
return this.renderSingle(d);
|
|
2607
2802
|
}
|
|
2608
2803
|
renderSingle(d) {
|
|
@@ -2618,11 +2813,11 @@ var RoxyMoonPhase = class extends import_lit13.LitElement {
|
|
|
2618
2813
|
<div class="stats">
|
|
2619
2814
|
${typeof d.illumination === "number" ? import_lit13.html`<div>
|
|
2620
2815
|
<span>Illumination</span>
|
|
2621
|
-
<strong>${(d.illumination
|
|
2816
|
+
<strong>${formatIllumination(d.illumination)}</strong>
|
|
2622
2817
|
</div>` : import_lit13.nothing}
|
|
2623
2818
|
${typeof d.age === "number" ? import_lit13.html`<div>
|
|
2624
2819
|
<span>Age</span>
|
|
2625
|
-
<strong>${d.age
|
|
2820
|
+
<strong>${formatNumber(d.age, 1)} days</strong>
|
|
2626
2821
|
</div>` : import_lit13.nothing}
|
|
2627
2822
|
${d.sign ? import_lit13.html`<div>
|
|
2628
2823
|
<span>Sign</span>
|
|
@@ -2747,6 +2942,10 @@ function phaseEmoji(phase) {
|
|
|
2747
2942
|
if (!phase) return "\u{1F319}";
|
|
2748
2943
|
return MOON_PHASE_EMOJI[phase.toLowerCase()] ?? "\u{1F319}";
|
|
2749
2944
|
}
|
|
2945
|
+
function formatIllumination(v) {
|
|
2946
|
+
const pct = v <= 1 ? v * 100 : v;
|
|
2947
|
+
return `${Math.round(pct)}%`;
|
|
2948
|
+
}
|
|
2750
2949
|
|
|
2751
2950
|
// packages/ui/src/components/natal-chart.ts
|
|
2752
2951
|
var import_lit14 = require("lit");
|
|
@@ -2762,12 +2961,14 @@ function polarToCartesian(cx, cy, radius, angleDeg) {
|
|
|
2762
2961
|
}
|
|
2763
2962
|
|
|
2764
2963
|
// packages/ui/src/components/natal-chart.ts
|
|
2765
|
-
var SIZE =
|
|
2964
|
+
var SIZE = 384;
|
|
2766
2965
|
var CENTER = SIZE / 2;
|
|
2767
2966
|
var OUTER_R = 150;
|
|
2768
2967
|
var SIGN_R = 134;
|
|
2769
2968
|
var HOUSE_R = 110;
|
|
2770
2969
|
var PLANET_R = 88;
|
|
2970
|
+
var ANGLE_TICK_R = 162;
|
|
2971
|
+
var ANGLE_LABEL_R = 176;
|
|
2771
2972
|
var RoxyNatalChart = class extends import_lit14.LitElement {
|
|
2772
2973
|
constructor() {
|
|
2773
2974
|
super(...arguments);
|
|
@@ -2775,10 +2976,17 @@ var RoxyNatalChart = class extends import_lit14.LitElement {
|
|
|
2775
2976
|
this.houseSystem = "placidus";
|
|
2776
2977
|
}
|
|
2777
2978
|
getPlanets() {
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
return
|
|
2979
|
+
return this.data?.planets ?? [];
|
|
2980
|
+
}
|
|
2981
|
+
getAscendant() {
|
|
2982
|
+
return this.data?.ascendant?.longitude ?? 0;
|
|
2983
|
+
}
|
|
2984
|
+
getMidheaven() {
|
|
2985
|
+
const m = this.data?.midheaven?.longitude;
|
|
2986
|
+
return typeof m === "number" ? m : null;
|
|
2987
|
+
}
|
|
2988
|
+
toAngle(lon) {
|
|
2989
|
+
return 180 + this.getAscendant() - lon;
|
|
2782
2990
|
}
|
|
2783
2991
|
render() {
|
|
2784
2992
|
if (!this.data)
|
|
@@ -2789,11 +2997,7 @@ var RoxyNatalChart = class extends import_lit14.LitElement {
|
|
|
2789
2997
|
<header>
|
|
2790
2998
|
<h2 class="title">Natal chart</h2>
|
|
2791
2999
|
${this.data.birthDetails ? import_lit14.html`<div class="meta">
|
|
2792
|
-
${[
|
|
2793
|
-
this.data.birthDetails.date,
|
|
2794
|
-
this.data.birthDetails.time,
|
|
2795
|
-
this.data.birthDetails.location
|
|
2796
|
-
].filter(Boolean).join(" \xB7 ")}
|
|
3000
|
+
${[this.data.birthDetails.date, this.data.birthDetails.time].filter(Boolean).join(" \xB7 ")}
|
|
2797
3001
|
</div>` : import_lit14.nothing}
|
|
2798
3002
|
</header>
|
|
2799
3003
|
<svg
|
|
@@ -2829,17 +3033,38 @@ var RoxyNatalChart = class extends import_lit14.LitElement {
|
|
|
2829
3033
|
/>
|
|
2830
3034
|
${this.renderSpokes()} ${this.renderSigns()} ${this.renderHouseNumbers()}
|
|
2831
3035
|
${this.renderAspects(planets, aspects)} ${this.renderPlanets(planets)}
|
|
3036
|
+
${this.renderAngles()}
|
|
2832
3037
|
</svg>
|
|
2833
3038
|
<div class="legend">
|
|
2834
3039
|
<span>${planets.length} planets</span>
|
|
2835
3040
|
<span>${aspects.length} aspects</span>
|
|
2836
|
-
<span
|
|
3041
|
+
<span><span class="legend-swatch" style="background: var(--roxy-success)"></span>harmonious</span>
|
|
3042
|
+
<span><span class="legend-swatch" style="background: var(--roxy-danger)"></span>challenging</span>
|
|
2837
3043
|
</div>
|
|
2838
3044
|
</div>`;
|
|
2839
3045
|
}
|
|
3046
|
+
renderAngles() {
|
|
3047
|
+
const asc = this.getAscendant();
|
|
3048
|
+
const mc = this.getMidheaven();
|
|
3049
|
+
const items = [this.renderAngleMark(asc, "ASC")];
|
|
3050
|
+
if (mc !== null) items.push(this.renderAngleMark(mc, "MC"));
|
|
3051
|
+
return items;
|
|
3052
|
+
}
|
|
3053
|
+
renderAngleMark(longitude, label) {
|
|
3054
|
+
const angle = this.toAngle(longitude);
|
|
3055
|
+
const tickInner = polarToCartesian(CENTER, CENTER, OUTER_R, angle);
|
|
3056
|
+
const tickOuter = polarToCartesian(CENTER, CENTER, ANGLE_TICK_R, angle);
|
|
3057
|
+
const labelPos = polarToCartesian(CENTER, CENTER, ANGLE_LABEL_R, angle);
|
|
3058
|
+
return import_lit14.svg`
|
|
3059
|
+
<g>
|
|
3060
|
+
<line class="angle-tick" x1=${tickInner.x} y1=${tickInner.y} x2=${tickOuter.x} y2=${tickOuter.y} />
|
|
3061
|
+
<text class="angle-marker" x=${labelPos.x} y=${labelPos.y} text-anchor="middle" dominant-baseline="central">${label}</text>
|
|
3062
|
+
</g>
|
|
3063
|
+
`;
|
|
3064
|
+
}
|
|
2840
3065
|
renderSpokes() {
|
|
2841
3066
|
return Array.from({ length: 12 }, (_, i) => {
|
|
2842
|
-
const angle = i * 30
|
|
3067
|
+
const angle = this.toAngle(i * 30);
|
|
2843
3068
|
const start = polarToCartesian(CENTER, CENTER, HOUSE_R, angle);
|
|
2844
3069
|
const end = polarToCartesian(CENTER, CENTER, OUTER_R, angle);
|
|
2845
3070
|
return import_lit14.svg`<line class="wheel-line" x1=${start.x} y1=${start.y} x2=${end.x} y2=${end.y} stroke-width="0.8" />`;
|
|
@@ -2861,45 +3086,58 @@ var RoxyNatalChart = class extends import_lit14.LitElement {
|
|
|
2861
3086
|
"Pisces"
|
|
2862
3087
|
];
|
|
2863
3088
|
return order.map((sign, i) => {
|
|
2864
|
-
const angle = i * 30 + 15
|
|
3089
|
+
const angle = this.toAngle(i * 30 + 15);
|
|
2865
3090
|
const pos = polarToCartesian(CENTER, CENTER, SIGN_R, angle);
|
|
2866
3091
|
return import_lit14.svg`<text class="sign-glyph" x=${pos.x} y=${pos.y} text-anchor="middle" dominant-baseline="central">${SIGN_GLYPH[sign]}</text>`;
|
|
2867
3092
|
});
|
|
2868
3093
|
}
|
|
2869
3094
|
renderHouseNumbers() {
|
|
3095
|
+
const ascSignIndex = Math.floor(this.getAscendant() / 30);
|
|
2870
3096
|
return Array.from({ length: 12 }, (_, i) => {
|
|
2871
|
-
const angle = i * 30 + 15
|
|
3097
|
+
const angle = this.toAngle(i * 30 + 15);
|
|
2872
3098
|
const pos = polarToCartesian(CENTER, CENTER, HOUSE_R - 12, angle);
|
|
2873
|
-
|
|
3099
|
+
const houseNum = (i - ascSignIndex + 12) % 12 + 1;
|
|
3100
|
+
return import_lit14.svg`<text class="house-num" x=${pos.x} y=${pos.y} text-anchor="middle" dominant-baseline="central">${houseNum}</text>`;
|
|
2874
3101
|
});
|
|
2875
3102
|
}
|
|
2876
3103
|
renderPlanets(planets) {
|
|
2877
3104
|
return planets.map((p) => {
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
const angle = lon - 90;
|
|
3105
|
+
if (!Number.isFinite(p.longitude)) return import_lit14.nothing;
|
|
3106
|
+
const angle = this.toAngle(p.longitude);
|
|
2881
3107
|
const pos = polarToCartesian(CENTER, CENTER, PLANET_R, angle);
|
|
2882
|
-
const
|
|
2883
|
-
const
|
|
2884
|
-
const
|
|
2885
|
-
return import_lit14.svg`<text class="planet-glyph" x=${pos.x} y=${pos.y} text-anchor="middle" dominant-baseline="central"><title>${name}${retro}</title>${
|
|
3108
|
+
const glyph = PLANET_GLYPH[capitalize2(p.name)] ?? p.name.slice(0, 2);
|
|
3109
|
+
const retro = p.isRetrograde ? " R" : "";
|
|
3110
|
+
const display = retro ? `${glyph}\u1D3F` : glyph;
|
|
3111
|
+
return import_lit14.svg`<text class="planet-glyph" x=${pos.x} y=${pos.y} text-anchor="middle" dominant-baseline="central"><title>${p.name}${retro}</title>${display}</text>`;
|
|
2886
3112
|
});
|
|
2887
3113
|
}
|
|
2888
3114
|
renderAspects(planets, aspects) {
|
|
2889
3115
|
const planetMap = /* @__PURE__ */ new Map();
|
|
2890
3116
|
for (const p of planets) {
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
if (name) planetMap.set(name, lon);
|
|
3117
|
+
if (typeof p.longitude !== "number") continue;
|
|
3118
|
+
const name = capitalize2(p.name);
|
|
3119
|
+
if (name) planetMap.set(name, p.longitude);
|
|
2895
3120
|
}
|
|
2896
3121
|
return aspects.map((a) => {
|
|
2897
|
-
const l1 = planetMap.get(capitalize2(a.planet1
|
|
2898
|
-
const l2 = planetMap.get(capitalize2(a.planet2
|
|
3122
|
+
const l1 = planetMap.get(capitalize2(a.planet1));
|
|
3123
|
+
const l2 = planetMap.get(capitalize2(a.planet2));
|
|
2899
3124
|
if (l1 === void 0 || l2 === void 0) return import_lit14.nothing;
|
|
2900
|
-
const p1 = polarToCartesian(
|
|
2901
|
-
|
|
2902
|
-
|
|
3125
|
+
const p1 = polarToCartesian(
|
|
3126
|
+
CENTER,
|
|
3127
|
+
CENTER,
|
|
3128
|
+
PLANET_R - 18,
|
|
3129
|
+
this.toAngle(l1)
|
|
3130
|
+
);
|
|
3131
|
+
const p2 = polarToCartesian(
|
|
3132
|
+
CENTER,
|
|
3133
|
+
CENTER,
|
|
3134
|
+
PLANET_R - 18,
|
|
3135
|
+
this.toAngle(l2)
|
|
3136
|
+
);
|
|
3137
|
+
const aspectName = normalizeAspect(a);
|
|
3138
|
+
const aspectClass = ASPECT_CLASS[aspectName] ?? "aspect-other";
|
|
3139
|
+
const orbLabel = formatNumber(a.orb, 1);
|
|
3140
|
+
return import_lit14.svg`<line class=${`aspect ${aspectClass}`} x1=${p1.x} y1=${p1.y} x2=${p2.x} y2=${p2.y}><title>${a.planet1} ${aspectName || ""} ${a.planet2}${orbLabel ? ` (orb ${orbLabel}\xB0)` : ""}</title></line>`;
|
|
2903
3141
|
});
|
|
2904
3142
|
}
|
|
2905
3143
|
};
|
|
@@ -2957,9 +3195,36 @@ RoxyNatalChart.styles = [
|
|
|
2957
3195
|
}
|
|
2958
3196
|
|
|
2959
3197
|
.aspect {
|
|
2960
|
-
stroke:
|
|
2961
|
-
stroke-width: 0.6;
|
|
3198
|
+
stroke-width: 0.8;
|
|
2962
3199
|
fill: none;
|
|
3200
|
+
opacity: 0.55;
|
|
3201
|
+
}
|
|
3202
|
+
.aspect-trine,
|
|
3203
|
+
.aspect-sextile {
|
|
3204
|
+
stroke: var(--roxy-success, #16a34a);
|
|
3205
|
+
}
|
|
3206
|
+
.aspect-square,
|
|
3207
|
+
.aspect-opposition {
|
|
3208
|
+
stroke: var(--roxy-danger, #dc2626);
|
|
3209
|
+
}
|
|
3210
|
+
.aspect-conjunction {
|
|
3211
|
+
stroke: var(--roxy-accent-fg, #b45309);
|
|
3212
|
+
}
|
|
3213
|
+
.aspect-other {
|
|
3214
|
+
stroke: var(--roxy-muted, #71717a);
|
|
3215
|
+
opacity: 0.4;
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
.angle-marker {
|
|
3219
|
+
fill: var(--roxy-accent-fg, #b45309);
|
|
3220
|
+
font-size: 10px;
|
|
3221
|
+
font-weight: 700;
|
|
3222
|
+
font-family: var(--roxy-font-sans);
|
|
3223
|
+
letter-spacing: 0.04em;
|
|
3224
|
+
}
|
|
3225
|
+
.angle-tick {
|
|
3226
|
+
stroke: var(--roxy-accent-fg, #b45309);
|
|
3227
|
+
stroke-width: 1.5;
|
|
2963
3228
|
}
|
|
2964
3229
|
|
|
2965
3230
|
.legend {
|
|
@@ -2969,6 +3234,14 @@ RoxyNatalChart.styles = [
|
|
|
2969
3234
|
flex-wrap: wrap;
|
|
2970
3235
|
gap: var(--roxy-space-md, 1rem);
|
|
2971
3236
|
}
|
|
3237
|
+
.legend-swatch {
|
|
3238
|
+
display: inline-block;
|
|
3239
|
+
width: 8px;
|
|
3240
|
+
height: 8px;
|
|
3241
|
+
border-radius: 50%;
|
|
3242
|
+
margin-right: 4px;
|
|
3243
|
+
vertical-align: middle;
|
|
3244
|
+
}
|
|
2972
3245
|
`
|
|
2973
3246
|
];
|
|
2974
3247
|
__decorateClass([
|
|
@@ -2984,6 +3257,16 @@ function capitalize2(s) {
|
|
|
2984
3257
|
if (!s) return "";
|
|
2985
3258
|
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
2986
3259
|
}
|
|
3260
|
+
var ASPECT_CLASS = {
|
|
3261
|
+
conjunction: "aspect-conjunction",
|
|
3262
|
+
sextile: "aspect-sextile",
|
|
3263
|
+
square: "aspect-square",
|
|
3264
|
+
trine: "aspect-trine",
|
|
3265
|
+
opposition: "aspect-opposition"
|
|
3266
|
+
};
|
|
3267
|
+
function normalizeAspect(a) {
|
|
3268
|
+
return (a.type ?? "").toLowerCase().replace(/_/g, "-");
|
|
3269
|
+
}
|
|
2987
3270
|
|
|
2988
3271
|
// packages/ui/src/components/numerology-card.ts
|
|
2989
3272
|
var import_lit15 = require("lit");
|
|
@@ -2999,42 +3282,63 @@ var RoxyNumerologyCard = class extends import_lit15.LitElement {
|
|
|
2999
3282
|
if (!d)
|
|
3000
3283
|
return import_lit15.html`<div class="roxy-empty" role="status">No numerology data</div>`;
|
|
3001
3284
|
const headerLabel = LABELS[this.type] ?? this.type;
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3285
|
+
if ("coreNumbers" in d) return this.renderChart(d, headerLabel);
|
|
3286
|
+
if ("personalYear" in d) return this.renderPersonalYear(d, headerLabel);
|
|
3287
|
+
return this.renderNumberCard(
|
|
3288
|
+
d,
|
|
3289
|
+
headerLabel
|
|
3290
|
+
);
|
|
3291
|
+
}
|
|
3292
|
+
renderNumberCard(d, headerLabel) {
|
|
3293
|
+
const keywords = d.meaning?.keywords ?? [];
|
|
3294
|
+
return import_lit15.html`<article class="card" aria-label=${headerLabel}>
|
|
3010
3295
|
<div class="hero">
|
|
3011
|
-
${typeof number === "number" ? import_lit15.html`<div class="numeral">${number}</div>` : import_lit15.nothing}
|
|
3296
|
+
${typeof d.number === "number" ? import_lit15.html`<div class="numeral">${d.number}</div>` : import_lit15.nothing}
|
|
3012
3297
|
<div>
|
|
3013
3298
|
<p class="label">${headerLabel}</p>
|
|
3014
|
-
${d.title ? import_lit15.html`<h2 class="title">${d.title}</h2>` :
|
|
3015
|
-
${d.type === "master" ? "Master number" : "Single digit"}
|
|
3016
|
-
</h2>` : import_lit15.nothing}
|
|
3299
|
+
${d.meaning?.title ? import_lit15.html`<h2 class="title">${d.meaning.title}</h2>` : import_lit15.nothing}
|
|
3017
3300
|
</div>
|
|
3018
3301
|
</div>
|
|
3019
|
-
${d.
|
|
3020
|
-
${d.meaning ? import_lit15.html`<p class="meaning">${d.meaning}</p>` : import_lit15.nothing}
|
|
3021
|
-
${d.advice ? import_lit15.html`<p>${d.advice}</p>` : import_lit15.nothing}
|
|
3302
|
+
${d.meaning?.description ? import_lit15.html`<p class="meaning">${d.meaning.description}</p>` : import_lit15.nothing}
|
|
3022
3303
|
${d.calculation ? import_lit15.html`<pre class="calc">${d.calculation}</pre>` : import_lit15.nothing}
|
|
3023
|
-
${
|
|
3024
|
-
${
|
|
3025
|
-
</div>` : import_lit15.nothing}
|
|
3026
|
-
${cores.length > 0 ? import_lit15.html`<div class="cores">
|
|
3027
|
-
${cores.map(([k, v]) => {
|
|
3028
|
-
const value = typeof v === "number" ? v : v.number;
|
|
3029
|
-
return import_lit15.html`<div class="item">
|
|
3030
|
-
<span>${humanize2(k)}</span>
|
|
3031
|
-
<strong>${value ?? ""}</strong>
|
|
3032
|
-
</div>`;
|
|
3033
|
-
})}
|
|
3304
|
+
${keywords.length > 0 ? import_lit15.html`<div class="chips">
|
|
3305
|
+
${keywords.map((k) => import_lit15.html`<span>${k}</span>`)}
|
|
3034
3306
|
</div>` : import_lit15.nothing}
|
|
3035
3307
|
${d.hasKarmicDebt && d.karmicDebtNumber ? import_lit15.html`<div class="karmic">
|
|
3036
3308
|
Karmic debt ${d.karmicDebtNumber}.
|
|
3037
|
-
${d.karmicDebtMeaning
|
|
3309
|
+
${karmicDebtText(d.karmicDebtMeaning)}
|
|
3310
|
+
</div>` : import_lit15.nothing}
|
|
3311
|
+
</article>`;
|
|
3312
|
+
}
|
|
3313
|
+
renderPersonalYear(d, headerLabel) {
|
|
3314
|
+
return import_lit15.html`<article class="card" aria-label=${headerLabel}>
|
|
3315
|
+
<div class="hero">
|
|
3316
|
+
${typeof d.personalYear === "number" ? import_lit15.html`<div class="numeral">${d.personalYear}</div>` : import_lit15.nothing}
|
|
3317
|
+
<div>
|
|
3318
|
+
<p class="label">${headerLabel}</p>
|
|
3319
|
+
${d.theme ? import_lit15.html`<h2 class="title">${d.theme}</h2>` : import_lit15.nothing}
|
|
3320
|
+
</div>
|
|
3321
|
+
</div>
|
|
3322
|
+
${d.forecast ? import_lit15.html`<p class="meaning">${d.forecast}</p>` : import_lit15.nothing}
|
|
3323
|
+
${d.advice ? import_lit15.html`<p>${d.advice}</p>` : import_lit15.nothing}
|
|
3324
|
+
</article>`;
|
|
3325
|
+
}
|
|
3326
|
+
renderChart(d, headerLabel) {
|
|
3327
|
+
const cores = Object.entries(d.coreNumbers).filter(
|
|
3328
|
+
([, v]) => v !== null && v !== void 0
|
|
3329
|
+
);
|
|
3330
|
+
return import_lit15.html`<article class="card" aria-label=${headerLabel}>
|
|
3331
|
+
<div>
|
|
3332
|
+
<p class="label">${headerLabel}</p>
|
|
3333
|
+
${d.profile?.name ? import_lit15.html`<h2 class="title">${d.profile.name}</h2>` : import_lit15.nothing}
|
|
3334
|
+
</div>
|
|
3335
|
+
${cores.length > 0 ? import_lit15.html`<div class="cores">
|
|
3336
|
+
${cores.map(
|
|
3337
|
+
([k, v]) => import_lit15.html`<div class="item">
|
|
3338
|
+
<span>${humanize2(k)}</span>
|
|
3339
|
+
<strong>${v.number ?? ""}</strong>
|
|
3340
|
+
</div>`
|
|
3341
|
+
)}
|
|
3038
3342
|
</div>` : import_lit15.nothing}
|
|
3039
3343
|
</article>`;
|
|
3040
3344
|
}
|
|
@@ -3089,7 +3393,8 @@ RoxyNumerologyCard.styles = [
|
|
|
3089
3393
|
background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 30%, transparent);
|
|
3090
3394
|
padding: var(--roxy-space-sm, 0.5rem);
|
|
3091
3395
|
border-radius: var(--roxy-radius-sm, 4px);
|
|
3092
|
-
|
|
3396
|
+
white-space: pre-wrap;
|
|
3397
|
+
overflow-wrap: anywhere;
|
|
3093
3398
|
}
|
|
3094
3399
|
|
|
3095
3400
|
.chips {
|
|
@@ -3153,6 +3458,10 @@ var LABELS = {
|
|
|
3153
3458
|
"personal-year": "Personal Year",
|
|
3154
3459
|
chart: "Numerology chart"
|
|
3155
3460
|
};
|
|
3461
|
+
function karmicDebtText(value) {
|
|
3462
|
+
if (!value) return "";
|
|
3463
|
+
return [value.description, value.challenge, value.resolution].filter(Boolean).join(" ");
|
|
3464
|
+
}
|
|
3156
3465
|
function humanize2(s) {
|
|
3157
3466
|
return s.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^\w/, (c) => c.toUpperCase());
|
|
3158
3467
|
}
|
|
@@ -3170,31 +3479,32 @@ var RoxyPanchangTable = class extends import_lit16.LitElement {
|
|
|
3170
3479
|
const d = this.data;
|
|
3171
3480
|
if (!d)
|
|
3172
3481
|
return import_lit16.html`<div class="roxy-empty" role="status">No panchang data</div>`;
|
|
3482
|
+
const detailed = "sunrise" in d ? d : null;
|
|
3173
3483
|
const fivefold = [
|
|
3174
3484
|
["Tithi", this.formatPart(d.tithi)],
|
|
3175
3485
|
["Nakshatra", this.formatPart(d.nakshatra)],
|
|
3176
3486
|
["Yoga", this.formatPart(d.yoga)],
|
|
3177
|
-
["Karana", this.formatPart(d.karana)]
|
|
3178
|
-
["Vara", d.vara ?? ""]
|
|
3179
|
-
];
|
|
3180
|
-
const muhurtas = [
|
|
3181
|
-
["Brahma Muhurta", d.brahmaMuhurta],
|
|
3182
|
-
["Abhijit Muhurta", d.abhijitMuhurta],
|
|
3183
|
-
["Vijaya Muhurta", d.vijayaMuhurta],
|
|
3184
|
-
["Godhuli Muhurta", d.godhuliMuhurta],
|
|
3185
|
-
["Nishita Muhurta", d.nishitaMuhurta],
|
|
3186
|
-
["Pratah Sandhya", d.pratahSandhya],
|
|
3187
|
-
["Sayahna Sandhya", d.sayahnaSandhya]
|
|
3188
|
-
];
|
|
3189
|
-
const inauspicious = [
|
|
3190
|
-
["Rahu Kaal", d.rahuKaal],
|
|
3191
|
-
["Yamaganda", d.yamaganda],
|
|
3192
|
-
["Gulika", d.gulika]
|
|
3487
|
+
["Karana", this.formatPart(d.karana)]
|
|
3193
3488
|
];
|
|
3489
|
+
if (detailed) fivefold.push(["Vara", this.formatPart(detailed.vara)]);
|
|
3490
|
+
const muhurtas = detailed ? [
|
|
3491
|
+
["Brahma Muhurta", detailed.brahmaMuhurta],
|
|
3492
|
+
["Abhijit Muhurta", detailed.abhijitMuhurta],
|
|
3493
|
+
["Vijaya Muhurta", detailed.vijayaMuhurta],
|
|
3494
|
+
["Godhuli Muhurta", detailed.godhuliMuhurta],
|
|
3495
|
+
["Nishita Muhurta", detailed.nishitaMuhurta],
|
|
3496
|
+
["Pratah Sandhya", detailed.pratahSandhya],
|
|
3497
|
+
["Sayahna Sandhya", detailed.sayahnaSandhya]
|
|
3498
|
+
] : [];
|
|
3499
|
+
const inauspicious = detailed ? [
|
|
3500
|
+
["Rahu Kaal", detailed.rahuKaal],
|
|
3501
|
+
["Yamaganda", detailed.yamaganda],
|
|
3502
|
+
["Gulika", detailed.gulika]
|
|
3503
|
+
] : [];
|
|
3194
3504
|
return import_lit16.html`<div class="wrap" aria-label="Panchang">
|
|
3195
3505
|
<header class="head">
|
|
3196
3506
|
<h2 class="title">Panchang</h2>
|
|
3197
|
-
<span class="date">${
|
|
3507
|
+
<span class="date">${detailed ? formatDate(detailed.date) : ""}</span>
|
|
3198
3508
|
</header>
|
|
3199
3509
|
<table>
|
|
3200
3510
|
<tbody>
|
|
@@ -3204,21 +3514,21 @@ var RoxyPanchangTable = class extends import_lit16.LitElement {
|
|
|
3204
3514
|
<td>${v}</td>
|
|
3205
3515
|
</tr>`
|
|
3206
3516
|
)}
|
|
3207
|
-
${
|
|
3517
|
+
${detailed?.sunrise ? import_lit16.html`<tr>
|
|
3208
3518
|
<th>Sunrise</th>
|
|
3209
|
-
<td>${
|
|
3519
|
+
<td>${formatTime(detailed.sunrise)}</td>
|
|
3210
3520
|
</tr>` : import_lit16.nothing}
|
|
3211
|
-
${
|
|
3521
|
+
${detailed?.sunset ? import_lit16.html`<tr>
|
|
3212
3522
|
<th>Sunset</th>
|
|
3213
|
-
<td>${
|
|
3523
|
+
<td>${formatTime(detailed.sunset)}</td>
|
|
3214
3524
|
</tr>` : import_lit16.nothing}
|
|
3215
|
-
${
|
|
3525
|
+
${detailed?.moonrise ? import_lit16.html`<tr>
|
|
3216
3526
|
<th>Moonrise</th>
|
|
3217
|
-
<td>${
|
|
3527
|
+
<td>${formatTime(detailed.moonrise)}</td>
|
|
3218
3528
|
</tr>` : import_lit16.nothing}
|
|
3219
|
-
${
|
|
3529
|
+
${detailed?.moonset ? import_lit16.html`<tr>
|
|
3220
3530
|
<th>Moonset</th>
|
|
3221
|
-
<td>${
|
|
3531
|
+
<td>${formatTime(detailed.moonset)}</td>
|
|
3222
3532
|
</tr>` : import_lit16.nothing}
|
|
3223
3533
|
</tbody>
|
|
3224
3534
|
</table>
|
|
@@ -3229,7 +3539,7 @@ var RoxyPanchangTable = class extends import_lit16.LitElement {
|
|
|
3229
3539
|
${muhurtas.filter(([, v]) => !!v).map(
|
|
3230
3540
|
([k, v]) => import_lit16.html`<tr>
|
|
3231
3541
|
<th>${k}</th>
|
|
3232
|
-
<td>${
|
|
3542
|
+
<td>${formatTimeRange(v)}</td>
|
|
3233
3543
|
</tr>`
|
|
3234
3544
|
)}
|
|
3235
3545
|
</tbody>
|
|
@@ -3240,7 +3550,7 @@ var RoxyPanchangTable = class extends import_lit16.LitElement {
|
|
|
3240
3550
|
${inauspicious.filter(([, v]) => !!v).map(
|
|
3241
3551
|
([k, v]) => import_lit16.html`<tr>
|
|
3242
3552
|
<th>${k}</th>
|
|
3243
|
-
<td>${
|
|
3553
|
+
<td>${formatTimeRange(v)}</td>
|
|
3244
3554
|
</tr>`
|
|
3245
3555
|
)}
|
|
3246
3556
|
</tbody>
|
|
@@ -3334,11 +3644,6 @@ __decorateClass([
|
|
|
3334
3644
|
RoxyPanchangTable = __decorateClass([
|
|
3335
3645
|
(0, import_decorators15.customElement)("roxy-panchang-table")
|
|
3336
3646
|
], RoxyPanchangTable);
|
|
3337
|
-
function formatRange(t) {
|
|
3338
|
-
if (!t) return "";
|
|
3339
|
-
if (t.start && t.end) return `${t.start} - ${t.end}`;
|
|
3340
|
-
return t.start ?? t.end ?? "";
|
|
3341
|
-
}
|
|
3342
3647
|
|
|
3343
3648
|
// packages/ui/src/components/synastry-chart.ts
|
|
3344
3649
|
var import_lit17 = require("lit");
|
|
@@ -3357,23 +3662,58 @@ var RoxySynastryChart = class extends import_lit17.LitElement {
|
|
|
3357
3662
|
render() {
|
|
3358
3663
|
if (!this.data)
|
|
3359
3664
|
return import_lit17.html`<div class="roxy-empty" role="status">No synastry data</div>`;
|
|
3360
|
-
const {
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
const
|
|
3368
|
-
const
|
|
3665
|
+
const { person1, person2, compatibilityScore, analysis } = this.data;
|
|
3666
|
+
const interAspects = this.data.interAspects ?? [];
|
|
3667
|
+
const p1Planets = person1?.planets ?? [];
|
|
3668
|
+
const p2Planets = person2?.planets ?? [];
|
|
3669
|
+
const score = typeof compatibilityScore === "number" ? Math.round(compatibilityScore) : void 0;
|
|
3670
|
+
const summaryText = analysis?.overall;
|
|
3671
|
+
const strengths = analysis?.strengths ?? [];
|
|
3672
|
+
const challenges = analysis?.challenges ?? [];
|
|
3673
|
+
const hasPlanets = p1Planets.length > 0 && p2Planets.length > 0;
|
|
3674
|
+
if (!hasPlanets) {
|
|
3675
|
+
return import_lit17.html`<div
|
|
3676
|
+
class="wrap"
|
|
3677
|
+
aria-label="Synastry compatibility chart"
|
|
3678
|
+
>
|
|
3679
|
+
<div class="head">
|
|
3680
|
+
<h2 class="title">Synastry</h2>
|
|
3681
|
+
${typeof score === "number" ? import_lit17.html`<span class="score" aria-label=${`Score ${score} of 100`}
|
|
3682
|
+
>${score} / 100</span
|
|
3683
|
+
>` : import_lit17.nothing}
|
|
3684
|
+
</div>
|
|
3685
|
+
<div class="missing-planets" role="status">
|
|
3686
|
+
Synastry response missing planet positions. Pass
|
|
3687
|
+
<code>data</code> with <code>person1.planets</code> and
|
|
3688
|
+
<code>person2.planets</code> arrays from the natal-chart endpoint, or
|
|
3689
|
+
use the <code><roxy-data></code> fallback.
|
|
3690
|
+
</div>
|
|
3691
|
+
${summaryText ? import_lit17.html`<p class="summary">${summaryText}</p>` : import_lit17.nothing}
|
|
3692
|
+
${interAspects.length > 0 ? this.renderAspects(interAspects) : import_lit17.nothing}
|
|
3693
|
+
${strengths.length > 0 || challenges.length > 0 ? import_lit17.html`<div class="lists">
|
|
3694
|
+
${strengths.length ? import_lit17.html`<div>
|
|
3695
|
+
<h3>Strengths</h3>
|
|
3696
|
+
<ul>
|
|
3697
|
+
${strengths.map((s) => import_lit17.html`<li>${s}</li>`)}
|
|
3698
|
+
</ul>
|
|
3699
|
+
</div>` : import_lit17.nothing}
|
|
3700
|
+
${challenges.length ? import_lit17.html`<div>
|
|
3701
|
+
<h3>Challenges</h3>
|
|
3702
|
+
<ul>
|
|
3703
|
+
${challenges.map((s) => import_lit17.html`<li>${s}</li>`)}
|
|
3704
|
+
</ul>
|
|
3705
|
+
</div>` : import_lit17.nothing}
|
|
3706
|
+
</div>` : import_lit17.nothing}
|
|
3707
|
+
</div>`;
|
|
3708
|
+
}
|
|
3369
3709
|
return import_lit17.html`<div
|
|
3370
3710
|
class="wrap"
|
|
3371
3711
|
aria-label="Synastry compatibility chart"
|
|
3372
3712
|
>
|
|
3373
3713
|
<div class="head">
|
|
3374
3714
|
<h2 class="title">Synastry</h2>
|
|
3375
|
-
${typeof
|
|
3376
|
-
>${
|
|
3715
|
+
${typeof score === "number" ? import_lit17.html`<span class="score" aria-label=${`Score ${score} of 100`}
|
|
3716
|
+
>${score} / 100</span
|
|
3377
3717
|
>` : import_lit17.nothing}
|
|
3378
3718
|
</div>
|
|
3379
3719
|
<svg
|
|
@@ -3404,34 +3744,39 @@ var RoxySynastryChart = class extends import_lit17.LitElement {
|
|
|
3404
3744
|
stroke-width="0.6"
|
|
3405
3745
|
/>
|
|
3406
3746
|
${this.renderSpokes()} ${this.renderSigns()}
|
|
3747
|
+
${this.renderInterAspectLines(p1Planets, p2Planets, interAspects)}
|
|
3407
3748
|
${this.renderRing(p1Planets, P1_R, "p1")} ${this.renderRing(p2Planets, P2_R, "p2")}
|
|
3408
3749
|
</svg>
|
|
3409
|
-
|
|
3750
|
+
<div class="legend-row">
|
|
3751
|
+
<span><span class="swatch" style="background: var(--roxy-accent)"></span>Person 1</span>
|
|
3752
|
+
<span><span class="swatch" style="background: var(--roxy-info)"></span>Person 2</span>
|
|
3753
|
+
<span><span class="swatch" style="background: var(--roxy-success)"></span>harmonious</span>
|
|
3754
|
+
<span><span class="swatch" style="background: var(--roxy-danger)"></span>challenging</span>
|
|
3755
|
+
</div>
|
|
3756
|
+
${summaryText ? import_lit17.html`<p class="summary">${summaryText}</p>` : import_lit17.nothing}
|
|
3410
3757
|
${interAspects.length > 0 ? this.renderAspects(interAspects) : import_lit17.nothing}
|
|
3411
|
-
${
|
|
3412
|
-
${
|
|
3758
|
+
${strengths.length > 0 || challenges.length > 0 ? import_lit17.html`<div class="lists">
|
|
3759
|
+
${strengths.length ? import_lit17.html`<div>
|
|
3413
3760
|
<h3>Strengths</h3>
|
|
3414
3761
|
<ul>
|
|
3415
|
-
${
|
|
3762
|
+
${strengths.map((s) => import_lit17.html`<li>${s}</li>`)}
|
|
3416
3763
|
</ul>
|
|
3417
3764
|
</div>` : import_lit17.nothing}
|
|
3418
|
-
${
|
|
3765
|
+
${challenges.length ? import_lit17.html`<div>
|
|
3419
3766
|
<h3>Challenges</h3>
|
|
3420
3767
|
<ul>
|
|
3421
|
-
${
|
|
3768
|
+
${challenges.map((s) => import_lit17.html`<li>${s}</li>`)}
|
|
3422
3769
|
</ul>
|
|
3423
3770
|
</div>` : import_lit17.nothing}
|
|
3424
3771
|
</div>` : import_lit17.nothing}
|
|
3425
3772
|
</div>`;
|
|
3426
3773
|
}
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
if (Array.isArray(p)) return p;
|
|
3430
|
-
return Object.entries(p).map(([name, e]) => ({ ...e, name }));
|
|
3774
|
+
toAngle(longitude) {
|
|
3775
|
+
return 180 - longitude;
|
|
3431
3776
|
}
|
|
3432
3777
|
renderSpokes() {
|
|
3433
3778
|
return Array.from({ length: 12 }, (_, i) => {
|
|
3434
|
-
const angle = i * 30
|
|
3779
|
+
const angle = this.toAngle(i * 30);
|
|
3435
3780
|
const start = polarToCartesian(CENTER2, CENTER2, P2_R - 14, angle);
|
|
3436
3781
|
const end = polarToCartesian(CENTER2, CENTER2, OUTER_R2, angle);
|
|
3437
3782
|
return import_lit17.svg`<line class="wheel-line" x1=${start.x} y1=${start.y} x2=${end.x} y2=${end.y} stroke-width="0.6" />`;
|
|
@@ -3453,19 +3798,43 @@ var RoxySynastryChart = class extends import_lit17.LitElement {
|
|
|
3453
3798
|
"Pisces"
|
|
3454
3799
|
];
|
|
3455
3800
|
return order.map((s, i) => {
|
|
3456
|
-
const angle = i * 30 + 15
|
|
3801
|
+
const angle = this.toAngle(i * 30 + 15);
|
|
3457
3802
|
const pos = polarToCartesian(CENTER2, CENTER2, SIGN_R2, angle);
|
|
3458
3803
|
return import_lit17.svg`<text class="sign" x=${pos.x} y=${pos.y} text-anchor="middle" dominant-baseline="central">${SIGN_GLYPH[s]}</text>`;
|
|
3459
3804
|
});
|
|
3460
3805
|
}
|
|
3461
3806
|
renderRing(planets, radius, cls) {
|
|
3462
3807
|
return planets.map((p) => {
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3808
|
+
if (!Number.isFinite(p.longitude)) return import_lit17.nothing;
|
|
3809
|
+
const pos = polarToCartesian(
|
|
3810
|
+
CENTER2,
|
|
3811
|
+
CENTER2,
|
|
3812
|
+
radius,
|
|
3813
|
+
this.toAngle(p.longitude)
|
|
3814
|
+
);
|
|
3815
|
+
const glyph = PLANET_GLYPH[capitalize3(p.name)] ?? p.name.slice(0, 2);
|
|
3816
|
+
return import_lit17.svg`<text class=${cls} x=${pos.x} y=${pos.y} text-anchor="middle" dominant-baseline="central"><title>${p.name}</title>${glyph}</text>`;
|
|
3817
|
+
});
|
|
3818
|
+
}
|
|
3819
|
+
renderInterAspectLines(p1, p2, aspects) {
|
|
3820
|
+
const longitudeOf = (list, name) => {
|
|
3821
|
+
const target = capitalize3(name);
|
|
3822
|
+
for (const p of list) {
|
|
3823
|
+
if (capitalize3(p.name) !== target) continue;
|
|
3824
|
+
if (typeof p.longitude === "number") return p.longitude;
|
|
3825
|
+
}
|
|
3826
|
+
return void 0;
|
|
3827
|
+
};
|
|
3828
|
+
return aspects.map((a) => {
|
|
3829
|
+
const l1 = longitudeOf(p1, a.planet1);
|
|
3830
|
+
const l2 = longitudeOf(p2, a.planet2);
|
|
3831
|
+
if (l1 === void 0 || l2 === void 0) return import_lit17.nothing;
|
|
3832
|
+
const out = polarToCartesian(CENTER2, CENTER2, P1_R - 12, this.toAngle(l1));
|
|
3833
|
+
const inn = polarToCartesian(CENTER2, CENTER2, P2_R + 8, this.toAngle(l2));
|
|
3834
|
+
const aspectName = normalizeAspect2(a);
|
|
3835
|
+
const cls = ASPECT_CLASS2[aspectName] ?? "aspect-other";
|
|
3836
|
+
const orbLabel = formatNumber(a.orb, 1);
|
|
3837
|
+
return import_lit17.svg`<line class=${`aspect ${cls}`} x1=${out.x} y1=${out.y} x2=${inn.x} y2=${inn.y}><title>${a.planet1} ${aspectName} ${a.planet2}${orbLabel ? ` (orb ${orbLabel}\xB0)` : ""}</title></line>`;
|
|
3469
3838
|
});
|
|
3470
3839
|
}
|
|
3471
3840
|
renderAspects(aspects) {
|
|
@@ -3480,15 +3849,13 @@ var RoxySynastryChart = class extends import_lit17.LitElement {
|
|
|
3480
3849
|
</tr>
|
|
3481
3850
|
</thead>
|
|
3482
3851
|
<tbody>
|
|
3483
|
-
${aspects.slice(0,
|
|
3852
|
+
${aspects.slice(0, 12).map(
|
|
3484
3853
|
(a) => import_lit17.html`<tr>
|
|
3485
|
-
<td>${a.planet1
|
|
3486
|
-
<td>${a.planet2
|
|
3487
|
-
<td>${a
|
|
3488
|
-
<td class="orb">
|
|
3489
|
-
|
|
3490
|
-
</td>
|
|
3491
|
-
<td>${a.strength ?? ""}</td>
|
|
3854
|
+
<td>${a.planet1}</td>
|
|
3855
|
+
<td>${a.planet2}</td>
|
|
3856
|
+
<td>${normalizeAspect2(a) || ""}</td>
|
|
3857
|
+
<td class="orb">${formatNumber(a.orb, 1)}</td>
|
|
3858
|
+
<td>${formatStrength(a.strength)}</td>
|
|
3492
3859
|
</tr>`
|
|
3493
3860
|
)}
|
|
3494
3861
|
</tbody>
|
|
@@ -3549,6 +3916,42 @@ RoxySynastryChart.styles = [
|
|
|
3549
3916
|
font-weight: 600;
|
|
3550
3917
|
font-size: 13px;
|
|
3551
3918
|
}
|
|
3919
|
+
.aspect {
|
|
3920
|
+
stroke-width: 0.8;
|
|
3921
|
+
fill: none;
|
|
3922
|
+
opacity: 0.5;
|
|
3923
|
+
}
|
|
3924
|
+
.aspect-trine,
|
|
3925
|
+
.aspect-sextile {
|
|
3926
|
+
stroke: var(--roxy-success, #16a34a);
|
|
3927
|
+
}
|
|
3928
|
+
.aspect-square,
|
|
3929
|
+
.aspect-opposition {
|
|
3930
|
+
stroke: var(--roxy-danger, #dc2626);
|
|
3931
|
+
}
|
|
3932
|
+
.aspect-conjunction {
|
|
3933
|
+
stroke: var(--roxy-accent-fg, #b45309);
|
|
3934
|
+
}
|
|
3935
|
+
.aspect-other {
|
|
3936
|
+
stroke: var(--roxy-muted, #71717a);
|
|
3937
|
+
opacity: 0.35;
|
|
3938
|
+
}
|
|
3939
|
+
.legend-row {
|
|
3940
|
+
display: flex;
|
|
3941
|
+
flex-wrap: wrap;
|
|
3942
|
+
gap: var(--roxy-space-md, 1rem);
|
|
3943
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
3944
|
+
color: var(--roxy-muted, #71717a);
|
|
3945
|
+
margin-top: calc(var(--roxy-space-xs, 0.25rem) * -1);
|
|
3946
|
+
}
|
|
3947
|
+
.legend-row .swatch {
|
|
3948
|
+
display: inline-block;
|
|
3949
|
+
width: 8px;
|
|
3950
|
+
height: 8px;
|
|
3951
|
+
border-radius: 50%;
|
|
3952
|
+
margin-right: 4px;
|
|
3953
|
+
vertical-align: middle;
|
|
3954
|
+
}
|
|
3552
3955
|
|
|
3553
3956
|
.summary {
|
|
3554
3957
|
margin: 0;
|
|
@@ -3596,6 +3999,23 @@ RoxySynastryChart.styles = [
|
|
|
3596
3999
|
padding-left: var(--roxy-space-md, 1rem);
|
|
3597
4000
|
font-size: var(--roxy-text-sm, 0.875rem);
|
|
3598
4001
|
}
|
|
4002
|
+
|
|
4003
|
+
.missing-planets {
|
|
4004
|
+
background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 8%, transparent);
|
|
4005
|
+
border: 1px solid var(--roxy-border, #e4e4e7);
|
|
4006
|
+
border-radius: var(--roxy-radius-md, 8px);
|
|
4007
|
+
padding: var(--roxy-space-md, 1rem);
|
|
4008
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
4009
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
4010
|
+
line-height: 1.5;
|
|
4011
|
+
}
|
|
4012
|
+
.missing-planets code {
|
|
4013
|
+
font-family: var(--roxy-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
4014
|
+
font-size: 0.95em;
|
|
4015
|
+
background: color-mix(in srgb, var(--roxy-fg, #0a0a0a) 6%, transparent);
|
|
4016
|
+
padding: 0 4px;
|
|
4017
|
+
border-radius: 4px;
|
|
4018
|
+
}
|
|
3599
4019
|
`
|
|
3600
4020
|
];
|
|
3601
4021
|
__decorateClass([
|
|
@@ -3608,6 +4028,20 @@ function capitalize3(s) {
|
|
|
3608
4028
|
if (!s) return "";
|
|
3609
4029
|
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
3610
4030
|
}
|
|
4031
|
+
var ASPECT_CLASS2 = {
|
|
4032
|
+
conjunction: "aspect-conjunction",
|
|
4033
|
+
sextile: "aspect-sextile",
|
|
4034
|
+
square: "aspect-square",
|
|
4035
|
+
trine: "aspect-trine",
|
|
4036
|
+
opposition: "aspect-opposition"
|
|
4037
|
+
};
|
|
4038
|
+
function normalizeAspect2(a) {
|
|
4039
|
+
return (a.type ?? "").toLowerCase().replace(/_/g, "-");
|
|
4040
|
+
}
|
|
4041
|
+
function formatStrength(s) {
|
|
4042
|
+
if (typeof s === "number") return Math.round(s).toString();
|
|
4043
|
+
return "";
|
|
4044
|
+
}
|
|
3611
4045
|
|
|
3612
4046
|
// packages/ui/src/components/tarot-card.ts
|
|
3613
4047
|
var import_lit18 = require("lit");
|
|
@@ -3621,18 +4055,17 @@ var RoxyTarotCard = class extends import_lit18.LitElement {
|
|
|
3621
4055
|
this.flipped = !this.flipped;
|
|
3622
4056
|
};
|
|
3623
4057
|
}
|
|
3624
|
-
getCard() {
|
|
3625
|
-
if (!this.data) return null;
|
|
3626
|
-
if ("card" in this.data && this.data.card) return this.data.card;
|
|
3627
|
-
return this.data;
|
|
3628
|
-
}
|
|
3629
4058
|
render() {
|
|
3630
|
-
const
|
|
3631
|
-
if (!
|
|
4059
|
+
const d = this.data;
|
|
4060
|
+
if (!d)
|
|
3632
4061
|
return import_lit18.html`<div class="roxy-empty" role="status">No tarot data</div>`;
|
|
4062
|
+
if ("card" in d) return this.renderDailyCard(d);
|
|
4063
|
+
return this.renderFullCard(d);
|
|
4064
|
+
}
|
|
4065
|
+
renderDailyCard(d) {
|
|
4066
|
+
const card = d.card;
|
|
3633
4067
|
const isReversed = this.flipped !== Boolean(card.reversed);
|
|
3634
|
-
const
|
|
3635
|
-
const dailyMessage = this.data && "dailyMessage" in this.data ? this.data.dailyMessage : void 0;
|
|
4068
|
+
const keywords = card.keywords ?? [];
|
|
3636
4069
|
return import_lit18.html`<article class="card" aria-label=${card.name ?? "Tarot card"}>
|
|
3637
4070
|
<div class="image-wrap">
|
|
3638
4071
|
${card.imageUrl ? import_lit18.html`<img
|
|
@@ -3657,15 +4090,60 @@ var RoxyTarotCard = class extends import_lit18.LitElement {
|
|
|
3657
4090
|
<div>
|
|
3658
4091
|
<div class="meta">
|
|
3659
4092
|
${card.arcana ? import_lit18.html`${card.arcana} arcana` : import_lit18.nothing}
|
|
3660
|
-
${card.number !== void 0 && card.number !== null ? import_lit18.html` · ${card.number}` : import_lit18.nothing}
|
|
3661
4093
|
${isReversed ? import_lit18.html` · reversed` : import_lit18.nothing}
|
|
3662
|
-
${card.position ? import_lit18.html`<span class="position">${card.position}</span>` : import_lit18.nothing}
|
|
3663
4094
|
</div>
|
|
3664
4095
|
<h2 class="title">${card.name ?? "Tarot card"}</h2>
|
|
3665
|
-
${dailyMessage ? import_lit18.html`<p class="message">${dailyMessage}</p>` : import_lit18.nothing}
|
|
3666
|
-
${meaning ? import_lit18.html`<p>${meaning}</p>` : import_lit18.nothing}
|
|
3667
|
-
${
|
|
3668
|
-
${
|
|
4096
|
+
${d.dailyMessage ? import_lit18.html`<p class="message">${d.dailyMessage}</p>` : import_lit18.nothing}
|
|
4097
|
+
${card.meaning ? import_lit18.html`<p>${card.meaning}</p>` : import_lit18.nothing}
|
|
4098
|
+
${keywords.length > 0 ? import_lit18.html`<div class="chips">
|
|
4099
|
+
${keywords.map((k) => import_lit18.html`<span>${k}</span>`)}
|
|
4100
|
+
</div>` : import_lit18.nothing}
|
|
4101
|
+
<button
|
|
4102
|
+
class="flip"
|
|
4103
|
+
type="button"
|
|
4104
|
+
@click=${this.toggleFlip}
|
|
4105
|
+
aria-pressed=${this.flipped ? "true" : "false"}
|
|
4106
|
+
>
|
|
4107
|
+
Flip card
|
|
4108
|
+
</button>
|
|
4109
|
+
</div>
|
|
4110
|
+
</article>`;
|
|
4111
|
+
}
|
|
4112
|
+
renderFullCard(d) {
|
|
4113
|
+
const isReversed = this.flipped;
|
|
4114
|
+
const orientedMeaning = isReversed ? d.reversed : d.upright;
|
|
4115
|
+
const keywords = isReversed ? d.keywords?.reversed ?? [] : d.keywords?.upright ?? [];
|
|
4116
|
+
return import_lit18.html`<article class="card" aria-label=${d.name ?? "Tarot card"}>
|
|
4117
|
+
<div class="image-wrap">
|
|
4118
|
+
${d.imageUrl ? import_lit18.html`<img
|
|
4119
|
+
class=${`image ${isReversed ? "reversed" : ""}`}
|
|
4120
|
+
src=${d.imageUrl}
|
|
4121
|
+
alt=${d.name ?? "Tarot card"}
|
|
4122
|
+
tabindex="0"
|
|
4123
|
+
@click=${this.toggleFlip}
|
|
4124
|
+
@keydown=${(e) => {
|
|
4125
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
4126
|
+
e.preventDefault();
|
|
4127
|
+
this.toggleFlip();
|
|
4128
|
+
}
|
|
4129
|
+
}}
|
|
4130
|
+
/>` : import_lit18.html`<div
|
|
4131
|
+
class=${`image ${isReversed ? "reversed" : ""}`}
|
|
4132
|
+
style="aspect-ratio: 0.6; display: flex; align-items: center; justify-content: center; color: var(--roxy-muted)"
|
|
4133
|
+
>
|
|
4134
|
+
${d.name ?? "?"}
|
|
4135
|
+
</div>`}
|
|
4136
|
+
</div>
|
|
4137
|
+
<div>
|
|
4138
|
+
<div class="meta">
|
|
4139
|
+
${d.arcana ? import_lit18.html`${d.arcana} arcana` : import_lit18.nothing}
|
|
4140
|
+
${d.number !== void 0 && d.number !== null ? import_lit18.html` · ${d.number}` : import_lit18.nothing}
|
|
4141
|
+
${isReversed ? import_lit18.html` · reversed` : import_lit18.nothing}
|
|
4142
|
+
</div>
|
|
4143
|
+
<h2 class="title">${d.name ?? "Tarot card"}</h2>
|
|
4144
|
+
${orientedMeaning?.description ? import_lit18.html`<p>${orientedMeaning.description}</p>` : import_lit18.nothing}
|
|
4145
|
+
${keywords.length > 0 ? import_lit18.html`<div class="chips">
|
|
4146
|
+
${keywords.map((k) => import_lit18.html`<span>${k}</span>`)}
|
|
3669
4147
|
</div>` : import_lit18.nothing}
|
|
3670
4148
|
<button
|
|
3671
4149
|
class="flip"
|
|
@@ -3735,11 +4213,6 @@ RoxyTarotCard.styles = [
|
|
|
3735
4213
|
letter-spacing: 0.06em;
|
|
3736
4214
|
margin-bottom: var(--roxy-space-sm, 0.5rem);
|
|
3737
4215
|
}
|
|
3738
|
-
.position {
|
|
3739
|
-
color: var(--roxy-info, #0284c7);
|
|
3740
|
-
margin-left: var(--roxy-space-xs, 0.25rem);
|
|
3741
|
-
text-transform: capitalize;
|
|
3742
|
-
}
|
|
3743
4216
|
|
|
3744
4217
|
.message {
|
|
3745
4218
|
color: var(--roxy-fg, #0a0a0a);
|
|
@@ -3801,22 +4274,30 @@ var RoxyTarotSpread = class extends import_lit19.LitElement {
|
|
|
3801
4274
|
const d = this.data;
|
|
3802
4275
|
if (!d)
|
|
3803
4276
|
return import_lit19.html`<div class="roxy-empty" role="status">No tarot spread</div>`;
|
|
3804
|
-
const
|
|
3805
|
-
const
|
|
3806
|
-
const
|
|
4277
|
+
const isYesNo = "answer" in d;
|
|
4278
|
+
const isDrawn = "cards" in d && !("spread" in d);
|
|
4279
|
+
const positions = isDrawn ? [] : "positions" in d ? d.positions ?? [] : [];
|
|
4280
|
+
const cards = isDrawn && "cards" in d ? d.cards : [];
|
|
4281
|
+
const answer = isYesNo ? d.answer : void 0;
|
|
4282
|
+
const strength = isYesNo ? d.strength : void 0;
|
|
4283
|
+
const spreadLabel = "spread" in d ? d.spread : this.spread.replace(/-/g, " ");
|
|
4284
|
+
const question = "question" in d ? d.question : void 0;
|
|
4285
|
+
const summary = "summary" in d ? d.summary : void 0;
|
|
4286
|
+
const yesNoInterp = isYesNo ? d.interpretation : void 0;
|
|
4287
|
+
const answerClass = answer ? answer.toLowerCase().replace(/[^a-z]/g, "") : "";
|
|
3807
4288
|
return import_lit19.html`<article class="wrap" aria-label="Tarot spread">
|
|
3808
4289
|
<header class="head">
|
|
3809
|
-
<h2 class="title">${
|
|
3810
|
-
${
|
|
4290
|
+
<h2 class="title">${spreadLabel}</h2>
|
|
4291
|
+
${question ? import_lit19.html`<span class="question">"${question}"</span>` : import_lit19.nothing}
|
|
3811
4292
|
</header>
|
|
3812
4293
|
${isYesNo ? import_lit19.html`<div>
|
|
3813
|
-
<span class=${`answer ${answerClass}`}>${
|
|
3814
|
-
${
|
|
4294
|
+
<span class=${`answer ${answerClass}`}>${answer}</span>
|
|
4295
|
+
${strength ? import_lit19.html`<small> · ${strength}</small>` : import_lit19.nothing}
|
|
3815
4296
|
</div>` : import_lit19.nothing}
|
|
3816
4297
|
${positions.length > 0 ? import_lit19.html`<div class="grid">
|
|
3817
4298
|
${positions.map(
|
|
3818
4299
|
(p) => import_lit19.html`<div class="card">
|
|
3819
|
-
<p class="label">${p.
|
|
4300
|
+
<p class="label">${p.name ?? ""}</p>
|
|
3820
4301
|
<div class="image">
|
|
3821
4302
|
${p.card?.imageUrl ? import_lit19.html`<img
|
|
3822
4303
|
src=${p.card.imageUrl}
|
|
@@ -3832,8 +4313,26 @@ var RoxyTarotSpread = class extends import_lit19.LitElement {
|
|
|
3832
4313
|
</div>`
|
|
3833
4314
|
)}
|
|
3834
4315
|
</div>` : import_lit19.nothing}
|
|
3835
|
-
${
|
|
3836
|
-
|
|
4316
|
+
${cards.length > 0 ? import_lit19.html`<div class="grid">
|
|
4317
|
+
${cards.map(
|
|
4318
|
+
(c) => import_lit19.html`<div class="card">
|
|
4319
|
+
<div class="image">
|
|
4320
|
+
${c.imageUrl ? import_lit19.html`<img
|
|
4321
|
+
src=${c.imageUrl}
|
|
4322
|
+
alt=${c.name ?? "tarot card"}
|
|
4323
|
+
class=${c.reversed ? "reversed" : ""}
|
|
4324
|
+
/>` : import_lit19.html`${c.name ?? "?"}`}
|
|
4325
|
+
</div>
|
|
4326
|
+
<p class="name">
|
|
4327
|
+
${c.name ?? ""}
|
|
4328
|
+
${c.reversed ? import_lit19.html`<small>(reversed)</small>` : import_lit19.nothing}
|
|
4329
|
+
</p>
|
|
4330
|
+
${c.meaning ? import_lit19.html`<p class="interp">${c.meaning}</p>` : import_lit19.nothing}
|
|
4331
|
+
</div>`
|
|
4332
|
+
)}
|
|
4333
|
+
</div>` : import_lit19.nothing}
|
|
4334
|
+
${summary ? import_lit19.html`<p class="reading">${summary}</p>` : import_lit19.nothing}
|
|
4335
|
+
${yesNoInterp ? import_lit19.html`<p class="reading">${yesNoInterp}</p>` : import_lit19.nothing}
|
|
3837
4336
|
</article>`;
|
|
3838
4337
|
}
|
|
3839
4338
|
};
|
|
@@ -3875,15 +4374,15 @@ RoxyTarotSpread.styles = [
|
|
|
3875
4374
|
}
|
|
3876
4375
|
.answer.yes {
|
|
3877
4376
|
background: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);
|
|
3878
|
-
color: var(--roxy-success, #
|
|
4377
|
+
color: var(--roxy-success-fg, #166534);
|
|
3879
4378
|
}
|
|
3880
4379
|
.answer.no {
|
|
3881
4380
|
background: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);
|
|
3882
|
-
color: var(--roxy-danger, #
|
|
4381
|
+
color: var(--roxy-danger-fg, #991b1b);
|
|
3883
4382
|
}
|
|
3884
4383
|
.answer.maybe {
|
|
3885
4384
|
background: color-mix(in srgb, var(--roxy-warning, #ea580c) 16%, transparent);
|
|
3886
|
-
color: var(--roxy-warning, #
|
|
4385
|
+
color: var(--roxy-warning-fg, #9a3412);
|
|
3887
4386
|
}
|
|
3888
4387
|
|
|
3889
4388
|
.grid {
|
|
@@ -4024,21 +4523,12 @@ var RoxyVedicKundli = class extends import_lit20.LitElement {
|
|
|
4024
4523
|
}
|
|
4025
4524
|
buildHouses() {
|
|
4026
4525
|
if (!this.data) return [];
|
|
4526
|
+
const data = this.data;
|
|
4027
4527
|
const houses = [];
|
|
4028
|
-
if (Array.isArray(this.data.houses)) {
|
|
4029
|
-
for (const h of this.data.houses) {
|
|
4030
|
-
houses.push({
|
|
4031
|
-
house: h.house ?? h.number ?? houses.length + 1,
|
|
4032
|
-
sign: h.sign ?? "",
|
|
4033
|
-
planets: h.planets ?? []
|
|
4034
|
-
});
|
|
4035
|
-
}
|
|
4036
|
-
if (houses.length > 0) return houses;
|
|
4037
|
-
}
|
|
4038
4528
|
for (let i = 0; i < 12; i++) {
|
|
4039
4529
|
const key = RASHI_KEYS[i];
|
|
4040
|
-
const bucket =
|
|
4041
|
-
const planets = (bucket?.signs ?? []).map((p) => p.
|
|
4530
|
+
const bucket = data[key];
|
|
4531
|
+
const planets = (bucket?.signs ?? []).map((p) => p.graha).filter(Boolean);
|
|
4042
4532
|
houses.push({
|
|
4043
4533
|
house: i + 1,
|
|
4044
4534
|
sign: RASHI_TO_SIGN[key] ?? "",
|
|
@@ -4078,19 +4568,28 @@ var RoxyVedicKundli = class extends import_lit20.LitElement {
|
|
|
4078
4568
|
</svg>
|
|
4079
4569
|
</div>`;
|
|
4080
4570
|
}
|
|
4571
|
+
isLagna(h) {
|
|
4572
|
+
const ascSign = this.data?.meta?.Lagna?.rashi;
|
|
4573
|
+
if (!ascSign) return false;
|
|
4574
|
+
return ascSign.toLowerCase() === h.sign.toLowerCase();
|
|
4575
|
+
}
|
|
4081
4576
|
renderHouseGroup(h) {
|
|
4082
4577
|
const center = SOUTH_HOUSE_CENTERS[h.house];
|
|
4083
4578
|
const signPos = SOUTH_SIGN_POSITIONS[h.house];
|
|
4084
4579
|
if (!center || !signPos) return import_lit20.nothing;
|
|
4085
4580
|
const signAbbr = SIGN_ABBR[h.sign] ?? "";
|
|
4086
4581
|
const planets = h.planets ?? [];
|
|
4582
|
+
const isLagna = this.isLagna(h);
|
|
4087
4583
|
return import_lit20.svg`
|
|
4088
4584
|
<g>
|
|
4585
|
+
${isLagna ? import_lit20.svg`<rect class="lagna-bg" x=${center.x - 30} y=${center.y - 28} width="60" height="56" rx="6" />` : import_lit20.nothing}
|
|
4089
4586
|
${signAbbr ? import_lit20.svg`<text class="sign-text" x=${signPos.x} y=${signPos.y} text-anchor="middle" dominant-baseline="central">${signAbbr}</text>` : import_lit20.nothing}
|
|
4587
|
+
${isLagna ? import_lit20.svg`<text class="lagna-marker" x=${center.x} y=${center.y - 18} text-anchor="middle" dominant-baseline="central">LAGNA</text>` : import_lit20.nothing}
|
|
4090
4588
|
${planets.map((planet, j) => {
|
|
4091
4589
|
const abbr = PLANET_ABBR[capitalize4(planet)] ?? planet.slice(0, 2);
|
|
4092
4590
|
const lineHeight = 13;
|
|
4093
|
-
const
|
|
4591
|
+
const baseY = isLagna ? center.y + 8 : center.y;
|
|
4592
|
+
const startY = baseY - (planets.length - 1) * lineHeight / 2;
|
|
4094
4593
|
const yPos = startY + j * lineHeight;
|
|
4095
4594
|
return import_lit20.svg`<text class="planet-text" x=${center.x} y=${yPos} text-anchor="middle" dominant-baseline="central">${abbr}</text>`;
|
|
4096
4595
|
})}
|
|
@@ -4132,6 +4631,18 @@ RoxyVedicKundli.styles = [
|
|
|
4132
4631
|
font-weight: 600;
|
|
4133
4632
|
font-family: var(--roxy-font-sans);
|
|
4134
4633
|
}
|
|
4634
|
+
.lagna-marker {
|
|
4635
|
+
fill: var(--roxy-accent-fg, #b45309);
|
|
4636
|
+
font-size: 8px;
|
|
4637
|
+
font-weight: 700;
|
|
4638
|
+
font-family: var(--roxy-font-sans);
|
|
4639
|
+
letter-spacing: 0.05em;
|
|
4640
|
+
}
|
|
4641
|
+
.lagna-bg {
|
|
4642
|
+
fill: color-mix(in srgb, var(--roxy-accent, #f59e0b) 12%, transparent);
|
|
4643
|
+
stroke: color-mix(in srgb, var(--roxy-accent, #f59e0b) 45%, transparent);
|
|
4644
|
+
stroke-width: 0.8;
|
|
4645
|
+
}
|
|
4135
4646
|
`
|
|
4136
4647
|
];
|
|
4137
4648
|
__decorateClass([
|
|
@@ -4148,27 +4659,307 @@ function capitalize4(s) {
|
|
|
4148
4659
|
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
|
|
4149
4660
|
}
|
|
4150
4661
|
|
|
4151
|
-
// packages/ui/src/
|
|
4152
|
-
var
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4662
|
+
// packages/ui/src/manifest.ts
|
|
4663
|
+
var ROXY_COMPONENTS = [
|
|
4664
|
+
{
|
|
4665
|
+
pascal: "RoxyNatalChart",
|
|
4666
|
+
tag: "roxy-natal-chart",
|
|
4667
|
+
slug: "natal-chart",
|
|
4668
|
+
domain: "astrology",
|
|
4669
|
+
heading: "Natal chart",
|
|
4670
|
+
endpoints: ["astrology.generateNatalChart"],
|
|
4671
|
+
description: "Western natal chart wheel for /astrology/natal-chart responses",
|
|
4672
|
+
docsLabel: "Western",
|
|
4673
|
+
endpointLabel: "POST /astrology/natal-chart",
|
|
4674
|
+
docsSummary: "Natal chart wheel with planet glyphs and aspect lines",
|
|
4675
|
+
topic: "Astrology"
|
|
4676
|
+
},
|
|
4677
|
+
{
|
|
4678
|
+
pascal: "RoxyHoroscopeCard",
|
|
4679
|
+
tag: "roxy-horoscope-card",
|
|
4680
|
+
slug: "horoscope-card",
|
|
4681
|
+
domain: "astrology",
|
|
4682
|
+
heading: "Daily horoscope",
|
|
4683
|
+
endpoints: [
|
|
4684
|
+
"astrology.getDailyHoroscope",
|
|
4685
|
+
"astrology.getWeeklyHoroscope",
|
|
4686
|
+
"astrology.getMonthlyHoroscope"
|
|
4687
|
+
],
|
|
4688
|
+
description: "Daily, weekly, or monthly horoscope card for /astrology/horoscope/...",
|
|
4689
|
+
docsLabel: "Western",
|
|
4690
|
+
endpointLabel: "GET /astrology/horoscope/{sign}/{daily,weekly,monthly}",
|
|
4691
|
+
docsSummary: "Daily, weekly, or monthly horoscope card",
|
|
4692
|
+
topic: "Astrology"
|
|
4693
|
+
},
|
|
4694
|
+
{
|
|
4695
|
+
pascal: "RoxySynastryChart",
|
|
4696
|
+
tag: "roxy-synastry-chart",
|
|
4697
|
+
slug: "synastry-chart",
|
|
4698
|
+
domain: "astrology",
|
|
4699
|
+
heading: "Synastry",
|
|
4700
|
+
endpoints: ["astrology.calculateSynastry"],
|
|
4701
|
+
description: "Dual-wheel synastry chart with inter-aspects table",
|
|
4702
|
+
docsLabel: "Western",
|
|
4703
|
+
endpointLabel: "POST /astrology/synastry",
|
|
4704
|
+
docsSummary: "Dual-wheel synastry with inter-aspects table",
|
|
4705
|
+
topic: "Astrology"
|
|
4706
|
+
},
|
|
4707
|
+
{
|
|
4708
|
+
pascal: "RoxyCompatibilityCard",
|
|
4709
|
+
tag: "roxy-compatibility-card",
|
|
4710
|
+
slug: "compatibility-card",
|
|
4711
|
+
domain: "astrology",
|
|
4712
|
+
heading: "Compatibility score",
|
|
4713
|
+
endpoints: [
|
|
4714
|
+
"astrology.calculateCompatibility",
|
|
4715
|
+
"numerology.calculateNumCompatibility",
|
|
4716
|
+
"biorhythm.calculateBioCompatibility"
|
|
4717
|
+
],
|
|
4718
|
+
description: "Cross-domain compatibility score card",
|
|
4719
|
+
docsLabel: "Cross",
|
|
4720
|
+
endpointLabel: "POST /astrology/compatibility-score, /numerology/compatibility, /biorhythm/compatibility",
|
|
4721
|
+
docsSummary: "Score card with category breakdown",
|
|
4722
|
+
topic: "Astrology"
|
|
4723
|
+
},
|
|
4724
|
+
{
|
|
4725
|
+
pascal: "RoxyMoonPhase",
|
|
4726
|
+
tag: "roxy-moon-phase",
|
|
4727
|
+
slug: "moon-phase",
|
|
4728
|
+
domain: "astrology",
|
|
4729
|
+
heading: "Moon phase",
|
|
4730
|
+
endpoints: [
|
|
4731
|
+
"astrology.getCurrentMoonPhase",
|
|
4732
|
+
"astrology.getUpcomingMoonPhases",
|
|
4733
|
+
"astrology.getMoonCalendar"
|
|
4734
|
+
],
|
|
4735
|
+
description: "Moon phase card and calendar",
|
|
4736
|
+
docsLabel: "Western",
|
|
4737
|
+
endpointLabel: "GET /astrology/moon-phase/{current,upcoming,calendar/...}",
|
|
4738
|
+
docsSummary: "Moon phase card and calendar",
|
|
4739
|
+
topic: "Astrology"
|
|
4740
|
+
},
|
|
4741
|
+
{
|
|
4742
|
+
pascal: "RoxyVedicKundli",
|
|
4743
|
+
tag: "roxy-vedic-kundli",
|
|
4744
|
+
slug: "vedic-kundli",
|
|
4745
|
+
domain: "vedic",
|
|
4746
|
+
heading: "Vedic kundli",
|
|
4747
|
+
endpoints: ["vedicAstrology.generateBirthChart"],
|
|
4748
|
+
description: "South or North Indian Vedic kundli for /vedic-astrology/birth-chart",
|
|
4749
|
+
docsLabel: "Vedic",
|
|
4750
|
+
endpointLabel: "POST /vedic-astrology/birth-chart",
|
|
4751
|
+
docsSummary: "South or North Indian kundli",
|
|
4752
|
+
topic: "Vedic"
|
|
4753
|
+
},
|
|
4754
|
+
{
|
|
4755
|
+
pascal: "RoxyPanchangTable",
|
|
4756
|
+
tag: "roxy-panchang-table",
|
|
4757
|
+
slug: "panchang-table",
|
|
4758
|
+
domain: "vedic",
|
|
4759
|
+
heading: "Panchang",
|
|
4760
|
+
endpoints: [
|
|
4761
|
+
"vedicAstrology.getBasicPanchang",
|
|
4762
|
+
"vedicAstrology.getDetailedPanchang"
|
|
4763
|
+
],
|
|
4764
|
+
description: "Panchang muhurta table with auspicious and inauspicious periods",
|
|
4765
|
+
docsLabel: "Vedic",
|
|
4766
|
+
endpointLabel: "POST /vedic-astrology/panchang/{basic,detailed}",
|
|
4767
|
+
docsSummary: "15+ muhurtas in detailed mode",
|
|
4768
|
+
topic: "Vedic"
|
|
4769
|
+
},
|
|
4770
|
+
{
|
|
4771
|
+
pascal: "RoxyDashaTimeline",
|
|
4772
|
+
tag: "roxy-dasha-timeline",
|
|
4773
|
+
slug: "dasha-timeline",
|
|
4774
|
+
domain: "vedic",
|
|
4775
|
+
heading: "Vimshottari dasha",
|
|
4776
|
+
endpoints: [
|
|
4777
|
+
"vedicAstrology.getCurrentDasha",
|
|
4778
|
+
"vedicAstrology.getMajorDashas",
|
|
4779
|
+
"vedicAstrology.getSubDashas"
|
|
4780
|
+
],
|
|
4781
|
+
description: "Vimshottari dasha timeline with active mahadasha highlighted",
|
|
4782
|
+
docsLabel: "Vedic",
|
|
4783
|
+
endpointLabel: "POST /vedic-astrology/dasha/{current,major,sub/...}",
|
|
4784
|
+
docsSummary: "Vimshottari mahadasha + antardasha + pratyantardasha",
|
|
4785
|
+
topic: "Vedic"
|
|
4786
|
+
},
|
|
4787
|
+
{
|
|
4788
|
+
pascal: "RoxyDoshaCard",
|
|
4789
|
+
tag: "roxy-dosha-card",
|
|
4790
|
+
slug: "dosha-card",
|
|
4791
|
+
domain: "vedic",
|
|
4792
|
+
heading: "Manglik dosha",
|
|
4793
|
+
endpoints: [
|
|
4794
|
+
"vedicAstrology.checkManglikDosha",
|
|
4795
|
+
"vedicAstrology.checkKalsarpaDosha",
|
|
4796
|
+
"vedicAstrology.checkSadhesati"
|
|
4797
|
+
],
|
|
4798
|
+
description: "Manglik, Kaal Sarp, or Sade Sati presence card",
|
|
4799
|
+
docsLabel: "Vedic",
|
|
4800
|
+
endpointLabel: "POST /vedic-astrology/dosha/{manglik,kalsarpa,sadhesati}",
|
|
4801
|
+
docsSummary: "Presence, severity, remedies, scoped effects",
|
|
4802
|
+
topic: "Vedic"
|
|
4803
|
+
},
|
|
4804
|
+
{
|
|
4805
|
+
pascal: "RoxyGunaMilan",
|
|
4806
|
+
tag: "roxy-guna-milan",
|
|
4807
|
+
slug: "guna-milan",
|
|
4808
|
+
domain: "vedic",
|
|
4809
|
+
heading: "Guna milan",
|
|
4810
|
+
endpoints: ["vedicAstrology.calculateGunMilan"],
|
|
4811
|
+
description: "36-point Ashtakoota matrimonial compatibility breakdown",
|
|
4812
|
+
docsLabel: "Vedic",
|
|
4813
|
+
endpointLabel: "POST /vedic-astrology/compatibility",
|
|
4814
|
+
docsSummary: "36-point Ashtakoota with eight sub-scores",
|
|
4815
|
+
topic: "Vedic"
|
|
4816
|
+
},
|
|
4817
|
+
{
|
|
4818
|
+
pascal: "RoxyKpPlanetsTable",
|
|
4819
|
+
tag: "roxy-kp-planets-table",
|
|
4820
|
+
slug: "kp-planets-table",
|
|
4821
|
+
domain: "vedic",
|
|
4822
|
+
heading: "KP planets",
|
|
4823
|
+
endpoints: ["vedicAstrology.getKpPlanets"],
|
|
4824
|
+
description: "KP planets table with sub-lord and sub-sub-lord columns",
|
|
4825
|
+
docsLabel: "Vedic (KP)",
|
|
4826
|
+
endpointLabel: "POST /vedic-astrology/kp/planets",
|
|
4827
|
+
docsSummary: "Sub-lord and sub-sub-lord columns",
|
|
4828
|
+
topic: "Vedic"
|
|
4829
|
+
},
|
|
4830
|
+
{
|
|
4831
|
+
pascal: "RoxyNumerologyCard",
|
|
4832
|
+
tag: "roxy-numerology-card",
|
|
4833
|
+
slug: "numerology-card",
|
|
4834
|
+
domain: "numerology",
|
|
4835
|
+
heading: "Life path number",
|
|
4836
|
+
endpoints: [
|
|
4837
|
+
"numerology.calculateLifePath",
|
|
4838
|
+
"numerology.calculateExpression",
|
|
4839
|
+
"numerology.calculatePersonalYear",
|
|
4840
|
+
"numerology.generateNumerologyChart"
|
|
4841
|
+
],
|
|
4842
|
+
description: "Numerology card for life path, expression, personal year, or full chart",
|
|
4843
|
+
docsLabel: "Numerology",
|
|
4844
|
+
endpointLabel: "POST /numerology/{life-path,expression,personal-year,chart}",
|
|
4845
|
+
docsSummary: "Life path, expression, personal year, full chart",
|
|
4846
|
+
topic: "Numerology"
|
|
4847
|
+
},
|
|
4848
|
+
{
|
|
4849
|
+
pascal: "RoxyTarotCard",
|
|
4850
|
+
tag: "roxy-tarot-card",
|
|
4851
|
+
slug: "tarot-card",
|
|
4852
|
+
domain: "tarot",
|
|
4853
|
+
heading: "Daily tarot card",
|
|
4854
|
+
endpoints: ["tarot.getCard", "tarot.getDailyCard"],
|
|
4855
|
+
description: "Single tarot card with upright/reversed flip animation",
|
|
4856
|
+
docsLabel: "Tarot",
|
|
4857
|
+
endpointLabel: "GET /tarot/cards/{id}, POST /tarot/daily",
|
|
4858
|
+
docsSummary: "Single card with upright and reversed flip",
|
|
4859
|
+
topic: "Tarot"
|
|
4860
|
+
},
|
|
4861
|
+
{
|
|
4862
|
+
pascal: "RoxyTarotSpread",
|
|
4863
|
+
tag: "roxy-tarot-spread",
|
|
4864
|
+
slug: "tarot-spread",
|
|
4865
|
+
domain: "tarot",
|
|
4866
|
+
heading: "Three-card spread",
|
|
4867
|
+
endpoints: [
|
|
4868
|
+
"tarot.castThreeCard",
|
|
4869
|
+
"tarot.castCelticCross",
|
|
4870
|
+
"tarot.castLoveSpread",
|
|
4871
|
+
"tarot.castYesNo",
|
|
4872
|
+
"tarot.drawCards"
|
|
4873
|
+
],
|
|
4874
|
+
description: "Tarot spread renderer for three-card, Celtic Cross, love, or yes/no",
|
|
4875
|
+
docsLabel: "Tarot",
|
|
4876
|
+
endpointLabel: "POST /tarot/spreads/{three-card,celtic-cross,love}, /tarot/yes-no, /tarot/draw",
|
|
4877
|
+
docsSummary: "Spreads with positions and reading",
|
|
4878
|
+
topic: "Tarot"
|
|
4879
|
+
},
|
|
4880
|
+
{
|
|
4881
|
+
pascal: "RoxyBiorhythmChart",
|
|
4882
|
+
tag: "roxy-biorhythm-chart",
|
|
4883
|
+
slug: "biorhythm-chart",
|
|
4884
|
+
domain: "biorhythm",
|
|
4885
|
+
heading: "Daily biorhythm",
|
|
4886
|
+
endpoints: [
|
|
4887
|
+
"biorhythm.getDailyBiorhythm",
|
|
4888
|
+
"biorhythm.getForecast",
|
|
4889
|
+
"biorhythm.getCriticalDays"
|
|
4890
|
+
],
|
|
4891
|
+
description: "Daily biorhythm bars or multi-day forecast cycle lines",
|
|
4892
|
+
docsLabel: "Biorhythm",
|
|
4893
|
+
endpointLabel: "POST /biorhythm/{daily,forecast,critical-days}",
|
|
4894
|
+
docsSummary: "Daily bars, forecast cycle lines, critical days",
|
|
4895
|
+
topic: "Biorhythm"
|
|
4896
|
+
},
|
|
4897
|
+
{
|
|
4898
|
+
pascal: "RoxyHexagram",
|
|
4899
|
+
tag: "roxy-hexagram",
|
|
4900
|
+
slug: "hexagram",
|
|
4901
|
+
domain: "iching",
|
|
4902
|
+
heading: "I Ching hexagram",
|
|
4903
|
+
endpoints: [
|
|
4904
|
+
"iching.getHexagram",
|
|
4905
|
+
"iching.castReading",
|
|
4906
|
+
"iching.getDailyHexagram",
|
|
4907
|
+
"iching.castDailyReading",
|
|
4908
|
+
"iching.getRandomHexagram"
|
|
4909
|
+
],
|
|
4910
|
+
description: "I Ching hexagram with trigram glyphs, judgment, image, and changing lines",
|
|
4911
|
+
docsLabel: "I Ching",
|
|
4912
|
+
endpointLabel: "GET /iching/hexagrams/{number}, /iching/cast, POST /iching/daily, /iching/daily/cast",
|
|
4913
|
+
docsSummary: "Hexagram with trigrams, judgment, image, changing lines",
|
|
4914
|
+
topic: "I Ching"
|
|
4915
|
+
},
|
|
4916
|
+
{
|
|
4917
|
+
pascal: "RoxyEndpointForm",
|
|
4918
|
+
tag: "roxy-endpoint-form",
|
|
4919
|
+
slug: "endpoint-form",
|
|
4920
|
+
domain: "utility",
|
|
4921
|
+
heading: "Schema-driven form",
|
|
4922
|
+
endpoints: [],
|
|
4923
|
+
description: "Schema-driven form that emits roxy-submit with a validated payload",
|
|
4924
|
+
docsLabel: "Helper",
|
|
4925
|
+
endpointLabel: "Any endpoint via x-roxy-ui hints",
|
|
4926
|
+
docsSummary: "Schema-driven form, emits roxy-submit",
|
|
4927
|
+
topic: "Helpers",
|
|
4928
|
+
selfFetching: true
|
|
4929
|
+
},
|
|
4930
|
+
{
|
|
4931
|
+
pascal: "RoxyLocationSearch",
|
|
4932
|
+
tag: "roxy-location-search",
|
|
4933
|
+
slug: "location-search",
|
|
4934
|
+
domain: "utility",
|
|
4935
|
+
heading: "City search",
|
|
4936
|
+
endpoints: ["location.searchCities"],
|
|
4937
|
+
description: "City search input with debounced /location/search calls",
|
|
4938
|
+
docsLabel: "Helper",
|
|
4939
|
+
endpointLabel: "GET /location/search",
|
|
4940
|
+
docsSummary: "Debounced city search input, emits roxy-location-select",
|
|
4941
|
+
topic: "Helpers",
|
|
4942
|
+
selfFetching: true
|
|
4943
|
+
},
|
|
4944
|
+
{
|
|
4945
|
+
pascal: "RoxyData",
|
|
4946
|
+
tag: "roxy-data",
|
|
4947
|
+
slug: "data",
|
|
4948
|
+
domain: "utility",
|
|
4949
|
+
heading: "Generic renderer",
|
|
4950
|
+
endpoints: [],
|
|
4951
|
+
description: "Generic fallback renderer for any OpenAPI response shape",
|
|
4952
|
+
docsLabel: "Helper",
|
|
4953
|
+
endpointLabel: "Any response shape",
|
|
4954
|
+
docsSummary: "Generic fallback renderer for unknown shapes",
|
|
4955
|
+
topic: "Helpers",
|
|
4956
|
+
selfFetching: true
|
|
4957
|
+
}
|
|
4173
4958
|
];
|
|
4959
|
+
|
|
4960
|
+
// packages/ui/src/version.ts
|
|
4961
|
+
var ROXY_UI_VERSION = "0.1.3";
|
|
4962
|
+
|
|
4963
|
+
// packages/ui/src/index.ts
|
|
4964
|
+
var ROXY_UI_COMPONENTS = ROXY_COMPONENTS.map((c) => c.slug);
|
|
4174
4965
|
//# sourceMappingURL=index.cjs.map
|