@roxyapi/ui 0.1.2 → 0.2.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 (220) hide show
  1. package/AGENTS.md +6 -0
  2. package/README.md +327 -14
  3. package/THEMING.md +24 -7
  4. package/dist/cdn/components/ashtakavarga-grid.js +349 -0
  5. package/dist/cdn/components/ashtakavarga-grid.js.map +7 -0
  6. package/dist/cdn/components/biorhythm-chart.js +15 -22
  7. package/dist/cdn/components/biorhythm-chart.js.map +3 -3
  8. package/dist/cdn/components/choghadiya-grid.js +239 -0
  9. package/dist/cdn/components/choghadiya-grid.js.map +7 -0
  10. package/dist/cdn/components/compatibility-card.js +36 -34
  11. package/dist/cdn/components/compatibility-card.js.map +4 -4
  12. package/dist/cdn/components/dasha-timeline.js +35 -39
  13. package/dist/cdn/components/dasha-timeline.js.map +4 -4
  14. package/dist/cdn/components/data.js +9 -9
  15. package/dist/cdn/components/data.js.map +4 -4
  16. package/dist/cdn/components/divisional-chart.js +279 -0
  17. package/dist/cdn/components/divisional-chart.js.map +7 -0
  18. package/dist/cdn/components/dosha-card.js +49 -49
  19. package/dist/cdn/components/dosha-card.js.map +3 -3
  20. package/dist/cdn/components/endpoint-form.js +47 -28
  21. package/dist/cdn/components/endpoint-form.js.map +4 -4
  22. package/dist/cdn/components/guna-milan.js +66 -24
  23. package/dist/cdn/components/guna-milan.js.map +4 -4
  24. package/dist/cdn/components/hexagram.js +26 -26
  25. package/dist/cdn/components/hexagram.js.map +3 -3
  26. package/dist/cdn/components/horoscope-card.js +47 -40
  27. package/dist/cdn/components/horoscope-card.js.map +4 -4
  28. package/dist/cdn/components/kp-planets-table.js +10 -10
  29. package/dist/cdn/components/kp-planets-table.js.map +4 -4
  30. package/dist/cdn/components/location-search.js +6 -6
  31. package/dist/cdn/components/location-search.js.map +3 -3
  32. package/dist/cdn/components/moon-phase.js +18 -18
  33. package/dist/cdn/components/moon-phase.js.map +4 -4
  34. package/dist/cdn/components/natal-chart.js +240 -24
  35. package/dist/cdn/components/natal-chart.js.map +4 -4
  36. package/dist/cdn/components/numerology-card.js +40 -31
  37. package/dist/cdn/components/numerology-card.js.map +4 -4
  38. package/dist/cdn/components/panchang-table.js +30 -30
  39. package/dist/cdn/components/panchang-table.js.map +4 -4
  40. package/dist/cdn/components/shadbala-table.js +312 -0
  41. package/dist/cdn/components/shadbala-table.js.map +7 -0
  42. package/dist/cdn/components/synastry-chart.js +129 -39
  43. package/dist/cdn/components/synastry-chart.js.map +4 -4
  44. package/dist/cdn/components/tarot-card.js +49 -20
  45. package/dist/cdn/components/tarot-card.js.map +3 -3
  46. package/dist/cdn/components/tarot-spread.js +43 -27
  47. package/dist/cdn/components/tarot-spread.js.map +3 -3
  48. package/dist/cdn/components/transits-table.js +391 -0
  49. package/dist/cdn/components/transits-table.js.map +7 -0
  50. package/dist/cdn/components/vedic-kundli.js +63 -27
  51. package/dist/cdn/components/vedic-kundli.js.map +4 -4
  52. package/dist/cdn/components/yoga-list.js +334 -0
  53. package/dist/cdn/components/yoga-list.js.map +7 -0
  54. package/dist/cdn/roxy-ui.js +2104 -544
  55. package/dist/cdn/roxy-ui.js.map +4 -4
  56. package/dist/components/ashtakavarga-grid.d.ts +26 -0
  57. package/dist/components/ashtakavarga-grid.d.ts.map +1 -0
  58. package/dist/components/ashtakavarga-grid.js +457 -0
  59. package/dist/components/ashtakavarga-grid.js.map +7 -0
  60. package/dist/components/biorhythm-chart.d.ts +2 -46
  61. package/dist/components/biorhythm-chart.d.ts.map +1 -1
  62. package/dist/components/biorhythm-chart.js +24 -23
  63. package/dist/components/biorhythm-chart.js.map +2 -2
  64. package/dist/components/choghadiya-grid.d.ts +19 -0
  65. package/dist/components/choghadiya-grid.d.ts.map +1 -0
  66. package/dist/components/choghadiya-grid.js +304 -0
  67. package/dist/components/choghadiya-grid.js.map +7 -0
  68. package/dist/components/compatibility-card.d.ts +2 -27
  69. package/dist/components/compatibility-card.d.ts.map +1 -1
  70. package/dist/components/compatibility-card.js +50 -29
  71. package/dist/components/compatibility-card.js.map +3 -3
  72. package/dist/components/dasha-timeline.d.ts +2 -31
  73. package/dist/components/dasha-timeline.d.ts.map +1 -1
  74. package/dist/components/dasha-timeline.js +32 -30
  75. package/dist/components/dasha-timeline.js.map +3 -3
  76. package/dist/components/data.d.ts +11 -7
  77. package/dist/components/data.d.ts.map +1 -1
  78. package/dist/components/data.js +16 -6
  79. package/dist/components/data.js.map +3 -3
  80. package/dist/components/divisional-chart.d.ts +20 -0
  81. package/dist/components/divisional-chart.d.ts.map +1 -0
  82. package/dist/components/divisional-chart.js +471 -0
  83. package/dist/components/divisional-chart.js.map +7 -0
  84. package/dist/components/dosha-card.d.ts +2 -16
  85. package/dist/components/dosha-card.d.ts.map +1 -1
  86. package/dist/components/dosha-card.js +45 -43
  87. package/dist/components/dosha-card.js.map +2 -2
  88. package/dist/components/endpoint-form.d.ts +2 -0
  89. package/dist/components/endpoint-form.d.ts.map +1 -1
  90. package/dist/components/endpoint-form.js +71 -11
  91. package/dist/components/endpoint-form.js.map +3 -3
  92. package/dist/components/guna-milan.d.ts +2 -20
  93. package/dist/components/guna-milan.d.ts.map +1 -1
  94. package/dist/components/guna-milan.js +79 -20
  95. package/dist/components/guna-milan.js.map +4 -4
  96. package/dist/components/hexagram.d.ts +3 -27
  97. package/dist/components/hexagram.d.ts.map +1 -1
  98. package/dist/components/hexagram.js +48 -15
  99. package/dist/components/hexagram.js.map +2 -2
  100. package/dist/components/horoscope-card.d.ts +2 -20
  101. package/dist/components/horoscope-card.d.ts.map +1 -1
  102. package/dist/components/horoscope-card.js +54 -18
  103. package/dist/components/horoscope-card.js.map +3 -3
  104. package/dist/components/kp-planets-table.d.ts +2 -21
  105. package/dist/components/kp-planets-table.d.ts.map +1 -1
  106. package/dist/components/kp-planets-table.js +10 -4
  107. package/dist/components/kp-planets-table.js.map +3 -3
  108. package/dist/components/location-search.d.ts +5 -14
  109. package/dist/components/location-search.d.ts.map +1 -1
  110. package/dist/components/location-search.js +45 -5
  111. package/dist/components/location-search.js.map +2 -2
  112. package/dist/components/moon-phase.d.ts +4 -21
  113. package/dist/components/moon-phase.d.ts.map +1 -1
  114. package/dist/components/moon-phase.js +34 -4
  115. package/dist/components/moon-phase.js.map +3 -3
  116. package/dist/components/natal-chart.d.ts +9 -43
  117. package/dist/components/natal-chart.d.ts.map +1 -1
  118. package/dist/components/natal-chart.js +346 -79
  119. package/dist/components/natal-chart.js.map +3 -3
  120. package/dist/components/numerology-card.d.ts +5 -37
  121. package/dist/components/numerology-card.d.ts.map +1 -1
  122. package/dist/components/numerology-card.js +58 -30
  123. package/dist/components/numerology-card.js.map +3 -3
  124. package/dist/components/panchang-table.d.ts +3 -62
  125. package/dist/components/panchang-table.d.ts.map +1 -1
  126. package/dist/components/panchang-table.js +62 -32
  127. package/dist/components/panchang-table.js.map +3 -3
  128. package/dist/components/shadbala-table.d.ts +18 -0
  129. package/dist/components/shadbala-table.d.ts.map +1 -0
  130. package/dist/components/shadbala-table.js +400 -0
  131. package/dist/components/shadbala-table.js.map +7 -0
  132. package/dist/components/synastry-chart.d.ts +9 -28
  133. package/dist/components/synastry-chart.d.ts.map +1 -1
  134. package/dist/components/synastry-chart.js +201 -56
  135. package/dist/components/synastry-chart.js.map +3 -3
  136. package/dist/components/tarot-card.d.ts +5 -29
  137. package/dist/components/tarot-card.d.ts.map +1 -1
  138. package/dist/components/tarot-card.js +59 -20
  139. package/dist/components/tarot-card.js.map +2 -2
  140. package/dist/components/tarot-spread.d.ts +2 -24
  141. package/dist/components/tarot-spread.d.ts.map +1 -1
  142. package/dist/components/tarot-spread.js +39 -13
  143. package/dist/components/tarot-spread.js.map +2 -2
  144. package/dist/components/transits-table.d.ts +21 -0
  145. package/dist/components/transits-table.d.ts.map +1 -0
  146. package/dist/components/transits-table.js +515 -0
  147. package/dist/components/transits-table.js.map +7 -0
  148. package/dist/components/vedic-kundli.d.ts +5 -28
  149. package/dist/components/vedic-kundli.d.ts.map +1 -1
  150. package/dist/components/vedic-kundli.js +147 -83
  151. package/dist/components/vedic-kundli.js.map +3 -3
  152. package/dist/components/yoga-list.d.ts +29 -0
  153. package/dist/components/yoga-list.d.ts.map +1 -0
  154. package/dist/components/yoga-list.js +389 -0
  155. package/dist/components/yoga-list.js.map +7 -0
  156. package/dist/index.cjs +3693 -1180
  157. package/dist/index.cjs.map +4 -4
  158. package/dist/index.d.ts +11 -4
  159. package/dist/index.d.ts.map +1 -1
  160. package/dist/index.js +3709 -1196
  161. package/dist/index.js.map +4 -4
  162. package/dist/manifest.d.ts +43 -0
  163. package/dist/manifest.d.ts.map +1 -0
  164. package/dist/manifest.json +7 -2
  165. package/dist/styles/tokens.css +73 -1
  166. package/dist/tokens/index.d.ts +6 -0
  167. package/dist/tokens/index.d.ts.map +1 -1
  168. package/dist/types/index.d.ts +2 -0
  169. package/dist/types/index.d.ts.map +1 -0
  170. package/dist/types/types.gen.d.ts +27811 -0
  171. package/dist/types/types.gen.d.ts.map +1 -0
  172. package/dist/utils/debounce.d.ts +9 -1
  173. package/dist/utils/debounce.d.ts.map +1 -1
  174. package/dist/utils/format.d.ts +29 -0
  175. package/dist/utils/format.d.ts.map +1 -0
  176. package/dist/utils/kundli-render.d.ts +63 -0
  177. package/dist/utils/kundli-render.d.ts.map +1 -0
  178. package/dist/utils/string.d.ts +14 -0
  179. package/dist/utils/string.d.ts.map +1 -0
  180. package/dist/version.d.ts +2 -0
  181. package/dist/version.d.ts.map +1 -0
  182. package/package.json +7 -1
  183. package/src/components/ashtakavarga-grid.ts +354 -0
  184. package/src/components/biorhythm-chart.ts +39 -84
  185. package/src/components/choghadiya-grid.ts +185 -0
  186. package/src/components/compatibility-card.ts +85 -52
  187. package/src/components/dasha-timeline.ts +55 -73
  188. package/src/components/data.ts +28 -16
  189. package/src/components/divisional-chart.ts +214 -0
  190. package/src/components/dosha-card.ts +72 -68
  191. package/src/components/endpoint-form.ts +80 -18
  192. package/src/components/guna-milan.ts +87 -47
  193. package/src/components/hexagram.ts +53 -43
  194. package/src/components/horoscope-card.ts +59 -43
  195. package/src/components/kp-planets-table.ts +8 -27
  196. package/src/components/location-search.ts +47 -23
  197. package/src/components/moon-phase.ts +28 -25
  198. package/src/components/natal-chart.ts +364 -110
  199. package/src/components/numerology-card.ts +86 -84
  200. package/src/components/panchang-table.ts +40 -78
  201. package/src/components/shadbala-table.ts +286 -0
  202. package/src/components/synastry-chart.ts +213 -97
  203. package/src/components/tarot-card.ts +76 -62
  204. package/src/components/tarot-spread.ts +72 -45
  205. package/src/components/transits-table.ts +350 -0
  206. package/src/components/vedic-kundli.ts +59 -173
  207. package/src/components/yoga-list.ts +328 -0
  208. package/src/index.ts +18 -26
  209. package/src/manifest.ts +340 -0
  210. package/src/styles/tokens.css +73 -1
  211. package/src/tokens/index.ts +14 -0
  212. package/src/types/types.gen.ts +3 -3
  213. package/src/utils/debounce.ts +23 -4
  214. package/src/utils/format.ts +75 -0
  215. package/src/utils/kundli-render.ts +197 -0
  216. package/src/utils/string.ts +23 -0
  217. package/src/version.ts +2 -0
  218. package/dist/utils/motion.d.ts +0 -13
  219. package/dist/utils/motion.d.ts.map +0 -1
  220. package/src/utils/motion.ts +0 -18
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Single source of truth for component metadata. Every consumer that needs
3
+ * the (tag, pascal, slug, description, heading) tuple reads from here:
4
+ * scripts/build-react.ts, scripts/build-registry.ts, scripts/sync-docs.ts,
5
+ * scripts/build-widgets.ts, and the browser-side apps/docs/manifest.js
6
+ * (mirrored at build time).
7
+ *
8
+ * Hand-maintained. Add a component → add one entry here. The OpenAPI spec
9
+ * does not yet carry component metadata, so this stays manual.
10
+ */
11
+
12
+ export interface RoxyComponent {
13
+ /** Pascal-case React export name, e.g. RoxyNatalChart */
14
+ pascal: string;
15
+ /** Custom-element tag, e.g. roxy-natal-chart */
16
+ tag: string;
17
+ /** Slug used in registry filenames and shadcn paths, e.g. natal-chart */
18
+ slug: string;
19
+ /** Short human-readable heading shown on demo cards. */
20
+ heading: string;
21
+ /** One-line description for registry / docs / SEO meta. */
22
+ description: string;
23
+ /** Domain column label in the synced README/AGENTS table. */
24
+ docsLabel: string;
25
+ /** Endpoint(s) column body in the synced README/AGENTS table. */
26
+ endpointLabel: string;
27
+ /** What-it-renders column body in the synced README/AGENTS table. */
28
+ docsSummary: string;
29
+ /** Filter category in the browser demo grid. */
30
+ topic: string;
31
+ /**
32
+ * True when the component does not consume a typed RoxyAPI response from a
33
+ * customer server route. Three cases today:
34
+ * - <roxy-data>: pure renderer, accepts any shape, no fetch.
35
+ * - <roxy-location-search>: calls /location/search itself via publishable key.
36
+ * - <roxy-endpoint-form>: introspects the OpenAPI spec, emits roxy-submit.
37
+ * The shadcn registry codegen emits a different doc body for these so we
38
+ * never document a server route example with an undefined `data` reference.
39
+ */
40
+ selfFetching?: boolean;
41
+ }
42
+
43
+ export const ROXY_COMPONENTS: readonly RoxyComponent[] = [
44
+ {
45
+ pascal: 'RoxyNatalChart',
46
+ tag: 'roxy-natal-chart',
47
+ slug: 'natal-chart',
48
+ heading: 'Natal chart',
49
+ description:
50
+ 'Western natal chart wheel for /astrology/natal-chart responses',
51
+ docsLabel: 'Western',
52
+ endpointLabel: 'POST /astrology/natal-chart',
53
+ docsSummary: 'Natal chart wheel with planet glyphs and aspect lines',
54
+ topic: 'Astrology',
55
+ },
56
+ {
57
+ pascal: 'RoxyHoroscopeCard',
58
+ tag: 'roxy-horoscope-card',
59
+ slug: 'horoscope-card',
60
+ heading: 'Daily horoscope',
61
+ description:
62
+ 'Daily, weekly, or monthly horoscope card for /astrology/horoscope/...',
63
+ docsLabel: 'Western',
64
+ endpointLabel: 'GET /astrology/horoscope/{sign}/{daily,weekly,monthly}',
65
+ docsSummary: 'Daily, weekly, or monthly horoscope card',
66
+ topic: 'Astrology',
67
+ },
68
+ {
69
+ pascal: 'RoxySynastryChart',
70
+ tag: 'roxy-synastry-chart',
71
+ slug: 'synastry-chart',
72
+ heading: 'Synastry',
73
+ description: 'Dual-wheel synastry chart with inter-aspects table',
74
+ docsLabel: 'Western',
75
+ endpointLabel: 'POST /astrology/synastry',
76
+ docsSummary: 'Dual-wheel synastry with inter-aspects table',
77
+ topic: 'Astrology',
78
+ },
79
+ {
80
+ pascal: 'RoxyCompatibilityCard',
81
+ tag: 'roxy-compatibility-card',
82
+ slug: 'compatibility-card',
83
+ heading: 'Compatibility score',
84
+ description: 'Cross-domain compatibility score card',
85
+ docsLabel: 'Cross',
86
+ endpointLabel:
87
+ 'POST /astrology/compatibility-score, /numerology/compatibility, /biorhythm/compatibility',
88
+ docsSummary: 'Score card with category breakdown',
89
+ topic: 'Astrology',
90
+ },
91
+ {
92
+ pascal: 'RoxyMoonPhase',
93
+ tag: 'roxy-moon-phase',
94
+ slug: 'moon-phase',
95
+ heading: 'Moon phase',
96
+ description: 'Moon phase card and calendar',
97
+ docsLabel: 'Western',
98
+ endpointLabel: 'GET /astrology/moon-phase/{current,upcoming,calendar/...}',
99
+ docsSummary: 'Moon phase card and calendar',
100
+ topic: 'Astrology',
101
+ },
102
+ {
103
+ pascal: 'RoxyVedicKundli',
104
+ tag: 'roxy-vedic-kundli',
105
+ slug: 'vedic-kundli',
106
+ heading: 'Vedic kundli',
107
+ description:
108
+ 'South or North Indian Vedic kundli for /vedic-astrology/birth-chart',
109
+ docsLabel: 'Vedic',
110
+ endpointLabel: 'POST /vedic-astrology/birth-chart',
111
+ docsSummary: 'South or North Indian kundli',
112
+ topic: 'Vedic',
113
+ },
114
+ {
115
+ pascal: 'RoxyPanchangTable',
116
+ tag: 'roxy-panchang-table',
117
+ slug: 'panchang-table',
118
+ heading: 'Panchang',
119
+ description:
120
+ 'Panchang muhurta table with auspicious and inauspicious periods',
121
+ docsLabel: 'Vedic',
122
+ endpointLabel: 'POST /vedic-astrology/panchang/{basic,detailed}',
123
+ docsSummary: '15+ muhurtas in detailed mode',
124
+ topic: 'Vedic',
125
+ },
126
+ {
127
+ pascal: 'RoxyDashaTimeline',
128
+ tag: 'roxy-dasha-timeline',
129
+ slug: 'dasha-timeline',
130
+ heading: 'Vimshottari dasha',
131
+ description: 'Vimshottari dasha timeline with active mahadasha highlighted',
132
+ docsLabel: 'Vedic',
133
+ endpointLabel: 'POST /vedic-astrology/dasha/{current,major,sub/...}',
134
+ docsSummary: 'Vimshottari mahadasha + antardasha + pratyantardasha',
135
+ topic: 'Vedic',
136
+ },
137
+ {
138
+ pascal: 'RoxyDoshaCard',
139
+ tag: 'roxy-dosha-card',
140
+ slug: 'dosha-card',
141
+ heading: 'Manglik dosha',
142
+ description: 'Manglik, Kaal Sarp, or Sade Sati presence card',
143
+ docsLabel: 'Vedic',
144
+ endpointLabel: 'POST /vedic-astrology/dosha/{manglik,kalsarpa,sadhesati}',
145
+ docsSummary: 'Presence, severity, remedies, scoped effects',
146
+ topic: 'Vedic',
147
+ },
148
+ {
149
+ pascal: 'RoxyGunaMilan',
150
+ tag: 'roxy-guna-milan',
151
+ slug: 'guna-milan',
152
+ heading: 'Guna milan',
153
+ description: '36-point Ashtakoota matrimonial compatibility breakdown',
154
+ docsLabel: 'Vedic',
155
+ endpointLabel: 'POST /vedic-astrology/compatibility',
156
+ docsSummary: '36-point Ashtakoota with eight sub-scores',
157
+ topic: 'Vedic',
158
+ },
159
+ {
160
+ pascal: 'RoxyKpPlanetsTable',
161
+ tag: 'roxy-kp-planets-table',
162
+ slug: 'kp-planets-table',
163
+ heading: 'KP planets',
164
+ description: 'KP planets table with sub-lord and sub-sub-lord columns',
165
+ docsLabel: 'Vedic (KP)',
166
+ endpointLabel: 'POST /vedic-astrology/kp/planets',
167
+ docsSummary: 'Sub-lord and sub-sub-lord columns',
168
+ topic: 'Vedic',
169
+ },
170
+ {
171
+ pascal: 'RoxyTransitsTable',
172
+ tag: 'roxy-transits-table',
173
+ slug: 'transits-table',
174
+ heading: 'Transits',
175
+ description: 'Live planet positions plus aspects to a natal chart',
176
+ docsLabel: 'Western',
177
+ endpointLabel: 'POST /astrology/transits',
178
+ docsSummary:
179
+ 'Transit planet positions plus optional aspects to a natal chart',
180
+ topic: 'Astrology',
181
+ },
182
+ {
183
+ pascal: 'RoxyDivisionalChart',
184
+ tag: 'roxy-divisional-chart',
185
+ slug: 'divisional-chart',
186
+ heading: 'Divisional chart',
187
+ description: 'D2 to D60 varga chart wheel with Vargottama markers',
188
+ docsLabel: 'Vedic',
189
+ endpointLabel: 'POST /vedic-astrology/divisional-chart',
190
+ docsSummary:
191
+ 'Generic divisional varga wheel from D2 Hora to D60 Shashtiamsa',
192
+ topic: 'Vedic',
193
+ },
194
+ {
195
+ pascal: 'RoxyAshtakavargaGrid',
196
+ tag: 'roxy-ashtakavarga-grid',
197
+ slug: 'ashtakavarga-grid',
198
+ heading: 'Ashtakavarga',
199
+ description: 'Sarva and Bhinna ashtakavarga heatmap with bindu scores',
200
+ docsLabel: 'Vedic',
201
+ endpointLabel: 'POST /vedic-astrology/ashtakavarga',
202
+ docsSummary: 'Sarva, Bhinna, and Shodhya Pinda views in a tabbed heatmap',
203
+ topic: 'Vedic',
204
+ },
205
+ {
206
+ pascal: 'RoxyShadbalaTable',
207
+ tag: 'roxy-shadbala-table',
208
+ slug: 'shadbala-table',
209
+ heading: 'Shadbala',
210
+ description: 'Six-fold planetary strength with adequacy badge per planet',
211
+ docsLabel: 'Vedic',
212
+ endpointLabel: 'POST /vedic-astrology/shadbala',
213
+ docsSummary:
214
+ 'Six-fold planetary strength bar plus rupas and adequacy badge',
215
+ topic: 'Vedic',
216
+ },
217
+ {
218
+ pascal: 'RoxyYogaList',
219
+ tag: 'roxy-yoga-list',
220
+ slug: 'yoga-list',
221
+ heading: 'Yoga catalog',
222
+ description:
223
+ 'Yoga reference cards from the catalog with optional detail mode',
224
+ docsLabel: 'Vedic',
225
+ endpointLabel: 'GET /vedic-astrology/yoga, /yoga/{id}',
226
+ docsSummary: 'Filterable yoga cards from the 300 plus yoga catalog',
227
+ topic: 'Vedic',
228
+ },
229
+ {
230
+ pascal: 'RoxyChoghadiyaGrid',
231
+ tag: 'roxy-choghadiya-grid',
232
+ slug: 'choghadiya-grid',
233
+ heading: 'Choghadiya',
234
+ description: 'Day and night Choghadiya muhurta tiles for activity timing',
235
+ docsLabel: 'Vedic',
236
+ endpointLabel: 'POST /vedic-astrology/panchang/choghadiya',
237
+ docsSummary: 'Day and night Choghadiya muhurta tiles colored by effect',
238
+ topic: 'Vedic',
239
+ },
240
+ {
241
+ pascal: 'RoxyNumerologyCard',
242
+ tag: 'roxy-numerology-card',
243
+ slug: 'numerology-card',
244
+ heading: 'Life path number',
245
+ description:
246
+ 'Numerology card for life path, expression, personal year, or full chart',
247
+ docsLabel: 'Numerology',
248
+ endpointLabel:
249
+ 'POST /numerology/{life-path,expression,personal-year,chart}',
250
+ docsSummary: 'Life path, expression, personal year, full chart',
251
+ topic: 'Numerology',
252
+ },
253
+ {
254
+ pascal: 'RoxyTarotCard',
255
+ tag: 'roxy-tarot-card',
256
+ slug: 'tarot-card',
257
+ heading: 'Daily tarot card',
258
+ description: 'Single tarot card with upright/reversed flip animation',
259
+ docsLabel: 'Tarot',
260
+ endpointLabel: 'GET /tarot/cards/{id}, POST /tarot/daily',
261
+ docsSummary: 'Single card with upright and reversed flip',
262
+ topic: 'Tarot',
263
+ },
264
+ {
265
+ pascal: 'RoxyTarotSpread',
266
+ tag: 'roxy-tarot-spread',
267
+ slug: 'tarot-spread',
268
+ heading: 'Three-card spread',
269
+ description:
270
+ 'Tarot spread renderer for three-card, Celtic Cross, love, or yes/no',
271
+ docsLabel: 'Tarot',
272
+ endpointLabel:
273
+ 'POST /tarot/spreads/{three-card,celtic-cross,love}, /tarot/yes-no, /tarot/draw',
274
+ docsSummary: 'Spreads with positions and reading',
275
+ topic: 'Tarot',
276
+ },
277
+ {
278
+ pascal: 'RoxyBiorhythmChart',
279
+ tag: 'roxy-biorhythm-chart',
280
+ slug: 'biorhythm-chart',
281
+ heading: 'Daily biorhythm',
282
+ description: 'Daily biorhythm bars or multi-day forecast cycle lines',
283
+ docsLabel: 'Biorhythm',
284
+ endpointLabel: 'POST /biorhythm/{daily,forecast,critical-days}',
285
+ docsSummary: 'Daily bars, forecast cycle lines, critical days',
286
+ topic: 'Biorhythm',
287
+ },
288
+ {
289
+ pascal: 'RoxyHexagram',
290
+ tag: 'roxy-hexagram',
291
+ slug: 'hexagram',
292
+ heading: 'I Ching hexagram',
293
+ description:
294
+ 'I Ching hexagram with trigram glyphs, judgment, image, and changing lines',
295
+ docsLabel: 'I Ching',
296
+ endpointLabel:
297
+ 'GET /iching/hexagrams/{number}, /iching/cast, POST /iching/daily, /iching/daily/cast',
298
+ docsSummary: 'Hexagram with trigrams, judgment, image, changing lines',
299
+ topic: 'I Ching',
300
+ },
301
+ {
302
+ pascal: 'RoxyEndpointForm',
303
+ tag: 'roxy-endpoint-form',
304
+ slug: 'endpoint-form',
305
+ heading: 'Schema-driven form',
306
+ description:
307
+ 'Schema-driven form that emits roxy-submit with a validated payload',
308
+ docsLabel: 'Helper',
309
+ endpointLabel: 'Any endpoint via x-roxy-ui hints',
310
+ docsSummary: 'Schema-driven form, emits roxy-submit',
311
+ topic: 'Helpers',
312
+ selfFetching: true,
313
+ },
314
+ {
315
+ pascal: 'RoxyLocationSearch',
316
+ tag: 'roxy-location-search',
317
+ slug: 'location-search',
318
+ heading: 'City search',
319
+ description: 'City search input with debounced /location/search calls',
320
+ docsLabel: 'Helper',
321
+ endpointLabel: 'GET /location/search',
322
+ docsSummary: 'Debounced city search input, emits roxy-location-select',
323
+ topic: 'Helpers',
324
+ selfFetching: true,
325
+ },
326
+ {
327
+ pascal: 'RoxyData',
328
+ tag: 'roxy-data',
329
+ slug: 'data',
330
+ heading: 'Generic renderer',
331
+ description: 'Generic fallback renderer for any OpenAPI response shape',
332
+ docsLabel: 'Helper',
333
+ endpointLabel: 'Any response shape',
334
+ docsSummary: 'Generic fallback renderer for unknown shapes',
335
+ topic: 'Helpers',
336
+ selfFetching: true,
337
+ },
338
+ ];
339
+
340
+ export type RoxyComponentSlug = (typeof ROXY_COMPONENTS)[number]['slug'];
@@ -25,11 +25,17 @@
25
25
  * with non-text use) keep --roxy-accent. */
