@roxyapi/ui 0.9.0 → 0.11.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 (378) hide show
  1. package/AGENTS.md +53 -27
  2. package/README.md +42 -12
  3. package/components-catalog.json +1022 -0
  4. package/dist/cdn/components/angel-number-card.js +52 -0
  5. package/dist/cdn/components/angel-number-card.js.map +7 -0
  6. package/dist/cdn/components/angel-number-lookup.js +52 -0
  7. package/dist/cdn/components/angel-number-lookup.js.map +7 -0
  8. package/dist/cdn/components/ashtakavarga-grid.js +10 -3
  9. package/dist/cdn/components/ashtakavarga-grid.js.map +4 -4
  10. package/dist/cdn/components/aspects-table.js +52 -0
  11. package/dist/cdn/components/aspects-table.js.map +7 -0
  12. package/dist/cdn/components/biorhythm-chart.js +10 -3
  13. package/dist/cdn/components/biorhythm-chart.js.map +4 -4
  14. package/dist/cdn/components/bodygraph.js +17 -10
  15. package/dist/cdn/components/bodygraph.js.map +4 -4
  16. package/dist/cdn/components/choghadiya-grid.js +10 -3
  17. package/dist/cdn/components/choghadiya-grid.js.map +4 -4
  18. package/dist/cdn/components/compatibility-card.js +10 -3
  19. package/dist/cdn/components/compatibility-card.js.map +4 -4
  20. package/dist/cdn/components/crystal-card.js +52 -0
  21. package/dist/cdn/components/crystal-card.js.map +7 -0
  22. package/dist/cdn/components/crystal-grid.js +52 -0
  23. package/dist/cdn/components/crystal-grid.js.map +7 -0
  24. package/dist/cdn/components/dasha-timeline.js +10 -3
  25. package/dist/cdn/components/dasha-timeline.js.map +4 -4
  26. package/dist/cdn/components/data.js +10 -3
  27. package/dist/cdn/components/data.js.map +4 -4
  28. package/dist/cdn/components/divisional-chart.js +31 -24
  29. package/dist/cdn/components/divisional-chart.js.map +4 -4
  30. package/dist/cdn/components/dosha-card.js +10 -3
  31. package/dist/cdn/components/dosha-card.js.map +4 -4
  32. package/dist/cdn/components/dream-card.js +52 -0
  33. package/dist/cdn/components/dream-card.js.map +7 -0
  34. package/dist/cdn/components/dream-search.js +52 -0
  35. package/dist/cdn/components/dream-search.js.map +7 -0
  36. package/dist/cdn/components/endpoint-form.js +3 -3
  37. package/dist/cdn/components/endpoint-form.js.map +3 -3
  38. package/dist/cdn/components/forecast-digest.js +52 -0
  39. package/dist/cdn/components/forecast-digest.js.map +7 -0
  40. package/dist/cdn/components/forecast-timeline.js +10 -3
  41. package/dist/cdn/components/forecast-timeline.js.map +4 -4
  42. package/dist/cdn/components/guna-milan.js +10 -3
  43. package/dist/cdn/components/guna-milan.js.map +4 -4
  44. package/dist/cdn/components/hd-connection.js +52 -0
  45. package/dist/cdn/components/hd-connection.js.map +7 -0
  46. package/dist/cdn/components/hd-penta.js +52 -0
  47. package/dist/cdn/components/hd-penta.js.map +7 -0
  48. package/dist/cdn/components/hd-variables.js +52 -0
  49. package/dist/cdn/components/hd-variables.js.map +7 -0
  50. package/dist/cdn/components/hexagram.js +10 -3
  51. package/dist/cdn/components/hexagram.js.map +4 -4
  52. package/dist/cdn/components/hora-table.js +52 -0
  53. package/dist/cdn/components/hora-table.js.map +7 -0
  54. package/dist/cdn/components/horoscope-card.js +10 -3
  55. package/dist/cdn/components/horoscope-card.js.map +4 -4
  56. package/dist/cdn/components/kp-chart.js +10 -3
  57. package/dist/cdn/components/kp-chart.js.map +4 -4
  58. package/dist/cdn/components/kp-planets-table.js +10 -3
  59. package/dist/cdn/components/kp-planets-table.js.map +4 -4
  60. package/dist/cdn/components/kp-ruling-planets.js +10 -3
  61. package/dist/cdn/components/kp-ruling-planets.js.map +4 -4
  62. package/dist/cdn/components/location-search.js +3 -3
  63. package/dist/cdn/components/location-search.js.map +2 -2
  64. package/dist/cdn/components/moon-phase.js +10 -3
  65. package/dist/cdn/components/moon-phase.js.map +4 -4
  66. package/dist/cdn/components/nakshatra-card.js +10 -3
  67. package/dist/cdn/components/nakshatra-card.js.map +4 -4
  68. package/dist/cdn/components/natal-chart.js +16 -9
  69. package/dist/cdn/components/natal-chart.js.map +4 -4
  70. package/dist/cdn/components/numerology-card.js +10 -3
  71. package/dist/cdn/components/numerology-card.js.map +4 -4
  72. package/dist/cdn/components/panchang-table.js +10 -3
  73. package/dist/cdn/components/panchang-table.js.map +4 -4
  74. package/dist/cdn/components/reference-card.js +52 -0
  75. package/dist/cdn/components/reference-card.js.map +7 -0
  76. package/dist/cdn/components/shadbala-table.js +10 -3
  77. package/dist/cdn/components/shadbala-table.js.map +4 -4
  78. package/dist/cdn/components/synastry-chart.js +16 -9
  79. package/dist/cdn/components/synastry-chart.js.map +4 -4
  80. package/dist/cdn/components/tarot-card.js +10 -3
  81. package/dist/cdn/components/tarot-card.js.map +4 -4
  82. package/dist/cdn/components/tarot-catalog.js +52 -0
  83. package/dist/cdn/components/tarot-catalog.js.map +7 -0
  84. package/dist/cdn/components/tarot-spread.js +10 -3
  85. package/dist/cdn/components/tarot-spread.js.map +4 -4
  86. package/dist/cdn/components/transits-table.js +10 -3
  87. package/dist/cdn/components/transits-table.js.map +4 -4
  88. package/dist/cdn/components/vedic-aspects.js +52 -0
  89. package/dist/cdn/components/vedic-aspects.js.map +7 -0
  90. package/dist/cdn/components/vedic-kundli.js +31 -24
  91. package/dist/cdn/components/vedic-kundli.js.map +4 -4
  92. package/dist/cdn/components/vedic-planets-table.js +10 -3
  93. package/dist/cdn/components/vedic-planets-table.js.map +4 -4
  94. package/dist/cdn/components/western-planets-table.js +10 -3
  95. package/dist/cdn/components/western-planets-table.js.map +4 -4
  96. package/dist/cdn/components/yoga-list.js +10 -3
  97. package/dist/cdn/components/yoga-list.js.map +4 -4
  98. package/dist/cdn/roxy-ui.js +92 -81
  99. package/dist/cdn/roxy-ui.js.map +4 -4
  100. package/dist/components/angel-number-card.d.ts +17 -0
  101. package/dist/components/angel-number-card.d.ts.map +1 -0
  102. package/dist/components/angel-number-card.js +2 -0
  103. package/dist/components/angel-number-card.js.map +7 -0
  104. package/dist/components/angel-number-lookup.d.ts +21 -0
  105. package/dist/components/angel-number-lookup.d.ts.map +1 -0
  106. package/dist/components/angel-number-lookup.js +2 -0
  107. package/dist/components/angel-number-lookup.js.map +7 -0
  108. package/dist/components/ashtakavarga-grid.d.ts +4 -5
  109. package/dist/components/ashtakavarga-grid.d.ts.map +1 -1
  110. package/dist/components/ashtakavarga-grid.js +1 -1
  111. package/dist/components/ashtakavarga-grid.js.map +4 -4
  112. package/dist/components/aspects-table.d.ts +23 -0
  113. package/dist/components/aspects-table.d.ts.map +1 -0
  114. package/dist/components/aspects-table.js +2 -0
  115. package/dist/components/aspects-table.js.map +7 -0
  116. package/dist/components/biorhythm-chart.d.ts +4 -5
  117. package/dist/components/biorhythm-chart.d.ts.map +1 -1
  118. package/dist/components/biorhythm-chart.js +1 -1
  119. package/dist/components/biorhythm-chart.js.map +4 -4
  120. package/dist/components/bodygraph.d.ts +4 -5
  121. package/dist/components/bodygraph.d.ts.map +1 -1
  122. package/dist/components/bodygraph.js +9 -9
  123. package/dist/components/bodygraph.js.map +4 -4
  124. package/dist/components/choghadiya-grid.d.ts +4 -5
  125. package/dist/components/choghadiya-grid.d.ts.map +1 -1
  126. package/dist/components/choghadiya-grid.js +1 -1
  127. package/dist/components/choghadiya-grid.js.map +4 -4
  128. package/dist/components/compatibility-card.d.ts +4 -5
  129. package/dist/components/compatibility-card.d.ts.map +1 -1
  130. package/dist/components/compatibility-card.js +1 -1
  131. package/dist/components/compatibility-card.js.map +4 -4
  132. package/dist/components/crystal-card.d.ts +19 -0
  133. package/dist/components/crystal-card.d.ts.map +1 -0
  134. package/dist/components/crystal-card.js +2 -0
  135. package/dist/components/crystal-card.js.map +7 -0
  136. package/dist/components/crystal-grid.d.ts +26 -0
  137. package/dist/components/crystal-grid.d.ts.map +1 -0
  138. package/dist/components/crystal-grid.js +2 -0
  139. package/dist/components/crystal-grid.js.map +7 -0
  140. package/dist/components/dasha-timeline.d.ts +4 -5
  141. package/dist/components/dasha-timeline.d.ts.map +1 -1
  142. package/dist/components/dasha-timeline.js +1 -1
  143. package/dist/components/dasha-timeline.js.map +4 -4
  144. package/dist/components/data.d.ts +5 -8
  145. package/dist/components/data.d.ts.map +1 -1
  146. package/dist/components/data.js +1 -1
  147. package/dist/components/data.js.map +4 -4
  148. package/dist/components/divisional-chart.d.ts +4 -5
  149. package/dist/components/divisional-chart.d.ts.map +1 -1
  150. package/dist/components/divisional-chart.js +59 -59
  151. package/dist/components/divisional-chart.js.map +4 -4
  152. package/dist/components/dosha-card.d.ts +4 -5
  153. package/dist/components/dosha-card.d.ts.map +1 -1
  154. package/dist/components/dosha-card.js +1 -1
  155. package/dist/components/dosha-card.js.map +4 -4
  156. package/dist/components/dream-card.d.ts +16 -0
  157. package/dist/components/dream-card.d.ts.map +1 -0
  158. package/dist/components/dream-card.js +2 -0
  159. package/dist/components/dream-card.js.map +7 -0
  160. package/dist/components/dream-search.d.ts +18 -0
  161. package/dist/components/dream-search.d.ts.map +1 -0
  162. package/dist/components/dream-search.js +2 -0
  163. package/dist/components/dream-search.js.map +7 -0
  164. package/dist/components/endpoint-form.d.ts +10 -5
  165. package/dist/components/endpoint-form.d.ts.map +1 -1
  166. package/dist/components/endpoint-form.js +1 -1
  167. package/dist/components/endpoint-form.js.map +3 -3
  168. package/dist/components/forecast-digest.d.ts +19 -0
  169. package/dist/components/forecast-digest.d.ts.map +1 -0
  170. package/dist/components/forecast-digest.js +2 -0
  171. package/dist/components/forecast-digest.js.map +7 -0
  172. package/dist/components/forecast-timeline.d.ts +8 -6
  173. package/dist/components/forecast-timeline.d.ts.map +1 -1
  174. package/dist/components/forecast-timeline.js +1 -1
  175. package/dist/components/forecast-timeline.js.map +4 -4
  176. package/dist/components/guna-milan.d.ts +4 -5
  177. package/dist/components/guna-milan.d.ts.map +1 -1
  178. package/dist/components/guna-milan.js +1 -1
  179. package/dist/components/guna-milan.js.map +4 -4
  180. package/dist/components/hd-connection.d.ts +18 -0
  181. package/dist/components/hd-connection.d.ts.map +1 -0
  182. package/dist/components/hd-connection.js +2 -0
  183. package/dist/components/hd-connection.js.map +7 -0
  184. package/dist/components/hd-penta.d.ts +18 -0
  185. package/dist/components/hd-penta.d.ts.map +1 -0
  186. package/dist/components/hd-penta.js +2 -0
  187. package/dist/components/hd-penta.js.map +7 -0
  188. package/dist/components/hd-variables.d.ts +17 -0
  189. package/dist/components/hd-variables.d.ts.map +1 -0
  190. package/dist/components/hd-variables.js +2 -0
  191. package/dist/components/hd-variables.js.map +7 -0
  192. package/dist/components/hexagram.d.ts +4 -5
  193. package/dist/components/hexagram.d.ts.map +1 -1
  194. package/dist/components/hexagram.js +1 -1
  195. package/dist/components/hexagram.js.map +4 -4
  196. package/dist/components/hora-table.d.ts +17 -0
  197. package/dist/components/hora-table.d.ts.map +1 -0
  198. package/dist/components/hora-table.js +2 -0
  199. package/dist/components/hora-table.js.map +7 -0
  200. package/dist/components/horoscope-card.d.ts +4 -5
  201. package/dist/components/horoscope-card.d.ts.map +1 -1
  202. package/dist/components/horoscope-card.js +1 -1
  203. package/dist/components/horoscope-card.js.map +4 -4
  204. package/dist/components/kp-chart.d.ts +4 -5
  205. package/dist/components/kp-chart.d.ts.map +1 -1
  206. package/dist/components/kp-chart.js +1 -1
  207. package/dist/components/kp-chart.js.map +4 -4
  208. package/dist/components/kp-planets-table.d.ts +4 -5
  209. package/dist/components/kp-planets-table.d.ts.map +1 -1
  210. package/dist/components/kp-planets-table.js +1 -1
  211. package/dist/components/kp-planets-table.js.map +4 -4
  212. package/dist/components/kp-ruling-planets.d.ts +4 -5
  213. package/dist/components/kp-ruling-planets.d.ts.map +1 -1
  214. package/dist/components/kp-ruling-planets.js +1 -1
  215. package/dist/components/kp-ruling-planets.js.map +4 -4
  216. package/dist/components/location-search.js +1 -1
  217. package/dist/components/location-search.js.map +2 -2
  218. package/dist/components/moon-phase.d.ts +5 -5
  219. package/dist/components/moon-phase.d.ts.map +1 -1
  220. package/dist/components/moon-phase.js +1 -1
  221. package/dist/components/moon-phase.js.map +4 -4
  222. package/dist/components/nakshatra-card.d.ts +4 -5
  223. package/dist/components/nakshatra-card.d.ts.map +1 -1
  224. package/dist/components/nakshatra-card.js +1 -1
  225. package/dist/components/nakshatra-card.js.map +4 -4
  226. package/dist/components/natal-chart.d.ts +4 -5
  227. package/dist/components/natal-chart.d.ts.map +1 -1
  228. package/dist/components/natal-chart.js +8 -8
  229. package/dist/components/natal-chart.js.map +4 -4
  230. package/dist/components/numerology-card.d.ts +15 -10
  231. package/dist/components/numerology-card.d.ts.map +1 -1
  232. package/dist/components/numerology-card.js +1 -1
  233. package/dist/components/numerology-card.js.map +4 -4
  234. package/dist/components/panchang-table.d.ts +4 -5
  235. package/dist/components/panchang-table.d.ts.map +1 -1
  236. package/dist/components/panchang-table.js +1 -1
  237. package/dist/components/panchang-table.js.map +4 -4
  238. package/dist/components/reference-card.d.ts +19 -0
  239. package/dist/components/reference-card.d.ts.map +1 -0
  240. package/dist/components/reference-card.js +2 -0
  241. package/dist/components/reference-card.js.map +7 -0
  242. package/dist/components/shadbala-table.d.ts +4 -5
  243. package/dist/components/shadbala-table.d.ts.map +1 -1
  244. package/dist/components/shadbala-table.js +1 -1
  245. package/dist/components/shadbala-table.js.map +4 -4
  246. package/dist/components/synastry-chart.d.ts +4 -5
  247. package/dist/components/synastry-chart.d.ts.map +1 -1
  248. package/dist/components/synastry-chart.js +7 -7
  249. package/dist/components/synastry-chart.js.map +4 -4
  250. package/dist/components/tarot-card.d.ts +4 -5
  251. package/dist/components/tarot-card.d.ts.map +1 -1
  252. package/dist/components/tarot-card.js +1 -1
  253. package/dist/components/tarot-card.js.map +4 -4
  254. package/dist/components/tarot-catalog.d.ts +20 -0
  255. package/dist/components/tarot-catalog.d.ts.map +1 -0
  256. package/dist/components/tarot-catalog.js +2 -0
  257. package/dist/components/tarot-catalog.js.map +7 -0
  258. package/dist/components/tarot-spread.d.ts +7 -8
  259. package/dist/components/tarot-spread.d.ts.map +1 -1
  260. package/dist/components/tarot-spread.js +1 -1
  261. package/dist/components/tarot-spread.js.map +4 -4
  262. package/dist/components/transits-table.d.ts +4 -5
  263. package/dist/components/transits-table.d.ts.map +1 -1
  264. package/dist/components/transits-table.js +1 -1
  265. package/dist/components/transits-table.js.map +4 -4
  266. package/dist/components/vedic-aspects.d.ts +16 -0
  267. package/dist/components/vedic-aspects.d.ts.map +1 -0
  268. package/dist/components/vedic-aspects.js +2 -0
  269. package/dist/components/vedic-aspects.js.map +7 -0
  270. package/dist/components/vedic-kundli.d.ts +22 -5
  271. package/dist/components/vedic-kundli.d.ts.map +1 -1
  272. package/dist/components/vedic-kundli.js +63 -63
  273. package/dist/components/vedic-kundli.js.map +4 -4
  274. package/dist/components/vedic-planets-table.d.ts +4 -5
  275. package/dist/components/vedic-planets-table.d.ts.map +1 -1
  276. package/dist/components/vedic-planets-table.js +1 -1
  277. package/dist/components/vedic-planets-table.js.map +4 -4
  278. package/dist/components/western-planets-table.d.ts +4 -5
  279. package/dist/components/western-planets-table.d.ts.map +1 -1
  280. package/dist/components/western-planets-table.js +1 -1
  281. package/dist/components/western-planets-table.js.map +4 -4
  282. package/dist/components/yoga-list.d.ts +6 -7
  283. package/dist/components/yoga-list.d.ts.map +1 -1
  284. package/dist/components/yoga-list.js +1 -1
  285. package/dist/components/yoga-list.js.map +4 -4
  286. package/dist/generated/endpoint-bindings.d.ts +15 -0
  287. package/dist/generated/endpoint-bindings.d.ts.map +1 -0
  288. package/dist/index.cjs +73 -73
  289. package/dist/index.cjs.map +4 -4
  290. package/dist/index.d.ts +16 -0
  291. package/dist/index.d.ts.map +1 -1
  292. package/dist/index.js +71 -71
  293. package/dist/index.js.map +4 -4
  294. package/dist/manifest.d.ts.map +1 -1
  295. package/dist/manifest.json +39 -24
  296. package/dist/styles/tokens-css.d.ts +1 -1
  297. package/dist/styles/tokens-css.d.ts.map +1 -1
  298. package/dist/styles/tokens.css +4 -0
  299. package/dist/types/index.d.ts +1 -1
  300. package/dist/types/index.d.ts.map +1 -1
  301. package/dist/types/types.gen.d.ts +1103 -164
  302. package/dist/types/types.gen.d.ts.map +1 -1
  303. package/dist/utils/angel-sections.d.ts +14 -0
  304. package/dist/utils/angel-sections.d.ts.map +1 -0
  305. package/dist/utils/base-element.d.ts +73 -0
  306. package/dist/utils/base-element.d.ts.map +1 -0
  307. package/dist/utils/base-styles.d.ts.map +1 -1
  308. package/dist/utils/fetch-controller.d.ts +60 -0
  309. package/dist/utils/fetch-controller.d.ts.map +1 -0
  310. package/dist/utils/kundli-render.d.ts +2 -1
  311. package/dist/utils/kundli-render.d.ts.map +1 -1
  312. package/dist/utils/kundli-styles.d.ts.map +1 -1
  313. package/dist/utils/markup-data.d.ts +34 -0
  314. package/dist/utils/markup-data.d.ts.map +1 -1
  315. package/dist/version.d.ts +1 -1
  316. package/dist/version.d.ts.map +1 -1
  317. package/package.json +2 -1
  318. package/src/components/angel-number-card.ts +210 -0
  319. package/src/components/angel-number-lookup.ts +207 -0
  320. package/src/components/ashtakavarga-grid.ts +15 -20
  321. package/src/components/aspects-table.ts +329 -0
  322. package/src/components/biorhythm-chart.ts +14 -18
  323. package/src/components/bodygraph.ts +9 -20
  324. package/src/components/choghadiya-grid.ts +15 -19
  325. package/src/components/compatibility-card.ts +9 -19
  326. package/src/components/crystal-card.ts +242 -0
  327. package/src/components/crystal-grid.ts +182 -0
  328. package/src/components/dasha-timeline.ts +9 -20
  329. package/src/components/data.ts +8 -27
  330. package/src/components/divisional-chart.ts +10 -18
  331. package/src/components/dosha-card.ts +8 -19
  332. package/src/components/dream-card.ts +88 -0
  333. package/src/components/dream-search.ts +135 -0
  334. package/src/components/endpoint-form.ts +149 -55
  335. package/src/components/forecast-digest.ts +213 -0
  336. package/src/components/forecast-timeline.ts +24 -19
  337. package/src/components/guna-milan.ts +8 -19
  338. package/src/components/hd-connection.ts +188 -0
  339. package/src/components/hd-penta.ts +165 -0
  340. package/src/components/hd-variables.ts +128 -0
  341. package/src/components/hexagram.ts +10 -18
  342. package/src/components/hora-table.ts +149 -0
  343. package/src/components/horoscope-card.ts +9 -19
  344. package/src/components/kp-chart.ts +11 -20
  345. package/src/components/kp-planets-table.ts +11 -20
  346. package/src/components/kp-ruling-planets.ts +8 -18
  347. package/src/components/moon-phase.ts +10 -19
  348. package/src/components/nakshatra-card.ts +11 -20
  349. package/src/components/natal-chart.ts +20 -23
  350. package/src/components/numerology-card.ts +90 -31
  351. package/src/components/panchang-table.ts +9 -19
  352. package/src/components/reference-card.ts +212 -0
  353. package/src/components/shadbala-table.ts +15 -18
  354. package/src/components/synastry-chart.ts +17 -20
  355. package/src/components/tarot-card.ts +9 -20
  356. package/src/components/tarot-catalog.ts +129 -0
  357. package/src/components/tarot-spread.ts +20 -21
  358. package/src/components/transits-table.ts +17 -20
  359. package/src/components/vedic-aspects.ts +188 -0
  360. package/src/components/vedic-kundli.ts +46 -19
  361. package/src/components/vedic-planets-table.ts +11 -19
  362. package/src/components/western-planets-table.ts +11 -19
  363. package/src/components/yoga-list.ts +17 -23
  364. package/src/generated/endpoint-bindings.ts +655 -0
  365. package/src/index.ts +27 -0
  366. package/src/manifest.ts +198 -6
  367. package/src/styles/tokens-css.ts +4 -0
  368. package/src/styles/tokens.css +4 -0
  369. package/src/types/index.ts +1 -1
  370. package/src/types/types.gen.ts +1123 -164
  371. package/src/utils/angel-sections.ts +38 -0
  372. package/src/utils/base-element.ts +183 -0
  373. package/src/utils/base-styles.ts +33 -0
  374. package/src/utils/fetch-controller.ts +166 -0
  375. package/src/utils/kundli-render.ts +9 -2
  376. package/src/utils/kundli-styles.ts +7 -1
  377. package/src/utils/markup-data.ts +45 -0
  378. package/src/version.ts +1 -1
