@roxyapi/ui 0.11.0 → 0.12.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 (139) hide show
  1. package/AGENTS.md +6 -0
  2. package/README.md +6 -0
  3. package/components-catalog.json +111 -1
  4. package/dist/cdn/components/astrocartography-map.js +58 -0
  5. package/dist/cdn/components/astrocartography-map.js.map +7 -0
  6. package/dist/cdn/components/divisional-chart.js +7 -7
  7. package/dist/cdn/components/divisional-chart.js.map +1 -1
  8. package/dist/cdn/components/dosha-card.js +2 -2
  9. package/dist/cdn/components/dosha-card.js.map +3 -3
  10. package/dist/cdn/components/fixed-stars.js +52 -0
  11. package/dist/cdn/components/fixed-stars.js.map +7 -0
  12. package/dist/cdn/components/hd-variables.js +2 -2
  13. package/dist/cdn/components/hd-variables.js.map +3 -3
  14. package/dist/cdn/components/hexagram.js +3 -3
  15. package/dist/cdn/components/hexagram.js.map +3 -3
  16. package/dist/cdn/components/local-space-compass.js +58 -0
  17. package/dist/cdn/components/local-space-compass.js.map +7 -0
  18. package/dist/cdn/components/moon-phase.js +3 -3
  19. package/dist/cdn/components/moon-phase.js.map +3 -3
  20. package/dist/cdn/components/natal-chart.js +8 -8
  21. package/dist/cdn/components/natal-chart.js.map +2 -2
  22. package/dist/cdn/components/positions-table.js +52 -0
  23. package/dist/cdn/components/positions-table.js.map +7 -0
  24. package/dist/cdn/components/profection-card.js +52 -0
  25. package/dist/cdn/components/profection-card.js.map +7 -0
  26. package/dist/cdn/components/reference-card.js +3 -3
  27. package/dist/cdn/components/reference-card.js.map +3 -3
  28. package/dist/cdn/components/relocation-wheel.js +61 -0
  29. package/dist/cdn/components/relocation-wheel.js.map +7 -0
  30. package/dist/cdn/components/synastry-chart.js +4 -4
  31. package/dist/cdn/components/synastry-chart.js.map +2 -2
  32. package/dist/cdn/components/vedic-kundli.js +5 -5
  33. package/dist/cdn/components/vedic-kundli.js.map +1 -1
  34. package/dist/cdn/components/vedic-planets-table.js +2 -2
  35. package/dist/cdn/components/vedic-planets-table.js.map +1 -1
  36. package/dist/cdn/components/western-planets-table.js +2 -2
  37. package/dist/cdn/components/western-planets-table.js.map +1 -1
  38. package/dist/cdn/components/yoga-list.js +3 -3
  39. package/dist/cdn/components/yoga-list.js.map +3 -3
  40. package/dist/cdn/roxy-ui.js +83 -71
  41. package/dist/cdn/roxy-ui.js.map +4 -4
  42. package/dist/components/astrocartography-map.d.ts +27 -0
  43. package/dist/components/astrocartography-map.d.ts.map +1 -0
  44. package/dist/components/astrocartography-map.js +8 -0
  45. package/dist/components/astrocartography-map.js.map +7 -0
  46. package/dist/components/divisional-chart.js +22 -22
  47. package/dist/components/divisional-chart.js.map +1 -1
  48. package/dist/components/dosha-card.d.ts.map +1 -1
  49. package/dist/components/dosha-card.js +1 -1
  50. package/dist/components/dosha-card.js.map +3 -3
  51. package/dist/components/fixed-stars.d.ts +21 -0
  52. package/dist/components/fixed-stars.d.ts.map +1 -0
  53. package/dist/components/fixed-stars.js +2 -0
  54. package/dist/components/fixed-stars.js.map +7 -0
  55. package/dist/components/hd-variables.d.ts.map +1 -1
  56. package/dist/components/hd-variables.js +1 -1
  57. package/dist/components/hd-variables.js.map +3 -3
  58. package/dist/components/hexagram.d.ts +3 -1
  59. package/dist/components/hexagram.d.ts.map +1 -1
  60. package/dist/components/hexagram.js +1 -1
  61. package/dist/components/hexagram.js.map +3 -3
  62. package/dist/components/local-space-compass.d.ts +23 -0
  63. package/dist/components/local-space-compass.d.ts.map +1 -0
  64. package/dist/components/local-space-compass.js +8 -0
  65. package/dist/components/local-space-compass.js.map +7 -0
  66. package/dist/components/moon-phase.d.ts.map +1 -1
  67. package/dist/components/moon-phase.js +1 -1
  68. package/dist/components/moon-phase.js.map +3 -3
  69. package/dist/components/natal-chart.d.ts +2 -0
  70. package/dist/components/natal-chart.d.ts.map +1 -1
  71. package/dist/components/natal-chart.js +6 -6
  72. package/dist/components/natal-chart.js.map +2 -2
  73. package/dist/components/positions-table.d.ts +34 -0
  74. package/dist/components/positions-table.d.ts.map +1 -0
  75. package/dist/components/positions-table.js +2 -0
  76. package/dist/components/positions-table.js.map +7 -0
  77. package/dist/components/profection-card.d.ts +18 -0
  78. package/dist/components/profection-card.d.ts.map +1 -0
  79. package/dist/components/profection-card.js +2 -0
  80. package/dist/components/profection-card.js.map +7 -0
  81. package/dist/components/reference-card.d.ts.map +1 -1
  82. package/dist/components/reference-card.js +1 -1
  83. package/dist/components/reference-card.js.map +3 -3
  84. package/dist/components/relocation-wheel.d.ts +21 -0
  85. package/dist/components/relocation-wheel.d.ts.map +1 -0
  86. package/dist/components/relocation-wheel.js +11 -0
  87. package/dist/components/relocation-wheel.js.map +7 -0
  88. package/dist/components/synastry-chart.js +3 -3
  89. package/dist/components/synastry-chart.js.map +2 -2
  90. package/dist/components/vedic-kundli.js +14 -14
  91. package/dist/components/vedic-kundli.js.map +1 -1
  92. package/dist/components/vedic-planets-table.js +1 -1
  93. package/dist/components/vedic-planets-table.js.map +1 -1
  94. package/dist/components/western-planets-table.js +1 -1
  95. package/dist/components/western-planets-table.js.map +1 -1
  96. package/dist/components/yoga-list.d.ts +5 -2
  97. package/dist/components/yoga-list.d.ts.map +1 -1
  98. package/dist/components/yoga-list.js +1 -1
  99. package/dist/components/yoga-list.js.map +3 -3
  100. package/dist/generated/endpoint-bindings.d.ts.map +1 -1
  101. package/dist/index.cjs +62 -50
  102. package/dist/index.cjs.map +4 -4
  103. package/dist/index.d.ts +6 -0
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +62 -50
  106. package/dist/index.js.map +4 -4
  107. package/dist/manifest.d.ts.map +1 -1
  108. package/dist/manifest.json +6 -0
  109. package/dist/types/index.d.ts +1 -1
  110. package/dist/types/index.d.ts.map +1 -1
  111. package/dist/types/types.gen.d.ts +7864 -5381
  112. package/dist/types/types.gen.d.ts.map +1 -1
  113. package/dist/utils/degree.d.ts +2 -0
  114. package/dist/utils/degree.d.ts.map +1 -1
  115. package/dist/utils/planet-color.d.ts +3 -0
  116. package/dist/utils/planet-color.d.ts.map +1 -0
  117. package/dist/version.d.ts +1 -1
  118. package/package.json +2 -1
  119. package/src/components/astrocartography-map.ts +436 -0
  120. package/src/components/dosha-card.ts +48 -16
  121. package/src/components/fixed-stars.ts +254 -0
  122. package/src/components/hd-variables.ts +30 -2
  123. package/src/components/hexagram.ts +11 -11
  124. package/src/components/local-space-compass.ts +299 -0
  125. package/src/components/moon-phase.ts +21 -2
  126. package/src/components/natal-chart.ts +36 -24
  127. package/src/components/positions-table.ts +442 -0
  128. package/src/components/profection-card.ts +173 -0
  129. package/src/components/reference-card.ts +40 -8
  130. package/src/components/relocation-wheel.ts +170 -0
  131. package/src/components/yoga-list.ts +95 -2
  132. package/src/generated/endpoint-bindings.ts +62 -0
  133. package/src/index.ts +6 -0
  134. package/src/manifest.ts +79 -0
  135. package/src/types/index.ts +1 -1
  136. package/src/types/types.gen.ts +7814 -5263
  137. package/src/utils/degree.ts +11 -0
  138. package/src/utils/planet-color.ts +45 -0
  139. package/src/version.ts +1 -1