26
26
  --roxy-accent-fg: #b45309;
27
27
 
28
- /* Color: status */
28
+ /* Color: status. The base value (success, warning, danger, info) is for
29
+ * fills and tints. The -fg variant is darker so text on a light tint passes
30
+ * WCAG AA (>= 4.5:1 on white). Use -fg whenever status color hits text. */
29
31
  --roxy-success: #16a34a;
32
+ --roxy-success-fg: #166534;
30
33
  --roxy-warning: #ea580c;
34
+ --roxy-warning-fg: #9a3412;
31
35
  --roxy-danger: #dc2626;
36
+ --roxy-danger-fg: #991b1b;
32
37
  --roxy-info: #0284c7;
38
+ --roxy-info-fg: #075985;
33
39
 
34
40
  /* Color: surface */
35
41
  --roxy-bg: #ffffff;
@@ -83,6 +89,16 @@
83
89
  /* Motion */
84
90
  --roxy-motion-duration: 200ms;
85
91
  --roxy-motion-easing: cubic-bezier(0.4, 0, 0.2, 1);
92
+
93
+ /* Heat scale: 7-step gradient used by ashtakavarga bindu cells.
94
+ * Low bindus (1) are cool green; high bindus (7+) are hot red. */
95
+ --roxy-heat-1: #f0fdf4;
96
+ --roxy-heat-2: #d1fae5;
97
+ --roxy-heat-3: #a7f3d0;
98
+ --roxy-heat-4: #fde68a;
99
+ --roxy-heat-5: #fdba74;
100
+ --roxy-heat-6: #fb923c;
101
+ --roxy-heat-7: #ef4444;
86
102
  }