@@ -0,0 +1,207 @@
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement } from 'lit/decorators.js';
3
+ import type { AnalyzeNumberSequenceResponse } from '../types/index.js';
4
+ import { buildMeaningSections } from '../utils/angel-sections.js';
5
+ import { RoxyDataElement } from '../utils/base-element.js';
6
+ import { baseStyles } from '../utils/base-styles.js';
7
+
8
+ /**
9
+ * Angel number lookup card. Renders /angel-numbers/lookup: the analysed sequence with its pattern classification (type, digit count, unique digits, palindrome, repeating), the known angel-number meaning when the sequence is in the database, and the foundational digit-root meaning that interprets any sequence. Built for synchronicity trackers where users enter arbitrary numbers.
10
+ */
11
+ @customElement('roxy-angel-number-lookup')
12
+ export class RoxyAngelNumberLookup extends RoxyDataElement<AnalyzeNumberSequenceResponse> {
13
+ static styles = [
14
+ baseStyles,
15
+ css`
16
+ .card {
17
+ background: var(--roxy-surface, #fff);
18
+ border: 1px solid var(--roxy-border, #e4e4e7);
19
+ border-radius: var(--roxy-radius-md, 8px);
20
+ padding: var(--roxy-space-lg, 1.5rem);
21
+ box-shadow: var(--roxy-shadow-sm);
22
+ display: grid;
23
+ gap: var(--roxy-space-md, 1rem);
24
+ }
25
+ .hero {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: var(--roxy-space-md, 1rem);
29
+ }
30
+ .numeral {
31
+ font-size: 3rem;
32
+ line-height: 1;
33
+ font-weight: var(--roxy-weight-bold, 600);
34
+ color: var(--roxy-accent-ink, #b45309);
35
+ font-variant-numeric: tabular-nums;
36
+ }
37
+ .label {
38
+ margin: 0;
39
+ font-size: var(--roxy-text-xs, 0.75rem);
40
+ color: var(--roxy-muted, #71717a);
41
+ text-transform: uppercase;
42
+ letter-spacing: 0.06em;
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
+ .badges {
50
+ display: flex;
51
+ flex-wrap: wrap;
52
+ gap: var(--roxy-space-xs, 0.25rem);
53
+ }
54
+ .badge {
55
+ display: inline-flex;
56
+ align-items: center;
57
+ padding: 3px 10px;
58
+ border-radius: var(--roxy-radius-full, 9999px);
59
+ font-size: var(--roxy-text-xs, 0.75rem);
60
+ font-weight: var(--roxy-weight-bold, 600);
61
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 35%, transparent);
62
+ color: var(--roxy-fg, #0a0a0a);
63
+ text-transform: capitalize;
64
+ }
65
+ .badge.flag {
66
+ background: color-mix(in srgb, var(--roxy-info, #0284c7) 16%, transparent);
67
+ color: var(--roxy-info-fg, #075985);
68
+ }
69
+ .section {
70
+ border-top: 1px solid var(--roxy-border, #e4e4e7);
71
+ padding-top: var(--roxy-space-md, 1rem);
72
+ display: grid;
73
+ gap: var(--roxy-space-sm, 0.5rem);
74
+ }
75
+ .section > .label {
76
+ margin: 0;
77
+ }
78
+ .section h3 {
79
+ margin: 0;
80
+ font-size: var(--roxy-text-base, 1rem);
81
+ font-weight: var(--roxy-weight-bold, 600);
82
+ color: var(--roxy-fg, #0a0a0a);
83
+ }
84
+ .section p {
85
+ margin: 0;
86
+ color: var(--roxy-fg, #0a0a0a);
87
+ line-height: 1.6;
88
+ font-size: var(--roxy-text-sm, 0.875rem);
89
+ }
90
+ .chips {
91
+ display: flex;
92
+ flex-wrap: wrap;
93
+ gap: var(--roxy-space-xs, 0.25rem);
94
+ }
95
+ .chips span {
96
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 14%, transparent);
97
+ padding: 2px 8px;
98
+ border-radius: var(--roxy-radius-full, 9999px);
99
+ font-size: var(--roxy-text-xs, 0.75rem);
100
+ }
101
+ details {
102
+ border: 1px solid var(--roxy-border, #e4e4e7);
103
+ border-radius: var(--roxy-radius-sm, 4px);
104
+ overflow: hidden;
105
+ }
106
+ summary {
107
+ cursor: pointer;
108
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
109
+ font-weight: var(--roxy-weight-bold, 600);
110
+ font-size: var(--roxy-text-sm, 0.875rem);
111
+ list-style-position: inside;
112
+ }
113
+ details p {
114
+ padding: 0 var(--roxy-space-md, 1rem) var(--roxy-space-md, 1rem);
115
+ }
116
+ `,
117
+ ];
118
+
119
+ protected renderEmpty() {
120
+ return html`<div class="roxy-empty" role="status">No number analysis</div>`;
121
+ }
122
+
123
+ protected renderData(d: AnalyzeNumberSequenceResponse) {
124
+ const known = d.knownMeaning;
125
+ const root = d.digitRootMeaning;
126
+ const heading = known?.title ?? 'Number analysis';
127
+
128
+ return html`<article class="card" aria-label=${`Number ${d.number ?? ''}`}>
129
+ <div class="hero">
130
+ ${d.number ? html`<div class="numeral">${d.number}</div>` : nothing}
131
+ <div>
132
+ <p class="label">Number analysis</p>
133
+ <h2 class="title">${heading}</h2>
134
+ </div>
135
+ </div>
136
+ <div class="badges">
137
+ ${d.type ? html`<span class="badge">${d.type}</span>` : nothing}
138
+ ${typeof d.digits === 'number' ? html`<span class="badge">${d.digits} digits</span>` : nothing}
139
+ ${typeof d.uniqueDigits === 'number' ? html`<span class="badge">${d.uniqueDigits} unique</span>` : nothing}
140
+ ${typeof d.digitRoot === 'number' ? html`<span class="badge">Digit root ${d.digitRoot}</span>` : nothing}
141
+ ${d.isPalindrome ? html`<span class="badge flag">Palindrome</span>` : nothing}
142
+ ${d.isRepeating ? html`<span class="badge flag">Repeating</span>` : nothing}
143
+ </div>
144
+ ${
145
+ known
146
+ ? html`<div class="section">
147
+ <p class="label">Known angel number</p>
148
+ ${known.coreMessage ? html`<p>${known.coreMessage}</p>` : nothing}
149
+ ${
150
+ known.keywords && known.keywords.length > 0
151
+ ? html`<div class="chips">${known.keywords.map((k) => html`<span>${k}</span>`)}</div>`
152
+ : nothing
153
+ }
154
+ ${this.renderMeaning(known.meaning, known.biblical, known.shadow)}
155
+ ${known.affirmation ? html`<p><em>${known.affirmation}</em></p>` : nothing}
156
+ </div>`
157
+ : nothing
158
+ }
159
+ ${
160
+ root
161
+ ? html`<div class="section">
162
+ <p class="label">Foundational digit root${root.number ? ` (${root.number})` : ''}</p>
163
+ ${root.title ? html`<h3>${root.title}</h3>` : nothing}
164
+ ${root.coreMessage ? html`<p>${root.coreMessage}</p>` : nothing}
165
+ ${!known ? this.renderRootMeaning(root) : nothing}
166
+ </div>`
167
+ : nothing
168
+ }
169
+ </article>`;
170
+ }
171
+
172
+ private renderMeaning(
173
+ meaning: Record<string, string> | undefined,
174
+ biblical?: string,
175
+ shadow?: string,
176
+ ) {
177
+ const sections = buildMeaningSections(meaning, biblical, shadow);
178
+ if (sections.length === 0) return nothing;
179
+ return html`${sections.map(
180
+ (s, i) => html`<details name="lookup-meaning" ?open=${i === 0}>
181
+ <summary>${s.label}</summary>
182
+ <p>${s.body}</p>
183
+ </details>`,
184
+ )}`;
185
+ }
186
+
187
+ /**
188
+ * Render the foundational digit-root reading for an unknown sequence: keyword chips, the full life-area accordion (including money), and the affirmation. The digit-root meaning carries no biblical or shadow field, so only the life areas are passed through.
189
+ */
190
+ private renderRootMeaning(
191
+ root: NonNullable<AnalyzeNumberSequenceResponse['digitRootMeaning']>,
192
+ ) {
193
+ return html`${
194
+ root.keywords && root.keywords.length > 0
195
+ ? html`<div class="chips">${root.keywords.map((k) => html`<span>${k}</span>`)}</div>`
196
+ : nothing
197
+ }${this.renderMeaning(root.meaning)}${
198
+ root.affirmation ? html`<p><em>${root.affirmation}</em></p>` : nothing
199
+ }`;
200
+ }
201
+ }
202
+
203
+ declare global {
204
+ interface HTMLElementTagNameMap {
205
+ 'roxy-angel-number-lookup': RoxyAngelNumberLookup;
206
+ }
207
+ }
@@ -1,9 +1,9 @@
1
- import { css, html, LitElement, nothing } from 'lit';
2
- import { customElement, property, state } from 'lit/decorators.js';
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement, state } from 'lit/decorators.js';
3
3
  import { SIGN_GLYPH } from '../tokens/index.js';