@@ -40,7 +40,15 @@ const PROSE_KEYS = new Set([
40
40
  'motto',
41
41
  ]);
42
42
  /** Keys never shown as their own row/section (rendered elsewhere or noise). */
43
- const SKIP_KEYS = new Set(['id', 'symbol', 'keywords', ...TITLE_KEYS]);
43
+ const SKIP_KEYS = new Set(['id', 'symbol', ...TITLE_KEYS]);
44
+
45
+ /** Best-effort one-line label for an object inside an array (e.g. a gate channel partner), joining its primitive values so it never renders as [object Object]. */
46
+ function objectLabel(obj: Record<string, unknown>): string {
47
+ return Object.values(obj)
48
+ .filter((v) => typeof v === 'string' || typeof v === 'number')
49
+ .map(String)
50
+ .join(' · ');
51
+ }
44
52
 
45
53
  @customElement('roxy-reference-card')
46
54
  export class RoxyReferenceCard extends RoxyDataElement<ReferenceData> {
@@ -140,17 +148,41 @@ export class RoxyReferenceCard extends RoxyDataElement<ReferenceData> {
140
148
  const prose: Array<[string, string]> = [];
141
149
  const lists: Array<[string, string[]]> = [];
142
150
  const facts: Array<[string, string]> = [];
143
- for (const [key, value] of Object.entries(rec)) {
144
- if (SKIP_KEYS.has(key) || value == null) continue;
151
+ // Bucket each field into prose / chip-list / fact. Recurses one level into
152
+ // nested objects (description {short,long}, keywords {positive,negative},
153
+ // meaning {...}, ichingHexagram {number,english}) and labels object-array
154
+ // items by their primitives, so nested content is never dropped and an array
155
+ // of objects never stringifies to [object Object].
156
+ const collect = (label: string, value: unknown, depth: number): void => {
157
+ if (value == null) return;
145
158
  if (Array.isArray(value)) {
146
- const items = value.filter((v) => v != null).map(String);
147
- if (items.length > 0) lists.push([key, items]);
159
+ const items = value
160
+ .filter((v) => v != null)
161
+ .map((v) =>
162
+ typeof v === 'object'
163
+ ? objectLabel(v as Record<string, unknown>)
164
+ : String(v),
165
+ )
166
+ .filter((s) => s.length > 0);
167
+ if (items.length > 0) lists.push([label, items]);
148
168
  } else if (typeof value === 'string') {
149
- if (PROSE_KEYS.has(key) || value.length > 48) prose.push([key, value]);
150
- else facts.push([key, value]);
169
+ if (PROSE_KEYS.has(label) || value.length > 48)
170
+ prose.push([label, value]);
171
+ else facts.push([label, value]);
151
172
  } else if (typeof value === 'number' || typeof value === 'boolean') {
152
- facts.push([key, String(value)]);
173
+ facts.push([label, String(value)]);
174
+ } else if (typeof value === 'object' && depth < 2) {
175
+ for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
176
+ collect(`${label} ${k}`, v, depth + 1);
177
+ }
153
178
  }
179
+ };
180
+ for (const [key, value] of Object.entries(rec)) {
181
+ if (SKIP_KEYS.has(key)) continue;
182
+ // The hero chip row already shows a top-level keywords ARRAY; an object
183
+ // keywords ({positive,negative}) falls through to collect() instead.
184
+ if (key === 'keywords' && Array.isArray(value)) continue;
185
+ collect(key, value, 0);
154
186
  }
155
187
 
156
188
  return html`<article class="card" aria-label=${title}>
@@ -0,0 +1,170 @@
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement } from 'lit/decorators.js';
3
+ // Registers <roxy-natal-chart>, reused below as the wheel renderer. The
4
+ // relocation response is structurally a natal chart (same planets, houses, and
5
+ // angles), so the wheel is shared rather than duplicated.
6
+ import './natal-chart.js';
7
+ import { PLANET_GLYPH } from '../tokens/index.js';
8
+ import type {
9
+ NatalChartResponse,
10
+ RelocationChartResponse,
11
+ } from '../types/index.js';
12
+ import { RoxyDataElement } from '../utils/base-element.js';
13
+ import { baseStyles } from '../utils/base-styles.js';
14
+ import { capitalize } from '../utils/string.js';
15
+
16
+ type HouseChange =
17
+ RelocationChartResponse['changes']['planetsChangedHouse'][number];
18
+
19
+ const glyphFor = (name: string): string =>
20
+ PLANET_GLYPH[capitalize(name)] ?? PLANET_GLYPH[name] ?? '';
21
+
22
+ /**
23
+ * Relocation chart. The birth instant is unchanged, so every planet keeps its
24
+ * natal sign and degree while the houses and angles are recomputed for a new
25
+ * place. Reuses {@link RoxyNatalChart} for the wheel (identical data shape) and
26
+ * adds the relocation read: the move geometry, the planets that change house,
27
+ * and the bodies pulled onto a relocated angle.
28
+ */
29
+ @customElement('roxy-relocation-wheel')
30
+ export class RoxyRelocationWheel extends RoxyDataElement<RelocationChartResponse> {
31
+ static styles = [
32
+ baseStyles,
33
+ css`
34
+ .stack {
35
+ display: grid;
36
+ gap: var(--roxy-space-md, 1rem);
37
+ }
38
+ .changes {
39
+ background: var(--roxy-surface, #fff);
40
+ color: var(--roxy-fg, #0a0a0a);
41
+ border: 1px solid var(--roxy-border, #e4e4e7);
42
+ border-radius: var(--roxy-radius-md, 8px);
43
+ padding: var(--roxy-space-lg, 1.5rem);
44
+ box-shadow: var(--roxy-shadow-sm);
45
+ display: grid;
46
+ gap: var(--roxy-space-md, 1rem);
47
+ }
48
+ .title {
49
+ font-size: var(--roxy-text-lg, 1.125rem);
50
+ font-weight: var(--roxy-weight-bold, 600);
51
+ margin: 0;
52
+ color: var(--roxy-primary, #0f172a);
53
+ }
54
+ .move {
55
+ display: flex;
56
+ flex-wrap: wrap;
57
+ gap: var(--roxy-space-xs, 0.25rem) var(--roxy-space-md, 1rem);
58
+ font-size: var(--roxy-text-sm, 0.875rem);
59
+ color: var(--roxy-muted, #71717a);
60
+ }
61
+ .summary {
62
+ font-size: var(--roxy-text-sm, 0.875rem);
63
+ color: var(--roxy-fg, #0a0a0a);
64
+ margin: 0;
65
+ }
66
+ .block-label {
67
+ font-size: var(--roxy-text-xs, 0.75rem);
68
+ font-weight: 600;
69
+ text-transform: uppercase;
70
+ letter-spacing: 0.06em;
71
+ color: var(--roxy-muted, #71717a);
72
+ margin: 0 0 var(--roxy-space-xs, 0.25rem);
73
+ }
74
+ .chips {
75
+ display: flex;
76
+ flex-wrap: wrap;
77
+ gap: var(--roxy-space-xs, 0.25rem);
78
+ }
79
+ .chip {
80
+ padding: 2px 10px;
81
+ border-radius: var(--roxy-radius-full, 9999px);
82
+ font-size: var(--roxy-text-xs, 0.75rem);
83
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 16%, transparent);
84
+ color: var(--roxy-fg, #0a0a0a);
85
+ }
86
+ .moves-list {
87
+ list-style: none;
88
+ margin: 0;
89
+ padding: 0;
90
+ display: grid;
91
+ gap: 2px;
92
+ }
93
+ .moves-list li {
94
+ font-size: var(--roxy-text-sm, 0.875rem);
95
+ color: var(--roxy-fg, #0a0a0a);
96
+ }
97
+ .moves-list .arrow {
98
+ color: var(--roxy-muted, #71717a);
99
+ }
100
+ .empty-note {
101
+ font-size: var(--roxy-text-sm, 0.875rem);
102
+ color: var(--roxy-muted, #71717a);
103
+ margin: 0;
104
+ }
105
+ `,
106
+ ];
107
+
108
+ protected renderEmpty() {
109
+ return html`<div class="roxy-empty" role="status">No relocation data</div>`;
110
+ }
111
+
112
+ protected renderData(data: RelocationChartResponse) {
113
+ const c = data.changes;
114
+ return html`<div class="stack">
115
+ <roxy-natal-chart
116
+ heading="Relocation chart"
117
+ .data=${data as unknown as NatalChartResponse}
118
+ ></roxy-natal-chart>
119
+ <section class="changes">
120
+ <h3 class="title">What changes at this location</h3>
121
+ <div class="move">
122
+ ${
123
+ typeof c?.distanceKm === 'number'
124
+ ? html`<span>${Math.round(c.distanceKm).toLocaleString()} km ${c.direction ?? ''} of birthplace</span>`
125
+ : nothing
126
+ }
127
+ ${
128
+ c
129
+ ? html`<span>Ascendant ${c.ascendantSignChanged ? 'changes sign' : 'keeps its sign'}</span>`
130
+ : nothing
131
+ }
132
+ </div>
133
+ ${
134
+ data.interpretation?.summary
135
+ ? html`<p class="summary">${data.interpretation.summary}</p>`
136
+ : nothing
137
+ }
138
+ ${
139
+ c?.angularPlanets?.length
140
+ ? html`<div>
141
+ <p class="block-label">Angular planets here</p>
142
+ <div class="chips">
143
+ ${c.angularPlanets.map((p) => html`<span class="chip">${glyphFor(p)} ${p}</span>`)}
144
+ </div>
145
+ </div>`
146
+ : nothing
147
+ }
148
+ <div>
149
+ <p class="block-label">Planets that change house</p>
150
+ ${
151
+ c?.planetsChangedHouse?.length
152
+ ? html`<ul class="moves-list">
153
+ ${c.planetsChangedHouse.map(
154
+ (m: HouseChange) =>
155
+ html`<li>${glyphFor(m.planet)} ${m.planet}: house ${m.natalHouse} <span class="arrow">to</span> ${m.relocatedHouse}</li>`,
156
+ )}
157
+ </ul>`
158
+ : html`<p class="empty-note">No planet changes house at this location.</p>`
159
+ }
160
+ </div>
161
+ </section>
162
+ </div>`;
163
+ }
164
+ }
165
+
166
+ declare global {
167
+ interface HTMLElementTagNameMap {
168
+ 'roxy-relocation-wheel': RoxyRelocationWheel;
169
+ }
170
+ }
@@ -15,12 +15,13 @@ type YogaListData =
15
15
  | { yogas: Array<GetYogaResponse> };
16
16
 
17
17
  /**
18
- * Yoga catalog and detail renderer. Accepts three data modes:
18
+ * Yoga catalog and detail renderer. Accepts four data modes:
19
19
  * - Catalog: ListYogasResponse (yogas array of {id, name} + total)
20
20
  * - Detail: GetYogaResponse (single yoga with description, result, quality)
21
21
  * - Detail array: { yogas: Array<GetYogaResponse> } for pre-filtered sets
22
+ * - Detect: DetectYogasResponse (each yoga carries a present verdict + evidence); present yogas render first, each badged present/absent with its classical evidence
22
23
  *
23
- * Catalog and detail-array modes include a live search filter.
24
+ * All multi-item modes include a live search filter.
24
25
  */
25
26
  @customElement('roxy-yoga-list')
26
27
  export class RoxyYogaList extends RoxyDataElement<YogaListData> {
@@ -132,6 +133,30 @@ export class RoxyYogaList extends RoxyDataElement<YogaListData> {
132
133
  color: var(--roxy-warning-fg, #b45309);
133
134
  border: 1px solid color-mix(in srgb, var(--roxy-warning, #f59e0b) 40%, transparent);
134
135
  }
136
+ .present-badge {
137
+ display: inline-block;
138
+ font-size: var(--roxy-text-xs, 0.75rem);
139
+ font-weight: 600;
140
+ padding: 0.15em 0.6em;
141
+ border-radius: 999px;
142
+ }
143
+ .present-badge.is-present {
144
+ background: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);
145
+ color: var(--roxy-success-fg, #166534);
146
+ }
147
+ .present-badge.is-absent {
148
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 55%, transparent);
149
+ color: var(--roxy-fg, #0a0a0a);
150
+ }
151
+ .detail-card.absent {
152
+ opacity: 0.72;
153
+ }
154
+ .evidence {
155
+ font-size: var(--roxy-text-xs, 0.75rem);
156
+ color: var(--roxy-muted, #71717a);
157
+ margin: 0;
158
+ line-height: var(--roxy-leading-normal, 1.5);
159
+ }
135
160
  .description {
136
161
  font-size: var(--roxy-text-sm, 0.875rem);
137
162
  color: var(--roxy-muted, #71717a);
@@ -211,6 +236,27 @@ export class RoxyYogaList extends RoxyDataElement<YogaListData> {
211
236
  </div>`;
212
237
  }
213
238
 
239
+ /** Detect-mode card: shows the present/absent verdict and the classical evidence that triggered or failed it. */
240
+ private renderDetectCard(y: DetectYogasResponse['yogas'][number]) {
241
+ return html`<div class="detail-card ${y.present ? '' : 'absent'}">
242
+ <p class="detail-name">
243
+ ${y.name}
244
+ ${y.quality ? this.renderQualityChip(y.quality) : nothing}
245
+ <span class="present-badge ${y.present ? 'is-present' : 'is-absent'}">${y.present ? 'Present' : 'Not present'}</span>
246
+ </p>
247
+ ${y.description ? html`<p class="description">${y.description}</p>` : nothing}
248
+ ${
249
+ y.present && y.result
250
+ ? html`<details>
251
+ <summary>Effects</summary>
252
+ <div class="result-body">${y.result}</div>
253
+ </details>`
254
+ : nothing
255
+ }
256
+ ${y.evidence ? html`<p class="evidence">${y.evidence}</p>` : nothing}
257
+ </div>`;
258
+ }
259
+
214
260
  protected renderEmpty() {
215
261
  return html`<div class="roxy-empty" role="status">No yoga data</div>`;
216
262
  }
@@ -232,6 +278,53 @@ export class RoxyYogaList extends RoxyDataElement<YogaListData> {
232
278
  const allYogas = (
233
279
  d as { yogas: Array<GetYogaResponse | { id: string; name: string }> }
234
280
  ).yogas;
281
+
282
+ // Detect mode: every entry carries a `present` verdict. Render present
283
+ // yogas first, mark each present/absent, and surface the classical
284
+ // evidence. Must precede the detail-array check because detect entries
285
+ // also carry `description`.
286
+ if (allYogas.length > 0 && 'present' in allYogas[0]) {
287
+ const detected = allYogas as DetectYogasResponse['yogas'];
288
+ const filtered = lc
289
+ ? detected.filter((y) => y.name.toLowerCase().includes(lc))
290
+ : detected;
291
+ const ordered = [
292
+ ...filtered.filter((y) => y.present),
293
+ ...filtered.filter((y) => !y.present),
294
+ ];
295
+ const presentCount =
296
+ (d as DetectYogasResponse).total ??
297
+ detected.filter((y) => y.present).length;
298
+ return html`<div class="wrap">
299
+ <div class="head">
300
+ <h2 class="title">Detected yogas</h2>
301
+ <span class="count">${presentCount} of ${detected.length} present</span>
302
+ </div>
303
+ <div class="search-wrap">
304
+ <input
305
+ class="search"
306
+ type="search"
307
+ placeholder="Filter yogas..."
308
+ aria-label="Filter detected yogas by name"
309
+ .value=${this.filter}
310
+ @input=${this.handleInput}
311
+ />
312
+ </div>
313
+ <div
314
+ class="detail-grid"
315
+ role="region"
316
+ aria-live="polite"
317
+ aria-label="Detected yogas"
318
+ >
319
+ ${
320
+ ordered.length > 0
321
+ ? ordered.map((y) => this.renderDetectCard(y))
322
+ : html`<p class="no-results">No yogas match your search.</p>`
323
+ }
324
+ </div>
325
+ </div>`;
326
+ }
327
+
235
328
  const isDetailArray = allYogas.length > 0 && 'description' in allYogas[0];
236
329
 
237
330
  if (isDetailArray) {
@@ -53,6 +53,13 @@ export const ENDPOINT_BINDINGS: Record<string, EndpointBinding[]> = {
53
53
  path: '/astrology/transit-aspects',
54
54
  },
55
55
  ],
56
+ 'roxy-astrocartography-map': [
57
+ {
58
+ operationId: 'generateAstrocartography',
59
+ method: 'POST',
60
+ path: '/astrology/astrocartography',
61
+ },
62
+ ],
56
63
  'roxy-biorhythm-chart': [
57
64
  {
58
65
  operationId: 'getCriticalDays',
@@ -216,6 +223,13 @@ export const ENDPOINT_BINDINGS: Record<string, EndpointBinding[]> = {
216
223
  path: '/dreams/symbols',
217
224
  },
218
225
  ],
226
+ 'roxy-fixed-stars': [
227
+ {
228
+ operationId: 'generateFixedStars',
229
+ method: 'POST',
230
+ path: '/astrology/fixed-stars',
231
+ },
232
+ ],
219
233
  'roxy-forecast-digest': [
220
234
  {
221
235
  operationId: 'generateDigest',
@@ -329,6 +343,13 @@ export const ENDPOINT_BINDINGS: Record<string, EndpointBinding[]> = {
329
343
  path: '/vedic-astrology/kp/ruling-planets',
330
344
  },
331
345
  ],
346
+ 'roxy-local-space-compass': [
347
+ {
348
+ operationId: 'generateLocalSpace',
349
+ method: 'POST',
350
+ path: '/astrology/local-space',
351
+ },
352
+ ],
332
353
  'roxy-moon-phase': [
333
354
  {
334
355
  operationId: 'getMoonCalendar',
@@ -477,6 +498,40 @@ export const ENDPOINT_BINDINGS: Record<string, EndpointBinding[]> = {
477
498
  },
478
499
  },
479
500
  ],
501
+ 'roxy-positions-table': [
502
+ {
503
+ operationId: 'calculateArabicLots',
504
+ method: 'POST',
505
+ path: '/astrology/arabic-lots',
506
+ },
507
+ {
508
+ operationId: 'generateAsteroids',
509
+ method: 'POST',
510
+ path: '/astrology/asteroids',
511
+ },
512
+ {
513
+ operationId: 'generateLilith',
514
+ method: 'POST',
515
+ path: '/astrology/lilith',
516
+ },
517
+ {
518
+ operationId: 'generateProgressions',
519
+ method: 'POST',
520
+ path: '/astrology/progressions',
521
+ },
522
+ {
523
+ operationId: 'generateSolarArc',
524
+ method: 'POST',
525
+ path: '/astrology/solar-arc',
526
+ },
527
+ ],
528
+ 'roxy-profection-card': [
529
+ {
530
+ operationId: 'generateProfections',
531
+ method: 'POST',
532
+ path: '/astrology/profections',
533
+ },
534
+ ],
480
535
  'roxy-reference-card': [
481
536
  {
482
537
  operationId: 'getPlanetMeaning',
@@ -519,6 +574,13 @@ export const ENDPOINT_BINDINGS: Record<string, EndpointBinding[]> = {
519
574
  path: '/vedic-astrology/rashis/{id}',
520
575
  },
521
576
  ],
577
+ 'roxy-relocation-wheel': [
578
+ {
579
+ operationId: 'generateRelocationChart',
580
+ method: 'POST',
581
+ path: '/astrology/relocation-chart',
582
+ },
583
+ ],
522
584
  'roxy-shadbala-table': [
523
585
  {
524
586
  operationId: 'calculateShadbala',
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ export { RoxyAngelNumberLookup } from './components/angel-number-lookup.js';
11
11
  export { RoxyAshtakavargaGrid } from './components/ashtakavarga-grid.js';
12
12
  // Western astrology
13
13
  export { RoxyAspectsTable } from './components/aspects-table.js';
14
+ export { RoxyAstrocartographyMap } from './components/astrocartography-map.js';
14
15
  // Biorhythm
15
16
  export { RoxyBiorhythmChart } from './components/biorhythm-chart.js';
16
17
  // Human Design
@@ -30,6 +31,7 @@ export { RoxyDreamCard } from './components/dream-card.js';
30
31
  export { RoxyDreamSearch } from './components/dream-search.js';
31
32
  // Helpers
32
33
  export { RoxyEndpointForm } from './components/endpoint-form.js';
34
+ export { RoxyFixedStars } from './components/fixed-stars.js';
33
35
  // Forecast
34
36
  export { RoxyForecastDigest } from './components/forecast-digest.js';
35
37
  export { RoxyForecastTimeline } from './components/forecast-timeline.js';
@@ -45,6 +47,7 @@ export { RoxyHoroscopeCard } from './components/horoscope-card.js';
45
47
  export { RoxyKpChart } from './components/kp-chart.js';
46
48
  export { RoxyKpPlanetsTable } from './components/kp-planets-table.js';
47
49
  export { RoxyKpRulingPlanets } from './components/kp-ruling-planets.js';
50
+ export { RoxyLocalSpaceCompass } from './components/local-space-compass.js';
48
51
  export { RoxyLocationSearch } from './components/location-search.js';
49
52
  export { RoxyMoonPhase } from './components/moon-phase.js';
50
53
  export { RoxyNakshatraCard } from './components/nakshatra-card.js';
@@ -53,7 +56,10 @@ export { RoxyNatalChart } from './components/natal-chart.js';
53
56
  // Numerology
54
57
  export { RoxyNumerologyCard } from './components/numerology-card.js';
55
58
  export { RoxyPanchangTable } from './components/panchang-table.js';
59
+ export { RoxyPositionsTable } from './components/positions-table.js';
60
+ export { RoxyProfectionCard } from './components/profection-card.js';
56
61
  export { RoxyReferenceCard } from './components/reference-card.js';
62
+ export { RoxyRelocationWheel } from './components/relocation-wheel.js';
57
63
  export { RoxyShadbalaTable } from './components/shadbala-table.js';
58
64
  export { RoxySynastryChart } from './components/synastry-chart.js';
59
65
  // Tarot
package/src/manifest.ts CHANGED
@@ -126,6 +126,85 @@ export const ROXY_COMPONENTS: readonly RoxyComponent[] = [
126
126
  docsSummary: 'Daily, weekly, or monthly horoscope card',
127
127
  topic: 'Astrology',
128
128
  },
129
+ {
130
+ pascal: 'RoxyAstrocartographyMap',
131
+ tag: 'roxy-astrocartography-map',
132
+ slug: 'astrocartography-map',
133
+ heading: 'Astrocartography',
134
+ description:
135
+ 'Astrocartography world map plotting each body Midheaven, IC, Ascendant, and Descendant relocation lines',
136
+ docsLabel: 'Western',
137
+ endpointLabel: 'POST /astrology/astrocartography',
138
+ docsSummary:
139
+ 'World map of planetary MC, IC, Ascendant, and Descendant lines with per-line interpretations',
140
+ topic: 'Astrology',
141
+ },
142
+ {
143
+ pascal: 'RoxyLocalSpaceCompass',
144
+ tag: 'roxy-local-space-compass',
145
+ slug: 'local-space-compass',
146
+ heading: 'Local space',
147
+ description:
148
+ 'Local space compass plotting each body direction from the birthplace by azimuth and altitude',
149
+ docsLabel: 'Western',
150
+ endpointLabel: 'POST /astrology/local-space',
151
+ docsSummary:
152
+ 'Compass dial of planetary azimuth lines from the birthplace, dimmed below the horizon',
153
+ topic: 'Astrology',
154
+ },
155
+ {
156
+ pascal: 'RoxyRelocationWheel',
157
+ tag: 'roxy-relocation-wheel',
158
+ slug: 'relocation-wheel',
159
+ heading: 'Relocation chart',
160
+ description:
161
+ 'Relocation chart wheel recomputing houses and angles for a new place, with the planets that change house',
162
+ docsLabel: 'Western',
163
+ endpointLabel: 'POST /astrology/relocation-chart',
164
+ docsSummary:
165
+ 'Relocated chart wheel plus the move geometry, angular planets, and planets that change house',
166
+ topic: 'Astrology',
167
+ },
168
+ {
169
+ pascal: 'RoxyPositionsTable',
170
+ tag: 'roxy-positions-table',
171
+ slug: 'positions-table',
172
+ heading: 'Positions table',
173
+ description:
174
+ 'Editorial positions table for asteroids, Black Moon Lilith, secondary progressions, solar arc directions, and the Arabic lots',
175
+ docsLabel: 'Western',
176
+ endpointLabel:
177
+ 'POST /astrology/asteroids, /astrology/lilith, /astrology/progressions, /astrology/solar-arc, /astrology/arabic-lots',
178
+ docsSummary:
179
+ 'Body, sign, degree, and per-shape columns (house, motion, formula, or natal arc) plus each reading',
180
+ topic: 'Astrology',
181
+ },
182
+ {
183
+ pascal: 'RoxyFixedStars',
184
+ tag: 'roxy-fixed-stars',
185
+ slug: 'fixed-stars',
186
+ heading: 'Fixed stars',
187
+ description:
188
+ 'Fixed star conjunctions to the natal chart, tightest first, with the precessed star catalog',
189
+ docsLabel: 'Western',
190
+ endpointLabel: 'POST /astrology/fixed-stars',
191
+ docsSummary:
192
+ 'Star to natal point conjunctions with readings, plus a catalog of position, magnitude, nature, and keywords',
193
+ topic: 'Astrology',
194
+ },
195
+ {
196
+ pascal: 'RoxyProfectionCard',
197
+ tag: 'roxy-profection-card',
198
+ slug: 'profection-card',
199
+ heading: 'Annual profection',
200
+ description:
201
+ 'Annual profection card with the profected house and sign, the lord of the year, and its natal placement',
202
+ docsLabel: 'Western',
203
+ endpointLabel: 'POST /astrology/profections',
204
+ docsSummary:
205
+ 'Profected house and sign for the year, the lord of the year, its natal placement, and the reading',
206
+ topic: 'Astrology',
207
+ },
129
208
  {
130
209
  pascal: 'RoxyCompatibilityCard',
131
210
  tag: 'roxy-compatibility-card',