87
103
 
88
104
  /* Dark theme via system preference */
@@ -94,10 +110,18 @@
94
110
  --roxy-accent: #fbbf24;
95
111
  --roxy-accent-fg: #fbbf24;
96
112
 
113
+ /* Status -fg overrides must mirror the explicit [data-theme="dark"] block
114
+ * below. Without these, a user on system dark with no data-theme attribute
115
+ * inherits the light-mode -fg values (e.g. #166534 success) which renders
116
+ * as near-invisible dark green on a near-black surface and fails WCAG AA. */
97
117
  --roxy-success: #22c55e;
118
+ --roxy-success-fg: #86efac;
98
119
  --roxy-warning: #fb923c;
120
+ --roxy-warning-fg: #fdba74;
99
121
  --roxy-danger: #ef4444;
122
+ --roxy-danger-fg: #fca5a5;
100
123
  --roxy-info: #38bdf8;
124
+ --roxy-info-fg: #7dd3fc;
101
125
 
102
126
  --roxy-bg: #0a0a0a;
103
127
  --roxy-fg: #fafafa;
@@ -109,9 +133,45 @@
109
133
  --roxy-shadow-md:
110
134
  0 4px 6px -1px rgba(0, 0, 0, 0.6), 0 2px 4px -2px rgba(0, 0, 0, 0.5);
111
135
  --roxy-shadow-lg: 0 12px 24px -8px rgba(0, 0, 0, 0.7);
136
+
137
+ --roxy-heat-1: #052e16;
138
+ --roxy-heat-2: #14532d;
139
+ --roxy-heat-3: #166534;
140
+ --roxy-heat-4: #92400e;
141
+ --roxy-heat-5: #b45309;
142
+ --roxy-heat-6: #c2410c;
143
+ --roxy-heat-7: #b91c1c;
112
144
  }
113
145
  }
114
146
 
147
+ /* Light theme override. Beats the @media (prefers-color-scheme: dark) block
148
+ * when the host explicitly opts back into light. Without this, a dark-mode OS
149
+ * pins the tokens to dark even after data-theme="light" is set. */
150
+ :root[data-theme="light"],
151
+ :host([data-theme="light"]),
152
+ .light :host {
153
+ --roxy-primary: #0f172a;
154
+ --roxy-secondary: #475569;
155
+ --roxy-accent: #f59e0b;
156
+ --roxy-accent-fg: #b45309;
157
+
158
+ --roxy-success: #16a34a;
159
+ --roxy-warning: #ea580c;
160
+ --roxy-danger: #dc2626;
161
+ --roxy-info: #0284c7;
162
+
163
+ --roxy-bg: #ffffff;
164
+ --roxy-fg: #0a0a0a;
165
+ --roxy-muted: #71717a;
166
+ --roxy-border: #e4e4e7;
167
+ --roxy-ring: rgba(245, 158, 11, 0.4);
168
+
169
+ --roxy-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
170
+ --roxy-shadow-md:
171
+ 0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -2px rgba(0, 0, 0, 0.06);
172
+ --roxy-shadow-lg: 0 12px 24px -8px rgba(0, 0, 0, 0.14);
173
+ }
174
+
115
175
  /* Dark theme via host opt-in */
116
176
  :root[data-theme="dark"],
117
177
  :host([data-theme="dark"]),
@@ -122,9 +182,13 @@
122
182
  --roxy-accent-fg: #fbbf24;
123
183
 
124
184
  --roxy-success: #22c55e;
185
+ --roxy-success-fg: #86efac;
125
186
  --roxy-warning: #fb923c;
187
+ --roxy-warning-fg: #fdba74;
126
188
  --roxy-danger: #ef4444;
189
+ --roxy-danger-fg: #fca5a5;
127
190
  --roxy-info: #38bdf8;
191
+ --roxy-info-fg: #7dd3fc;
128
192
 
129
193
  --roxy-bg: #0a0a0a;
130
194
  --roxy-fg: #fafafa;
@@ -136,6 +200,14 @@
136
200
  --roxy-shadow-md:
137
201
  0 4px 6px -1px rgba(0, 0, 0, 0.6), 0 2px 4px -2px rgba(0, 0, 0, 0.5);
138
202
  --roxy-shadow-lg: 0 12px 24px -8px rgba(0, 0, 0, 0.7);
203
+
204
+ --roxy-heat-1: #052e16;
205
+ --roxy-heat-2: #14532d;
206
+ --roxy-heat-3: #166534;
207
+ --roxy-heat-4: #92400e;
208
+ --roxy-heat-5: #b45309;
209
+ --roxy-heat-6: #c2410c;
210
+ --roxy-heat-7: #b91c1c;
139
211
  }