4
4
  import type { AshtakavargaResponse } from '../types/index.js';
5
+ import { RoxyDataElement } from '../utils/base-element.js';
5
6
  import { baseStyles } from '../utils/base-styles.js';
6
- import { MarkupDataController } from '../utils/markup-data.js';
7
7
 
8
8
  type Tab = 'sarva' | 'bhinna' | 'pinda';
9
9
 
@@ -20,11 +20,17 @@ const TABS: Tab[] = ['sarva', 'bhinna', 'pinda'];
20
20
  * and Shodhya Pinda. Pass `data` from /vedic-astrology/ashtakavarga.
21
21
  */
22
22
  @customElement('roxy-ashtakavarga-grid')
23
- export class RoxyAshtakavargaGrid extends LitElement {
23
+ export class RoxyAshtakavargaGrid extends RoxyDataElement<AshtakavargaResponse> {
24
24
  static styles = [
25
25
  baseStyles,
26
26
  css`
27
27
  .wrap {
28
+ background: var(--roxy-surface, #fff);
29
+ color: var(--roxy-fg, #0a0a0a);
30
+ border: 1px solid var(--roxy-border, #e4e4e7);
31
+ border-radius: var(--roxy-radius-md, 8px);
32
+ padding: var(--roxy-space-lg, 1.5rem);
33
+ box-shadow: var(--roxy-shadow-sm);
28
34
  display: grid;
29
35
  gap: var(--roxy-space-md, 1rem);
30
36
  }
@@ -195,26 +201,15 @@ export class RoxyAshtakavargaGrid extends LitElement {
195
201
  `,
196
202
  ];
197
203
 
198
- constructor() {
199
- super();
200
- // Enables hydrating `data` from a direct-child
201
- // <script type="application/json" class="roxy-data"> for server-rendered
202
- // and cached consumers. The JavaScript `data` property still wins.
203
- new MarkupDataController(this);
204
- }
205
-
206
- @property({ attribute: false })
207
- data: AshtakavargaResponse | null = null;
208
-
209
204
  @state()
210
205
  activeTab: Tab = 'sarva';
211
206
 
212
- render() {
213
- if (!this.data) {
214
- return html`<div class="roxy-empty" role="status">No ashtakavarga data</div>`;
215
- }
207
+ protected renderEmpty() {
208
+ return html`<div class="roxy-empty" role="status">No ashtakavarga data</div>`;
209
+ }
216
210
 
217
- const signs = this.data.signs ?? [];
211
+ protected renderData(d: AshtakavargaResponse) {
212
+ const signs = d.signs ?? [];
218
213
 
219
214
  return html`<div class="wrap" aria-label="Ashtakavarga grid">
220
215
  <div class="head">
@@ -0,0 +1,329 @@
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement } from 'lit/decorators.js';
3
+ import { PLANET_GLYPH } from '../tokens/index.js';
4
+ import type {
5
+ CalculateAspectsResponse,
6
+ CalculateTransitAspectsResponse,
7
+ DetectAspectPatternsResponse,
8
+ } from '../types/index.js';
9
+ import { RoxyDataElement } from '../utils/base-element.js';
10
+ import { baseStyles } from '../utils/base-styles.js';
11
+ import { chevron, disclosureStyles } from '../utils/disclosure.js';
12
+ import { formatNumber } from '../utils/format.js';
13
+ import { capitalize } from '../utils/string.js';
14
+
15
+ /**
16
+ * Natal + transit aspect grid with chart-pattern detection. Renders three endpoints that share an aspects/patterns shape: /astrology/aspects (natal aspects + patterns + a harmonious/challenging summary), /astrology/transit-aspects (transiting-to-natal aspects with timing guidance), and /astrology/aspect-patterns (patterns only: grand trines, t-squares, stelliums, yods, kites). Each aspect row shows the two bodies, the aspect type coloured by nature, its orb and strength, and an expandable interpretation; patterns render as labelled cards listing the planets they bind.
17
+ */
18
+ type AspectsData =
19
+ | CalculateAspectsResponse
20
+ | CalculateTransitAspectsResponse
21
+ | DetectAspectPatternsResponse;
22
+
23
+ @customElement('roxy-aspects-table')
24
+ export class RoxyAspectsTable extends RoxyDataElement<AspectsData> {
25
+ static styles = [
26
+ baseStyles,
27
+ disclosureStyles,
28
+ css`
29
+ .wrap {
30
+ background: var(--roxy-surface, #fff);
31
+ color: var(--roxy-fg, #0a0a0a);
32
+ border: 1px solid var(--roxy-border, #e4e4e7);
33
+ border-radius: var(--roxy-radius-md, 8px);
34
+ padding: var(--roxy-space-lg, 1.5rem);
35
+ box-shadow: var(--roxy-shadow-sm);
36
+ display: grid;
37
+ gap: var(--roxy-space-md, 1rem);
38
+ }
39
+ .head {
40
+ display: flex;
41
+ justify-content: space-between;
42
+ align-items: baseline;
43
+ gap: var(--roxy-space-md, 1rem);
44
+ flex-wrap: wrap;
45
+ }
46
+ .title {
47
+ font-size: var(--roxy-text-lg, 1.125rem);
48
+ font-weight: var(--roxy-weight-bold, 600);
49
+ margin: 0;
50
+ }
51
+ .subtitle {
52
+ color: var(--roxy-muted, #71717a);
53
+ font-size: var(--roxy-text-sm, 0.875rem);
54
+ margin: 0;
55
+ }
56
+ .summary-pills {
57
+ display: flex;
58
+ flex-wrap: wrap;
59
+ gap: var(--roxy-space-sm, 0.5rem);
60
+ }
61
+ .pill {
62
+ display: inline-flex;
63
+ align-items: center;
64
+ gap: 4px;
65
+ padding: 2px var(--roxy-space-sm, 0.5rem);
66
+ border-radius: var(--roxy-radius-full, 9999px);
67
+ font-size: var(--roxy-text-xs, 0.75rem);
68
+ font-weight: var(--roxy-weight-bold, 600);
69
+ border: 1px solid currentColor;
70
+ }
71
+ .pill--muted {
72
+ color: var(--roxy-fg, #0a0a0a);
73
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent);
74
+ }
75
+ .pill--success {
76
+ color: var(--roxy-success-fg, #166534);
77
+ background: color-mix(in srgb, var(--roxy-success, #16a34a) 10%, transparent);
78
+ }
79
+ .pill--danger {
80
+ color: var(--roxy-danger-fg, #991b1b);
81
+ background: color-mix(in srgb, var(--roxy-danger, #dc2626) 10%, transparent);
82
+ }
83
+ .section-label {
84
+ font-size: var(--roxy-text-xs, 0.75rem);
85
+ color: var(--roxy-muted, #71717a);
86
+ text-transform: uppercase;
87
+ letter-spacing: 0.06em;
88
+ font-weight: var(--roxy-weight-bold, 600);
89
+ margin: 0 0 var(--roxy-space-xs, 0.25rem) 0;
90
+ }
91
+ .aspect-card {
92
+ border: 1px solid var(--roxy-border, #e4e4e7);
93
+ border-radius: var(--roxy-radius-md, 8px);
94
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
95
+ margin-bottom: var(--roxy-space-xs, 0.25rem);
96
+ }
97
+ .aspect-card summary {
98
+ cursor: pointer;
99
+ font-weight: 500;
100
+ color: var(--roxy-fg, #0a0a0a);
101
+ display: flex;
102
+ flex-wrap: wrap;
103
+ align-items: center;
104
+ gap: 0.5em;
105
+ }
106
+ .aspect-card summary .meta {
107
+ color: var(--roxy-muted, #71717a);
108
+ font-weight: 400;
109
+ font-size: var(--roxy-text-xs, 0.75rem);
110
+ margin-left: auto;
111
+ font-variant-numeric: tabular-nums;
112
+ }
113
+ .interp-body {
114
+ margin-top: var(--roxy-space-xs, 0.25rem);
115
+ color: var(--roxy-fg, #0a0a0a);
116
+ font-size: var(--roxy-text-sm, 0.875rem);
117
+ line-height: 1.45;
118
+ }
119
+ .interp-body p {
120
+ margin: 0 0 var(--roxy-space-xs, 0.25rem);
121
+ }
122
+ .interp-keywords {
123
+ display: flex;
124
+ flex-wrap: wrap;
125
+ gap: 0.25rem;
126
+ margin-top: 0.5rem;
127
+ }
128
+ .kw {
129
+ padding: 1px 8px;
130
+ border-radius: 9999px;
131
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 14%, transparent);
132
+ color: var(--roxy-fg, #0a0a0a);
133
+ font-size: var(--roxy-text-xs, 0.75rem);
134
+ }
135
+ .glyph {
136
+ font-size: 1.1em;
137
+ line-height: 1;
138
+ }
139
+ .nature-badge {
140
+ display: inline-block;
141
+ padding: 1px 8px;
142
+ border-radius: 9999px;
143
+ font-size: var(--roxy-text-xs, 0.75rem);
144
+ font-weight: 600;
145
+ text-transform: capitalize;
146
+ }
147
+ .nature-badge.harmonious {
148
+ background: color-mix(in srgb, var(--roxy-success, #16a34a) 12%, transparent);
149
+ color: var(--roxy-success-fg, #166534);
150
+ }
151
+ .nature-badge.challenging {
152
+ background: color-mix(in srgb, var(--roxy-danger, #dc2626) 12%, transparent);
153
+ color: var(--roxy-danger-fg, #991b1b);
154
+ }
155
+ .nature-badge.neutral {
156
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent);
157
+ color: var(--roxy-fg, #0a0a0a);
158
+ }
159
+ .pattern {
160
+ border: 1px solid var(--roxy-border, #e4e4e7);
161
+ border-radius: var(--roxy-radius-md, 8px);
162
+ padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
163
+ margin-bottom: var(--roxy-space-xs, 0.25rem);
164
+ display: grid;
165
+ gap: 0.35rem;
166
+ }
167
+ .pattern-head {
168
+ display: flex;
169
+ align-items: baseline;
170
+ gap: 0.5rem;
171
+ flex-wrap: wrap;
172
+ }
173
+ .pattern-name {
174
+ font-weight: var(--roxy-weight-bold, 600);
175
+ }
176
+ .pattern-planets {
177
+ color: var(--roxy-accent-ink, #b45309);
178
+ font-size: var(--roxy-text-sm, 0.875rem);
179
+ }
180
+ .pattern-tight {
181
+ margin-left: auto;
182
+ color: var(--roxy-muted, #71717a);
183
+ font-size: var(--roxy-text-xs, 0.75rem);
184
+ font-variant-numeric: tabular-nums;
185
+ }
186
+ .pattern-interp {
187
+ color: var(--roxy-fg, #0a0a0a);
188
+ font-size: var(--roxy-text-sm, 0.875rem);
189
+ line-height: 1.45;
190
+ margin: 0;
191
+ }
192
+ `,
193
+ ];
194
+
195
+ protected renderEmpty() {
196
+ return html`<div class="roxy-empty" role="status">No aspect data</div>`;
197
+ }
198
+
199
+ protected renderData(d: AspectsData) {
200
+ const aspects = 'aspects' in d ? (d.aspects ?? []) : [];
201
+ const patterns = 'patterns' in d ? (d.patterns ?? []) : [];
202
+ const summary = 'summary' in d ? d.summary : undefined;
203
+ if (aspects.length === 0 && patterns.length === 0)
204
+ return this.renderEmpty();
205
+
206
+ return html`<div class="wrap" aria-label="Aspects">
207
+ <div class="head">
208
+ <h2 class="title">Aspects</h2>
209
+ ${aspects.length > 0 ? html`<p class="subtitle">${aspects.length} aspects</p>` : nothing}
210
+ </div>
211
+ ${summary ? this.renderSummary(summary) : nothing}
212
+ ${
213
+ aspects.length > 0
214
+ ? html`<div role="list" aria-label="Aspect list">
215
+ ${aspects.map((a, i) => this.renderAspect(a, i))}
216
+ </div>`
217
+ : nothing
218
+ }
219
+ ${
220
+ patterns.length > 0
221
+ ? html`<div>
222
+ <p class="section-label">Patterns</p>
223
+ ${patterns.map((p) => this.renderPattern(p))}
224
+ </div>`
225
+ : nothing
226
+ }
227
+ </div>`;
228
+ }
229
+
230
+ private renderSummary(
231
+ s:
232
+ | NonNullable<CalculateAspectsResponse['summary']>
233
+ | NonNullable<CalculateTransitAspectsResponse['summary']>,
234
+ ) {
235
+ const total = 'totalAspects' in s ? s.totalAspects : s.total;
236
+ return html`<div class="summary-pills" role="region" aria-label="Aspect summary">
237
+ ${typeof total === 'number' ? html`<span class="pill pill--muted">Total: ${total}</span>` : nothing}
238
+ <span class="pill pill--success">Harmonious: ${s.harmonious}</span>
239
+ <span class="pill pill--danger">Challenging: ${s.challenging}</span>
240
+ <span class="pill pill--muted">Neutral: ${s.neutral}</span>
241
+ </div>`;
242
+ }
243
+
244
+ private renderAspect(
245
+ a:
246
+ | NonNullable<CalculateAspectsResponse['aspects']>[number]
247
+ | NonNullable<CalculateTransitAspectsResponse['aspects']>[number],
248
+ idx: number,
249
+ ) {
250
+ const g1 = PLANET_GLYPH[capitalize(a.planet1)] ?? '';
251
+ const g2 = PLANET_GLYPH[capitalize(a.planet2)] ?? '';
252
+ const nature = (a.interpretation ?? 'neutral').toLowerCase();
253
+ const type = (a.type ?? '').toLowerCase().replace(/_/g, ' ');
254
+ const status = a.isApplying ? 'Applying' : 'Separating';
255
+ // Natal aspects carry `meaning` (static aspect lore); transits carry `transitInterpretation` (timed guidance).
256
+ const meaning = 'meaning' in a ? a.meaning : undefined;
257
+ const transit =
258
+ 'transitInterpretation' in a ? a.transitInterpretation : undefined;
259
+ const hasBody = Boolean(meaning || transit);
260
+ const header = html`<span aria-hidden="true" class="glyph">${g1}</span>${a.planet1}
261
+ <span class="nature-badge ${nature}">${type}</span>
262
+ <span aria-hidden="true" class="glyph">${g2}</span>${a.planet2}
263
+ <span class="meta">${status} · orb ${formatNumber(a.orb, 2)}° · str ${formatNumber(a.strength, 0)}</span>`;
264
+ if (!hasBody) {
265
+ return html`<div class="aspect-card" role="listitem">
266
+ <div class="summary" style="cursor:default">${header}</div>
267
+ </div>`;
268
+ }
269
+ return html`<details class="aspect-card" role="listitem" name="aspects" ?open=${idx === 0}>
270
+ <summary>${header}${chevron()}</summary>
271
+ <div class="interp-body">
272
+ ${meaning ? this.renderMeaning(meaning) : nothing}
273
+ ${transit ? this.renderTransit(transit) : nothing}
274
+ </div>
275
+ </details>`;
276
+ }
277
+
278
+ private renderMeaning(
279
+ m: NonNullable<
280
+ NonNullable<CalculateAspectsResponse['aspects']>[number]['meaning']
281
+ >,
282
+ ) {
283
+ const text = m.description?.short ?? m.description?.long;
284
+ return html`${text ? html`<p>${text}</p>` : nothing}
285
+ ${
286
+ m.keywords?.length
287
+ ? html`<div class="interp-keywords">${m.keywords.map((k) => html`<span class="kw">${k}</span>`)}</div>`
288
+ : nothing
289
+ }`;
290
+ }
291
+
292
+ private renderTransit(
293
+ t: NonNullable<
294
+ NonNullable<
295
+ CalculateTransitAspectsResponse['aspects']
296
+ >[number]['transitInterpretation']
297
+ >,
298
+ ) {
299
+ return html`${t.summary ? html`<p>${t.summary}</p>` : nothing}
300
+ ${t.impact ? html`<p><strong>Impact:</strong> ${t.impact}</p>` : nothing}
301
+ ${t.timing ? html`<p><strong>Timing:</strong> ${t.timing}</p>` : nothing}
302
+ ${t.guidance ? html`<p><strong>Guidance:</strong> ${t.guidance}</p>` : nothing}
303
+ ${
304
+ t.keywords?.length
305
+ ? html`<div class="interp-keywords">${t.keywords.map((k) => html`<span class="kw">${k}</span>`)}</div>`
306
+ : nothing
307
+ }`;
308
+ }
309
+
310
+ private renderPattern(
311
+ p: NonNullable<DetectAspectPatternsResponse['patterns']>[number],
312
+ ) {
313
+ const planets = p.planets ?? [];
314
+ return html`<div class="pattern">
315
+ <div class="pattern-head">
316
+ <span class="pattern-name">${p.name ?? p.kind ?? 'Pattern'}</span>
317
+ ${planets.length ? html`<span class="pattern-planets">${planets.join(', ')}</span>` : nothing}
318
+ ${typeof p.tightness === 'number' ? html`<span class="pattern-tight">${formatNumber(p.tightness, 0)}% tight</span>` : nothing}
319
+ </div>
320
+ ${p.interpretation ? html`<p class="pattern-interp">${p.interpretation}</p>` : nothing}
321
+ </div>`;
322
+ }
323
+ }
324
+
325
+ declare global {
326
+ interface HTMLElementTagNameMap {
327
+ 'roxy-aspects-table': RoxyAspectsTable;
328
+ }
329
+ }
@@ -1,12 +1,12 @@
1
- import { css, html, LitElement, nothing, svg } from 'lit';
1
+ import { css, html, nothing, svg } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
3
  import type {
4
4
  GetCriticalDaysResponse,
5
5
  GetDailyBiorhythmResponse,
6
6
  GetForecastResponse,
7
7
  } from '../types/index.js';
8
+ import { RoxyDataElement } from '../utils/base-element.js';
8
9
  import { baseStyles } from '../utils/base-styles.js';
9
- import { MarkupDataController } from '../utils/markup-data.js';
10
10
 
11
11
  type BiorhythmData =
12
12
  | GetDailyBiorhythmResponse
@@ -30,11 +30,17 @@ const CYCLE_COLOR: Record<string, string> = {
30
30
  * Biorhythm chart. Renders /biorhythm/{daily,forecast,critical-days}.
31
31
  */
32
32
  @customElement('roxy-biorhythm-chart')
33
- export class RoxyBiorhythmChart extends LitElement {
33
+ export class RoxyBiorhythmChart extends RoxyDataElement<BiorhythmData> {
34
34
  static styles = [
35
35
  baseStyles,
36
36
  css`
37
37
  .wrap {
38
+ background: var(--roxy-surface, #fff);
39
+ color: var(--roxy-fg, #0a0a0a);
40
+ border: 1px solid var(--roxy-border, #e4e4e7);
41
+ border-radius: var(--roxy-radius-md, 8px);
42
+ padding: var(--roxy-space-lg, 1.5rem);
43
+ box-shadow: var(--roxy-shadow-sm);
38
44
  display: grid;
39
45
  gap: var(--roxy-space-md, 1rem);
40
46
  }
@@ -99,6 +105,7 @@ export class RoxyBiorhythmChart extends LitElement {
99
105
  svg {
100
106
  display: block;
101
107
  width: 100%;
108
+ max-width: var(--roxy-chart-max-width, 600px);
102
109
  height: auto;
103
110
  }
104
111
  .crit {
@@ -112,25 +119,14 @@ export class RoxyBiorhythmChart extends LitElement {
112
119
  `,
113
120
  ];
114
121
 
115
- constructor() {
116
- super();
117
- // Enables hydrating `data` from a direct-child
118
- // <script type="application/json" class="roxy-data"> for server-rendered
119
- // and cached consumers. The JavaScript `data` property still wins.
120
- new MarkupDataController(this);
121
- }
122
-
123
- @property({ attribute: false })
124
- data: BiorhythmData | null = null;
125
-
126
122
  @property({ type: String, reflect: true })
127
123
  mode: 'daily' | 'forecast' | 'critical-days' = 'daily';
128
124
 
129
- render() {
130
- const d = this.data;
131
- if (!d)
132
- return html`<div class="roxy-empty" role="status">No biorhythm data</div>`;
125
+ protected renderEmpty() {
126
+ return html`<div class="roxy-empty" role="status">No biorhythm data</div>`;
127
+ }
133
128
 
129
+ protected renderData(d: BiorhythmData) {
134
130
  if (this.mode === 'critical-days' && 'criticalDays' in d) {
135
131
  return this.renderCritical(d as GetCriticalDaysResponse);
136
132
  }