@roxyapi/ui 0.2.3 → 0.3.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.
Files changed (119) hide show
  1. package/AGENTS.md +15 -10
  2. package/README.md +15 -10
  3. package/dist/cdn/components/compatibility-card.js.map +1 -1
  4. package/dist/cdn/components/dasha-timeline.js +8 -8
  5. package/dist/cdn/components/dasha-timeline.js.map +2 -2
  6. package/dist/cdn/components/divisional-chart.js +35 -23
  7. package/dist/cdn/components/divisional-chart.js.map +4 -4
  8. package/dist/cdn/components/guna-milan.js.map +1 -1
  9. package/dist/cdn/components/kp-chart.js +306 -0
  10. package/dist/cdn/components/kp-chart.js.map +7 -0
  11. package/dist/cdn/components/kp-planets-table.js.map +1 -1
  12. package/dist/cdn/components/kp-ruling-planets.js +269 -0
  13. package/dist/cdn/components/kp-ruling-planets.js.map +7 -0
  14. package/dist/cdn/components/location-search.js +7 -5
  15. package/dist/cdn/components/location-search.js.map +3 -3
  16. package/dist/cdn/components/moon-phase.js.map +1 -1
  17. package/dist/cdn/components/nakshatra-card.js +229 -0
  18. package/dist/cdn/components/nakshatra-card.js.map +7 -0
  19. package/dist/cdn/components/natal-chart.js +228 -115
  20. package/dist/cdn/components/natal-chart.js.map +4 -4
  21. package/dist/cdn/components/numerology-card.js +3 -3
  22. package/dist/cdn/components/numerology-card.js.map +2 -2
  23. package/dist/cdn/components/panchang-table.js.map +1 -1
  24. package/dist/cdn/components/shadbala-table.js.map +1 -1
  25. package/dist/cdn/components/synastry-chart.js +3 -3
  26. package/dist/cdn/components/synastry-chart.js.map +2 -2
  27. package/dist/cdn/components/transits-table.js.map +1 -1
  28. package/dist/cdn/components/vedic-kundli.js +34 -22
  29. package/dist/cdn/components/vedic-kundli.js.map +4 -4
  30. package/dist/cdn/components/vedic-planets-table.js +231 -0
  31. package/dist/cdn/components/vedic-planets-table.js.map +7 -0
  32. package/dist/cdn/components/western-planets-table.js +220 -0
  33. package/dist/cdn/components/western-planets-table.js.map +7 -0
  34. package/dist/cdn/roxy-ui.js +1078 -331
  35. package/dist/cdn/roxy-ui.js.map +4 -4
  36. package/dist/components/compatibility-card.js.map +1 -1
  37. package/dist/components/dasha-timeline.d.ts.map +1 -1
  38. package/dist/components/dasha-timeline.js.map +2 -2
  39. package/dist/components/divisional-chart.d.ts +5 -3
  40. package/dist/components/divisional-chart.d.ts.map +1 -1
  41. package/dist/components/divisional-chart.js +159 -38
  42. package/dist/components/divisional-chart.js.map +3 -3
  43. package/dist/components/guna-milan.js.map +1 -1
  44. package/dist/components/kp-chart.d.ts +26 -0
  45. package/dist/components/kp-chart.d.ts.map +1 -0
  46. package/dist/components/kp-chart.js +382 -0
  47. package/dist/components/kp-chart.js.map +7 -0
  48. package/dist/components/kp-planets-table.js.map +1 -1
  49. package/dist/components/kp-ruling-planets.d.ts +20 -0
  50. package/dist/components/kp-ruling-planets.d.ts.map +1 -0
  51. package/dist/components/kp-ruling-planets.js +275 -0
  52. package/dist/components/kp-ruling-planets.js.map +7 -0
  53. package/dist/components/location-search.d.ts.map +1 -1
  54. package/dist/components/location-search.js +9 -2
  55. package/dist/components/location-search.js.map +2 -2
  56. package/dist/components/moon-phase.js.map +1 -1
  57. package/dist/components/nakshatra-card.d.ts +18 -0
  58. package/dist/components/nakshatra-card.d.ts.map +1 -0
  59. package/dist/components/nakshatra-card.js +231 -0
  60. package/dist/components/nakshatra-card.js.map +7 -0
  61. package/dist/components/natal-chart.d.ts +28 -0
  62. package/dist/components/natal-chart.d.ts.map +1 -1
  63. package/dist/components/natal-chart.js +401 -104
  64. package/dist/components/natal-chart.js.map +2 -2
  65. package/dist/components/numerology-card.d.ts.map +1 -1
  66. package/dist/components/numerology-card.js.map +2 -2
  67. package/dist/components/panchang-table.js.map +1 -1
  68. package/dist/components/shadbala-table.js.map +1 -1
  69. package/dist/components/synastry-chart.js.map +2 -2
  70. package/dist/components/transits-table.js.map +1 -1
  71. package/dist/components/vedic-kundli.d.ts +7 -3
  72. package/dist/components/vedic-kundli.d.ts.map +1 -1
  73. package/dist/components/vedic-kundli.js +209 -87
  74. package/dist/components/vedic-kundli.js.map +3 -3
  75. package/dist/components/vedic-planets-table.d.ts +21 -0
  76. package/dist/components/vedic-planets-table.d.ts.map +1 -0
  77. package/dist/components/vedic-planets-table.js +355 -0
  78. package/dist/components/vedic-planets-table.js.map +7 -0
  79. package/dist/components/western-planets-table.d.ts +21 -0
  80. package/dist/components/western-planets-table.d.ts.map +1 -0
  81. package/dist/components/western-planets-table.js +350 -0
  82. package/dist/components/western-planets-table.js.map +7 -0
  83. package/dist/index.cjs +2042 -695
  84. package/dist/index.cjs.map +4 -4
  85. package/dist/index.d.ts +5 -0
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +2029 -682
  88. package/dist/index.js.map +4 -4
  89. package/dist/manifest.d.ts.map +1 -1
  90. package/dist/manifest.json +23 -18
  91. package/dist/styles/tokens.css +4 -0
  92. package/dist/types/types.gen.d.ts +343 -49
  93. package/dist/types/types.gen.d.ts.map +1 -1
  94. package/dist/utils/degree.d.ts +12 -0
  95. package/dist/utils/degree.d.ts.map +1 -1
  96. package/dist/utils/format.d.ts +1 -1
  97. package/dist/utils/kundli-render.d.ts +85 -12
  98. package/dist/utils/kundli-render.d.ts.map +1 -1
  99. package/dist/version.d.ts +1 -1
  100. package/package.json +1 -1
  101. package/src/components/dasha-timeline.ts +1 -7
  102. package/src/components/divisional-chart.ts +27 -41
  103. package/src/components/kp-chart.ts +313 -0
  104. package/src/components/kp-ruling-planets.ts +196 -0
  105. package/src/components/location-search.ts +16 -2
  106. package/src/components/nakshatra-card.ts +149 -0
  107. package/src/components/natal-chart.ts +408 -119
  108. package/src/components/numerology-card.ts +1 -5
  109. package/src/components/vedic-kundli.ts +30 -40
  110. package/src/components/vedic-planets-table.ts +184 -0
  111. package/src/components/western-planets-table.ts +180 -0
  112. package/src/index.ts +5 -0
  113. package/src/manifest.ts +146 -84
  114. package/src/styles/tokens.css +4 -0
  115. package/src/types/types.gen.ts +343 -49
  116. package/src/utils/degree.ts +21 -0
  117. package/src/utils/format.ts +1 -1
  118. package/src/utils/kundli-render.ts +234 -29
  119. package/src/version.ts +1 -1
@@ -1,27 +1,25 @@
1
1
  import { css, html, LitElement } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
- import { RASHI_KEYS } from '../tokens/index.js';
4
3
  import type { BirthChartResponse } from '../types/index.js';
5
4
  import { baseStyles } from '../utils/base-styles.js';
6
- import type { HouseDef } from '../utils/kundli-render.js';
7
5
  import {
8
- RASHI_TO_SIGN,
6
+ buildHousesFromMeta,
7
+ type HouseDef,
8
+ renderEastFrame,
9
+ renderEastHouseGroup,
9
10
  renderNorthFrame,
10
11
  renderNorthHouseGroup,
11
12
  renderSouthFrame,
12
13
  renderSouthHouseGroup,
13
14
  } from '../utils/kundli-render.js';
14
15
 
15
- type RashiBucket = BirthChartResponse['aries'];
16
-
17
- // The /vedic-astrology/birth-chart response carries all 12 rashi keys
18
- // (aries, taurus, ..., pisces), each shaped like the spec-typed `aries`
19
- // bucket. This local alias indexes by rashi name without per-call casts.
20
- type BirthChartByRashi = BirthChartResponse & Record<string, RashiBucket>;
21
-
22
16
  /**
23
- * Vedic kundli (D1 Rashi chart). South Indian style by default. Pass `data`
24
- * from /vedic-astrology/birth-chart. North Indian style via chartStyle="north".
17
+ * Vedic kundli (D1 Rashi chart). Pass `data` from /vedic-astrology/birth-chart.
18
+ * Three render styles via the `chart-style` attribute: south (default),
19
+ * north, and east. All three draw the identical planet-in-sign data, so the
20
+ * style is purely a layout choice. Each planet shows its abbreviation and
21
+ * whole-degree, with an SVG tooltip carrying exact position, nakshatra, pada,
22
+ * and avastha.
25
23
  *
26
24
  * Theming flows through CSS custom properties on :host, so the chart adopts
27
25
  * the host page palette without runtime color probing.
@@ -58,7 +56,7 @@ export class RoxyVedicKundli extends LitElement {
58
56
  }
59
57
  .planet-text {
60
58
  fill: var(--roxy-fg, #0a0a0a);
61
- font-size: 11px;
59
+ font-size: 10px;
62
60
  font-weight: 600;
63
61
  font-family: var(--roxy-font-sans);
64
62
  }
@@ -87,35 +85,31 @@ export class RoxyVedicKundli extends LitElement {
87
85
  data: BirthChartResponse | null = null;
88
86
 
89
87
  @property({ type: String, reflect: true, attribute: 'chart-style' })
90
- chartStyle: 'south' | 'north' = 'south';
88
+ chartStyle: 'south' | 'north' | 'east' = 'south';
91
89
 
92
90
  private buildHouses(): HouseDef[] {
93
- if (!this.data) return [];
94
- const data = this.data as BirthChartByRashi;
95
- const lagnaSign = this.data?.meta?.Lagna?.rashi ?? '';
96
- const houses: HouseDef[] = [];
97
- for (let i = 0; i < 12; i++) {
98
- const key = RASHI_KEYS[i];
99
- const bucket = data[key];
100
- const planets = (bucket?.signs ?? []).map((p) => p.graha).filter(Boolean);
101
- const sign = RASHI_TO_SIGN[key] ?? '';
102
- houses.push({
103
- number: i + 1,
104
- sign,
105
- planets,
106
- isLagna: lagnaSign
107
- ? lagnaSign.toLowerCase() === sign.toLowerCase()
108
- : false,
109
- });
110
- }
111
- return houses;
91
+ if (!this.data?.meta) return [];
92
+ return buildHousesFromMeta(this.data.meta);
112
93
  }
113
94
 
114
95
  render() {
115
96
  if (!this.data)
116
97
  return html`<div class="roxy-empty" role="status">No kundli data</div>`;
117
98
  const houses = this.buildHouses();
118
- const isNorth = this.chartStyle === 'north';
99
+ const style = this.chartStyle;
100
+
101
+ const frame =
102
+ style === 'north'
103
+ ? renderNorthFrame()
104
+ : style === 'east'
105
+ ? renderEastFrame()
106
+ : renderSouthFrame();
107
+ const houseGroup =
108
+ style === 'north'
109
+ ? renderNorthHouseGroup
110
+ : style === 'east'
111
+ ? renderEastHouseGroup
112
+ : renderSouthHouseGroup;
119
113
 
120
114
  return html`<div class="wrap">
121
115
  <h2 class="title">Vedic kundli</h2>
@@ -125,12 +119,8 @@ export class RoxyVedicKundli extends LitElement {
125
119
  aria-label="Vedic birth chart with twelve sign houses"
126
120
  >
127
121
  <title>Vedic kundli</title>
128
- ${isNorth ? renderNorthFrame() : renderSouthFrame()}
129
- ${
130
- isNorth
131
- ? houses.map((h) => renderNorthHouseGroup(h))
132
- : houses.map((h) => renderSouthHouseGroup(h))
133
- }
122
+ ${frame}
123
+ ${houses.map((h) => houseGroup(h))}
134
124
  </svg>
135
125
  </div>`;
136
126
  }
@@ -0,0 +1,184 @@
1
+ import { css, html, LitElement, nothing } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+ import { PLANET_GLYPH, SIGN_GLYPH } from '../tokens/index.js';
4
+ import type { BirthChartResponse } from '../types/index.js';
5
+ import { baseStyles } from '../utils/base-styles.js';
6
+ import { formatSignPosition } from '../utils/degree.js';
7
+ import { capitalize } from '../utils/string.js';
8
+
9
+ /**
10
+ * Fixed display order: Lagna pinned first as the chart frame, then the nine
11
+ * grahas in classical sequence. Any graha not in this list is appended.
12
+ */
13
+ const GRAHA_ORDER = [
14
+ 'Lagna',
15
+ 'Sun',
16
+ 'Moon',
17
+ 'Mars',
18
+ 'Mercury',
19
+ 'Jupiter',
20
+ 'Venus',
21
+ 'Saturn',
22
+ 'Rahu',
23
+ 'Ketu',
24
+ ];
25
+
26
+ type MetaEntry = BirthChartResponse['meta'][string];
27
+
28
+ /**
29
+ * Vedic planetary positions table. Renders /vedic-astrology/birth-chart `meta`
30
+ * as the full reference-grade positions grid a practitioner reads alongside
31
+ * the kundli wheel: graha, rashi, exact degree, nakshatra and pada, nakshatra
32
+ * lord, bhava (house), Baladi avastha, and retrograde.
33
+ */
34
+ @customElement('roxy-vedic-planets-table')
35
+ export class RoxyVedicPlanetsTable extends LitElement {
36
+ static styles = [
37
+ baseStyles,
38
+ css`
39
+ .wrap {
40
+ border: 1px solid var(--roxy-border, #e4e4e7);
41
+ border-radius: var(--roxy-radius-md, 8px);
42
+ background: var(--roxy-bg, #fff);
43
+ overflow: auto;
44
+ box-shadow: var(--roxy-shadow-sm);
45
+ }
46
+ .head {
47
+ padding: var(--roxy-space-md, 1rem);
48
+ border-bottom: 1px solid var(--roxy-border, #e4e4e7);
49
+ }
50
+ .title {
51
+ margin: 0;
52
+ font-size: var(--roxy-text-lg, 1.125rem);
53
+ font-weight: var(--roxy-weight-bold, 600);
54
+ }
55
+ table {
56
+ width: 100%;
57
+ border-collapse: collapse;
58
+ font-size: var(--roxy-text-sm, 0.875rem);
59
+ min-width: 620px;
60
+ }
61
+ thead {
62
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 20%, transparent);
63
+ }
64
+ th,
65
+ td {
66
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
67
+ text-align: left;
68
+ white-space: nowrap;
69
+ }
70
+ th {
71
+ color: var(--roxy-muted, #71717a);
72
+ font-weight: var(--roxy-weight-bold, 600);
73
+ text-transform: uppercase;
74
+ font-size: var(--roxy-text-xs, 0.75rem);
75
+ letter-spacing: 0.04em;
76
+ }
77
+ tbody tr {
78
+ border-top: 1px solid var(--roxy-border, #e4e4e7);
79
+ }
80
+ tbody tr.lagna {
81
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 10%, transparent);
82
+ }
83
+ td.graha {
84
+ font-weight: var(--roxy-weight-bold, 600);
85
+ color: var(--roxy-fg, #0a0a0a);
86
+ }
87
+ .glyph {
88
+ margin-right: 0.4em;
89
+ color: var(--roxy-muted, #71717a);
90
+ }
91
+ /* On the tinted Lagna row the muted glyph drops below the WCAG AA
92
+ contrast floor, so use the accent foreground there instead. */
93
+ tbody tr.lagna .glyph {
94
+ color: var(--roxy-accent-fg, #b45309);
95
+ }
96
+ .retro {
97
+ color: var(--roxy-warning-fg, #9a3412);
98
+ font-size: var(--roxy-text-xs, 0.75rem);
99
+ font-weight: var(--roxy-weight-bold, 600);
100
+ }
101
+ .num {
102
+ font-variant-numeric: tabular-nums;
103
+ }
104
+ `,
105
+ ];
106
+
107
+ @property({ attribute: false })
108
+ data: BirthChartResponse | null = null;
109
+
110
+ /** Ordered [name, entry] pairs: GRAHA_ORDER first, then any extras. */
111
+ private orderedRows(): Array<[string, MetaEntry]> {
112
+ const meta = this.data?.meta ?? {};
113
+ const seen = new Set<string>();
114
+ const rows: Array<[string, MetaEntry]> = [];
115
+ for (const name of GRAHA_ORDER) {
116
+ const entry = meta[name];
117
+ if (entry) {
118
+ rows.push([name, entry]);
119
+ seen.add(name);
120
+ }
121
+ }
122
+ for (const [name, entry] of Object.entries(meta)) {
123
+ if (!seen.has(name)) rows.push([name, entry]);
124
+ }
125
+ return rows;
126
+ }
127
+
128
+ render() {
129
+ if (!this.data?.meta)
130
+ return html`<div class="roxy-empty" role="status">No chart data</div>`;
131
+ const rows = this.orderedRows();
132
+
133
+ return html`<div class="wrap" aria-label="Vedic planetary positions" tabindex="0">
134
+ <header class="head">
135
+ <h2 class="title">Planetary positions</h2>
136
+ </header>
137
+ <table role="table">
138
+ <thead>
139
+ <tr>
140
+ <th scope="col">Graha</th>
141
+ <th scope="col">Rashi</th>
142
+ <th scope="col">Degree</th>
143
+ <th scope="col">Nakshatra</th>
144
+ <th scope="col">Pada</th>
145
+ <th scope="col">Nak. lord</th>
146
+ <th scope="col">House</th>
147
+ <th scope="col">Avastha</th>
148
+ <th scope="col">Retro</th>
149
+ </tr>
150
+ </thead>
151
+ <tbody>
152
+ ${rows.map(([name, p]) => {
153
+ const isLagna = (p.graha ?? name) === 'Lagna';
154
+ const glyph = PLANET_GLYPH[capitalize(p.graha ?? name)] ?? '';
155
+ const signGlyph = SIGN_GLYPH[capitalize(p.rashi ?? '')] ?? '';
156
+ return html`<tr class=${isLagna ? 'lagna' : ''}>
157
+ <td class="graha">
158
+ ${glyph ? html`<span class="glyph">${glyph}</span>` : nothing}${p.graha ?? name}
159
+ </td>
160
+ <td>
161
+ ${signGlyph ? html`<span class="glyph">${signGlyph}</span>` : nothing}${p.rashi ?? ''}
162
+ </td>
163
+ <td class="num">
164
+ ${typeof p.longitude === 'number' ? formatSignPosition(p.longitude) : ''}
165
+ </td>
166
+ <td>${p.nakshatra?.name ?? ''}</td>
167
+ <td class="num">${p.nakshatra?.pada ?? ''}</td>
168
+ <td>${p.nakshatra?.lord ?? ''}</td>
169
+ <td class="num">${typeof p.house === 'number' ? p.house : ''}</td>
170
+ <td>${p.awastha ?? ''}</td>
171
+ <td>${p.isRetrograde ? html`<span class="retro">R</span>` : nothing}</td>
172
+ </tr>`;
173
+ })}
174
+ </tbody>
175
+ </table>
176
+ </div>`;
177
+ }
178
+ }
179
+
180
+ declare global {
181
+ interface HTMLElementTagNameMap {
182
+ 'roxy-vedic-planets-table': RoxyVedicPlanetsTable;
183
+ }
184
+ }
@@ -0,0 +1,180 @@
1
+ import { css, html, LitElement, nothing } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+ import { PLANET_GLYPH, SIGN_GLYPH } from '../tokens/index.js';
4
+ import type { NatalChartResponse } from '../types/index.js';
5
+ import { baseStyles } from '../utils/base-styles.js';
6
+ import { formatSignPosition } from '../utils/degree.js';
7
+ import { formatNumber } from '../utils/format.js';
8
+ import { capitalize } from '../utils/string.js';
9
+
10
+ /** A body or point row, normalized so planets and the four angles share a table. */
11
+ interface BodyRow {
12
+ name: string;
13
+ sign?: string;
14
+ longitude?: number;
15
+ house?: number;
16
+ speed?: number;
17
+ isRetrograde?: boolean;
18
+ /** True for the chart angles (ASC, MC, Part of Fortune, Vertex). */
19
+ isPoint?: boolean;
20
+ }
21
+
22
+ /**
23
+ * Western planetary positions table. Renders a /astrology/natal-chart response
24
+ * as the reference-grade positions grid astrologers read alongside the wheel:
25
+ * every body with its sign, exact degree, house, and daily motion, followed by
26
+ * the four chart points (Ascendant, Midheaven, Part of Fortune, Vertex).
27
+ */
28
+ @customElement('roxy-western-planets-table')
29
+ export class RoxyWesternPlanetsTable extends LitElement {
30
+ static styles = [
31
+ baseStyles,
32
+ css`
33
+ .wrap {
34
+ border: 1px solid var(--roxy-border, #e4e4e7);
35
+ border-radius: var(--roxy-radius-md, 8px);
36
+ background: var(--roxy-bg, #fff);
37
+ overflow: auto;
38
+ box-shadow: var(--roxy-shadow-sm);
39
+ }
40
+ .head {
41
+ padding: var(--roxy-space-md, 1rem);
42
+ border-bottom: 1px solid var(--roxy-border, #e4e4e7);
43
+ }
44
+ .title {
45
+ margin: 0;
46
+ font-size: var(--roxy-text-lg, 1.125rem);
47
+ font-weight: var(--roxy-weight-bold, 600);
48
+ }
49
+ table {
50
+ width: 100%;
51
+ border-collapse: collapse;
52
+ font-size: var(--roxy-text-sm, 0.875rem);
53
+ min-width: 460px;
54
+ }
55
+ thead {
56
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 20%, transparent);
57
+ }
58
+ th,
59
+ td {
60
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
61
+ text-align: left;
62
+ white-space: nowrap;
63
+ }
64
+ th {
65
+ color: var(--roxy-muted, #71717a);
66
+ font-weight: var(--roxy-weight-bold, 600);
67
+ text-transform: uppercase;
68
+ font-size: var(--roxy-text-xs, 0.75rem);
69
+ letter-spacing: 0.04em;
70
+ }
71
+ tbody tr {
72
+ border-top: 1px solid var(--roxy-border, #e4e4e7);
73
+ }
74
+ tbody tr.point {
75
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 8%, transparent);
76
+ }
77
+ td.body {
78
+ font-weight: var(--roxy-weight-bold, 600);
79
+ color: var(--roxy-fg, #0a0a0a);
80
+ }
81
+ .glyph {
82
+ margin-right: 0.4em;
83
+ color: var(--roxy-muted, #71717a);
84
+ }
85
+ .retro {
86
+ color: var(--roxy-danger, #dc2626);
87
+ font-weight: var(--roxy-weight-bold, 600);
88
+ }
89
+ .num {
90
+ font-variant-numeric: tabular-nums;
91
+ }
92
+ `,
93
+ ];
94
+
95
+ @property({ attribute: false })
96
+ data: NatalChartResponse | null = null;
97
+
98
+ /** Build the ordered row list: the planets array, then the four chart points. */
99
+ private rows(): BodyRow[] {
100
+ const d = this.data;
101
+ if (!d) return [];
102
+ const rows: BodyRow[] = (d.planets ?? []).map((p) => ({
103
+ name: p.name,
104
+ sign: p.sign,
105
+ longitude: p.longitude,
106
+ house: p.house,
107
+ speed: p.speed,
108
+ isRetrograde: p.isRetrograde,
109
+ }));
110
+ for (const [name, point] of [
111
+ ['Ascendant', d.ascendant],
112
+ ['Midheaven', d.midheaven],
113
+ ['Part of Fortune', d.partOfFortune],
114
+ ['Vertex', d.vertex],
115
+ ] as const) {
116
+ if (point) {
117
+ rows.push({
118
+ name,
119
+ sign: point.sign,
120
+ longitude: point.longitude,
121
+ isPoint: true,
122
+ });
123
+ }
124
+ }
125
+ return rows;
126
+ }
127
+
128
+ render() {
129
+ if (!this.data?.planets)
130
+ return html`<div class="roxy-empty" role="status">No chart data</div>`;
131
+ const rows = this.rows();
132
+
133
+ return html`<div class="wrap" aria-label="Western planetary positions" tabindex="0">
134
+ <header class="head">
135
+ <h2 class="title">Planetary positions</h2>
136
+ </header>
137
+ <table role="table">
138
+ <thead>
139
+ <tr>
140
+ <th scope="col">Body</th>
141
+ <th scope="col">Sign</th>
142
+ <th scope="col">Degree</th>
143
+ <th scope="col">House</th>
144
+ <th scope="col">Motion</th>
145
+ </tr>
146
+ </thead>
147
+ <tbody>
148
+ ${rows.map((r) => {
149
+ const glyph = PLANET_GLYPH[capitalize(r.name)] ?? '';
150
+ const signGlyph = SIGN_GLYPH[capitalize(r.sign ?? '')] ?? '';
151
+ const speed =
152
+ typeof r.speed === 'number' ? formatNumber(r.speed, 3) : '';
153
+ return html`<tr class=${r.isPoint ? 'point' : ''}>
154
+ <td class="body">
155
+ ${glyph ? html`<span class="glyph">${glyph}</span>` : nothing}${r.name}
156
+ </td>
157
+ <td>
158
+ ${signGlyph ? html`<span class="glyph">${signGlyph}</span>` : nothing}${r.sign ?? ''}
159
+ </td>
160
+ <td class="num">
161
+ ${typeof r.longitude === 'number' ? formatSignPosition(r.longitude) : ''}
162
+ </td>
163
+ <td class="num">${typeof r.house === 'number' ? r.house : ''}</td>
164
+ <td class="num">
165
+ ${speed ? html`${speed}°/day` : nothing}
166
+ ${r.isRetrograde ? html`<span class="retro"> ℞</span>` : nothing}
167
+ </td>
168
+ </tr>`;
169
+ })}
170
+ </tbody>
171
+ </table>
172
+ </div>`;
173
+ }
174
+ }
175
+
176
+ declare global {
177
+ interface HTMLElementTagNameMap {
178
+ 'roxy-western-planets-table': RoxyWesternPlanetsTable;
179
+ }
180
+ }
package/src/index.ts CHANGED
@@ -21,9 +21,12 @@ export { RoxyGunaMilan } from './components/guna-milan.js';
21
21
  // I Ching
