@roxyapi/ui 0.1.2 → 0.1.3

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 (167) hide show
  1. package/README.md +321 -14
  2. package/THEMING.md +24 -7
  3. package/dist/cdn/components/biorhythm-chart.js +15 -22
  4. package/dist/cdn/components/biorhythm-chart.js.map +3 -3
  5. package/dist/cdn/components/compatibility-card.js +36 -34
  6. package/dist/cdn/components/compatibility-card.js.map +4 -4
  7. package/dist/cdn/components/dasha-timeline.js +35 -39
  8. package/dist/cdn/components/dasha-timeline.js.map +4 -4
  9. package/dist/cdn/components/data.js +6 -6
  10. package/dist/cdn/components/data.js.map +3 -3
  11. package/dist/cdn/components/dosha-card.js +13 -13
  12. package/dist/cdn/components/dosha-card.js.map +2 -2
  13. package/dist/cdn/components/endpoint-form.js +47 -28
  14. package/dist/cdn/components/endpoint-form.js.map +3 -3
  15. package/dist/cdn/components/guna-milan.js +18 -18
  16. package/dist/cdn/components/guna-milan.js.map +4 -4
  17. package/dist/cdn/components/hexagram.js +26 -26
  18. package/dist/cdn/components/hexagram.js.map +3 -3
  19. package/dist/cdn/components/horoscope-card.js +38 -38
  20. package/dist/cdn/components/horoscope-card.js.map +3 -3
  21. package/dist/cdn/components/kp-planets-table.js +10 -10
  22. package/dist/cdn/components/kp-planets-table.js.map +4 -4
  23. package/dist/cdn/components/location-search.js +6 -6
  24. package/dist/cdn/components/location-search.js.map +3 -3
  25. package/dist/cdn/components/moon-phase.js +21 -21
  26. package/dist/cdn/components/moon-phase.js.map +4 -4
  27. package/dist/cdn/components/natal-chart.js +61 -19
  28. package/dist/cdn/components/natal-chart.js.map +4 -4
  29. package/dist/cdn/components/numerology-card.js +40 -31
  30. package/dist/cdn/components/numerology-card.js.map +3 -3
  31. package/dist/cdn/components/panchang-table.js +25 -25
  32. package/dist/cdn/components/panchang-table.js.map +4 -4
  33. package/dist/cdn/components/synastry-chart.js +129 -39
  34. package/dist/cdn/components/synastry-chart.js.map +4 -4
  35. package/dist/cdn/components/tarot-card.js +49 -20
  36. package/dist/cdn/components/tarot-card.js.map +3 -3
  37. package/dist/cdn/components/tarot-spread.js +43 -27
  38. package/dist/cdn/components/tarot-spread.js.map +3 -3
  39. package/dist/cdn/components/vedic-kundli.js +23 -9
  40. package/dist/cdn/components/vedic-kundli.js.map +3 -3
  41. package/dist/cdn/roxy-ui.js +560 -350
  42. package/dist/cdn/roxy-ui.js.map +4 -4
  43. package/dist/components/biorhythm-chart.d.ts +2 -46
  44. package/dist/components/biorhythm-chart.d.ts.map +1 -1
  45. package/dist/components/biorhythm-chart.js +24 -23
  46. package/dist/components/biorhythm-chart.js.map +2 -2
  47. package/dist/components/compatibility-card.d.ts +2 -27
  48. package/dist/components/compatibility-card.d.ts.map +1 -1
  49. package/dist/components/compatibility-card.js +50 -29
  50. package/dist/components/compatibility-card.js.map +3 -3
  51. package/dist/components/dasha-timeline.d.ts +2 -31
  52. package/dist/components/dasha-timeline.d.ts.map +1 -1
  53. package/dist/components/dasha-timeline.js +32 -30
  54. package/dist/components/dasha-timeline.js.map +3 -3
  55. package/dist/components/data.d.ts +6 -0
  56. package/dist/components/data.d.ts.map +1 -1
  57. package/dist/components/data.js +9 -1
  58. package/dist/components/data.js.map +2 -2
  59. package/dist/components/dosha-card.d.ts +2 -16
  60. package/dist/components/dosha-card.d.ts.map +1 -1
  61. package/dist/components/dosha-card.js +12 -13
  62. package/dist/components/dosha-card.js.map +2 -2
  63. package/dist/components/endpoint-form.d.ts +2 -0
  64. package/dist/components/endpoint-form.d.ts.map +1 -1
  65. package/dist/components/endpoint-form.js +66 -8
  66. package/dist/components/endpoint-form.js.map +2 -2
  67. package/dist/components/guna-milan.d.ts +2 -20
  68. package/dist/components/guna-milan.d.ts.map +1 -1
  69. package/dist/components/guna-milan.js +22 -12
  70. package/dist/components/guna-milan.js.map +3 -3
  71. package/dist/components/hexagram.d.ts +3 -27
  72. package/dist/components/hexagram.d.ts.map +1 -1
  73. package/dist/components/hexagram.js +31 -15
  74. package/dist/components/hexagram.js.map +2 -2
  75. package/dist/components/horoscope-card.d.ts +2 -20
  76. package/dist/components/horoscope-card.d.ts.map +1 -1
  77. package/dist/components/horoscope-card.js +24 -15
  78. package/dist/components/horoscope-card.js.map +2 -2
  79. package/dist/components/kp-planets-table.d.ts +2 -21
  80. package/dist/components/kp-planets-table.d.ts.map +1 -1
  81. package/dist/components/kp-planets-table.js +10 -4
  82. package/dist/components/kp-planets-table.js.map +3 -3
  83. package/dist/components/location-search.d.ts +3 -11
  84. package/dist/components/location-search.d.ts.map +1 -1
  85. package/dist/components/location-search.js +45 -5
  86. package/dist/components/location-search.js.map +2 -2
  87. package/dist/components/moon-phase.d.ts +4 -21
  88. package/dist/components/moon-phase.d.ts.map +1 -1
  89. package/dist/components/moon-phase.js +17 -4
  90. package/dist/components/moon-phase.js.map +3 -3
  91. package/dist/components/natal-chart.d.ts +7 -43
  92. package/dist/components/natal-chart.d.ts.map +1 -1
  93. package/dist/components/natal-chart.js +130 -70
  94. package/dist/components/natal-chart.js.map +3 -3
  95. package/dist/components/numerology-card.d.ts +5 -37
  96. package/dist/components/numerology-card.d.ts.map +1 -1
  97. package/dist/components/numerology-card.js +54 -28
  98. package/dist/components/numerology-card.js.map +2 -2
  99. package/dist/components/panchang-table.d.ts +3 -62
  100. package/dist/components/panchang-table.d.ts.map +1 -1
  101. package/dist/components/panchang-table.js +62 -32
  102. package/dist/components/panchang-table.js.map +3 -3
  103. package/dist/components/synastry-chart.d.ts +9 -28
  104. package/dist/components/synastry-chart.d.ts.map +1 -1
  105. package/dist/components/synastry-chart.js +178 -38
  106. package/dist/components/synastry-chart.js.map +3 -3
  107. package/dist/components/tarot-card.d.ts +5 -29
  108. package/dist/components/tarot-card.d.ts.map +1 -1
  109. package/dist/components/tarot-card.js +59 -20
  110. package/dist/components/tarot-card.js.map +2 -2
  111. package/dist/components/tarot-spread.d.ts +2 -24
  112. package/dist/components/tarot-spread.d.ts.map +1 -1
  113. package/dist/components/tarot-spread.js +39 -13
  114. package/dist/components/tarot-spread.js.map +2 -2
  115. package/dist/components/vedic-kundli.d.ts +3 -23
  116. package/dist/components/vedic-kundli.d.ts.map +1 -1
  117. package/dist/components/vedic-kundli.js +25 -13
  118. package/dist/components/vedic-kundli.js.map +2 -2
  119. package/dist/index.cjs +1149 -358
  120. package/dist/index.cjs.map +4 -4
  121. package/dist/index.d.ts +6 -4
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js +1149 -358
  124. package/dist/index.js.map +4 -4
  125. package/dist/manifest.d.ts +49 -0
  126. package/dist/manifest.d.ts.map +1 -0
  127. package/dist/manifest.json +1 -1
  128. package/dist/styles/tokens.css +47 -1
  129. package/dist/tokens/index.d.ts.map +1 -1
  130. package/dist/types/index.d.ts +2 -0
  131. package/dist/types/index.d.ts.map +1 -0
  132. package/dist/types/types.gen.d.ts +27811 -0
  133. package/dist/types/types.gen.d.ts.map +1 -0
  134. package/dist/utils/debounce.d.ts +9 -1
  135. package/dist/utils/debounce.d.ts.map +1 -1
  136. package/dist/utils/format.d.ts +15 -0
  137. package/dist/utils/format.d.ts.map +1 -0
  138. package/dist/version.d.ts +2 -0
  139. package/dist/version.d.ts.map +1 -0
  140. package/package.json +7 -1
  141. package/src/components/biorhythm-chart.ts +39 -84
  142. package/src/components/compatibility-card.ts +85 -52
  143. package/src/components/dasha-timeline.ts +55 -73
  144. package/src/components/data.ts +20 -1
  145. package/src/components/dosha-card.ts +18 -31
  146. package/src/components/endpoint-form.ts +79 -11
  147. package/src/components/guna-milan.ts +16 -34
  148. package/src/components/hexagram.ts +53 -43
  149. package/src/components/horoscope-card.ts +51 -39
  150. package/src/components/kp-planets-table.ts +8 -27
  151. package/src/components/location-search.ts +45 -20
  152. package/src/components/moon-phase.ts +28 -25
  153. package/src/components/natal-chart.ts +129 -84
  154. package/src/components/numerology-card.ts +87 -79
  155. package/src/components/panchang-table.ts +40 -78
  156. package/src/components/synastry-chart.ts +220 -78
  157. package/src/components/tarot-card.ts +76 -62
  158. package/src/components/tarot-spread.ts +72 -45
  159. package/src/components/vedic-kundli.ts +42 -51
  160. package/src/index.ts +14 -24
  161. package/src/manifest.ts +366 -0
  162. package/src/styles/tokens.css +47 -1
  163. package/src/tokens/index.ts +5 -0
  164. package/src/types/types.gen.ts +1 -1
  165. package/src/utils/debounce.ts +23 -4
  166. package/src/utils/format.ts +57 -0
  167. package/src/version.ts +2 -0
