@roxyapi/ui 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +27 -1
- package/README.md +115 -14
- package/dist/cdn/components/ashtakavarga-grid.js +74 -19
- package/dist/cdn/components/ashtakavarga-grid.js.map +2 -2
- package/dist/cdn/components/biorhythm-chart.js +18 -4
- package/dist/cdn/components/biorhythm-chart.js.map +2 -2
- package/dist/cdn/components/choghadiya-grid.js +47 -12
- package/dist/cdn/components/choghadiya-grid.js.map +3 -3
- package/dist/cdn/components/compatibility-card.js +21 -7
- package/dist/cdn/components/compatibility-card.js.map +2 -2
- package/dist/cdn/components/dasha-timeline.js +113 -28
- package/dist/cdn/components/dasha-timeline.js.map +3 -3
- package/dist/cdn/components/data.js +27 -13
- package/dist/cdn/components/data.js.map +2 -2
- package/dist/cdn/components/divisional-chart.js +225 -118
- package/dist/cdn/components/divisional-chart.js.map +4 -4
- package/dist/cdn/components/dosha-card.js +18 -4
- package/dist/cdn/components/dosha-card.js.map +2 -2
- package/dist/cdn/components/endpoint-form.js +25 -11
- package/dist/cdn/components/endpoint-form.js.map +2 -2
- package/dist/cdn/components/guna-milan.js +20 -6
- package/dist/cdn/components/guna-milan.js.map +2 -2
- package/dist/cdn/components/hexagram.js +22 -8
- package/dist/cdn/components/hexagram.js.map +2 -2
- package/dist/cdn/components/horoscope-card.js +20 -6
- package/dist/cdn/components/horoscope-card.js.map +2 -2
- package/dist/cdn/components/kp-chart.js +19 -5
- package/dist/cdn/components/kp-chart.js.map +2 -2
- package/dist/cdn/components/kp-planets-table.js +17 -3
- package/dist/cdn/components/kp-planets-table.js.map +2 -2
- package/dist/cdn/components/kp-ruling-planets.js +17 -3
- package/dist/cdn/components/kp-ruling-planets.js.map +2 -2
- package/dist/cdn/components/location-search.js +18 -4
- package/dist/cdn/components/location-search.js.map +2 -2
- package/dist/cdn/components/moon-phase.js +27 -13
- package/dist/cdn/components/moon-phase.js.map +2 -2
- package/dist/cdn/components/nakshatra-card.js +16 -2
- package/dist/cdn/components/nakshatra-card.js.map +2 -2
- package/dist/cdn/components/natal-chart.js +79 -40
- package/dist/cdn/components/natal-chart.js.map +3 -3
- package/dist/cdn/components/numerology-card.js +18 -4
- package/dist/cdn/components/numerology-card.js.map +2 -2
- package/dist/cdn/components/panchang-table.js +53 -25
- package/dist/cdn/components/panchang-table.js.map +3 -3
- package/dist/cdn/components/shadbala-table.js +24 -10
- package/dist/cdn/components/shadbala-table.js.map +2 -2
- package/dist/cdn/components/synastry-chart.js +96 -48
- package/dist/cdn/components/synastry-chart.js.map +3 -3
- package/dist/cdn/components/tarot-card.js +17 -3
- package/dist/cdn/components/tarot-card.js.map +2 -2
- package/dist/cdn/components/tarot-spread.js +39 -25
- package/dist/cdn/components/tarot-spread.js.map +2 -2
- package/dist/cdn/components/transits-table.js +18 -4
- package/dist/cdn/components/transits-table.js.map +2 -2
- package/dist/cdn/components/vedic-kundli.js +215 -105
- package/dist/cdn/components/vedic-kundli.js.map +4 -4
- package/dist/cdn/components/vedic-planets-table.js +22 -8
- package/dist/cdn/components/vedic-planets-table.js.map +2 -2
- package/dist/cdn/components/western-planets-table.js +18 -4
- package/dist/cdn/components/western-planets-table.js.map +2 -2
- package/dist/cdn/components/yoga-list.js +17 -3
- package/dist/cdn/components/yoga-list.js.map +2 -2
- package/dist/cdn/roxy-ui.js +1082 -816
- package/dist/cdn/roxy-ui.js.map +4 -4
- package/dist/components/ashtakavarga-grid.d.ts +13 -1
- package/dist/components/ashtakavarga-grid.d.ts.map +1 -1
- package/dist/components/ashtakavarga-grid.js +86 -11
- package/dist/components/ashtakavarga-grid.js.map +2 -2
- package/dist/components/biorhythm-chart.js +14 -0
- package/dist/components/biorhythm-chart.js.map +2 -2
- package/dist/components/choghadiya-grid.d.ts +6 -0
- package/dist/components/choghadiya-grid.d.ts.map +1 -1
- package/dist/components/choghadiya-grid.js +50 -2
- package/dist/components/choghadiya-grid.js.map +2 -2
- package/dist/components/compatibility-card.js +14 -0
- package/dist/components/compatibility-card.js.map +2 -2
- package/dist/components/dasha-timeline.d.ts +10 -0
- package/dist/components/dasha-timeline.d.ts.map +1 -1
- package/dist/components/dasha-timeline.js +135 -4
- package/dist/components/dasha-timeline.js.map +2 -2
- package/dist/components/data.js +14 -0
- package/dist/components/data.js.map +2 -2
- package/dist/components/divisional-chart.d.ts +9 -6
- package/dist/components/divisional-chart.d.ts.map +1 -1
- package/dist/components/divisional-chart.js +546 -251
- package/dist/components/divisional-chart.js.map +4 -4
- package/dist/components/dosha-card.js +14 -0
- package/dist/components/dosha-card.js.map +2 -2
- package/dist/components/endpoint-form.js +14 -0
- package/dist/components/endpoint-form.js.map +2 -2
- package/dist/components/guna-milan.js +14 -0
- package/dist/components/guna-milan.js.map +2 -2
- package/dist/components/hexagram.js +14 -0
- package/dist/components/hexagram.js.map +2 -2
- package/dist/components/horoscope-card.js +14 -0
- package/dist/components/horoscope-card.js.map +2 -2
- package/dist/components/kp-chart.js +14 -0
- package/dist/components/kp-chart.js.map +2 -2
- package/dist/components/kp-planets-table.js +14 -0
- package/dist/components/kp-planets-table.js.map +2 -2
- package/dist/components/kp-ruling-planets.js +14 -0
- package/dist/components/kp-ruling-planets.js.map +2 -2
- package/dist/components/location-search.js +14 -0
- package/dist/components/location-search.js.map +2 -2
- package/dist/components/moon-phase.js +14 -0
- package/dist/components/moon-phase.js.map +2 -2
- package/dist/components/nakshatra-card.js +14 -0
- package/dist/components/nakshatra-card.js.map +2 -2
- package/dist/components/natal-chart.d.ts.map +1 -1
- package/dist/components/natal-chart.js +76 -6
- package/dist/components/natal-chart.js.map +2 -2
- package/dist/components/numerology-card.js +14 -0
- package/dist/components/numerology-card.js.map +2 -2
- package/dist/components/panchang-table.d.ts +1 -0
- package/dist/components/panchang-table.d.ts.map +1 -1
- package/dist/components/panchang-table.js +37 -1
- package/dist/components/panchang-table.js.map +2 -2
- package/dist/components/shadbala-table.js +14 -0
- package/dist/components/shadbala-table.js.map +2 -2
- package/dist/components/synastry-chart.d.ts +6 -0
- package/dist/components/synastry-chart.d.ts.map +1 -1
- package/dist/components/synastry-chart.js +106 -7
- package/dist/components/synastry-chart.js.map +2 -2
- package/dist/components/tarot-card.js +14 -0
- package/dist/components/tarot-card.js.map +2 -2
- package/dist/components/tarot-spread.js +14 -0
- package/dist/components/tarot-spread.js.map +2 -2
- package/dist/components/transits-table.js +14 -0
- package/dist/components/transits-table.js.map +2 -2
- package/dist/components/vedic-kundli.d.ts +14 -9
- package/dist/components/vedic-kundli.d.ts.map +1 -1
- package/dist/components/vedic-kundli.js +537 -245
- package/dist/components/vedic-kundli.js.map +4 -4
- package/dist/components/vedic-planets-table.js +14 -0
- package/dist/components/vedic-planets-table.js.map +2 -2
- package/dist/components/western-planets-table.js +14 -0
- package/dist/components/western-planets-table.js.map +2 -2
- package/dist/components/yoga-list.js +14 -0
- package/dist/components/yoga-list.js.map +2 -2
- package/dist/index.cjs +1397 -797
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +1278 -678
- package/dist/index.js.map +4 -4
- package/dist/manifest.json +23 -23
- package/dist/styles/tokens.css +8 -23
- package/dist/utils/base-styles.d.ts.map +1 -1
- package/dist/utils/kundli-render.d.ts +43 -104
- package/dist/utils/kundli-render.d.ts.map +1 -1
- package/dist/utils/kundli-styles.d.ts +13 -0
- package/dist/utils/kundli-styles.d.ts.map +1 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/ashtakavarga-grid.ts +73 -11
- package/src/components/choghadiya-grid.ts +37 -2
- package/src/components/dasha-timeline.ts +135 -4
- package/src/components/divisional-chart.ts +40 -97
- package/src/components/natal-chart.ts +89 -6
- package/src/components/panchang-table.ts +34 -1
- package/src/components/synastry-chart.ts +84 -8
- package/src/components/vedic-kundli.ts +35 -95
- package/src/styles/tokens.css +8 -23
- package/src/utils/base-styles.ts +14 -0
- package/src/utils/kundli-render.ts +609 -270
- package/src/utils/kundli-styles.ts +124 -0
- package/src/version.ts +1 -1
|
@@ -10,7 +10,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// packages/ui/src/components/divisional-chart.ts
|
|
13
|
-
import { css as
|
|
13
|
+
import { css as css3, html as html2, LitElement, nothing as nothing2 } from "lit";
|
|
14
14
|
import { customElement, property } from "lit/decorators.js";
|
|
15
15
|
|
|
16
16
|
// packages/ui/src/tokens/index.ts
|
|
@@ -170,10 +170,24 @@ var baseStyles = css`
|
|
|
170
170
|
outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
|
|
171
171
|
outline-offset: 2px;
|
|
172
172
|
}
|
|
173
|
+
|
|
174
|
+
/* Force the text-style variant on every Unicode glyph in the component.
|
|
175
|
+
* macOS and iOS substitute coloured emoji glyphs for the planetary and
|
|
176
|
+
* gender Unicode code points (Mars, Venus, Mercury, etc.) when the
|
|
177
|
+
* system colour-emoji font wins font selection. The text-style variant
|
|
178
|
+
* keeps glyphs monochrome so they inherit the surrounding fill colour
|
|
179
|
+
* and match the brand palette consistently across platforms.
|
|
180
|
+
*
|
|
181
|
+
* font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,
|
|
182
|
+
* Firefox 139+). On older browsers the rule is silently ignored.
|
|
183
|
+
*/
|
|
184
|
+
:host {
|
|
185
|
+
font-variant-emoji: text;
|
|
186
|
+
}
|
|
173
187
|
`;
|
|
174
188
|
|
|
175
189
|
// packages/ui/src/utils/kundli-render.ts
|
|
176
|
-
import { nothing, svg } from "lit";
|
|
190
|
+
import { html, nothing, svg } from "lit";
|
|
177
191
|
|
|
178
192
|
// packages/ui/src/utils/degree.ts
|
|
179
193
|
function normalizeLongitude(lon) {
|
|
@@ -204,25 +218,45 @@ function capitalize(s) {
|
|
|
204
218
|
}
|
|
205
219
|
|
|
206
220
|
// packages/ui/src/utils/kundli-render.ts
|
|
221
|
+
var VIEW_BOX = 400;
|
|
222
|
+
var MARGIN = 20;
|
|
223
|
+
var INNER = VIEW_BOX - 2 * MARGIN;
|
|
224
|
+
var CENTRE = VIEW_BOX / 2;
|
|
207
225
|
var RASHI_TO_SIGN = Object.fromEntries(
|
|
208
226
|
SIGNS_ORDER.map((s) => [s.toLowerCase(), s])
|
|
209
227
|
);
|
|
228
|
+
var CHART_STYLES = [
|
|
229
|
+
{ id: "north", label: "North" },
|
|
230
|
+
{ id: "south", label: "South" },
|
|
231
|
+
{ id: "east", label: "East" }
|
|
232
|
+
];
|
|
210
233
|
var RETRO_MARK = "\u02B3";
|
|
211
|
-
function
|
|
234
|
+
function isDivisionalPlacement(p, cellSign) {
|
|
235
|
+
if (typeof p.longitude !== "number" || !Number.isFinite(p.longitude)) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
return longitudeToSignPosition(p.longitude).sign.toLowerCase() !== cellSign.toLowerCase();
|
|
239
|
+
}
|
|
240
|
+
function grahaLabel(p, cellSign) {
|
|
212
241
|
const abbr = PLANET_ABBR[capitalize(p.graha)] ?? p.graha.slice(0, 2);
|
|
213
242
|
const retro = p.isRetrograde ? RETRO_MARK : "";
|
|
214
|
-
if (typeof p.longitude !== "number" || !Number.isFinite(p.longitude)) {
|
|
243
|
+
if (typeof p.longitude !== "number" || !Number.isFinite(p.longitude) || isDivisionalPlacement(p, cellSign)) {
|
|
215
244
|
return `${abbr}${retro}`;
|
|
216
245
|
}
|
|
217
246
|
const { degree } = longitudeToSignPosition(p.longitude);
|
|
218
247
|
return `${abbr} ${degree}\xB0${retro}`;
|
|
219
248
|
}
|
|
220
|
-
function grahaTitle(p) {
|
|
249
|
+
function grahaTitle(p, cellSign) {
|
|
221
250
|
const parts = [capitalize(p.graha)];
|
|
251
|
+
const divisional = isDivisionalPlacement(p, cellSign);
|
|
252
|
+
if (divisional) {
|
|
253
|
+
parts.push(`in ${cellSign}`);
|
|
254
|
+
}
|
|
222
255
|
if (typeof p.longitude === "number" && Number.isFinite(p.longitude)) {
|
|
223
256
|
const sp = longitudeToSignPosition(p.longitude);
|
|
257
|
+
const minute = String(sp.minute).padStart(2, "0");
|
|
224
258
|
parts.push(
|
|
225
|
-
|
|
259
|
+
divisional ? `D1: ${sp.degree}\xB0${minute}' ${sp.sign}` : `${sp.degree}\xB0${minute}' ${sp.sign}`
|
|
226
260
|
);
|
|
227
261
|
}
|
|
228
262
|
if (p.nakshatra?.name) {
|
|
@@ -233,249 +267,562 @@ function grahaTitle(p) {
|
|
|
233
267
|
if (p.isRetrograde) parts.push("retrograde");
|
|
234
268
|
return parts.join(" \xB7 ");
|
|
235
269
|
}
|
|
236
|
-
function renderPlanetStack(planets, cx, baseY, lineHeight) {
|
|
270
|
+
function renderPlanetStack(planets, cellSign, cx, baseY, lineHeight) {
|
|
237
271
|
const startY = baseY - (planets.length - 1) * lineHeight / 2;
|
|
238
272
|
return planets.map((p, j) => {
|
|
239
273
|
const yPos = startY + j * lineHeight;
|
|
240
274
|
return svg`<text class="planet-text" x=${cx} y=${yPos} text-anchor="middle" dominant-baseline="central">${grahaLabel(
|
|
241
|
-
p
|
|
242
|
-
|
|
275
|
+
p,
|
|
276
|
+
cellSign
|
|
277
|
+
)}<title>${grahaTitle(p, cellSign)}</title></text>`;
|
|
243
278
|
});
|
|
244
279
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
7: { x: 45, y: 150 },
|
|
281
|
-
8: { x: 75, y: 100 },
|
|
282
|
-
9: { x: 100, y: 80 },
|
|
283
|
-
10: { x: 150, y: 108 },
|
|
284
|
-
11: { x: 200, y: 80 },
|
|
285
|
-
12: { x: 200, y: 220 }
|
|
286
|
-
};
|
|
287
|
-
var EAST_HOUSE_CENTERS = {
|
|
288
|
-
1: { x: 150, y: 80 },
|
|
289
|
-
// inner diamond, top
|
|
290
|
-
2: { x: 220, y: 33 },
|
|
291
|
-
// top-right corner, upper triangle
|
|
292
|
-
3: { x: 267, y: 80 },
|
|
293
|
-
// top-right corner, right triangle
|
|
294
|
-
4: { x: 220, y: 150 },
|
|
295
|
-
// inner diamond, right
|
|
296
|
-
5: { x: 267, y: 220 },
|
|
297
|
-
// bottom-right corner, right triangle
|
|
298
|
-
6: { x: 220, y: 267 },
|
|
299
|
-
// bottom-right corner, lower triangle
|
|
300
|
-
7: { x: 150, y: 220 },
|
|
301
|
-
// inner diamond, bottom
|
|
302
|
-
8: { x: 80, y: 267 },
|
|
303
|
-
// bottom-left corner, lower triangle
|
|
304
|
-
9: { x: 33, y: 220 },
|
|
305
|
-
// bottom-left corner, left triangle
|
|
306
|
-
10: { x: 80, y: 150 },
|
|
307
|
-
// inner diamond, left
|
|
308
|
-
11: { x: 33, y: 80 },
|
|
309
|
-
// top-left corner, left triangle
|
|
310
|
-
12: { x: 80, y: 33 }
|
|
311
|
-
// top-left corner, upper triangle
|
|
312
|
-
};
|
|
313
|
-
var EAST_SIGN_POSITIONS = {
|
|
314
|
-
1: { x: 150, y: 55 },
|
|
315
|
-
2: { x: 235, y: 24 },
|
|
316
|
-
3: { x: 276, y: 62 },
|
|
317
|
-
4: { x: 242, y: 150 },
|
|
318
|
-
5: { x: 276, y: 238 },
|
|
319
|
-
6: { x: 235, y: 276 },
|
|
320
|
-
7: { x: 150, y: 245 },
|
|
321
|
-
8: { x: 65, y: 276 },
|
|
322
|
-
9: { x: 24, y: 238 },
|
|
323
|
-
10: { x: 58, y: 150 },
|
|
324
|
-
11: { x: 24, y: 62 },
|
|
325
|
-
12: { x: 65, y: 24 }
|
|
280
|
+
function toKundliViewModel(meta, divisionLabel) {
|
|
281
|
+
const placements = {};
|
|
282
|
+
for (const sign of SIGNS_ORDER) placements[sign.toLowerCase()] = [];
|
|
283
|
+
let lagnaSign = "";
|
|
284
|
+
for (const [name, pos] of Object.entries(meta ?? {})) {
|
|
285
|
+
const rashiKey = (pos?.rashi ?? "").toLowerCase();
|
|
286
|
+
if (name === "Lagna" || pos?.graha === "Lagna") {
|
|
287
|
+
lagnaSign = RASHI_TO_SIGN[rashiKey] ?? "";
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (!rashiKey || !(rashiKey in placements)) continue;
|
|
291
|
+
placements[rashiKey]?.push({
|
|
292
|
+
graha: pos.graha ?? name,
|
|
293
|
+
longitude: pos.longitude,
|
|
294
|
+
nakshatra: pos.nakshatra,
|
|
295
|
+
isRetrograde: pos.isRetrograde,
|
|
296
|
+
awastha: pos.awastha
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
return { lagnaSign, placements, divisionLabel };
|
|
300
|
+
}
|
|
301
|
+
var SOUTH_CELL = INNER / 4;
|
|
302
|
+
var SOUTH_CELL_GRID = {
|
|
303
|
+
Pisces: { col: 0, row: 0 },
|
|
304
|
+
Aries: { col: 1, row: 0 },
|
|
305
|
+
Taurus: { col: 2, row: 0 },
|
|
306
|
+
Gemini: { col: 3, row: 0 },
|
|
307
|
+
Cancer: { col: 3, row: 1 },
|
|
308
|
+
Leo: { col: 3, row: 2 },
|
|
309
|
+
Virgo: { col: 3, row: 3 },
|
|
310
|
+
Libra: { col: 2, row: 3 },
|
|
311
|
+
Scorpio: { col: 1, row: 3 },
|
|
312
|
+
Sagittarius: { col: 0, row: 3 },
|
|
313
|
+
Capricorn: { col: 0, row: 2 },
|
|
314
|
+
Aquarius: { col: 0, row: 1 }
|
|
326
315
|
};
|
|
327
|
-
function
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
316
|
+
function southCellRect(sign) {
|
|
317
|
+
const g = SOUTH_CELL_GRID[sign] ?? { col: 0, row: 0 };
|
|
318
|
+
return {
|
|
319
|
+
x: MARGIN + g.col * SOUTH_CELL,
|
|
320
|
+
y: MARGIN + g.row * SOUTH_CELL,
|
|
321
|
+
w: SOUTH_CELL,
|
|
322
|
+
h: SOUTH_CELL
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function renderSouthFrame(divisionLabel) {
|
|
326
|
+
const a = MARGIN;
|
|
327
|
+
const b = MARGIN + SOUTH_CELL;
|
|
328
|
+
const c = MARGIN + 2 * SOUTH_CELL;
|
|
329
|
+
const d = MARGIN + 3 * SOUTH_CELL;
|
|
330
|
+
const e = VIEW_BOX - MARGIN;
|
|
333
331
|
return svg`
|
|
334
|
-
<
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
332
|
+
<rect class="line" x=${a} y=${a} width=${INNER} height=${INNER} stroke-width="1.5" fill="none" />
|
|
333
|
+
<line class="line" x1=${a} y1=${b} x2=${e} y2=${b} stroke-width="1" />
|
|
334
|
+
<line class="line" x1=${a} y1=${d} x2=${e} y2=${d} stroke-width="1" />
|
|
335
|
+
<line class="line" x1=${b} y1=${a} x2=${b} y2=${e} stroke-width="1" />
|
|
336
|
+
<line class="line" x1=${d} y1=${a} x2=${d} y2=${e} stroke-width="1" />
|
|
337
|
+
<line class="line" x1=${a} y1=${c} x2=${b} y2=${c} stroke-width="1" />
|
|
338
|
+
<line class="line" x1=${d} y1=${c} x2=${e} y2=${c} stroke-width="1" />
|
|
339
|
+
<line class="line" x1=${c} y1=${a} x2=${c} y2=${b} stroke-width="1" />
|
|
340
|
+
<line class="line" x1=${c} y1=${d} x2=${c} y2=${e} stroke-width="1" />
|
|
341
|
+
${divisionLabel ? svg`<text class="centre-label" x=${CENTRE} y=${CENTRE} text-anchor="middle" dominant-baseline="central">${divisionLabel}</text>` : nothing}
|
|
342
|
+
`;
|
|
343
|
+
}
|
|
344
|
+
function houseNumberInSign(sign, lagnaSign) {
|
|
345
|
+
const lagnaIdx = SIGNS_ORDER.findIndex((s) => s === lagnaSign);
|
|
346
|
+
const signIdx = SIGNS_ORDER.findIndex((s) => s === sign);
|
|
347
|
+
if (lagnaIdx === -1 || signIdx === -1) return 0;
|
|
348
|
+
return (signIdx - lagnaIdx + 12) % 12 + 1;
|
|
349
|
+
}
|
|
350
|
+
function renderSouthCell(sign, planets, isLagna, houseNum) {
|
|
351
|
+
const r = southCellRect(sign);
|
|
352
|
+
const cx = r.x + r.w / 2;
|
|
353
|
+
const cy = r.y + r.h / 2;
|
|
354
|
+
const signAbbr = SIGN_ABBR[sign] ?? sign.slice(0, 2);
|
|
355
|
+
const slashInset = 14;
|
|
356
|
+
return svg`
|
|
357
|
+
<g class=${isLagna ? "cell lagna" : "cell"}>
|
|
358
|
+
${isLagna ? svg`
|
|
359
|
+
<rect class="lagna-bg" x=${r.x} y=${r.y} width=${r.w} height=${r.h} />
|
|
360
|
+
<line class="lagna-slash" x1=${r.x + r.w - slashInset} y1=${r.y + slashInset} x2=${r.x + slashInset} y2=${r.y + r.h - slashInset} stroke-width="1.2" />
|
|
361
|
+
` : nothing}
|
|
362
|
+
<text class="sign-text" x=${r.x + 6} y=${r.y + 12} text-anchor="start" dominant-baseline="central">${signAbbr}</text>
|
|
363
|
+
${houseNum > 0 ? svg`<text class="house-num" x=${r.x + r.w - 6} y=${r.y + 12} text-anchor="end" dominant-baseline="central">${houseNum}</text>` : nothing}
|
|
364
|
+
${planets.length ? renderPlanetStack(planets, sign, cx, cy + 4, 14) : nothing}
|
|
343
365
|
</g>
|
|
344
366
|
`;
|
|
345
367
|
}
|
|
346
|
-
function
|
|
368
|
+
function renderSouthSvg(vm) {
|
|
369
|
+
const lagnaKey = vm.lagnaSign.toLowerCase();
|
|
370
|
+
return svg`
|
|
371
|
+
${renderSouthFrame(vm.divisionLabel)}
|
|
372
|
+
${SIGNS_ORDER.map(
|
|
373
|
+
(sign) => renderSouthCell(
|
|
374
|
+
sign,
|
|
375
|
+
vm.placements[sign.toLowerCase()] ?? [],
|
|
376
|
+
sign.toLowerCase() === lagnaKey,
|
|
377
|
+
houseNumberInSign(sign, vm.lagnaSign)
|
|
378
|
+
)
|
|
379
|
+
)}
|
|
380
|
+
`;
|
|
381
|
+
}
|
|
382
|
+
var NORTH_VERTICES = {
|
|
383
|
+
tl: { x: MARGIN, y: MARGIN },
|
|
384
|
+
tr: { x: VIEW_BOX - MARGIN, y: MARGIN },
|
|
385
|
+
br: { x: VIEW_BOX - MARGIN, y: VIEW_BOX - MARGIN },
|
|
386
|
+
bl: { x: MARGIN, y: VIEW_BOX - MARGIN },
|
|
387
|
+
top: { x: CENTRE, y: MARGIN },
|
|
388
|
+
right: { x: VIEW_BOX - MARGIN, y: CENTRE },
|
|
389
|
+
bottom: { x: CENTRE, y: VIEW_BOX - MARGIN },
|
|
390
|
+
left: { x: MARGIN, y: CENTRE },
|
|
391
|
+
tlMid: { x: CENTRE - INNER / 4, y: CENTRE - INNER / 4 },
|
|
392
|
+
trMid: { x: CENTRE + INNER / 4, y: CENTRE - INNER / 4 },
|
|
393
|
+
brMid: { x: CENTRE + INNER / 4, y: CENTRE + INNER / 4 },
|
|
394
|
+
blMid: { x: CENTRE - INNER / 4, y: CENTRE + INNER / 4 }
|
|
395
|
+
};
|
|
396
|
+
function centroidOf(pts) {
|
|
397
|
+
const x = pts.reduce((s, p) => s + p.x, 0) / pts.length;
|
|
398
|
+
const y = pts.reduce((s, p) => s + p.y, 0) / pts.length;
|
|
399
|
+
return { x, y };
|
|
400
|
+
}
|
|
401
|
+
var NORTH_HOUSE_CENTERS = {
|
|
402
|
+
1: { x: CENTRE, y: NORTH_VERTICES.tlMid.y },
|
|
403
|
+
2: centroidOf([NORTH_VERTICES.tl, NORTH_VERTICES.top, NORTH_VERTICES.tlMid]),
|
|
404
|
+
3: centroidOf([NORTH_VERTICES.tl, NORTH_VERTICES.left, NORTH_VERTICES.tlMid]),
|
|
405
|
+
4: { x: NORTH_VERTICES.tlMid.x, y: CENTRE },
|
|
406
|
+
5: centroidOf([NORTH_VERTICES.bl, NORTH_VERTICES.left, NORTH_VERTICES.blMid]),
|
|
407
|
+
6: centroidOf([
|
|
408
|
+
NORTH_VERTICES.bl,
|
|
409
|
+
NORTH_VERTICES.bottom,
|
|
410
|
+
NORTH_VERTICES.blMid
|
|
411
|
+
]),
|
|
412
|
+
7: { x: CENTRE, y: NORTH_VERTICES.blMid.y },
|
|
413
|
+
8: centroidOf([
|
|
414
|
+
NORTH_VERTICES.br,
|
|
415
|
+
NORTH_VERTICES.bottom,
|
|
416
|
+
NORTH_VERTICES.brMid
|
|
417
|
+
]),
|
|
418
|
+
9: centroidOf([
|
|
419
|
+
NORTH_VERTICES.br,
|
|
420
|
+
NORTH_VERTICES.right,
|
|
421
|
+
NORTH_VERTICES.brMid
|
|
422
|
+
]),
|
|
423
|
+
10: { x: NORTH_VERTICES.brMid.x, y: CENTRE },
|
|
424
|
+
11: centroidOf([
|
|
425
|
+
NORTH_VERTICES.tr,
|
|
426
|
+
NORTH_VERTICES.right,
|
|
427
|
+
NORTH_VERTICES.trMid
|
|
428
|
+
]),
|
|
429
|
+
12: centroidOf([NORTH_VERTICES.tr, NORTH_VERTICES.top, NORTH_VERTICES.trMid])
|
|
430
|
+
};
|
|
431
|
+
function rashiInHouse(houseNum, lagnaSign) {
|
|
432
|
+
const lagnaIdx = SIGNS_ORDER.findIndex((s) => s === lagnaSign);
|
|
433
|
+
if (lagnaIdx === -1) return houseNum;
|
|
434
|
+
return (lagnaIdx + houseNum - 1) % 12 + 1;
|
|
435
|
+
}
|
|
436
|
+
function renderNorthFrame(divisionLabel) {
|
|
437
|
+
const { tl, tr, br, bl, top, right, bottom, left } = NORTH_VERTICES;
|
|
347
438
|
return svg`
|
|
348
|
-
<
|
|
349
|
-
<
|
|
350
|
-
<line class="line" x1
|
|
351
|
-
<line class="line" x1
|
|
352
|
-
|
|
353
|
-
<line class="line" x1="150" y1="290" x2="10" y2="150" stroke-width="0.6" stroke-dasharray="3,3" />
|
|
354
|
-
<line class="line" x1="150" y1="290" x2="290" y2="150" stroke-width="0.6" stroke-dasharray="3,3" />
|
|
439
|
+
<rect class="line" x=${tl.x} y=${tl.y} width=${INNER} height=${INNER} stroke-width="1.5" fill="none" />
|
|
440
|
+
<polygon class="line" points="${top.x},${top.y} ${right.x},${right.y} ${bottom.x},${bottom.y} ${left.x},${left.y}" stroke-width="1" fill="none" />
|
|
441
|
+
<line class="line" x1=${tl.x} y1=${tl.y} x2=${br.x} y2=${br.y} stroke-width="1" />
|
|
442
|
+
<line class="line" x1=${tr.x} y1=${tr.y} x2=${bl.x} y2=${bl.y} stroke-width="1" />
|
|
443
|
+
${divisionLabel ? svg`<text class="centre-label" x=${CENTRE} y=${CENTRE} text-anchor="middle" dominant-baseline="central">${divisionLabel}</text>` : nothing}
|
|
355
444
|
`;
|
|
356
445
|
}
|
|
357
|
-
function
|
|
358
|
-
const
|
|
359
|
-
if (!
|
|
360
|
-
const
|
|
446
|
+
function renderNorthCell(houseNum, rashiNum, sign, planets, isLagna) {
|
|
447
|
+
const c = NORTH_HOUSE_CENTERS[houseNum];
|
|
448
|
+
if (!c) return svg``;
|
|
449
|
+
const rashiOffsetY = Math.min(14, Math.abs(c.y - CENTRE) * 0.45 + 6);
|
|
450
|
+
const ascOffsetY = rashiOffsetY + 12;
|
|
361
451
|
return svg`
|
|
362
|
-
<g>
|
|
363
|
-
|
|
364
|
-
${
|
|
365
|
-
|
|
366
|
-
${renderPlanetStack(h.planets, center.x, center.y + 14, 11)}
|
|
452
|
+
<g class=${isLagna ? "cell lagna" : "cell"}>
|
|
453
|
+
<text class="rashi-num" x=${c.x} y=${c.y - rashiOffsetY} text-anchor="middle" dominant-baseline="central">${rashiNum}</text>
|
|
454
|
+
${isLagna ? svg`<text class="lagna-marker" x=${c.x} y=${c.y - ascOffsetY} text-anchor="middle" dominant-baseline="central">Asc</text>` : nothing}
|
|
455
|
+
${planets.length ? renderPlanetStack(planets, sign, c.x, c.y + 8, 12) : nothing}
|
|
367
456
|
</g>
|
|
368
457
|
`;
|
|
369
458
|
}
|
|
370
|
-
function
|
|
459
|
+
function renderNorthSvg(vm) {
|
|
460
|
+
const lagnaSign = vm.lagnaSign || "Aries";
|
|
371
461
|
return svg`
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
462
|
+
${renderNorthFrame(vm.divisionLabel)}
|
|
463
|
+
${Array.from({ length: 12 }, (_, i) => {
|
|
464
|
+
const houseNum = i + 1;
|
|
465
|
+
const rashiNum = rashiInHouse(houseNum, lagnaSign);
|
|
466
|
+
const sign = SIGNS_ORDER[rashiNum - 1] ?? "Aries";
|
|
467
|
+
return renderNorthCell(
|
|
468
|
+
houseNum,
|
|
469
|
+
rashiNum,
|
|
470
|
+
sign,
|
|
471
|
+
vm.placements[sign.toLowerCase()] ?? [],
|
|
472
|
+
houseNum === 1
|
|
473
|
+
);
|
|
474
|
+
})}
|
|
382
475
|
`;
|
|
383
476
|
}
|
|
384
|
-
|
|
477
|
+
var EAST_CELL = INNER / 3;
|
|
478
|
+
function eastCells() {
|
|
479
|
+
const a = MARGIN;
|
|
480
|
+
const b = MARGIN + EAST_CELL;
|
|
481
|
+
const c = MARGIN + 2 * EAST_CELL;
|
|
482
|
+
const d = VIEW_BOX - MARGIN;
|
|
483
|
+
const aries = [
|
|
484
|
+
{ x: b, y: a },
|
|
485
|
+
{ x: c, y: a },
|
|
486
|
+
{ x: c, y: b },
|
|
487
|
+
{ x: b, y: b }
|
|
488
|
+
];
|
|
489
|
+
const cancer = [
|
|
490
|
+
{ x: a, y: b },
|
|
491
|
+
{ x: b, y: b },
|
|
492
|
+
{ x: b, y: c },
|
|
493
|
+
{ x: a, y: c }
|
|
494
|
+
];
|
|
495
|
+
const libra = [
|
|
496
|
+
{ x: b, y: c },
|
|
497
|
+
{ x: c, y: c },
|
|
498
|
+
{ x: c, y: d },
|
|
499
|
+
{ x: b, y: d }
|
|
500
|
+
];
|
|
501
|
+
const capricorn = [
|
|
502
|
+
{ x: c, y: b },
|
|
503
|
+
{ x: d, y: b },
|
|
504
|
+
{ x: d, y: c },
|
|
505
|
+
{ x: c, y: c }
|
|
506
|
+
];
|
|
507
|
+
const taurus = [
|
|
508
|
+
{ x: a, y: a },
|
|
509
|
+
{ x: b, y: a },
|
|
510
|
+
{ x: b, y: b }
|
|
511
|
+
];
|
|
512
|
+
const gemini = [
|
|
513
|
+
{ x: a, y: a },
|
|
514
|
+
{ x: b, y: b },
|
|
515
|
+
{ x: a, y: b }
|
|
516
|
+
];
|
|
517
|
+
const leo = [
|
|
518
|
+
{ x: a, y: c },
|
|
519
|
+
{ x: b, y: c },
|
|
520
|
+
{ x: a, y: d }
|
|
521
|
+
];
|
|
522
|
+
const virgo = [
|
|
523
|
+
{ x: b, y: c },
|
|
524
|
+
{ x: b, y: d },
|
|
525
|
+
{ x: a, y: d }
|
|
526
|
+
];
|
|
527
|
+
const scorpio = [
|
|
528
|
+
{ x: c, y: c },
|
|
529
|
+
{ x: c, y: d },
|
|
530
|
+
{ x: d, y: d }
|
|
531
|
+
];
|
|
532
|
+
const sagittarius = [
|
|
533
|
+
{ x: c, y: c },
|
|
534
|
+
{ x: d, y: d },
|
|
535
|
+
{ x: d, y: c }
|
|
536
|
+
];
|
|
537
|
+
const aquarius = [
|
|
538
|
+
{ x: d, y: a },
|
|
539
|
+
{ x: d, y: b },
|
|
540
|
+
{ x: c, y: b }
|
|
541
|
+
];
|
|
542
|
+
const pisces = [
|
|
543
|
+
{ x: c, y: a },
|
|
544
|
+
{ x: d, y: a },
|
|
545
|
+
{ x: c, y: b }
|
|
546
|
+
];
|
|
547
|
+
const polys = {
|
|
548
|
+
Aries: aries,
|
|
549
|
+
Taurus: taurus,
|
|
550
|
+
Gemini: gemini,
|
|
551
|
+
Cancer: cancer,
|
|
552
|
+
Leo: leo,
|
|
553
|
+
Virgo: virgo,
|
|
554
|
+
Libra: libra,
|
|
555
|
+
Scorpio: scorpio,
|
|
556
|
+
Sagittarius: sagittarius,
|
|
557
|
+
Capricorn: capricorn,
|
|
558
|
+
Aquarius: aquarius,
|
|
559
|
+
Pisces: pisces
|
|
560
|
+
};
|
|
561
|
+
const out = {};
|
|
562
|
+
for (const [sign, points] of Object.entries(polys)) {
|
|
563
|
+
out[sign] = { points: [...points], centroid: centroidOf(points) };
|
|
564
|
+
}
|
|
565
|
+
return out;
|
|
566
|
+
}
|
|
567
|
+
var EAST_CELLS = eastCells();
|
|
568
|
+
function renderEastFrame(divisionLabel) {
|
|
569
|
+
const a = MARGIN;
|
|
570
|
+
const b = MARGIN + EAST_CELL;
|
|
571
|
+
const c = MARGIN + 2 * EAST_CELL;
|
|
572
|
+
const d = VIEW_BOX - MARGIN;
|
|
385
573
|
return svg`
|
|
386
|
-
<rect class="line" x
|
|
387
|
-
<line class="line" x1
|
|
388
|
-
<line class="line" x1
|
|
389
|
-
<
|
|
574
|
+
<rect class="line" x=${a} y=${a} width=${INNER} height=${INNER} stroke-width="1.5" fill="none" />
|
|
575
|
+
<line class="line" x1=${a} y1=${b} x2=${b} y2=${b} stroke-width="1" />
|
|
576
|
+
<line class="line" x1=${c} y1=${b} x2=${d} y2=${b} stroke-width="1" />
|
|
577
|
+
<line class="line" x1=${a} y1=${c} x2=${b} y2=${c} stroke-width="1" />
|
|
578
|
+
<line class="line" x1=${c} y1=${c} x2=${d} y2=${c} stroke-width="1" />
|
|
579
|
+
<line class="line" x1=${b} y1=${a} x2=${b} y2=${b} stroke-width="1" />
|
|
580
|
+
<line class="line" x1=${b} y1=${c} x2=${b} y2=${d} stroke-width="1" />
|
|
581
|
+
<line class="line" x1=${c} y1=${a} x2=${c} y2=${b} stroke-width="1" />
|
|
582
|
+
<line class="line" x1=${c} y1=${c} x2=${c} y2=${d} stroke-width="1" />
|
|
583
|
+
<line class="line" x1=${a} y1=${a} x2=${b} y2=${b} stroke-width="1" />
|
|
584
|
+
<line class="line" x1=${d} y1=${a} x2=${c} y2=${b} stroke-width="1" />
|
|
585
|
+
<line class="line" x1=${d} y1=${d} x2=${c} y2=${c} stroke-width="1" />
|
|
586
|
+
<line class="line" x1=${a} y1=${d} x2=${b} y2=${c} stroke-width="1" />
|
|
587
|
+
${divisionLabel ? svg`<text class="centre-label" x=${CENTRE} y=${CENTRE} text-anchor="middle" dominant-baseline="central">${divisionLabel}</text>` : nothing}
|
|
390
588
|
`;
|
|
391
589
|
}
|
|
392
|
-
function
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const signAbbr = SIGN_ABBR[
|
|
590
|
+
function renderEastCell(sign, planets, isLagna, houseNum) {
|
|
591
|
+
const cell = EAST_CELLS[sign];
|
|
592
|
+
if (!cell) return svg``;
|
|
593
|
+
const { centroid: cen, points } = cell;
|
|
594
|
+
const signAbbr = SIGN_ABBR[sign] ?? sign.slice(0, 2);
|
|
595
|
+
const polyPoints = points.map((p) => `${p.x},${p.y}`).join(" ");
|
|
397
596
|
return svg`
|
|
398
|
-
<g>
|
|
399
|
-
${
|
|
400
|
-
|
|
401
|
-
${
|
|
402
|
-
${
|
|
597
|
+
<g class=${isLagna ? "cell lagna" : "cell"}>
|
|
598
|
+
${isLagna ? svg`<polygon class="lagna-bg" points=${polyPoints} />` : nothing}
|
|
599
|
+
<text class="sign-text" x=${cen.x} y=${cen.y - 16} text-anchor="middle" dominant-baseline="central">${signAbbr}</text>
|
|
600
|
+
${houseNum > 0 ? svg`<text class="house-num" x=${cen.x + 18} y=${cen.y - 16} text-anchor="start" dominant-baseline="central">${houseNum}</text>` : nothing}
|
|
601
|
+
${isLagna ? svg`<text class="lagna-marker" x=${cen.x} y=${cen.y - 30} text-anchor="middle" dominant-baseline="central">Asc</text>` : nothing}
|
|
602
|
+
${planets.length ? renderPlanetStack(planets, sign, cen.x, cen.y + 4, 12) : nothing}
|
|
403
603
|
</g>
|
|
404
604
|
`;
|
|
405
605
|
}
|
|
406
|
-
function
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
lagnaKey = rashiKey;
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
if (!rashiKey) continue;
|
|
416
|
-
const list = byRashi.get(rashiKey) ?? [];
|
|
417
|
-
list.push({
|
|
418
|
-
graha: pos.graha ?? name,
|
|
419
|
-
longitude: pos.longitude,
|
|
420
|
-
nakshatra: pos.nakshatra,
|
|
421
|
-
isRetrograde: pos.isRetrograde,
|
|
422
|
-
awastha: pos.awastha
|
|
423
|
-
});
|
|
424
|
-
byRashi.set(rashiKey, list);
|
|
425
|
-
}
|
|
426
|
-
return SIGNS_ORDER.map((sign, i) => {
|
|
427
|
-
const key = sign.toLowerCase();
|
|
428
|
-
return {
|
|
429
|
-
number: i + 1,
|
|
606
|
+
function renderEastSvg(vm) {
|
|
607
|
+
const lagnaKey = vm.lagnaSign.toLowerCase();
|
|
608
|
+
return svg`
|
|
609
|
+
${renderEastFrame(vm.divisionLabel)}
|
|
610
|
+
${SIGNS_ORDER.map(
|
|
611
|
+
(sign) => renderEastCell(
|
|
430
612
|
sign,
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
613
|
+
vm.placements[sign.toLowerCase()] ?? [],
|
|
614
|
+
sign.toLowerCase() === lagnaKey,
|
|
615
|
+
houseNumberInSign(sign, vm.lagnaSign)
|
|
616
|
+
)
|
|
617
|
+
)}
|
|
618
|
+
`;
|
|
435
619
|
}
|
|
620
|
+
function renderKundliSvg(vm, style) {
|
|
621
|
+
switch (style) {
|
|
622
|
+
case "north":
|
|
623
|
+
return renderNorthSvg(vm);
|
|
624
|
+
case "east":
|
|
625
|
+
return renderEastSvg(vm);
|
|
626
|
+
default:
|
|
627
|
+
return renderSouthSvg(vm);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
function renderKundliStyleTablist(active, setStyle) {
|
|
631
|
+
const onKeyDown = (e) => {
|
|
632
|
+
const idx = CHART_STYLES.findIndex((s) => s.id === active);
|
|
633
|
+
if (e.key === "ArrowRight") {
|
|
634
|
+
e.preventDefault();
|
|
635
|
+
const next = CHART_STYLES[(idx + 1) % CHART_STYLES.length];
|
|
636
|
+
if (next) setStyle(next.id);
|
|
637
|
+
} else if (e.key === "ArrowLeft") {
|
|
638
|
+
e.preventDefault();
|
|
639
|
+
const next = CHART_STYLES[(idx - 1 + CHART_STYLES.length) % CHART_STYLES.length];
|
|
640
|
+
if (next) setStyle(next.id);
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
return html`<div
|
|
644
|
+
class="kundli-tablist"
|
|
645
|
+
role="tablist"
|
|
646
|
+
aria-label="Kundli style"
|
|
647
|
+
@keydown=${onKeyDown}
|
|
648
|
+
>
|
|
649
|
+
${CHART_STYLES.map(
|
|
650
|
+
(s) => html`<button
|
|
651
|
+
type="button"
|
|
652
|
+
class="kundli-tab"
|
|
653
|
+
role="tab"
|
|
654
|
+
id="kundli-tab-${s.id}"
|
|
655
|
+
aria-selected=${active === s.id ? "true" : "false"}
|
|
656
|
+
tabindex=${active === s.id ? "0" : "-1"}
|
|
657
|
+
@click=${() => setStyle(s.id)}
|
|
658
|
+
>
|
|
659
|
+
${s.label}
|
|
660
|
+
</button>`
|
|
661
|
+
)}
|
|
662
|
+
</div>`;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// packages/ui/src/utils/kundli-styles.ts
|
|
666
|
+
import { css as css2 } from "lit";
|
|
667
|
+
var kundliStyles = css2`
|
|
668
|
+
.wrap {
|
|
669
|
+
display: grid;
|
|
670
|
+
gap: var(--roxy-space-md, 1rem);
|
|
671
|
+
}
|
|
672
|
+
.header {
|
|
673
|
+
display: flex;
|
|
674
|
+
flex-wrap: wrap;
|
|
675
|
+
align-items: center;
|
|
676
|
+
justify-content: space-between;
|
|
677
|
+
gap: var(--roxy-space-sm, 0.5rem);
|
|
678
|
+
}
|
|
679
|
+
.title {
|
|
680
|
+
font-size: var(--roxy-text-lg, 1.125rem);
|
|
681
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
682
|
+
margin: 0;
|
|
683
|
+
}
|
|
684
|
+
.kundli-tablist {
|
|
685
|
+
display: inline-flex;
|
|
686
|
+
gap: 2px;
|
|
687
|
+
border-bottom: 2px solid var(--roxy-border, #e4e4e7);
|
|
688
|
+
}
|
|
689
|
+
.kundli-tab {
|
|
690
|
+
padding: var(--roxy-space-xs, 0.25rem) var(--roxy-space-md, 1rem);
|
|
691
|
+
font-size: var(--roxy-text-sm, 0.875rem);
|
|
692
|
+
background: none;
|
|
693
|
+
border: none;
|
|
694
|
+
border-bottom: 2px solid transparent;
|
|
695
|
+
margin-bottom: -2px;
|
|
696
|
+
cursor: pointer;
|
|
697
|
+
color: var(--roxy-muted, #71717a);
|
|
698
|
+
font-family: inherit;
|
|
699
|
+
transition: color var(--roxy-motion-duration, 200ms)
|
|
700
|
+
var(--roxy-motion-easing, ease);
|
|
701
|
+
}
|
|
702
|
+
.kundli-tab[aria-selected='true'] {
|
|
703
|
+
color: var(--roxy-accent-fg, #b45309);
|
|
704
|
+
border-bottom-color: var(--roxy-accent, #f59e0b);
|
|
705
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
706
|
+
}
|
|
707
|
+
.kundli-tab:hover:not([aria-selected='true']) {
|
|
708
|
+
color: var(--roxy-fg, #0a0a0a);
|
|
709
|
+
}
|
|
710
|
+
.kundli-tab:focus-visible {
|
|
711
|
+
outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
|
|
712
|
+
outline-offset: 2px;
|
|
713
|
+
border-radius: 4px;
|
|
714
|
+
}
|
|
715
|
+
svg {
|
|
716
|
+
display: block;
|
|
717
|
+
width: 100%;
|
|
718
|
+
max-width: 560px;
|
|
719
|
+
aspect-ratio: 1 / 1;
|
|
720
|
+
height: auto;
|
|
721
|
+
margin: 0 auto;
|
|
722
|
+
}
|
|
723
|
+
.line {
|
|
724
|
+
fill: transparent;
|
|
725
|
+
stroke: var(--roxy-border, #d4d4d8);
|
|
726
|
+
}
|
|
727
|
+
.sign-text {
|
|
728
|
+
fill: var(--roxy-muted, #71717a);
|
|
729
|
+
font-size: 11px;
|
|
730
|
+
font-weight: 500;
|
|
731
|
+
font-family: var(--roxy-font-sans);
|
|
732
|
+
text-transform: uppercase;
|
|
733
|
+
letter-spacing: 0.04em;
|
|
734
|
+
}
|
|
735
|
+
.rashi-num {
|
|
736
|
+
fill: var(--roxy-muted, #71717a);
|
|
737
|
+
font-size: 12px;
|
|
738
|
+
font-weight: 500;
|
|
739
|
+
font-family: var(--roxy-font-sans);
|
|
740
|
+
}
|
|
741
|
+
.house-num {
|
|
742
|
+
fill: var(--roxy-accent-fg, #b45309);
|
|
743
|
+
font-size: 11px;
|
|
744
|
+
font-weight: 600;
|
|
745
|
+
font-family: var(--roxy-font-sans);
|
|
746
|
+
opacity: 0.85;
|
|
747
|
+
}
|
|
748
|
+
.planet-text {
|
|
749
|
+
fill: var(--roxy-fg, #0a0a0a);
|
|
750
|
+
font-size: 13px;
|
|
751
|
+
font-weight: 600;
|
|
752
|
+
font-family: var(--roxy-font-sans);
|
|
753
|
+
}
|
|
754
|
+
.centre-label {
|
|
755
|
+
fill: var(--roxy-muted, #71717a);
|
|
756
|
+
font-size: 14px;
|
|
757
|
+
font-weight: 600;
|
|
758
|
+
font-family: var(--roxy-font-sans);
|
|
759
|
+
letter-spacing: 0.02em;
|
|
760
|
+
}
|
|
761
|
+
.lagna-marker {
|
|
762
|
+
fill: var(--roxy-accent-fg, #b45309);
|
|
763
|
+
font-size: 10px;
|
|
764
|
+
font-weight: 700;
|
|
765
|
+
font-family: var(--roxy-font-sans);
|
|
766
|
+
letter-spacing: 0.08em;
|
|
767
|
+
text-transform: uppercase;
|
|
768
|
+
}
|
|
769
|
+
.lagna-bg {
|
|
770
|
+
fill: color-mix(in srgb, var(--roxy-accent, #f59e0b) 14%, transparent);
|
|
771
|
+
}
|
|
772
|
+
.lagna-slash {
|
|
773
|
+
stroke: var(--roxy-accent, #f59e0b);
|
|
774
|
+
stroke-linecap: round;
|
|
775
|
+
opacity: 0.7;
|
|
776
|
+
}
|
|
777
|
+
`;
|
|
436
778
|
|
|
437
779
|
// packages/ui/src/components/divisional-chart.ts
|
|
438
780
|
var RoxyDivisionalChart = class extends LitElement {
|
|
439
781
|
constructor() {
|
|
440
782
|
super(...arguments);
|
|
441
783
|
this.data = null;
|
|
442
|
-
this.chartStyle = "
|
|
784
|
+
this.chartStyle = "north";
|
|
785
|
+
this.setStyle = (next) => {
|
|
786
|
+
this.chartStyle = next;
|
|
787
|
+
};
|
|
443
788
|
}
|
|
444
|
-
|
|
445
|
-
if (!this.data?.chart?.meta) return
|
|
446
|
-
|
|
789
|
+
viewModel() {
|
|
790
|
+
if (!this.data?.chart?.meta) return null;
|
|
791
|
+
const { division } = this.data;
|
|
792
|
+
const label = `D${division.number} ${division.name}`;
|
|
793
|
+
return toKundliViewModel(this.data.chart.meta, label);
|
|
447
794
|
}
|
|
448
795
|
render() {
|
|
449
|
-
|
|
450
|
-
|
|
796
|
+
const vm = this.viewModel();
|
|
797
|
+
if (!this.data || !vm)
|
|
798
|
+
return html2`<div class="roxy-empty" role="status">No divisional chart data</div>`;
|
|
451
799
|
const { division, vargottama } = this.data;
|
|
452
|
-
|
|
453
|
-
const style = this.chartStyle;
|
|
454
|
-
const frame = style === "north" ? renderNorthFrame() : style === "east" ? renderEastFrame() : renderSouthFrame();
|
|
455
|
-
const houseGroup = style === "north" ? renderNorthHouseGroup : style === "east" ? renderEastHouseGroup : renderSouthHouseGroup;
|
|
456
|
-
return html`<div class="wrap">
|
|
800
|
+
return html2`<div class="wrap">
|
|
457
801
|
<div class="header">
|
|
458
|
-
<
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
802
|
+
<div>
|
|
803
|
+
<h2 class="title">
|
|
804
|
+
D${division.number} ${division.name}
|
|
805
|
+
${division.sanskritName && division.sanskritName !== division.name ? html2`<span class="division-meta"> · ${division.sanskritName}</span>` : nothing2}
|
|
806
|
+
</h2>
|
|
807
|
+
${division.significance ? html2`<p class="significance">${division.significance}</p>` : nothing2}
|
|
808
|
+
</div>
|
|
809
|
+
${renderKundliStyleTablist(this.chartStyle, this.setStyle)}
|
|
463
810
|
</div>
|
|
464
811
|
|
|
465
812
|
<svg
|
|
466
|
-
viewBox="0 0
|
|
813
|
+
viewBox="0 0 400 400"
|
|
814
|
+
preserveAspectRatio="xMidYMid meet"
|
|
467
815
|
role="img"
|
|
468
816
|
aria-label="D${division.number} ${division.name} divisional chart with twelve sign houses"
|
|
469
817
|
>
|
|
470
818
|
<title>D${division.number} ${division.name}</title>
|
|
471
|
-
${
|
|
472
|
-
${houses.map((h) => houseGroup(h))}
|
|
819
|
+
${renderKundliSvg(vm, this.chartStyle)}
|
|
473
820
|
</svg>
|
|
474
821
|
|
|
475
|
-
${vargottama && vargottama.length > 0 ?
|
|
822
|
+
${vargottama && vargottama.length > 0 ? html2`<div class="vargottama-row" role="list" aria-label="Vargottama planets">
|
|
476
823
|
<span class="vargottama-label">Vargottama:</span>
|
|
477
824
|
${vargottama.map(
|
|
478
|
-
(planet) =>
|
|
825
|
+
(planet) => html2`<span class="vargottama-pill" role="listitem">
|
|
479
826
|
${PLANET_GLYPH[planet] ?? ""} ${planet}
|
|
480
827
|
</span>`
|
|
481
828
|
)}
|
|
@@ -485,20 +832,8 @@ var RoxyDivisionalChart = class extends LitElement {
|
|
|
485
832
|
};
|
|
486
833
|
RoxyDivisionalChart.styles = [
|
|
487
834
|
baseStyles,
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
display: grid;
|
|
491
|
-
gap: var(--roxy-space-md, 1rem);
|
|
492
|
-
}
|
|
493
|
-
.header {
|
|
494
|
-
display: grid;
|
|
495
|
-
gap: var(--roxy-space-xs, 0.25rem);
|
|
496
|
-
}
|
|
497
|
-
.title {
|
|
498
|
-
font-size: var(--roxy-text-lg, 1.125rem);
|
|
499
|
-
font-weight: var(--roxy-weight-bold, 600);
|
|
500
|
-
margin: 0;
|
|
501
|
-
}
|
|
835
|
+
kundliStyles,
|
|
836
|
+
css3`
|
|
502
837
|
.division-meta {
|
|
503
838
|
font-size: var(--roxy-text-sm, 0.875rem);
|
|
504
839
|
color: var(--roxy-muted, #71717a);
|
|
@@ -511,46 +846,6 @@ RoxyDivisionalChart.styles = [
|
|
|
511
846
|
padding-left: var(--roxy-space-sm, 0.5rem);
|
|
512
847
|
margin: 0;
|
|
513
848
|
}
|
|
514
|
-
svg {
|
|
515
|
-
display: block;
|
|
516
|
-
width: 100%;
|
|
517
|
-
max-width: 360px;
|
|
518
|
-
margin: 0 auto;
|
|
519
|
-
}
|
|
520
|
-
.line {
|
|
521
|
-
fill: transparent;
|
|
522
|
-
stroke: var(--roxy-border, #e4e4e7);
|
|
523
|
-
}
|
|
524
|
-
.sign-text {
|
|
525
|
-
fill: var(--roxy-muted, #71717a);
|
|
526
|
-
font-size: 9px;
|
|
527
|
-
font-weight: 500;
|
|
528
|
-
font-family: var(--roxy-font-sans);
|
|
529
|
-
}
|
|
530
|
-
.planet-text {
|
|
531
|
-
fill: var(--roxy-fg, #0a0a0a);
|
|
532
|
-
font-size: 11px;
|
|
533
|
-
font-weight: 600;
|
|
534
|
-
font-family: var(--roxy-font-sans);
|
|
535
|
-
}
|
|
536
|
-
.house-num {
|
|
537
|
-
fill: var(--roxy-muted, #71717a);
|
|
538
|
-
font-size: 9px;
|
|
539
|
-
font-weight: 400;
|
|
540
|
-
font-family: var(--roxy-font-sans);
|
|
541
|
-
}
|
|
542
|
-
.lagna-marker {
|
|
543
|
-
fill: var(--roxy-accent-fg, #b45309);
|
|
544
|
-
font-size: 8px;
|
|
545
|
-
font-weight: 700;
|
|
546
|
-
font-family: var(--roxy-font-sans);
|
|
547
|
-
letter-spacing: 0.05em;
|
|
548
|
-
}
|
|
549
|
-
.lagna-bg {
|
|
550
|
-
fill: color-mix(in srgb, var(--roxy-accent, #f59e0b) 12%, transparent);
|
|
551
|
-
stroke: color-mix(in srgb, var(--roxy-accent, #f59e0b) 45%, transparent);
|
|
552
|
-
stroke-width: 0.8;
|
|
553
|
-
}
|
|
554
849
|
.vargottama-row {
|
|
555
850
|
display: flex;
|
|
556
851
|
flex-wrap: wrap;
|