140
212
 
141
213
  /* Reduced motion override */
@@ -22,6 +22,11 @@ export const PLANET_GLYPH: Record<string, string> = {
22
22
  Lagna: 'La',
23
23
  NorthNode: '☊',
24
24
  SouthNode: '☋',
25
+ 'North node': '☊',
26
+ 'South node': '☋',
27
+ Chiron: '⚷',
28
+ Lilith: '⚸',
29
+ 'Black moon lilith': '⚸',
25
30
  };
26
31
 
27
32
  export const PLANET_ABBR: Record<string, string> = {
@@ -86,6 +91,15 @@ export const SIGNS_ORDER = [
86
91
  'Pisces',
87
92
  ] as const;
88
93
 
94
+ /**
95
+ * Lowercase rashi keys in canonical zodiac order. Derived from `SIGNS_ORDER`
96
+ * so the two stay in lockstep. The /vedic-astrology/birth-chart response
97
+ * carries planet buckets keyed by these names.
98
+ */
99
+ export const RASHI_KEYS = SIGNS_ORDER.map((s) =>
100
+ s.toLowerCase(),
101
+ ) as readonly Lowercase<(typeof SIGNS_ORDER)[number]>[];
102
+
89
103
  /** Aspect symbols. Used by synastry and natal chart aspect tables. */
90
104
  export const ASPECT_SYMBOL: Record<string, string> = {
91
105
  conjunction: '☌',
@@ -27907,7 +27907,7 @@ export type ListCountriesData = {
27907
27907
  path?: never;
27908
27908
  query?: {
27909
27909
  /**
27910
- * Maximum items to return per page. Range: 1-50, default 50.
27910
+ * Maximum items to return per page. Range: 1-250, default 50.
27911
27911
  */
27912
27912
  limit?: number;
27913
27913
  /**
@@ -28024,7 +28024,7 @@ export type ListCountriesError = ListCountriesErrors[keyof ListCountriesErrors];
28024
28024
 
28025
28025
  export type ListCountriesResponses = {
28026
28026
  /**
28027
- * Alphabetically sorted list of all 227 countries with ISO codes and city counts
28027
+ * Alphabetically sorted list of all countries with ISO codes and city counts
28028
28028
  */
28029
28029
  200: {
28030
28030
  /**
@@ -28075,7 +28075,7 @@ export type GetCitiesByCountryData = {
28075
28075
  };
28076
28076
  query?: {
28077
28077
  /**
28078
- * Maximum items to return per page. Range: 1-200, default 50.
28078
+ * Maximum items to return per page. Range: 1-100, default 20.
28079
28079
  */
28080
28080
  limit?: number;
28081
28081
  /**
@@ -1,13 +1,32 @@
1
1
  /**
2
2
  * Lightweight debounce for input handlers. Used by location search.
3
+ *
4
+ * The returned function exposes a `.cancel()` method so callers can clear a
5
+ * pending invocation when the host element disconnects, preventing the timer
6
+ * from firing on a detached node and mutating reactive state after teardown.
3
7
  */
8
+ export interface Debounced<F extends (...args: never[]) => unknown> {
9
+ (...args: Parameters<F>): void;
10
+ cancel: () => void;
11
+ }
12
+
4
13
  export function debounce<F extends (...args: never[]) => unknown>(
5
14
  fn: F,
6
15
  wait: number,
7
- ): F {
16
+ ): Debounced<F> {
8
17
  let timer: ReturnType<typeof setTimeout> | undefined;
9
- return ((...args: Parameters<F>) => {
18
+ const debounced = ((...args: Parameters<F>) => {
10
19
  if (timer) clearTimeout(timer);
11
- timer = setTimeout(() => fn(...args), wait);
12
- }) as F;
20
+ timer = setTimeout(() => {
21
+ timer = undefined;
22
+ fn(...args);
23
+ }, wait);
24
+ }) as Debounced<F>;
25
+ debounced.cancel = () => {
26
+ if (timer) {
27
+ clearTimeout(timer);
28
+ timer = undefined;
29
+ }
30
+ };
31
+ return debounced;
13
32
  }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Display formatters for ISO timestamps and floats coming back from the API.
3
+ * Every helper returns "" for nullish or unparseable input so it falls out of
4
+ * template literals cleanly.
5
+ */
6
+
7
+ export function formatTime(input: unknown): string {
8
+ if (typeof input !== 'string' || input.length === 0) return '';
9
+ if (/^\d{4}-\d{2}-\d{2}$/.test(input)) return '';
10
+ const bareTime = /^\d{2}:\d{2}(:\d{2})?$/.test(input);
11
+ const iso = bareTime ? `1970-01-01T${input}` : input;
12
+ const d = new Date(iso);
13
+ if (Number.isNaN(d.getTime())) return input;
14
+ return d.toLocaleTimeString(undefined, {
15
+ hour: 'numeric',
16
+ minute: '2-digit',
17
+ hour12: true,
18
+ });
19
+ }
20
+
21
+ export function formatDate(input: unknown): string {
22
+ if (typeof input !== 'string' || input.length === 0) return '';
23
+ const d = new Date(
24
+ /^\d{4}-\d{2}-\d{2}$/.test(input) ? `${input}T00:00:00` : input,
25
+ );
26
+ if (Number.isNaN(d.getTime())) return input;
27
+ return d.toLocaleDateString(undefined, {
28
+ month: 'short',
29
+ day: 'numeric',
30
+ year: 'numeric',
31
+ });
32
+ }
33
+
34
+ export function formatTimeRange(
35
+ t: { start?: string; end?: string } | undefined,
36
+ ): string {
37
+ if (!t) return '';
38
+ const start = formatTime(t.start);
39
+ const end = formatTime(t.end);
40
+ if (start && end) return `${start} - ${end}`;
41
+ return start || end || '';
42
+ }
43
+
44
+ export function formatNumber(value: unknown, dp = 1): string {
45
+ if (typeof value !== 'number' || !Number.isFinite(value)) return '';
46
+ return value.toFixed(dp).replace(/\.?0+$/, '');
47
+ }
48
+
49
+ export function formatPercent(value: unknown, dp = 1): string {
50
+ const n = formatNumber(value, dp);
51
+ return n ? `${n}%` : '';
52
+ }
53
+
54
+ /**
55
+ * CSS class name per aspect type. Used by natal and synastry chart aspect
56
+ * lines so the same color encoding (harmonious vs challenging) applies in
57
+ * both wheels. Keys are lowercase canonical names, values are CSS class
58
+ * suffixes the chart components define in their `:host` styles.
59
+ */
60
+ export const ASPECT_CLASS: Record<string, string> = {
61
+ conjunction: 'aspect-conjunction',
62
+ sextile: 'aspect-sextile',
63
+ square: 'aspect-square',
64
+ trine: 'aspect-trine',
65
+ opposition: 'aspect-opposition',
66
+ };
67
+
68
+ /**
69
+ * Normalize an aspect entry's `type` field to a lowercase, hyphen-separated
70
+ * canonical name (`SEMI_SEXTILE` → `semi-sextile`). Accepts any aspect-shaped
71
+ * object so both natal and synastry inter-aspect entries can share this.
72
+ */
73
+ export function normalizeAspect(a: { type?: string }): string {
74
+ return (a.type ?? '').toLowerCase().replace(/_/g, '-');
75
+ }