package/README.md CHANGED
@@ -1,17 +1,131 @@
1
1
  <p align="center">
2
2
  <a href="https://roxyapi.com/ui">
3
- <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/banner.png" alt="Roxy UI. Beautiful spiritual components in 30 minutes." width="100%">
3
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/banner.png" alt="Roxy UI: complete UI library for astrology, vedic, tarot, and more" width="100%">
4
4
  </a>
5
5
  </p>
6
6
 
7
7
  # @roxyapi/ui
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/@roxyapi/ui)](https://www.npmjs.com/package/@roxyapi/ui)
10
+ [![Live preview](https://img.shields.io/badge/live%20preview-roxyapi.github.io%2Fui-7c3aed?logo=github)](https://roxyapi.github.io/ui/)
10
11
  [![Docs](https://img.shields.io/badge/docs-roxyapi.com-blue)](https://roxyapi.com/ui)
11
12
  [![API Reference](https://img.shields.io/badge/api%20reference-roxyapi.com-blue)](https://roxyapi.com/api-reference)
12
13
  [![Pricing](https://img.shields.io/badge/pricing-roxyapi.com-blue)](https://roxyapi.com/pricing)
14
+ [![License](https://img.shields.io/npm/l/@roxyapi/ui)](LICENSE)
15
+
16
+ > Live demo: **<https://roxyapi.github.io/ui/>**. Every component rendered against real API responses, light + dark, with the React/shadcn install command per card.
17
+
18
+ Web components for the RoxyAPI catalog. Drop astrology, tarot, numerology, and every other RoxyAPI domain into any framework with one script tag or one npm install. Stateless components, typed responses, theme-agnostic. Beautiful defaults out of the box; the look is yours after that.
19
+
20
+ ## Theme-agnostic, every component
21
+
22
+ Light, dark, your brand. Override one CSS variable and every component updates. No class overrides, no rebuild, no Tailwind required. Customize live at <https://roxyapi.github.io/ui/> using the **Customize** dialog (every token, color picker, copy-paste snippet) or write your own variables on `:root`.
23
+
24
+ <table>
25
+ <tr>
26
+ <th width="50%" align="center">Light</th>
27
+ <th width="50%" align="center">Dark</th>
28
+ </tr>
29
+ <tr>
30
+ <td width="50%" align="center">
31
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/natal-chart-light.png" alt="Natal chart, light mode">
32
+ </td>
33
+ <td width="50%" align="center">
34
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/natal-chart-dark.png" alt="Natal chart, dark mode">
35
+ </td>
36
+ </tr>
37
+ <tr>
38
+ <td width="50%" align="center">
39
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/vedic-kundli-light.png" alt="Vedic kundli, light mode">
40
+ </td>
41
+ <td width="50%" align="center">
42
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/vedic-kundli-dark.png" alt="Vedic kundli, dark mode">
43
+ </td>
44
+ </tr>
45
+ </table>
13
46
 
14
- Web components for the RoxyAPI catalog. Drop astrology, tarot, numerology, and every other RoxyAPI domain into any framework with one script tag or one npm install. Stateless components, typed responses, beautiful defaults in 30 minutes.
47
+ ```css
48
+ :root {
49
+ /* Surface */
50
+ --roxy-bg: #fafafa;
51
+ --roxy-fg: #0a0a0a;
52
+ --roxy-muted: #71717a;
53
+ --roxy-border: #e4e4e7;
54
+
55
+ /* Brand */
56
+ --roxy-accent: #f59e0b;
57
+ --roxy-accent-fg: #b45309;
58
+
59
+ /* Status (each has a -fg variant for WCAG-AA text contrast) */
60
+ --roxy-success: #16a34a;
61
+ --roxy-warning: #f59e0b;
62
+ --roxy-danger: #dc2626;
63
+ --roxy-info: #2563eb;
64
+
65
+ /* Shape + motion */
66
+ --roxy-radius-md: 12px;
67
+ --roxy-shadow-md: 0 4px 12px rgba(0,0,0,0.08);
68
+ --roxy-motion-duration: 200ms; /* 0ms when prefers-reduced-motion */
69
+ }
70
+
71
+ [data-theme="dark"] {
72
+ --roxy-bg: #0a0a0a;
73
+ --roxy-fg: #fafafa;
74
+ --roxy-muted: #a1a1aa;
75
+ --roxy-border: #27272a;
76
+ }
77
+ ```
78
+
79
+ Pick a tone, set the vars, every chart and card follows. Full token reference at [THEMING.md](https://github.com/RoxyAPI/ui/blob/main/packages/ui/THEMING.md). Live tweaker on the [demo site](https://roxyapi.github.io/ui/).
80
+
81
+ ## Gallery (chart-heavy components)
82
+
83
+ <table>
84
+ <tr>
85
+ <td width="50%"><strong>Synastry</strong> · <code>&lt;roxy-synastry-chart&gt;</code><br><sub>POST /astrology/synastry</sub><br>
86
+ <picture>
87
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/synastry-chart-dark.png">
88
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/synastry-chart-light.png" alt="Synastry dual-wheel with inter-aspects">
89
+ </picture>
90
+ </td>
91
+ <td width="50%"><strong>Moon phase</strong> · <code>&lt;roxy-moon-phase&gt;</code><br><sub>GET /astrology/moon-phase/&lbrace;current,upcoming,calendar&rbrace;</sub><br>
92
+ <picture>
93
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/moon-phase-dark.png">
94
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/moon-phase-light.png" alt="Moon phase card with illumination and age">
95
+ </picture>
96
+ </td>
97
+ </tr>
98
+ <tr>
99
+ <td width="50%"><strong>Biorhythm</strong> · <code>&lt;roxy-biorhythm-chart&gt;</code><br><sub>POST /biorhythm/&lbrace;daily,forecast,critical-days&rbrace;</sub><br>
100
+ <picture>
101
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/biorhythm-chart-dark.png">
102
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/biorhythm-chart-light.png" alt="Biorhythm physical, emotional, intellectual cycle bars">
103
+ </picture>
104
+ </td>
105
+ <td width="50%"><strong>I Ching hexagram</strong> · <code>&lt;roxy-hexagram&gt;</code><br><sub>GET /iching/hexagrams/&lbrace;number&rbrace;, /iching/cast</sub><br>
106
+ <picture>
107
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/hexagram-dark.png">
108
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/hexagram-light.png" alt="I Ching hexagram with trigrams and judgment">
109
+ </picture>
110
+ </td>
111
+ </tr>
112
+ <tr>
113
+ <td width="50%"><strong>Dasha timeline</strong> · <code>&lt;roxy-dasha-timeline&gt;</code><br><sub>POST /vedic-astrology/dasha/&lbrace;current,major,sub&rbrace;</sub><br>
114
+ <picture>
115
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/dasha-timeline-dark.png">
116
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/dasha-timeline-light.png" alt="Vimshottari dasha mahadasha and antardasha timeline">
117
+ </picture>
118
+ </td>
119
+ <td width="50%"><strong>Tarot spread</strong> · <code>&lt;roxy-tarot-spread&gt;</code><br><sub>POST /tarot/spreads/&lbrace;three-card,celtic-cross,love&rbrace;</sub><br>
120
+ <picture>
121
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/tarot-spread-dark.png">
122
+ <img src="https://raw.githubusercontent.com/RoxyAPI/ui/main/assets/screenshots/tarot-spread-light.png" alt="Tarot spread with three-card layout and reading">
123
+ </picture>
124
+ </td>
125
+ </tr>
126
+ </table>
127
+
128
+ Tables, cards, forms, and helper components in the [live demo](https://roxyapi.github.io/ui/).
15
129
 
16
130
  ## Why developers use Roxy UI
17
131
 
@@ -34,7 +148,7 @@ Vanilla HTML. Three lines. No build step.
34
148
  ></script>
35
149
  <roxy-natal-chart id="chart"></roxy-natal-chart>
36
150
  <script type="module">
37
- import { createRoxy } from 'https://cdn.jsdelivr.net/npm/@roxyapi/sdk@1/dist/factory.js';
151
+ import { createRoxy } from 'https://cdn.jsdelivr.net/npm/@roxyapi/sdk@latest/dist/factory.js';
38
152
  const roxy = createRoxy(import.meta.env?.ROXY_API_KEY);
39
153
  const { data } = await roxy.astrology.generateNatalChart({
40
154
  body: { date: '1990-01-15', time: '14:30:00', latitude: 28.6139, longitude: 77.209, timezone: 5.5 },
@@ -93,18 +207,29 @@ document.querySelector('roxy-vedic-kundli')!.data = kundli;
93
207
 
94
208
  Always call `/location/search` first. Every chart endpoint expects latitude, longitude, and timezone.
95
209
 
210
+ > **Timezone format.** RoxyAPI accepts both forms: a decimal-hour offset (`5.5` for IST, `-5` for EST) or an IANA name (`'Asia/Kolkata'`, `'America/New_York'`). Pick one and stay consistent. The decimal form is shorter and what `/location/search` returns; examples on this page use it. The IANA form is correct over DST boundaries when historical accuracy matters.
211
+
212
+ ## API keys
213
+
214
+ Get keys at <https://roxyapi.com/account>.
215
+
216
+ - **Secret key** (server-side only). Use in Node, Bun, Hono, Next.js route handlers, Workers. Never commit, never ship in client bundles.
217
+ - **Publishable key** (`pk_live_*` / `pk_test_*`). Safe in browsers, locked to the origins you register on the key. Use with the widgets auto-mount script for WordPress, Shopify, static HTML, embed scenarios. The API gateway rejects requests from any origin not on the key's allowlist.
218
+
219
+ For the SDK examples on this page, set `ROXY_API_KEY` to a secret key in your server env. For the widgets auto-mount path (`data-publishable-key="pk_live_xxx"`), use a publishable key with your site's domain registered.
220
+
96
221
  ## Distribution
97
222
 
98
223
  | Surface | URL |
99
224
  |---|---|
100
225
  | npm `@roxyapi/ui` | `npmjs.com/package/@roxyapi/ui` |
101
226
  | npm `@roxyapi/ui-react` | `npmjs.com/package/@roxyapi/ui-react` |
102
- | jsdelivr full UMD | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js` |
103
- | jsdelivr per-component UMD | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/components/{name}.js` |
227
+ | jsDelivr CDN (full bundle) | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js` |
228
+ | jsDelivr CDN (per component) | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/components/{name}.js` |
104
229
  | Widgets auto-mount | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/widgets.js` |
105
- | shadcn registry | `bunx shadcn add https://cdn.jsdelivr.net/gh/RoxyAPI/ui@main/registry/{name}.json` |
230
+ | shadcn registry | `npx shadcn@latest add https://cdn.jsdelivr.net/gh/RoxyAPI/ui@v0.1.2/registry/{name}.json` |
106
231
 
107
- ## Phase 1 components
232
+ ## Components
108
233
 
109
234
  <!-- BEGIN:COMPONENTS -->
110
235
  | Element | Domain | Endpoint(s) | What it renders |
@@ -139,11 +264,10 @@ Always call `/location/search` first. Every chart endpoint expects latitude, lon
139
264
  - Numerology calculators with full-chart breakdowns and personal year forecasts.
140
265
  - Biorhythm dashboards with critical-day alerts.
141
266
  - I Ching apps with hexagram lookup and three-coin casting.
142
- - Founder hosted-app surfaces consuming the same components under brand themes.
143
267
 
144
268
  ## Theming
145
269
 
146
- Every component reads from `--roxy-*` CSS custom properties. Override globally on `:root` or per element. Light + dark defaults, container queries for responsive layouts at 320px and up. See [THEMING.md](packages/ui/THEMING.md) for the full token reference.
270
+ Every component reads from `--roxy-*` CSS custom properties. Override globally on `:root` or per element. Light + dark defaults, container queries for responsive layouts at 320px and up. See [THEMING.md](https://github.com/RoxyAPI/ui/blob/main/packages/ui/THEMING.md) for the full token reference.
147
271
 
148
272
  ```css
149
273
  :root {
@@ -167,10 +291,13 @@ roxy-natal-chart {
167
291
 
168
292
  ## Built for AI agents
169
293
 
170
- - Works with Claude Code, Cursor, Copilot, Codex, Gemini CLI.
171
- - Ships with `AGENTS.md` so agents know which component to render for which response.
172
- - Combines with the `@roxyapi/sdk` for typed prop shapes that match the OpenAPI spec.
173
- - Remote MCP servers per domain at `roxyapi.com/mcp/{domain}`. No local setup, runs in seconds.
294
+ [`AGENTS.md`](AGENTS.md) is bundled inside both npm packages. Once installed, agents can read it from `node_modules/@roxyapi/ui/AGENTS.md` (or `@roxyapi/ui-react/AGENTS.md`) for the component decision tree, integration patterns, and rules.
295
+
296
+ - Works with Claude Code, Cursor, Copilot, Codex, Gemini CLI, and any MCP-compatible client.
297
+ - Component decision tree maps each RoxyAPI endpoint to the component that renders its response.
298
+ - Typed prop shapes derive from the OpenAPI spec. The SDK at `@roxyapi/sdk` returns shapes that flow straight into `data`. No field renames, no glue code.
299
+ - Remote MCP servers per domain at `roxyapi.com/mcp/{domain}`. No local setup. JSON tool-call responses feed straight into the matching component.
300
+ - Use cases agents handle in one prompt: birth chart from city + DOB, daily tarot embed, Vedic kundli matching, numerology life-path card, biorhythm dashboard, daily horoscope by sign, panchang for the day, I Ching three-coin cast.
174
301
 
175
302
  ## Build anything, fast
176
303
 
@@ -183,7 +310,187 @@ bun run preview
183
310
  # http://localhost:3001
184
311
  ```
185
312
 
186
- Three steps. Thirty minutes. See [examples](examples/) for a full vanilla HTML, React, Vue, and WordPress integration.
313
+ Local preview serves `apps/docs/` on port 3001. Same directory and same paths the live demo at <https://roxyapi.github.io/ui/> serves. See [examples](examples/) for vanilla HTML, React, Vue, and WordPress.
314
+
315
+ ## Stack and integrations
316
+
317
+ Roxy UI runs in any framework that supports the DOM: **React, Next.js, Vue, Svelte, Angular, Solid, Astro, Qwik, Hono, Remix, Nuxt, SvelteKit, Lit, plain HTML, WordPress, Shopify themes that allow custom code, and any MCP-compatible AI agent**. Distribution paths: npm, jsDelivr CDN, shadcn registry. Use cases: astrology widgets, kundli matching, daily horoscope, tarot reader, numerology calculator, biorhythm dashboard, I Ching cast, panchang almanac, dasha timeline, moon phase tracker, synastry compatibility, dosha checker.
318
+
319
+ ## FAQ
320
+
321
+ <details>
322
+ <summary><strong>How big is each component? What is the bundle cost?</strong></summary>
323
+
324
+ Per-component bundles run 8-10 KB gzipped, capped at 30 KB by CI. The full bundle (every component, helpers, base styles) is around 26 KB gzipped, capped at 150 KB. The React package loads the runtime on mount, so a route that renders one chart pays for one component, not the whole catalog. Pin a concrete version in production for byte-stable cache hits.
325
+ </details>
326
+
327
+ <details>
328
+ <summary><strong>Does this work with Next.js App Router, Remix, Nuxt, SvelteKit, and Astro?</strong></summary>
329
+
330
+ Yes. The components are standard custom elements; any framework that touches the DOM can mount them. For SSR/RSC frameworks, fetch on the server, pass the response to a client island. Next.js App Router pattern:
331
+
332
+ ```tsx
333
+ // app/page.tsx (Server Component)
334
+ import { createRoxy } from '@roxyapi/sdk';
335
+ import ChartView from './chart-view';
336
+
337
+ const roxy = createRoxy(process.env.ROXY_API_KEY!);
338
+
339
+ export default async function Page() {
340
+ const { data } = await roxy.astrology.generateNatalChart({
341
+ body: { date: '1990-01-15', time: '14:30:00', latitude: 28.6139, longitude: 77.209, timezone: 5.5 },
342
+ });
343
+ return <ChartView data={data} />;
344
+ }
345
+ ```
346
+
347
+ ```tsx
348
+ // app/chart-view.tsx (Client Component)
349
+ 'use client';
350
+ import { RoxyNatalChart } from '@roxyapi/ui-react';
351
+
352
+ export default function ChartView({ data }: { data: unknown }) {
353
+ return <RoxyNatalChart data={data} />;
354
+ }
355
+ ```
356
+
357
+ The server component fetches, the client component renders. The API key never crosses the network. Same shape works in Remix loaders, Nuxt server routes, SvelteKit `+page.server.ts`, and Astro server endpoints.
358
+ </details>
359
+
360
+ <details>
361
+ <summary><strong>Tailwind v3 vs v4 compatibility?</strong></summary>
362
+
363
+ Both work. Components do not consume Tailwind utilities. Tailwind utilities apply outside the components on wrappers and containers; inside the Shadow DOM, components read `--roxy-*` CSS custom properties only.
364
+
365
+ For Tailwind v4 users, the shadcn registry installs a CSS bridge that maps your existing v4 design tokens onto `--roxy-*`. For Tailwind v3 users, set `--roxy-*` directly on `:root`, or write a tiny bridge:
366
+
367
+ ```css
368
+ :root {
369
+ --roxy-bg: theme(colors.background);
370
+ --roxy-fg: theme(colors.foreground);
371
+ --roxy-accent: theme(colors.primary.DEFAULT);
372
+ --roxy-border: theme(colors.border);
373
+ }
374
+ ```
375
+ </details>
376
+
377
+ <details>
378
+ <summary><strong>How do React 17/18 vs 19 differ for custom-event handling?</strong></summary>
379
+
380
+ React 19 routes hyphenated DOM events through camelCase props or lowercase attributes correctly, so `<RoxyLocationSearch onroxy-location-select={...}>` works as expected.
381
+
382
+ For React 17 and 18, use a ref plus `addEventListener` in `useEffect`:
383
+
384
+ ```tsx
385
+ const ref = useRef<HTMLElement>(null);
386
+ useEffect(() => {
387
+ const el = ref.current;
388
+ if (!el) return;
389
+ const handler = (e: Event) => console.log((e as CustomEvent).detail);
390
+ el.addEventListener('roxy-location-select', handler);
391
+ return () => el.removeEventListener('roxy-location-select', handler);
392
+ }, []);
393
+
394
+ return <roxy-location-search ref={ref} />;
395
+ ```
396
+
397
+ Upgrade to React 19 when you can; the wrappers route everything cleanly.
398
+ </details>
399
+
400
+ <details>
401
+ <summary><strong>Browser support matrix?</strong></summary>
402
+
403
+ Chrome 120+, Firefox 120+, Safari 17+, Edge 120+. The floor is set by ES modules, Custom Elements v1, Shadow DOM v1, container queries, and `color-mix()`. No polyfills shipped; older browsers fail loud rather than degrade silently. This covers ~95% of global traffic per Can I Use.
404
+ </details>
405
+
406
+ <details>
407
+ <summary><strong>Are the TypeScript types reliable?</strong></summary>
408
+
409
+ Yes. Component prop types are regenerated from the OpenAPI spec on every release via `@hey-api/openapi-ts`. Spec change in the API translates to typed change at the component boundary. There are no hand-written response shapes inside components, so types cannot drift from what the API returns. The SDK at `@roxyapi/sdk` shares the same type pipeline.
410
+ </details>
411
+
412
+ <details>
413
+ <summary><strong>What is the accessibility story?</strong></summary>
414
+
415
+ WAI-ARIA 1.2 throughout. Keyboard navigation on every interactive surface. Focus rings honor `--roxy-ring`. `prefers-reduced-motion: reduce` pins `--roxy-motion-duration` to `0ms` and disables entry animations. Color contrast hits WCAG AA at the defaults; verify any custom palette before shipping. CI runs axe-core against every component; zero blocking violations is a build gate.
416
+ </details>
417
+
418
+ <details>
419
+ <summary><strong>Why can my Tailwind classes not reach the chart inside the component?</strong></summary>
420
+
421
+ Components ship in Shadow DOM for style isolation; Tailwind utilities are scoped to the page tree and stop at the shadow boundary. This is by design: customer styles cannot accidentally bleed into a chart, and component styles cannot leak out. Theme through `--roxy-*` custom properties (they pierce the shadow boundary) on `:root` or per element.
422
+ </details>
423
+
424
+ <details>
425
+ <summary><strong>What is the security model for API keys?</strong></summary>
426
+
427
+ Two key classes. Secret keys (unprefixed) live server-side only and grant full access. Publishable keys (`pk_live_*` / `pk_test_*`) are browser-safe and locked to an origin allowlist registered on the key. The API gateway rejects requests from any other origin and counts the failed attempt against the rate limit, so a stolen key cannot be brute-fired from elsewhere.
428
+
429
+ For CSP, allow `script-src https://cdn.jsdelivr.net` if loading the bundle from the CDN. Subresource Integrity hashes are available via the jsDelivr SRI API for any pinned version.
430
+ </details>
431
+
432
+ <details>
433
+ <summary><strong>How does versioning work?</strong></summary>
434
+
435
+ Semver. Pre-1.0, minor bumps may include breaking changes (we will note them in the changelog). Patch bumps are always backwards-compatible. Pin a concrete version in production code:
436
+
437
+ ```bash
438
+ npm install @roxyapi/ui@0.1.x
439
+ ```
440
+
441
+ ```html
442
+ <script src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@0.1.5/dist/cdn/roxy-ui.js"></script>
443
+ ```
444
+
445
+ The `@latest` URL on this page is for paste-friendly marketing; production code should pin.
446
+ </details>
447
+
448
+ <details>
449
+ <summary><strong>How do I test components in my app?</strong></summary>
450
+
451
+ Mock `@roxyapi/sdk` at the network boundary so unit tests do not hit the live API. Snapshot the Shadow DOM output for visual stability. End-to-end with Playwright works well; the components emit semantic ARIA roles, so locators are stable across releases.
452
+ </details>
453
+
454
+ <details>
455
+ <summary><strong>What if I want to fork or own a component?</strong></summary>
456
+
457
+ Use the shadcn registry. The registry drops the component source, a wrapper file, and a CSS theme bridge into your repo. Edit anything; the source is yours from that point.
458
+
459
+ ```bash
460
+ npx shadcn@latest add https://cdn.jsdelivr.net/gh/RoxyAPI/ui@v0.1.2/registry/natal-chart.json
461
+ ```
462
+ </details>
463
+
464
+ <details>
465
+ <summary><strong>What if I need an endpoint that has no dedicated component?</strong></summary>
466
+
467
+ Use `<roxy-data>`. It is the generic fallback renderer; pass any RoxyAPI response and it produces a structured layout (tables, lists, badges) without bespoke logic. New endpoints render automatically; bespoke components ship only when a novel pattern emerges.
468
+ </details>
469
+
470
+ <details>
471
+ <summary><strong>Does this integrate with MCP-aware AI agents?</strong></summary>
472
+
473
+ Yes. RoxyAPI hosts a remote MCP server per domain at `roxyapi.com/mcp/{domain}`. Configure once, render anywhere:
474
+
475
+ ```json
476
+ {
477
+ "mcpServers": {
478
+ "roxy-astrology": {
479
+ "url": "https://roxyapi.com/mcp/astrology",
480
+ "headers": { "Authorization": "Bearer <your-secret-key>" }
481
+ }
482
+ }
483
+ }
484
+ ```
485
+
486
+ Tool-call JSON has the same shape as the SDK response. Pass it straight into the matching component.
487
+ </details>
488
+
489
+ <details>
490
+ <summary><strong>License and contribution?</strong></summary>
491
+
492
+ MIT. Source on [GitHub](https://github.com/RoxyAPI/ui). Open an issue or pull request for bugs and ideas. The component manifest is data-driven, so most additions are spec changes upstream rather than UI repo edits.
493
+ </details>
187
494
 
188
495
  ## License
189
496
 
package/THEMING.md CHANGED
@@ -8,19 +8,20 @@ Every Roxy UI component reads its colors, fonts, spacing, and motion from a sing
8
8
 
9
9
  | Variable | Light default | Dark default | Used by |
10
10
  |---|---|---|---|
11
- | `--roxy-primary` | `#0f172a` | `#f8fafc` | Headings, primary text |
12
- | `--roxy-secondary` | `#475569` | `#94a3b8` | Subheadings, muted accents |
11
+ | `--roxy-bg` | `#ffffff` | `#0a0a0a` | Card and chart backgrounds |
12
+ | `--roxy-fg` | `#0a0a0a` | `#fafafa` | Body text, headings |
13
+ | `--roxy-muted` | `#71717a` | `#a1a1aa` | Secondary text, subheadings |
14
+ | `--roxy-border` | `#e4e4e7` | `#27272a` | Wheel lines, table borders |
13
15
  | `--roxy-accent` | `#f59e0b` | `#fbbf24` | Planet glyphs, hexagram lines, focused state |
16
+ | `--roxy-accent-fg` | `#b45309` | `#fcd34d` | Accent-on-accent text (WCAG-AA contrast) |
14
17
  | `--roxy-success` | `#16a34a` | `#22c55e` | Positive doshas, biorhythm peaks |
15
18
  | `--roxy-warning` | `#ea580c` | `#fb923c` | Caution states, mid severity |
16
19
  | `--roxy-danger` | `#dc2626` | `#ef4444` | Manglik present, critical days |
17
20
  | `--roxy-info` | `#0284c7` | `#38bdf8` | Informational badges |
18
- | `--roxy-bg` | `#ffffff` | `#0a0a0a` | Card and chart backgrounds |
19
- | `--roxy-fg` | `#0a0a0a` | `#fafafa` | Body text |
20
- | `--roxy-muted` | `#71717a` | `#a1a1aa` | Secondary text |
21
- | `--roxy-border` | `#e4e4e7` | `#27272a` | Wheel lines, table borders |
22
21
  | `--roxy-ring` | `rgba(245, 158, 11, 0.4)` | `rgba(251, 191, 36, 0.45)` | Focus outlines |
23
22
 
23
+ Status tokens each have a `-fg` variant (e.g. `--roxy-success-fg`) for text rendered on top of the status color, sized for WCAG-AA contrast.
24
+
24
25
  ### Typography
25
26
 
26
27
  | Variable | Default | Notes |
@@ -112,7 +113,21 @@ Three opt-in mechanisms work out of the box.
112
113
 
113
114
  ### Map Tailwind tokens
114
115
 
115
- Tailwind users can map our tokens to theirs in five lines of `globals.css`:
116
+ Tailwind users can map our tokens to theirs in five lines of `globals.css`. Pick the syntax that matches your Tailwind version.
117
+
118
+ **Tailwind v4 (CSS-first config, recommended):**
119
+
120
+ ```css
121
+ :root {
122
+ --roxy-bg: var(--color-background);
123
+ --roxy-fg: var(--color-foreground);
124
+ --roxy-accent: var(--color-primary);
125
+ --roxy-border: var(--color-border);
126
+ --roxy-radius-md: var(--radius);
127
+ }
128
+ ```
129
+
130
+ **Tailwind v3 (`tailwind.config.js`):**
116
131
 
117
132
  ```css
118
133
  :root {
@@ -124,6 +139,8 @@ Tailwind users can map our tokens to theirs in five lines of `globals.css`:
124
139
  }
125
140
  ```
126
141
 
142
+ If you used the shadcn registry path, this bridge installs automatically and reads from your existing shadcn tokens.
143
+
127
144
  ## A11y
128
145
 
129
146
  Color contrast must stay at 4.5:1 minimum against `--roxy-bg` for body text and 3:1 for large text. The defaults pass WCAG AA. Verify any custom palette with the axe Chrome extension or any contrast checker before shipping.
@@ -1,6 +1,6 @@
1
- "use strict";var RoxyUI_biorhythm_chart=(()=>{var T=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var wt=Object.getOwnPropertyNames;var Ct=Object.prototype.hasOwnProperty;var Pt=(i,t)=>{for(var e in t)T(i,e,{get:t[e],enumerable:!0})},Dt=(i,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of wt(t))!Ct.call(i,r)&&r!==e&&T(i,r,{get:()=>t[r],enumerable:!(s=rt(t,r))||s.enumerable});return i};var Ot=i=>Dt(T({},"__esModule",{value:!0}),i),H=(i,t,e,s)=>{for(var r=s>1?void 0:s?rt(t,e):t,o=i.length-1,n;o>=0;o--)(n=i[o])&&(r=(s?n(t,e,r):n(r))||r);return s&&r&&T(t,e,r),r};var Wt={};Pt(Wt,{RoxyBiorhythmChart:()=>v});var j=globalThis,z=j.ShadowRoot&&(j.ShadyCSS===void 0||j.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,V=Symbol(),it=new WeakMap,C=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==V)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o,e=this.t;if(z&&t===void 0){let s=e!==void 0&&e.length===1;s&&(t=it.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),s&&it.set(e,t))}return t}toString(){return this.cssText}},ot=i=>new C(typeof i=="string"?i:i+"",void 0,V),P=(i,...t)=>{let e=i.length===1?i[0]:t.reduce((s,r,o)=>s+(n=>{if(n._$cssResult$===!0)return n.cssText;if(typeof n=="number")return n;throw Error("Value passed to 'css' function must be a 'css' function result: "+n+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(r)+i[o+1],i[0]);return new C(e,i,V)},nt=(i,t)=>{if(z)i.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of t){let s=document.createElement("style"),r=j.litNonce;r!==void 0&&s.setAttribute("nonce",r),s.textContent=e.cssText,i.appendChild(s)}},W=z?i=>i:i=>i instanceof CSSStyleSheet?(t=>{let e="";for(let s of t.cssRules)e+=s.cssText;return ot(e)})(i):i;var{is:Ut,defineProperty:kt,getOwnPropertyDescriptor:Rt,getOwnPropertyNames:Mt,getOwnPropertySymbols:Nt,getPrototypeOf:Tt}=Object,B=globalThis,at=B.trustedTypes,Ht=at?at.emptyScript:"",jt=B.reactiveElementPolyfillSupport,D=(i,t)=>i,O={toAttribute(i,t){switch(t){case Boolean:i=i?Ht:null;break;case Object:case Array:i=i==null?i:JSON.stringify(i)}return i},fromAttribute(i,t){let e=i;switch(t){case Boolean:e=i!==null;break;case Number:e=i===null?null:Number(i);break;case Object:case Array:try{e=JSON.parse(i)}catch{e=null}}return e}},L=(i,t)=>!Ut(i,t),ct={attribute:!0,type:String,converter:O,reflect:!1,useDefault:!1,hasChanged:L};Symbol.metadata??=Symbol("metadata"),B.litPropertyMetadata??=new WeakMap;var f=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=ct){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){let s=Symbol(),r=this.getPropertyDescriptor(t,s,e);r!==void 0&&kt(this.prototype,t,r)}}static getPropertyDescriptor(t,e,s){let{get:r,set:o}=Rt(this.prototype,t)??{get(){return this[e]},set(n){this[e]=n}};return{get:r,set(n){let c=r?.call(this);o?.call(this,n),this.requestUpdate(t,c,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??ct}static _$Ei(){if(this.hasOwnProperty(D("elementProperties")))return;let t=Tt(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(D("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(D("properties"))){let e=this.properties,s=[...Mt(e),...Nt(e)];for(let r of s)this.createProperty(r,e[r])}let t=this[Symbol.metadata];if(t!==null){let e=litPropertyMetadata.get(t);if(e!==void 0)for(let[s,r]of e)this.elementProperties.set(s,r)}this._$Eh=new Map;for(let[e,s]of this.elementProperties){let r=this._$Eu(e,s);r!==void 0&&this._$Eh.set(r,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){let e=[];if(Array.isArray(t)){let s=new Set(t.flat(1/0).reverse());for(let r of s)e.unshift(W(r))}else t!==void 0&&e.push(W(t));return e}static _$Eu(t,e){let s=e.attribute;return s===!1?void 0:typeof s=="string"?s:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){let t=new Map,e=this.constructor.elementProperties;for(let s of e.keys())this.hasOwnProperty(s)&&(t.set(s,this[s]),delete this[s]);t.size>0&&(this._$Ep=t)}createRenderRoot(){let t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return nt(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,s){this._$AK(t,s)}_$ET(t,e){let s=this.constructor.elementProperties.get(t),r=this.constructor._$Eu(t,s);if(r!==void 0&&s.reflect===!0){let o=(s.converter?.toAttribute!==void 0?s.converter:O).toAttribute(e,s.type);this._$Em=t,o==null?this.removeAttribute(r):this.setAttribute(r,o),this._$Em=null}}_$AK(t,e){let s=this.constructor,r=s._$Eh.get(t);if(r!==void 0&&this._$Em!==r){let o=s.getPropertyOptions(r),n=typeof o.converter=="function"?{fromAttribute:o.converter}:o.converter?.fromAttribute!==void 0?o.converter:O;this._$Em=r;let c=n.fromAttribute(e,o.type);this[r]=c??this._$Ej?.get(r)??c,this._$Em=null}}requestUpdate(t,e,s,r=!1,o){if(t!==void 0){let n=this.constructor;if(r===!1&&(o=this[t]),s??=n.getPropertyOptions(t),!((s.hasChanged??L)(o,e)||s.useDefault&&s.reflect&&o===this._$Ej?.get(t)&&!this.hasAttribute(n._$Eu(t,s))))return;this.C(t,e,s)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:s,reflect:r,wrapped:o},n){s&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,n??e??this[t]),o!==!0||n!==void 0)||(this._$AL.has(t)||(this.hasUpdated||s||(e=void 0),this._$AL.set(t,e)),r===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}let t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[r,o]of this._$Ep)this[r]=o;this._$Ep=void 0}let s=this.constructor.elementProperties;if(s.size>0)for(let[r,o]of s){let{wrapped:n}=o,c=this[r];n!==!0||this._$AL.has(r)||c===void 0||this.C(r,void 0,o,c)}}let t=!1,e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(s=>s.hostUpdate?.()),this.update(e)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(t){}firstUpdated(t){}};f.elementStyles=[],f.shadowRootOptions={mode:"open"},f[D("elementProperties")]=new Map,f[D("finalized")]=new Map,jt?.({ReactiveElement:f}),(B.reactiveElementVersions??=[]).push("2.1.2");var X=globalThis,lt=i=>i,q=X.trustedTypes,ht=q?q.createPolicy("lit-html",{createHTML:i=>i}):void 0,ft="$lit$",g=`lit$${Math.random().toFixed(9).slice(2)}$`,gt="?"+g,zt=`<${gt}>`,x=document,k=()=>x.createComment(""),R=i=>i===null||typeof i!="object"&&typeof i!="function",tt=Array.isArray,Bt=i=>tt(i)||typeof i?.[Symbol.iterator]=="function",K=`[
2
- \f\r]`,U=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,dt=/-->/g,pt=/>/g,_=RegExp(`>|${K}(?:([^\\s"'>=/]+)(${K}*=${K}*(?:[^
3
- \f\r"'\`<>=]|("|')|))|$)`,"g"),ut=/'/g,mt=/"/g,$t=/^(?:script|style|textarea|title)$/i,et=i=>(t,...e)=>({_$litType$:i,strings:t,values:e}),u=et(1),vt=et(2),Qt=et(3),A=Symbol.for("lit-noChange"),h=Symbol.for("lit-nothing"),yt=new WeakMap,b=x.createTreeWalker(x,129);function _t(i,t){if(!tt(i)||!i.hasOwnProperty("raw"))throw Error("invalid template strings array");return ht!==void 0?ht.createHTML(t):t}var Lt=(i,t)=>{let e=i.length-1,s=[],r,o=t===2?"<svg>":t===3?"<math>":"",n=U;for(let c=0;c<e;c++){let a=i[c],d,p,l=-1,m=0;for(;m<a.length&&(n.lastIndex=m,p=n.exec(a),p!==null);)m=n.lastIndex,n===U?p[1]==="!--"?n=dt:p[1]!==void 0?n=pt:p[2]!==void 0?($t.test(p[2])&&(r=RegExp("</"+p[2],"g")),n=_):p[3]!==void 0&&(n=_):n===_?p[0]===">"?(n=r??U,l=-1):p[1]===void 0?l=-2:(l=n.lastIndex-p[2].length,d=p[1],n=p[3]===void 0?_:p[3]==='"'?mt:ut):n===mt||n===ut?n=_:n===dt||n===pt?n=U:(n=_,r=void 0);let y=n===_&&i[c+1].startsWith("/>")?" ":"";o+=n===U?a+zt:l>=0?(s.push(d),a.slice(0,l)+ft+a.slice(l)+g+y):a+g+(l===-2?c:y)}return[_t(i,o+(i[e]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),s]},M=class i{constructor({strings:t,_$litType$:e},s){let r;this.parts=[];let o=0,n=0,c=t.length-1,a=this.parts,[d,p]=Lt(t,e);if(this.el=i.createElement(d,s),b.currentNode=this.el.content,e===2||e===3){let l=this.el.content.firstChild;l.replaceWith(...l.childNodes)}for(;(r=b.nextNode())!==null&&a.length<c;){if(r.nodeType===1){if(r.hasAttributes())for(let l of r.getAttributeNames())if(l.endsWith(ft)){let m=p[n++],y=r.getAttribute(l).split(g),S=/([.?@])?(.*)/.exec(m);a.push({type:1,index:o,name:S[2],strings:y,ctor:S[1]==="."?J:S[1]==="?"?Z:S[1]==="@"?G:w}),r.removeAttribute(l)}else l.startsWith(g)&&(a.push({type:6,index:o}),r.removeAttribute(l));if($t.test(r.tagName)){let l=r.textContent.split(g),m=l.length-1;if(m>0){r.textContent=q?q.emptyScript:"";for(let y=0;y<m;y++)r.append(l[y],k()),b.nextNode(),a.push({type:2,index:++o});r.append(l[m],k())}}}else if(r.nodeType===8)if(r.data===gt)a.push({type:2,index:o});else{let l=-1;for(;(l=r.data.indexOf(g,l+1))!==-1;)a.push({type:7,index:o}),l+=g.length-1}o++}}static createElement(t,e){let s=x.createElement("template");return s.innerHTML=t,s}};function E(i,t,e=i,s){if(t===A)return t;let r=s!==void 0?e._$Co?.[s]:e._$Cl,o=R(t)?void 0:t._$litDirective$;return r?.constructor!==o&&(r?._$AO?.(!1),o===void 0?r=void 0:(r=new o(i),r._$AT(i,e,s)),s!==void 0?(e._$Co??=[])[s]=r:e._$Cl=r),r!==void 0&&(t=E(i,r._$AS(i,t.values),r,s)),t}var Y=class{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){let{el:{content:e},parts:s}=this._$AD,r=(t?.creationScope??x).importNode(e,!0);b.currentNode=r;let o=b.nextNode(),n=0,c=0,a=s[0];for(;a!==void 0;){if(n===a.index){let d;a.type===2?d=new N(o,o.nextSibling,this,t):a.type===1?d=new a.ctor(o,a.name,a.strings,this,t):a.type===6&&(d=new Q(o,this,t)),this._$AV.push(d),a=s[++c]}n!==a?.index&&(o=b.nextNode(),n++)}return b.currentNode=x,r}p(t){let e=0;for(let s of this._$AV)s!==void 0&&(s.strings!==void 0?(s._$AI(t,s,e),e+=s.strings.length-2):s._$AI(t[e])),e++}},N=class i{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,s,r){this.type=2,this._$AH=h,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=s,this.options=r,this._$Cv=r?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode,e=this._$AM;return e!==void 0&&t?.nodeType===11&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=E(this,t,e),R(t)?t===h||t==null||t===""?(this._$AH!==h&&this._$AR(),this._$AH=h):t!==this._$AH&&t!==A&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):Bt(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==h&&R(this._$AH)?this._$AA.nextSibling.data=t:this.T(x.createTextNode(t)),this._$AH=t}$(t){let{values:e,_$litType$:s}=t,r=typeof s=="number"?this._$AC(t):(s.el===void 0&&(s.el=M.createElement(_t(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===r)this._$AH.p(e);else{let o=new Y(r,this),n=o.u(this.options);o.p(e),this.T(n),this._$AH=o}}_$AC(t){let e=yt.get(t.strings);return e===void 0&&yt.set(t.strings,e=new M(t)),e}k(t){tt(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,s,r=0;for(let o of t)r===e.length?e.push(s=new i(this.O(k()),this.O(k()),this,this.options)):s=e[r],s._$AI(o),r++;r<e.length&&(this._$AR(s&&s._$AB.nextSibling,r),e.length=r)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){let s=lt(t).nextSibling;lt(t).remove(),t=s}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}},w=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,s,r,o){this.type=1,this._$AH=h,this._$AN=void 0,this.element=t,this.name=e,this._$AM=r,this.options=o,s.length>2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=h}_$AI(t,e=this,s,r){let o=this.strings,n=!1;if(o===void 0)t=E(this,t,e,0),n=!R(t)||t!==this._$AH&&t!==A,n&&(this._$AH=t);else{let c=t,a,d;for(t=o[0],a=0;a<o.length-1;a++)d=E(this,c[s+a],e,a),d===A&&(d=this._$AH[a]),n||=!R(d)||d!==this._$AH[a],d===h?t=h:t!==h&&(t+=(d??"")+o[a+1]),this._$AH[a]=d}n&&!r&&this.j(t)}j(t){t===h?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}},J=class extends w{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===h?void 0:t}},Z=class extends w{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==h)}},G=class extends w{constructor(t,e,s,r,o){super(t,e,s,r,o),this.type=5}_$AI(t,e=this){if((t=E(this,t,e,0)??h)===A)return;let s=this._$AH,r=t===h&&s!==h||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,o=t!==h&&(s===h||r);r&&this.element.removeEventListener(this.name,this,s),o&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}},Q=class{constructor(t,e,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){E(this,t)}};var qt=X.litHtmlPolyfillSupport;qt?.(M,N),(X.litHtmlVersions??=[]).push("3.3.2");var bt=(i,t,e)=>{let s=e?.renderBefore??t,r=s._$litPart$;if(r===void 0){let o=e?.renderBefore??null;s._$litPart$=r=new N(t.insertBefore(k(),o),o,void 0,e??{})}return r._$AI(i),r};var st=globalThis,$=class extends f{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){let e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=bt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return A}};$._$litElement$=!0,$.finalized=!0,st.litElementHydrateSupport?.({LitElement:$});var It=st.litElementPolyfillSupport;It?.({LitElement:$});(st.litElementVersions??=[]).push("4.2.2");var xt=i=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(i,t)}):customElements.define(i,t)};var Ft={attribute:!0,type:String,converter:O,reflect:!1,hasChanged:L},Vt=(i=Ft,t,e)=>{let{kind:s,metadata:r}=e,o=globalThis.litPropertyMetadata.get(r);if(o===void 0&&globalThis.litPropertyMetadata.set(r,o=new Map),s==="setter"&&((i=Object.create(i)).wrapped=!0),o.set(e.name,i),s==="accessor"){let{name:n}=e;return{set(c){let a=t.get.call(this);t.set.call(this,c),this.requestUpdate(n,a,i,!0,c)},init(c){return c!==void 0&&this.C(n,void 0,i,c),c}}}if(s==="setter"){let{name:n}=e;return function(c){let a=this[n];t.call(this,c),this.requestUpdate(n,a,i,!0,c)}}throw Error("Unsupported decorator location: "+s)};function I(i){return(t,e)=>typeof e=="object"?Vt(i,t,e):((s,r,o)=>{let n=r.hasOwnProperty(o);return r.constructor.createProperty(o,s),n?Object.getOwnPropertyDescriptor(r,o):void 0})(i,t,e)}var At=P`
1
+ "use strict";var RoxyUI_biorhythm_chart=(()=>{var T=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var wt=Object.getOwnPropertyNames;var Ct=Object.prototype.hasOwnProperty;var Pt=(i,t)=>{for(var e in t)T(i,e,{get:t[e],enumerable:!0})},Rt=(i,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of wt(t))!Ct.call(i,r)&&r!==e&&T(i,r,{get:()=>t[r],enumerable:!(s=rt(t,r))||s.enumerable});return i};var Ut=i=>Rt(T({},"__esModule",{value:!0}),i),H=(i,t,e,s)=>{for(var r=s>1?void 0:s?rt(t,e):t,o=i.length-1,n;o>=0;o--)(n=i[o])&&(r=(s?n(t,e,r):n(r))||r);return s&&r&&T(t,e,r),r};var Vt={};Pt(Vt,{RoxyBiorhythmChart:()=>v});var j=globalThis,z=j.ShadowRoot&&(j.ShadyCSS===void 0||j.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,G=Symbol(),it=new WeakMap,C=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==G)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o,e=this.t;if(z&&t===void 0){let s=e!==void 0&&e.length===1;s&&(t=it.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),s&&it.set(e,t))}return t}toString(){return this.cssText}},ot=i=>new C(typeof i=="string"?i:i+"",void 0,G),P=(i,...t)=>{let e=i.length===1?i[0]:t.reduce((s,r,o)=>s+(n=>{if(n._$cssResult$===!0)return n.cssText;if(typeof n=="number")return n;throw Error("Value passed to 'css' function must be a 'css' function result: "+n+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(r)+i[o+1],i[0]);return new C(e,i,G)},nt=(i,t)=>{if(z)i.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of t){let s=document.createElement("style"),r=j.litNonce;r!==void 0&&s.setAttribute("nonce",r),s.textContent=e.cssText,i.appendChild(s)}},V=z?i=>i:i=>i instanceof CSSStyleSheet?(t=>{let e="";for(let s of t.cssRules)e+=s.cssText;return ot(e)})(i):i;var{is:Ot,defineProperty:kt,getOwnPropertyDescriptor:Mt,getOwnPropertyNames:Nt,getOwnPropertySymbols:Dt,getPrototypeOf:Tt}=Object,L=globalThis,at=L.trustedTypes,Ht=at?at.emptyScript:"",jt=L.reactiveElementPolyfillSupport,R=(i,t)=>i,U={toAttribute(i,t){switch(t){case Boolean:i=i?Ht:null;break;case Object:case Array:i=i==null?i:JSON.stringify(i)}return i},fromAttribute(i,t){let e=i;switch(t){case Boolean:e=i!==null;break;case Number:e=i===null?null:Number(i);break;case Object:case Array:try{e=JSON.parse(i)}catch{e=null}}return e}},q=(i,t)=>!Ot(i,t),lt={attribute:!0,type:String,converter:U,reflect:!1,useDefault:!1,hasChanged:q};Symbol.metadata??=Symbol("metadata"),L.litPropertyMetadata??=new WeakMap;var f=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=lt){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){let s=Symbol(),r=this.getPropertyDescriptor(t,s,e);r!==void 0&&kt(this.prototype,t,r)}}static getPropertyDescriptor(t,e,s){let{get:r,set:o}=Mt(this.prototype,t)??{get(){return this[e]},set(n){this[e]=n}};return{get:r,set(n){let l=r?.call(this);o?.call(this,n),this.requestUpdate(t,l,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??lt}static _$Ei(){if(this.hasOwnProperty(R("elementProperties")))return;let t=Tt(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(R("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(R("properties"))){let e=this.properties,s=[...Nt(e),...Dt(e)];for(let r of s)this.createProperty(r,e[r])}let t=this[Symbol.metadata];if(t!==null){let e=litPropertyMetadata.get(t);if(e!==void 0)for(let[s,r]of e)this.elementProperties.set(s,r)}this._$Eh=new Map;for(let[e,s]of this.elementProperties){let r=this._$Eu(e,s);r!==void 0&&this._$Eh.set(r,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){let e=[];if(Array.isArray(t)){let s=new Set(t.flat(1/0).reverse());for(let r of s)e.unshift(V(r))}else t!==void 0&&e.push(V(t));return e}static _$Eu(t,e){let s=e.attribute;return s===!1?void 0:typeof s=="string"?s:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){let t=new Map,e=this.constructor.elementProperties;for(let s of e.keys())this.hasOwnProperty(s)&&(t.set(s,this[s]),delete this[s]);t.size>0&&(this._$Ep=t)}createRenderRoot(){let t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return nt(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,s){this._$AK(t,s)}_$ET(t,e){let s=this.constructor.elementProperties.get(t),r=this.constructor._$Eu(t,s);if(r!==void 0&&s.reflect===!0){let o=(s.converter?.toAttribute!==void 0?s.converter:U).toAttribute(e,s.type);this._$Em=t,o==null?this.removeAttribute(r):this.setAttribute(r,o),this._$Em=null}}_$AK(t,e){let s=this.constructor,r=s._$Eh.get(t);if(r!==void 0&&this._$Em!==r){let o=s.getPropertyOptions(r),n=typeof o.converter=="function"?{fromAttribute:o.converter}:o.converter?.fromAttribute!==void 0?o.converter:U;this._$Em=r;let l=n.fromAttribute(e,o.type);this[r]=l??this._$Ej?.get(r)??l,this._$Em=null}}requestUpdate(t,e,s,r=!1,o){if(t!==void 0){let n=this.constructor;if(r===!1&&(o=this[t]),s??=n.getPropertyOptions(t),!((s.hasChanged??q)(o,e)||s.useDefault&&s.reflect&&o===this._$Ej?.get(t)&&!this.hasAttribute(n._$Eu(t,s))))return;this.C(t,e,s)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:s,reflect:r,wrapped:o},n){s&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,n??e??this[t]),o!==!0||n!==void 0)||(this._$AL.has(t)||(this.hasUpdated||s||(e=void 0),this._$AL.set(t,e)),r===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}let t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[r,o]of this._$Ep)this[r]=o;this._$Ep=void 0}let s=this.constructor.elementProperties;if(s.size>0)for(let[r,o]of s){let{wrapped:n}=o,l=this[r];n!==!0||this._$AL.has(r)||l===void 0||this.C(r,void 0,o,l)}}let t=!1,e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(s=>s.hostUpdate?.()),this.update(e)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(t){}firstUpdated(t){}};f.elementStyles=[],f.shadowRootOptions={mode:"open"},f[R("elementProperties")]=new Map,f[R("finalized")]=new Map,jt?.({ReactiveElement:f}),(L.reactiveElementVersions??=[]).push("2.1.2");var X=globalThis,ct=i=>i,B=X.trustedTypes,ht=B?B.createPolicy("lit-html",{createHTML:i=>i}):void 0,ft="$lit$",$=`lit$${Math.random().toFixed(9).slice(2)}$`,$t="?"+$,zt=`<${$t}>`,b=document,k=()=>b.createComment(""),M=i=>i===null||typeof i!="object"&&typeof i!="function",tt=Array.isArray,Lt=i=>tt(i)||typeof i?.[Symbol.iterator]=="function",W=`[
2
+ \f\r]`,O=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,dt=/-->/g,pt=/>/g,_=RegExp(`>|${W}(?:([^\\s"'>=/]+)(${W}*=${W}*(?:[^
3
+ \f\r"'\`<>=]|("|')|))|$)`,"g"),ut=/'/g,mt=/"/g,gt=/^(?:script|style|textarea|title)$/i,et=i=>(t,...e)=>({_$litType$:i,strings:t,values:e}),u=et(1),vt=et(2),Qt=et(3),A=Symbol.for("lit-noChange"),h=Symbol.for("lit-nothing"),yt=new WeakMap,x=b.createTreeWalker(b,129);function _t(i,t){if(!tt(i)||!i.hasOwnProperty("raw"))throw Error("invalid template strings array");return ht!==void 0?ht.createHTML(t):t}var qt=(i,t)=>{let e=i.length-1,s=[],r,o=t===2?"<svg>":t===3?"<math>":"",n=O;for(let l=0;l<e;l++){let a=i[l],d,p,c=-1,m=0;for(;m<a.length&&(n.lastIndex=m,p=n.exec(a),p!==null);)m=n.lastIndex,n===O?p[1]==="!--"?n=dt:p[1]!==void 0?n=pt:p[2]!==void 0?(gt.test(p[2])&&(r=RegExp("</"+p[2],"g")),n=_):p[3]!==void 0&&(n=_):n===_?p[0]===">"?(n=r??O,c=-1):p[1]===void 0?c=-2:(c=n.lastIndex-p[2].length,d=p[1],n=p[3]===void 0?_:p[3]==='"'?mt:ut):n===mt||n===ut?n=_:n===dt||n===pt?n=O:(n=_,r=void 0);let y=n===_&&i[l+1].startsWith("/>")?" ":"";o+=n===O?a+zt:c>=0?(s.push(d),a.slice(0,c)+ft+a.slice(c)+$+y):a+$+(c===-2?l:y)}return[_t(i,o+(i[e]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),s]},N=class i{constructor({strings:t,_$litType$:e},s){let r;this.parts=[];let o=0,n=0,l=t.length-1,a=this.parts,[d,p]=qt(t,e);if(this.el=i.createElement(d,s),x.currentNode=this.el.content,e===2||e===3){let c=this.el.content.firstChild;c.replaceWith(...c.childNodes)}for(;(r=x.nextNode())!==null&&a.length<l;){if(r.nodeType===1){if(r.hasAttributes())for(let c of r.getAttributeNames())if(c.endsWith(ft)){let m=p[n++],y=r.getAttribute(c).split($),S=/([.?@])?(.*)/.exec(m);a.push({type:1,index:o,name:S[2],strings:y,ctor:S[1]==="."?Y:S[1]==="?"?J:S[1]==="@"?Z:w}),r.removeAttribute(c)}else c.startsWith($)&&(a.push({type:6,index:o}),r.removeAttribute(c));if(gt.test(r.tagName)){let c=r.textContent.split($),m=c.length-1;if(m>0){r.textContent=B?B.emptyScript:"";for(let y=0;y<m;y++)r.append(c[y],k()),x.nextNode(),a.push({type:2,index:++o});r.append(c[m],k())}}}else if(r.nodeType===8)if(r.data===$t)a.push({type:2,index:o});else{let c=-1;for(;(c=r.data.indexOf($,c+1))!==-1;)a.push({type:7,index:o}),c+=$.length-1}o++}}static createElement(t,e){let s=b.createElement("template");return s.innerHTML=t,s}};function E(i,t,e=i,s){if(t===A)return t;let r=s!==void 0?e._$Co?.[s]:e._$Cl,o=M(t)?void 0:t._$litDirective$;return r?.constructor!==o&&(r?._$AO?.(!1),o===void 0?r=void 0:(r=new o(i),r._$AT(i,e,s)),s!==void 0?(e._$Co??=[])[s]=r:e._$Cl=r),r!==void 0&&(t=E(i,r._$AS(i,t.values),r,s)),t}var K=class{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){let{el:{content:e},parts:s}=this._$AD,r=(t?.creationScope??b).importNode(e,!0);x.currentNode=r;let o=x.nextNode(),n=0,l=0,a=s[0];for(;a!==void 0;){if(n===a.index){let d;a.type===2?d=new D(o,o.nextSibling,this,t):a.type===1?d=new a.ctor(o,a.name,a.strings,this,t):a.type===6&&(d=new Q(o,this,t)),this._$AV.push(d),a=s[++l]}n!==a?.index&&(o=x.nextNode(),n++)}return x.currentNode=b,r}p(t){let e=0;for(let s of this._$AV)s!==void 0&&(s.strings!==void 0?(s._$AI(t,s,e),e+=s.strings.length-2):s._$AI(t[e])),e++}},D=class i{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,s,r){this.type=2,this._$AH=h,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=s,this.options=r,this._$Cv=r?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode,e=this._$AM;return e!==void 0&&t?.nodeType===11&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=E(this,t,e),M(t)?t===h||t==null||t===""?(this._$AH!==h&&this._$AR(),this._$AH=h):t!==this._$AH&&t!==A&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):Lt(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==h&&M(this._$AH)?this._$AA.nextSibling.data=t:this.T(b.createTextNode(t)),this._$AH=t}$(t){let{values:e,_$litType$:s}=t,r=typeof s=="number"?this._$AC(t):(s.el===void 0&&(s.el=N.createElement(_t(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===r)this._$AH.p(e);else{let o=new K(r,this),n=o.u(this.options);o.p(e),this.T(n),this._$AH=o}}_$AC(t){let e=yt.get(t.strings);return e===void 0&&yt.set(t.strings,e=new N(t)),e}k(t){tt(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,s,r=0;for(let o of t)r===e.length?e.push(s=new i(this.O(k()),this.O(k()),this,this.options)):s=e[r],s._$AI(o),r++;r<e.length&&(this._$AR(s&&s._$AB.nextSibling,r),e.length=r)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){let s=ct(t).nextSibling;ct(t).remove(),t=s}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}},w=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,s,r,o){this.type=1,this._$AH=h,this._$AN=void 0,this.element=t,this.name=e,this._$AM=r,this.options=o,s.length>2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=h}_$AI(t,e=this,s,r){let o=this.strings,n=!1;if(o===void 0)t=E(this,t,e,0),n=!M(t)||t!==this._$AH&&t!==A,n&&(this._$AH=t);else{let l=t,a,d;for(t=o[0],a=0;a<o.length-1;a++)d=E(this,l[s+a],e,a),d===A&&(d=this._$AH[a]),n||=!M(d)||d!==this._$AH[a],d===h?t=h:t!==h&&(t+=(d??"")+o[a+1]),this._$AH[a]=d}n&&!r&&this.j(t)}j(t){t===h?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}},Y=class extends w{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===h?void 0:t}},J=class extends w{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==h)}},Z=class extends w{constructor(t,e,s,r,o){super(t,e,s,r,o),this.type=5}_$AI(t,e=this){if((t=E(this,t,e,0)??h)===A)return;let s=this._$AH,r=t===h&&s!==h||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,o=t!==h&&(s===h||r);r&&this.element.removeEventListener(this.name,this,s),o&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}},Q=class{constructor(t,e,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){E(this,t)}};var Bt=X.litHtmlPolyfillSupport;Bt?.(N,D),(X.litHtmlVersions??=[]).push("3.3.2");var xt=(i,t,e)=>{let s=e?.renderBefore??t,r=s._$litPart$;if(r===void 0){let o=e?.renderBefore??null;s._$litPart$=r=new D(t.insertBefore(k(),o),o,void 0,e??{})}return r._$AI(i),r};var st=globalThis,g=class extends f{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){let e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=xt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return A}};g._$litElement$=!0,g.finalized=!0,st.litElementHydrateSupport?.({LitElement:g});var It=st.litElementPolyfillSupport;It?.({LitElement:g});(st.litElementVersions??=[]).push("4.2.2");var bt=i=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(i,t)}):customElements.define(i,t)};var Ft={attribute:!0,type:String,converter:U,reflect:!1,hasChanged:q},Gt=(i=Ft,t,e)=>{let{kind:s,metadata:r}=e,o=globalThis.litPropertyMetadata.get(r);if(o===void 0&&globalThis.litPropertyMetadata.set(r,o=new Map),s==="setter"&&((i=Object.create(i)).wrapped=!0),o.set(e.name,i),s==="accessor"){let{name:n}=e;return{set(l){let a=t.get.call(this);t.set.call(this,l),this.requestUpdate(n,a,i,!0,l)},init(l){return l!==void 0&&this.C(n,void 0,i,l),l}}}if(s==="setter"){let{name:n}=e;return function(l){let a=this[n];t.call(this,l),this.requestUpdate(n,a,i,!0,l)}}throw Error("Unsupported decorator location: "+s)};function I(i){return(t,e)=>typeof e=="object"?Gt(i,t,e):((s,r,o)=>{let n=r.hasOwnProperty(o);return r.constructor.createProperty(o,s),n?Object.getOwnPropertyDescriptor(r,o):void 0})(i,t,e)}var At=P`
4
4
  :host {
5
5
  display: block;
6
6
  container-type: inline-size;
@@ -82,34 +82,29 @@
82
82
  outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
83
83
  outline-offset: 2px;
84
84
  }
85
- `;var St={physical:"#dc2626",emotional:"#0284c7",intellectual:"#16a34a",intuitive:"#a855f7",aesthetic:"#f59e0b",awareness:"#ec4899",spiritual:"#14b8a6",passion:"#ef4444",mastery:"#6366f1",wisdom:"#475569"},v=class extends ${constructor(){super(...arguments);this.data=null;this.mode="daily"}render(){let e=this.data;return e?this.mode==="critical-days"&&e.criticalDays?.length?this.renderCritical(e):this.mode==="forecast"&&e.days?.length?this.renderForecast(e):this.renderDaily(e):u`<div class="roxy-empty" role="status">No biorhythm data</div>`}renderDaily(e){let s=e.cycles??{},r=Object.entries(s);return u`<section class="wrap" aria-label="Daily biorhythm">
85
+ `;var St={physical:"#dc2626",emotional:"#0284c7",intellectual:"#16a34a",intuitive:"#a855f7",aesthetic:"#f59e0b",awareness:"#ec4899",spiritual:"#14b8a6",passion:"#ef4444",mastery:"#6366f1",wisdom:"#475569"},v=class extends g{constructor(){super(...arguments);this.data=null;this.mode="daily"}render(){let e=this.data;return e?this.mode==="critical-days"&&"criticalDays"in e?this.renderCritical(e):this.mode==="forecast"&&"days"in e?this.renderForecast(e):this.renderDaily(e):u`<div class="roxy-empty" role="status">No biorhythm data</div>`}renderDaily(e){let s=e.quickRead??{},r=Object.entries(s).map(([o,n])=>{let l=typeof n=="number"?n:0,a=Math.abs(l)>1?l/100:l;return[o,a]});return u`<section class="wrap" aria-label="Daily biorhythm">
86
86
  <header class="head">
87
87
  <h2 class="title">Biorhythm</h2>
88
88
  ${typeof e.energyRating=="number"?u`<span class="energy">Energy ${e.energyRating}/10</span>`:h}
89
89
  </header>
90
90
  <div class="bars" role="list">
91
- ${r.map(([o,n])=>{let c=typeof n=="number"?n:0,a=(c+1)/2*100,d=St[o]??"var(--roxy-accent, #f59e0b)";return u`<div class="bar" role="listitem">
91
+ ${r.map(([o,n])=>{let l=(n+1)/2*100,a=St[o]??"var(--roxy-accent, #f59e0b)";return u`<div class="bar" role="listitem">
92
92
  <span style="text-transform: capitalize">${o}</span>
93
93
  <span class="track">
94
94
  <span
95
95
  class="fill"
96
- style="width: ${a}%; background: ${d}"
96
+ style="width: ${l}%; background: ${a}"
97
97
  ></span>
98
98
  </span>
99
- <span class="value">${(c*100).toFixed(0)}%</span>
99
+ <span class="value">${Math.round(n*100)}%</span>
100
100
  </div>`})}
101
101
  </div>
102
- ${e.interpretation?u`<p class="advice">${e.interpretation}</p>`:h}
102
+ ${e.dailyMessage?u`<p class="advice">${e.dailyMessage}</p>`:h}
103
103
  ${e.advice?u`<p class="advice">${e.advice}</p>`:h}
104
- ${e.criticalAlerts?.length?u`<div>
105
- ${e.criticalAlerts.map(o=>u`<p class="alert">${o}</p>`)}
106
- </div>`:h}
107
- </section>`}renderForecast(e){let s=e.days??[];if(s.length===0)return u`<div class="roxy-empty" role="status">No forecast</div>`;let r=600,o=160,n=r/Math.max(s.length-1,1),c=Object.keys(s[0]?.cycles??{});return u`<section class="wrap" aria-label="Biorhythm forecast">
104
+ </section>`}renderForecast(e){let s=e.days??[];if(s.length===0)return u`<div class="roxy-empty" role="status">No forecast</div>`;let r=600,o=160,n=r/Math.max(s.length-1,1),l=["physical","emotional","intellectual","intuitive"];return u`<section class="wrap" aria-label="Biorhythm forecast">
108
105
  <header class="head">
109
106
  <h2 class="title">Forecast</h2>
110
- <span class="energy"
111
- >${e.startDate??""} - ${e.endDate??""}</span
112
- >
107
+ <span class="energy">${e.startDate} - ${e.endDate}</span>
113
108
  </header>
114
109
  <svg
115
110
  viewBox="0 0 ${r} ${o}"
@@ -125,19 +120,17 @@
125
120
  stroke="var(--roxy-border, #e4e4e7)"
126
121
  stroke-width="1"
127
122
  />
128
- ${c.map(a=>{let d=s.map((l,m)=>{let y=l.cycles?.[a]??0,S=m*n,Et=o/2-y*(o/2-8);return`${S.toFixed(2)},${Et.toFixed(2)}`}).join(" "),p=St[a]??"#475569";return vt`<polyline points=${d} fill="none" stroke=${p} stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />`})}
123
+ ${l.map(a=>{let d=s.map((c,m)=>{let y=c[a]??0,S=m*n,Et=o/2-y/100*(o/2-8);return`${S.toFixed(2)},${Et.toFixed(2)}`}).join(" "),p=St[a]??"#475569";return vt`<polyline points=${d} fill="none" stroke=${p} stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />`})}
129
124
  </svg>
130
125
  ${e.summary?.periodAdvice?u`<p class="advice">${e.summary.periodAdvice}</p>`:h}
131
126
  </section>`}renderCritical(e){return u`<section class="wrap" aria-label="Critical days">
132
127
  <header class="head">
133
128
  <h2 class="title">Critical days</h2>
134
- <span class="energy"
135
- >${e.totalCriticalDays??e.criticalDays?.length??0} total</span
136
- >
129
+ <span class="energy">${e.totalCriticalDays} total</span>
137
130
  </header>
138
131
  <div>
139
- ${(e.criticalDays??[]).map(s=>u`<span class="crit"
140
- >${s.date} · ${s.cycle??""} ${s.severity??""}</span
132
+ ${e.criticalDays.map(s=>u`<span class="crit"
133
+ >${s.date} · ${s.cycle} ${s.severity}</span
141
134
  >`)}
142
135
  </div>
143
136
  </section>`}};v.styles=[At,P`
@@ -216,7 +209,7 @@
216
209
  display: inline-block;
217
210
  margin: 2px;
218
211
  }
219
- `],H([I({attribute:!1})],v.prototype,"data",2),H([I({type:String,reflect:!0})],v.prototype,"mode",2),v=H([xt("roxy-biorhythm-chart")],v);return Ot(Wt);})();
212
+ `],H([I({attribute:!1})],v.prototype,"data",2),H([I({type:String,reflect:!0})],v.prototype,"mode",2),v=H([bt("roxy-biorhythm-chart")],v);return Ut(Vt);})();
220
213
  /*! Bundled license information:
221
214
 
222
215
  @lit/reactive-element/css-tag.js: