@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
@@ -1,20 +1,6 @@
1
1
  import { LitElement } from 'lit';
2
- interface DoshaData {
3
- present?: boolean;
4
- severity?: 'Mild' | 'Moderate' | 'Severe' | string;
5
- type?: string;
6
- description?: string;
7
- remedies?: string[];
8
- exceptions?: string[];
9
- effects?: string | {
10
- marriage?: string;
11
- personality?: string;
12
- timing?: string;
13
- relationships?: string;
14
- general?: string;
15
- phases?: Record<string, string>;
16
- };
17
- }
2
+ import type { KalsarpaResponse, ManglikResponse, SadhesatiResponse } from '../types/index.js';
3
+ type DoshaData = ManglikResponse | KalsarpaResponse | SadhesatiResponse;
18
4
  /**
19
5
  * Dosha presence card. Renders /vedic-astrology/dosha/{manglik,kalsarpa,sadhesati}.
20
6
  * Visual severity indicator + remedies + scoped effects.
@@ -1 +1 @@
1
- {"version":3,"file":"dosha-card.d.ts","sourceRoot":"","sources":["../../src/components/dosha-card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAIrD,UAAU,SAAS;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EACL,MAAM,GACN;QACA,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC/B,CAAC;CACL;AAQD;;;GAGG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC5C,MAAM,CAAC,MAAM,4BA4FX;IAGF,IAAI,EAAE,SAAS,GAAG,IAAI,CAAQ;IAG9B,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAa;IAEhE,MAAM;IAyDN,OAAO,CAAC,aAAa;CAgBrB;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,iBAAiB,EAAE,aAAa,CAAC;KACjC;CACD"}
1
+ {"version":3,"file":"dosha-card.d.ts","sourceRoot":"","sources":["../../src/components/dosha-card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAErD,OAAO,KAAK,EACX,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,MAAM,mBAAmB,CAAC;AAG3B,KAAK,SAAS,GAAG,eAAe,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAQxE;;;GAGG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC5C,MAAM,CAAC,MAAM,4BA2FX;IAGF,IAAI,EAAE,SAAS,GAAG,IAAI,CAAQ;IAG9B,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAa;IAEhE,MAAM;IA2EN,OAAO,CAAC,aAAa;CAerB;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,iBAAiB,EAAE,aAAa,CAAC;KACjC;CACD"}
@@ -117,46 +117,49 @@ var RoxyDoshaCard = class extends LitElement {
117
117
  return html`<div class="roxy-empty" role="status">No dosha data</div>`;
118
118
  const present = !!d.present;
119
119
  const label = DOSHA_LABELS[this.type] ?? this.type;
120
- const sevClass = (d.severity ?? "").toLowerCase();
120
+ const sevLower = (d.severity ?? "").toLowerCase();
121
+ const tier = sevLower === "severe" ? 3 : sevLower === "moderate" ? 2 : sevLower === "mild" ? 1 : 0;
122
+ const pct = tier * 33;
123
+ const barColor = tier === 3 ? "var(--roxy-danger)" : tier === 2 ? "var(--roxy-warning)" : tier === 1 ? "var(--roxy-success)" : "transparent";
121
124
  return html`<article
122
125
  class="card"
123
126
  aria-label=${label}
124
127
  >
125
128
  <header class="head">
126
129
  <h2 class="title">${label}</h2>
127
- <div style="display:flex; gap:0.5rem; align-items:center;">
128
- <span class=${`badge ${present ? "present" : "absent"}`}>
129
- ${present ? "Present" : "Absent"}
130
- </span>
131
- ${d.severity ? html`<span
132
- class=${`severity ${sevClass}`}
133
- role="img"
134
- aria-label=${`Severity ${d.severity}`}
135
- >
136
- <span></span><span></span><span></span>
137
- </span>` : nothing}
138
- </div>
130
+ <span class=${`badge ${present ? "present" : "absent"}`}>
131
+ ${present ? "Present" : "Absent"}
132
+ </span>
139
133
  </header>
134
+ ${d.severity ? html`<div
135
+ class="severity-bar"
136
+ role="meter"
137
+ aria-valuemin="0"
138
+ aria-valuemax="3"
139
+ aria-valuenow="${tier}"
140
+ aria-label="Severity ${d.severity}"
141
+ >
142
+ <span class="severity-fill" style="width: ${pct}%; background: ${barColor};"></span>
143
+ </div>` : nothing}
140
144
  ${d.description ? html`<p class="description">${d.description}</p>` : nothing}
141
- ${this.renderEffects(d.effects)}
145
+ ${this.renderEffects(d)}
142
146
  ${d.remedies && d.remedies.length > 0 ? html`<div>
143
147
  <h3>Remedies</h3>
144
148
  <ul>
145
149
  ${d.remedies.map((r) => html`<li>${r}</li>`)}
146
150
  </ul>
147
151
  </div>` : nothing}
148
- ${d.exceptions && d.exceptions.length > 0 ? html`<div>
149
- <h3>Exceptions</h3>
150
- <ul>
151
- ${d.exceptions.map((r) => html`<li>${r}</li>`)}
152
- </ul>
153
- </div>` : nothing}
152
+ ${"exceptions" in d && d.exceptions && d.exceptions.length > 0 ? html`<div>
153
+ <h3>Exceptions</h3>
154
+ <ul>
155
+ ${d.exceptions.map((r) => html`<li>${r}</li>`)}
156
+ </ul>
157
+ </div>` : nothing}
154
158
  </article>`;
155
159
  }
156
- renderEffects(e) {
157
- if (!e) return nothing;
158
- if (typeof e === "string") return html`<p>${e}</p>`;
159
- const entries = Object.entries(e).filter(
160
+ renderEffects(d) {
161
+ if (!d.effects) return nothing;
162
+ const entries = Object.entries(d.effects).filter(
160
163
  ([, v]) => typeof v === "string" && v.length > 0
161
164
  );
162
165
  if (entries.length === 0) return nothing;
@@ -208,31 +211,30 @@ RoxyDoshaCard.styles = [
208
211
  }
209
212
  .badge.absent {
210
213
  background: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);
211
- color: var(--roxy-success, #16a34a);
214
+ color: var(--roxy-success-fg, #166534);
212
215
  }
213
216
  .badge.present {
214
217
  background: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);
215
- color: var(--roxy-danger, #dc2626);
216
- }
217
- .severity {
218
- display: flex;
219
- align-items: center;
220
- gap: 4px;
221
- }
222
- .severity span {
223
- width: 14px;
224
- height: 4px;
225
- border-radius: 2px;
226
- background: var(--roxy-border, #e4e4e7);
218
+ color: var(--roxy-danger-fg, #991b1b);
227
219
  }
228
- .severity.mild span:nth-child(1) {
229
- background: var(--roxy-warning, #ea580c);
220
+ .severity-bar {
221
+ position: relative;
222
+ width: 100%;
223
+ height: 8px;
224
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 30%, transparent);
225
+ border-radius: 4px;
226
+ overflow: hidden;
230
227
  }
231
- .severity.moderate span:nth-child(-n + 2) {
232
- background: var(--roxy-warning, #ea580c);
228
+ .severity-fill {
229
+ display: block;
230
+ height: 100%;
231
+ transition: width var(--roxy-motion-duration, 200ms) ease-out;
232
+ border-radius: 4px;
233
233
  }
234
- .severity.severe span {
235
- background: var(--roxy-danger, #dc2626);
234
+ @media (prefers-reduced-motion: reduce) {
235
+ .severity-fill {
236
+ transition: none;
237
+ }
236
238
  }
237
239
 
238
240
  .description {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/dosha-card.ts", "../../src/utils/base-styles.ts"],
4
- "sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ninterface DoshaData {\n\tpresent?: boolean;\n\tseverity?: 'Mild' | 'Moderate' | 'Severe' | string;\n\ttype?: string;\n\tdescription?: string;\n\tremedies?: string[];\n\texceptions?: string[];\n\teffects?:\n\t\t| string\n\t\t| {\n\t\t\t\tmarriage?: string;\n\t\t\t\tpersonality?: string;\n\t\t\t\ttiming?: string;\n\t\t\t\trelationships?: string;\n\t\t\t\tgeneral?: string;\n\t\t\t\tphases?: Record<string, string>;\n\t\t };\n}\n\nconst DOSHA_LABELS: Record<string, string> = {\n\tmanglik: 'Mangal Dosha',\n\tkalsarpa: 'Kaal Sarp Dosha',\n\tsadhesati: 'Sade Sati',\n};\n\n/**\n * Dosha presence card. Renders /vedic-astrology/dosha/{manglik,kalsarpa,sadhesati}.\n * Visual severity indicator + remedies + scoped effects.\n */\n@customElement('roxy-dosha-card')\nexport class RoxyDoshaCard extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.card {\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\t\t\tbox-shadow: var(--roxy-shadow-sm);\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.head {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: space-between;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tflex-wrap: wrap;\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\ttext-transform: capitalize;\n\t\t\t}\n\t\t\t.badge {\n\t\t\t\tdisplay: inline-flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t\tpadding: 4px 10px;\n\t\t\t\tborder-radius: var(--roxy-radius-full, 9999px);\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\ttext-transform: uppercase;\n\t\t\t\tletter-spacing: 0.06em;\n\t\t\t}\n\t\t\t.badge.absent {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);\n\t\t\t\tcolor: var(--roxy-success, #16a34a);\n\t\t\t}\n\t\t\t.badge.present {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);\n\t\t\t\tcolor: var(--roxy-danger, #dc2626);\n\t\t\t}\n\t\t\t.severity {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 4px;\n\t\t\t}\n\t\t\t.severity span {\n\t\t\t\twidth: 14px;\n\t\t\t\theight: 4px;\n\t\t\t\tborder-radius: 2px;\n\t\t\t\tbackground: var(--roxy-border, #e4e4e7);\n\t\t\t}\n\t\t\t.severity.mild span:nth-child(1) {\n\t\t\t\tbackground: var(--roxy-warning, #ea580c);\n\t\t\t}\n\t\t\t.severity.moderate span:nth-child(-n + 2) {\n\t\t\t\tbackground: var(--roxy-warning, #ea580c);\n\t\t\t}\n\t\t\t.severity.severe span {\n\t\t\t\tbackground: var(--roxy-danger, #dc2626);\n\t\t\t}\n\n\t\t\t.description {\n\t\t\t\tmargin: 0;\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\n\t\t\th3 {\n\t\t\t\tmargin: 0 0 var(--roxy-space-xs, 0.25rem);\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\ttext-transform: uppercase;\n\t\t\t\tletter-spacing: 0.06em;\n\t\t\t}\n\t\t\tul {\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding-left: var(--roxy-space-md, 1rem);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t\t.effects {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.effects p {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: DoshaData | null = null;\n\n\t@property({ type: String, reflect: true })\n\ttype: 'manglik' | 'kalsarpa' | 'sadhesati' | string = 'manglik';\n\n\trender() {\n\t\tconst d = this.data;\n\t\tif (!d)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No dosha data</div>`;\n\n\t\tconst present = !!d.present;\n\t\tconst label = DOSHA_LABELS[this.type] ?? this.type;\n\t\tconst sevClass = (d.severity ?? '').toLowerCase();\n\n\t\treturn html`<article\n\t\t\tclass=\"card\"\n\t\t\taria-label=${label}\n\t\t>\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">${label}</h2>\n\t\t\t\t<div style=\"display:flex; gap:0.5rem; align-items:center;\">\n\t\t\t\t\t<span class=${`badge ${present ? 'present' : 'absent'}`}>\n\t\t\t\t\t\t${present ? 'Present' : 'Absent'}\n\t\t\t\t\t</span>\n\t\t\t\t\t${\n\t\t\t\t\t\td.severity\n\t\t\t\t\t\t\t? html`<span\n\t\t\t\t\t\t\t\tclass=${`severity ${sevClass}`}\n\t\t\t\t\t\t\t\trole=\"img\"\n\t\t\t\t\t\t\t\taria-label=${`Severity ${d.severity}`}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span></span><span></span><span></span>\n\t\t\t\t\t\t\t</span>`\n\t\t\t\t\t\t\t: nothing\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t</header>\n\t\t\t${d.description ? html`<p class=\"description\">${d.description}</p>` : nothing}\n\t\t\t${this.renderEffects(d.effects)}\n\t\t\t${\n\t\t\t\td.remedies && d.remedies.length > 0\n\t\t\t\t\t? html`<div>\n\t\t\t\t\t\t<h3>Remedies</h3>\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t${d.remedies.map((r) => html`<li>${r}</li>`)}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t\t${\n\t\t\t\td.exceptions && d.exceptions.length > 0\n\t\t\t\t\t? html`<div>\n\t\t\t\t\t\t<h3>Exceptions</h3>\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t${d.exceptions.map((r) => html`<li>${r}</li>`)}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t</article>`;\n\t}\n\n\tprivate renderEffects(e: DoshaData['effects']) {\n\t\tif (!e) return nothing;\n\t\tif (typeof e === 'string') return html`<p>${e}</p>`;\n\t\tconst entries = Object.entries(e).filter(\n\t\t\t([, v]) => typeof v === 'string' && v.length > 0,\n\t\t);\n\t\tif (entries.length === 0) return nothing;\n\t\treturn html`<div class=\"effects\">\n\t\t\t${entries.map(\n\t\t\t\t([k, v]) => html`<div>\n\t\t\t\t\t<h3>${k}</h3>\n\t\t\t\t\t<p>${v}</p>\n\t\t\t\t</div>`,\n\t\t\t)}\n\t\t</div>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-dosha-card': RoxyDoshaCard;\n\t}\n}\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n"],
5
- "mappings": ";;;;;;;;;;;;AAAA,SAAS,OAAAA,MAAK,MAAM,YAAY,eAAe;AAC/C,SAAS,eAAe,gBAAgB;;;ACDxC,SAAS,WAAW;AAMb,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ADiB1B,IAAM,eAAuC;AAAA,EAC5C,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AACZ;AAOO,IAAM,gBAAN,cAA4B,WAAW;AAAA,EAAvC;AAAA;AAgGN,gBAAyB;AAGzB,gBAAsD;AAAA;AAAA,EAEtD,SAAS;AACR,UAAM,IAAI,KAAK;AACf,QAAI,CAAC;AACJ,aAAO;AAER,UAAM,UAAU,CAAC,CAAC,EAAE;AACpB,UAAM,QAAQ,aAAa,KAAK,IAAI,KAAK,KAAK;AAC9C,UAAM,YAAY,EAAE,YAAY,IAAI,YAAY;AAEhD,WAAO;AAAA;AAAA,gBAEO,KAAK;AAAA;AAAA;AAAA,wBAGG,KAAK;AAAA;AAAA,mBAEV,SAAS,UAAU,YAAY,QAAQ,EAAE;AAAA,QACpD,UAAU,YAAY,QAAQ;AAAA;AAAA,OAGhC,EAAE,WACC;AAAA,gBACO,YAAY,QAAQ,EAAE;AAAA;AAAA,qBAEjB,YAAY,EAAE,QAAQ,EAAE;AAAA;AAAA;AAAA,kBAIpC,OACJ;AAAA;AAAA;AAAA,KAGA,EAAE,cAAc,8BAA8B,EAAE,WAAW,SAAS,OAAO;AAAA,KAC3E,KAAK,cAAc,EAAE,OAAO,CAAC;AAAA,KAE9B,EAAE,YAAY,EAAE,SAAS,SAAS,IAC/B;AAAA;AAAA;AAAA,SAGE,EAAE,SAAS,IAAI,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC;AAAA;AAAA,eAG5C,OACJ;AAAA,KAEC,EAAE,cAAc,EAAE,WAAW,SAAS,IACnC;AAAA;AAAA;AAAA,SAGE,EAAE,WAAW,IAAI,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC;AAAA;AAAA,eAG9C,OACJ;AAAA;AAAA,EAEF;AAAA,EAEQ,cAAc,GAAyB;AAC9C,QAAI,CAAC,EAAG,QAAO;AACf,QAAI,OAAO,MAAM,SAAU,QAAO,UAAU,CAAC;AAC7C,UAAM,UAAU,OAAO,QAAQ,CAAC,EAAE;AAAA,MACjC,CAAC,CAAC,EAAE,CAAC,MAAM,OAAO,MAAM,YAAY,EAAE,SAAS;AAAA,IAChD;AACA,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WAAO;AAAA,KACJ,QAAQ;AAAA,MACT,CAAC,CAAC,GAAG,CAAC,MAAM;AAAA,WACL,CAAC;AAAA,UACF,CAAC;AAAA;AAAA,IAER,CAAC;AAAA;AAAA,EAEH;AACD;AA9Ka,cACL,SAAS;AAAA,EACf;AAAA,EACAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0FD;AAGA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GA/FlB,cAgGZ;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GAlG7B,cAmGZ;AAnGY,gBAAN;AAAA,EADN,cAAc,iBAAiB;AAAA,GACnB;",
4
+ "sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport type {\n\tKalsarpaResponse,\n\tManglikResponse,\n\tSadhesatiResponse,\n} from '../types/index.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ntype DoshaData = ManglikResponse | KalsarpaResponse | SadhesatiResponse;\n\nconst DOSHA_LABELS: Record<string, string> = {\n\tmanglik: 'Mangal Dosha',\n\tkalsarpa: 'Kaal Sarp Dosha',\n\tsadhesati: 'Sade Sati',\n};\n\n/**\n * Dosha presence card. Renders /vedic-astrology/dosha/{manglik,kalsarpa,sadhesati}.\n * Visual severity indicator + remedies + scoped effects.\n */\n@customElement('roxy-dosha-card')\nexport class RoxyDoshaCard extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.card {\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\t\t\tbox-shadow: var(--roxy-shadow-sm);\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.head {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: space-between;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tflex-wrap: wrap;\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\ttext-transform: capitalize;\n\t\t\t}\n\t\t\t.badge {\n\t\t\t\tdisplay: inline-flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t\tpadding: 4px 10px;\n\t\t\t\tborder-radius: var(--roxy-radius-full, 9999px);\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\ttext-transform: uppercase;\n\t\t\t\tletter-spacing: 0.06em;\n\t\t\t}\n\t\t\t.badge.absent {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);\n\t\t\t\tcolor: var(--roxy-success-fg, #166534);\n\t\t\t}\n\t\t\t.badge.present {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-danger, #dc2626) 16%, transparent);\n\t\t\t\tcolor: var(--roxy-danger-fg, #991b1b);\n\t\t\t}\n\t\t\t.severity-bar {\n\t\t\t\tposition: relative;\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 8px;\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-border, #e4e4e7) 30%, transparent);\n\t\t\t\tborder-radius: 4px;\n\t\t\t\toverflow: hidden;\n\t\t\t}\n\t\t\t.severity-fill {\n\t\t\t\tdisplay: block;\n\t\t\t\theight: 100%;\n\t\t\t\ttransition: width var(--roxy-motion-duration, 200ms) ease-out;\n\t\t\t\tborder-radius: 4px;\n\t\t\t}\n\t\t\t@media (prefers-reduced-motion: reduce) {\n\t\t\t\t.severity-fill {\n\t\t\t\t\ttransition: none;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t.description {\n\t\t\t\tmargin: 0;\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\n\t\t\th3 {\n\t\t\t\tmargin: 0 0 var(--roxy-space-xs, 0.25rem);\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\ttext-transform: uppercase;\n\t\t\t\tletter-spacing: 0.06em;\n\t\t\t}\n\t\t\tul {\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding-left: var(--roxy-space-md, 1rem);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t\t.effects {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.effects p {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: DoshaData | null = null;\n\n\t@property({ type: String, reflect: true })\n\ttype: 'manglik' | 'kalsarpa' | 'sadhesati' | string = 'manglik';\n\n\trender() {\n\t\tconst d = this.data;\n\t\tif (!d)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No dosha data</div>`;\n\n\t\tconst present = !!d.present;\n\t\tconst label = DOSHA_LABELS[this.type] ?? this.type;\n\t\tconst sevLower = (d.severity ?? '').toLowerCase();\n\t\tconst tier =\n\t\t\tsevLower === 'severe'\n\t\t\t\t? 3\n\t\t\t\t: sevLower === 'moderate'\n\t\t\t\t\t? 2\n\t\t\t\t\t: sevLower === 'mild'\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: 0;\n\t\tconst pct = tier * 33;\n\t\tconst barColor =\n\t\t\ttier === 3\n\t\t\t\t? 'var(--roxy-danger)'\n\t\t\t\t: tier === 2\n\t\t\t\t\t? 'var(--roxy-warning)'\n\t\t\t\t\t: tier === 1\n\t\t\t\t\t\t? 'var(--roxy-success)'\n\t\t\t\t\t\t: 'transparent';\n\n\t\treturn html`<article\n\t\t\tclass=\"card\"\n\t\t\taria-label=${label}\n\t\t>\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">${label}</h2>\n\t\t\t\t<span class=${`badge ${present ? 'present' : 'absent'}`}>\n\t\t\t\t\t${present ? 'Present' : 'Absent'}\n\t\t\t\t</span>\n\t\t\t</header>\n\t\t\t${\n\t\t\t\td.severity\n\t\t\t\t\t? html`<div\n\t\t\t\t\t\tclass=\"severity-bar\"\n\t\t\t\t\t\trole=\"meter\"\n\t\t\t\t\t\taria-valuemin=\"0\"\n\t\t\t\t\t\taria-valuemax=\"3\"\n\t\t\t\t\t\taria-valuenow=\"${tier}\"\n\t\t\t\t\t\taria-label=\"Severity ${d.severity}\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span class=\"severity-fill\" style=\"width: ${pct}%; background: ${barColor};\"></span>\n\t\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t\t${d.description ? html`<p class=\"description\">${d.description}</p>` : nothing}\n\t\t\t${this.renderEffects(d)}\n\t\t\t${\n\t\t\t\td.remedies && d.remedies.length > 0\n\t\t\t\t\t? html`<div>\n\t\t\t\t\t\t<h3>Remedies</h3>\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t${d.remedies.map((r) => html`<li>${r}</li>`)}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t\t${\n\t\t\t\t'exceptions' in d && d.exceptions && d.exceptions.length > 0\n\t\t\t\t\t? html`<div>\n\t\t\t\t\t<h3>Exceptions</h3>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t${d.exceptions.map((r) => html`<li>${r}</li>`)}\n\t\t\t\t\t</ul>\n\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t</article>`;\n\t}\n\n\tprivate renderEffects(d: DoshaData) {\n\t\tif (!d.effects) return nothing;\n\t\tconst entries = Object.entries(d.effects).filter(\n\t\t\t([, v]) => typeof v === 'string' && v.length > 0,\n\t\t);\n\t\tif (entries.length === 0) return nothing;\n\t\treturn html`<div class=\"effects\">\n\t\t\t${entries.map(\n\t\t\t\t([k, v]) => html`<div>\n\t\t\t\t\t<h3>${k}</h3>\n\t\t\t\t\t<p>${v}</p>\n\t\t\t\t</div>`,\n\t\t\t)}\n\t\t</div>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-dosha-card': RoxyDoshaCard;\n\t}\n}\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n"],
5
+ "mappings": "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",
6
6
  "names": ["css", "css"]
7
7
  }
@@ -20,8 +20,10 @@ export declare class RoxyEndpointForm extends LitElement {
20
20
  private values;
21
21
  private hasLocation;
22
22
  private loaded;
23
+ private specError;
23
24
  connectedCallback(): void;
24
25
  private loadSchema;
26
+ private retryLoadSchema;
25
27
  private resolve;
26
28
  private fieldType;
27
29
  private setValue;
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint-form.d.ts","sourceRoot":"","sources":["../../src/components/endpoint-form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAiCrD;;;;;;;;;;GAUG;AACH,qBACa,gBAAiB,SAAQ,UAAU;IAC/C,MAAM,CAAC,MAAM,4BAyFX;IAGF,QAAQ,SAAiC;IAGzC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAU;IAGhC,OAAO,SAA6C;IAGpD,WAAW,SAAY;IAGvB,OAAO,CAAC,MAAM,CAAkB;IAGhC,OAAO,CAAC,MAAM,CAA+B;IAG7C,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,MAAM,CAAS;IAEvB,iBAAiB,IAAI,IAAI;YAKX,UAAU;IAqFxB,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU,CAehB;IAEF,OAAO,CAAC,QAAQ,CAwBd;IAEF,MAAM;IA6EN,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,MAAM;CAQd;AASD,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,oBAAoB,EAAE,gBAAgB,CAAC;KACvC;CACD"}
1
+ {"version":3,"file":"endpoint-form.d.ts","sourceRoot":"","sources":["../../src/components/endpoint-form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AA6DrD;;;;;;;;;;GAUG;AACH,qBACa,gBAAiB,SAAQ,UAAU;IAC/C,MAAM,CAAC,MAAM,4BAyGX;IAGF,QAAQ,SAAiC;IAGzC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAU;IAGhC,OAAO,SAA6C;IAGpD,WAAW,SAAY;IAGvB,OAAO,CAAC,MAAM,CAAkB;IAGhC,OAAO,CAAC,MAAM,CAA+B;IAG7C,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,MAAM,CAAS;IAGvB,OAAO,CAAC,SAAS,CAAuB;IAExC,iBAAiB,IAAI,IAAI;YAKX,UAAU;IA8FxB,OAAO,CAAC,eAAe,CAIrB;IAEF,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU,CAehB;IAEF,OAAO,CAAC,QAAQ,CAwBd;IAEF,MAAM;IAoFN,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,MAAM;CAQd;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,oBAAoB,EAAE,gBAAgB,CAAC;KACvC;CACD"}
@@ -99,7 +99,27 @@ var baseStyles = css`
99
99
  }
100
100
  `;
101
101
 
102
+ // packages/ui/src/utils/string.ts
103
+ function humanize(s) {
104
+ return s.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^\w/, (c) => c.toUpperCase());
105
+ }
106
+
102
107
  // packages/ui/src/components/endpoint-form.ts
108
+ var specCache = /* @__PURE__ */ new Map();
109
+ async function loadSpec(url) {
110
+ let pending = specCache.get(url);
111
+ if (!pending) {
112
+ pending = fetch(url).then(async (res) => {
113
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
114
+ return await res.json();
115
+ }).catch((err) => {
116
+ specCache.delete(url);
117
+ throw err;
118
+ });
119
+ specCache.set(url, pending);
120
+ }
121
+ return pending;
122
+ }
103
123
  var RoxyEndpointForm = class extends LitElement {
104
124
  constructor() {
105
125
  super(...arguments);
@@ -111,6 +131,12 @@ var RoxyEndpointForm = class extends LitElement {
111
131
  this.values = {};
112
132
  this.hasLocation = false;
113
133
  this.loaded = false;
134
+ this.specError = null;
135
+ this.retryLoadSchema = () => {
136
+ this.loaded = false;
137
+ this.specError = null;
138
+ void this.loadSchema();
139
+ };
114
140
  this.onLocation = (e) => {
115
141
  const detail = e.detail;
116
142
  if (detail) {
@@ -151,13 +177,16 @@ var RoxyEndpointForm = class extends LitElement {
151
177
  void this.loadSchema();
152
178
  }
153
179
  async loadSchema() {
180
+ this.specError = null;
154
181
  try {
155
- const res = await fetch(this.specUrl);
156
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
157
- const spec = await res.json();
182
+ const spec = await loadSpec(this.specUrl);
158
183
  const path = `/${this.endpoint.replace(/^\//, "")}`;
159
184
  const op = spec.paths?.[path]?.[this.method.toLowerCase()];
160
- if (!op) return;
185
+ if (!op) {
186
+ throw new Error(
187
+ `Endpoint ${this.method} ${path} not found in OpenAPI spec`
188
+ );
189
+ }
161
190
  const schemas = spec.components?.schemas ?? {};
162
191
  const fields = [];
163
192
  let bodySchema;
@@ -202,8 +231,17 @@ var RoxyEndpointForm = class extends LitElement {
202
231
  }
203
232
  this.values = init;
204
233
  this.loaded = true;
205
- } catch (_err) {
234
+ } catch (err) {
235
+ const message = err instanceof Error ? err.message : String(err);
236
+ this.specError = message;
206
237
  this.loaded = true;
238
+ this.dispatchEvent(
239
+ new CustomEvent("roxy-spec-error", {
240
+ detail: { url: this.specUrl, message },
241
+ bubbles: true,
242
+ composed: true
243
+ })
244
+ );
207
245
  }
208
246
  }
209
247
  resolve(schema, all) {
@@ -229,6 +267,12 @@ var RoxyEndpointForm = class extends LitElement {
229
267
  if (!this.loaded) {
230
268
  return html`<form><div class="roxy-skeleton" style="height: 8rem"></div></form>`;
231
269
  }
270
+ if (this.specError) {
271
+ return html`<div class="spec-error" role="alert">
272
+ Schema load failed: ${this.specError}
273
+ <button type="button" class="submit" @click=${this.retryLoadSchema}>Retry</button>
274
+ </div>`;
275
+ }
232
276
  const renderField = (f) => {
233
277
  if (this.hasLocation && (f.name === "latitude" || f.name === "longitude" || f.name === "timezone")) {
234
278
  return nothing;
@@ -326,22 +370,27 @@ RoxyEndpointForm.styles = [
326
370
  .fields {
327
371
  display: grid;
328
372
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
373
+ align-items: start;
329
374
  gap: var(--roxy-space-md, 1rem);
330
375
  }
331
376
  .field {
332
- display: grid;
377
+ display: flex;
378
+ flex-direction: column;
333
379
  gap: var(--roxy-space-xs, 0.25rem);
380
+ min-width: 0;
334
381
  }
335
382
  label {
336
383
  font-size: var(--roxy-text-sm, 0.875rem);
337
384
  color: var(--roxy-secondary, #475569);
338
385
  }
339
386
  label .req {
340
- color: var(--roxy-danger, #dc2626);
387
+ color: var(--roxy-danger-fg, #991b1b);
341
388
  margin-left: 4px;
342
389
  }
343
390
  input,
344
391
  select {
392
+ width: 100%;
393
+ box-sizing: border-box;
345
394
  padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
346
395
  font-size: var(--roxy-text-base, 1rem);
347
396
  font-family: inherit;
@@ -376,7 +425,7 @@ RoxyEndpointForm.styles = [
376
425
  button.submit {
377
426
  justify-self: start;
378
427
  background: var(--roxy-accent-fg, #b45309);
379
- color: #fff;
428
+ color: var(--roxy-bg, #fff);
380
429
  border: 0;
381
430
  border-radius: var(--roxy-radius-md, 8px);
382
431
  padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-lg, 1.5rem);
@@ -394,6 +443,17 @@ RoxyEndpointForm.styles = [
394
443
  outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
395
444
  outline-offset: 2px;
396
445
  }
446
+ .spec-error {
447
+ display: grid;
448
+ gap: var(--roxy-space-md, 1rem);
449
+ justify-items: start;
450
+ background: var(--roxy-bg, #fff);
451
+ border: 1px solid var(--roxy-danger, #dc2626);
452
+ border-radius: var(--roxy-radius-md, 8px);
453
+ padding: var(--roxy-space-lg, 1.5rem);
454
+ color: var(--roxy-danger-fg, #991b1b);
455
+ font-size: var(--roxy-text-sm, 0.875rem);
456
+ }
397
457
  `
398
458
  ];
399
459
  __decorateClass([
@@ -420,12 +480,12 @@ __decorateClass([
420
480
  __decorateClass([
421
481
  state()
422
482
  ], RoxyEndpointForm.prototype, "loaded", 2);
483
+ __decorateClass([
484
+ state()
485
+ ], RoxyEndpointForm.prototype, "specError", 2);
423
486
  RoxyEndpointForm = __decorateClass([
424
487
  customElement("roxy-endpoint-form")
425
488
  ], RoxyEndpointForm);
426
- function humanize(s) {
427
- return s.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^\w/, (c) => c.toUpperCase());
428
- }
429
489
  export {
430
490
  RoxyEndpointForm
431
491
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/components/endpoint-form.ts", "../../src/utils/base-styles.ts"],
4
- "sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ninterface OpenApiSchemaRef {\n\t$ref?: string;\n}\n\ninterface OpenApiSchema extends OpenApiSchemaRef {\n\ttype?: string;\n\tformat?: string;\n\tdescription?: string;\n\tenum?: string[];\n\tdefault?: unknown;\n\tminimum?: number;\n\tmaximum?: number;\n\tproperties?: Record<string, OpenApiSchema>;\n\trequired?: string[];\n\titems?: OpenApiSchema;\n\texample?: unknown;\n}\n\ninterface FieldDef {\n\tname: string;\n\ttype: string;\n\trequired: boolean;\n\tdescription?: string;\n\tenum?: string[];\n\tmin?: number;\n\tmax?: number;\n\tdefault?: unknown;\n}\n\n/**\n * Schema-driven form. Pass `endpoint` (e.g. \"vedic-astrology/birth-chart\").\n * The form introspects the cached OpenAPI spec, slots a roxy-location-search\n * when latitude+longitude+timezone fields are present, and emits a\n * `roxy-submit` CustomEvent with the validated payload on submit. The caller\n * decides what to do (call the SDK, render a chart, navigate).\n *\n * Build-time hints (x-roxy-ui formGroups) are read by scripts/build.ts and\n * baked into a static map. At runtime the component falls back to runtime\n * fetch of /api/v2/openapi.json when no map is provided.\n */\n@customElement('roxy-endpoint-form')\nexport class RoxyEndpointForm extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\tform {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\t\t\tbox-shadow: var(--roxy-shadow-sm);\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\t\t\t.fields {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.field {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tcolor: var(--roxy-secondary, #475569);\n\t\t\t}\n\t\t\tlabel .req {\n\t\t\t\tcolor: var(--roxy-danger, #dc2626);\n\t\t\t\tmargin-left: 4px;\n\t\t\t}\n\t\t\tinput,\n\t\t\tselect {\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-family: inherit;\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t}\n\t\t\tinput:focus,\n\t\t\tselect:focus {\n\t\t\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\t\t\toutline-offset: 2px;\n\t\t\t\tborder-color: var(--roxy-accent-fg, #b45309);\n\t\t\t}\n\t\t\t.help {\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t}\n\t\t\t.location-block {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t\tgrid-column: 1 / -1;\n\t\t\t}\n\t\t\t.coords {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(3, 1fr);\n\t\t\t\tgap: var(--roxy-space-sm, 0.5rem);\n\t\t\t}\n\t\t\t.coords input {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t\tbutton.submit {\n\t\t\t\tjustify-self: start;\n\t\t\t\tbackground: var(--roxy-accent-fg, #b45309);\n\t\t\t\tcolor: #fff;\n\t\t\t\tborder: 0;\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-lg, 1.5rem);\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tcursor: pointer;\n\t\t\t\ttransition:\n\t\t\t\t\ttransform var(--roxy-motion-duration, 200ms)\n\t\t\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1));\n\t\t\t}\n\t\t\tbutton.submit:hover {\n\t\t\t\ttransform: scale(1.02);\n\t\t\t}\n\t\t\tbutton.submit:focus-visible {\n\t\t\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\t\t\toutline-offset: 2px;\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ type: String, attribute: 'data-endpoint' })\n\tendpoint = 'vedic-astrology/birth-chart';\n\n\t@property({ type: String })\n\tmethod: 'GET' | 'POST' = 'POST';\n\n\t@property({ type: String, attribute: 'spec-url' })\n\tspecUrl = 'https://roxyapi.com/api/v2/openapi.json';\n\n\t@property({ type: String, attribute: 'submit-label' })\n\tsubmitLabel = 'Submit';\n\n\t@state()\n\tprivate fields: FieldDef[] = [];\n\n\t@state()\n\tprivate values: Record<string, unknown> = {};\n\n\t@state()\n\tprivate hasLocation = false;\n\n\t@state()\n\tprivate loaded = false;\n\n\tconnectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tvoid this.loadSchema();\n\t}\n\n\tprivate async loadSchema() {\n\t\ttry {\n\t\t\tconst res = await fetch(this.specUrl);\n\t\t\tif (!res.ok) throw new Error(`HTTP ${res.status}`);\n\t\t\tconst spec = (await res.json()) as {\n\t\t\t\tpaths?: Record<string, Record<string, unknown>>;\n\t\t\t\tcomponents?: { schemas?: Record<string, OpenApiSchema> };\n\t\t\t};\n\t\t\tconst path = `/${this.endpoint.replace(/^\\//, '')}`;\n\t\t\tconst op = spec.paths?.[path]?.[this.method.toLowerCase()] as\n\t\t\t\t| {\n\t\t\t\t\t\trequestBody?: {\n\t\t\t\t\t\t\tcontent?: Record<\n\t\t\t\t\t\t\t\tstring,\n\t\t\t\t\t\t\t\t{ schema?: OpenApiSchema | OpenApiSchemaRef }\n\t\t\t\t\t\t\t>;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparameters?: Array<{\n\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\tin: string;\n\t\t\t\t\t\t\trequired?: boolean;\n\t\t\t\t\t\t\tschema?: OpenApiSchema;\n\t\t\t\t\t\t}>;\n\t\t\t\t }\n\t\t\t\t| undefined;\n\t\t\tif (!op) return;\n\n\t\t\tconst schemas = spec.components?.schemas ?? {};\n\t\t\tconst fields: FieldDef[] = [];\n\t\t\tlet bodySchema: OpenApiSchema | undefined;\n\n\t\t\tif (op.requestBody) {\n\t\t\t\tconst ref = op.requestBody.content?.['application/json']?.schema;\n\t\t\t\tbodySchema = this.resolve(ref, schemas);\n\t\t\t}\n\n\t\t\tif (bodySchema?.properties) {\n\t\t\t\tconst required = new Set(bodySchema.required ?? []);\n\t\t\t\tfor (const [name, sub] of Object.entries(bodySchema.properties)) {\n\t\t\t\t\tconst resolved = this.resolve(sub, schemas) ?? {};\n\t\t\t\t\tfields.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\ttype: this.fieldType(resolved),\n\t\t\t\t\t\trequired: required.has(name),\n\t\t\t\t\t\tdescription: resolved.description,\n\t\t\t\t\t\tenum: resolved.enum,\n\t\t\t\t\t\tmin: resolved.minimum,\n\t\t\t\t\t\tmax: resolved.maximum,\n\t\t\t\t\t\tdefault: resolved.default,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const param of op.parameters ?? []) {\n\t\t\t\tif (param.in === 'path' || param.in === 'query') {\n\t\t\t\t\tconst resolved = this.resolve(param.schema, schemas) ?? {};\n\t\t\t\t\tfields.push({\n\t\t\t\t\t\tname: param.name,\n\t\t\t\t\t\ttype: this.fieldType(resolved),\n\t\t\t\t\t\trequired: !!param.required,\n\t\t\t\t\t\tdescription: resolved.description,\n\t\t\t\t\t\tenum: resolved.enum,\n\t\t\t\t\t\tdefault: resolved.default,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.fields = fields;\n\t\t\tthis.hasLocation =\n\t\t\t\tfields.some((f) => f.name === 'latitude') &&\n\t\t\t\tfields.some((f) => f.name === 'longitude') &&\n\t\t\t\tfields.some((f) => f.name === 'timezone');\n\n\t\t\t// Pre-fill defaults\n\t\t\tconst init: Record<string, unknown> = {};\n\t\t\tfor (const f of fields) {\n\t\t\t\tif (f.default !== undefined) init[f.name] = f.default;\n\t\t\t}\n\t\t\tthis.values = init;\n\t\t\tthis.loaded = true;\n\t\t} catch (_err) {\n\t\t\tthis.loaded = true;\n\t\t}\n\t}\n\n\tprivate resolve(\n\t\tschema: OpenApiSchema | OpenApiSchemaRef | undefined,\n\t\tall: Record<string, OpenApiSchema>,\n\t): OpenApiSchema | undefined {\n\t\tif (!schema) return undefined;\n\t\tif ('$ref' in schema && schema.$ref) {\n\t\t\tconst name = schema.$ref.split('/').pop();\n\t\t\treturn name ? all[name] : undefined;\n\t\t}\n\t\treturn schema as OpenApiSchema;\n\t}\n\n\tprivate fieldType(s: OpenApiSchema): string {\n\t\tif (s.enum) return 'enum';\n\t\tif (s.format === 'date') return 'date';\n\t\tif (s.format === 'time') return 'time';\n\t\tif (s.format === 'date-time') return 'datetime';\n\t\tif (s.type === 'integer' || s.type === 'number') return 'number';\n\t\treturn 'text';\n\t}\n\n\tprivate setValue(name: string, value: unknown) {\n\t\tthis.values = { ...this.values, [name]: value };\n\t}\n\n\tprivate onLocation = (e: Event) => {\n\t\tconst detail = (e as CustomEvent).detail as {\n\t\t\tlatitude?: number;\n\t\t\tlongitude?: number;\n\t\t\ttimezone?: string;\n\t\t\tutcOffset?: number;\n\t\t};\n\t\tif (detail) {\n\t\t\tthis.values = {\n\t\t\t\t...this.values,\n\t\t\t\tlatitude: detail.latitude,\n\t\t\t\tlongitude: detail.longitude,\n\t\t\t\ttimezone: detail.timezone ?? detail.utcOffset,\n\t\t\t};\n\t\t}\n\t};\n\n\tprivate onSubmit = (e: Event) => {\n\t\te.preventDefault();\n\t\tconst missing = this.fields\n\t\t\t.filter((f) => f.required)\n\t\t\t.filter(\n\t\t\t\t(f) => this.values[f.name] === undefined || this.values[f.name] === '',\n\t\t\t);\n\t\tif (missing.length > 0) {\n\t\t\tthis.dispatchEvent(\n\t\t\t\tnew CustomEvent('roxy-validation-error', {\n\t\t\t\t\tdetail: { missing: missing.map((m) => m.name) },\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcomposed: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('roxy-submit', {\n\t\t\t\tdetail: { endpoint: this.endpoint, values: this.values },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t);\n\t};\n\n\trender() {\n\t\tif (!this.loaded) {\n\t\t\treturn html`<form><div class=\"roxy-skeleton\" style=\"height: 8rem\"></div></form>`;\n\t\t}\n\n\t\tconst renderField = (f: FieldDef) => {\n\t\t\tif (\n\t\t\t\tthis.hasLocation &&\n\t\t\t\t(f.name === 'latitude' ||\n\t\t\t\t\tf.name === 'longitude' ||\n\t\t\t\t\tf.name === 'timezone')\n\t\t\t) {\n\t\t\t\treturn nothing;\n\t\t\t}\n\t\t\tconst inputId = `roxy-form-${f.name}`;\n\t\t\treturn html`<div class=\"field\">\n\t\t\t\t<label for=${inputId}>\n\t\t\t\t\t${humanize(f.name)}${f.required ? html`<span class=\"req\" aria-hidden=\"true\">*</span>` : nothing}\n\t\t\t\t</label>\n\t\t\t\t${\n\t\t\t\t\tf.enum\n\t\t\t\t\t\t? html`<select\n\t\t\t\t\t\t\tid=${inputId}\n\t\t\t\t\t\t\t?required=${f.required}\n\t\t\t\t\t\t\t@change=${(e: Event) => this.setValue(f.name, (e.target as HTMLSelectElement).value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<option value=\"\">Choose</option>\n\t\t\t\t\t\t\t${f.enum.map(\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\topt,\n\t\t\t\t\t\t\t\t) => html`<option value=${opt} ?selected=${this.values[f.name] === opt}>\n\t\t\t\t\t\t\t\t\t${opt}\n\t\t\t\t\t\t\t\t</option>`,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</select>`\n\t\t\t\t\t\t: html`<input\n\t\t\t\t\t\t\tid=${inputId}\n\t\t\t\t\t\t\ttype=${this.htmlType(f.type)}\n\t\t\t\t\t\t\t?required=${f.required}\n\t\t\t\t\t\t\tmin=${f.min ?? ''}\n\t\t\t\t\t\t\tmax=${f.max ?? ''}\n\t\t\t\t\t\t\tstep=${f.type === 'number' ? 'any' : ''}\n\t\t\t\t\t\t\t.value=${(this.values[f.name] ?? '') as string}\n\t\t\t\t\t\t\t@input=${(e: Event) =>\n\t\t\t\t\t\t\t\tthis.setValue(\n\t\t\t\t\t\t\t\t\tf.name,\n\t\t\t\t\t\t\t\t\tthis.coerce(f.type, (e.target as HTMLInputElement).value),\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>`\n\t\t\t\t}\n\t\t\t\t${f.description ? html`<small class=\"help\">${f.description}</small>` : nothing}\n\t\t\t</div>`;\n\t\t};\n\n\t\treturn html`<form @submit=${this.onSubmit}>\n\t\t\t<h2 class=\"title\">${humanize(this.endpoint.split('/').pop() ?? '')}</h2>\n\t\t\t${\n\t\t\t\tthis.hasLocation\n\t\t\t\t\t? html`<div class=\"location-block\">\n\t\t\t\t\t\t<label>Birth location</label>\n\t\t\t\t\t\t<roxy-location-search\n\t\t\t\t\t\t\t@roxy-location-select=${this.onLocation}\n\t\t\t\t\t\t\tplaceholder=\"City of birth\"\n\t\t\t\t\t\t></roxy-location-search>\n\t\t\t\t\t\t<small class=\"help\">\n\t\t\t\t\t\t\tRequired: latitude, longitude, timezone. Pick a city to autofill.\n\t\t\t\t\t\t</small>\n\t\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t\t<div class=\"fields\">\n\t\t\t\t${this.fields.map((f) => renderField(f))}\n\t\t\t</div>\n\t\t\t<button class=\"submit\" type=\"submit\">${this.submitLabel}</button>\n\t\t</form>`;\n\t}\n\n\tprivate htmlType(t: string): string {\n\t\tswitch (t) {\n\t\t\tcase 'date':\n\t\t\t\treturn 'date';\n\t\t\tcase 'time':\n\t\t\t\treturn 'time';\n\t\t\tcase 'datetime':\n\t\t\t\treturn 'datetime-local';\n\t\t\tcase 'number':\n\t\t\t\treturn 'number';\n\t\t\tdefault:\n\t\t\t\treturn 'text';\n\t\t}\n\t}\n\n\tprivate coerce(t: string, v: string): unknown {\n\t\tif (v === '') return undefined;\n\t\tif (t === 'number') {\n\t\t\tconst n = Number(v);\n\t\t\treturn Number.isFinite(n) ? n : undefined;\n\t\t}\n\t\treturn v;\n\t}\n}\n\nfunction humanize(s: string): string {\n\treturn s\n\t\t.replace(/[_-]+/g, ' ')\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-endpoint-form': RoxyEndpointForm;\n\t}\n}\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n"],
5
- "mappings": "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",
3
+ "sources": ["../../src/components/endpoint-form.ts", "../../src/utils/base-styles.ts", "../../src/utils/string.ts"],
4
+ "sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { baseStyles } from '../utils/base-styles.js';\nimport { humanize } from '../utils/string.js';\n\ninterface OpenApiSchemaRef {\n\t$ref?: string;\n}\n\ninterface OpenApiSchema extends OpenApiSchemaRef {\n\ttype?: string;\n\tformat?: string;\n\tdescription?: string;\n\tenum?: string[];\n\tdefault?: unknown;\n\tminimum?: number;\n\tmaximum?: number;\n\tproperties?: Record<string, OpenApiSchema>;\n\trequired?: string[];\n\titems?: OpenApiSchema;\n\texample?: unknown;\n}\n\ninterface FieldDef {\n\tname: string;\n\ttype: string;\n\trequired: boolean;\n\tdescription?: string;\n\tenum?: string[];\n\tmin?: number;\n\tmax?: number;\n\tdefault?: unknown;\n}\n\ninterface OpenApiDoc {\n\tpaths?: Record<string, Record<string, unknown>>;\n\tcomponents?: { schemas?: Record<string, OpenApiSchema> };\n}\n\nconst specCache = new Map<string, Promise<OpenApiDoc>>();\n\nasync function loadSpec(url: string): Promise<OpenApiDoc> {\n\tlet pending = specCache.get(url);\n\tif (!pending) {\n\t\tpending = fetch(url)\n\t\t\t.then(async (res) => {\n\t\t\t\tif (!res.ok) throw new Error(`HTTP ${res.status}`);\n\t\t\t\treturn (await res.json()) as OpenApiDoc;\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\t// Evict the rejected promise BEFORE rethrowing so subsequent\n\t\t\t\t// callers (the user clicking Retry, a remount) hit the network\n\t\t\t\t// again instead of replaying the cached failure forever.\n\t\t\t\tspecCache.delete(url);\n\t\t\t\tthrow err;\n\t\t\t});\n\t\tspecCache.set(url, pending);\n\t}\n\treturn pending;\n}\n\n/**\n * Schema-driven form. Pass `endpoint` (e.g. \"vedic-astrology/birth-chart\").\n * The form introspects the cached OpenAPI spec, slots a roxy-location-search\n * when latitude+longitude+timezone fields are present, and emits a\n * `roxy-submit` CustomEvent with the validated payload on submit. The caller\n * decides what to do (call the SDK, render a chart, navigate).\n *\n * Build-time hints (x-roxy-ui formGroups) are read by scripts/build.ts and\n * baked into a static map. At runtime the component falls back to runtime\n * fetch of /api/v2/openapi.json when no map is provided.\n */\n@customElement('roxy-endpoint-form')\nexport class RoxyEndpointForm extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\tform {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\t\t\tbox-shadow: var(--roxy-shadow-sm);\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\t\t\t.fields {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));\n\t\t\t\talign-items: start;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.field {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-direction: column;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t\tmin-width: 0;\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tcolor: var(--roxy-secondary, #475569);\n\t\t\t}\n\t\t\tlabel .req {\n\t\t\t\tcolor: var(--roxy-danger-fg, #991b1b);\n\t\t\t\tmargin-left: 4px;\n\t\t\t}\n\t\t\tinput,\n\t\t\tselect {\n\t\t\t\twidth: 100%;\n\t\t\t\tbox-sizing: border-box;\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-family: inherit;\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t}\n\t\t\tinput:focus,\n\t\t\tselect:focus {\n\t\t\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\t\t\toutline-offset: 2px;\n\t\t\t\tborder-color: var(--roxy-accent-fg, #b45309);\n\t\t\t}\n\t\t\t.help {\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t}\n\t\t\t.location-block {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t\tgrid-column: 1 / -1;\n\t\t\t}\n\t\t\t.coords {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: repeat(3, 1fr);\n\t\t\t\tgap: var(--roxy-space-sm, 0.5rem);\n\t\t\t}\n\t\t\t.coords input {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t\tbutton.submit {\n\t\t\t\tjustify-self: start;\n\t\t\t\tbackground: var(--roxy-accent-fg, #b45309);\n\t\t\t\tcolor: var(--roxy-bg, #fff);\n\t\t\t\tborder: 0;\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-lg, 1.5rem);\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tcursor: pointer;\n\t\t\t\ttransition:\n\t\t\t\t\ttransform var(--roxy-motion-duration, 200ms)\n\t\t\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1));\n\t\t\t}\n\t\t\tbutton.submit:hover {\n\t\t\t\ttransform: scale(1.02);\n\t\t\t}\n\t\t\tbutton.submit:focus-visible {\n\t\t\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\t\t\toutline-offset: 2px;\n\t\t\t}\n\t\t\t.spec-error {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tjustify-items: start;\n\t\t\t\tbackground: var(--roxy-bg, #fff);\n\t\t\t\tborder: 1px solid var(--roxy-danger, #dc2626);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\t\t\tcolor: var(--roxy-danger-fg, #991b1b);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ type: String, attribute: 'data-endpoint' })\n\tendpoint = 'vedic-astrology/birth-chart';\n\n\t@property({ type: String })\n\tmethod: 'GET' | 'POST' = 'POST';\n\n\t@property({ type: String, attribute: 'spec-url' })\n\tspecUrl = 'https://roxyapi.com/api/v2/openapi.json';\n\n\t@property({ type: String, attribute: 'submit-label' })\n\tsubmitLabel = 'Submit';\n\n\t@state()\n\tprivate fields: FieldDef[] = [];\n\n\t@state()\n\tprivate values: Record<string, unknown> = {};\n\n\t@state()\n\tprivate hasLocation = false;\n\n\t@state()\n\tprivate loaded = false;\n\n\t@state()\n\tprivate specError: string | null = null;\n\n\tconnectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tvoid this.loadSchema();\n\t}\n\n\tprivate async loadSchema() {\n\t\tthis.specError = null;\n\t\ttry {\n\t\t\tconst spec = await loadSpec(this.specUrl);\n\t\t\tconst path = `/${this.endpoint.replace(/^\\//, '')}`;\n\t\t\tconst op = spec.paths?.[path]?.[this.method.toLowerCase()] as\n\t\t\t\t| {\n\t\t\t\t\t\trequestBody?: {\n\t\t\t\t\t\t\tcontent?: Record<\n\t\t\t\t\t\t\t\tstring,\n\t\t\t\t\t\t\t\t{ schema?: OpenApiSchema | OpenApiSchemaRef }\n\t\t\t\t\t\t\t>;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tparameters?: Array<{\n\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\tin: string;\n\t\t\t\t\t\t\trequired?: boolean;\n\t\t\t\t\t\t\tschema?: OpenApiSchema;\n\t\t\t\t\t\t}>;\n\t\t\t\t }\n\t\t\t\t| undefined;\n\t\t\tif (!op) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Endpoint ${this.method} ${path} not found in OpenAPI spec`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst schemas = spec.components?.schemas ?? {};\n\t\t\tconst fields: FieldDef[] = [];\n\t\t\tlet bodySchema: OpenApiSchema | undefined;\n\n\t\t\tif (op.requestBody) {\n\t\t\t\tconst ref = op.requestBody.content?.['application/json']?.schema;\n\t\t\t\tbodySchema = this.resolve(ref, schemas);\n\t\t\t}\n\n\t\t\tif (bodySchema?.properties) {\n\t\t\t\tconst required = new Set(bodySchema.required ?? []);\n\t\t\t\tfor (const [name, sub] of Object.entries(bodySchema.properties)) {\n\t\t\t\t\tconst resolved = this.resolve(sub, schemas) ?? {};\n\t\t\t\t\tfields.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\ttype: this.fieldType(resolved),\n\t\t\t\t\t\trequired: required.has(name),\n\t\t\t\t\t\tdescription: resolved.description,\n\t\t\t\t\t\tenum: resolved.enum,\n\t\t\t\t\t\tmin: resolved.minimum,\n\t\t\t\t\t\tmax: resolved.maximum,\n\t\t\t\t\t\tdefault: resolved.default,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const param of op.parameters ?? []) {\n\t\t\t\tif (param.in === 'path' || param.in === 'query') {\n\t\t\t\t\tconst resolved = this.resolve(param.schema, schemas) ?? {};\n\t\t\t\t\tfields.push({\n\t\t\t\t\t\tname: param.name,\n\t\t\t\t\t\ttype: this.fieldType(resolved),\n\t\t\t\t\t\trequired: !!param.required,\n\t\t\t\t\t\tdescription: resolved.description,\n\t\t\t\t\t\tenum: resolved.enum,\n\t\t\t\t\t\tdefault: resolved.default,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.fields = fields;\n\t\t\tthis.hasLocation =\n\t\t\t\tfields.some((f) => f.name === 'latitude') &&\n\t\t\t\tfields.some((f) => f.name === 'longitude') &&\n\t\t\t\tfields.some((f) => f.name === 'timezone');\n\n\t\t\t// Pre-fill defaults\n\t\t\tconst init: Record<string, unknown> = {};\n\t\t\tfor (const f of fields) {\n\t\t\t\tif (f.default !== undefined) init[f.name] = f.default;\n\t\t\t}\n\t\t\tthis.values = init;\n\t\t\tthis.loaded = true;\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : String(err);\n\t\t\tthis.specError = message;\n\t\t\tthis.loaded = true;\n\t\t\tthis.dispatchEvent(\n\t\t\t\tnew CustomEvent('roxy-spec-error', {\n\t\t\t\t\tdetail: { url: this.specUrl, message },\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcomposed: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate retryLoadSchema = () => {\n\t\tthis.loaded = false;\n\t\tthis.specError = null;\n\t\tvoid this.loadSchema();\n\t};\n\n\tprivate resolve(\n\t\tschema: OpenApiSchema | OpenApiSchemaRef | undefined,\n\t\tall: Record<string, OpenApiSchema>,\n\t): OpenApiSchema | undefined {\n\t\tif (!schema) return undefined;\n\t\tif ('$ref' in schema && schema.$ref) {\n\t\t\tconst name = schema.$ref.split('/').pop();\n\t\t\treturn name ? all[name] : undefined;\n\t\t}\n\t\treturn schema as OpenApiSchema;\n\t}\n\n\tprivate fieldType(s: OpenApiSchema): string {\n\t\tif (s.enum) return 'enum';\n\t\tif (s.format === 'date') return 'date';\n\t\tif (s.format === 'time') return 'time';\n\t\tif (s.format === 'date-time') return 'datetime';\n\t\tif (s.type === 'integer' || s.type === 'number') return 'number';\n\t\treturn 'text';\n\t}\n\n\tprivate setValue(name: string, value: unknown) {\n\t\tthis.values = { ...this.values, [name]: value };\n\t}\n\n\tprivate onLocation = (e: Event) => {\n\t\tconst detail = (e as CustomEvent).detail as {\n\t\t\tlatitude?: number;\n\t\t\tlongitude?: number;\n\t\t\ttimezone?: string;\n\t\t\tutcOffset?: number;\n\t\t};\n\t\tif (detail) {\n\t\t\tthis.values = {\n\t\t\t\t...this.values,\n\t\t\t\tlatitude: detail.latitude,\n\t\t\t\tlongitude: detail.longitude,\n\t\t\t\ttimezone: detail.timezone ?? detail.utcOffset,\n\t\t\t};\n\t\t}\n\t};\n\n\tprivate onSubmit = (e: Event) => {\n\t\te.preventDefault();\n\t\tconst missing = this.fields\n\t\t\t.filter((f) => f.required)\n\t\t\t.filter(\n\t\t\t\t(f) => this.values[f.name] === undefined || this.values[f.name] === '',\n\t\t\t);\n\t\tif (missing.length > 0) {\n\t\t\tthis.dispatchEvent(\n\t\t\t\tnew CustomEvent('roxy-validation-error', {\n\t\t\t\t\tdetail: { missing: missing.map((m) => m.name) },\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcomposed: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('roxy-submit', {\n\t\t\t\tdetail: { endpoint: this.endpoint, values: this.values },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t);\n\t};\n\n\trender() {\n\t\tif (!this.loaded) {\n\t\t\treturn html`<form><div class=\"roxy-skeleton\" style=\"height: 8rem\"></div></form>`;\n\t\t}\n\n\t\tif (this.specError) {\n\t\t\treturn html`<div class=\"spec-error\" role=\"alert\">\n\t\t\t\tSchema load failed: ${this.specError}\n\t\t\t\t<button type=\"button\" class=\"submit\" @click=${this.retryLoadSchema}>Retry</button>\n\t\t\t</div>`;\n\t\t}\n\n\t\tconst renderField = (f: FieldDef) => {\n\t\t\tif (\n\t\t\t\tthis.hasLocation &&\n\t\t\t\t(f.name === 'latitude' ||\n\t\t\t\t\tf.name === 'longitude' ||\n\t\t\t\t\tf.name === 'timezone')\n\t\t\t) {\n\t\t\t\treturn nothing;\n\t\t\t}\n\t\t\tconst inputId = `roxy-form-${f.name}`;\n\t\t\treturn html`<div class=\"field\">\n\t\t\t\t<label for=${inputId}>\n\t\t\t\t\t${humanize(f.name)}${f.required ? html`<span class=\"req\" aria-hidden=\"true\">*</span>` : nothing}\n\t\t\t\t</label>\n\t\t\t\t${\n\t\t\t\t\tf.enum\n\t\t\t\t\t\t? html`<select\n\t\t\t\t\t\t\tid=${inputId}\n\t\t\t\t\t\t\t?required=${f.required}\n\t\t\t\t\t\t\t@change=${(e: Event) => this.setValue(f.name, (e.target as HTMLSelectElement).value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<option value=\"\">Choose</option>\n\t\t\t\t\t\t\t${f.enum.map(\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\topt,\n\t\t\t\t\t\t\t\t) => html`<option value=${opt} ?selected=${this.values[f.name] === opt}>\n\t\t\t\t\t\t\t\t\t${opt}\n\t\t\t\t\t\t\t\t</option>`,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</select>`\n\t\t\t\t\t\t: html`<input\n\t\t\t\t\t\t\tid=${inputId}\n\t\t\t\t\t\t\ttype=${this.htmlType(f.type)}\n\t\t\t\t\t\t\t?required=${f.required}\n\t\t\t\t\t\t\tmin=${f.min ?? ''}\n\t\t\t\t\t\t\tmax=${f.max ?? ''}\n\t\t\t\t\t\t\tstep=${f.type === 'number' ? 'any' : ''}\n\t\t\t\t\t\t\t.value=${(this.values[f.name] ?? '') as string}\n\t\t\t\t\t\t\t@input=${(e: Event) =>\n\t\t\t\t\t\t\t\tthis.setValue(\n\t\t\t\t\t\t\t\t\tf.name,\n\t\t\t\t\t\t\t\t\tthis.coerce(f.type, (e.target as HTMLInputElement).value),\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>`\n\t\t\t\t}\n\t\t\t\t${f.description ? html`<small class=\"help\">${f.description}</small>` : nothing}\n\t\t\t</div>`;\n\t\t};\n\n\t\treturn html`<form @submit=${this.onSubmit}>\n\t\t\t<h2 class=\"title\">${humanize(this.endpoint.split('/').pop() ?? '')}</h2>\n\t\t\t${\n\t\t\t\tthis.hasLocation\n\t\t\t\t\t? html`<div class=\"location-block\">\n\t\t\t\t\t\t<label>Birth location</label>\n\t\t\t\t\t\t<roxy-location-search\n\t\t\t\t\t\t\t@roxy-location-select=${this.onLocation}\n\t\t\t\t\t\t\tplaceholder=\"City of birth\"\n\t\t\t\t\t\t></roxy-location-search>\n\t\t\t\t\t\t<small class=\"help\">\n\t\t\t\t\t\t\tRequired: latitude, longitude, timezone. Pick a city to autofill.\n\t\t\t\t\t\t</small>\n\t\t\t\t\t</div>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t\t<div class=\"fields\">\n\t\t\t\t${this.fields.map((f) => renderField(f))}\n\t\t\t</div>\n\t\t\t<button class=\"submit\" type=\"submit\">${this.submitLabel}</button>\n\t\t</form>`;\n\t}\n\n\tprivate htmlType(t: string): string {\n\t\tswitch (t) {\n\t\t\tcase 'date':\n\t\t\t\treturn 'date';\n\t\t\tcase 'time':\n\t\t\t\treturn 'time';\n\t\t\tcase 'datetime':\n\t\t\t\treturn 'datetime-local';\n\t\t\tcase 'number':\n\t\t\t\treturn 'number';\n\t\t\tdefault:\n\t\t\t\treturn 'text';\n\t\t}\n\t}\n\n\tprivate coerce(t: string, v: string): unknown {\n\t\tif (v === '') return undefined;\n\t\tif (t === 'number') {\n\t\t\tconst n = Number(v);\n\t\t\treturn Number.isFinite(n) ? n : undefined;\n\t\t}\n\t\treturn v;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-endpoint-form': RoxyEndpointForm;\n\t}\n}\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n", "/**\n * Shared string helpers used across components. Single source of truth so the\n * same formatting rules apply to every key/label/title that surfaces in the\n * shadow tree.\n *\n * - `capitalize`: title-cases the first character, lowercases the rest. Used\n * when matching API-supplied planet/sign names against the glyph maps in\n * `tokens/index.ts`, which use canonical TitleCase keys.\n * - `humanize`: turns an API key (`birth_date`, `birthDate`, `mahadasha-end`)\n * into a label suitable for display (\"Birth date\", \"Mahadasha end\").\n */\n\nexport function capitalize(s: string): string {\n\tif (!s) return '';\n\treturn s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nexport function humanize(s: string): string {\n\treturn s\n\t\t.replace(/[_-]+/g, ' ')\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["css", "css"]
7
7
  }
@@ -1,28 +1,11 @@
1
1
  import { LitElement } from 'lit';
2
- interface GunaCategory {
3
- name?: string;
4
- score?: number;
5
- max?: number;
6
- maxScore?: number;
7
- description?: string;
8
- }
9
- interface GunaData {
10
- total?: number;
11
- totalScore?: number;
12
- maxScore?: number;
13
- percentage?: number;
14
- isCompatible?: boolean;
15
- recommendation?: string;
16
- doshas?: string[];
17
- doshaCancellations?: string[];
18
- breakdown?: GunaCategory[];
19
- }
2
+ import type { CompatibilityResponse } from '../types/index.js';
20
3
  /**
21
4
  * 36-point Ashtakoota score card. Renders /vedic-astrology/compatibility.
22
5
  */
23
6
  export declare class RoxyGunaMilan extends LitElement {
24
7
  static styles: import("lit").CSSResult[];
25
- data: GunaData | null;
8
+ data: CompatibilityResponse | null;
26
9
  render(): import("lit").TemplateResult<1>;
27
10
  }
28
11
  export declare const GUNA_CATEGORIES: string[];
@@ -31,5 +14,4 @@ declare global {
31
14
  'roxy-guna-milan': RoxyGunaMilan;
32
15
  }
33
16
  }
34
- export {};
35
17
  //# sourceMappingURL=guna-milan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guna-milan.d.ts","sourceRoot":"","sources":["../../src/components/guna-milan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAIrD,UAAU,YAAY;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,QAAQ;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;CAC3B;AAaD;;GAEG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC5C,MAAM,CAAC,MAAM,4BAgGX;IAGF,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAE7B,MAAM;CAsEN;AA2BD,eAAO,MAAM,eAAe,UAAsB,CAAC;AAEnD,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,iBAAiB,EAAE,aAAa,CAAC;KACjC;CACD"}
1
+ {"version":3,"file":"guna-milan.d.ts","sourceRoot":"","sources":["../../src/components/guna-milan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAErD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAe/D;;GAEG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC5C,MAAM,CAAC,MAAM,4BA4HX;IAGF,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAAQ;IAE1C,MAAM;CAqGN;AA0BD,eAAO,MAAM,eAAe,UAAsB,CAAC;AAEnD,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,iBAAiB,EAAE,aAAa,CAAC;KACjC;CACD"}