22
22
  export { RoxyHexagram } from './components/hexagram.js';
23
23
  export { RoxyHoroscopeCard } from './components/horoscope-card.js';
24
+ export { RoxyKpChart } from './components/kp-chart.js';
24
25
  export { RoxyKpPlanetsTable } from './components/kp-planets-table.js';
26
+ export { RoxyKpRulingPlanets } from './components/kp-ruling-planets.js';
25
27
  export { RoxyLocationSearch } from './components/location-search.js';
26
28
  export { RoxyMoonPhase } from './components/moon-phase.js';
29
+ export { RoxyNakshatraCard } from './components/nakshatra-card.js';
27
30
  // Western astrology
28
31
  export { RoxyNatalChart } from './components/natal-chart.js';
29
32
  // Numerology
@@ -37,6 +40,8 @@ export { RoxyTarotSpread } from './components/tarot-spread.js';
37
40
  export { RoxyTransitsTable } from './components/transits-table.js';
38
41
  // Vedic astrology
39
42
  export { RoxyVedicKundli } from './components/vedic-kundli.js';
43
+ export { RoxyVedicPlanetsTable } from './components/vedic-planets-table.js';
44
+ export { RoxyWesternPlanetsTable } from './components/western-planets-table.js';
40
45
  export { RoxyYogaList } from './components/yoga-list.js';
41
46
 
42
47
  import { ROXY_COMPONENTS, type RoxyComponentSlug } from './manifest.js';